public override SubTable GetSubTable(uint i) { if (i >= SubTableCount) { throw new ArgumentOutOfRangeException(); } SubTable st = null; uint stOffset = m_offsetLookupTable + (uint)GetSubTableOffset(i); if ((string)m_tag == "GPOS") { switch (LookupType) { case 1: st = new val_GPOS.SinglePos_val(stOffset, m_bufTable); break; case 2: st = new val_GPOS.PairPos_val(stOffset, m_bufTable); break; case 3: st = new val_GPOS.CursivePos_val(stOffset, m_bufTable); break; case 4: st = new val_GPOS.MarkBasePos_val(stOffset, m_bufTable); break; case 5: st = new val_GPOS.MarkLigPos_val(stOffset, m_bufTable); break; case 6: st = new val_GPOS.MarkMarkPos_val(stOffset, m_bufTable); break; case 7: st = new val_GPOS.ContextPos_val(stOffset, m_bufTable); break; case 8: st = new val_GPOS.ChainContextPos_val(stOffset, m_bufTable); break; case 9: st = new val_GPOS.ExtensionPos_val(stOffset, m_bufTable); break; } } else if ((string)m_tag == "GSUB") { switch (LookupType) { case 1: st = new val_GSUB.SingleSubst_val(stOffset, m_bufTable); break; case 2: st = new val_GSUB.MultipleSubst_val(stOffset, m_bufTable); break; case 3: st = new val_GSUB.AlternateSubst_val(stOffset, m_bufTable); break; case 4: st = new val_GSUB.LigatureSubst_val(stOffset, m_bufTable); break; case 5: st = new val_GSUB.ContextSubst_val(stOffset, m_bufTable); break; case 6: st = new val_GSUB.ChainContextSubst_val(stOffset, m_bufTable); break; case 7: st = new val_GSUB.ExtensionSubst_val(stOffset, m_bufTable); break; case 8: st = new val_GSUB.ReverseChainSubst_val(stOffset, m_bufTable); break; } } else { throw new InvalidOperationException("unknown table type"); } return(st); }
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); }