예제 #1
0
        private bool ReadWoff2(Stream stream)
        {
            _woffVersion = WoffUtils.Woff2Version;

            uint sizeRead = 0;

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

            sizeRead = _woffHeader.HeaderSize;

            Debug.Assert(sizeRead == WoffUtils.Woff2HeaderSize);

            if (!_woffHeader.Read(stream))
            {
                return(false);
            }

            // 2. TableDirectory: Directory of font tables, containing size and other info.
            uint offset = 0;

            _woffDirs = new List <WoffTableDirectory>(_woffHeader.NumTables);
            for (ushort i = 0; i < _woffHeader.NumTables; i++)
            {
                var woffDir = new WoffTableDirectory(i, _woffVersion, offset);

                if (woffDir.Read(stream, _woffHeader.IsTrueType))
                {
                    if (woffDir.IsTransformed)
                    {
                        _isTransformed = true;
                    }
                    _woffDirs.Add(woffDir);

                    offset += woffDir.CompLength;
                }
            }

            // 3. CollectionDirectory: An optional table containing the font fragment descriptions
            //    of font collection entries.
            if (_woffHeader.IsCollection)
            {
                var isLoaded = this.ReadWoff2Fonts(stream);
            }
            else
            {
                var isLoaded = this.ReadWoff2Font(stream);
            }

            // 5. ExtendedMetadata: An optional block of extended metadata, represented in XML format
            //    and compressed for storage in the WOFF2 file.
            _metadata = new WoffMetadata(_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 = WoffBuffer.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 = WoffBuffer.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 WoffPrivateData(_woffHeader.PrivateOffset, _woffHeader.PrivateLength);
            if (_woffHeader.HasPrivateData)
            {
                stream.Seek(_woffHeader.PrivateOffset, SeekOrigin.Begin);

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

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

                Debug.Assert(bytesRead == bytesCount);

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

                _privateData.Data = privateBuffer;
            }

            return(true);
        }
예제 #2
0
        private bool ReadWoff1(Stream stream)
        {
            _woffVersion = WoffUtils.Woff1Version;

            var woffFont = new WoffFont(_woffHeader);

            _woffFonts.Add(woffFont);
            woffFont.BeginDirectory(_woffVersion);

            _woffHeader = new WoffHeader(WoffUtils.Woff1Version);
            _woffDirs   = null;

            int sizeRead = 0;

            sizeRead = _woffHeader.HeaderSize;

            Debug.Assert(sizeRead == WoffUtils.Woff1HeaderSize);

            if (!_woffHeader.Read(stream))
            {
                return(false);
            }

            _woffDirs = new List <WoffTableDirectory>(_woffHeader.NumTables);

            // 2. TableDirectory: Directory of font tables, containing size and other info.
            for (ushort i = 0; i < _woffHeader.NumTables; i++)
            {
                var woffDir = new WoffTableDirectory(i, _woffVersion);
                if (woffDir.Read(stream))
                {
                    _woffDirs.Add(woffDir);

                    woffFont.AddDirectory(woffDir);
                }
            }

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

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

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

                Debug.Assert(bytesRead == bytesCount);

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

                woffDir.CompTable = tableBuffer;
                if (woffDir.CompLength == woffDir.OrigLength)
                {
                    // table data is not compressed
                    woffDir.OrigTable = tableBuffer;
                }
                else
                {
                    bytesCount = (int)woffDir.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);
                    }

                    woffDir.OrigTable = origBuffer;
                }
            }

            _metadata = new WoffMetadata(_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 = WoffBuffer.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 WoffPrivateData(_woffHeader.PrivateOffset, _woffHeader.PrivateLength);
            if (_woffHeader.HasPrivateData)
            {
                stream.Seek(_woffHeader.PrivateOffset, SeekOrigin.Begin);

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

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

                Debug.Assert(bytesRead == bytesCount);

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

                _privateData.Data = privateBuffer;
            }

            woffFont.EndDirectory();

            return(true);
        }