Example #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);
        }
Example #2
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);
        }