/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.VORG_CFF_Font)) { if (fontOwner.ContainsPostScriptOutlines()) { v.Pass(T.VORG_CFF_Font, P.VORG_P_CFF_Font, m_tag); } else { v.Error(T.VORG_CFF_Font, E.VORG_E_CFF_Font, m_tag); bRet = false; } } if (v.PerformTest(T.VORG_Version)) { if (majorVersion == 1 && minorVersion == 0) { v.Pass(T.VORG_Version, P.VORG_P_Version, m_tag); } else { v.Error(T.VORG_Version, E.VORG_E_Version, m_tag); bRet = false; } } return bRet; }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.VORG_CFF_Font)) { if (fontOwner.ContainsPostScriptOutlines()) { v.Pass(T.VORG_CFF_Font, P.VORG_P_CFF_Font, m_tag); } else { v.Error(T.VORG_CFF_Font, E.VORG_E_CFF_Font, m_tag); bRet = false; } } if (v.PerformTest(T.VORG_Version)) { if (majorVersion == 1 && minorVersion == 0) { v.Pass(T.VORG_Version, P.VORG_P_Version, m_tag); } else { v.Error(T.VORG_Version, E.VORG_E_Version, m_tag); bRet = false; } } return(bRet); }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; bRet &= ((val_BASE)table).ValidateNoOverlap(m_offsetBaseScriptListTable, CalcLength(), v, sIdentity, table.GetTag()); bool bOrderOk = true; if (BaseScriptCount > 1) { for (uint i = 0; i < BaseScriptCount - 1; i++) { BaseScriptRecord ThisBsr = GetBaseScriptRecord(i); BaseScriptRecord NextBsr = GetBaseScriptRecord(i + 1); if (ThisBsr.BaseScriptTag >= NextBsr.BaseScriptTag) { v.Error(T.T_NULL, E.BASE_E_BaseScriptList_Order, table.m_tag, sIdentity); bOrderOk = false; bRet = false; break; } } } if (bOrderOk) { v.Pass(T.T_NULL, P.BASE_P_BaseScriptList_Order, table.m_tag, sIdentity); } bool bOffsetsOk = true; for (uint i = 0; i < BaseScriptCount; i++) { BaseScriptRecord bsr = GetBaseScriptRecord(i); if (bsr.BaseScriptOffset + m_offsetBaseScriptListTable > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.BASE_E_BaseScriptList_Offset, table.m_tag, sIdentity + ", index = " + i); bOffsetsOk = false; bRet = false; } } if (bOffsetsOk) { v.Pass(T.T_NULL, P.BASE_P_BaseScriptList_Offset, table.m_tag, sIdentity); } for (uint i = 0; i < BaseScriptCount; i++) { BaseScriptRecord bsr = GetBaseScriptRecord(i); BaseScriptTable_val bst = GetBaseScriptTable_val(bsr); bst.Validate(v, sIdentity + ", BaseScriptRecord[" + i + "](" + bsr.BaseScriptTag + ")", table); } return(bRet); }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; bRet &= ((val_GDEF)table).ValidateNoOverlap(m_offsetLigCaretListTable, CalcLength(), v, sIdentity, table.GetTag()); if (CoverageOffset == 0) { v.Error(T.T_NULL, E.GDEF_E_LigCaretListTable_CoverageOffset_0, table.m_tag, sIdentity); bRet = false; } else if (CoverageOffset > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GDEF_E_LigCaretListTable_CoverageOffset_invalid, table.m_tag, sIdentity); bRet = false; } else { v.Pass(T.T_NULL, P.GDEF_P_LigCaretListTable_CoverageOffset, table.m_tag, sIdentity); CoverageTable_val ct = GetCoverageTable_val(); ct.Validate(v, sIdentity + ", Coverage", table); } if (m_offsetLigCaretListTable + (uint)FieldOffsets.LigGlyphOffsets + LigGlyphCount * 2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GDEF_E_LigCaretListTable_LigGlyphArray_PastEOT, table.m_tag, sIdentity); bRet = false; } bool bOffsetsOk = true; for (uint i = 0; i < LigGlyphCount; i++) { if (m_offsetLigCaretListTable + GetLigGlyphOffset(i) > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GDEF_E_LigCaretListTable_LigGlyphOffset, table.m_tag, sIdentity + ", index = " + i); bOffsetsOk = false; bRet = false; } else { LigGlyphTable_val lgt = GetLigGlyphTable_val(i); lgt.Validate(v, sIdentity + ", LigGlyph[" + i + "]", table); } } if (bOffsetsOk) { v.Pass(T.T_NULL, P.GDEF_P_LigCaretListTable_LigGlyphArray, table.m_tag, sIdentity); } return(bRet); }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; Table_maxp maxpTable = (Table_maxp)fontOwner.GetTable("maxp"); if (maxpTable == null) { v.Error(T.T_NULL, E._TEST_E_TableMissing, m_tag, "Unable to test this table, maxp table is invalid or missing"); return(false); } if (v.PerformTest(T.vmtx_TableLength)) { uint CalcTableLength = GetNumOfLongVerMetrics(fontOwner) * 4 + (fontOwner.GetMaxpNumGlyphs() - GetNumOfLongVerMetrics(fontOwner)) * 2; if (CalcTableLength == GetLength()) { v.Pass(T.vmtx_TableLength, P.vmtx_P_TableLength, m_tag); } else { v.Error(T.vmtx_TableLength, E.vmtx_E_TableLength, m_tag); bRet = false; } } return(bRet); }
protected bool CheckTableAlignment(Validator v) { Debug.Assert(m_OffsetTable != null); bool bRet = false; if (m_OffsetTable != null) { bRet = true; for (int i = 0; i < m_OffsetTable.DirectoryEntries.Count; i++) { DirectoryEntry de = (DirectoryEntry)m_OffsetTable.DirectoryEntries[i]; if ((de.offset & 0x03) != 0) { v.Warning(T.T_NULL, W._DE_W_TableAlignment, null, (string)de.tag); //bRet = false; } } if (bRet == true) { v.Pass(P._DE_P_TableAlignment, null); } } return(bRet); }
private bool ValidateGlyfPartiallyUnreferenced(Validator validator, OTFont fontOwner) { int numEntry = this.NumEntry(fontOwner); if (numEntry == Table_loca.ValueInvalid) { validator.Warning(T.T_NULL, W.loca_W_GlyfPartiallyUnreferenced, this.m_tag); return(false); } int offsLast; if (!this.GetGlyfOffset(numEntry - 1, out offsLast, validator, fontOwner)) { validator.Warning(T.T_NULL, W.loca_W_GlyfPartiallyUnreferenced, this.m_tag); return(false); } int lengthGlyf = this.LengthGlyf(fontOwner); if (lengthGlyf == Table_loca.ValueInvalid) { validator.Warning(T.T_NULL, W.loca_W_GlyfPartiallyUnreferenced, this.m_tag); return(false); } if (lengthGlyf != offsLast) { validator.Warning(T.T_NULL, W.loca_W_GlyfPartiallyUnreferenced, this.m_tag); return(false); } validator.Pass(P.loca_P_GlyfPartiallyUnreferenced, this.m_tag); return(true); }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; bRet &= ((val_GDEF)table).ValidateNoOverlap(m_offsetMarkGlyphSetsDefTable, CalcLength(), v, sIdentity, table.GetTag()); if (MarkSetTableFormat != 1) { v.Error(T.T_NULL, E.GDEF_E_MarkSetTableFormat, table.m_tag, sIdentity + ": MarkSetTableFormat=" + MarkSetTableFormat.ToString()); bRet = false; } if (m_offsetMarkGlyphSetsDefTable + CalcLength() > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GDEF_E_MarkGlyphSetsDefTable_PastEOT, table.m_tag, sIdentity); bRet = false; } v.Info(T.T_NULL, I.GDEF_I_MarkSetCount, table.m_tag, sIdentity + ": MarkSetCount=" + MarkSetCount); // TODO: check Coverage [MarkSetCount] array? if (bRet) { v.Pass(T.T_NULL, P.GDEF_P_MarkGlyphSetsDefTable, table.m_tag, sIdentity); } return bRet; }
public bool ValidateNumEntries(Validator validator, OTFont fontOwner) { int numGlyph = this.NumGlyph(fontOwner); int numEntry = this.NumEntry(fontOwner); if ((numGlyph == Table_loca.ValueInvalid) || (numEntry == Table_loca.ValueInvalid) || (numEntry != numGlyph + 1)) { if (validator != null) { validator.Error(T.T_NULL, E.loca_E_NumEntries, m_tag, "number of entries=" + numEntry + " number of glyphs=" + numGlyph); } return(false); } else { if (validator != null) { validator.Pass(P.loca_P_NumEntries, m_tag); } return(true); } }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; Table_maxp maxpTable = (Table_maxp)fontOwner.GetTable("maxp"); if (maxpTable == null) { v.Error(T.T_NULL, E._TEST_E_TableMissing, m_tag, "Unable to test this table, maxp table is invalid or missing"); return false; } if (v.PerformTest(T.vmtx_TableLength)) { uint CalcTableLength = GetNumOfLongVerMetrics(fontOwner)*4 + (fontOwner.GetMaxpNumGlyphs() - GetNumOfLongVerMetrics(fontOwner))*2; if (CalcTableLength == GetLength()) { v.Pass(T.vmtx_TableLength, P.vmtx_P_TableLength, m_tag); } else { v.Error(T.vmtx_TableLength, E.vmtx_E_TableLength, m_tag); bRet = false; } } return bRet; }
public bool ValidateNumEntries(Validator validator, OTFont fontOwner) { int numGlyph=this.NumGlyph(fontOwner); int numEntry=this.NumEntry(fontOwner); if ((numGlyph==Table_loca.ValueInvalid)|| (numEntry==Table_loca.ValueInvalid)|| (numEntry!=numGlyph+1)) { if (validator!=null) { validator.Error(T.T_NULL, E.loca_E_NumEntries, m_tag, "number of entries="+numEntry+" number of glyphs="+numGlyph); } return false; } else { if (validator!=null) { validator.Pass(P.loca_P_NumEntries, m_tag); } return true; } }
protected bool CheckTagNames(Validator v) { Debug.Assert(m_OffsetTable != null); bool bRet = false; if (m_OffsetTable != null) { bRet = true; for (int i = 0; i < m_OffsetTable.DirectoryEntries.Count; i++) { DirectoryEntry de = (DirectoryEntry)m_OffsetTable.DirectoryEntries[i]; if (!de.tag.IsValid()) { v.Error(T.T_NULL, E._DE_E_TagName, null, (string)de.tag); bRet = false; } } if (bRet == true) { v.Pass(P._DE_P_TagName, null); } } return(bRet); }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; bRet &= ((val_BASE)table).ValidateNoOverlap(m_offsetBaseTagListTable, CalcLength(), v, sIdentity, table.GetTag()); bool bTagsValid = true; for (uint i = 0; i < BaseTagCount; i++) { OTTag BaselineTag = GetBaselineTag(i); if (!BaselineTag.IsValid()) { v.Error(T.T_NULL, E.BASE_E_BaseTagList_TagValid, table.m_tag, sIdentity + ", tag = 0x" + ((uint)BaselineTag).ToString("x8")); bTagsValid = false; bRet = false; } } if (bTagsValid) { v.Pass(T.T_NULL, P.BASE_P_BaseTagList_TagValid, table.m_tag, sIdentity); } bool bOrderOk = true; if (BaseTagCount > 1) { for (uint i = 0; i < BaseTagCount - 1; i++) { OTTag ThisTag = GetBaselineTag(i); OTTag NextTag = GetBaselineTag(i + 1); if (ThisTag >= NextTag) { v.Error(T.T_NULL, E.BASE_E_BaseTagList_TagOrder, table.m_tag, sIdentity); bOrderOk = false; bRet = false; break; } } } if (bOrderOk) { v.Pass(T.T_NULL, P.BASE_P_BaseTagList_TagOrder, table.m_tag, sIdentity); } return(bRet); }
bool Validate_indexSubTable(Validator v, indexSubTable ist, indexSubTableArray ista, string sID, OTFontVal fontOwner) { bool bOk = true; if (!Validate_indexSubHeader(v, ist.header, sID, fontOwner)) { bOk = false; } switch (ist.header.indexFormat) { case 1: if (!Validate_indexSubTable_format1(v, (indexSubTable1)ist, ista, sID, fontOwner)) { bOk = false; } break; case 2: if (!Validate_indexSubTable_format2(v, (indexSubTable2)ist, ista, sID, fontOwner)) { bOk = false; } break; case 3: if (!Validate_indexSubTable_format3(v, (indexSubTable3)ist, ista, sID, fontOwner)) { bOk = false; } break; case 4: if (!Validate_indexSubTable_format4(v, (indexSubTable4)ist, ista, sID, fontOwner)) { bOk = false; } break; case 5: if (!Validate_indexSubTable_format5(v, (indexSubTable5)ist, ista, sID, fontOwner)) { bOk = false; } break; default: Debug.Assert(false, "illegal index format", "format = " + ist.header.indexFormat); break; } if (bOk) { v.Pass(T.EBLC_indexSubTables, P.EBLC_P_indexSubTables, m_tag, sID); } return(bOk); }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.vhea_version)) { if (version.GetUint() == 0x00010000 || version.GetUint() == 0x00011000) { v.Pass(T.vhea_version, P.vhea_P_version, m_tag, "0x" + version.GetUint().ToString("x8")); } else { v.Error(T.vhea_version, E.vhea_E_version, m_tag, "0x" + version.GetUint().ToString("x8")); bRet = false; } } if (v.PerformTest(T.vhea_ReservedFields)) { if (reserved1 == 0 && reserved2 == 0 && reserved3 == 0 && reserved4 == 0) { v.Pass(T.vhea_ReservedFields, P.vhea_P_ReservedFields, m_tag); } else { v.Error(T.vhea_ReservedFields, E.vhea_E_ReservedFields, m_tag); bRet = false; } } if (v.PerformTest(T.vhea_metricDataFormat)) { if (metricDataFormat == 0) { v.Pass(T.vhea_metricDataFormat, P.vhea_P_metricDataFormat, m_tag); } else { v.Error(T.vhea_metricDataFormat, E.vhea_E_metricDataFormat, m_tag, metricDataFormat.ToString()); bRet = false; } } return bRet; }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.vhea_version)) { if (version.GetUint() == 0x00010000 || version.GetUint() == 0x00011000) { v.Pass(T.vhea_version, P.vhea_P_version, m_tag, "0x" + version.GetUint().ToString("x8")); } else { v.Error(T.vhea_version, E.vhea_E_version, m_tag, "0x" + version.GetUint().ToString("x8")); bRet = false; } } if (v.PerformTest(T.vhea_ReservedFields)) { if (reserved1 == 0 && reserved2 == 0 && reserved3 == 0 && reserved4 == 0) { v.Pass(T.vhea_ReservedFields, P.vhea_P_ReservedFields, m_tag); } else { v.Error(T.vhea_ReservedFields, E.vhea_E_ReservedFields, m_tag); bRet = false; } } if (v.PerformTest(T.vhea_metricDataFormat)) { if (metricDataFormat == 0) { v.Pass(T.vhea_metricDataFormat, P.vhea_P_metricDataFormat, m_tag); } else { v.Error(T.vhea_metricDataFormat, E.vhea_E_metricDataFormat, m_tag, metricDataFormat.ToString()); bRet = false; } } return(bRet); }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; bRet &= ((val_BASE)table).ValidateNoOverlap(m_offsetAxisTable, CalcLength(), v, sIdentity, table.GetTag()); if (BaseTagListOffset == 0) { v.Pass(T.T_NULL, P.BASE_P_AxisTable_BaseTagListOffset_null, table.m_tag, sIdentity); } else if (BaseTagListOffset + m_offsetAxisTable > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.BASE_E_AxisTable_BaseTagListOffset, table.m_tag, sIdentity); bRet = false; } else { v.Pass(T.T_NULL, P.BASE_P_AxisTable_BaseTagListOffset_valid, table.m_tag, sIdentity); BaseTagListTable_val btlt = GetBaseTagListTable_val(); btlt.Validate(v, sIdentity, table); } if (BaseScriptListOffset == 0) { v.Error(T.T_NULL, E.BASE_E_AxisTable_BaseScriptListOffset_null, table.m_tag, sIdentity); bRet = false; } else if (BaseScriptListOffset + m_offsetAxisTable > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.BASE_E_AxisTable_BaseScriptListOffset, table.m_tag, sIdentity); bRet = false; } else { v.Pass(T.T_NULL, P.BASE_P_AxisTable_BaseScriptListOffset_valid, table.m_tag, sIdentity); BaseScriptListTable_val bslt = GetBaseScriptListTable_val(); bslt.Validate(v, sIdentity, table); } return(bRet); }
protected bool CheckForRecommendedTables(Validator v) { bool bRet = true; bool bMissing = false; if (!IsPostScript()) { if (GetDirectoryEntry("gasp") == null) { v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "gasp"); bMissing = true; } Table_hmtx hmtxTable = (Table_hmtx)GetTable("hmtx"); if (hmtxTable != null) { if (!hmtxTable.IsMonospace(this) && !ContainsSymbolsOnly()) { if (GetDirectoryEntry("kern") == null) { v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "kern"); bMissing = true; } if (GetDirectoryEntry("hdmx") == null) { v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "hdmx"); bMissing = true; } } } if (GetDirectoryEntry("VDMX") == null) { v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "VDMX"); bMissing = true; } } if (GetDirectoryEntry("DSIG") == null && !GetFile().IsCollection()) { v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "DSIG"); bMissing = true; } if (!bMissing) { v.Pass(P._FONT_P_MissingRecommendedTable, null); } return(bRet); }
private bool ValidateGlyfEntryLengthAlignment(Validator validator, OTFont fontOwner) { int cntWarn = 0; int numEntry = this.NumEntry(fontOwner); if (numEntry == Table_loca.ValueInvalid) { if (validator != null) { validator.Warning(T.T_NULL, W.loca_W_GlyfEntryLengthAlignment, m_tag, "Unable to determine the number of entries in the 'loca' table"); } return(false); } int offsGlyfCur, offsGlyfNext; for (int iEntry = 0; iEntry < numEntry - 1; iEntry++) { if ((!this.GetGlyfOffset(iEntry, out offsGlyfCur, validator, fontOwner)) || (!this.GetGlyfOffset(iEntry + 1, out offsGlyfNext, validator, fontOwner))) { cntWarn++; continue; } if (((offsGlyfNext - offsGlyfCur) % 4) != 0) { cntWarn++; } } if (validator != null) { if (cntWarn == 0) { validator.Pass(P.loca_P_GlyfEntryLengthAlignment, m_tag); } else { validator.Warning(T.T_NULL, W.loca_W_GlyfEntryLengthAlignment, m_tag, "Number of glyphs with the warning = " + cntWarn); } } return(cntWarn == 0); }
private bool ValidateGlyfEntryEmpty(Validator validator, OTFont fontOwner) { int cntInfo = 0; int numEntry = this.NumEntry(fontOwner); if (numEntry == Table_loca.ValueInvalid) { if (validator != null) { validator.Warning(T.T_NULL, W._TEST_W_OtherErrorsInTable, m_tag, "Unable to determine the number of entries in the 'loca' table"); } return(false); } int offsGlyfCur, offsGlyfNext; for (int iEntry = 0; iEntry < numEntry - 1; iEntry++) { if ((!this.GetGlyfOffset(iEntry, out offsGlyfCur, validator, fontOwner)) || (!this.GetGlyfOffset(iEntry + 1, out offsGlyfNext, validator, fontOwner))) { cntInfo++; continue; } if (offsGlyfNext == offsGlyfCur) { cntInfo++; } } if (validator != null) { if (cntInfo == 0) { validator.Pass(P.loca_P_GlyfEntryEmpty, m_tag); } else { validator.Info(T.T_NULL, I.loca_I_GlyfEntryEmpty, m_tag, "Number of glyphs that are empty = " + cntInfo); } } return(cntInfo == 0); }
private bool ValidateOffsetsIncreasing(Validator validator, OTFont fontOwner) { int cntErr = 0; int numEntry = this.NumEntry(fontOwner); if (numEntry == Table_loca.ValueInvalid) { if (validator != null) { validator.Error(T.T_NULL, E.loca_E_OffsetsIncreasing, m_tag, "Unable to determine the number of entries in the 'loca' table"); } return(false); } int offsGlyfCur, offsGlyfNext; for (int iEntry = 0; iEntry < numEntry - 1; iEntry++) { if ((!this.GetGlyfOffset(iEntry, out offsGlyfCur, validator, fontOwner)) || (!this.GetGlyfOffset(iEntry + 1, out offsGlyfNext, validator, fontOwner))) { cntErr++; continue; } if (offsGlyfNext < offsGlyfCur) { cntErr++; } } if (validator != null) { if (cntErr == 0) { validator.Pass(P.loca_P_OffsetsIncreasing, m_tag); } else { validator.Error(T.T_NULL, E.loca_E_OffsetsIncreasing, m_tag, "Number of glyphs with the error = " + cntErr); } } return(cntErr == 0); }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; bRet &= ((val_BASE)table).ValidateNoOverlap(m_offsetBaseCoordTable, CalcLength(), v, sIdentity, table.GetTag()); if (BaseCoordFormat == 1 || BaseCoordFormat == 2 || BaseCoordFormat == 3) { v.Pass(T.T_NULL, P.BASE_P_BaseCoordTable_format, table.m_tag, sIdentity); } else { v.Error(T.T_NULL, E.BASE_E_BaseCoordTable_format, table.m_tag, sIdentity + ", format = " + BaseCoordFormat); } return(bRet); }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.cvt_length)) { if ((m_bufTable.GetLength() & 1) != 0) { v.Error(T.cvt_length, E.cvt_E_length_odd, m_tag); bRet = false; } else { v.Pass(T.cvt_length, P.cvt_P_length_even, m_tag); } } return bRet; }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.cvt_length)) { if ((m_bufTable.GetLength() & 1) != 0) { v.Error(T.cvt_length, E.cvt_E_length_odd, m_tag); bRet = false; } else { v.Pass(T.cvt_length, P.cvt_P_length_even, m_tag); } } return(bRet); }
/* * VALIDATION FUNCTIONS */ public bool ValidateFormat(Validator validator, OTFont fontOwner) { int format=this.Format(fontOwner); if ((format!=0)&&(format!=1)) { if (validator!=null) { validator.Error(E.loca_E_Format, m_tag); } return false; } else { if (validator!=null) { validator.Pass(P.loca_P_Format, m_tag); } return true; } }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; bRet &= ((val_GDEF)table).ValidateNoOverlap(m_offsetLigGlyphTable, CalcLength(), v, sIdentity, table.GetTag()); if (m_offsetLigGlyphTable + (uint)FieldOffsets.CaretValueOffsets + CaretCount * 2 > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GDEF_E_LigGlyphTable_CaretValueArray_PastEOT, table.m_tag, sIdentity); bRet = false; } bool bOffsetsOk = true; for (uint i = 0; i < CaretCount; i++) { if (m_offsetLigGlyphTable + GetCaretValueOffset(i) > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.GDEF_E_LigGlyphTable_CaretValueOffset, table.m_tag, sIdentity); bOffsetsOk = false; bRet = false; } } if (bOffsetsOk) { v.Pass(T.T_NULL, P.GDEF_P_LigGlyphTable_CaretValueArray, table.m_tag, sIdentity); } for (uint i = 0; i < CaretCount; i++) { CaretValueTable cvt = GetCaretValueTable(i); if (cvt.CaretValueFormat < 1 || cvt.CaretValueFormat > 3) { v.Error(T.T_NULL, E.GDEF_E_CaretValueTable_Format, table.m_tag, sIdentity + ", CaretValue[" + i + "], format = " + cvt.CaretValueFormat); bRet = false; } } return(bRet); }
protected bool CheckTagsAscending(Validator v) { Debug.Assert(m_OffsetTable != null); bool bRet = false; if (m_OffsetTable != null) { bRet = true; for (int i = 0; i < m_OffsetTable.DirectoryEntries.Count; i++) { DirectoryEntry de1 = (DirectoryEntry)m_OffsetTable.DirectoryEntries[i]; // compare this directory entry with every one that follows it for (int j = i + 1; j < m_OffsetTable.DirectoryEntries.Count; j++) { DirectoryEntry de2 = (DirectoryEntry)m_OffsetTable.DirectoryEntries[j]; if ((uint)de1.tag > (uint)de2.tag) { v.Error(E._DE_E_TagsAscending, null); bRet = false; break; } } if (bRet == false) { break; } } if (bRet == true) { v.Pass(P._DE_P_TagsAscending, null); } } return(bRet); }
/* * VALIDATION FUNCTIONS */ public bool ValidateFormat(Validator validator, OTFont fontOwner) { int format = this.Format(fontOwner); if ((format != 0) && (format != 1)) { if (validator != null) { validator.Error(E.loca_E_Format, m_tag); } return(false); } else { if (validator != null) { validator.Pass(P.loca_P_Format, m_tag); } return(true); } }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; bRet &= ((val_BASE)table).ValidateNoOverlap(m_offsetBaseValuesTable, CalcLength(), v, sIdentity, table.GetTag()); // check BaseCoord offsets bool bOffsetsOk = true; for (uint i = 0; i < BaseCoordCount; i++) { ushort bco = GetBaseCoordOffset(i); if (bco == 0) { v.Error(T.T_NULL, E.BASE_E_BaseValuesTable_BCO_0, table.m_tag, sIdentity + ", BaseCoordOffset index = " + i); bOffsetsOk = false; bRet = false; } else if (bco + m_offsetBaseValuesTable > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.BASE_E_BaseValuesTable_BCO_invalid, table.m_tag, sIdentity + ", BaseCoordOffset index = " + i); bOffsetsOk = false; bRet = false; } } if (bOffsetsOk) { v.Pass(T.T_NULL, P.BASE_P_BaseValuesTable_BCO, table.m_tag, sIdentity); } // check the BaseCoord tables for (uint i = 0; i < BaseCoordCount; i++) { BaseCoordTable_val bct = GetBaseCoordTable_val(i); bct.Validate(v, sIdentity, table); } return(bRet); }
protected bool CheckForNoUnnecessaryTables(Validator v) { bool bRet = true; bool bFoundUnnecessary = false; Table_hmtx hmtxTable = (Table_hmtx)GetTable("hmtx"); if (hmtxTable != null) { if (hmtxTable.IsMonospace(this)) { if (GetDirectoryEntry("hdmx") != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "hdmx table not needed for monospaced font"); bFoundUnnecessary = true; } if (GetDirectoryEntry("LTSH") != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "LTSH table not needed for monospaced font"); bFoundUnnecessary = true; } if (GetDirectoryEntry("kern") != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "kern table not needed for monospaced font"); bFoundUnnecessary = true; } } if (GetDirectoryEntry("CFF ") == null && GetDirectoryEntry("VORG") != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "VORG table not needed, it may optionally be present for fonts with Postscript outlines"); bFoundUnnecessary = true; } if (GetDirectoryEntry("PCLT") != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "PCLT table not needed, Microsoft no longer recommends including this table"); bFoundUnnecessary = true; } } if (GetDirectoryEntry("CFF ") != null) { string [] UnnecessaryTables = {"glyf", "fpgm", "cvt ", "loca", "prep"}; for (int i=0; i<UnnecessaryTables.Length; i++) { if (GetDirectoryEntry(UnnecessaryTables[i]) != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, UnnecessaryTables[i] + " not needed since the font contains a 'CFF ' table"); bFoundUnnecessary = true; } } } if (GetDirectoryEntry("glyf") != null) { if (GetDirectoryEntry("CFF ") != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "CFF not needed since the font contains a 'CFF ' table"); bFoundUnnecessary = true; } } if (ContainsLatinOnly()) { if (GetDirectoryEntry("vhea") != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "vhea not needed since the font only contains Latin characters"); bFoundUnnecessary = true; } if (GetDirectoryEntry("vmtx") != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "vmtx not needed since the font only contains Latin characters"); bFoundUnnecessary = true; } } if (!bFoundUnnecessary) { v.Pass(P._FONT_P_UnnecessaryTable, null); } return bRet; }
protected bool CheckTagsAscending(Validator v) { Debug.Assert(m_OffsetTable != null); bool bRet = false; if (m_OffsetTable != null) { bRet = true; for (int i = 0; i<m_OffsetTable.DirectoryEntries.Count; i++) { DirectoryEntry de1 = (DirectoryEntry)m_OffsetTable.DirectoryEntries[i]; // compare this directory entry with every one that follows it for (int j=i+1; j<m_OffsetTable.DirectoryEntries.Count; j++) { DirectoryEntry de2 = (DirectoryEntry)m_OffsetTable.DirectoryEntries[j]; if ((uint)de1.tag > (uint)de2.tag) { v.Error(E._DE_E_TagsAscending, null); bRet = false; break; } } if (bRet == false) { break; } } if (bRet == true) { v.Pass(P._DE_P_TagsAscending, null); } } return bRet; }
protected bool CheckForRequiredTables(Validator v) { bool bRet = true; string [] RequiredTables = {"cmap", "head", "hhea", "hmtx", "maxp", "name", "OS/2", "post"}; for (int i=0; i<RequiredTables.Length; i++) { if (GetDirectoryEntry(RequiredTables[i]) == null) { v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, RequiredTables[i]); bRet = false; } } if (GetDirectoryEntry("glyf") == null && GetDirectoryEntry("CFF ") == null && GetDirectoryEntry("EBDT") == null && GetDirectoryEntry("CBDT") == null) { v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "Font must contain either a 'glyf', 'CFF ', 'EBDT' or 'CBDT' table"); bRet = false; } if (GetDirectoryEntry("glyf") != null) { string [] RequiredGlyphTables = {"loca"}; for (int i=0; i<RequiredGlyphTables.Length; i++) { if (GetDirectoryEntry(RequiredGlyphTables[i]) == null) { v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, RequiredGlyphTables[i] + " is required since the font contains a glyf table"); bRet = false; } } } if (GetDirectoryEntry("EBDT") != null) { if (GetDirectoryEntry("EBLC") == null) { v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "EBLC is required since the font contains an EBDT table"); bRet = false; } } if (GetDirectoryEntry("EBLC") != null) { if (GetDirectoryEntry("EBDT") == null) { v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "EBDT is required since the font contains an EBLC table"); bRet = false; } } if (GetDirectoryEntry("EBSC") != null) { if (GetDirectoryEntry("EBDT") == null) { v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "EBDT is required since the font contains an EBSC table"); bRet = false; } if (GetDirectoryEntry("EBLC") == null) { v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "EBLC is required since the font contains an EBSC table"); bRet = false; } } if (bRet) { v.Pass(P._FONT_P_MissingRequiredTable, null); } return bRet; }
private bool CheckUnicodeRanges(Validator v, OTFont fontOwner) { bool bRet = true; bool bOk = true; if (version == 0) { if (ulUnicodeRange1 != 0) { v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "Range[0] was undefined. All bits must be 0."); bOk = false; } if (ulUnicodeRange2 != 0) { v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "Range[1] was undefined. All bits must be 0."); bOk = false; } if (ulUnicodeRange3 != 0) { v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "Range[2] was undefined. All bits must be 0."); bOk = false; } if (ulUnicodeRange4 != 0) { v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "Range[3] was undefined. All bits must be 0."); bOk = false; } if (bOk) { v.Pass(P.OS_2_P_UnicodeRanges, m_tag); } else { bRet = false; } return bRet; } // count the number of entries in each unicode range in the cmap subtable UnicodeRanges ur = new UnicodeRanges(); for (uint c = 0; c < 0xffff; c++) { // check if c is mapped to a glyph uint iGlyph = fontOwner.FastMapUnicodeToGlyphID((char)c); if (iGlyph != 0) { UnicodeRanges.Range r = ur.GetRange(c); if (r != null) { r.count++; } } } uint nCharsInRange; // bit 0 uint BASIC_LATIN_LOW = 0x0020; nCharsInRange = ur.GetRange(BASIC_LATIN_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000001, nCharsInRange, "Basic Latin"); // bit 1 uint LATIN_1_SUPPLEMENT_LOW = 0x00A0; nCharsInRange = ur.GetRange(LATIN_1_SUPPLEMENT_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000002, nCharsInRange, "Latin-1 Supplement"); // bit 2 uint LATIN_EXTENDED_A_LOW = 0x0100; nCharsInRange = ur.GetRange(LATIN_EXTENDED_A_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000004, nCharsInRange, "Latin Extended-A"); // bit 3 uint LATIN_EXTENDED_B_LOW = 0x0180; nCharsInRange = ur.GetRange(LATIN_EXTENDED_B_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000008, nCharsInRange, "Latin Extended-B"); // bit 4 uint IPA_EXTENSIONS_LOW = 0x0250; uint Phonetic_Extensions = 0x1D00; uint Phonetic_Extensions_Supplement = 0x1D80; nCharsInRange = ur.GetRange(IPA_EXTENSIONS_LOW).count + ur.GetRange(Phonetic_Extensions).count + ur.GetRange(Phonetic_Extensions_Supplement).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000010, nCharsInRange, "IPA Extensions"); // bit 5 uint SPACING_MODIFIER_LETTERS_LOW = 0x02B0; uint Modifier_Tone_Letters = 0xA700; nCharsInRange = ur.GetRange(SPACING_MODIFIER_LETTERS_LOW).count + ur.GetRange(Modifier_Tone_Letters).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000020, nCharsInRange, "Spacing Modifier Letters"); // bit 6 uint COMBINING_DIACRITICAL_MARKS_LOW = 0x0300; uint Combining_Diacritical_Marks_Supplement = 0x1DC0; nCharsInRange = ur.GetRange(COMBINING_DIACRITICAL_MARKS_LOW).count + ur.GetRange(Combining_Diacritical_Marks_Supplement).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000040, nCharsInRange, "Combining Diacritical Marks"); // bit 7 uint GREEK_LOW = 0x0370; nCharsInRange = ur.GetRange(GREEK_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000080, nCharsInRange, "Greek"); // v1: Greek Symbols and Coptic // v2/v3: Reserved for Unicode SubRanges // v4: Coptic 2C80-2CFF if (version > 1 && version < 4) { // bit 8 reserved if ((ulUnicodeRange1 & 0x00000100) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #8"); } } // TODO: v4 // bit 9 uint CYRILLIC_LOW = 0x0400; uint CYRILLIC_SUPPLEMENTARY_LOW = 0x0500; uint Cyrillic_Extended_A = 0x2DE0; uint Cyrillic_Extended_B = 0xA640; nCharsInRange = ur.GetRange(CYRILLIC_LOW).count + ur.GetRange(CYRILLIC_SUPPLEMENTARY_LOW).count + ur.GetRange(Cyrillic_Extended_A).count + ur.GetRange(Cyrillic_Extended_B).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange1, 0x00000200, nCharsInRange, "Cyrillic, Cyrillic Supplementary"); // bit 10 uint ARMENIAN_LOW = 0x0530; nCharsInRange = ur.GetRange(ARMENIAN_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000400, nCharsInRange, "Armenian"); // bit 11 uint HEBREW_LOW = 0x0590; nCharsInRange = ur.GetRange(HEBREW_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000800, nCharsInRange, "Hebrew"); // v1: Hebrew Extended (A and B blocks combined) // v2/v3: Reserved for Unicode SubRanges // v4: Vai A500-A63F if (version > 1 && version < 4) { // bit 12 reserved if ((ulUnicodeRange1 & 0x00001000) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #12"); } } // TODO: v4 // bit 13 uint ARABIC_LOW = 0x0600; uint Arabic_Supplement = 0x0750; nCharsInRange = ur.GetRange(ARABIC_LOW).count + ur.GetRange(Arabic_Supplement).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00002000, nCharsInRange, "Arabic"); // v1: Arabic Extended // v2/v3: Reserved for Unicode SubRanges // v4: NKo 07C0-07FF if (version > 1 && version < 4) { // bit 14 reserved if ((ulUnicodeRange1 & 0x00004000) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #14"); } } // TODO: v4 // bit 15 uint DEVANAGARI_LOW = 0x0900; nCharsInRange = ur.GetRange(DEVANAGARI_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00008000, nCharsInRange, "Devanagari"); // bit 16 uint BENGALI_LOW = 0x0980; nCharsInRange = ur.GetRange(BENGALI_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00010000, nCharsInRange, "Bengali"); // bit 17 uint GURMUKHI_LOW = 0x0A00; nCharsInRange = ur.GetRange(GURMUKHI_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00020000, nCharsInRange, "Gurmukhi"); // bit 18 uint GUJARATI_LOW = 0x0A80; nCharsInRange = ur.GetRange(GUJARATI_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00040000, nCharsInRange, "Gujarati"); // bit 19 uint ORIYA_LOW = 0x0B00; nCharsInRange = ur.GetRange(ORIYA_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00080000, nCharsInRange, "Oriya"); // bit 20 uint TAMIL_LOW = 0x0B80; nCharsInRange = ur.GetRange(TAMIL_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00100000, nCharsInRange, "Tamil"); // bit 21 uint TELUGU_LOW = 0x0C00; nCharsInRange = ur.GetRange(TELUGU_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00200000, nCharsInRange, "Telugu"); // bit 22 uint KANNADA_LOW = 0x0C80; nCharsInRange = ur.GetRange(KANNADA_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00400000, nCharsInRange, "Kannada"); // bit 23 uint MALAYALAM_LOW = 0x0D00; nCharsInRange = ur.GetRange(MALAYALAM_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00800000, nCharsInRange, "Malayalam"); // bit 24 uint THAI_LOW = 0x0E00; nCharsInRange = ur.GetRange(THAI_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x01000000, nCharsInRange, "Thai"); // bit 25 uint LAO_LOW = 0x0E80; nCharsInRange = ur.GetRange(LAO_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x02000000, nCharsInRange, "Lao"); // v3: Georgian // v4: Georgian 10A0-10FF // Georgian Supplement 2D00-2D2F // TODO: v4 // bit 26 uint GEORGIAN_LOW = 0x10A0; uint Georgian_Supplement = 0x2D00; nCharsInRange = ur.GetRange(GEORGIAN_LOW).count + ur.GetRange(Georgian_Supplement).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x04000000, nCharsInRange, "Georgian"); // v1: Georgian Extended // v2/v3: Reserved for Unicode SubRanges // v4: Balinese 1B00-1B7F if (version > 1 && version < 4) { // bit 27 reserved if ((ulUnicodeRange1 & 0x08000000) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #27"); } } // TODO: v4 // bit 28 uint HANGUL_JAMO_LOW = 0x1100; nCharsInRange = ur.GetRange(HANGUL_JAMO_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x10000000, nCharsInRange, "Hangul Jamo"); // bit 29 uint LATIN_EXTENDED_ADDITIONAL_LOW = 0x1E00; uint Latin_Extended_C = 0x2C60; uint Latin_Extended_D = 0xA720; nCharsInRange = ur.GetRange(LATIN_EXTENDED_ADDITIONAL_LOW).count + ur.GetRange(Latin_Extended_C).count + ur.GetRange(Latin_Extended_D).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x20000000, nCharsInRange, "Latin Extended Additional"); // bit 30 uint GREEK_EXTENDED_LOW = 0x1F00; nCharsInRange = ur.GetRange(GREEK_EXTENDED_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x40000000, nCharsInRange, "Greek Extended"); // bit 31 uint GENERAL_PUNCTUATION_LOW = 0x2000; uint Supplemental_Punctuation = 0x2E00; nCharsInRange = ur.GetRange(GENERAL_PUNCTUATION_LOW).count + ur.GetRange(Supplemental_Punctuation).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x80000000, nCharsInRange, "General Punctuation"); // bit 32 uint SUPER_SUB_SCRIPTS_LOW = 0x2070; nCharsInRange = ur.GetRange(SUPER_SUB_SCRIPTS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000001, nCharsInRange, "Superscripts and Subscripts"); // bit 33 uint CURRENCY_SYMBOLS_LOW = 0x20A0; nCharsInRange = ur.GetRange(CURRENCY_SYMBOLS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000002, nCharsInRange, "Currency Symbols"); // bit 34 uint SYMBOL_COMBINING_MARKS_LOW = 0x20D0; nCharsInRange = ur.GetRange(SYMBOL_COMBINING_MARKS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000004, nCharsInRange, "Combining Diacritical marks for symbols"); // bit 35 uint LETTERLIKE_SYMBOLS_LOW = 0x2100; nCharsInRange = ur.GetRange(LETTERLIKE_SYMBOLS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000008, nCharsInRange, "Letterlike Symbols"); // bit 36 uint NUMBER_FORMS_LOW = 0x2150; nCharsInRange = ur.GetRange(NUMBER_FORMS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000010, nCharsInRange, "Number Forms"); // bit 37 uint ARROWS_LOW = 0x2190; uint SUPPLEMENTAL_ARROWS_A_LOW = 0x27F0; uint SUPPLEMENTAL_ARROWS_B_LOW = 0x2900; uint Miscellaneous_Symbols_and_Arrows = 0x2B00; nCharsInRange = ur.GetRange(ARROWS_LOW).count + ur.GetRange(SUPPLEMENTAL_ARROWS_A_LOW).count + ur.GetRange(SUPPLEMENTAL_ARROWS_B_LOW).count + ur.GetRange(Miscellaneous_Symbols_and_Arrows).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x00000020, nCharsInRange, "Arrows, Supplementary Arrows A, Supplementary Arrows B"); // bit 38 uint MATH_OPERATORS_LOW = 0x2200; uint SUPPLEMENTAL_MATH_OPERATORS_LOW = 0x2A00; uint MISC_MATH_SYMBOLS_A_LOW = 0x27C0; uint MISC_MATH_SYMBOLS_B_LOW = 0x2980; nCharsInRange = ur.GetRange(MATH_OPERATORS_LOW).count + ur.GetRange(SUPPLEMENTAL_MATH_OPERATORS_LOW).count + ur.GetRange(MISC_MATH_SYMBOLS_A_LOW).count + ur.GetRange(MISC_MATH_SYMBOLS_B_LOW).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x00000040, nCharsInRange, "Mathematical Operators, Supplemental Mathematical Operators, Mathematical Symbols A, Mathematical Symbols B"); // bit 39 uint MISC_TECHNICAL_LOW = 0x2300; nCharsInRange = ur.GetRange(MISC_TECHNICAL_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000080, nCharsInRange, "Miscellaneous Technical"); // bit 40 uint CONTROL_PICTURES_LOW = 0x2400; nCharsInRange = ur.GetRange(CONTROL_PICTURES_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000100, nCharsInRange, "Control Pictures"); // bit 41 uint OCR_LOW = 0x2440; nCharsInRange = ur.GetRange(OCR_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000200, nCharsInRange, "Optical Character Recognition"); // bit 42 uint ENCLOSED_ALPHANUMERICS_LOW = 0x2460; nCharsInRange = ur.GetRange(ENCLOSED_ALPHANUMERICS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000400, nCharsInRange, "Enclosed Alphanumerics"); // bit 43 uint BOX_DRAWING_LOW = 0x2500; nCharsInRange = ur.GetRange(BOX_DRAWING_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000800, nCharsInRange, "Box Drawing"); // bit 44 uint BLOCK_ELEMENTS_LOW = 0x2580; nCharsInRange = ur.GetRange(BLOCK_ELEMENTS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00001000, nCharsInRange, "Block Elements"); // bit 45 uint GEOMETRIC_SHAPES_LOW = 0x25A0; nCharsInRange = ur.GetRange(GEOMETRIC_SHAPES_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00002000, nCharsInRange, "Geometric Shapes"); // bit 46 uint MISC_SYMBOLS_LOW = 0x2600; nCharsInRange = ur.GetRange(MISC_SYMBOLS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00004000, nCharsInRange, "Miscellaneous Symbols"); // bit 47 uint DINGBATS_LOW = 0x2700; nCharsInRange = ur.GetRange(DINGBATS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00008000, nCharsInRange, "Dingbats"); // bit 48 uint CJK_SYMBOLS_PUNCTUATION_LOW = 0x3000; nCharsInRange = ur.GetRange(CJK_SYMBOLS_PUNCTUATION_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00010000, nCharsInRange, "CJK Symbols and Punctuation"); // bit 49 uint HIRAGANA_LOW = 0x3040; nCharsInRange = ur.GetRange(HIRAGANA_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00020000, nCharsInRange, "Hiragana"); // bit 50 uint KATAKANA_LOW = 0x30A0; uint Katakana_Phonetic_Extensions = 0x31F0; nCharsInRange = ur.GetRange(KATAKANA_LOW).count + ur.GetRange(Katakana_Phonetic_Extensions).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00040000, nCharsInRange, "Katakana"); // bit 51 uint BOPOMOFO_LOW = 0x3100; uint BOPOMOFO_EXTENDED_LOW = 0x31A0; nCharsInRange = ur.GetRange(BOPOMOFO_LOW).count + ur.GetRange(BOPOMOFO_EXTENDED_LOW).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x00080000, nCharsInRange, "Bopomofo, Bopomofo Extended"); // bit 52 uint HANGUL_COMPAT_JAMO_LOW = 0x3130; nCharsInRange = ur.GetRange(HANGUL_COMPAT_JAMO_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00100000, nCharsInRange, "Hangul Compatibility Jamo"); // v2: CJK Miscellaneous // v3: Reserved for Unicode SubRanges // v4: Phags-pa A840-A87F // bit 53 !!! OT Spec 1.3 says bit 53 is CJK Misc !!! // !!! Since there's no unicode range name !!! // !!! that maps nicely to CJK Misc, !!! // !!! I naturally just ignore it. !!! /* bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00200000, nCharsInRange, "CJK Miscellaneous"); */ // TODO: v4 // bit 54 uint ENCLOSED_CJK_LETTERS_MONTHS_LOW = 0x3200; nCharsInRange = ur.GetRange(ENCLOSED_CJK_LETTERS_MONTHS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00400000, nCharsInRange, "Enclosed CJK Letters and Months"); // bit 55 uint CJK_COMPATIBILITY_LOW = 0x3300; nCharsInRange = ur.GetRange(CJK_COMPATIBILITY_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00800000, nCharsInRange, "CJK Compatibility"); // bit 56 uint HANGUL_LOW = 0xAC00; nCharsInRange = ur.GetRange(HANGUL_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x01000000, nCharsInRange, "Hangul"); // v1: Reserved for Unicode SubRanges // v2: Surrogates // v3: Non-Plane 0 * // v4: Non-Plane 0 * D800-DFFF // bit 57 surrogates if (version > 1) { bool bSurrogatesCmapPresent = false; Table_cmap cmapTable = (Table_cmap)fontOwner.GetTable("cmap"); if (cmapTable != null) { Table_cmap.EncodingTableEntry eteUniSurrogates = cmapTable.GetEncodingTableEntry(3,10); if (eteUniSurrogates != null) bSurrogatesCmapPresent = true; } if ((ulUnicodeRange2 & 0x02000000) == 0) { if (bSurrogatesCmapPresent) { v.Error(T.T_NULL, E.OS_2_E_SurrogatesBitClear, m_tag); bOk = false; } } else { if (!bSurrogatesCmapPresent) { v.Error(T.T_NULL, E.OS_2_E_SurrogatesBitSet, m_tag); bOk = false; } } } // v1/v2/v3: Reserved for Unicode SubRanges // v4: Phoenician 10900-1091F if (version < 4) { // bit 58 reserved if ((ulUnicodeRange2 & 0x04000000) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #58"); } } // TODO: v4 // bit 59 uint CJK_UNIFIED_IDEOGRAPHS_LOW = 0x4E00; uint CJK_RADICALS_SUPPLEMENT_LOW = 0x2E80; uint KANGXI_RADICALS_LOW = 0x2F00; uint IDEOGRAPHIC_DESCRIPTION_CHARS_LOW = 0x2FF0; uint CJK_UNIFIED_IDEOGRAPHS_EXT_A_LOW = 0x3400; uint CJK_UNIFIED_IDEOGRAPHS_EXT_B_LOW = 0x20000; uint KANBUN_LOW = 0x3190; nCharsInRange = ur.GetRange(CJK_UNIFIED_IDEOGRAPHS_LOW).count + ur.GetRange(CJK_RADICALS_SUPPLEMENT_LOW).count + ur.GetRange(KANGXI_RADICALS_LOW).count + ur.GetRange(IDEOGRAPHIC_DESCRIPTION_CHARS_LOW).count + ur.GetRange(CJK_UNIFIED_IDEOGRAPHS_EXT_A_LOW).count + ur.GetRange(CJK_UNIFIED_IDEOGRAPHS_EXT_B_LOW).count + ur.GetRange(KANBUN_LOW).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x08000000, nCharsInRange, "CJK Unified Ideographs, CJK Radicals Supplement, Kangxi Radicals, Ideographic Description Chars, CJK Unified Ideographs Extended A, CJK Unified Ideographs Extended B, Kanbun"); // bit 60 uint PRIVATE_USE_AREA_LOW = 0xE000; if (!fontOwner.ContainsMsSymbolEncodedCmap()) { nCharsInRange = ur.GetRange(PRIVATE_USE_AREA_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x10000000, nCharsInRange, "Private Use Area"); } // bit 61 uint CJK_Strokes = 0x31C0; uint CJK_COMPATIBILITY_IDEOGRAPHS_LOW = 0xF900; uint CJK_COMPATIBILITY_IDEO_SUPP_LOW = 0x2F800; nCharsInRange = ur.GetRange(CJK_Strokes).count + ur.GetRange(CJK_COMPATIBILITY_IDEOGRAPHS_LOW).count + ur.GetRange(CJK_COMPATIBILITY_IDEO_SUPP_LOW).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x20000000, nCharsInRange, "CJK Compatibility Ideographs, CJK Compatibility Ideographs Supplement"); // bit 62 uint ALPHABETIC_PRESENTATION_FORMS_LOW = 0xFB00; nCharsInRange = ur.GetRange(ALPHABETIC_PRESENTATION_FORMS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x40000000, nCharsInRange, "Alphabetic Presentation Forms"); // bit 63 uint ARABIC_PRESENTATION_FORMS_A_LOW = 0xFB50; nCharsInRange = ur.GetRange(ARABIC_PRESENTATION_FORMS_A_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x80000000, nCharsInRange, "Arabic Presentation Forms-A"); // bit 64 uint COMBINING_HALF_MARKS_LOW = 0xFE20; nCharsInRange = ur.GetRange(COMBINING_HALF_MARKS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000001, nCharsInRange, "Combining Half Marks"); // bit 65 uint Vertical_Forms = 0xFE10; uint CJK_COMPATIBILITY_FORMS_LOW = 0xFE30; nCharsInRange = ur.GetRange(Vertical_Forms).count + ur.GetRange(CJK_COMPATIBILITY_FORMS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000002, nCharsInRange, "CJK Compatibility Forms"); // bit 66 uint SMALL_FORM_VARIANTS_LOW = 0xFE50; nCharsInRange = ur.GetRange(SMALL_FORM_VARIANTS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000004, nCharsInRange, "Small Form Variants"); // bit 67 uint ARABIC_PRESENTATION_FORMS_B_LOW = 0xFE70; nCharsInRange = ur.GetRange(ARABIC_PRESENTATION_FORMS_B_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000008, nCharsInRange, "Arabic Presentation Forms-B"); // bit 68 uint HALFWIDTH_FULLWIDTH_FORMS_LOW = 0xFF00; nCharsInRange = ur.GetRange(HALFWIDTH_FULLWIDTH_FORMS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000010, nCharsInRange, "Halfwidth and Fullwidth Forms"); // bit 69 uint SPECIALS_LOW = 0xFFF0; nCharsInRange = ur.GetRange(SPECIALS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000020, nCharsInRange, "Specials"); // v1: 70-127 Reserved for Unicode SubRanges if (version < 2) { for (int bitpos = 6; bitpos < 32; bitpos++) { if ((ulUnicodeRange3 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (64+bitpos)); } } for (int bitpos = 0; bitpos < 32; bitpos++) { if ((ulUnicodeRange4 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (96+bitpos)); } } } else { // bit 70 uint TIBETAN_LOW = 0x0F00; nCharsInRange = ur.GetRange(TIBETAN_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000040, nCharsInRange, "Tibetan"); // bit 71 uint SYRIAC_LOW = 0x0700; nCharsInRange = ur.GetRange(SYRIAC_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000080, nCharsInRange, "Syriac"); // bit 72 uint THAANA_LOW = 0x0780; nCharsInRange = ur.GetRange(THAANA_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000100, nCharsInRange, "Thaana"); // bit 73 uint SINHALA_LOW = 0x0D80; nCharsInRange = ur.GetRange(SINHALA_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000200, nCharsInRange, "Sinhala"); // bit 74 uint MYANMAR_LOW = 0x1000; nCharsInRange = ur.GetRange(MYANMAR_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000400, nCharsInRange, "Myanmar"); // bit 75 uint ETHIOPIC_LOW = 0x1200; uint Ethiopic_Supplement = 0x1380; uint Ethiopic_Extended = 0x2D80; nCharsInRange = ur.GetRange(ETHIOPIC_LOW).count + ur.GetRange(Ethiopic_Supplement).count + ur.GetRange(Ethiopic_Extended).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000800, nCharsInRange, "Ethiopic"); // bit 76 uint CHEROKEE_LOW = 0x13A0; nCharsInRange = ur.GetRange(CHEROKEE_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00001000, nCharsInRange, "Cherokee"); // bit 77 uint UNIFIED_CANADIAN_AB_SYL_LOW = 0x1400; nCharsInRange = ur.GetRange(UNIFIED_CANADIAN_AB_SYL_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00002000, nCharsInRange, "Unified Canadian Syllabics"); // bit 78 uint OGHAM_LOW = 0x1680; nCharsInRange = ur.GetRange(OGHAM_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00004000, nCharsInRange, "Ogham"); // bit 79 uint RUNIC_LOW = 0x16A0; nCharsInRange = ur.GetRange(RUNIC_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00008000, nCharsInRange, "Runic"); // bit 80 uint KHMER_LOW = 0x1780; uint Khmer_Symbols = 0x19E0; nCharsInRange = ur.GetRange(KHMER_LOW).count + ur.GetRange(Khmer_Symbols).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00010000, nCharsInRange, "Khmer"); // bit 81 uint MONGOLIAN_LOW = 0x1800; nCharsInRange = ur.GetRange(MONGOLIAN_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00020000, nCharsInRange, "Mongolian"); // bit 82 uint BRAILLE_PATTERNS_LOW = 0x2800; nCharsInRange = ur.GetRange(BRAILLE_PATTERNS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00040000, nCharsInRange, "Braille"); // bit 83 uint YI_LOW = 0xA000; uint YI_RADICALS_LOW = 0xA490; nCharsInRange = ur.GetRange(YI_LOW).count + ur.GetRange(YI_RADICALS_LOW).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange3, 0x00080000, nCharsInRange, "Yi, Yi Radicals"); // v2: 84-127 Reserved for Unicode SubRanges if (version < 3) { for (int bitpos = 20; bitpos < 32; bitpos++) { if ((ulUnicodeRange3 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (64+bitpos)); } } for (int bitpos = 0; bitpos < 32; bitpos++) { if ((ulUnicodeRange4 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (96+bitpos)); } } } else { // bit 84 uint TAGALOG_LOW = 0x1700; uint HANUNOO_LOW = 0x1720; uint BUHID_LOW = 0x1740; uint TAGBANWA_LOW = 0x1760; nCharsInRange = ur.GetRange(TAGALOG_LOW).count + ur.GetRange(HANUNOO_LOW).count + ur.GetRange(BUHID_LOW).count + ur.GetRange(TAGBANWA_LOW).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange3, 0x00100000, nCharsInRange, "Tagalog, Hanunoo, Buhid, Tagbanwa"); // bit 85 uint OLD_ITALIC_LOW = 0x10300; nCharsInRange = ur.GetRange(OLD_ITALIC_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00200000, nCharsInRange, "Old Italic"); // bit 86 uint GOTHIC_LOW = 0x10330; nCharsInRange = ur.GetRange(GOTHIC_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00400000, nCharsInRange, "Gothic"); // bit 87 uint DESERET_LOW = 0x10400; nCharsInRange = ur.GetRange(DESERET_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00800000, nCharsInRange, "Deseret"); // bit 88 uint BYZANTINE_MUSICAL_SYMBOLS_LOW = 0x1D000; uint MUSICAL_SYMBOLS_LOW = 0x1D100; uint Ancient_Greek_Musical_Notation = 0x1D200; nCharsInRange = ur.GetRange(BYZANTINE_MUSICAL_SYMBOLS_LOW).count + ur.GetRange(MUSICAL_SYMBOLS_LOW).count + ur.GetRange(Ancient_Greek_Musical_Notation).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange3, 0x01000000, nCharsInRange, "Byzantine Musical Symbols, Musical Symbols"); // bit 89 uint MATHEMATICAL_ALPHANUMERIC_LOW = 0x1D400; nCharsInRange = ur.GetRange(MATHEMATICAL_ALPHANUMERIC_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x02000000, nCharsInRange, "Mathematical Alphanumeric Symbols"); // bit 90 uint PRIVATE_USE_15_LOW = 0xFFF80; uint PRIVATE_USE_16_LOW = 0x10FF80; nCharsInRange = ur.GetRange(PRIVATE_USE_15_LOW).count + ur.GetRange(PRIVATE_USE_16_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x04000000, nCharsInRange, "Private Use (Plane 15), Private Use (Plane 16)"); // bit 91 uint Variation_Selectors = 0xFE00; uint VARIATION_SELECTORS_SUPP = 0xE0100; nCharsInRange = ur.GetRange(Variation_Selectors).count + ur.GetRange(VARIATION_SELECTORS_SUPP).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x08000000, nCharsInRange, "Variation Selectors"); // bit 92 uint TAGS_LOW = 0xE0000; nCharsInRange = ur.GetRange(TAGS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x10000000, nCharsInRange, "Tags"); // v3: 93-127 Reserved for Unicode SubRanges if (version < 4) { for (int bitpos = 29; bitpos < 32; bitpos++) { if ((ulUnicodeRange3 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (64+bitpos)); } } for (int bitpos = 0; bitpos < 32; bitpos++) { if ((ulUnicodeRange4 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (96+bitpos)); } } } else { // v4 addition /* 93 Limbu 1900-194F 94 Tai Le 1950-197F 95 New Tai Lue 1980-19DF 96 Buginese 1A00-1A1F 97 Glagolitic 2C00-2C5F 98 Tifinagh 2D30-2D7F 99 Yijing Hexagram Symbols 4DC0-4DFF 100 Syloti Nagri A800-A82F 101 Linear B Syllabary 10000-1007F Linear B Ideograms 10080-100FF Aegean Numbers 10100-1013F 102 Ancient Greek Numbers 10140-1018F 103 Ugaritic 10380-1039F 104 Old Persian 103A0-103DF 105 Shavian 10450-1047F 106 Osmanya 10480-104AF 107 Cypriot Syllabary 10800-1083F 108 Kharoshthi 10A00-10A5F 109 Tai Xuan Jing Symbols 1D300-1D35F 110 Cuneiform 12000-123FF Cuneiform Numbers and Punctuation 12400-1247F 111 Counting Rod Numerals 1D360-1D37F 112 Sundanese 1B80-1BBF 113 Lepcha 1C00-1C4F 114 Ol Chiki 1C50-1C7F 115 Saurashtra A880-A8DF 116 Kayah Li A900-A92F 117 Rejang A930-A95F 118 Cham AA00-AA5F 119 Ancient Symbols 10190-101CF 120 Phaistos Disc 101D0-101FF 121 Carian 102A0-102DF Lycian 10280-1029F Lydian 10920-1093F 122 Domino Tiles 1F030-1F09F Mahjong Tiles 1F000-1F02F 123-127 Reserved for process-internal usage */ // TODO: v4 addition } } } if (bOk) { v.Pass(P.OS_2_P_UnicodeRanges, m_tag); } else { 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, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.cmap_Version)) { if (TableVersionNumber == 0) { v.Pass(T.cmap_Version, P.cmap_P_version, m_tag); } else { v.Error(T.cmap_Version, E.cmap_E_version, m_tag, TableVersionNumber.ToString()); bRet = false; } } // Check that the number of encoding records seems to // agree with the numTables field, and that each offset // is greater than 0 and less than the length of the cmap // table. bool bOffsetsOk = true; if (v.PerformTest(T.cmap_SubtableOffset)) { for (uint i=0; i<NumberOfEncodingTables; i++) { EncodingTableEntry ete = GetEncodingTableEntry(i); if (ete != null) { if (ete.offset == 0) { v.Error(T.cmap_SubtableOffset, E.cmap_E_SubtableOffset_zero, m_tag, "encoding table entry index = " + i.ToString() + ", platformID = " + ete.platformID + ", encodingID = " + ete.encodingID); bRet = false; bOffsetsOk = false; } if (ete.offset > m_bufTable.GetLength()) { v.Error(T.cmap_SubtableOffset, E.cmap_E_SubtableOffset_eot, m_tag, "encoding table entry index = " + i.ToString() + ", platformID = " + ete.platformID + ", encodingID = " + ete.encodingID); bRet = false; bOffsetsOk = false; } } else { v.Warning(T.cmap_SubtableOffset, W._TEST_W_OtherErrorsInTable, m_tag, "cmap table appears to be corrupt. " + " No further tests will be performed."); return bRet; } } if (bOffsetsOk) { v.Pass(T.cmap_SubtableOffset, P.cmap_P_SubtableOffset, m_tag); } } // Check that each subtable can be retrieved from the font // and that its offset + length lies within the cmap. bool bLengthsOk = true; if (v.PerformTest(T.cmap_SubtableLength)) { for (uint i=0; i<NumberOfEncodingTables; i++) { EncodingTableEntry ete = GetEncodingTableEntry(i); Subtable st = GetSubtable(ete); if (st != null) { if (st.length == 0) { v.Error(T.cmap_SubtableLength, E.cmap_E_SubtableLength_zero, m_tag, i.ToString()); bRet = false; bLengthsOk = false; } if (ete.offset + st.length > m_bufTable.GetLength()) { v.Error(T.cmap_SubtableLength, E.cmap_E_SubtableLength_eot, m_tag, i.ToString()); bRet = false; bLengthsOk = false; } } else { string sDetails = "PlatID = " + ete.platformID + ", EncID = " + ete.encodingID; v.Warning(T.cmap_SubtableLength, W._TEST_W_OtherErrorsInTable, m_tag, "unable to validate the length of subtable - " + sDetails); bLengthsOk = false; } } if (bLengthsOk) { v.Pass(T.cmap_SubtableLength, P.cmap_P_SubtableLength, m_tag); } } // Assuming previous tests ok, check that sort order is by // 1. increasing platformID // 2. increasing encodingID // 3. increasing language if (v.PerformTest(T.cmap_SubtableSortOrder)) { if (bOffsetsOk && bLengthsOk) { bool bOrderOk = true; if (NumberOfEncodingTables > 1) { EncodingTableEntry etePrev = GetEncodingTableEntry(0); for (uint i=1; i<NumberOfEncodingTables; i++) { EncodingTableEntry ete = GetEncodingTableEntry(i); if (etePrev.platformID == ete.platformID) { if (etePrev.encodingID == ete.encodingID) { Subtable stPrev = GetSubtable(etePrev); Subtable st = GetSubtable(ete); if (stPrev.language > st.language) { bOrderOk = false; } } else if (etePrev.encodingID > ete.encodingID) { bOrderOk = false; } } else if (etePrev.platformID > ete.platformID) { bOrderOk = false; } etePrev = ete; } } if (bOrderOk) { v.Pass(T.cmap_SubtableSortOrder, P.cmap_P_SubtableSortOrder, m_tag); } else { v.Error(T.cmap_SubtableSortOrder, E.cmap_E_SubtableSortOrder, m_tag); bRet = false; } } else { v.Warning(T.cmap_SubtableSortOrder, W._TEST_W_OtherErrorsInTable, m_tag, "unable to validate sort order"); } } // Check that no encoding record has the same // (platformID,encodingID,language) // as the previous one. if (v.PerformTest(T.cmap_DuplicateSubtables)) { if (bOffsetsOk && bLengthsOk) { bool bNoDuplicates = true; if (NumberOfEncodingTables > 1) { EncodingTableEntry etePrev = GetEncodingTableEntry(0); for (uint i=1; i<NumberOfEncodingTables; i++) { EncodingTableEntry ete = GetEncodingTableEntry(i); if (etePrev.platformID == ete.platformID) { if (etePrev.encodingID == ete.encodingID) { Subtable stPrev = GetSubtable(etePrev); Subtable st = GetSubtable(ete); if (stPrev.language == st.language) { bNoDuplicates = false; } } } etePrev = ete; } } if (bNoDuplicates) { v.Pass(T.cmap_DuplicateSubtables, P.cmap_P_DuplicateSubtables, m_tag); } else { v.Error(T.cmap_DuplicateSubtables, E.cmap_E_DuplicateSubtables, m_tag); bRet = false; } } else { string unable = "unable to validate that there are " + "no duplicate subtables"; v.Warning(T.cmap_DuplicateSubtables, W._TEST_W_OtherErrorsInTable, m_tag, unable ); } } // Check that no subtable overlaps and subtable following it, // in other words, check for the beginning of one subtable // falling within the bounds of a subtable that follows it. if (v.PerformTest(T.cmap_SubtableOverlap)) { if (bOffsetsOk && bLengthsOk) { bool bNoOverlap = true; if (NumberOfEncodingTables > 1) { for (uint i=0; i<NumberOfEncodingTables; i++) { EncodingTableEntry ete1 = GetEncodingTableEntry(i); Subtable st1 = GetSubtable(ete1); for (uint j=i+1; j<NumberOfEncodingTables; j++) { EncodingTableEntry ete2 = GetEncodingTableEntry(j); Subtable st2 = GetSubtable(ete2); if ( (ete1.offset > ete2.offset && ete1.offset < ete2.offset + st2.length) || (ete2.offset > ete1.offset && ete2.offset < ete1.offset + st1.length) ) { v.Error(T.cmap_SubtableOverlap, E.cmap_E_SubtableOverlap, m_tag, i.ToString() + " " + j.ToString()); bRet = false; bNoOverlap = true; } } } } if (bNoOverlap) { v.Pass(T.cmap_SubtableOverlap, P.cmap_P_SubtableOverlap, m_tag); } } else { v.Warning(T.cmap_SubtableOverlap, W._TEST_W_OtherErrorsInTable, m_tag, "unable to validate that no subtables overlap"); } } // Check that all subtable formats (First USHORT in the subtable) // is an even number between 0 and 14, inclusive. if (v.PerformTest(T.cmap_ValidFormat)) { bool bAllFormatsValid = true; for (uint i=0; i<NumberOfEncodingTables; i++) { EncodingTableEntry ete = GetEncodingTableEntry(i); if (ete.offset < m_bufTable.GetLength()-1) { // the format of the subtable is the first uint16 ushort format = m_bufTable.GetUshort(ete.offset); if (format > HIGHEST_FORMAT || ((format&1)==1)) { string sDetails = "PlatID = " + ete.platformID + ", EncID = " + ete.encodingID + ", Fmt = " + format; v.Error(T.cmap_ValidFormat, E.cmap_E_SubtableValidFormat, m_tag, sDetails); bRet = false; bAllFormatsValid = false; } } else { string sDetails = "PlatID = " + ete.platformID + ", EncID = " + ete.encodingID; string unable = "unable to validate format number for subtable - "; v.Warning(T.cmap_ValidFormat, W._TEST_W_OtherErrorsInTable, m_tag, unable + sDetails); bAllFormatsValid = false; } } if (bAllFormatsValid) { v.Pass(T.cmap_ValidFormat, P.cmap_P_SubtableValidFormat, m_tag); } } // Assuming maxp is present, get the number of glyphs from maxp, // and for each subtable, run its validate routine. if (v.PerformTest(T.cmap_SubtableInternalFormat)) { if (fontOwner.GetTable("maxp") == null) { string cant = "can't check subtable internal formats - " + "maxp table inaccessible"; v.Warning(T.cmap_SubtableInternalFormat, W._TEST_W_ErrorInAnotherTable, m_tag, cant ); } else { for (uint i=0; i<NumberOfEncodingTables; i++) { bool bInternalFormatOk = true; EncodingTableEntry ete = GetEncodingTableEntry(i); Subtable st = GetSubtable(ete); if (st != null) { ushort numGlyphs = fontOwner.GetMaxpNumGlyphs(); string sIdentity = "PlatID = " + ete.platformID + ", EncID = " + ete.encodingID + ", Fmt = " + st.format; ISubtableValidate valSubtable = (ISubtableValidate)st; bInternalFormatOk = valSubtable.Validate(v, this, numGlyphs, sIdentity); bRet &= bInternalFormatOk; if (bInternalFormatOk) { v.Pass(T.cmap_SubtableInternalFormat, P.cmap_P_InternalFormat, m_tag, sIdentity); } } else { string sDetails = "PlatID = " + ete.platformID + ", EncID = " + ete.encodingID; v.Warning(T.cmap_SubtableInternalFormat, W._TEST_W_OtherErrorsInTable, m_tag, "unable to validate internal format " + "for subtable - " + sDetails); } } } } // Pass if there is at least one subtable with platformID == 1 and // one subtable with platformID == 3. // Warn if either is missing. if (v.PerformTest(T.cmap_AppleMSSupport)) { bool bFoundApple = false; bool bFoundMS = false; for (uint i=0; i<NumberOfEncodingTables; i++) { EncodingTableEntry ete = GetEncodingTableEntry(i); if (ete.platformID == 1) { bFoundApple = true; } else if (ete.platformID == 3) { bFoundMS = true; } } if (bFoundApple && bFoundMS) { v.Pass(T.cmap_AppleMSSupport, P.cmap_P_AppleMSSupport, m_tag); } else if (!bFoundApple) { v.Warning(T.cmap_AppleMSSupport, W.cmap_W_AppleMSSupport_A, m_tag); } else if (!bFoundMS) { v.Warning(T.cmap_AppleMSSupport, W.cmap_W_AppleMSSupport_M, m_tag); } } // Find encoding table with platformID==1, encodingID==0 // i.e., Macintosh. Make sure that the Apple Logo, code point 240, // is mapped to glyphID 0, a legal requirement for Microsoft fonts // developed for use on Apple platforms. if (v.PerformTest(T.cmap_AppleLogo)) { EncodingTableEntry ete = GetEncodingTableEntry(1,0); if (ete != null) { Subtable st = GetSubtable(ete); if (st != null) { byte[] charbuf = new byte[2]; charbuf[0] = 240; charbuf[1] = 0; uint glyph = st.MapCharToGlyph(charbuf, 0); if (glyph == 0) { v.Pass(T.cmap_AppleLogo, P.cmap_P_AppleLogo, m_tag); } else { v.Warning(T.cmap_AppleLogo, W.cmap_W_AppleLogo, m_tag); } } else { string sDetails = "PlatID = " + ete.platformID + ", EncID = " + ete.encodingID; string unable = "unable to validate apple logo for subtable - "; v.Warning(T.cmap_AppleLogo, W._TEST_W_OtherErrorsInTable, m_tag, unable + sDetails); } } else { v.Warning(T.cmap_AppleLogo, W.cmap_W_AppleLogo_NoMap, m_tag); } } // Euro symbol. // Unless there is a Microsoft Symbol encoding cmap (3,0): // * Make sure that any apple cmap(1,0) contains a glyph U+00db // * Make sure that any Microsoft Unicode cmap (3,1) contains // a glyph U+20AC. if (v.PerformTest(T.cmap_EuroGlyph)) { EncodingTableEntry eteSym = GetEncodingTableEntry(3,0); if (eteSym == null) { EncodingTableEntry eteMac = GetEncodingTableEntry(1,0); if (eteMac != null) { Subtable st = GetSubtable(eteMac); if (st != null) { byte[] charbuf = new byte[2]; charbuf[0] = 0xdb; charbuf[1] = 0; uint glyph = st.MapCharToGlyph(charbuf, 0); if (glyph != 0) { v.Pass(T.cmap_EuroGlyph, P.cmap_P_EuroGlyph_Mac, m_tag); } else { v.Warning(T.cmap_EuroGlyph, W.cmap_W_EuroGlyph_Mac, m_tag); } } else { string sDetails = "PlatID = " + eteMac.platformID + ", EncID = " + eteMac.encodingID; string unable = "unable to validate if euro glyph " + "is present for subtable - "; v.Warning(T.cmap_EuroGlyph, W._TEST_W_OtherErrorsInTable, m_tag, unable + sDetails); } } EncodingTableEntry eteUni = GetEncodingTableEntry(3,1); if (eteUni != null) { Subtable st = GetSubtable(eteUni); if (st != null) { byte[] charbuf = new byte[2]; charbuf[0] = 0xac; charbuf[1] = 0x20; uint glyph = st.MapCharToGlyph(charbuf, 0); if (glyph != 0) { v.Pass(T.cmap_EuroGlyph, P.cmap_P_EuroGlyph_Uni, m_tag); } else { v.Warning(T.cmap_EuroGlyph, W.cmap_W_EuroGlyph_Uni, m_tag); } } else { string sDetails = "PlatID = " + eteMac.platformID + ", EncID = " + eteMac.encodingID; string unable = "unable to validate if euro glyph" + " is present for subtable - "; v.Warning(T.cmap_EuroGlyph, W._TEST_W_OtherErrorsInTable, m_tag, unable + sDetails); } } } } // Make sure that no glyphs, other than "fi" and "fl" ligatures, // are mapped from the "private use area", that is, // 0xE000 - 0xF8FF. The above ligatures may only be a the // prescribed places. // // Checks that 0xf001 and 0xfb01 map to the same place, and // Checks that 0xf002 and 0xfb02 map to the same place. // // Only warn if a problem. if (v.PerformTest(T.cmap_PrivateUse)) { EncodingTableEntry eteUni = GetEncodingTableEntry(3,1); if (eteUni != null) { Subtable st = GetSubtable(eteUni); if (st != null) { bool bFoundGlyph = false; bool bFoundLigChar = false; byte[] charbuf = new byte[2]; for (char c='\xe000'; c<'\xf8ff'; c++) { uint glyph = fontOwner.FastMapUnicodeToGlyphID(c); if (glyph != 0) { if (c == '\xf001') { // check to see if this is the 'fi' ligature uint glyph2 = fontOwner. FastMapUnicodeToGlyphID('\xfb01'); if (glyph == glyph2) { bFoundLigChar = true; } else { bFoundGlyph = true; break; } } else if (c == '\xf002') { // check to see if this is the 'fl' ligature uint glyph2 = fontOwner. FastMapUnicodeToGlyphID('\xfb02'); if (glyph == glyph2) { bFoundLigChar = true; } else { bFoundGlyph = true; break; } } else { bFoundGlyph = true; break; } } } if (bFoundGlyph) { v.Warning(T.cmap_PrivateUse, W.cmap_W_UnicodePrivateUse, m_tag); } else if (bFoundLigChar) { v.Pass(T.cmap_PrivateUse, P.cmap_P_UnicodePrivateUse_lig, m_tag); } else { v.Pass(T.cmap_PrivateUse, P.cmap_P_UnicodePrivateUse, m_tag); } } else { string sDetails = "PlatID = " + eteUni.platformID + ", EncID = " + eteUni.encodingID; v.Warning(T.cmap_PrivateUse, W._TEST_W_OtherErrorsInTable, m_tag, "unable to validate Private Use Area " + "for subtable - " + sDetails); } } } // Check that subtable language field is zero if not mac platform if (v.PerformTest(T.cmap_NonMacSubtableLanguage)) { bool bOk = true; for (uint i=0; i<NumberOfEncodingTables; i++) { EncodingTableEntry ete = GetEncodingTableEntry(i); Subtable st = GetSubtable(ete); if (st != null) { if (ete.platformID != 1) // not mac { if (st.language != 0) { string sDetails = "PlatID = " + ete.platformID + ", EncID = " + ete.encodingID + ", Language = " + st.language; v.Error(T.cmap_SubtableLanguage, E.cmap_E_NonMacSubtableLanguage, m_tag, sDetails); bOk = false; } } } } if (bOk) { v.Pass(T.cmap_SubtableLanguage, P.cmap_P_NonMacSubtableLanguage, m_tag); } } 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; }
protected bool CheckForNoUnnecessaryTables(Validator v) { bool bRet = true; bool bFoundUnnecessary = false; Table_hmtx hmtxTable = (Table_hmtx)GetTable("hmtx"); if (hmtxTable != null) { if (hmtxTable.IsMonospace(this)) { if (GetDirectoryEntry("hdmx") != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "hdmx table not needed for monospaced font"); bFoundUnnecessary = true; } if (GetDirectoryEntry("LTSH") != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "LTSH table not needed for monospaced font"); bFoundUnnecessary = true; } if (GetDirectoryEntry("kern") != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "kern table not needed for monospaced font"); bFoundUnnecessary = true; } } if (GetDirectoryEntry("CFF ") == null && GetDirectoryEntry("VORG") != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "VORG table not needed, it may optionally be present for fonts with Postscript outlines"); bFoundUnnecessary = true; } if (GetDirectoryEntry("PCLT") != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "PCLT table not needed, Microsoft no longer recommends including this table"); bFoundUnnecessary = true; } } if (GetDirectoryEntry("CFF ") != null) { string [] UnnecessaryTables = { "glyf", "fpgm", "cvt ", "loca", "prep" }; for (int i = 0; i < UnnecessaryTables.Length; i++) { if (GetDirectoryEntry(UnnecessaryTables[i]) != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, UnnecessaryTables[i] + " not needed since the font contains a 'CFF ' table"); bFoundUnnecessary = true; } } } if (GetDirectoryEntry("glyf") != null) { if (GetDirectoryEntry("CFF ") != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "CFF not needed since the font contains a 'CFF ' table"); bFoundUnnecessary = true; } } if (ContainsLatinOnly()) { if (GetDirectoryEntry("vhea") != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "vhea not needed since the font only contains Latin characters"); bFoundUnnecessary = true; } if (GetDirectoryEntry("vmtx") != null) { v.Warning(T.T_NULL, W._FONT_W_UnnecessaryTable, null, "vmtx not needed since the font only contains Latin characters"); bFoundUnnecessary = true; } } if (!bFoundUnnecessary) { v.Pass(P._FONT_P_UnnecessaryTable, null); } 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 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; 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; }
protected bool CheckForOptimalTableOrder(Validator v) { bool bRet = true; if (!GetFile().IsCollection()) // don't perform this test on .ttc files { string [] OrderedTables = null; string [] TTOrderedTables = { "head", "hhea", "maxp", "OS/2", "hmtx", "LTSH", "VDMX", "hdmx", "cmap", "fpgm", "prep", "cvt ", "loca", "glyf", "kern", "name", "post", "gasp", "PCLT" /*"DSIG"*/ }; string [] PSOrderedTables = { "head", "hhea", "maxp", "OS/2", "name", "cmap", "post", "CFF " }; if (ContainsTrueTypeOutlines()) { OrderedTables = TTOrderedTables; } else if (ContainsPostScriptOutlines()) { OrderedTables = PSOrderedTables; } if (OrderedTables != null) { Debug.Assert(m_OffsetTable != null); bool bOrderOk = true; if (m_OffsetTable != null) { for (int i=0; i<OrderedTables.Length-1; i++) { for (int j=i+1; j<OrderedTables.Length; j++) { DirectoryEntry deBefore = GetDirectoryEntry(OrderedTables[i]); DirectoryEntry deAfter = GetDirectoryEntry(OrderedTables[j]); if (deBefore != null && deAfter != null) { if (deBefore.offset > deAfter.offset) { string sDetails = "table '" + deAfter.tag + "' precedes table '" + deBefore.tag + "'"; v.Warning(T.T_NULL, W._FONT_W_OptimalOrder, null, sDetails); bOrderOk = false; break; } } } if (!bOrderOk) { break; } } } if (bOrderOk) { v.Pass(P._FONT_P_OptimalOrder, null); } } } return bRet; }
protected bool CheckForRecommendedTables(Validator v) { bool bRet = true; bool bMissing = false; if (!IsPostScript()) { if (GetDirectoryEntry("gasp") == null) { v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "gasp"); bMissing = true; } Table_hmtx hmtxTable = (Table_hmtx)GetTable("hmtx"); if (hmtxTable != null) { if (!hmtxTable.IsMonospace(this) && !ContainsSymbolsOnly()) { if (GetDirectoryEntry("kern") == null) { v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "kern"); bMissing = true; } if (GetDirectoryEntry("hdmx") == null) { v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "hdmx"); bMissing = true; } } } if (GetDirectoryEntry("VDMX") == null) { v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "VDMX"); bMissing = true; } } if (GetDirectoryEntry("DSIG") == null) { v.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "DSIG"); bMissing = true; } if (!bMissing) { v.Pass(P._FONT_P_MissingRecommendedTable, null); } return bRet; }
protected bool CheckForRequiredTables(Validator v) { bool bRet = true; string [] RequiredTables = { "cmap", "head", "hhea", "hmtx", "maxp", "name", "OS/2", "post" }; for (int i = 0; i < RequiredTables.Length; i++) { if (GetDirectoryEntry(RequiredTables[i]) == null) { v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, RequiredTables[i]); bRet = false; } } if (GetDirectoryEntry("glyf") == null && GetDirectoryEntry("CFF ") == null && GetDirectoryEntry("CFF2") == null && GetDirectoryEntry("EBDT") == null && GetDirectoryEntry("CBDT") == null) { v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "Font must contain either a 'glyf', 'CFF ', 'CFF2', 'EBDT' or 'CBDT' table"); bRet = false; } if (GetDirectoryEntry("glyf") != null) { string [] RequiredGlyphTables = { "loca" }; for (int i = 0; i < RequiredGlyphTables.Length; i++) { if (GetDirectoryEntry(RequiredGlyphTables[i]) == null) { v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, RequiredGlyphTables[i] + " is required since the font contains a glyf table"); bRet = false; } } } if (GetDirectoryEntry("EBDT") != null) { if (GetDirectoryEntry("EBLC") == null) { v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "EBLC is required since the font contains an EBDT table"); bRet = false; } } if (GetDirectoryEntry("EBLC") != null) { if (GetDirectoryEntry("EBDT") == null) { v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "EBDT is required since the font contains an EBLC table"); bRet = false; } } if (GetDirectoryEntry("EBSC") != null) { if (GetDirectoryEntry("EBDT") == null) { v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "EBDT is required since the font contains an EBSC table"); bRet = false; } if (GetDirectoryEntry("EBLC") == null) { v.Error(T.T_NULL, E._FONT_E_MissingRequiredTable, null, "EBLC is required since the font contains an EBSC table"); bRet = false; } } if (bRet) { v.Pass(P._FONT_P_MissingRequiredTable, null); } 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; }
protected bool CheckTagNames(Validator v) { Debug.Assert(m_OffsetTable != null); bool bRet = false; if (m_OffsetTable != null) { bRet = true; for (int i = 0; i<m_OffsetTable.DirectoryEntries.Count; i++) { DirectoryEntry de = (DirectoryEntry)m_OffsetTable.DirectoryEntries[i]; if (!de.tag.IsValid()) { v.Error(T.T_NULL, E._DE_E_TagName, null, (string)de.tag); bRet = false; } } if (bRet == true) { v.Pass(P._DE_P_TagName, null); } } 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 methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.PCLT_TableLength)) { if (GetLength() == 54) { v.Pass(T.PCLT_TableLength, P.PCLT_P_TableLength, m_tag); } else { v.Error(T.PCLT_TableLength, E.PCLT_E_TableLength, m_tag, GetLength().ToString()); bRet = false; } } if (v.PerformTest(T.PCLT_Version)) { if (Version.GetUint() == 0x00010000) { v.Pass(T.PCLT_Version, P.PCLT_P_Version, m_tag); } else { v.Error(T.PCLT_Version, E.PCLT_E_Version, m_tag, "0x"+Version.GetUint().ToString("x8")); bRet = false; } } if (v.PerformTest(T.PCLT_Pitch)) { Table_hmtx hmtxTable = (Table_hmtx)fontOwner.GetTable("hmtx"); Table_maxp maxpTable = (Table_maxp)fontOwner.GetTable("maxp"); if (hmtxTable == null) { v.Error(T.PCLT_Pitch, E._TEST_E_TableMissing, m_tag, "hmtx"); bRet = false; } else if (maxpTable == null) { v.Error(T.PCLT_Pitch, E._TEST_E_TableMissing, m_tag, "maxp"); bRet = false; } else { uint iSpaceGlyph = fontOwner.FastMapUnicodeToGlyphID(' '); if (iSpaceGlyph < fontOwner.GetMaxpNumGlyphs()) { Table_hmtx.longHorMetric hmSpace = hmtxTable.GetOrMakeHMetric(iSpaceGlyph, fontOwner); if (hmSpace != null) { if (Pitch == hmSpace.advanceWidth) { v.Pass(T.PCLT_Pitch, P.PCLT_P_Pitch, m_tag); } else { string s = "actual = " + Pitch + ", expected = " + hmSpace.advanceWidth; v.Error(T.PCLT_Pitch, E.PCLT_E_Pitch, m_tag, s); bRet = false; } } } else { // JJF Figure out what to do v.Warning(T.PCLT_Pitch, W._TEST_W_ErrorInAnotherTable, m_tag, "can't validate Pitch field, error getting the space glyph"); bRet = false; } } } if (v.PerformTest(T.PCLT_Style)) { ushort Posture = (ushort)(Style & 0x0003); ushort Width = (ushort)((Style>>2) & 0x0007); ushort Structure = (ushort)((Style>>5) & 0x001f); ushort Reserved = (ushort)(Style>>10); bool bBitsOk = true; if (Posture == 3) { v.Error(T.PCLT_Style, E.PCLT_E_Style_Posture, m_tag, "0x"+Style.ToString("x4")); bBitsOk = false; bRet = false; } if (Width == 5) { v.Error(T.PCLT_Style, E.PCLT_E_Style_Width, m_tag, "0x"+Style.ToString("x4")); bBitsOk = false; bRet = false; } if (Structure > 17) { v.Error(T.PCLT_Style, E.PCLT_E_Style_Structure, m_tag, "0x"+Style.ToString("x4")); bBitsOk = false; bRet = false; } if (Reserved != 0) { v.Error(T.PCLT_Style, E.PCLT_E_Style_Reserved, m_tag, "0x"+Style.ToString("x4")); bBitsOk = false; bRet = false; } if (bBitsOk) { v.Pass(T.PCLT_Style, P.PCLT_P_Style, m_tag); } } if (v.PerformTest(T.PCLT_StrokeWeight)) { if (StrokeWeight >= -7 && StrokeWeight <= 7) { v.Pass(T.PCLT_StrokeWeight, P.PCLT_P_StrokeWeight, m_tag, StrokeWeight.ToString()); } else { v.Error(T.PCLT_StrokeWeight, E.PCLT_E_StrokeWeight, m_tag, StrokeWeight.ToString()); bRet = false; } } if (v.PerformTest(T.PCLT_WidthType)) { if (WidthType >= -5 && WidthType <= 5) { v.Pass(T.PCLT_WidthType, P.PCLT_P_WidthType, m_tag, WidthType.ToString()); } else { v.Error(T.PCLT_WidthType, E.PCLT_E_WidthType, m_tag, WidthType.ToString()); bRet = false; } } if (v.PerformTest(T.PCLT_SerifStyle)) { uint bot6 = (uint)SerifStyle & 0x3f; uint top2 = (uint)SerifStyle>>6; bool bBitsOk = true; if (bot6 > 12) { v.Error(T.PCLT_SerifStyle, E.PCLT_E_Bottom6, m_tag, "0x"+SerifStyle.ToString("x2")); bBitsOk = false; bRet = false; } if (top2 == 0 || top2 == 3) { v.Error(T.PCLT_SerifStyle, E.PCLT_E_Top2, m_tag); bBitsOk = false; bRet = false; } if (bBitsOk) { v.Pass(T.PCLT_SerifStyle, P.PCLT_P_SerifStyle, m_tag); } } if (v.PerformTest(T.PCLT_Reserved)) { if (Reserved == 0) { v.Pass(T.PCLT_Reserved, P.PCLT_P_Reserved, m_tag); } else { v.Error(T.PCLT_Reserved, E.PCLT_E_Reserved, m_tag, Reserved.ToString()); bRet = false; } } return bRet; }
private bool CheckUnicodeRanges(Validator v, OTFont fontOwner) { bool bRet = true; bool bOk = true; if (version == 0) { if (ulUnicodeRange1 != 0) { v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "Range[0] was undefined. All bits must be 0."); bOk = false; } if (ulUnicodeRange2 != 0) { v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "Range[1] was undefined. All bits must be 0."); bOk = false; } if (ulUnicodeRange3 != 0) { v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "Range[2] was undefined. All bits must be 0."); bOk = false; } if (ulUnicodeRange4 != 0) { v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "Range[3] was undefined. All bits must be 0."); bOk = false; } if (bOk) { v.Pass(P.OS_2_P_UnicodeRanges, m_tag); } else { bRet = false; } return bRet; } // count the number of entries in each unicode range in the cmap subtable UnicodeRanges ur = new UnicodeRanges(); for (uint c = 0; c < 0xffff; c++) { // check if c is mapped to a glyph uint iGlyph = fontOwner.FastMapUnicodeToGlyphID((char)c); if (iGlyph != 0) { UnicodeRanges.Range r = ur.GetRange(c); if (r != null) { r.count++; } } } uint nCharsInRange; // bit 0 uint BASIC_LATIN_LOW = 0x0020; nCharsInRange = ur.GetRange(BASIC_LATIN_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000001, nCharsInRange, "Basic Latin"); // bit 1 uint LATIN_1_SUPPLEMENT_LOW = 0x00A0; nCharsInRange = ur.GetRange(LATIN_1_SUPPLEMENT_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000002, nCharsInRange, "Latin-1 Supplement"); // bit 2 uint LATIN_EXTENDED_A_LOW = 0x0100; nCharsInRange = ur.GetRange(LATIN_EXTENDED_A_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000004, nCharsInRange, "Latin Extended-A"); // bit 3 uint LATIN_EXTENDED_B_LOW = 0x0180; nCharsInRange = ur.GetRange(LATIN_EXTENDED_B_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000008, nCharsInRange, "Latin Extended-B"); // bit 4 uint IPA_EXTENSIONS_LOW = 0x0250; nCharsInRange = ur.GetRange(IPA_EXTENSIONS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000010, nCharsInRange, "IPA Extensions"); // bit 5 uint SPACING_MODIFIER_LETTERS_LOW = 0x02B0; nCharsInRange = ur.GetRange(SPACING_MODIFIER_LETTERS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000020, nCharsInRange, "Spacing Modifier Letters"); // bit 6 uint COMBINING_DIACRITICAL_MARKS_LOW = 0x0300; nCharsInRange = ur.GetRange(COMBINING_DIACRITICAL_MARKS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000040, nCharsInRange, "Combining Diacritical Marks"); // bit 7 uint GREEK_LOW = 0x0370; nCharsInRange = ur.GetRange(GREEK_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000080, nCharsInRange, "Greek"); // bit 8 reserved if ((ulUnicodeRange1 & 0x00000100) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #8"); } // bit 9 uint CYRILLIC_LOW = 0x0400; uint CYRILLIC_SUPPLEMENTARY_LOW = 0x0500; nCharsInRange = ur.GetRange(CYRILLIC_LOW).count + ur.GetRange(CYRILLIC_SUPPLEMENTARY_LOW).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange1, 0x00000200, nCharsInRange, "Cyrillic, Cyrillic Supplementary"); // bit 10 uint ARMENIAN_LOW = 0x0530; nCharsInRange = ur.GetRange(ARMENIAN_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000400, nCharsInRange, "Armenian"); // bit 11 uint HEBREW_LOW = 0x0590; nCharsInRange = ur.GetRange(HEBREW_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00000800, nCharsInRange, "Hebrew"); if (version > 1) { // bit 12 reserved if ((ulUnicodeRange1 & 0x00001000) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #12"); } } // bit 13 uint ARABIC_LOW = 0x0600; nCharsInRange = ur.GetRange(ARABIC_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00002000, nCharsInRange, "Arabic"); if (version > 1) { // bit 14 reserved if ((ulUnicodeRange1 & 0x00004000) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #14"); } } // bit 15 uint DEVANAGARI_LOW = 0x0900; nCharsInRange = ur.GetRange(DEVANAGARI_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00008000, nCharsInRange, "Devanagari"); // bit 16 uint BENGALI_LOW = 0x0980; nCharsInRange = ur.GetRange(BENGALI_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00010000, nCharsInRange, "Bengali"); // bit 17 uint GURMUKHI_LOW = 0x0A00; nCharsInRange = ur.GetRange(GURMUKHI_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00020000, nCharsInRange, "Gurmukhi"); // bit 18 uint GUJARATI_LOW = 0x0A80; nCharsInRange = ur.GetRange(GUJARATI_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00040000, nCharsInRange, "Gujarati"); // bit 19 uint ORIYA_LOW = 0x0B00; nCharsInRange = ur.GetRange(ORIYA_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00080000, nCharsInRange, "Oriya"); // bit 20 uint TAMIL_LOW = 0x0B80; nCharsInRange = ur.GetRange(TAMIL_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00100000, nCharsInRange, "Tamil"); // bit 21 uint TELUGU_LOW = 0x0C00; nCharsInRange = ur.GetRange(TELUGU_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00200000, nCharsInRange, "Telugu"); // bit 22 uint KANNADA_LOW = 0x0C80; nCharsInRange = ur.GetRange(KANNADA_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00400000, nCharsInRange, "Kannada"); // bit 23 uint MALAYALAM_LOW = 0x0D00; nCharsInRange = ur.GetRange(MALAYALAM_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x00800000, nCharsInRange, "Malayalam"); // bit 24 uint THAI_LOW = 0x0E00; nCharsInRange = ur.GetRange(THAI_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x01000000, nCharsInRange, "Thai"); // bit 25 uint LAO_LOW = 0x0E80; nCharsInRange = ur.GetRange(LAO_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x02000000, nCharsInRange, "Lao"); // bit 26 uint GEORGIAN_LOW = 0x10A0; nCharsInRange = ur.GetRange(GEORGIAN_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x04000000, nCharsInRange, "Georgian"); if (version > 1) { // bit 27 reserved if ((ulUnicodeRange1 & 0x08000000) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #27"); } } // bit 28 uint HANGUL_JAMO_LOW = 0x1100; nCharsInRange = ur.GetRange(HANGUL_JAMO_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x10000000, nCharsInRange, "Hangul Jamo"); // bit 29 uint LATIN_EXTENDED_ADDITIONAL_LOW = 0x1E00; nCharsInRange = ur.GetRange(LATIN_EXTENDED_ADDITIONAL_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x20000000, nCharsInRange, "Latin Extended Additional"); // bit 30 uint GREEK_EXTENDED_LOW = 0x1F00; nCharsInRange = ur.GetRange(GREEK_EXTENDED_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x40000000, nCharsInRange, "Greek Extended"); // bit 31 uint GENERAL_PUNCTUATION_LOW = 0x2000; nCharsInRange = ur.GetRange(GENERAL_PUNCTUATION_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange1, 0x80000000, nCharsInRange, "General Punctuation"); // bit 32 uint SUPER_SUB_SCRIPTS_LOW = 0x2070; nCharsInRange = ur.GetRange(SUPER_SUB_SCRIPTS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000001, nCharsInRange, "Superscripts and Subscripts"); // bit 33 uint CURRENCY_SYMBOLS_LOW = 0x20A0; nCharsInRange = ur.GetRange(CURRENCY_SYMBOLS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000002, nCharsInRange, "Currency Symbols"); // bit 34 uint SYMBOL_COMBINING_MARKS_LOW = 0x20D0; nCharsInRange = ur.GetRange(SYMBOL_COMBINING_MARKS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000004, nCharsInRange, "Combining Diacritical marks for symbols"); // bit 35 uint LETTERLIKE_SYMBOLS_LOW = 0x2100; nCharsInRange = ur.GetRange(LETTERLIKE_SYMBOLS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000008, nCharsInRange, "Letterlike Symbols"); // bit 36 uint NUMBER_FORMS_LOW = 0x2150; nCharsInRange = ur.GetRange(NUMBER_FORMS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000010, nCharsInRange, "Number Forms"); // bit 37 uint ARROWS_LOW = 0x2190; uint SUPPLEMENTAL_ARROWS_A_LOW = 0x27F0; uint SUPPLEMENTAL_ARROWS_B_LOW = 0x2900; nCharsInRange = ur.GetRange(ARROWS_LOW).count + ur.GetRange(SUPPLEMENTAL_ARROWS_A_LOW).count + ur.GetRange(SUPPLEMENTAL_ARROWS_B_LOW).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x00000020, nCharsInRange, "Arrows, Supplementary Arrows A, Supplementary Arrows B"); // bit 38 uint MATH_OPERATORS_LOW = 0x2200; uint SUPPLEMENTAL_MATH_OPERATORS_LOW = 0x2A00; uint MISC_MATH_SYMBOLS_A_LOW = 0x27C0; uint MISC_MATH_SYMBOLS_B_LOW = 0x2980; nCharsInRange = ur.GetRange(MATH_OPERATORS_LOW).count + ur.GetRange(SUPPLEMENTAL_MATH_OPERATORS_LOW).count + ur.GetRange(MISC_MATH_SYMBOLS_A_LOW).count + ur.GetRange(MISC_MATH_SYMBOLS_B_LOW).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x00000040, nCharsInRange, "Mathematical Operators, Supplemental Mathematical Operators, Mathematical Symbols A, Mathematical Symbols B"); // bit 39 uint MISC_TECHNICAL_LOW = 0x2300; nCharsInRange = ur.GetRange(MISC_TECHNICAL_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000080, nCharsInRange, "Miscellaneous Technical"); // bit 40 uint CONTROL_PICTURES_LOW = 0x2400; nCharsInRange = ur.GetRange(CONTROL_PICTURES_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000100, nCharsInRange, "Control Pictures"); // bit 41 uint OCR_LOW = 0x2440; nCharsInRange = ur.GetRange(OCR_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000200, nCharsInRange, "Optical Character Recognition"); // bit 42 uint ENCLOSED_ALPHANUMERICS_LOW = 0x2460; nCharsInRange = ur.GetRange(ENCLOSED_ALPHANUMERICS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000400, nCharsInRange, "Enclosed Alphanumerics"); // bit 43 uint BOX_DRAWING_LOW = 0x2500; nCharsInRange = ur.GetRange(BOX_DRAWING_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00000800, nCharsInRange, "Box Drawing"); // bit 44 uint BLOCK_ELEMENTS_LOW = 0x2580; nCharsInRange = ur.GetRange(BLOCK_ELEMENTS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00001000, nCharsInRange, "Block Elements"); // bit 45 uint GEOMETRIC_SHAPES_LOW = 0x25A0; nCharsInRange = ur.GetRange(GEOMETRIC_SHAPES_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00002000, nCharsInRange, "Geometric Shapes"); // bit 46 uint MISC_SYMBOLS_LOW = 0x2600; nCharsInRange = ur.GetRange(MISC_SYMBOLS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00004000, nCharsInRange, "Miscellaneous Symbols"); // bit 47 uint DINGBATS_LOW = 0x2700; nCharsInRange = ur.GetRange(DINGBATS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00008000, nCharsInRange, "Dingbats"); // bit 48 uint CJK_SYMBOLS_PUNCTUATION_LOW = 0x3000; nCharsInRange = ur.GetRange(CJK_SYMBOLS_PUNCTUATION_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00010000, nCharsInRange, "CJK Symbols and Punctuation"); // bit 49 uint HIRAGANA_LOW = 0x3040; nCharsInRange = ur.GetRange(HIRAGANA_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00020000, nCharsInRange, "Hiragana"); // bit 50 uint KATAKANA_LOW = 0x30A0; nCharsInRange = ur.GetRange(KATAKANA_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00040000, nCharsInRange, "Katakana"); // bit 51 uint BOPOMOFO_LOW = 0x3100; uint BOPOMOFO_EXTENDED_LOW = 0x31A0; nCharsInRange = ur.GetRange(BOPOMOFO_LOW).count + ur.GetRange(BOPOMOFO_EXTENDED_LOW).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x00080000, nCharsInRange, "Bopomofo, Bopomofo Extended"); // bit 52 uint HANGUL_COMPAT_JAMO_LOW = 0x3130; nCharsInRange = ur.GetRange(HANGUL_COMPAT_JAMO_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00100000, nCharsInRange, "Hangul Compatibility Jamo"); // bit 53 !!! OT Spec 1.3 says bit 53 is CJK Misc !!! // !!! Since there's no unicode range name !!! // !!! that maps nicely to CJK Misc, !!! // !!! I naturally just ignore it. !!! /* bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00200000, nCharsInRange, "CJK Miscellaneous"); */ // bit 54 uint ENCLOSED_CJK_LETTERS_MONTHS_LOW = 0x3200; nCharsInRange = ur.GetRange(ENCLOSED_CJK_LETTERS_MONTHS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00400000, nCharsInRange, "Enclosed CJK Letters and Months"); // bit 55 uint CJK_COMPATIBILITY_LOW = 0x3300; nCharsInRange = ur.GetRange(CJK_COMPATIBILITY_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x00800000, nCharsInRange, "CJK Compatibility"); // bit 56 uint HANGUL_LOW = 0xAC00; nCharsInRange = ur.GetRange(HANGUL_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x01000000, nCharsInRange, "Hangul"); // bit 57 surrogates if (version > 1) { bool bSurrogatesCmapPresent = false; Table_cmap cmapTable = (Table_cmap)fontOwner.GetTable("cmap"); if (cmapTable != null) { Table_cmap.EncodingTableEntry eteUniSurrogates = cmapTable.GetEncodingTableEntry(3,10); if (eteUniSurrogates != null) bSurrogatesCmapPresent = true; } if ((ulUnicodeRange2 & 0x02000000) == 0) { if (bSurrogatesCmapPresent) { v.Error(T.T_NULL, E.OS_2_E_SurrogatesBitClear, m_tag); bOk = false; } } else { if (!bSurrogatesCmapPresent) { v.Error(T.T_NULL, E.OS_2_E_SurrogatesBitSet, m_tag); bOk = false; } } } // bit 58 reserved if ((ulUnicodeRange2 & 0x04000000) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #58"); } // bit 59 uint CJK_UNIFIED_IDEOGRAPHS_LOW = 0x4E00; uint CJK_RADICALS_SUPPLEMENT_LOW = 0x2E80; uint KANGXI_RADICALS_LOW = 0x2F00; uint IDEOGRAPHIC_DESCRIPTION_CHARS_LOW = 0x2FF0; uint CJK_UNIFIED_IDEOGRAPHS_EXT_A_LOW = 0x3400; uint CJK_UNIFIED_IDEOGRAPHS_EXT_B_LOW = 0x20000; uint KANBUN_LOW = 0x3190; nCharsInRange = ur.GetRange(CJK_UNIFIED_IDEOGRAPHS_LOW).count + ur.GetRange(CJK_RADICALS_SUPPLEMENT_LOW).count + ur.GetRange(KANGXI_RADICALS_LOW).count + ur.GetRange(IDEOGRAPHIC_DESCRIPTION_CHARS_LOW).count + ur.GetRange(CJK_UNIFIED_IDEOGRAPHS_EXT_A_LOW).count + ur.GetRange(CJK_UNIFIED_IDEOGRAPHS_EXT_B_LOW).count + ur.GetRange(KANBUN_LOW).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x08000000, nCharsInRange, "CJK Unified Ideographs, CJK Radicals Supplement, Kangxi Radicals, Ideographic Description Chars, CJK Unified Ideographs Extended A, CJK Unified Ideographs Extended B, Kanbun"); // bit 60 uint PRIVATE_USE_AREA_LOW = 0xE000; if (!fontOwner.ContainsMsSymbolEncodedCmap()) { nCharsInRange = ur.GetRange(PRIVATE_USE_AREA_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x10000000, nCharsInRange, "Private Use Area"); } // bit 61 uint CJK_COMPATIBILITY_IDEOGRAPHS_LOW = 0xF900; uint CJK_COMPATIBILITY_IDEO_SUPP_LOW = 0x2F800; nCharsInRange = ur.GetRange(CJK_COMPATIBILITY_IDEOGRAPHS_LOW).count + ur.GetRange(CJK_COMPATIBILITY_IDEO_SUPP_LOW).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange2, 0x20000000, nCharsInRange, "CJK Compatibility Ideographs, CJK Compatibility Ideographs Supplement"); // bit 62 uint ALPHABETIC_PRESENTATION_FORMS_LOW = 0xFB00; nCharsInRange = ur.GetRange(ALPHABETIC_PRESENTATION_FORMS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x40000000, nCharsInRange, "Alphabetic Presentation Forms"); // bit 63 uint ARABIC_PRESENTATION_FORMS_A_LOW = 0xFB50; nCharsInRange = ur.GetRange(ARABIC_PRESENTATION_FORMS_A_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange2, 0x80000000, nCharsInRange, "Arabic Presentation Forms-A"); // bit 64 uint COMBINING_HALF_MARKS_LOW = 0xFE20; nCharsInRange = ur.GetRange(COMBINING_HALF_MARKS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000001, nCharsInRange, "Combining Half Marks"); // bit 65 uint CJK_COMPATIBILITY_FORMS_LOW = 0xFE30; nCharsInRange = ur.GetRange(CJK_COMPATIBILITY_FORMS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000002, nCharsInRange, "CJK Compatibility Forms"); // bit 66 uint SMALL_FORM_VARIANTS_LOW = 0xFE50; nCharsInRange = ur.GetRange(SMALL_FORM_VARIANTS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000004, nCharsInRange, "Small Form Variants"); // bit 67 uint ARABIC_PRESENTATION_FORMS_B_LOW = 0xFE70; nCharsInRange = ur.GetRange(ARABIC_PRESENTATION_FORMS_B_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000008, nCharsInRange, "Arabic Presentation Forms-B"); // bit 68 uint HALFWIDTH_FULLWIDTH_FORMS_LOW = 0xFF00; nCharsInRange = ur.GetRange(HALFWIDTH_FULLWIDTH_FORMS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000010, nCharsInRange, "Halfwidth and Fullwidth Forms"); // bit 69 uint SPECIALS_LOW = 0xFFF0; nCharsInRange = ur.GetRange(SPECIALS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000020, nCharsInRange, "Specials"); if (version < 2) { for (int bitpos = 6; bitpos < 32; bitpos++) { if ((ulUnicodeRange3 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (64+bitpos)); } } for (int bitpos = 0; bitpos < 32; bitpos++) { if ((ulUnicodeRange4 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (96+bitpos)); } } } else { // bit 70 uint TIBETAN_LOW = 0x0F00; nCharsInRange = ur.GetRange(TIBETAN_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000040, nCharsInRange, "Tibetan"); // bit 71 uint SYRIAC_LOW = 0x0700; nCharsInRange = ur.GetRange(SYRIAC_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000080, nCharsInRange, "Syriac"); // bit 72 uint THAANA_LOW = 0x0780; nCharsInRange = ur.GetRange(THAANA_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000100, nCharsInRange, "Thaana"); // bit 73 uint SINHALA_LOW = 0x0D80; nCharsInRange = ur.GetRange(SINHALA_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000200, nCharsInRange, "Sinhala"); // bit 74 uint MYANMAR_LOW = 0x1000; nCharsInRange = ur.GetRange(MYANMAR_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000400, nCharsInRange, "Myanmar"); // bit 75 uint ETHIOPIC_LOW = 0x1200; nCharsInRange = ur.GetRange(ETHIOPIC_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00000800, nCharsInRange, "Ethiopic"); // bit 76 uint CHEROKEE_LOW = 0x13A0; nCharsInRange = ur.GetRange(CHEROKEE_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00001000, nCharsInRange, "Cherokee"); // bit 77 uint UNIFIED_CANADIAN_AB_SYL_LOW = 0x1400; nCharsInRange = ur.GetRange(UNIFIED_CANADIAN_AB_SYL_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00002000, nCharsInRange, "Unified Canadian Syllabics"); // bit 78 uint OGHAM_LOW = 0x1680; nCharsInRange = ur.GetRange(OGHAM_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00004000, nCharsInRange, "Ogham"); // bit 79 uint RUNIC_LOW = 0x16A0; nCharsInRange = ur.GetRange(RUNIC_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00008000, nCharsInRange, "Runic"); // bit 80 uint KHMER_LOW = 0x1780; nCharsInRange = ur.GetRange(KHMER_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00010000, nCharsInRange, "Khmer"); // bit 81 uint MONGOLIAN_LOW = 0x1800; nCharsInRange = ur.GetRange(MONGOLIAN_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00020000, nCharsInRange, "Mongolian"); // bit 82 uint BRAILLE_PATTERNS_LOW = 0x2800; nCharsInRange = ur.GetRange(BRAILLE_PATTERNS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00040000, nCharsInRange, "Braille"); // bit 83 uint YI_LOW = 0xA000; uint YI_RADICALS_LOW = 0xA490; nCharsInRange = ur.GetRange(YI_LOW).count + ur.GetRange(YI_RADICALS_LOW).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange3, 0x00080000, nCharsInRange, "Yi, Yi Radicals"); if (version < 3) { for (int bitpos = 20; bitpos < 32; bitpos++) { if ((ulUnicodeRange3 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (64+bitpos)); } } for (int bitpos = 0; bitpos < 32; bitpos++) { if ((ulUnicodeRange4 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (96+bitpos)); } } } else { // bit 84 uint TAGALOG_LOW = 0x1700; uint HANUNOO_LOW = 0x1720; uint BUHID_LOW = 0x1740; uint TAGBANWA_LOW = 0x1760; nCharsInRange = ur.GetRange(TAGALOG_LOW).count + ur.GetRange(HANUNOO_LOW).count + ur.GetRange(BUHID_LOW).count + ur.GetRange(TAGBANWA_LOW).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange3, 0x00100000, nCharsInRange, "Tagalog, Hanunoo, Buhid, Tagbanwa"); // bit 85 uint OLD_ITALIC_LOW = 0x10300; nCharsInRange = ur.GetRange(OLD_ITALIC_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00200000, nCharsInRange, "Old Italic"); // bit 86 uint GOTHIC_LOW = 0x10330; nCharsInRange = ur.GetRange(GOTHIC_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00400000, nCharsInRange, "Gothic"); // bit 87 uint DESERET_LOW = 0x10400; nCharsInRange = ur.GetRange(DESERET_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x00800000, nCharsInRange, "Deseret"); // bit 88 uint BYZANTINE_MUSICAL_SYMBOLS_LOW = 0x1D000; uint MUSICAL_SYMBOLS_LOW = 0x1D100; nCharsInRange = ur.GetRange(BYZANTINE_MUSICAL_SYMBOLS_LOW).count + ur.GetRange(MUSICAL_SYMBOLS_LOW).count; bOk &= VerifyUnicodeRanges(v, ulUnicodeRange3, 0x01000000, nCharsInRange, "Byzantine Musical Symbols, Musical Symbols"); // bit 89 uint MATHEMATICAL_ALPHANUMERIC_LOW = 0x1D400; nCharsInRange = ur.GetRange(MATHEMATICAL_ALPHANUMERIC_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x02000000, nCharsInRange, "Mathematical Alphanumeric Symbols"); // bit 90 uint PRIVATE_USE_15_LOW = 0xFFF80; uint PRIVATE_USE_16_LOW = 0x10FF80; nCharsInRange = ur.GetRange(PRIVATE_USE_15_LOW).count + ur.GetRange(PRIVATE_USE_16_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x04000000, nCharsInRange, "Private Use (Plane 15), Private Use (Plane 16)"); // bit 91 uint VARIATION_SELECTORS_LOW = 0xE0100; nCharsInRange = ur.GetRange(VARIATION_SELECTORS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x08000000, nCharsInRange, "Variation Selectors"); // bit 92 uint TAGS_LOW = 0xE0000; nCharsInRange = ur.GetRange(TAGS_LOW).count; bOk &= VerifyUnicodeRange(v, ulUnicodeRange3, 0x10000000, nCharsInRange, "Tags"); for (int bitpos = 29; bitpos < 32; bitpos++) { if ((ulUnicodeRange3 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (64+bitpos)); } } for (int bitpos = 0; bitpos < 32; bitpos++) { if ((ulUnicodeRange4 & (1<<bitpos)) != 0) { bOk = false; v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_Unicode, m_tag, "bit #" + (96+bitpos)); } } } } if (bOk) { v.Pass(P.OS_2_P_UnicodeRanges, m_tag); } else { bRet = false; } return bRet; }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; bool bNumSizesOkay = true; Table_EBDT EBDTTable = (Table_EBDT)fontOwner.GetTable("EBDT"); if (v.PerformTest(T.EBLC_version)) { if (version.GetUint() == 0x00020000) { v.Pass(T.EBLC_version, P.EBLC_P_version, m_tag); } else { v.Error(T.EBLC_version, E.EBLC_E_version, m_tag, "version = 0x" + version.GetUint().ToString("x8") + ", unable to continue validation"); return(false); } } if (v.PerformTest(T.EBLC_numSizes)) { if (numSizes < (m_bufTable.GetLength() / 48)) { v.Pass(T.EBLC_numSizes, P.EBLC_P_numSizes, m_tag); } else { v.Error(T.EBLC_numSizes, E.EBLC_E_numSizes, m_tag, "0x" + numSizes.ToString("x8")); bNumSizesOkay = false; bRet = false; } } if (v.PerformTest(T.EBLC_TableDependency)) { if (EBDTTable != null) { v.Pass(T.EBLC_TableDependency, P.EBLC_P_TableDependency, m_tag); } else { v.Error(T.EBLC_TableDependency, E.EBLC_E_TableDependency, m_tag); bRet = false; } } if (v.PerformTest(T.EBLC_indexSubTableArrayOffset) && bNumSizesOkay == true) { bool bOffsetsOk = true; bool bIndicesOk = true; uint SmallestPossibleOffset = 8 + numSizes * 48; // sizeof header + sizeof bitmapSizeTAbles for (uint i = 0; i < numSizes; i++) { bitmapSizeTable bst = GetBitmapSizeTable(i); // start must be less than or equal to end if (bst.startGlyphIndex > bst.endGlyphIndex) { string s = "index = " + i + ", start index = " + bst.startGlyphIndex + ", stop index = " + bst.endGlyphIndex; v.Error(T.EBLC_SizeTableIndexOrder, E.EBLC_E_BitmapSizeTableIndexOrder, m_tag, s); bIndicesOk = false; bRet = false; } if (bst.indexSubTableArrayOffset < SmallestPossibleOffset || bst.indexSubTableArrayOffset + bst.indexTablesSize > GetLength()) { string s = "index = " + i + ", indexSubTableArrayOffset = " + bst.indexSubTableArrayOffset + ", indexTablesSize = " + bst.indexTablesSize; v.Error(T.EBLC_indexSubTableArrayOffset, E.EBLC_E_indexSubTableArrayOffset, m_tag, s); bOffsetsOk = false; bRet = false; } else { indexSubTableArray[] ista = GetIndexSubTableArray(bst); for (uint j = 0; j < bst.numberOfIndexSubTables; j++) { // first must be less than or equal to last if (ista[j].firstGlyphIndex > ista[j].lastGlyphIndex) { } // subtable indices must be within size table range if (ista[j].firstGlyphIndex <bst.startGlyphIndex || ista[j].lastGlyphIndex> bst.endGlyphIndex) { } } } } if (bOffsetsOk) { v.Pass(T.EBLC_indexSubTableArrayOffset, P.EBLC_P_indexSubTableArrayOffset, m_tag); } if (bIndicesOk) { v.Pass(T.EBLC_SizeTableIndexOrder, P.EBLC_P_BitmapSizeTableIndexOrder, m_tag); } } if (v.PerformTest(T.EBLC_bitDepth) && bNumSizesOkay == true) { bool bBitDepthOk = true; for (uint i = 0; i < numSizes; i++) { bitmapSizeTable bst = GetBitmapSizeTable(i); if (bst.bitDepth != 1 && bst.bitDepth != 2 && bst.bitDepth != 4 && bst.bitDepth != 8) { string s = "index = " + i + ", bitDepth = " + bst.bitDepth; v.Error(T.EBLC_bitDepth, E.EBLC_E_bitDepth, m_tag, s); bBitDepthOk = false; bRet = false; } } if (bBitDepthOk) { v.Pass(T.EBLC_bitDepth, P.EBLC_P_bitDepth, m_tag); } } if (v.PerformTest(T.EBLC_indexSubTables) && bNumSizesOkay == true) { for (uint i = 0; i < numSizes; i++) { bitmapSizeTable bst = GetBitmapSizeTable(i); string sSize = "bitmapsize[" + i + "], ppemX=" + bst.ppemX + ", ppemY=" + bst.ppemY; indexSubTableArray[] ista = GetIndexSubTableArray(bst); for (uint j = 0; j < bst.numberOfIndexSubTables; j++) { indexSubTable ist = bst.GetIndexSubTable(ista[j]); string sID = sSize + ", indexSubTable[" + j + "](fmt " + ist.header.indexFormat + ")"; if (!Validate_indexSubTable(v, ist, ista[j], sID, fontOwner)) { bRet = false; } } } } return(bRet); }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.OS_2_Version)) { if (version == 0 || version == 1 || version == 2) { v.Warning(T.OS_2_Version, W.OS_2_W_Version_old, m_tag, version.ToString()); } else if (version == 3) { v.Pass(T.OS_2_Version, P.OS_2_P_Version, m_tag, version.ToString()); } else { v.Error(T.OS_2_Version, E.OS_2_E_Version, m_tag, version.ToString()); bRet = false; } } if (v.PerformTest(T.OS_2_TableLength)) { uint len = GetLength(); if ((version == 0 && len == 78) || (version == 1 && len == 86) || (version == 2 && len == 96) || (version == 3 && len == 96)) { v.Pass(T.OS_2_TableLength, P.OS_2_P_TableLength, m_tag); } else { v.Error(T.OS_2_TableLength, E.OS_2_E_TableLength, m_tag); bRet = false; } } if (!bRet) { v.Warning(T.T_NULL, W._TEST_W_OtherErrorsInTable, m_tag, "OS/2 table appears to be corrupt. No further tests will be performed."); return bRet; } if (v.PerformTest(T.OS_2_xAvgCharWidth)) { if (fontOwner.GetTable("maxp") == null) { v.Warning(T.OS_2_xAvgCharWidth, W._TEST_W_ErrorInAnotherTable, m_tag, "maxp table inaccessible, can't check Avg Char Width"); } else { if (fontOwner.ContainsTrueTypeOutlines()) { Table_hmtx hmtxTable = (Table_hmtx)fontOwner.GetTable("hmtx"); val_loca locaTable = (val_loca)fontOwner.GetTable("loca"); val_maxp maxpTable = (val_maxp)fontOwner.GetTable("maxp"); if (hmtxTable == null) { v.Error(T.OS_2_xAvgCharWidth, E._TEST_E_TableMissing, m_tag, "hmtx"); bRet = false; } else if (locaTable == null) { v.Error(T.OS_2_xAvgCharWidth, E._TEST_E_TableMissing, m_tag, "loca"); bRet = false; } else if (maxpTable == null) { v.Error(T.OS_2_xAvgCharWidth, E._TEST_E_TableMissing, m_tag, "maxp"); bRet = false; } else { if ( version == 3 || fontOwner.ContainsMsSymbolEncodedCmap()) { int nTotalWidth = 0; int nTotalGlyphs = 0; for (uint iGlyph=0; iGlyph<fontOwner.GetMaxpNumGlyphs(); iGlyph++) { Table_hmtx.longHorMetric hm = hmtxTable.GetOrMakeHMetric(iGlyph, fontOwner); if (hm != null) { nTotalWidth += hm.advanceWidth; // only average non-zero width glyphs if (hm.advanceWidth > 0) { nTotalGlyphs ++; } } } short CalcAvgWidth = 0; if (nTotalGlyphs > 0) CalcAvgWidth = (short)(nTotalWidth / nTotalGlyphs); if (xAvgCharWidth == CalcAvgWidth) { v.Pass(T.OS_2_xAvgCharWidth, P.OS_2_P_xAvgCharWidth, m_tag); } else { string s = "actual = " + xAvgCharWidth + ", calc = " + CalcAvgWidth; v.Error(T.OS_2_xAvgCharWidth, E.OS_2_E_xAvgCharWidth, m_tag, s); bRet = false; } } else { // do weighed average ushort [] weightLC = { 64, 14, 27, 35, 100, 20, 14, 42, 63, 3, 6, 35, 20, 56, 56, 17, 4, 49, 56, 71, 31, 10, 18, 3, 18, 2 }; ushort weightSpace = 166; try { uint iSpaceGlyph = fontOwner.FastMapUnicodeToGlyphID(' '); if (iSpaceGlyph >= fontOwner.GetMaxpNumGlyphs()) { throw new ApplicationException("error in cmap table"); } Table_hmtx.longHorMetric hmSpace = hmtxTable.GetOrMakeHMetric(iSpaceGlyph, fontOwner); if (hmSpace != null) { int nTotalWeight = hmSpace.advanceWidth * weightSpace; int nLowerCase = 0; for (char c = 'a'; c <= 'z'; c++) { uint iGlyph = fontOwner.FastMapUnicodeToGlyphID(c); if (iGlyph > 0 && iGlyph < fontOwner.GetMaxpNumGlyphs()) { nLowerCase ++; Table_hmtx.longHorMetric hm = hmtxTable.GetOrMakeHMetric(iGlyph, fontOwner); nTotalWeight += hm.advanceWidth * weightLC[c-'a']; } } short CalcAvgWidth = 0; if (nLowerCase == 26) { CalcAvgWidth = (short)(nTotalWeight / 1000); } else { int nTotalWidth = 0; int nTotalGlyphs = 0; for (uint iGlyph=0; iGlyph<fontOwner.GetMaxpNumGlyphs(); iGlyph++) { Table_hmtx.longHorMetric hm = hmtxTable.GetOrMakeHMetric(iGlyph, fontOwner); nTotalWidth += hm.advanceWidth; nTotalGlyphs ++; } CalcAvgWidth = (short)(nTotalWidth / nTotalGlyphs); } if (xAvgCharWidth == CalcAvgWidth) { v.Pass(T.OS_2_xAvgCharWidth, P.OS_2_P_xAvgCharWidth, m_tag); } else { string s = "actual = " + xAvgCharWidth + ", calc = " + CalcAvgWidth; v.Error(T.OS_2_xAvgCharWidth, E.OS_2_E_xAvgCharWidth, m_tag, s); bRet = false; } } else { v.Warning(T.OS_2_xAvgCharWidth, W.OS_2_W_hmtx_invalid, m_tag, "unable to parse hmtx table"); } } catch (ApplicationException e) { v.Warning(T.OS_2_xAvgCharWidth, W._TEST_W_ErrorInAnotherTable, m_tag, "xAvgCharWidth cannot be validated due to " + e.Message); } } } } else { // not a TT outline font - should embedded bitmap only font be handled here? v.Info(T.OS_2_xAvgCharWidth, I._TEST_I_NotForCFF, m_tag, "test = OS/2_xAvgCharWidth"); } } } if (v.PerformTest(T.OS_2_WeightClass)) { if (usWeightClass >= 100 && usWeightClass <= 900 && usWeightClass% 100 == 0) { bool bWeightClassOk = true; // compare to the PANOSE weight value if (panose_byte1 == 2 || panose_byte1 == 3 || panose_byte1 == 4) // latin text, hand writing, or decorative { if (panose_byte3 > 1) { // convert PANOSE weight value from a range of [2..11] to a range of [100..900] (reasonably close anyway, given integer math) int nConvertedPANOSE = (panose_byte3-2)*89+100; int nDifference = Math.Abs(usWeightClass - nConvertedPANOSE); if (nDifference < 200) { v.Pass(T.OS_2_WeightClass, P.OS_2_P_WeightClass_PANOSE, m_tag); } else { v.Warning(T.OS_2_WeightClass, W.OS_2_W_WeightClass_PANOSE, m_tag, "usWeightClass = " + usWeightClass + ", PANOSE weight = " + panose_byte3); bWeightClassOk = false; } } } if (bWeightClassOk) { v.Pass(T.OS_2_WeightClass, P.OS_2_P_WeightClass, m_tag, usWeightClass.ToString()); } } else { v.Error(T.OS_2_WeightClass, E.OS_2_E_WeightClass, m_tag, usWeightClass.ToString()); bRet = false; } } if (v.PerformTest(T.OS_2_WidthClass)) { if (usWidthClass >=1 && usWidthClass <= 9) { v.Pass(T.OS_2_WidthClass, P.OS_2_P_WidthClass, m_tag, usWidthClass.ToString()); } else { v.Error(T.OS_2_WidthClass, E.OS_2_E_WidthClass, m_tag, usWidthClass.ToString()); bRet = false; } } if (v.PerformTest(T.OS_2_fsType)) { bool bPass = true; if ((fsType & 0xfcf1) != 0) { v.Error(T.OS_2_fsType, E.OS_2_E_fsTypeReserved, m_tag, "0x"+fsType.ToString("x4")); bRet = false; bPass = false; } else { int nExclusiveBits = 0; if ((fsType & 0x0002) !=0) //Restricted License Embedding { nExclusiveBits++; } if ((fsType & 0x0004) != 0) // Preview and Print embedding { nExclusiveBits++; } if ((fsType & 0x0008) != 0) // Editable embedding { nExclusiveBits++; } if (nExclusiveBits > 1) { string sDetails = "0x"+fsType.ToString("x4"); if ((fsType & 0x0002) !=0) { sDetails += ", Restricted License Embedding"; } if ((fsType & 0x0004) != 0) { sDetails += ", Preview and Print embedding"; } if ((fsType & 0x0008) != 0) { sDetails += ", Editable embedding"; } v.Error(T.OS_2_fsType, E.OS_2_E_fsTypeExclusiveBits, m_tag, sDetails); bRet = false; bPass = false; } } if (bPass) { string sDetails = "0x"+fsType.ToString("x4"); if (fsType == 0) { sDetails += ", Installable Embedding"; } if ((fsType & 0x0002) !=0) { sDetails += ", Restricted License Embedding"; } if ((fsType & 0x0004) != 0) { sDetails += ", Preview and Print embedding"; } if ((fsType & 0x0008) != 0) { sDetails += ", Editable embedding"; } if ((fsType & 0x0100) != 0) { sDetails += ", No subsetting"; } if ((fsType & 0x0200) != 0) { sDetails += ", Bitmap embedding only"; } v.Pass(T.OS_2_fsType, P.OS_2_P_fsType, m_tag, sDetails); } } if (v.PerformTest(T.OS_2_SubscriptSuperscript)) { Table_head headTable = (Table_head)fontOwner.GetTable("head"); if (headTable != null) { ushort unitsPerEm = headTable.unitsPerEm; ushort SmallestScript = (ushort)(unitsPerEm / 10); bool bNoWarnOrErr = true; if (ySubscriptXSize < SmallestScript || ySubscriptXSize > unitsPerEm ) { v.Warning(T.OS_2_SubscriptSuperscript, W.OS_2_W_ySubscriptXSize_unlikely, m_tag, ySubscriptXSize.ToString()); bNoWarnOrErr = false; } if (ySubscriptYSize < SmallestScript || ySubscriptYSize > unitsPerEm ) { v.Warning(T.OS_2_SubscriptSuperscript, W.OS_2_W_ySubscriptYSize_unlikely, m_tag, ySubscriptYSize.ToString()); bNoWarnOrErr = false; } if (ySubscriptYOffset < 0 ) { v.Warning(T.OS_2_SubscriptSuperscript, W.OS_2_W_ySubscriptYOffset_LTZero, m_tag, ySubscriptYOffset.ToString()); bNoWarnOrErr = false; } if (ySuperscriptXSize < SmallestScript || ySuperscriptXSize > unitsPerEm ) { v.Warning(T.OS_2_SubscriptSuperscript, W.OS_2_W_ySuperscriptXSize_unlikely, m_tag, ySuperscriptXSize.ToString()); bNoWarnOrErr = false; } if (ySuperscriptYSize < SmallestScript || ySuperscriptYSize > unitsPerEm ) { v.Warning(T.OS_2_SubscriptSuperscript, W.OS_2_W_ySuperscriptYSize_unlikely, m_tag, ySuperscriptYSize.ToString()); bNoWarnOrErr = false; } if (ySuperscriptYOffset < 0 ) { v.Warning(T.OS_2_SubscriptSuperscript, W.OS_2_W_ySuperscriptYOffset_unlikely, m_tag, ySuperscriptYOffset.ToString()); bNoWarnOrErr = false; } if (bNoWarnOrErr) { v.Pass(T.OS_2_SubscriptSuperscript, P.OS_2_P_SuperscriptSubscript, m_tag); } } else { v.Error(T.OS_2_SubscriptSuperscript, E._TEST_E_TableMissing, m_tag, "head"); bRet = false; } } if (v.PerformTest(T.OS_2_Strikeout)) { Table_head headTable = (Table_head)fontOwner.GetTable("head"); if (headTable != null) { ushort unitsPerEm = headTable.unitsPerEm; bool bNoWarnings = true; if (yStrikeoutSize < 0 || yStrikeoutSize > unitsPerEm / 2 ) { v.Warning(T.OS_2_Strikeout, W.OS_2_W_yStrikeoutSize_unlikely, m_tag, yStrikeoutSize.ToString()); bNoWarnings = false; } if (yStrikeoutPosition <= 0 ) { v.Warning(T.OS_2_Strikeout, W.OS_2_W_yStrikeoutPosition_unlikely, m_tag, yStrikeoutPosition.ToString()); bNoWarnings = false; } if (bNoWarnings) { v.Pass(T.OS_2_Strikeout, P.OS_2_P_Strikeout, m_tag); } } else { v.Error(T.OS_2_Strikeout, E._TEST_E_TableMissing, m_tag, "head"); bRet = false; } } if (v.PerformTest(T.OS_2_FamilyClass)) { bool bIDsOk = true; byte ClassID = (byte)(sFamilyClass >> 8); byte SubclassID = (byte)(sFamilyClass); if (ClassID == 6 || ClassID == 11 || ClassID == 13 || ClassID == 14 ) { v.Error(T.OS_2_FamilyClass, E.OS_2_E_sFamilyClass_classID_reserved, m_tag, ClassID.ToString()); bIDsOk = false; bRet = false; } if (ClassID > 14 ) { v.Error(T.OS_2_FamilyClass, E.OS_2_E_sFamilyClass_ClassID_undefined, m_tag, ClassID.ToString()); bIDsOk = false; bRet = false; } if (SubclassID > 15 ) { v.Error(T.OS_2_FamilyClass, E.OS_2_E_sFamilyClass_subclassID_undefined, m_tag, ClassID.ToString()); bIDsOk = false; bRet = false; } if (bIDsOk) { v.Pass(T.OS_2_FamilyClass, P.OS_2_P_sFamilyClass, m_tag); } } if (v.PerformTest(T.OS_2_Panose)) { bool bPanoseOk = true; if (panose_byte1 < 5) // panose kind valid, but not latin symbol { if (fontOwner.ContainsSymbolsOnly()) { v.Error(T.OS_2_Panose, E.OS_2_E_Panose_FamilyTypeNotSymbol, m_tag, "PANOSE byte 1 = " + panose_byte1.ToString()); bPanoseOk = false; bRet = false; } } else if (panose_byte1 == 5) // panose family kind == latin symbol { if (!fontOwner.ContainsSymbolsOnly()) { v.Error(T.OS_2_Panose, E.OS_2_E_Panose_FamilyTypeSymbol, m_tag, "PANOSE byte 1 = " + panose_byte1.ToString()); bPanoseOk = false; bRet = false; } } else if ( panose_byte1 > 5 ) // family kind is invalid { v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bFamilyType, m_tag, panose_byte1.ToString()); bPanoseOk = false; bRet = false; } if (panose_byte1 == 2) // family kind == latin text { if ( panose_byte2 > 15 ) { v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bSerifStyle, m_tag, panose_byte2.ToString()); bPanoseOk = false; bRet = false; } } if ( panose_byte3 > 11 ) // byte3 always means weight { v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bWeight, m_tag, panose_byte3.ToString()); bPanoseOk = false; bRet = false; } if (panose_byte1 == 5) // panose family kind == latin symbol { if (panose_byte3 != 1) // weight must be 1 for symbols { v.Error(T.OS_2_Panose, E.OS_2_E_Panose_SymbolWeight, m_tag, panose_byte3.ToString()); bPanoseOk = false; bRet = false; } if (panose_byte5 != 1) // aspect ratio & contrast must be 1 for symbols { v.Error(T.OS_2_Panose, E.OS_2_E_Panose_SymbolAspectRatio, m_tag, panose_byte5.ToString()); bPanoseOk = false; bRet = false; } } if (panose_byte1 == 2) // family kind == latin text { // the following tests are only valid when family kind is latin text if ( panose_byte4 > 9 ) { v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bProportion, m_tag, panose_byte4.ToString()); bPanoseOk = false; bRet = false; } if ( panose_byte5 > 9 ) { v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bContrast, m_tag, panose_byte5.ToString()); bPanoseOk = false; bRet = false; } if ( panose_byte6 > 10 ) { v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bStrokeVariation, m_tag, panose_byte6.ToString()); bPanoseOk = false; bRet = false; } if ( panose_byte7 > 11 ) { v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bArmStyle, m_tag, panose_byte7.ToString()); bPanoseOk = false; bRet = false; } if ( panose_byte8 > 15 ) { v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bLetterform, m_tag, panose_byte8.ToString()); bPanoseOk = false; bRet = false; } if ( panose_byte9 > 13 ) { v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bMidline, m_tag, panose_byte9.ToString()); bPanoseOk = false; bRet = false; } if ( panose_byte10 > 7 ) { v.Error(T.OS_2_Panose, E.OS_2_E_Panose_bXHeight, m_tag, panose_byte10.ToString()); bPanoseOk = false; bRet = false; } } if (panose_byte1 == 0 && panose_byte2 == 0 && panose_byte3 == 0 && panose_byte4 == 0 && panose_byte5 == 0 && panose_byte6 == 0 && panose_byte7 == 0 && panose_byte8 == 0 && panose_byte9 == 0 && panose_byte10 == 0 ) { v.Warning(T.OS_2_Panose, W.OS_2_W_Panose_undefined, m_tag); bPanoseOk = false; } if (bPanoseOk) { v.Pass(T.OS_2_Panose, P.OS_2_P_Panose, m_tag); } } if (v.PerformTest(T.OS_2_UnicodeRanges)) { bRet &= CheckUnicodeRanges(v, fontOwner); } if (v.PerformTest(T.OS_2_fsSelection)) { bool bSelOk = true; Table_name nameTable = (Table_name)fontOwner.GetTable("name"); string sStyle = null; string sStyleLower = null; if (nameTable != null) { sStyle = nameTable.GetStyleString(); if (sStyle != null) { sStyleLower = sStyle.ToLower(); } } // reserved bits if ( (fsSelection & 0xFF80 ) != 0 ) { // we need to look for Win 3.1 font pages // Fonts with these const ushort HEBREW_FONT_PAGE = 0xB100; const ushort SIMP_ARABIC_FONT_PAGE = 0xB200; const ushort TRAD_ARABIC_FONT_PAGE = 0xB300; const ushort OEM_ARABIC_FONT_PAGE = 0xB400; const ushort SIMP_FARSI_FONT_PAGE = 0xBA00; const ushort TRAD_FARSI_FONT_PAGE = 0xBB00; const ushort THAI_FONT_PAGE = 0xDE00; String sDetails = "Bit(s) "; bool bFoundFirstBadBit = false; if (version == 0) { switch (fsSelection & 0xFF00) { case HEBREW_FONT_PAGE: sDetails = "Hebrew Windows 3.1 font page"; break; case SIMP_ARABIC_FONT_PAGE: sDetails = "Simplified Arabic Windows 3.1 font page"; break; case TRAD_ARABIC_FONT_PAGE: sDetails = "Traditional Arabic Windows 3.1 font page"; break; case OEM_ARABIC_FONT_PAGE: sDetails = "OEM Arabic Windows 3.1 font page"; break; case SIMP_FARSI_FONT_PAGE: sDetails = "Simplified Farsi Windows 3.1 font page"; break; case TRAD_FARSI_FONT_PAGE: sDetails = "Traditional Farsi Windows 3.1 font page"; break; case THAI_FONT_PAGE: sDetails = "Thai Windows 3.1 font page"; break; default: for (int i=0; i<16; i++) { int nBitValue = 1<<i; if ((nBitValue & 0xFF80) != 0) { if ((fsSelection & nBitValue) != 0) { if (bFoundFirstBadBit) { sDetails += ", " + i; } else { sDetails += i.ToString(); bFoundFirstBadBit = true; } } } } break; } } else { for (int i=0; i<16; i++) { int nBitValue = 1<<i; if ((nBitValue & 0xFF80) != 0) { if ((fsSelection & nBitValue) != 0) { if (bFoundFirstBadBit) { sDetails += ", " + i; } else { sDetails += i.ToString(); bFoundFirstBadBit = true; } } } } } v.Error(T.OS_2_fsSelection, E.OS_2_E_fsSelection_undefbits, m_tag, sDetails); bSelOk = false; bRet = false; } // compare to head.macStyle italic and bold bits Table_head headTable = (Table_head)fontOwner.GetTable("head"); if (headTable != null) { bool bItalic = ((fsSelection & 0x01) != 0 ); bool bBold = ((fsSelection & 0x20) != 0 ); bool bMacBold = ((headTable.macStyle & 0x0001) != 0); bool bMacItal = ((headTable.macStyle & 0x0002) != 0); if (bItalic != bMacItal) { string sDetails = null; if (bItalic) sDetails = "fsSelection italic bit is set, but macstyle italic bit is clear"; else sDetails = "fsSelection italic bit is clear, but macstyle italic bit is set"; v.Error(T.OS_2_fsSelection, E.OS_2_E_fsSelection_macStyle_italic, m_tag, sDetails); bSelOk = false; bRet = false; } if (bBold != bMacBold) { string sDetails = null; if (bBold) sDetails = "fsSelection bold bit is set, but macstyle bold bit is clear"; else sDetails = "fsSelection bold bit is clear, but macstyle bold bit is set"; v.Error(T.OS_2_fsSelection, E.OS_2_E_fsSelection_macStyle_bold, m_tag, sDetails); bSelOk = false; bRet = false; } } if ((fsSelection & 0x01) != 0 ) // italic bit { // compare to name subfamily if (sStyleLower != null) { if (sStyleLower.IndexOf("italic") == -1 && sStyleLower.IndexOf("oblique") == -1) { v.Error(T.OS_2_fsSelection, E.OS_2_E_fsSelection_subfamily, m_tag, "fsSelection italic bit is set, but subfamily is " + sStyle); bSelOk = false; bRet = false; } } } if ((fsSelection & 0x20) != 0 ) // bold bit { // compare to name subfamily if (sStyleLower != null) { if (sStyleLower.IndexOf("bold") == -1) { v.Error(T.OS_2_fsSelection, E.OS_2_E_fsSelection_subfamily, m_tag, "fsSelection bold bit is set, but subfamily is " + sStyle); bSelOk = false; bRet = false; } } if (usWeightClass <= 500) { v.Warning(T.OS_2_fsSelection, W.OS_2_W_fsSelection_weight, m_tag, "usWeightClass = " + usWeightClass); bSelOk = false; } } if ((fsSelection & 0x40) != 0 ) // regular bit { if ((fsSelection & 0x20) != 0 ) { v.Error(T.OS_2_fsSelection, E.OS_2_E_reg_bold, m_tag); bSelOk = false; bRet = false; } if ((fsSelection & 0x01) != 0) { v.Error(T.OS_2_fsSelection, E.OS_2_E_reg_ital, m_tag); bSelOk = false; bRet = false; } if (sStyleLower != null) { // compare to name subfamily if (sStyleLower.CompareTo("regular") != 0) { v.Error(T.OS_2_fsSelection, E.OS_2_E_fsSelection_subfamily, m_tag, "fsSelection regular bit is set, but subfamily is " + sStyle); bSelOk = false; bRet = false; } } } if (bSelOk) { v.Pass(T.OS_2_fsSelection, P.OS_2_P_fsSelection, m_tag); } } if (v.PerformTest(T.OS_2_CharIndexes)) { Table_cmap cmapTable = (Table_cmap)fontOwner.GetTable("cmap"); if (cmapTable != null) { ushort charFirst = 0xffff; ushort charLast = 0; Table_cmap.EncodingTableEntry eteUni = cmapTable.GetEncodingTableEntry(3,1); if (eteUni == null) { // presumably a symbol font eteUni = cmapTable.GetEncodingTableEntry(3,0); } if (eteUni != null) { Table_cmap.Subtable st = cmapTable.GetSubtable(eteUni); if (st != null) { bool bCmapOk = true; byte[] charbuf = new byte[2]; // find the first char for (ushort c=0; c<0xffff; c++) { charbuf[0] = (byte)c; charbuf[1] = (byte)(c>>8); uint glyphID; try { glyphID = st.MapCharToGlyph(charbuf, 0); } catch { bCmapOk = false; break; } if (glyphID != 0) { charFirst = c; break; } } // find the last char (start at fffd: fffe and ffff aren't legal characters) if (bCmapOk) { for (ushort c=0xfffd; c>0; c--) { charbuf[0] = (byte)c; charbuf[1] = (byte)(c>>8); uint glyphID; try { glyphID = st.MapCharToGlyph(charbuf, 0); } catch { bCmapOk = false; break; } if (glyphID != 0) { charLast = c; break; } } } if (!bCmapOk) { v.Warning(T.OS_2_CharIndexes, W._TEST_W_ErrorInAnotherTable, m_tag, "usFirstCharIndex and usLastCharIndex cannot be validated due to errors in the cmap table"); } else if (usFirstCharIndex == charFirst && usLastCharIndex == charLast) { v.Pass(T.OS_2_CharIndexes, P.OS_2_P_CharIndexes, m_tag, "first = 0x" + usFirstCharIndex.ToString("x4") + ", last = 0x" + usLastCharIndex.ToString("x4")); } else { if (usFirstCharIndex != charFirst) { String sDetails = "actual = 0x" + usFirstCharIndex.ToString("x4") + ", calculated = 0x" + charFirst.ToString("x4"); v.Error(T.OS_2_CharIndexes, E.OS_2_E_usFirstCharIndex, m_tag, sDetails); bRet = false; } if (usLastCharIndex != charLast) { String sDetails = "actual = 0x" + usLastCharIndex.ToString("x4") + ", calculated = 0x" + charLast.ToString("x4"); v.Error(T.OS_2_CharIndexes, E.OS_2_E_usLastCharIndex, m_tag, sDetails); bRet = false; } } } else { v.Warning(T.OS_2_CharIndexes, W._TEST_W_ErrorInAnotherTable, m_tag, "usFirstCharIndex and usLastCharIndex cannot be validated due to errors in the cmap table"); } } } else { v.Error(T.OS_2_CharIndexes, E._TEST_E_TableMissing, m_tag, "cmap"); bRet = false; } } if (v.PerformTest(T.OS_2_TypoMetrics)) { bool bOk = true; if (sTypoAscender <= 0) { v.Error(T.OS_2_TypoMetrics, E.OS_2_E_sTypoAscender_notpositive, m_tag, sTypoAscender.ToString()); bOk = false; bRet = false; } if (sTypoDescender > 0) { v.Error(T.OS_2_TypoMetrics, E.OS_2_E_sTypoDescender_positive, m_tag, sTypoDescender.ToString()); bOk = false; bRet = false; } Table_head headTable = (Table_head)fontOwner.GetTable("head"); if (headTable != null) { if (sTypoAscender - sTypoDescender > headTable.unitsPerEm) { string sDetails = "sTypoAscender = " + sTypoAscender + ", sTypoDescender = " + sTypoDescender; v.Warning(T.OS_2_TypoMetrics, W.OS_2_W_sTypoAscenderDescender_difference, m_tag, sDetails); bOk = false; } } else { v.Error(T.OS_2_TypoMetrics, E._TEST_E_TableMissing, m_tag, "head"); bRet = false; } if (bOk) { string sDetails = "sTypoAscender = " + sTypoAscender + ", sTypoDescender = " + sTypoDescender; v.Pass(T.OS_2_TypoMetrics, P.OS_2_P_sTypoAscenderDescender, m_tag, sDetails); } } if (v.PerformTest(T.OS_2_CodePageRanges)) { if (version >= 1) { bRet &= CheckCodePageRanges(v, fontOwner); } } if (v.PerformTest(T.OS_2_sxHeight)) { if (version >= 2) { if (sxHeight == 0) { if (fontOwner.FastMapUnicodeToGlyphID((char)0x0078) != 0) { v.Error(T.OS_2_sxHeight, E.OS_2_E_sxHeight, m_tag); bRet = false; } else { v.Pass(T.OS_2_sxHeight, P.OS_2_P_sxHeight_zero, m_tag, sxHeight.ToString()); } } else { v.Pass(T.OS_2_sxHeight, P.OS_2_P_sxHeight_nonzero, m_tag, sxHeight.ToString()); } } } if (v.PerformTest(T.OS_2_sCapHeight)) { if (version >= 2) { if (sCapHeight == 0) { if (fontOwner.FastMapUnicodeToGlyphID((char)0x0048) != 0) { v.Error(T.OS_2_sCapHeight, E.OS_2_E_sCapHeight, m_tag); bRet = false; } else { v.Pass(T.OS_2_sCapHeight, P.OS_2_P_sCapHeight_zero, m_tag, sCapHeight.ToString()); } } else { v.Pass(T.OS_2_sCapHeight, P.OS_2_P_sCapHeight_nonzero, m_tag, sCapHeight.ToString()); } } } if (v.PerformTest(T.OS_2_usDefaultChar)) { if (version >= 2) { if (usDefaultChar == 0) { v.Pass(T.OS_2_usDefaultChar, P.OS_2_P_usDefaultChar_zero, m_tag); } else if (fontOwner.FastMapUnicodeToGlyphID((char)usDefaultChar) != 0) { v.Pass(T.OS_2_usDefaultChar, P.OS_2_P_usDefaultChar_nonzero, m_tag, "0x" + usDefaultChar.ToString("x4")); } else { v.Error(T.OS_2_usDefaultChar, E.OS_2_E_usDefaultChar_notmapped, m_tag, "0x" + usDefaultChar.ToString("x4")); bRet = false; } } } if (v.PerformTest(T.OS_2_usBreakChar)) { if (version >= 2) { if (fontOwner.FastMapUnicodeToGlyphID((char)usBreakChar) != 0) { v.Pass(T.OS_2_usBreakChar, P.OS_2_P_usBreakChar_mapped, m_tag); } else { v.Error(T.OS_2_usBreakChar, E.OS_2_E_usBreakChar_notmapped, m_tag, "0x" + usBreakChar.ToString("x4")); bRet = false; } } } if (v.PerformTest(T.OS_2_usMaxContext)) { if (version >= 2) { ushort GPOSMaxContext = 0; Table_GPOS GPOSTable = (Table_GPOS)fontOwner.GetTable("GPOS"); if (GPOSTable != null) { GPOSMaxContext = GPOSTable.GetMaxContext(); } ushort GSUBMaxContext = 0; Table_GSUB GSUBTable = (Table_GSUB)fontOwner.GetTable("GSUB"); if (GSUBTable != null) { GSUBMaxContext = GSUBTable.GetMaxContext(); } ushort CalcMaxContext = Math.Max(GPOSMaxContext, GSUBMaxContext); if (usMaxContext == CalcMaxContext) { v.Pass(T.OS_2_usMaxContext, P.OS_2_P_usMaxContext, m_tag, usMaxContext.ToString()); } else { v.Error(T.OS_2_usMaxContext, E.OS_2_E_usMaxContext, m_tag, "calc = " + CalcMaxContext + ", actual = " + usMaxContext); bRet = false; } } } return bRet; }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.BASE_Version)) { if (Version.GetUint() == 0x00010000 || Version.GetUint() == 0x00010001) { v.Pass(T.BASE_Version, P.BASE_P_Version, m_tag); } else { v.Error(T.BASE_Version, E.BASE_E_Version, m_tag, "0x" + Version.GetUint().ToString("x8")); bRet = false; } } if (v.PerformTest(T.BASE_HeaderOffsets)) { if (HorizAxisOffset == 0) { v.Pass(T.BASE_HeaderOffsets, P.BASE_P_HorizAxisOffset_null, m_tag); } else if (HorizAxisOffset < GetLength()) { v.Pass(T.BASE_HeaderOffsets, P.BASE_P_HorizAxisOffset_valid, m_tag); } else { v.Error(T.BASE_HeaderOffsets, E.BASE_E_HorizAxisOffset_OutsideTable, m_tag); bRet = false; } if (VertAxisOffset == 0) { v.Pass(T.BASE_HeaderOffsets, P.BASE_P_VertAxisOffset_null, m_tag); } else if (VertAxisOffset < GetLength()) { v.Pass(T.BASE_HeaderOffsets, P.BASE_P_VertAxisOffset_valid, m_tag); } else { v.Error(T.BASE_HeaderOffsets, E.BASE_E_VertAxisOffset_OutsideTable, m_tag); bRet = false; } } if (v.PerformTest(T.BASE_HorizAxisTable)) { AxisTable_val at = GetHorizAxisTable_val(); if (at != null) { at.Validate(v, "H Axis", this); } } if (v.PerformTest(T.BASE_VertAxisTable)) { AxisTable_val at = GetVertAxisTable_val(); if (at != null) { at.Validate(v, "V Axis", this); } } // TODO: BASE Item Variation Store return(bRet); }
protected bool CheckTableAlignment(Validator v) { Debug.Assert(m_OffsetTable != null); bool bRet = false; if (m_OffsetTable != null) { bRet = true; for (int i = 0; i<m_OffsetTable.DirectoryEntries.Count; i++) { DirectoryEntry de = (DirectoryEntry)m_OffsetTable.DirectoryEntries[i]; if ((de.offset & 0x03) != 0) { v.Warning(T.T_NULL, W._DE_W_TableAlignment, null, (string)de.tag); //bRet = false; } } if (bRet == true) { v.Pass(P._DE_P_TableAlignment, null); } } return bRet; }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.head_TableLength)) { if (m_bufTable.GetLength() == 54) { v.Pass(T.head_TableLength, P.head_P_TableLength, m_tag); } else { v.Error(T.head_TableLength, E.head_E_TableLength, m_tag, m_bufTable.GetLength().ToString()); bRet = false; } } if (v.PerformTest(T.head_TableVersion)) { if (TableVersionNumber.GetUint() == 0x00010000) { v.Pass(T.head_TableVersion, P.head_P_TableVersion, m_tag); } else { v.Error(T.head_TableVersion, E.head_E_TableVersion, m_tag, "0x"+TableVersionNumber.GetUint().ToString("x8")); bRet = false; } } if (v.PerformTest(T.head_fontRevision)) { string sVersion = fontOwner.GetFontVersion(); if (sVersion != null) { if (sVersion.Length >= 11 && sVersion.StartsWith("Version ") && Char.IsDigit(sVersion, 8)) { string sVersionNum = sVersion.Substring(8); bool bFoundDecPt = false; int nLastDigitPos = 0; for (int i=0; i<sVersionNum.Length; i++) { if (Char.IsDigit(sVersionNum, i)) { nLastDigitPos = i; } else if (sVersionNum[i] == '.') { if (!bFoundDecPt) { bFoundDecPt = true; } else { break; } } else { break; } } double fVersion = Double.Parse(sVersionNum.Substring(0, nLastDigitPos+1)); double fRevision = fontRevision.GetDouble(); if (Math.Round(fVersion, 3) == Math.Round(fRevision, 3)) { v.Pass(T.head_fontRevision, P.head_P_fontRevision, m_tag, fRevision.ToString("f3")); } else { string s = "revision: " + fRevision.ToString("f3") + ", version: " + sVersionNum; v.Warning(T.head_fontRevision, W.head_W_fontRevision, m_tag, s); } } } } if (v.PerformTest(T.head_ChecksumAdjustment)) { if (checkSumAdjustment == 0xb1b0afba - fontOwner.CalcChecksum()) { v.Pass(T.head_ChecksumAdjustment, P.head_P_FontChecksum, m_tag, "0x"+checkSumAdjustment.ToString("x8")); } else { v.Error(T.head_ChecksumAdjustment, E.head_E_FontChecksum, m_tag, "0x"+checkSumAdjustment.ToString("x8")); bRet = false; } } if (v.PerformTest(T.head_MagicNumber)) { if (magicNumber == 0x5f0f3cf5) { v.Pass(T.head_MagicNumber, P.head_P_MagicNumber, m_tag); } else { v.Error(T.head_MagicNumber, E.head_E_MagicNumber, m_tag, "0x"+magicNumber.ToString("x8")); bRet = false; } } if (v.PerformTest(T.head_FlagTests)) { ushort val = flags; // bit 0 indicates baseline for font at y=0 // bit 1 indicates left sidebearing point at x=0 // bit 2 indicates instructions may depend on point size // bit 3 indicates forcing ppem to integer values instead of fractional values // bit 4 indicates non-linear scaling - if set allows presence of LTSH and/or hdmx tables Table_hdmx hdmxTable = (Table_hdmx)fontOwner.GetTable("hdmx"); Table_LTSH LTSHTable = (Table_LTSH)fontOwner.GetTable("LTSH"); if ((val & 0x0010) == 0) { if (hdmxTable == null) { v.Pass(T.head_FlagTests, P.head_P_flags_bit4_0_hdmx, m_tag); } else { v.Error(T.head_FlagTests, E.head_E_flags_bit4_0_hdmx, m_tag); } if (LTSHTable == null) { v.Pass(T.head_FlagTests, P.head_P_flags_bit4_0_LTSH, m_tag); } else { v.Error(T.head_FlagTests, E.head_E_flags_bit4_0_LTSH, m_tag); } } else { if (hdmxTable != null) { v.Pass(T.head_FlagTests, P.head_P_flags_bit4_1_hdmx, m_tag); } else { v.Warning(T.head_FlagTests, W.head_W_flags_bit4_1_hdmx, m_tag); } if (LTSHTable != null) { v.Pass(T.head_FlagTests, P.head_P_flags_bit4_1_LTSH, m_tag); } else { v.Warning(T.head_FlagTests, W.head_W_flags_bit4_1_LTSH, m_tag); } } // bits 5 - 10 are used by apple and ignored by windows // bit 11 indicates font data is 'lossless' as a result of having been compressed/decompressed // bit 12 indicates a converted font // bit 13 indicates optimized for cleartype // bit 14 reserved if ((val & 0x4000) == 0) { v.Pass(T.head_FlagTests, P.head_P_flags_bit14, m_tag); } else { v.Error(T.head_FlagTests, E.head_E_flags_bit14, m_tag, val.ToString()); bRet = false; } // bit 15 reserved if ((val & 0x8000) == 0) { v.Pass(T.head_FlagTests, P.head_P_flags_bit15, m_tag); } else { v.Error(T.head_FlagTests, E.head_E_flags_bit15, m_tag, val.ToString()); bRet = false; } } if (v.PerformTest(T.head_UnitsPerEmValues)) { ushort val = unitsPerEm; bool bInRange = false; if (val < 16) // opentype spec says min value is 16 { v.Error(T.head_UnitsPerEmValues, E.head_E_unitsPerEm_LT16, m_tag, val.ToString()); bRet = false; } else if (val < 64) // apple spec says min value is 64 { v.Warning(T.head_UnitsPerEmValues, W.head_W_unitsPerEM_LT64, m_tag, val.ToString()); } else if (val > 16384) { v.Error(T.head_UnitsPerEmValues, E.head_E_unitsPerEM_GT16384, m_tag, val.ToString()); bRet = false; } else { bInRange = true; } // apple spec says unitsPerEm must be power of two // but don't check if it's a CFF font if (!fontOwner.ContainsPostScriptOutlines()) { bool bPowerOfTwo = false; for (int i=0; i<16; i++) { ushort nPow2 = (ushort)(1<<i); if (val == nPow2) { bPowerOfTwo = true; break; } } if (bPowerOfTwo) { if (bInRange) { v.Pass(T.head_UnitsPerEmValues, P.head_P_unitsPerEm, m_tag, val.ToString()); } } else { v.Warning(T.head_UnitsPerEmValues, W.head_W_unitsPerEm_Pow2, m_tag, val.ToString()); } } } if (v.PerformTest(T.head_Dates)) { DateTime dtBeforeTrueType = new DateTime(1985, 1, 1); if ((created >> 32) == 0) { DateTime dtCreated = this.GetCreatedDateTime(); if (created == 0) { v.Warning(T.head_Dates, W.head_W_created_0, m_tag); } else if (dtCreated < dtBeforeTrueType || dtCreated > DateTime.Now) { string sDetails = "created = " + created + " (" + dtCreated.ToString("f", null) + ")"; v.Warning(T.head_Dates, W.head_W_created_unlikely, m_tag, sDetails); } else { v.Pass(T.head_Dates, P.head_P_created_0, m_tag); } } else { string sDetails = "created = 0x" + created.ToString("x16"); v.Error(T.head_Dates, E.head_E_created_invalid, m_tag, sDetails); bRet = false; } if ((modified >> 32) == 0) { DateTime dtModified = this.GetModifiedDateTime(); if (modified == 0) { v.Warning(T.head_Dates, W.head_W_modified_0, m_tag); } else if (dtModified < dtBeforeTrueType || dtModified > DateTime.Now) { string sDetails = "modified = " + modified + " (" + dtModified.ToString("f", null) + ")"; v.Warning(T.head_Dates, W.head_W_modified_unlikely, m_tag, sDetails); } else { v.Pass(T.head_Dates, P.head_P_modified_0, m_tag); } } else { string sDetails = "modified = 0x" + modified.ToString("x16"); v.Error(T.head_Dates, E.head_E_modified_invalid, m_tag, sDetails); bRet = false; } } if (v.PerformTest(T.head_MinMaxValues)) { if (fontOwner.ContainsTrueTypeOutlines()) { if (xMin > xMax) { v.Error(T.head_MinMaxValues, E.head_E_xMin_GT_xMax, m_tag); bRet = false; } if (yMin > yMax) { v.Error(T.head_MinMaxValues, E.head_E_yMin_GT_yMax, m_tag); bRet = false; } short xMinExpected = 32767; short xMaxExpected = -32768; short yMinExpected = 32767; short yMaxExpected = -32768; Table_glyf glyfTable = (Table_glyf)fontOwner.GetTable("glyf"); if (glyfTable != null) { Table_maxp maxp = (Table_maxp)fontOwner.GetTable("maxp"); if (maxp != null) { for (uint i=0; i<fontOwner.GetMaxpNumGlyphs(); i++) { Table_glyf.header h = glyfTable.GetGlyphHeader(i, fontOwner); if (h != null) { if (xMinExpected > h.xMin) xMinExpected = h.xMin; if (xMaxExpected < h.xMax) xMaxExpected = h.xMax; if (yMinExpected > h.yMin) yMinExpected = h.yMin; if (yMaxExpected < h.yMax) yMaxExpected = h.yMax; } } if (xMin == xMinExpected) { String s = "xMin = " + xMin; v.Pass(T.head_MinMaxValues, P.head_P_xMin_glyf, m_tag, s); } else { string s = "actual: " + xMin + ", expected: " + xMinExpected; v.Error(T.head_MinMaxValues, E.head_E_xMin_glyf, m_tag, s); bRet = false; } if (yMin == yMinExpected) { String s = "yMin = " + yMin; v.Pass(T.head_MinMaxValues, P.head_P_yMin_glyf, m_tag, s); } else { string s = "actual: " + yMin + ", expected: " + yMinExpected; v.Error(T.head_MinMaxValues, E.head_E_yMin_glyf, m_tag, s); bRet = false; } if (xMax == xMaxExpected) { String s = "xMax = " + xMax; v.Pass(T.head_MinMaxValues, P.head_P_xMax_glyf, m_tag, s); } else { string s = "actual: " + xMax + ", expected: " + xMaxExpected; v.Error(T.head_MinMaxValues, E.head_E_xMax_glyf, m_tag, s); bRet = false; } if (yMax == yMaxExpected) { String s = "yMax = " + yMax; v.Pass(T.head_MinMaxValues, P.head_P_yMax_glyf, m_tag, s); } else { string s = "actual: " + yMax + ", expected: " + yMaxExpected; v.Error(T.head_MinMaxValues, E.head_E_yMax_glyf, m_tag, s); bRet = false; } } else { v.Error(T.head_MinMaxValues, E._TEST_E_TableMissing, m_tag, "maxp"); } } else { v.Error(T.head_MinMaxValues, E._TEST_E_TableMissing, m_tag, "glyf"); } } else { v.Info(T.head_MinMaxValues, I._TEST_I_NotForCFF, m_tag, "test = head_MinMaxValues"); } } if (v.PerformTest(T.head_MacStyleBits)) { bool bMacBold = ((macStyle & 0x0001) != 0); bool bMacItal = ((macStyle & 0x0002) != 0); // subfamily (style) string Table_name nameTable = (Table_name)fontOwner.GetTable("name"); string sStyle = null; string sStyleLower = null; if (nameTable != null) { sStyle = nameTable.GetStyleString(); if (sStyle != null) { sStyleLower = sStyle.ToLower(); } } if (sStyleLower != null) { if (bMacBold && sStyleLower.IndexOf("bold") == -1) { v.Error(T.head_MacStyleBits, E.head_E_macStyleBold_subfamily, m_tag, "macStyle bold bit is set, but subfamily is " + sStyle); bRet = false; } else if (!bMacBold && sStyleLower.IndexOf("bold") != -1) { v.Error(T.head_MacStyleBits, E.head_E_macStyleBold_subfamily, m_tag, "macStyle bold bit is clear, but subfamily is " + sStyle); bRet = false; } else { v.Pass(T.head_MacStyleBits, P.head_P_macStyleBold_subfamily, m_tag); } if (bMacItal && sStyleLower.IndexOf("italic") == -1 && sStyleLower.IndexOf("oblique") == -1) { v.Error(T.head_MacStyleBits, E.head_E_macStyleItal_subfamily, m_tag, "macStyle italic bit is set, but subfamily is " + sStyle); bRet = false; } else if (!bMacItal && (sStyleLower.IndexOf("italic") != -1 || sStyleLower.IndexOf("oblique") != -1)) { v.Error(T.head_MacStyleBits, E.head_E_macStyleItal_subfamily, m_tag, "macStyle italic bit is clear, but subfamily is " + sStyle); bRet = false; } else { v.Pass(T.head_MacStyleBits, P.head_P_macStyleItal_subfamily, m_tag); } } Table_OS2 OS2Table = (Table_OS2)fontOwner.GetTable("OS/2"); if (OS2Table != null) { // fsSelection bool bOS2Bold = ((OS2Table.fsSelection & 0x0020) != 0); bool bOS2Ital = ((OS2Table.fsSelection & 0x0001) != 0); if (bMacBold == bOS2Bold) { v.Pass(T.head_MacStyleBits, P.head_P_macStyleBold_OS2, m_tag); } else if (bMacBold) { v.Error(T.head_MacStyleBits, E.head_E_macStyleBold1_OS2, m_tag); bRet = false; } else { v.Error(T.head_MacStyleBits, E.head_E_macStyleBold0_OS2, m_tag); bRet = false; } if (bMacItal == bOS2Ital) { v.Pass(T.head_MacStyleBits, P.head_P_macStyleItal_OS2, m_tag); } else if (bMacItal) { v.Error(T.head_MacStyleBits, E.head_E_macStyleItal1_OS2, m_tag); bRet = false; } else { v.Error(T.head_MacStyleBits, E.head_E_macStyleItal0_OS2, m_tag); bRet = false; } } Table_post postTable = (Table_post)fontOwner.GetTable("post"); if (postTable != null) { bool bPostItal = (postTable.italicAngle.GetUint() != 0); if (bMacItal == bPostItal) { v.Pass(T.head_MacStyleBits, P.head_P_macStyleItal_post, m_tag); } else if (bMacItal) { v.Error(T.head_MacStyleBits, E.head_E_macStyleItal1_post, m_tag); bRet = false; } else { v.Error(T.head_MacStyleBits, E.head_E_macStyleItal0_post, m_tag); bRet = false; } } } if (v.PerformTest(T.head_LowestRecSize)) { if (lowestRecPPEM == 0) { v.Error(T.head_LowestRecSize, E.head_E_lowestRecPPEM_zero, m_tag); bRet = false; } else if (lowestRecPPEM >= 1 && lowestRecPPEM <= 6) { v.Warning(T.head_LowestRecSize, W.head_W_lowestRecPPEM_small, m_tag, "lowestRecPPEM = " + lowestRecPPEM.ToString()); } else if (lowestRecPPEM >= 36) { v.Warning(T.head_LowestRecSize, W.head_W_lowestRecPPEM_large, m_tag, "lowestRecPPEM = " + lowestRecPPEM.ToString()); } else { v.Pass(T.head_LowestRecSize, P.head_P_lowestRecPPEM, m_tag); } } if (v.PerformTest(T.head_FontDirectionHint)) { if (fontDirectionHint >= -2 && fontDirectionHint <= 2) { v.Pass(T.head_FontDirectionHint, P.head_P_fontDirectionHint, m_tag, fontDirectionHint.ToString()); } else { v.Error(T.head_FontDirectionHint, E.head_E_fontDirectionHint, m_tag, fontDirectionHint.ToString()); bRet = false; } } if (v.PerformTest(T.head_IndexToLocFormat)) { if (fontOwner.ContainsPostScriptOutlines()) { v.Pass(T.head_IndexToLocFormat, P.head_P_indexToLocFormat_ignore, m_tag, "indexToLocFormat = " + indexToLocFormat); } else { if (indexToLocFormat == 0 || indexToLocFormat == 1) { v.Pass(T.head_IndexToLocFormat, P.head_P_indexToLocFormat_range, m_tag, indexToLocFormat.ToString()); } else { v.Error(T.head_IndexToLocFormat, E.head_E_indexToLocFormat_range, m_tag, indexToLocFormat.ToString()); bRet = false; } if (indexToLocFormat == 0 || indexToLocFormat == 1) { Table_loca locaTable = (Table_loca)fontOwner.GetTable("loca"); if (locaTable != null) { Table_maxp maxpTable = (Table_maxp)fontOwner.GetTable("maxp"); if (maxpTable != null) { uint locaTableElementSize = 0; if (indexToLocFormat == 0) locaTableElementSize = 2; else if (indexToLocFormat == 1) locaTableElementSize = 4; uint CalcLocaLength = (uint)(maxpTable.NumGlyphs + 1) * locaTableElementSize; if (CalcLocaLength == locaTable.GetLength()) { v.Pass(T.head_IndexToLocFormat, P.head_P_indexToLocFormat_match, m_tag, indexToLocFormat.ToString()); } else { v.Error(T.head_IndexToLocFormat, E.head_E_indexToLocFormat_match, m_tag, indexToLocFormat.ToString()); bRet = false; } } else { v.Error(T.head_IndexToLocFormat, E._TEST_E_TableMissing, m_tag, "maxp"); } } else { v.Error(T.head_IndexToLocFormat, E._TEST_E_TableMissing, m_tag, "loca"); } } } } if (v.PerformTest(T.head_GlyphDataFormat)) { if (glyphDataFormat == 0) { v.Pass(T.head_GlyphDataFormat, P.head_P_glyphDataFormat, m_tag); } else { v.Error(T.head_GlyphDataFormat, E.head_E_glyphDataFormat, m_tag); bRet = false; } } return bRet; }
private bool CheckCodePageRanges(Validator v, OTFont fontOwner) { bool bRet = true; bRet &= CheckCodePageBit(0, 1252, "Latin 1", v, fontOwner); bRet &= CheckCodePageBit(1, 1250, "Latin 2", v, fontOwner); bRet &= CheckCodePageBit(2, 1251, "Cyrillic", v, fontOwner); bRet &= CheckCodePageBit(3, 1253, "Greek", v, fontOwner); bRet &= CheckCodePageBit(4, 1254, "Turkish", v, fontOwner); bRet &= CheckCodePageBit(5, 1255, "Hebrew", v, fontOwner); bRet &= CheckCodePageBit(6, 1256, "Arabic", v, fontOwner); bRet &= CheckCodePageBit(7, 1257, "Baltic", v, fontOwner); bRet &= CheckCodePageBit(8, 1258, "Vietnamese", v, fontOwner); // bits 9-15 are reserved bRet &= CheckCodePageBit( 9, 0, null, v, fontOwner); bRet &= CheckCodePageBit(10, 0, null, v, fontOwner); bRet &= CheckCodePageBit(11, 0, null, v, fontOwner); bRet &= CheckCodePageBit(12, 0, null, v, fontOwner); bRet &= CheckCodePageBit(13, 0, null, v, fontOwner); bRet &= CheckCodePageBit(14, 0, null, v, fontOwner); bRet &= CheckCodePageBit(15, 0, null, v, fontOwner); bRet &= CheckCodePageBit(16, 874, "Thai", v, fontOwner); bRet &= CheckCodePageBit(17, 932, "Japanese Shift-JIS", v, fontOwner); bRet &= CheckCodePageBit(18, 936, "Chinese simplified", v, fontOwner); bRet &= CheckCodePageBit(19, 949, "Korean Wansung", v, fontOwner); bRet &= CheckCodePageBit(20, 950, "Chinese traditional", v, fontOwner); bRet &= CheckCodePageBit(21, 1361, "Korean Johab", v, fontOwner); // bits 22-28 are reserved bRet &= CheckCodePageBit(22, 0, null, v, fontOwner); bRet &= CheckCodePageBit(23, 0, null, v, fontOwner); bRet &= CheckCodePageBit(24, 0, null, v, fontOwner); bRet &= CheckCodePageBit(25, 0, null, v, fontOwner); bRet &= CheckCodePageBit(26, 0, null, v, fontOwner); bRet &= CheckCodePageBit(27, 0, null, v, fontOwner); bRet &= CheckCodePageBit(28, 0, null, v, fontOwner); bRet &= CheckCodePageBit(29, 10000, "Mac character set", v, fontOwner); //bRet &= CheckCodePageBit(30, ???? , "OEM character set", v, fontOwner); // no code page specified bRet &= CheckCodePageBit(31, 0, "Symbol character set", v, fontOwner); // bits 32-47 are reserved bRet &= CheckCodePageBit(32, 0, null, v, fontOwner); bRet &= CheckCodePageBit(33, 0, null, v, fontOwner); bRet &= CheckCodePageBit(34, 0, null, v, fontOwner); bRet &= CheckCodePageBit(35, 0, null, v, fontOwner); bRet &= CheckCodePageBit(36, 0, null, v, fontOwner); bRet &= CheckCodePageBit(37, 0, null, v, fontOwner); bRet &= CheckCodePageBit(38, 0, null, v, fontOwner); bRet &= CheckCodePageBit(39, 0, null, v, fontOwner); bRet &= CheckCodePageBit(40, 0, null, v, fontOwner); bRet &= CheckCodePageBit(41, 0, null, v, fontOwner); bRet &= CheckCodePageBit(42, 0, null, v, fontOwner); bRet &= CheckCodePageBit(43, 0, null, v, fontOwner); bRet &= CheckCodePageBit(44, 0, null, v, fontOwner); bRet &= CheckCodePageBit(45, 0, null, v, fontOwner); bRet &= CheckCodePageBit(46, 0, null, v, fontOwner); bRet &= CheckCodePageBit(47, 0, null, v, fontOwner); bRet &= CheckCodePageBit(48, 869, "IBM Greek", v, fontOwner); bRet &= CheckCodePageBit(49, 866, "MS-DOS Russian", v, fontOwner); bRet &= CheckCodePageBit(50, 865, "MS-DOS Nordic", v, fontOwner); bRet &= CheckCodePageBit(51, 864, "Arabic", v, fontOwner); bRet &= CheckCodePageBit(52, 863, "MS-DOS Canadian French", v, fontOwner); bRet &= CheckCodePageBit(53, 862, "Hebrew", v, fontOwner); bRet &= CheckCodePageBit(54, 861, "MS-DOS Icelandic", v, fontOwner); bRet &= CheckCodePageBit(55, 860, "MS-DOS Portuguese", v, fontOwner); bRet &= CheckCodePageBit(56, 857, "IBM Turkish", v, fontOwner); bRet &= CheckCodePageBit(57, 855, "IBM Cyrillic", v, fontOwner); bRet &= CheckCodePageBit(58, 852, "Latin 2", v, fontOwner); bRet &= CheckCodePageBit(59, 775, "MS-DOS Baltic", v, fontOwner); bRet &= CheckCodePageBit(60, 737, "Greek", v, fontOwner); bRet &= CheckCodePageBit(61, 708, "Arabic; ASMO 708", v, fontOwner); bRet &= CheckCodePageBit(62, 850, "WE/Latin 1", v, fontOwner); bRet &= CheckCodePageBit(63, 437, "US", v, fontOwner); if (bRet == true) { v.Pass(P.OS_2_P_CodePageRanges, m_tag); } return bRet; }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; bRet &= ((val_BASE)table).ValidateNoOverlap(m_offsetBaseScriptTable, CalcLength(), v, sIdentity, table.GetTag()); // check the BaseValuesOffset if (BaseValuesOffset == 0) { v.Pass(T.T_NULL, P.BASE_P_BaseValuesOffset_null, table.m_tag, sIdentity); } else if (BaseValuesOffset + m_offsetBaseScriptTable > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.BASE_E_BaseValuesOffset, table.m_tag, sIdentity); } else { v.Pass(T.T_NULL, P.BASE_P_BaseValuesOffset, table.m_tag, sIdentity); } // check the DefaultMinMaxOffset if (DefaultMinMaxOffset == 0) { v.Pass(T.T_NULL, P.BASE_P_DefaultMinMaxOffset_null, table.m_tag, sIdentity); } else if (DefaultMinMaxOffset + m_offsetBaseScriptTable > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.BASE_E_DefaultMinMaxOffset, table.m_tag, sIdentity); } else { v.Pass(T.T_NULL, P.BASE_P_DefaultMinMaxOffset, table.m_tag, sIdentity); } // check the BaseLangSysRecord order bool bOrderOk = true; if (BaseLangSysCount > 1) { for (uint i = 0; i < BaseLangSysCount - 1; i++) { BaseLangSysRecord ThisBlsr = GetBaseLangSysRecord(i); BaseLangSysRecord NextBlsr = GetBaseLangSysRecord(i + 1); if (ThisBlsr.BaseLangSysTag >= NextBlsr.BaseLangSysTag) { v.Error(T.T_NULL, E.BASE_E_BaseLangSysRecord_order, table.m_tag, sIdentity); bOrderOk = false; bRet = false; } } } if (bOrderOk) { v.Pass(T.T_NULL, P.BASE_P_BaseLangSysRecord_order, table.m_tag, sIdentity); } // check the BaseLangSysRecord MinMaxOffsets bool bOffsetsOk = true; for (uint i = 0; i < BaseLangSysCount; i++) { BaseLangSysRecord bslr = GetBaseLangSysRecord(i); if (bslr.MinMaxOffset == 0) { v.Error(T.T_NULL, E.BASE_E_BaseLangSysRecord_offset0, table.m_tag, sIdentity + ", BaseLangSysRecord index = " + i); bOffsetsOk = false; bRet = false; } else if (bslr.MinMaxOffset + m_offsetBaseScriptTable > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.BASE_E_BaseLangSysRecord_offset, table.m_tag, sIdentity + ", BaseLangSysRecord index = " + i); bOffsetsOk = false; bRet = false; } } if (bOffsetsOk) { v.Pass(T.T_NULL, P.BASE_P_BaseLangSysRecord_offsets, table.m_tag, sIdentity); } // check the BaseValuesTable if (BaseValuesOffset != 0) { BaseValuesTable_val bvt = GetBaseValuesTable_val(); bvt.Validate(v, sIdentity, table); } // check the Default MinMaxTable if (DefaultMinMaxOffset != 0) { MinMaxTable_val mmt = GetDefaultMinMaxTable_val(); mmt.Validate(v, sIdentity + ", default MinMax", table); } // check the BaseLangSysRecord MinMaxTables for (uint i = 0; i < BaseLangSysCount; i++) { BaseLangSysRecord blsr = GetBaseLangSysRecord(i); MinMaxTable_val mmt = GetMinMaxTable_val(blsr); mmt.Validate(v, sIdentity + ", BaseLangSysRecord[" + i + "]", table); } return(bRet); }
/***************** * public methods */ public bool Validate() { bool bRet = true; int canrast; Validator v = GetFile().GetValidator(); if (v.PerformTest(T._OFFSET_sfntVersion)) { uint sfnt = m_OffsetTable.sfntVersion.GetUint(); if (!OTFile.IsValidSfntVersion(sfnt)) { v.Error(T._OFFSET_sfntVersion, E._OFFSET_E_InvalidSFNT, null, "0x" + sfnt.ToString("x8")); bRet = false; } } if (v.PerformTest(T._OFFSET_numTables)) { if (m_OffsetTable.numTables == 0) { v.Error(T._OFFSET_numTables, E._OFFSET_E_numTables, null); bRet = false; } else { v.Pass(T._OFFSET_numTables, P._OFFSET_P_numTables, null, m_OffsetTable.numTables.ToString()); } } if (v.PerformTest(T._OFFSET_BinarySearchFields)) { ushort numTables = m_OffsetTable.numTables; ushort CalculatedSearchRange = (ushort)(util.MaxPower2LE(numTables) * 16); ushort CalculatedEntrySelector = util.Log2(util.MaxPower2LE(numTables)); ushort CalculatedRangeShift = (ushort)(numTables * 16 - CalculatedSearchRange); bool bBinaryFieldsOk = true; if (m_OffsetTable.searchRange != CalculatedSearchRange) { v.Error(T._OFFSET_BinarySearchFields, E._OFFSET_E_searchRange, null, m_OffsetTable.searchRange.ToString()); bBinaryFieldsOk = false; bRet = false; } if (m_OffsetTable.entrySelector != CalculatedEntrySelector) { v.Error(T._OFFSET_BinarySearchFields, E._OFFSET_E_entrySelector, null, m_OffsetTable.entrySelector.ToString()); bBinaryFieldsOk = false; bRet = false; } if (m_OffsetTable.rangeShift != CalculatedRangeShift) { v.Error(T._OFFSET_BinarySearchFields, E._OFFSET_E_rangeShift, null, m_OffsetTable.rangeShift.ToString()); bBinaryFieldsOk = false; bRet = false; } if (bBinaryFieldsOk) { v.Pass(T._OFFSET_BinarySearchFields, P._OFFSET_P_BinarySearchTables, null); } } bRet &= CheckDirectoryEntriesNonZero(v); bRet &= CheckTablesInFileAndNotOverlapping(v); bRet &= CheckNoDuplicateTags(v); if (v.PerformTest(T._DE_TagsAscendingOrder)) { bRet &= CheckTagsAscending(v); } if (v.PerformTest(T._DE_TagNames)) { bRet &= CheckTagNames(v); } if (v.PerformTest(T._DE_TableAlignment)) { bRet &= CheckTableAlignment(v); } if (v.PerformTest(T._FONT_RequiredTables)) { bRet &= CheckForRequiredTables(v); } if (v.PerformTest(T._FONT_RecommendedTables)) { bRet &= CheckForRecommendedTables(v); } if (v.PerformTest(T._FONT_UnnecessaryTables)) { bRet &= CheckForNoUnnecessaryTables(v); } if (v.PerformTest(T._FONT_OptimalTableOrder)) { bRet &= CheckForOptimalTableOrder(v); } // Validate each table if (m_OffsetTable != null) { for (int i = 0; i < m_OffsetTable.DirectoryEntries.Count; i++) { // check to see if user canceled validation if (v.CancelFlag) { break; } // get the table DirectoryEntry de = (DirectoryEntry)m_OffsetTable.DirectoryEntries[i]; OTTable table = GetFile().GetTableManager().GetTable(this, de); // Will it really happen? if (GetFile().GetTableManager().GetUnaliasedTableName(de.tag) == "DSIG" && GetFile().IsCollection()) { continue; } if (GetFile().GetTableManager().GetUnaliasedTableName(de.tag) == "glyf" && Is_TTC_LaterIdenticalTable("glyf")) { v.Info(T.T_NULL, I.glyf_I_IDENTICAL_GLYF_TABLES_IN_TTC, de.tag, "glyf"); continue; } if (GetFile().GetTableManager().GetUnaliasedTableName(de.tag) == "EBDT" && Is_TTC_LaterIdenticalTable("EBDT")) { v.Info(T.T_NULL, I.glyf_I_IDENTICAL_GLYF_TABLES_IN_TTC, de.tag, "EBDT"); continue; } // Call the function that validates a single table bRet &= this.GetFile().ValidateTable(table, v, de, this); } } canrast = TestFontRasterization(); ushort numGlyphs = GetMaxpNumGlyphs(); // rasterization test - BW v.OnRastTestValidationEvent_BW(true); if (v.PeformRastTest_BW() && Is_TTC_LaterIdenticalTable("glyf")) { v.Info(T.T_NULL, I.glyf_I_IDENTICAL_GLYF_TABLES_IN_TTC, null, "B/W Rasterization"); } else if (v.PeformRastTest_BW()) { if (canrast > 0) { try { // fetch the rasterizer object and initialize it with this font RasterInterf ri = GetFile().GetRasterizer(); ri.RasterNewSfnt(GetFile().GetFileStream(), GetFontIndexInFile()); // call the rasterizer RasterInterf.UpdateProgressDelegate upg = new RasterInterf.UpdateProgressDelegate(v.OnTableProgress); RasterInterf.RastTestErrorDelegate rted = new RasterInterf.RastTestErrorDelegate(v.OnRastTestError); int x = v.GetRastTestXRes(); int y = v.GetRastTestYRes(); int [] pointsizes = v.GetRastTestPointSizes(); RastTestTransform rtt = v.GetRastTestTransform(); bRet &= ri.RastTest( x, y, pointsizes, rtt.stretchX, rtt.stretchY, rtt.rotation, rtt.skew, rtt.matrix, true, false, false, 0, rted, upg, numGlyphs); if (ri.GetRastErrorCount() == 0) { v.Pass(T.T_NULL, P._rast_P_rasterization, null); } } catch (Exception e) { v.ApplicationError(T.T_NULL, E._rast_A_ExceptionUnhandled, null, e.Message + e.StackTrace); } } else if (canrast == 0) { v.Info(T.T_NULL, I._rast_I_rasterization, null, GetDevMetricsDataError()); } else { v.Error(T.T_NULL, E._rast_E_rasterization, null, GetDevMetricsDataError()); bRet = false; } } else { v.Info(I._TEST_I_RastTestNotSelected, null); } v.OnRastTestValidationEvent_BW(false); // rasterization test - Grayscale v.OnRastTestValidationEvent_Grayscale(true); if (v.PeformRastTest_Grayscale() && Is_TTC_LaterIdenticalTable("glyf")) { v.Info(T.T_NULL, I.glyf_I_IDENTICAL_GLYF_TABLES_IN_TTC, null, "Grayscale Rasterization"); } else if (v.PeformRastTest_Grayscale()) { if (canrast > 0) { try { // fetch the rasterizer object and initialize it with this font RasterInterf ri = GetFile().GetRasterizer(); ri.RasterNewSfnt(GetFile().GetFileStream(), GetFontIndexInFile()); // call the rasterizer RasterInterf.UpdateProgressDelegate upg = new RasterInterf.UpdateProgressDelegate(v.OnTableProgress); RasterInterf.RastTestErrorDelegate rted = new RasterInterf.RastTestErrorDelegate(v.OnRastTestError); int x = v.GetRastTestXRes(); int y = v.GetRastTestYRes(); int [] pointsizes = v.GetRastTestPointSizes(); RastTestTransform rtt = v.GetRastTestTransform(); bRet &= ri.RastTest( x, y, pointsizes, rtt.stretchX, rtt.stretchY, rtt.rotation, rtt.skew, rtt.matrix, false, true, false, 0, rted, upg, numGlyphs); if (ri.GetRastErrorCount() == 0) { v.Pass(T.T_NULL, P._rast_P_rasterization, null); } } catch (Exception e) { v.ApplicationError(T.T_NULL, E._rast_A_ExceptionUnhandled, null, e.Message + e.StackTrace); } } else if (canrast == 0) { v.Info(T.T_NULL, I._rast_I_rasterization, null, GetDevMetricsDataError()); } else { v.Error(T.T_NULL, E._rast_E_rasterization, null, GetDevMetricsDataError()); bRet = false; } } else { v.Info(I._TEST_I_RastTestNotSelected, null); } v.OnRastTestValidationEvent_Grayscale(false); // rasterization test - Cleartype v.OnRastTestValidationEvent_Cleartype(true); if (v.PeformRastTest_Cleartype() && Is_TTC_LaterIdenticalTable("glyf")) { v.Info(T.T_NULL, I.glyf_I_IDENTICAL_GLYF_TABLES_IN_TTC, null, "Cleartype Rasterization"); } else if (v.PeformRastTest_Cleartype()) { if (canrast > 0) { try { uint CTFlags = v.GetCleartypeFlags(); // fetch the rasterizer object and initialize it with this font RasterInterf ri = GetFile().GetRasterizer(); ri.RasterNewSfnt(GetFile().GetFileStream(), GetFontIndexInFile()); // call the rasterizer RasterInterf.UpdateProgressDelegate upg = new RasterInterf.UpdateProgressDelegate(v.OnTableProgress); RasterInterf.RastTestErrorDelegate rted = new RasterInterf.RastTestErrorDelegate(v.OnRastTestError); int x = v.GetRastTestXRes(); int y = v.GetRastTestYRes(); int [] pointsizes = v.GetRastTestPointSizes(); RastTestTransform rtt = v.GetRastTestTransform(); bRet &= ri.RastTest( x, y, pointsizes, rtt.stretchX, rtt.stretchY, rtt.rotation, rtt.skew, rtt.matrix, false, false, true, CTFlags, rted, upg, numGlyphs); if (ri.GetRastErrorCount() == 0) { v.Pass(T.T_NULL, P._rast_P_rasterization, null); } } catch (Exception e) { v.ApplicationError(T.T_NULL, E._rast_A_ExceptionUnhandled, null, e.Message + e.StackTrace); } } else if (canrast == 0) { v.Info(T.T_NULL, I._rast_I_rasterization, null, GetDevMetricsDataError()); } else { v.Error(T.T_NULL, E._rast_E_rasterization, null, GetDevMetricsDataError()); bRet = false; } } else { v.Info(I._TEST_I_RastTestNotSelected, null); } v.OnRastTestValidationEvent_Cleartype(false); return(bRet); }
public bool Validate(Validator v, string sIdentity, OTTable table) { bool bRet = true; bRet &= ((val_BASE)table).ValidateNoOverlap(m_offsetMinMaxTable, CalcLength(), v, sIdentity, table.GetTag()); // check the MinCoordOffset if (MinCoordOffset == 0) { v.Pass(T.T_NULL, P.BASE_P_MinMaxTable_MinCO_0, table.m_tag, sIdentity); } else if (MinCoordOffset + m_offsetMinMaxTable > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.BASE_E_MinMaxTable_MinCO, table.m_tag, sIdentity); bRet = false; } else { v.Pass(T.T_NULL, P.BASE_P_MinMaxTable_MinCO, table.m_tag, sIdentity); } // check the MaxCoordOffset if (MaxCoordOffset == 0) { v.Pass(T.T_NULL, P.BASE_P_MinMaxTable_MaxCO_0, table.m_tag, sIdentity); } else if (MaxCoordOffset + m_offsetMinMaxTable > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.BASE_E_MinMaxTable_MaxCO, table.m_tag, sIdentity); bRet = false; } else { v.Pass(T.T_NULL, P.BASE_P_MinMaxTable_MaxCO, table.m_tag, sIdentity); } // check the FeatMinMaxRecords bool bFeatMinMaxRecordsOk = true; for (uint i = 0; i < FeatMinMaxCount; i++) { FeatMinMaxRecord fmmr = GetFeatMinMaxRecord(i); if (fmmr != null) { if (fmmr.MinCoordOffset + m_offsetMinMaxTable > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.BASE_E_FeatMinMaxRecords_MinCO_offset, table.m_tag, sIdentity + ", FeatMinMaxRecord[" + i + "]"); bFeatMinMaxRecordsOk = false; bRet = false; } if (fmmr.MaxCoordOffset + m_offsetMinMaxTable > m_bufTable.GetLength()) { v.Error(T.T_NULL, E.BASE_E_FeatMinMaxRecords_MaxCO_offset, table.m_tag, sIdentity + ", FeatMinMaxRecord[" + i + "]"); bFeatMinMaxRecordsOk = false; bRet = false; } } else { bFeatMinMaxRecordsOk = false; } } if (bFeatMinMaxRecordsOk) { v.Pass(T.T_NULL, P.BASE_P_FeatMinMaxRecords_offsets, table.m_tag, sIdentity); } // check the BaseCoord Tables BaseCoordTable_val bct = null; bct = GetMinCoordTable_val(); if (bct != null) { bct.Validate(v, sIdentity, table); } bct = GetMaxCoordTable_val(); if (bct != null) { bct.Validate(v, sIdentity, table); } for (uint i = 0; i < FeatMinMaxCount; i++) { FeatMinMaxRecord fmmr = GetFeatMinMaxRecord(i); bct = GetFeatMinCoordTable_val(fmmr); if (bct != null) { bct.Validate(v, sIdentity, table); } bct = GetFeatMaxCoordTable_val(fmmr); if (bct != null) { bct.Validate(v, sIdentity, table); } } return(bRet); }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.gasp_Version)) { if (version == 0 || version == 1) { v.Pass(T.gasp_Version, P.gasp_P_Version, m_tag, "version = " + version.ToString()); } else { v.Error(T.gasp_Version, E.gasp_E_Version, m_tag, "version = " + version.ToString() + ", unable to continue validation"); return false; } } if (v.PerformTest(T.gasp_rangeGaspBehavior)) { bool bFlagsOk = true; string first_error = null; for (uint i=0; i<numRanges; i++) { GaspRange gr = GetGaspRange(i); if (gr != null) { if ( (version == 0 && gr.rangeGaspBehavior > 0x3) || (version == 1 && gr.rangeGaspBehavior > 0xf)) { bFlagsOk = false; first_error = "version=" + version + ", range #" + i + ", rangeGaspBehavior=0x" + gr.rangeGaspBehavior.ToString("X4"); break; } } } if (bFlagsOk) { v.Pass(T.gasp_rangeGaspBehavior, P.gasp_P_rangeGaspBehavior, m_tag); } else { v.Error(T.gasp_rangeGaspBehavior, E.gasp_E_rangeGaspBehavior, m_tag, first_error); bRet = false; } } if (v.PerformTest(T.gasp_SortOrder)) { bool bSortOk = true; if (numRanges > 1) { GaspRange grCurr = GetGaspRange(0); GaspRange grNext = null; for (uint i=1; i<numRanges; i++) { grNext = GetGaspRange(i); if (grCurr.rangeMaxPPEM >= grNext.rangeMaxPPEM) { bSortOk = false; break; } grCurr = grNext; } } if (bSortOk) { v.Pass(T.gasp_SortOrder, P.gasp_P_SortOrder, m_tag); } else { v.Error(T.gasp_SortOrder, E.gasp_E_SortOrder, m_tag); bRet = false; } } if (v.PerformTest(T.gasp_Sentinel)) { GaspRange gr = GetGaspRange((uint)numRanges-1); if (gr.rangeMaxPPEM == 0xFFFF) { v.Pass(T.gasp_Sentinel, P.gasp_P_Sentinel, m_tag); } else { v.Error(T.gasp_Sentinel, E.gasp_E_Sentinel, m_tag); bRet = false; } } if (v.PerformTest(T.gasp_AdjRangeIdenticalFlags)) { bool bNoAdjIdent = true; if (numRanges > 1) { for (uint i=0; i<numRanges-1; i++) { GaspRange grCurr = GetGaspRange(i); GaspRange grNext = GetGaspRange(i+1); if (grCurr.rangeGaspBehavior == grNext.rangeGaspBehavior) { string sDetails = "rangeGaspBehavior[" + i + "] = " + grCurr.rangeGaspBehavior + ", rangeGaspBehavior[" + (i+1) + "] = " + grNext.rangeGaspBehavior; v.Warning(T.gasp_AdjRangeIdenticalFlags, W.gasp_W_AdjRangeIdenticalFlags, m_tag, sDetails); bNoAdjIdent = false; } } } if (bNoAdjIdent) { v.Pass(T.gasp_AdjRangeIdenticalFlags, P.gasp_P_AdjRangeIdenticalFlags, m_tag); } } return bRet; }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.VDMX_Version)) { if (version == 0 || version == 1) { v.Pass(T.VDMX_Version, P.VDMX_P_Version, m_tag, version.ToString()); } else { v.Error(T.VDMX_Version, E.VDMX_E_Version, m_tag, version.ToString()); bRet = false; } } if (v.PerformTest(T.VDMX_Offsets)) { bool bOffsetsOk = true; ushort minPossibleOffset = (ushort)((ushort)FieldOffsets.ratRange + numRatios * 4 + numRatios*2); ushort maxPossibleOffset = (ushort)GetLength(); for (uint i=0; i<numRatios; i++) { ushort offset = GetVdmxGroupOffset(i); if (offset < minPossibleOffset || offset > maxPossibleOffset) { v.Error(T.VDMX_Offsets, E.VDMX_E_InvalidOffset, m_tag, "#" + i + " offset = " + offset); bOffsetsOk = false; bRet = false; } } if (bOffsetsOk) { v.Pass(T.VDMX_Offsets, P.VDMX_P_Offsets, m_tag); } } if (v.PerformTest(T.VDMX_GroupsInTable)) { bool bGroupsOk = true; for (uint i=0; i<numRatios; i++) { Vdmx vdmx = GetVdmxGroup(i); uint EndOffset = (uint)GetVdmxGroupOffset(i) + 4 + (uint)vdmx.recs*6; if (EndOffset > GetLength()) { v.Error(T.VDMX_GroupsInTable, E.VDMX_E_GroupsInTable, m_tag, "group# " + i); bGroupsOk = false; bRet = false; } } if (bGroupsOk) { v.Pass(T.VDMX_GroupsInTable, P.VDMX_P_GroupsInTable, m_tag); } } if (v.PerformTest(T.VDMX_CompareToCalcData)) { bool bDataOk = true; bool needtol = false; RasterInterf.DevMetricsData dmd = null; try { Version ver = fontOwner.GetFile().GetRasterizer().FTVersion; if ( ver.CompareTo(new Version(2,6,1)) < 0 ) v.Warning(T.VDMX_CompareToCalcData, W.VDMX_W_Need_Newer_FreeType, m_tag, "Using FreeType Version " + ver + " may not get correct results for VDMX"); dmd = fontOwner.GetCalculatedDevMetrics(); } catch (InvalidOperationException e) { // JJF Figure out what to do. Changed to warning v.Warning(T.VDMX_CompareToCalcData, W._TEST_W_ErrorInAnotherTable, m_tag, e.Message); } catch(Exception e) { v.ApplicationError(T.VDMX_CompareToCalcData, E._Table_E_Exception, m_tag, e.Message); bRet = false; } if (dmd != null) { for (uint iRatio=0; iRatio<numRatios; iRatio++) { Ratios ratio = GetRatioRange(iRatio); Vdmx group = GetVdmxGroup(iRatio); for (uint iEntry=0; iEntry<group.recs; iEntry++) { Vdmx.vTable vTableEntry = group.GetEntry(iEntry); if (vTableEntry.yPelHeight <= 255) { if (vTableEntry.yPelHeight == dmd.vdmxData.groups[iRatio].entry[vTableEntry.yPelHeight - group.startsz].yPelHeight) { if (vTableEntry.yMin != dmd.vdmxData.groups[iRatio].entry[iEntry].yMin || vTableEntry.yMax != dmd.vdmxData.groups[iRatio].entry[iEntry].yMax){ int dif = dmd.vdmxData.groups[iRatio].entry[iEntry].yMax - dmd.vdmxData.groups[iRatio].entry[iEntry].yMin; if (!TestTolerance(dmd.vdmxData.groups[iRatio].entry[iEntry].yMin, vTableEntry.yMin, dif) || !TestTolerance(dmd.vdmxData.groups[iRatio].entry[iEntry].yMax, vTableEntry.yMax, dif)) { String sDetails = "group[" + iRatio + "], entry[" + iEntry + "], yPelHeight = " + vTableEntry.yPelHeight + ", yMin,yMax = " + vTableEntry.yMin + "," + vTableEntry.yMax + ", calculated yMin,yMax = " + dmd.vdmxData.groups[iRatio].entry[iEntry].yMin + "," + dmd.vdmxData.groups[iRatio].entry[iEntry].yMax; v.Error(T.VDMX_CompareToCalcData, E.VDMX_E_CalcData, m_tag, sDetails); bDataOk = false; } else { needtol = true; } } /* else { String s = "group[" + iRatio + "], yPelHeight = " + vTableEntry.yPelHeight + ", entry OK"; v.DebugMsg(s, m_tag); } */ } else { Debug.Assert(false); } } else { String sDetails = "group[" + iRatio + "], entry[" + iEntry + "], yPelHeight = " + vTableEntry.yPelHeight; v.Error(T.VDMX_CompareToCalcData, E.VDMX_E_yPelHeight_illegal, m_tag, sDetails); bDataOk = false; } } } if (bDataOk) { if (needtol) { String sDetails = "The differences were smaller than the tolerance, so they may well be valid if the VDMX was hand-tuned"; v.Warning(T.VDMX_CompareToCalcData, W.VDMX_W_CalcData, m_tag, sDetails); } else { v.Pass(T.VDMX_CompareToCalcData, P.VDMX_P_CalcData, m_tag); } } else { //v.Error(T.VDMX_CompareToCalcData, E.VDMX_E_CalcData, m_tag); bRet = false; } } else { // Rasterization could not occur for various reasons. string s = "Unable to get calculated device metrics."; v.Error(T.VDMX_CompareToCalcData, E.VDMX_E_CalcData, m_tag, s); bDataOk = false; bRet = false; } } return bRet; }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; ushort numGlyphs = GetNumGlyphs(fontOwner); if (v.PerformTest(T.hdmx_Version)) { if (TableVersionNumber == 0) { v.Pass(T.hdmx_Version, P.hdmx_P_Version, m_tag); } else { v.Error(T.hdmx_Version, E.hdmx_E_Version, m_tag, TableVersionNumber.ToString()); bRet = false; } } bool bNumDeviceRecordsOk = true; if (v.PerformTest(T.hdmx_NumDeviceRecords)) { if (NumberDeviceRecords >= 0) { v.Pass(T.hdmx_NumDeviceRecords, P.hdmx_P_NumDeviceRecords, m_tag, NumberDeviceRecords.ToString()); } else { v.Error(T.hdmx_NumDeviceRecords, E.hdmx_E_NumDeviceRecords_neg, m_tag, NumberDeviceRecords.ToString()); bNumDeviceRecordsOk = false; bRet = false; } } bool bSizeOk = true; if (v.PerformTest(T.hdmx_SizeofDeviceRecord)) { if ((SizeofDeviceRecord & 3) != 0) { v.Error(T.hdmx_SizeofDeviceRecord, E.hdmx_E_SizeofDeviceRecord_alignment, m_tag, SizeofDeviceRecord.ToString()); bSizeOk = false; bRet = false; } uint CalculatedSizeofDeviceRecord = CalculateSizeofDeviceRecord(numGlyphs); if (SizeofDeviceRecord != CalculatedSizeofDeviceRecord) { string s = "actual = " + SizeofDeviceRecord + ", calc = " + CalculatedSizeofDeviceRecord; v.Error(T.hdmx_SizeofDeviceRecord, E.hdmx_E_SizeofDeviceRecord_numGlyphs, m_tag, s); bSizeOk = false; bRet = false; } if (bSizeOk) { v.Pass(T.hdmx_SizeofDeviceRecord, P.hdmx_P_SizeofDeviceRecord, m_tag, SizeofDeviceRecord.ToString()); } } bool bLengthOk = true; if (v.PerformTest(T.hdmx_TableLength)) { if (bNumDeviceRecordsOk) { uint CalculatedTableLength = 8 + (uint)NumberDeviceRecords * CalculateSizeofDeviceRecord(numGlyphs); if (GetLength() == CalculatedTableLength) { v.Pass(T.hdmx_TableLength, P.hdmx_P_TableLength, m_tag); } else { string s = "actual: " + GetLength() + ", calc: " + CalculatedTableLength; v.Error(T.hdmx_TableLength, E.hdmx_E_TableLength, m_tag, s); bLengthOk = false; bRet = false; } } else { v.Warning(T.hdmx_TableLength, W._TEST_W_OtherErrorsInTable, m_tag, "unable to validate table length"); } } if (v.PerformTest(T.hdmx_DeviceRecordPadBytesZero)) { if (bSizeOk && bLengthOk & bNumDeviceRecordsOk) { uint unpaddedLength = (uint)numGlyphs + 2; if ((unpaddedLength & 3) == 0) { v.Pass(T.hdmx_DeviceRecordPadBytesZero, P.hdmx_P_DeviceRecordPadBytes_none, m_tag); } else { bool bPadOk = true; if (NumberDeviceRecords > 1) { for (uint i=0; i<NumberDeviceRecords; i++) { DeviceRecord dr = GetDeviceRecord(i, numGlyphs); for (uint j=0; j<dr.GetNumPadBytes(); j++) { if (dr.GetPadByte(j) != 0) { bPadOk = false; break; } } } } if (bPadOk) { v.Pass(T.hdmx_DeviceRecordPadBytesZero, P.hdmx_P_DeviceRecordPadBytes_zero, m_tag); } else { v.Error(T.hdmx_DeviceRecordPadBytesZero, E.hdmx_E_DeviceRecordPadBytes_nonzero, m_tag); bRet = false; } } } else { v.Warning(T.hdmx_DeviceRecordPadBytesZero, W._TEST_W_OtherErrorsInTable, m_tag, "unable to validate that device record padding bytes are zero"); } } if (v.PerformTest(T.hdmx_SortedOrder)) { if (bSizeOk && bLengthOk && bNumDeviceRecordsOk) { bool bSortOk = true; if (NumberDeviceRecords > 1) { DeviceRecord drCurr = GetDeviceRecord(0, numGlyphs); DeviceRecord drNext = null; for (uint i=1; i<NumberDeviceRecords; i++) { drNext = GetDeviceRecord(i, numGlyphs); if (drCurr.PixelSize >= drNext.PixelSize) { bSortOk = false; break; } drCurr = drNext; } } if (bSortOk) { v.Pass(T.hdmx_SortedOrder, P.hdmx_P_SortedOrder, m_tag); } else { v.Error(T.hdmx_SortedOrder, E.hdmx_E_SortedOrder, m_tag); bRet = false; } } else { v.Warning(T.hdmx_SortedOrder, W._TEST_W_OtherErrorsInTable, m_tag, "unable to validate that device records are in sorted order"); } } if (v.PerformTest(T.hdmx_DuplicateDeviceRecords)) { if (bSizeOk && bLengthOk && bNumDeviceRecordsOk) { bool bNoDup = true; if (NumberDeviceRecords > 1) { for (uint i=0; i<NumberDeviceRecords-1; i++) { DeviceRecord dr1 = GetDeviceRecord(i, numGlyphs); for (uint j=i+1; j<NumberDeviceRecords; j++) { DeviceRecord dr2 = GetDeviceRecord(j, numGlyphs); if (dr1.PixelSize == dr2.PixelSize) { bNoDup = false; break; } } } } if (bNoDup) { v.Pass(T.hdmx_DuplicateDeviceRecords, P.hdmx_P_DuplicateDeviceRecords, m_tag); } else { v.Error(T.hdmx_DuplicateDeviceRecords, E.hdmx_E_DuplicateDeviceRecords, m_tag); bRet = false; } } else { v.Warning(T.hdmx_DuplicateDeviceRecords, W._TEST_W_OtherErrorsInTable, m_tag, "unable to validate that there are no duplicate device records"); } } if (v.PerformTest(T.hdmx_Widths)) { if (bSizeOk && bLengthOk && bNumDeviceRecordsOk) { bool bWidthsOk = true; RasterInterf.DevMetricsData dmd = null; try { Version ver = fontOwner.GetFile().GetRasterizer().FTVersion; if ( ver.CompareTo(new Version(2,6,1)) < 0 ) v.Warning(T.hdmx_Widths, W.hdmx_W_Need_Newer_FreeType, m_tag, "Using FreeType Version " + ver + " may not get correct results for HDMX"); dmd = fontOwner.GetCalculatedDevMetrics(); } catch (Exception e) { v.ApplicationError(T.hdmx_Widths, E._Table_E_Exception, m_tag, e.Message); bRet = false; } if (dmd != null) { for (uint i=0; i<NumberDeviceRecords; i++) { DeviceRecord dr = GetDeviceRecord(i, numGlyphs); for (uint iGlyph=0; iGlyph<numGlyphs; iGlyph++) { if (dr.GetWidth(iGlyph) != dmd.hdmxData.Records[i].Widths[iGlyph]) { String sDetails = "rec " + i + ", PixelSize " + dr.PixelSize + ", glyph# " + iGlyph + ", width = " + dr.GetWidth(iGlyph) + ", calc = " + dmd.hdmxData.Records[i].Widths[iGlyph]; v.Error(T.hdmx_Widths, E.hdmx_E_Widths, m_tag, sDetails); bWidthsOk = false; bRet = false; } } } if (bWidthsOk) { v.Pass(T.hdmx_Widths, P.hdmx_P_Widths, m_tag); } } else { // if user didn't cancel, then check for error message if (!v.CancelFlag) { String sDetails = null; try { sDetails = fontOwner.GetDevMetricsDataError(); } catch (Exception e) { v.ApplicationError(T.hdmx_Widths, E._Table_E_Exception, m_tag, e.Message); } Debug.Assert(sDetails != null); v.Error(T.hdmx_Widths, E.hdmx_E_Rasterizer, m_tag, sDetails); bRet = false; } } } else { v.Warning(T.hdmx_Widths, W._TEST_W_OtherErrorsInTable, m_tag, "unable to validate that the widths are correct"); } } return bRet; }