Bug Summary

File:jdk/src/java.desktop/share/native/libsplashscreen/splashscreen_gfx_impl.c
Warning:line 305, column 34
The left operand of '+' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name splashscreen_gfx_impl.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjava -I /home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -D LIBC=gnu -D _GNU_SOURCE -D _REENTRANT -D _LARGEFILE64_SOURCE -D LINUX -D DEBUG -D _LITTLE_ENDIAN -D ARCH="amd64" -D amd64 -D _LP64=1 -D SPLASHSCREEN -D PNG_NO_MMX_CODE -D PNG_ARM_NEON_OPT=0 -D PNG_ARM_NEON_IMPLEMENTATION=0 -D WITH_X11 -I /home/daniel/Projects/java/jdk/src/java.desktop/unix/native/libsplashscreen -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libsplashscreen -I /home/daniel/Projects/java/jdk/src/java.desktop/unix/native/common/awt/systemscale -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libjavajpeg -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/headers/java.desktop -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libsplashscreen/giflib -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libsplashscreen/libpng -I /home/daniel/Projects/java/jdk/src/java.base/unix/native/include -I /home/daniel/Projects/java/jdk/src/java.base/share/native/include -I /home/daniel/Projects/java/jdk/src/java.base/linux/native/libjava -I /home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjava -D _FORTIFY_SOURCE=2 -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused -Wno-sign-compare -Wno-type-limits -Wno-unused-result -Wno-maybe-uninitialized -Wno-shift-negative-value -Wno-implicit-fallthrough -Wno-unused-function -std=c99 -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libsplashscreen/splashscreen_gfx_impl.c

