public OTFont(OTFile f, uint fileOffset, uint ttcIndex) { // Used only for TTCs _file = f; _offsetInFile = fileOffset; _ttcIndex = ttcIndex; _isInTtc = true; _defaultLabel = f.GetFileInfo().Name + ":" + ttcIndex.ToString(); if (ttcIndex >= f.NumFonts) { throw new ArgumentOutOfRangeException("TTCIndex", "TTCIndex is greater than the last font index (number of fonts - 1)"); } MemoryStream ms = f.GetMemoryStream(); if (fileOffset >= ms.Length) { _validationStatus |= OTFile.OTFileValidation_StructureOffsetOutOfRange; throw new ArgumentOutOfRangeException("fileOffset", "The offset in fileOffset is greater than the length of the file"); } ReadFont_Internal(ms); }
// following constructor will result in Offset table for font being read // and certain simple tables but not other tables public OTFont(OTFile f) { // used only for single-font file; start of font assumed to be @ 0 _file = f; _offsetInFile = 0; _defaultLabel = f.GetFileInfo().Name; MemoryStream ms = f.GetMemoryStream(); ReadFont_Internal(ms); }
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; }
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); } }
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); _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
} // 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
} // temporarily replace the abstract modifier with virtual protected virtual void CalculateCheckSum() { // This will need to be overridden for the 'head' table _calculatedChecksum = OTFile.CalcTableCheckSum(_parentFont.MemoryStream, _tableRecord.Offset, _tableRecord.Length); }
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
protected override void CalculateCheckSum() { /* The 'head' table requires special handling for calculating a checksum. The * process also involves the head.checksumAdjustment field. Both will be * calculated. * * From OT spec (v1.8.3) font file regarding TableRecord.checkSum for 'head': * To calculate the checkSum for the 'head' table which itself includes the * checkSumAdjustment entry for the entire font, do the following: * 1. Set the checkSumAdjustment to 0. * 2. Calculate the checksum for all the tables including the 'head' table * and enter that value into the table directory. * * NOTE: This wording is unclear and can be misleading. The TableRecord.checkSum * for 'head' is calculated using the modified 'head' data only, not the rest of * the file. * * From OT spec 'head' table regarding checkSumAdjustment: * To compute it: set it to 0, sum the entire font as uint32, * then store 0xB1B0AFBA - sum. * * If the font is used as a component in a font collection file, the value * of this field will be invalidated by changes to the file structure and * font table directory, and must be ignored. * * If in a TTC, ignore all that and just set both to 0. */ if (_parentFont.File.IsCollection) { _calculatedChecksum = 0; _calculatedCheckSumAdjustment = 0; return; } // get a copy of the byte array segment for the 'head' table byte[] fileData = _parentFont.MemoryStream.GetBuffer(); // ref, not copy! // make sure to get a four-byte-integral slice uint length = (_tableRecord.Length + 3U) & ~3U; byte[] headDataSegment = new byte[length]; Array.ConstrainedCopy(fileData, (int)_tableRecord.Offset, headDataSegment, 0, (int)length); // In the copy, clear the checkSumAdjustment field, bytes at relative offset 8 to 11 byte[] bytes = new byte[4] { 0, 0, 0, 0 }; bytes.CopyTo(headDataSegment, 8); // calculate the checksum for this modified 'head' copy -- that should match what's in TableRecord MemoryStream ms = new MemoryStream(headDataSegment, 0, headDataSegment.Length, true, true); _calculatedChecksum = OTFile.CalcTableCheckSum(ms, 0, length); // Now to calculate checkSumAdjustment: need to checksum the entire file with // head.checkSumAdjustment set to 0. Instead of copying the entire file, we // can compute checksum in steps: start with the file segment before the // 'head' table; then add onto that the modified 'head' copy; then add to // that the remainder of the file. // // NOTE: C# addition is left associative. We can't calculate three separate // checksums and then combine them. We need to start the calculation for the // second and third portions using the prior sum as the initial left operand. // get checksum for first file segment before the 'head' table // (note: head offset must be > 0) UInt32 sum = OTFile.CalcTableCheckSum(_parentFont.MemoryStream, 0, _tableRecord.Offset); // continue with the modified 'head' segment, passing sum as leftPriorSum sum = OTFile.CalcTableCheckSum(ms, 0, length, sum); // continue with the remainder of the file uint offsetAfterHead = _tableRecord.Offset + length; if (offsetAfterHead < _parentFont.File.Length) { sum = OTFile.CalcTableCheckSum(_parentFont.MemoryStream, offsetAfterHead, (uint)(_parentFont.File.Length - offsetAfterHead), sum); } // Now get 0xB1B0AFBA - sum unchecked { _calculatedCheckSumAdjustment = 0xB1B0AFBA - sum; } } // CalculateChecksum
} // 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