Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/native/libsplashscreen/splashscreen_gfx_impl.h
41149 views
1
/*
2
* Copyright (c) 2005, 2010, 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
#ifndef SPLASHSCREEN_GFX_IMPL_H
27
#define SPLASHSCREEN_GFX_IMPL_H
28
29
#include "splashscreen_gfx.h"
30
31
/* here come some very simple macros */
32
33
/* advance a pointer p by sizeof(type)*n bytes */
34
#define INCPN(type,p,n) ((p) = (type*)(p)+(n))
35
36
/* advance a pointer by sizeof(type) */
37
#define INCP(type,p) INCPN(type,(p),1)
38
39
/* store a typed value to pointed location */
40
#define PUT(type,p,v) (*(type*)(p) = (type)(v))
41
42
/* load a typed value from pointed location */
43
#define GET(type,p) (*(type*)p)
44
45
/* same as cond<0?-1:0 */
46
enum
47
{
48
IFNEG_SHIFT_BITS = sizeof(int) * 8 - 1
49
};
50
51
#define IFNEG(cond) ((int)(cond)>>IFNEG_SHIFT_BITS)
52
53
/* same as cond<0?n1:n2 */
54
#define IFNEGPOS(cond,n1,n2) ((IFNEG(cond)&(n1))|((~IFNEG(cond))&(n2)))
55
56
/* value shifted left by n bits, negative n is allowed */
57
#define LSHIFT(value,n) IFNEGPOS((n),(value)>>-(n),(value)<<(n))
58
59
/* value shifted right by n bits, negative n is allowed */
60
#define RSHIFT(value,n) IFNEGPOS(n,(value)<<-(n),(value)>>(n))
61
62
/* converts a single i'th component to the specific format defined by format->shift[i] and format->mask[i] */
63
#define CONVCOMP(quad,format,i) \
64
(LSHIFT((quad),(format)->shift[i])&(format)->mask[i])
65
66
/* extracts the component defined by format->shift[i] and format->mask[i] from a specific-format value */
67
#define UNCONVCOMP(value,format,i) \
68
(RSHIFT((value)&(format)->mask[i],(format)->shift[i]))
69
70
/* dithers the color using the dither matrices and colormap from format
71
indices to dither matrices are passed as arguments */
72
INLINE unsigned
73
ditherColor(rgbquad_t value, ImageFormat * format, int row, int col)
74
{
75
int blue = QUAD_BLUE(value);
76
int green = QUAD_GREEN(value);
77
int red = QUAD_RED(value);
78
79
blue = format->dithers[0].colorTable[blue +
80
format->dithers[0].matrix[col & DITHER_MASK][row & DITHER_MASK]];
81
green = format->dithers[1].colorTable[green +
82
format->dithers[1].matrix[col & DITHER_MASK][row & DITHER_MASK]];
83
red = format->dithers[2].colorTable[red +
84
format->dithers[2].matrix[col & DITHER_MASK][row & DITHER_MASK]];
85
return red + green + blue;
86
}
87
88
/* blend (lerp between) two rgb quads
89
src and dst alpha is ignored
90
the algorithm: src*alpha+dst*(1-alpha)=(src-dst)*alpha+dst, rb and g are done separately
91
*/
92
INLINE rgbquad_t
93
blendRGB(rgbquad_t dst, rgbquad_t src, rgbquad_t alpha)
94
{
95
const rgbquad_t a = alpha;
96
const rgbquad_t a1 = 0xFF - alpha;
97
98
return MAKE_QUAD(
99
(rgbquad_t)((QUAD_RED(src) * a + QUAD_RED(dst) * a1) / 0xFF),
100
(rgbquad_t)((QUAD_GREEN(src) * a + QUAD_GREEN(dst) * a1) / 0xFF),
101
(rgbquad_t)((QUAD_BLUE(src) * a + QUAD_BLUE(dst) * a1) / 0xFF),
102
0);
103
}
104
105
/* scales rgb quad by alpha. basically similar to what's above. src alpha is retained.
106
used for premultiplying alpha
107
108
btw: braindead MSVC6 generates _three_ mul instructions for this function */
109
110
INLINE rgbquad_t
111
premultiplyRGBA(rgbquad_t src)
112
{
113
rgbquad_t srb = src & 0xFF00FF;
114
rgbquad_t sg = src & 0xFF00;
115
rgbquad_t alpha = src >> QUAD_ALPHA_SHIFT;
116
117
alpha += 1;
118
119
srb *= alpha;
120
sg *= alpha;
121
srb >>= 8;
122
sg >>= 8;
123
124
return (src & 0xFF000000) | (srb & 0xFF00FF) | (sg & 0xFF00);
125
}
126
127
/* The functions below are inherently ineffective, but the performance seems to be
128
more or less adequate for the case of splash screens. They can be optimized later
129
if needed. The idea of optimization is to provide inlineable form of putRGBADither and
130
getRGBA at least for certain most frequently used visuals. Something like this is
131
done in Java 2D ("loops"). This would be possible with C++ templates, but making it
132
clean for C would require ugly preprocessor tricks. Leaving it out for later.
133
*/
134
135
/* convert a single pixel color value from rgbquad according to visual format
136
and place it to pointed location
137
ordered dithering used when necessary */
138
INLINE void
139
putRGBADither(rgbquad_t value, void *ptr, ImageFormat * format,
140
int row, int col)
141
{
142
if (format->premultiplied) {
143
value = premultiplyRGBA(value);
144
}
145
if (format->dithers) {
146
value = format->colorIndex[ditherColor(value, format, row, col)];
147
}
148
else {
149
value = CONVCOMP(value, format, 0) | CONVCOMP(value, format, 1) |
150
CONVCOMP(value, format, 2) | CONVCOMP(value, format, 3);
151
}
152
switch (format->byteOrder) {
153
case BYTE_ORDER_LSBFIRST:
154
switch (format->depthBytes) { /* lack of *break*'s is intentional */
155
case 4:
156
PUT(byte_t, ptr, value & 0xff);
157
value >>= 8;
158
INCP(byte_t, ptr);
159
case 3:
160
PUT(byte_t, ptr, value & 0xff);
161
value >>= 8;
162
INCP(byte_t, ptr);
163
case 2:
164
PUT(byte_t, ptr, value & 0xff);
165
value >>= 8;
166
INCP(byte_t, ptr);
167
case 1:
168
PUT(byte_t, ptr, value & 0xff);
169
}
170
break;
171
case BYTE_ORDER_MSBFIRST:
172
switch (format->depthBytes) { /* lack of *break*'s is intentional */
173
case 4:
174
PUT(byte_t, ptr, (value >> 24) & 0xff);
175
INCP(byte_t, ptr);
176
case 3:
177
PUT(byte_t, ptr, (value >> 16) & 0xff);
178
INCP(byte_t, ptr);
179
case 2:
180
PUT(byte_t, ptr, (value >> 8) & 0xff);
181
INCP(byte_t, ptr);
182
case 1:
183
PUT(byte_t, ptr, value & 0xff);
184
}
185
break;
186
case BYTE_ORDER_NATIVE:
187
switch (format->depthBytes) {
188
case 4:
189
PUT(rgbquad_t, ptr, value);
190
break;
191
case 3: /* not supported, LSB or MSB should always be specified */
192
PUT(byte_t, ptr, 0xff); /* Put a stub value */
193
INCP(byte_t, ptr);
194
PUT(byte_t, ptr, 0xff);
195
INCP(byte_t, ptr);
196
PUT(byte_t, ptr, 0xff);
197
break;
198
case 2:
199
PUT(word_t, ptr, value);
200
break;
201
case 1:
202
PUT(byte_t, ptr, value);
203
break;
204
}
205
}
206
}
207
208
/* load a single pixel color value and un-convert it to rgbquad according to visual format */
209
INLINE rgbquad_t
210
getRGBA(void *ptr, ImageFormat * format)
211
{
212
/*
213
FIXME: color is not un-alpha-premultiplied on get
214
this is not required by current code, but it makes the implementation inconsistent
215
i.e. put(get) will not work right for alpha-premultiplied images */
216
217
/* get the value basing on depth and byte order */
218
rgbquad_t value = 0;
219
220
switch (format->byteOrder) {
221
case BYTE_ORDER_LSBFIRST:
222
switch (format->depthBytes) {
223
case 4:
224
value |= GET(byte_t, ptr);
225
value <<= 8;
226
INCP(byte_t, ptr);
227
case 3:
228
value |= GET(byte_t, ptr);
229
value <<= 8;
230
INCP(byte_t, ptr);
231
case 2:
232
value |= GET(byte_t, ptr);
233
value <<= 8;
234
INCP(byte_t, ptr);
235
case 1:
236
value |= GET(byte_t, ptr);
237
}
238
break;
239
case BYTE_ORDER_MSBFIRST:
240
switch (format->depthBytes) { /* lack of *break*'s is intentional */
241
case 4:
242
value |= (GET(byte_t, ptr) << 24);
243
INCP(byte_t, ptr);
244
case 3:
245
value |= (GET(byte_t, ptr) << 16);
246
INCP(byte_t, ptr);
247
case 2:
248
value |= (GET(byte_t, ptr) << 8);
249
INCP(byte_t, ptr);
250
case 1:
251
value |= GET(byte_t, ptr);
252
}
253
break;
254
case BYTE_ORDER_NATIVE:
255
switch (format->depthBytes) {
256
case 4:
257
value = GET(rgbquad_t, ptr);
258
break;
259
case 3: /* not supported, LSB or MSB should always be specified */
260
value = 0xFFFFFFFF; /*return a stub value */
261
break;
262
case 2:
263
value = (rgbquad_t) GET(word_t, ptr);
264
break;
265
case 1:
266
value = (rgbquad_t) GET(byte_t, ptr);
267
break;
268
}
269
break;
270
}
271
/* now un-convert the value */
272
if (format->colorMap) {
273
if (value == format->transparentColor)
274
return 0;
275
else
276
return format->colorMap[value];
277
}
278
else {
279
return UNCONVCOMP(value, format, 0) | UNCONVCOMP(value, format, 1) |
280
UNCONVCOMP(value, format, 2) | UNCONVCOMP(value, format, 3) |
281
format->fixedBits;
282
}
283
}
284
285
/* fill the line with the specified color according to visual format */
286
INLINE void
287
fillLine(rgbquad_t color, void *pDst, int incDst, int n,
288
ImageFormat * dstFormat, int row, int col)
289
{
290
int i;
291
292
for (i = 0; i < n; ++i) {
293
putRGBADither(color, pDst, dstFormat, row, col++);
294
INCPN(byte_t, pDst, incDst);
295
}
296
}
297
298
/* find the shift for specified mask, also verify the mask is valid */
299
INLINE int
300
getMaskShift(rgbquad_t mask, int *pShift, int *pnumBits)
301
{
302
int shift = 0, numBits = 0;
303
304
/* check the mask is not empty */
305
if (!mask)
306
return 0;
307
/* calculate the shift */
308
while ((mask & 1) == 0) {
309
++shift;
310
mask >>= 1;
311
}
312
/* check the mask is contigious */
313
if ((mask & (mask + 1)) != 0)
314
return 0;
315
/* calculate the number of bits */
316
do {
317
++numBits;
318
mask >>= 1;
319
} while ((mask & 1) != 0);
320
*pShift = shift;
321
*pnumBits = numBits;
322
return 1;
323
}
324
325
#endif
326
327