/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libsplashscreen/splashscreen_gfx_impl.c

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* */
29const 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 */
57void
58initDither(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 */
77INLINEstatic int
78scaleColor(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 */
86int
87quantizeColors(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
125void
126initColorCube(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*/
157void
158convertLine(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 */
202void
203initRect(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
222int
223convertRect(ImageRect * pSrcRect, ImageRect * pDstRect, int mode)
224{
225 return convertRect2(pSrcRect, pDstRect, mode, NULL((void*)0));
226}
227
228int
229convertRect2(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
269int
270fillRect(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 */
288void
289initFormat(ImageFormat * format, int redMask, int greenMask, int blueMask,
290 int alphaMask)
291{
292 int i, shift, numBits;
1
'shift' declared without an initial value
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++) {
2
Loop condition is true. Entering loop body
304 getMaskShift(format->mask[i], &shift, &numBits);
3
Calling 'getMaskShift'
7
Returning from 'getMaskShift'
305 format->shift[i] = shift + numBits - i * 8 - 8;
8
The left operand of '+' is a garbage value
306 }
307}
308
309/* dump the visual format */
310void
311dumpFormat(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 */
328void
329optimizeFormat(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
337int
338platformByteOrder()
339{
340 int test = 1;
341
342 *(char *) &test = 0;
343 return test ? BYTE_ORDER_MSBFIRST : BYTE_ORDER_LSBFIRST;
344}

/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libsplashscreen/splashscreen_gfx_impl.h

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)) ((p) = (type*)(p)+(n))
35
36/* advance a pointer by sizeof(type) */
37#define INCP(type,p)(((p)) = (type*)((p))+(1)) INCPN(type,(p),1)(((p)) = (type*)((p))+(1))
38
39/* store a typed value to pointed location */
40#define PUT(type,p,v)(*(type*)(p) = (type)(v)) (*(type*)(p) = (type)(v))
41
42/* load a typed value from pointed location */
43#define GET(type,p)(*(type*)p) (*(type*)p)
44
45/* same as cond<0?-1:0 */
46enum
47{
48 IFNEG_SHIFT_BITS = sizeof(int) * 8 - 1
49};
50
51#define IFNEG(cond)((int)(cond)>>IFNEG_SHIFT_BITS) ((int)(cond)>>IFNEG_SHIFT_BITS)
52
53/* same as cond<0?n1:n2 */
54#define IFNEGPOS(cond,n1,n2)((((int)(cond)>>IFNEG_SHIFT_BITS)&(n1))|((~((int)(cond
)>>IFNEG_SHIFT_BITS))&(n2)))
((IFNEG(cond)((int)(cond)>>IFNEG_SHIFT_BITS)&(n1))|((~IFNEG(cond)((int)(cond)>>IFNEG_SHIFT_BITS))&(n2)))
55
56/* value shifted left by n bits, negative n is allowed */
57#define LSHIFT(value,n)((((int)((n))>>IFNEG_SHIFT_BITS)&((value)>>-(
n)))|((~((int)((n))>>IFNEG_SHIFT_BITS))&((value)<<
(n))))
IFNEGPOS((n),(value)>>-(n),(value)<<(n))((((int)((n))>>IFNEG_SHIFT_BITS)&((value)>>-(
n)))|((~((int)((n))>>IFNEG_SHIFT_BITS))&((value)<<
(n))))
58
59/* value shifted right by n bits, negative n is allowed */
60#define RSHIFT(value,n)((((int)(n)>>IFNEG_SHIFT_BITS)&((value)<<-(n)
))|((~((int)(n)>>IFNEG_SHIFT_BITS))&((value)>>
(n))))
IFNEGPOS(n,(value)<<-(n),(value)>>(n))((((int)(n)>>IFNEG_SHIFT_BITS)&((value)<<-(n)
))|((~((int)(n)>>IFNEG_SHIFT_BITS))&((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)(((((int)(((format)->shift[i]))>>IFNEG_SHIFT_BITS)&
(((quad))>>-((format)->shift[i])))|((~((int)(((format
)->shift[i]))>>IFNEG_SHIFT_BITS))&(((quad))<<
((format)->shift[i]))))&(format)->mask[i])
\
64 (LSHIFT((quad),(format)->shift[i])((((int)(((format)->shift[i]))>>IFNEG_SHIFT_BITS)&
(((quad))>>-((format)->shift[i])))|((~((int)(((format
)->shift[i]))>>IFNEG_SHIFT_BITS))&(((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)(((((int)((format)->shift[i])>>IFNEG_SHIFT_BITS)&
(((value)&(format)->mask[i])<<-((format)->shift
[i])))|((~((int)((format)->shift[i])>>IFNEG_SHIFT_BITS
))&(((value)&(format)->mask[i])>>((format)->
shift[i])))))
\
68 (RSHIFT((value)&(format)->mask[i],(format)->shift[i])((((int)((format)->shift[i])>>IFNEG_SHIFT_BITS)&
(((value)&(format)->mask[i])<<-((format)->shift
[i])))|((~((int)((format)->shift[i])>>IFNEG_SHIFT_BITS
))&(((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 */
72INLINEstatic unsigned
73ditherColor(rgbquad_t value, ImageFormat * format, int row, int col)
74{
75 int blue = QUAD_BLUE(value)(((value)&0x000000FF)>>0);
76 int green = QUAD_GREEN(value)(((value)&0x0000FF00)>>8);
77 int red = QUAD_RED(value)(((value)&0x00FF0000)>>16);
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*/
92INLINEstatic rgbquad_t
93blendRGB(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((((0)<<24)&0xFF000000)| ((((rgbquad_t)(((((src)&
0x00FF0000)>>16) * a + (((dst)&0x00FF0000)>>16
) * a1) / 0xFF))<<16)&0x00FF0000)| ((((rgbquad_t)((
(((src)&0x0000FF00)>>8) * a + (((dst)&0x0000FF00
)>>8) * a1) / 0xFF))<<8)&0x0000FF00)| ((((rgbquad_t
)(((((src)&0x000000FF)>>0) * a + (((dst)&0x000000FF
)>>0) * a1) / 0xFF))<<0)&0x000000FF)
99 (rgbquad_t)((QUAD_RED(src) * a + QUAD_RED(dst) * a1) / 0xFF),(((0)<<24)&0xFF000000)| ((((rgbquad_t)(((((src)&
0x00FF0000)>>16) * a + (((dst)&0x00FF0000)>>16
) * a1) / 0xFF))<<16)&0x00FF0000)| ((((rgbquad_t)((
(((src)&0x0000FF00)>>8) * a + (((dst)&0x0000FF00
)>>8) * a1) / 0xFF))<<8)&0x0000FF00)| ((((rgbquad_t
)(((((src)&0x000000FF)>>0) * a + (((dst)&0x000000FF
)>>0) * a1) / 0xFF))<<0)&0x000000FF)
100 (rgbquad_t)((QUAD_GREEN(src) * a + QUAD_GREEN(dst) * a1) / 0xFF),(((0)<<24)&0xFF000000)| ((((rgbquad_t)(((((src)&
0x00FF0000)>>16) * a + (((dst)&0x00FF0000)>>16
) * a1) / 0xFF))<<16)&0x00FF0000)| ((((rgbquad_t)((
(((src)&0x0000FF00)>>8) * a + (((dst)&0x0000FF00
)>>8) * a1) / 0xFF))<<8)&0x0000FF00)| ((((rgbquad_t
)(((((src)&0x000000FF)>>0) * a + (((dst)&0x000000FF
)>>0) * a1) / 0xFF))<<0)&0x000000FF)
101 (rgbquad_t)((QUAD_BLUE(src) * a + QUAD_BLUE(dst) * a1) / 0xFF),(((0)<<24)&0xFF000000)| ((((rgbquad_t)(((((src)&
0x00FF0000)>>16) * a + (((dst)&0x00FF0000)>>16
) * a1) / 0xFF))<<16)&0x00FF0000)| ((((rgbquad_t)((
(((src)&0x0000FF00)>>8) * a + (((dst)&0x0000FF00
)>>8) * a1) / 0xFF))<<8)&0x0000FF00)| ((((rgbquad_t
)(((((src)&0x000000FF)>>0) * a + (((dst)&0x000000FF
)>>0) * a1) / 0xFF))<<0)&0x000000FF)
102 0)(((0)<<24)&0xFF000000)| ((((rgbquad_t)(((((src)&
0x00FF0000)>>16) * a + (((dst)&0x00FF0000)>>16
) * a1) / 0xFF))<<16)&0x00FF0000)| ((((rgbquad_t)((
(((src)&0x0000FF00)>>8) * a + (((dst)&0x0000FF00
)>>8) * a1) / 0xFF))<<8)&0x0000FF00)| ((((rgbquad_t
)(((((src)&0x000000FF)>>0) * a + (((dst)&0x000000FF
)>>0) * a1) / 0xFF))<<0)&0x000000FF)
;
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
110INLINEstatic rgbquad_t
111premultiplyRGBA(rgbquad_t src)
112{
113 rgbquad_t srb = src & 0xFF00FF;
114 rgbquad_t sg = src & 0xFF00;
115 rgbquad_t alpha = src >> QUAD_ALPHA_SHIFT24;
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 */
138INLINEstatic void
139putRGBADither(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)(((((int)(((format)->shift[0]))>>IFNEG_SHIFT_BITS)&
(((value))>>-((format)->shift[0])))|((~((int)(((format
)->shift[0]))>>IFNEG_SHIFT_BITS))&(((value))<<
((format)->shift[0]))))&(format)->mask[0])
| CONVCOMP(value, format, 1)(((((int)(((format)->shift[1]))>>IFNEG_SHIFT_BITS)&
(((value))>>-((format)->shift[1])))|((~((int)(((format
)->shift[1]))>>IFNEG_SHIFT_BITS))&(((value))<<
((format)->shift[1]))))&(format)->mask[1])
|
150 CONVCOMP(value, format, 2)(((((int)(((format)->shift[2]))>>IFNEG_SHIFT_BITS)&
(((value))>>-((format)->shift[2])))|((~((int)(((format
)->shift[2]))>>IFNEG_SHIFT_BITS))&(((value))<<
((format)->shift[2]))))&(format)->mask[2])
| CONVCOMP(value, format, 3)(((((int)(((format)->shift[3]))>>IFNEG_SHIFT_BITS)&
(((value))>>-((format)->shift[3])))|((~((int)(((format
)->shift[3]))>>IFNEG_SHIFT_BITS))&(((value))<<
((format)->shift[3]))))&(format)->mask[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)(*(byte_t*)(ptr) = (byte_t)(value & 0xff));
157 value >>= 8;
158 INCP(byte_t, ptr)(((ptr)) = (byte_t*)((ptr))+(1));
159 case 3:
160 PUT(byte_t, ptr, value & 0xff)(*(byte_t*)(ptr) = (byte_t)(value & 0xff));
161 value >>= 8;
162 INCP(byte_t, ptr)(((ptr)) = (byte_t*)((ptr))+(1));
163 case 2:
164 PUT(byte_t, ptr, value & 0xff)(*(byte_t*)(ptr) = (byte_t)(value & 0xff));
165 value >>= 8;
166 INCP(byte_t, ptr)(((ptr)) = (byte_t*)((ptr))+(1));
167 case 1:
168 PUT(byte_t, ptr, value & 0xff)(*(byte_t*)(ptr) = (byte_t)(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)(*(byte_t*)(ptr) = (byte_t)((value >> 24) & 0xff));
175 INCP(byte_t, ptr)(((ptr)) = (byte_t*)((ptr))+(1));
176 case 3:
177 PUT(byte_t, ptr, (value >> 16) & 0xff)(*(byte_t*)(ptr) = (byte_t)((value >> 16) & 0xff));
178 INCP(byte_t, ptr)(((ptr)) = (byte_t*)((ptr))+(1));
179 case 2:
180 PUT(byte_t, ptr, (value >> 8) & 0xff)(*(byte_t*)(ptr) = (byte_t)((value >> 8) & 0xff));
181 INCP(byte_t, ptr)(((ptr)) = (byte_t*)((ptr))+(1));
182 case 1:
183 PUT(byte_t, ptr, value & 0xff)(*(byte_t*)(ptr) = (byte_t)(value & 0xff));
184 }
185 break;
186 case BYTE_ORDER_NATIVE:
187 switch (format->depthBytes) {
188 case 4:
189 PUT(rgbquad_t, ptr, value)(*(rgbquad_t*)(ptr) = (rgbquad_t)(value));
190 break;
191 case 3: /* not supported, LSB or MSB should always be specified */
192 PUT(byte_t, ptr, 0xff)(*(byte_t*)(ptr) = (byte_t)(0xff)); /* Put a stub value */
193 INCP(byte_t, ptr)(((ptr)) = (byte_t*)((ptr))+(1));
194 PUT(byte_t, ptr, 0xff)(*(byte_t*)(ptr) = (byte_t)(0xff));
195 INCP(byte_t, ptr)(((ptr)) = (byte_t*)((ptr))+(1));
196 PUT(byte_t, ptr, 0xff)(*(byte_t*)(ptr) = (byte_t)(0xff));
197 break;
198 case 2:
199 PUT(word_t, ptr, value)(*(word_t*)(ptr) = (word_t)(value));
200 break;
201 case 1:
202 PUT(byte_t, ptr, value)(*(byte_t*)(ptr) = (byte_t)(value));
203 break;
204 }
205 }
206}
207
208/* load a single pixel color value and un-convert it to rgbquad according to visual format */
209INLINEstatic rgbquad_t
210getRGBA(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)(*(byte_t*)ptr);
225 value <<= 8;
226 INCP(byte_t, ptr)(((ptr)) = (byte_t*)((ptr))+(1));
227 case 3:
228 value |= GET(byte_t, ptr)(*(byte_t*)ptr);
229 value <<= 8;
230 INCP(byte_t, ptr)(((ptr)) = (byte_t*)((ptr))+(1));
231 case 2:
232 value |= GET(byte_t, ptr)(*(byte_t*)ptr);
233 value <<= 8;
234 INCP(byte_t, ptr)(((ptr)) = (byte_t*)((ptr))+(1));
235 case 1:
236 value |= GET(byte_t, ptr)(*(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)(*(byte_t*)ptr) << 24);
243 INCP(byte_t, ptr)(((ptr)) = (byte_t*)((ptr))+(1));
244 case 3:
245 value |= (GET(byte_t, ptr)(*(byte_t*)ptr) << 16);
246 INCP(byte_t, ptr)(((ptr)) = (byte_t*)((ptr))+(1));
247 case 2:
248 value |= (GET(byte_t, ptr)(*(byte_t*)ptr) << 8);
249 INCP(byte_t, ptr)(((ptr)) = (byte_t*)((ptr))+(1));
250 case 1:
251 value |= GET(byte_t, ptr)(*(byte_t*)ptr);
252 }
253 break;
254 case BYTE_ORDER_NATIVE:
255 switch (format->depthBytes) {
256 case 4:
257 value = GET(rgbquad_t, ptr)(*(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)(*(word_t*)ptr);
264 break;
265 case 1:
266 value = (rgbquad_t) GET(byte_t, ptr)(*(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)(((((int)((format)->shift[0])>>IFNEG_SHIFT_BITS)&
(((value)&(format)->mask[0])<<-((format)->shift
[0])))|((~((int)((format)->shift[0])>>IFNEG_SHIFT_BITS
))&(((value)&(format)->mask[0])>>((format)->
shift[0])))))
| UNCONVCOMP(value, format, 1)(((((int)((format)->shift[1])>>IFNEG_SHIFT_BITS)&
(((value)&(format)->mask[1])<<-((format)->shift
[1])))|((~((int)((format)->shift[1])>>IFNEG_SHIFT_BITS
))&(((value)&(format)->mask[1])>>((format)->
shift[1])))))
|
280 UNCONVCOMP(value, format, 2)(((((int)((format)->shift[2])>>IFNEG_SHIFT_BITS)&
(((value)&(format)->mask[2])<<-((format)->shift
[2])))|((~((int)((format)->shift[2])>>IFNEG_SHIFT_BITS
))&(((value)&(format)->mask[2])>>((format)->
shift[2])))))
| UNCONVCOMP(value, format, 3)(((((int)((format)->shift[3])>>IFNEG_SHIFT_BITS)&
(((value)&(format)->mask[3])<<-((format)->shift
[3])))|((~((int)((format)->shift[3])>>IFNEG_SHIFT_BITS
))&(((value)&(format)->mask[3])>>((format)->
shift[3])))))
|
281 format->fixedBits;
282 }
283}
284
285/* fill the line with the specified color according to visual format */
286INLINEstatic void
287fillLine(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)((pDst) = (byte_t*)(pDst)+(incDst));
295 }
296}
297
298/* find the shift for specified mask, also verify the mask is valid */
299INLINEstatic int
300getMaskShift(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)
4
Assuming 'mask' is 0
5
Taking true branch
306 return 0;
6
Returning without writing to '*pShift'
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