public void ReadTableRecord(MemoryStream ms) { _validationStatus = OTFile.OTFileValidation_PartialValidation; if (ms.Length - ms.Position < TableRecordSize) { _validationStatus |= OTFile.OTFileValidation_StructureLengthOutOfRange; } try { _tableTag = OTTag.ReadTag(ms); _checksum = OTFile.ReadUInt32(ms); _tableOffset = OTFile.ReadUInt32(ms); _tableLength = OTFile.ReadUInt32(ms); } catch (OTDataIncompleteReadException e) { _validationStatus |= OTFile.OTFileValidation_ReadTrunctated; throw new OTRecordParseException("OT parse error: unable to read table record", e); } } // ReadTableRecord
public static UInt32 CalcTableCheckSum(MemoryStream ms, UInt32 offset, UInt32 length, UInt32 leftPriorSum) { // C# addition is left associative, not left-and-right. To combine checksums // computed on separate adjacent portions of memory, following UInt32s must // be added to the prior sum as the right operand: priorSum + nextVal, not // nextVal + priorSum. The leftPriorSum parameter is a starting left-operand // value. ms.Seek(offset, SeekOrigin.Begin); UInt32 sum = leftPriorSum; // greedy: length is expected to be multiple of 4 with 0 padding UInt32 count = ((length + 3U) & ~3U) / sizeof(UInt32); for (int i = 0; i < count; i++) { unchecked // allow overflow { sum += OTFile.ReadUInt32(ms); } } return(sum); }
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); } }
} // 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 != 2) { _validationStatus |= OTFile.OTFileValidation_StructureVersionNotSupported; throw new OTUnknownVersionException("OT parse error: unrecognized " + _tableTag + " version"); } if (_version.FixedTableMinorVersionToInteger() > _fmtx_2_latestKnownMinorVersion) { _validationStatus |= OTFile.OTFileValidation_StructureMinorVersionUnknown; } if (_tableRecord.Length < _fmtx_2_0_headerLength) { _validationStatus |= OTFile.OTFileValidation_TableLengthTooShort; } // Known version, OK to continue try { _glyphIndex = OTFile.ReadUInt32(ms); _horizontalBefore = OTFile.ReadUInt8(ms); _horizontalAfter = OTFile.ReadUInt8(ms); _horizontalCaretHead = OTFile.ReadUInt8(ms); _horizontalCaretBase = OTFile.ReadUInt8(ms); _verticalBefore = OTFile.ReadUInt8(ms); _verticalAfter = OTFile.ReadUInt8(ms); _verticalCaretHead = OTFile.ReadUInt8(ms); _verticalCaretBase = OTFile.ReadUInt8(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