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); }
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); }