示例#1
0
        private bool ImportWoff2(Stream stream)
        {
            int sizeRead = 0;

            // 1. WOFF2Header: File header with basic font type and version, along with offsets
            //    to metadata and private data blocks.
            _woffHeader = new SvgWoffHeader();
            _woffTables = null;

            var buffer = new byte[SvgWoffHeader.Woff2Size];

            sizeRead = stream.Read(buffer, 0, (int)SvgWoffHeader.Woff2Size);

            Debug.Assert(sizeRead == SvgWoffHeader.Woff2Size);

            if (!_woffHeader.SetHeader(buffer))
            {
                return(false);
            }

            // 2. TableDirectory: Directory of font tables, containing size and other info.
            _woffTables = new List <SvgWoffTableDirectory>(_woffHeader.NumTables);
            for (int i = 0; i < _woffHeader.NumTables; i++)
            {
                var woffTable = new SvgWoffTableDirectory();
                if (woffTable.SetHeader(stream, _woffHeader.IsTrueType))
                {
                    if (woffTable.IsTransformed)
                    {
                        _isTransformed = true;
                    }
                    _woffTables.Add(woffTable);
                }
            }

            // 3. CollectionDirectory: An optional table containing the font fragment descriptions
            //    of font collection entries.
            if (_woffHeader.IsCollection)
            {
                //TODO: WOFF2 - Font collection not yet supported
                return(false);
            }

            // 4. CompressedFontData: Contents of font tables, compressed for storage in the WOFF2 file.
            int bytesRead  = 0;
            int bytesCount = (int)_woffHeader.TotalCompressedSize;

            if (bytesCount != 0)
            {
                byte[] compressedBuffer = SvgWoffObject.ReadBytes(stream, bytesCount, out bytesRead);
                Debug.Assert(bytesRead == bytesCount);
                if (bytesRead != bytesCount)
                {
                    return(false);
                }

                using (var brotliStream = new BrotliInputStream(new MemoryStream(compressedBuffer)))
                {
                    for (int i = 0; i < _woffHeader.NumTables; i++)
                    {
                        var woffTable = _woffTables[i];

                        bytesCount = (int)woffTable.TransformLength;

                        var tableBuffer = SvgWoffObject.ReadBytes(brotliStream, bytesCount, out bytesRead);

                        Debug.Assert(bytesRead == bytesCount);

                        if (bytesRead != bytesCount)
                        {
                            return(false);
                        }

                        woffTable.CompTable = tableBuffer;
                        woffTable.OrigTable = tableBuffer;

                        if (!_isTransformed)
                        {
                            woffTable.OrigChecksum = woffTable.CalculateChecksum();
                        }
                    }
                }
            }

            // 5. ExtendedMetadata: An optional block of extended metadata, represented in XML format
            //    and compressed for storage in the WOFF2 file.
            _metadata = new SvgWoffMetadata(_woffHeader.MetaOffset,
                                            _woffHeader.MetaLength, _woffHeader.MetaOrigLength);
            if (_woffHeader.HasMetadata)
            {
                stream.Seek(_woffHeader.MetaOffset, SeekOrigin.Begin);

                bytesRead  = 0;
                bytesCount = (int)_woffHeader.MetaLength;

                var metaBuffer = SvgWoffObject.ReadBytes(stream, bytesCount, out bytesRead);

                Debug.Assert(bytesRead == bytesCount);

                if (bytesRead != bytesCount)
                {
                    return(false);
                }

                _metadata.Data     = metaBuffer;
                _metadata.OrigData = metaBuffer;

                if (_woffHeader.MetaLength != _woffHeader.MetaOrigLength)
                {
                    bytesCount = (int)_woffHeader.MetaOrigLength;

                    using (var brotliStream = new BrotliInputStream(new MemoryStream(metaBuffer)))
                    {
                        var origBuffer = SvgWoffObject.ReadBytes(brotliStream, bytesCount, out bytesRead);

                        Debug.Assert(bytesRead == bytesCount);

                        if (bytesRead != bytesCount)
                        {
                            return(false);
                        }

                        _metadata.OrigData = origBuffer;
                    }
                }
            }

            // 6. PrivateData: An optional block of private data for the font designer, foundry, or vendor to use.
            _privateData = new SvgWoffPrivateData(_woffHeader.PrivateOffset, _woffHeader.PrivateLength);
            if (_woffHeader.HasPrivateData)
            {
                stream.Seek(_woffHeader.PrivateOffset, SeekOrigin.Begin);

                bytesRead  = 0;
                bytesCount = (int)_woffHeader.PrivateLength;

                var privateBuffer = SvgWoffObject.ReadBytes(stream, bytesCount, out bytesRead);

                Debug.Assert(bytesRead == bytesCount);

                if (bytesRead != bytesCount)
                {
                    return(false);
                }

                _privateData.Data = privateBuffer;
            }
            _woffVersion = 2;

//            ((List<SvgWoffTableDirectory>)(_woffTables)).Sort(new WoffTableComparer());

            return(true);
        }
