Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.c
41149 views
1
/*
2
* Copyright (c) 2005, 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 "splashscreen_impl.h"
27
#include "splashscreen_gfx_impl.h"
28
#define BUFF_SIZE 1024
29
#ifdef _MSC_VER
30
# ifndef snprintf
31
# define snprintf _snprintf
32
# endif
33
#endif
34
int splashIsVisible = 0;
35
36
Splash *
37
SplashGetInstance()
38
{
39
static Splash splash;
40
static int preInitialized = 0;
41
if (!preInitialized) {
42
memset(&splash, 0, sizeof(Splash));
43
splash.currentFrame = -1;
44
preInitialized = 1;
45
}
46
return &splash;
47
}
48
49
JNIEXPORT void
50
SplashSetFileJarName(const char* fileName, const char* jarName) {
51
Splash *splash = SplashGetInstance();
52
53
free(splash->fileName);
54
splash->fileName = SplashConvertStringAlloc(fileName, &splash->fileNameLen);
55
56
free(splash->jarName);
57
splash->jarName = SplashConvertStringAlloc(jarName, &splash->jarNameLen);
58
}
59
60
JNIEXPORT int
61
SplashInit()
62
{
63
Splash *splash = SplashGetInstance();
64
65
memset(splash, 0, sizeof(Splash));
66
splash->currentFrame = -1;
67
splash->scaleFactor = 1;
68
initFormat(&splash->imageFormat, QUAD_RED_MASK, QUAD_GREEN_MASK,
69
QUAD_BLUE_MASK, QUAD_ALPHA_MASK);
70
return SplashInitPlatform(splash);
71
}
72
73
JNIEXPORT void
74
SplashClose()
75
{
76
Splash *splash = SplashGetInstance();
77
78
if (splash->isVisible > 0) {
79
SplashLock(splash);
80
splash->isVisible = -1;
81
SplashClosePlatform(splash);
82
SplashUnlock(splash);
83
}
84
}
85
86
void
87
SplashCleanup(Splash * splash)
88
{
89
int i;
90
91
splash->currentFrame = -1;
92
SplashCleanupPlatform(splash);
93
if (splash->frames) {
94
for (i = 0; i < splash->frameCount; i++) {
95
if (splash->frames[i].bitmapBits) {
96
free(splash->frames[i].bitmapBits);
97
splash->frames[i].bitmapBits = NULL;
98
}
99
}
100
free(splash->frames);
101
splash->frames = NULL;
102
}
103
if (splash->overlayData) {
104
free(splash->overlayData);
105
splash->overlayData = NULL;
106
}
107
SplashSetFileJarName(NULL, NULL);
108
}
109
110
JNIEXPORT void
111
SplashSetScaleFactor(float scaleFactor)
112
{
113
Splash *splash = SplashGetInstance();
114
splash->scaleFactor = scaleFactor;
115
}
116
117
void
118
SplashDone(Splash * splash)
119
{
120
SplashCleanup(splash);
121
SplashDonePlatform(splash);
122
}
123
124
int
125
SplashIsStillLooping(Splash * splash)
126
{
127
if (splash->currentFrame < 0) {
128
return 0;
129
}
130
return splash->loopCount != 1 ||
131
splash->currentFrame + 1 < splash->frameCount;
132
}
133
134
void
135
SplashUpdateScreenData(Splash * splash)
136
{
137
ImageRect srcRect, dstRect;
138
if (splash->currentFrame < 0) {
139
return;
140
}
141
142
initRect(&srcRect, 0, 0, splash->width, splash->height, 1,
143
splash->width * sizeof(rgbquad_t),
144
splash->frames[splash->currentFrame].bitmapBits, &splash->imageFormat);
145
if (splash->screenData) {
146
free(splash->screenData);
147
}
148
splash->screenStride = splash->width * splash->screenFormat.depthBytes;
149
if (splash->byteAlignment > 1) {
150
splash->screenStride =
151
(splash->screenStride + splash->byteAlignment - 1) &
152
~(splash->byteAlignment - 1);
153
}
154
splash->screenData = malloc(splash->height * splash->screenStride);
155
initRect(&dstRect, 0, 0, splash->width, splash->height, 1,
156
splash->screenStride, splash->screenData, &splash->screenFormat);
157
if (splash->overlayData) {
158
convertRect2(&srcRect, &dstRect, CVT_BLEND, &splash->overlayRect);
159
}
160
else {
161
convertRect(&srcRect, &dstRect, CVT_COPY);
162
}
163
}
164
165
void
166
SplashNextFrame(Splash * splash)
167
{
168
if (splash->currentFrame < 0) {
169
return;
170
}
171
do {
172
if (!SplashIsStillLooping(splash)) {
173
return;
174
}
175
splash->time += splash->frames[splash->currentFrame].delay;
176
if (++splash->currentFrame >= splash->frameCount) {
177
splash->currentFrame = 0;
178
if (splash->loopCount > 0) {
179
splash->loopCount--;
180
}
181
}
182
} while (splash->time + splash->frames[splash->currentFrame].delay -
183
SplashTime() <= 0);
184
}
185
186
int
187
BitmapToYXBandedRectangles(ImageRect * pSrcRect, RECT_T * out)
188
{
189
RECT_T *pPrevLine = NULL, *pFirst = out, *pThis = pFirst;
190
int i, j, i0;
191
int length;
192
193
for (j = 0; j < pSrcRect->numLines; j++) {
194
195
/* generate data for a scanline */
196
197
byte_t *pSrc = (byte_t *) pSrcRect->pBits + j * pSrcRect->stride;
198
RECT_T *pLine = pThis;
199
200
i = 0;
201
202
do {
203
while (i < pSrcRect->numSamples &&
204
getRGBA(pSrc, pSrcRect->format) < ALPHA_THRESHOLD) {
205
pSrc += pSrcRect->depthBytes;
206
++i;
207
}
208
if (i >= pSrcRect->numSamples) {
209
break;
210
}
211
i0 = i;
212
while (i < pSrcRect->numSamples &&
213
getRGBA(pSrc, pSrcRect->format) >= ALPHA_THRESHOLD) {
214
pSrc += pSrcRect->depthBytes;
215
++i;
216
}
217
RECT_SET(*pThis, i0, j, i - i0, 1);
218
++pThis;
219
} while (i < pSrcRect->numSamples);
220
221
/* check if the previous scanline is exactly the same, merge if so
222
(this is the only optimization we can use for YXBanded rectangles, and win32 supports
223
YXBanded only */
224
225
length = pThis - pLine;
226
if (pPrevLine && pLine - pPrevLine == length) {
227
for (i = 0; i < length && RECT_EQ_X(pPrevLine[i], pLine[i]); ++i) {
228
}
229
if (i == pLine - pPrevLine) {
230
// do merge
231
for (i = 0; i < length; i++) {
232
RECT_INC_HEIGHT(pPrevLine[i]);
233
}
234
pThis = pLine;
235
continue;
236
}
237
}
238
/* or else use the generated scanline */
239
240
pPrevLine = pLine;
241
}
242
return pThis - pFirst;
243
}
244
245
typedef struct FILEFORMAT
246
{
247
int sign;
248
int (*decodeStream) (Splash * splash, SplashStream * stream);
249
} FILEFORMAT;
250
251
static const FILEFORMAT formats[] = {
252
{0x47, SplashDecodeGifStream},
253
{0x89, SplashDecodePngStream},
254
{0xFF, SplashDecodeJpegStream}
255
};
256
257
static int
258
SplashLoadStream(SplashStream * stream)
259
{
260
int success = 0;
261
int c;
262
size_t i;
263
264
Splash *splash = SplashGetInstance();
265
if (splash->isVisible < 0) {
266
stream->close(stream);
267
return 0;
268
}
269
270
SplashLock(splash);
271
272
/* the formats we support can be easily distinguished by the first byte */
273
c = stream->peek(stream);
274
if (c != -1) {
275
for (i = 0; i < sizeof(formats) / sizeof(FILEFORMAT); i++) {
276
if (c == formats[i].sign) {
277
success = formats[i].decodeStream(splash, stream);
278
break;
279
}
280
}
281
}
282
stream->close(stream);
283
284
if (!success) { // failed to decode
285
if (splash->isVisible == 0) {
286
SplashCleanup(splash);
287
}
288
SplashUnlock(splash); // SplashClose locks
289
if (splash->isVisible == 0) {
290
SplashClose();
291
}
292
}
293
else {
294
splash->currentFrame = 0;
295
if (splash->isVisible == 0) {
296
SplashStart(splash);
297
} else {
298
SplashReconfigure(splash);
299
splash->time = SplashTime();
300
}
301
SplashUnlock(splash);
302
}
303
return success;
304
}
305
306
JNIEXPORT int
307
SplashLoadFile(const char *filename)
308
{
309
SplashStream stream;
310
return SplashStreamInitFile(&stream, filename) &&
311
SplashLoadStream(&stream);
312
}
313
314
JNIEXPORT int
315
SplashLoadMemory(void *data, int size)
316
{
317
SplashStream stream;
318
return SplashStreamInitMemory(&stream, data, size) &&
319
SplashLoadStream(&stream);
320
}
321
322
/* SplashStart MUST be called from under the lock */
323
324
void
325
SplashStart(Splash * splash)
326
{
327
if (splash->isVisible == 0) {
328
SplashCreateThread(splash);
329
splash->isVisible = 1;
330
}
331
}
332
333
/* SplashStream functions */
334
335
static int readFile(void* pStream, void* pData, int nBytes) {
336
FILE* f = ((SplashStream*)pStream)->arg.stdio.f;
337
return fread(pData, 1, nBytes, f);
338
}
339
static int peekFile(void* pStream) {
340
FILE* f = ((SplashStream*)pStream)->arg.stdio.f;
341
int c = fgetc(f);
342
if (c != EOF) {
343
ungetc(c, f);
344
return c;
345
} else {
346
return -1;
347
}
348
}
349
350
static void closeFile(void* pStream) {
351
FILE* f = ((SplashStream*)pStream)->arg.stdio.f;
352
fclose(f);
353
}
354
355
static int readMem(void* pStream, void* pData, int nBytes) {
356
unsigned char* pSrc = (unsigned char*)(((SplashStream*)pStream)->arg.mem.pData);
357
unsigned char* pSrcEnd = (unsigned char*)(((SplashStream*)pStream)->arg.mem.pDataEnd);
358
if (nBytes > pSrcEnd - pSrc) {
359
nBytes = pSrcEnd - pSrc;
360
}
361
if (nBytes>0) {
362
memcpy(pData, pSrc, nBytes);
363
pSrc += nBytes;
364
((SplashStream*)pStream)->arg.mem.pData = (void*)pSrc;
365
}
366
return nBytes;
367
}
368
369
static int peekMem(void* pStream) {
370
unsigned char* pSrc = (unsigned char*)(((SplashStream*)pStream)->arg.mem.pData);
371
unsigned char* pSrcEnd = (unsigned char*)(((SplashStream*)pStream)->arg.mem.pDataEnd);
372
if (pSrc >= pSrcEnd) {
373
return -1;
374
} else {
375
return (int)*pSrc;
376
}
377
}
378
379
static void closeMem(void* pStream) {
380
}
381
382
int SplashStreamInitFile(SplashStream * pStream, const char* filename) {
383
pStream->arg.stdio.f = fopen(filename, "rb");
384
pStream->read = readFile;
385
pStream->peek = peekFile;
386
pStream->close = closeFile;
387
return pStream->arg.stdio.f != 0;
388
}
389
390
int SplashStreamInitMemory(SplashStream * pStream, void* pData, int size) {
391
pStream->arg.mem.pData = (unsigned char*)pData;
392
pStream->arg.mem.pDataEnd = (unsigned char*)pData + size;
393
pStream->read = readMem;
394
pStream->peek = peekMem;
395
pStream->close = closeMem;
396
return 1;
397
}
398
399
JNIEXPORT int
400
SplashGetScaledImgNameMaxPstfixLen(const char *fileName){
401
return strlen(fileName) + strlen("@100pct") + 1;
402
}
403
404
jboolean GetScaledImageName(const char *fileName, char *scaleImageName,
405
float *scaleFactor, const size_t scaledImageLength) {
406
if (*scaleFactor > 1.0) {
407
FILE *fp = NULL;
408
char scaledImgPct[BUFF_SIZE];
409
char scaledImgX[BUFF_SIZE];
410
char *scaledImageXName = NULL;
411
char *scaledImagePctName = malloc(scaledImageLength);
412
char *dupFileName = strdup(fileName);
413
char *fileExtension = strrchr(dupFileName, '.');
414
size_t lengthPct = 0;
415
size_t lengthX = 0;
416
int retValPct = 0;
417
int retValX = 0;
418
jboolean isPctScaledImage = (*scaleFactor * 100) != ((int) (*scaleFactor)) *100;
419
snprintf(scaledImgPct, BUFF_SIZE, "%s%d%s", "@",
420
(int) (*scaleFactor * 100), "pct");
421
if (!isPctScaledImage) {
422
scaledImageXName = malloc(scaledImageLength);
423
snprintf(scaledImgX, BUFF_SIZE, "%s%d%s", "@", (int) (*scaleFactor), "x");
424
}
425
/*File is missing extension */
426
if (fileExtension == NULL) {
427
lengthPct = strlen(dupFileName) +
428
strlen(scaledImgPct) + 1;
429
if (!isPctScaledImage) {
430
lengthX = strlen(dupFileName) +
431
strlen(scaledImgX) + 1;
432
}
433
if (lengthPct > scaledImageLength || lengthX > scaledImageLength) {
434
cleanUp(dupFileName, scaledImageXName, scaledImagePctName, scaleFactor);
435
return JNI_FALSE;
436
}
437
retValPct = snprintf(scaledImagePctName, lengthPct, "%s%s", dupFileName,
438
scaledImgPct);
439
if (!isPctScaledImage) {
440
retValX = snprintf(scaledImageXName, lengthX, "%s%s", dupFileName,
441
scaledImgX);
442
}
443
if ((retValPct < 0 || (retValPct > lengthPct - 1)) ||
444
(retValX < 0 || (retValX > lengthX - 1))) {
445
cleanUp(dupFileName, scaledImageXName, scaledImagePctName, scaleFactor);
446
return JNI_FALSE;
447
}
448
} else {
449
int length_Without_Ext = fileExtension - dupFileName;
450
lengthPct = length_Without_Ext + strlen(scaledImgPct) +
451
strlen(fileExtension) + 1;
452
if (!isPctScaledImage) {
453
lengthX = length_Without_Ext + strlen(scaledImgX) +
454
strlen(fileExtension) + 1;
455
}
456
if (lengthPct > scaledImageLength || lengthX > scaledImageLength) {
457
cleanUp(dupFileName, scaledImageXName, scaledImagePctName, scaleFactor);
458
return JNI_FALSE;
459
}
460
retValPct = snprintf(scaledImagePctName, lengthPct, "%.*s%s%s",
461
length_Without_Ext, dupFileName, scaledImgPct, fileExtension);
462
if (!isPctScaledImage) {
463
retValX = snprintf(scaledImageXName, lengthX, "%.*s%s%s",
464
length_Without_Ext, dupFileName, scaledImgX, fileExtension);
465
}
466
if ((retValPct < 0 || (retValPct > lengthPct - 1)) ||
467
(retValX < 0 || (retValX > lengthX - 1))) {
468
cleanUp(dupFileName, scaledImageXName, scaledImagePctName, scaleFactor);
469
return JNI_FALSE;
470
}
471
}
472
free(dupFileName);
473
if (!(fp = fopen(scaledImagePctName, "r"))) {
474
if (!isPctScaledImage && (fp = fopen(scaledImageXName, "r"))) {
475
fclose(fp);
476
strcpy(scaleImageName, scaledImageXName);
477
free(scaledImageXName);
478
free(scaledImagePctName);
479
return JNI_TRUE;
480
}
481
cleanUp(NULL, scaledImageXName, scaledImagePctName, scaleFactor);
482
return JNI_FALSE;
483
}
484
fclose(fp);
485
strcpy(scaleImageName, scaledImagePctName);
486
free(scaledImageXName);
487
free(scaledImagePctName);
488
return JNI_TRUE;
489
}
490
return JNI_FALSE;
491
}
492
493
void cleanUp(char *fName, char *xName, char *pctName, float *scaleFactor) {
494
*scaleFactor = 1;
495
free(fName);
496
free(xName);
497
free(pctName);
498
}
499
500