public void ReadLayerRecord(MemoryStream ms) { _validationStatus = OTFile.OTRecordValidation_PartialValidation; try { _gID = OTFile.ReadUInt16(ms); _paletteIndex = OTFile.ReadUInt16(ms); } catch (OTDataTypeReadException e) { _validationStatus |= OTFile.OTRecordValidation_ReadTrunctated; throw new OTDataIncompleteReadException("OT parse error: unable to read layer record", e); } // record-internal validations are complete _validationStatus &= (0xff - OTFile.OTRecordValidation_PartialValidation); _validationStatus |= OTFile.OTRecordValidation_InternalValidationOnly; }
protected override void ReadTable_Internal() { // Base class constructor ran partial validations on the table record, // including checking that the offset and length are within bounds if ((_validationStatus & OTFile.OTFileValidation_StructureOffsetOutOfRange) != 0) { // out of range so can't read anything return; } MemoryStream ms = _parentFont.MemoryStream; // Read header fields // Table has 16-bit (minor) version field, so any version has known fields if (_tableRecord.Length < _colr_0_headerLength) _validationStatus |= OTFile.OTFileValidation_TableLengthTooShort; try { ms.Seek(_tableRecord.Offset, SeekOrigin.Begin); _version = OTFile.ReadUInt16(ms); _numBaseGlyphRecords = OTFile.ReadUInt16(ms); _baseGlyphRecordsOffset = OTFile.ReadUInt32(ms); _layerRecordsOffset = OTFile.ReadUInt32(ms); _numLayerRecords = OTFile.ReadUInt16(ms); } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTDataIncompleteReadException("OT parse error: unable to read " + _tableTag + " table", e); } if (_version > _latestKnownMinorVersion) _validationStatus |= OTFile.OTFileValidation_StructureMinorVersionUnknown; // check length then read base glyph records uint requiredLength = _baseGlyphRecordsOffset + _numBaseGlyphRecords * _baseGlyphRecordLength; if (_tableRecord.Length < requiredLength) _validationStatus |= OTFile.OTFileValidation_TableLengthTooShort; try { ms.Seek(_tableRecord.Offset + _baseGlyphRecordsOffset, SeekOrigin.Begin); _baseGlyphRecords = new BaseGlyphRecord[_numBaseGlyphRecords]; for (uint i = 0; i < _numBaseGlyphRecords; i++) { _baseGlyphRecords[i].ReadBaseGlyphRecord(ms); } } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTDataIncompleteReadException("OT parse error: unable to read " + _tableTag + " table", e); } // check length then read layer records requiredLength = _layerRecordsOffset + _numLayerRecords * _layerRecordLength; if (_tableRecord.Length < requiredLength) _validationStatus |= OTFile.OTFileValidation_TableLengthTooShort; try { ms.Seek(_tableRecord.Offset + _layerRecordsOffset, SeekOrigin.Begin); _layerRecords = new LayerRecord[_numLayerRecords]; for (uint i = 0; i < _numLayerRecords; i++) { _layerRecords[i].ReadLayerRecord(ms); } } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTDataIncompleteReadException("OT parse error: unable to read " + _tableTag + " table", e); } }
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
} // Validate #endregion #region Private instance methods protected override void ReadTable_Internal() { // Base class constructor ran partial validations on the table record, // including checking that the offset and length are within bounds if ((_validationStatus & OTFile.OTFileValidation_StructureOffsetOutOfRange) != 0) { // out of range so can't read anything return; } MemoryStream ms = _parentFont.MemoryStream; // Get the version and check that before continuing try { ms.Seek(_tableRecord.Offset, SeekOrigin.Begin); _majorVersion = OTFile.ReadUInt16(ms); _minorVersion = OTFile.ReadUInt16(ms); } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTFileParseException("OT parse error: unable to read " + _tableTag + " table", e); } if (_majorVersion != 1) { _validationStatus |= OTFile.OTFileValidation_StructureVersionNotSupported; throw new OTUnknownVersionException("OT parse error: unrecognized " + _tableTag + " version"); } if (_minorVersion > _hhea_1_latestKnownVersion) { _validationStatus |= OTFile.OTFileValidation_StructureMinorVersionUnknown; } if (_tableRecord.Length < _hhea_1_0_headerLength) { _validationStatus |= OTFile.OTFileValidation_TableLengthTooShort; } // Known version, OK to continue try { _ascender = OTFile.ReadOTFword(ms); _descender = OTFile.ReadOTFword(ms); _lineGap = OTFile.ReadOTFword(ms); _advanceWidthMax = OTFile.ReadOTUfword(ms); _minLeftSideBearing = OTFile.ReadOTFword(ms); _minRightSideBearing = OTFile.ReadOTFword(ms); _xMaxExtent = OTFile.ReadOTFword(ms); _caretSlopeRise = OTFile.ReadInt16(ms); _caretSlopeRun = OTFile.ReadInt16(ms); _caretOffset = OTFile.ReadInt16(ms); _reserved1 = OTFile.ReadInt16(ms); _reserved2 = OTFile.ReadInt16(ms); _reserved3 = OTFile.ReadInt16(ms); _reserved4 = OTFile.ReadInt16(ms); _metricDataFormat = OTFile.ReadInt16(ms); _numberOfHMetrics = OTFile.ReadUInt16(ms); } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTFileParseException("OT parse error: unable to read " + _tableTag + " table", e); } } // ReadTable_Internal
} // Validate #endregion #region Private instance methods protected override void ReadTable_Internal() { // Base class constructor ran partial validations on the table record, // including checking that the offset and length are within bounds if ((_validationStatus & OTFile.OTFileValidation_StructureOffsetOutOfRange) != 0) { // out of range so can't read anything return; } MemoryStream ms = _parentFont.MemoryStream; // Get the version and check that before continuing try { ms.Seek(_tableRecord.Offset, SeekOrigin.Begin); _version = OTFixed.ReadFixed(ms); } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTFileParseException("OT parse error: unable to read " + _tableTag + " table", e); } if (_version.Mantissa != 0 && _version.Mantissa != 1) { _validationStatus |= OTFile.OTFileValidation_StructureVersionNotSupported; throw new OTUnknownVersionException("OT parse error: unrecognized " + _tableTag + " version"); } switch (_version.Mantissa) { case 0: if (_version.FixedTableMinorVersionToInteger() > _maxp_0_latestKnownMinorVersion) { _validationStatus |= OTFile.OTFileValidation_StructureMinorVersionUnknown; } if (_tableRecord.Length < _maxp_0_5_headerLength) { _validationStatus |= OTFile.OTFileValidation_TableLengthTooShort; } break; case 1: if (_version.FixedTableMinorVersionToInteger() > _maxp_1_latestKnownMinorVersion) { _validationStatus |= OTFile.OTFileValidation_StructureMinorVersionUnknown; } if (_tableRecord.Length < _maxp_1_0_headerLength) { _validationStatus |= OTFile.OTFileValidation_TableLengthTooShort; } break; } // Known version, OK to continue try { _numGlyphs = OTFile.ReadUInt16(ms); } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTFileParseException("OT parse error: unable to read " + _tableTag + " table", e); } if (_version.Mantissa == 1) { try { _maxPoints = OTFile.ReadUInt16(ms); _maxContours = OTFile.ReadUInt16(ms); _maxCompositePoints = OTFile.ReadUInt16(ms); _maxCompositeContours = OTFile.ReadUInt16(ms); _maxZones = OTFile.ReadUInt16(ms); _maxTwilightPoints = OTFile.ReadUInt16(ms); _maxStorage = OTFile.ReadUInt16(ms); _maxFunctionDefs = OTFile.ReadUInt16(ms); _maxInstructionDefs = OTFile.ReadUInt16(ms); _maxStackElements = OTFile.ReadUInt16(ms); _maxSizeOfInstructions = OTFile.ReadUInt16(ms); _maxComponentElements = OTFile.ReadUInt16(ms); _maxComponentDepth = OTFile.ReadUInt16(ms); } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTFileParseException("OT parse error: unable to read " + _tableTag + " table", e); } } } // ReadTable_Internal
public void ReadTtcHeader(MemoryStream ms) { // Makes sure we're at the start of the file. ms.Seek(0, SeekOrigin.Begin); _fileOffset = 0; _validationStatus = OTFile.OTFileValidation_PartialValidation; if (ms.Length < (4 + 2 * sizeof(UInt16))) { _validationStatus |= OTFile.OTFileValidation_TtcHeaderLengthOutOfRange | OTFile.OTFileValidation_StructureLengthOutOfRange; } try { _tag = new byte[4]; if (ms.Read(_tag) < 4) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTDataIncompleteReadException("OT parse error: unable to read sufficient bytes to TTC header tag"); } _majorVersion = OTFile.ReadUInt16(ms); _minorVersion = OTFile.ReadUInt16(ms); } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTFileParseException("OT parse error: unable to read TTC header", e); } if (_majorVersion != 1 && _majorVersion != 2) { _validationStatus |= OTFile.OTFileValidation_StructureVersionNotSupported; throw new OTUnknownVersionException("OT parse error: unrecognized TTC header version"); } if (ms.Length < (4 + 2 * sizeof(UInt16) + sizeof(UInt32))) { _validationStatus |= OTFile.OTFileValidation_TtcHeaderLengthOutOfRange | OTFile.OTFileValidation_StructureLengthOutOfRange; } try { _numFonts = OTFile.ReadUInt32(ms); } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTFileParseException("OT parse error: unable to read TTC header", e); } if (ms.Length < (4 + 2 * sizeof(UInt16) + (_numFonts + 1) * sizeof(UInt32))) { _validationStatus |= OTFile.OTFileValidation_TtcHeaderLengthOutOfRange | OTFile.OTFileValidation_StructureLengthOutOfRange; } _offsetTableOffsets = new uint[_numFonts]; for (UInt32 i = 0; i < _numFonts; i++) { try { _offsetTableOffsets[i] = OTFile.ReadUInt32(ms); } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTFileParseException("OT parse error: unable to read TTC header", e); } } // loop over offsets array if (_majorVersion == 2) { // may have DSIG table if (ms.Length < (4 + 2 * sizeof(UInt16) + (_numFonts + 4) * sizeof(UInt32))) { _validationStatus |= OTFile.OTFileValidation_TtcHeaderLengthOutOfRange | OTFile.OTFileValidation_StructureLengthOutOfRange; } try { _dsigTag = new byte[4]; if (ms.Read(_dsigTag) < 4) { throw new OTDataIncompleteReadException("OT parse error: unable to read sufficient bytes to DSIG tag"); } _dsigLength = OTFile.ReadUInt32(ms); _dsigOffset = OTFile.ReadUInt32(ms); } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTFileParseException("OT parse error: unable to read TTC header", e); } } // version 2.x } // ReadTtcHeader
} // Validate #endregion #region Private instance methods protected override void ReadTable_Internal() { // Base class constructor ran partial validations on the table record, // including checking that the offset and length are within bounds if ((_validationStatus & OTFile.OTFileValidation_StructureOffsetOutOfRange) != 0) { // out of range so can't read anything return; } MemoryStream ms = _parentFont.MemoryStream; // Get the version and check that before continuing try { ms.Seek(_tableRecord.Offset, SeekOrigin.Begin); _majorVersion = OTFile.ReadUInt16(ms); _minorVersion = OTFile.ReadUInt16(ms); } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTFileParseException("OT parse error: unable to read " + _tableTag + " table", e); } if (_majorVersion != 1) { _validationStatus |= OTFile.OTFileValidation_StructureVersionNotSupported; throw new OTUnknownVersionException("OT parse error: unrecognized " + _tableTag + " version"); } if (_minorVersion > _head_1_latestKnownMinorVersion) { _validationStatus |= OTFile.OTFileValidation_StructureMinorVersionUnknown; } if (_tableRecord.Length < _head_1_0_headerLength) { _validationStatus |= OTFile.OTFileValidation_TableLengthTooShort; } // Known version, OK to continue try { _fontRevision = OTFixed.ReadFixed(ms); _checkSumAdjustment = OTFile.ReadUInt32(ms); _magicNumber = OTFile.ReadUInt32(ms); _flagsRaw = OTFile.ReadUInt16(ms); _unitsPerEm = OTFile.ReadUInt16(ms); _createdRaw = OTFile.ReadOTLongDateTimeAsInt64(ms); _modifiedRaw = OTFile.ReadOTLongDateTimeAsInt64(ms); _xMin = OTFile.ReadInt16(ms); _yMin = OTFile.ReadInt16(ms); _xMax = OTFile.ReadInt16(ms); _yMax = OTFile.ReadInt16(ms); _macStyleRaw = OTFile.ReadUInt16(ms); _lowestRecPPEm = OTFile.ReadUInt16(ms); _fontDirectionHint = OTFile.ReadInt16(ms); _indexToLocFormat = OTFile.ReadInt16(ms); _glyphDataFormat = OTFile.ReadInt16(ms); } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTFileParseException("OT parse error: unable to read " + _tableTag + " table", e); } SetHeadFlagValues(); // set HeadFlags struct values SetHeadMacStyleValues(); // set HeadMacStyle struct values } // ReadTable_Internal