/************************ * public methods */ public OTTable GetTable(OTFont fontOwner, DirectoryEntry de) { // first try getting it from the table cache OTTable table = GetTableFromCache(de); if (table == null) { if ( de.length != 0 && de.offset != 0 && de.offset < m_file.GetFileLength() && de.offset + de.length <= m_file.GetFileLength()) { // read the table from the file MBOBuffer buf = m_file.ReadPaddedBuffer(de.offset, de.length); if (buf != null) { // put the buffer into a table object table = CreateTableObject(de.tag, buf); // add the table to the cache CachedTables.Add(table); } } } return table; }
/// <summary>Return <c>true</c> iff <c>de</c> is for a /// <c>DirectoryEntry</c> for a table equal to this one in /// tag, checksum, file offset and length. /// </summary> public bool MatchDirectoryEntry(DirectoryEntry de) { bool bRet = true; if (de.tag != m_tag) { bRet = false; } if (de.checkSum != CalcChecksum()) { bRet = false; } if (!MatchFileOffsetLength(de.offset, de.length)) { bRet = false; } return bRet; }
/************************ * protected methods */ protected OTTable GetTableFromCache(DirectoryEntry de) { OTTable ot = null; for (int i=0; i<CachedTables.Count; i++) { OTTable temp = (OTTable)CachedTables[i]; if (temp.MatchFileOffsetLength(de.offset, de.length)) { ot = temp; break; } } return ot; }
/// <summary>Notify observer of TableBegin and TableEnd events</summary> public void OnTableValidationEvent(DirectoryEntry de, bool bBegin) { if (m_OnValidateEvent != null) { if (bBegin) { m_OnValidateEvent(EventTypes.TableBegin, de); } else { m_OnValidateEvent(EventTypes.TableEnd, de); } } }
public void OnBeginTableTest(DirectoryEntry de) { StdOut("Table Test: " + (string)de.tag); }
/// <summary>Write a TTC (TT Collection) to a disk file.</summary> public static bool WriteTTCFile(FileStream fs, OTFont[] fonts) { bool bRet = true; // build the TTC header OTTag TTCtag = (OTTag)"ttcf"; uint version = 0x00020000; uint DirectoryCount = (uint)fonts.Length; uint [] TableDirectory = new uint[fonts.Length]; uint ulDsigTag = 0; uint ulDsigLength = 0; uint ulDsigOffset = 0; uint TTCHeaderLen = 12 + DirectoryCount * 4 + 12; // length of version 2.0 header // build an array of offset tables OffsetTable[] otArr = new OffsetTable[fonts.Length]; for (int iFont=0; iFont<fonts.Length; iFont++) { otArr[iFont] = new OffsetTable(new OTFixed(1,0), fonts[iFont].GetNumTables()); } // build an array of head tables that will contain the updated modified field and font checksum Table_head[] arrHeadTables = new Table_head[fonts.Length]; for (int i=0; i<fonts.Length; i++) { // get the cache Table_head headTable = (Table_head)fonts[i].GetTable("head"); Table_head.head_cache headCache = (Table_head.head_cache)headTable.GetCache(); // set the 'modified' field to the current date DateTime dt = DateTime.Now; headCache.modified = headTable.DateTimeToSecondsSince1904(dt); // generate a new table and add it to the array Table_head newHead = (Table_head)headCache.GenerateTable(); arrHeadTables[i] = newHead; } // build a list of directory entries for each font long FilePos = TTCHeaderLen; for (int iFont = 0; iFont<fonts.Length; iFont++) { ushort numTables = fonts[iFont].GetNumTables(); TableDirectory[iFont] = (uint)FilePos; FilePos += 12 + numTables*16; uint PrevFilePos = 0; for (ushort i=0; i<numTables; i++) { OTTable table = fonts[iFont].GetTable(i); OTTag tag = table.m_tag; if ((string)tag == "head") { table = arrHeadTables[iFont]; } // check if this table is a duplicate of a table in a previous font PrevFilePos = 0; if (iFont > 0) { for (int iPrevFont=0; iPrevFont<iFont; iPrevFont++) { for (int iTable=0; iTable<fonts[iPrevFont].GetNumTables(); iTable++) { OTTable PrevTable = fonts[iPrevFont].GetTable(table.m_tag); if (PrevTable != null) { if (MBOBuffer.BinaryEqual(table.m_bufTable, PrevTable.m_bufTable)) { // get the file position for the previous table for (int iDe=0; iDe<otArr[iPrevFont].DirectoryEntries.Count; iDe++) { DirectoryEntry dePrev = (DirectoryEntry)otArr[iPrevFont].DirectoryEntries[iDe]; if (dePrev.tag == table.m_tag) { PrevFilePos = dePrev.offset; break; } } } } } } } // build a new directory entry DirectoryEntry de = new DirectoryEntry(); de.tag = new OTTag(tag.GetBytes()); de.checkSum = table.CalcChecksum(); de.length = table.GetLength(); if (PrevFilePos != 0) { de.offset = (uint)PrevFilePos; } else { de.offset = (uint)FilePos; FilePos += table.GetBuffer().GetPaddedLength(); } otArr[iFont].DirectoryEntries.Add(de); } // sort the directory entries if (numTables > 1) { for (int i=0; i<numTables-1; i++) { for (int j=i+1; j<numTables; j++) { if (((DirectoryEntry)otArr[iFont].DirectoryEntries[i]).tag > ((DirectoryEntry)otArr[iFont].DirectoryEntries[j]).tag) { DirectoryEntry temp = (DirectoryEntry)otArr[iFont].DirectoryEntries[i]; otArr[iFont].DirectoryEntries[i] = (DirectoryEntry)otArr[iFont].DirectoryEntries[j]; otArr[iFont].DirectoryEntries[j] = temp; } } } } } // update each font's checksum in the head table for (int iFont=0; iFont<fonts.Length; iFont++) { ushort numTables = fonts[iFont].GetNumTables(); // calculate the checksum uint sum = 0; sum += otArr[iFont].CalcOffsetTableChecksum(); sum += otArr[iFont].CalcDirectoryEntriesChecksum(); for (ushort i=0; i<numTables; i++) { DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i]; OTTable table = fonts[iFont].GetTable(de.tag); if ((string)de.tag == "head") { table = arrHeadTables[iFont]; } sum += table.CalcChecksum(); } // get the cache Table_head headTable = arrHeadTables[iFont]; Table_head.head_cache headCache = (Table_head.head_cache)headTable.GetCache(); // set the checkSumAdujustment field headCache.checkSumAdjustment = 0xb1b0afba - sum; // generate a new table and replace the head table in the array of head tables Table_head newHead = (Table_head)headCache.GenerateTable(); arrHeadTables[iFont] = newHead; } // write the TTC header WriteUint32MBO(fs, (uint)TTCtag); WriteUint32MBO(fs, version); WriteUint32MBO(fs, DirectoryCount); for (int i=0; i<fonts.Length; i++) { WriteUint32MBO(fs, TableDirectory[i]); } WriteUint32MBO(fs, ulDsigTag); WriteUint32MBO(fs, ulDsigLength); WriteUint32MBO(fs, ulDsigOffset); // write out each font for (int iFont=0; iFont<fonts.Length; iFont++) { ushort numTables = fonts[iFont].GetNumTables(); // write the offset table fs.Write(otArr[iFont].m_buf.GetBuffer(), 0, (int)otArr[iFont].m_buf.GetLength()); // write the directory entries for (int i=0; i<numTables; i++) { DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i]; fs.Write(de.m_buf.GetBuffer(), 0, (int)de.m_buf.GetLength()); } // write out each table unless a shared version has been written for (ushort i=0; i<numTables; i++) { DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i]; if (fs.Position == de.offset) { OTTable table = fonts[iFont].GetTable(de.tag); if ((string)table.m_tag == "head") { table = arrHeadTables[iFont]; } fs.Write(table.m_bufTable.GetBuffer(), 0, (int)table.GetBuffer().GetPaddedLength()); } } } return bRet; }
/****************** * protected methods */ protected static OffsetTable ReadOffsetTable(OTFile file, uint filepos) { // read the Offset Table from the file const int SIZEOF_OFFSETTABLE = 12; OffsetTable ot = null; // read the offset table MBOBuffer buf = file.ReadPaddedBuffer(filepos, SIZEOF_OFFSETTABLE); if (buf != null) { if (OTFile.IsValidSfntVersion(buf.GetUint(0))) { ot = new OffsetTable(buf); } } // now read the directory entries if (ot != null) { const int SIZEOF_DIRECTORYENTRY = 16; for (int i=0; i<ot.numTables; i++) { uint dirFilePos = (uint)(filepos+SIZEOF_OFFSETTABLE+i*SIZEOF_DIRECTORYENTRY); MBOBuffer DirEntBuf = file.ReadPaddedBuffer(dirFilePos, SIZEOF_DIRECTORYENTRY); if (DirEntBuf != null) { DirectoryEntry de = new DirectoryEntry(DirEntBuf); ot.DirectoryEntries.Add(de); } else { Debug.Assert(false); break; } } } return ot; }
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; }
public void OnBeginTableTest( DirectoryEntry de ) { string name = ( string )de.tag; if (m_verbose == true && m_vp.IsTestingTable(name)) StdOut( "Table Test: " + name ); }
public DirectoryEntry(DirectoryEntry obj) { if (m_buf == null) m_buf = new MBOBuffer(16); tag = new OTTag(obj.tag.GetBytes()); checkSum = obj.checkSum; offset = obj.offset; length = obj.length; }
private void OnBeginTable( DirectoryEntry de ) { m_xmlWriter.WriteStartElement("TableEntry"); m_xmlWriter.WriteAttributeString("Tag", de.tag); m_xmlWriter.WriteAttributeString("Offset", "0x"+de.offset.ToString("x8")); m_xmlWriter.WriteAttributeString("Length", "0x"+de.length.ToString("x8")); m_xmlWriter.WriteAttributeString("Checksum", "0x"+de.checkSum.ToString("x8")); m_xmlWriter.WriteAttributeString("CodeFriendlyTag", MakeCodeFriendlyTag(de.tag)); m_xmlWriter.WriteWhitespace("\r\n"); m_callbacks.OnBeginTableTest( de ); }
/***************** * 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 bool Validate() { long StartTicks = DateTime.Now.Ticks; bool bRet = true; m_Validator.OnFileValidationEvent(this, true); for (uint i=0; i<m_nFonts; i++) { // check to see if user canceled validation if (m_Validator.CancelFlag) { bRet = false; break; } m_Validator.OnFontValidationEvent(i, true); OTFontVal f = GetFont(i); if (f != null) { m_Validator.OnFontParsedEvent(f); if(!f.Validate()) bRet = false; } m_Validator.OnFontValidationEvent(i, false); } // build the elapsed time string int nSeconds = (int)((DateTime.Now.Ticks-StartTicks)/(double)10000000); int nHours = nSeconds / 3600; nSeconds = nSeconds - nHours*3600; int nMins = nSeconds / 60; nSeconds = nSeconds - nMins*60; string sTime = nHours.ToString() + ":" + nMins.ToString("d2") + ":" + nSeconds.ToString("d2"); m_Validator.Info(T.T_NULL, I._GEN_I_TotalValTime, null, sTime); //Let's try to validate the DSIG table in a TTC, if it exists if (IsCollection()) { if (m_ttch.version >= 0x00020000 && GetTableManager().GetUnaliasedTableName(m_ttch.DsigTag) == "DSIG") { MBOBuffer buf = this.ReadPaddedBuffer(m_ttch.DsigOffset, m_ttch.DsigLength); OTTable table = GetTableManager().CreateTableObject(m_ttch.DsigTag, buf); DirectoryEntry de = new DirectoryEntry(); de.tag = m_ttch.DsigTag; de.offset = m_ttch.DsigOffset; de.length = m_ttch.DsigLength; OTFontVal fontOwner = new OTFontVal(this); bRet &= ValidateTable(table, m_Validator, de, fontOwner); } else { m_Validator.Warning(T.T_NULL, W._FONT_W_MissingRecommendedTable, null, "DSIG"); } } m_Validator.OnFileValidationEvent(this, false); if (m_Validator.CancelFlag) { m_Validator.ApplicationError(T.T_NULL, E._GEN_E_UserCanceled, null, ""); bRet = false; } return bRet; }
public void OnBeginTableTest( DirectoryEntry de ){ }
/****************** * protected methods */ protected static OffsetTable ReadOffsetTable(OTFileVal file, uint filepos) { // read the Offset Table from the file Validator v = file.GetValidator(); const int SIZEOF_OFFSETTABLE = 12; OffsetTable ot = null; // read the offset table MBOBuffer buf = file.ReadPaddedBuffer(filepos, SIZEOF_OFFSETTABLE); if (buf != null) { if (OTFile.IsValidSfntVersion(buf.GetUint(0))) { ot = new OffsetTable(buf); } else { v.Error(T.T_NULL, E._OFFSET_E_InvalidSFNT, null, "0x"+buf.GetUint(0).ToString("x8")); } } // now read the directory entries if (ot != null) { const int SIZEOF_DIRECTORYENTRY = 16; for (int i=0; i<ot.numTables; i++) { uint dirFilePos = (uint)(filepos+SIZEOF_OFFSETTABLE+i*SIZEOF_DIRECTORYENTRY); MBOBuffer DirEntBuf = file.ReadPaddedBuffer(dirFilePos, SIZEOF_DIRECTORYENTRY); if (DirEntBuf != null) { DirectoryEntry de = new DirectoryEntry(); de.tag = new OTTag(DirEntBuf.GetBuffer()); de.checkSum = DirEntBuf.GetUint(4); de.offset = DirEntBuf.GetUint(8); de.length = DirEntBuf.GetUint(12); ot.DirectoryEntries.Add(de); if (de.offset > file.GetFileLength()) { v.Error(T.T_NULL, E._DE_E_OffsetPastEOF, de.tag, "0x"+de.offset.ToString("x8")); } } else { break; } } } return ot; }
static byte[] get_TTC_digest( OTFile f ) { TTCHeader ttc = f.GetTTCHeader(); uint back_shift = 12; //if ( ttc.version == 0x00020000 ) back_shift = 0; TTCHBuffer ttcb = new TTCHBuffer ( 12 + ttc.DirectoryCount * 4 + 12 - back_shift ); // write the TTC header ttcb.FillUint32MBO((uint) ttc.TTCTag); ttcb.FillUint32MBO(ttc.version); ttcb.FillUint32MBO(ttc.DirectoryCount); for (int i=0; i< f.GetNumFonts() ; i++) { ttcb.FillUint32MBO( (uint) ttc.DirectoryOffsets[i] - back_shift); } //if ( ttc.version == 0x00020000 ) { ttcb.FillUint32MBO( 0 ); ttcb.FillUint32MBO( 0 ); ttcb.FillUint32MBO( 0 ); } hash.TransformBlock ( ttcb.buffer, 0, ttcb.buffer.Length, ttcb.buffer, 0 ); // build an array of offset tables OffsetTable[] otArr = new OffsetTable[f.GetNumFonts()]; for (uint iFont=0; iFont<f.GetNumFonts(); iFont++) { otArr[iFont] = new OffsetTable(new OTFixed(1,0), f.GetFont(iFont).GetNumTables()); for (ushort i=0; i<f.GetFont(iFont).GetNumTables(); i++) { DirectoryEntry old = f.GetFont(iFont).GetDirectoryEntry(i); DirectoryEntry de = new DirectoryEntry(old); de.offset -= back_shift; otArr[iFont].DirectoryEntries.Add(de); } } if ( (uint) ttc.DirectoryOffsets[(int)f.GetNumFonts()-1] < f.GetFont(0).GetDirectoryEntry(0).offset ) { // assume directory-contiguous for (uint iFont=0; iFont<f.GetNumFonts(); iFont++) { // write the offset table hash.TransformBlock (otArr[iFont].m_buf.GetBuffer(), 0, (int)otArr[iFont].m_buf.GetLength(), otArr[iFont].m_buf.GetBuffer(), 0); // write the directory entries for (int i=0; i<f.GetFont(iFont).GetNumTables(); i++) { DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i]; hash.TransformBlock (de.m_buf.GetBuffer(), 0, (int)de.m_buf.GetLength(), de.m_buf.GetBuffer(), 0 ); } } } // write out each font uint PrevPos = 0; for (uint iFont=0; iFont<f.GetNumFonts(); iFont++) { ushort numTables = f.GetFont(iFont).GetNumTables(); if ( (uint) ttc.DirectoryOffsets[(int)f.GetNumFonts()-1] > f.GetFont(0).GetDirectoryEntry(0).offset ) { // assume font-contiguous // write the offset table hash.TransformBlock (otArr[iFont].m_buf.GetBuffer(), 0, (int)otArr[iFont].m_buf.GetLength(), otArr[iFont].m_buf.GetBuffer(), 0 ); // write the directory entries for (int i=0; i<numTables; i++) { DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i]; hash.TransformBlock (de.m_buf.GetBuffer(), 0, (int)de.m_buf.GetLength(), de.m_buf.GetBuffer(), 0 ); } } // write out each table unless a shared version has been written for (ushort i=0; i<numTables; i++) { DirectoryEntry de = (DirectoryEntry)otArr[iFont].DirectoryEntries[i]; if (PrevPos < de.offset) //crude { OTTable table = f.GetFont(iFont).GetTable(de.tag); hash.TransformBlock (table.m_bufTable.GetBuffer(), 0, (int)table.GetBuffer().GetPaddedLength(), table.m_bufTable.GetBuffer(), 0 ); PrevPos = de.offset; } } } byte[] usFlag = {0, 1}; hash.TransformFinalBlock(usFlag, 0,2); return hash.Hash; }
public void OnBeginTableTest( DirectoryEntry de ) { UpdateLabelText( labelTestname, "" + de.tag ); UpdateLabelText( labelTestProgress, "" ); UpdateLabelVisible( labelTestProgress, false ); }
/// <summary>Add a new table to an non-file based table. Table cannot /// already exist in the font. /// </summary> public void AddTable(OTTable t) { if (m_File != null) { throw new ApplicationException("attempted to add a table to a file-based OTFont object"); } if (GetDirectoryEntry(t.m_tag) != null) { throw new ArgumentException("the specified table already exists in the font"); } // build a new directory entry DirectoryEntry de = new DirectoryEntry(); de.tag = new OTTag(t.m_tag.GetBytes()); de.checkSum = t.CalcChecksum(); de.offset = 0; // this value won't get fixed up until the font is written de.length = t.GetLength(); // add the directory entry m_OffsetTable.DirectoryEntries.Add(de); m_OffsetTable.numTables++; // add the table to the list of tables in memory MemBasedTables.Add(t); // special handling for certain tables string sTable = (string)t.m_tag; if (sTable == "CFF ") { m_OutlineType = OutlineType.OUTLINE_POSTSCRIPT; } else if (sTable == "glyf") { m_OutlineType = OutlineType.OUTLINE_TRUETYPE; } }
public DirectoryEntry(DirectoryEntry obj) { tag = new OTTag(obj.tag.GetBytes()); checkSum = obj.checkSum; offset = obj.offset; length = obj.length; }
protected OTTable GetTable(DirectoryEntry de) { OTTable table = null; if (m_File != null) { // get the table from OTFile's table manager table = m_File.GetTableManager().GetTable(this, de); } else { // get the table from the list in memory for (int i=0; i<MemBasedTables.Count; i++) { OTTable t = (OTTable)MemBasedTables[i]; if (de.tag == t.m_tag) { table = t; break; } } } return table; }
/// <summary>Write a single OTF to a disk file, with tables in /// proper order, checksums set, etc. /// </summary> public static bool WriteSfntFile(FileStream fs, OTFont font) { bool bRet = true; OTFixed sfntVersion = new OTFixed(1,0); ushort numTables = font.GetNumTables(); OffsetTable ot = new OffsetTable(sfntVersion, numTables); // order tables in fastfont order string [] arrOrderedNames = null; string [] ttNames = { "head", "hhea", "maxp", "OS/2", "hmtx", "LTSH", "VDMX", "hdmx", "cmap", "fpgm", "prep", "cvt ", "loca", "glyf", "kern", "name", "post", "gasp", "PCLT" }; string [] psNames = { "head", "hhea", "maxp", "OS/2", "name", "cmap", "post", "CFF " }; if (font.ContainsTrueTypeOutlines()) { arrOrderedNames = ttNames; } else if (font.ContainsPostScriptOutlines()) { arrOrderedNames = psNames; } OTTable[] OrderedTables = new OTTable[numTables]; for (ushort i=0; i<numTables; i++) { OrderedTables[i] = font.GetTable(i); } if (arrOrderedNames != null) { ushort curpos = 0; for (int iName=0; iName<arrOrderedNames.Length; iName++) { for (ushort i=curpos; i<numTables; i++) { if (arrOrderedNames[iName] == (string)OrderedTables[i].m_tag) { OTTable temp = OrderedTables[curpos]; OrderedTables[curpos] = OrderedTables[i]; OrderedTables[i] = temp; curpos++; break; } } } } // update the modified date in the head table for (int i=0; i<OrderedTables.Length; i++) { if ((string)OrderedTables[i].m_tag == "head") { // get the cache Table_head headTable = (Table_head)OrderedTables[i]; Table_head.head_cache headCache = (Table_head.head_cache)headTable.GetCache(); // set the 'modified' field to the current date and time DateTime dt = DateTime.Now; headCache.modified = headTable.DateTimeToSecondsSince1904(dt); // generate a new table and replace the head table in the list of ordered tables Table_head newHead = (Table_head)headCache.GenerateTable(); OrderedTables[i] = newHead; break; } } // build a list of directory entries long TableFilePos = 12 + numTables*16; for (ushort i=0; i<numTables; i++) { OTTable table = OrderedTables[i]; OTTag tag = table.m_tag; // build a new directory entry DirectoryEntry de = new DirectoryEntry(); de.tag = new OTTag(tag.GetBytes()); de.checkSum = table.CalcChecksum(); de.offset = (uint)TableFilePos; de.length = table.GetLength(); ot.DirectoryEntries.Add(de); TableFilePos += table.GetBuffer().GetPaddedLength(); } // sort the directory entries if (numTables > 1) { for (int i=0; i<numTables-1; i++) { for (int j=i+1; j<numTables; j++) { if (((DirectoryEntry)(ot.DirectoryEntries[i])).tag > ((DirectoryEntry)(ot.DirectoryEntries[j])).tag) { DirectoryEntry temp = (DirectoryEntry)ot.DirectoryEntries[i]; ot.DirectoryEntries[i] = (DirectoryEntry)ot.DirectoryEntries[j]; ot.DirectoryEntries[j] = temp; } } } } // update the font checksum in the head table for (int i=0; i<OrderedTables.Length; i++) { if ((string)OrderedTables[i].m_tag == "head") { // calculate the checksum uint sum = 0; sum += ot.CalcOffsetTableChecksum(); sum += ot.CalcDirectoryEntriesChecksum(); for (int j=0; j<OrderedTables.Length; j++) { sum += OrderedTables[j].CalcChecksum(); } // get the cache Table_head headTable = (Table_head)OrderedTables[i]; Table_head.head_cache headCache = (Table_head.head_cache)headTable.GetCache(); // set the checkSumAdujustment field headCache.checkSumAdjustment = 0xb1b0afba - sum; // generate a new table and replace the head table in the list of ordered tables Table_head newHead = (Table_head)headCache.GenerateTable(); OrderedTables[i] = newHead; break; } } // write the offset table fs.Write(ot.m_buf.GetBuffer(), 0, (int)ot.m_buf.GetLength()); // write the directory entries for (int i=0; i<numTables; i++) { DirectoryEntry de = (DirectoryEntry)ot.DirectoryEntries[i]; fs.Write(de.m_buf.GetBuffer(), 0, (int)de.m_buf.GetLength()); } // write the tables for (ushort i=0; i<numTables; i++) { OTTable table = OrderedTables[i]; fs.Write(table.m_bufTable.GetBuffer(), 0, (int)table.GetBuffer().GetPaddedLength()); } return bRet; }