Skip to content

Commit 855b0f4

Browse files
committed
Merge branch 'feature/woff2' into develop
2 parents c1093d1 + 8dd6f7e commit 855b0f4

File tree

645 files changed

+10666
-13
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

645 files changed

+10666
-13
lines changed

io/src/main/java/com/itextpdf/io/IOException.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ public class IOException extends RuntimeException {
119119
public static final String InvalidCodeEncounteredWhileDecoding2dGroup4CompressedData = "Invalid code encountered while decoding 2D group 4 compressed data.";
120120
public static final String InvalidIccProfile = "Invalid ICC profile.";
121121
public static final String InvalidJpeg2000File = "Invalid JPEG2000 file.";
122+
public static final String InvalidWoff2File = "Invalid WOFF2 font file.";
122123
public static final String InvalidWoffFile = "Invalid WOFF font file.";
123124
@Deprecated
124125
public static final String InvalidMagicValueForBmpFile = "Invalid magic value for bmp file. Must be 'BM'";
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
/* Copyright 2015 Google Inc. All Rights Reserved.
2+
3+
Distributed under MIT license.
4+
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5+
*/
6+
7+
package com.itextpdf.io.codec.brotli.dec;
8+
9+
import java.io.IOException;
10+
import java.io.InputStream;
11+
12+
/**
13+
* Bit reading helpers.
14+
*/
15+
final class BitReader {
16+
17+
/**
18+
* Input byte buffer, consist of a ring-buffer and a "slack" region where bytes from the start of
19+
* the ring-buffer are copied.
20+
*/
21+
private static final int CAPACITY = 1024;
22+
private static final int SLACK = 16;
23+
private static final int INT_BUFFER_SIZE = CAPACITY + SLACK;
24+
private static final int BYTE_READ_SIZE = CAPACITY << 2;
25+
private static final int BYTE_BUFFER_SIZE = INT_BUFFER_SIZE << 2;
26+
27+
private final byte[] byteBuffer = new byte[BYTE_BUFFER_SIZE];
28+
private final int[] intBuffer = new int[INT_BUFFER_SIZE];
29+
private final IntReader intReader = new IntReader();
30+
31+
private InputStream input;
32+
33+
/**
34+
* Input stream is finished.
35+
*/
36+
private boolean endOfStreamReached;
37+
38+
/**
39+
* Pre-fetched bits.
40+
*/
41+
long accumulator;
42+
43+
/**
44+
* Current bit-reading position in accumulator.
45+
*/
46+
int bitOffset;
47+
48+
/**
49+
* Offset of next item in intBuffer.
50+
*/
51+
private int intOffset;
52+
53+
/* Number of bytes in unfinished "int" item. */
54+
private int tailBytes = 0;
55+
56+
/**
57+
* Fills up the input buffer.
58+
*
59+
* <p> No-op if there are at least 36 bytes present after current position.
60+
*
61+
* <p> After encountering the end of the input stream, 64 additional zero bytes are copied to the
62+
* buffer.
63+
*/
64+
// TODO: Split to check and read; move read outside of decoding loop.
65+
static void readMoreInput(BitReader br) {
66+
if (br.intOffset <= CAPACITY - 9) {
67+
return;
68+
}
69+
if (br.endOfStreamReached) {
70+
if (intAvailable(br) >= -2) {
71+
return;
72+
}
73+
throw new BrotliRuntimeException("No more input");
74+
}
75+
int readOffset = br.intOffset << 2;
76+
int bytesRead = BYTE_READ_SIZE - readOffset;
77+
System.arraycopy(br.byteBuffer, readOffset, br.byteBuffer, 0, bytesRead);
78+
br.intOffset = 0;
79+
try {
80+
while (bytesRead < BYTE_READ_SIZE) {
81+
int len = br.input.read(br.byteBuffer, bytesRead, BYTE_READ_SIZE - bytesRead);
82+
// EOF is -1 in Java, but 0 in C#.
83+
if (len <= 0) {
84+
br.endOfStreamReached = true;
85+
br.tailBytes = bytesRead;
86+
bytesRead += 3;
87+
break;
88+
}
89+
bytesRead += len;
90+
}
91+
} catch (IOException e) {
92+
throw new BrotliRuntimeException("Failed to read input", e);
93+
}
94+
IntReader.convert(br.intReader, bytesRead >> 2);
95+
}
96+
97+
static void checkHealth(BitReader br, boolean endOfStream) {
98+
if (!br.endOfStreamReached) {
99+
return;
100+
}
101+
int byteOffset = (br.intOffset << 2) + ((br.bitOffset + 7) >> 3) - 8;
102+
if (byteOffset > br.tailBytes) {
103+
throw new BrotliRuntimeException("Read after end");
104+
}
105+
if (endOfStream && (byteOffset != br.tailBytes)) {
106+
throw new BrotliRuntimeException("Unused bytes after end");
107+
}
108+
}
109+
110+
/**
111+
* Advances the Read buffer by 5 bytes to make room for reading next 24 bits.
112+
*/
113+
static void fillBitWindow(BitReader br) {
114+
if (br.bitOffset >= 32) {
115+
br.accumulator = ((long) br.intBuffer[br.intOffset++] << 32) | (br.accumulator >>> 32);
116+
br.bitOffset -= 32;
117+
}
118+
}
119+
120+
/**
121+
* Reads the specified number of bits from Read Buffer.
122+
*/
123+
static int readBits(BitReader br, int n) {
124+
fillBitWindow(br);
125+
int val = (int) (br.accumulator >>> br.bitOffset) & ((1 << n) - 1);
126+
br.bitOffset += n;
127+
return val;
128+
}
129+
130+
/**
131+
* Initialize bit reader.
132+
*
133+
* <p> Initialisation turns bit reader to a ready state. Also a number of bytes is prefetched to
134+
* accumulator. Because of that this method may block until enough data could be read from input.
135+
*
136+
* @param br BitReader POJO
137+
* @param input data source
138+
*/
139+
static void init(BitReader br, InputStream input) {
140+
if (br.input != null) {
141+
throw new IllegalStateException("Bit reader already has associated input stream");
142+
}
143+
IntReader.init(br.intReader, br.byteBuffer, br.intBuffer);
144+
br.input = input;
145+
br.accumulator = 0;
146+
br.bitOffset = 64;
147+
br.intOffset = CAPACITY;
148+
br.endOfStreamReached = false;
149+
prepare(br);
150+
}
151+
152+
private static void prepare(BitReader br) {
153+
readMoreInput(br);
154+
checkHealth(br, false);
155+
fillBitWindow(br);
156+
fillBitWindow(br);
157+
}
158+
159+
static void reload(BitReader br) {
160+
if (br.bitOffset == 64) {
161+
prepare(br);
162+
}
163+
}
164+
165+
static void close(BitReader br) throws IOException {
166+
InputStream is = br.input;
167+
br.input = null;
168+
if (is != null) {
169+
is.close();
170+
}
171+
}
172+
173+
static void jumpToByteBoundary(BitReader br) {
174+
int padding = (64 - br.bitOffset) & 7;
175+
if (padding != 0) {
176+
int paddingBits = BitReader.readBits(br, padding);
177+
if (paddingBits != 0) {
178+
throw new BrotliRuntimeException("Corrupted padding bits");
179+
}
180+
}
181+
}
182+
183+
static int intAvailable(BitReader br) {
184+
int limit = CAPACITY;
185+
if (br.endOfStreamReached) {
186+
limit = (br.tailBytes + 3) >> 2;
187+
}
188+
return limit - br.intOffset;
189+
}
190+
191+
static void copyBytes(BitReader br, byte[] data, int offset, int length) {
192+
if ((br.bitOffset & 7) != 0) {
193+
throw new BrotliRuntimeException("Unaligned copyBytes");
194+
}
195+
196+
// Drain accumulator.
197+
while ((br.bitOffset != 64) && (length != 0)) {
198+
data[offset++] = (byte) (br.accumulator >>> br.bitOffset);
199+
br.bitOffset += 8;
200+
length--;
201+
}
202+
if (length == 0) {
203+
return;
204+
}
205+
206+
// Get data from shadow buffer with "sizeof(int)" granularity.
207+
int copyInts = Math.min(intAvailable(br), length >> 2);
208+
if (copyInts > 0) {
209+
int readOffset = br.intOffset << 2;
210+
System.arraycopy(br.byteBuffer, readOffset, data, offset, copyInts << 2);
211+
offset += copyInts << 2;
212+
length -= copyInts << 2;
213+
br.intOffset += copyInts;
214+
}
215+
if (length == 0) {
216+
return;
217+
}
218+
219+
// Read tail bytes.
220+
if (intAvailable(br) > 0) {
221+
// length = 1..3
222+
fillBitWindow(br);
223+
while (length != 0) {
224+
data[offset++] = (byte) (br.accumulator >>> br.bitOffset);
225+
br.bitOffset += 8;
226+
length--;
227+
}
228+
checkHealth(br, false);
229+
return;
230+
}
231+
232+
// Now it is possible to copy bytes directly.
233+
try {
234+
while (length > 0) {
235+
int len = br.input.read(data, offset, length);
236+
if (len == -1) {
237+
throw new BrotliRuntimeException("Unexpected end of input");
238+
}
239+
offset += len;
240+
length -= len;
241+
}
242+
} catch (IOException e) {
243+
throw new BrotliRuntimeException("Failed to read input", e);
244+
}
245+
}
246+
}

0 commit comments

Comments
 (0)