示例#2
0
        private bool ExportSingle(Stream stream)
        {
            if (stream == null || _woffHeader == null || _woffTables == null || _woffTables.Count == 0)
            {
                return(false);
            }

            var numTables     = _woffHeader.NumTables;
            var searchRange   = (ushort)(SvgWoffObject.MaxPower2LE(numTables) * TableSize);
            var entrySelector = SvgWoffObject.Log2(SvgWoffObject.MaxPower2LE(numTables));
            var rangeShift    = (ushort)(numTables * TableSize - searchRange);

            int offset = 0;
            // Write the font offset table...
            var headerBuffer = new byte[HeaderSize];

            // uint32:	sfntVersion	0x00010000 or 0x4F54544F ('OTTO')
            offset += SvgWoffObject.WriteUInt32BE(headerBuffer, offset, _woffHeader.Flavor);
            // uint16:	numTables	Number of tables.
            offset += SvgWoffObject.WriteUInt16BE(headerBuffer, offset, _woffHeader.NumTables);
            // uint16	searchRange	(Maximum power of 2 <= numTables) x 16.
            offset += SvgWoffObject.WriteUInt16BE(headerBuffer, offset, searchRange);
            // uint16:	entrySelector	Log2(maximum power of 2 <= numTables).
            offset += SvgWoffObject.WriteUInt16BE(headerBuffer, offset, entrySelector);
            // uint16:	rangeShift	NumTables x 16-searchRange.
            offset += SvgWoffObject.WriteUInt16BE(headerBuffer, offset, rangeShift);

            stream.Write(headerBuffer, 0, (int)HeaderSize);

            uint tablesOffset = HeaderSize + numTables * TableSize;

            var tableBuffer = new byte[TableSize];

            for (int i = 0; i < numTables; i++)
            {
                offset = 0;
                var woffTable = _woffTables[i];
                // Tag:	tableTag	Table identifier.
                offset += SvgWoffObject.WriteUInt32BE(tableBuffer, offset, woffTable.Tag);
                // uint32:	checkSum	CheckSum for this table.
                offset += SvgWoffObject.WriteUInt32BE(tableBuffer, offset, woffTable.OrigChecksum);
                // Offset32	offset	Offset from beginning of TrueType font file.
                offset += SvgWoffObject.WriteUInt32BE(tableBuffer, offset, tablesOffset);
                // uint32	length	Length of this table.
                offset += SvgWoffObject.WriteUInt32BE(tableBuffer, offset, woffTable.OrigLength);

                stream.Write(tableBuffer, 0, (int)TableSize);

                tablesOffset += woffTable.OrigLength;
                if (tablesOffset % 4 != 0)
                {
                    tablesOffset += 4 - (tablesOffset % 4);
                }
            }

            var paddingBuffer = new byte[4];

            for (int i = 0; i < numTables; i++)
            {
                var woffTable = _woffTables[i];

                stream.Write(woffTable.OrigTable, 0, (int)woffTable.OrigLength);
                stream.Write(paddingBuffer, 0, (int)woffTable.Padding);
            }

            return(true);
        }
