private void OnFontParsed(OTFont f) { string sFontName = f.GetFontName(); string sFontVersion = f.GetFontVersion(); m_xmlWriter.WriteStartElement("FontInfo"); if (sFontName != null) { m_xmlWriter.WriteAttributeString("FontName", sFontName); } else { m_xmlWriter.WriteAttributeString("FontName", "BAD FONT NAME"); } if (sFontVersion != null) { m_xmlWriter.WriteAttributeString("FontVersion", sFontVersion); } else { m_xmlWriter.WriteAttributeString("FontVersion", "BAD FONT VERSION"); } string date = f.GetFontModifiedDate().ToShortDateString(); m_xmlWriter.WriteAttributeString("FontDate", date); m_xmlWriter.WriteEndElement(); m_xmlWriter.WriteWhitespace("\r\n"); }
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 void OTFileFieldInitializationHandlingTest() { bool caughtExpectedException = false; // will set to true if expected exception is caught OTFile target = new OTFile(); Assert.IsNull(target.GetFileInfo(), "Error: unexpected FileInfo"); Assert.IsNull(target.GetMemoryStream(), "Error: unexpected FileStream"); try { OTFont f = target.GetFont(0); } catch (NullReferenceException) { caughtExpectedException = true; } Assert.IsTrue(caughtExpectedException, "Error: expected exception not caught"); Assert.IsFalse(target.IsCollection, "Error: unexpected value in unopened OTFile"); Assert.IsFalse(target.IsSupportedFileType, "Error: unexpected value in unopened OTFile"); Assert.IsTrue(target.Length == 0, "Error: unexpected value in unopened OTFile"); Assert.IsTrue(target.NumFonts == 0, "Error: unexpected value in unopened OTFile"); Assert.IsNull(target.SfntVersionTag, "Error: unexpected value in unopened OTFile"); TtcHeader t = target.TtcHeader; Assert.IsTrue(t.FileOffset == 0, "Error: unexpected value in unconfigured TtcHeader"); Assert.IsNull(t.TtcTag, "Error: unexpected value in unconfigured TtcHeader"); Assert.IsTrue(t.MajorVersion == 0, "Error: unexpected value in unconfigured TtcHeader"); Assert.IsTrue(t.MinorVersion == 0, "Error: unexpected value in unconfigured TtcHeader"); Assert.IsTrue(t.NumFonts == 0, "Error: unexpected value in unconfigured TtcHeader"); Assert.IsNull(t.OffsetTableOffsets, "Error: unexpected value in unconfigured TtcHeader"); Assert.IsNull(t.DSIGTag, "Error: unexpected value in unconfigured TtcHeader"); Assert.IsTrue(t.DSIGLength == 0, "Error: unexpected value in unconfigured TtcHeader"); Assert.IsTrue(t.DSIGOffset == 0, "Error: unexpected value in unconfigured TtcHeader"); Assert.IsFalse(t.HasDSIG, "Error: unexpected value in unconfigured TtcHeader"); }
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 void OTFileOpenTest_ReadSingleFontOffsetTable() { OTFile target = new OTFile(); string FilePath = "TestData\\selawk.ttf"; try { target.ReadFromFile(FilePath); } catch (Exception) { // unexpected exception } Assert.IsTrue(target.SfntVersionTag == (OTTag)(0x00010000), "Error: unexpected sfnt tag"); OTFont f = target.GetFont(0); Assert.IsTrue(f.OffsetInFile == 0, "Error: unexpected font offset"); Assert.IsTrue(f.SfntVersionTag == (OTTag)(0x00010000), "Error: unexpected font value"); Assert.IsFalse(f.IsWithinTtc, "Error: unexpected font value"); Assert.IsTrue(f.OffsetTable.OffsetInFile == 0, "Error: unexpected offset table offset"); Assert.IsTrue(f.OffsetTable.SfntVersion == (OTTag)(0x00010000), "Error: unexpected font offset table value"); Assert.IsTrue(f.OffsetTable.NumTables == 15, "Error: unexpected font offset table value"); Assert.IsTrue(f.OffsetTable.SearchRange == 0x0080, "Error: unexpected font offset table value"); Assert.IsTrue(f.OffsetTable.EntrySelector == 0x0003, "Error: unexpected font offset table value"); Assert.IsTrue(f.OffsetTable.RangeShift == 0x0070, "Error: unexpected font offset table value"); }
/* * CONSTRUCTORS */ public I_IOGlyphsFile() { this.m_font = null; this.m_tableLoca = null; this.m_tableGlyf = null; this.m_validator = null; this.m_numGlyph = GConsts.IND_UNINITIALIZED; this.m_toCloseFileOnClear = false; }
public DSIGInfo(string filename) { fontfile = new OTFile(); tDSIG = null; Warn_TTCv1 = false; Warn_DSIG_in_memFonts = false; Warn_MalformedSIG = false; usNumSigs = 0; if (!fontfile.open(filename)) { throw new IOException("Cannot open file " + filename); } TTCHeader ttc = null; if (fontfile.IsCollection()) { ttc = fontfile.GetTTCHeader(); if (fontfile.GetTableManager().GetUnaliasedTableName(ttc.DsigTag) == "DSIG") { MBOBuffer buf = fontfile.ReadPaddedBuffer(ttc.DsigOffset, ttc.DsigLength); tDSIG = (Table_DSIG)fontfile.GetTableManager().CreateTableObject(ttc.DsigTag, buf); } for (uint i = 0; i < fontfile.GetNumFonts(); i++) { OTFont fn = fontfile.GetFont(i); Table_DSIG memDSIG = (Table_DSIG)fn.GetTable("DSIG"); if (memDSIG != null) { Warn_DSIG_in_memFonts = true; break; } } } else { OTFont fn = fontfile.GetFont(0); tDSIG = (Table_DSIG)fn.GetTable("DSIG"); } HaveDSIG = ((tDSIG == null) ? false : true); // Officially we should only warn if HaveDSIG true if (fontfile.IsCollection() && ttc.version != 0x00020000) { Warn_TTCv1 = true; } if (HaveDSIG) { FurtherWork(); } }
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 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 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 void OTFileOpenTest_ReadTtcHeaderAndOffsetTables() { OTFile target = new OTFile(); string FilePath = "TestData\\CAMBRIA.TTC"; try { target.ReadFromFile(FilePath); } catch (Exception) { // unexpected exception } Assert.IsTrue(target.SfntVersionTag == (OTTag)("ttcf"), "Error: unexpected sfnt tag"); // check one detail of ttc header Assert.IsTrue(target.TtcHeader.DSIGOffset == 0x0018AB54, "Error: unexpected TtcHeader value"); Assert.IsTrue(target.NumFonts == 2, "Error: unexpected OTFile value"); Assert.IsTrue(target.Length == 1622732, "Error: unexpected OTFile value"); Assert.IsTrue(target.IsSupportedFileType, "Error: unexpected OTFile value"); Assert.IsTrue(target.IsCollection, "Error: unexpected OTFile value"); // now check that offset tables of both fonts are read OTFont f = target.GetFont(0); Assert.IsTrue(f.OffsetInFile == 0x20, "Error: unexpected font offset"); Assert.IsTrue(f.SfntVersionTag == (OTTag)(0x00010000), "Error: unexpected font value"); Assert.IsTrue(f.IsWithinTtc, "Error: unexpected font value"); Assert.IsTrue(f.OffsetTable.OffsetInFile == 0x20, "Error: unexpected offset table offset"); Assert.IsTrue(f.OffsetTable.SfntVersion == (OTTag)(0x00010000), "Error: unexpected font offset table value"); Assert.IsTrue(f.OffsetTable.NumTables == 20, "Error: unexpected font offset table value"); Assert.IsTrue(f.OffsetTable.SearchRange == 0x0100, "Error: unexpected font offset table value"); Assert.IsTrue(f.OffsetTable.EntrySelector == 0x0004, "Error: unexpected font offset table value"); Assert.IsTrue(f.OffsetTable.RangeShift == 64, "Error: unexpected font offset table value"); f = target.GetFont(1); Assert.IsTrue(f.OffsetInFile == 0x16C, "Error: unexpected font offset"); Assert.IsTrue(f.SfntVersionTag == (OTTag)(0x00010000), "Error: unexpected font value"); Assert.IsTrue(f.IsWithinTtc, "Error: unexpected font value"); Assert.IsTrue(f.OffsetTable.OffsetInFile == 0x16C, "Error: unexpected offset table offset"); Assert.IsTrue(f.OffsetTable.SfntVersion == (OTTag)(0x00010000), "Error: unexpected font offset table value"); Assert.IsTrue(f.OffsetTable.NumTables == 21, "Error: unexpected font offset table value"); Assert.IsTrue(f.OffsetTable.SearchRange == 0x0100, "Error: unexpected font offset table value"); Assert.IsTrue(f.OffsetTable.EntrySelector == 0x0004, "Error: unexpected font offset table value"); Assert.IsTrue(f.OffsetTable.RangeShift == 80, "Error: unexpected font offset table value"); }
public void Clear() { if (this.m_toCloseFileOnClear) { if (this.m_font != null) { this.m_font.GetFile().close(); } } this.m_font = null; this.m_tableLoca = null; this.m_tableGlyf = null; if (this.m_validator != null) { this.m_validator.Clear(); } this.m_validator = null; }
/* * METHODS PRIVATE: GLYF ACCESS */ private bool GetGlyfOffset(int indexGlyph, out int offsGlyf, Validator validator, OTFont fontOwner) { offsGlyf = Table_loca.ValueInvalid; int numEntry = this.NumEntry(fontOwner); if (numEntry == Table_loca.ValueInvalid) { return(false); } if ((indexGlyph < 0) || (indexGlyph >= numEntry)) { //Debug.Assert(false, "Table_loca: GetGlyfOffset"); return(false); } int sizeEntry = this.SizeEntry(fontOwner); if (sizeEntry == Table_loca.ValueInvalid) { return(false); } int pozLoca = sizeEntry * indexGlyph; if (pozLoca + sizeEntry > this.GetLength()) { if (validator != null) { validator.Error(E._GEN_E_OffsetExceedsTableLength, "loca"); } return(false); } if (sizeEntry == 2) { offsGlyf = 2 * m_bufTable.GetUshort((uint)pozLoca); } else { offsGlyf = (int)(m_bufTable.GetUint((uint)pozLoca)); } return(true); }
/* * 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); } }
/* * PROPERTIES */ /* * public OTFile FileFont * { * get {return this.font.GetFile();} * } */ /* * METHODS: I_IOGLYPHS */ public bool Initialize(Object source, DIAction dia) { /* * ASSUMPTION: source is either * - OTFont or * - NameFileFont */ this.m_validator = new Validator(); this.m_validator.DIA = dia; this.m_font = source as OTFont; if (this.m_font == null) { string nameFileFont = source as string; if (nameFileFont != null) { Validator validatorDummy = new Validator(); OTFileVal file = new OTFileVal(validatorDummy); if (!file.open(nameFileFont)) { this.m_validator.Error(T.T_NULL, E.glyf_E_UnableToStartValidation, (OTTag)"glyf", "Unable to open font file " + nameFileFont); this.Clear(); return(false); } this.m_toCloseFileOnClear = true; try { this.m_font = file.GetFont(0); } catch { this.m_validator.Error(T.T_NULL, E.glyf_E_UnableToStartValidation, (OTTag)"glyf", "Unable to get font from the file" + nameFileFont); this.Clear(); return(false); } } } this.m_tableGlyf = (val_glyf)this.m_font.GetTable("glyf"); if (this.m_tableGlyf == null) { this.m_validator.Error(T.T_NULL, E.glyf_E_UnableToStartValidation, (OTTag)"glyf", "Missing table: glyf"); this.Clear(); return(false); } this.m_tableLoca = (val_loca)this.m_font.GetTable("loca"); if (this.m_tableLoca == null) { this.m_validator.Error(T.T_NULL, E.glyf_E_UnableToStartValidation, (OTTag)"glyf", "Missing table: loca"); this.Clear(); return(false); } if (!this.m_tableLoca.ValidateFormat(m_validator, this.m_font)) { this.m_validator.Error(T.T_NULL, E.glyf_E_UnableToStartValidation, (OTTag)"glyf", "Table 'loca' has incorrect format"); this.Clear(); return(false); } if (!this.m_tableLoca.ValidateNumEntries(null, this.m_font)) { this.m_validator.Error(T.T_NULL, E.glyf_E_UnableToStartValidation, (OTTag)"glyf", "Table 'loca' has incorrect number of entries"); this.Clear(); return(false); } this.m_numGlyph = this.m_tableLoca.NumEntry(this.m_font) - 1; return(true); }
/// <summary>Notify observer of FontParsed event</summary> public void OnFontParsedEvent(OTFont f) { m_OnValidateEvent(EventTypes.FontParsed, f); }
static int Main(string[] args) { verbose = 0; if (args.Length == 0) { Console.WriteLine("CFFInfo [-v] [-v] [-v] fontfile"); return(0); } OTFile f = new OTFile(); Table_CFF tCFF = null; string filename = null; verbose = 0; for (int i = 0; i < args.Length; i++) { if ("-v" == args[i]) { verbose++; } else { filename = args[i]; } } if (!f.open(filename)) { Console.WriteLine("Error: Cannot open {0} as font file", filename); return(0); } if (f.GetNumFonts() != 1) { Console.WriteLine("{0} contains {1} member fonts", filename, f.GetNumFonts()); } for (uint iFont = 0; iFont < f.GetNumFonts(); iFont++) { OTFont fn = f.GetFont(iFont); tCFF = (Table_CFF)fn.GetTable("CFF "); Console.WriteLine("{0} CFF table: {1}", filename, (tCFF == null) ? "Absent" : "Present"); if (tCFF == null) { continue; } /* header */ /* INDEX's */ Console.WriteLine("Name:\tcount={0}\tsize={1}", tCFF.Name.count, tCFF.Name.size); Console.WriteLine("TopDICT:\tcount={0}\tsize={1}", tCFF.TopDICT.count, tCFF.TopDICT.size); Console.WriteLine("String:\tcount={0}\tsize={1}", tCFF.String.count, tCFF.String.size); Console.WriteLine("GlobalSubr:\tcount={0}\tsize={1}", tCFF.GlobalSubr.count, tCFF.GlobalSubr.size); /* INDEX success */ var overlap = new DataOverlapDetector(); overlap.CheckForNoOverlap(0, tCFF.hdrSize); overlap.CheckForNoOverlap(tCFF.Name.begin, tCFF.Name.size); overlap.CheckForNoOverlap(tCFF.TopDICT.begin, tCFF.TopDICT.size); overlap.CheckForNoOverlap(tCFF.String.begin, tCFF.String.size); overlap.CheckForNoOverlap(tCFF.GlobalSubr.begin, tCFF.GlobalSubr.size); if (verbose > 1) { Console.WriteLine("Region-hdr :\t{0}\t{1}", 0, tCFF.hdrSize); Console.WriteLine("Region-Name :\t{0}\t{1}", tCFF.Name.begin, tCFF.Name.size); Console.WriteLine("Region-TopDICT :\t{0}\t{1}", tCFF.TopDICT.begin, tCFF.TopDICT.size); Console.WriteLine("Region-String :\t{0}\t{1}", tCFF.String.begin, tCFF.String.size); Console.WriteLine("Region-GlobalSubr :\t{0}\t{1}", tCFF.GlobalSubr.begin, tCFF.GlobalSubr.size); } for (uint i = 0; i < tCFF.Name.count; i++) { Console.WriteLine("Name: " + tCFF.Name.GetString(i)); } try{ for (uint i = 0; i < tCFF.String.count; i++) { var a = tCFF.String.GetString(i); if (verbose > 0) { Console.WriteLine("String #{0}: {1}", i, a); } } } catch (DecoderFallbackException) { for (uint i = 0; i < tCFF.String.count; i++) { var a = tCFF.String.GetUTFString(i); if (verbose > 0) { Console.WriteLine("String #{0}: {1}", i, a); } } } for (uint iDICT = 0; iDICT < tCFF.TopDICT.count; iDICT++) { var curTopDICT = tCFF.GetTopDICT(iDICT); Console.WriteLine("FullName in TopDICT: " + curTopDICT.FullName); overlap.CheckForNoOverlap((uint)curTopDICT.offsetPrivate, (uint)curTopDICT.sizePrivate); if (verbose > 1) { Console.WriteLine("Region-Private :\t{0}\t{1}", curTopDICT.offsetPrivate, curTopDICT.sizePrivate); } Console.WriteLine("Offset to Charset:\t" + curTopDICT.offsetCharset); Console.WriteLine("Offset to Encoding:\t" + curTopDICT.offsetEncoding); Table_CFF.DICTData topPrivateDict = null; try { topPrivateDict = tCFF.GetPrivate(curTopDICT); } catch (ArgumentOutOfRangeException e) { Console.WriteLine("Broken Private Dict:" + e.Message); } if (topPrivateDict != null && topPrivateDict.Subrs != 0) { var topPrivSubrs = tCFF.GetINDEX(curTopDICT.offsetPrivate + topPrivateDict.Subrs); overlap.CheckForNoOverlap(topPrivSubrs.begin, topPrivSubrs.size); if (verbose > 1) { Console.WriteLine("Region-PrivSubrs :\t{0}\t{1}", topPrivSubrs.begin, topPrivSubrs.size); } } var CharStrings = tCFF.GetINDEX(curTopDICT.offsetCharStrings); Console.WriteLine("CharStrings count: " + CharStrings.count); overlap.CheckForNoOverlap(CharStrings.begin, CharStrings.size); if (verbose > 1) { Console.WriteLine("Region-CharStrings:\t{0}\t{1}", CharStrings.begin, CharStrings.size); } if (curTopDICT.ROS != null) { Console.WriteLine("CID ROS: " + curTopDICT.ROS); Console.WriteLine("Offset to CID FDSelect:\t" + curTopDICT.offsetFDSelect); } if (curTopDICT.offsetFDArray > 0) { var FDArray = tCFF.GetINDEX(curTopDICT.offsetFDArray); overlap.CheckForNoOverlap(FDArray.begin, FDArray.size); if (verbose > 1) { Console.WriteLine("Region-FDArray :\t{0}\t{1}", FDArray.begin, FDArray.size); } for (uint i = 0; i < FDArray.count; i++) { var FDict = tCFF.GetDICT(FDArray.GetData(i)); Console.WriteLine("CID FontDict #{0}: {1}", i, FDict.FontName); overlap.CheckForNoOverlap((uint)FDict.offsetPrivate, (uint)FDict.sizePrivate); if (verbose > 1) { Console.WriteLine("Region-CID FontDict #{2} :\t{0}\t{1}", FDict.offsetPrivate, FDict.sizePrivate, i); } Table_CFF.DICTData FDictPrivate = null; try { FDictPrivate = tCFF.GetPrivate(FDict); } catch (ArgumentOutOfRangeException e) { Console.WriteLine("Broken CID FD Private Dict #{0}:{1}", i, e.Message); } if (FDictPrivate != null && FDictPrivate.Subrs != 0) { var PrivSubrs = tCFF.GetINDEX(FDict.offsetPrivate + FDictPrivate.Subrs); overlap.CheckForNoOverlap(PrivSubrs.begin, PrivSubrs.size); if (verbose > 1) { Console.WriteLine("Region-CID PrivSubrs #{2} :\t{0}\t{1}", PrivSubrs.begin, PrivSubrs.size, i); } } } } } Console.WriteLine("Tested region: {0} of {1}", overlap.Occupied, tCFF.GetLength()); if (overlap.ends != tCFF.GetLength()) { } } return(0); }
private bool ValidateOffsetWithinGlyfRange(Validator validator, OTFont fontOwner) { int cntErr = 0; int lengthGlyf = this.LengthGlyf(fontOwner); if (lengthGlyf == Table_loca.ValueInvalid) { if (validator != null) { validator.Error(T.T_NULL, E.loca_E_OffsetWithinGlyfRange, m_tag, "Unable to determine the length of the 'glyf' table"); } return(false); } int numEntry = this.NumEntry(fontOwner); if (numEntry == Table_loca.ValueInvalid) { if (validator != null) { validator.Error(T.T_NULL, E.loca_E_OffsetWithinGlyfRange, m_tag, "Unable to determine the number of entries in the 'loca' table"); } return(false); } int offsCur; for (int iEntry = 0; iEntry < numEntry; iEntry++) { GetGlyfOffset(iEntry, out offsCur, fontOwner); if (iEntry != numEntry - 1) { int offsNext; GetGlyfOffset(iEntry + 1, out offsNext, fontOwner); int length = offsNext - offsCur; if ((offsCur < 0) || (offsCur >= lengthGlyf && length != 0)) { validator.Error(T.T_NULL, E.loca_E_OffsetWithinGlyfRange, m_tag, "offset[" + iEntry + "] = " + (uint)offsCur); cntErr++; } } else { if ((offsCur < 0) || (offsCur > lengthGlyf)) { validator.Error(T.T_NULL, E.loca_E_OffsetWithinGlyfRange, m_tag, "offset[" + iEntry + "] = " + (uint)offsCur); cntErr++; } } } if (validator != null) { if (cntErr == 0) { validator.Pass(P.loca_P_OffsetWithinGlyfRange, m_tag); } } return(cntErr == 0); }
static int Main(string[] args) { if (args.Length == 0) { Console.WriteLine("DSIGInfo [-v] [-v] [-v] fontfile"); return(0); } OTFile f = new OTFile(); Table_DSIG tDSIG = null; string filename = null; verbose = 0; for (int i = 0; i < args.Length; i++) { if ("-v" == args[i]) { verbose++; } else { filename = args[i]; } } if (!f.open(filename)) { Console.WriteLine("Error: Cannot open {0} as font file", filename); return(0); } TTCHeader ttc = null; if (f.IsCollection()) { ttc = f.GetTTCHeader(); if (f.GetTableManager().GetUnaliasedTableName(ttc.DsigTag) == "DSIG") { MBOBuffer buf = f.ReadPaddedBuffer(ttc.DsigOffset, ttc.DsigLength); tDSIG = (Table_DSIG)f.GetTableManager().CreateTableObject(ttc.DsigTag, buf); } for (uint i = 0; i < f.GetNumFonts(); i++) { OTFont fn = f.GetFont(i); Table_DSIG memDSIG = (Table_DSIG)fn.GetTable("DSIG"); if (memDSIG != null) { Console.WriteLine("Warning: DSIG in member font"); break; } } } else { OTFont fn = f.GetFont(0); tDSIG = (Table_DSIG)fn.GetTable("DSIG"); } Console.WriteLine("{0} DSIG table: {1}", filename, (tDSIG == null) ? "Absent" : "Present"); if (tDSIG == null) { return(0); } if (f.IsCollection() && ttc.version != 0x00020000) { Console.WriteLine("Warning: TTC has DSIG but header version is 0x{0}, != 0x00020000", ttc.version.ToString("X8")); } if (tDSIG.usNumSigs != 1) { Console.WriteLine("NumSigs = {0}", tDSIG.usNumSigs); } for (uint v = 0; v < tDSIG.usNumSigs; v++) { Table_DSIG.SignatureBlock sgb; try { sgb = tDSIG.GetSignatureBlock(v); } catch (IndexOutOfRangeException) { Console.WriteLine("Error: Out of Range SignatureBlock {0}", v); break; } SignedCms cms = new SignedCms(); try { cms.Decode(sgb.bSignature); } catch (Exception e) { if (e is NullReferenceException || /* Mono */ e is CryptographicException /* .Net2 */) { Console.WriteLine("Error: Malformed Signature"); break; } Console.WriteLine("Error: Malformed Signature (Unexpected Case 1)"); throw; } if (cms.SignerInfos.Count > 1) { Console.WriteLine("#SignerInfos: {0}", cms.SignerInfos.Count); } foreach (var si in cms.SignerInfos) { Console.WriteLine(si.Certificate); if (Type.GetType("Mono.Runtime") == null) { foreach (var ua in si.UnsignedAttributes) { foreach (var asnd in ua.Values) { try { ASN1 vv = new ASN1(asnd.RawData); ASN1 t = new ASN1(vv[3][1][1].Value); Console.WriteLine("Decoded Signing Time: {0}", ASN1Convert.ToDateTime(t)); } catch (Exception) { /* Nothing to do */ } } } } } Console.WriteLine("#Certificates: {0}", cms.Certificates.Count); #if HAVE_MONO_X509 certs = new Mono.Security.X509.X509CertificateCollection(); //Mono.Security.X509.X509Chain signerChain = new Mono.Security.X509.X509Chain (); #endif foreach (var x509 in cms.Certificates) { #if HAVE_MONO_X509 certs.Add(new Mono.Security.X509.X509Certificate(x509.RawData)); #endif if (verbose > 0) { Console.WriteLine(x509); } else { Console.WriteLine(x509.Subject); } } ; #if HAVE_MONO_X509 Mono.Security.X509.X509Certificate x = new Mono.Security.X509.X509Certificate(cms.SignerInfos[0].Certificate.RawData); Mono.Security.X509.X509Certificate parent = x; while (x != null) // Self-signed is fine - the font bundled CA is self-signed. { parent = x; // last valid x = FindCertificateParent(x); if (x != null && x.Equals(parent)) { break; } } #endif // Windows 10/.net 4.6.x throws here ASN1 spc; try { spc = new ASN1(cms.ContentInfo.Content); } catch (Exception e) { if (e is IndexOutOfRangeException) { Console.WriteLine("Error: Malformed Signature (Win10/.net 4.6.x)"); break; } Console.WriteLine("Error: Malformed Signature (Unexpected Case 2)"); throw; } ASN1 playload_oid = null; ASN1 oid = null; ASN1 digest = null; ASN1 obsolete = null; if (Type.GetType("Mono.Runtime") == null) { // DotNet is much saner! playload_oid = spc[0][0]; obsolete = spc[0][1][0]; oid = spc[1][0][0]; digest = spc[1][1]; } else { playload_oid = spc[0]; obsolete = spc[1][0]; oid = spc[2][0][0]; digest = spc[2][1]; } string algo = ASN1Convert.ToOid(oid); string algoname = (new Oid(algo)).FriendlyName; Console.WriteLine("Digest Algorithm: {0}", algoname); byte[] Value = digest.Value; StringBuilder hexLine_sig = new StringBuilder(); for (int i = 0; i < Value.Length; i++) { hexLine_sig.AppendFormat("{0} ", Value [i].ToString("X2")); } hexLine_sig.AppendFormat(Environment.NewLine); switch (algoname) { case "md5": hash = HashAlgorithm.Create("MD5"); break; case "sha1": hash = HashAlgorithm.Create("SHA1"); break; default: throw new NotImplementedException("Unknown HashAlgorithm: " + algoname); } byte[] cdigest; if (f.IsCollection()) { cdigest = get_TTC_digest(f); } else { cdigest = get_TTF_digest(f); } StringBuilder hexLine = new StringBuilder(); for (int i = 0; i < cdigest.Length; i++) { hexLine.AppendFormat("{0} ", cdigest [i].ToString("X2")); } hexLine.AppendFormat(Environment.NewLine); Console.WriteLine("{0} Signed Digest:\t{1}", algoname.ToUpper(), hexLine_sig); Console.WriteLine("Calculated Digest:\t{0}", hexLine); string root_thumb = ""; #if HAVE_MONO_X509 root_thumb = (new System.Security.Cryptography.X509Certificates.X509Certificate2(parent.RawData)).Thumbprint; Console.WriteLine("ChainEnd Name: {0}", parent.SubjectName); Console.WriteLine("ChainEnd Self-Signed: {0}", parent.IsSelfSigned); #endif Console.WriteLine("ChainEnd: {0}", root_thumb); bool trusted = false; try { string root_id = trusted_roots[root_thumb]; Console.WriteLine("RootID: {0}", root_id); trusted = true; } catch (KeyNotFoundException) {} Console.WriteLine("Trusted: {0}", trusted); } return(0); }
/* * METHODS PUBLIC: GLYF ACCESS */ public bool GetValidateEntryGlyf(int indexGlyph, out int offsStart, out int length, Validator validator, OTFont fontOwner) { offsStart = Table_loca.ValueInvalid; length = Table_loca.ValueInvalid; int offsGlyfCur, offsGlyfNext; if ((!this.GetGlyfOffset(indexGlyph, out offsGlyfCur, validator, fontOwner)) || (!this.GetGlyfOffset(indexGlyph + 1, out offsGlyfNext, validator, fontOwner))) { return(false); // the error is already reported } int lengthGlyf = this.LengthGlyf(fontOwner); if (lengthGlyf == Table_loca.ValueInvalid) { return(false); } if ((offsGlyfCur < 0) || (offsGlyfCur >= lengthGlyf)) { if (validator != null) { validator.Error(E.loca_E_OffsetWithinGlyfRange, "loca"); } return(false); } if ((offsGlyfNext < 0) || (offsGlyfNext >= lengthGlyf)) { int numEntry = this.NumEntry(fontOwner); if ((indexGlyph != numEntry - 2) || (offsGlyfNext != lengthGlyf)) { if (validator != null) { validator.Error(T.T_NULL, E.loca_E_OffsetWithinGlyfRange, (OTTag)"loca", "index glyph=" + indexGlyph + 1); } } } int lengthGlyfCur = offsGlyfNext - offsGlyfCur; if (lengthGlyfCur < 0) { if (validator != null) { validator.Error(E.loca_E_OffsetsIncreasing, "loca"); } return(false); } if (lengthGlyfCur == 0) { if (validator != null) { validator.Warning(T.T_NULL, W.loca_W_GlyfEntryEmpty, "loca"); } } if (lengthGlyfCur % 4 != 0) { if (validator != null) { validator.Warning(T.T_NULL, W.loca_W_GlyfEntryLengthAlignment, "loca"); } } offsStart = offsGlyfCur; length = lengthGlyfCur; return(true); }
static byte[] get_TTF_digest(OTFile f) { OTFont fn = f.GetFont(0); Table_DSIG tDSIG = (Table_DSIG)fn.GetTable("DSIG"); DirectoryEntry deDSIG = null; // sort table by offset Dictionary <uint, int> offsetlookup = new Dictionary <uint, int>(); var list = new List <uint>(); for (ushort i = 0; i < fn.GetNumTables(); i++) { DirectoryEntry de = fn.GetDirectoryEntry(i); offsetlookup.Add(de.offset, i); list.Add(de.offset); if ((string)de.tag == "DSIG") { deDSIG = de; } } list.Sort(); // New offset table var old_ot = fn.GetOffsetTable(); OffsetTable ot = new OffsetTable(old_ot.sfntVersion, (ushort)(old_ot.numTables - 1)); for (ushort i = 0; i < fn.GetNumTables(); i++) { DirectoryEntry oldde = fn.GetDirectoryEntry(i); if ((string)oldde.tag != "DSIG") { DirectoryEntry de = new DirectoryEntry(oldde); de.offset -= 16; // one less entry if (de.offset > deDSIG.offset) { de.offset -= tDSIG.GetBuffer().GetPaddedLength(); } ot.DirectoryEntries.Add(de); } } hash.TransformBlock(ot.m_buf.GetBuffer(), 0, (int)ot.m_buf.GetLength(), ot.m_buf.GetBuffer(), 0); for (int i = 0; i < ot.DirectoryEntries.Count; i++) { DirectoryEntry de = (DirectoryEntry)ot.DirectoryEntries[i]; hash.TransformBlock(de.m_buf.GetBuffer(), 0, (int)de.m_buf.GetLength(), de.m_buf.GetBuffer(), 0); } Table_head headTable = (Table_head)fn.GetTable("head"); // calculate the checksum uint sum = 0; sum += ot.CalcOffsetTableChecksum(); sum += ot.CalcDirectoryEntriesChecksum(); foreach (var key in list) { OTTable table = fn.GetTable((ushort)offsetlookup[key]); if ((string)table.GetTag() != "DSIG") { sum += table.CalcChecksum(); } } Table_head.head_cache headCache = (Table_head.head_cache)headTable.GetCache(); // set the checkSumAdujustment field headCache.checkSumAdjustment = 0xb1b0afba - sum; Table_head newHead = (Table_head)headCache.GenerateTable(); foreach (var key in list) { OTTable table = fn.GetTable((ushort)offsetlookup[key]); if ((string)table.GetTag() == "head") { table = newHead; } if ((string)table.GetTag() != "DSIG") { hash.TransformBlock(table.m_bufTable.GetBuffer(), 0, (int)table.GetBuffer().GetPaddedLength(), table.m_bufTable.GetBuffer(), 0); } } byte[] usFlag = { 0, 1 }; hash.TransformFinalBlock(usFlag, 0, 2); return(hash.Hash); }
private void GetCompositeGlyphStats(Table_glyf.CompositeGlyph cg, ref short nContours, ref ushort nPoints, ref ushort nInstructions, ref ushort nComponentElements, ref ushort nComponentDepth, OTFont fontOwner, Table_glyf glyfTable) { ushort nPointsTemp = 0; short nContoursTemp = 0; ushort nInstructionsTemp = 0; short TotalContours = 0; ushort TotalPoints = 0; ushort maxInstructions = 0; nComponentDepth++; int nCompositeGlyphs = 0; while (cg != null) { nCompositeGlyphs++; nInstructions = Math.Max(nInstructions, cg.GetNumInstructions()); Table_glyf.header glyfHeader = glyfTable.GetGlyphHeader(cg.glyphIndex, fontOwner); if (glyfHeader != null) { if (glyfHeader.numberOfContours >= 0) { nContoursTemp = glyfHeader.numberOfContours; Table_glyf.SimpleGlyph sg = glyfHeader.GetSimpleGlyph(); nPointsTemp = (ushort)(sg.GetEndPtOfContour((uint)glyfHeader.numberOfContours - 1) + 1); nInstructionsTemp = sg.instructionLength; } else { Table_glyf.CompositeGlyph EmbeddedCG = glyfHeader.GetCompositeGlyph(); GetCompositeGlyphStats(EmbeddedCG, ref nContoursTemp, ref nPointsTemp, ref nInstructionsTemp, ref nComponentElements, ref nComponentDepth, fontOwner, glyfTable); } TotalContours += nContoursTemp; TotalPoints += nPointsTemp; maxInstructions = Math.Max(maxInstructions, nInstructionsTemp); } cg = cg.GetNextCompositeGlyph(); } nComponentElements = (ushort)Math.Max(nComponentElements, nCompositeGlyphs); nContours = TotalContours; nPoints = TotalPoints; nInstructions = maxInstructions; }
static int Main(string[] args) { verbose = 0; if (args.Length == 0) { Console.WriteLine("SVGInfo [-v] [-v] [-v] fontfile"); return(0); } OTFile f = new OTFile(); Table_SVG tSVG = null; string filename = null; verbose = 0; for (int i = 0; i < args.Length; i++) { if ("-v" == args[i]) { verbose++; } else { filename = args[i]; } } if (!f.open(filename)) { Console.WriteLine("Error: Cannot open {0} as font file", filename); return(0); } for (uint i = 0; i < f.GetNumFonts(); i++) { OTFont fn = f.GetFont(i); tSVG = (Table_SVG)fn.GetTable("SVG "); Console.WriteLine("{0} SVG table: {1}", filename, (tSVG == null) ? "Absent" : "Present"); if (tSVG == null) { continue; } Console.WriteLine("version={0}, reserved={1}, offsetToSVGDocIndex={2}, numEntries={3}", tSVG.version, tSVG.reserved, tSVG.offsetToSVGDocIndex, tSVG.numEntries); Console.WriteLine("start\tend\tOffset\tLength"); Console.WriteLine("=====\t===\t======\t======"); for (uint j = 0; j < tSVG.numEntries; j++) { var index = tSVG.GetDocIndexEntry(j); Console.WriteLine("{0}\t{1}\t{2}\t{3}", index.startGlyphID, index.endGlyphID, index.svgDocOffset, index.svgDocLength); } if (verbose > 0) { XmlDocument doc = new XmlDocument(); if (verbose < 2) { doc.XmlResolver = null; //suppress network fetch } for (uint j = 0; j < tSVG.numEntries; j++) { var svgdoc = tSVG.GetDoc(j); Console.WriteLine("=={0}==", j); using (MemoryStream ms = new MemoryStream(svgdoc)) { doc.Load(ms); } using (XmlTextWriter writer = new XmlTextWriter(Console.Out)) { writer.Formatting = Formatting.Indented; writer.Indentation = 4; doc.Save(writer); writer.Flush(); } Console.WriteLine(""); //Newline } } } return(0); }
private bool ComputeMaxpStats(Table_glyf glyfTable, OTFont fontOwner) { bool bRet = true; try { maxPointsCalc = 0; maxContoursCalc = 0; maxCompositePointsCalc = 0; maxCompositeContoursCalc = 0; maxSizeOfInstructionsCalc = 0; maxComponentElementsCalc = 0; maxComponentDepthCalc = 0; for (uint iGlyph = 0; iGlyph < NumGlyphs; iGlyph++) { Table_glyf.header glyfHeader = glyfTable.GetGlyphHeader(iGlyph, fontOwner); if (glyfHeader != null) { if (glyfHeader.numberOfContours >= 0) { Table_glyf.SimpleGlyph sg = glyfHeader.GetSimpleGlyph(); maxPointsCalc = (ushort)Math.Max(maxPointsCalc, sg.GetEndPtOfContour((uint)glyfHeader.numberOfContours - 1) + 1); maxContoursCalc = (ushort)Math.Max(maxContoursCalc, glyfHeader.numberOfContours); maxSizeOfInstructionsCalc = Math.Max(maxSizeOfInstructionsCalc, sg.instructionLength); } else { ushort nPointsTemp = 0; short nContoursTemp = 0; ushort nInstructionsTemp = 0; ushort nCompElementsTemp = 0; ushort nCompDepthTemp = 0; Table_glyf.CompositeGlyph cg = glyfHeader.GetCompositeGlyph(); GetCompositeGlyphStats(cg, ref nContoursTemp, ref nPointsTemp, ref nInstructionsTemp, ref nCompElementsTemp, ref nCompDepthTemp, fontOwner, glyfTable); maxCompositePointsCalc = Math.Max(maxCompositePointsCalc, nPointsTemp); maxCompositeContoursCalc = Math.Max(maxCompositeContoursCalc, nContoursTemp); maxSizeOfInstructionsCalc = Math.Max(maxSizeOfInstructionsCalc, nInstructionsTemp); maxComponentElementsCalc = Math.Max(maxComponentElementsCalc, nCompElementsTemp); maxComponentDepthCalc = Math.Max(maxComponentDepthCalc, nCompDepthTemp); } } } } catch { maxPointsCalc = 0; maxContoursCalc = 0; maxCompositePointsCalc = 0; maxCompositeContoursCalc = 0; maxSizeOfInstructionsCalc = 0; maxComponentElementsCalc = 0; maxComponentDepthCalc = 0; bRet = false; } return(bRet); }