diff --git a/src/harfbuzz-dump-main.c b/src/harfbuzz-dump-main.c deleted file mode 100644 index dfb35fbaa..000000000 --- a/src/harfbuzz-dump-main.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2000 Red Hat, Inc. - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Red Hat Author(s): Owen Taylor - */ - -#include -#include - -#include "harfbuzz.h" -#include "harfbuzz-dump.h" - -#define N_ELEMENTS(arr) (sizeof(arr)/ sizeof((arr)[0])) - -static int -croak (const char *situation, HB_Error error) -{ - fprintf (stderr, "%s: Error %d\n", situation, error); - - exit (1); -} - -int -main (int argc, char **argv) -{ - HB_Error error; - FT_Library library; - HB_Font font; - HB_GSUB gsub; - HB_GPOS gpos; - - if (argc != 2) - { - fprintf (stderr, "Usage: harfbuzz-dump MYFONT.TTF\n"); - exit(1); - } - - if ((error = FT_Init_FreeType (&library))) - croak ("FT_Init_FreeType", error); - - if ((error = FT_New_Face (library, argv[1], 0, &font))) - croak ("FT_New_Face", error); - - printf ("\n"); - printf ("\n"); - - if (!(error = HB_Load_GSUB_Table (font, &gsub, NULL))) - { - HB_Dump_GSUB_Table (gsub, stdout); - - if ((error = HB_Done_GSUB_Table (gsub))) - croak ("HB_Done_GSUB_Table", error); - } - else if (error != HB_Err_Not_Covered) - fprintf (stderr, "HB_Load_GSUB_Table: error 0x%x\n", error); - - if (!(error = HB_Load_GPOS_Table (font, &gpos, NULL))) - { - HB_Dump_GPOS_Table (gpos, stdout); - - if ((error = HB_Done_GPOS_Table (gpos))) - croak ("HB_Done_GPOS_Table", error); - } - else if (error != HB_Err_Not_Covered) - fprintf (stderr, "HB_Load_GPOS_Table: error 0x%x\n", error); - - printf ("\n"); - - if ((error = FT_Done_Face (font))) - croak ("FT_Done_Face", error); - - if ((error = FT_Done_FreeType (library))) - croak ("FT_Done_FreeType", error); - - return 0; -} - diff --git a/src/harfbuzz-dump.c b/src/harfbuzz-dump.c deleted file mode 100644 index 861166474..000000000 --- a/src/harfbuzz-dump.c +++ /dev/null @@ -1,768 +0,0 @@ -/* - * Copyright (C) 2000, 2007 Red Hat, Inc. - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Red Hat Author(s): Owen Taylor, Behdad Esfahbod - */ - -#include "harfbuzz-impl.h" -#include "harfbuzz-dump.h" -#include "harfbuzz-gdef-private.h" -#include "harfbuzz-gsub-private.h" -#include "harfbuzz-gpos-private.h" -#include "harfbuzz-open-private.h" -#include - -#define DUMP(format) dump (stream, indent, format) -#define DUMP1(format, arg1) dump (stream, indent, format, arg1) -#define DUMP2(format, arg1, arg2) dump (stream, indent, format, arg1, arg2) -#define DUMP3(format, arg1, arg2, arg3) dump (stream, indent, format, arg1, arg2, arg3) - -#define DUMP_FINT(strct,fld) dump (stream, indent, "<" #fld ">%d\n", (strct)->fld) -#define DUMP_FUINT(strct,fld) dump (stream, indent, "<" #fld ">%u\n", (strct)->fld) -#define DUMP_FGLYPH(strct,fld) dump (stream, indent, "<" #fld ">%#06x\n", (strct)->fld) -#define DUMP_FGLYPH(strct,fld) dump (stream, indent, "<" #fld ">%#06x\n", (strct)->fld) -#define DUMP_USHORT_ARRAY(strct,fld,cnt) Dump_UShort_Array ((strct)->fld, cnt, #fld, stream, indent); - -#define DEF_DUMP(type) static void Dump_ ## type (HB_ ## type *type, FILE *stream, int indent, HB_Type hb_type) -#define RECURSE(name, type, val) do { DUMP ("<" #name ">\n"); Dump_ ## type (val, stream, indent + 1, hb_type); DUMP ("\n"); } while (0) -#define RECURSE_NUM(name, i, type, val) do { DUMP1 ("<" #name "> \n", i); Dump_ ## type (val, stream, indent + 1, hb_type); DUMP ("\n"); } while (0) -#define DUMP_VALUE_RECORD(val, frmt) do { DUMP ("\n"); Dump_ValueRecord (val, stream, indent + 1, hb_type, frmt); DUMP ("\n"); } while (0) - -static void -do_indent (FILE *stream, int indent) -{ - fprintf (stream, "%*s", indent * 3, ""); -} - -#if __GNUC__ >= 3 -__attribute__((__format__(__printf__, 3, 4))) -#endif -static void -dump (FILE *stream, int indent, const char *format, ...) -{ - va_list list; - - do_indent (stream, indent); - - va_start (list, format); - vfprintf (stream, format, list); - va_end (list); -} - -static void -Dump_UShort_Array (HB_UShort *array, int count, const char *name, FILE *stream, int indent) -{ - int i; - - do_indent (stream, indent); - - fprintf (stream, "<%s>", name); - for (i = 0; i < count; i++) - fprintf (stream, "%d%s", array[i], i == 0 ? "" : " "); - fprintf (stream, "\n", name); -} - -static void -Print_Tag (HB_UInt tag, FILE *stream) -{ - fprintf (stream, "%c%c%c%c", - (unsigned char)(tag >> 24), - (unsigned char)((tag >> 16) & 0xff), - (unsigned char)((tag >> 8) & 0xff), - (unsigned char)(tag & 0xff)); -} - -DEF_DUMP (LangSys) -{ - int i; - - HB_UNUSED(hb_type); - - DUMP_FUINT (LangSys, LookupOrderOffset); - DUMP_FUINT (LangSys, ReqFeatureIndex); - DUMP_FUINT (LangSys, FeatureCount); - - for (i=0; i < LangSys->FeatureCount; i++) - DUMP1("%d\n", LangSys->FeatureIndex[i]); -} - -DEF_DUMP (ScriptTable) -{ - int i; - - RECURSE (DefaultLangSys, LangSys, &ScriptTable->DefaultLangSys); - - DUMP_FUINT (ScriptTable, LangSysCount); - - for (i=0; i < ScriptTable->LangSysCount; i++) - { - do_indent (stream, indent); - fprintf (stream, ""); - Print_Tag (ScriptTable->LangSysRecord[i].LangSysTag, stream); - fprintf (stream, "\n"); - RECURSE_NUM (LangSys, i, LangSys, &ScriptTable->LangSysRecord[i].LangSys); - } -} - -DEF_DUMP (ScriptList) -{ - int i; - - DUMP_FUINT (ScriptList, ScriptCount); - - for (i=0; i < ScriptList->ScriptCount; i++) - { - do_indent (stream, indent); - fprintf (stream, ""); - Print_Tag (ScriptList->ScriptRecord[i].ScriptTag, stream); - fprintf (stream, "\n"); - RECURSE_NUM (Script, i, ScriptTable, &ScriptList->ScriptRecord[i].Script); - } -} - -DEF_DUMP (Feature) -{ - int i; - - HB_UNUSED(hb_type); - - DUMP_FUINT (Feature, FeatureParams); - DUMP_FUINT (Feature, LookupListCount); - - for (i=0; i < Feature->LookupListCount; i++) - DUMP1("%d\n", Feature->LookupListIndex[i]); -} - -DEF_DUMP (MarkRecord) -{ - HB_UNUSED(hb_type); - - DUMP_FUINT (MarkRecord, Class); - DUMP1("%d\n", MarkRecord->MarkAnchor.PosFormat ); -} - -DEF_DUMP (MarkArray) -{ - int i; - - DUMP_FUINT (MarkArray, MarkCount); - - for (i=0; i < MarkArray->MarkCount; i++) - RECURSE_NUM (MarkRecord, i, MarkRecord, &MarkArray->MarkRecord[i]); -} - -DEF_DUMP (FeatureList) -{ - int i; - - DUMP_FUINT (FeatureList, FeatureCount); - - for (i=0; i < FeatureList->FeatureCount; i++) - { - do_indent (stream, indent); - fprintf (stream, ""); - Print_Tag (FeatureList->FeatureRecord[i].FeatureTag, stream); - fprintf (stream, " \n", i); - RECURSE_NUM (Feature, i, Feature, &FeatureList->FeatureRecord[i].Feature); - } -} - -DEF_DUMP (Coverage) -{ - HB_UNUSED(hb_type); - - DUMP_FUINT (Coverage, CoverageFormat); - - if (Coverage->CoverageFormat == 1) - { - int i; - DUMP_FUINT (&Coverage->cf.cf1, GlyphCount); - - for (i = 0; i < Coverage->cf.cf1.GlyphCount; i++) - DUMP2("%#06x \n", - Coverage->cf.cf1.GlyphArray[i], i); - } - else - { - int i; - DUMP_FUINT (&Coverage->cf.cf2, RangeCount); - - for ( i = 0; i < Coverage->cf.cf2.RangeCount; i++ ) - DUMP3("%#06x - %#06x \n", - Coverage->cf.cf2.RangeRecord[i].Start, - Coverage->cf.cf2.RangeRecord[i].End, i); - } -} - -DEF_DUMP (ClassRangeRecord) -{ - HB_UNUSED(hb_type); - - DUMP_FGLYPH (ClassRangeRecord, Start); - DUMP_FGLYPH (ClassRangeRecord, End); - DUMP_FUINT (ClassRangeRecord, Class); -} - -DEF_DUMP (ClassDefinition) -{ - HB_UNUSED(hb_type); - - DUMP_FUINT( ClassDefinition, ClassFormat); - DUMP_FUINT( ClassDefinition, loaded); - - if (ClassDefinition->ClassFormat == 1) - { - int i; - HB_ClassDefFormat1 *ClassDefFormat1 = &ClassDefinition->cd.cd1; - DUMP("\n"); - DUMP_FUINT (ClassDefFormat1, StartGlyph ); - DUMP_FUINT (ClassDefFormat1, GlyphCount ); - for (i = 0; i < ClassDefFormat1->GlyphCount; i++) - DUMP2(" %d ", ClassDefFormat1->ClassValueArray[i], - ClassDefFormat1->StartGlyph+i ); - } - else if (ClassDefinition->ClassFormat == 2) - { - int i; - HB_ClassDefFormat2 *ClassDefFormat2 = &ClassDefinition->cd.cd2; - DUMP_FUINT (ClassDefFormat2, ClassRangeCount); - - for (i = 0; i < ClassDefFormat2->ClassRangeCount; i++) - RECURSE_NUM (ClassRangeRecord, i, ClassRangeRecord, &ClassDefFormat2->ClassRangeRecord[i]); - } - else - fprintf(stderr, "invalid class def table!!!\n"); -} - -DEF_DUMP (SubstLookupRecord) -{ - HB_UNUSED(hb_type); - - DUMP_FUINT (SubstLookupRecord, SequenceIndex); - DUMP_FUINT (SubstLookupRecord, LookupListIndex); -} - -DEF_DUMP (ChainSubClassRule) -{ - int i; - - DUMP_USHORT_ARRAY (ChainSubClassRule, Backtrack, ChainSubClassRule->BacktrackGlyphCount); - DUMP_USHORT_ARRAY (ChainSubClassRule, Input, ChainSubClassRule->InputGlyphCount - 1); - DUMP_USHORT_ARRAY (ChainSubClassRule, Lookahead, ChainSubClassRule->LookaheadGlyphCount); - - for (i = 0; i < ChainSubClassRule->SubstCount; i++) - RECURSE_NUM (SubstLookupRecord, i, SubstLookupRecord, &ChainSubClassRule->SubstLookupRecord[i]); - - indent--; -} - -DEF_DUMP (ChainSubClassSet) -{ - int i; - - DUMP_FUINT( ChainSubClassSet, ChainSubClassRuleCount ); - for (i = 0; i < ChainSubClassSet->ChainSubClassRuleCount; i++) - RECURSE_NUM (ChainSubClassRule, i, ChainSubClassRule, &ChainSubClassSet->ChainSubClassRule[i]); -} - -static void -Dump_GSUB_Lookup_Single (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type) -{ - HB_SingleSubst *SingleSubst = &subtable->st.gsub.single; - - DUMP_FUINT (SingleSubst, SubstFormat); - RECURSE (Coverage, Coverage, &SingleSubst->Coverage); - - if (SingleSubst->SubstFormat == 1) - { - DUMP_FINT (&SingleSubst->ssf.ssf1, DeltaGlyphID); - } - else - { - int i; - - DUMP_FINT (&SingleSubst->ssf.ssf2, GlyphCount); - for (i=0; i < SingleSubst->ssf.ssf2.GlyphCount; i++) - DUMP2("%#06x \n", SingleSubst->ssf.ssf2.Substitute[i], i); - } -} - -DEF_DUMP (Ligature) -{ - int i; - - HB_UNUSED(hb_type); - - DUMP_FGLYPH (Ligature, LigGlyph); - DUMP_FUINT (Ligature, ComponentCount); - - for (i=0; i < Ligature->ComponentCount - 1; i++) - DUMP1("%#06x\n", Ligature->Component[i]); -} - -DEF_DUMP (LigatureSet) -{ - int i; - - DUMP_FUINT (LigatureSet, LigatureCount); - - for (i=0; i < LigatureSet->LigatureCount; i++) - RECURSE_NUM (Ligature, i, Ligature, &LigatureSet->Ligature[i]); -} - -static void -Dump_GSUB_Lookup_Ligature (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type) -{ - int i; - HB_LigatureSubst *LigatureSubst = &subtable->st.gsub.ligature; - - DUMP_FUINT (LigatureSubst, SubstFormat); - RECURSE (Coverage, Coverage, &LigatureSubst->Coverage); - - DUMP_FUINT (LigatureSubst, LigatureSetCount); - - for (i=0; i < LigatureSubst->LigatureSetCount; i++) - RECURSE_NUM (LigatureSet, i, LigatureSet, &LigatureSubst->LigatureSet[i]); -} - -DEF_DUMP (ContextSubstFormat1) -{ - HB_UNUSED(hb_type); - HB_UNUSED(ContextSubstFormat1); - - - DUMP("\n"); -} - -DEF_DUMP (ContextSubstFormat2) -{ - DUMP_FUINT (ContextSubstFormat2, MaxContextLength); - RECURSE (Coverage, Coverage, &ContextSubstFormat2->Coverage); - RECURSE (ClassDefinition, ClassDefinition, &ContextSubstFormat2->ClassDef); -} - -DEF_DUMP (ContextSubstFormat3) -{ - HB_UNUSED(hb_type); - HB_UNUSED(ContextSubstFormat3); - - DUMP("\n"); -} - -static void -Dump_GSUB_Lookup_Context (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type) -{ - HB_ContextSubst *ContextSubst = &subtable->st.gsub.context; - - DUMP_FUINT (ContextSubst, SubstFormat); - switch( ContextSubst->SubstFormat ) - { - case 1: - Dump_ContextSubstFormat1 (&ContextSubst->csf.csf1, stream, indent+2, hb_type); - break; - case 2: - Dump_ContextSubstFormat2 (&ContextSubst->csf.csf2, stream, indent+2, hb_type); - break; - case 3: - Dump_ContextSubstFormat3 (&ContextSubst->csf.csf3, stream, indent+2, hb_type); - break; - default: - fprintf(stderr, "invalid subformat!!!!!\n"); - } -} - -DEF_DUMP (ChainContextSubstFormat1) -{ - HB_UNUSED(hb_type); - HB_UNUSED(ChainContextSubstFormat1); - - DUMP("\n"); -} - -DEF_DUMP (ChainContextSubstFormat2) -{ - int i; - - RECURSE (Coverage, Coverage, &ChainContextSubstFormat2->Coverage); - DUMP_FUINT (ChainContextSubstFormat2, MaxBacktrackLength); - RECURSE (ClassDefinition, ClassDefinition, &ChainContextSubstFormat2->BacktrackClassDef); - DUMP_FUINT (ChainContextSubstFormat2, MaxInputLength); - RECURSE (ClassDefinition, ClassDefinition, &ChainContextSubstFormat2->InputClassDef); - DUMP_FUINT (ChainContextSubstFormat2, MaxLookaheadLength); - RECURSE (ClassDefinition, ClassDefinition, &ChainContextSubstFormat2->LookaheadClassDef); - - DUMP_FUINT (ChainContextSubstFormat2, ChainSubClassSetCount); - for (i = 0; i < ChainContextSubstFormat2->ChainSubClassSetCount; i++) - RECURSE (ChainSubClassSet, ChainSubClassSet, &ChainContextSubstFormat2->ChainSubClassSet[i]); -} - -DEF_DUMP (ChainContextSubstFormat3) -{ - int i; - - DUMP_FUINT (ChainContextSubstFormat3, BacktrackGlyphCount); - for (i = 0; i < ChainContextSubstFormat3->BacktrackGlyphCount; i++) - RECURSE (BacktrackCoverage, Coverage, &ChainContextSubstFormat3->BacktrackCoverage[i]); - DUMP_FUINT (ChainContextSubstFormat3, InputGlyphCount); - for (i = 0; i < ChainContextSubstFormat3->InputGlyphCount; i++) - RECURSE (InputCoverage, Coverage, &ChainContextSubstFormat3->InputCoverage[i]); - DUMP_FUINT (ChainContextSubstFormat3, LookaheadGlyphCount); - for (i = 0; i < ChainContextSubstFormat3->LookaheadGlyphCount; i++) - RECURSE (LookaheadCoverage, Coverage, &ChainContextSubstFormat3->LookaheadCoverage[i]); - - for (i = 0; i < ChainContextSubstFormat3->SubstCount; i++) - RECURSE_NUM (SubstLookupRecord, i, SubstLookupRecord, &ChainContextSubstFormat3->SubstLookupRecord[i]); - -} - -static void -Dump_GSUB_Lookup_Chain (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type) -{ - HB_ChainContextSubst *chain = &subtable->st.gsub.chain; - - DUMP_FUINT (chain, SubstFormat); - switch (chain->SubstFormat) - { - case 1: - Dump_ChainContextSubstFormat1 (&chain->ccsf.ccsf1, stream, indent+2, hb_type); - break; - case 2: - Dump_ChainContextSubstFormat2 (&chain->ccsf.ccsf2, stream, indent+2, hb_type); - break; - case 3: - Dump_ChainContextSubstFormat3 (&chain->ccsf.ccsf3, stream, indent+2, hb_type); - break; - default: - fprintf(stderr, "invalid subformat!!!!!\n"); - } -} - -static void -Dump_Device (HB_Device *Device, FILE *stream, int indent, HB_Type hb_type) -{ - int i; - int bits; - int n_per; - unsigned int mask; - - HB_UNUSED(hb_type); - - DUMP_FUINT (Device, StartSize); - DUMP_FUINT (Device, EndSize); - DUMP_FUINT (Device, DeltaFormat); - switch (Device->DeltaFormat) - { - case 1: - bits = 2; - break; - case 2: - bits = 4; - break; - case 3: - bits = 8; - break; - default: - bits = 0; - break; - } - - DUMP (""); - if (!bits) - { - - fprintf(stderr, "invalid DeltaFormat!!!!!\n"); - } - else - { - n_per = 16 / bits; - mask = (1 << bits) - 1; - mask = mask << (16 - bits); - - for (i = Device->StartSize; i <= Device->EndSize ; i++) - { - HB_UShort val = Device->DeltaValue[i / n_per]; - HB_Short signed_val = ((val << ((i % n_per) * bits)) & mask); - dump (stream, indent, "%d", signed_val >> (16 - bits)); - if (i != Device->EndSize) - DUMP (", "); - } - } - DUMP ("\n"); -} - -static void -Dump_ValueRecord (HB_ValueRecord *ValueRecord, FILE *stream, int indent, HB_Type hb_type, HB_UShort value_format) -{ - if (value_format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT) - DUMP_FINT (ValueRecord, XPlacement); - if (value_format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT) - DUMP_FINT (ValueRecord, YPlacement); - if (value_format & HB_GPOS_FORMAT_HAVE_X_ADVANCE) - DUMP_FINT (ValueRecord, XAdvance); - if (value_format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE) - DUMP_FINT (ValueRecord, XAdvance); - if (value_format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE) - RECURSE (Device, Device, &ValueRecord->XPlacementDevice); - if (value_format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE) - RECURSE (Device, Device, &ValueRecord->YPlacementDevice); - if (value_format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE) - RECURSE (Device, Device, &ValueRecord->XAdvanceDevice); - if (value_format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE) - RECURSE (Device, Device, &ValueRecord->YAdvanceDevice); - if (value_format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT) - DUMP_FUINT (ValueRecord, XIdPlacement); - if (value_format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT) - DUMP_FUINT (ValueRecord, YIdPlacement); - if (value_format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE) - DUMP_FUINT (ValueRecord, XIdAdvance); - if (value_format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE) - DUMP_FUINT (ValueRecord, XIdAdvance); -} - -static void -Dump_GPOS_Lookup_Single (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type) -{ - HB_SinglePos *SinglePos = &subtable->st.gpos.single; - - DUMP_FUINT (SinglePos, PosFormat); - RECURSE (Coverage, Coverage, &SinglePos->Coverage); - - DUMP_FUINT (SinglePos, ValueFormat); - - if (SinglePos->PosFormat == 1) - { - DUMP_VALUE_RECORD (&SinglePos->spf.spf1.Value, SinglePos->ValueFormat); - } - else - { - int i; - - DUMP_FUINT (&SinglePos->spf.spf2, ValueCount); - for (i = 0; i < SinglePos->spf.spf2.ValueCount; i++) - DUMP_VALUE_RECORD (&SinglePos->spf.spf2.Value[i], SinglePos->ValueFormat); - } -} - -static void -Dump_PairValueRecord (HB_PairValueRecord *PairValueRecord, FILE *stream, int indent, HB_Type hb_type, HB_UShort ValueFormat1, HB_UShort ValueFormat2) -{ - DUMP_FUINT (PairValueRecord, SecondGlyph); - DUMP_VALUE_RECORD (&PairValueRecord->Value1, ValueFormat1); - DUMP_VALUE_RECORD (&PairValueRecord->Value2, ValueFormat2); -} - -static void -Dump_PairSet (HB_PairSet *PairSet, FILE *stream, int indent, HB_Type hb_type, HB_UShort ValueFormat1, HB_UShort ValueFormat2) -{ - int i; - DUMP_FUINT (PairSet, PairValueCount); - - for (i = 0; i < PairSet->PairValueCount; i++) - { - DUMP ("\n"); - Dump_PairValueRecord (&PairSet->PairValueRecord[i], stream, indent + 1, hb_type, ValueFormat1, ValueFormat2); - DUMP ("\n"); - } -} - -static void -Dump_GPOS_Lookup_Pair (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type) -{ - HB_PairPos *PairPos = &subtable->st.gpos.pair; - - DUMP_FUINT (PairPos, PosFormat); - RECURSE (Coverage, Coverage, &PairPos->Coverage); - - DUMP_FUINT (PairPos, ValueFormat1); - DUMP_FUINT (PairPos, ValueFormat2); - - if (PairPos->PosFormat == 1) - { - int i; - - DUMP_FUINT (&PairPos->ppf.ppf1, PairSetCount); - for (i = 0; i < PairPos->ppf.ppf1.PairSetCount; i++) - { - DUMP ("\n"); - Dump_PairSet (&PairPos->ppf.ppf1.PairSet[i], stream, indent + 1, hb_type, PairPos->ValueFormat1, PairPos->ValueFormat2); - DUMP ("\n"); - } - } - else - { - } -} - -static void -Dump_GPOS_Lookup_Markbase (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type) -{ - int i; - HB_MarkBasePos *markbase = &subtable->st.gpos.markbase; - - DUMP_FUINT (markbase, PosFormat); - RECURSE (Coverage, Coverage, &markbase->MarkCoverage); - RECURSE (Coverage, Coverage, &markbase->BaseCoverage); - DUMP_FUINT (markbase, ClassCount); - RECURSE (MarkArray, MarkArray, &markbase->MarkArray); - - DUMP ("\n"); - indent++; - - DUMP_FUINT (&markbase->BaseArray, BaseCount); - for (i = 0; i < markbase->BaseArray.BaseCount; i++) - { - int j; - HB_BaseRecord *r = &markbase->BaseArray.BaseRecord[i]; - DUMP1 (" \n", i); - for (j = 0; j < markbase->ClassCount; j++) - DUMP1 (" %d\n", r->BaseAnchor->PosFormat); - DUMP ("\n"); - } - - indent--; - DUMP ("\n"); -} - -DEF_DUMP (Lookup) -{ - int i; - const char *lookup_name; - void (*lookup_func) (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type) = NULL; - - if (hb_type == HB_Type_GSUB) - { - switch (Lookup->LookupType) - { - case HB_GSUB_LOOKUP_SINGLE: - lookup_name = "SINGLE"; - lookup_func = Dump_GSUB_Lookup_Single; - break; - case HB_GSUB_LOOKUP_MULTIPLE: - lookup_name = "MULTIPLE"; - break; - case HB_GSUB_LOOKUP_ALTERNATE: - lookup_name = "ALTERNATE"; - break; - case HB_GSUB_LOOKUP_LIGATURE: - lookup_name = "LIGATURE"; - lookup_func = Dump_GSUB_Lookup_Ligature; - break; - case HB_GSUB_LOOKUP_CONTEXT: - lookup_name = "CONTEXT"; - lookup_func = Dump_GSUB_Lookup_Context; - break; - case HB_GSUB_LOOKUP_CHAIN: - lookup_name = "CHAIN"; - lookup_func = Dump_GSUB_Lookup_Chain; - break; - default: - lookup_name = "(unknown)"; - lookup_func = NULL; - break; - } - } - else - { - switch (Lookup->LookupType) - { - case HB_GPOS_LOOKUP_SINGLE: - lookup_name = "SINGLE"; - lookup_func = Dump_GPOS_Lookup_Single; - break; - case HB_GPOS_LOOKUP_PAIR: - lookup_name = "PAIR"; - lookup_func = Dump_GPOS_Lookup_Pair; - break; - case HB_GPOS_LOOKUP_CURSIVE: - lookup_name = "CURSIVE"; - break; - case HB_GPOS_LOOKUP_MARKBASE: - lookup_name = "MARKBASE"; - lookup_func = Dump_GPOS_Lookup_Markbase; - break; - case HB_GPOS_LOOKUP_MARKLIG: - lookup_name = "MARKLIG"; - break; - case HB_GPOS_LOOKUP_MARKMARK: - lookup_name = "MARKMARK"; - break; - case HB_GPOS_LOOKUP_CONTEXT: - lookup_name = "CONTEXT"; - break; - case HB_GPOS_LOOKUP_CHAIN: - lookup_name = "CHAIN"; - break; - default: - lookup_name = "(unknown)"; - lookup_func = NULL; - break; - } - } - - DUMP2("%s \n", lookup_name, Lookup->LookupType); - DUMP1("%#06x\n", Lookup->LookupFlag); - - for (i=0; i < Lookup->SubTableCount; i++) - { - DUMP ("\n"); - if (lookup_func) - (*lookup_func) (&Lookup->SubTable[i], stream, indent + 1, hb_type); - DUMP ("\n"); - } -} - -DEF_DUMP (LookupList) -{ - int i; - - DUMP_FUINT (LookupList, LookupCount); - - for (i=0; i < LookupList->LookupCount; i++) - RECURSE_NUM (Lookup, i, Lookup, &LookupList->Lookup[i]); -} - -void -HB_Dump_GSUB_Table (HB_GSUB gsub, FILE *stream) -{ - int indent = 1; - HB_Type hb_type = HB_Type_GSUB; - - do_indent (stream, indent); - fprintf(stream, "\n"); - RECURSE (ScriptList, ScriptList, &gsub->ScriptList); - RECURSE (FeatureList, FeatureList, &gsub->FeatureList); - RECURSE (LookupList, LookupList, &gsub->LookupList); -} - -void -HB_Dump_GPOS_Table (HB_GPOS gpos, FILE *stream) -{ - int indent = 1; - HB_Type hb_type = HB_Type_GPOS; - - do_indent (stream, indent); - fprintf(stream, "\n"); - RECURSE (ScriptList, ScriptList, &gpos->ScriptList); - RECURSE (FeatureList, FeatureList, &gpos->FeatureList); - RECURSE (LookupList, LookupList, &gpos->LookupList); -} diff --git a/src/harfbuzz-dump.h b/src/harfbuzz-dump.h deleted file mode 100644 index ea4a62b2e..000000000 --- a/src/harfbuzz-dump.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2000, 2007 Red Hat, Inc. - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Red Hat Author(s): Owen Taylor, Behdad Esfahbod - */ - -#ifndef HARFBUZZ_DUMP_H -#define HARFBUZZ_DUMP_H - -#include -#include "harfbuzz-gsub.h" -#include "harfbuzz-gpos.h" - -HB_BEGIN_HEADER - -void HB_Dump_GSUB_Table (HB_GSUB gsub, FILE *stream); -void HB_Dump_GPOS_Table (HB_GPOS gpos, FILE *stream); - -HB_END_HEADER - -#endif /* HARFBUZZ_DUMP_H */ diff --git a/src/harfbuzz-gdef-private.h b/src/harfbuzz-gdef-private.h deleted file mode 100644 index e22b1b20c..000000000 --- a/src/harfbuzz-gdef-private.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2006 Behdad Esfahbod - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#ifndef HARFBUZZ_GDEF_PRIVATE_H -#define HARFBUZZ_GDEF_PRIVATE_H - -#include "harfbuzz-impl.h" -#include "harfbuzz-stream-private.h" -#include "harfbuzz-buffer-private.h" -#include "harfbuzz-gdef.h" - -HB_BEGIN_HEADER - - -/* Attachment related structures */ - -struct HB_AttachPoint_ -{ - HB_UShort PointCount; /* size of the PointIndex array */ - HB_UShort* PointIndex; /* array of contour points */ -}; - -/* Ligature Caret related structures */ - -struct HB_CaretValueFormat1_ -{ - HB_Short Coordinate; /* x or y value (in design units) */ -}; - -typedef struct HB_CaretValueFormat1_ HB_CaretValueFormat1; - - -struct HB_CaretValueFormat2_ -{ - HB_UShort CaretValuePoint; /* contour point index on glyph */ -}; - -typedef struct HB_CaretValueFormat2_ HB_CaretValueFormat2; - - -struct HB_CaretValueFormat3_ -{ - HB_Short Coordinate; /* x or y value (in design units) */ - HB_Device Device; /* Device table for x or y value */ -}; - -typedef struct HB_CaretValueFormat3_ HB_CaretValueFormat3; - - -struct HB_CaretValueFormat4_ -{ - HB_UShort IdCaretValue; /* metric ID */ -}; - -typedef struct HB_CaretValueFormat4_ HB_CaretValueFormat4; - - -struct HB_CaretValue_ -{ - HB_UShort CaretValueFormat; /* 1, 2, 3, or 4 */ - - union - { - HB_CaretValueFormat1 cvf1; - HB_CaretValueFormat2 cvf2; - HB_CaretValueFormat3 cvf3; - HB_CaretValueFormat4 cvf4; - } cvf; -}; - -typedef struct HB_CaretValue_ HB_CaretValue; - - -struct HB_LigGlyph_ -{ - HB_Bool loaded; - - HB_UShort CaretCount; /* number of caret values */ - HB_CaretValue* CaretValue; /* array of caret values */ -}; - - -HB_INTERNAL HB_Error -_HB_GDEF_Add_Glyph_Property( HB_GDEFHeader* gdef, - HB_UShort glyphID, - HB_UShort properties ); - -HB_INTERNAL HB_Error -_HB_GDEF_Check_Property( HB_GDEFHeader* gdef, - HB_GlyphItem item, - HB_UShort flags, - HB_UShort* properties ); - -HB_INTERNAL HB_Error -_HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( HB_GDEFHeader* gdef, - HB_Stream input, - HB_Lookup* lo, - HB_UShort num_lookups ); - -HB_END_HEADER - -#endif /* HARFBUZZ_GDEF_PRIVATE_H */ diff --git a/src/harfbuzz-gdef.c b/src/harfbuzz-gdef.c deleted file mode 100644 index 1bda9073b..000000000 --- a/src/harfbuzz-gdef.c +++ /dev/null @@ -1,1160 +0,0 @@ -/* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2006 Behdad Esfahbod - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#include "harfbuzz-impl.h" -#include "harfbuzz-gdef-private.h" -#include "harfbuzz-open-private.h" - -static HB_Error Load_AttachList( HB_AttachList* al, - HB_Stream stream ); -static HB_Error Load_LigCaretList( HB_LigCaretList* lcl, - HB_Stream stream ); - -static void Free_AttachList( HB_AttachList* al ); -static void Free_LigCaretList( HB_LigCaretList* lcl ); - -static void Free_NewGlyphClasses( HB_GDEFHeader* gdef ); - - - -/* GDEF glyph classes */ - -#define UNCLASSIFIED_GLYPH 0 -#define SIMPLE_GLYPH 1 -#define LIGATURE_GLYPH 2 -#define MARK_GLYPH 3 -#define COMPONENT_GLYPH 4 - - - - - - -HB_Error HB_New_GDEF_Table( HB_GDEFHeader** retptr ) -{ - HB_Error error; - - HB_GDEFHeader* gdef; - - if ( !retptr ) - return ERR(HB_Err_Invalid_Argument); - - if ( ALLOC( gdef, sizeof( *gdef ) ) ) - return error; - - gdef->GlyphClassDef.loaded = FALSE; - gdef->AttachList.loaded = FALSE; - gdef->LigCaretList.loaded = FALSE; - gdef->MarkAttachClassDef_offset = 0; - gdef->MarkAttachClassDef.loaded = FALSE; - - gdef->LastGlyph = 0; - gdef->NewGlyphClasses = NULL; - - *retptr = gdef; - - return HB_Err_Ok; -} - - -HB_Error HB_Load_GDEF_Table( HB_Font font, - HB_GDEFHeader** retptr ) -{ - HB_Error error; - HB_Stream stream = font->stream; - HB_UInt cur_offset, new_offset, base_offset; - - HB_GDEFHeader* gdef; - - - if ( !retptr ) - return ERR(HB_Err_Invalid_Argument); - - if ( GOTO_Table( TTAG_GDEF ) ) - return error; - - if (( error = HB_New_GDEF_Table ( &gdef ) )) - return error; - - base_offset = FILE_Pos(); - - /* skip version */ - - if ( FILE_Seek( base_offset + 4L ) || - ACCESS_Frame( 2L ) ) - goto Fail0; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - /* all GDEF subtables are optional */ - - if ( new_offset ) - { - new_offset += base_offset; - - /* only classes 1-4 are allowed here */ - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_ClassDefinition( &gdef->GlyphClassDef, 5, - stream ) ) != HB_Err_Ok ) - goto Fail0; - (void)FILE_Seek( cur_offset ); - } - - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_AttachList( &gdef->AttachList, - stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_LigCaretList( &gdef->LigCaretList, - stream ) ) != HB_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - } - - /* OpenType 1.2 has introduced the `MarkAttachClassDef' field. We - first have to scan the LookupFlag values to find out whether we - must load it or not. Here we only store the offset of the table. */ - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - gdef->MarkAttachClassDef_offset = new_offset + base_offset; - else - gdef->MarkAttachClassDef_offset = 0; - - *retptr = gdef; - - return HB_Err_Ok; - -Fail3: - Free_LigCaretList( &gdef->LigCaretList ); - -Fail2: - Free_AttachList( &gdef->AttachList ); - -Fail1: - _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef ); - -Fail0: - FREE( gdef ); - - return error; -} - - -HB_Error HB_Done_GDEF_Table ( HB_GDEFHeader* gdef ) -{ - Free_LigCaretList( &gdef->LigCaretList ); - Free_AttachList( &gdef->AttachList ); - _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef ); - _HB_OPEN_Free_ClassDefinition( &gdef->MarkAttachClassDef ); - - Free_NewGlyphClasses( gdef ); - - FREE( gdef ); - - return HB_Err_Ok; -} - - - - -/******************************* - * AttachList related functions - *******************************/ - - -/* AttachPoint */ - -static HB_Error Load_AttachPoint( HB_AttachPoint* ap, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - HB_UShort* pi; - - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = ap->PointCount = GET_UShort(); - - FORGET_Frame(); - - ap->PointIndex = NULL; - - if ( count ) - { - if ( ALLOC_ARRAY( ap->PointIndex, count, HB_UShort ) ) - return error; - - pi = ap->PointIndex; - - if ( ACCESS_Frame( count * 2L ) ) - { - FREE( pi ); - return error; - } - - for ( n = 0; n < count; n++ ) - pi[n] = GET_UShort(); - - FORGET_Frame(); - } - - return HB_Err_Ok; -} - - -static void Free_AttachPoint( HB_AttachPoint* ap ) -{ - FREE( ap->PointIndex ); -} - - -/* AttachList */ - -static HB_Error Load_AttachList( HB_AttachList* al, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_AttachPoint* ap; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &al->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = al->GlyphCount = GET_UShort(); - - FORGET_Frame(); - - al->AttachPoint = NULL; - - if ( ALLOC_ARRAY( al->AttachPoint, count, HB_AttachPoint ) ) - goto Fail2; - - ap = al->AttachPoint; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_AttachPoint( &ap[n], stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - al->loaded = TRUE; - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - Free_AttachPoint( &ap[m] ); - - FREE( ap ); - -Fail2: - _HB_OPEN_Free_Coverage( &al->Coverage ); - return error; -} - - -static void Free_AttachList( HB_AttachList* al ) -{ - HB_UShort n, count; - - HB_AttachPoint* ap; - - - if ( !al->loaded ) - return; - - if ( al->AttachPoint ) - { - count = al->GlyphCount; - ap = al->AttachPoint; - - for ( n = 0; n < count; n++ ) - Free_AttachPoint( &ap[n] ); - - FREE( ap ); - } - - _HB_OPEN_Free_Coverage( &al->Coverage ); -} - - - -/********************************* - * LigCaretList related functions - *********************************/ - - -/* CaretValueFormat1 */ -/* CaretValueFormat2 */ -/* CaretValueFormat3 */ -/* CaretValueFormat4 */ - -static HB_Error Load_CaretValue( HB_CaretValue* cv, - HB_Stream stream ) -{ - HB_Error error; - - HB_UInt cur_offset, new_offset, base_offset; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - cv->CaretValueFormat = GET_UShort(); - - FORGET_Frame(); - - switch ( cv->CaretValueFormat ) - { - case 1: - if ( ACCESS_Frame( 2L ) ) - return error; - - cv->cvf.cvf1.Coordinate = GET_Short(); - - FORGET_Frame(); - - break; - - case 2: - if ( ACCESS_Frame( 2L ) ) - return error; - - cv->cvf.cvf2.CaretValuePoint = GET_UShort(); - - FORGET_Frame(); - - break; - - case 3: - if ( ACCESS_Frame( 4L ) ) - return error; - - cv->cvf.cvf3.Coordinate = GET_Short(); - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Device( &cv->cvf.cvf3.Device, - stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - break; - - case 4: - if ( ACCESS_Frame( 2L ) ) - return error; - - cv->cvf.cvf4.IdCaretValue = GET_UShort(); - - FORGET_Frame(); - break; - - default: - return ERR(HB_Err_Invalid_SubTable_Format); - } - - return HB_Err_Ok; -} - - -static void Free_CaretValue( HB_CaretValue* cv ) -{ - if ( cv->CaretValueFormat == 3 ) - _HB_OPEN_Free_Device( &cv->cvf.cvf3.Device ); -} - - -/* LigGlyph */ - -static HB_Error Load_LigGlyph( HB_LigGlyph* lg, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_CaretValue* cv; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = lg->CaretCount = GET_UShort(); - - FORGET_Frame(); - - lg->CaretValue = NULL; - - if ( ALLOC_ARRAY( lg->CaretValue, count, HB_CaretValue ) ) - return error; - - cv = lg->CaretValue; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_CaretValue( &cv[n], stream ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail: - for ( m = 0; m < n; m++ ) - Free_CaretValue( &cv[m] ); - - FREE( cv ); - return error; -} - - -static void Free_LigGlyph( HB_LigGlyph* lg ) -{ - HB_UShort n, count; - - HB_CaretValue* cv; - - - if ( lg->CaretValue ) - { - count = lg->CaretCount; - cv = lg->CaretValue; - - for ( n = 0; n < count; n++ ) - Free_CaretValue( &cv[n] ); - - FREE( cv ); - } -} - - -/* LigCaretList */ - -static HB_Error Load_LigCaretList( HB_LigCaretList* lcl, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort m, n, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_LigGlyph* lg; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &lcl->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = lcl->LigGlyphCount = GET_UShort(); - - FORGET_Frame(); - - lcl->LigGlyph = NULL; - - if ( ALLOC_ARRAY( lcl->LigGlyph, count, HB_LigGlyph ) ) - goto Fail2; - - lg = lcl->LigGlyph; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_LigGlyph( &lg[n], stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - lcl->loaded = TRUE; - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - Free_LigGlyph( &lg[m] ); - - FREE( lg ); - -Fail2: - _HB_OPEN_Free_Coverage( &lcl->Coverage ); - return error; -} - - -static void Free_LigCaretList( HB_LigCaretList* lcl ) -{ - HB_UShort n, count; - - HB_LigGlyph* lg; - - - if ( !lcl->loaded ) - return; - - if ( lcl->LigGlyph ) - { - count = lcl->LigGlyphCount; - lg = lcl->LigGlyph; - - for ( n = 0; n < count; n++ ) - Free_LigGlyph( &lg[n] ); - - FREE( lg ); - } - - _HB_OPEN_Free_Coverage( &lcl->Coverage ); -} - - - -/*********** - * GDEF API - ***********/ - - -static HB_UShort Get_New_Class( HB_GDEFHeader* gdef, - HB_UShort glyphID, - HB_UShort index ) -{ - HB_UShort glyph_index, array_index, count; - HB_UShort byte, bits; - - HB_ClassRangeRecord* gcrr; - HB_UShort** ngc; - - - if ( glyphID >= gdef->LastGlyph ) - return 0; - - count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount; - gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord; - ngc = gdef->NewGlyphClasses; - - if ( index < count && glyphID < gcrr[index].Start ) - { - array_index = index; - if ( index == 0 ) - glyph_index = glyphID; - else - glyph_index = glyphID - gcrr[index - 1].End - 1; - } - else - { - array_index = index + 1; - glyph_index = glyphID - gcrr[index].End - 1; - } - - byte = ngc[array_index][glyph_index / 4]; - bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 ); - - return bits & 0x000F; -} - - - -HB_Error HB_GDEF_Get_Glyph_Property( HB_GDEFHeader* gdef, - HB_UShort glyphID, - HB_UShort* property ) -{ - HB_UShort class = 0, index = 0; /* shut compiler up */ - - HB_Error error; - - - if ( !gdef || !property ) - return ERR(HB_Err_Invalid_Argument); - - /* first, we check for mark attach classes */ - - if ( gdef->MarkAttachClassDef.loaded ) - { - error = _HB_OPEN_Get_Class( &gdef->MarkAttachClassDef, glyphID, &class, &index ); - if ( error && error != HB_Err_Not_Covered ) - return error; - if ( !error ) - { - *property = class << 8; - return HB_Err_Ok; - } - } - - error = _HB_OPEN_Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index ); - if ( error && error != HB_Err_Not_Covered ) - return error; - - /* if we have a constructed class table, check whether additional - values have been assigned */ - - if ( error == HB_Err_Not_Covered && gdef->NewGlyphClasses ) - class = Get_New_Class( gdef, glyphID, index ); - - switch ( class ) - { - default: - case UNCLASSIFIED_GLYPH: - *property = 0; - break; - - case SIMPLE_GLYPH: - *property = HB_GDEF_BASE_GLYPH; - break; - - case LIGATURE_GLYPH: - *property = HB_GDEF_LIGATURE; - break; - - case MARK_GLYPH: - *property = HB_GDEF_MARK; - break; - - case COMPONENT_GLYPH: - *property = HB_GDEF_COMPONENT; - break; - } - - return HB_Err_Ok; -} - - -static HB_Error Make_ClassRange( HB_ClassDefinition* cd, - HB_UShort start, - HB_UShort end, - HB_UShort class ) -{ - HB_Error error; - HB_UShort index; - - HB_ClassDefFormat2* cdf2; - HB_ClassRangeRecord* crr; - - - cdf2 = &cd->cd.cd2; - - if ( REALLOC_ARRAY( cdf2->ClassRangeRecord, - cdf2->ClassRangeCount + 1 , - HB_ClassRangeRecord ) ) - return error; - - cdf2->ClassRangeCount++; - - crr = cdf2->ClassRangeRecord; - index = cdf2->ClassRangeCount - 1; - - crr[index].Start = start; - crr[index].End = end; - crr[index].Class = class; - - return HB_Err_Ok; -} - - - -HB_Error HB_GDEF_Build_ClassDefinition( HB_GDEFHeader* gdef, - HB_UShort num_glyphs, - HB_UShort glyph_count, - HB_UShort* glyph_array, - HB_UShort* class_array ) -{ - HB_UShort start, curr_glyph, curr_class; - HB_UShort n, m, count; - HB_Error error; - - HB_ClassDefinition* gcd; - HB_ClassRangeRecord* gcrr; - HB_UShort** ngc; - - - if ( !gdef || !glyph_array || !class_array ) - return ERR(HB_Err_Invalid_Argument); - - gcd = &gdef->GlyphClassDef; - - /* We build a format 2 table */ - - gcd->ClassFormat = 2; - - gcd->cd.cd2.ClassRangeCount = 0; - gcd->cd.cd2.ClassRangeRecord = NULL; - - start = glyph_array[0]; - curr_class = class_array[0]; - curr_glyph = start; - - if ( curr_class >= 5 ) - { - error = ERR(HB_Err_Invalid_Argument); - goto Fail4; - } - - glyph_count--; - - for ( n = 0; n < glyph_count + 1; n++ ) - { - if ( curr_glyph == glyph_array[n] && curr_class == class_array[n] ) - { - if ( n == glyph_count ) - { - if ( ( error = Make_ClassRange( gcd, start, - curr_glyph, - curr_class ) ) != HB_Err_Ok ) - goto Fail3; - } - else - { - if ( curr_glyph == 0xFFFF ) - { - error = ERR(HB_Err_Invalid_Argument); - goto Fail3; - } - else - curr_glyph++; - } - } - else - { - if ( ( error = Make_ClassRange( gcd, start, - curr_glyph - 1, - curr_class ) ) != HB_Err_Ok ) - goto Fail3; - - if ( curr_glyph > glyph_array[n] ) - { - error = ERR(HB_Err_Invalid_Argument); - goto Fail3; - } - - start = glyph_array[n]; - curr_class = class_array[n]; - curr_glyph = start; - - if ( curr_class >= 5 ) - { - error = ERR(HB_Err_Invalid_Argument); - goto Fail3; - } - - if ( n == glyph_count ) - { - if ( ( error = Make_ClassRange( gcd, start, - curr_glyph, - curr_class ) ) != HB_Err_Ok ) - goto Fail3; - } - else - { - if ( curr_glyph == 0xFFFF ) - { - error = ERR(HB_Err_Invalid_Argument); - goto Fail3; - } - else - curr_glyph++; - } - } - } - - /* now prepare the arrays for class values assigned during the lookup - process */ - - if ( ALLOC_ARRAY( gdef->NewGlyphClasses, - gcd->cd.cd2.ClassRangeCount + 1, HB_UShort* ) ) - goto Fail3; - - count = gcd->cd.cd2.ClassRangeCount; - gcrr = gcd->cd.cd2.ClassRangeRecord; - ngc = gdef->NewGlyphClasses; - - /* We allocate arrays for all glyphs not covered by the class range - records. Each element holds four class values. */ - - if ( count > 0 ) - { - if ( gcrr[0].Start ) - { - if ( ALLOC_ARRAY( ngc[0], ( gcrr[0].Start + 3 ) / 4, HB_UShort ) ) - goto Fail2; - } - - for ( n = 1; n < count; n++ ) - { - if ( gcrr[n].Start - gcrr[n - 1].End > 1 ) - if ( ALLOC_ARRAY( ngc[n], - ( gcrr[n].Start - gcrr[n - 1].End + 2 ) / 4, - HB_UShort ) ) - goto Fail1; - } - - if ( gcrr[count - 1].End != num_glyphs - 1 ) - { - if ( ALLOC_ARRAY( ngc[count], - ( num_glyphs - gcrr[count - 1].End + 2 ) / 4, - HB_UShort ) ) - goto Fail1; - } - } - else if ( num_glyphs > 0 ) - { - if ( ALLOC_ARRAY( ngc[count], - ( num_glyphs + 3 ) / 4, - HB_UShort ) ) - goto Fail2; - } - - gdef->LastGlyph = num_glyphs - 1; - - gdef->MarkAttachClassDef_offset = 0L; - gdef->MarkAttachClassDef.loaded = FALSE; - - gcd->loaded = TRUE; - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - FREE( ngc[m] ); - -Fail2: - FREE( gdef->NewGlyphClasses ); - -Fail3: - FREE( gcd->cd.cd2.ClassRangeRecord ); - -Fail4: - return error; -} - - -static void Free_NewGlyphClasses( HB_GDEFHeader* gdef ) -{ - HB_UShort** ngc; - HB_UShort n, count; - - - if ( gdef->NewGlyphClasses ) - { - count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount + 1; - ngc = gdef->NewGlyphClasses; - - for ( n = 0; n < count; n++ ) - FREE( ngc[n] ); - - FREE( ngc ); - } -} - - -HB_INTERNAL HB_Error -_HB_GDEF_Add_Glyph_Property( HB_GDEFHeader* gdef, - HB_UShort glyphID, - HB_UShort property ) -{ - HB_Error error; - HB_UShort class, new_class, index = 0; /* shut compiler up */ - HB_UShort byte, bits, mask; - HB_UShort array_index, glyph_index, count; - - HB_ClassRangeRecord* gcrr; - HB_UShort** ngc; - - - error = _HB_OPEN_Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index ); - if ( error && error != HB_Err_Not_Covered ) - return error; - - /* we don't accept glyphs covered in `GlyphClassDef' */ - - if ( !error ) - return HB_Err_Not_Covered; - - switch ( property ) - { - case 0: - new_class = UNCLASSIFIED_GLYPH; - break; - - case HB_GDEF_BASE_GLYPH: - new_class = SIMPLE_GLYPH; - break; - - case HB_GDEF_LIGATURE: - new_class = LIGATURE_GLYPH; - break; - - case HB_GDEF_MARK: - new_class = MARK_GLYPH; - break; - - case HB_GDEF_COMPONENT: - new_class = COMPONENT_GLYPH; - break; - - default: - return ERR(HB_Err_Invalid_Argument); - } - - count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount; - gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord; - ngc = gdef->NewGlyphClasses; - - if ( index < count && glyphID < gcrr[index].Start ) - { - array_index = index; - if ( index == 0 ) - glyph_index = glyphID; - else - glyph_index = glyphID - gcrr[index - 1].End - 1; - } - else - { - array_index = index + 1; - glyph_index = glyphID - gcrr[index].End - 1; - } - - byte = ngc[array_index][glyph_index / 4]; - bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 ); - class = bits & 0x000F; - - /* we don't overwrite existing entries */ - - if ( !class ) - { - bits = new_class << ( 16 - ( glyph_index % 4 + 1 ) * 4 ); - mask = ~( 0x000F << ( 16 - ( glyph_index % 4 + 1 ) * 4 ) ); - - ngc[array_index][glyph_index / 4] &= mask; - ngc[array_index][glyph_index / 4] |= bits; - } - - return HB_Err_Ok; -} - - -HB_INTERNAL HB_Error -_HB_GDEF_Check_Property( HB_GDEFHeader* gdef, - HB_GlyphItem gitem, - HB_UShort flags, - HB_UShort* property ) -{ - HB_Error error; - - if ( gdef ) - { - HB_UShort basic_glyph_class; - HB_UShort desired_attachment_class; - - if ( gitem->gproperty == HB_GLYPH_PROPERTY_UNKNOWN ) - { - error = HB_GDEF_Get_Glyph_Property( gdef, gitem->gindex, &gitem->gproperty ); - if ( error ) - return error; - } - - *property = gitem->gproperty; - - /* If the glyph was found in the MarkAttachmentClass table, - * then that class value is the high byte of the result, - * otherwise the low byte contains the basic type of the glyph - * as defined by the GlyphClassDef table. - */ - if ( *property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) - basic_glyph_class = HB_GDEF_MARK; - else - basic_glyph_class = *property; - - /* Return Not_Covered, if, for example, basic_glyph_class - * is HB_GDEF_LIGATURE and LookFlags includes HB_LOOKUP_FLAG_IGNORE_LIGATURES - */ - if ( flags & basic_glyph_class ) - return HB_Err_Not_Covered; - - /* The high byte of LookupFlags has the meaning - * "ignore marks of attachment type different than - * the attachment type specified." - */ - desired_attachment_class = flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS; - if ( desired_attachment_class ) - { - if ( basic_glyph_class == HB_GDEF_MARK && - *property != desired_attachment_class ) - return HB_Err_Not_Covered; - } - } else { - *property = 0; - } - - return HB_Err_Ok; -} - -HB_INTERNAL HB_Error -_HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( HB_GDEFHeader* gdef, - HB_Stream stream, - HB_Lookup* lo, - HB_UShort num_lookups) -{ - HB_Error error = HB_Err_Ok; - HB_UShort i; - - /* We now check the LookupFlags for values larger than 0xFF to find - out whether we need to load the `MarkAttachClassDef' field of the - GDEF table -- this hack is necessary for OpenType 1.2 tables since - the version field of the GDEF table hasn't been incremented. - - For constructed GDEF tables, we only load it if - `MarkAttachClassDef_offset' is not zero (nevertheless, a build of - a constructed mark attach table is not supported currently). */ - - if ( gdef && - gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded ) - { - for ( i = 0; i < num_lookups; i++ ) - { - - if ( lo[i].LookupFlag & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) - { - if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) || - ( error = _HB_OPEN_Load_ClassDefinition( &gdef->MarkAttachClassDef, - 256, stream ) ) != HB_Err_Ok ) - goto Done; - - break; - } - } - } - -Done: - return error; -} - -/* END */ diff --git a/src/harfbuzz-gdef.h b/src/harfbuzz-gdef.h deleted file mode 100644 index dc33d21d6..000000000 --- a/src/harfbuzz-gdef.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2006 Behdad Esfahbod - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#ifndef HARFBUZZ_GDEF_H -#define HARFBUZZ_GDEF_H - -#include "harfbuzz-open.h" - -HB_BEGIN_HEADER - - -/* GDEF glyph properties. Note that HB_GDEF_COMPONENT has no corresponding - * flag in the LookupFlag field. */ -#define HB_GDEF_BASE_GLYPH 0x0002 -#define HB_GDEF_LIGATURE 0x0004 -#define HB_GDEF_MARK 0x0008 -#define HB_GDEF_COMPONENT 0x0010 - - -typedef struct HB_AttachPoint_ HB_AttachPoint; - - -struct HB_AttachList_ -{ - HB_Bool loaded; - - HB_Coverage Coverage; /* Coverage table */ - HB_UShort GlyphCount; /* number of glyphs with - attachments */ - HB_AttachPoint* AttachPoint; /* array of AttachPoint tables */ -}; - -typedef struct HB_AttachList_ HB_AttachList; - -typedef struct HB_LigGlyph_ HB_LigGlyph; - -struct HB_LigCaretList_ -{ - HB_Bool loaded; - - HB_Coverage Coverage; /* Coverage table */ - HB_UShort LigGlyphCount; /* number of ligature glyphs */ - HB_LigGlyph* LigGlyph; /* array of LigGlyph tables */ -}; - -typedef struct HB_LigCaretList_ HB_LigCaretList; - - - -/* The `NewGlyphClasses' field is not defined in the TTO specification. - We use it for fonts with a constructed `GlyphClassDef' structure - (i.e., which don't have a GDEF table) to collect glyph classes - assigned during the lookup process. The number of arrays in this - pointer array is GlyphClassDef->cd.cd2.ClassRangeCount+1; the nth - array then contains the glyph class values of the glyphs not covered - by the ClassRangeRecords structures with index n-1 and n. We store - glyph class values for four glyphs in a single array element. - - `LastGlyph' is identical to the number of glyphs minus one in the - font; we need it only if `NewGlyphClasses' is not NULL (to have an - upper bound for the last array). - - Note that we first store the file offset to the `MarkAttachClassDef' - field (which has been introduced in OpenType 1.2) -- since the - `Version' field value hasn't been increased to indicate that we have - one more field for some obscure reason, we must parse the GSUB table - to find out whether class values refer to this table. Only then we - can finally load the MarkAttachClassDef structure if necessary. */ - -struct HB_GDEFHeader_ -{ - HB_UInt offset; - - HB_16Dot16 Version; - - HB_ClassDefinition GlyphClassDef; - HB_AttachList AttachList; - HB_LigCaretList LigCaretList; - HB_UInt MarkAttachClassDef_offset; - HB_ClassDefinition MarkAttachClassDef; /* new in OT 1.2 */ - - HB_UShort LastGlyph; - HB_UShort** NewGlyphClasses; -}; - -typedef struct HB_GDEFHeader_ HB_GDEFHeader; -typedef struct HB_GDEFHeader_* HB_GDEF; - - -HB_Error HB_New_GDEF_Table( HB_GDEFHeader** retptr ); - - -HB_Error HB_Load_GDEF_Table( HB_Font font, - HB_GDEFHeader** gdef ); - - -HB_Error HB_Done_GDEF_Table ( HB_GDEFHeader* gdef ); - - -HB_Error HB_GDEF_Get_Glyph_Property( HB_GDEFHeader* gdef, - HB_UShort glyphID, - HB_UShort* properties ); - -HB_Error HB_GDEF_Build_ClassDefinition( HB_GDEFHeader* gdef, - HB_UShort num_glyphs, - HB_UShort glyph_count, - HB_UShort* glyph_array, - HB_UShort* class_array ); - - -HB_END_HEADER - -#endif /* HARFBUZZ_GDEF_H */ diff --git a/src/harfbuzz-global.h b/src/harfbuzz-global.h deleted file mode 100644 index 7b8a0f27c..000000000 --- a/src/harfbuzz-global.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2007 Trolltech ASA - * Copyright (C) 2007 Red Hat, Inc. - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Red Hat Author(s): Behdad Esfahbod - */ - -#ifndef HARFBUZZ_GLOBAL_H -#define HARFBUZZ_GLOBAL_H - -/* XXX */ -#include "hb-ot-layout.h" - -#include -#include FT_FREETYPE_H - -#ifdef __cplusplus -#define HB_BEGIN_HEADER extern "C" { -#define HB_END_HEADER } -#else -#define HB_BEGIN_HEADER /* nothing */ -#define HB_END_HEADER /* nothing */ -#endif - -HB_BEGIN_HEADER - -#define HB_MAKE_TAG(a,b,c,d) FT_MAKE_TAG(a,b,c,d) -typedef FT_Pos HB_Fixed; /* 26.6 */ -typedef FT_Fixed HB_16Dot16; /* 16.6 */ -typedef FT_Face HB_Font; - -typedef unsigned char HB_Byte; -typedef signed char HB_Char; -typedef unsigned short HB_UShort; -typedef signed short HB_Short; -typedef unsigned int HB_UInt; -typedef signed int HB_Int; -typedef int HB_Bool; -typedef void * HB_Pointer; - - -typedef enum { - /* no error */ - HB_Err_Ok = 0x0000, - HB_Err_Not_Covered = 0xFFFF, - - /* _hb_err() is called whenever returning the following errors, - * and in a couple places for HB_Err_Not_Covered too. */ - - /* programmer error */ - HB_Err_Invalid_Argument = 0x1A66, - - /* font error */ - HB_Err_Invalid_SubTable_Format = 0x157F, - HB_Err_Invalid_SubTable = 0x1570, - HB_Err_Read_Error = 0x6EAD, - - /* system error */ - HB_Err_Out_Of_Memory = 0xDEAD -} HB_Error; - -HB_END_HEADER - -#endif diff --git a/src/harfbuzz-gpos-private.h b/src/harfbuzz-gpos-private.h deleted file mode 100644 index 3a5c4bc26..000000000 --- a/src/harfbuzz-gpos-private.h +++ /dev/null @@ -1,712 +0,0 @@ -/* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2006 Behdad Esfahbod - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#ifndef HARFBUZZ_GPOS_PRIVATE_H -#define HARFBUZZ_GPOS_PRIVATE_H - -#include "harfbuzz-impl.h" -#include "harfbuzz-stream-private.h" -#include "harfbuzz-gpos.h" - -HB_BEGIN_HEADER - - -/* shared tables */ - -struct HB_ValueRecord_ -{ - HB_Short XPlacement; /* horizontal adjustment for - placement */ - HB_Short YPlacement; /* vertical adjustment for - placement */ - HB_Short XAdvance; /* horizontal adjustment for - advance */ - HB_Short YAdvance; /* vertical adjustment for - advance */ - HB_Device XPlacementDevice; /* device table for horizontal - placement */ - HB_Device YPlacementDevice; /* device table for vertical - placement */ - HB_Device XAdvanceDevice; /* device table for horizontal - advance */ - HB_Device YAdvanceDevice; /* device table for vertical - advance */ - HB_UShort XIdPlacement; /* horizontal placement metric ID */ - HB_UShort YIdPlacement; /* vertical placement metric ID */ - HB_UShort XIdAdvance; /* horizontal advance metric ID */ - HB_UShort YIdAdvance; /* vertical advance metric ID */ -}; - -typedef struct HB_ValueRecord_ HB_ValueRecord; - - -/* Mask values to scan the value format of the ValueRecord structure. - We always expand compressed ValueRecords of the font. */ - -#define HB_GPOS_FORMAT_HAVE_X_PLACEMENT 0x0001 -#define HB_GPOS_FORMAT_HAVE_Y_PLACEMENT 0x0002 -#define HB_GPOS_FORMAT_HAVE_X_ADVANCE 0x0004 -#define HB_GPOS_FORMAT_HAVE_Y_ADVANCE 0x0008 -#define HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE 0x0010 -#define HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE 0x0020 -#define HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE 0x0040 -#define HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE 0x0080 -#define HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT 0x0100 -#define HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT 0x0200 -#define HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE 0x0400 -#define HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE 0x0800 - - -struct HB_AnchorFormat1_ -{ - HB_Short XCoordinate; /* horizontal value */ - HB_Short YCoordinate; /* vertical value */ -}; - -typedef struct HB_AnchorFormat1_ HB_AnchorFormat1; - - -struct HB_AnchorFormat2_ -{ - HB_Short XCoordinate; /* horizontal value */ - HB_Short YCoordinate; /* vertical value */ - HB_UShort AnchorPoint; /* index to glyph contour point */ -}; - -typedef struct HB_AnchorFormat2_ HB_AnchorFormat2; - - -struct HB_AnchorFormat3_ -{ - HB_Short XCoordinate; /* horizontal value */ - HB_Short YCoordinate; /* vertical value */ - HB_Device XDeviceTable; /* device table for X coordinate */ - HB_Device YDeviceTable; /* device table for Y coordinate */ -}; - -typedef struct HB_AnchorFormat3_ HB_AnchorFormat3; - - -struct HB_AnchorFormat4_ -{ - HB_UShort XIdAnchor; /* horizontal metric ID */ - HB_UShort YIdAnchor; /* vertical metric ID */ -}; - -typedef struct HB_AnchorFormat4_ HB_AnchorFormat4; - - -struct HB_Anchor_ -{ - HB_UShort PosFormat; /* 1, 2, 3, or 4 -- 0 indicates - that there is no Anchor table */ - - union - { - HB_AnchorFormat1 af1; - HB_AnchorFormat2 af2; - HB_AnchorFormat3 af3; - HB_AnchorFormat4 af4; - } af; -}; - -typedef struct HB_Anchor_ HB_Anchor; - - -struct HB_MarkRecord_ -{ - HB_UShort Class; /* mark class */ - HB_Anchor MarkAnchor; /* anchor table */ -}; - -typedef struct HB_MarkRecord_ HB_MarkRecord; - - -struct HB_MarkArray_ -{ - HB_UShort MarkCount; /* number of MarkRecord tables */ - HB_MarkRecord* MarkRecord; /* array of MarkRecord tables */ -}; - -typedef struct HB_MarkArray_ HB_MarkArray; - - -/* LookupType 1 */ - -struct HB_SinglePosFormat1_ -{ - HB_ValueRecord Value; /* ValueRecord for all covered - glyphs */ -}; - -typedef struct HB_SinglePosFormat1_ HB_SinglePosFormat1; - - -struct HB_SinglePosFormat2_ -{ - HB_UShort ValueCount; /* number of ValueRecord tables */ - HB_ValueRecord* Value; /* array of ValueRecord tables */ -}; - -typedef struct HB_SinglePosFormat2_ HB_SinglePosFormat2; - - -struct HB_SinglePos_ -{ - HB_UShort PosFormat; /* 1 or 2 */ - HB_Coverage Coverage; /* Coverage table */ - - HB_UShort ValueFormat; /* format of ValueRecord table */ - - union - { - HB_SinglePosFormat1 spf1; - HB_SinglePosFormat2 spf2; - } spf; -}; - -typedef struct HB_SinglePos_ HB_SinglePos; - - -/* LookupType 2 */ - -struct HB_PairValueRecord_ -{ - HB_UShort SecondGlyph; /* glyph ID for second glyph */ - HB_ValueRecord Value1; /* pos. data for first glyph */ - HB_ValueRecord Value2; /* pos. data for second glyph */ -}; - -typedef struct HB_PairValueRecord_ HB_PairValueRecord; - - -struct HB_PairSet_ -{ - HB_UShort PairValueCount; - /* number of PairValueRecord tables */ - HB_PairValueRecord* PairValueRecord; - /* array of PairValueRecord tables */ -}; - -typedef struct HB_PairSet_ HB_PairSet; - - -struct HB_PairPosFormat1_ -{ - HB_UShort PairSetCount; /* number of PairSet tables */ - HB_PairSet* PairSet; /* array of PairSet tables */ -}; - -typedef struct HB_PairPosFormat1_ HB_PairPosFormat1; - - -struct HB_Class2Record_ -{ - HB_ValueRecord Value1; /* pos. data for first glyph */ - HB_ValueRecord Value2; /* pos. data for second glyph */ -}; - -typedef struct HB_Class2Record_ HB_Class2Record; - - -struct HB_Class1Record_ -{ - HB_Class2Record* Class2Record; /* array of Class2Record tables */ -}; - -typedef struct HB_Class1Record_ HB_Class1Record; - - -struct HB_PairPosFormat2_ -{ - HB_ClassDefinition ClassDef1; /* class def. for first glyph */ - HB_ClassDefinition ClassDef2; /* class def. for second glyph */ - HB_UShort Class1Count; /* number of classes in ClassDef1 - table */ - HB_UShort Class2Count; /* number of classes in ClassDef2 - table */ - HB_Class1Record* Class1Record; /* array of Class1Record tables */ -}; - -typedef struct HB_PairPosFormat2_ HB_PairPosFormat2; - - -struct HB_PairPos_ -{ - HB_UShort PosFormat; /* 1 or 2 */ - HB_Coverage Coverage; /* Coverage table */ - HB_UShort ValueFormat1; /* format of ValueRecord table - for first glyph */ - HB_UShort ValueFormat2; /* format of ValueRecord table - for second glyph */ - - union - { - HB_PairPosFormat1 ppf1; - HB_PairPosFormat2 ppf2; - } ppf; -}; - -typedef struct HB_PairPos_ HB_PairPos; - - -/* LookupType 3 */ - -struct HB_EntryExitRecord_ -{ - HB_Anchor EntryAnchor; /* entry Anchor table */ - HB_Anchor ExitAnchor; /* exit Anchor table */ -}; - - -typedef struct HB_EntryExitRecord_ HB_EntryExitRecord; - -struct HB_CursivePos_ -{ - HB_UShort PosFormat; /* always 1 */ - HB_Coverage Coverage; /* Coverage table */ - HB_UShort EntryExitCount; - /* number of EntryExitRecord tables */ - HB_EntryExitRecord* EntryExitRecord; - /* array of EntryExitRecord tables */ -}; - -typedef struct HB_CursivePos_ HB_CursivePos; - - -/* LookupType 4 */ - -struct HB_BaseRecord_ -{ - HB_Anchor* BaseAnchor; /* array of base glyph anchor - tables */ -}; - -typedef struct HB_BaseRecord_ HB_BaseRecord; - - -struct HB_BaseArray_ -{ - HB_UShort BaseCount; /* number of BaseRecord tables */ - HB_BaseRecord* BaseRecord; /* array of BaseRecord tables */ -}; - -typedef struct HB_BaseArray_ HB_BaseArray; - - -struct HB_MarkBasePos_ -{ - HB_UShort PosFormat; /* always 1 */ - HB_Coverage MarkCoverage; /* mark glyph coverage table */ - HB_Coverage BaseCoverage; /* base glyph coverage table */ - HB_UShort ClassCount; /* number of mark classes */ - HB_MarkArray MarkArray; /* mark array table */ - HB_BaseArray BaseArray; /* base array table */ -}; - -typedef struct HB_MarkBasePos_ HB_MarkBasePos; - - -/* LookupType 5 */ - -struct HB_ComponentRecord_ -{ - HB_Anchor* LigatureAnchor; /* array of ligature glyph anchor - tables */ -}; - -typedef struct HB_ComponentRecord_ HB_ComponentRecord; - - -struct HB_LigatureAttach_ -{ - HB_UShort ComponentCount; - /* number of ComponentRecord tables */ - HB_ComponentRecord* ComponentRecord; - /* array of ComponentRecord tables */ -}; - -typedef struct HB_LigatureAttach_ HB_LigatureAttach; - - -struct HB_LigatureArray_ -{ - HB_UShort LigatureCount; /* number of LigatureAttach tables */ - HB_LigatureAttach* LigatureAttach; - /* array of LigatureAttach tables */ -}; - -typedef struct HB_LigatureArray_ HB_LigatureArray; - - -struct HB_MarkLigPos_ -{ - HB_UShort PosFormat; /* always 1 */ - HB_Coverage MarkCoverage; /* mark glyph coverage table */ - HB_Coverage LigatureCoverage; - /* ligature glyph coverage table */ - HB_UShort ClassCount; /* number of mark classes */ - HB_MarkArray MarkArray; /* mark array table */ - HB_LigatureArray LigatureArray; /* ligature array table */ -}; - -typedef struct HB_MarkLigPos_ HB_MarkLigPos; - - -/* LookupType 6 */ - -struct HB_Mark2Record_ -{ - HB_Anchor* Mark2Anchor; /* array of mark glyph anchor - tables */ -}; - -typedef struct HB_Mark2Record_ HB_Mark2Record; - - -struct HB_Mark2Array_ -{ - HB_UShort Mark2Count; /* number of Mark2Record tables */ - HB_Mark2Record* Mark2Record; /* array of Mark2Record tables */ -}; - -typedef struct HB_Mark2Array_ HB_Mark2Array; - - -struct HB_MarkMarkPos_ -{ - HB_UShort PosFormat; /* always 1 */ - HB_Coverage Mark1Coverage; /* first mark glyph coverage table */ - HB_Coverage Mark2Coverage; /* second mark glyph coverave table */ - HB_UShort ClassCount; /* number of combining mark classes */ - HB_MarkArray Mark1Array; /* MarkArray table for first mark */ - HB_Mark2Array Mark2Array; /* MarkArray table for second mark */ -}; - -typedef struct HB_MarkMarkPos_ HB_MarkMarkPos; - - -/* needed by both lookup type 7 and 8 */ - -struct HB_PosLookupRecord_ -{ - HB_UShort SequenceIndex; /* index into current - glyph sequence */ - HB_UShort LookupListIndex; /* Lookup to apply to that pos. */ -}; - -typedef struct HB_PosLookupRecord_ HB_PosLookupRecord; - - -/* LookupType 7 */ - -struct HB_PosRule_ -{ - HB_UShort GlyphCount; /* total number of input glyphs */ - HB_UShort PosCount; /* number of PosLookupRecord tables */ - HB_UShort* Input; /* array of input glyph IDs */ - HB_PosLookupRecord* PosLookupRecord; - /* array of PosLookupRecord tables */ -}; - -typedef struct HB_PosRule_ HB_PosRule; - - -struct HB_PosRuleSet_ -{ - HB_UShort PosRuleCount; /* number of PosRule tables */ - HB_PosRule* PosRule; /* array of PosRule tables */ -}; - -typedef struct HB_PosRuleSet_ HB_PosRuleSet; - - -struct HB_ContextPosFormat1_ -{ - HB_Coverage Coverage; /* Coverage table */ - HB_UShort PosRuleSetCount; /* number of PosRuleSet tables */ - HB_PosRuleSet* PosRuleSet; /* array of PosRuleSet tables */ -}; - -typedef struct HB_ContextPosFormat1_ HB_ContextPosFormat1; - - -struct HB_PosClassRule_ -{ - HB_UShort GlyphCount; /* total number of context classes */ - HB_UShort PosCount; /* number of PosLookupRecord tables */ - HB_UShort* Class; /* array of classes */ - HB_PosLookupRecord* PosLookupRecord; - /* array of PosLookupRecord tables */ -}; - -typedef struct HB_PosClassRule_ HB_PosClassRule; - - -struct HB_PosClassSet_ -{ - HB_UShort PosClassRuleCount; - /* number of PosClassRule tables */ - HB_PosClassRule* PosClassRule; /* array of PosClassRule tables */ -}; - -typedef struct HB_PosClassSet_ HB_PosClassSet; - - -/* The `MaxContextLength' field is not defined in the TTO specification - but simplifies the implementation of this format. It holds the - maximal context length used in the context rules. */ - -struct HB_ContextPosFormat2_ -{ - HB_UShort MaxContextLength; - /* maximal context length */ - HB_Coverage Coverage; /* Coverage table */ - HB_ClassDefinition ClassDef; /* ClassDef table */ - HB_UShort PosClassSetCount; - /* number of PosClassSet tables */ - HB_PosClassSet* PosClassSet; /* array of PosClassSet tables */ -}; - -typedef struct HB_ContextPosFormat2_ HB_ContextPosFormat2; - - -struct HB_ContextPosFormat3_ -{ - HB_UShort GlyphCount; /* number of input glyphs */ - HB_UShort PosCount; /* number of PosLookupRecord tables */ - HB_Coverage* Coverage; /* array of Coverage tables */ - HB_PosLookupRecord* PosLookupRecord; - /* array of PosLookupRecord tables */ -}; - -typedef struct HB_ContextPosFormat3_ HB_ContextPosFormat3; - - -struct HB_ContextPos_ -{ - HB_UShort PosFormat; /* 1, 2, or 3 */ - - union - { - HB_ContextPosFormat1 cpf1; - HB_ContextPosFormat2 cpf2; - HB_ContextPosFormat3 cpf3; - } cpf; -}; - -typedef struct HB_ContextPos_ HB_ContextPos; - - -/* LookupType 8 */ - -struct HB_ChainPosRule_ -{ - HB_UShort BacktrackGlyphCount; - /* total number of backtrack glyphs */ - HB_UShort* Backtrack; /* array of backtrack glyph IDs */ - HB_UShort InputGlyphCount; - /* total number of input glyphs */ - HB_UShort* Input; /* array of input glyph IDs */ - HB_UShort LookaheadGlyphCount; - /* total number of lookahead glyphs */ - HB_UShort* Lookahead; /* array of lookahead glyph IDs */ - HB_UShort PosCount; /* number of PosLookupRecords */ - HB_PosLookupRecord* PosLookupRecord; - /* array of PosLookupRecords */ -}; - -typedef struct HB_ChainPosRule_ HB_ChainPosRule; - - -struct HB_ChainPosRuleSet_ -{ - HB_UShort ChainPosRuleCount; - /* number of ChainPosRule tables */ - HB_ChainPosRule* ChainPosRule; /* array of ChainPosRule tables */ -}; - -typedef struct HB_ChainPosRuleSet_ HB_ChainPosRuleSet; - - -struct HB_ChainContextPosFormat1_ -{ - HB_Coverage Coverage; /* Coverage table */ - HB_UShort ChainPosRuleSetCount; - /* number of ChainPosRuleSet tables */ - HB_ChainPosRuleSet* ChainPosRuleSet; - /* array of ChainPosRuleSet tables */ -}; - -typedef struct HB_ChainContextPosFormat1_ HB_ChainContextPosFormat1; - - -struct HB_ChainPosClassRule_ -{ - HB_UShort BacktrackGlyphCount; - /* total number of backtrack - classes */ - HB_UShort* Backtrack; /* array of backtrack classes */ - HB_UShort InputGlyphCount; - /* total number of context classes */ - HB_UShort* Input; /* array of context classes */ - HB_UShort LookaheadGlyphCount; - /* total number of lookahead - classes */ - HB_UShort* Lookahead; /* array of lookahead classes */ - HB_UShort PosCount; /* number of PosLookupRecords */ - HB_PosLookupRecord* PosLookupRecord; - /* array of substitution lookups */ -}; - -typedef struct HB_ChainPosClassRule_ HB_ChainPosClassRule; - - -struct HB_ChainPosClassSet_ -{ - HB_UShort ChainPosClassRuleCount; - /* number of ChainPosClassRule - tables */ - HB_ChainPosClassRule* ChainPosClassRule; - /* array of ChainPosClassRule - tables */ -}; - -typedef struct HB_ChainPosClassSet_ HB_ChainPosClassSet; - - -/* The `MaxXXXLength' fields are not defined in the TTO specification - but simplifies the implementation of this format. It holds the - maximal context length used in the specific context rules. */ - -struct HB_ChainContextPosFormat2_ -{ - HB_Coverage Coverage; /* Coverage table */ - - HB_UShort MaxBacktrackLength; - /* maximal backtrack length */ - HB_ClassDefinition BacktrackClassDef; - /* BacktrackClassDef table */ - HB_UShort MaxInputLength; - /* maximal input length */ - HB_ClassDefinition InputClassDef; - /* InputClassDef table */ - HB_UShort MaxLookaheadLength; - /* maximal lookahead length */ - HB_ClassDefinition LookaheadClassDef; - /* LookaheadClassDef table */ - - HB_UShort ChainPosClassSetCount; - /* number of ChainPosClassSet - tables */ - HB_ChainPosClassSet* ChainPosClassSet; - /* array of ChainPosClassSet - tables */ -}; - -typedef struct HB_ChainContextPosFormat2_ HB_ChainContextPosFormat2; - - -struct HB_ChainContextPosFormat3_ -{ - HB_UShort BacktrackGlyphCount; - /* number of backtrack glyphs */ - HB_Coverage* BacktrackCoverage; - /* array of backtrack Coverage - tables */ - HB_UShort InputGlyphCount; - /* number of input glyphs */ - HB_Coverage* InputCoverage; - /* array of input coverage - tables */ - HB_UShort LookaheadGlyphCount; - /* number of lookahead glyphs */ - HB_Coverage* LookaheadCoverage; - /* array of lookahead coverage - tables */ - HB_UShort PosCount; /* number of PosLookupRecords */ - HB_PosLookupRecord* PosLookupRecord; - /* array of substitution lookups */ -}; - -typedef struct HB_ChainContextPosFormat3_ HB_ChainContextPosFormat3; - - -struct HB_ChainContextPos_ -{ - HB_UShort PosFormat; /* 1, 2, or 3 */ - - union - { - HB_ChainContextPosFormat1 ccpf1; - HB_ChainContextPosFormat2 ccpf2; - HB_ChainContextPosFormat3 ccpf3; - } ccpf; -}; - -typedef struct HB_ChainContextPos_ HB_ChainContextPos; - - -#if 0 -/* LookupType 10 */ -struct HB_ExtensionPos_ -{ - HB_UShort PosFormat; /* always 1 */ - HB_UShort LookuptType; /* lookup-type of referenced subtable */ - HB_GPOS_SubTable *subtable; /* referenced subtable */ -}; - -typedef struct HB_ExtensionPos_ HB_ExtensionPos; -#endif - - -union HB_GPOS_SubTable_ -{ - HB_SinglePos single; - HB_PairPos pair; - HB_CursivePos cursive; - HB_MarkBasePos markbase; - HB_MarkLigPos marklig; - HB_MarkMarkPos markmark; - HB_ContextPos context; - HB_ChainContextPos chain; -}; - -typedef union HB_GPOS_SubTable_ HB_GPOS_SubTable; - - - -HB_INTERNAL HB_Error -_HB_GPOS_Load_SubTable( HB_GPOS_SubTable* st, - HB_Stream stream, - HB_UShort lookup_type ); - -HB_INTERNAL void -_HB_GPOS_Free_SubTable( HB_GPOS_SubTable* st, - HB_UShort lookup_type ); - -HB_END_HEADER - -#endif /* HARFBUZZ_GPOS_PRIVATE_H */ diff --git a/src/harfbuzz-gpos.c b/src/harfbuzz-gpos.c deleted file mode 100644 index c4e8a786c..000000000 --- a/src/harfbuzz-gpos.c +++ /dev/null @@ -1,6071 +0,0 @@ -/* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2006 Behdad Esfahbod - * Copyright (C) 2007 Red Hat, Inc. - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Red Hat Author(s): Behdad Esfahbod - */ - -#include "harfbuzz-impl.h" -#include "harfbuzz-gpos-private.h" -#include "harfbuzz-open-private.h" -#include "harfbuzz-gdef-private.h" - -struct GPOS_Instance_ -{ - HB_GPOSHeader* gpos; - HB_Font font; - HB_Bool dvi; - HB_UShort load_flags; /* how the glyph should be loaded */ - HB_Bool r2l; - - HB_UShort last; /* the last valid glyph -- used - with cursive positioning */ - HB_Fixed anchor_x; /* the coordinates of the anchor point */ - HB_Fixed anchor_y; /* of the last valid glyph */ -}; - -typedef struct GPOS_Instance_ GPOS_Instance; - - -static HB_Error GPOS_Do_Glyph_Lookup( GPOS_Instance* gpi, - HB_UShort lookup_index, - HB_Buffer buffer, - HB_UShort context_length, - int nesting_level ); - - - -/* the client application must replace this with something more - meaningful if multiple master fonts are to be supported. */ - -static HB_Error default_mmfunc( HB_Font font, - HB_UShort metric_id, - HB_Fixed* metric_value, - void* data ) -{ - HB_UNUSED(font); - HB_UNUSED(metric_id); - HB_UNUSED(metric_value); - HB_UNUSED(data); - return ERR(HB_Err_Not_Covered); /* ERR() call intended */ -} - - - -HB_Error HB_Load_GPOS_Table( HB_Font font, - HB_GPOSHeader** retptr, - hb_ot_layout_t *layout ) -{ - HB_UInt cur_offset, new_offset, base_offset; - - HB_GPOSHeader* gpos; - - HB_Stream stream = font->stream; - HB_Error error; - - - if ( !retptr || !layout ) - return ERR(HB_Err_Invalid_Argument); - - if ( GOTO_Table( TTAG_GPOS ) ) - return error; - - base_offset = FILE_Pos(); - - if ( ALLOC ( gpos, sizeof( *gpos ) ) ) - return error; - - gpos->gfunc = (HB_GlyphFunction) FT_Load_Glyph; - gpos->mmfunc = default_mmfunc; - - /* skip version */ - - if ( FILE_Seek( base_offset + 4L ) || - ACCESS_Frame( 2L ) ) - goto Fail4; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_ScriptList( &gpos->ScriptList, - stream ) ) != HB_Err_Ok ) - goto Fail4; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_FeatureList( &gpos->FeatureList, - stream ) ) != HB_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_LookupList( &gpos->LookupList, - stream, HB_Type_GPOS ) ) != HB_Err_Ok ) - goto Fail2; - - gpos->layout = layout; /* can be NULL */ - - *retptr = gpos; - - return HB_Err_Ok; - -Fail2: - _HB_OPEN_Free_FeatureList( &gpos->FeatureList ); - -Fail3: - _HB_OPEN_Free_ScriptList( &gpos->ScriptList ); - -Fail4: - FREE( gpos ); - - return error; -} - - -HB_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos ) -{ - _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS ); - _HB_OPEN_Free_FeatureList( &gpos->FeatureList ); - _HB_OPEN_Free_ScriptList( &gpos->ScriptList ); - - FREE( gpos ); - - return HB_Err_Ok; -} - - -/***************************** - * SubTable related functions - *****************************/ - -/* shared tables */ - -/* ValueRecord */ - -/* There is a subtle difference in the specs between a `table' and a - `record' -- offsets for device tables in ValueRecords are taken from - the parent table and not the parent record. */ - -static HB_Error Load_ValueRecord( HB_ValueRecord* vr, - HB_UShort format, - HB_UInt base_offset, - HB_Stream stream ) -{ - HB_Error error; - - HB_UInt cur_offset, new_offset; - - - if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT ) - { - if ( ACCESS_Frame( 2L ) ) - return error; - - vr->XPlacement = GET_Short(); - - FORGET_Frame(); - } - else - vr->XPlacement = 0; - - if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT ) - { - if ( ACCESS_Frame( 2L ) ) - return error; - - vr->YPlacement = GET_Short(); - - FORGET_Frame(); - } - else - vr->YPlacement = 0; - - if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE ) - { - if ( ACCESS_Frame( 2L ) ) - return error; - - vr->XAdvance = GET_Short(); - - FORGET_Frame(); - } - else - vr->XAdvance = 0; - - if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE ) - { - if ( ACCESS_Frame( 2L ) ) - return error; - - vr->YAdvance = GET_Short(); - - FORGET_Frame(); - } - else - vr->YAdvance = 0; - - if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE ) - { - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Device( &vr->XPlacementDevice, - stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - } - else - goto empty1; - } - else - { - empty1: - vr->XPlacementDevice.StartSize = 0; - vr->XPlacementDevice.EndSize = 0; - vr->XPlacementDevice.DeltaValue = NULL; - } - - if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Device( &vr->YPlacementDevice, - stream ) ) != HB_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - } - else - goto empty2; - } - else - { - empty2: - vr->YPlacementDevice.StartSize = 0; - vr->YPlacementDevice.EndSize = 0; - vr->YPlacementDevice.DeltaValue = NULL; - } - - if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Device( &vr->XAdvanceDevice, - stream ) ) != HB_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - } - else - goto empty3; - } - else - { - empty3: - vr->XAdvanceDevice.StartSize = 0; - vr->XAdvanceDevice.EndSize = 0; - vr->XAdvanceDevice.DeltaValue = NULL; - } - - if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Device( &vr->YAdvanceDevice, - stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - else - goto empty4; - } - else - { - empty4: - vr->YAdvanceDevice.StartSize = 0; - vr->YAdvanceDevice.EndSize = 0; - vr->YAdvanceDevice.DeltaValue = NULL; - } - - if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - vr->XIdPlacement = GET_UShort(); - - FORGET_Frame(); - } - else - vr->XIdPlacement = 0; - - if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - vr->YIdPlacement = GET_UShort(); - - FORGET_Frame(); - } - else - vr->YIdPlacement = 0; - - if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - vr->XIdAdvance = GET_UShort(); - - FORGET_Frame(); - } - else - vr->XIdAdvance = 0; - - if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - vr->YIdAdvance = GET_UShort(); - - FORGET_Frame(); - } - else - vr->YIdAdvance = 0; - - return HB_Err_Ok; - -Fail1: - _HB_OPEN_Free_Device( &vr->YAdvanceDevice ); - -Fail2: - _HB_OPEN_Free_Device( &vr->XAdvanceDevice ); - -Fail3: - _HB_OPEN_Free_Device( &vr->YPlacementDevice ); - return error; -} - - -static void Free_ValueRecord( HB_ValueRecord* vr, - HB_UShort format ) -{ - if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE ) - _HB_OPEN_Free_Device( &vr->YAdvanceDevice ); - if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE ) - _HB_OPEN_Free_Device( &vr->XAdvanceDevice ); - if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE ) - _HB_OPEN_Free_Device( &vr->YPlacementDevice ); - if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE ) - _HB_OPEN_Free_Device( &vr->XPlacementDevice ); -} - - -static HB_Error Get_ValueRecord( GPOS_Instance* gpi, - HB_ValueRecord* vr, - HB_UShort format, - HB_Position gd ) -{ - HB_Fixed value; - HB_Short pixel_value; - HB_Error error = HB_Err_Ok; - HB_GPOSHeader* gpos = gpi->gpos; - - HB_UShort x_ppem, y_ppem; - HB_16Dot16 x_scale, y_scale; - - - if ( !format ) - return HB_Err_Ok; - - x_ppem = gpi->font->size->metrics.x_ppem; - y_ppem = gpi->font->size->metrics.y_ppem; - x_scale = gpi->font->size->metrics.x_scale; - y_scale = gpi->font->size->metrics.y_scale; - - /* design units -> fractional pixel */ - - if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT ) - gd->x_pos += x_scale * vr->XPlacement / 0x10000; - if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT ) - gd->y_pos += y_scale * vr->YPlacement / 0x10000; - if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE ) - gd->x_advance += x_scale * vr->XAdvance / 0x10000; - if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE ) - gd->y_advance += y_scale * vr->YAdvance / 0x10000; - - if ( !gpi->dvi ) - { - /* pixel -> fractional pixel */ - - if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE ) - { - _HB_OPEN_Get_Device( &vr->XPlacementDevice, x_ppem, &pixel_value ); - gd->x_pos += pixel_value << 6; - } - if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE ) - { - _HB_OPEN_Get_Device( &vr->YPlacementDevice, y_ppem, &pixel_value ); - gd->y_pos += pixel_value << 6; - } - if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE ) - { - _HB_OPEN_Get_Device( &vr->XAdvanceDevice, x_ppem, &pixel_value ); - gd->x_advance += pixel_value << 6; - } - if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE ) - { - _HB_OPEN_Get_Device( &vr->YAdvanceDevice, y_ppem, &pixel_value ); - gd->y_advance += pixel_value << 6; - } - } - - /* values returned from mmfunc() are already in fractional pixels */ - - if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT ) - { - error = (gpos->mmfunc)( gpi->font, vr->XIdPlacement, - &value, gpos->data ); - if ( error ) - return error; - gd->x_pos += value; - } - if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT ) - { - error = (gpos->mmfunc)( gpi->font, vr->YIdPlacement, - &value, gpos->data ); - if ( error ) - return error; - gd->y_pos += value; - } - if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE ) - { - error = (gpos->mmfunc)( gpi->font, vr->XIdAdvance, - &value, gpos->data ); - if ( error ) - return error; - gd->x_advance += value; - } - if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE ) - { - error = (gpos->mmfunc)( gpi->font, vr->YIdAdvance, - &value, gpos->data ); - if ( error ) - return error; - gd->y_advance += value; - } - - return error; -} - - -/* AnchorFormat1 */ -/* AnchorFormat2 */ -/* AnchorFormat3 */ -/* AnchorFormat4 */ - -static HB_Error Load_Anchor( HB_Anchor* an, - HB_Stream stream ) -{ - HB_Error error; - - HB_UInt cur_offset, new_offset, base_offset; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - an->PosFormat = GET_UShort(); - - FORGET_Frame(); - - switch ( an->PosFormat ) - { - case 1: - if ( ACCESS_Frame( 4L ) ) - return error; - - an->af.af1.XCoordinate = GET_Short(); - an->af.af1.YCoordinate = GET_Short(); - - FORGET_Frame(); - break; - - case 2: - if ( ACCESS_Frame( 6L ) ) - return error; - - an->af.af2.XCoordinate = GET_Short(); - an->af.af2.YCoordinate = GET_Short(); - an->af.af2.AnchorPoint = GET_UShort(); - - FORGET_Frame(); - break; - - case 3: - if ( ACCESS_Frame( 6L ) ) - return error; - - an->af.af3.XCoordinate = GET_Short(); - an->af.af3.YCoordinate = GET_Short(); - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Device( &an->af.af3.XDeviceTable, - stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - } - else - { - an->af.af3.XDeviceTable.StartSize = 0; - an->af.af3.XDeviceTable.EndSize = 0; - an->af.af3.XDeviceTable.DeltaValue = NULL; - } - - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Device( &an->af.af3.YDeviceTable, - stream ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - else - { - an->af.af3.YDeviceTable.StartSize = 0; - an->af.af3.YDeviceTable.EndSize = 0; - an->af.af3.YDeviceTable.DeltaValue = NULL; - } - break; - - case 4: - if ( ACCESS_Frame( 4L ) ) - return error; - - an->af.af4.XIdAnchor = GET_UShort(); - an->af.af4.YIdAnchor = GET_UShort(); - - FORGET_Frame(); - break; - - default: - return ERR(HB_Err_Invalid_SubTable_Format); - } - - return HB_Err_Ok; - -Fail: - _HB_OPEN_Free_Device( &an->af.af3.XDeviceTable ); - return error; -} - - -static void Free_Anchor( HB_Anchor* an ) -{ - if ( an->PosFormat == 3 ) - { - _HB_OPEN_Free_Device( &an->af.af3.YDeviceTable ); - _HB_OPEN_Free_Device( &an->af.af3.XDeviceTable ); - } -} - - -static HB_Error Get_Anchor( GPOS_Instance* gpi, - HB_Anchor* an, - HB_UShort glyph_index, - HB_Fixed* x_value, - HB_Fixed* y_value ) -{ - HB_Error error = HB_Err_Ok; - - FT_Outline outline; - HB_GPOSHeader* gpos = gpi->gpos; - HB_UShort ap; - - HB_Short pixel_value; - HB_UShort load_flags; - - HB_UShort x_ppem, y_ppem; - HB_16Dot16 x_scale, y_scale; - - - x_ppem = gpi->font->size->metrics.x_ppem; - y_ppem = gpi->font->size->metrics.y_ppem; - x_scale = gpi->font->size->metrics.x_scale; - y_scale = gpi->font->size->metrics.y_scale; - - switch ( an->PosFormat ) - { - case 0: - /* The special case of an empty AnchorTable */ - default: - - return HB_Err_Not_Covered; - - case 1: - *x_value = x_scale * an->af.af1.XCoordinate / 0x10000; - *y_value = y_scale * an->af.af1.YCoordinate / 0x10000; - break; - - case 2: - /* glyphs must be scaled */ - - load_flags = gpi->load_flags & ~FT_LOAD_NO_SCALE; - - if ( !gpi->dvi ) - { - error = (gpos->gfunc)( gpi->font, glyph_index, load_flags ); - if ( error ) - return error; - - if ( gpi->font->glyph->format != ft_glyph_format_outline ) - return ERR(HB_Err_Invalid_SubTable); - - ap = an->af.af2.AnchorPoint; - - outline = gpi->font->glyph->outline; - - /* if n_points is set to zero, we use the design coordinate value pair. - * This can happen e.g. for sbit glyphs. */ - if ( !outline.n_points ) - goto no_contour_point; - - if ( ap >= outline.n_points ) - return ERR(HB_Err_Invalid_SubTable); - - *x_value = outline.points[ap].x; - *y_value = outline.points[ap].y; - } - else - { - no_contour_point: - *x_value = x_scale * an->af.af3.XCoordinate / 0x10000; - *y_value = y_scale * an->af.af3.YCoordinate / 0x10000; - } - break; - - case 3: - if ( !gpi->dvi ) - { - _HB_OPEN_Get_Device( &an->af.af3.XDeviceTable, x_ppem, &pixel_value ); - *x_value = pixel_value << 6; - _HB_OPEN_Get_Device( &an->af.af3.YDeviceTable, y_ppem, &pixel_value ); - *y_value = pixel_value << 6; - } - else - *x_value = *y_value = 0; - - *x_value += x_scale * an->af.af3.XCoordinate / 0x10000; - *y_value += y_scale * an->af.af3.YCoordinate / 0x10000; - break; - - case 4: - error = (gpos->mmfunc)( gpi->font, an->af.af4.XIdAnchor, - x_value, gpos->data ); - if ( error ) - return error; - - error = (gpos->mmfunc)( gpi->font, an->af.af4.YIdAnchor, - y_value, gpos->data ); - if ( error ) - return error; - break; - } - - return error; -} - - -/* MarkArray */ - -static HB_Error Load_MarkArray ( HB_MarkArray* ma, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_MarkRecord* mr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = ma->MarkCount = GET_UShort(); - - FORGET_Frame(); - - ma->MarkRecord = NULL; - - if ( ALLOC_ARRAY( ma->MarkRecord, count, HB_MarkRecord ) ) - return error; - - mr = ma->MarkRecord; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 4L ) ) - goto Fail; - - mr[n].Class = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Anchor( &mr[n].MarkAnchor, stream ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail: - for ( m = 0; m < n; m++ ) - Free_Anchor( &mr[m].MarkAnchor ); - - FREE( mr ); - return error; -} - - -static void Free_MarkArray( HB_MarkArray* ma ) -{ - HB_UShort n, count; - - HB_MarkRecord* mr; - - - if ( ma->MarkRecord ) - { - count = ma->MarkCount; - mr = ma->MarkRecord; - - for ( n = 0; n < count; n++ ) - Free_Anchor( &mr[n].MarkAnchor ); - - FREE( mr ); - } -} - - -/* LookupType 1 */ - -/* SinglePosFormat1 */ -/* SinglePosFormat2 */ - -static HB_Error Load_SinglePos( HB_GPOS_SubTable* st, - HB_Stream stream ) -{ - HB_Error error; - HB_SinglePos* sp = &st->single; - - HB_UShort n, m, count, format; - HB_UInt cur_offset, new_offset, base_offset; - - HB_ValueRecord* vr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 6L ) ) - return error; - - sp->PosFormat = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - format = sp->ValueFormat = GET_UShort(); - - FORGET_Frame(); - - if ( !format ) - return ERR(HB_Err_Invalid_SubTable); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &sp->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - switch ( sp->PosFormat ) - { - case 1: - error = Load_ValueRecord( &sp->spf.spf1.Value, format, - base_offset, stream ); - if ( error ) - goto Fail2; - break; - - case 2: - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = sp->spf.spf2.ValueCount = GET_UShort(); - - FORGET_Frame(); - - sp->spf.spf2.Value = NULL; - - if ( ALLOC_ARRAY( sp->spf.spf2.Value, count, HB_ValueRecord ) ) - goto Fail2; - - vr = sp->spf.spf2.Value; - - for ( n = 0; n < count; n++ ) - { - error = Load_ValueRecord( &vr[n], format, base_offset, stream ); - if ( error ) - goto Fail1; - } - break; - - default: - return ERR(HB_Err_Invalid_SubTable_Format); - } - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - Free_ValueRecord( &vr[m], format ); - - FREE( vr ); - -Fail2: - _HB_OPEN_Free_Coverage( &sp->Coverage ); - return error; -} - - -static void Free_SinglePos( HB_GPOS_SubTable* st ) -{ - HB_UShort n, count, format; - HB_SinglePos* sp = &st->single; - - HB_ValueRecord* v; - - - format = sp->ValueFormat; - - switch ( sp->PosFormat ) - { - case 1: - Free_ValueRecord( &sp->spf.spf1.Value, format ); - break; - - case 2: - if ( sp->spf.spf2.Value ) - { - count = sp->spf.spf2.ValueCount; - v = sp->spf.spf2.Value; - - for ( n = 0; n < count; n++ ) - Free_ValueRecord( &v[n], format ); - - FREE( v ); - } - break; - default: - break; - } - - _HB_OPEN_Free_Coverage( &sp->Coverage ); -} - -static HB_Error Lookup_SinglePos( GPOS_Instance* gpi, - HB_GPOS_SubTable* st, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort index, property; - HB_Error error; - HB_GPOSHeader* gpos = gpi->gpos; - HB_SinglePos* sp = &st->single; - - HB_UNUSED(nesting_level); - - if ( context_length != 0xFFFF && context_length < 1 ) - return HB_Err_Not_Covered; - - if ( CHECK_Property( gpos->layout, IN_CURITEM(), flags, &property ) ) - return error; - - error = _HB_OPEN_Coverage_Index( &sp->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - switch ( sp->PosFormat ) - { - case 1: - error = Get_ValueRecord( gpi, &sp->spf.spf1.Value, - sp->ValueFormat, POSITION( buffer->in_pos ) ); - if ( error ) - return error; - break; - - case 2: - if ( index >= sp->spf.spf2.ValueCount ) - return ERR(HB_Err_Invalid_SubTable); - error = Get_ValueRecord( gpi, &sp->spf.spf2.Value[index], - sp->ValueFormat, POSITION( buffer->in_pos ) ); - if ( error ) - return error; - break; - - default: - return ERR(HB_Err_Invalid_SubTable); - } - - (buffer->in_pos)++; - - return HB_Err_Ok; -} - - -/* LookupType 2 */ - -/* PairSet */ - -static HB_Error Load_PairSet ( HB_PairSet* ps, - HB_UShort format1, - HB_UShort format2, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt base_offset; - - HB_PairValueRecord* pvr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = ps->PairValueCount = GET_UShort(); - - FORGET_Frame(); - - ps->PairValueRecord = NULL; - - if ( ALLOC_ARRAY( ps->PairValueRecord, count, HB_PairValueRecord ) ) - return error; - - pvr = ps->PairValueRecord; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - pvr[n].SecondGlyph = GET_UShort(); - - FORGET_Frame(); - - if ( format1 ) - { - error = Load_ValueRecord( &pvr[n].Value1, format1, - base_offset, stream ); - if ( error ) - goto Fail; - } - if ( format2 ) - { - error = Load_ValueRecord( &pvr[n].Value2, format2, - base_offset, stream ); - if ( error ) - { - if ( format1 ) - Free_ValueRecord( &pvr[n].Value1, format1 ); - goto Fail; - } - } - } - - return HB_Err_Ok; - -Fail: - for ( m = 0; m < n; m++ ) - { - if ( format1 ) - Free_ValueRecord( &pvr[m].Value1, format1 ); - if ( format2 ) - Free_ValueRecord( &pvr[m].Value2, format2 ); - } - - FREE( pvr ); - return error; -} - - -static void Free_PairSet( HB_PairSet* ps, - HB_UShort format1, - HB_UShort format2 ) -{ - HB_UShort n, count; - - HB_PairValueRecord* pvr; - - - if ( ps->PairValueRecord ) - { - count = ps->PairValueCount; - pvr = ps->PairValueRecord; - - for ( n = 0; n < count; n++ ) - { - if ( format1 ) - Free_ValueRecord( &pvr[n].Value1, format1 ); - if ( format2 ) - Free_ValueRecord( &pvr[n].Value2, format2 ); - } - - FREE( pvr ); - } -} - - -/* PairPosFormat1 */ - -static HB_Error Load_PairPos1( HB_PairPosFormat1* ppf1, - HB_UShort format1, - HB_UShort format2, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_PairSet* ps; - - - base_offset = FILE_Pos() - 8L; - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = ppf1->PairSetCount = GET_UShort(); - - FORGET_Frame(); - - ppf1->PairSet = NULL; - - if ( ALLOC_ARRAY( ppf1->PairSet, count, HB_PairSet ) ) - return error; - - ps = ppf1->PairSet; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_PairSet( &ps[n], format1, - format2, stream ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail: - for ( m = 0; m < n; m++ ) - Free_PairSet( &ps[m], format1, format2 ); - - FREE( ps ); - return error; -} - - -static void Free_PairPos1( HB_PairPosFormat1* ppf1, - HB_UShort format1, - HB_UShort format2 ) -{ - HB_UShort n, count; - - HB_PairSet* ps; - - - if ( ppf1->PairSet ) - { - count = ppf1->PairSetCount; - ps = ppf1->PairSet; - - for ( n = 0; n < count; n++ ) - Free_PairSet( &ps[n], format1, format2 ); - - FREE( ps ); - } -} - - -/* PairPosFormat2 */ - -static HB_Error Load_PairPos2( HB_PairPosFormat2* ppf2, - HB_UShort format1, - HB_UShort format2, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort m, n, k, count1, count2; - HB_UInt cur_offset, new_offset1, new_offset2, base_offset; - - HB_Class1Record* c1r; - HB_Class2Record* c2r; - - - base_offset = FILE_Pos() - 8L; - - if ( ACCESS_Frame( 8L ) ) - return error; - - new_offset1 = GET_UShort() + base_offset; - new_offset2 = GET_UShort() + base_offset; - - /* `Class1Count' and `Class2Count' are the upper limits for class - values, thus we read it now to make additional safety checks. */ - - count1 = ppf2->Class1Count = GET_UShort(); - count2 = ppf2->Class2Count = GET_UShort(); - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset1 ) || - ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef1, count1, - stream ) ) != HB_Err_Ok ) - return error; - if ( FILE_Seek( new_offset2 ) || - ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef2, count2, - stream ) ) != HB_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - - ppf2->Class1Record = NULL; - - if ( ALLOC_ARRAY( ppf2->Class1Record, count1, HB_Class1Record ) ) - goto Fail2; - - c1r = ppf2->Class1Record; - - for ( m = 0; m < count1; m++ ) - { - c1r[m].Class2Record = NULL; - - if ( ALLOC_ARRAY( c1r[m].Class2Record, count2, HB_Class2Record ) ) - goto Fail1; - - c2r = c1r[m].Class2Record; - - for ( n = 0; n < count2; n++ ) - { - if ( format1 ) - { - error = Load_ValueRecord( &c2r[n].Value1, format1, - base_offset, stream ); - if ( error ) - goto Fail0; - } - if ( format2 ) - { - error = Load_ValueRecord( &c2r[n].Value2, format2, - base_offset, stream ); - if ( error ) - { - if ( format1 ) - Free_ValueRecord( &c2r[n].Value1, format1 ); - goto Fail0; - } - } - } - - continue; - - Fail0: - for ( k = 0; k < n; k++ ) - { - if ( format1 ) - Free_ValueRecord( &c2r[k].Value1, format1 ); - if ( format2 ) - Free_ValueRecord( &c2r[k].Value2, format2 ); - } - goto Fail1; - } - - return HB_Err_Ok; - -Fail1: - for ( k = 0; k < m; k++ ) - { - c2r = c1r[k].Class2Record; - - for ( n = 0; n < count2; n++ ) - { - if ( format1 ) - Free_ValueRecord( &c2r[n].Value1, format1 ); - if ( format2 ) - Free_ValueRecord( &c2r[n].Value2, format2 ); - } - - FREE( c2r ); - } - - FREE( c1r ); -Fail2: - - _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2 ); - -Fail3: - _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1 ); - return error; -} - - -static void Free_PairPos2( HB_PairPosFormat2* ppf2, - HB_UShort format1, - HB_UShort format2 ) -{ - HB_UShort m, n, count1, count2; - - HB_Class1Record* c1r; - HB_Class2Record* c2r; - - - if ( ppf2->Class1Record ) - { - c1r = ppf2->Class1Record; - count1 = ppf2->Class1Count; - count2 = ppf2->Class2Count; - - for ( m = 0; m < count1; m++ ) - { - c2r = c1r[m].Class2Record; - - for ( n = 0; n < count2; n++ ) - { - if ( format1 ) - Free_ValueRecord( &c2r[n].Value1, format1 ); - if ( format2 ) - Free_ValueRecord( &c2r[n].Value2, format2 ); - } - - FREE( c2r ); - } - - FREE( c1r ); - - _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2 ); - _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1 ); - } -} - - -static HB_Error Load_PairPos( HB_GPOS_SubTable* st, - HB_Stream stream ) -{ - HB_Error error; - HB_PairPos* pp = &st->pair; - - HB_UShort format1, format2; - HB_UInt cur_offset, new_offset, base_offset; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 8L ) ) - return error; - - pp->PosFormat = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - format1 = pp->ValueFormat1 = GET_UShort(); - format2 = pp->ValueFormat2 = GET_UShort(); - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &pp->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - switch ( pp->PosFormat ) - { - case 1: - error = Load_PairPos1( &pp->ppf.ppf1, format1, format2, stream ); - if ( error ) - goto Fail; - break; - - case 2: - error = Load_PairPos2( &pp->ppf.ppf2, format1, format2, stream ); - if ( error ) - goto Fail; - break; - - default: - return ERR(HB_Err_Invalid_SubTable_Format); - } - - return HB_Err_Ok; - -Fail: - _HB_OPEN_Free_Coverage( &pp->Coverage ); - return error; -} - - -static void Free_PairPos( HB_GPOS_SubTable* st ) -{ - HB_UShort format1, format2; - HB_PairPos* pp = &st->pair; - - - format1 = pp->ValueFormat1; - format2 = pp->ValueFormat2; - - switch ( pp->PosFormat ) - { - case 1: - Free_PairPos1( &pp->ppf.ppf1, format1, format2 ); - break; - - case 2: - Free_PairPos2( &pp->ppf.ppf2, format1, format2 ); - break; - - default: - break; - } - - _HB_OPEN_Free_Coverage( &pp->Coverage ); -} - - -static HB_Error Lookup_PairPos1( GPOS_Instance* gpi, - HB_PairPosFormat1* ppf1, - HB_Buffer buffer, - HB_UInt first_pos, - HB_UShort index, - HB_UShort format1, - HB_UShort format2 ) -{ - HB_Error error; - HB_UShort numpvr, glyph2; - - HB_PairValueRecord* pvr; - - - if ( index >= ppf1->PairSetCount ) - return ERR(HB_Err_Invalid_SubTable); - - pvr = ppf1->PairSet[index].PairValueRecord; - if ( !pvr ) - return ERR(HB_Err_Invalid_SubTable); - - glyph2 = IN_CURGLYPH(); - - for ( numpvr = ppf1->PairSet[index].PairValueCount; - numpvr; - numpvr--, pvr++ ) - { - if ( glyph2 == pvr->SecondGlyph ) - { - error = Get_ValueRecord( gpi, &pvr->Value1, format1, - POSITION( first_pos ) ); - if ( error ) - return error; - return Get_ValueRecord( gpi, &pvr->Value2, format2, - POSITION( buffer->in_pos ) ); - } - } - - return HB_Err_Not_Covered; -} - - -static HB_Error Lookup_PairPos2( GPOS_Instance* gpi, - HB_PairPosFormat2* ppf2, - HB_Buffer buffer, - HB_UInt first_pos, - HB_UShort format1, - HB_UShort format2 ) -{ - HB_Error error; - HB_UShort cl1 = 0, cl2 = 0; /* shut compiler up */ - - HB_Class1Record* c1r; - HB_Class2Record* c2r; - - - error = _HB_OPEN_Get_Class( &ppf2->ClassDef1, IN_GLYPH( first_pos ), - &cl1, NULL ); - if ( error && error != HB_Err_Not_Covered ) - return error; - error = _HB_OPEN_Get_Class( &ppf2->ClassDef2, IN_CURGLYPH(), - &cl2, NULL ); - if ( error && error != HB_Err_Not_Covered ) - return error; - - c1r = &ppf2->Class1Record[cl1]; - if ( !c1r ) - return ERR(HB_Err_Invalid_SubTable); - c2r = &c1r->Class2Record[cl2]; - - error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) ); - if ( error ) - return error; - return Get_ValueRecord( gpi, &c2r->Value2, format2, POSITION( buffer->in_pos ) ); -} - - -static HB_Error Lookup_PairPos( GPOS_Instance* gpi, - HB_GPOS_SubTable* st, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_Error error; - HB_UShort index, property; - HB_UInt first_pos; - HB_GPOSHeader* gpos = gpi->gpos; - HB_PairPos* pp = &st->pair; - - HB_UNUSED(nesting_level); - - if ( buffer->in_pos >= buffer->in_length - 1 ) - return HB_Err_Not_Covered; /* Not enough glyphs in stream */ - - if ( context_length != 0xFFFF && context_length < 2 ) - return HB_Err_Not_Covered; - - if ( CHECK_Property( gpos->layout, IN_CURITEM(), flags, &property ) ) - return error; - - error = _HB_OPEN_Coverage_Index( &pp->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - /* second glyph */ - - first_pos = buffer->in_pos; - (buffer->in_pos)++; - - while ( CHECK_Property( gpos->layout, IN_CURITEM(), - flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( buffer->in_pos == buffer->in_length ) - { - buffer->in_pos = first_pos; - return HB_Err_Not_Covered; - } - (buffer->in_pos)++; - - } - - switch ( pp->PosFormat ) - { - case 1: - error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, buffer, - first_pos, index, - pp->ValueFormat1, pp->ValueFormat2 ); - break; - - case 2: - error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, buffer, first_pos, - pp->ValueFormat1, pp->ValueFormat2 ); - break; - - default: - return ERR(HB_Err_Invalid_SubTable_Format); - } - - /* if we don't have coverage for the second glyph don't skip it for - further lookups but reset in_pos back to the first_glyph and let - the caller in Do_String_Lookup increment in_pos */ - if ( error == HB_Err_Not_Covered ) - buffer->in_pos = first_pos; - - /* adjusting the `next' glyph */ - - if ( pp->ValueFormat2 ) - (buffer->in_pos)++; - - return error; -} - - -/* LookupType 3 */ - -/* CursivePosFormat1 */ - -static HB_Error Load_CursivePos( HB_GPOS_SubTable* st, - HB_Stream stream ) -{ - HB_Error error; - HB_CursivePos* cp = &st->cursive; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_EntryExitRecord* eer; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 4L ) ) - return error; - - cp->PosFormat = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &cp->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = cp->EntryExitCount = GET_UShort(); - - FORGET_Frame(); - - cp->EntryExitRecord = NULL; - - if ( ALLOC_ARRAY( cp->EntryExitRecord, count, HB_EntryExitRecord ) ) - goto Fail2; - - eer = cp->EntryExitRecord; - - for ( n = 0; n < count; n++ ) - { - HB_UInt entry_offset; - - if ( ACCESS_Frame( 2L ) ) - return error; - - entry_offset = new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Anchor( &eer[n].EntryAnchor, - stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - else - eer[n].EntryAnchor.PosFormat = 0; - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Anchor( &eer[n].ExitAnchor, - stream ) ) != HB_Err_Ok ) - { - if ( entry_offset ) - Free_Anchor( &eer[n].EntryAnchor ); - goto Fail1; - } - (void)FILE_Seek( cur_offset ); - } - else - eer[n].ExitAnchor.PosFormat = 0; - } - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - { - Free_Anchor( &eer[m].EntryAnchor ); - Free_Anchor( &eer[m].ExitAnchor ); - } - - FREE( eer ); - -Fail2: - _HB_OPEN_Free_Coverage( &cp->Coverage ); - return error; -} - - -static void Free_CursivePos( HB_GPOS_SubTable* st ) -{ - HB_UShort n, count; - HB_CursivePos* cp = &st->cursive; - - HB_EntryExitRecord* eer; - - - if ( cp->EntryExitRecord ) - { - count = cp->EntryExitCount; - eer = cp->EntryExitRecord; - - for ( n = 0; n < count; n++ ) - { - Free_Anchor( &eer[n].EntryAnchor ); - Free_Anchor( &eer[n].ExitAnchor ); - } - - FREE( eer ); - } - - _HB_OPEN_Free_Coverage( &cp->Coverage ); -} - - -static HB_Error Lookup_CursivePos( GPOS_Instance* gpi, - HB_GPOS_SubTable* st, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort index, property; - HB_Error error; - HB_GPOSHeader* gpos = gpi->gpos; - HB_CursivePos* cp = &st->cursive; - - HB_EntryExitRecord* eer; - HB_Fixed entry_x, entry_y; - HB_Fixed exit_x, exit_y; - - HB_UNUSED(nesting_level); - - if ( context_length != 0xFFFF && context_length < 1 ) - { - gpi->last = 0xFFFF; - return HB_Err_Not_Covered; - } - - /* Glyphs not having the right GDEF property will be ignored, i.e., - gpi->last won't be reset (contrary to user defined properties). */ - - if ( CHECK_Property( gpos->layout, IN_CURITEM(), flags, &property ) ) - return error; - - /* We don't handle mark glyphs here. According to Andrei, this isn't - possible, but who knows... */ - - if ( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK ) - { - gpi->last = 0xFFFF; - return HB_Err_Not_Covered; - } - - error = _HB_OPEN_Coverage_Index( &cp->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - { - gpi->last = 0xFFFF; - return error; - } - - if ( index >= cp->EntryExitCount ) - return ERR(HB_Err_Invalid_SubTable); - - eer = &cp->EntryExitRecord[index]; - - /* Now comes the messiest part of the whole OpenType - specification. At first glance, cursive connections seem easy - to understand, but there are pitfalls! The reason is that - the specs don't mention how to compute the advance values - resp. glyph offsets. I was told it would be an omission, to - be fixed in the next OpenType version... Again many thanks to - Andrei Burago for clarifications. - - Consider the following example: - - | xadv1 | - +---------+ - | | - +-----+--+ 1 | - | | .| | - | 0+--+------+ - | 2 | - | | - 0+--------+ - | xadv2 | - - glyph1: advance width = 12 - anchor point = (3,1) - - glyph2: advance width = 11 - anchor point = (9,4) - - LSB is 1 for both glyphs (so the boxes drawn above are glyph - bboxes). Writing direction is R2L; `0' denotes the glyph's - coordinate origin. - - Now the surprising part: The advance width of the *left* glyph - (resp. of the *bottom* glyph) will be modified, no matter - whether the writing direction is L2R or R2L (resp. T2B or - B2T)! This assymetry is caused by the fact that the glyph's - coordinate origin is always the lower left corner for all - writing directions. - - Continuing the above example, we can compute the new - (horizontal) advance width of glyph2 as - - 9 - 3 = 6 , - - and the new vertical offset of glyph2 as - - 1 - 4 = -3 . - - - Vertical writing direction is far more complicated: - - a) Assuming that we recompute the advance height of the lower glyph: - - -- - +---------+ - -- | | - +-----+--+ 1 | yadv1 - | | .| | - yadv2 | 0+--+------+ -- BSB1 -- - | 2 | -- -- y_offset - | | - BSB2 -- 0+--------+ -- - -- -- - - glyph1: advance height = 6 - anchor point = (3,1) - - glyph2: advance height = 7 - anchor point = (9,4) - - TSB is 1 for both glyphs; writing direction is T2B. - - - BSB1 = yadv1 - (TSB1 + ymax1) - BSB2 = yadv2 - (TSB2 + ymax2) - y_offset = y2 - y1 - - vertical advance width of glyph2 - = y_offset + BSB2 - BSB1 - = (y2 - y1) + (yadv2 - (TSB2 + ymax2)) - (yadv1 - (TSB1 + ymax1)) - = y2 - y1 + yadv2 - TSB2 - ymax2 - (yadv1 - TSB1 - ymax1) - = y2 - y1 + yadv2 - TSB2 - ymax2 - yadv1 + TSB1 + ymax1 - - - b) Assuming that we recompute the advance height of the upper glyph: - - -- -- - +---------+ -- TSB1 - -- -- | | - TSB2 -- +-----+--+ 1 | yadv1 ymax1 - | | .| | - yadv2 | 0+--+------+ -- -- - ymax2 | 2 | -- y_offset - | | - -- 0+--------+ -- - -- - - glyph1: advance height = 6 - anchor point = (3,1) - - glyph2: advance height = 7 - anchor point = (9,4) - - TSB is 1 for both glyphs; writing direction is T2B. - - y_offset = y2 - y1 - - vertical advance width of glyph2 - = TSB1 + ymax1 + y_offset - (TSB2 + ymax2) - = TSB1 + ymax1 + y2 - y1 - TSB2 - ymax2 - - - Comparing a) with b) shows that b) is easier to compute. I'll wait - for a reply from Andrei to see what should really be implemented... - - Since horizontal advance widths or vertical advance heights - can be used alone but not together, no ambiguity occurs. */ - - if ( gpi->last == 0xFFFF ) - goto end; - - /* Get_Anchor() returns HB_Err_Not_Covered if there is no anchor - table. */ - - error = Get_Anchor( gpi, &eer->EntryAnchor, IN_CURGLYPH(), - &entry_x, &entry_y ); - if ( error == HB_Err_Not_Covered ) - goto end; - if ( error ) - return error; - - if ( gpi->r2l ) - { - POSITION( buffer->in_pos )->x_advance = entry_x - gpi->anchor_x; - POSITION( buffer->in_pos )->new_advance = TRUE; - } - else - { - POSITION( gpi->last )->x_advance = gpi->anchor_x - entry_x; - POSITION( gpi->last )->new_advance = TRUE; - } - - if ( flags & HB_LOOKUP_FLAG_RIGHT_TO_LEFT ) - { - POSITION( gpi->last )->cursive_chain = gpi->last - buffer->in_pos; - POSITION( gpi->last )->y_pos = entry_y - gpi->anchor_y; - } - else - { - POSITION( buffer->in_pos )->cursive_chain = buffer->in_pos - gpi->last; - POSITION( buffer->in_pos )->y_pos = gpi->anchor_y - entry_y; - } - -end: - error = Get_Anchor( gpi, &eer->ExitAnchor, IN_CURGLYPH(), - &exit_x, &exit_y ); - if ( error == HB_Err_Not_Covered ) - gpi->last = 0xFFFF; - else - { - gpi->last = buffer->in_pos; - gpi->anchor_x = exit_x; - gpi->anchor_y = exit_y; - } - if ( error ) - return error; - - (buffer->in_pos)++; - - return HB_Err_Ok; -} - - -/* LookupType 4 */ - -/* BaseArray */ - -static HB_Error Load_BaseArray( HB_BaseArray* ba, - HB_UShort num_classes, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort m, n, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_BaseRecord *br; - HB_Anchor *ban, *bans; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = ba->BaseCount = GET_UShort(); - - FORGET_Frame(); - - ba->BaseRecord = NULL; - - if ( ALLOC_ARRAY( ba->BaseRecord, count, HB_BaseRecord ) ) - return error; - - br = ba->BaseRecord; - - bans = NULL; - - if ( ALLOC_ARRAY( bans, count * num_classes, HB_Anchor ) ) - goto Fail; - - for ( m = 0; m < count; m++ ) - { - br[m].BaseAnchor = NULL; - - ban = br[m].BaseAnchor = bans + m * num_classes; - - for ( n = 0; n < num_classes; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - if (new_offset == base_offset) { - /* XXX - * Doulos SIL Regular is buggy and has zero offsets here. - * Skip it - */ - ban[n].PosFormat = 0; - continue; - } - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Anchor( &ban[n], stream ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - } - - return HB_Err_Ok; - -Fail: - FREE( bans ); - FREE( br ); - return error; -} - - -static void Free_BaseArray( HB_BaseArray* ba, - HB_UShort num_classes ) -{ - HB_BaseRecord *br; - HB_Anchor *bans; - - HB_UNUSED(num_classes); - - if ( ba->BaseRecord ) - { - br = ba->BaseRecord; - - if ( ba->BaseCount ) - { - bans = br[0].BaseAnchor; - FREE( bans ); - } - - FREE( br ); - } -} - - -/* MarkBasePosFormat1 */ - -static HB_Error Load_MarkBasePos( HB_GPOS_SubTable* st, - HB_Stream stream ) -{ - HB_Error error; - HB_MarkBasePos* mbp = &st->markbase; - - HB_UInt cur_offset, new_offset, base_offset; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 4L ) ) - return error; - - mbp->PosFormat = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - if (mbp->PosFormat != 1) - return ERR(HB_Err_Invalid_SubTable_Format); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &mbp->MarkCoverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &mbp->BaseCoverage, stream ) ) != HB_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 4L ) ) - goto Fail2; - - mbp->ClassCount = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_MarkArray( &mbp->MarkArray, stream ) ) != HB_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_BaseArray( &mbp->BaseArray, mbp->ClassCount, - stream ) ) != HB_Err_Ok ) - goto Fail1; - - return HB_Err_Ok; - -Fail1: - Free_MarkArray( &mbp->MarkArray ); - -Fail2: - _HB_OPEN_Free_Coverage( &mbp->BaseCoverage ); - -Fail3: - _HB_OPEN_Free_Coverage( &mbp->MarkCoverage ); - return error; -} - - -static void Free_MarkBasePos( HB_GPOS_SubTable* st ) -{ - HB_MarkBasePos* mbp = &st->markbase; - - Free_BaseArray( &mbp->BaseArray, mbp->ClassCount ); - Free_MarkArray( &mbp->MarkArray ); - _HB_OPEN_Free_Coverage( &mbp->BaseCoverage ); - _HB_OPEN_Free_Coverage( &mbp->MarkCoverage ); -} - - -static HB_Error Lookup_MarkBasePos( GPOS_Instance* gpi, - HB_GPOS_SubTable* st, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort i, j, mark_index, base_index, property, class; - HB_Fixed x_mark_value, y_mark_value, x_base_value, y_base_value; - HB_Error error; - HB_GPOSHeader* gpos = gpi->gpos; - HB_MarkBasePos* mbp = &st->markbase; - - HB_MarkArray* ma; - HB_BaseArray* ba; - HB_BaseRecord* br; - HB_Anchor* mark_anchor; - HB_Anchor* base_anchor; - - HB_Position o; - - HB_UNUSED(nesting_level); - - if ( context_length != 0xFFFF && context_length < 1 ) - return HB_Err_Not_Covered; - - if ( flags & HB_LOOKUP_FLAG_IGNORE_BASE_GLYPHS ) - return HB_Err_Not_Covered; - - if ( CHECK_Property( gpos->layout, IN_CURITEM(), - flags, &property ) ) - return error; - - error = _HB_OPEN_Coverage_Index( &mbp->MarkCoverage, IN_CURGLYPH(), - &mark_index ); - if ( error ) - return error; - - /* now we search backwards for a non-mark glyph */ - - i = 1; - j = buffer->in_pos - 1; - - while ( i <= buffer->in_pos ) - { - property = _hb_ot_layout_get_glyph_property (gpos->layout, IN_GLYPH(j)); - if ( !property ) - return HB_Err_Not_Covered; - - if ( !( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) ) - break; - - i++; - j--; - } - - /* The following assertion is too strong -- at least for mangal.ttf. */ -#if 0 - if ( property != HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH ) - return HB_Err_Not_Covered; -#endif - - if ( i > buffer->in_pos ) - return HB_Err_Not_Covered; - - error = _HB_OPEN_Coverage_Index( &mbp->BaseCoverage, IN_GLYPH( j ), - &base_index ); - if ( error ) - return error; - - ma = &mbp->MarkArray; - - if ( mark_index >= ma->MarkCount ) - return ERR(HB_Err_Invalid_SubTable); - - class = ma->MarkRecord[mark_index].Class; - mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor; - - if ( class >= mbp->ClassCount ) - return ERR(HB_Err_Invalid_SubTable); - - ba = &mbp->BaseArray; - - if ( base_index >= ba->BaseCount ) - return ERR(HB_Err_Invalid_SubTable); - - br = &ba->BaseRecord[base_index]; - base_anchor = &br->BaseAnchor[class]; - - error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(), - &x_mark_value, &y_mark_value ); - if ( error ) - return error; - - error = Get_Anchor( gpi, base_anchor, IN_GLYPH( j ), - &x_base_value, &y_base_value ); - if ( error ) - return error; - - /* anchor points are not cumulative */ - - o = POSITION( buffer->in_pos ); - - o->x_pos = x_base_value - x_mark_value; - o->y_pos = y_base_value - y_mark_value; - o->x_advance = 0; - o->y_advance = 0; - o->back = i; - - (buffer->in_pos)++; - - return HB_Err_Ok; -} - - -/* LookupType 5 */ - -/* LigatureAttach */ - -static HB_Error Load_LigatureAttach( HB_LigatureAttach* lat, - HB_UShort num_classes, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort m, n, k, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_ComponentRecord* cr; - HB_Anchor* lan; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = lat->ComponentCount = GET_UShort(); - - FORGET_Frame(); - - lat->ComponentRecord = NULL; - - if ( ALLOC_ARRAY( lat->ComponentRecord, count, HB_ComponentRecord ) ) - return error; - - cr = lat->ComponentRecord; - - for ( m = 0; m < count; m++ ) - { - cr[m].LigatureAnchor = NULL; - - if ( ALLOC_ARRAY( cr[m].LigatureAnchor, num_classes, HB_Anchor ) ) - goto Fail; - - lan = cr[m].LigatureAnchor; - - for ( n = 0; n < num_classes; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail0; - - new_offset = GET_UShort(); - - FORGET_Frame(); - - if ( new_offset ) - { - new_offset += base_offset; - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Anchor( &lan[n], stream ) ) != HB_Err_Ok ) - goto Fail0; - (void)FILE_Seek( cur_offset ); - } - else - lan[n].PosFormat = 0; - } - - continue; - Fail0: - for ( k = 0; k < n; k++ ) - Free_Anchor( &lan[k] ); - goto Fail; - } - - return HB_Err_Ok; - -Fail: - for ( k = 0; k < m; k++ ) - { - lan = cr[k].LigatureAnchor; - - for ( n = 0; n < num_classes; n++ ) - Free_Anchor( &lan[n] ); - - FREE( lan ); - } - - FREE( cr ); - return error; -} - - -static void Free_LigatureAttach( HB_LigatureAttach* lat, - HB_UShort num_classes ) -{ - HB_UShort m, n, count; - - HB_ComponentRecord* cr; - HB_Anchor* lan; - - - if ( lat->ComponentRecord ) - { - count = lat->ComponentCount; - cr = lat->ComponentRecord; - - for ( m = 0; m < count; m++ ) - { - lan = cr[m].LigatureAnchor; - - for ( n = 0; n < num_classes; n++ ) - Free_Anchor( &lan[n] ); - - FREE( lan ); - } - - FREE( cr ); - } -} - - -/* LigatureArray */ - -static HB_Error Load_LigatureArray( HB_LigatureArray* la, - HB_UShort num_classes, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_LigatureAttach* lat; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = la->LigatureCount = GET_UShort(); - - FORGET_Frame(); - - la->LigatureAttach = NULL; - - if ( ALLOC_ARRAY( la->LigatureAttach, count, HB_LigatureAttach ) ) - return error; - - lat = la->LigatureAttach; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_LigatureAttach( &lat[n], num_classes, - stream ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail: - for ( m = 0; m < n; m++ ) - Free_LigatureAttach( &lat[m], num_classes ); - - FREE( lat ); - return error; -} - - -static void Free_LigatureArray( HB_LigatureArray* la, - HB_UShort num_classes ) -{ - HB_UShort n, count; - - HB_LigatureAttach* lat; - - - if ( la->LigatureAttach ) - { - count = la->LigatureCount; - lat = la->LigatureAttach; - - for ( n = 0; n < count; n++ ) - Free_LigatureAttach( &lat[n], num_classes ); - - FREE( lat ); - } -} - - -/* MarkLigPosFormat1 */ - -static HB_Error Load_MarkLigPos( HB_GPOS_SubTable* st, - HB_Stream stream ) -{ - HB_Error error; - HB_MarkLigPos* mlp = &st->marklig; - - HB_UInt cur_offset, new_offset, base_offset; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 4L ) ) - return error; - - mlp->PosFormat = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &mlp->MarkCoverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &mlp->LigatureCoverage, - stream ) ) != HB_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 4L ) ) - goto Fail2; - - mlp->ClassCount = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_MarkArray( &mlp->MarkArray, stream ) ) != HB_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_LigatureArray( &mlp->LigatureArray, mlp->ClassCount, - stream ) ) != HB_Err_Ok ) - goto Fail1; - - return HB_Err_Ok; - -Fail1: - Free_MarkArray( &mlp->MarkArray ); - -Fail2: - _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage ); - -Fail3: - _HB_OPEN_Free_Coverage( &mlp->MarkCoverage ); - return error; -} - - -static void Free_MarkLigPos( HB_GPOS_SubTable* st ) -{ - HB_MarkLigPos* mlp = &st->marklig; - - Free_LigatureArray( &mlp->LigatureArray, mlp->ClassCount ); - Free_MarkArray( &mlp->MarkArray ); - _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage ); - _HB_OPEN_Free_Coverage( &mlp->MarkCoverage ); -} - - -static HB_Error Lookup_MarkLigPos( GPOS_Instance* gpi, - HB_GPOS_SubTable* st, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort i, j, mark_index, lig_index, property, class; - HB_UShort mark_glyph; - HB_Fixed x_mark_value, y_mark_value, x_lig_value, y_lig_value; - HB_Error error; - HB_GPOSHeader* gpos = gpi->gpos; - HB_MarkLigPos* mlp = &st->marklig; - - HB_MarkArray* ma; - HB_LigatureArray* la; - HB_LigatureAttach* lat; - HB_ComponentRecord* cr; - HB_UShort comp_index; - HB_Anchor* mark_anchor; - HB_Anchor* lig_anchor; - - HB_Position o; - - HB_UNUSED(nesting_level); - - if ( context_length != 0xFFFF && context_length < 1 ) - return HB_Err_Not_Covered; - - if ( flags & HB_LOOKUP_FLAG_IGNORE_LIGATURES ) - return HB_Err_Not_Covered; - - mark_glyph = IN_CURGLYPH(); - - if ( CHECK_Property( gpos->layout, IN_CURITEM(), flags, &property ) ) - return error; - - error = _HB_OPEN_Coverage_Index( &mlp->MarkCoverage, mark_glyph, &mark_index ); - if ( error ) - return error; - - /* now we search backwards for a non-mark glyph */ - - i = 1; - j = buffer->in_pos - 1; - - while ( i <= buffer->in_pos ) - { - property = _hb_ot_layout_get_glyph_property (gpos->layout, IN_GLYPH(j)); - if ( !property ) - return HB_Err_Not_Covered; - - if ( !( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) ) - break; - - i++; - j--; - } - - /* Similar to Lookup_MarkBasePos(), I suspect that this assertion is - too strong, thus it is commented out. */ -#if 0 - if ( property != HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE ) - return HB_Err_Not_Covered; -#endif - - if ( i > buffer->in_pos ) - return HB_Err_Not_Covered; - - error = _HB_OPEN_Coverage_Index( &mlp->LigatureCoverage, IN_GLYPH( j ), - &lig_index ); - if ( error ) - return error; - - ma = &mlp->MarkArray; - - if ( mark_index >= ma->MarkCount ) - return ERR(HB_Err_Invalid_SubTable); - - class = ma->MarkRecord[mark_index].Class; - mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor; - - if ( class >= mlp->ClassCount ) - return ERR(HB_Err_Invalid_SubTable); - - la = &mlp->LigatureArray; - - if ( lig_index >= la->LigatureCount ) - return ERR(HB_Err_Invalid_SubTable); - - lat = &la->LigatureAttach[lig_index]; - - /* We must now check whether the ligature ID of the current mark glyph - is identical to the ligature ID of the found ligature. If yes, we - can directly use the component index. If not, we attach the mark - glyph to the last component of the ligature. */ - - if ( IN_LIGID( j ) == IN_LIGID( buffer->in_pos) ) - { - comp_index = IN_COMPONENT( buffer->in_pos ); - if ( comp_index >= lat->ComponentCount ) - return HB_Err_Not_Covered; - } - else - comp_index = lat->ComponentCount - 1; - - cr = &lat->ComponentRecord[comp_index]; - lig_anchor = &cr->LigatureAnchor[class]; - - error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(), - &x_mark_value, &y_mark_value ); - if ( error ) - return error; - error = Get_Anchor( gpi, lig_anchor, IN_GLYPH( j ), - &x_lig_value, &y_lig_value ); - if ( error ) - return error; - - /* anchor points are not cumulative */ - - o = POSITION( buffer->in_pos ); - - o->x_pos = x_lig_value - x_mark_value; - o->y_pos = y_lig_value - y_mark_value; - o->x_advance = 0; - o->y_advance = 0; - o->back = i; - - (buffer->in_pos)++; - - return HB_Err_Ok; -} - - -/* LookupType 6 */ - -/* Mark2Array */ - -static HB_Error Load_Mark2Array( HB_Mark2Array* m2a, - HB_UShort num_classes, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort k, m, n, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_Mark2Record *m2r; - HB_Anchor *m2an, *m2ans; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = m2a->Mark2Count = GET_UShort(); - - FORGET_Frame(); - - m2a->Mark2Record = NULL; - - if ( ALLOC_ARRAY( m2a->Mark2Record, count, HB_Mark2Record ) ) - return error; - - m2r = m2a->Mark2Record; - - m2ans = NULL; - - if ( ALLOC_ARRAY( m2ans, count * num_classes, HB_Anchor ) ) - goto Fail; - - for ( m = 0; m < count; m++ ) - { - m2an = m2r[m].Mark2Anchor = m2ans + m * num_classes; - - for ( n = 0; n < num_classes; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - if (new_offset == base_offset) { - /* Anchor table not provided. Skip loading. - * Some versions of FreeSans hit this. */ - m2an[n].PosFormat = 0; - continue; - } - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Anchor( &m2an[n], stream ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - } - - return HB_Err_Ok; - -Fail: - FREE( m2ans ); - FREE( m2r ); - return error; -} - - -static void Free_Mark2Array( HB_Mark2Array* m2a, - HB_UShort num_classes ) -{ - HB_Mark2Record *m2r; - HB_Anchor *m2ans; - - HB_UNUSED(num_classes); - - if ( m2a->Mark2Record ) - { - m2r = m2a->Mark2Record; - - if ( m2a->Mark2Count ) - { - m2ans = m2r[0].Mark2Anchor; - FREE( m2ans ); - } - - FREE( m2r ); - } -} - - -/* MarkMarkPosFormat1 */ - -static HB_Error Load_MarkMarkPos( HB_GPOS_SubTable* st, - HB_Stream stream ) -{ - HB_Error error; - HB_MarkMarkPos* mmp = &st->markmark; - - HB_UInt cur_offset, new_offset, base_offset; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 4L ) ) - return error; - - mmp->PosFormat = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &mmp->Mark1Coverage, - stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &mmp->Mark2Coverage, - stream ) ) != HB_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 4L ) ) - goto Fail2; - - mmp->ClassCount = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_MarkArray( &mmp->Mark1Array, stream ) ) != HB_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Mark2Array( &mmp->Mark2Array, mmp->ClassCount, - stream ) ) != HB_Err_Ok ) - goto Fail1; - - return HB_Err_Ok; - -Fail1: - Free_MarkArray( &mmp->Mark1Array ); - -Fail2: - _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage ); - -Fail3: - _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage ); - return error; -} - - -static void Free_MarkMarkPos( HB_GPOS_SubTable* st ) -{ - HB_MarkMarkPos* mmp = &st->markmark; - - Free_Mark2Array( &mmp->Mark2Array, mmp->ClassCount ); - Free_MarkArray( &mmp->Mark1Array ); - _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage ); - _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage ); -} - - -static HB_Error Lookup_MarkMarkPos( GPOS_Instance* gpi, - HB_GPOS_SubTable* st, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort i, j, mark1_index, mark2_index, property, class; - HB_Fixed x_mark1_value, y_mark1_value, - x_mark2_value, y_mark2_value; - HB_Error error; - HB_GPOSHeader* gpos = gpi->gpos; - HB_MarkMarkPos* mmp = &st->markmark; - - HB_MarkArray* ma1; - HB_Mark2Array* ma2; - HB_Mark2Record* m2r; - HB_Anchor* mark1_anchor; - HB_Anchor* mark2_anchor; - - HB_Position o; - - HB_UNUSED(nesting_level); - - if ( context_length != 0xFFFF && context_length < 1 ) - return HB_Err_Not_Covered; - - if ( flags & HB_LOOKUP_FLAG_IGNORE_MARKS ) - return HB_Err_Not_Covered; - - if ( CHECK_Property( gpos->layout, IN_CURITEM(), - flags, &property ) ) - return error; - - error = _HB_OPEN_Coverage_Index( &mmp->Mark1Coverage, IN_CURGLYPH(), - &mark1_index ); - if ( error ) - return error; - - /* now we search backwards for a suitable mark glyph until a non-mark - glyph */ - - if ( buffer->in_pos == 0 ) - return HB_Err_Not_Covered; - - i = 1; - j = buffer->in_pos - 1; - while ( i <= buffer->in_pos ) - { - property = _hb_ot_layout_get_glyph_property (gpos->layout, IN_GLYPH(j)); - if ( !property ) - return HB_Err_Not_Covered; - - if ( !( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) ) - return HB_Err_Not_Covered; - - if ( flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) - { - if ( property == (flags & 0xFF00) ) - break; - } - else - break; - - i++; - j--; - } - - error = _HB_OPEN_Coverage_Index( &mmp->Mark2Coverage, IN_GLYPH( j ), - &mark2_index ); - if ( error ) - return error; - - ma1 = &mmp->Mark1Array; - - if ( mark1_index >= ma1->MarkCount ) - return ERR(HB_Err_Invalid_SubTable); - - class = ma1->MarkRecord[mark1_index].Class; - mark1_anchor = &ma1->MarkRecord[mark1_index].MarkAnchor; - - if ( class >= mmp->ClassCount ) - return ERR(HB_Err_Invalid_SubTable); - - ma2 = &mmp->Mark2Array; - - if ( mark2_index >= ma2->Mark2Count ) - return ERR(HB_Err_Invalid_SubTable); - - m2r = &ma2->Mark2Record[mark2_index]; - mark2_anchor = &m2r->Mark2Anchor[class]; - - error = Get_Anchor( gpi, mark1_anchor, IN_CURGLYPH(), - &x_mark1_value, &y_mark1_value ); - if ( error ) - return error; - error = Get_Anchor( gpi, mark2_anchor, IN_GLYPH( j ), - &x_mark2_value, &y_mark2_value ); - if ( error ) - return error; - - /* anchor points are not cumulative */ - - o = POSITION( buffer->in_pos ); - - o->x_pos = x_mark2_value - x_mark1_value; - o->y_pos = y_mark2_value - y_mark1_value; - o->x_advance = 0; - o->y_advance = 0; - o->back = 1; - - (buffer->in_pos)++; - - return HB_Err_Ok; -} - - -/* Do the actual positioning for a context positioning (either format - 7 or 8). This is only called after we've determined that the stream - matches the subrule. */ - -static HB_Error Do_ContextPos( GPOS_Instance* gpi, - HB_UShort GlyphCount, - HB_UShort PosCount, - HB_PosLookupRecord* pos, - HB_Buffer buffer, - int nesting_level ) -{ - HB_Error error; - HB_UInt i, old_pos; - - - i = 0; - - while ( i < GlyphCount ) - { - if ( PosCount && i == pos->SequenceIndex ) - { - old_pos = buffer->in_pos; - - /* Do a positioning */ - - error = GPOS_Do_Glyph_Lookup( gpi, pos->LookupListIndex, buffer, - GlyphCount, nesting_level ); - - if ( error ) - return error; - - pos++; - PosCount--; - i += buffer->in_pos - old_pos; - } - else - { - i++; - (buffer->in_pos)++; - } - } - - return HB_Err_Ok; -} - - -/* LookupType 7 */ - -/* PosRule */ - -static HB_Error Load_PosRule( HB_PosRule* pr, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - HB_UShort* i; - - HB_PosLookupRecord* plr; - - - if ( ACCESS_Frame( 4L ) ) - return error; - - pr->GlyphCount = GET_UShort(); - pr->PosCount = GET_UShort(); - - FORGET_Frame(); - - pr->Input = NULL; - - count = pr->GlyphCount - 1; /* only GlyphCount - 1 elements */ - - if ( ALLOC_ARRAY( pr->Input, count, HB_UShort ) ) - return error; - - i = pr->Input; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail2; - - for ( n = 0; n < count; n++ ) - i[n] = GET_UShort(); - - FORGET_Frame(); - - pr->PosLookupRecord = NULL; - - count = pr->PosCount; - - if ( ALLOC_ARRAY( pr->PosLookupRecord, count, HB_PosLookupRecord ) ) - goto Fail2; - - plr = pr->PosLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - plr[n].SequenceIndex = GET_UShort(); - plr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return HB_Err_Ok; - -Fail1: - FREE( plr ); - -Fail2: - FREE( i ); - return error; -} - - -static void Free_PosRule( HB_PosRule* pr ) -{ - FREE( pr->PosLookupRecord ); - FREE( pr->Input ); -} - - -/* PosRuleSet */ - -static HB_Error Load_PosRuleSet( HB_PosRuleSet* prs, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_PosRule* pr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = prs->PosRuleCount = GET_UShort(); - - FORGET_Frame(); - - prs->PosRule = NULL; - - if ( ALLOC_ARRAY( prs->PosRule, count, HB_PosRule ) ) - return error; - - pr = prs->PosRule; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_PosRule( &pr[n], stream ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail: - for ( m = 0; m < n; m++ ) - Free_PosRule( &pr[m] ); - - FREE( pr ); - return error; -} - - -static void Free_PosRuleSet( HB_PosRuleSet* prs ) -{ - HB_UShort n, count; - - HB_PosRule* pr; - - - if ( prs->PosRule ) - { - count = prs->PosRuleCount; - pr = prs->PosRule; - - for ( n = 0; n < count; n++ ) - Free_PosRule( &pr[n] ); - - FREE( pr ); - } -} - - -/* ContextPosFormat1 */ - -static HB_Error Load_ContextPos1( HB_ContextPosFormat1* cpf1, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_PosRuleSet* prs; - - - base_offset = FILE_Pos() - 2L; - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &cpf1->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = cpf1->PosRuleSetCount = GET_UShort(); - - FORGET_Frame(); - - cpf1->PosRuleSet = NULL; - - if ( ALLOC_ARRAY( cpf1->PosRuleSet, count, HB_PosRuleSet ) ) - goto Fail2; - - prs = cpf1->PosRuleSet; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_PosRuleSet( &prs[n], stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - Free_PosRuleSet( &prs[m] ); - - FREE( prs ); - -Fail2: - _HB_OPEN_Free_Coverage( &cpf1->Coverage ); - return error; -} - - -static void Free_ContextPos1( HB_ContextPosFormat1* cpf1 ) -{ - HB_UShort n, count; - - HB_PosRuleSet* prs; - - - if ( cpf1->PosRuleSet ) - { - count = cpf1->PosRuleSetCount; - prs = cpf1->PosRuleSet; - - for ( n = 0; n < count; n++ ) - Free_PosRuleSet( &prs[n] ); - - FREE( prs ); - } - - _HB_OPEN_Free_Coverage( &cpf1->Coverage ); -} - - -/* PosClassRule */ - -static HB_Error Load_PosClassRule( HB_ContextPosFormat2* cpf2, - HB_PosClassRule* pcr, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - - HB_UShort* c; - HB_PosLookupRecord* plr; - - - if ( ACCESS_Frame( 4L ) ) - return error; - - pcr->GlyphCount = GET_UShort(); - pcr->PosCount = GET_UShort(); - - FORGET_Frame(); - - if ( pcr->GlyphCount > cpf2->MaxContextLength ) - cpf2->MaxContextLength = pcr->GlyphCount; - - pcr->Class = NULL; - - count = pcr->GlyphCount - 1; /* only GlyphCount - 1 elements */ - - if ( ALLOC_ARRAY( pcr->Class, count, HB_UShort ) ) - return error; - - c = pcr->Class; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail2; - - for ( n = 0; n < count; n++ ) - c[n] = GET_UShort(); - - FORGET_Frame(); - - pcr->PosLookupRecord = NULL; - - count = pcr->PosCount; - - if ( ALLOC_ARRAY( pcr->PosLookupRecord, count, HB_PosLookupRecord ) ) - goto Fail2; - - plr = pcr->PosLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - plr[n].SequenceIndex = GET_UShort(); - plr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return HB_Err_Ok; - -Fail1: - FREE( plr ); - -Fail2: - FREE( c ); - return error; -} - - -static void Free_PosClassRule( HB_PosClassRule* pcr ) -{ - FREE( pcr->PosLookupRecord ); - FREE( pcr->Class ); -} - - -/* PosClassSet */ - -static HB_Error Load_PosClassSet( HB_ContextPosFormat2* cpf2, - HB_PosClassSet* pcs, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_PosClassRule* pcr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = pcs->PosClassRuleCount = GET_UShort(); - - FORGET_Frame(); - - pcs->PosClassRule = NULL; - - if ( ALLOC_ARRAY( pcs->PosClassRule, count, HB_PosClassRule ) ) - return error; - - pcr = pcs->PosClassRule; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_PosClassRule( cpf2, &pcr[n], - stream ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail: - for ( m = 0; m < n; m++ ) - Free_PosClassRule( &pcr[m] ); - - FREE( pcr ); - return error; -} - - -static void Free_PosClassSet( HB_PosClassSet* pcs ) -{ - HB_UShort n, count; - - HB_PosClassRule* pcr; - - - if ( pcs->PosClassRule ) - { - count = pcs->PosClassRuleCount; - pcr = pcs->PosClassRule; - - for ( n = 0; n < count; n++ ) - Free_PosClassRule( &pcr[n] ); - - FREE( pcr ); - } -} - - -/* ContextPosFormat2 */ - -static HB_Error Load_ContextPos2( HB_ContextPosFormat2* cpf2, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_PosClassSet* pcs; - - - base_offset = FILE_Pos() - 2; - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &cpf2->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 4L ) ) - goto Fail3; - - new_offset = GET_UShort() + base_offset; - - /* `PosClassSetCount' is the upper limit for class values, thus we - read it now to make an additional safety check. */ - - count = cpf2->PosClassSetCount = GET_UShort(); - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_ClassDefinition( &cpf2->ClassDef, count, - stream ) ) != HB_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - - cpf2->PosClassSet = NULL; - cpf2->MaxContextLength = 0; - - if ( ALLOC_ARRAY( cpf2->PosClassSet, count, HB_PosClassSet ) ) - goto Fail2; - - pcs = cpf2->PosClassSet; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - if ( new_offset != base_offset ) /* not a NULL offset */ - { - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_PosClassSet( cpf2, &pcs[n], - stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - else - { - /* we create a PosClassSet table with no entries */ - - cpf2->PosClassSet[n].PosClassRuleCount = 0; - cpf2->PosClassSet[n].PosClassRule = NULL; - } - } - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; n++ ) - Free_PosClassSet( &pcs[m] ); - - FREE( pcs ); - -Fail2: - _HB_OPEN_Free_ClassDefinition( &cpf2->ClassDef ); - -Fail3: - _HB_OPEN_Free_Coverage( &cpf2->Coverage ); - return error; -} - - -static void Free_ContextPos2( HB_ContextPosFormat2* cpf2 ) -{ - HB_UShort n, count; - - HB_PosClassSet* pcs; - - - if ( cpf2->PosClassSet ) - { - count = cpf2->PosClassSetCount; - pcs = cpf2->PosClassSet; - - for ( n = 0; n < count; n++ ) - Free_PosClassSet( &pcs[n] ); - - FREE( pcs ); - } - - _HB_OPEN_Free_ClassDefinition( &cpf2->ClassDef ); - _HB_OPEN_Free_Coverage( &cpf2->Coverage ); -} - - -/* ContextPosFormat3 */ - -static HB_Error Load_ContextPos3( HB_ContextPosFormat3* cpf3, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_Coverage* c; - HB_PosLookupRecord* plr; - - - base_offset = FILE_Pos() - 2L; - - if ( ACCESS_Frame( 4L ) ) - return error; - - cpf3->GlyphCount = GET_UShort(); - cpf3->PosCount = GET_UShort(); - - FORGET_Frame(); - - cpf3->Coverage = NULL; - - count = cpf3->GlyphCount; - - if ( ALLOC_ARRAY( cpf3->Coverage, count, HB_Coverage ) ) - return error; - - c = cpf3->Coverage; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != HB_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - } - - cpf3->PosLookupRecord = NULL; - - count = cpf3->PosCount; - - if ( ALLOC_ARRAY( cpf3->PosLookupRecord, count, HB_PosLookupRecord ) ) - goto Fail2; - - plr = cpf3->PosLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - plr[n].SequenceIndex = GET_UShort(); - plr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return HB_Err_Ok; - -Fail1: - FREE( plr ); - -Fail2: - for ( n = 0; n < count; n++ ) - _HB_OPEN_Free_Coverage( &c[n] ); - - FREE( c ); - return error; -} - - -static void Free_ContextPos3( HB_ContextPosFormat3* cpf3 ) -{ - HB_UShort n, count; - - HB_Coverage* c; - - - FREE( cpf3->PosLookupRecord ); - - if ( cpf3->Coverage ) - { - count = cpf3->GlyphCount; - c = cpf3->Coverage; - - for ( n = 0; n < count; n++ ) - _HB_OPEN_Free_Coverage( &c[n] ); - - FREE( c ); - } -} - - -/* ContextPos */ - -static HB_Error Load_ContextPos( HB_GPOS_SubTable* st, - HB_Stream stream ) -{ - HB_Error error; - HB_ContextPos* cp = &st->context; - - - if ( ACCESS_Frame( 2L ) ) - return error; - - cp->PosFormat = GET_UShort(); - - FORGET_Frame(); - - switch ( cp->PosFormat ) - { - case 1: - return Load_ContextPos1( &cp->cpf.cpf1, stream ); - - case 2: - return Load_ContextPos2( &cp->cpf.cpf2, stream ); - - case 3: - return Load_ContextPos3( &cp->cpf.cpf3, stream ); - - default: - return ERR(HB_Err_Invalid_SubTable_Format); - } - - return HB_Err_Ok; /* never reached */ -} - - -static void Free_ContextPos( HB_GPOS_SubTable* st ) -{ - HB_ContextPos* cp = &st->context; - - switch ( cp->PosFormat ) - { - case 1: Free_ContextPos1( &cp->cpf.cpf1 ); break; - case 2: Free_ContextPos2( &cp->cpf.cpf2 ); break; - case 3: Free_ContextPos3( &cp->cpf.cpf3 ); break; - default: break; - } -} - - -static HB_Error Lookup_ContextPos1( GPOS_Instance* gpi, - HB_ContextPosFormat1* cpf1, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort index, property; - HB_UShort i, j, k, numpr; - HB_Error error; - HB_GPOSHeader* gpos = gpi->gpos; - - HB_PosRule* pr; - hb_ot_layout_t* layout; - - - layout = gpos->layout; - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - error = _HB_OPEN_Coverage_Index( &cpf1->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - pr = cpf1->PosRuleSet[index].PosRule; - numpr = cpf1->PosRuleSet[index].PosRuleCount; - - for ( k = 0; k < numpr; k++ ) - { - if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount ) - goto next_posrule; - - if ( buffer->in_pos + pr[k].GlyphCount > buffer->in_length ) - goto next_posrule; /* context is too long */ - - for ( i = 1, j = buffer->in_pos + 1; i < pr[k].GlyphCount; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + pr[k].GlyphCount - i == (HB_Int)buffer->in_length ) - goto next_posrule; - j++; - } - - if ( IN_GLYPH( j ) != pr[k].Input[i - 1] ) - goto next_posrule; - } - - return Do_ContextPos( gpi, pr[k].GlyphCount, - pr[k].PosCount, pr[k].PosLookupRecord, - buffer, - nesting_level ); - - next_posrule: - ; - } - - return HB_Err_Not_Covered; -} - - -static HB_Error Lookup_ContextPos2( GPOS_Instance* gpi, - HB_ContextPosFormat2* cpf2, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort index, property; - HB_Error error; - HB_UShort i, j, k, known_classes; - - HB_UShort* classes; - HB_UShort* cl; - HB_GPOSHeader* gpos = gpi->gpos; - - HB_PosClassSet* pcs; - HB_PosClassRule* pr; - hb_ot_layout_t* layout; - - - layout = gpos->layout; - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - /* Note: The coverage table in format 2 doesn't give an index into - anything. It just lets us know whether or not we need to - do any lookup at all. */ - - error = _HB_OPEN_Coverage_Index( &cpf2->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - if (cpf2->MaxContextLength < 1) - return HB_Err_Not_Covered; - - if ( ALLOC_ARRAY( classes, cpf2->MaxContextLength, HB_UShort ) ) - return error; - - error = _HB_OPEN_Get_Class( &cpf2->ClassDef, IN_CURGLYPH(), - &classes[0], NULL ); - if ( error && error != HB_Err_Not_Covered ) - goto End; - known_classes = 0; - - pcs = &cpf2->PosClassSet[classes[0]]; - if ( !pcs ) - { - error = ERR(HB_Err_Invalid_SubTable); - goto End; - } - - for ( k = 0; k < pcs->PosClassRuleCount; k++ ) - { - pr = &pcs->PosClassRule[k]; - - if ( context_length != 0xFFFF && context_length < pr->GlyphCount ) - goto next_posclassrule; - - if ( buffer->in_pos + pr->GlyphCount > buffer->in_length ) - goto next_posclassrule; /* context is too long */ - - cl = pr->Class; - - /* Start at 1 because [0] is implied */ - - for ( i = 1, j = buffer->in_pos + 1; i < pr->GlyphCount; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - goto End; - - if ( j + pr->GlyphCount - i == (HB_Int)buffer->in_length ) - goto next_posclassrule; - j++; - } - - if ( i > known_classes ) - { - /* Keeps us from having to do this for each rule */ - - error = _HB_OPEN_Get_Class( &cpf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL ); - if ( error && error != HB_Err_Not_Covered ) - goto End; - known_classes = i; - } - - if ( cl[i - 1] != classes[i] ) - goto next_posclassrule; - } - - error = Do_ContextPos( gpi, pr->GlyphCount, - pr->PosCount, pr->PosLookupRecord, - buffer, - nesting_level ); - goto End; - - next_posclassrule: - ; - } - - error = HB_Err_Not_Covered; - -End: - FREE( classes ); - return error; -} - - -static HB_Error Lookup_ContextPos3( GPOS_Instance* gpi, - HB_ContextPosFormat3* cpf3, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_Error error; - HB_UShort index, i, j, property; - HB_GPOSHeader* gpos = gpi->gpos; - - HB_Coverage* c; - hb_ot_layout_t* layout; - - - layout = gpos->layout; - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount ) - return HB_Err_Not_Covered; - - if ( buffer->in_pos + cpf3->GlyphCount > buffer->in_length ) - return HB_Err_Not_Covered; /* context is too long */ - - c = cpf3->Coverage; - - for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + cpf3->GlyphCount - i == (HB_Int)buffer->in_length ) - return HB_Err_Not_Covered; - j++; - } - - error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index ); - if ( error ) - return error; - } - - return Do_ContextPos( gpi, cpf3->GlyphCount, - cpf3->PosCount, cpf3->PosLookupRecord, - buffer, - nesting_level ); -} - - -static HB_Error Lookup_ContextPos( GPOS_Instance* gpi, - HB_GPOS_SubTable* st, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_ContextPos* cp = &st->context; - - switch ( cp->PosFormat ) - { - case 1: - return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, buffer, - flags, context_length, nesting_level ); - - case 2: - return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, buffer, - flags, context_length, nesting_level ); - - case 3: - return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, buffer, - flags, context_length, nesting_level ); - - default: - return ERR(HB_Err_Invalid_SubTable_Format); - } - - return HB_Err_Ok; /* never reached */ -} - - -/* LookupType 8 */ - -/* ChainPosRule */ - -static HB_Error Load_ChainPosRule( HB_ChainPosRule* cpr, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - HB_UShort* b; - HB_UShort* i; - HB_UShort* l; - - HB_PosLookupRecord* plr; - - - if ( ACCESS_Frame( 2L ) ) - return error; - - cpr->BacktrackGlyphCount = GET_UShort(); - - FORGET_Frame(); - - cpr->Backtrack = NULL; - - count = cpr->BacktrackGlyphCount; - - if ( ALLOC_ARRAY( cpr->Backtrack, count, HB_UShort ) ) - return error; - - b = cpr->Backtrack; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail4; - - for ( n = 0; n < count; n++ ) - b[n] = GET_UShort(); - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail4; - - cpr->InputGlyphCount = GET_UShort(); - - FORGET_Frame(); - - cpr->Input = NULL; - - count = cpr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */ - - if ( ALLOC_ARRAY( cpr->Input, count, HB_UShort ) ) - goto Fail4; - - i = cpr->Input; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail3; - - for ( n = 0; n < count; n++ ) - i[n] = GET_UShort(); - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - cpr->LookaheadGlyphCount = GET_UShort(); - - FORGET_Frame(); - - cpr->Lookahead = NULL; - - count = cpr->LookaheadGlyphCount; - - if ( ALLOC_ARRAY( cpr->Lookahead, count, HB_UShort ) ) - goto Fail3; - - l = cpr->Lookahead; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail2; - - for ( n = 0; n < count; n++ ) - l[n] = GET_UShort(); - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - cpr->PosCount = GET_UShort(); - - FORGET_Frame(); - - cpr->PosLookupRecord = NULL; - - count = cpr->PosCount; - - if ( ALLOC_ARRAY( cpr->PosLookupRecord, count, HB_PosLookupRecord ) ) - goto Fail2; - - plr = cpr->PosLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - plr[n].SequenceIndex = GET_UShort(); - plr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return HB_Err_Ok; - -Fail1: - FREE( plr ); - -Fail2: - FREE( l ); - -Fail3: - FREE( i ); - -Fail4: - FREE( b ); - return error; -} - - -static void Free_ChainPosRule( HB_ChainPosRule* cpr ) -{ - FREE( cpr->PosLookupRecord ); - FREE( cpr->Lookahead ); - FREE( cpr->Input ); - FREE( cpr->Backtrack ); -} - - -/* ChainPosRuleSet */ - -static HB_Error Load_ChainPosRuleSet( HB_ChainPosRuleSet* cprs, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_ChainPosRule* cpr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = cprs->ChainPosRuleCount = GET_UShort(); - - FORGET_Frame(); - - cprs->ChainPosRule = NULL; - - if ( ALLOC_ARRAY( cprs->ChainPosRule, count, HB_ChainPosRule ) ) - return error; - - cpr = cprs->ChainPosRule; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_ChainPosRule( &cpr[n], stream ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail: - for ( m = 0; m < n; m++ ) - Free_ChainPosRule( &cpr[m] ); - - FREE( cpr ); - return error; -} - - -static void Free_ChainPosRuleSet( HB_ChainPosRuleSet* cprs ) -{ - HB_UShort n, count; - - HB_ChainPosRule* cpr; - - - if ( cprs->ChainPosRule ) - { - count = cprs->ChainPosRuleCount; - cpr = cprs->ChainPosRule; - - for ( n = 0; n < count; n++ ) - Free_ChainPosRule( &cpr[n] ); - - FREE( cpr ); - } -} - - -/* ChainContextPosFormat1 */ - -static HB_Error Load_ChainContextPos1( HB_ChainContextPosFormat1* ccpf1, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_ChainPosRuleSet* cprs; - - - base_offset = FILE_Pos() - 2L; - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &ccpf1->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = ccpf1->ChainPosRuleSetCount = GET_UShort(); - - FORGET_Frame(); - - ccpf1->ChainPosRuleSet = NULL; - - if ( ALLOC_ARRAY( ccpf1->ChainPosRuleSet, count, HB_ChainPosRuleSet ) ) - goto Fail2; - - cprs = ccpf1->ChainPosRuleSet; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_ChainPosRuleSet( &cprs[n], stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - Free_ChainPosRuleSet( &cprs[m] ); - - FREE( cprs ); - -Fail2: - _HB_OPEN_Free_Coverage( &ccpf1->Coverage ); - return error; -} - - -static void Free_ChainContextPos1( HB_ChainContextPosFormat1* ccpf1 ) -{ - HB_UShort n, count; - - HB_ChainPosRuleSet* cprs; - - - if ( ccpf1->ChainPosRuleSet ) - { - count = ccpf1->ChainPosRuleSetCount; - cprs = ccpf1->ChainPosRuleSet; - - for ( n = 0; n < count; n++ ) - Free_ChainPosRuleSet( &cprs[n] ); - - FREE( cprs ); - } - - _HB_OPEN_Free_Coverage( &ccpf1->Coverage ); -} - - -/* ChainPosClassRule */ - -static HB_Error Load_ChainPosClassRule( - HB_ChainContextPosFormat2* ccpf2, - HB_ChainPosClassRule* cpcr, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - - HB_UShort* b; - HB_UShort* i; - HB_UShort* l; - HB_PosLookupRecord* plr; - - - if ( ACCESS_Frame( 2L ) ) - return error; - - cpcr->BacktrackGlyphCount = GET_UShort(); - - FORGET_Frame(); - - if ( cpcr->BacktrackGlyphCount > ccpf2->MaxBacktrackLength ) - ccpf2->MaxBacktrackLength = cpcr->BacktrackGlyphCount; - - cpcr->Backtrack = NULL; - - count = cpcr->BacktrackGlyphCount; - - if ( ALLOC_ARRAY( cpcr->Backtrack, count, HB_UShort ) ) - return error; - - b = cpcr->Backtrack; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail4; - - for ( n = 0; n < count; n++ ) - b[n] = GET_UShort(); - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail4; - - cpcr->InputGlyphCount = GET_UShort(); - - if ( cpcr->InputGlyphCount > ccpf2->MaxInputLength ) - ccpf2->MaxInputLength = cpcr->InputGlyphCount; - - FORGET_Frame(); - - cpcr->Input = NULL; - - count = cpcr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */ - - if ( ALLOC_ARRAY( cpcr->Input, count, HB_UShort ) ) - goto Fail4; - - i = cpcr->Input; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail3; - - for ( n = 0; n < count; n++ ) - i[n] = GET_UShort(); - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - cpcr->LookaheadGlyphCount = GET_UShort(); - - FORGET_Frame(); - - if ( cpcr->LookaheadGlyphCount > ccpf2->MaxLookaheadLength ) - ccpf2->MaxLookaheadLength = cpcr->LookaheadGlyphCount; - - cpcr->Lookahead = NULL; - - count = cpcr->LookaheadGlyphCount; - - if ( ALLOC_ARRAY( cpcr->Lookahead, count, HB_UShort ) ) - goto Fail3; - - l = cpcr->Lookahead; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail2; - - for ( n = 0; n < count; n++ ) - l[n] = GET_UShort(); - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - cpcr->PosCount = GET_UShort(); - - FORGET_Frame(); - - cpcr->PosLookupRecord = NULL; - - count = cpcr->PosCount; - - if ( ALLOC_ARRAY( cpcr->PosLookupRecord, count, HB_PosLookupRecord ) ) - goto Fail2; - - plr = cpcr->PosLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - plr[n].SequenceIndex = GET_UShort(); - plr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return HB_Err_Ok; - -Fail1: - FREE( plr ); - -Fail2: - FREE( l ); - -Fail3: - FREE( i ); - -Fail4: - FREE( b ); - return error; -} - - -static void Free_ChainPosClassRule( HB_ChainPosClassRule* cpcr ) -{ - FREE( cpcr->PosLookupRecord ); - FREE( cpcr->Lookahead ); - FREE( cpcr->Input ); - FREE( cpcr->Backtrack ); -} - - -/* PosClassSet */ - -static HB_Error Load_ChainPosClassSet( - HB_ChainContextPosFormat2* ccpf2, - HB_ChainPosClassSet* cpcs, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_ChainPosClassRule* cpcr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = cpcs->ChainPosClassRuleCount = GET_UShort(); - - FORGET_Frame(); - - cpcs->ChainPosClassRule = NULL; - - if ( ALLOC_ARRAY( cpcs->ChainPosClassRule, count, - HB_ChainPosClassRule ) ) - return error; - - cpcr = cpcs->ChainPosClassRule; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_ChainPosClassRule( ccpf2, &cpcr[n], - stream ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail: - for ( m = 0; m < n; m++ ) - Free_ChainPosClassRule( &cpcr[m] ); - - FREE( cpcr ); - return error; -} - - -static void Free_ChainPosClassSet( HB_ChainPosClassSet* cpcs ) -{ - HB_UShort n, count; - - HB_ChainPosClassRule* cpcr; - - - if ( cpcs->ChainPosClassRule ) - { - count = cpcs->ChainPosClassRuleCount; - cpcr = cpcs->ChainPosClassRule; - - for ( n = 0; n < count; n++ ) - Free_ChainPosClassRule( &cpcr[n] ); - - FREE( cpcr ); - } -} - - -/* ChainContextPosFormat2 */ - -static HB_Error Load_ChainContextPos2( HB_ChainContextPosFormat2* ccpf2, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - HB_UInt backtrack_offset, input_offset, lookahead_offset; - - HB_ChainPosClassSet* cpcs; - - - base_offset = FILE_Pos() - 2; - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &ccpf2->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 8L ) ) - goto Fail5; - - backtrack_offset = GET_UShort(); - input_offset = GET_UShort(); - lookahead_offset = GET_UShort(); - - /* `ChainPosClassSetCount' is the upper limit for input class values, - thus we read it now to make an additional safety check. No limit - is known or needed for the other two class definitions */ - - count = ccpf2->ChainPosClassSetCount = GET_UShort(); - - FORGET_Frame(); - - if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->BacktrackClassDef, 65535, - backtrack_offset, base_offset, - stream ) ) != HB_Err_Ok ) - goto Fail5; - if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->InputClassDef, count, - input_offset, base_offset, - stream ) ) != HB_Err_Ok ) - goto Fail4; - if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->LookaheadClassDef, 65535, - lookahead_offset, base_offset, - stream ) ) != HB_Err_Ok ) - goto Fail3; - - ccpf2->ChainPosClassSet = NULL; - ccpf2->MaxBacktrackLength = 0; - ccpf2->MaxInputLength = 0; - ccpf2->MaxLookaheadLength = 0; - - if ( ALLOC_ARRAY( ccpf2->ChainPosClassSet, count, HB_ChainPosClassSet ) ) - goto Fail2; - - cpcs = ccpf2->ChainPosClassSet; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - if ( new_offset != base_offset ) /* not a NULL offset */ - { - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_ChainPosClassSet( ccpf2, &cpcs[n], - stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - else - { - /* we create a ChainPosClassSet table with no entries */ - - ccpf2->ChainPosClassSet[n].ChainPosClassRuleCount = 0; - ccpf2->ChainPosClassSet[n].ChainPosClassRule = NULL; - } - } - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - Free_ChainPosClassSet( &cpcs[m] ); - - FREE( cpcs ); - -Fail2: - _HB_OPEN_Free_ClassDefinition( &ccpf2->LookaheadClassDef ); - -Fail3: - _HB_OPEN_Free_ClassDefinition( &ccpf2->InputClassDef ); - -Fail4: - _HB_OPEN_Free_ClassDefinition( &ccpf2->BacktrackClassDef ); - -Fail5: - _HB_OPEN_Free_Coverage( &ccpf2->Coverage ); - return error; -} - - -static void Free_ChainContextPos2( HB_ChainContextPosFormat2* ccpf2 ) -{ - HB_UShort n, count; - - HB_ChainPosClassSet* cpcs; - - - if ( ccpf2->ChainPosClassSet ) - { - count = ccpf2->ChainPosClassSetCount; - cpcs = ccpf2->ChainPosClassSet; - - for ( n = 0; n < count; n++ ) - Free_ChainPosClassSet( &cpcs[n] ); - - FREE( cpcs ); - } - - _HB_OPEN_Free_ClassDefinition( &ccpf2->LookaheadClassDef ); - _HB_OPEN_Free_ClassDefinition( &ccpf2->InputClassDef ); - _HB_OPEN_Free_ClassDefinition( &ccpf2->BacktrackClassDef ); - - _HB_OPEN_Free_Coverage( &ccpf2->Coverage ); -} - - -/* ChainContextPosFormat3 */ - -static HB_Error Load_ChainContextPos3( HB_ChainContextPosFormat3* ccpf3, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, nb, ni, nl, m, count; - HB_UShort backtrack_count, input_count, lookahead_count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_Coverage* b; - HB_Coverage* i; - HB_Coverage* l; - HB_PosLookupRecord* plr; - - - base_offset = FILE_Pos() - 2L; - - if ( ACCESS_Frame( 2L ) ) - return error; - - ccpf3->BacktrackGlyphCount = GET_UShort(); - - FORGET_Frame(); - - ccpf3->BacktrackCoverage = NULL; - - backtrack_count = ccpf3->BacktrackGlyphCount; - - if ( ALLOC_ARRAY( ccpf3->BacktrackCoverage, backtrack_count, - HB_Coverage ) ) - return error; - - b = ccpf3->BacktrackCoverage; - - for ( nb = 0; nb < backtrack_count; nb++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail4; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok ) - goto Fail4; - (void)FILE_Seek( cur_offset ); - } - - if ( ACCESS_Frame( 2L ) ) - goto Fail4; - - ccpf3->InputGlyphCount = GET_UShort(); - - FORGET_Frame(); - - ccpf3->InputCoverage = NULL; - - input_count = ccpf3->InputGlyphCount; - - if ( ALLOC_ARRAY( ccpf3->InputCoverage, input_count, HB_Coverage ) ) - goto Fail4; - - i = ccpf3->InputCoverage; - - for ( ni = 0; ni < input_count; ni++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != HB_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - } - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - ccpf3->LookaheadGlyphCount = GET_UShort(); - - FORGET_Frame(); - - ccpf3->LookaheadCoverage = NULL; - - lookahead_count = ccpf3->LookaheadGlyphCount; - - if ( ALLOC_ARRAY( ccpf3->LookaheadCoverage, lookahead_count, - HB_Coverage ) ) - goto Fail3; - - l = ccpf3->LookaheadCoverage; - - for ( nl = 0; nl < lookahead_count; nl++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - } - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - ccpf3->PosCount = GET_UShort(); - - FORGET_Frame(); - - ccpf3->PosLookupRecord = NULL; - - count = ccpf3->PosCount; - - if ( ALLOC_ARRAY( ccpf3->PosLookupRecord, count, HB_PosLookupRecord ) ) - goto Fail2; - - plr = ccpf3->PosLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - plr[n].SequenceIndex = GET_UShort(); - plr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return HB_Err_Ok; - -Fail1: - FREE( plr ); - -Fail2: - for ( m = 0; m < nl; m++ ) - _HB_OPEN_Free_Coverage( &l[m] ); - - FREE( l ); - -Fail3: - for ( m = 0; m < ni; m++ ) - _HB_OPEN_Free_Coverage( &i[m] ); - - FREE( i ); - -Fail4: - for ( m = 0; m < nb; m++ ) - _HB_OPEN_Free_Coverage( &b[m] ); - - FREE( b ); - return error; -} - - -static void Free_ChainContextPos3( HB_ChainContextPosFormat3* ccpf3 ) -{ - HB_UShort n, count; - - HB_Coverage* c; - - - FREE( ccpf3->PosLookupRecord ); - - if ( ccpf3->LookaheadCoverage ) - { - count = ccpf3->LookaheadGlyphCount; - c = ccpf3->LookaheadCoverage; - - for ( n = 0; n < count; n++ ) - _HB_OPEN_Free_Coverage( &c[n] ); - - FREE( c ); - } - - if ( ccpf3->InputCoverage ) - { - count = ccpf3->InputGlyphCount; - c = ccpf3->InputCoverage; - - for ( n = 0; n < count; n++ ) - _HB_OPEN_Free_Coverage( &c[n] ); - - FREE( c ); - } - - if ( ccpf3->BacktrackCoverage ) - { - count = ccpf3->BacktrackGlyphCount; - c = ccpf3->BacktrackCoverage; - - for ( n = 0; n < count; n++ ) - _HB_OPEN_Free_Coverage( &c[n] ); - - FREE( c ); - } -} - - -/* ChainContextPos */ - -static HB_Error Load_ChainContextPos( HB_GPOS_SubTable* st, - HB_Stream stream ) -{ - HB_Error error; - HB_ChainContextPos* ccp = &st->chain; - - - if ( ACCESS_Frame( 2L ) ) - return error; - - ccp->PosFormat = GET_UShort(); - - FORGET_Frame(); - - switch ( ccp->PosFormat ) - { - case 1: - return Load_ChainContextPos1( &ccp->ccpf.ccpf1, stream ); - - case 2: - return Load_ChainContextPos2( &ccp->ccpf.ccpf2, stream ); - - case 3: - return Load_ChainContextPos3( &ccp->ccpf.ccpf3, stream ); - - default: - return ERR(HB_Err_Invalid_SubTable_Format); - } - - return HB_Err_Ok; /* never reached */ -} - - -static void Free_ChainContextPos( HB_GPOS_SubTable* st ) -{ - HB_ChainContextPos* ccp = &st->chain; - - switch ( ccp->PosFormat ) - { - case 1: Free_ChainContextPos1( &ccp->ccpf.ccpf1 ); break; - case 2: Free_ChainContextPos2( &ccp->ccpf.ccpf2 ); break; - case 3: Free_ChainContextPos3( &ccp->ccpf.ccpf3 ); break; - default: break; - } -} - - -static HB_Error Lookup_ChainContextPos1( - GPOS_Instance* gpi, - HB_ChainContextPosFormat1* ccpf1, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort index, property; - HB_UShort i, j, k, num_cpr; - HB_UShort bgc, igc, lgc; - HB_Error error; - HB_GPOSHeader* gpos = gpi->gpos; - - HB_ChainPosRule* cpr; - HB_ChainPosRule curr_cpr; - hb_ot_layout_t* layout; - - - layout = gpos->layout; - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - error = _HB_OPEN_Coverage_Index( &ccpf1->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - cpr = ccpf1->ChainPosRuleSet[index].ChainPosRule; - num_cpr = ccpf1->ChainPosRuleSet[index].ChainPosRuleCount; - - for ( k = 0; k < num_cpr; k++ ) - { - curr_cpr = cpr[k]; - bgc = curr_cpr.BacktrackGlyphCount; - igc = curr_cpr.InputGlyphCount; - lgc = curr_cpr.LookaheadGlyphCount; - - if ( context_length != 0xFFFF && context_length < igc ) - goto next_chainposrule; - - /* check whether context is too long; it is a first guess only */ - - if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length ) - goto next_chainposrule; - - if ( bgc ) - { - /* Since we don't know in advance the number of glyphs to inspect, - we search backwards for matches in the backtrack glyph array */ - - for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + 1 == bgc - i ) - goto next_chainposrule; - j--; - } - - /* In OpenType 1.3, it is undefined whether the offsets of - backtrack glyphs is in logical order or not. Version 1.4 - will clarify this: - - Logical order - a b c d e f g h i j - i - Input offsets - 0 1 - Backtrack offsets - 3 2 1 0 - Lookahead offsets - 0 1 2 3 */ - - if ( IN_GLYPH( j ) != curr_cpr.Backtrack[i] ) - goto next_chainposrule; - } - } - - /* Start at 1 because [0] is implied */ - - for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + igc - i + lgc == (HB_Int)buffer->in_length ) - goto next_chainposrule; - j++; - } - - if ( IN_GLYPH( j ) != curr_cpr.Input[i - 1] ) - goto next_chainposrule; - } - - /* we are starting to check for lookahead glyphs right after the - last context glyph */ - - for ( i = 0; i < lgc; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + lgc - i == (HB_Int)buffer->in_length ) - goto next_chainposrule; - j++; - } - - if ( IN_GLYPH( j ) != curr_cpr.Lookahead[i] ) - goto next_chainposrule; - } - - return Do_ContextPos( gpi, igc, - curr_cpr.PosCount, - curr_cpr.PosLookupRecord, - buffer, - nesting_level ); - - next_chainposrule: - ; - } - - return HB_Err_Not_Covered; -} - - -static HB_Error Lookup_ChainContextPos2( - GPOS_Instance* gpi, - HB_ChainContextPosFormat2* ccpf2, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort index, property; - HB_Error error; - HB_UShort i, j, k; - HB_UShort bgc, igc, lgc; - HB_UShort known_backtrack_classes, - known_input_classes, - known_lookahead_classes; - - HB_UShort* backtrack_classes; - HB_UShort* input_classes; - HB_UShort* lookahead_classes; - - HB_UShort* bc; - HB_UShort* ic; - HB_UShort* lc; - HB_GPOSHeader* gpos = gpi->gpos; - - HB_ChainPosClassSet* cpcs; - HB_ChainPosClassRule cpcr; - hb_ot_layout_t* layout; - - - layout = gpos->layout; - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - /* Note: The coverage table in format 2 doesn't give an index into - anything. It just lets us know whether or not we need to - do any lookup at all. */ - - error = _HB_OPEN_Coverage_Index( &ccpf2->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - if ( ALLOC_ARRAY( backtrack_classes, ccpf2->MaxBacktrackLength, HB_UShort ) ) - return error; - known_backtrack_classes = 0; - - if (ccpf2->MaxInputLength < 1) - return HB_Err_Not_Covered; - - if ( ALLOC_ARRAY( input_classes, ccpf2->MaxInputLength, HB_UShort ) ) - goto End3; - known_input_classes = 1; - - if ( ALLOC_ARRAY( lookahead_classes, ccpf2->MaxLookaheadLength, HB_UShort ) ) - goto End2; - known_lookahead_classes = 0; - - error = _HB_OPEN_Get_Class( &ccpf2->InputClassDef, IN_CURGLYPH(), - &input_classes[0], NULL ); - if ( error && error != HB_Err_Not_Covered ) - goto End1; - - cpcs = &ccpf2->ChainPosClassSet[input_classes[0]]; - if ( !cpcs ) - { - error = ERR(HB_Err_Invalid_SubTable); - goto End1; - } - - for ( k = 0; k < cpcs->ChainPosClassRuleCount; k++ ) - { - cpcr = cpcs->ChainPosClassRule[k]; - bgc = cpcr.BacktrackGlyphCount; - igc = cpcr.InputGlyphCount; - lgc = cpcr.LookaheadGlyphCount; - - if ( context_length != 0xFFFF && context_length < igc ) - goto next_chainposclassrule; - - /* check whether context is too long; it is a first guess only */ - - if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length ) - goto next_chainposclassrule; - - if ( bgc ) - { - /* Since we don't know in advance the number of glyphs to inspect, - we search backwards for matches in the backtrack glyph array. - Note that `known_backtrack_classes' starts at index 0. */ - - bc = cpcr.Backtrack; - - for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - goto End1; - - if ( j + 1 == bgc - i ) - goto next_chainposclassrule; - j++; - } - - if ( i >= known_backtrack_classes ) - { - /* Keeps us from having to do this for each rule */ - - error = _HB_OPEN_Get_Class( &ccpf2->BacktrackClassDef, IN_GLYPH( j ), - &backtrack_classes[i], NULL ); - if ( error && error != HB_Err_Not_Covered ) - goto End1; - known_backtrack_classes = i; - } - - if ( bc[i] != backtrack_classes[i] ) - goto next_chainposclassrule; - } - } - - ic = cpcr.Input; - - /* Start at 1 because [0] is implied */ - - for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - goto End1; - - if ( j + igc - i + lgc == (HB_Int)buffer->in_length ) - goto next_chainposclassrule; - j++; - } - - if ( i >= known_input_classes ) - { - error = _HB_OPEN_Get_Class( &ccpf2->InputClassDef, IN_GLYPH( j ), - &input_classes[i], NULL ); - if ( error && error != HB_Err_Not_Covered ) - goto End1; - known_input_classes = i; - } - - if ( ic[i - 1] != input_classes[i] ) - goto next_chainposclassrule; - } - - /* we are starting to check for lookahead glyphs right after the - last context glyph */ - - lc = cpcr.Lookahead; - - for ( i = 0; i < lgc; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - goto End1; - - if ( j + lgc - i == (HB_Int)buffer->in_length ) - goto next_chainposclassrule; - j++; - } - - if ( i >= known_lookahead_classes ) - { - error = _HB_OPEN_Get_Class( &ccpf2->LookaheadClassDef, IN_GLYPH( j ), - &lookahead_classes[i], NULL ); - if ( error && error != HB_Err_Not_Covered ) - goto End1; - known_lookahead_classes = i; - } - - if ( lc[i] != lookahead_classes[i] ) - goto next_chainposclassrule; - } - - error = Do_ContextPos( gpi, igc, - cpcr.PosCount, - cpcr.PosLookupRecord, - buffer, - nesting_level ); - goto End1; - - next_chainposclassrule: - ; - } - - error = HB_Err_Not_Covered; - -End1: - FREE( lookahead_classes ); - -End2: - FREE( input_classes ); - -End3: - FREE( backtrack_classes ); - return error; -} - - -static HB_Error Lookup_ChainContextPos3( - GPOS_Instance* gpi, - HB_ChainContextPosFormat3* ccpf3, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort index, i, j, property; - HB_UShort bgc, igc, lgc; - HB_Error error; - HB_GPOSHeader* gpos = gpi->gpos; - - HB_Coverage* bc; - HB_Coverage* ic; - HB_Coverage* lc; - hb_ot_layout_t* layout; - - - layout = gpos->layout; - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - bgc = ccpf3->BacktrackGlyphCount; - igc = ccpf3->InputGlyphCount; - lgc = ccpf3->LookaheadGlyphCount; - - if ( context_length != 0xFFFF && context_length < igc ) - return HB_Err_Not_Covered; - - /* check whether context is too long; it is a first guess only */ - - if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length ) - return HB_Err_Not_Covered; - - if ( bgc ) - { - /* Since we don't know in advance the number of glyphs to inspect, - we search backwards for matches in the backtrack glyph array */ - - bc = ccpf3->BacktrackCoverage; - - for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + 1 == bgc - i ) - return HB_Err_Not_Covered; - j--; - } - - error = _HB_OPEN_Coverage_Index( &bc[i], IN_GLYPH( j ), &index ); - if ( error ) - return error; - } - } - - ic = ccpf3->InputCoverage; - - for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ ) - { - /* We already called CHECK_Property for IN_GLYPH ( buffer->in_pos ) */ - while ( j > buffer->in_pos && CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + igc - i + lgc == (HB_Int)buffer->in_length ) - return HB_Err_Not_Covered; - j++; - } - - error = _HB_OPEN_Coverage_Index( &ic[i], IN_GLYPH( j ), &index ); - if ( error ) - return error; - } - - /* we are starting to check for lookahead glyphs right after the - last context glyph */ - - lc = ccpf3->LookaheadCoverage; - - for ( i = 0; i < lgc; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + lgc - i == (HB_Int)buffer->in_length ) - return HB_Err_Not_Covered; - j++; - } - - error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index ); - if ( error ) - return error; - } - - return Do_ContextPos( gpi, igc, - ccpf3->PosCount, - ccpf3->PosLookupRecord, - buffer, - nesting_level ); -} - - -static HB_Error Lookup_ChainContextPos( - GPOS_Instance* gpi, - HB_GPOS_SubTable* st, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_ChainContextPos* ccp = &st->chain; - - switch ( ccp->PosFormat ) - { - case 1: - return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, buffer, - flags, context_length, - nesting_level ); - - case 2: - return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, buffer, - flags, context_length, - nesting_level ); - - case 3: - return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, buffer, - flags, context_length, - nesting_level ); - - default: - return ERR(HB_Err_Invalid_SubTable_Format); - } - - return HB_Err_Ok; /* never reached */ -} - - - -/*********** - * GPOS API - ***********/ - - - -HB_Error HB_GPOS_Select_Script( HB_GPOSHeader* gpos, - HB_UInt script_tag, - HB_UShort* script_index ) -{ - HB_UShort n; - - HB_ScriptList* sl; - HB_ScriptRecord* sr; - - - if ( !gpos || !script_index ) - return ERR(HB_Err_Invalid_Argument); - - sl = &gpos->ScriptList; - sr = sl->ScriptRecord; - - for ( n = 0; n < sl->ScriptCount; n++ ) - if ( script_tag == sr[n].ScriptTag ) - { - *script_index = n; - - return HB_Err_Ok; - } - - return HB_Err_Not_Covered; -} - - - -HB_Error HB_GPOS_Select_Language( HB_GPOSHeader* gpos, - HB_UInt language_tag, - HB_UShort script_index, - HB_UShort* language_index, - HB_UShort* req_feature_index ) -{ - HB_UShort n; - - HB_ScriptList* sl; - HB_ScriptRecord* sr; - HB_ScriptTable* s; - HB_LangSysRecord* lsr; - - - if ( !gpos || !language_index || !req_feature_index ) - return ERR(HB_Err_Invalid_Argument); - - sl = &gpos->ScriptList; - sr = sl->ScriptRecord; - - if ( script_index >= sl->ScriptCount ) - return ERR(HB_Err_Invalid_Argument); - - s = &sr[script_index].Script; - lsr = s->LangSysRecord; - - for ( n = 0; n < s->LangSysCount; n++ ) - if ( language_tag == lsr[n].LangSysTag ) - { - *language_index = n; - *req_feature_index = lsr[n].LangSys.ReqFeatureIndex; - - return HB_Err_Ok; - } - - return HB_Err_Not_Covered; -} - - -/* selecting 0xFFFF for language_index asks for the values of the - default language (DefaultLangSys) */ - - -HB_Error HB_GPOS_Select_Feature( HB_GPOSHeader* gpos, - HB_UInt feature_tag, - HB_UShort script_index, - HB_UShort language_index, - HB_UShort* feature_index ) -{ - HB_UShort n; - - HB_ScriptList* sl; - HB_ScriptRecord* sr; - HB_ScriptTable* s; - HB_LangSysRecord* lsr; - HB_LangSys* ls; - HB_UShort* fi; - - HB_FeatureList* fl; - HB_FeatureRecord* fr; - - - if ( !gpos || !feature_index ) - return ERR(HB_Err_Invalid_Argument); - - sl = &gpos->ScriptList; - sr = sl->ScriptRecord; - - fl = &gpos->FeatureList; - fr = fl->FeatureRecord; - - if ( script_index >= sl->ScriptCount ) - return ERR(HB_Err_Invalid_Argument); - - s = &sr[script_index].Script; - lsr = s->LangSysRecord; - - if ( language_index == 0xFFFF ) - ls = &s->DefaultLangSys; - else - { - if ( language_index >= s->LangSysCount ) - return ERR(HB_Err_Invalid_Argument); - - ls = &lsr[language_index].LangSys; - } - - fi = ls->FeatureIndex; - - for ( n = 0; n < ls->FeatureCount; n++ ) - { - if ( fi[n] >= fl->FeatureCount ) - return ERR(HB_Err_Invalid_SubTable_Format); - - if ( feature_tag == fr[fi[n]].FeatureTag ) - { - *feature_index = fi[n]; - - return HB_Err_Ok; - } - } - - return HB_Err_Not_Covered; -} - - -/* The next three functions return a null-terminated list */ - - -HB_Error HB_GPOS_Query_Scripts( HB_GPOSHeader* gpos, - HB_UInt** script_tag_list ) -{ - HB_Error error; - HB_UShort n; - HB_UInt* stl; - - HB_ScriptList* sl; - HB_ScriptRecord* sr; - - - if ( !gpos || !script_tag_list ) - return ERR(HB_Err_Invalid_Argument); - - sl = &gpos->ScriptList; - sr = sl->ScriptRecord; - - if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, HB_UInt ) ) - return error; - - for ( n = 0; n < sl->ScriptCount; n++ ) - stl[n] = sr[n].ScriptTag; - stl[n] = 0; - - *script_tag_list = stl; - - return HB_Err_Ok; -} - - - -HB_Error HB_GPOS_Query_Languages( HB_GPOSHeader* gpos, - HB_UShort script_index, - HB_UInt** language_tag_list ) -{ - HB_Error error; - HB_UShort n; - HB_UInt* ltl; - - HB_ScriptList* sl; - HB_ScriptRecord* sr; - HB_ScriptTable* s; - HB_LangSysRecord* lsr; - - - if ( !gpos || !language_tag_list ) - return ERR(HB_Err_Invalid_Argument); - - sl = &gpos->ScriptList; - sr = sl->ScriptRecord; - - if ( script_index >= sl->ScriptCount ) - return ERR(HB_Err_Invalid_Argument); - - s = &sr[script_index].Script; - lsr = s->LangSysRecord; - - if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, HB_UInt ) ) - return error; - - for ( n = 0; n < s->LangSysCount; n++ ) - ltl[n] = lsr[n].LangSysTag; - ltl[n] = 0; - - *language_tag_list = ltl; - - return HB_Err_Ok; -} - - -/* selecting 0xFFFF for language_index asks for the values of the - default language (DefaultLangSys) */ - - -HB_Error HB_GPOS_Query_Features( HB_GPOSHeader* gpos, - HB_UShort script_index, - HB_UShort language_index, - HB_UInt** feature_tag_list ) -{ - HB_UShort n; - HB_Error error; - HB_UInt* ftl; - - HB_ScriptList* sl; - HB_ScriptRecord* sr; - HB_ScriptTable* s; - HB_LangSysRecord* lsr; - HB_LangSys* ls; - HB_UShort* fi; - - HB_FeatureList* fl; - HB_FeatureRecord* fr; - - - if ( !gpos || !feature_tag_list ) - return ERR(HB_Err_Invalid_Argument); - - sl = &gpos->ScriptList; - sr = sl->ScriptRecord; - - fl = &gpos->FeatureList; - fr = fl->FeatureRecord; - - if ( script_index >= sl->ScriptCount ) - return ERR(HB_Err_Invalid_Argument); - - s = &sr[script_index].Script; - lsr = s->LangSysRecord; - - if ( language_index == 0xFFFF ) - ls = &s->DefaultLangSys; - else - { - if ( language_index >= s->LangSysCount ) - return ERR(HB_Err_Invalid_Argument); - - ls = &lsr[language_index].LangSys; - } - - fi = ls->FeatureIndex; - - if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, HB_UInt ) ) - return error; - - for ( n = 0; n < ls->FeatureCount; n++ ) - { - if ( fi[n] >= fl->FeatureCount ) - { - FREE( ftl ); - return ERR(HB_Err_Invalid_SubTable_Format); - } - ftl[n] = fr[fi[n]].FeatureTag; - } - ftl[n] = 0; - - *feature_tag_list = ftl; - - return HB_Err_Ok; -} - - -/* Do an individual subtable lookup. Returns HB_Err_Ok if positioning - has been done, or HB_Err_Not_Covered if not. */ -static HB_Error GPOS_Do_Glyph_Lookup( GPOS_Instance* gpi, - HB_UShort lookup_index, - HB_Buffer buffer, - HB_UShort context_length, - int nesting_level ) -{ - HB_Error error = HB_Err_Not_Covered; - HB_UShort i, flags, lookup_count; - HB_GPOSHeader* gpos = gpi->gpos; - HB_Lookup* lo; - int lookup_type; - - - nesting_level++; - - if ( nesting_level > HB_MAX_NESTING_LEVEL ) - return ERR(HB_Err_Not_Covered); /* ERR() call intended */ - - lookup_count = gpos->LookupList.LookupCount; - if (lookup_index >= lookup_count) - return error; - - lo = &gpos->LookupList.Lookup[lookup_index]; - flags = lo->LookupFlag; - lookup_type = lo->LookupType; - - for ( i = 0; i < lo->SubTableCount; i++ ) - { - HB_GPOS_SubTable *st = &lo->SubTable[i].st.gpos; - - switch (lookup_type) { - case HB_GPOS_LOOKUP_SINGLE: - error = Lookup_SinglePos ( gpi, st, buffer, flags, context_length, nesting_level ); break; - case HB_GPOS_LOOKUP_PAIR: - error = Lookup_PairPos ( gpi, st, buffer, flags, context_length, nesting_level ); break; - case HB_GPOS_LOOKUP_CURSIVE: - error = Lookup_CursivePos ( gpi, st, buffer, flags, context_length, nesting_level ); break; - case HB_GPOS_LOOKUP_MARKBASE: - error = Lookup_MarkBasePos ( gpi, st, buffer, flags, context_length, nesting_level ); break; - case HB_GPOS_LOOKUP_MARKLIG: - error = Lookup_MarkLigPos ( gpi, st, buffer, flags, context_length, nesting_level ); break; - case HB_GPOS_LOOKUP_MARKMARK: - error = Lookup_MarkMarkPos ( gpi, st, buffer, flags, context_length, nesting_level ); break; - case HB_GPOS_LOOKUP_CONTEXT: - error = Lookup_ContextPos ( gpi, st, buffer, flags, context_length, nesting_level ); break; - case HB_GPOS_LOOKUP_CHAIN: - error = Lookup_ChainContextPos ( gpi, st, buffer, flags, context_length, nesting_level ); break; - /*case HB_GPOS_LOOKUP_EXTENSION: - error = Lookup_ExtensionPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;*/ - default: - error = HB_Err_Not_Covered; - } - - /* Check whether we have a successful positioning or an error other - than HB_Err_Not_Covered */ - if ( error != HB_Err_Not_Covered ) - return error; - } - - return HB_Err_Not_Covered; -} - - -HB_INTERNAL HB_Error -_HB_GPOS_Load_SubTable( HB_GPOS_SubTable* st, - HB_Stream stream, - HB_UShort lookup_type ) -{ - switch ( lookup_type ) { - case HB_GPOS_LOOKUP_SINGLE: return Load_SinglePos ( st, stream ); - case HB_GPOS_LOOKUP_PAIR: return Load_PairPos ( st, stream ); - case HB_GPOS_LOOKUP_CURSIVE: return Load_CursivePos ( st, stream ); - case HB_GPOS_LOOKUP_MARKBASE: return Load_MarkBasePos ( st, stream ); - case HB_GPOS_LOOKUP_MARKLIG: return Load_MarkLigPos ( st, stream ); - case HB_GPOS_LOOKUP_MARKMARK: return Load_MarkMarkPos ( st, stream ); - case HB_GPOS_LOOKUP_CONTEXT: return Load_ContextPos ( st, stream ); - case HB_GPOS_LOOKUP_CHAIN: return Load_ChainContextPos ( st, stream ); - /*case HB_GPOS_LOOKUP_EXTENSION: return Load_ExtensionPos ( st, stream );*/ - default: return ERR(HB_Err_Invalid_SubTable_Format); - } -} - - -HB_INTERNAL void -_HB_GPOS_Free_SubTable( HB_GPOS_SubTable* st, - HB_UShort lookup_type ) -{ - switch ( lookup_type ) { - case HB_GPOS_LOOKUP_SINGLE: Free_SinglePos ( st ); return; - case HB_GPOS_LOOKUP_PAIR: Free_PairPos ( st ); return; - case HB_GPOS_LOOKUP_CURSIVE: Free_CursivePos ( st ); return; - case HB_GPOS_LOOKUP_MARKBASE: Free_MarkBasePos ( st ); return; - case HB_GPOS_LOOKUP_MARKLIG: Free_MarkLigPos ( st ); return; - case HB_GPOS_LOOKUP_MARKMARK: Free_MarkMarkPos ( st ); return; - case HB_GPOS_LOOKUP_CONTEXT: Free_ContextPos ( st ); return; - case HB_GPOS_LOOKUP_CHAIN: Free_ChainContextPos ( st ); return; - /*case HB_GPOS_LOOKUP_EXTENSION: Free_ExtensionPos ( st ); return;*/ - default: return; - } -} - - -/* apply one lookup to the input string object */ - -static HB_Error GPOS_Do_String_Lookup( GPOS_Instance* gpi, - HB_UShort lookup_index, - HB_Buffer buffer ) -{ - HB_Error error, retError = HB_Err_Not_Covered; - HB_GPOSHeader* gpos = gpi->gpos; - - HB_UInt* properties = gpos->LookupList.Properties; - - const int nesting_level = 0; - /* 0xFFFF indicates that we don't have a context length yet */ - const HB_UShort context_length = 0xFFFF; - - - gpi->last = 0xFFFF; /* no last valid glyph for cursive pos. */ - - buffer->in_pos = 0; - while ( buffer->in_pos < buffer->in_length ) - { - if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] ) - { - /* Note that the connection between mark and base glyphs hold - exactly one (string) lookup. For example, it would be possible - that in the first lookup, mark glyph X is attached to base - glyph A, and in the next lookup it is attached to base glyph B. - It is up to the font designer to provide meaningful lookups and - lookup order. */ - - error = GPOS_Do_Glyph_Lookup( gpi, lookup_index, buffer, context_length, nesting_level ); - if ( error && error != HB_Err_Not_Covered ) - return error; - } - else - { - /* Contrary to properties defined in GDEF, user-defined properties - will always stop a possible cursive positioning. */ - gpi->last = 0xFFFF; - - error = HB_Err_Not_Covered; - } - - if ( error == HB_Err_Not_Covered ) - (buffer->in_pos)++; - else - retError = error; - } - - return retError; -} - - -static HB_Error Position_CursiveChain ( HB_Buffer buffer ) -{ - HB_UInt i, j; - HB_Position positions = buffer->positions; - - /* First handle all left-to-right connections */ - for (j = 0; j < buffer->in_length; j++) - { - if (positions[j].cursive_chain > 0) - positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos; - } - - /* Then handle all right-to-left connections */ - for (i = buffer->in_length; i > 0; i--) - { - j = i - 1; - - if (positions[j].cursive_chain < 0) - positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos; - } - - return HB_Err_Ok; -} - - -HB_Error HB_GPOS_Add_Feature( HB_GPOSHeader* gpos, - HB_UShort feature_index, - HB_UInt property ) -{ - HB_UShort i; - - HB_Feature feature; - HB_UInt* properties; - HB_UShort* index; - HB_UShort lookup_count; - - /* Each feature can only be added once */ - - if ( !gpos || - feature_index >= gpos->FeatureList.FeatureCount || - gpos->FeatureList.ApplyCount == gpos->FeatureList.FeatureCount ) - return ERR(HB_Err_Invalid_Argument); - - gpos->FeatureList.ApplyOrder[gpos->FeatureList.ApplyCount++] = feature_index; - - properties = gpos->LookupList.Properties; - - feature = gpos->FeatureList.FeatureRecord[feature_index].Feature; - index = feature.LookupListIndex; - lookup_count = gpos->LookupList.LookupCount; - - for ( i = 0; i < feature.LookupListCount; i++ ) - { - HB_UShort lookup_index = index[i]; - if (lookup_index < lookup_count) - properties[lookup_index] |= property; - } - - return HB_Err_Ok; -} - - - -HB_Error HB_GPOS_Clear_Features( HB_GPOSHeader* gpos ) -{ - HB_UShort i; - - HB_UInt* properties; - - - if ( !gpos ) - return ERR(HB_Err_Invalid_Argument); - - gpos->FeatureList.ApplyCount = 0; - - properties = gpos->LookupList.Properties; - - for ( i = 0; i < gpos->LookupList.LookupCount; i++ ) - properties[i] = 0; - - return HB_Err_Ok; -} - - - -HB_Error HB_GPOS_Register_Glyph_Function( HB_GPOSHeader* gpos, - HB_GlyphFunction gfunc ) -{ - if ( !gpos ) - return ERR(HB_Err_Invalid_Argument); - - gpos->gfunc = gfunc; - - return HB_Err_Ok; -} - - - -HB_Error HB_GPOS_Register_MM_Function( HB_GPOSHeader* gpos, - HB_MMFunction mmfunc, - void* data ) -{ - if ( !gpos ) - return ERR(HB_Err_Invalid_Argument); - - gpos->mmfunc = mmfunc; - gpos->data = data; - - return HB_Err_Ok; -} - -/* If `dvi' is TRUE, glyph contour points for anchor points and device - tables are ignored -- you will get device independent values. */ - - -HB_Error HB_GPOS_Apply_String( HB_Font font, - HB_GPOSHeader* gpos, - HB_UShort load_flags, - HB_Buffer buffer, - HB_Bool dvi, - HB_Bool r2l ) -{ - HB_Error error, retError = HB_Err_Not_Covered; - GPOS_Instance gpi; - int i, j, lookup_count, num_features; - - if ( !font || !gpos || !buffer ) - return ERR(HB_Err_Invalid_Argument); - - if ( buffer->in_length == 0 ) - return HB_Err_Not_Covered; - - gpi.font = font; - gpi.gpos = gpos; - gpi.load_flags = load_flags; - gpi.r2l = r2l; - gpi.dvi = dvi; - - lookup_count = gpos->LookupList.LookupCount; - num_features = gpos->FeatureList.ApplyCount; - - if ( num_features ) - { - error = _hb_buffer_clear_positions( buffer ); - if ( error ) - return error; - } - - for ( i = 0; i < num_features; i++ ) - { - HB_UShort feature_index = gpos->FeatureList.ApplyOrder[i]; - HB_Feature feature = gpos->FeatureList.FeatureRecord[feature_index].Feature; - - for ( j = 0; j < feature.LookupListCount; j++ ) - { - HB_UShort lookup_index = feature.LookupListIndex[j]; - - /* Skip nonexistant lookups */ - if (lookup_index >= lookup_count) - continue; - - error = GPOS_Do_String_Lookup( &gpi, lookup_index, buffer ); - if ( error ) - { - if ( error != HB_Err_Not_Covered ) - return error; - } - else - retError = error; - } - } - - if ( num_features ) - { - error = Position_CursiveChain ( buffer ); - if ( error ) - return error; - } - - return retError; -} - -/* END */ diff --git a/src/harfbuzz-gpos.h b/src/harfbuzz-gpos.h deleted file mode 100644 index 0460e2b8d..000000000 --- a/src/harfbuzz-gpos.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2006 Behdad Esfahbod - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#ifndef HARFBUZZ_GPOS_H -#define HARFBUZZ_GPOS_H - -#include "harfbuzz-open.h" -#include "harfbuzz-buffer.h" - -HB_BEGIN_HEADER - - -/* Lookup types for glyph positioning */ - -#define HB_GPOS_LOOKUP_SINGLE 1 -#define HB_GPOS_LOOKUP_PAIR 2 -#define HB_GPOS_LOOKUP_CURSIVE 3 -#define HB_GPOS_LOOKUP_MARKBASE 4 -#define HB_GPOS_LOOKUP_MARKLIG 5 -#define HB_GPOS_LOOKUP_MARKMARK 6 -#define HB_GPOS_LOOKUP_CONTEXT 7 -#define HB_GPOS_LOOKUP_CHAIN 8 -#define HB_GPOS_LOOKUP_EXTENSION 9 - - -/* A pointer to a function which loads a glyph. Its parameters are - the same as in a call to Load_Glyph() -- if no glyph loading - function will be registered with HB_GPOS_Register_Glyph_Function(), - Load_Glyph() will be called indeed. The purpose of this function - pointer is to provide a hook for caching glyph outlines and sbits - (using the instance's generic pointer to hold the data). - - If for some reason no outline data is available (e.g. for an - embedded bitmap glyph), _glyph->outline.n_points should be set to - zero. */ - -typedef HB_Error (*HB_GlyphFunction)(HB_Font font, - HB_UInt glyphIndex, - HB_Int loadFlags ); - - -/* A pointer to a function which accesses the PostScript interpreter. - Multiple Master fonts need this interface to convert a metric ID - (as stored in an OpenType font version 1.2 or higher) `metric_id' - into a metric value (returned in `metric_value'). - - `data' points to the user-defined structure specified during a - call to HB_GPOS_Register_MM_Function(). - - `metric_value' must be returned as a scaled value (but shouldn't - be rounded). */ - -typedef HB_Error (*HB_MMFunction)(HB_Font font, - HB_UShort metric_id, - HB_Fixed* metric_value, - void* data ); - - -struct HB_GPOSHeader_ -{ - HB_16Dot16 Version; - - HB_ScriptList ScriptList; - HB_FeatureList FeatureList; - HB_LookupList LookupList; - - hb_ot_layout_t *layout; - - /* the next field is used for a callback function to get the - glyph outline. */ - - HB_GlyphFunction gfunc; - - /* this is OpenType 1.2 -- Multiple Master fonts need this - callback function to get various metric values from the - PostScript interpreter. */ - - HB_MMFunction mmfunc; - void* data; -}; - -typedef struct HB_GPOSHeader_ HB_GPOSHeader; -typedef HB_GPOSHeader* HB_GPOS; - - -HB_Error HB_Load_GPOS_Table( HB_Font font, - HB_GPOSHeader** gpos, - hb_ot_layout_t *layout ); - - -HB_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos ); - - -HB_Error HB_GPOS_Select_Script( HB_GPOSHeader* gpos, - HB_UInt script_tag, - HB_UShort* script_index ); - -HB_Error HB_GPOS_Select_Language( HB_GPOSHeader* gpos, - HB_UInt language_tag, - HB_UShort script_index, - HB_UShort* language_index, - HB_UShort* req_feature_index ); - -HB_Error HB_GPOS_Select_Feature( HB_GPOSHeader* gpos, - HB_UInt feature_tag, - HB_UShort script_index, - HB_UShort language_index, - HB_UShort* feature_index ); - - -HB_Error HB_GPOS_Query_Scripts( HB_GPOSHeader* gpos, - HB_UInt** script_tag_list ); - -HB_Error HB_GPOS_Query_Languages( HB_GPOSHeader* gpos, - HB_UShort script_index, - HB_UInt** language_tag_list ); - -HB_Error HB_GPOS_Query_Features( HB_GPOSHeader* gpos, - HB_UShort script_index, - HB_UShort language_index, - HB_UInt** feature_tag_list ); - - -HB_Error HB_GPOS_Add_Feature( HB_GPOSHeader* gpos, - HB_UShort feature_index, - HB_UInt properties ); - -HB_Error HB_GPOS_Clear_Features( HB_GPOSHeader* gpos ); - - -HB_Error HB_GPOS_Register_Glyph_Function( HB_GPOSHeader* gpos, - HB_GlyphFunction gfunc ); - - -HB_Error HB_GPOS_Register_MM_Function( HB_GPOSHeader* gpos, - HB_MMFunction mmfunc, - void* data ); - -/* If `dvi' is TRUE, glyph contour points for anchor points and device - tables are ignored -- you will get device independent values. */ - - -HB_Error HB_GPOS_Apply_String( HB_Font font, - HB_GPOSHeader* gpos, - HB_UShort load_flags, - HB_Buffer buffer, - HB_Bool dvi, - HB_Bool r2l ); - -HB_END_HEADER - -#endif /* HARFBUZZ_GPOS_H */ diff --git a/src/harfbuzz-gsub-private.h b/src/harfbuzz-gsub-private.h deleted file mode 100644 index d4cb65193..000000000 --- a/src/harfbuzz-gsub-private.h +++ /dev/null @@ -1,476 +0,0 @@ -/* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2006 Behdad Esfahbod - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#ifndef HARFBUZZ_GSUB_PRIVATE_H -#define HARFBUZZ_GSUB_PRIVATE_H - -#include "harfbuzz-impl.h" -#include "harfbuzz-stream-private.h" -#include "harfbuzz-gsub.h" - -HB_BEGIN_HEADER - - -typedef union HB_GSUB_SubTable_ HB_GSUB_SubTable; - -/* LookupType 1 */ - -struct HB_SingleSubstFormat1_ -{ - HB_Short DeltaGlyphID; /* constant added to get - substitution glyph index */ -}; - -typedef struct HB_SingleSubstFormat1_ HB_SingleSubstFormat1; - - -struct HB_SingleSubstFormat2_ -{ - HB_UShort GlyphCount; /* number of glyph IDs in - Substitute array */ - HB_UShort* Substitute; /* array of substitute glyph IDs */ -}; - -typedef struct HB_SingleSubstFormat2_ HB_SingleSubstFormat2; - - -struct HB_SingleSubst_ -{ - HB_UShort SubstFormat; /* 1 or 2 */ - HB_Coverage Coverage; /* Coverage table */ - - union - { - HB_SingleSubstFormat1 ssf1; - HB_SingleSubstFormat2 ssf2; - } ssf; -}; - -typedef struct HB_SingleSubst_ HB_SingleSubst; - - -/* LookupType 2 */ - -struct HB_Sequence_ -{ - HB_UShort GlyphCount; /* number of glyph IDs in the - Substitute array */ - HB_UShort* Substitute; /* string of glyph IDs to - substitute */ -}; - -typedef struct HB_Sequence_ HB_Sequence; - - -struct HB_MultipleSubst_ -{ - HB_UShort SubstFormat; /* always 1 */ - HB_Coverage Coverage; /* Coverage table */ - HB_UShort SequenceCount; /* number of Sequence tables */ - HB_Sequence* Sequence; /* array of Sequence tables */ -}; - -typedef struct HB_MultipleSubst_ HB_MultipleSubst; - - -/* LookupType 3 */ - -struct HB_AlternateSet_ -{ - HB_UShort GlyphCount; /* number of glyph IDs in the - Alternate array */ - HB_UShort* Alternate; /* array of alternate glyph IDs */ -}; - -typedef struct HB_AlternateSet_ HB_AlternateSet; - - -struct HB_AlternateSubst_ -{ - HB_UShort SubstFormat; /* always 1 */ - HB_Coverage Coverage; /* Coverage table */ - HB_UShort AlternateSetCount; - /* number of AlternateSet tables */ - HB_AlternateSet* AlternateSet; /* array of AlternateSet tables */ -}; - -typedef struct HB_AlternateSubst_ HB_AlternateSubst; - - -/* LookupType 4 */ - -struct HB_Ligature_ -{ - HB_UShort LigGlyph; /* glyphID of ligature - to substitute */ - HB_UShort ComponentCount; /* number of components in ligature */ - HB_UShort* Component; /* array of component glyph IDs */ -}; - -typedef struct HB_Ligature_ HB_Ligature; - - -struct HB_LigatureSet_ -{ - HB_UShort LigatureCount; /* number of Ligature tables */ - HB_Ligature* Ligature; /* array of Ligature tables */ -}; - -typedef struct HB_LigatureSet_ HB_LigatureSet; - - -struct HB_LigatureSubst_ -{ - HB_UShort SubstFormat; /* always 1 */ - HB_Coverage Coverage; /* Coverage table */ - HB_UShort LigatureSetCount; /* number of LigatureSet tables */ - HB_LigatureSet* LigatureSet; /* array of LigatureSet tables */ -}; - -typedef struct HB_LigatureSubst_ HB_LigatureSubst; - - -/* needed by both lookup type 5 and 6 */ - -struct HB_SubstLookupRecord_ -{ - HB_UShort SequenceIndex; /* index into current - glyph sequence */ - HB_UShort LookupListIndex; /* Lookup to apply to that pos. */ -}; - -typedef struct HB_SubstLookupRecord_ HB_SubstLookupRecord; - - -/* LookupType 5 */ - -struct HB_SubRule_ -{ - HB_UShort GlyphCount; /* total number of input glyphs */ - HB_UShort SubstCount; /* number of SubstLookupRecord - tables */ - HB_UShort* Input; /* array of input glyph IDs */ - HB_SubstLookupRecord* SubstLookupRecord; - /* array of SubstLookupRecord - tables */ -}; - -typedef struct HB_SubRule_ HB_SubRule; - - -struct HB_SubRuleSet_ -{ - HB_UShort SubRuleCount; /* number of SubRule tables */ - HB_SubRule* SubRule; /* array of SubRule tables */ -}; - -typedef struct HB_SubRuleSet_ HB_SubRuleSet; - - -struct HB_ContextSubstFormat1_ -{ - HB_Coverage Coverage; /* Coverage table */ - HB_UShort SubRuleSetCount; /* number of SubRuleSet tables */ - HB_SubRuleSet* SubRuleSet; /* array of SubRuleSet tables */ -}; - -typedef struct HB_ContextSubstFormat1_ HB_ContextSubstFormat1; - - -struct HB_SubClassRule_ -{ - HB_UShort GlyphCount; /* total number of context classes */ - HB_UShort SubstCount; /* number of SubstLookupRecord - tables */ - HB_UShort* Class; /* array of classes */ - HB_SubstLookupRecord* SubstLookupRecord; - /* array of SubstLookupRecord - tables */ -}; - -typedef struct HB_SubClassRule_ HB_SubClassRule; - - -struct HB_SubClassSet_ -{ - HB_UShort SubClassRuleCount; - /* number of SubClassRule tables */ - HB_SubClassRule* SubClassRule; /* array of SubClassRule tables */ -}; - -typedef struct HB_SubClassSet_ HB_SubClassSet; - - -/* The `MaxContextLength' field is not defined in the TTO specification - but simplifies the implementation of this format. It holds the - maximal context length used in the context rules. */ - -struct HB_ContextSubstFormat2_ -{ - HB_UShort MaxContextLength; - /* maximal context length */ - HB_Coverage Coverage; /* Coverage table */ - HB_ClassDefinition ClassDef; /* ClassDef table */ - HB_UShort SubClassSetCount; - /* number of SubClassSet tables */ - HB_SubClassSet* SubClassSet; /* array of SubClassSet tables */ -}; - -typedef struct HB_ContextSubstFormat2_ HB_ContextSubstFormat2; - - -struct HB_ContextSubstFormat3_ -{ - HB_UShort GlyphCount; /* number of input glyphs */ - HB_UShort SubstCount; /* number of SubstLookupRecords */ - HB_Coverage* Coverage; /* array of Coverage tables */ - HB_SubstLookupRecord* SubstLookupRecord; - /* array of substitution lookups */ -}; - -typedef struct HB_ContextSubstFormat3_ HB_ContextSubstFormat3; - - -struct HB_ContextSubst_ -{ - HB_UShort SubstFormat; /* 1, 2, or 3 */ - - union - { - HB_ContextSubstFormat1 csf1; - HB_ContextSubstFormat2 csf2; - HB_ContextSubstFormat3 csf3; - } csf; -}; - -typedef struct HB_ContextSubst_ HB_ContextSubst; - - -/* LookupType 6 */ - -struct HB_ChainSubRule_ -{ - HB_UShort BacktrackGlyphCount; - /* total number of backtrack glyphs */ - HB_UShort* Backtrack; /* array of backtrack glyph IDs */ - HB_UShort InputGlyphCount; - /* total number of input glyphs */ - HB_UShort* Input; /* array of input glyph IDs */ - HB_UShort LookaheadGlyphCount; - /* total number of lookahead glyphs */ - HB_UShort* Lookahead; /* array of lookahead glyph IDs */ - HB_UShort SubstCount; /* number of SubstLookupRecords */ - HB_SubstLookupRecord* SubstLookupRecord; - /* array of SubstLookupRecords */ -}; - -typedef struct HB_ChainSubRule_ HB_ChainSubRule; - - -struct HB_ChainSubRuleSet_ -{ - HB_UShort ChainSubRuleCount; - /* number of ChainSubRule tables */ - HB_ChainSubRule* ChainSubRule; /* array of ChainSubRule tables */ -}; - -typedef struct HB_ChainSubRuleSet_ HB_ChainSubRuleSet; - - -struct HB_ChainContextSubstFormat1_ -{ - HB_Coverage Coverage; /* Coverage table */ - HB_UShort ChainSubRuleSetCount; - /* number of ChainSubRuleSet tables */ - HB_ChainSubRuleSet* ChainSubRuleSet; - /* array of ChainSubRuleSet tables */ -}; - -typedef struct HB_ChainContextSubstFormat1_ HB_ChainContextSubstFormat1; - - -struct HB_ChainSubClassRule_ -{ - HB_UShort BacktrackGlyphCount; - /* total number of backtrack - classes */ - HB_UShort* Backtrack; /* array of backtrack classes */ - HB_UShort InputGlyphCount; - /* total number of context classes */ - HB_UShort* Input; /* array of context classes */ - HB_UShort LookaheadGlyphCount; - /* total number of lookahead - classes */ - HB_UShort* Lookahead; /* array of lookahead classes */ - HB_UShort SubstCount; /* number of SubstLookupRecords */ - HB_SubstLookupRecord* SubstLookupRecord; - /* array of substitution lookups */ -}; - -typedef struct HB_ChainSubClassRule_ HB_ChainSubClassRule; - - -struct HB_ChainSubClassSet_ -{ - HB_UShort ChainSubClassRuleCount; - /* number of ChainSubClassRule - tables */ - HB_ChainSubClassRule* ChainSubClassRule; - /* array of ChainSubClassRule - tables */ -}; - -typedef struct HB_ChainSubClassSet_ HB_ChainSubClassSet; - - -/* The `MaxXXXLength' fields are not defined in the TTO specification - but simplifies the implementation of this format. It holds the - maximal context length used in the specific context rules. */ - -struct HB_ChainContextSubstFormat2_ -{ - HB_Coverage Coverage; /* Coverage table */ - - HB_UShort MaxBacktrackLength; - /* maximal backtrack length */ - HB_ClassDefinition BacktrackClassDef; - /* BacktrackClassDef table */ - HB_UShort MaxInputLength; - /* maximal input length */ - HB_ClassDefinition InputClassDef; - /* InputClassDef table */ - HB_UShort MaxLookaheadLength; - /* maximal lookahead length */ - HB_ClassDefinition LookaheadClassDef; - /* LookaheadClassDef table */ - - HB_UShort ChainSubClassSetCount; - /* number of ChainSubClassSet - tables */ - HB_ChainSubClassSet* ChainSubClassSet; - /* array of ChainSubClassSet - tables */ -}; - -typedef struct HB_ChainContextSubstFormat2_ HB_ChainContextSubstFormat2; - - -struct HB_ChainContextSubstFormat3_ -{ - HB_UShort BacktrackGlyphCount; - /* number of backtrack glyphs */ - HB_Coverage* BacktrackCoverage; - /* array of backtrack Coverage - tables */ - HB_UShort InputGlyphCount; - /* number of input glyphs */ - HB_Coverage* InputCoverage; - /* array of input coverage - tables */ - HB_UShort LookaheadGlyphCount; - /* number of lookahead glyphs */ - HB_Coverage* LookaheadCoverage; - /* array of lookahead coverage - tables */ - HB_UShort SubstCount; /* number of SubstLookupRecords */ - HB_SubstLookupRecord* SubstLookupRecord; - /* array of substitution lookups */ -}; - -typedef struct HB_ChainContextSubstFormat3_ HB_ChainContextSubstFormat3; - - -struct HB_ChainContextSubst_ -{ - HB_UShort SubstFormat; /* 1, 2, or 3 */ - - union - { - HB_ChainContextSubstFormat1 ccsf1; - HB_ChainContextSubstFormat2 ccsf2; - HB_ChainContextSubstFormat3 ccsf3; - } ccsf; -}; - -typedef struct HB_ChainContextSubst_ HB_ChainContextSubst; - - -#if 0 -/* LookupType 7 */ -struct HB_ExtensionSubst_ -{ - HB_UShort SubstFormat; /* always 1 */ - HB_UShort LookuptType; /* lookup-type of referenced subtable */ - HB_GSUB_SubTable *subtable; /* referenced subtable */ -}; - -typedef struct HB_ExtensionSubst_ HB_ExtensionSubst; -#endif - - -/* LookupType 8 */ -struct HB_ReverseChainContextSubst_ -{ - HB_UShort SubstFormat; /* always 1 */ - HB_Coverage Coverage; /* coverage table for input glyphs */ - HB_UShort BacktrackGlyphCount; /* number of backtrack glyphs */ - HB_Coverage* BacktrackCoverage; /* array of backtrack Coverage - tables */ - HB_UShort LookaheadGlyphCount; /* number of lookahead glyphs */ - HB_Coverage* LookaheadCoverage; /* array of lookahead Coverage - tables */ - HB_UShort GlyphCount; /* number of Glyph IDs */ - HB_UShort* Substitute; /* array of substitute Glyph ID */ -}; - -typedef struct HB_ReverseChainContextSubst_ HB_ReverseChainContextSubst; - - -union HB_GSUB_SubTable_ -{ - HB_SingleSubst single; - HB_MultipleSubst multiple; - HB_AlternateSubst alternate; - HB_LigatureSubst ligature; - HB_ContextSubst context; - HB_ChainContextSubst chain; - HB_ReverseChainContextSubst reverse; -}; - - - - -HB_INTERNAL HB_Error -_HB_GSUB_Load_SubTable( HB_GSUB_SubTable* st, - HB_Stream stream, - HB_UShort lookup_type ); - -HB_INTERNAL void -_HB_GSUB_Free_SubTable( HB_GSUB_SubTable* st, - HB_UShort lookup_type ); - -HB_END_HEADER - -#endif /* HARFBUZZ_GSUB_PRIVATE_H */ diff --git a/src/harfbuzz-gsub.c b/src/harfbuzz-gsub.c deleted file mode 100644 index cb8c9c33f..000000000 --- a/src/harfbuzz-gsub.c +++ /dev/null @@ -1,4304 +0,0 @@ -/* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2006 Behdad Esfahbod - * Copyright (C) 2007 Red Hat, Inc. - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Red Hat Author(s): Behdad Esfahbod - */ - -#include "harfbuzz-impl.h" -#include "harfbuzz-gsub-private.h" -#include "harfbuzz-open-private.h" -#include "harfbuzz-gdef-private.h" - -static HB_Error GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub, - HB_UShort lookup_index, - HB_Buffer buffer, - HB_UShort context_length, - int nesting_level ); - - - -/********************** - * Auxiliary functions - **********************/ - - - -HB_Error HB_Load_GSUB_Table( HB_Font font, - HB_GSUBHeader** retptr, - hb_ot_layout_t *layout ) -{ - HB_Stream stream = font->stream; - HB_Error error; - HB_UInt cur_offset, new_offset, base_offset; - - HB_GSUBHeader* gsub; - - if ( !retptr || !layout ) - return ERR(HB_Err_Invalid_Argument); - - if ( GOTO_Table( TTAG_GSUB ) ) - return error; - - base_offset = FILE_Pos(); - - if ( ALLOC ( gsub, sizeof( *gsub ) ) ) - return error; - - - /* skip version */ - - if ( FILE_Seek( base_offset + 4L ) || - ACCESS_Frame( 2L ) ) - goto Fail4; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_ScriptList( &gsub->ScriptList, - stream ) ) != HB_Err_Ok ) - goto Fail4; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_FeatureList( &gsub->FeatureList, - stream ) ) != HB_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_LookupList( &gsub->LookupList, - stream, HB_Type_GSUB ) ) != HB_Err_Ok ) - goto Fail2; - - gsub->layout = layout; /* can be NULL */ - - *retptr = gsub; - - return HB_Err_Ok; - -Fail2: - _HB_OPEN_Free_FeatureList( &gsub->FeatureList ); - -Fail3: - _HB_OPEN_Free_ScriptList( &gsub->ScriptList ); - -Fail4: - FREE ( gsub ); - - - return error; -} - - -HB_Error HB_Done_GSUB_Table( HB_GSUBHeader* gsub ) -{ - _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB ); - _HB_OPEN_Free_FeatureList( &gsub->FeatureList ); - _HB_OPEN_Free_ScriptList( &gsub->ScriptList ); - - FREE( gsub ); - - return HB_Err_Ok; -} - -/***************************** - * SubTable related functions - *****************************/ - - -/* LookupType 1 */ - -/* SingleSubstFormat1 */ -/* SingleSubstFormat2 */ - -static HB_Error Load_SingleSubst( HB_GSUB_SubTable* st, - HB_Stream stream ) -{ - HB_Error error; - HB_SingleSubst* ss = &st->single; - - HB_UShort n, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_UShort* s; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 4L ) ) - return error; - - ss->SubstFormat = GET_UShort(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &ss->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - switch ( ss->SubstFormat ) - { - case 1: - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - ss->ssf.ssf1.DeltaGlyphID = GET_UShort(); - - FORGET_Frame(); - - break; - - case 2: - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = ss->ssf.ssf2.GlyphCount = GET_UShort(); - - FORGET_Frame(); - - ss->ssf.ssf2.Substitute = NULL; - - if ( ALLOC_ARRAY( ss->ssf.ssf2.Substitute, count, HB_UShort ) ) - goto Fail2; - - s = ss->ssf.ssf2.Substitute; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - s[n] = GET_UShort(); - - FORGET_Frame(); - - break; - - default: - return ERR(HB_Err_Invalid_SubTable_Format); - } - - return HB_Err_Ok; - -Fail1: - FREE( s ); - -Fail2: - _HB_OPEN_Free_Coverage( &ss->Coverage ); - return error; -} - - -static void Free_SingleSubst( HB_GSUB_SubTable* st ) -{ - HB_SingleSubst* ss = &st->single; - - switch ( ss->SubstFormat ) - { - case 1: - break; - - case 2: - FREE( ss->ssf.ssf2.Substitute ); - break; - - default: - break; - } - - _HB_OPEN_Free_Coverage( &ss->Coverage ); -} - - -static HB_Error Lookup_SingleSubst( HB_GSUBHeader* gsub, - HB_GSUB_SubTable* st, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort index, value, property; - HB_Error error; - HB_SingleSubst* ss = &st->single; - hb_ot_layout_t* layout = gsub->layout; - - HB_UNUSED(nesting_level); - - if ( context_length != 0xFFFF && context_length < 1 ) - return HB_Err_Not_Covered; - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - error = _HB_OPEN_Coverage_Index( &ss->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - switch ( ss->SubstFormat ) - { - case 1: - value = (IN_CURGLYPH() + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF; - if ( REPLACE_Glyph( buffer, value ) ) - return error; - break; - - case 2: - if ( index >= ss->ssf.ssf2.GlyphCount ) - return ERR(HB_Err_Invalid_SubTable); - value = ss->ssf.ssf2.Substitute[index]; - if ( REPLACE_Glyph( buffer, value ) ) - return error; - break; - - default: - return ERR(HB_Err_Invalid_SubTable); - } - - if ( _hb_ot_layout_has_new_glyph_classes (layout) ) - { - /* we inherit the old glyph class to the substituted glyph */ - - hb_ot_layout_set_glyph_class (layout, value, property); - } - - return HB_Err_Ok; -} - - -/* LookupType 2 */ - -/* Sequence */ - -static HB_Error Load_Sequence( HB_Sequence* s, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - HB_UShort* sub; - - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = s->GlyphCount = GET_UShort(); - - FORGET_Frame(); - - s->Substitute = NULL; - - if ( count ) - { - if ( ALLOC_ARRAY( s->Substitute, count, HB_UShort ) ) - return error; - - sub = s->Substitute; - - if ( ACCESS_Frame( count * 2L ) ) - { - FREE( sub ); - return error; - } - - for ( n = 0; n < count; n++ ) - sub[n] = GET_UShort(); - - FORGET_Frame(); - } - - return HB_Err_Ok; -} - - -static void Free_Sequence( HB_Sequence* s ) -{ - FREE( s->Substitute ); -} - - -/* MultipleSubstFormat1 */ - -static HB_Error Load_MultipleSubst( HB_GSUB_SubTable* st, - HB_Stream stream ) -{ - HB_Error error; - HB_MultipleSubst* ms = &st->multiple; - - HB_UShort n = 0, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_Sequence* s; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 4L ) ) - return error; - - ms->SubstFormat = GET_UShort(); /* should be 1 */ - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &ms->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = ms->SequenceCount = GET_UShort(); - - FORGET_Frame(); - - ms->Sequence = NULL; - - if ( ALLOC_ARRAY( ms->Sequence, count, HB_Sequence ) ) - goto Fail2; - - s = ms->Sequence; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Sequence( &s[n], stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - Free_Sequence( &s[m] ); - - FREE( s ); - -Fail2: - _HB_OPEN_Free_Coverage( &ms->Coverage ); - return error; -} - - -static void Free_MultipleSubst( HB_GSUB_SubTable* st ) -{ - HB_UShort n, count; - HB_MultipleSubst* ms = &st->multiple; - - HB_Sequence* s; - - - if ( ms->Sequence ) - { - count = ms->SequenceCount; - s = ms->Sequence; - - for ( n = 0; n < count; n++ ) - Free_Sequence( &s[n] ); - - FREE( s ); - } - - _HB_OPEN_Free_Coverage( &ms->Coverage ); -} - - -static HB_Error Lookup_MultipleSubst( HB_GSUBHeader* gsub, - HB_GSUB_SubTable* st, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_Error error; - HB_UShort index, property, n, count; - HB_UShort*s; - HB_MultipleSubst* ms = &st->multiple; - hb_ot_layout_t* layout = gsub->layout; - - HB_UNUSED(nesting_level); - - if ( context_length != 0xFFFF && context_length < 1 ) - return HB_Err_Not_Covered; - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - error = _HB_OPEN_Coverage_Index( &ms->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - if ( index >= ms->SequenceCount ) - return ERR(HB_Err_Invalid_SubTable); - - count = ms->Sequence[index].GlyphCount; - s = ms->Sequence[index].Substitute; - - if ( ADD_String( buffer, 1, count, s, 0xFFFF, 0xFFFF ) ) - return error; - - if ( _hb_ot_layout_has_new_glyph_classes (layout) ) - { - /* this is a guess only ... */ - - if ( property == HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE ) - property = HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH; - - for ( n = 0; n < count; n++ ) - hb_ot_layout_set_glyph_class (layout, s[n], property); - } - - return HB_Err_Ok; -} - - -/* LookupType 3 */ - -/* AlternateSet */ - -static HB_Error Load_AlternateSet( HB_AlternateSet* as, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - HB_UShort* a; - - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = as->GlyphCount = GET_UShort(); - - FORGET_Frame(); - - as->Alternate = NULL; - - if ( ALLOC_ARRAY( as->Alternate, count, HB_UShort ) ) - return error; - - a = as->Alternate; - - if ( ACCESS_Frame( count * 2L ) ) - { - FREE( a ); - return error; - } - - for ( n = 0; n < count; n++ ) - a[n] = GET_UShort(); - - FORGET_Frame(); - - return HB_Err_Ok; -} - - -static void Free_AlternateSet( HB_AlternateSet* as ) -{ - FREE( as->Alternate ); -} - - -/* AlternateSubstFormat1 */ - -static HB_Error Load_AlternateSubst( HB_GSUB_SubTable* st, - HB_Stream stream ) -{ - HB_Error error; - HB_AlternateSubst* as = &st->alternate; - - HB_UShort n = 0, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_AlternateSet* aset; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 4L ) ) - return error; - - as->SubstFormat = GET_UShort(); /* should be 1 */ - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &as->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = as->AlternateSetCount = GET_UShort(); - - FORGET_Frame(); - - as->AlternateSet = NULL; - - if ( ALLOC_ARRAY( as->AlternateSet, count, HB_AlternateSet ) ) - goto Fail2; - - aset = as->AlternateSet; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_AlternateSet( &aset[n], stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - Free_AlternateSet( &aset[m] ); - - FREE( aset ); - -Fail2: - _HB_OPEN_Free_Coverage( &as->Coverage ); - return error; -} - - -static void Free_AlternateSubst( HB_GSUB_SubTable* st ) -{ - HB_UShort n, count; - HB_AlternateSubst* as = &st->alternate; - - HB_AlternateSet* aset; - - - if ( as->AlternateSet ) - { - count = as->AlternateSetCount; - aset = as->AlternateSet; - - for ( n = 0; n < count; n++ ) - Free_AlternateSet( &aset[n] ); - - FREE( aset ); - } - - _HB_OPEN_Free_Coverage( &as->Coverage ); -} - - -static HB_Error Lookup_AlternateSubst( HB_GSUBHeader* gsub, - HB_GSUB_SubTable* st, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_Error error; - HB_UShort index, value, alt_index, property; - HB_AlternateSubst* as = &st->alternate; - hb_ot_layout_t* layout = gsub->layout; - HB_AlternateSet aset; - - HB_UNUSED(nesting_level); - - if ( context_length != 0xFFFF && context_length < 1 ) - return HB_Err_Not_Covered; - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - error = _HB_OPEN_Coverage_Index( &as->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - aset = as->AlternateSet[index]; - - /* we use a user-defined callback function to get the alternate index */ - - if ( gsub->altfunc ) - alt_index = (gsub->altfunc)( buffer->out_pos, IN_CURGLYPH(), - aset.GlyphCount, aset.Alternate, - gsub->data ); - else - alt_index = 0; - - value = aset.Alternate[alt_index]; - if ( REPLACE_Glyph( buffer, value ) ) - return error; - - if ( _hb_ot_layout_has_new_glyph_classes (layout) ) - /* we inherit the old glyph class to the substituted glyph */ - hb_ot_layout_set_glyph_class (layout, value, property); - - return HB_Err_Ok; -} - - -/* LookupType 4 */ - -/* Ligature */ - -static HB_Error Load_Ligature( HB_Ligature* l, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - HB_UShort* c; - - - if ( ACCESS_Frame( 4L ) ) - return error; - - l->LigGlyph = GET_UShort(); - l->ComponentCount = GET_UShort(); - - FORGET_Frame(); - - l->Component = NULL; - - count = l->ComponentCount - 1; /* only ComponentCount - 1 elements */ - - if ( ALLOC_ARRAY( l->Component, count, HB_UShort ) ) - return error; - - c = l->Component; - - if ( ACCESS_Frame( count * 2L ) ) - { - FREE( c ); - return error; - } - - for ( n = 0; n < count; n++ ) - c[n] = GET_UShort(); - - FORGET_Frame(); - - return HB_Err_Ok; -} - - -static void Free_Ligature( HB_Ligature* l ) -{ - FREE( l->Component ); -} - - -/* LigatureSet */ - -static HB_Error Load_LigatureSet( HB_LigatureSet* ls, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n = 0, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_Ligature* l; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = ls->LigatureCount = GET_UShort(); - - FORGET_Frame(); - - ls->Ligature = NULL; - - if ( ALLOC_ARRAY( ls->Ligature, count, HB_Ligature ) ) - return error; - - l = ls->Ligature; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Ligature( &l[n], stream ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail: - for ( m = 0; m < n; m++ ) - Free_Ligature( &l[m] ); - - FREE( l ); - return error; -} - - -static void Free_LigatureSet( HB_LigatureSet* ls ) -{ - HB_UShort n, count; - - HB_Ligature* l; - - - if ( ls->Ligature ) - { - count = ls->LigatureCount; - l = ls->Ligature; - - for ( n = 0; n < count; n++ ) - Free_Ligature( &l[n] ); - - FREE( l ); - } -} - - -/* LigatureSubstFormat1 */ - -static HB_Error Load_LigatureSubst( HB_GSUB_SubTable* st, - HB_Stream stream ) -{ - HB_Error error; - HB_LigatureSubst* ls = &st->ligature; - - HB_UShort n = 0, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_LigatureSet* lset; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 4L ) ) - return error; - - ls->SubstFormat = GET_UShort(); /* should be 1 */ - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &ls->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = ls->LigatureSetCount = GET_UShort(); - - FORGET_Frame(); - - ls->LigatureSet = NULL; - - if ( ALLOC_ARRAY( ls->LigatureSet, count, HB_LigatureSet ) ) - goto Fail2; - - lset = ls->LigatureSet; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_LigatureSet( &lset[n], stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - Free_LigatureSet( &lset[m] ); - - FREE( lset ); - -Fail2: - _HB_OPEN_Free_Coverage( &ls->Coverage ); - return error; -} - - -static void Free_LigatureSubst( HB_GSUB_SubTable* st ) -{ - HB_UShort n, count; - HB_LigatureSubst* ls = &st->ligature; - - HB_LigatureSet* lset; - - - if ( ls->LigatureSet ) - { - count = ls->LigatureSetCount; - lset = ls->LigatureSet; - - for ( n = 0; n < count; n++ ) - Free_LigatureSet( &lset[n] ); - - FREE( lset ); - } - - _HB_OPEN_Free_Coverage( &ls->Coverage ); -} - - -static HB_Error Lookup_LigatureSubst( HB_GSUBHeader* gsub, - HB_GSUB_SubTable* st, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort index, property; - HB_Error error; - HB_UShort numlig, i, j, is_mark, first_is_mark = FALSE; - HB_UShort* c; - HB_LigatureSubst* ls = &st->ligature; - hb_ot_layout_t* layout = gsub->layout; - - HB_Ligature* lig; - - HB_UNUSED(nesting_level); - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - if ( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) - first_is_mark = TRUE; - - error = _HB_OPEN_Coverage_Index( &ls->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - if ( index >= ls->LigatureSetCount ) - return ERR(HB_Err_Invalid_SubTable); - - lig = ls->LigatureSet[index].Ligature; - - for ( numlig = ls->LigatureSet[index].LigatureCount; - numlig; - numlig--, lig++ ) - { - if ( buffer->in_pos + lig->ComponentCount > buffer->in_length ) - goto next_ligature; /* Not enough glyphs in input */ - - c = lig->Component; - - is_mark = first_is_mark; - - if ( context_length != 0xFFFF && context_length < lig->ComponentCount ) - break; - - for ( i = 1, j = buffer->in_pos + 1; i < lig->ComponentCount; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + lig->ComponentCount - i == (HB_Int)buffer->in_length ) - goto next_ligature; - j++; - } - - if ( !( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) ) - is_mark = FALSE; - - if ( IN_GLYPH( j ) != c[i - 1] ) - goto next_ligature; - } - - if ( _hb_ot_layout_has_new_glyph_classes (layout) ) - /* this is just a guess ... */ - hb_ot_layout_set_glyph_class (layout, lig->LigGlyph, is_mark ? HB_OT_LAYOUT_GLYPH_CLASS_MARK : HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE); - - if ( j == buffer->in_pos + i ) /* No input glyphs skipped */ - { - /* We don't use a new ligature ID if there are no skipped - glyphs and the ligature already has an ID. */ - - if ( IN_LIGID( buffer->in_pos ) ) - { - if ( ADD_String( buffer, i, 1, &lig->LigGlyph, - 0xFFFF, 0xFFFF ) ) - return error; - } - else - { - HB_UShort ligID = _hb_buffer_allocate_ligid( buffer ); - if ( ADD_String( buffer, i, 1, &lig->LigGlyph, - 0xFFFF, ligID ) ) - return error; - } - } - else - { - HB_UShort ligID = _hb_buffer_allocate_ligid( buffer ); - if ( ADD_Glyph( buffer, lig->LigGlyph, 0xFFFF, ligID ) ) - return error; - - /* Now we must do a second loop to copy the skipped glyphs to - `out' and assign component values to it. We start with the - glyph after the first component. Glyphs between component - i and i+1 belong to component i. Together with the ligID - value it is later possible to check whether a specific - component value really belongs to a given ligature. */ - - for ( i = 0; i < lig->ComponentCount - 1; i++ ) - { - while ( CHECK_Property( layout, IN_CURITEM(), - flags, &property ) ) - if ( ADD_Glyph( buffer, IN_CURGLYPH(), i, ligID ) ) - return error; - - (buffer->in_pos)++; - } - } - - return HB_Err_Ok; - - next_ligature: - ; - } - - return HB_Err_Not_Covered; -} - - -/* Do the actual substitution for a context substitution (either format - 5 or 6). This is only called after we've determined that the input - matches the subrule. */ - -static HB_Error Do_ContextSubst( HB_GSUBHeader* gsub, - HB_UShort GlyphCount, - HB_UShort SubstCount, - HB_SubstLookupRecord* subst, - HB_Buffer buffer, - int nesting_level ) -{ - HB_Error error; - HB_UInt i, old_pos; - - - i = 0; - - while ( i < GlyphCount ) - { - if ( SubstCount && i == subst->SequenceIndex ) - { - old_pos = buffer->in_pos; - - /* Do a substitution */ - - error = GSUB_Do_Glyph_Lookup( gsub, subst->LookupListIndex, buffer, - GlyphCount, nesting_level ); - - subst++; - SubstCount--; - i += buffer->in_pos - old_pos; - - if ( error == HB_Err_Not_Covered ) - { - if ( COPY_Glyph( buffer ) ) - return error; - i++; - } - else if ( error ) - return error; - } - else - { - /* No substitution for this index */ - - if ( COPY_Glyph( buffer ) ) - return error; - i++; - } - } - - return HB_Err_Ok; -} - - -/* LookupType 5 */ - -/* SubRule */ - -static HB_Error Load_SubRule( HB_SubRule* sr, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - HB_UShort* i; - - HB_SubstLookupRecord* slr; - - - if ( ACCESS_Frame( 4L ) ) - return error; - - sr->GlyphCount = GET_UShort(); - sr->SubstCount = GET_UShort(); - - FORGET_Frame(); - - sr->Input = NULL; - - count = sr->GlyphCount - 1; /* only GlyphCount - 1 elements */ - - if ( ALLOC_ARRAY( sr->Input, count, HB_UShort ) ) - return error; - - i = sr->Input; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail2; - - for ( n = 0; n < count; n++ ) - i[n] = GET_UShort(); - - FORGET_Frame(); - - sr->SubstLookupRecord = NULL; - - count = sr->SubstCount; - - if ( ALLOC_ARRAY( sr->SubstLookupRecord, count, HB_SubstLookupRecord ) ) - goto Fail2; - - slr = sr->SubstLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - slr[n].SequenceIndex = GET_UShort(); - slr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return HB_Err_Ok; - -Fail1: - FREE( slr ); - -Fail2: - FREE( i ); - return error; -} - - -static void Free_SubRule( HB_SubRule* sr ) -{ - FREE( sr->SubstLookupRecord ); - FREE( sr->Input ); -} - - -/* SubRuleSet */ - -static HB_Error Load_SubRuleSet( HB_SubRuleSet* srs, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n = 0, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_SubRule* sr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = srs->SubRuleCount = GET_UShort(); - - FORGET_Frame(); - - srs->SubRule = NULL; - - if ( ALLOC_ARRAY( srs->SubRule, count, HB_SubRule ) ) - return error; - - sr = srs->SubRule; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_SubRule( &sr[n], stream ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail: - for ( m = 0; m < n; m++ ) - Free_SubRule( &sr[m] ); - - FREE( sr ); - return error; -} - - -static void Free_SubRuleSet( HB_SubRuleSet* srs ) -{ - HB_UShort n, count; - - HB_SubRule* sr; - - - if ( srs->SubRule ) - { - count = srs->SubRuleCount; - sr = srs->SubRule; - - for ( n = 0; n < count; n++ ) - Free_SubRule( &sr[n] ); - - FREE( sr ); - } -} - - -/* ContextSubstFormat1 */ - -static HB_Error Load_ContextSubst1( HB_ContextSubstFormat1* csf1, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n = 0, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_SubRuleSet* srs; - - - base_offset = FILE_Pos() - 2L; - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &csf1->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = csf1->SubRuleSetCount = GET_UShort(); - - FORGET_Frame(); - - csf1->SubRuleSet = NULL; - - if ( ALLOC_ARRAY( csf1->SubRuleSet, count, HB_SubRuleSet ) ) - goto Fail2; - - srs = csf1->SubRuleSet; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_SubRuleSet( &srs[n], stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - Free_SubRuleSet( &srs[m] ); - - FREE( srs ); - -Fail2: - _HB_OPEN_Free_Coverage( &csf1->Coverage ); - return error; -} - - -static void Free_ContextSubst1( HB_ContextSubstFormat1* csf1 ) -{ - HB_UShort n, count; - - HB_SubRuleSet* srs; - - - if ( csf1->SubRuleSet ) - { - count = csf1->SubRuleSetCount; - srs = csf1->SubRuleSet; - - for ( n = 0; n < count; n++ ) - Free_SubRuleSet( &srs[n] ); - - FREE( srs ); - } - - _HB_OPEN_Free_Coverage( &csf1->Coverage ); -} - - -/* SubClassRule */ - -static HB_Error Load_SubClassRule( HB_ContextSubstFormat2* csf2, - HB_SubClassRule* scr, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - - HB_UShort* c; - HB_SubstLookupRecord* slr; - - - if ( ACCESS_Frame( 4L ) ) - return error; - - scr->GlyphCount = GET_UShort(); - scr->SubstCount = GET_UShort(); - - if ( scr->GlyphCount > csf2->MaxContextLength ) - csf2->MaxContextLength = scr->GlyphCount; - - FORGET_Frame(); - - scr->Class = NULL; - - count = scr->GlyphCount - 1; /* only GlyphCount - 1 elements */ - - if ( ALLOC_ARRAY( scr->Class, count, HB_UShort ) ) - return error; - - c = scr->Class; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail2; - - for ( n = 0; n < count; n++ ) - c[n] = GET_UShort(); - - FORGET_Frame(); - - scr->SubstLookupRecord = NULL; - - count = scr->SubstCount; - - if ( ALLOC_ARRAY( scr->SubstLookupRecord, count, HB_SubstLookupRecord ) ) - goto Fail2; - - slr = scr->SubstLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - slr[n].SequenceIndex = GET_UShort(); - slr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return HB_Err_Ok; - -Fail1: - FREE( slr ); - -Fail2: - FREE( c ); - return error; -} - - -static void Free_SubClassRule( HB_SubClassRule* scr ) -{ - FREE( scr->SubstLookupRecord ); - FREE( scr->Class ); -} - - -/* SubClassSet */ - -static HB_Error Load_SubClassSet( HB_ContextSubstFormat2* csf2, - HB_SubClassSet* scs, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n = 0, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_SubClassRule* scr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = scs->SubClassRuleCount = GET_UShort(); - - FORGET_Frame(); - - scs->SubClassRule = NULL; - - if ( ALLOC_ARRAY( scs->SubClassRule, count, HB_SubClassRule ) ) - return error; - - scr = scs->SubClassRule; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_SubClassRule( csf2, &scr[n], - stream ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail: - for ( m = 0; m < n; m++ ) - Free_SubClassRule( &scr[m] ); - - FREE( scr ); - return error; -} - - -static void Free_SubClassSet( HB_SubClassSet* scs ) -{ - HB_UShort n, count; - - HB_SubClassRule* scr; - - - if ( scs->SubClassRule ) - { - count = scs->SubClassRuleCount; - scr = scs->SubClassRule; - - for ( n = 0; n < count; n++ ) - Free_SubClassRule( &scr[n] ); - - FREE( scr ); - } -} - - -/* ContextSubstFormat2 */ - -static HB_Error Load_ContextSubst2( HB_ContextSubstFormat2* csf2, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n = 0, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_SubClassSet* scs; - - - base_offset = FILE_Pos() - 2; - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &csf2->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 4L ) ) - goto Fail3; - - new_offset = GET_UShort() + base_offset; - - /* `SubClassSetCount' is the upper limit for class values, thus we - read it now to make an additional safety check. */ - - count = csf2->SubClassSetCount = GET_UShort(); - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_ClassDefinition( &csf2->ClassDef, count, - stream ) ) != HB_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - - csf2->SubClassSet = NULL; - csf2->MaxContextLength = 0; - - if ( ALLOC_ARRAY( csf2->SubClassSet, count, HB_SubClassSet ) ) - goto Fail2; - - scs = csf2->SubClassSet; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - if ( new_offset != base_offset ) /* not a NULL offset */ - { - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_SubClassSet( csf2, &scs[n], - stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - else - { - /* we create a SubClassSet table with no entries */ - - csf2->SubClassSet[n].SubClassRuleCount = 0; - csf2->SubClassSet[n].SubClassRule = NULL; - } - } - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - Free_SubClassSet( &scs[m] ); - - FREE( scs ); - -Fail2: - _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef ); - -Fail3: - _HB_OPEN_Free_Coverage( &csf2->Coverage ); - return error; -} - - -static void Free_ContextSubst2( HB_ContextSubstFormat2* csf2 ) -{ - HB_UShort n, count; - - HB_SubClassSet* scs; - - - if ( csf2->SubClassSet ) - { - count = csf2->SubClassSetCount; - scs = csf2->SubClassSet; - - for ( n = 0; n < count; n++ ) - Free_SubClassSet( &scs[n] ); - - FREE( scs ); - } - - _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef ); - _HB_OPEN_Free_Coverage( &csf2->Coverage ); -} - - -/* ContextSubstFormat3 */ - -static HB_Error Load_ContextSubst3( HB_ContextSubstFormat3* csf3, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n = 0, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_Coverage* c; - HB_SubstLookupRecord* slr; - - - base_offset = FILE_Pos() - 2L; - - if ( ACCESS_Frame( 4L ) ) - return error; - - csf3->GlyphCount = GET_UShort(); - csf3->SubstCount = GET_UShort(); - - FORGET_Frame(); - - csf3->Coverage = NULL; - - count = csf3->GlyphCount; - - if ( ALLOC_ARRAY( csf3->Coverage, count, HB_Coverage ) ) - return error; - - c = csf3->Coverage; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != HB_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - } - - csf3->SubstLookupRecord = NULL; - - count = csf3->SubstCount; - - if ( ALLOC_ARRAY( csf3->SubstLookupRecord, count, - HB_SubstLookupRecord ) ) - goto Fail2; - - slr = csf3->SubstLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - slr[n].SequenceIndex = GET_UShort(); - slr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return HB_Err_Ok; - -Fail1: - FREE( slr ); - -Fail2: - for ( m = 0; m < n; m++ ) - _HB_OPEN_Free_Coverage( &c[m] ); - - FREE( c ); - return error; -} - - -static void Free_ContextSubst3( HB_ContextSubstFormat3* csf3 ) -{ - HB_UShort n, count; - - HB_Coverage* c; - - - FREE( csf3->SubstLookupRecord ); - - if ( csf3->Coverage ) - { - count = csf3->GlyphCount; - c = csf3->Coverage; - - for ( n = 0; n < count; n++ ) - _HB_OPEN_Free_Coverage( &c[n] ); - - FREE( c ); - } -} - - -/* ContextSubst */ - -static HB_Error Load_ContextSubst( HB_GSUB_SubTable* st, - HB_Stream stream ) -{ - HB_Error error; - HB_ContextSubst* cs = &st->context; - - - if ( ACCESS_Frame( 2L ) ) - return error; - - cs->SubstFormat = GET_UShort(); - - FORGET_Frame(); - - switch ( cs->SubstFormat ) - { - case 1: return Load_ContextSubst1( &cs->csf.csf1, stream ); - case 2: return Load_ContextSubst2( &cs->csf.csf2, stream ); - case 3: return Load_ContextSubst3( &cs->csf.csf3, stream ); - default: return ERR(HB_Err_Invalid_SubTable_Format); - } - - return HB_Err_Ok; /* never reached */ -} - - -static void Free_ContextSubst( HB_GSUB_SubTable* st ) -{ - HB_ContextSubst* cs = &st->context; - - switch ( cs->SubstFormat ) - { - case 1: Free_ContextSubst1( &cs->csf.csf1 ); break; - case 2: Free_ContextSubst2( &cs->csf.csf2 ); break; - case 3: Free_ContextSubst3( &cs->csf.csf3 ); break; - default: break; - } -} - - -static HB_Error Lookup_ContextSubst1( HB_GSUBHeader* gsub, - HB_ContextSubstFormat1* csf1, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort index, property; - HB_UShort i, j, k, numsr; - HB_Error error; - - HB_SubRule* sr; - hb_ot_layout_t* layout; - - - layout = gsub->layout; - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - error = _HB_OPEN_Coverage_Index( &csf1->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - sr = csf1->SubRuleSet[index].SubRule; - numsr = csf1->SubRuleSet[index].SubRuleCount; - - for ( k = 0; k < numsr; k++ ) - { - if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount ) - goto next_subrule; - - if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length ) - goto next_subrule; /* context is too long */ - - for ( i = 1, j = buffer->in_pos + 1; i < sr[k].GlyphCount; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + sr[k].GlyphCount - i == (HB_Int)buffer->in_length ) - goto next_subrule; - j++; - } - - if ( IN_GLYPH( j ) != sr[k].Input[i - 1] ) - goto next_subrule; - } - - return Do_ContextSubst( gsub, sr[k].GlyphCount, - sr[k].SubstCount, sr[k].SubstLookupRecord, - buffer, - nesting_level ); - next_subrule: - ; - } - - return HB_Err_Not_Covered; -} - - -static HB_Error Lookup_ContextSubst2( HB_GSUBHeader* gsub, - HB_ContextSubstFormat2* csf2, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort index, property; - HB_Error error; - HB_UShort i, j, k, known_classes; - - HB_UShort* classes; - HB_UShort* cl; - - HB_SubClassSet* scs; - HB_SubClassRule* sr; - hb_ot_layout_t* layout; - - - layout = gsub->layout; - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - /* Note: The coverage table in format 2 doesn't give an index into - anything. It just lets us know whether or not we need to - do any lookup at all. */ - - error = _HB_OPEN_Coverage_Index( &csf2->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - if (csf2->MaxContextLength < 1) - return HB_Err_Not_Covered; - - if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, HB_UShort ) ) - return error; - - error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_CURGLYPH(), - &classes[0], NULL ); - if ( error && error != HB_Err_Not_Covered ) - goto End; - known_classes = 0; - - scs = &csf2->SubClassSet[classes[0]]; - if ( !scs ) - { - error = ERR(HB_Err_Invalid_SubTable); - goto End; - } - - for ( k = 0; k < scs->SubClassRuleCount; k++ ) - { - sr = &scs->SubClassRule[k]; - - if ( context_length != 0xFFFF && context_length < sr->GlyphCount ) - goto next_subclassrule; - - if ( buffer->in_pos + sr->GlyphCount > buffer->in_length ) - goto next_subclassrule; /* context is too long */ - - cl = sr->Class; - - /* Start at 1 because [0] is implied */ - - for ( i = 1, j = buffer->in_pos + 1; i < sr->GlyphCount; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - goto End; - - if ( j + sr->GlyphCount - i < (HB_Int)buffer->in_length ) - goto next_subclassrule; - j++; - } - - if ( i > known_classes ) - { - /* Keeps us from having to do this for each rule */ - - error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL ); - if ( error && error != HB_Err_Not_Covered ) - goto End; - known_classes = i; - } - - if ( cl[i - 1] != classes[i] ) - goto next_subclassrule; - } - - error = Do_ContextSubst( gsub, sr->GlyphCount, - sr->SubstCount, sr->SubstLookupRecord, - buffer, - nesting_level ); - goto End; - - next_subclassrule: - ; - } - - error = HB_Err_Not_Covered; - -End: - FREE( classes ); - return error; -} - - -static HB_Error Lookup_ContextSubst3( HB_GSUBHeader* gsub, - HB_ContextSubstFormat3* csf3, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_Error error; - HB_UShort index, i, j, property; - - HB_Coverage* c; - hb_ot_layout_t* layout; - - - layout = gsub->layout; - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - if ( context_length != 0xFFFF && context_length < csf3->GlyphCount ) - return HB_Err_Not_Covered; - - if ( buffer->in_pos + csf3->GlyphCount > buffer->in_length ) - return HB_Err_Not_Covered; /* context is too long */ - - c = csf3->Coverage; - - for ( i = 1, j = buffer->in_pos + 1; i < csf3->GlyphCount; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + csf3->GlyphCount - i == (HB_Int)buffer->in_length ) - return HB_Err_Not_Covered; - j++; - } - - error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index ); - if ( error ) - return error; - } - - return Do_ContextSubst( gsub, csf3->GlyphCount, - csf3->SubstCount, csf3->SubstLookupRecord, - buffer, - nesting_level ); -} - - -static HB_Error Lookup_ContextSubst( HB_GSUBHeader* gsub, - HB_GSUB_SubTable* st, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_ContextSubst* cs = &st->context; - - switch ( cs->SubstFormat ) - { - case 1: return Lookup_ContextSubst1( gsub, &cs->csf.csf1, buffer, flags, context_length, nesting_level ); - case 2: return Lookup_ContextSubst2( gsub, &cs->csf.csf2, buffer, flags, context_length, nesting_level ); - case 3: return Lookup_ContextSubst3( gsub, &cs->csf.csf3, buffer, flags, context_length, nesting_level ); - default: return ERR(HB_Err_Invalid_SubTable_Format); - } - - return HB_Err_Ok; /* never reached */ -} - - -/* LookupType 6 */ - -/* ChainSubRule */ - -static HB_Error Load_ChainSubRule( HB_ChainSubRule* csr, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - HB_UShort* b; - HB_UShort* i; - HB_UShort* l; - - HB_SubstLookupRecord* slr; - - - if ( ACCESS_Frame( 2L ) ) - return error; - - csr->BacktrackGlyphCount = GET_UShort(); - - FORGET_Frame(); - - csr->Backtrack = NULL; - - count = csr->BacktrackGlyphCount; - - if ( ALLOC_ARRAY( csr->Backtrack, count, HB_UShort ) ) - return error; - - b = csr->Backtrack; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail4; - - for ( n = 0; n < count; n++ ) - b[n] = GET_UShort(); - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail4; - - csr->InputGlyphCount = GET_UShort(); - - FORGET_Frame(); - - csr->Input = NULL; - - count = csr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */ - - if ( ALLOC_ARRAY( csr->Input, count, HB_UShort ) ) - goto Fail4; - - i = csr->Input; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail3; - - for ( n = 0; n < count; n++ ) - i[n] = GET_UShort(); - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - csr->LookaheadGlyphCount = GET_UShort(); - - FORGET_Frame(); - - csr->Lookahead = NULL; - - count = csr->LookaheadGlyphCount; - - if ( ALLOC_ARRAY( csr->Lookahead, count, HB_UShort ) ) - goto Fail3; - - l = csr->Lookahead; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail2; - - for ( n = 0; n < count; n++ ) - l[n] = GET_UShort(); - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - csr->SubstCount = GET_UShort(); - - FORGET_Frame(); - - csr->SubstLookupRecord = NULL; - - count = csr->SubstCount; - - if ( ALLOC_ARRAY( csr->SubstLookupRecord, count, HB_SubstLookupRecord ) ) - goto Fail2; - - slr = csr->SubstLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - slr[n].SequenceIndex = GET_UShort(); - slr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return HB_Err_Ok; - -Fail1: - FREE( slr ); - -Fail2: - FREE( l ); - -Fail3: - FREE( i ); - -Fail4: - FREE( b ); - return error; -} - - -static void Free_ChainSubRule( HB_ChainSubRule* csr ) -{ - FREE( csr->SubstLookupRecord ); - FREE( csr->Lookahead ); - FREE( csr->Input ); - FREE( csr->Backtrack ); -} - - -/* ChainSubRuleSet */ - -static HB_Error Load_ChainSubRuleSet( HB_ChainSubRuleSet* csrs, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n = 0, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_ChainSubRule* csr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = csrs->ChainSubRuleCount = GET_UShort(); - - FORGET_Frame(); - - csrs->ChainSubRule = NULL; - - if ( ALLOC_ARRAY( csrs->ChainSubRule, count, HB_ChainSubRule ) ) - return error; - - csr = csrs->ChainSubRule; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_ChainSubRule( &csr[n], stream ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail: - for ( m = 0; m < n; m++ ) - Free_ChainSubRule( &csr[m] ); - - FREE( csr ); - return error; -} - - -static void Free_ChainSubRuleSet( HB_ChainSubRuleSet* csrs ) -{ - HB_UShort n, count; - - HB_ChainSubRule* csr; - - - if ( csrs->ChainSubRule ) - { - count = csrs->ChainSubRuleCount; - csr = csrs->ChainSubRule; - - for ( n = 0; n < count; n++ ) - Free_ChainSubRule( &csr[n] ); - - FREE( csr ); - } -} - - -/* ChainContextSubstFormat1 */ - -static HB_Error Load_ChainContextSubst1( - HB_ChainContextSubstFormat1* ccsf1, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n = 0, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_ChainSubRuleSet* csrs; - - - base_offset = FILE_Pos() - 2L; - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &ccsf1->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = ccsf1->ChainSubRuleSetCount = GET_UShort(); - - FORGET_Frame(); - - ccsf1->ChainSubRuleSet = NULL; - - if ( ALLOC_ARRAY( ccsf1->ChainSubRuleSet, count, HB_ChainSubRuleSet ) ) - goto Fail2; - - csrs = ccsf1->ChainSubRuleSet; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_ChainSubRuleSet( &csrs[n], stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - Free_ChainSubRuleSet( &csrs[m] ); - - FREE( csrs ); - -Fail2: - _HB_OPEN_Free_Coverage( &ccsf1->Coverage ); - return error; -} - - -static void Free_ChainContextSubst1( HB_ChainContextSubstFormat1* ccsf1 ) -{ - HB_UShort n, count; - - HB_ChainSubRuleSet* csrs; - - - if ( ccsf1->ChainSubRuleSet ) - { - count = ccsf1->ChainSubRuleSetCount; - csrs = ccsf1->ChainSubRuleSet; - - for ( n = 0; n < count; n++ ) - Free_ChainSubRuleSet( &csrs[n] ); - - FREE( csrs ); - } - - _HB_OPEN_Free_Coverage( &ccsf1->Coverage ); -} - - -/* ChainSubClassRule */ - -static HB_Error Load_ChainSubClassRule( - HB_ChainContextSubstFormat2* ccsf2, - HB_ChainSubClassRule* cscr, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - - HB_UShort* b; - HB_UShort* i; - HB_UShort* l; - HB_SubstLookupRecord* slr; - - - if ( ACCESS_Frame( 2L ) ) - return error; - - cscr->BacktrackGlyphCount = GET_UShort(); - - FORGET_Frame(); - - if ( cscr->BacktrackGlyphCount > ccsf2->MaxBacktrackLength ) - ccsf2->MaxBacktrackLength = cscr->BacktrackGlyphCount; - - cscr->Backtrack = NULL; - - count = cscr->BacktrackGlyphCount; - - if ( ALLOC_ARRAY( cscr->Backtrack, count, HB_UShort ) ) - return error; - - b = cscr->Backtrack; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail4; - - for ( n = 0; n < count; n++ ) - b[n] = GET_UShort(); - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail4; - - cscr->InputGlyphCount = GET_UShort(); - - FORGET_Frame(); - - if ( cscr->InputGlyphCount > ccsf2->MaxInputLength ) - ccsf2->MaxInputLength = cscr->InputGlyphCount; - - cscr->Input = NULL; - - count = cscr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */ - - if ( ALLOC_ARRAY( cscr->Input, count, HB_UShort ) ) - goto Fail4; - - i = cscr->Input; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail3; - - for ( n = 0; n < count; n++ ) - i[n] = GET_UShort(); - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - cscr->LookaheadGlyphCount = GET_UShort(); - - FORGET_Frame(); - - if ( cscr->LookaheadGlyphCount > ccsf2->MaxLookaheadLength ) - ccsf2->MaxLookaheadLength = cscr->LookaheadGlyphCount; - - cscr->Lookahead = NULL; - - count = cscr->LookaheadGlyphCount; - - if ( ALLOC_ARRAY( cscr->Lookahead, count, HB_UShort ) ) - goto Fail3; - - l = cscr->Lookahead; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail2; - - for ( n = 0; n < count; n++ ) - l[n] = GET_UShort(); - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - cscr->SubstCount = GET_UShort(); - - FORGET_Frame(); - - cscr->SubstLookupRecord = NULL; - - count = cscr->SubstCount; - - if ( ALLOC_ARRAY( cscr->SubstLookupRecord, count, - HB_SubstLookupRecord ) ) - goto Fail2; - - slr = cscr->SubstLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - slr[n].SequenceIndex = GET_UShort(); - slr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return HB_Err_Ok; - -Fail1: - FREE( slr ); - -Fail2: - FREE( l ); - -Fail3: - FREE( i ); - -Fail4: - FREE( b ); - return error; -} - - -static void Free_ChainSubClassRule( HB_ChainSubClassRule* cscr ) -{ - FREE( cscr->SubstLookupRecord ); - FREE( cscr->Lookahead ); - FREE( cscr->Input ); - FREE( cscr->Backtrack ); -} - - -/* SubClassSet */ - -static HB_Error Load_ChainSubClassSet( - HB_ChainContextSubstFormat2* ccsf2, - HB_ChainSubClassSet* cscs, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n = 0, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_ChainSubClassRule* cscr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = cscs->ChainSubClassRuleCount = GET_UShort(); - - FORGET_Frame(); - - cscs->ChainSubClassRule = NULL; - - if ( ALLOC_ARRAY( cscs->ChainSubClassRule, count, - HB_ChainSubClassRule ) ) - return error; - - cscr = cscs->ChainSubClassRule; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_ChainSubClassRule( ccsf2, &cscr[n], - stream ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail: - for ( m = 0; m < n; m++ ) - Free_ChainSubClassRule( &cscr[m] ); - - FREE( cscr ); - return error; -} - - -static void Free_ChainSubClassSet( HB_ChainSubClassSet* cscs ) -{ - HB_UShort n, count; - - HB_ChainSubClassRule* cscr; - - - if ( cscs->ChainSubClassRule ) - { - count = cscs->ChainSubClassRuleCount; - cscr = cscs->ChainSubClassRule; - - for ( n = 0; n < count; n++ ) - Free_ChainSubClassRule( &cscr[n] ); - - FREE( cscr ); - } -} - - -/* ChainContextSubstFormat2 */ - -static HB_Error Load_ChainContextSubst2( - HB_ChainContextSubstFormat2* ccsf2, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n = 0, m, count; - HB_UInt cur_offset, new_offset, base_offset; - HB_UInt backtrack_offset, input_offset, lookahead_offset; - - HB_ChainSubClassSet* cscs; - - - base_offset = FILE_Pos() - 2; - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &ccsf2->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - if ( ACCESS_Frame( 8L ) ) - goto Fail5; - - backtrack_offset = GET_UShort(); - input_offset = GET_UShort(); - lookahead_offset = GET_UShort(); - - /* `ChainSubClassSetCount' is the upper limit for input class values, - thus we read it now to make an additional safety check. No limit - is known or needed for the other two class definitions */ - - count = ccsf2->ChainSubClassSetCount = GET_UShort(); - - FORGET_Frame(); - - if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->BacktrackClassDef, 65535, - backtrack_offset, base_offset, - stream ) ) != HB_Err_Ok ) - goto Fail5; - - if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->InputClassDef, count, - input_offset, base_offset, - stream ) ) != HB_Err_Ok ) - goto Fail4; - if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->LookaheadClassDef, 65535, - lookahead_offset, base_offset, - stream ) ) != HB_Err_Ok ) - goto Fail3; - - ccsf2->ChainSubClassSet = NULL; - ccsf2->MaxBacktrackLength = 0; - ccsf2->MaxInputLength = 0; - ccsf2->MaxLookaheadLength = 0; - - if ( ALLOC_ARRAY( ccsf2->ChainSubClassSet, count, HB_ChainSubClassSet ) ) - goto Fail2; - - cscs = ccsf2->ChainSubClassSet; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - if ( new_offset != base_offset ) /* not a NULL offset */ - { - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_ChainSubClassSet( ccsf2, &cscs[n], - stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - else - { - /* we create a ChainSubClassSet table with no entries */ - - ccsf2->ChainSubClassSet[n].ChainSubClassRuleCount = 0; - ccsf2->ChainSubClassSet[n].ChainSubClassRule = NULL; - } - } - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - Free_ChainSubClassSet( &cscs[m] ); - - FREE( cscs ); - -Fail2: - _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef ); - -Fail3: - _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef ); - -Fail4: - _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef ); - -Fail5: - _HB_OPEN_Free_Coverage( &ccsf2->Coverage ); - return error; -} - - -static void Free_ChainContextSubst2( HB_ChainContextSubstFormat2* ccsf2 ) -{ - HB_UShort n, count; - - HB_ChainSubClassSet* cscs; - - - if ( ccsf2->ChainSubClassSet ) - { - count = ccsf2->ChainSubClassSetCount; - cscs = ccsf2->ChainSubClassSet; - - for ( n = 0; n < count; n++ ) - Free_ChainSubClassSet( &cscs[n] ); - - FREE( cscs ); - } - - _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef ); - _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef ); - _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef ); - - _HB_OPEN_Free_Coverage( &ccsf2->Coverage ); -} - - -/* ChainContextSubstFormat3 */ - -static HB_Error Load_ChainContextSubst3( - HB_ChainContextSubstFormat3* ccsf3, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, nb = 0, ni =0, nl = 0, m, count; - HB_UShort backtrack_count, input_count, lookahead_count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_Coverage* b; - HB_Coverage* i; - HB_Coverage* l; - HB_SubstLookupRecord* slr; - - - base_offset = FILE_Pos() - 2L; - - if ( ACCESS_Frame( 2L ) ) - return error; - - ccsf3->BacktrackGlyphCount = GET_UShort(); - - FORGET_Frame(); - - ccsf3->BacktrackCoverage = NULL; - - backtrack_count = ccsf3->BacktrackGlyphCount; - - if ( ALLOC_ARRAY( ccsf3->BacktrackCoverage, backtrack_count, - HB_Coverage ) ) - return error; - - b = ccsf3->BacktrackCoverage; - - for ( nb = 0; nb < backtrack_count; nb++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail4; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok ) - goto Fail4; - (void)FILE_Seek( cur_offset ); - } - - if ( ACCESS_Frame( 2L ) ) - goto Fail4; - - ccsf3->InputGlyphCount = GET_UShort(); - - FORGET_Frame(); - - ccsf3->InputCoverage = NULL; - - input_count = ccsf3->InputGlyphCount; - - if ( ALLOC_ARRAY( ccsf3->InputCoverage, input_count, HB_Coverage ) ) - goto Fail4; - - i = ccsf3->InputCoverage; - - for ( ni = 0; ni < input_count; ni++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != HB_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - } - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - ccsf3->LookaheadGlyphCount = GET_UShort(); - - FORGET_Frame(); - - ccsf3->LookaheadCoverage = NULL; - - lookahead_count = ccsf3->LookaheadGlyphCount; - - if ( ALLOC_ARRAY( ccsf3->LookaheadCoverage, lookahead_count, - HB_Coverage ) ) - goto Fail3; - - l = ccsf3->LookaheadCoverage; - - for ( nl = 0; nl < lookahead_count; nl++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - } - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - ccsf3->SubstCount = GET_UShort(); - - FORGET_Frame(); - - ccsf3->SubstLookupRecord = NULL; - - count = ccsf3->SubstCount; - - if ( ALLOC_ARRAY( ccsf3->SubstLookupRecord, count, - HB_SubstLookupRecord ) ) - goto Fail2; - - slr = ccsf3->SubstLookupRecord; - - if ( ACCESS_Frame( count * 4L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - { - slr[n].SequenceIndex = GET_UShort(); - slr[n].LookupListIndex = GET_UShort(); - } - - FORGET_Frame(); - - return HB_Err_Ok; - -Fail1: - FREE( slr ); - -Fail2: - for ( m = 0; m < nl; m++ ) - _HB_OPEN_Free_Coverage( &l[m] ); - - FREE( l ); - -Fail3: - for ( m = 0; m < ni; m++ ) - _HB_OPEN_Free_Coverage( &i[m] ); - - FREE( i ); - -Fail4: - for ( m = 0; m < nb; m++ ) - _HB_OPEN_Free_Coverage( &b[m] ); - - FREE( b ); - return error; -} - - -static void Free_ChainContextSubst3( HB_ChainContextSubstFormat3* ccsf3 ) -{ - HB_UShort n, count; - - HB_Coverage* c; - - - FREE( ccsf3->SubstLookupRecord ); - - if ( ccsf3->LookaheadCoverage ) - { - count = ccsf3->LookaheadGlyphCount; - c = ccsf3->LookaheadCoverage; - - for ( n = 0; n < count; n++ ) - _HB_OPEN_Free_Coverage( &c[n] ); - - FREE( c ); - } - - if ( ccsf3->InputCoverage ) - { - count = ccsf3->InputGlyphCount; - c = ccsf3->InputCoverage; - - for ( n = 0; n < count; n++ ) - _HB_OPEN_Free_Coverage( &c[n] ); - - FREE( c ); - } - - if ( ccsf3->BacktrackCoverage ) - { - count = ccsf3->BacktrackGlyphCount; - c = ccsf3->BacktrackCoverage; - - for ( n = 0; n < count; n++ ) - _HB_OPEN_Free_Coverage( &c[n] ); - - FREE( c ); - } -} - - -/* ChainContextSubst */ - -static HB_Error Load_ChainContextSubst( HB_GSUB_SubTable* st, - HB_Stream stream ) -{ - HB_Error error; - HB_ChainContextSubst* ccs = &st->chain; - - if ( ACCESS_Frame( 2L ) ) - return error; - - ccs->SubstFormat = GET_UShort(); - - FORGET_Frame(); - - switch ( ccs->SubstFormat ) { - case 1: return Load_ChainContextSubst1( &ccs->ccsf.ccsf1, stream ); - case 2: return Load_ChainContextSubst2( &ccs->ccsf.ccsf2, stream ); - case 3: return Load_ChainContextSubst3( &ccs->ccsf.ccsf3, stream ); - default: return ERR(HB_Err_Invalid_SubTable_Format); - } - - return HB_Err_Ok; /* never reached */ -} - - -static void Free_ChainContextSubst( HB_GSUB_SubTable* st ) -{ - HB_ChainContextSubst* ccs = &st->chain; - - switch ( ccs->SubstFormat ) { - case 1: Free_ChainContextSubst1( &ccs->ccsf.ccsf1 ); break; - case 2: Free_ChainContextSubst2( &ccs->ccsf.ccsf2 ); break; - case 3: Free_ChainContextSubst3( &ccs->ccsf.ccsf3 ); break; - default: break; - } -} - - -static HB_Error Lookup_ChainContextSubst1( HB_GSUBHeader* gsub, - HB_ChainContextSubstFormat1* ccsf1, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort index, property; - HB_UShort i, j, k, num_csr; - HB_UShort bgc, igc, lgc; - HB_Error error; - - HB_ChainSubRule* csr; - HB_ChainSubRule curr_csr; - hb_ot_layout_t* layout; - - - layout = gsub->layout; - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - error = _HB_OPEN_Coverage_Index( &ccsf1->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - csr = ccsf1->ChainSubRuleSet[index].ChainSubRule; - num_csr = ccsf1->ChainSubRuleSet[index].ChainSubRuleCount; - - for ( k = 0; k < num_csr; k++ ) - { - curr_csr = csr[k]; - bgc = curr_csr.BacktrackGlyphCount; - igc = curr_csr.InputGlyphCount; - lgc = curr_csr.LookaheadGlyphCount; - - if ( context_length != 0xFFFF && context_length < igc ) - goto next_chainsubrule; - - /* check whether context is too long; it is a first guess only */ - - if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length ) - goto next_chainsubrule; - - if ( bgc ) - { - /* since we don't know in advance the number of glyphs to inspect, - we search backwards for matches in the backtrack glyph array */ - - for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- ) - { - while ( CHECK_Property( layout, OUT_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + 1 == bgc - i ) - goto next_chainsubrule; - j--; - } - - /* In OpenType 1.3, it is undefined whether the offsets of - backtrack glyphs is in logical order or not. Version 1.4 - will clarify this: - - Logical order - a b c d e f g h i j - i - Input offsets - 0 1 - Backtrack offsets - 3 2 1 0 - Lookahead offsets - 0 1 2 3 */ - - if ( OUT_GLYPH( j ) != curr_csr.Backtrack[i] ) - goto next_chainsubrule; - } - } - - /* Start at 1 because [0] is implied */ - - for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + igc - i + lgc == (HB_Int)buffer->in_length ) - goto next_chainsubrule; - j++; - } - - if ( IN_GLYPH( j ) != curr_csr.Input[i - 1] ) - goto next_chainsubrule; - } - - /* we are starting to check for lookahead glyphs right after the - last context glyph */ - - for ( i = 0; i < lgc; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + lgc - i == (HB_Int)buffer->in_length ) - goto next_chainsubrule; - j++; - } - - if ( IN_GLYPH( j ) != curr_csr.Lookahead[i] ) - goto next_chainsubrule; - } - - return Do_ContextSubst( gsub, igc, - curr_csr.SubstCount, - curr_csr.SubstLookupRecord, - buffer, - nesting_level ); - - next_chainsubrule: - ; - } - - return HB_Err_Not_Covered; -} - - -static HB_Error Lookup_ChainContextSubst2( HB_GSUBHeader* gsub, - HB_ChainContextSubstFormat2* ccsf2, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort index, property; - HB_Error error; - HB_UShort i, j, k; - HB_UShort bgc, igc, lgc; - HB_UShort known_backtrack_classes, - known_input_classes, - known_lookahead_classes; - - HB_UShort* backtrack_classes; - HB_UShort* input_classes; - HB_UShort* lookahead_classes; - - HB_UShort* bc; - HB_UShort* ic; - HB_UShort* lc; - - HB_ChainSubClassSet* cscs; - HB_ChainSubClassRule ccsr; - hb_ot_layout_t* layout; - - - layout = gsub->layout; - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - /* Note: The coverage table in format 2 doesn't give an index into - anything. It just lets us know whether or not we need to - do any lookup at all. */ - - error = _HB_OPEN_Coverage_Index( &ccsf2->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - if ( ALLOC_ARRAY( backtrack_classes, ccsf2->MaxBacktrackLength, HB_UShort ) ) - return error; - known_backtrack_classes = 0; - - if (ccsf2->MaxInputLength < 1) - return HB_Err_Not_Covered; - - if ( ALLOC_ARRAY( input_classes, ccsf2->MaxInputLength, HB_UShort ) ) - goto End3; - known_input_classes = 1; - - if ( ALLOC_ARRAY( lookahead_classes, ccsf2->MaxLookaheadLength, HB_UShort ) ) - goto End2; - known_lookahead_classes = 0; - - error = _HB_OPEN_Get_Class( &ccsf2->InputClassDef, IN_CURGLYPH(), - &input_classes[0], NULL ); - if ( error && error != HB_Err_Not_Covered ) - goto End1; - - cscs = &ccsf2->ChainSubClassSet[input_classes[0]]; - if ( !cscs ) - { - error = ERR(HB_Err_Invalid_SubTable); - goto End1; - } - - for ( k = 0; k < cscs->ChainSubClassRuleCount; k++ ) - { - ccsr = cscs->ChainSubClassRule[k]; - bgc = ccsr.BacktrackGlyphCount; - igc = ccsr.InputGlyphCount; - lgc = ccsr.LookaheadGlyphCount; - - if ( context_length != 0xFFFF && context_length < igc ) - goto next_chainsubclassrule; - - /* check whether context is too long; it is a first guess only */ - - if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length ) - goto next_chainsubclassrule; - - if ( bgc ) - { - /* Since we don't know in advance the number of glyphs to inspect, - we search backwards for matches in the backtrack glyph array. - Note that `known_backtrack_classes' starts at index 0. */ - - bc = ccsr.Backtrack; - - for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- ) - { - while ( CHECK_Property( layout, OUT_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - goto End1; - - if ( j + 1 == bgc - i ) - goto next_chainsubclassrule; - j--; - } - - if ( i >= known_backtrack_classes ) - { - /* Keeps us from having to do this for each rule */ - - error = _HB_OPEN_Get_Class( &ccsf2->BacktrackClassDef, OUT_GLYPH( j ), - &backtrack_classes[i], NULL ); - if ( error && error != HB_Err_Not_Covered ) - goto End1; - known_backtrack_classes = i; - } - - if ( bc[i] != backtrack_classes[i] ) - goto next_chainsubclassrule; - } - } - - ic = ccsr.Input; - - /* Start at 1 because [0] is implied */ - - for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - goto End1; - - if ( j + igc - i + lgc == (HB_Int)buffer->in_length ) - goto next_chainsubclassrule; - j++; - } - - if ( i >= known_input_classes ) - { - error = _HB_OPEN_Get_Class( &ccsf2->InputClassDef, IN_GLYPH( j ), - &input_classes[i], NULL ); - if ( error && error != HB_Err_Not_Covered ) - goto End1; - known_input_classes = i; - } - - if ( ic[i - 1] != input_classes[i] ) - goto next_chainsubclassrule; - } - - /* we are starting to check for lookahead glyphs right after the - last context glyph */ - - lc = ccsr.Lookahead; - - for ( i = 0; i < lgc; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - goto End1; - - if ( j + lgc - i == (HB_Int)buffer->in_length ) - goto next_chainsubclassrule; - j++; - } - - if ( i >= known_lookahead_classes ) - { - error = _HB_OPEN_Get_Class( &ccsf2->LookaheadClassDef, IN_GLYPH( j ), - &lookahead_classes[i], NULL ); - if ( error && error != HB_Err_Not_Covered ) - goto End1; - known_lookahead_classes = i; - } - - if ( lc[i] != lookahead_classes[i] ) - goto next_chainsubclassrule; - } - - error = Do_ContextSubst( gsub, igc, - ccsr.SubstCount, - ccsr.SubstLookupRecord, - buffer, - nesting_level ); - goto End1; - - next_chainsubclassrule: - ; - } - - error = HB_Err_Not_Covered; - -End1: - FREE( lookahead_classes ); - -End2: - FREE( input_classes ); - -End3: - FREE( backtrack_classes ); - return error; -} - - -static HB_Error Lookup_ChainContextSubst3( HB_GSUBHeader* gsub, - HB_ChainContextSubstFormat3* ccsf3, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort index, i, j, property; - HB_UShort bgc, igc, lgc; - HB_Error error; - - HB_Coverage* bc; - HB_Coverage* ic; - HB_Coverage* lc; - hb_ot_layout_t* layout; - - - layout = gsub->layout; - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - bgc = ccsf3->BacktrackGlyphCount; - igc = ccsf3->InputGlyphCount; - lgc = ccsf3->LookaheadGlyphCount; - - if ( context_length != 0xFFFF && context_length < igc ) - return HB_Err_Not_Covered; - - /* check whether context is too long; it is a first guess only */ - - if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length ) - return HB_Err_Not_Covered; - - if ( bgc ) - { - /* Since we don't know in advance the number of glyphs to inspect, - we search backwards for matches in the backtrack glyph array */ - - bc = ccsf3->BacktrackCoverage; - - for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- ) - { - while ( CHECK_Property( layout, OUT_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + 1 == bgc - i ) - return HB_Err_Not_Covered; - j--; - } - - error = _HB_OPEN_Coverage_Index( &bc[i], OUT_GLYPH( j ), &index ); - if ( error ) - return error; - } - } - - ic = ccsf3->InputCoverage; - - for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ ) - { - /* We already called CHECK_Property for IN_GLYPH( buffer->in_pos ) */ - while ( j > buffer->in_pos && CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + igc - i + lgc == (HB_Int)buffer->in_length ) - return HB_Err_Not_Covered; - j++; - } - - error = _HB_OPEN_Coverage_Index( &ic[i], IN_GLYPH( j ), &index ); - if ( error ) - return error; - } - - /* we are starting for lookahead glyphs right after the last context - glyph */ - - lc = ccsf3->LookaheadCoverage; - - for ( i = 0; i < lgc; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + lgc - i == (HB_Int)buffer->in_length ) - return HB_Err_Not_Covered; - j++; - } - - error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index ); - if ( error ) - return error; - } - - return Do_ContextSubst( gsub, igc, - ccsf3->SubstCount, - ccsf3->SubstLookupRecord, - buffer, - nesting_level ); -} - - -static HB_Error Lookup_ChainContextSubst( HB_GSUBHeader* gsub, - HB_GSUB_SubTable* st, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_ChainContextSubst* ccs = &st->chain; - - switch ( ccs->SubstFormat ) { - case 1: return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, buffer, flags, context_length, nesting_level ); - case 2: return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, buffer, flags, context_length, nesting_level ); - case 3: return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, buffer, flags, context_length, nesting_level ); - default: return ERR(HB_Err_Invalid_SubTable_Format); - } -} - - -static HB_Error Load_ReverseChainContextSubst( HB_GSUB_SubTable* st, - HB_Stream stream ) -{ - HB_Error error; - HB_ReverseChainContextSubst* rccs = &st->reverse; - - HB_UShort m, count; - - HB_UShort nb = 0, nl = 0, n; - HB_UShort backtrack_count, lookahead_count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_Coverage* b; - HB_Coverage* l; - HB_UShort* sub; - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - rccs->SubstFormat = GET_UShort(); - - if ( rccs->SubstFormat != 1 ) - return ERR(HB_Err_Invalid_SubTable_Format); - - FORGET_Frame(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &rccs->Coverage, stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - - - if ( ACCESS_Frame( 2L ) ) - goto Fail4; - - rccs->BacktrackGlyphCount = GET_UShort(); - - FORGET_Frame(); - - rccs->BacktrackCoverage = NULL; - - backtrack_count = rccs->BacktrackGlyphCount; - - if ( ALLOC_ARRAY( rccs->BacktrackCoverage, backtrack_count, - HB_Coverage ) ) - goto Fail4; - - b = rccs->BacktrackCoverage; - - for ( nb = 0; nb < backtrack_count; nb++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - } - - - if ( ACCESS_Frame( 2L ) ) - goto Fail3; - - rccs->LookaheadGlyphCount = GET_UShort(); - - FORGET_Frame(); - - rccs->LookaheadCoverage = NULL; - - lookahead_count = rccs->LookaheadGlyphCount; - - if ( ALLOC_ARRAY( rccs->LookaheadCoverage, lookahead_count, - HB_Coverage ) ) - goto Fail3; - - l = rccs->LookaheadCoverage; - - for ( nl = 0; nl < lookahead_count; nl++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - } - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - rccs->GlyphCount = GET_UShort(); - - FORGET_Frame(); - - rccs->Substitute = NULL; - - count = rccs->GlyphCount; - - if ( ALLOC_ARRAY( rccs->Substitute, count, - HB_UShort ) ) - goto Fail2; - - sub = rccs->Substitute; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail1; - - for ( n = 0; n < count; n++ ) - sub[n] = GET_UShort(); - - FORGET_Frame(); - - return HB_Err_Ok; - -Fail1: - FREE( sub ); - -Fail2: - for ( m = 0; m < nl; m++ ) - _HB_OPEN_Free_Coverage( &l[m] ); - - FREE( l ); - -Fail3: - for ( m = 0; m < nb; m++ ) - _HB_OPEN_Free_Coverage( &b[m] ); - - FREE( b ); - -Fail4: - _HB_OPEN_Free_Coverage( &rccs->Coverage ); - return error; -} - - -static void Free_ReverseChainContextSubst( HB_GSUB_SubTable* st ) -{ - HB_UShort n, count; - HB_ReverseChainContextSubst* rccs = &st->reverse; - - HB_Coverage* c; - - _HB_OPEN_Free_Coverage( &rccs->Coverage ); - - if ( rccs->LookaheadCoverage ) - { - count = rccs->LookaheadGlyphCount; - c = rccs->LookaheadCoverage; - - for ( n = 0; n < count; n++ ) - _HB_OPEN_Free_Coverage( &c[n] ); - - FREE( c ); - } - - if ( rccs->BacktrackCoverage ) - { - count = rccs->BacktrackGlyphCount; - c = rccs->BacktrackCoverage; - - for ( n = 0; n < count; n++ ) - _HB_OPEN_Free_Coverage( &c[n] ); - - FREE( c ); - } - - FREE ( rccs->Substitute ); -} - - -static HB_Error Lookup_ReverseChainContextSubst( HB_GSUBHeader* gsub, - HB_GSUB_SubTable* st, - HB_Buffer buffer, - HB_UShort flags, - HB_UShort context_length, - int nesting_level ) -{ - HB_UShort index, input_index, i, j, property; - HB_UShort bgc, lgc; - HB_Error error; - - HB_ReverseChainContextSubst* rccs = &st->reverse; - HB_Coverage* bc; - HB_Coverage* lc; - hb_ot_layout_t* layout; - - if ( nesting_level != 1 || context_length != 0xFFFF ) - return HB_Err_Not_Covered; - - layout = gsub->layout; - - if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) ) - return error; - - bgc = rccs->BacktrackGlyphCount; - lgc = rccs->LookaheadGlyphCount; - - /* check whether context is too long; it is a first guess only */ - - if ( bgc > buffer->in_pos || buffer->in_pos + 1 + lgc > buffer->in_length ) - return HB_Err_Not_Covered; - - if ( bgc ) - { - /* Since we don't know in advance the number of glyphs to inspect, - we search backwards for matches in the backtrack glyph array */ - - bc = rccs->BacktrackCoverage; - - for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + 1 == bgc - i ) - return HB_Err_Not_Covered; - j--; - } - - error = _HB_OPEN_Coverage_Index( &bc[i], IN_GLYPH( j ), &index ); - if ( error ) - return error; - } - } - - j = buffer->in_pos; - - error = _HB_OPEN_Coverage_Index( &rccs->Coverage, IN_GLYPH( j ), &input_index ); - if ( error ) - return error; - - lc = rccs->LookaheadCoverage; - - for ( i = 0, j = buffer->in_pos + 1; i < lgc; i++, j++ ) - { - while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) ) - { - if ( error && error != HB_Err_Not_Covered ) - return error; - - if ( j + lgc - i == (HB_Int)buffer->in_length ) - return HB_Err_Not_Covered; - j++; - } - - error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index ); - if ( error ) - return error; - } - - IN_CURGLYPH() = rccs->Substitute[input_index]; - buffer->in_pos--; /* Reverse! */ - - return error; -} - - - -/*********** - * GSUB API - ***********/ - - - -HB_Error HB_GSUB_Select_Script( HB_GSUBHeader* gsub, - HB_UInt script_tag, - HB_UShort* script_index ) -{ - HB_UShort n; - - HB_ScriptList* sl; - HB_ScriptRecord* sr; - - - if ( !gsub || !script_index ) - return ERR(HB_Err_Invalid_Argument); - - sl = &gsub->ScriptList; - sr = sl->ScriptRecord; - - for ( n = 0; n < sl->ScriptCount; n++ ) - if ( script_tag == sr[n].ScriptTag ) - { - *script_index = n; - - return HB_Err_Ok; - } - - return HB_Err_Not_Covered; -} - - - -HB_Error HB_GSUB_Select_Language( HB_GSUBHeader* gsub, - HB_UInt language_tag, - HB_UShort script_index, - HB_UShort* language_index, - HB_UShort* req_feature_index ) -{ - HB_UShort n; - - HB_ScriptList* sl; - HB_ScriptRecord* sr; - HB_ScriptTable* s; - HB_LangSysRecord* lsr; - - - if ( !gsub || !language_index || !req_feature_index ) - return ERR(HB_Err_Invalid_Argument); - - sl = &gsub->ScriptList; - sr = sl->ScriptRecord; - - if ( script_index >= sl->ScriptCount ) - return ERR(HB_Err_Invalid_Argument); - - s = &sr[script_index].Script; - lsr = s->LangSysRecord; - - for ( n = 0; n < s->LangSysCount; n++ ) - if ( language_tag == lsr[n].LangSysTag ) - { - *language_index = n; - *req_feature_index = lsr[n].LangSys.ReqFeatureIndex; - - return HB_Err_Ok; - } - - return HB_Err_Not_Covered; -} - - -/* selecting 0xFFFF for language_index asks for the values of the - default language (DefaultLangSys) */ - - -HB_Error HB_GSUB_Select_Feature( HB_GSUBHeader* gsub, - HB_UInt feature_tag, - HB_UShort script_index, - HB_UShort language_index, - HB_UShort* feature_index ) -{ - HB_UShort n; - - HB_ScriptList* sl; - HB_ScriptRecord* sr; - HB_ScriptTable* s; - HB_LangSysRecord* lsr; - HB_LangSys* ls; - HB_UShort* fi; - - HB_FeatureList* fl; - HB_FeatureRecord* fr; - - - if ( !gsub || !feature_index ) - return ERR(HB_Err_Invalid_Argument); - - sl = &gsub->ScriptList; - sr = sl->ScriptRecord; - - fl = &gsub->FeatureList; - fr = fl->FeatureRecord; - - if ( script_index >= sl->ScriptCount ) - return ERR(HB_Err_Invalid_Argument); - - s = &sr[script_index].Script; - lsr = s->LangSysRecord; - - if ( language_index == 0xFFFF ) - ls = &s->DefaultLangSys; - else - { - if ( language_index >= s->LangSysCount ) - return ERR(HB_Err_Invalid_Argument); - - ls = &lsr[language_index].LangSys; - } - - fi = ls->FeatureIndex; - - for ( n = 0; n < ls->FeatureCount; n++ ) - { - if ( fi[n] >= fl->FeatureCount ) - return ERR(HB_Err_Invalid_SubTable_Format); - - if ( feature_tag == fr[fi[n]].FeatureTag ) - { - *feature_index = fi[n]; - - return HB_Err_Ok; - } - } - - return HB_Err_Not_Covered; -} - - -/* The next three functions return a null-terminated list */ - - -HB_Error HB_GSUB_Query_Scripts( HB_GSUBHeader* gsub, - HB_UInt** script_tag_list ) -{ - HB_UShort n; - HB_Error error; - HB_UInt* stl; - - HB_ScriptList* sl; - HB_ScriptRecord* sr; - - - if ( !gsub || !script_tag_list ) - return ERR(HB_Err_Invalid_Argument); - - sl = &gsub->ScriptList; - sr = sl->ScriptRecord; - - if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, HB_UInt ) ) - return error; - - for ( n = 0; n < sl->ScriptCount; n++ ) - stl[n] = sr[n].ScriptTag; - stl[n] = 0; - - *script_tag_list = stl; - - return HB_Err_Ok; -} - - - -HB_Error HB_GSUB_Query_Languages( HB_GSUBHeader* gsub, - HB_UShort script_index, - HB_UInt** language_tag_list ) -{ - HB_UShort n; - HB_Error error; - HB_UInt* ltl; - - HB_ScriptList* sl; - HB_ScriptRecord* sr; - HB_ScriptTable* s; - HB_LangSysRecord* lsr; - - - if ( !gsub || !language_tag_list ) - return ERR(HB_Err_Invalid_Argument); - - sl = &gsub->ScriptList; - sr = sl->ScriptRecord; - - if ( script_index >= sl->ScriptCount ) - return ERR(HB_Err_Invalid_Argument); - - s = &sr[script_index].Script; - lsr = s->LangSysRecord; - - if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, HB_UInt ) ) - return error; - - for ( n = 0; n < s->LangSysCount; n++ ) - ltl[n] = lsr[n].LangSysTag; - ltl[n] = 0; - - *language_tag_list = ltl; - - return HB_Err_Ok; -} - - -/* selecting 0xFFFF for language_index asks for the values of the - default language (DefaultLangSys) */ - - -HB_Error HB_GSUB_Query_Features( HB_GSUBHeader* gsub, - HB_UShort script_index, - HB_UShort language_index, - HB_UInt** feature_tag_list ) -{ - HB_UShort n; - HB_Error error; - HB_UInt* ftl; - - HB_ScriptList* sl; - HB_ScriptRecord* sr; - HB_ScriptTable* s; - HB_LangSysRecord* lsr; - HB_LangSys* ls; - HB_UShort* fi; - - HB_FeatureList* fl; - HB_FeatureRecord* fr; - - - if ( !gsub || !feature_tag_list ) - return ERR(HB_Err_Invalid_Argument); - - sl = &gsub->ScriptList; - sr = sl->ScriptRecord; - - fl = &gsub->FeatureList; - fr = fl->FeatureRecord; - - if ( script_index >= sl->ScriptCount ) - return ERR(HB_Err_Invalid_Argument); - - s = &sr[script_index].Script; - lsr = s->LangSysRecord; - - if ( language_index == 0xFFFF ) - ls = &s->DefaultLangSys; - else - { - if ( language_index >= s->LangSysCount ) - return ERR(HB_Err_Invalid_Argument); - - ls = &lsr[language_index].LangSys; - } - - fi = ls->FeatureIndex; - - if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, HB_UInt ) ) - return error; - - for ( n = 0; n < ls->FeatureCount; n++ ) - { - if ( fi[n] >= fl->FeatureCount ) - { - FREE( ftl ); - return ERR(HB_Err_Invalid_SubTable_Format); - } - ftl[n] = fr[fi[n]].FeatureTag; - } - ftl[n] = 0; - - *feature_tag_list = ftl; - - return HB_Err_Ok; -} - - -/* Do an individual subtable lookup. Returns HB_Err_Ok if substitution - has been done, or HB_Err_Not_Covered if not. */ -static HB_Error GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub, - HB_UShort lookup_index, - HB_Buffer buffer, - HB_UShort context_length, - int nesting_level ) -{ - HB_Error error = HB_Err_Not_Covered; - HB_UShort i, flags, lookup_count; - HB_Lookup* lo; - int lookup_type; - - nesting_level++; - - if ( nesting_level > HB_MAX_NESTING_LEVEL ) - return ERR(HB_Err_Not_Covered); /* ERR() call intended */ - - lookup_count = gsub->LookupList.LookupCount; - if (lookup_index >= lookup_count) - return error; - - lo = &gsub->LookupList.Lookup[lookup_index]; - flags = lo->LookupFlag; - lookup_type = lo->LookupType; - - for ( i = 0; i < lo->SubTableCount; i++ ) - { - HB_GSUB_SubTable *st = &lo->SubTable[i].st.gsub; - - switch (lookup_type) { - case HB_GSUB_LOOKUP_SINGLE: - error = Lookup_SingleSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break; - case HB_GSUB_LOOKUP_MULTIPLE: - error = Lookup_MultipleSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break; - case HB_GSUB_LOOKUP_ALTERNATE: - error = Lookup_AlternateSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break; - case HB_GSUB_LOOKUP_LIGATURE: - error = Lookup_LigatureSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break; - case HB_GSUB_LOOKUP_CONTEXT: - error = Lookup_ContextSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break; - case HB_GSUB_LOOKUP_CHAIN: - error = Lookup_ChainContextSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break; - /*case HB_GSUB_LOOKUP_EXTENSION: - error = Lookup_ExtensionSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;*/ - case HB_GSUB_LOOKUP_REVERSE_CHAIN: - error = Lookup_ReverseChainContextSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break; - default: - error = HB_Err_Not_Covered; - }; - - /* Check whether we have a successful substitution or an error other - than HB_Err_Not_Covered */ - if ( error != HB_Err_Not_Covered ) - return error; - } - - return HB_Err_Not_Covered; -} - - -HB_INTERNAL HB_Error -_HB_GSUB_Load_SubTable( HB_GSUB_SubTable* st, - HB_Stream stream, - HB_UShort lookup_type ) -{ - switch (lookup_type) { - case HB_GSUB_LOOKUP_SINGLE: return Load_SingleSubst ( st, stream ); - case HB_GSUB_LOOKUP_MULTIPLE: return Load_MultipleSubst ( st, stream ); - case HB_GSUB_LOOKUP_ALTERNATE: return Load_AlternateSubst ( st, stream ); - case HB_GSUB_LOOKUP_LIGATURE: return Load_LigatureSubst ( st, stream ); - case HB_GSUB_LOOKUP_CONTEXT: return Load_ContextSubst ( st, stream ); - case HB_GSUB_LOOKUP_CHAIN: return Load_ChainContextSubst ( st, stream ); - /*case HB_GSUB_LOOKUP_EXTENSION: return Load_ExtensionSubst ( st, stream );*/ - case HB_GSUB_LOOKUP_REVERSE_CHAIN: return Load_ReverseChainContextSubst ( st, stream ); - default: return ERR(HB_Err_Invalid_SubTable_Format); - }; -} - - -HB_INTERNAL void -_HB_GSUB_Free_SubTable( HB_GSUB_SubTable* st, - HB_UShort lookup_type ) -{ - switch ( lookup_type ) { - case HB_GSUB_LOOKUP_SINGLE: Free_SingleSubst ( st ); return; - case HB_GSUB_LOOKUP_MULTIPLE: Free_MultipleSubst ( st ); return; - case HB_GSUB_LOOKUP_ALTERNATE: Free_AlternateSubst ( st ); return; - case HB_GSUB_LOOKUP_LIGATURE: Free_LigatureSubst ( st ); return; - case HB_GSUB_LOOKUP_CONTEXT: Free_ContextSubst ( st ); return; - case HB_GSUB_LOOKUP_CHAIN: Free_ChainContextSubst ( st ); return; - /*case HB_GSUB_LOOKUP_EXTENSION: Free_ExtensionSubst ( st ); return;*/ - case HB_GSUB_LOOKUP_REVERSE_CHAIN: Free_ReverseChainContextSubst ( st ); return; - default: return; - }; -} - - - -/* apply one lookup to the input string object */ - -static HB_Error GSUB_Do_String_Lookup( HB_GSUBHeader* gsub, - HB_UShort lookup_index, - HB_Buffer buffer ) -{ - HB_Error error, retError = HB_Err_Not_Covered; - - HB_UInt* properties = gsub->LookupList.Properties; - int lookup_type = gsub->LookupList.Lookup[lookup_index].LookupType; - - const int nesting_level = 0; - /* 0xFFFF indicates that we don't have a context length yet */ - const HB_UShort context_length = 0xFFFF; - - switch (lookup_type) { - - case HB_GSUB_LOOKUP_SINGLE: - case HB_GSUB_LOOKUP_MULTIPLE: - case HB_GSUB_LOOKUP_ALTERNATE: - case HB_GSUB_LOOKUP_LIGATURE: - case HB_GSUB_LOOKUP_CONTEXT: - case HB_GSUB_LOOKUP_CHAIN: - /* in/out forward substitution (implemented lazy) */ - - _hb_buffer_clear_output ( buffer ); - buffer->in_pos = 0; - while ( buffer->in_pos < buffer->in_length ) - { - if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] ) - { - error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer, context_length, nesting_level ); - if ( error ) - { - if ( error != HB_Err_Not_Covered ) - return error; - } - else - retError = error; - } - else - error = HB_Err_Not_Covered; - - if ( error == HB_Err_Not_Covered ) - if ( COPY_Glyph ( buffer ) ) - return error; - } - /* we shouldn't swap if error occurred. - * - * also don't swap if nothing changed (ie HB_Err_Not_Covered). - * shouldn't matter in that case though. - */ - if ( retError == HB_Err_Ok ) - _hb_buffer_swap( buffer ); - - return retError; - - case HB_GSUB_LOOKUP_REVERSE_CHAIN: - /* in-place backward substitution */ - - buffer->in_pos = buffer->in_length - 1; - do - { - if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] ) - { - error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer, context_length, nesting_level ); - if ( error ) - { - if ( error != HB_Err_Not_Covered ) - return error; - } - else - retError = error; - } - else - error = HB_Err_Not_Covered; - - if ( error == HB_Err_Not_Covered ) - buffer->in_pos--; - } - while ((HB_Int) buffer->in_pos >= 0); - - return retError; - - /*case HB_GSUB_LOOKUP_EXTENSION:*/ - default: - return retError; - }; -} - - -HB_Error HB_GSUB_Add_Feature( HB_GSUBHeader* gsub, - HB_UShort feature_index, - HB_UInt property ) -{ - HB_UShort i; - - HB_Feature feature; - HB_UInt* properties; - HB_UShort* index; - HB_UShort lookup_count; - - /* Each feature can only be added once */ - - if ( !gsub || - feature_index >= gsub->FeatureList.FeatureCount || - gsub->FeatureList.ApplyCount == gsub->FeatureList.FeatureCount ) - return ERR(HB_Err_Invalid_Argument); - - gsub->FeatureList.ApplyOrder[gsub->FeatureList.ApplyCount++] = feature_index; - - properties = gsub->LookupList.Properties; - - feature = gsub->FeatureList.FeatureRecord[feature_index].Feature; - index = feature.LookupListIndex; - lookup_count = gsub->LookupList.LookupCount; - - for ( i = 0; i < feature.LookupListCount; i++ ) - { - HB_UShort lookup_index = index[i]; - if (lookup_index < lookup_count) - properties[lookup_index] |= property; - } - - return HB_Err_Ok; -} - - - -HB_Error HB_GSUB_Clear_Features( HB_GSUBHeader* gsub ) -{ - HB_UShort i; - - HB_UInt* properties; - - - if ( !gsub ) - return ERR(HB_Err_Invalid_Argument); - - gsub->FeatureList.ApplyCount = 0; - - properties = gsub->LookupList.Properties; - - for ( i = 0; i < gsub->LookupList.LookupCount; i++ ) - properties[i] = 0; - - return HB_Err_Ok; -} - - - -HB_Error HB_GSUB_Register_Alternate_Function( HB_GSUBHeader* gsub, - HB_AltFunction altfunc, - void* data ) -{ - if ( !gsub ) - return ERR(HB_Err_Invalid_Argument); - - gsub->altfunc = altfunc; - gsub->data = data; - - return HB_Err_Ok; -} - -/* returns error if one happened, otherwise returns HB_Err_Not_Covered if no - * feature were applied, or HB_Err_Ok otherwise. - */ -HB_Error HB_GSUB_Apply_String( HB_GSUBHeader* gsub, - HB_Buffer buffer ) -{ - HB_Error error, retError = HB_Err_Not_Covered; - int i, j, lookup_count, num_features; - - if ( !gsub || - !buffer) - return ERR(HB_Err_Invalid_Argument); - - if ( buffer->in_length == 0 ) - return retError; - - lookup_count = gsub->LookupList.LookupCount; - num_features = gsub->FeatureList.ApplyCount; - - for ( i = 0; i < num_features; i++) - { - HB_UShort feature_index = gsub->FeatureList.ApplyOrder[i]; - HB_Feature feature = gsub->FeatureList.FeatureRecord[feature_index].Feature; - - for ( j = 0; j < feature.LookupListCount; j++ ) - { - HB_UShort lookup_index = feature.LookupListIndex[j]; - - /* Skip nonexistant lookups */ - if (lookup_index >= lookup_count) - continue; - - error = GSUB_Do_String_Lookup( gsub, lookup_index, buffer ); - if ( error ) - { - if ( error != HB_Err_Not_Covered ) - return error; - } - else - retError = error; - } - } - - error = retError; - - return error; -} - - -/* END */ diff --git a/src/harfbuzz-gsub.h b/src/harfbuzz-gsub.h deleted file mode 100644 index f4deac121..000000000 --- a/src/harfbuzz-gsub.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2006 Behdad Esfahbod - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#ifndef HARFBUZZ_GSUB_H -#define HARFBUZZ_GSUB_H - -#include "harfbuzz-gdef.h" -#include "harfbuzz-buffer.h" - -HB_BEGIN_HEADER - - -/* Lookup types for glyph substitution */ - -#define HB_GSUB_LOOKUP_SINGLE 1 -#define HB_GSUB_LOOKUP_MULTIPLE 2 -#define HB_GSUB_LOOKUP_ALTERNATE 3 -#define HB_GSUB_LOOKUP_LIGATURE 4 -#define HB_GSUB_LOOKUP_CONTEXT 5 -#define HB_GSUB_LOOKUP_CHAIN 6 -#define HB_GSUB_LOOKUP_EXTENSION 7 -#define HB_GSUB_LOOKUP_REVERSE_CHAIN 8 - - -/* A pointer to a function which selects the alternate glyph. `pos' is - the position of the glyph with index `glyphID', `num_alternates' - gives the number of alternates in the `alternates' array. `data' - points to the user-defined structure specified during a call to - HB_GSUB_Register_Alternate_Function(). The function must return an - index into the `alternates' array. */ - -typedef HB_UShort (*HB_AltFunction)(HB_UInt pos, - HB_UShort glyphID, - HB_UShort num_alternates, - HB_UShort* alternates, - void* data ); - - -struct HB_GSUBHeader_ -{ - HB_UInt offset; - - HB_16Dot16 Version; - - HB_ScriptList ScriptList; - HB_FeatureList FeatureList; - HB_LookupList LookupList; - - hb_ot_layout_t *layout; - - /* the next two fields are used for an alternate substitution callback - function to select the proper alternate glyph. */ - - HB_AltFunction altfunc; - void* data; -}; - -typedef struct HB_GSUBHeader_ HB_GSUBHeader; -typedef HB_GSUBHeader* HB_GSUB; - - -HB_Error HB_Load_GSUB_Table( HB_Font font, - HB_GSUBHeader** gsub, - hb_ot_layout_t *layout ); - - -HB_Error HB_Done_GSUB_Table( HB_GSUBHeader* gsub ); - - -HB_Error HB_GSUB_Select_Script( HB_GSUBHeader* gsub, - HB_UInt script_tag, - HB_UShort* script_index ); - -HB_Error HB_GSUB_Select_Language( HB_GSUBHeader* gsub, - HB_UInt language_tag, - HB_UShort script_index, - HB_UShort* language_index, - HB_UShort* req_feature_index ); - -HB_Error HB_GSUB_Select_Feature( HB_GSUBHeader* gsub, - HB_UInt feature_tag, - HB_UShort script_index, - HB_UShort language_index, - HB_UShort* feature_index ); - - -HB_Error HB_GSUB_Query_Scripts( HB_GSUBHeader* gsub, - HB_UInt** script_tag_list ); - -HB_Error HB_GSUB_Query_Languages( HB_GSUBHeader* gsub, - HB_UShort script_index, - HB_UInt** language_tag_list ); - -HB_Error HB_GSUB_Query_Features( HB_GSUBHeader* gsub, - HB_UShort script_index, - HB_UShort language_index, - HB_UInt** feature_tag_list ); - - -HB_Error HB_GSUB_Add_Feature( HB_GSUBHeader* gsub, - HB_UShort feature_index, - HB_UInt properties ); - -HB_Error HB_GSUB_Clear_Features( HB_GSUBHeader* gsub ); - - -HB_Error HB_GSUB_Register_Alternate_Function( HB_GSUBHeader* gsub, - HB_AltFunction altfunc, - void* data ); - - -HB_Error HB_GSUB_Apply_String( HB_GSUBHeader* gsub, - HB_Buffer buffer ); - - -HB_END_HEADER - -#endif /* HARFBUZZ_GSUB_H */ diff --git a/src/harfbuzz-impl.c b/src/harfbuzz-impl.c deleted file mode 100644 index ffcef8060..000000000 --- a/src/harfbuzz-impl.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2007 Trolltech ASA - * Copyright (C) 2007 Red Hat, Inc. - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Red Hat Author(s): Behdad Esfahbod - */ - -#include "harfbuzz-impl.h" - - -HB_INTERNAL HB_Pointer -_hb_alloc( size_t size, - HB_Error *perror ) -{ - HB_Error error = 0; - HB_Pointer block = NULL; - - if ( size > 0 ) - { - block = calloc( 1, size ); - if ( !block ) - error = ERR(HB_Err_Out_Of_Memory); - } - - *perror = error; - return block; -} - - -HB_INTERNAL HB_Pointer -_hb_realloc( HB_Pointer block, - size_t new_size, - HB_Error *perror ) -{ - HB_Pointer block2 = NULL; - HB_Error error = 0; - - block2 = realloc( block, new_size ); - if ( block2 == NULL && new_size != 0 ) - error = ERR(HB_Err_Out_Of_Memory); - - if ( !error ) - block = block2; - - *perror = error; - return block; -} - - -HB_INTERNAL void -_hb_free( HB_Pointer block ) -{ - if ( block ) - free( block ); -} - - -/* helper func to set a breakpoint on */ -HB_INTERNAL HB_Error -_hb_err (HB_Error code) -{ - return code; -} diff --git a/src/harfbuzz-impl.h b/src/harfbuzz-impl.h deleted file mode 100644 index 60508edd6..000000000 --- a/src/harfbuzz-impl.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2006 Behdad Esfahbod - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#ifndef HARFBUZZ_IMPL_H -#define HARFBUZZ_IMPL_H - -#include -#include FT_FREETYPE_H -#include FT_TRUETYPE_TAGS_H - -#include "harfbuzz-global.h" - -#include - -/* XXX */ -#include "hb-ot-layout-private.h" - -HB_BEGIN_HEADER - -#ifndef HB_INTERNAL -# define HB_INTERNAL -#endif - -#ifndef NULL -# define NULL ((void *)0) -#endif - -#ifndef FALSE -# define FALSE 0 -#endif - -#ifndef TRUE -# define TRUE 1 -#endif - -#ifndef TTAG_GDEF -# define TTAG_GDEF HB_MAKE_TAG( 'G', 'D', 'E', 'F' ) -#endif -#ifndef TTAG_GPOS -# define TTAG_GPOS HB_MAKE_TAG( 'G', 'P', 'O', 'S' ) -#endif -#ifndef TTAG_GSUB -# define TTAG_GSUB HB_MAKE_TAG( 'G', 'S', 'U', 'B' ) -#endif - -#ifndef HB_UNUSED -# define HB_UNUSED(arg) ((arg) = (arg)) -#endif - -#ifndef HB_LIKELY -# define HB_LIKELY(cond) (cond) -#endif -#ifndef HB_UNLIKELY -# define HB_UNLIKELY(cond) (cond) -#endif - - -#define ALLOC(_ptr,_size) \ - ( *(void**)&(_ptr) = _hb_alloc( _size, &error ), error != 0 ) - -#define REALLOC(_ptr,_newsz) \ - ( (_ptr) = _hb_realloc( (_ptr), (_newsz), &error ), error != 0 ) - -#define FREE(_ptr) \ - do { \ - if ( (_ptr) ) \ - { \ - _hb_free( _ptr ); \ - _ptr = NULL; \ - } \ - } while (0) - -#define ALLOC_ARRAY(_ptr,_count,_type) \ - ALLOC(_ptr,(_count)*sizeof(_type)) - -#define REALLOC_ARRAY(_ptr,_newcnt,_type) \ - REALLOC(_ptr,(_newcnt)*sizeof(_type)) - -#define MEM_Copy(dest,source,count) memcpy( (char*)(dest), (const char*)(source), (size_t)(count) ) - -#define ERR(err) _hb_err (err) - - -HB_INTERNAL HB_Pointer -_hb_alloc( size_t size, - HB_Error *perror_ ); - -HB_INTERNAL HB_Pointer -_hb_realloc( HB_Pointer block, - size_t new_size, - HB_Error *perror_ ); - -HB_INTERNAL void -_hb_free( HB_Pointer block ); - - -/* helper func to set a breakpoint on */ -HB_INTERNAL HB_Error -_hb_err (HB_Error code); - - -HB_END_HEADER - -#endif /* HARFBUZZ_IMPL_H */ diff --git a/src/harfbuzz-open-private.h b/src/harfbuzz-open-private.h deleted file mode 100644 index e14753d87..000000000 --- a/src/harfbuzz-open-private.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2006 Behdad Esfahbod - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#ifndef HARFBUZZ_OPEN_PRIVATE_H -#define HARFBUZZ_OPEN_PRIVATE_H - -#include "harfbuzz-impl.h" -#include "harfbuzz-open.h" -#include "harfbuzz-gsub-private.h" -#include "harfbuzz-gpos-private.h" - -HB_BEGIN_HEADER - - -struct HB_SubTable_ -{ - union - { - HB_GSUB_SubTable gsub; - HB_GPOS_SubTable gpos; - } st; -}; - - -HB_INTERNAL HB_Error -_HB_OPEN_Load_ScriptList( HB_ScriptList* sl, - HB_Stream input ); -HB_INTERNAL HB_Error -_HB_OPEN_Load_FeatureList( HB_FeatureList* fl, - HB_Stream input ); -HB_INTERNAL HB_Error -_HB_OPEN_Load_LookupList( HB_LookupList* ll, - HB_Stream input, - HB_Type type ); - -HB_INTERNAL HB_Error -_HB_OPEN_Load_Coverage( HB_Coverage* c, - HB_Stream input ); -HB_INTERNAL HB_Error -_HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd, - HB_UShort limit, - HB_Stream input ); -HB_INTERNAL HB_Error -_HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition* cd, - HB_UShort limit, - HB_UInt class_offset, - HB_UInt base_offset, - HB_Stream input ); -HB_INTERNAL HB_Error -_HB_OPEN_Load_Device( HB_Device* d, - HB_Stream input ); - -HB_INTERNAL void _HB_OPEN_Free_ScriptList( HB_ScriptList* sl ); -HB_INTERNAL void _HB_OPEN_Free_FeatureList( HB_FeatureList* fl ); -HB_INTERNAL void _HB_OPEN_Free_LookupList( HB_LookupList* ll, - HB_Type type ); - -HB_INTERNAL void _HB_OPEN_Free_Coverage( HB_Coverage* c ); -HB_INTERNAL void _HB_OPEN_Free_ClassDefinition( HB_ClassDefinition* cd ); -HB_INTERNAL void _HB_OPEN_Free_Device( HB_Device* d ); - - - -HB_INTERNAL HB_Error -_HB_OPEN_Coverage_Index( HB_Coverage* c, - HB_UShort glyphID, - HB_UShort* index ); -HB_INTERNAL HB_Error -_HB_OPEN_Get_Class( HB_ClassDefinition* cd, - HB_UShort glyphID, - HB_UShort* klass, - HB_UShort* index ); -HB_INTERNAL HB_Error -_HB_OPEN_Get_Device( HB_Device* d, - HB_UShort size, - HB_Short* value ); - -HB_END_HEADER - -#endif /* HARFBUZZ_OPEN_PRIVATE_H */ diff --git a/src/harfbuzz-open.c b/src/harfbuzz-open.c deleted file mode 100644 index 68b27d4b6..000000000 --- a/src/harfbuzz-open.c +++ /dev/null @@ -1,1405 +0,0 @@ -/* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2006 Behdad Esfahbod - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#include "harfbuzz-impl.h" -#include "harfbuzz-open-private.h" - - -/*************************** - * Script related functions - ***************************/ - - -/* LangSys */ - -static HB_Error Load_LangSys( HB_LangSys* ls, - HB_Stream stream ) -{ - HB_Error error; - HB_UShort n, count; - HB_UShort* fi; - - - if ( ACCESS_Frame( 6L ) ) - return error; - - ls->LookupOrderOffset = GET_UShort(); /* should be 0 */ - ls->ReqFeatureIndex = GET_UShort(); - count = ls->FeatureCount = GET_UShort(); - - FORGET_Frame(); - - ls->FeatureIndex = NULL; - - if ( ALLOC_ARRAY( ls->FeatureIndex, count, HB_UShort ) ) - return error; - - if ( ACCESS_Frame( count * 2L ) ) - { - FREE( ls->FeatureIndex ); - return error; - } - - fi = ls->FeatureIndex; - - for ( n = 0; n < count; n++ ) - fi[n] = GET_UShort(); - - FORGET_Frame(); - - return HB_Err_Ok; -} - - -static void Free_LangSys( HB_LangSys* ls ) -{ - FREE( ls->FeatureIndex ); -} - - -/* Script */ - -static HB_Error Load_Script( HB_ScriptTable* s, - HB_Stream stream ) -{ - HB_Error error; - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_LangSysRecord* lsr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - if ( new_offset != base_offset ) /* not a NULL offset */ - { - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_LangSys( &s->DefaultLangSys, - stream ) ) != HB_Err_Ok ) - return error; - (void)FILE_Seek( cur_offset ); - } - else - { - /* we create a DefaultLangSys table with no entries */ - - s->DefaultLangSys.LookupOrderOffset = 0; - s->DefaultLangSys.ReqFeatureIndex = 0xFFFF; - s->DefaultLangSys.FeatureCount = 0; - s->DefaultLangSys.FeatureIndex = NULL; - } - - if ( ACCESS_Frame( 2L ) ) - goto Fail2; - - count = s->LangSysCount = GET_UShort(); - - FORGET_Frame(); - - s->LangSysRecord = NULL; - - if ( ALLOC_ARRAY( s->LangSysRecord, count, HB_LangSysRecord ) ) - goto Fail2; - - lsr = s->LangSysRecord; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 6L ) ) - goto Fail1; - - lsr[n].LangSysTag = GET_ULong(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_LangSys( &lsr[n].LangSys, stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - Free_LangSys( &lsr[m].LangSys ); - - FREE( s->LangSysRecord ); - -Fail2: - Free_LangSys( &s->DefaultLangSys ); - return error; -} - - -static void Free_Script( HB_ScriptTable* s ) -{ - HB_UShort n, count; - - HB_LangSysRecord* lsr; - - - Free_LangSys( &s->DefaultLangSys ); - - if ( s->LangSysRecord ) - { - count = s->LangSysCount; - lsr = s->LangSysRecord; - - for ( n = 0; n < count; n++ ) - Free_LangSys( &lsr[n].LangSys ); - - FREE( lsr ); - } -} - - -/* ScriptList */ - -HB_INTERNAL HB_Error -_HB_OPEN_Load_ScriptList( HB_ScriptList* sl, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, script_count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_ScriptRecord* sr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - script_count = GET_UShort(); - - FORGET_Frame(); - - sl->ScriptRecord = NULL; - - if ( ALLOC_ARRAY( sl->ScriptRecord, script_count, HB_ScriptRecord ) ) - return error; - - sr = sl->ScriptRecord; - - sl->ScriptCount= 0; - for ( n = 0; n < script_count; n++ ) - { - if ( ACCESS_Frame( 6L ) ) - goto Fail; - - sr[sl->ScriptCount].ScriptTag = GET_ULong(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - - if ( FILE_Seek( new_offset ) ) - goto Fail; - - error = Load_Script( &sr[sl->ScriptCount].Script, stream ); - if ( error == HB_Err_Ok ) - sl->ScriptCount += 1; - else if ( error != HB_Err_Not_Covered ) - goto Fail; - - (void)FILE_Seek( cur_offset ); - } - - /* Empty tables are harmless and generated by fontforge. - * See http://bugzilla.gnome.org/show_bug.cgi?id=347073 - */ -#if 0 - if ( sl->ScriptCount == 0 ) - { - error = ERR(HB_Err_Invalid_SubTable); - goto Fail; - } -#endif - - return HB_Err_Ok; - -Fail: - for ( n = 0; n < sl->ScriptCount; n++ ) - Free_Script( &sr[n].Script ); - - FREE( sl->ScriptRecord ); - return error; -} - - -HB_INTERNAL void -_HB_OPEN_Free_ScriptList( HB_ScriptList* sl ) -{ - HB_UShort n, count; - - HB_ScriptRecord* sr; - - - if ( sl->ScriptRecord ) - { - count = sl->ScriptCount; - sr = sl->ScriptRecord; - - for ( n = 0; n < count; n++ ) - Free_Script( &sr[n].Script ); - - FREE( sr ); - } -} - - - -/********************************* - * Feature List related functions - *********************************/ - - -/* Feature */ - -static HB_Error Load_Feature( HB_Feature* f, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - - HB_UShort* lli; - - - if ( ACCESS_Frame( 4L ) ) - return error; - - f->FeatureParams = GET_UShort(); /* should be 0 */ - count = f->LookupListCount = GET_UShort(); - - FORGET_Frame(); - - f->LookupListIndex = NULL; - - if ( ALLOC_ARRAY( f->LookupListIndex, count, HB_UShort ) ) - return error; - - lli = f->LookupListIndex; - - if ( ACCESS_Frame( count * 2L ) ) - { - FREE( f->LookupListIndex ); - return error; - } - - for ( n = 0; n < count; n++ ) - lli[n] = GET_UShort(); - - FORGET_Frame(); - - return HB_Err_Ok; -} - - -static void Free_Feature( HB_Feature* f ) -{ - FREE( f->LookupListIndex ); -} - - -/* FeatureList */ - -HB_INTERNAL HB_Error -_HB_OPEN_Load_FeatureList( HB_FeatureList* fl, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_FeatureRecord* fr; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = fl->FeatureCount = GET_UShort(); - - FORGET_Frame(); - - fl->FeatureRecord = NULL; - - if ( ALLOC_ARRAY( fl->FeatureRecord, count, HB_FeatureRecord ) ) - return error; - if ( ALLOC_ARRAY( fl->ApplyOrder, count, HB_UShort ) ) - goto Fail2; - - fl->ApplyCount = 0; - - fr = fl->FeatureRecord; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 6L ) ) - goto Fail1; - - fr[n].FeatureTag = GET_ULong(); - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Feature( &fr[n].Feature, stream ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail1: - for ( m = 0; m < n; m++ ) - Free_Feature( &fr[m].Feature ); - - FREE( fl->ApplyOrder ); - -Fail2: - FREE( fl->FeatureRecord ); - - return error; -} - - -HB_INTERNAL void -_HB_OPEN_Free_FeatureList( HB_FeatureList* fl ) -{ - HB_UShort n, count; - - HB_FeatureRecord* fr; - - - if ( fl->FeatureRecord ) - { - count = fl->FeatureCount; - fr = fl->FeatureRecord; - - for ( n = 0; n < count; n++ ) - Free_Feature( &fr[n].Feature ); - - FREE( fr ); - } - - FREE( fl->ApplyOrder ); -} - - - -/******************************** - * Lookup List related functions - ********************************/ - -/* the subroutines of the following two functions are defined in - ftxgsub.c and ftxgpos.c respectively */ - - -/* SubTable */ - -static HB_Error Load_SubTable( HB_SubTable* st, - HB_Stream stream, - HB_Type table_type, - HB_UShort lookup_type ) -{ - if ( table_type == HB_Type_GSUB ) - return _HB_GSUB_Load_SubTable ( &st->st.gsub, stream, lookup_type ); - else - return _HB_GPOS_Load_SubTable ( &st->st.gpos, stream, lookup_type ); -} - - -static void Free_SubTable( HB_SubTable* st, - HB_Type table_type, - HB_UShort lookup_type ) -{ - if ( table_type == HB_Type_GSUB ) - _HB_GSUB_Free_SubTable ( &st->st.gsub, lookup_type ); - else - _HB_GPOS_Free_SubTable ( &st->st.gpos, lookup_type ); -} - - -/* Lookup */ - -static HB_Error Load_Lookup( HB_Lookup* l, - HB_Stream stream, - HB_Type type ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_SubTable* st; - - HB_Bool is_extension = FALSE; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 6L ) ) - return error; - - l->LookupType = GET_UShort(); - l->LookupFlag = GET_UShort(); - count = l->SubTableCount = GET_UShort(); - - FORGET_Frame(); - - l->SubTable = NULL; - - if ( ALLOC_ARRAY( l->SubTable, count, HB_SubTable ) ) - return error; - - st = l->SubTable; - - if ( ( type == HB_Type_GSUB && l->LookupType == HB_GSUB_LOOKUP_EXTENSION ) || - ( type == HB_Type_GPOS && l->LookupType == HB_GPOS_LOOKUP_EXTENSION ) ) - is_extension = TRUE; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - - if ( is_extension ) - { - if ( FILE_Seek( new_offset ) || ACCESS_Frame( 8L ) ) - goto Fail; - - if (GET_UShort() != 1) /* format should be 1 */ - goto Fail; - - l->LookupType = GET_UShort(); - new_offset += GET_ULong(); - - FORGET_Frame(); - } - - if ( FILE_Seek( new_offset ) || - ( error = Load_SubTable( &st[n], stream, - type, l->LookupType ) ) != HB_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail: - for ( m = 0; m < n; m++ ) - Free_SubTable( &st[m], type, l->LookupType ); - - FREE( l->SubTable ); - return error; -} - - -static void Free_Lookup( HB_Lookup* l, - HB_Type type ) -{ - HB_UShort n, count; - - HB_SubTable* st; - - - if ( l->SubTable ) - { - count = l->SubTableCount; - st = l->SubTable; - - for ( n = 0; n < count; n++ ) - Free_SubTable( &st[n], type, l->LookupType ); - - FREE( st ); - } -} - - -/* LookupList */ - -HB_INTERNAL HB_Error -_HB_OPEN_Load_LookupList( HB_LookupList* ll, - HB_Stream stream, - HB_Type type ) -{ - HB_Error error; - - HB_UShort n, m, count; - HB_UInt cur_offset, new_offset, base_offset; - - HB_Lookup* l; - - - base_offset = FILE_Pos(); - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = ll->LookupCount = GET_UShort(); - - FORGET_Frame(); - - ll->Lookup = NULL; - - if ( ALLOC_ARRAY( ll->Lookup, count, HB_Lookup ) ) - return error; - if ( ALLOC_ARRAY( ll->Properties, count, HB_UInt ) ) - goto Fail2; - - l = ll->Lookup; - - for ( n = 0; n < count; n++ ) - { - if ( ACCESS_Frame( 2L ) ) - goto Fail1; - - new_offset = GET_UShort() + base_offset; - - FORGET_Frame(); - - cur_offset = FILE_Pos(); - if ( FILE_Seek( new_offset ) || - ( error = Load_Lookup( &l[n], stream, type ) ) != HB_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return HB_Err_Ok; - -Fail1: - FREE( ll->Properties ); - - for ( m = 0; m < n; m++ ) - Free_Lookup( &l[m], type ); - -Fail2: - FREE( ll->Lookup ); - return error; -} - - -HB_INTERNAL void -_HB_OPEN_Free_LookupList( HB_LookupList* ll, - HB_Type type ) -{ - HB_UShort n, count; - - HB_Lookup* l; - - - FREE( ll->Properties ); - - if ( ll->Lookup ) - { - count = ll->LookupCount; - l = ll->Lookup; - - for ( n = 0; n < count; n++ ) - Free_Lookup( &l[n], type ); - - FREE( l ); - } -} - - - -/***************************** - * Coverage related functions - *****************************/ - - -/* CoverageFormat1 */ - -static HB_Error Load_Coverage1( HB_CoverageFormat1* cf1, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - - HB_UShort* ga; - - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = cf1->GlyphCount = GET_UShort(); - - FORGET_Frame(); - - cf1->GlyphArray = NULL; - - if ( ALLOC_ARRAY( cf1->GlyphArray, count, HB_UShort ) ) - return error; - - ga = cf1->GlyphArray; - - if ( ACCESS_Frame( count * 2L ) ) - { - FREE( cf1->GlyphArray ); - return error; - } - - for ( n = 0; n < count; n++ ) - ga[n] = GET_UShort(); - - FORGET_Frame(); - - return HB_Err_Ok; -} - - -static void Free_Coverage1( HB_CoverageFormat1* cf1 ) -{ - FREE( cf1->GlyphArray ); -} - - -/* CoverageFormat2 */ - -static HB_Error Load_Coverage2( HB_CoverageFormat2* cf2, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - - HB_RangeRecord* rr; - - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = cf2->RangeCount = GET_UShort(); - - FORGET_Frame(); - - cf2->RangeRecord = NULL; - - if ( ALLOC_ARRAY( cf2->RangeRecord, count, HB_RangeRecord ) ) - return error; - - rr = cf2->RangeRecord; - - if ( ACCESS_Frame( count * 6L ) ) - goto Fail; - - for ( n = 0; n < count; n++ ) - { - rr[n].Start = GET_UShort(); - rr[n].End = GET_UShort(); - rr[n].StartCoverageIndex = GET_UShort(); - - /* sanity check; we are limited to 16bit integers */ - if ( rr[n].Start > rr[n].End || - ( rr[n].End - rr[n].Start + (long)rr[n].StartCoverageIndex ) >= - 0x10000L ) - { - error = ERR(HB_Err_Invalid_SubTable); - goto Fail; - } - } - - FORGET_Frame(); - - return HB_Err_Ok; - -Fail: - FREE( cf2->RangeRecord ); - return error; -} - - -static void Free_Coverage2( HB_CoverageFormat2* cf2 ) -{ - FREE( cf2->RangeRecord ); -} - - -HB_INTERNAL HB_Error -_HB_OPEN_Load_Coverage( HB_Coverage* c, - HB_Stream stream ) -{ - HB_Error error; - - if ( ACCESS_Frame( 2L ) ) - return error; - - c->CoverageFormat = GET_UShort(); - - FORGET_Frame(); - - switch ( c->CoverageFormat ) - { - case 1: return Load_Coverage1( &c->cf.cf1, stream ); - case 2: return Load_Coverage2( &c->cf.cf2, stream ); - default: return ERR(HB_Err_Invalid_SubTable_Format); - } - - return HB_Err_Ok; /* never reached */ -} - - -HB_INTERNAL void -_HB_OPEN_Free_Coverage( HB_Coverage* c ) -{ - switch ( c->CoverageFormat ) - { - case 1: Free_Coverage1( &c->cf.cf1 ); break; - case 2: Free_Coverage2( &c->cf.cf2 ); break; - default: break; - } -} - - -static HB_Error Coverage_Index1( HB_CoverageFormat1* cf1, - HB_UShort glyphID, - HB_UShort* index ) -{ - HB_UShort min, max, new_min, new_max, middle; - - HB_UShort* array = cf1->GlyphArray; - - - /* binary search */ - - if ( cf1->GlyphCount == 0 ) - return HB_Err_Not_Covered; - - new_min = 0; - new_max = cf1->GlyphCount - 1; - - do - { - min = new_min; - max = new_max; - - /* we use (min + max) / 2 = max - (max - min) / 2 to avoid - overflow and rounding errors */ - - middle = max - ( ( max - min ) >> 1 ); - - if ( glyphID == array[middle] ) - { - *index = middle; - return HB_Err_Ok; - } - else if ( glyphID < array[middle] ) - { - if ( middle == min ) - break; - new_max = middle - 1; - } - else - { - if ( middle == max ) - break; - new_min = middle + 1; - } - } while ( min < max ); - - return HB_Err_Not_Covered; -} - - -static HB_Error Coverage_Index2( HB_CoverageFormat2* cf2, - HB_UShort glyphID, - HB_UShort* index ) -{ - HB_UShort min, max, new_min, new_max, middle; - - HB_RangeRecord* rr = cf2->RangeRecord; - - - /* binary search */ - - if ( cf2->RangeCount == 0 ) - return HB_Err_Not_Covered; - - new_min = 0; - new_max = cf2->RangeCount - 1; - - do - { - min = new_min; - max = new_max; - - /* we use (min + max) / 2 = max - (max - min) / 2 to avoid - overflow and rounding errors */ - - middle = max - ( ( max - min ) >> 1 ); - - if ( glyphID >= rr[middle].Start && glyphID <= rr[middle].End ) - { - *index = rr[middle].StartCoverageIndex + glyphID - rr[middle].Start; - return HB_Err_Ok; - } - else if ( glyphID < rr[middle].Start ) - { - if ( middle == min ) - break; - new_max = middle - 1; - } - else - { - if ( middle == max ) - break; - new_min = middle + 1; - } - } while ( min < max ); - - return HB_Err_Not_Covered; -} - - -HB_INTERNAL HB_Error -_HB_OPEN_Coverage_Index( HB_Coverage* c, - HB_UShort glyphID, - HB_UShort* index ) -{ - switch ( c->CoverageFormat ) - { - case 1: return Coverage_Index1( &c->cf.cf1, glyphID, index ); - case 2: return Coverage_Index2( &c->cf.cf2, glyphID, index ); - default: return ERR(HB_Err_Invalid_SubTable_Format); - } - - return HB_Err_Ok; /* never reached */ -} - - - -/************************************* - * Class Definition related functions - *************************************/ - - -/* ClassDefFormat1 */ - -static HB_Error Load_ClassDef1( HB_ClassDefinition* cd, - HB_UShort limit, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - - HB_UShort* cva; - - HB_ClassDefFormat1* cdf1; - - - cdf1 = &cd->cd.cd1; - - if ( ACCESS_Frame( 4L ) ) - return error; - - cdf1->StartGlyph = GET_UShort(); - count = cdf1->GlyphCount = GET_UShort(); - - FORGET_Frame(); - - /* sanity check; we are limited to 16bit integers */ - - if ( cdf1->StartGlyph + (long)count >= 0x10000L ) - return ERR(HB_Err_Invalid_SubTable); - - cdf1->ClassValueArray = NULL; - - if ( ALLOC_ARRAY( cdf1->ClassValueArray, count, HB_UShort ) ) - return error; - - cva = cdf1->ClassValueArray; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail; - - for ( n = 0; n < count; n++ ) - { - cva[n] = GET_UShort(); - if ( cva[n] >= limit ) - { - error = ERR(HB_Err_Invalid_SubTable); - goto Fail; - } - } - - FORGET_Frame(); - - return HB_Err_Ok; - -Fail: - FREE( cva ); - - return error; -} - - -static void Free_ClassDef1( HB_ClassDefFormat1* cdf1 ) -{ - FREE( cdf1->ClassValueArray ); -} - - -/* ClassDefFormat2 */ - -static HB_Error Load_ClassDef2( HB_ClassDefinition* cd, - HB_UShort limit, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - - HB_ClassRangeRecord* crr; - - HB_ClassDefFormat2* cdf2; - - - cdf2 = &cd->cd.cd2; - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = GET_UShort(); - cdf2->ClassRangeCount = 0; /* zero for now. we fill with the number of good entries later */ - - FORGET_Frame(); - - cdf2->ClassRangeRecord = NULL; - - if ( ALLOC_ARRAY( cdf2->ClassRangeRecord, count, HB_ClassRangeRecord ) ) - return error; - - crr = cdf2->ClassRangeRecord; - - if ( ACCESS_Frame( count * 6L ) ) - goto Fail; - - for ( n = 0; n < count; n++ ) - { - crr[n].Start = GET_UShort(); - crr[n].End = GET_UShort(); - crr[n].Class = GET_UShort(); - - /* sanity check */ - - if ( crr[n].Start > crr[n].End || - crr[n].Class >= limit ) - { - /* XXX - * Corrupt entry. Skip it. - * This is hit by Nafees Nastaliq font for example - */ - n--; - count--; - } - } - - FORGET_Frame(); - - cdf2->ClassRangeCount = count; - - return HB_Err_Ok; - -Fail: - FREE( crr ); - - return error; -} - - -static void Free_ClassDef2( HB_ClassDefFormat2* cdf2 ) -{ - FREE( cdf2->ClassRangeRecord ); -} - - -/* ClassDefinition */ - -HB_INTERNAL HB_Error -_HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd, - HB_UShort limit, - HB_Stream stream ) -{ - HB_Error error; - - if ( ACCESS_Frame( 2L ) ) - return error; - - cd->ClassFormat = GET_UShort(); - - FORGET_Frame(); - - switch ( cd->ClassFormat ) - { - case 1: error = Load_ClassDef1( cd, limit, stream ); break; - case 2: error = Load_ClassDef2( cd, limit, stream ); break; - default: error = ERR(HB_Err_Invalid_SubTable_Format); break; - } - - if ( error ) - return error; - - cd->loaded = TRUE; - - return HB_Err_Ok; -} - - -static HB_Error -_HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition* cd ) -{ - HB_Error error; - - cd->ClassFormat = 1; /* Meaningless */ - - if ( ALLOC_ARRAY( cd->cd.cd1.ClassValueArray, 1, HB_UShort ) ) - return error; - - return HB_Err_Ok; -} - -HB_INTERNAL HB_Error -_HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition* cd, - HB_UShort limit, - HB_UInt class_offset, - HB_UInt base_offset, - HB_Stream stream ) -{ - HB_Error error; - HB_UInt cur_offset; - - cur_offset = FILE_Pos(); - - if ( class_offset ) - { - if ( !FILE_Seek( class_offset + base_offset ) ) - error = _HB_OPEN_Load_ClassDefinition( cd, limit, stream ); - } - else - error = _HB_OPEN_Load_EmptyClassDefinition ( cd ); - - if (error == HB_Err_Ok) - (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */ - - return error; -} - -HB_INTERNAL void -_HB_OPEN_Free_ClassDefinition( HB_ClassDefinition* cd ) -{ - if ( !cd->loaded ) - return; - - switch ( cd->ClassFormat ) - { - case 1: Free_ClassDef1( &cd->cd.cd1 ); break; - case 2: Free_ClassDef2( &cd->cd.cd2 ); break; - default: break; - } -} - - -static HB_Error Get_Class1( HB_ClassDefFormat1* cdf1, - HB_UShort glyphID, - HB_UShort* klass, - HB_UShort* index ) -{ - HB_UShort* cva = cdf1->ClassValueArray; - - - if ( index ) - *index = 0; - - if ( glyphID >= cdf1->StartGlyph && - glyphID < cdf1->StartGlyph + cdf1->GlyphCount ) - { - *klass = cva[glyphID - cdf1->StartGlyph]; - return HB_Err_Ok; - } - else - { - *klass = 0; - return HB_Err_Not_Covered; - } -} - - -/* we need the index value of the last searched class range record - in case of failure for constructed GDEF tables */ - -static HB_Error Get_Class2( HB_ClassDefFormat2* cdf2, - HB_UShort glyphID, - HB_UShort* klass, - HB_UShort* index ) -{ - HB_Error error = HB_Err_Ok; - HB_UShort min, max, new_min, new_max, middle; - - HB_ClassRangeRecord* crr = cdf2->ClassRangeRecord; - - - /* binary search */ - - if ( cdf2->ClassRangeCount == 0 ) - { - *klass = 0; - if ( index ) - *index = 0; - - return HB_Err_Not_Covered; - } - - new_min = 0; - new_max = cdf2->ClassRangeCount - 1; - - do - { - min = new_min; - max = new_max; - - /* we use (min + max) / 2 = max - (max - min) / 2 to avoid - overflow and rounding errors */ - - middle = max - ( ( max - min ) >> 1 ); - - if ( glyphID >= crr[middle].Start && glyphID <= crr[middle].End ) - { - *klass = crr[middle].Class; - error = HB_Err_Ok; - break; - } - else if ( glyphID < crr[middle].Start ) - { - if ( middle == min ) - { - *klass = 0; - error = HB_Err_Not_Covered; - break; - } - new_max = middle - 1; - } - else - { - if ( middle == max ) - { - *klass = 0; - error = HB_Err_Not_Covered; - break; - } - new_min = middle + 1; - } - } while ( min < max ); - - if ( index ) - *index = middle; - - return error; -} - - -HB_INTERNAL HB_Error -_HB_OPEN_Get_Class( HB_ClassDefinition* cd, - HB_UShort glyphID, - HB_UShort* klass, - HB_UShort* index ) -{ - switch ( cd->ClassFormat ) - { - case 1: return Get_Class1( &cd->cd.cd1, glyphID, klass, index ); - case 2: return Get_Class2( &cd->cd.cd2, glyphID, klass, index ); - default: return ERR(HB_Err_Invalid_SubTable_Format); - } - - return HB_Err_Ok; /* never reached */ -} - - - -/*************************** - * Device related functions - ***************************/ - - -HB_INTERNAL HB_Error -_HB_OPEN_Load_Device( HB_Device* d, - HB_Stream stream ) -{ - HB_Error error; - - HB_UShort n, count; - - HB_UShort* dv; - - - if ( ACCESS_Frame( 6L ) ) - return error; - - d->StartSize = GET_UShort(); - d->EndSize = GET_UShort(); - d->DeltaFormat = GET_UShort(); - - FORGET_Frame(); - - d->DeltaValue = NULL; - - if ( d->StartSize > d->EndSize || - d->DeltaFormat == 0 || d->DeltaFormat > 3 ) - { - /* XXX - * I've seen fontforge generate DeltaFormat == 0. - * Just return Ok and let the NULL DeltaValue disable - * this table. - */ - return HB_Err_Ok; - } - - count = ( ( d->EndSize - d->StartSize + 1 ) >> - ( 4 - d->DeltaFormat ) ) + 1; - - if ( ALLOC_ARRAY( d->DeltaValue, count, HB_UShort ) ) - return error; - - if ( ACCESS_Frame( count * 2L ) ) - { - FREE( d->DeltaValue ); - return error; - } - - dv = d->DeltaValue; - - for ( n = 0; n < count; n++ ) - dv[n] = GET_UShort(); - - FORGET_Frame(); - - return HB_Err_Ok; -} - - -HB_INTERNAL void -_HB_OPEN_Free_Device( HB_Device* d ) -{ - FREE( d->DeltaValue ); -} - - -/* Since we have the delta values stored in compressed form, we must - uncompress it now. To simplify the interface, the function always - returns a meaningful value in `value'; the error is just for - information. - | | - format = 1: 0011223344556677|8899101112131415|... - | | - byte 1 byte 2 - - 00: (byte >> 14) & mask - 11: (byte >> 12) & mask - ... - - mask = 0x0003 - | | - format = 2: 0000111122223333|4444555566667777|... - | | - byte 1 byte 2 - - 0000: (byte >> 12) & mask - 1111: (byte >> 8) & mask - ... - - mask = 0x000F - | | - format = 3: 0000000011111111|2222222233333333|... - | | - byte 1 byte 2 - - 00000000: (byte >> 8) & mask - 11111111: (byte >> 0) & mask - .... - - mask = 0x00FF */ - -HB_INTERNAL HB_Error -_HB_OPEN_Get_Device( HB_Device* d, - HB_UShort size, - HB_Short* value ) -{ - HB_UShort byte, bits, mask, f, s; - - - f = d->DeltaFormat; - - if ( d->DeltaValue && size >= d->StartSize && size <= d->EndSize ) - { - s = size - d->StartSize; - byte = d->DeltaValue[s >> ( 4 - f )]; - bits = byte >> ( 16 - ( ( s % ( 1 << ( 4 - f ) ) + 1 ) << f ) ); - mask = 0xFFFF >> ( 16 - ( 1 << f ) ); - - *value = (HB_Short)( bits & mask ); - - /* conversion to a signed value */ - - if ( *value >= ( ( mask + 1 ) >> 1 ) ) - *value -= mask + 1; - - return HB_Err_Ok; - } - else - { - *value = 0; - return HB_Err_Not_Covered; - } -} - - -/* END */ diff --git a/src/harfbuzz-open.h b/src/harfbuzz-open.h deleted file mode 100644 index 2ed4440b1..000000000 --- a/src/harfbuzz-open.h +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2006 Behdad Esfahbod - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#ifndef HARFBUZZ_OPEN_H -#define HARFBUZZ_OPEN_H - -#include "harfbuzz-global.h" - -HB_BEGIN_HEADER - -/* Use this if a feature applies to all glyphs */ -#define HB_ALL_GLYPHS 0xFFFF - -#define HB_DEFAULT_LANGUAGE 0xFFFF - -#define HB_MAX_NESTING_LEVEL 100 - - -/* Script list related structures */ - -struct HB_LangSys_ -{ - HB_UShort LookupOrderOffset; /* always 0 for TT Open 1.0 */ - HB_UShort ReqFeatureIndex; /* required FeatureIndex */ - HB_UShort FeatureCount; /* number of Feature indices */ - HB_UShort* FeatureIndex; /* array of Feature indices */ -}; - -typedef struct HB_LangSys_ HB_LangSys; - - -struct HB_LangSysRecord_ -{ - HB_UInt LangSysTag; /* LangSysTag identifier */ - HB_LangSys LangSys; /* LangSys table */ -}; - -typedef struct HB_LangSysRecord_ HB_LangSysRecord; - - -struct HB_ScriptTable_ -{ - HB_LangSys DefaultLangSys; /* DefaultLangSys table */ - HB_UShort LangSysCount; /* number of LangSysRecords */ - HB_LangSysRecord* LangSysRecord; /* array of LangSysRecords */ -}; - -typedef struct HB_ScriptTable_ HB_ScriptTable; - - -struct HB_ScriptRecord_ -{ - HB_UInt ScriptTag; /* ScriptTag identifier */ - HB_ScriptTable Script; /* Script table */ -}; - -typedef struct HB_ScriptRecord_ HB_ScriptRecord; - - -struct HB_ScriptList_ -{ - HB_UShort ScriptCount; /* number of ScriptRecords */ - HB_ScriptRecord* ScriptRecord; /* array of ScriptRecords */ -}; - -typedef struct HB_ScriptList_ HB_ScriptList; - - -/* Feature list related structures */ - -struct HB_Feature_ -{ - HB_UShort FeatureParams; /* always 0 for TT Open 1.0 */ - HB_UShort LookupListCount; /* number of LookupList indices */ - HB_UShort* LookupListIndex; /* array of LookupList indices */ -}; - -typedef struct HB_Feature_ HB_Feature; - - -struct HB_FeatureRecord_ -{ - HB_UInt FeatureTag; /* FeatureTag identifier */ - HB_Feature Feature; /* Feature table */ -}; - -typedef struct HB_FeatureRecord_ HB_FeatureRecord; - - -struct HB_FeatureList_ -{ - HB_UShort FeatureCount; /* number of FeatureRecords */ - HB_FeatureRecord* FeatureRecord; /* array of FeatureRecords */ - HB_UShort* ApplyOrder; /* order to apply features */ - HB_UShort ApplyCount; /* number of elements in ApplyOrder */ -}; - -typedef struct HB_FeatureList_ HB_FeatureList; - - -/* Lookup list related structures */ - -typedef struct HB_SubTable_ HB_SubTable; - - -struct HB_Lookup_ -{ - HB_UShort LookupType; /* Lookup type */ - HB_UShort LookupFlag; /* Lookup qualifiers */ - HB_UShort SubTableCount; /* number of SubTables */ - HB_SubTable* SubTable; /* array of SubTables */ -}; - -typedef struct HB_Lookup_ HB_Lookup; - - -/* The `Properties' field is not defined in the OpenType specification but - is needed for processing lookups. If properties[n] is > 0, the - functions HB_GSUB_Apply_String() resp. HB_GPOS_Apply_String() will - process Lookup[n] for glyphs which have the specific bit not set in - the `properties' field of the input string object. */ - -struct HB_LookupList_ -{ - HB_UShort LookupCount; /* number of Lookups */ - HB_Lookup* Lookup; /* array of Lookup records */ - HB_UInt* Properties; /* array of flags */ -}; - -typedef struct HB_LookupList_ HB_LookupList; - - -/* Possible LookupFlag bit masks. `HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS' comes from the - OpenType 1.2 specification; HB_LOOKUP_FLAG_RIGHT_TO_LEFT has been (re)introduced in - OpenType 1.3 -- if set, the last glyph in a cursive attachment - sequence has to be positioned on the baseline -- regardless of the - writing direction. */ - -#define HB_LOOKUP_FLAG_RIGHT_TO_LEFT 0x0001 -#define HB_LOOKUP_FLAG_IGNORE_BASE_GLYPHS 0x0002 -#define HB_LOOKUP_FLAG_IGNORE_LIGATURES 0x0004 -#define HB_LOOKUP_FLAG_IGNORE_MARKS 0x0008 -#define HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS 0xFF00 - - -struct HB_CoverageFormat1_ -{ - HB_UShort GlyphCount; /* number of glyphs in GlyphArray */ - HB_UShort* GlyphArray; /* array of glyph IDs */ -}; - -typedef struct HB_CoverageFormat1_ HB_CoverageFormat1; - - -struct HB_RangeRecord_ -{ - HB_UShort Start; /* first glyph ID in the range */ - HB_UShort End; /* last glyph ID in the range */ - HB_UShort StartCoverageIndex; /* coverage index of first - glyph ID in the range */ -}; - -typedef struct HB_RangeRecord_ HB_RangeRecord; - - -struct HB_CoverageFormat2_ -{ - HB_UShort RangeCount; /* number of RangeRecords */ - HB_RangeRecord* RangeRecord; /* array of RangeRecords */ -}; - -typedef struct HB_CoverageFormat2_ HB_CoverageFormat2; - - -struct HB_Coverage_ -{ - HB_UShort CoverageFormat; /* 1 or 2 */ - - union - { - HB_CoverageFormat1 cf1; - HB_CoverageFormat2 cf2; - } cf; -}; - -typedef struct HB_Coverage_ HB_Coverage; - - -struct HB_ClassDefFormat1_ -{ - HB_UShort StartGlyph; /* first glyph ID of the - ClassValueArray */ - HB_UShort GlyphCount; /* size of the ClassValueArray */ - HB_UShort* ClassValueArray; /* array of class values */ -}; - -typedef struct HB_ClassDefFormat1_ HB_ClassDefFormat1; - - -struct HB_ClassRangeRecord_ -{ - HB_UShort Start; /* first glyph ID in the range */ - HB_UShort End; /* last glyph ID in the range */ - HB_UShort Class; /* applied to all glyphs in range */ -}; - -typedef struct HB_ClassRangeRecord_ HB_ClassRangeRecord; - - -struct HB_ClassDefFormat2_ -{ - HB_UShort ClassRangeCount; - /* number of ClassRangeRecords */ - HB_ClassRangeRecord* ClassRangeRecord; - /* array of ClassRangeRecords */ -}; - -typedef struct HB_ClassDefFormat2_ HB_ClassDefFormat2; - - -struct HB_ClassDefinition_ -{ - HB_Bool loaded; - - HB_UShort ClassFormat; /* 1 or 2 */ - - union - { - HB_ClassDefFormat1 cd1; - HB_ClassDefFormat2 cd2; - } cd; -}; - -typedef struct HB_ClassDefinition_ HB_ClassDefinition; - - -struct HB_Device_ -{ - HB_UShort StartSize; /* smallest size to correct */ - HB_UShort EndSize; /* largest size to correct */ - HB_UShort DeltaFormat; /* DeltaValue array data format: - 1, 2, or 3 */ - HB_UShort* DeltaValue; /* array of compressed data */ -}; - -typedef struct HB_Device_ HB_Device; - - -enum HB_Type_ -{ - HB_Type_GSUB, - HB_Type_GPOS -}; - -typedef enum HB_Type_ HB_Type; - - -HB_END_HEADER - -#endif /* HARFBUZZ_OPEN_H */ diff --git a/src/harfbuzz-stream-private.h b/src/harfbuzz-stream-private.h deleted file mode 100644 index 1d88584a4..000000000 --- a/src/harfbuzz-stream-private.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2006 Behdad Esfahbod - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#ifndef HARFBUZZ_STREAM_PRIVATE_H -#define HARFBUZZ_STREAM_PRIVATE_H - -#include "harfbuzz-impl.h" - -HB_BEGIN_HEADER - -typedef FT_Stream HB_Stream; - -HB_INTERNAL HB_Int -_hb_stream_pos( HB_Stream stream ); - -HB_INTERNAL HB_Error -_hb_stream_seek( HB_Stream stream, - HB_UInt pos ); - -HB_INTERNAL HB_Error -_hb_stream_frame_enter( HB_Stream stream, - HB_UInt size ); - -HB_INTERNAL void -_hb_stream_frame_exit( HB_Stream stream ); - -HB_INTERNAL HB_Error -_hb_font_goto_table( HB_Font font, - HB_UInt tag ); - -/* convenience macros */ - -#define SET_ERR(c) ( (error = (c)) != 0 ) - -#define GOTO_Table(tag) SET_ERR( _hb_font_goto_table( font, tag ) ) -#define FILE_Pos() _hb_stream_pos( stream ) -#define FILE_Seek(pos) SET_ERR( _hb_stream_seek( stream, pos ) ) -#define ACCESS_Frame(size) SET_ERR( _hb_stream_frame_enter( stream, size ) ) -#define FORGET_Frame() _hb_stream_frame_exit( stream ) - -#define GET_Byte() (*stream->cursor++) -#define GET_Short() (stream->cursor += 2, (HB_Short)( \ - (*(((HB_Byte*)stream->cursor)-2) << 8) | \ - *(((HB_Byte*)stream->cursor)-1) \ - )) -#define GET_Long() (stream->cursor += 4, (HB_Int)( \ - (*(((HB_Byte*)stream->cursor)-4) << 24) | \ - (*(((HB_Byte*)stream->cursor)-3) << 16) | \ - (*(((HB_Byte*)stream->cursor)-2) << 8) | \ - *(((HB_Byte*)stream->cursor)-1) \ - )) - - -#define GET_Char() ((HB_Char)GET_Byte()) -#define GET_UShort() ((HB_UShort)GET_Short()) -#define GET_ULong() ((HB_UInt)GET_Long()) -#define GET_Tag4() GET_ULong() - -HB_END_HEADER - -#endif /* HARFBUZZ_STREAM_PRIVATE_H */ diff --git a/src/harfbuzz-stream.c b/src/harfbuzz-stream.c deleted file mode 100644 index 6d35479f6..000000000 --- a/src/harfbuzz-stream.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (C) 2005 David Turner - * Copyright (C) 2007 Trolltech ASA - * Copyright (C) 2007 Red Hat, Inc. - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Red Hat Author(s): Behdad Esfahbod - */ - -#include "harfbuzz-impl.h" -#include "harfbuzz-stream-private.h" -#include - -#if 0 -#include -#define LOG(x) _hb_log x - -static void -_hb_log( const char* format, ... ) -{ - va_list ap; - - va_start( ap, format ); - vfprintf( stderr, format, ap ); - va_end( ap ); -} - -#else -#define LOG(x) do {} while (0) -#endif - - -/* only used internally */ -static HB_Pointer -_hb_qalloc( HB_UInt size, - HB_Error *perror ) -{ - HB_Error error = 0; - HB_Pointer block = NULL; - - if ( size > 0 ) - { - block = malloc( size ); - if ( !block ) - error = ERR(HB_Err_Out_Of_Memory); - } - - *perror = error; - return block; -} - -#undef QALLOC /* just in case */ -#define QALLOC(ptr,size) ( (ptr) = _hb_qalloc( (size), &error ), error != 0 ) - -HB_INTERNAL HB_Int -_hb_stream_pos( HB_Stream stream ) -{ - LOG(( "_hb_stream_pos() -> %ld\n", stream->pos )); - return stream->pos; -} - - -HB_INTERNAL HB_Error -_hb_stream_seek( HB_Stream stream, - HB_UInt pos ) -{ - HB_Error error = 0; - - stream->pos = pos; - if ( stream->read ) - { - if ( stream->read( stream, pos, NULL, 0 ) ) - error = ERR(HB_Err_Read_Error); - } - else if ( pos > stream->size ) - error = ERR(HB_Err_Read_Error); - - LOG(( "_hb_stream_seek(%ld) -> 0x%04X\n", pos, error )); - return error; -} - - -HB_INTERNAL HB_Error -_hb_stream_frame_enter( HB_Stream stream, - HB_UInt count ) -{ - HB_Error error = HB_Err_Ok; - HB_UInt read_bytes; - - if ( stream->read ) - { - /* allocate the frame in memory */ - - if ( QALLOC( stream->base, count ) ) - goto Exit; - - /* read it */ - read_bytes = stream->read( stream, stream->pos, - stream->base, count ); - if ( read_bytes < count ) - { - FREE( stream->base ); - error = ERR(HB_Err_Read_Error); - } - stream->cursor = stream->base; - stream->limit = stream->cursor + count; - stream->pos += read_bytes; - } - else - { - /* check new position, watch for overflow */ - if (HB_UNLIKELY (stream->pos + count > stream->size || - stream->pos + count < stream->pos)) - { - error = ERR(HB_Err_Read_Error); - goto Exit; - } - - /* set cursor */ - stream->cursor = stream->base + stream->pos; - stream->limit = stream->cursor + count; - stream->pos += count; - } - -Exit: - LOG(( "_hb_stream_frame_enter(%ld) -> 0x%04X\n", count, error )); - return error; -} - - -HB_INTERNAL void -_hb_stream_frame_exit( HB_Stream stream ) -{ - if ( stream->read ) - { - FREE( stream->base ); - } - stream->cursor = NULL; - stream->limit = NULL; - - LOG(( "_hb_stream_frame_exit()\n" )); -} - - -HB_INTERNAL HB_Error -_hb_font_goto_table( HB_Font font, - HB_UInt the_tag ) -{ - HB_Stream stream = font->stream; - - HB_UInt offset = 0, sig; - HB_UInt count, nn; - HB_Error error; - - LOG(( "_hb_font_goto_table( %p, %c%c%c%c, %p )\n", - font, - (int)((the_tag >> 24) & 0xFF), - (int)((the_tag >> 16) & 0xFF), - (int)((the_tag >> 8) & 0xFF), - (int)(the_tag & 0xFF), - stream )); - - if ( !FT_IS_SFNT(font) ) - { - LOG(( "not a SFNT font !!\n" )); - error = ERR(HB_Err_Invalid_Argument); - goto Exit; - } - - /* parse the directory table directly, without using - * FreeType's built-in data structures - */ - - if ( FILE_Seek( 0 ) || ACCESS_Frame( 4 ) ) - goto Exit; - - sig = GET_Tag4(); - - FORGET_Frame(); - - if ( sig == HB_MAKE_TAG( 't', 't', 'c', 'f' ) ) - { - /* deal with TrueType collections */ - LOG(( ">> This is a TrueType Collection\n" )); - - if ( FILE_Seek( 12 + font->face_index*4 ) || - ACCESS_Frame( 4 ) ) - goto Exit; - - offset = GET_ULong(); - - FORGET_Frame(); - } - - LOG(( "TrueType offset = %ld\n", offset )); - - if ( FILE_Seek( offset+4 ) || - ACCESS_Frame( 2 ) ) - goto Exit; - - count = GET_UShort(); - - FORGET_Frame(); - - if ( FILE_Seek( offset+12 ) || - ACCESS_Frame( count*16 ) ) - goto Exit; - - for ( nn = 0; nn < count; nn++ ) - { - HB_UInt tag = GET_ULong(); - HB_UInt checksum = GET_ULong(); - HB_UInt start = GET_ULong(); - HB_UInt size = GET_ULong(); - - HB_UNUSED(checksum); - HB_UNUSED(size); - - if ( tag == the_tag ) - { - LOG(( "TrueType table (start: %ld) (size: %ld)\n", start, size )); - error = _hb_stream_seek( stream, start ); - goto FoundIt; - } - } - error = HB_Err_Not_Covered; - -FoundIt: - FORGET_Frame(); - -Exit: - LOG(( "TrueType error=%d\n", error )); - - return error; -} - -#undef QALLOC - diff --git a/src/harfbuzz.c b/src/harfbuzz.c deleted file mode 100644 index a0415f5cc..000000000 --- a/src/harfbuzz.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2006 Behdad Esfahbod - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#define HB_INTERNAL static -#include "harfbuzz-buffer.c" -#include "harfbuzz-gsub.c" -#include "harfbuzz-gpos.c" -#include "harfbuzz-impl.c" -#include "harfbuzz-open.c" -#include "harfbuzz-stream.c" diff --git a/src/harfbuzz.h b/src/harfbuzz.h deleted file mode 100644 index d23b6bc26..000000000 --- a/src/harfbuzz.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2006 Behdad Esfahbod - * - * This is part of HarfBuzz, an OpenType Layout engine library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#ifndef HARFBUZZ_H -#define HARFBUZZ_H - -#include "harfbuzz-global.h" -#include "harfbuzz-buffer.h" -#include "harfbuzz-gsub.h" -#include "harfbuzz-gpos.h" -#include "harfbuzz-open.h" - -#endif /* HARFBUZZ_OPEN_H */