示例#3
0
        private bool ImportWoff1(Stream stream)
        {
            int sizeRead = 0;

            _woffHeader = new SvgWoffHeader();
            _woffTables = null;

            var buffer = new byte[SvgWoffHeader.Woff1Size];

            sizeRead = stream.Read(buffer, 0, (int)SvgWoffHeader.Woff1Size);

            Debug.Assert(sizeRead == SvgWoffHeader.Woff1Size);

            if (!_woffHeader.SetHeader(buffer))
            {
                return(false);
            }

            _woffTables = new List <SvgWoffTableDirectory>(_woffHeader.NumTables);

            for (int i = 0; i < _woffHeader.NumTables; i++)
            {
                buffer = new byte[SvgWoffTableDirectory.Woff1Size];

                sizeRead = stream.Read(buffer, 0, (int)SvgWoffTableDirectory.Woff1Size);

                Debug.Assert(sizeRead == SvgWoffTableDirectory.Woff1Size);

                var woffTable = new SvgWoffTableDirectory();
                if (woffTable.SetHeader(buffer))
                {
                    _woffTables.Add(woffTable);
                }
            }

            for (int i = 0; i < _woffHeader.NumTables; i++)
            {
                var woffTable = _woffTables[i];

                stream.Seek(woffTable.Offset, SeekOrigin.Begin);

                int bytesRead  = 0;
                int bytesCount = (int)woffTable.CompLength;
                if (bytesCount == 0)
                {
                    continue;
                }
                var tableBuffer = SvgWoffObject.ReadBytes(stream, bytesCount, out bytesRead);

                Debug.Assert(bytesRead == bytesCount);

                if (bytesRead != bytesCount)
                {
                    return(false);
                }

                woffTable.CompTable = tableBuffer;
                if (woffTable.CompLength == woffTable.OrigLength)
                {
                    // table data is not compressed
                    woffTable.OrigTable = tableBuffer;
                }
                else
                {
                    bytesCount = (int)woffTable.OrigLength;
                    var origBuffer = new byte[bytesCount];

                    using (var zlibStream = new ZLibStream(new MemoryStream(tableBuffer),
                                                           CompressionMode.Decompress, false))
                    {
                        int bytesStart = 0;

                        do
                        {
                            bytesRead = zlibStream.Read(origBuffer, bytesStart, bytesCount);
                            if (bytesRead == 0)
                            {
                                break;
                            }
                            bytesStart += bytesRead;
                            bytesCount -= bytesRead;
                        } while (bytesCount > 0);
                    }

                    woffTable.OrigTable = origBuffer;
                }
            }

            _metadata = new SvgWoffMetadata(_woffHeader.MetaOffset, _woffHeader.MetaLength, _woffHeader.MetaOrigLength);
            if (_woffHeader.HasMetadata)
            {
                stream.Seek(_woffHeader.MetaOffset, SeekOrigin.Begin);

                int bytesRead  = 0;
                int bytesCount = (int)_woffHeader.MetaLength;

                var metaBuffer = SvgWoffObject.ReadBytes(stream, bytesCount, out bytesRead);

                Debug.Assert(bytesRead == bytesCount);

                if (bytesRead != bytesCount)
                {
                    return(false);
                }

                _metadata.Data     = metaBuffer;
                _metadata.OrigData = metaBuffer;

                if (_woffHeader.MetaLength != _woffHeader.MetaOrigLength)
                {
                    bytesCount = (int)_woffHeader.MetaOrigLength;
                    var origBuffer = new byte[bytesCount];

                    using (var zlibStream = new ZLibStream(new MemoryStream(metaBuffer),
                                                           CompressionMode.Decompress, false))
                    {
                        int bytesStart = 0;

                        do
                        {
                            bytesRead = zlibStream.Read(origBuffer, bytesStart, bytesCount);
                            if (bytesRead == 0)
                            {
                                break;
                            }
                            bytesStart += bytesRead;
                            bytesCount -= bytesRead;
                        } while (bytesCount > 0);
                    }

                    _metadata.OrigData = origBuffer;
                }
            }

            _privateData = new SvgWoffPrivateData(_woffHeader.PrivateOffset, _woffHeader.PrivateLength);
            if (_woffHeader.HasPrivateData)
            {
                stream.Seek(_woffHeader.PrivateOffset, SeekOrigin.Begin);

                int bytesRead  = 0;
                int bytesCount = (int)_woffHeader.PrivateLength;

                var privateBuffer = SvgWoffObject.ReadBytes(stream, bytesCount, out bytesRead);

                Debug.Assert(bytesRead == bytesCount);

                if (bytesRead != bytesCount)
                {
                    return(false);
                }

                _privateData.Data = privateBuffer;
            }
            _woffVersion = 1;

            return(true);
        }