public bool Validate_Format2(Validator v, string sIdentity, Table_EBLC.indexSubTable ist) { bool bOk = true; Table_EBLC.indexSubTableArray ista = ist.GetIndexSubTableArray(); for (ushort idGlyph = ista.firstGlyphIndex; idGlyph <= ista.lastGlyphIndex; idGlyph++) { // validate small metrics smallGlyphMetrics sgm = null; try { sgm = GetSmallMetrics(ist, idGlyph, ista.firstGlyphIndex); } catch (Exception e) { v.ApplicationError(T.EBDT_GlyphImageData, E._Table_E_Exception, m_tag, "EBDT.Format2: " + e.Message); bOk = false; return(bOk); } if (sgm != null) { smallGlyphMetrics_val sgm_val = smallGlyphMetrics_val.CreateFromSmallGlyphMetrics(sgm); if (!sgm_val.Validate(v, sIdentity + ", idGlyph=" + idGlyph, this)) { bOk = false; } // validate image data // - this is just bitmap data, any values should be valid } } return(bOk); }
/************************ * 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() { 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); }
/***************** * protected methods */ /***************** * public methods */ //meant to avoid code repetition (is called from OTFontVal too) public bool ValidateTable(OTTable table, Validator v, DirectoryEntry de, OTFontVal fontOwner) { String tname = GetTableManager().GetUnaliasedTableName(de.tag); bool bRet = true; // verify the checksum value from the directory entry matches the checksum for the table if (!(tname == "DSIG" && IsCollection())) { uint calcChecksum = 0; if (table != null) { calcChecksum = table.CalcChecksum(); } if (de.checkSum != calcChecksum) { string s = "table '" + de.tag + "', calc: 0x" + calcChecksum.ToString("x8") + ", font: 0x" + de.checkSum.ToString("x8"); v.Error(T.T_NULL, E._DE_E_ChecksumError, de.tag, s); bRet = false; } } // verify that table has pad bytes set to zero if (table != null) { uint nBytes = 0; try { nBytes = GetNumPadBytesAfterTable(table); } catch (Exception e) { v.ApplicationError(T.T_NULL, E._Table_E_Exception, de.tag, "GetNumPadBytesAfterTable: " + e.Message); bRet = false; } bool bPadBytesZero = true; if (nBytes != 0) { long PadFilePos = table.GetBuffer().GetFilePos() + table.GetBuffer().GetLength(); byte[] padbuf = ReadBytes(PadFilePos, nBytes); for (int iByte = 0; iByte < padbuf.Length; iByte++) { if (padbuf[iByte] != 0) { bPadBytesZero = false; break; } } } if (bPadBytesZero == false) { v.Warning(T.T_NULL, W._DE_W_PadBytesNotZero, de.tag, "after " + de.tag + " table"); } } // ask the table object to validate its data if (!(tname == "DSIG" && IsCollection())) { v.OnTableValidationEvent(de, true); } if (table != null) { if (v.TestTable(de.tag)) // don't test deselected tables { try { ITableValidate valtable = (ITableValidate)table; bRet &= valtable.Validate(v, fontOwner); } catch (InvalidCastException e) { v.ApplicationError(T.T_NULL, E._Table_E_Exception, table.m_tag, e.ToString()); bRet = false; } } else { v.Info(I._Table_I_NotSelected, de.tag); } } else { if (de.length == 0) { // check if it's a known OT table type since zero length private tables seem allowable if (TableManager.IsKnownOTTableType(de.tag)) { v.Error(T.T_NULL, E._Table_E_Invalid, de.tag, "The directory entry length is zero"); bRet = false; } } else if (de.offset == 0) { v.Error(T.T_NULL, E._Table_E_Invalid, de.tag, "The directory entry offset is zero"); bRet = false; } else if (de.offset > GetFileLength()) { v.Error(T.T_NULL, E._Table_E_Invalid, de.tag, "The table offset points past end of file"); bRet = false; } else if (de.offset + de.length > GetFileLength()) { v.Error(T.T_NULL, E._Table_E_Invalid, de.tag, "The table extends past end of file"); bRet = false; } else { v.Error(E._Table_E_Invalid, de.tag); bRet = false; } } if (!(tname == "DSIG" && IsCollection())) { v.OnTableValidationEvent(de, 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; }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.DSIG_Formats)) { bool bFormatsOk = true; for (uint i = 0; i < usNumSigs; i++) { SigFormatOffset sfo; try { sfo = GetSigFormatOffset(i); if (sfo.ulFormat != 1) { v.Error(T.DSIG_Formats, E.DSIG_E_Formats, m_tag, "block " + i + ", format = " + sfo.ulFormat); bFormatsOk = false; bRet = false; } } catch (IndexOutOfRangeException e) { v.Error(T.DSIG_Formats, E.DSIG_E_Formats, m_tag, "block " + i + ", " + e); bFormatsOk = false; bRet = false; break; // No point continuing } } if (bFormatsOk) { v.Pass(T.DSIG_Formats, P.DSIG_P_Formats, m_tag); } } if (v.PerformTest(T.DSIG_Reserved)) { bool bReservedOk = true; for (uint i = 0; i < usNumSigs; i++) { SignatureBlock sb; try { sb = GetSignatureBlock(i); if (sb.usReserved1 != 0 || sb.usReserved2 != 0) { v.Error(T.DSIG_Reserved, E.DSIG_E_Reserved, m_tag, "block " + i); bReservedOk = false; bRet = false; } } catch (IndexOutOfRangeException) { v.Error(T.DSIG_Reserved, E.DSIG_E_Reserved, m_tag, "block " + i); bReservedOk = false; bRet = false; break; // No point continuing } } if (bReservedOk) { v.Pass(T.DSIG_Reserved, P.DSIG_P_Reserved, m_tag); } } if (v.PerformTest(T.DSIG_VerifySignature)) { OTFile file = fontOwner.GetFile(); System.IO.FileStream fs = file.GetFileStream(); String sFilename = fs.Name; try { WinVerifyTrustWrapper wvt = new WinVerifyTrustWrapper(); if (wvt.WinVerifyTrustFile(sFilename)) { if (wvt.usNumSigs > 0) { if (wvt.Warn_TTCv1 || wvt.Warn_DSIG_in_memFonts) { v.Warning(T.DSIG_VerifySignature, W.DSIG_W_VerifySignature_Generic, m_tag, (wvt.Warn_TTCv1 ? "TTC with v1 header;":"") + (wvt.Warn_DSIG_in_memFonts ? "DSIG tables detected in member fonts;":"")); } v.Pass(T.DSIG_VerifySignature, P.DSIG_P_VerifySignature, m_tag, wvt.Signer); } else { v.Pass(T.DSIG_VerifySignature, P.DSIG_P_VerifySignature, m_tag); } } else { v.Error(T.DSIG_VerifySignature, E.DSIG_E_VerifySignature, m_tag); bRet = false; } } catch (Exception e) { if (e is NotImplementedException) { v.ApplicationError(T.DSIG_VerifySignature, E.DSIG_A_UNUSUAL_TTC_TABLE_LAYOUT, m_tag, e.Message); } else { v.Error(T.DSIG_VerifySignature, E.DSIG_E_VerifySignature, m_tag, e.Message); } bRet = false; } } return(bRet); }
private bool CheckCodePageBit(int nBit, uint CodePage, string sName, Validator v, OTFont fontOwner) { bool bRet = true; int nTotalChars = 0; int nMissingChars = 0; // decode the bit number bool bBitSet; if (nBit < 32) { bBitSet = ((ulCodePageRange1 & (1<<nBit)) != 0); } else { bBitSet = ((ulCodePageRange2 & (1<<(nBit-32))) != 0); } if (nBit == 31) { // symbol character set Table_cmap cmapTable = (Table_cmap)fontOwner.GetTable("cmap"); if (cmapTable != null) { if (cmapTable.GetEncodingTableEntry(3,0) != null) { if (!bBitSet) { v.Error(T.T_NULL, E.OS_2_E_SymbolBitClear, m_tag); bRet = false; } } else { if (bBitSet) { int nPresentChars = 0; for (ushort c=0xf000; c<= 0xf0ff; c++) { if (fontOwner.FastMapUnicodeToGlyphID((char)c) != 0) { nPresentChars++; } } if (nPresentChars == 0) { v.Error(T.T_NULL, E.OS_2_E_SymbolBitSet, m_tag); bRet = false; } } } } else { v.Error(T.T_NULL, E._TEST_E_TableMissing, m_tag, "cmap"); bRet = false; } } else if (CodePage == 0) { // reserved field, bit should not be set if (bBitSet) { v.Error(T.T_NULL, E.OS_2_E_ReservedBitSet_CodePage, m_tag, "bit #" + nBit); bRet = false; } } else { try { if (MultiByte.IsCodePageInstalled(CodePage)) { ushort [] arrMissingChars = new ushort[10]; uint nMaxCharSize = MultiByte.GetCodePageMaxCharSize(CodePage); if (nMaxCharSize == 1) { for (ushort c = 0; c<256; c++) { // check for special case: MultiByteToWideChar maps char 0xca in CP1255 to U05BA, but CP1255 spec says its not defined if (CodePage != 1255 || c != 0xca) { CheckCodePageGlyph(CodePage, (char)c, ref nTotalChars, ref nMissingChars, arrMissingChars, fontOwner); } } } else if (nMaxCharSize == 2) { bool [] LeadByteMap = new bool[256]; for (int i=0; i<256; i++) { LeadByteMap[i] = MultiByte.IsCodePageLeadByte(CodePage, (byte)i); } for (ushort c = 0; c<256; c++) { if (LeadByteMap[c] == false) { CheckCodePageGlyph(CodePage, (char)c, ref nTotalChars, ref nMissingChars, arrMissingChars, fontOwner); } } for (uint leadbyte = 0; leadbyte<256; leadbyte++) { if (LeadByteMap[leadbyte] == true) { for (uint secondbyte = 0; secondbyte<256; secondbyte++) { char c = (char)((leadbyte << 8) + secondbyte); CheckCodePageGlyph(CodePage, c, ref nTotalChars, ref nMissingChars, arrMissingChars, fontOwner); } } } } else { Debug.Assert(false); } if (bBitSet) { if (nMissingChars != 0) { string sDetails = "bit #" + nBit + ", " + sName; int n = 0; if (nMissingChars <=10) { sDetails += " (missing chars:"; n = nMissingChars; } else { sDetails += " (" + nMissingChars + " missing, first ten missing chars are:"; n = 10; } for (int i=0; i<n; i++) { sDetails += " U" + arrMissingChars[i].ToString("X4"); } sDetails += ")"; v.Warning(T.T_NULL, W.OS_2_W_CodePageRangeBitSet, m_tag, sDetails); } } else { if (nMissingChars == 0) { v.Warning(T.T_NULL, W.OS_2_W_CodePageRangeBitClear, m_tag, "bit #" + nBit + ", " + sName); } } } else { v.ApplicationError(T.T_NULL, E.OS_2_A_CodePageNotInstalled, m_tag, "CodePage " + CodePage + " is not installed on the system"); } } catch (Exception e) { v.ApplicationError(T.T_NULL, E.OS_2_A_CodePageNotInstalled, m_tag, "CodePage " + CodePage + " throws an exception:" + e.Message); } } return bRet; }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.kern_TableVersion)) { if (version == 0) { v.Pass(T.kern_TableVersion, P.kern_P_TableVersion, m_tag); } else { v.Error(T.kern_TableVersion, E.kern_E_TableVersion, m_tag, "version = " + version.ToString() + ", unrecognized version #, no further tests can be performed"); return(false); } } if (v.PerformTest(T.kern_NumSubtables)) { if (nTables != 0) { v.Pass(T.kern_NumSubtables, P.kern_P_NumSubTables, m_tag, nTables.ToString()); } else { v.Error(T.kern_NumSubtables, E.kern_E_NumSubTables, m_tag); bRet = false; } } if (v.PerformTest(T.kern_SubtableFormats)) { bool bFormatsOk = true; for (uint i = 0; i < nTables; i++) { SubTableHeader sth = GetSubTableHeader(i); if (sth != null) { if (sth.GetFormat() != 0 && sth.GetFormat() != 2) { v.Error(T.kern_SubtableFormats, E.kern_E_SubtableFormats, m_tag, "subtable #" + i + ", format " + sth.GetFormat()); bFormatsOk = false; bRet = false; } } else { v.Error(T.kern_SubtableFormats, E.kern_E_SubTableExtendsPastEOT, m_tag, "subtable #" + i); bFormatsOk = false; bRet = false; break; } } if (bFormatsOk) { v.Pass(T.kern_SubtableFormats, P.kern_P_SubtableFormats, m_tag); } } if (!bRet) { v.Warning(T.kern_SubtableFormats, W._TEST_W_OtherErrorsInTable, m_tag, "kern table appears to be corrupt. No further tests will be performed."); return(bRet); } if (v.PerformTest(T.kern_SubtableLength)) { bool bLengthsOk = true; for (uint i = 0; i < nTables; i++) { SubTable st = this.GetSubTable(i); if (st.length != st.CalculatedLength()) { v.Error(T.kern_SubtableLength, E.kern_E_SubtableLength, m_tag, "subtable #" + i + ", length = " + st.length + ", calculated length = " + st.CalculatedLength()); bLengthsOk = false; bRet = false; } } if (bLengthsOk) { v.Pass(T.kern_SubtableLength, P.kern_P_SubtableLengths, m_tag); } } if (v.PerformTest(T.kern_CoverageReservedBits)) { bool bReservedOk = true; for (uint i = 0; i < nTables; i++) { SubTable st = this.GetSubTable(i); if ((st.coverage & 0xf0) != 0) { bReservedOk = false; v.Error(T.kern_CoverageReservedBits, E.kern_E_ReservedCoverageBits, m_tag, "subtable #" + i); bRet = false; break; } } if (bReservedOk) { v.Pass(T.kern_CoverageReservedBits, P.kern_P_ReservedCoverageBits, m_tag); } } if (v.PerformTest(T.kern_Format0_SearchFields)) { bool bBinaryFieldsOk = true; for (uint i = 0; i < nTables; i++) { SubTable st = this.GetSubTable(i); if (st.version == 0) { SubTableFormat0 stf0 = (SubTableFormat0)st; ushort nPairs = stf0.nPairs; ushort sizeofEntry = 6; if (nPairs != 0) { ushort CalculatedSearchRange = (ushort)(util.MaxPower2LE(nPairs) * sizeofEntry); ushort CalculatedEntrySelector = util.Log2(util.MaxPower2LE(nPairs)); ushort CalculatedRangeShift = (ushort)((nPairs - util.MaxPower2LE(nPairs)) * sizeofEntry); if (stf0.searchRange != CalculatedSearchRange) { string s = "subtable #" + i + ", calc = " + CalculatedSearchRange + ", actual = " + stf0.searchRange; v.Error(T.kern_Format0_SearchFields, E.kern_E_Format0_searchRange, m_tag, s); bBinaryFieldsOk = false; bRet = false; } if (stf0.entrySelector != CalculatedEntrySelector) { string s = "subtable #" + i + ", calc = " + CalculatedEntrySelector + ", actual = " + stf0.entrySelector; v.Error(T.kern_Format0_SearchFields, E.kern_E_Format0_entrySelector, m_tag, s); bBinaryFieldsOk = false; bRet = false; } if (stf0.rangeShift != CalculatedRangeShift) { string s = "subtable #" + i + ", calc = " + CalculatedRangeShift + ", actual = " + stf0.rangeShift; v.Error(T.kern_Format0_SearchFields, E.kern_E_Format0_rangeShift, m_tag, s); bBinaryFieldsOk = false; bRet = false; } } else { // cannot validate fields since they are undefined when nPairs is zero v.Warning(T.kern_Format0_SearchFields, W.kern_W_Format0_SearchFields, m_tag, "subtable #" + i + ", nPairs = " + stf0.nPairs); bBinaryFieldsOk = false; } } } if (bBinaryFieldsOk) { v.Pass(T.kern_Format0_SearchFields, P.kern_P_Format0_SearchFields, m_tag); } } if (v.PerformTest(T.kern_Format0_GlyphIDs)) { for (uint i = 0; i < nTables; i++) { SubTable st = this.GetSubTable(i); if (st.version == 0) { bool bGlyphIDsOk = true; SubTableFormat0 stf0 = (SubTableFormat0)st; for (int iPair = 0; iPair < stf0.nPairs; iPair++) { ushort left = 0, right = 0; short kernvalue = 0; stf0.GetKerningPairAndValue(iPair, ref left, ref right, ref kernvalue); ushort numGlyphs = fontOwner.GetMaxpNumGlyphs(); if (left >= numGlyphs) { v.Error(T.kern_Format0_GlyphIDs, E.kern_E_Format0_GlyphIDs, m_tag, "kern pair[" + iPair + "]: left = " + left); bGlyphIDsOk = false; bRet = false; } if (right >= numGlyphs) { v.Error(T.kern_Format0_GlyphIDs, E.kern_E_Format0_GlyphIDs, m_tag, "kern pair[" + iPair + "]: right = " + right); bGlyphIDsOk = false; bRet = false; } } if (bGlyphIDsOk) { v.Pass(T.kern_Format0_GlyphIDs, P.kern_P_Format0_GlyphIDs, m_tag); } } } } if (v.PerformTest(T.kern_Format0_Values)) { for (uint i = 0; i < nTables; i++) { SubTable st = this.GetSubTable(i); if (st.version == 0) { SubTableFormat0 stf0 = (SubTableFormat0)st; Table_hmtx hmtxTable = (Table_hmtx)fontOwner.GetTable("hmtx"); if (hmtxTable != null) { bool bValuesOk = true; for (int iPair = 0; iPair < stf0.nPairs; iPair++) { ushort left = 0, right = 0; short kernvalue = 0; stf0.GetKerningPairAndValue(iPair, ref left, ref right, ref kernvalue); short absKernValue = Math.Abs(kernvalue); Table_hmtx.longHorMetric lhmLeft = null; Table_hmtx.longHorMetric lhmRight = null; try { lhmLeft = hmtxTable.GetOrMakeHMetric(left, fontOwner); lhmRight = hmtxTable.GetOrMakeHMetric(right, fontOwner); } catch (Exception e) { v.ApplicationError(T.kern_Format0_Values, E._Table_E_Exception, m_tag, "GetOrMakeHMetric:" + e.Message); bValuesOk = false; bRet = false; break; } if (lhmLeft == null || lhmRight == null) { v.ApplicationError(T.kern_Format0_Values, E._Table_E_Exception, m_tag, "hmtx Left or Right null"); bValuesOk = false; bRet = false; break; } if (absKernValue > lhmLeft.advanceWidth && absKernValue > lhmRight.advanceWidth) { v.Error(T.kern_Format0_Values, E.kern_E_Format0_Values, m_tag, "kern pair[" + iPair + "]: left id = " + left + ", right id = " + right + ", value = " + kernvalue); bValuesOk = false; bRet = false; } } if (bValuesOk) { v.Pass(T.kern_Format0_Values, P.kern_P_Format0_Values, m_tag); } } } } } if (v.PerformTest("kern_Format0_IDsInCmap")) { for (uint i = 0; i < nTables; i++) { SubTable st = this.GetSubTable(i); if (st.version == 0) { SubTableFormat0 stf0 = (SubTableFormat0)st; Table_cmap cmapTable = (Table_cmap)fontOwner.GetTable("cmap"); if (cmapTable != null) { Table_cmap.Subtable cmapSubtable = cmapTable.GetSubtable(3, 10); if (cmapSubtable == null) { cmapSubtable = cmapTable.GetSubtable(3, 1); } if (cmapSubtable == null) { Table_cmap.EncodingTableEntry ete = cmapTable.GetEncodingTableEntry(0); cmapSubtable = cmapTable.GetSubtable(ete); } if (cmapSubtable != null) { uint [] map = cmapSubtable.GetMap(); bool bAllIDsInCmap = true; for (int iPair = 0; iPair < stf0.nPairs; iPair++) { ushort left = 0, right = 0; short kernvalue = 0; stf0.GetKerningPairAndValue(iPair, ref left, ref right, ref kernvalue); bool bFoundLeft = false; bool bFoundRight = false; for (int j = 0; j < map.Length; j++) { if (left == map[j]) { bFoundLeft = true; break; } } for (int j = 0; j < map.Length; j++) { if (right == map[j]) { bFoundRight = true; break; } } if (bFoundLeft == false) { v.Error(T.kern_Format0_IDsInCmap, E.kern_E_Format0_GlyphIdInCmap, m_tag, "kern pair[" + iPair + "]: left id = " + left); bAllIDsInCmap = false; bRet = false; } if (bFoundRight == false) { v.Error(T.kern_Format0_IDsInCmap, E.kern_E_Format0_GlyphIdInCmap, m_tag, "kern pair[" + iPair + "]: right id = " + right); bAllIDsInCmap = false; bRet = false; } } if (bAllIDsInCmap) { v.Pass(T.kern_Format0_IDsInCmap, P.kern_P_Format0_GlyphIdInCmap, 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 { dmd = fontOwner.GetCalculatedDevMetrics(); } catch (Exception e) { v.ApplicationError(T.VDMX_CompareToCalcData, 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.VDMX_CompareToCalcData, 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); }
/***************** * protected methods */ /***************** * public methods */ //meant to avoid code repetition (is called from OTFontVal too) public bool ValidateTable(OTTable table, Validator v, DirectoryEntry de, OTFontVal fontOwner) { String tname = GetTableManager().GetUnaliasedTableName(de.tag); bool bRet = true; // verify the checksum value from the directory entry matches the checksum for the table if (!(tname == "DSIG" && IsCollection())) { uint calcChecksum = 0; if (table != null) { calcChecksum = table.CalcChecksum(); } if (de.checkSum != calcChecksum) { string s = "table '" + de.tag + "', calc: 0x" + calcChecksum.ToString("x8") + ", font: 0x" + de.checkSum.ToString("x8"); v.Error(T.T_NULL, E._DE_E_ChecksumError, de.tag, s); bRet = false; } } // verify that table has pad bytes set to zero if (table != null) { uint nBytes = GetNumPadBytesAfterTable(table); bool bPadBytesZero = true; if (nBytes != 0) { long PadFilePos = table.GetBuffer().GetFilePos() + table.GetBuffer().GetLength(); byte[] padbuf = ReadBytes(PadFilePos, nBytes); for (int iByte = 0; iByte < padbuf.Length; iByte++) { if (padbuf[iByte] != 0) { bPadBytesZero = false; break; } } } if (bPadBytesZero == false) { v.Warning(T.T_NULL, W._DE_W_PadBytesNotZero, de.tag, "after " + de.tag + " table"); } } // ask the table object to validate its data if (!(tname == "DSIG" && IsCollection())) v.OnTableValidationEvent(de, true); if (table != null) { if (v.TestTable(de.tag)) // don't test deselected tables { try { ITableValidate valtable = (ITableValidate)table; bRet &= valtable.Validate(v, fontOwner); } catch (InvalidCastException e) { v.ApplicationError(T.T_NULL, E._Table_E_Exception, table.m_tag, e.ToString()); bRet = false; } } else { v.Info(I._Table_I_NotSelected, de.tag); } } else { if (de.length == 0) { // check if it's a known OT table type since zero length private tables seem allowable if (TableManager.IsKnownOTTableType(de.tag)) { v.Error(T.T_NULL, E._Table_E_Invalid, de.tag, "The directory entry length is zero"); bRet = false; } } else if (de.offset == 0) { v.Error(T.T_NULL, E._Table_E_Invalid, de.tag, "The directory entry offset is zero"); bRet = false; } else if (de.offset > GetFileLength()) { v.Error(T.T_NULL, E._Table_E_Invalid, de.tag, "The table offset points past end of file"); bRet = false; } else if (de.offset + de.length > GetFileLength()) { v.Error(T.T_NULL, E._Table_E_Invalid, de.tag, "The table extends past end of file"); bRet = false; } else { v.Error(E._Table_E_Invalid, de.tag); bRet = false; } } if (!(tname == "DSIG" && IsCollection())) v.OnTableValidationEvent(de, false); return bRet; }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.LTSH_version)) { if (version == 0) { v.Pass(T.LTSH_version, P.LTSH_P_version, m_tag); } else { v.Error(T.LTSH_version, E.LTSH_E_version, m_tag, version.ToString()); bRet = false; } } 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.LTSH_numGlyphs)) { if (numGlyphs == fontOwner.GetMaxpNumGlyphs()) { v.Pass(T.LTSH_numGlyphs, P.LTSH_P_numGlyphs, m_tag); } else { string s = "LTSH.numGlyphs = " + numGlyphs + ", maxp.numGlyphs = " + fontOwner.GetMaxpNumGlyphs(); v.Error(T.LTSH_numGlyphs, E.LTSH_E_numGlyphs, m_tag, s); bRet = false; } } if (v.PerformTest(T.LTSH_TableLength)) { uint CalcLength = (uint)FieldOffsets.yPels + numGlyphs; if (GetLength() == CalcLength) { v.Pass(T.LTSH_TableLength, P.LTSH_P_TableLength, m_tag); } else { string s = "calc length = " + CalcLength + ", actual length = " + GetLength(); v.Error(T.LTSH_TableLength, E.LTSH_E_TableLength, m_tag, s); bRet = false; } } if (v.PerformTest(T.LTSH_yPels)) { bool bYPelsOk = true; RasterInterf.DevMetricsData dmd = null; try { Version ver = fontOwner.GetFile().GetRasterizer().FTVersion; if (ver.CompareTo(new Version(2, 6, 1)) < 0) { v.Warning(T.LTSH_yPels, W.LTSH_W_Need_Newer_FreeType, m_tag, "Using FreeType Version " + ver + " may not get correct results for LTSH"); } dmd = fontOwner.GetCalculatedDevMetrics(); } catch (Exception e) { v.ApplicationError(T.LTSH_yPels, E._Table_E_Exception, m_tag, e.Message); bRet = false; } if (dmd != null) { for (uint iGlyphIndex = 0; iGlyphIndex < numGlyphs; iGlyphIndex++) { if (iGlyphIndex >= fontOwner.GetMaxpNumGlyphs()) { // JJF. Figure out what to do v.Warning(T.LTSH_yPels, W._TEST_W_OtherErrorsInTable, m_tag, "can't test all yPel values, LTSH.numGlyphs does not equal maxp.numGlyphs"); bRet = false; bYPelsOk = false; break; } if (GetYPel(iGlyphIndex) != dmd.ltshData.yPels[iGlyphIndex]) { String sDetails = "glyph# = " + iGlyphIndex + ", value = " + GetYPel(iGlyphIndex) + ", calculated value = " + dmd.ltshData.yPels[iGlyphIndex]; v.Error(T.LTSH_yPels, E.LTSH_E_yPels, m_tag, sDetails); bRet = false; bYPelsOk = false; } /* * else * { * String sDetails = "glyph# = " + iGlyphIndex + ", value = " + GetYPel(iGlyphIndex); * v.DebugMsg("yPel value OK! " + sDetails, m_tag); * } */ if (GetYPel(iGlyphIndex) == 0) { String sDetails = "glyph# = " + iGlyphIndex; v.Warning(T.LTSH_yPels, W.LTSH_W_yPels_zero, m_tag, sDetails); } } if (bYPelsOk) { v.Pass(T.LTSH_yPels, P.LTSH_P_yPels, 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.LTSH_yPels, E._Table_E_Exception, m_tag, e.Message); } Debug.Assert(sDetails != null); v.Error(T.LTSH_yPels, E.LTSH_E_Rasterizer, m_tag, sDetails); bRet = false; } } } return(bRet); }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.LTSH_version)) { if (version == 0) { v.Pass(T.LTSH_version, P.LTSH_P_version, m_tag); } else { v.Error(T.LTSH_version, E.LTSH_E_version, m_tag, version.ToString()); bRet = false; } } 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.LTSH_numGlyphs)) { if (numGlyphs == fontOwner.GetMaxpNumGlyphs()) { v.Pass(T.LTSH_numGlyphs, P.LTSH_P_numGlyphs, m_tag); } else { string s = "LTSH.numGlyphs = " + numGlyphs + ", maxp.numGlyphs = " + fontOwner.GetMaxpNumGlyphs(); v.Error(T.LTSH_numGlyphs, E.LTSH_E_numGlyphs, m_tag, s); bRet = false; } } if (v.PerformTest(T.LTSH_TableLength)) { uint CalcLength = (uint)FieldOffsets.yPels + numGlyphs; if (GetLength() == CalcLength) { v.Pass(T.LTSH_TableLength, P.LTSH_P_TableLength, m_tag); } else { string s = "calc length = " + CalcLength + ", actual length = " + GetLength(); v.Error(T.LTSH_TableLength, E.LTSH_E_TableLength, m_tag, s); bRet = false; } } if (v.PerformTest(T.LTSH_yPels)) { bool bYPelsOk = true; RasterInterf.DevMetricsData dmd = null; try { Version ver = fontOwner.GetFile().GetRasterizer().FTVersion; if ( ver.CompareTo(new Version(2,6,1)) < 0 ) v.Warning(T.LTSH_yPels, W.LTSH_W_Need_Newer_FreeType, m_tag, "Using FreeType Version " + ver + " may not get correct results for LTSH"); dmd = fontOwner.GetCalculatedDevMetrics(); } catch (Exception e) { v.ApplicationError(T.LTSH_yPels, E._Table_E_Exception, m_tag, e.Message); bRet = false; } if (dmd != null) { for( uint iGlyphIndex = 0; iGlyphIndex < numGlyphs; iGlyphIndex++ ) { if (iGlyphIndex >= fontOwner.GetMaxpNumGlyphs()) { // JJF. Figure out what to do v.Warning(T.LTSH_yPels, W._TEST_W_OtherErrorsInTable, m_tag, "can't test all yPel values, LTSH.numGlyphs does not equal maxp.numGlyphs"); bRet = false; bYPelsOk = false; break; } if( GetYPel(iGlyphIndex) != dmd.ltshData.yPels[iGlyphIndex] ) { String sDetails = "glyph# = " + iGlyphIndex + ", value = " + GetYPel(iGlyphIndex) + ", calculated value = " + dmd.ltshData.yPels[iGlyphIndex]; v.Error(T.LTSH_yPels, E.LTSH_E_yPels, m_tag, sDetails); bRet = false; bYPelsOk = false; } /* else { String sDetails = "glyph# = " + iGlyphIndex + ", value = " + GetYPel(iGlyphIndex); v.DebugMsg("yPel value OK! " + sDetails, m_tag); } */ if (GetYPel(iGlyphIndex) == 0) { String sDetails = "glyph# = " + iGlyphIndex; v.Warning(T.LTSH_yPels, W.LTSH_W_yPels_zero, m_tag, sDetails); } } if (bYPelsOk) { v.Pass(T.LTSH_yPels, P.LTSH_P_yPels, 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.LTSH_yPels, E._Table_E_Exception, m_tag, e.Message); } Debug.Assert(sDetails != null); v.Error(T.LTSH_yPels, E.LTSH_E_Rasterizer, m_tag, sDetails); bRet = false; } } } return bRet; }