File: | jdk/src/java.desktop/share/native/libsplashscreen/splashscreen_gfx_impl.c |
Warning: | line 81, column 9 Division by zero |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright (c) 2005, 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_gfx_impl.h" | |||
27 | ||||
28 | /* *INDENT-OFF* */ | |||
29 | const byte_t baseDitherMatrix[DITHER_SIZE][DITHER_SIZE] = { | |||
30 | /* Bayer's order-4 dither array. Generated by the code given in | |||
31 | * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I. | |||
32 | */ | |||
33 | { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, | |||
34 | { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, | |||
35 | { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, | |||
36 | { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, | |||
37 | { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, | |||
38 | { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, | |||
39 | { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, | |||
40 | { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, | |||
41 | { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, | |||
42 | { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, | |||
43 | { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, | |||
44 | { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, | |||
45 | { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, | |||
46 | { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, | |||
47 | { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, | |||
48 | { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } | |||
49 | }; | |||
50 | /* *INDENT-ON* */ | |||
51 | ||||
52 | // FIXME: tinting on some colormaps (e.g. 1-2-1) means something is slightly wrong with | |||
53 | // colormap calculation... probably it's some rounding error | |||
54 | ||||
55 | /* calculates the colorTable for mapping from 0..255 to 0..numColors-1 | |||
56 | also calculates the dithering matrix, scaling baseDitherMatrix accordingly */ | |||
57 | void | |||
58 | initDither(DitherSettings * pDither, int numColors, int scale) | |||
59 | { | |||
60 | int i, j; | |||
61 | ||||
62 | pDither->numColors = numColors; | |||
63 | for (i = 0; i < (MAX_COLOR_VALUE255 + 1) * 2; i++) { | |||
64 | pDither->colorTable[i] = | |||
65 | (((i > MAX_COLOR_VALUE255) ? MAX_COLOR_VALUE255 : i) * | |||
66 | (numColors - 1) / MAX_COLOR_VALUE255) * scale; | |||
67 | } | |||
68 | for (i = 0; i < DITHER_SIZE; i++) | |||
69 | for (j = 0; j < DITHER_SIZE; j++) | |||
70 | pDither->matrix[i][j] = | |||
71 | (int) baseDitherMatrix[i][j] / (numColors - 1); | |||
72 | } | |||
73 | ||||
74 | /* scale a number on the range of 0..numColorsIn-1 to 0..numColorsOut-1 | |||
75 | 0 maps to 0 and numColorsIn-1 maps to numColorsOut-1 | |||
76 | intermediate values are spread evenly between 0 and numColorsOut-1 */ | |||
77 | INLINEstatic int | |||
78 | scaleColor(int color, int numColorsIn, int numColorsOut) | |||
79 | { | |||
80 | return (color * (numColorsOut - 1) + (numColorsIn - 1) / 2) | |||
81 | / (numColorsIn - 1); | |||
| ||||
82 | } | |||
83 | ||||
84 | /* build a colormap for a color cube and a dithering matrix. color cube is quantized | |||
85 | according to the provided maximum number of colors */ | |||
86 | int | |||
87 | quantizeColors(int maxNumColors, int *numColors) | |||
88 | { | |||
89 | ||||
90 | // static const int scale[3]={10000/11,10000/69,10000/30}; | |||
91 | // FIXME: sort out the adaptive color cube subdivision... realistic 11:69:30 is good on photos, | |||
92 | // but would be bad on other pictures. A stupid approximation is used now. | |||
93 | ||||
94 | static const int scale[3] = { 8, 4, 6 }; | |||
95 | ||||
96 | // maxNumColors should be at least 2x2x2=8, or we lose some color components completely | |||
97 | numColors[0] = numColors[1] = numColors[2] = 2; | |||
98 | ||||
99 | while (1) { | |||
100 | int idx[3] = { 0, 1, 2 }; | |||
101 | /* bubble sort the three indexes according to scaled numColors values */ | |||
102 | #define SORT(i,j)if (numColors[idx[i]]*scale[idx[i]]>numColors[idx[j]]*scale [idx[j]]) { int t = idx[i]; idx[i] = idx[j]; idx[j] = t; } \ | |||
103 | if (numColors[idx[i]]*scale[idx[i]]>numColors[idx[j]]*scale[idx[j]]) \ | |||
104 | { int t = idx[i]; idx[i] = idx[j]; idx[j] = t; } | |||
105 | SORT(0, 1)if (numColors[idx[0]]*scale[idx[0]]>numColors[idx[1]]*scale [idx[1]]) { int t = idx[0]; idx[0] = idx[1]; idx[1] = t; }; | |||
106 | SORT(1, 2)if (numColors[idx[1]]*scale[idx[1]]>numColors[idx[2]]*scale [idx[2]]) { int t = idx[1]; idx[1] = idx[2]; idx[2] = t; }; | |||
107 | SORT(0, 1)if (numColors[idx[0]]*scale[idx[0]]>numColors[idx[1]]*scale [idx[1]]) { int t = idx[0]; idx[0] = idx[1]; idx[1] = t; }; | |||
108 | /* try increasing numColors for the first color */ | |||
109 | if ((numColors[idx[0]] + 1) * numColors[idx[1]] * | |||
110 | numColors[idx[2]] <= maxNumColors) { | |||
111 | numColors[idx[0]]++; | |||
112 | } else if (numColors[idx[0]] * (numColors[idx[1]] + 1) * | |||
113 | numColors[idx[2]] <= maxNumColors) { | |||
114 | numColors[idx[1]]++; | |||
115 | } else if (numColors[idx[0]] * numColors[idx[1]] * | |||
116 | (numColors[idx[2]] + 1) <= maxNumColors) { | |||
117 | numColors[idx[2]]++; | |||
118 | } else { | |||
119 | break; | |||
120 | } | |||
121 | } | |||
122 | return numColors[0] * numColors[1] * numColors[2]; | |||
123 | } | |||
124 | ||||
125 | void | |||
126 | initColorCube(int *numColors, rgbquad_t * pColorMap, DitherSettings * pDithers, | |||
127 | rgbquad_t * colorIndex) | |||
128 | { | |||
129 | int r, g, b, n; | |||
130 | ||||
131 | n = 0; | |||
132 | for (r = 0; r < numColors[2]; r++) { | |||
| ||||
133 | for (g = 0; g < numColors[1]; g++) | |||
134 | for (b = 0; b < numColors[0]; b++) { | |||
135 | pColorMap[colorIndex[n++]] = | |||
136 | scaleColor(b, numColors[0], MAX_COLOR_VALUE255) + | |||
137 | (scaleColor(g, numColors[1], MAX_COLOR_VALUE255) << 8) + | |||
138 | (scaleColor(r, numColors[2], MAX_COLOR_VALUE255) << 16); | |||
139 | } | |||
140 | } | |||
141 | initDither(pDithers + 0, numColors[0], 1); | |||
142 | initDither(pDithers + 1, numColors[1], numColors[0]); | |||
143 | initDither(pDithers + 2, numColors[2], numColors[1] * numColors[0]); | |||
144 | } | |||
145 | ||||
146 | /* | |||
147 | the function below is a line conversion loop | |||
148 | ||||
149 | incSrc and incDst are pSrc and pDst increment values for the loop, in bytes | |||
150 | mode defines how the pixels should be processed | |||
151 | ||||
152 | mode==CVT_COPY means the pixels should be copied as is | |||
153 | mode==CVT_ALPHATEST means pixels should be skipped when source pixel alpha is above the threshold | |||
154 | mode==CVT_BLEND means alpha blending between source and destination should be performed, while | |||
155 | destination alpha should be retained. source alpha is used for blending. | |||
156 | */ | |||
157 | void | |||
158 | convertLine(void *pSrc, int incSrc, void *pDst, int incDst, int numSamples, | |||
159 | ImageFormat * srcFormat, ImageFormat * dstFormat, int doAlpha, | |||
160 | void *pSrc2, int incSrc2, ImageFormat * srcFormat2, | |||
161 | int row, int col) | |||
162 | { | |||
163 | int i; | |||
164 | ||||
165 | switch (doAlpha) { | |||
166 | case CVT_COPY: | |||
167 | for (i = 0; i < numSamples; ++i) { | |||
168 | putRGBADither(getRGBA(pSrc, srcFormat), pDst, dstFormat, | |||
169 | row, col++); | |||
170 | INCPN(byte_t, pSrc, incSrc)((pSrc) = (byte_t*)(pSrc)+(incSrc)); | |||
171 | INCPN(byte_t, pDst, incDst)((pDst) = (byte_t*)(pDst)+(incDst)); | |||
172 | } | |||
173 | break; | |||
174 | case CVT_ALPHATEST: | |||
175 | for (i = 0; i < numSamples; ++i) { | |||
176 | rgbquad_t color = getRGBA(pSrc, srcFormat); | |||
177 | ||||
178 | if (color >= ALPHA_THRESHOLD0x80000000) { // test for alpha component >50%. that's an extra branch, and it's bad... | |||
179 | putRGBADither(color, pDst, dstFormat, row, col++); | |||
180 | } | |||
181 | INCPN(byte_t, pSrc, incSrc)((pSrc) = (byte_t*)(pSrc)+(incSrc)); | |||
182 | INCPN(byte_t, pDst, incDst)((pDst) = (byte_t*)(pDst)+(incDst)); | |||
183 | } | |||
184 | break; | |||
185 | case CVT_BLEND: | |||
186 | for (i = 0; i < numSamples; ++i) { | |||
187 | rgbquad_t src = getRGBA(pSrc, srcFormat); | |||
188 | rgbquad_t src2 = getRGBA(pSrc2, srcFormat); | |||
189 | ||||
190 | putRGBADither(blendRGB(src, src2, | |||
191 | QUAD_ALPHA(src2)(((src2)&0xFF000000)>>24)) | (src & QUAD_ALPHA_MASK0xFF000000), pDst, dstFormat, | |||
192 | row, col++); | |||
193 | INCPN(byte_t, pSrc, incSrc)((pSrc) = (byte_t*)(pSrc)+(incSrc)); | |||
194 | INCPN(byte_t, pDst, incDst)((pDst) = (byte_t*)(pDst)+(incDst)); | |||
195 | INCPN(byte_t, pSrc2, incSrc2)((pSrc2) = (byte_t*)(pSrc2)+(incSrc2)); | |||
196 | } | |||
197 | break; | |||
198 | } | |||
199 | } | |||
200 | ||||
201 | /* initialize ImageRect structure according to function arguments */ | |||
202 | void | |||
203 | initRect(ImageRect * pRect, int x, int y, int width, int height, int jump, | |||
204 | int stride, void *pBits, ImageFormat * format) | |||
205 | { | |||
206 | int depthBytes = format->depthBytes; | |||
207 | ||||
208 | pRect->pBits = pBits; | |||
209 | INCPN(byte_t, pRect->pBits, (intptr_t) y * stride + x * depthBytes)((pRect->pBits) = (byte_t*)(pRect->pBits)+((intptr_t) y * stride + x * depthBytes)); | |||
210 | pRect->numLines = height; | |||
211 | pRect->numSamples = width; | |||
212 | pRect->stride = stride * jump; | |||
213 | pRect->depthBytes = depthBytes; | |||
214 | pRect->format = format; | |||
215 | pRect->row = y; | |||
216 | pRect->col = x; | |||
217 | pRect->jump = jump; | |||
218 | } | |||
219 | ||||
220 | /* copy image rectangle from source to destination, or from two sources with blending */ | |||
221 | ||||
222 | int | |||
223 | convertRect(ImageRect * pSrcRect, ImageRect * pDstRect, int mode) | |||
224 | { | |||
225 | return convertRect2(pSrcRect, pDstRect, mode, NULL((void*)0)); | |||
226 | } | |||
227 | ||||
228 | int | |||
229 | convertRect2(ImageRect * pSrcRect, ImageRect * pDstRect, int mode, | |||
230 | ImageRect * pSrcRect2) | |||
231 | { | |||
232 | int numLines = pSrcRect->numLines; | |||
233 | int numSamples = pSrcRect->numSamples; | |||
234 | void *pSrc = pSrcRect->pBits; | |||
235 | void *pDst = pDstRect->pBits; | |||
236 | void *pSrc2 = NULL((void*)0); | |||
237 | int j, row; | |||
238 | ||||
239 | if (pDstRect->numLines < numLines) | |||
240 | numLines = pDstRect->numLines; | |||
241 | if (pDstRect->numSamples < numSamples) { | |||
242 | numSamples = pDstRect->numSamples; | |||
243 | } | |||
244 | if (pSrcRect2) { | |||
245 | if (pSrcRect2->numLines < numLines) { | |||
246 | numLines = pSrcRect2->numLines; | |||
247 | } | |||
248 | if (pSrcRect2->numSamples < numSamples) { | |||
249 | numSamples = pSrcRect2->numSamples; | |||
250 | } | |||
251 | pSrc2 = pSrcRect2->pBits; | |||
252 | } | |||
253 | row = pDstRect->row; | |||
254 | for (j = 0; j < numLines; j++) { | |||
255 | convertLine(pSrc, pSrcRect->depthBytes, pDst, pDstRect->depthBytes, | |||
256 | numSamples, pSrcRect->format, pDstRect->format, mode, | |||
257 | pSrc2, pSrcRect2 ? pSrcRect2->depthBytes : 0, | |||
258 | pSrcRect2 ? pSrcRect2->format : 0, row, pDstRect->col); | |||
259 | INCPN(byte_t, pSrc, pSrcRect->stride)((pSrc) = (byte_t*)(pSrc)+(pSrcRect->stride)); | |||
260 | INCPN(byte_t, pDst, pDstRect->stride)((pDst) = (byte_t*)(pDst)+(pDstRect->stride)); | |||
261 | if (pSrcRect2) { | |||
262 | INCPN(byte_t, pSrc2, pSrcRect2->stride)((pSrc2) = (byte_t*)(pSrc2)+(pSrcRect2->stride)); | |||
263 | } | |||
264 | row += pDstRect->jump; | |||
265 | } | |||
266 | return numLines * pSrcRect->stride; | |||
267 | } | |||
268 | ||||
269 | int | |||
270 | fillRect(rgbquad_t color, ImageRect * pDstRect) | |||
271 | { | |||
272 | int numLines = pDstRect->numLines; | |||
273 | int numSamples = pDstRect->numSamples; | |||
274 | void *pDst = pDstRect->pBits; | |||
275 | int j, row; | |||
276 | ||||
277 | row = pDstRect->row; | |||
278 | for (j = 0; j < numLines; j++) { | |||
279 | fillLine(color, pDst, pDstRect->depthBytes, numSamples, | |||
280 | pDstRect->format, row, pDstRect->col); | |||
281 | INCPN(byte_t, pDst, pDstRect->stride)((pDst) = (byte_t*)(pDst)+(pDstRect->stride)); | |||
282 | row += pDstRect->jump; | |||
283 | } | |||
284 | return numLines * pDstRect->stride; | |||
285 | } | |||
286 | ||||
287 | /* init the masks; all other parameters are initialized to default values */ | |||
288 | void | |||
289 | initFormat(ImageFormat * format, int redMask, int greenMask, int blueMask, | |||
290 | int alphaMask) | |||
291 | { | |||
292 | int i, shift, numBits; | |||
293 | ||||
294 | format->byteOrder = BYTE_ORDER_NATIVE; | |||
295 | format->colorMap = NULL((void*)0); | |||
296 | format->depthBytes = 4; | |||
297 | format->fixedBits = 0; | |||
298 | format->premultiplied = 0; | |||
299 | format->mask[0] = blueMask; | |||
300 | format->mask[1] = greenMask; | |||
301 | format->mask[2] = redMask; | |||
302 | format->mask[3] = alphaMask; | |||
303 | for (i = 0; i < 4; i++) { | |||
304 | getMaskShift(format->mask[i], &shift, &numBits); | |||
305 | format->shift[i] = shift + numBits - i * 8 - 8; | |||
306 | } | |||
307 | } | |||
308 | ||||
309 | /* dump the visual format */ | |||
310 | void | |||
311 | dumpFormat(ImageFormat * format) | |||
312 | { | |||
313 | #ifdef _DEBUG | |||
314 | int i; | |||
315 | ||||
316 | printf("byteorder=%d colormap=%08x depthBytes=%d fixedBits=%08x transparentColor=%u ",__printf_chk (2 - 1, "byteorder=%d colormap=%08x depthBytes=%d fixedBits=%08x transparentColor=%u " , format->byteOrder, (unsigned) format->colorMap, format ->depthBytes, (unsigned) format->fixedBits, (unsigned) format ->transparentColor) | |||
317 | format->byteOrder, (unsigned) format->colorMap, format->depthBytes,__printf_chk (2 - 1, "byteorder=%d colormap=%08x depthBytes=%d fixedBits=%08x transparentColor=%u " , format->byteOrder, (unsigned) format->colorMap, format ->depthBytes, (unsigned) format->fixedBits, (unsigned) format ->transparentColor) | |||
318 | (unsigned) format->fixedBits, (unsigned) format->transparentColor)__printf_chk (2 - 1, "byteorder=%d colormap=%08x depthBytes=%d fixedBits=%08x transparentColor=%u " , format->byteOrder, (unsigned) format->colorMap, format ->depthBytes, (unsigned) format->fixedBits, (unsigned) format ->transparentColor); | |||
319 | for (i = 0; i < 4; i++) { | |||
320 | printf("mask[%d]=%08x shift[%d]=%d\n", i, (unsigned) format->mask[i], i,__printf_chk (2 - 1, "mask[%d]=%08x shift[%d]=%d\n", i, (unsigned ) format->mask[i], i, format->shift[i]) | |||
321 | format->shift[i])__printf_chk (2 - 1, "mask[%d]=%08x shift[%d]=%d\n", i, (unsigned ) format->mask[i], i, format->shift[i]); | |||
322 | } | |||
323 | printf("\n")__printf_chk (2 - 1, "\n"); | |||
324 | #endif | |||
325 | } | |||
326 | ||||
327 | /* optimize the format */ | |||
328 | void | |||
329 | optimizeFormat(ImageFormat * format) | |||
330 | { | |||
331 | if (platformByteOrder() == format->byteOrder && format->depthBytes != 3) { | |||
332 | format->byteOrder = BYTE_ORDER_NATIVE; | |||
333 | } | |||
334 | /* FIXME: some advanced optimizations are possible, especially for format pairs */ | |||
335 | } | |||
336 | ||||
337 | int | |||
338 | platformByteOrder() | |||
339 | { | |||
340 | int test = 1; | |||
341 | ||||
342 | *(char *) &test = 0; | |||
343 | return test ? BYTE_ORDER_MSBFIRST : BYTE_ORDER_LSBFIRST; | |||
344 | } |