/************************ * public methods */ public OTTable GetTable(OTFont fontOwner, DirectoryEntry de) { // first try getting it from the table cache OTTable table = GetTableFromCache(de); if (table == null) { if (de.length != 0 && de.offset != 0 && de.offset < m_file.GetFileLength() && de.offset + de.length <= m_file.GetFileLength()) { // read the table from the file MBOBuffer buf = m_file.ReadPaddedBuffer(de.offset, de.length); if (buf != null) { // put the buffer into a table object table = CreateTableObject(de.tag, buf); // add the table to the cache CachedTables.Add(table); } } } return(table); }
/***************** * public methods */ /// /// <summary>Calculate the check sum for the font as the /// sum of the checksums of the offset table, directory entries, and /// each table. /// </summary> public uint CalcChecksum() { uint sum = 0; sum += m_OffsetTable.CalcOffsetTableChecksum(); sum += m_OffsetTable.CalcDirectoryEntriesChecksum(); if (m_OffsetTable != null) { for (int i = 0; i < m_OffsetTable.DirectoryEntries.Count; i++) { DirectoryEntry de = (DirectoryEntry)m_OffsetTable.DirectoryEntries[i]; OTTable table = GetTable(de); uint calcChecksum = 0; if (table != null) { calcChecksum = table.CalcChecksum(); } sum += calcChecksum; } } return(sum); }
protected OTTable GetTable(DirectoryEntry de) { OTTable table = null; if (m_File != null) { // get the table from OTFile's table manager table = m_File.GetTableManager().GetTable(this, de); } else { // get the table from the list in memory for (int i = 0; i < MemBasedTables.Count; i++) { OTTable t = (OTTable)MemBasedTables[i]; if (de.tag == t.m_tag) { table = t; break; } } } return(table); }
public bool Validate(Validator v, string sIdentity, OTTable tableOwner) { bool bOk = true; // ??? // ??? are there any values that are invalid ??? // ??? return bOk; }
/// <summary>Return the ith table in the directory entries, /// or null if there is no such entry. /// </summary> public OTTable GetTable(ushort i) { OTTable table = null; DirectoryEntry de = GetDirectoryEntry(i); if (de != null) { table = GetTable(de); } return(table); }
/// <summary>Rmove a table to an non-file based table. Throws /// exception if table is not in font. /// </summary> public void RemoveTable(OTTag tag) { if (m_File != null) { throw new ApplicationException("attempted to remove a table from a file-based OTFont object"); } if (GetDirectoryEntry(tag) == null) { throw new ArgumentException("the specified table doesn't doesn't exist in the font"); } // remove the directory entry for (int i = 0; i < m_OffsetTable.DirectoryEntries.Count; i++) { DirectoryEntry de = (DirectoryEntry)m_OffsetTable.DirectoryEntries[i]; if (tag == de.tag) { m_OffsetTable.DirectoryEntries.RemoveAt(i); m_OffsetTable.numTables--; break; } } // remove the table from the list of tables in memory for (int i = 0; i < MemBasedTables.Count; i++) { OTTable t = (OTTable)MemBasedTables[i]; if (tag == t.m_tag) { MemBasedTables.RemoveAt(i); break; } } string sTable = (string)tag; if (sTable == "CFF ") { m_OutlineType = OutlineType.OUTLINE_INVALID; } else if (sTable == "glyf") { m_OutlineType = OutlineType.OUTLINE_INVALID; } }
/// <summary>Return the first table with tag == <c>tag</c> /// or null if there is no such table. /// </summary> public OTTable GetTable(OTTag tag) { OTTable table = null; // find the directory entry in this font that matches the tag DirectoryEntry de = GetDirectoryEntry(tag); if (de != null) { table = GetTable(de); } return(table); }
/************************ * protected methods */ protected OTTable GetTableFromCache(DirectoryEntry de) { OTTable ot = null; for (int i = 0; i < CachedTables.Count; i++) { OTTable temp = (OTTable)CachedTables[i]; if (temp.MatchFileOffsetLength(de.offset, de.length)) { ot = temp; break; } } return(ot); }
public uint GetNumPadBytesAfterTable(OTTable t) { long TableFilePos = t.GetBuffer().GetFilePos(); if (TableFilePos == -1) { // the table's file position is initialized to -1 if the table was not read from a file throw new ApplicationException("invalid file position"); } uint TableLength = t.GetBuffer().GetLength(); long PadFilePos = TableFilePos + TableLength; long NextTablePos = m_fs.Length; // possible DSIG in TTC after all the tables if (IsCollection() && m_ttch.DsigTag != null && (string)m_ttch.DsigTag == "DSIG" && m_ttch.DsigOffset > 0 && m_ttch.DsigOffset < NextTablePos && (string)t.m_tag != "DSIG") { NextTablePos = m_ttch.DsigOffset; } for (uint iFont = 0; iFont < m_nFonts; iFont++) { if (IsCollection()) { uint offset = (uint)m_ttch.DirectoryOffsets[(int)iFont]; if (offset >= PadFilePos && offset < NextTablePos) { NextTablePos = offset; } } OTFont f = GetFont(iFont); for (ushort iTable = 0; iTable < f.GetNumTables(); iTable++) { DirectoryEntry de = f.GetDirectoryEntry(iTable); if (de.offset >= PadFilePos && de.offset < NextTablePos) { NextTablePos = de.offset; } } } return((uint)(NextTablePos - PadFilePos)); }
/// <summary>Add a new table to an non-file based table. Table cannot /// already exist in the font. /// </summary> public void AddTable(OTTable t) { if (m_File != null) { throw new ApplicationException("attempted to add a table to a file-based OTFont object"); } if (GetDirectoryEntry(t.m_tag) != null) { throw new ArgumentException("the specified table already exists in the font"); } // build a new directory entry DirectoryEntry de = new DirectoryEntry(); de.tag = new OTTag(t.m_tag.GetBytes()); de.checkSum = t.CalcChecksum(); de.offset = 0; // this value won't get fixed up until the font is written de.length = t.GetLength(); // add the directory entry m_OffsetTable.DirectoryEntries.Add(de); m_OffsetTable.numTables++; // add the table to the list of tables in memory MemBasedTables.Add(t); // special handling for certain tables string sTable = (string)t.m_tag; if (sTable == "CFF ") { m_OutlineType = OutlineType.OUTLINE_POSTSCRIPT; } else if (sTable == "glyf") { m_OutlineType = OutlineType.OUTLINE_TRUETYPE; } }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; // check for data overlap bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetLigature, CalcLength(), v, sIdentity, table.GetTag()); // check the component array length if (m_offsetLigature + (uint)FieldOffsets.ComponentGlyphIDs + (CompCount-1)*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", Component array"); bRet = false; } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; sIdentity += "(ExtensionSubst)"; // check for data overlap bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetExtensionSubst, CalcLength(), v, sIdentity, table.GetTag()); // check the SubstFormat if (SubstFormat != 1) { v.Error(T.T_NULL, E.GSUB_E_SubtableFormat, table.m_tag, sIdentity + ", SubstFormat = " + SubstFormat); bRet = false; } // check the ExtensionLookupType if (ExtensionLookupType >= 7) { v.Error(T.T_NULL, E.GSUB_E_ExtensionLookupType, table.m_tag, sIdentity + ", ExtensionLookupType = " + ExtensionLookupType); bRet = false; } // check the ExtensionOffset if (m_offsetExtensionSubst + ExtensionOffset > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", ExtensionOffset"); bRet = false; } if (bRet) { v.Pass(T.T_NULL, P.GSUB_P_ExtensionSubst, table.m_tag, sIdentity); } // validate the subtable SubTable st = null; switch (ExtensionLookupType) { case 1: st = new val_GSUB.SingleSubst_val (m_offsetExtensionSubst + ExtensionOffset, m_bufTable); break; case 2: st = new val_GSUB.MultipleSubst_val (m_offsetExtensionSubst + ExtensionOffset, m_bufTable); break; case 3: st = new val_GSUB.AlternateSubst_val (m_offsetExtensionSubst + ExtensionOffset, m_bufTable); break; case 4: st = new val_GSUB.LigatureSubst_val (m_offsetExtensionSubst + ExtensionOffset, m_bufTable); break; case 5: st = new val_GSUB.ContextSubst_val (m_offsetExtensionSubst + ExtensionOffset, m_bufTable); break; case 6: st = new val_GSUB.ChainContextSubst_val(m_offsetExtensionSubst + ExtensionOffset, m_bufTable); break; } if (st != null) { I_OTLValidate iv = (I_OTLValidate)st; iv.Validate(v, sIdentity, table); } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; bool bScriptTableOk = true; // check the DefaultLangSys offset if (DefaultLangSysOffset != 0) { if (m_offsetScriptTable + DefaultLangSysOffset > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_ScriptTable_E_DefaultLangSysOffset, table.m_tag, sIdentity); bScriptTableOk = false; bRet = false; } else { // check the DefaultLangSys table LangSysTable_val lst = GetDefaultLangSysTable_val(); bRet &= lst.Validate(v, sIdentity + ", DefaultLangSysTable", table); } } // check the LansgSysRecord array length if (m_offsetScriptTable + (uint)FieldOffsets.LangSysRecord + LangSysCount * 6 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_ScriptTable_E_LangSysRecordArray_pastEOT, table.m_tag, sIdentity); bScriptTableOk = false; bRet = false; } // check that the LangSysRecord array is sorted alphabetically if (LangSysCount > 1) { for (uint i=0; i<LangSysCount-1; i++) { LangSysRecord ThisLsr = GetLangSysRecord(i); LangSysRecord NextLsr = GetLangSysRecord(i+1); if (ThisLsr.LangSysTag >= NextLsr.LangSysTag) { v.Error(T.T_NULL, E._OTL_ScriptTable_E_LangSysRecordArray_order, table.m_tag, sIdentity); bScriptTableOk = false; bRet = false; } } } // check each LangSysRecord for (uint i=0; i<LangSysCount; i++) { LangSysRecord lsr = GetLangSysRecord(i); // check the tag if (!lsr.LangSysTag.IsValid()) { v.Error(T.T_NULL, E._OTL_ScriptTable_E_LangSysRecord_tag, table.m_tag, sIdentity + ", LangSysRecord[" + i + "]"); bScriptTableOk = false; bRet = false; } // check the offset if (m_offsetScriptTable + lsr.LangSysOffset > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_ScriptTable_E_LangSysRecord_offset, table.m_tag, sIdentity + ", LangSysRecord[" + i + "]"); bScriptTableOk = false; bRet = false; } // validate the langsys table LangSysTable_val lst = GetLangSysTable_val(lsr); bRet &= lst.Validate(v, sIdentity + ", LangSysRecord[" + i + "], LangSysTable", table); } if (bScriptTableOk) { v.Pass(T.T_NULL, P._OTL_ScriptTable_P_valid, table.m_tag, sIdentity); } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; // check that ClassRangeRecord array doesn't extend past end of table if (m_offsetClassDefFormat2 + (uint)FieldOffsets.ClassRangeRecordArray + ClassRangeCount*6 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_ClassDefinitionTable_E_RangeRecordArrayPastEOT, table.m_tag, sIdentity); bRet = false; } // check that ClassRangeRecord array is in sorted order if (ClassRangeCount > 1) { for (uint i=0; i<ClassRangeCount-1; i++) { ClassRangeRecord ThisCrr = GetClassRangeRecord(i); ClassRangeRecord NextCrr = GetClassRangeRecord(i+1); if (ThisCrr.Start >= NextCrr.Start) { v.Error(T.T_NULL, E._OTL_ClassDefinitionTable_E_RangeRecordArray_order, table.m_tag, sIdentity); bRet = false; // temporary debug code /* v.DebugMsg("ClassRangeCount = " + ClassRangeCount, tag); for (uint j=0; j<ClassRangeCount; j++) { ClassRangeRecord crr = GetClassRangeRecord(j); v.DebugMsg("ClassRangeRecord[" + j + "].Start = " + crr.Start, tag); } */ break; } } } return bRet; }
/// <summary>Write a TTC (TT Collection) to a disk file.</summary> public static bool WriteTTCFile(FileStream fs, OTFont[] fonts) { bool bRet = true; // build the TTC header OTTag TTCtag = (OTTag)"ttcf"; uint version = 0x00020000; uint DirectoryCount = (uint)fonts.Length; uint [] TableDirectory = new uint[fonts.Length]; uint ulDsigTag = 0; uint ulDsigLength = 0; uint ulDsigOffset = 0; uint TTCHeaderLen = 12 + DirectoryCount * 4 + 12; // length of version 2.0 header // build an array of offset tables OffsetTable[] otArr = new OffsetTable[fonts.Length]; for (int iFont = 0; iFont < fonts.Length; iFont++) { otArr[iFont] = new OffsetTable(new OTFixed(1, 0), fonts[iFont].GetNumTables()); } // build an array of head tables that will contain the updated modified field and font checksum Table_head[] arrHeadTables = new Table_head[fonts.Length]; for (int i = 0; i < fonts.Length; i++) { // get the cache Table_head headTable = (Table_head)fonts[i].GetTable("head"); Table_head.head_cache headCache = (Table_head.head_cache)headTable.GetCache(); // set the 'modified' field to the current date DateTime dt = DateTime.Now; headCache.modified = headTable.DateTimeToSecondsSince1904(dt); // generate a new table and add it to the array Table_head newHead = (Table_head)headCache.GenerateTable(); arrHeadTables[i] = newHead; } // build a list of directory entries for each font long FilePos = TTCHeaderLen; for (int iFont = 0; iFont < fonts.Length; iFont++) { ushort numTables = fonts[iFont].GetNumTables(); TableDirectory[iFont] = (uint)FilePos; FilePos += 12 + numTables * 16; uint PrevFilePos = 0; for (ushort i = 0; i < numTables; i++) { OTTable table = fonts[iFont].GetTable(i); OTTag tag = table.m_tag; if ((string)tag == "head") { table = arrHeadTables[iFont]; } // check if this table is a duplicate of a table in a previous font PrevFilePos = 0; if (iFont > 0) { for (int iPrevFont = 0; iPrevFont < iFont; iPrevFont++) { for (int iTable = 0; iTable < fonts[iPrevFont].GetNumTables(); iTable++) { OTTable PrevTable = fonts[iPrevFont].GetTable(table.m_tag); if (PrevTable != null) { if (MBOBuffer.BinaryEqual(table.m_bufTable, PrevTable.m_bufTable)) { // get the file position for the previous table for (int iDe = 0; iDe < otArr[iPrevFont].DirectoryEntries.Count; iDe++) { DirectoryEntry dePrev = (DirectoryEntry)otArr[iPrevFont].DirectoryEntries[iDe]; if (dePrev.tag == table.m_tag) { PrevFilePos = dePrev.offset; break; } } } } } } } // build a new directory entry DirectoryEntry de = new DirectoryEntry(); de.tag = new OTTag(tag.GetBytes()); de.checkSum = table.CalcChecksum(); de.length = table.GetLength(); if (PrevFilePos != 0) { de.offset = (uint)PrevFilePos; } else { de.offset = (uint)FilePos; FilePos += table.GetBuffer().GetPaddedLength(); } otArr[iFont].DirectoryEntries.Add(de); } // sort the directory entries if (numTables > 1) { for (int i = 0; i < numTables - 1; i++) { for (int j = i + 1; j < numTables; j++) { if (((DirectoryEntry)otArr[iFont].DirectoryEntries[i]).tag > ((DirectoryEntry)otArr[iFont].DirectoryEntries[j]).tag) { DirectoryEntry temp = (DirectoryEntry)otArr[iFont].DirectoryEntries[i]; otArr[iFont].DirectoryEntries[i] = (DirectoryEntry)otArr[iFont].DirectoryEntries[j]; otArr[iFont].DirectoryEntries[j] = temp; } } } } } // update each font's checksum in the head table for (int iFont = 0; iFont < fonts.Length; iFont++) { ushort numTables = fonts[iFont].GetNumTables(); // calculate the checksum uint sum = 0; sum += otArr[iFont].CalcOffsetTableChecksum(); sum += otArr[iFont].CalcDirectoryEntriesChecksum(); for (ushort i = 0; i < numTables; i++) { DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i]; OTTable table = fonts[iFont].GetTable(de.tag); if ((string)de.tag == "head") { table = arrHeadTables[iFont]; } sum += table.CalcChecksum(); } // get the cache Table_head headTable = arrHeadTables[iFont]; Table_head.head_cache headCache = (Table_head.head_cache)headTable.GetCache(); // set the checkSumAdujustment field headCache.checkSumAdjustment = 0xb1b0afba - sum; // generate a new table and replace the head table in the array of head tables Table_head newHead = (Table_head)headCache.GenerateTable(); arrHeadTables[iFont] = newHead; } // write the TTC header WriteUint32MBO(fs, (uint)TTCtag); WriteUint32MBO(fs, version); WriteUint32MBO(fs, DirectoryCount); for (int i = 0; i < fonts.Length; i++) { WriteUint32MBO(fs, TableDirectory[i]); } WriteUint32MBO(fs, ulDsigTag); WriteUint32MBO(fs, ulDsigLength); WriteUint32MBO(fs, ulDsigOffset); // write out each font for (int iFont = 0; iFont < fonts.Length; iFont++) { ushort numTables = fonts[iFont].GetNumTables(); // write the offset table fs.Write(otArr[iFont].m_buf.GetBuffer(), 0, (int)otArr[iFont].m_buf.GetLength()); // write the directory entries for (int i = 0; i < numTables; i++) { DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i]; fs.Write(de.m_buf.GetBuffer(), 0, (int)de.m_buf.GetLength()); } // write out each table unless a shared version has been written for (ushort i = 0; i < numTables; i++) { DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i]; if (fs.Position == de.offset) { OTTable table = fonts[iFont].GetTable(de.tag); if ((string)table.m_tag == "head") { table = arrHeadTables[iFont]; } fs.Write(table.m_bufTable.GetBuffer(), 0, (int)table.GetBuffer().GetPaddedLength()); } } } return(bRet); }
/// <summary>Write a single OTF to a disk file, with tables in /// proper order, checksums set, etc. /// </summary> public static bool WriteSfntFile(FileStream fs, OTFont font) { bool bRet = true; OTFixed sfntVersion = new OTFixed(1, 0); ushort numTables = font.GetNumTables(); OffsetTable ot = new OffsetTable(sfntVersion, numTables); // order tables in fastfont order string [] arrOrderedNames = null; string [] ttNames = { "head", "hhea", "maxp", "OS/2", "hmtx", "LTSH", "VDMX", "hdmx", "cmap", "fpgm", "prep", "cvt ", "loca", "glyf", "kern", "name", "post", "gasp", "PCLT" }; string [] psNames = { "head", "hhea", "maxp", "OS/2", "name", "cmap", "post", "CFF " }; if (font.ContainsTrueTypeOutlines()) { arrOrderedNames = ttNames; } else if (font.ContainsPostScriptOutlines()) { arrOrderedNames = psNames; } OTTable[] OrderedTables = new OTTable[numTables]; for (ushort i = 0; i < numTables; i++) { OrderedTables[i] = font.GetTable(i); } if (arrOrderedNames != null) { ushort curpos = 0; for (int iName = 0; iName < arrOrderedNames.Length; iName++) { for (ushort i = curpos; i < numTables; i++) { if (arrOrderedNames[iName] == (string)OrderedTables[i].m_tag) { OTTable temp = OrderedTables[curpos]; OrderedTables[curpos] = OrderedTables[i]; OrderedTables[i] = temp; curpos++; break; } } } } // update the modified date in the head table for (int i = 0; i < OrderedTables.Length; i++) { if ((string)OrderedTables[i].m_tag == "head") { // get the cache Table_head headTable = (Table_head)OrderedTables[i]; Table_head.head_cache headCache = (Table_head.head_cache)headTable.GetCache(); // set the 'modified' field to the current date and time DateTime dt = DateTime.Now; headCache.modified = headTable.DateTimeToSecondsSince1904(dt); // generate a new table and replace the head table in the list of ordered tables Table_head newHead = (Table_head)headCache.GenerateTable(); OrderedTables[i] = newHead; break; } } // build a list of directory entries long TableFilePos = 12 + numTables * 16; for (ushort i = 0; i < numTables; i++) { OTTable table = OrderedTables[i]; OTTag tag = table.m_tag; // build a new directory entry DirectoryEntry de = new DirectoryEntry(); de.tag = new OTTag(tag.GetBytes()); de.checkSum = table.CalcChecksum(); de.offset = (uint)TableFilePos; de.length = table.GetLength(); ot.DirectoryEntries.Add(de); TableFilePos += table.GetBuffer().GetPaddedLength(); } // sort the directory entries if (numTables > 1) { for (int i = 0; i < numTables - 1; i++) { for (int j = i + 1; j < numTables; j++) { if (((DirectoryEntry)(ot.DirectoryEntries[i])).tag > ((DirectoryEntry)(ot.DirectoryEntries[j])).tag) { DirectoryEntry temp = (DirectoryEntry)ot.DirectoryEntries[i]; ot.DirectoryEntries[i] = (DirectoryEntry)ot.DirectoryEntries[j]; ot.DirectoryEntries[j] = temp; } } } } // update the font checksum in the head table for (int i = 0; i < OrderedTables.Length; i++) { if ((string)OrderedTables[i].m_tag == "head") { // calculate the checksum uint sum = 0; sum += ot.CalcOffsetTableChecksum(); sum += ot.CalcDirectoryEntriesChecksum(); for (int j = 0; j < OrderedTables.Length; j++) { sum += OrderedTables[j].CalcChecksum(); } // get the cache Table_head headTable = (Table_head)OrderedTables[i]; Table_head.head_cache headCache = (Table_head.head_cache)headTable.GetCache(); // set the checkSumAdujustment field headCache.checkSumAdjustment = 0xb1b0afba - sum; // generate a new table and replace the head table in the list of ordered tables Table_head newHead = (Table_head)headCache.GenerateTable(); OrderedTables[i] = newHead; break; } } // write the offset table fs.Write(ot.m_buf.GetBuffer(), 0, (int)ot.m_buf.GetLength()); // write the directory entries for (int i = 0; i < numTables; i++) { DirectoryEntry de = (DirectoryEntry)ot.DirectoryEntries[i]; fs.Write(de.m_buf.GetBuffer(), 0, (int)de.m_buf.GetLength()); } // write the tables for (ushort i = 0; i < numTables; i++) { OTTable table = OrderedTables[i]; fs.Write(table.m_bufTable.GetBuffer(), 0, (int)table.GetBuffer().GetPaddedLength()); } return(bRet); }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; // check for data overlap bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetSubClassSet, CalcLength(), v, sIdentity, table.GetTag()); // check the SubClassRule array length if (m_offsetSubClassSet + (uint)FieldOffsets.SubClassRuleOffsets + SubClassRuleCount*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", SubClassRule array"); bRet = false; } // check each SubClassRule offset for (uint i=0; i<SubClassRuleCount; i++) { if (m_offsetSubClassSet + GetSubClassRuleOffset(i) > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", SubClassRule[" + i + "]"); bRet = false; } } // check each SubClassRule table for (uint i=0; i<SubClassRuleCount; i++) { SubClassRule_val scr = GetSubClassRuleTable_val(i); bRet &= scr.Validate(v, sIdentity + ", SubClassRule[" + i + "]", table); } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; // check for data overlap bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetContextSubst, CalcLength(), v, sIdentity, table.GetTag()); // check the coverage offset if (m_offsetContextSubst + CoverageOffset > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", Coverage offset"); bRet = false; } // check the coverage table CoverageTable_val ct = GetCoverageTable_val(); bRet &= ct.Validate(v, sIdentity + ", Coverage", table); // check the ClassDef offset if (m_offsetContextSubst + ClassDefOffset > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", ClassDef offset"); bRet = false; } // check the ClassDef table ClassDefTable_val cdt = GetClassDefTable_val(); bRet &= cdt.Validate(v, sIdentity + ", ClassDef", table); // check the SubClassSet array length if (m_offsetContextSubst + (uint)FieldOffsets.SubClassSetOffsets + SubClassSetCount*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", SubClassSet array"); bRet = false; } // check each SubClassSet offset for (uint i=0; i<SubClassSetCount; i++) { if (m_offsetContextSubst + GetSubClassSetOffset(i) > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", SubClassSet[" + i + "]"); bRet = false; } } // check each SubClassSet table for (uint i=0; i<SubClassSetCount; i++) { if (GetSubClassSetOffset(i) != 0) { SubClassSet_val scs = GetSubClassSetTable_val(i); if (scs != null) { bRet &= scs.Validate(v, sIdentity + ", SubClassSet[" + i + "]", table); } } } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; // check for data overlap bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetSubRule, CalcLength(), v, sIdentity, table.GetTag()); // check the Input array length if (m_offsetSubRule + (uint)FieldOffsets.InputGlyphIds + (GlyphCount-1)*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", Input array"); bRet = false; } // check the SubstLookupRecord array length uint offset = m_offsetSubRule + (uint)FieldOffsets.InputGlyphIds + (uint)(GlyphCount-1)*2; if (offset + SubstCount*4 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", SubstLookupRecord array"); bRet = false; } // check each SubstLookupRecord for (uint i=0; i<SubstCount; i++) { SubstLookupRecord slr = GetSubstLookupRecord(i); if (slr.SequenceIndex > GlyphCount) { string sValues = ", slr.SequenceIndex = " + slr.SequenceIndex + ", slr.LookupListIndex = " + slr.LookupListIndex + ", GlyphCount = " + GlyphCount; v.Error(T.T_NULL, E.GSUB_E_SubstLookupRecord_SequenceIndex, table.m_tag, sIdentity + ", SubstLookupRecord[" + i + "]" + sValues); bRet = false; } } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; sIdentity += "(ContextSubst, fmt " + SubstFormat + ")"; if (SubstFormat == 1) { ContextSubstFormat1_val f1 = GetContextSubstFormat1_val(); bRet &= f1.Validate(v, sIdentity, table); } else if (SubstFormat == 2) { ContextSubstFormat2_val f2 = GetContextSubstFormat2_val(); bRet &= f2.Validate(v, sIdentity, table); } else if (SubstFormat == 3) { ContextSubstFormat3_val f3 = GetContextSubstFormat3_val(); bRet &= f3.Validate(v, sIdentity, table); } else { v.Error(T.T_NULL, E.GSUB_E_SubtableFormat, table.m_tag, sIdentity); bRet = false; } if (bRet) { v.Pass(T.T_NULL, P.GSUB_P_ContextSubst, table.m_tag, sIdentity); } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; if (ClassFormat == 1) { ClassDefFormat1_val cdf1 = GetClassDefFormat1_val(); bRet &= cdf1.Validate(v, sIdentity + "(Fmt1)", table); } else if (ClassFormat == 2) { ClassDefFormat2_val cdf2 = GetClassDefFormat2_val(); bRet &= cdf2.Validate(v, sIdentity + "(Fmt2)", table); } else { v.Error(T.T_NULL, E._OTL_ClassDefinitionTable_E_Format, table.m_tag, sIdentity + ", format = " + ClassFormat.ToString()); bRet = false; } // way too many ClassDefTables to justify this pass message //if (bRet) //{ // v.Pass("_OTL_ClassDefinitionTable_P_valid", table.m_tag, sIdentity); //} return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; if (m_offsetClassDefFormat1 + (uint)FieldOffsets.ClassValueArray + GlyphCount*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_ClassDefinitionTable_E_GlyphArrayPastEOT, table.m_tag, sIdentity); bRet = false; } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; bool bScriptListOk = true; // check that ScriptRecord array doesn't extend past end of table if (m_offsetScriptListTable + (uint)FieldOffsets.ScriptRecords + 6*ScriptCount > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_ScriptListTable_E_ScriptRecordArray_pastEOT, table.m_tag, sIdentity); bScriptListOk = false; bRet = false; } // check that ScriptRecord array is in alphabetical order if (ScriptCount > 1) { for (uint i=0; i<ScriptCount-1; i++) { ScriptRecord srCurr = GetScriptRecord(i); ScriptRecord srNext = GetScriptRecord(i+1); if (srCurr.ScriptTag >= srNext.ScriptTag) { v.Error(T.T_NULL, E._OTL_ScriptListTable_E_ScriptRecordArray_order, table.m_tag, sIdentity); bScriptListOk = false; bRet = false; } } } // check each ScriptRecord for (uint i=0; i<ScriptCount; i++) { // check the tag ScriptRecord sr = GetScriptRecord(i); if (!sr.ScriptTag.IsValid()) { v.Error(T.T_NULL, E._OTL_ScriptListTable_E_ScriptRecord_tag, table.m_tag, sIdentity + ", ScriptRecord[" + i + "]"); bScriptListOk = false; bRet = false; } // check the offset if (m_offsetScriptListTable + sr.ScriptTableOffset > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_ScriptListTable_E_ScriptRecord_offset, table.m_tag, sIdentity + ", ScriptRecord[" + i + "]"); bScriptListOk = false; bRet = false; } // validate the ScriptTable ScriptTable_val st = GetScriptTable_val(sr); bRet &= st.Validate(v, sIdentity + ", ScriptRecord[" + i + "](" + sr.ScriptTag + "), ScriptTable", table); } if (bScriptListOk) { v.Pass(T.T_NULL, P._OTL_ScriptListTable_P_valid, table.m_tag, sIdentity); } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; // check StartSize for unreasonable values if (StartSize > 16384) { v.Warning(T.T_NULL, W._OTL_DeviceTable_W_StartSize, table.m_tag, sIdentity + ", StartSize = " + StartSize); } // check EndSize for unreasonable values if (EndSize > 16384) { v.Warning(T.T_NULL, W._OTL_DeviceTable_W_EndSize, table.m_tag, sIdentity + ", EndSize = " + EndSize); } // check that StartSize <= EndSize if (StartSize > EndSize) { v.Error(T.T_NULL, E._OTL_DeviceTable_E_sizes, table.m_tag, sIdentity); bRet = false; } // check DeltaFormat is 1, 2, or 3 if (DeltaFormat < 1 || DeltaFormat > 3) { v.Error(T.T_NULL, E._OTL_DeviceTable_E_DeltaFormat, table.m_tag, sIdentity + ", DeltaFormat = " + DeltaFormat); bRet = false; } else { // check that DeltaValue array doesn't extend past the end of the table int nSizes = EndSize - StartSize + 1; int nValuesPerUint = 16 >> DeltaFormat; int nUints = nSizes / nValuesPerUint; if (nSizes % nValuesPerUint != 0) nUints++; if (m_offsetDeviceTable + (uint)FieldOffsets.DeltaValueArray + nUints > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_DeviceTable_E_DeltaValueArray_pastEOT, table.m_tag, sIdentity); bRet = false; } } // way too many device tables to justify this pass message //if (bRet) //{ // v.Pass("_OTL_DeviceTable_P_valid", table.m_tag, sIdentity); //} return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; if (LookupOrder != 0) { v.Error(T.T_NULL, E._OTL_LangSysTable_E_LookupOrder, table.m_tag, sIdentity); bRet = false; } if (m_offsetLangSysTable + (uint)FieldOffsets.FeatureIndexArray + FeatureCount*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_LangSysTable_E_FeatureIndexArray_pastEOT, table.m_tag, sIdentity); bRet = false; } if (bRet) { v.Pass(T.T_NULL, P._OTL_LangSysTable_P_valid, table.m_tag, sIdentity); } return bRet; }
public virtual OTTable CreateTableObject(OTTag tag, MBOBuffer buf) { OTTable table = null; string sName = GetUnaliasedTableName(tag); switch (sName) { case "BASE": table = new Table_BASE(tag, buf); break; case "CFF ": table = new Table_CFF(tag, buf); break; case "cmap": table = new Table_cmap(tag, buf); break; case "cvt ": table = new Table_cvt(tag, buf); break; case "DSIG": table = new Table_DSIG(tag, buf); break; case "EBDT": table = new Table_EBDT(tag, buf); break; case "EBLC": table = new Table_EBLC(tag, buf); break; case "EBSC": table = new Table_EBSC(tag, buf); break; case "fpgm": table = new Table_fpgm(tag, buf); break; case "gasp": table = new Table_gasp(tag, buf); break; case "GDEF": table = new Table_GDEF(tag, buf); break; case "glyf": table = new Table_glyf(tag, buf); break; case "GPOS": table = new Table_GPOS(tag, buf); break; case "GSUB": table = new Table_GSUB(tag, buf); break; case "hdmx": table = new Table_hdmx(tag, buf); break; case "head": table = new Table_head(tag, buf); break; case "hhea": table = new Table_hhea(tag, buf); break; case "hmtx": table = new Table_hmtx(tag, buf); break; case "JSTF": table = new Table_JSTF(tag, buf); break; case "kern": table = new Table_kern(tag, buf); break; case "loca": table = new Table_loca(tag, buf); break; case "LTSH": table = new Table_LTSH(tag, buf); break; case "maxp": table = new Table_maxp(tag, buf); break; case "name": table = new Table_name(tag, buf); break; case "OS/2": table = new Table_OS2(tag, buf); break; case "PCLT": table = new Table_PCLT(tag, buf); break; case "post": table = new Table_post(tag, buf); break; case "prep": table = new Table_prep(tag, buf); break; case "VDMX": table = new Table_VDMX(tag, buf); break; case "vhea": table = new Table_vhea(tag, buf); break; case "vmtx": table = new Table_vmtx(tag, buf); break; case "VORG": table = new Table_VORG(tag, buf); break; //case "Zapf": table = new Table_Zapf(tag, buf); break; default: table = new Table__Unknown(tag, buf); break; } return(table); }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; bool bFeatureListOk = true; // check the FeatureRecord array length if (m_offsetFeatureListTable + (uint)FieldOffsets.FeatureRecordArray + FeatureCount*6 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_FeatureListTable_E_FeatureRecordArray_pastEOT, table.m_tag, sIdentity); bFeatureListOk = false; bRet = false; } // check that the FeatureRecord array is sorted alphabetically if (FeatureCount > 1) { for (uint i=0; i<FeatureCount-1; i++) { FeatureRecord frCurr = GetFeatureRecord(i); FeatureRecord frNext = GetFeatureRecord(i+1); if (frCurr.FeatureTag > frNext.FeatureTag) { v.Error(T.T_NULL, E._OTL_FeatureListTable_E_FeatureRecordArray_order, table.m_tag, sIdentity); bFeatureListOk = false; bRet = false; break; } } } // check each FeatureRecord for (uint i=0; i<FeatureCount; i++) { FeatureRecord fr = GetFeatureRecord(i); if (fr != null) { // check tag if (!fr.FeatureTag.IsValid()) { v.Error(T.T_NULL, E._OTL_FeatureListTable_E_FeatureRecord_tag, table.m_tag, sIdentity + ", FeatureRecord[" + i + "]"); bFeatureListOk = false; bRet = false; } else if (!IsKnownFeatureTag(fr.FeatureTag)) { v.Warning(T.T_NULL, W._OTL_FeatureListTable_W_FeatureRecord_tag, table.m_tag, sIdentity + ", FeatureRecord[" + i + "], tag = '" + fr.FeatureTag + "'"); } // check offset if (m_offsetFeatureListTable + fr.FeatureTableOffset > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_FeatureListTable_E_FeatureRecord_offset, table.m_tag, sIdentity + ", FeatureRecord[" + i + "]"); bFeatureListOk = false; bRet = false; } else { // validate the feature table FeatureTable_val ft = GetFeatureTable_val(fr); bRet &= ft.Validate(v, sIdentity + ", FeatureRecord[" + i + "]" + "(" + (string)fr.FeatureTag + ")" + ", FeatureTable", table); } } else { bFeatureListOk = false; bRet = false; } } if (bFeatureListOk) { v.Pass(T.T_NULL, P._OTL_FeatureListTable_P_valid, table.m_tag, sIdentity); } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; // check for data overlap bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetSingleSubst, CalcLength(), v, sIdentity, table.GetTag()); // check the coverage offset if (m_offsetSingleSubst + CoverageOffset > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", Coverage offset"); bRet = false; } // check the coverage table CoverageTable_val ct = GetCoverageTable_val(); bRet &= ct.Validate(v, sIdentity + ", Coverage", table); // check the Substitute array length if (m_offsetSingleSubst + (uint)FieldOffsets.SubstituteGlyphIDs + GlyphCount*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", Substitute array"); bRet = false; } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; // check for data overlap bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetAlternateSet, CalcLength(), v, sIdentity, table.GetTag()); // check the alternate array length if (m_offsetAlternateSet + (uint)FieldOffsets.AlternateGlyphIDs + GlyphCount*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", Alternate array"); bRet = false; } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; sIdentity += "(ReverseChainSubst)"; // check for data overlap bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetReverseChainSubst, CalcLength(), v, sIdentity, table.GetTag()); // check the SubstFormat if (SubstFormat != 1) { v.Error(T.T_NULL, E.GSUB_E_SubtableFormat, table.m_tag, sIdentity + ", SubstFormat = " + SubstFormat); bRet = false; } // check the coverage offset if (m_offsetReverseChainSubst + CoverageOffset > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", Coverage offset"); bRet = false; } // check the coverage table CoverageTable_val ct = GetCoverageTable_val(); bRet &= ct.Validate(v, sIdentity + ", Coverage table", table); // check the BacktrackCoverage array length uint offset = m_offsetReverseChainSubst + (uint)FieldOffsets.BacktrackCoverageOffsets; if (offset + BacktrackGlyphCount*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", BacktrackCoverage array"); bRet = false; } // check each BacktrackCoverage offset for (uint i=0; i<BacktrackGlyphCount; i++) { if (m_offsetReverseChainSubst + GetBacktrackCoverageOffset(i) > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", BacktrackCoverage[" + i + "]"); bRet = false; } } // check each BacktrackCoverage table for (uint i=0; i<BacktrackGlyphCount; i++) { CoverageTable_val bct = GetBacktrackCoverageTable_val(i); bRet &= bct.Validate(v, sIdentity + ", BacktrackCoverage[" + i + "]", table); } // check the LookaheadCoverage array length offset = m_offsetReverseChainSubst + (uint)FieldOffsets.BacktrackCoverageOffsets + (uint)BacktrackGlyphCount*2 + 2; if (offset + LookaheadGlyphCount*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", LookaheadCoverage array"); bRet = false; } // check each LookaheadCoverage offset for (uint i=0; i<LookaheadGlyphCount; i++) { if (m_offsetReverseChainSubst + GetLookaheadCoverageOffset(i) > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", LookaheadCoverage[" + i + "]"); bRet = false; } } // check each LookaheadCoverage table for (uint i=0; i<LookaheadGlyphCount; i++) { CoverageTable_val lct = GetLookaheadCoverageTable_val(i); bRet &= lct.Validate(v, sIdentity + ", LookaheadCoverage[" + i + "]", table); } // check the SubstituteGlyphIDs array length offset = m_offsetReverseChainSubst + (uint)FieldOffsets.BacktrackCoverageOffsets + (uint)BacktrackGlyphCount*2 + 2 + (uint)LookaheadGlyphCount*2 + 2; if (offset + SubstituteGlyphCount*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", Substitue Glyph ID array"); bRet = false; } if (bRet) { v.Pass(T.T_NULL, P.GSUB_P_ReverseChainContextSubst, table.m_tag, sIdentity); } return bRet; }
public bool Validate( Validator v, OTTable table, ushort numGlyphs, String sIdentity ) { bool bRet = true; m_v = v; m_table = table; m_sIdentity = sIdentity; m_numGlyphs = numGlyphs; List<VarSelectorRecord> recs = new List<VarSelectorRecord>(); // Find the offset of the start of the Default and // Non-Default UVS tables to make sure that // everything the offsets point to is within the table // area. const uint f14HeaderLength = 10; // USHORT, ULONG, ULONG const uint varSelRecLength = 11; // UINT24, ULONG, ULONG uint dataStart = f14HeaderLength + ( NumVarSelectorRecs * varSelRecLength ); // Fill in recs while we are at it. bool bLengthsOk = CheckLengths( dataStart, recs ); bRet = bLengthsOk; if ( !bLengthsOk ) { string unable = "Unable to perform more tests"; // Is the 2nd arg correct? v.Warning( T.T_NULL, W._TEST_W_OtherErrorsInTable, m_table.m_tag, unable + SDetails() ); goto Finish; } // We now know that all the tables are within the data area, // that is, from dataStart to the end of the subtable. Now // we about overlapping and non-packed tables. bool bOverlapsOk = CheckOverlaps( dataStart, recs ); if ( !bOverlapsOk ) { bRet = false; string unable = "Unable to perform more tests"; // Is the 2nd arg correct? v.Warning( T.T_NULL, W._TEST_W_OtherErrorsInTable, m_table.m_tag, unable + SDetails() ); goto Finish; } // Check that all values in offset tables are legal bRet = CheckLegalValues( recs ); Finish: return bRet; }
public bool Validate(Validator v, OTTable table, ushort numGlyphs, String sIdentity) { bool bRet = true; // check the mapping byte [] charbuf = new byte[2]; for (uint i = 0; i<=65535; i++) { char c = (char)i; charbuf[0] = (byte)c; charbuf[1] = (byte)(c>>8); uint nGlyphID = MapCharToGlyph(charbuf, 0); if (nGlyphID >= numGlyphs) { v.Error(T.T_NULL, E.cmap_E_Mapping, table.m_tag, sIdentity + ", char = 0x" + ((uint)c).ToString("X4") + ", glyphID = " + nGlyphID); bRet = false; } } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; // check for data overlap bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetChainContextSubst, CalcLength(), v, sIdentity, table.GetTag()); // check the BacktrackCoverage array length uint offset = m_offsetChainContextSubst + (uint)FieldOffsets.BacktrackCoverageOffsets; if (offset + BacktrackGlyphCount*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", BacktrackCoverage array"); bRet = false; } // check each BacktrackCoverage offset for (uint i=0; i<BacktrackGlyphCount; i++) { if (m_offsetChainContextSubst + GetBacktrackCoverageOffset(i) > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", BacktrackCoverage[" + i + "]"); bRet = false; } } // check each BacktrackCoverage table for (uint i=0; i<BacktrackGlyphCount; i++) { CoverageTable_val ct = GetBacktrackCoverageTable_val(i); ct.Validate(v, sIdentity + ", BacktrackCoverage[" + i + "]", table); } // check the InputCoverage array length offset = m_offsetChainContextSubst + (uint)FieldOffsets.BacktrackCoverageOffsets + (uint)BacktrackGlyphCount*2 + 2; if (offset + InputGlyphCount*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", InputCoverage array"); bRet = false; } // check each InputCoverage offset for (uint i=0; i<InputGlyphCount; i++) { if (m_offsetChainContextSubst + GetInputCoverageOffset(i) > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", InputCoverage[" + i + "]"); bRet = false; } } // check each InputCoverage table for (uint i=0; i<InputGlyphCount; i++) { CoverageTable_val ct = GetInputCoverageTable_val(i); ct.Validate(v, sIdentity + ", InputCoverage[" + i + "]", table); } // check the LookaheadCoverage array length offset = m_offsetChainContextSubst + (uint)FieldOffsets.BacktrackCoverageOffsets + (uint)BacktrackGlyphCount*2 + 2 + (uint)InputGlyphCount*2 + 2; if (offset + LookaheadGlyphCount*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", LookaheadCoverage array"); bRet = false; } // check each LookaheadCoverage offset for (uint i=0; i<LookaheadGlyphCount; i++) { if (m_offsetChainContextSubst + GetLookaheadCoverageOffset(i) > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", LookaheadCoverage[" + i + "]"); bRet = false; } } // check each LookaheadCoverage table for (uint i=0; i<LookaheadGlyphCount; i++) { CoverageTable_val ct = GetLookaheadCoverageTable_val(i); ct.Validate(v, sIdentity + ", LookaheadCoverage[" + i + "]", table); } // check the SubstLookupRecord array length offset = m_offsetChainContextSubst + (uint)FieldOffsets.BacktrackCoverageOffsets + (uint)BacktrackGlyphCount*2 + 2 + (uint)InputGlyphCount*2 + 2 + (uint)LookaheadGlyphCount*2 + 2; if (offset + SubstCount*4 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", SubstLookupRecord array"); bRet = false; } // check each SubstLookupRecord for (uint i=0; i<SubstCount; i++) { SubstLookupRecord slr = GetSubstLookupRecord(i); if (slr.SequenceIndex > InputGlyphCount) { string sValues = ", slr.SequenceIndex = " + slr.SequenceIndex + ", slr.LookupListIndex = " + slr.LookupListIndex + ", InputGlyphCount = " + InputGlyphCount; v.Error(T.T_NULL, E.GSUB_E_SubstLookupRecord_SequenceIndex, table.m_tag, sIdentity + ", SubstLookupRecord[" + i + "]" + sValues); bRet = false; } } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; // check that FeatureParams is null if (FeatureParams != 0) { v.Error(T.T_NULL, E._OTL_FeatureTable_E_FeatureParams_nonnull, table.m_tag, sIdentity); bRet = false; } // check LookupListIndex array length if (m_offsetFeatureTable + (uint)FieldOffsets.LookupListIndexArray + LookupCount * 2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_FeatureTable_E_LookupListIndexArray_pastEOT, table.m_tag, sIdentity); bRet = false; } if (bRet) { v.Pass(T.T_NULL, P._OTL_FeatureTable_P_valid, table.m_tag, sIdentity); } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; sIdentity += "(LigatureSubst, fmt " + SubstFormat + ")"; if (SubstFormat == 1) { // check for data overlap bRet &= ((val_GSUB)table).ValidateNoOverlap(m_offsetLigatureSubst, CalcLength(), v, sIdentity, table.GetTag()); // check the coverage offset if (m_offsetLigatureSubst + CoverageOffset > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", Coverage offset"); bRet = false; } // check the coverage table CoverageTable_val ct = GetCoverageTable_val(); bRet &= ct.Validate(v, sIdentity + ", Coverage", table); // check the LigatureSet array length if (m_offsetLigatureSubst + (uint)FieldOffsets.LigatureSetOffsets + LigSetCount*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Array_pastEOT, table.m_tag, sIdentity + ", LigatureSet array"); bRet = false; } // check each LigatureSet offset for (uint i=0; i<LigSetCount; i++) { if (m_offsetLigatureSubst + GetLigatureSetOffset(i) > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GSUB_E_Offset_PastEOT, table.m_tag, sIdentity + ", LigatureSet[" + i + "]"); bRet = false; } } // check each LigatureSet table for (uint i=0; i<LigSetCount; i++) { LigatureSet_val ls = GetLigatureSetTable_val(i); bRet &= ls.Validate(v, sIdentity + ", LigatureSet[" + i + "]", table); } } else { v.Error(T.T_NULL, E.GSUB_E_SubtableFormat, table.m_tag, sIdentity); bRet = false; } if (bRet) { v.Pass(T.T_NULL, P.GSUB_P_LigatureSubst, table.m_tag, sIdentity); } return bRet; }
public bool Validate(Validator v, OTTable table, ushort numGlyphs, String sIdentity) { bool bRet = true; // warn if not encoding id 10 if (m_ete.encodingID != 10) { v.Warning(T.T_NULL, W.cmap_W_f12_EncID, table.m_tag, sIdentity); } // check that groups are sorted by ascending startCharCodes if (nGroups > 1) { for (uint i=0; i<nGroups-1; i++) { Group gCurr = GetGroup(i); Group gNext = GetGroup(i+1); if (gCurr.startCharCode >= gNext.startCharCode) { v.Error(T.T_NULL, E.cmap_E_f12_SortOrder, table.m_tag, sIdentity); bRet = false; break; } } } // check each start code is less than or equal to the end code for (uint i=0; i<nGroups; i++) { Group g = GetGroup(i); if (g.startCharCode > g.endCharCode) { String sDetails = ", group[" + i + "], startCharCode = 0x" + g.startCharCode.ToString("X8") + ", endCharCode = 0x" + g.endCharCode.ToString("X8"); v.Error(T.T_NULL, E.cmap_E_f12_StartCode_GT_EndCode, table.m_tag, sIdentity + sDetails); bRet = false; } } // check the mapping for (uint i=0; i<nGroups; i++) { Group g = GetGroup(i); uint c = g.endCharCode; uint nGlyphID = g.startGlyphID + (c - g.startCharCode); if (nGlyphID >= numGlyphs) { v.Error(T.T_NULL, E.cmap_E_Mapping, table.m_tag, sIdentity + ", char = 0x" + ((uint)c).ToString("X4") + ", glyphID = " + nGlyphID); bRet = false; } } // if encoding id 10, then check that the greatest character // is not greater than 0x10ffff if (m_ete.encodingID == 10) { if (nGroups > 0) { Group lastgroup = GetGroup(nGroups-1); if (lastgroup.endCharCode > 0x10ffff) { v.Error(T.T_NULL, E.cmap_E_f12_EndCode_GT_10FFFF, table.m_tag, sIdentity + ", last endCharCode = 0x" + lastgroup.endCharCode.ToString("X8")); bRet = false; } } } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; bool bLookupListOk = true; // check that the Lookup array doesn't extend past end of table if (m_offsetLookupListTable + (uint)FieldOffsets.LookupArray + LookupCount * 2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_LookupListTable_E_LookupArray_pastEOT, table.m_tag, sIdentity); bLookupListOk = false; bRet = false; } // check that each offset is within the table for (uint i=0; i<LookupCount; i++) { if (m_offsetLookupListTable + GetLookupOffset(i) > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_LookupListTable_E_Lookup_offset, table.m_tag, sIdentity + ", Lookup[" + i + "]"); bLookupListOk = false; bRet = false; } } // validate each lookup table for (uint i=0; i<LookupCount; i++) { LookupTable_val lt = GetLookupTable_val(i); if (lt != null) { bRet &= lt.Validate(v, sIdentity + ", Lookup[" + i + "]", table); } else { bLookupListOk = false; bRet = false; } } if (bLookupListOk) { v.Pass(T.T_NULL, P._OTL_LookupListTable_P_valid, table.m_tag, sIdentity); } return bRet; }
public bool Validate(Validator v, OTTable table, ushort numGlyphs, String sIdentity) { bool bRet = true; // check the length if (length != 262) { v.Error(T.T_NULL, E.cmap_E_f0_length, table.m_tag, sIdentity); bRet = false; } // check the mapping for (char c = (char)0; c<256; c++) { ushort nGlyphID = GetGlyphID(c); if (nGlyphID >= numGlyphs) { v.Error(T.T_NULL, E.cmap_E_Mapping, table.m_tag, sIdentity + ", char = 0x" + ((uint)c).ToString("X4") + ", glyphID = " + nGlyphID); bRet = false; } } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; // check the LookupType if (((string)table.m_tag == "GPOS") && LookupType > 9 || ((string)table.m_tag == "GSUB" && LookupType > 8)) { v.Error(T.T_NULL, E._OTL_LookupTable_E_LookupType, table.m_tag, sIdentity + ", LookupType = " + LookupType); bRet = false; } // check LookupFlag reserved bits are clear if ((LookupFlag & 0x00f0) != 0) { v.Error(T.T_NULL, E._OTL_LookupTable_E_LookupFlag_reserved, table.m_tag, sIdentity); bRet = false; } // check Subtable offset array doesn't extend past end of table if (m_offsetLookupTable + (uint)FieldOffsets.SubTableOffsetArray + SubTableCount*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_LookupTable_E_SubtableArray_pastEOT, table.m_tag, sIdentity); bRet = false; } // check Subtable offsets don't point past end of table for (uint i=0; i<SubTableCount; i++) { // verify that the subtable offset is accessible, if not error was already reported if (m_offsetLookupTable + (uint)FieldOffsets.SubTableOffsetArray + i*2 + 2 <= m_bufTable.GetLength()) { if (m_offsetLookupTable + GetSubTableOffset(i) > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_LookupTable_E_SubtableArray_offset, table.m_tag, sIdentity + ", SubTable[" + i + "]"); bRet = false; } } } // way too many lookup tables to justify this pass message //if (bRet) //{ // v.Pass("_OTL_LookupTable_P_valid", table.m_tag, sIdentity); //} // validate each subtable for (uint i=0; i<SubTableCount; i++) { // verify that the subtable offset is accessible, if not error was already reported if (m_offsetLookupTable + (uint)FieldOffsets.SubTableOffsetArray + i*2 + 2 <= m_bufTable.GetLength()) { // verify subtable offset is valid if (m_offsetLookupTable + GetSubTableOffset(i) <= m_bufTable.GetLength()) { SubTable st = GetSubTable(i); if (st != null) { I_OTLValidate iv = (I_OTLValidate)st; bRet &= iv.Validate(v, sIdentity + ", SubTable[" + i + "]", table); } else { v.Warning(T.T_NULL, W._TEST_W_OtherErrorsInTable, table.m_tag, "unable to validate subtable: " + sIdentity + ", SubTable[" + i + "]"); } } else { v.Warning(T.T_NULL, W._TEST_W_OtherErrorsInTable, table.m_tag, "unable to validate subtable: " + sIdentity + ", SubTable[" + i + "]"); } } } return bRet; }
public bool Validate(Validator v, OTTable table, ushort numGlyphs, String sIdentity) { bool bRet = true; // check that segCountX2 is even if ((segCountX2 & 1) == 1) { v.Error(T.T_NULL, E.cmap_E_f4_segCountX2, table.m_tag, sIdentity + ", segCountX2 = " + segCountX2); bRet = false; } // check searchRange ushort segCount = (ushort)(segCountX2 / 2); ushort CalculatedSearchRange = (ushort)(2 * util.MaxPower2LE(segCount)); if (searchRange != CalculatedSearchRange) { v.Error(T.T_NULL, E.cmap_E_f4_searchRange, table.m_tag, sIdentity + ", searchRange = " + searchRange + ", calc = " + CalculatedSearchRange); bRet = false; } // check entrySelector ushort CalculatedEntrySelector = util.Log2((ushort)(CalculatedSearchRange/2)); if (entrySelector != CalculatedEntrySelector) { v.Error(T.T_NULL, E.cmap_E_f4_entrySelector, table.m_tag, sIdentity + ", entrySelector = " + entrySelector + ", calc = " + CalculatedEntrySelector); bRet = false; } // check rangeShift ushort CalculatedRangeShift = (ushort)(2 * segCount - CalculatedSearchRange); if (rangeShift != CalculatedRangeShift) { v.Error(T.T_NULL, E.cmap_E_f4_rangeShift, table.m_tag, sIdentity + ", rangeShift = " + rangeShift + ", calc = " + CalculatedRangeShift); bRet = false; } // check that final endCode value is 0xffff if (GetEndCode((uint)segCount-1) != 0xffff) { v.Error(T.T_NULL, E.cmap_E_f4_FinalEndCode, table.m_tag, sIdentity + ", endCode[" + (segCount-1) + "] = " + GetEndCode((uint)segCount-1)); bRet = false; } // check that end character codes are in ascending order if (segCount > 1) { for (uint i=0; i<segCount-1; i++) { if (GetEndCode(i) >= GetEndCode(i+1)) { v.Error(T.T_NULL, E.cmap_E_f4_EndCodeOrder, table.m_tag, sIdentity); bRet = false; break; } } } // check that the reservedPad is zero if ( m_ete.offset + (uint)FieldOffsets.endCode + segCountX2 < m_bufTable.GetLength() && reservedPad != 0) { v.Error(T.T_NULL, E.cmap_E_f4_reservedPad, table.m_tag, sIdentity); bRet = false; } // check that each start character code is not greater than // the corresponding end character code for (uint i=0; i<segCount; i++) { if (GetStartCode(i) > GetEndCode(i)) { String sDetails = ", startCode[" + i + "] = " + GetStartCode(i) + " , endCode[" + i + "] = " + GetEndCode(i); v.Error(T.T_NULL, E.cmap_E_f4_StartCode_GT_EndCode, table.m_tag, sIdentity + sDetails); bRet = false; } } // check that each delta value (where idRangeOffset == 0) // added to the start code is not negative for (uint i=0; i<segCount; i++) { if (GetIdRangeOffset(i) == 0) { if (GetIdDelta(i) + GetStartCode(i) < 0) { String sDetails = ", idDelta[" + i + "] = " + GetIdDelta(i) + ", startCode[" + i + "] = " + GetStartCode(i); v.Error(T.T_NULL, E.cmap_E_f4_idDeltaNeg, table.m_tag, sIdentity + sDetails); bRet = false; } } } // check range offsets for (uint i=0; i<segCount; i++) { ushort idRangeOffset = GetIdRangeOffset(i); ushort endCode = GetEndCode(i); ushort startCode = GetStartCode(i); if (idRangeOffset != 0) { uint AddressOfIdRangeOffset = (uint)FieldOffsets.endCode + segCountX2*3u + 2 + i*2; uint obscureIndex = (uint) (idRangeOffset + (endCode - startCode)*2 + AddressOfIdRangeOffset); if (obscureIndex > length) { v.Error(T.T_NULL, E.cmap_E_f4_idRangeOffset, table.m_tag, sIdentity + ", idRangeOffset[" + i + "] = " + idRangeOffset); bRet = false; } } } // check that glyph ids are less than numGlyphs for (uint i=0; i<segCount; i++) { int nGlyphMappingErrors = 0; // Report the first 10 errors and // a count of errors after that. int nMaxMappingErrors = 10; ushort idRangeOffset = GetIdRangeOffset(i); ushort endCode = GetEndCode(i); ushort startCode = GetStartCode(i); short idDelta = GetIdDelta(i); ushort nGlyph; for (uint j=startCode; j<= endCode; j++) { ushort c = (ushort)j; nGlyph = 0; if (idRangeOffset == 0) { nGlyph = (ushort)(c + idDelta); } else { uint AddressOfIdRangeOffset = (uint) FieldOffsets.endCode + segCountX2*3u + 2 + i*2; uint obscureIndex = (uint) (idRangeOffset + (c-startCode)*2 + AddressOfIdRangeOffset); // throw out invalid indexes for this test // (they should have already been reported) if (obscureIndex < length && (m_ete.offset + obscureIndex < m_bufTable.GetLength())) { nGlyph = m_bufTable.GetUshort(m_ete.offset + obscureIndex); } if (nGlyph !=0 ) { nGlyph = (ushort)(nGlyph + idDelta); } } if (nGlyph > numGlyphs) { // it is possible that an entire segment is bad. // That causes a hang like behavior and a // bloated error file // that cannot be opened because it is so huge. if (nGlyphMappingErrors < nMaxMappingErrors) { v.Error(T.T_NULL, E.cmap_E_Mapping, table.m_tag, sIdentity + ", char = 0x" + c.ToString("X4") + ", glyphID = " + nGlyph); } nGlyphMappingErrors++; } } if (nGlyphMappingErrors >= nMaxMappingErrors) { string sDetails = sIdentity + ", segment = " + i + " has " + nGlyphMappingErrors + " glyphs mapped out of range"; v.Error(T.T_NULL, E.cmap_E_Mapping, table.m_tag, sDetails); bRet = false; } } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; if (CoverageFormat == 1) { if (m_offsetCoverageTable + (uint)FieldOffsets1.GlyphArray + F1GlyphCount*2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_CoverageTable_E_GlyphArrayPastEOT, table.m_tag, sIdentity); bRet = false; } } else if (CoverageFormat == 2) { if (m_offsetCoverageTable + (uint)FieldOffsets2.RangeRecordArray + F2RangeCount*6 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E._OTL_CoverageTable_E_RangeRecordArrayPastEOT, table.m_tag, sIdentity); bRet = false; } } else { v.Error(T.T_NULL, E._OTL_CoverageTable_E_Format, table.m_tag, sIdentity + ", format = " + CoverageFormat.ToString()); bRet = false; } // way too many coverage tables to justify this pass message //if (bRet) //{ // v.Pass("_OTL_CoverageTable_P_valid", table.m_tag, sIdentity); //} return bRet; }