Example #1
0
        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);
        }
Example #2
0
        // 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);
        }
Example #3
0
            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;
            }
Example #4
0
        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
Example #5
0
        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);
        }
Example #6
0
        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);
            }
        }
Example #7
0
        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
Example #8
0
        } // 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
Example #9
0
        } // 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
Example #10
0
        } // 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
Example #11
0
        }                                               // 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);
        }
Example #12
0
        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
Example #13
0
        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
Example #14
0
        } // 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