public uint FastMapUnicode32ToGlyphID(uint c) { // this routine caches the windows 3,10 cmap for better performance // but might use tons of heap uint glyphID = 0xffffffff; if (m_arrUnicodeToGlyph_3_10 == null) { Table_cmap cmapTable = (Table_cmap)GetTable("cmap"); if (cmapTable != null) { Table_cmap.Format12 subtable = (Table_cmap.Format12)cmapTable.GetSubtable(3, 10); // Apple Color Emoji does not have a 3.10 charmap if (subtable == null) { return(glyphID); } Table_cmap.Format12.Group g = subtable.GetGroup(subtable.nGroups - 1); uint nArraySize = g.endCharCode + 1; m_arrUnicodeToGlyph_3_10 = new uint[nArraySize]; for (uint i = 0; i < nArraySize; i++) { m_arrUnicodeToGlyph_3_10[i] = 0; } for (uint nGroup = 0; nGroup < subtable.nGroups; nGroup++) { g = subtable.GetGroup(nGroup); for (uint i = 0; i <= g.endCharCode - g.startCharCode; i++) { m_arrUnicodeToGlyph_3_10[g.startCharCode + i] = g.startGlyphID + i; } } } } Debug.Assert(m_arrUnicodeToGlyph_3_10 != null); if (m_arrUnicodeToGlyph_3_10 != null) { if (c >= m_arrUnicodeToGlyph_3_10.Length) { return(0); } glyphID = m_arrUnicodeToGlyph_3_10[c]; } return(glyphID); }
public uint FastMapUnicodeToGlyphID(char c) { // this routine caches the windows unicode cmap for better performance // but uses 256K of heap uint glyphID = 0xffffffff; if (m_arrUnicodeToGlyph_3_1 == null) { m_arrUnicodeToGlyph_3_1 = new uint[0x00010000]; for (uint i = 0; i <= 0xffff; i++) { m_arrUnicodeToGlyph_3_1[i] = 0; } Table_cmap cmapTable = (Table_cmap)GetTable("cmap"); if (cmapTable != null) { Table_cmap.EncodingTableEntry eteUni = cmapTable.GetEncodingTableEntry(3, 1); if (eteUni != null) { Table_cmap.Subtable st = cmapTable.GetSubtable(eteUni); if (st != null) { byte [] buf = new byte[2]; for (ushort i = 0; i < 0xffff; i++) { buf[0] = (byte)i; buf[1] = (byte)(i >> 8); uint g = st.MapCharToGlyph(buf, 0); if (g != 0) { // BEWARE: Some bad fonts have the glyph ID greater than # of glyphs // and we're not throwing it out here! m_arrUnicodeToGlyph_3_1[i] = g; } } } } } } Debug.Assert(m_arrUnicodeToGlyph_3_1 != null); if (m_arrUnicodeToGlyph_3_1 != null) { glyphID = m_arrUnicodeToGlyph_3_1[c]; } return(glyphID); }
// TODO: rewrite public void ReadFontMetrics(out int descendMin, out int ascendMax, out int lsbMin, out int rsbMax, DIAction dia) { descendMin = -700; ascendMax = 2100; lsbMin = -1000; rsbMax = 3500; try { BoxD bboxRes = new BoxD(); Table_cmap tableCmap = (Table_cmap)this.m_font.GetTable("cmap"); if (tableCmap == null) { return; } Table_cmap.EncodingTableEntry eteUni = tableCmap.GetEncodingTableEntry(3, 1); if (eteUni == null) { return; } Table_cmap.Subtable subtableCmap = tableCmap.GetSubtable(eteUni); char[] samples = { 'A', 'W', 'p' }; for (int iSample = 0; iSample < samples.Length; iSample++) { byte[] charbuf = new byte[2]; charbuf[0] = (byte)'A'; charbuf[1] = 0; int indGlyph = (int)subtableCmap.MapCharToGlyph(charbuf, 0); Table_glyf.header header = this.m_tableGlyf.GetGlyphHeader((uint)indGlyph, this.m_font); if (header == null) { return; } BoxD bboxCur = new BoxD(header.xMin, header.yMin, header.xMax, header.yMax); bboxRes.Unite(bboxCur); } descendMin = (int)bboxRes.VecMin.Y; ascendMax = (int)bboxRes.VecMax.Y; lsbMin = (int)bboxRes.VecMin.X; rsbMax = (int)bboxRes.VecMax.X; } catch { } }
public bool HaveNonBMPChars() { Table_cmap cmapTable = (Table_cmap)GetTable("cmap"); if (cmapTable != null) { Table_cmap.Format12 subtable = (Table_cmap.Format12)cmapTable.GetSubtable(3, 10); if (subtable != null) { return(true); } } return(false); }
public bool ContainsMsSymbolEncodedCmap() { if (!bCheckedForSymbolCmap) { Table_cmap cmapTable = (Table_cmap)GetTable("cmap"); if (cmapTable != null) { Table_cmap.EncodingTableEntry eteUni = cmapTable.GetEncodingTableEntry(3, 0); if (eteUni != null) { m_bContainsMsSymbolEncodedCmap = true; } } bCheckedForSymbolCmap = true; } return(m_bContainsMsSymbolEncodedCmap); }
/************************ * public methods */ public bool Validate(Validator v, OTFontVal fontOwner) { bool bRet = true; if (v.PerformTest(T.name_FormatSelector)) { if (FormatSelector == 0) { v.Pass(T.name_FormatSelector, P.name_P_FormatSelector, m_tag); } else { v.Error(T.name_FormatSelector, E.name_E_FormatSelector, m_tag, FormatSelector.ToString()); bRet = false; } } if (v.PerformTest(T.name_StringsWithinTable)) { bool bStringsWithinTable = true; uint tableLength = GetLength(); for (uint i = 0; i < NumberNameRecords; i++) { NameRecord nr = GetNameRecord(i); if (nr != null) { if (nr.StringOffset + nr.StringLength > tableLength) { v.Error(T.name_StringsWithinTable, E.name_E_StringsWithinTable, m_tag, "string# " + i); bStringsWithinTable = false; bRet = false; } } else { v.Warning(T.name_StringsWithinTable, W._TEST_W_OtherErrorsInTable, m_tag); bStringsWithinTable = false; break; } } if (bStringsWithinTable) { v.Pass(T.name_StringsWithinTable, P.name_P_StringsWithinTable, m_tag); } } if (v.PerformTest(T.name_NameRecordsSorted)) { bool bSortedOrder = true; if (NumberNameRecords > 1) { NameRecord CurrNR = GetNameRecord(0); NameRecord NextNR = null; for (uint i = 0; i < NumberNameRecords - 1; i++) { NextNR = GetNameRecord(i + 1); if (CurrNR == null || NextNR == null) { bSortedOrder = false; break; } if (CurrNR.PlatformID > NextNR.PlatformID) { bSortedOrder = false; break; } else if (CurrNR.PlatformID == NextNR.PlatformID) { if (CurrNR.EncodingID > NextNR.EncodingID) { bSortedOrder = false; break; } else if (CurrNR.EncodingID == NextNR.EncodingID) { if (CurrNR.LanguageID > NextNR.LanguageID) { bSortedOrder = false; break; } else if (CurrNR.LanguageID == NextNR.LanguageID) { if (CurrNR.NameID > NextNR.NameID) { bSortedOrder = false; break; } } } } CurrNR = NextNR; } } if (bSortedOrder) { v.Pass(T.name_NameRecordsSorted, P.name_P_NameRecordsSorted, m_tag); } else { v.Error(T.name_NameRecordsSorted, E.name_E_NameRecordsSorted, m_tag); bRet = false; } } if (v.PerformTest(T.name_ReservedNameIDs)) { bool bReservedOk = true; for (uint i = 0; i < NumberNameRecords; i++) { NameRecord nr = GetNameRecord(i); if (nr != null) { if (nr.NameID >= 26 && nr.NameID <= 255) { string s = "platID = " + nr.PlatformID + ", encID = " + nr.EncodingID + ", langID = " + nr.LanguageID + ", nameID = " + nr.NameID; v.Error(T.name_ReservedNameIDs, E.name_E_ReservedNameID, m_tag, s); bReservedOk = false; break; } } else { v.Warning(T.name_ReservedNameIDs, W._TEST_W_OtherErrorsInTable, m_tag); bReservedOk = false; break; } } if (bReservedOk) { v.Pass(T.name_ReservedNameIDs, P.name_P_ReservedNameID, m_tag); } } if (v.PerformTest(T.name_BothPlatforms)) { bool bMac = false; bool bMS = false; for (uint i = 0; i < NumberNameRecords; i++) { NameRecord nr = GetNameRecord(i); if (nr != null) { if (nr.PlatformID == 1) { bMac = true; } else if (nr.PlatformID == 3) { bMS = true; } } } if (bMac && bMS) { v.Pass(T.name_BothPlatforms, P.name_P_BothPlatforms, m_tag); } else if (!bMac) { v.Error(T.name_BothPlatforms, E.name_E_NoMacPlatform, m_tag); bRet = false; } else if (!bMS) { v.Error(T.name_BothPlatforms, E.name_E_NoMSPlatform, m_tag); bRet = false; } } if (v.PerformTest(T.name_VersionString)) { bool bFound = false; string sVersion = ""; for (uint i = 0; i < NumberNameRecords; i++) { NameRecord nr = GetNameRecord(i); if (nr != null) { if (nr.PlatformID == 3 && // ms (nr.EncodingID == 1 /* unicode */ || nr.EncodingID == 0 /*symbol*/) && nr.NameID == 5) // version string { bFound = true; bool bVerStringValid = false; byte [] buf = GetEncodedString(nr); string s = ""; if (buf != null) { sVersion = ""; for (int j = 0; j < buf.Length / 2; j++) { char c = (char)(ushort)(buf[j * 2] << 8 | buf[j * 2 + 1]); sVersion += c; } if (sVersion.Length >= 11 && sVersion.StartsWith("Version ") && Char.IsDigit(sVersion, 8)) { int j = 9; // advance past the digits in the major number while (j < sVersion.Length) { if (Char.IsDigit(sVersion, j)) { j++; } else { break; } } // if major number is followed by a period if (sVersion[j] == '.') { // advance past the period j++; // check for a digit if (Char.IsDigit(sVersion, j)) { bVerStringValid = true; } } } } s = "platID = " + nr.PlatformID + ", encID = " + nr.EncodingID + ", langID = " + nr.LanguageID + ", \"" + sVersion + "\""; if (bVerStringValid) { v.Pass(T.name_VersionString, P.name_P_VersionStringFormat, m_tag, s); } else { v.Error(T.name_VersionString, E.name_E_VersionStringFormat, m_tag, s); bRet = false; } // compare to mac version string if present string sMacVer = GetString(1, 0, 0xffff, 5); if (sMacVer != null) { if (sVersion.CompareTo(sMacVer) != 0) { v.Warning(T.name_VersionString, W.name_W_VersionMismatch_MS_MAC, m_tag); } } // compare to 3,10 version string if present string s310Ver = GetString(3, 10, nr.LanguageID, 5); if (s310Ver != null) { if (sVersion.CompareTo(s310Ver) != 0) { string s310 = "platID = 3, encID = 10, langID = " + nr.LanguageID + ", \"" + s310Ver + "\""; v.Warning(T.name_VersionString, W.name_W_VersionMismatch_3_1_3_10, m_tag, s + " / " + s310); } } } } } if (!bFound) { v.Error(T.name_VersionString, E.name_E_VersionStringNotFound, m_tag); bRet = false; } } if (v.PerformTest(T.name_PlatformSpecificEncoding)) { bool bIDsOk = true; for (uint i = 0; i < NumberNameRecords; i++) { NameRecord nr = GetNameRecord(i); if (nr != null) { if (nr.PlatformID == 0) // unicode { if (nr.EncodingID > 7) { string s = "platID = " + nr.PlatformID + ", encID = " + nr.EncodingID + ", langID = " + nr.LanguageID + ", nameID = " + nr.NameID; v.Error(T.name_PlatformSpecificEncoding, E.name_E_PlatformSpecificEncoding, m_tag, s); bIDsOk = false; bRet = false; } } else if (nr.PlatformID == 1) // mac { if (nr.EncodingID > 32) { string s = "platID = " + nr.PlatformID + ", encID = " + nr.EncodingID + ", langID = " + nr.LanguageID + ", nameID = " + nr.NameID; v.Error(T.name_PlatformSpecificEncoding, E.name_E_PlatformSpecificEncoding, m_tag, s); bIDsOk = false; bRet = false; } } else if (nr.PlatformID == 2) // iso { if (nr.EncodingID > 2) { string s = "platID = " + nr.PlatformID + ", encID = " + nr.EncodingID + ", langID = " + nr.LanguageID + ", nameID = " + nr.NameID; v.Error(T.name_PlatformSpecificEncoding, E.name_E_PlatformSpecificEncoding, m_tag, s); bIDsOk = false; bRet = false; } } else if (nr.PlatformID == 3) // MS { if (nr.EncodingID > 10) { string s = "platID = " + nr.PlatformID + ", encID = " + nr.EncodingID + ", langID = " + nr.LanguageID + ", nameID = " + nr.NameID; v.Error(T.name_PlatformSpecificEncoding, E.name_E_PlatformSpecificEncoding, m_tag, s); bIDsOk = false; bRet = false; } } /* * else if (nr.PlatformID == 4) // Custom * { * } */ } else { v.Warning(T.name_PlatformSpecificEncoding, W._TEST_W_OtherErrorsInTable, m_tag); bIDsOk = false; break; } } if (bIDsOk) { v.Pass(T.name_PlatformSpecificEncoding, P.name_P_PlatformSpecificEncoding, m_tag); } } if (v.PerformTest(T.name_MSLanguageIDs)) { bool bFound = false; bool bIDsOk = true; ushort [] MSLangIDs = // taken from Q224804 { 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x040D, 0x040e, 0x040F, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041D, 0x041E, 0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0429, 0x042a, 0x042b, 0x042c, 0x042D, 0x042e, 0x042f, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043b, 0x043d, 0x043e, 0x043f, 0x0441, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, 0x0457, 0x0459, 0x0461, 0x0801, 0x0804, 0x0807, 0x0809, 0x080a, 0x080c, 0x0810, 0x0812, 0x0813, 0x0814, 0x0816, 0x0818, 0x0819, 0x081a, 0x081d, 0x0820, 0x0827, 0x082c, 0x083e, 0x0843, 0x0860, 0x0861, 0x0C01, 0x0C04, 0x0c07, 0x0c09, 0x0c0a, 0x0c0c, 0x0c1a, 0x1001, 0x1004, 0x1007, 0x1009, 0x100a, 0x100c, 0x1401, 0x1404, 0x1407, 0x1409, 0x140a, 0x140c, 0x1801, 0x1809, 0x180a, 0x180c, 0x1C01, 0x1c09, 0x1c0a, 0x2001, 0x2009, 0x200a, 0x2401, 0x2409, 0x240a, 0x2801, 0x2809, 0x280a, 0x2C01, 0x2c09, 0x2c0a, 0x3001, 0x3009, 0x300a, 0x3401, 0x3409, 0x340a, 0x3801, 0x380a, 0x3C01, 0x3c0a, 0x4001, 0x400a, 0x440a, 0x480a, 0x4c0a, 0x500a }; for (uint i = 0; i < NumberNameRecords; i++) { NameRecord nr = GetNameRecord(i); if (nr != null) { if (nr.PlatformID == 3 && nr.EncodingID == 1) { bFound = true; bool bValidID = false; for (uint j = 0; j < MSLangIDs.Length; j++) { if (nr.LanguageID == MSLangIDs[j]) { bValidID = true; break; } } if (!bValidID) { string s = "platID = " + nr.PlatformID + ", encID = " + nr.EncodingID + ", langID = 0x" + nr.LanguageID.ToString("x4") + ", nameID = " + nr.NameID; v.Error(T.name_MSLanguageIDs, E.name_E_MSLanguageID, m_tag, s); bIDsOk = false; bRet = false; } } } } if (bFound && bIDsOk) { v.Pass(T.name_MSLanguageIDs, P.name_P_MSLanguageID, m_tag); } } if (v.PerformTest(T.name_unicode_length)) { bool bLengthsOk = true; for (uint i = 0; i < NumberNameRecords; i++) { NameRecord nr = GetNameRecord(i); if (nr != null) { if (nr.PlatformID == 0 || nr.PlatformID == 2 || // unicode or iso platform (nr.PlatformID == 3 && nr.EncodingID == 1)) // microsoft platform, unicode encoding { if ((nr.StringLength & 1) == 1) { string s = "platID = " + nr.PlatformID + ", encID = " + nr.EncodingID + ", langID = " + nr.LanguageID + ", nameID = " + nr.NameID + ", length = " + nr.StringLength; v.Error(T.name_unicode_length, E.name_E_UnicodeLength, m_tag, s); bLengthsOk = false; bRet = false; } } } else { v.Warning(T.name_unicode_length, W._TEST_W_OtherErrorsInTable, m_tag); bLengthsOk = false; break; } } if (bLengthsOk) { v.Pass(T.name_unicode_length, P.name_P_UnicodeLength, m_tag); } } if (v.PerformTest(T.name_Postscript)) { bool bPostscriptOk = true; string sPostscriptMac = GetString(1, 0, 0, 6); if (sPostscriptMac != null) { if (sPostscriptMac.Length > 63) { v.Error(T.name_Postscript, E.name_E_Postscript_length, m_tag, "name string (1, 0, 0, 6) is " + sPostscriptMac.Length + " characters long"); bRet = false; bPostscriptOk = false; } for (int i = 0; i < sPostscriptMac.Length; i++) { char c = sPostscriptMac[i]; if (c < 33 || c > 126 || c == '[' || c == ']' || c == '(' || c == ')' || c == '{' || c == '}' || c == '<' || c == '>' || c == '/' || c == '%') { v.Error(T.name_Postscript, E.name_E_Postscript_chars, m_tag, "name string (1, 0, 0, 6) contains an illegal character at index " + i); bRet = false; bPostscriptOk = false; } } } ushort nEncoding = 1; if (fontOwner.ContainsMsSymbolEncodedCmap()) { nEncoding = 0; } string sPostscriptMS = GetString(3, nEncoding, 0x409, 6); // ms if (sPostscriptMS != null) { if (sPostscriptMS.Length > 63) { v.Error(T.name_Postscript, E.name_E_Postscript_length, m_tag, "name string (3, " + nEncoding + ", 0x409, 6) is " + sPostscriptMS.Length + " characters long"); bRet = false; bPostscriptOk = false; } for (int i = 0; i < sPostscriptMS.Length; i++) { char c = sPostscriptMS[i]; if (c < 33 || c > 126 || c == '[' || c == ']' || c == '(' || c == ')' || c == '{' || c == '}' || c == '<' || c == '>' || c == '/' || c == '%') { v.Error(T.name_Postscript, E.name_E_Postscript_chars, m_tag, "name string (3, " + nEncoding + ", 0x409, 6) contains an illegal character at index " + i); bRet = false; bPostscriptOk = false; } } } if (sPostscriptMac == null && sPostscriptMS != null) { v.Error(T.name_Postscript, E.name_E_Postscript_missing, m_tag, "Mac Postscript string is missing, but MS Postscript string is present"); bRet = false; bPostscriptOk = false; } else if (sPostscriptMac != null && sPostscriptMS == null) { v.Error(T.name_Postscript, E.name_E_Postscript_missing, m_tag, "MS Postscript string is missing, but Mac Postscript string is present"); bRet = false; bPostscriptOk = false; } if (sPostscriptMac != null && sPostscriptMS != null) { if (sPostscriptMac != sPostscriptMS) { v.Error(T.name_Postscript, E.name_E_Postscript_unequal, m_tag, "mac postscript = " + sPostscriptMac + ", MS postscript = " + sPostscriptMS); bRet = false; bPostscriptOk = false; } } if (sPostscriptMac != null && sPostscriptMS != null && bPostscriptOk) { v.Pass(T.name_Postscript, P.name_P_Postscript, m_tag); } } if (v.PerformTest(T.name_Subfamily)) { string sStyle = GetStyleString(); if (sStyle != null) { Table_OS2 OS2Table = (Table_OS2)fontOwner.GetTable("OS/2"); if (OS2Table != null) { bool bStyleOk = true; string sStyleDetails = ""; string s = sStyle.ToLower(); bool bItalic = ((OS2Table.fsSelection & 0x01) != 0); bool bBold = ((OS2Table.fsSelection & 0x20) != 0); if (bItalic) { if (s.IndexOf("italic") == -1 && s.IndexOf("oblique") == -1) { bStyleOk = false; sStyleDetails = "OS/2.fsSelection italic bit is set, but subfamily string = '" + sStyle + "'"; } } else { if (s.IndexOf("italic") != -1 || s.IndexOf("oblique") != -1) { bStyleOk = false; sStyleDetails = "OS/2.fsSelection italic bit is clear, but subfamily string = '" + sStyle + "'"; } } if (bBold) { if (s.IndexOf("bold") == -1) { bStyleOk = false; sStyleDetails = "OS/2.fsSelection bold bit is set, but subfamily string = '" + sStyle + "'"; } } else { if (s.IndexOf("bold") != -1) { bStyleOk = false; sStyleDetails = "OS/2.fsSelection bold bit is clear, but subfamily string = '" + sStyle + "'"; } } if (bStyleOk) { v.Pass(T.name_Subfamily, P.name_P_subfamily, m_tag); } else { v.Warning(T.name_Subfamily, W.name_W_subfamily_style, m_tag, sStyleDetails); } } } } if (v.PerformTest(T.name_NoFormat14)) { bool bStringOK = true; for (uint i = 0; i < NumberNameRecords; i++) { NameRecord nr = GetNameRecord(i); if (nr != null && nr.NameID == 19 && nr.PlatformID == 0 && nr.EncodingID == 5) { string sDetails = "name string(" + nr.PlatformID + ", " + nr.EncodingID + ", 0x" + nr.LanguageID.ToString("x4") + ", " + nr.NameID + ", offset=0x" + nr.StringOffset.ToString("x4") + ")"; v.Error(T.name_NoFormat14, E.name_E_NoFormat14, m_tag, sDetails); bRet = false; bStringOK = false; } } if (bStringOK) { string sDetails = "PlatformID=0, EncodingID=5 is for " + "Variation Sequences (Format 14)"; v.Pass(T.name_NoFormat14, P.name_P_NoFormat14, m_tag, sDetails); } } if (v.PerformTest(T.name_SampleString)) { Table_cmap cmapTable = (Table_cmap)fontOwner.GetTable("cmap"); if (cmapTable != null) { for (uint i = 0; i < NumberNameRecords; i++) { NameRecord nr = GetNameRecord(i); if (nr != null) { if (nr.NameID == 19) { if (nr.PlatformID == 0 && nr.EncodingID == 5) { // Unicode platform encoding ID 5 can be // used for encodings in the 'cmap' table // but not for strings in the 'name' table. // It has already been flagged as an error, // so we will just skip it here. break; } Table_cmap.Subtable CmapSubTable = cmapTable.GetSubtable(nr.PlatformID, nr.EncodingID); if (CmapSubTable != null) { bool bStringOk = true; byte[] strbuf = GetEncodedString(nr); for (uint j = 0; j < strbuf.Length;) { if (CmapSubTable.MapCharToGlyph(strbuf, j, true) == 0) { string sDetails = "name string(" + nr.PlatformID + ", " + nr.EncodingID + ", 0x" + nr.LanguageID.ToString("x4") + ", " + nr.NameID + "), character at index " + j + " is not mapped"; v.Error(T.name_SampleString, E.name_E_sample, m_tag, sDetails); bStringOk = false; bRet = false; break; } j += CmapSubTable.BytesInChar(strbuf, j); } if (bStringOk) { string sDetails = "name string(" + nr.PlatformID + ", " + nr.EncodingID + ", 0x" + nr.LanguageID.ToString("x4") + ", " + nr.NameID + ")"; v.Pass(T.name_SampleString, P.name_P_sample, m_tag, sDetails); } } } } } } } if (v.PerformTest(T.name_NameID1to6)) { for (uint id = 1; id <= 6; id++) { bool bFound = false; for (uint i = 0; i < NumberNameRecords; i++) { NameRecord nr = GetNameRecord(i); if (nr != null) { if (nr.NameID == id) { bFound = true; break; } } } if (!bFound) { v.Warning(T.name_NameID1to6, W.name_W_ID_1to6_Required_For_Common_OSes, m_tag, "Missing Name ID " + id); } } } if (v.PerformTest(T.name_PreferredFamily)) { bool bFound = false; for (uint i = 0; i < NumberNameRecords; i++) { NameRecord nr = GetNameRecord(i); if (nr != null) { if (nr.NameID == 16) { string sPrefFam = this.GetString(nr.PlatformID, nr.EncodingID, nr.LanguageID, 16); string s = "platID = " + nr.PlatformID + ", encID = " + nr.EncodingID + ", langID = " + nr.LanguageID + ", nameID = " + nr.NameID + ", \"" + sPrefFam + "\""; v.Info(T.name_PreferredFamily, I.name_I_Preferred_family_present, m_tag, s); bFound = true; } } } if (!bFound) { v.Info(T.name_PreferredFamily, I.name_I_Preferred_family_not_present, m_tag); } } if (v.PerformTest(T.name_PreferredSubfamily)) { bool bFound = false; for (uint i = 0; i < NumberNameRecords; i++) { NameRecord nr = GetNameRecord(i); if (nr != null) { if (nr.NameID == 17) { string sPrefSubfam = this.GetString(nr.PlatformID, nr.EncodingID, nr.LanguageID, 17); string s = "platID = " + nr.PlatformID + ", encID = " + nr.EncodingID + ", langID = " + nr.LanguageID + ", nameID = " + nr.NameID + ", \"" + sPrefSubfam + "\""; v.Info(T.name_PreferredSubfamily, I.name_I_Preferred_subfamily_present, m_tag, s); bFound = true; } } } if (!bFound) { v.Info(T.name_PreferredSubfamily, I.name_I_Preferred_subfamily_not_present, m_tag); } } if (v.PerformTest(T.name_CopyrightConsistent)) { bool bCopyrightOk = true; // get mac roman English Copyright string if present string sMac = GetString(1, 0, 0, 0); // get windows 3,0 English Copyright string if present string sWin3_0 = GetString(3, 0, 1033, 0); // get windows 3,1 English Copyright string if present string sWin3_1 = GetString(3, 1, 1033, 0); // get windows 3,10 English Copyright string if present string sWin3_10 = GetString(3, 10, 1033, 0); // compare strings if (sMac != null) { if (sWin3_0 != null) { if (sWin3_0.CompareTo(sMac) != 0) { string sDetails = "(1,0,0,0)='" + sMac + "', (3,0,1033,0)='" + sWin3_0 + "'"; v.Warning(T.name_CopyrightConsistent, W.name_W_CopyrightInconsistent, m_tag, sDetails); bCopyrightOk = false; } } if (sWin3_1 != null) { if (sWin3_1.CompareTo(sMac) != 0) { string sDetails = "(1,0,0,0)='" + sMac + "', (3,1,1033,0)='" + sWin3_1 + "'"; v.Warning(T.name_CopyrightConsistent, W.name_W_CopyrightInconsistent, m_tag, sDetails); bCopyrightOk = false; } } if (sWin3_10 != null) { if (sWin3_10.CompareTo(sMac) != 0) { string sDetails = "(1,0,0,0)='" + sMac + "', (3,10,1033,0)='" + sWin3_10 + "'"; v.Warning(T.name_CopyrightConsistent, W.name_W_CopyrightInconsistent, m_tag, sDetails); bCopyrightOk = false; } } } if (sWin3_0 != null) { if (sWin3_1 != null) { if (sWin3_1.CompareTo(sWin3_0) != 0) { string sDetails = "(3,0,1033,0)='" + sWin3_0 + "', (3,1,1033,0)='" + sWin3_1 + "'"; v.Warning(T.name_CopyrightConsistent, W.name_W_CopyrightInconsistent, m_tag, sDetails); bCopyrightOk = false; } } if (sWin3_10 != null) { if (sWin3_10.CompareTo(sWin3_0) != 0) { string sDetails = "(3,0,1033,0)='" + sWin3_0 + "', (3,10,1033,0)='" + sWin3_10 + "'"; v.Warning(T.name_CopyrightConsistent, W.name_W_CopyrightInconsistent, m_tag, sDetails); bCopyrightOk = false; } } } if (sWin3_1 != null) { if (sWin3_10 != null) { if (sWin3_10.CompareTo(sWin3_1) != 0) { string sDetails = "(3,1,1033,0)='" + sWin3_1 + "', (3,10,1033,0)='" + sWin3_10 + "'"; v.Warning(T.name_CopyrightConsistent, W.name_W_CopyrightInconsistent, m_tag, sDetails); bCopyrightOk = false; } } } if (bCopyrightOk) { v.Pass(T.name_CopyrightConsistent, P.name_P_CopyrightConsistent, m_tag); } else { //bRet = false; } } if (v.PerformTest(T.name_TrademarkConsistent)) { bool bTrademarkOk = true; // get mac roman English Trademark string if present string sMac = GetString(1, 0, 0, 7); // get windows 3,0 English Trademark string if present string sWin3_0 = GetString(3, 0, 1033, 7); // get windows 3,1 English Trademark string if present string sWin3_1 = GetString(3, 1, 1033, 7); // get windows 3,10 English Trademark string if present string sWin3_10 = GetString(3, 10, 1033, 7); // compare strings if (sMac != null) { if (sWin3_0 != null) { if (sWin3_0.CompareTo(sMac) != 0) { string sDetails = "(1,0,0,7)='" + sMac + "', (3,0,1033,7)='" + sWin3_0 + "'"; v.Warning(T.name_TrademarkConsistent, W.name_W_TrademarkInconsistent, m_tag, sDetails); bTrademarkOk = false; } } if (sWin3_1 != null) { if (sWin3_1.CompareTo(sMac) != 0) { string sDetails = "(1,0,0,7)='" + sMac + "', (3,1,1033,7)='" + sWin3_1 + "'"; v.Warning(T.name_TrademarkConsistent, W.name_W_TrademarkInconsistent, m_tag, sDetails); bTrademarkOk = false; } } if (sWin3_10 != null) { if (sWin3_10.CompareTo(sMac) != 0) { string sDetails = "(1,0,0,7)='" + sMac + "', (3,10,1033,7)='" + sWin3_10 + "'"; v.Warning(T.name_TrademarkConsistent, W.name_W_TrademarkInconsistent, m_tag, sDetails); bTrademarkOk = false; } } } if (sWin3_0 != null) { if (sWin3_1 != null) { if (sWin3_1.CompareTo(sWin3_0) != 0) { string sDetails = "(3,0,1033,7)='" + sWin3_0 + "', (3,1,1033,7)='" + sWin3_1 + "'"; v.Warning(T.name_TrademarkConsistent, W.name_W_TrademarkInconsistent, m_tag, sDetails); bTrademarkOk = false; } } if (sWin3_10 != null) { if (sWin3_10.CompareTo(sWin3_0) != 0) { string sDetails = "(3,0,1033,7)='" + sWin3_0 + "', (3,10,1033,7)='" + sWin3_10 + "'"; v.Warning(T.name_TrademarkConsistent, W.name_W_TrademarkInconsistent, m_tag, sDetails); bTrademarkOk = false; } } } if (sWin3_1 != null) { if (sWin3_10 != null) { if (sWin3_10.CompareTo(sWin3_1) != 0) { string sDetails = "(3,1,1033,7)='" + sWin3_1 + "', (3,10,1033,7)='" + sWin3_10 + "'"; v.Warning(T.name_TrademarkConsistent, W.name_W_TrademarkInconsistent, m_tag, sDetails); bTrademarkOk = false; } } } if (bTrademarkOk) { v.Pass(T.name_TrademarkConsistent, P.name_P_TrademarkConsistent, m_tag); } else { //bRet = false; } } if (v.PerformTest(T.name_DescriptionConsistent)) { bool bDescriptionOk = true; // get mac roman English Description string if present string sMac = GetString(1, 0, 0, 10); // get windows 3,0 English Description string if present string sWin3_0 = GetString(3, 0, 1033, 10); // get windows 3,1 English Description string if present string sWin3_1 = GetString(3, 1, 1033, 10); // get windows 3,10 English Description string if present string sWin3_10 = GetString(3, 10, 1033, 10); // compare strings if (sMac != null) { if (sWin3_0 != null) { if (sWin3_0.CompareTo(sMac) != 0) { string sDetails = "(1,0,0,10)='" + sMac + "', (3,0,1033,10)='" + sWin3_0 + "'"; v.Warning(T.name_DescriptionConsistent, W.name_W_DescriptionInconsistent, m_tag, sDetails); bDescriptionOk = false; } } if (sWin3_1 != null) { if (sWin3_1.CompareTo(sMac) != 0) { string sDetails = "(1,0,0,10)='" + sMac + "', (3,1,1033,10)='" + sWin3_1 + "'"; v.Warning(T.name_DescriptionConsistent, W.name_W_DescriptionInconsistent, m_tag, sDetails); bDescriptionOk = false; } } if (sWin3_10 != null) { if (sWin3_10.CompareTo(sMac) != 0) { string sDetails = "(1,0,0,10)='" + sMac + "', (3,10,1033,10)='" + sWin3_10 + "'"; v.Warning(T.name_DescriptionConsistent, W.name_W_DescriptionInconsistent, m_tag, sDetails); bDescriptionOk = false; } } } if (sWin3_0 != null) { if (sWin3_1 != null) { if (sWin3_1.CompareTo(sWin3_0) != 0) { string sDetails = "(3,0,1033,10)='" + sWin3_0 + "', (3,1,1033,10)='" + sWin3_1 + "'"; v.Warning(T.name_DescriptionConsistent, W.name_W_DescriptionInconsistent, m_tag, sDetails); bDescriptionOk = false; } } if (sWin3_10 != null) { if (sWin3_10.CompareTo(sWin3_0) != 0) { string sDetails = "(3,0,1033,10)='" + sWin3_0 + "', (3,10,1033,10)='" + sWin3_10 + "'"; v.Warning(T.name_DescriptionConsistent, W.name_W_DescriptionInconsistent, m_tag, sDetails); bDescriptionOk = false; } } } if (sWin3_1 != null) { if (sWin3_10 != null) { if (sWin3_10.CompareTo(sWin3_1) != 0) { string sDetails = "(3,1,1033,10)='" + sWin3_1 + "', (3,10,1033,10)='" + sWin3_10 + "'"; v.Warning(T.name_DescriptionConsistent, W.name_W_DescriptionInconsistent, m_tag, sDetails); bDescriptionOk = false; } } } if (bDescriptionOk) { v.Pass(T.name_DescriptionConsistent, P.name_P_DescriptionConsistent, m_tag); } else { //bRet = false; } } return(bRet); }
public virtual OTTable CreateTableObject(OTTag tag, MBOBuffer buf) { OTTable table = null; string sName = GetUnaliasedTableName(tag); switch (sName) { case "BASE": table = new Table_BASE(tag, buf); break; case "CFF ": table = new Table_CFF(tag, buf); break; case "cmap": table = new Table_cmap(tag, buf); break; case "cvt ": table = new Table_cvt(tag, buf); break; case "DSIG": table = new Table_DSIG(tag, buf); break; case "EBDT": table = new Table_EBDT(tag, buf); break; case "EBLC": table = new Table_EBLC(tag, buf); break; case "EBSC": table = new Table_EBSC(tag, buf); break; case "fpgm": table = new Table_fpgm(tag, buf); break; case "gasp": table = new Table_gasp(tag, buf); break; case "GDEF": table = new Table_GDEF(tag, buf); break; case "glyf": table = new Table_glyf(tag, buf); break; case "GPOS": table = new Table_GPOS(tag, buf); break; case "GSUB": table = new Table_GSUB(tag, buf); break; case "hdmx": table = new Table_hdmx(tag, buf); break; case "head": table = new Table_head(tag, buf); break; case "hhea": table = new Table_hhea(tag, buf); break; case "hmtx": table = new Table_hmtx(tag, buf); break; case "JSTF": table = new Table_JSTF(tag, buf); break; case "kern": table = new Table_kern(tag, buf); break; case "loca": table = new Table_loca(tag, buf); break; case "LTSH": table = new Table_LTSH(tag, buf); break; case "maxp": table = new Table_maxp(tag, buf); break; case "name": table = new Table_name(tag, buf); break; case "OS/2": table = new Table_OS2(tag, buf); break; case "PCLT": table = new Table_PCLT(tag, buf); break; case "post": table = new Table_post(tag, buf); break; case "prep": table = new Table_prep(tag, buf); break; case "VDMX": table = new Table_VDMX(tag, buf); break; case "vhea": table = new Table_vhea(tag, buf); break; case "vmtx": table = new Table_vmtx(tag, buf); break; case "VORG": table = new Table_VORG(tag, buf); break; //case "Zapf": table = new Table_Zapf(tag, buf); break; default: table = new Table__Unknown(tag, buf); break; } return(table); }
/************************ * public 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); }