Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/native/libawt/awt/image/gif/gifdecoder.c
41161 views
1
/*
2
* Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
#include <stdio.h>
27
#include "jni.h"
28
#include "jni_util.h"
29
30
#define OUTCODELENGTH 4097
31
32
/* We use Get/ReleasePrimitiveArrayCritical functions to avoid
33
* the need to copy buffer elements.
34
*
35
* MAKE SURE TO:
36
*
37
* - carefully insert pairs of RELEASE_ARRAYS and GET_ARRAYS around
38
* callbacks to Java.
39
* - call RELEASE_ARRAYS before returning to Java.
40
*
41
* Otherwise things will go horribly wrong. There may be memory leaks,
42
* excessive pinning, or even VM crashes!
43
*
44
* Note that GetPrimitiveArrayCritical may fail!
45
*/
46
47
#define GET_ARRAYS() \
48
prefix = (short *) \
49
(*env)->GetPrimitiveArrayCritical(env, prefixh, 0); \
50
if (prefix == 0) \
51
goto out_of_memory; \
52
suffix = (unsigned char *) \
53
(*env)->GetPrimitiveArrayCritical(env, suffixh, 0); \
54
if (suffix == 0) \
55
goto out_of_memory; \
56
outCode = (unsigned char *) \
57
(*env)->GetPrimitiveArrayCritical(env, outCodeh, 0); \
58
if (outCode == 0) \
59
goto out_of_memory; \
60
rasline = (unsigned char *) \
61
(*env)->GetPrimitiveArrayCritical(env, raslineh, 0); \
62
if (rasline == 0) \
63
goto out_of_memory; \
64
block = (unsigned char *) \
65
(*env)->GetPrimitiveArrayCritical(env, blockh, 0); \
66
if (block == 0) \
67
goto out_of_memory
68
69
/*
70
* Note that it is important to check whether the arrays are NULL,
71
* because GetPrimitiveArrayCritical might have failed.
72
*/
73
#define RELEASE_ARRAYS() \
74
if (prefix) \
75
(*env)->ReleasePrimitiveArrayCritical(env, prefixh, prefix, 0); \
76
if (suffix) \
77
(*env)->ReleasePrimitiveArrayCritical(env, suffixh, suffix, 0); \
78
if (outCode) \
79
(*env)->ReleasePrimitiveArrayCritical(env, outCodeh, outCode, 0); \
80
if (rasline) \
81
(*env)->ReleasePrimitiveArrayCritical(env, raslineh, rasline, 0); \
82
if (block) \
83
(*env)->ReleasePrimitiveArrayCritical(env, blockh, block, 0)
84
85
/* Place holders for the old native interface. */
86
87
long
88
sun_awt_image_GifImageDecoder_parseImage()
89
{
90
return 0;
91
}
92
93
void
94
sun_awt_image_GifImageDecoder_initIDs()
95
{
96
}
97
98
static jmethodID readID;
99
static jmethodID sendID;
100
static jfieldID prefixID;
101
static jfieldID suffixID;
102
static jfieldID outCodeID;
103
104
JNIEXPORT void JNICALL
105
Java_sun_awt_image_GifImageDecoder_initIDs(JNIEnv *env, jclass this)
106
{
107
CHECK_NULL(readID = (*env)->GetMethodID(env, this, "readBytes", "([BII)I"));
108
CHECK_NULL(sendID = (*env)->GetMethodID(env, this, "sendPixels",
109
"(IIII[BLjava/awt/image/ColorModel;)I"));
110
CHECK_NULL(prefixID = (*env)->GetFieldID(env, this, "prefix", "[S"));
111
CHECK_NULL(suffixID = (*env)->GetFieldID(env, this, "suffix", "[B"));
112
CHECK_NULL(outCodeID = (*env)->GetFieldID(env, this, "outCode", "[B"));
113
}
114
115
JNIEXPORT jboolean JNICALL
116
Java_sun_awt_image_GifImageDecoder_parseImage(JNIEnv *env,
117
jobject this,
118
jint relx, jint rely,
119
jint width, jint height,
120
jboolean interlace,
121
jint initCodeSize,
122
jbyteArray blockh,
123
jbyteArray raslineh,
124
jobject cmh)
125
{
126
/* Patrick Naughton:
127
* Note that I ignore the possible existence of a local color map.
128
* I'm told there aren't many files around that use them, and the
129
* spec says it's defined for future use. This could lead to an
130
* error reading some files.
131
*
132
* Start reading the image data. First we get the intial code size
133
* and compute decompressor constant values, based on this code
134
* size.
135
*
136
* The GIF spec has it that the code size is the code size used to
137
* compute the above values is the code size given in the file,
138
* but the code size used in compression/decompression is the code
139
* size given in the file plus one. (thus the ++).
140
*
141
* Arthur van Hoff:
142
* The following narly code reads LZW compressed data blocks and
143
* dumps it into the image data. The input stream is broken up into
144
* blocks of 1-255 characters, each preceded by a length byte.
145
* 3-12 bit codes are read from these blocks. The codes correspond to
146
* entry is the hashtable (the prefix, suffix stuff), and the appropriate
147
* pixels are written to the image.
148
*/
149
static int verbose = 0;
150
151
int clearCode = (1 << initCodeSize);
152
int eofCode = clearCode + 1;
153
int bitMask;
154
int curCode;
155
int outCount;
156
157
/* Variables used to form reading data */
158
int blockEnd = 0;
159
int remain = 0;
160
int byteoff = 0;
161
int accumbits = 0;
162
int accumdata = 0;
163
164
/* Variables used to decompress the data */
165
int codeSize = initCodeSize + 1;
166
int maxCode = 1 << codeSize;
167
int codeMask = maxCode - 1;
168
int freeCode = clearCode + 2;
169
int code = 0;
170
int oldCode = 0;
171
unsigned char prevChar = 0;
172
173
/* Temproray storage for decompression */
174
short *prefix;
175
unsigned char *suffix = NULL;
176
unsigned char *outCode = NULL;
177
unsigned char *rasline = NULL;
178
unsigned char *block = NULL;
179
180
jshortArray prefixh = (*env)->GetObjectField(env, this, prefixID);
181
jbyteArray suffixh = (*env)->GetObjectField(env, this, suffixID);
182
jbyteArray outCodeh = (*env)->GetObjectField(env, this, outCodeID);
183
184
int blockLength = 0;
185
186
/* Variables used for writing pixels */
187
int x = width;
188
int y = 0;
189
int off = 0;
190
int passinc = interlace ? 8 : 1;
191
int passht = passinc;
192
int len;
193
194
/* We have verified the initial code size on the java layer.
195
* Here we just check bounds for particular indexes. */
196
if (freeCode >= 4096 || maxCode >= 4096) {
197
return 0;
198
}
199
if (blockh == 0 || raslineh == 0
200
|| prefixh == 0 || suffixh == 0
201
|| outCodeh == 0)
202
{
203
JNU_ThrowNullPointerException(env, 0);
204
return 0;
205
}
206
if (((*env)->GetArrayLength(env, prefixh) != 4096) ||
207
((*env)->GetArrayLength(env, suffixh) != 4096) ||
208
((*env)->GetArrayLength(env, outCodeh) != OUTCODELENGTH))
209
{
210
JNU_ThrowArrayIndexOutOfBoundsException(env, 0);
211
return 0;
212
}
213
214
if (verbose) {
215
fprintf(stdout, "Decompressing...");
216
}
217
218
/* Fix for bugid 4216605 Some animated GIFs display corrupted. */
219
bitMask = clearCode - 1;
220
221
GET_ARRAYS();
222
223
/* Read codes until the eofCode is encountered */
224
for (;;) {
225
if (accumbits < codeSize) {
226
/* fill the buffer if needed */
227
while (remain < 2) {
228
if (blockEnd) {
229
/* Sometimes we have one last byte to process... */
230
if (remain == 1 && accumbits + 8 >= codeSize) {
231
remain--;
232
goto last_byte;
233
}
234
RELEASE_ARRAYS();
235
if (off > 0) {
236
(*env)->CallIntMethod(env, this, sendID,
237
relx, rely + y,
238
width, passht,
239
raslineh, cmh);
240
}
241
/* quietly accept truncated GIF images */
242
return 1;
243
}
244
/* move remaining bytes to the beginning of the buffer */
245
block[0] = block[byteoff];
246
byteoff = 0;
247
248
RELEASE_ARRAYS();
249
/* fill the block */
250
len = (*env)->CallIntMethod(env, this, readID,
251
blockh, remain, blockLength + 1);
252
if (len > blockLength + 1) len = blockLength + 1;
253
if ((*env)->ExceptionOccurred(env)) {
254
return 0;
255
}
256
GET_ARRAYS();
257
258
remain += blockLength;
259
if (len > 0) {
260
remain -= (len - 1);
261
blockLength = 0;
262
} else {
263
blockLength = block[remain];
264
}
265
if (blockLength == 0) {
266
blockEnd = 1;
267
}
268
}
269
remain -= 2;
270
271
/* 2 bytes at a time saves checking for accumbits < codeSize.
272
* We know we'll get enough and also that we can't overflow
273
* since codeSize <= 12.
274
*/
275
accumdata += (block[byteoff++] & 0xff) << accumbits;
276
accumbits += 8;
277
last_byte:
278
accumdata += (block[byteoff++] & 0xff) << accumbits;
279
accumbits += 8;
280
}
281
282
/* Compute the code */
283
code = accumdata & codeMask;
284
accumdata >>= codeSize;
285
accumbits -= codeSize;
286
287
/*
288
* Interpret the code
289
*/
290
if (code == clearCode) {
291
/* Clear code sets everything back to its initial value, then
292
* reads the immediately subsequent code as uncompressed data.
293
*/
294
if (verbose) {
295
RELEASE_ARRAYS();
296
fprintf(stdout, ".");
297
fflush(stdout);
298
GET_ARRAYS();
299
}
300
301
/* Note that freeCode is one less than it is supposed to be,
302
* this is because it will be incremented next time round the loop
303
*/
304
freeCode = clearCode + 1;
305
codeSize = initCodeSize + 1;
306
maxCode = 1 << codeSize;
307
codeMask = maxCode - 1;
308
309
/* Continue if we've NOT reached the end, some Gif images
310
* contain bogus codes after the last clear code.
311
*/
312
if (y < height) {
313
continue;
314
}
315
316
/* pretend we've reached the end of the data */
317
code = eofCode;
318
}
319
320
if (code == eofCode) {
321
/* make sure we read the whole block of pixels. */
322
flushit:
323
while (!blockEnd) {
324
RELEASE_ARRAYS();
325
if (verbose) {
326
fprintf(stdout, "flushing %d bytes\n", blockLength);
327
}
328
if ((*env)->CallIntMethod(env, this, readID,
329
blockh, 0, blockLength + 1) != 0
330
|| (*env)->ExceptionOccurred(env))
331
{
332
/* quietly accept truncated GIF images */
333
return (!(*env)->ExceptionOccurred(env));
334
}
335
GET_ARRAYS();
336
blockLength = block[blockLength];
337
blockEnd = (blockLength == 0);
338
}
339
RELEASE_ARRAYS();
340
return 1;
341
}
342
343
/* It must be data: save code in CurCode */
344
curCode = code;
345
outCount = OUTCODELENGTH;
346
347
/* If greater or equal to freeCode, not in the hash table
348
* yet; repeat the last character decoded
349
*/
350
if (curCode >= freeCode) {
351
if (curCode > freeCode) {
352
/*
353
* if we get a code too far outside our range, it
354
* could case the parser to start traversing parts
355
* of our data structure that are out of range...
356
*/
357
goto flushit;
358
}
359
curCode = oldCode;
360
outCode[--outCount] = prevChar;
361
}
362
363
/* Unless this code is raw data, pursue the chain pointed
364
* to by curCode through the hash table to its end; each
365
* code in the chain puts its associated output code on
366
* the output queue.
367
*/
368
while (curCode > bitMask) {
369
outCode[--outCount] = suffix[curCode];
370
if (outCount == 0) {
371
/*
372
* In theory this should never happen since our
373
* prefix and suffix arrays are monotonically
374
* decreasing and so outCode will only be filled
375
* as much as those arrays, but I don't want to
376
* take that chance and the test is probably
377
* cheap compared to the read and write operations.
378
* If we ever do overflow the array, we will just
379
* flush the rest of the data and quietly accept
380
* the GIF as truncated here.
381
*/
382
goto flushit;
383
}
384
curCode = prefix[curCode];
385
}
386
387
/* The last code in the chain is treated as raw data. */
388
prevChar = (unsigned char)curCode;
389
outCode[--outCount] = prevChar;
390
391
/* Now we put the data out to the Output routine. It's
392
* been stacked LIFO, so deal with it that way...
393
*
394
* Note that for some malformed images we have to skip
395
* current frame and continue with rest of data
396
* because we may have not enough info to interpret
397
* corrupted frame correctly.
398
* However, we can not skip frame without decoding it
399
* and therefore we have to continue looping through data
400
* but skip internal output loop.
401
*
402
* In particular this is possible when
403
* width of the frame is set to zero. If
404
* global width (i.e. width of the logical screen)
405
* is zero too then zero-length scanline buffer
406
* is allocated in java code and we have no buffer to
407
* store decoded data in.
408
*/
409
len = OUTCODELENGTH - outCount;
410
while ((width > 0) && (--len >= 0)) {
411
rasline[off++] = outCode[outCount++];
412
413
/* Update the X-coordinate, and if it overflows, update the
414
* Y-coordinate
415
*/
416
if (--x == 0) {
417
/* If a non-interlaced picture, just increment y to the next
418
* scan line. If it's interlaced, deal with the interlace as
419
* described in the GIF spec. Put the decoded scan line out
420
* to the screen if we haven't gone past the bottom of it
421
*/
422
int count;
423
RELEASE_ARRAYS();
424
count = (*env)->CallIntMethod(env, this, sendID,
425
relx, rely + y,
426
width, passht,
427
raslineh, cmh);
428
if (count <= 0 || (*env)->ExceptionOccurred(env)) {
429
/* Nobody is listening any more. */
430
if (verbose) {
431
fprintf(stdout, "Orphan gif decoder quitting\n");
432
}
433
return 0;
434
}
435
GET_ARRAYS();
436
x = width;
437
off = 0;
438
/* pass inc ht ystart */
439
/* 0 8 8 0 */
440
/* 1 8 4 4 */
441
/* 2 4 2 2 */
442
/* 3 2 1 1 */
443
y += passinc;
444
while (y >= height) {
445
passinc = passht;
446
passht >>= 1;
447
y = passht;
448
if (passht == 0) {
449
goto flushit;
450
}
451
}
452
}
453
}
454
455
/* Build the hash table on-the-fly. No table is stored in the file. */
456
prefix[freeCode] = (short)oldCode;
457
suffix[freeCode] = prevChar;
458
oldCode = code;
459
460
/* Point to the next slot in the table. If we exceed the
461
* maxCode, increment the code size unless
462
* it's already 12. If it is, do nothing: the next code
463
* decompressed better be CLEAR
464
*/
465
if (++freeCode >= maxCode) {
466
if (codeSize < 12) {
467
codeSize++;
468
maxCode <<= 1;
469
codeMask = maxCode - 1;
470
} else {
471
/* Just in case */
472
freeCode = maxCode - 1;
473
}
474
}
475
}
476
out_of_memory:
477
RELEASE_ARRAYS();
478
return 0;
479
}
480
481