} // ReadTableRecord public UInt64 Validate(long fileLength) { // Check that tag is defined and known, and that table // offset & length are in bounds. if (!OTFont.IsKnownTableType(_tableTag)) { _validationStatus |= OTFile.OTFileValidation_UnknownTableTag; } if (!OTFont.IsSupportedTableType(_tableTag)) { _validationStatus |= OTFile.OTFileValidation_UnsupportedTableTag; } if (_tableOffset > fileLength) { _validationStatus |= OTFile.OTFileValidation_ReferencedStructureOffsetOutOfRange; } if (_tableOffset + _tableLength > fileLength) { _validationStatus |= OTFile.OTFileValidation_ReferencedStructureLengthOutOfRange; } // completed validateions; clear the partial validation flag and check for errors _validationStatus &= ~OTFile.OTFileValidation_PartialValidation; if ((_validationStatus & OTFile.OTFileValidation_ValidationIssueMask) == 0) { _validationStatus = OTFile.OTFileValidation_Valid; } return(_validationStatus); } // Validate
public OTTable(OTFont parentFont, TableRecord tableRecord) { // This is only used temporarily to create a placeholder table if the table type is not supported. _parentFont = parentFont; _tableRecord = tableRecord; CalculateCheckSum(); _validationStatus = OTFile.OTFileValidation_PartialValidation | ValidateTableRecord(); }
public OTTable(OTFont parentFont, TableRecord tableRecord, string expectedTag, bool parseWhenConstructed) { // Used for derived classes for specific table types if (tableRecord.Tag.ToString() != expectedTag) { throw new ArgumentException("TableRecord has the wrong tag for the '" + expectedTag + " table"); } _parentFont = parentFont; _tableRecord = tableRecord; CalculateCheckSum(); _validationStatus = OTFile.OTFileValidation_PartialValidation | ValidateTableRecord(); if (parseWhenConstructed) { ReadTable_Internal(); } }
public TableColr(OTFont parentFont, TableRecord tableRecord) : base(parentFont, tableRecord, _tableTag, /* parseWhenConstructed */ true) { // Base class constructor validates table record values, and marks // validation completion status as partial validation }
public void ReadOffsetTable(MemoryStream ms, uint fileOffset) { // offset was validated as in bounds by upstream caller; set read position _offsetInFile = fileOffset; ms.Seek((long)fileOffset, SeekOrigin.Begin); _validationStatus = OTFile.OTFileValidation_PartialValidation; // check length to read sfnt version tag and read if (_offsetInFile + 4 > ms.Length) { _validationStatus |= OTFile.OTFileValidation_OffsetTableLengthOutOfRange | OTFile.OTFileValidation_StructureLengthOutOfRange; } try { _sfntTag = OTTag.ReadTag(ms); } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTTableParseException("OT parse error: unable to read Offset Table", e); } // check that the sfnt version is supported before continuing if (!OTFont.IsSupportedSfntVersion(_sfntTag)) { _validationStatus |= OTFile.OTFileValidation_SfntVersionNotSupported; throw new OTTableParseException("OT parse error: font resource has an unsupported sfnt version"); } // check length to read remaining header fields, then read if (_offsetInFile + 12 > ms.Length) { _validationStatus |= OTFile.OTFileValidation_OffsetTableLengthOutOfRange | OTFile.OTFileValidation_StructureLengthOutOfRange; } try { _numTables = OTFile.ReadUInt16(ms); _searchRange = OTFile.ReadUInt16(ms); _entrySelector = OTFile.ReadUInt16(ms); _rangeShift = OTFile.ReadUInt16(ms); } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTTableParseException("OT parse error: unable to read Offset Table", e); } // check length to read encoding records array, then read the records if (_offsetInFile + 12 + _numTables * TableRecord.TableRecordSize > ms.Length) { _validationStatus |= OTFile.OTFileValidation_OffsetTableLengthOutOfRange | OTFile.OTFileValidation_StructureLengthOutOfRange; } _tableRecords = new TableRecord[_numTables]; // constructs struct records with default values _tableMap = new Dictionary <string, uint>(); try { for (uint i = 0; i < _numTables; i++) { _tableRecords[i].ReadTableRecord(ms); try { _tableMap.Add(_tableRecords[i].Tag.ToString(), i); } catch (ArgumentException) { // duplicate tag; first one wins _validationStatus |= OTFile.OTFileValidation_StructureHasDuplicateEntries; } } } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTTableParseException("OT parse error: unable to read Offset Table", e); } } // ReadOffsetTable
private void ReadFont_Internal(MemoryStream ms) { // results in Offset table for font being read, but no other tables // assumed: _offsetInFile has already been set and validated as in bounds try { _offsetTable.ReadOffsetTable(ms, _offsetInFile); } catch (OTTableParseException e) { throw new OTFontParseException("Unable to parse font data", e); } // Offset table for font has been read; we know how many and what kind // of tables. _tables = new OTTable[_offsetTable.NumTables]; // initialized with entries == null _validationStatusOfTables = new UInt64[_offsetTable.NumTables]; // initialized with entries == NotValidated // The following is something temporary: populate an array of OTTable objects // passing each its offset table record. The record is all that's needed to // parse each table; but once an object is created (OTTable), it can't change // itself into a different type; it can only be substituted with a different // type of object, and that substitution would have to be done by something // else. for (int i = 0; i < _offsetTable.NumTables; i++) { if (OTFont.IsSupportedTableType(_offsetTable.TableRecords[i].Tag)) { switch (_offsetTable.TableRecords[i].Tag.ToString()) { case "COLR": _tables[i] = new TableColr(this, _offsetTable.TableRecords[i]); break; case "fmtx": _tables[i] = new TableFmtx(this, _offsetTable.TableRecords[i]); break; case "head": _tables[i] = new TableHead(this, _offsetTable.TableRecords[i]); break; case "hhea": _tables[i] = new TableHhea(this, _offsetTable.TableRecords[i]); break; case "maxp": _tables[i] = new TableMaxp(this, _offsetTable.TableRecords[i]); break; } } else { _tables[i] = new OTTable(this, _offsetTable.TableRecords[i]); } } } // ReadFont_Internal
public void ReadFromFile(FileInfo fileInfo) { // save fileinfo for later reference _fi = fileInfo; // Check that file exists. (Handle FileStream exception in advance.) if (!_fi.Exists) { throw new FileNotFoundException("File " + _fi.FullName + " was not found.", _fi.FullName); } // read file as a byte array, then construct memory stream from byte array { byte[] bytes; try { // File.ReadAllBytes opens a filestream and then ensures it is closed bytes = File.ReadAllBytes(_fi.FullName); _ms = new MemoryStream(bytes, 0, bytes.Length, false, true); } catch (IOException e) { throw e; } } // Read sfntVersion tag try { _sfntVersionTag = OTTag.ReadTag(_ms); } catch (OTDataIncompleteReadException e) { throw new OTFileParseException("OT parse error: unable to read sfnt tag", e); } // supported format? if (!IsSupportedSfntVersion(_sfntVersionTag)) { _validationStatus = OTFileValidation_SfntVersionNotSupported; throw new OTFileParseException("OT parse error: not a known and supported sfnt type (sfnt tag = " + _sfntVersionTag.ToString()); } _validationStatus = OTFile.OTFileValidation_PartialValidation; // TTC? get TTC header if (_sfntVersionTag == (OTTag)"ttcf") { try { _ttcHeader.ReadTtcHeader(_ms); // will set read position to start of file } catch (OTException e) { _validationStatus = _ttcHeader.ValidationStatus; throw new OTFileParseException("OT parse error: unable to read TTC header", e); } _numFonts = _ttcHeader.NumFonts; } else { _numFonts = 1; } // initialize new font object(s); this will get the font headers for each font resource _fonts = new OTFont[_numFonts]; if (_sfntVersionTag == (OTTag)"ttcf") { for (uint i = 0; i < _numFonts; i++) { _fonts[i] = new OTFont(this, _ttcHeader.OffsetTableOffsets[i], i); } } else // single font { _fonts[0] = new OTFont(this); } // got TTC header; created font objects and got all the header info for each // caller can now poke individual fonts to get additional info as needed // finally, get validation status on ttc header, offset tables _validationStatusOfFonts = new UInt64[_numFonts]; for (int i = 0; i < _numFonts; i++) { // simple validations -- full validation on a table-by-table basis _fonts[i].Validate(_ms.Length, true); } if (_sfntVersionTag == (OTTag)"ttcf") { // treat ttc header validation as part of the file validation _validationStatus |= _ttcHeader.Validate(_ms.Length); // check for validation issues in any of the font resources for (int i = 0; i < _numFonts; i++) { if ((_fonts[i].ValidationStatus & OTFile.OTFileValidation_ValidationIssueMask) != 0) { _validationStatus |= OTFile.OTFileValidation_ValidationIssueInChildStructure; break; } } } else { // treat font resource validation as part of the file validation _validationStatus |= (_fonts[0].ValidationStatus & OTFile.OTFileValidation_ValidationIssueMask); } } // ReadFromFile