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/awt_ImageRep.c
41159 views
1
/*
2
* Copyright (c) 1997, 2014, 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 <string.h>
27
28
#include "jni.h"
29
#include "jni_util.h"
30
#include "awt_parseImage.h"
31
#include "imageInitIDs.h"
32
#include "sun_awt_image_ImageRepresentation.h"
33
34
static int compareLUTs(unsigned int *lut1, int numLut1, int transIdx,
35
unsigned int *lut2, int numLut2, unsigned char *cvtLut,
36
int *retNumLut1, int *retTransIdx, int *jniFlagP);
37
38
static int findIdx(unsigned int rgb, unsigned int *lut, int numLut1);
39
40
#define ALPHA_MASK 0xff000000
41
#ifndef FALSE
42
# define FALSE 0
43
#endif
44
#ifndef TRUE
45
# define TRUE 1
46
#endif
47
48
#define CHECK_STRIDE(yy, hh, ss) \
49
if ((ss) != 0) { \
50
int limit = 0x7fffffff / ((ss) > 0 ? (ss) : -(ss)); \
51
if (limit < (yy) || limit < ((yy) + (hh) - 1)) { \
52
/* integer oveflow */ \
53
return JNI_FALSE; \
54
} \
55
} \
56
57
#define CHECK_SRC() \
58
do { \
59
int pixeloffset; \
60
if (off < 0 || off >= srcDataLength) { \
61
return JNI_FALSE; \
62
} \
63
CHECK_STRIDE(0, h, scansize); \
64
\
65
/* check scansize */ \
66
pixeloffset = scansize * (h - 1); \
67
if ((w - 1) > (0x7fffffff - pixeloffset)) { \
68
return JNI_FALSE; \
69
} \
70
pixeloffset += (w - 1); \
71
\
72
if (off > (0x7fffffff - pixeloffset)) { \
73
return JNI_FALSE; \
74
} \
75
} while (0) \
76
77
#define CHECK_DST(xx, yy) \
78
do { \
79
int soffset = (yy) * sStride; \
80
int poffset = (xx) * pixelStride; \
81
if (poffset > (0x7fffffff - soffset)) { \
82
return JNI_FALSE; \
83
} \
84
poffset += soffset; \
85
if (dstDataOff > (0x7fffffff - poffset)) { \
86
return JNI_FALSE; \
87
} \
88
poffset += dstDataOff; \
89
\
90
if (poffset < 0 || poffset >= dstDataLength) { \
91
return JNI_FALSE; \
92
} \
93
} while (0) \
94
95
static jfieldID s_JnumSrcLUTID;
96
static jfieldID s_JsrcLUTtransIndexID;
97
98
JNIEXPORT void JNICALL
99
Java_sun_awt_image_ImageRepresentation_initIDs(JNIEnv *env, jclass cls) {
100
CHECK_NULL(s_JnumSrcLUTID = (*env)->GetFieldID(env, cls, "numSrcLUT", "I"));
101
CHECK_NULL(s_JsrcLUTtransIndexID = (*env)->GetFieldID(env, cls,
102
"srcLUTtransIndex", "I"));
103
}
104
105
/*
106
* This routine is used to draw ICM pixels into a default color model
107
*/
108
JNIEXPORT jboolean JNICALL
109
Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls,
110
jint x, jint y, jint w,
111
jint h, jintArray jlut,
112
jbyteArray jpix, jint off,
113
jint scansize,
114
jobject jict)
115
{
116
unsigned char *srcData = NULL;
117
jint srcDataLength;
118
int *dstData;
119
jint dstDataLength;
120
jint dstDataOff;
121
int *dstP, *dstyP;
122
unsigned char *srcyP, *srcP;
123
int *srcLUT = NULL;
124
int yIdx, xIdx;
125
int sStride;
126
int *cOffs;
127
int pixelStride;
128
jobject joffs = NULL;
129
jobject jdata = NULL;
130
131
if (JNU_IsNull(env, jlut)) {
132
JNU_ThrowNullPointerException(env, "NullPointerException");
133
return JNI_FALSE;
134
}
135
136
if (JNU_IsNull(env, jpix)) {
137
JNU_ThrowNullPointerException(env, "NullPointerException");
138
return JNI_FALSE;
139
}
140
141
if (x < 0 || w < 1 || (0x7fffffff - x) < w) {
142
return JNI_FALSE;
143
}
144
145
if (y < 0 || h < 1 || (0x7fffffff - y) < h) {
146
return JNI_FALSE;
147
}
148
149
sStride = (*env)->GetIntField(env, jict, g_ICRscanstrID);
150
pixelStride = (*env)->GetIntField(env, jict, g_ICRpixstrID);
151
joffs = (*env)->GetObjectField(env, jict, g_ICRdataOffsetsID);
152
jdata = (*env)->GetObjectField(env, jict, g_ICRdataID);
153
154
if (JNU_IsNull(env, jdata)) {
155
/* no destination buffer */
156
return JNI_FALSE;
157
}
158
159
if (JNU_IsNull(env, joffs) || (*env)->GetArrayLength(env, joffs) < 1) {
160
/* invalid data offstes in raster */
161
return JNI_FALSE;
162
}
163
164
srcDataLength = (*env)->GetArrayLength(env, jpix);
165
dstDataLength = (*env)->GetArrayLength(env, jdata);
166
167
cOffs = (int *) (*env)->GetPrimitiveArrayCritical(env, joffs, NULL);
168
if (cOffs == NULL) {
169
(*env)->ExceptionClear(env);
170
JNU_ThrowNullPointerException(env, "Null channel offset array");
171
return JNI_FALSE;
172
}
173
174
dstDataOff = cOffs[0];
175
176
/* the offset array is not needed anymore and can be released */
177
(*env)->ReleasePrimitiveArrayCritical(env, joffs, cOffs, JNI_ABORT);
178
joffs = NULL;
179
cOffs = NULL;
180
181
/* do basic validation: make sure that offsets for
182
* first pixel and for last pixel are safe to calculate and use */
183
CHECK_STRIDE(y, h, sStride);
184
CHECK_STRIDE(x, w, pixelStride);
185
186
CHECK_DST(x, y);
187
CHECK_DST(x + w -1, y + h - 1);
188
189
/* check source array */
190
CHECK_SRC();
191
192
srcLUT = (int *) (*env)->GetPrimitiveArrayCritical(env, jlut, NULL);
193
if (srcLUT == NULL) {
194
(*env)->ExceptionClear(env);
195
JNU_ThrowNullPointerException(env, "Null IndexColorModel LUT");
196
return JNI_FALSE;
197
}
198
199
srcData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jpix,
200
NULL);
201
if (srcData == NULL) {
202
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT);
203
(*env)->ExceptionClear(env);
204
JNU_ThrowNullPointerException(env, "Null data array");
205
return JNI_FALSE;
206
}
207
208
dstData = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, NULL);
209
if (dstData == NULL) {
210
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT);
211
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
212
(*env)->ExceptionClear(env);
213
JNU_ThrowNullPointerException(env, "Null tile data array");
214
return JNI_FALSE;
215
}
216
217
dstyP = dstData + dstDataOff + y*sStride + x*pixelStride;
218
srcyP = srcData + off;
219
for (yIdx = 0; yIdx < h; yIdx++, srcyP += scansize, dstyP+=sStride) {
220
srcP = srcyP;
221
dstP = dstyP;
222
for (xIdx = 0; xIdx < w; xIdx++, dstP+=pixelStride) {
223
*dstP = srcLUT[*srcP++];
224
}
225
}
226
227
/* Release the locked arrays */
228
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT);
229
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
230
(*env)->ReleasePrimitiveArrayCritical(env, jdata, dstData, JNI_ABORT);
231
232
return JNI_TRUE;
233
}
234
235
JNIEXPORT jboolean JNICALL
236
Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
237
jint x, jint y, jint w,
238
jint h, jintArray jlut,
239
jint transIdx, jint numLut,
240
jobject jicm,
241
jbyteArray jpix, jint off,
242
jint scansize,
243
jobject jbct, jint dstDataOff)
244
{
245
unsigned int *srcLUT = NULL;
246
unsigned int *newLUT = NULL;
247
int sStride;
248
int pixelStride;
249
int mapSize;
250
jobject jdata = NULL;
251
jobject jnewlut = NULL;
252
jint srcDataLength;
253
jint dstDataLength;
254
unsigned char *srcData;
255
unsigned char *dstData;
256
unsigned char *dataP;
257
unsigned char *pixP;
258
int i;
259
int j;
260
int newNumLut;
261
int newTransIdx;
262
int jniFlag = JNI_ABORT;
263
unsigned char *ydataP;
264
unsigned char *ypixP;
265
unsigned char cvtLut[256];
266
267
if (JNU_IsNull(env, jlut)) {
268
JNU_ThrowNullPointerException(env, "NullPointerException");
269
return JNI_FALSE;
270
}
271
272
if (JNU_IsNull(env, jpix)) {
273
JNU_ThrowNullPointerException(env, "NullPointerException");
274
return JNI_FALSE;
275
}
276
277
if (x < 0 || w < 1 || (0x7fffffff - x) < w) {
278
return JNI_FALSE;
279
}
280
281
if (y < 0 || h < 1 || (0x7fffffff - y) < h) {
282
return JNI_FALSE;
283
}
284
285
286
sStride = (*env)->GetIntField(env, jbct, g_BCRscanstrID);
287
pixelStride =(*env)->GetIntField(env, jbct, g_BCRpixstrID);
288
jdata = (*env)->GetObjectField(env, jbct, g_BCRdataID);
289
jnewlut = (*env)->GetObjectField(env, jicm, g_ICMrgbID);
290
mapSize = (*env)->GetIntField(env, jicm, g_ICMmapSizeID);
291
292
if (numLut < 0 || numLut > 256 || mapSize < 0 || mapSize > 256) {
293
/* Ether old or new ICM has a palette that exceeds capacity
294
of byte data type, so we have to convert the image data
295
to default representation.
296
*/
297
return JNI_FALSE;
298
}
299
300
if (JNU_IsNull(env, jdata)) {
301
/* no destination buffer */
302
return JNI_FALSE;
303
}
304
305
srcDataLength = (*env)->GetArrayLength(env, jpix);
306
dstDataLength = (*env)->GetArrayLength(env, jdata);
307
308
CHECK_STRIDE(y, h, sStride);
309
CHECK_STRIDE(x, w, pixelStride);
310
311
CHECK_DST(x, y);
312
CHECK_DST(x + w -1, y + h - 1);
313
314
/* check source array */
315
CHECK_SRC();
316
317
srcLUT = (unsigned int *) (*env)->GetPrimitiveArrayCritical(env, jlut,
318
NULL);
319
if (srcLUT == NULL) {
320
/* out of memory error already thrown */
321
return JNI_FALSE;
322
}
323
324
newLUT = (unsigned int *) (*env)->GetPrimitiveArrayCritical(env, jnewlut,
325
NULL);
326
if (newLUT == NULL) {
327
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT,
328
JNI_ABORT);
329
/* out of memory error already thrown */
330
return JNI_FALSE;
331
}
332
333
newNumLut = numLut;
334
newTransIdx = transIdx;
335
if (compareLUTs(srcLUT, numLut, transIdx, newLUT, mapSize,
336
cvtLut, &newNumLut, &newTransIdx, &jniFlag) == FALSE) {
337
/* Need to convert to ICR */
338
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT,
339
JNI_ABORT);
340
(*env)->ReleasePrimitiveArrayCritical(env, jnewlut, newLUT, JNI_ABORT);
341
return JNI_FALSE;
342
}
343
344
/* Don't need these any more */
345
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, jniFlag);
346
(*env)->ReleasePrimitiveArrayCritical(env, jnewlut, newLUT, JNI_ABORT);
347
348
if (newNumLut != numLut) {
349
/* Need to write back new number of entries in lut */
350
(*env)->SetIntField(env, cls, s_JnumSrcLUTID, newNumLut);
351
}
352
353
if (newTransIdx != transIdx) {
354
(*env)->SetIntField(env, cls, s_JsrcLUTtransIndexID, newTransIdx);
355
}
356
357
srcData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jpix,
358
NULL);
359
if (srcData == NULL) {
360
/* out of memory error already thrown */
361
return JNI_FALSE;
362
}
363
364
dstData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jdata,
365
NULL);
366
if (dstData == NULL) {
367
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
368
/* out of memory error already thrown */
369
return JNI_FALSE;
370
}
371
372
ydataP = dstData + dstDataOff + y*sStride + x*pixelStride;
373
ypixP = srcData + off;
374
375
for (i=0; i < h; i++) {
376
dataP = ydataP;
377
pixP = ypixP;
378
for (j=0; j < w; j++) {
379
*dataP = cvtLut[*pixP];
380
dataP += pixelStride;
381
pixP++;
382
}
383
ydataP += sStride;
384
ypixP += scansize;
385
}
386
387
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
388
(*env)->ReleasePrimitiveArrayCritical(env, jdata, dstData, JNI_ABORT);
389
390
return JNI_TRUE;
391
}
392
393
static int compareLUTs(unsigned int *lut1, int numLut1, int transIdx,
394
unsigned int *lut2, int numLut2, unsigned char *cvtLut,
395
int *retNumLut1, int *retTransIdx, int *jniFlagP)
396
{
397
int i;
398
int idx;
399
int newTransIdx = -1;
400
unsigned int rgb;
401
int changed = FALSE;
402
int maxSize = (numLut1 > numLut2 ? numLut1 : numLut2);
403
404
*jniFlagP = JNI_ABORT;
405
406
for (i=0; i < maxSize; i++) {
407
cvtLut[i] = i;
408
}
409
410
for (i=0; i < numLut2; i++) {
411
/* If this slot in new palette is different from the
412
* same slot in current palette, then we try to find
413
* this color in other slots. On failure, add this color
414
* to current palette.
415
*/
416
if ((i >= numLut1) ||
417
(lut1[i] != lut2[i]))
418
{
419
rgb = lut2[i];
420
/* Transparent */
421
if ((rgb & ALPHA_MASK) == 0) {
422
if (transIdx == -1) {
423
if (numLut1 < 256) {
424
cvtLut[i] = numLut1;
425
newTransIdx = i;
426
transIdx = i;
427
numLut1++;
428
changed = TRUE;
429
}
430
else {
431
return FALSE;
432
}
433
}
434
cvtLut[i] = transIdx;
435
}
436
else {
437
if ((idx = findIdx(rgb, lut1, numLut1)) == -1) {
438
if (numLut1 < 256) {
439
lut1[numLut1] = rgb;
440
cvtLut[i] = numLut1;
441
numLut1++;
442
changed = TRUE;
443
}
444
else {
445
/* Bad news... need to convert image */
446
return FALSE;
447
}
448
} else {
449
cvtLut[i] = idx;
450
}
451
}
452
}
453
}
454
455
if (changed) {
456
*jniFlagP = 0;
457
*retNumLut1 = numLut1;
458
if (newTransIdx != -1) {
459
*retTransIdx = newTransIdx;
460
}
461
}
462
return TRUE;
463
}
464
465
static int findIdx(unsigned int rgb, unsigned int *lut, int numLut) {
466
int i;
467
468
if ((rgb&0xff000000)==0) {
469
for (i=0; i < numLut; i++) {
470
if ((lut[i]&0xff000000)==0) return i;
471
}
472
}
473
else {
474
for (i=0; i < numLut; i++) {
475
if (lut[i] == rgb) return i;
476
}
477
}
478
return -1;
479
}
480
481