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_VALUE + 1) * 2; i++) { 64 pDither->colorTable[i] = 65 (((i > MAX_COLOR_VALUE) ? MAX_COLOR_VALUE : i) * 66 (numColors - 1) / MAX_COLOR_VALUE) * 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 INLINE 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) \ 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); 106 SORT(1, 2); 107 SORT(0, 1); 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_VALUE) + 137 (scaleColor(g, numColors[1], MAX_COLOR_VALUE) << 8) + 138 (scaleColor(r, numColors[2], MAX_COLOR_VALUE) << 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); 171 INCPN(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_THRESHOLD) { // 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); 182 INCPN(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)) | (src & QUAD_ALPHA_MASK), pDst, dstFormat, 192 row, col++); 193 INCPN(byte_t, pSrc, incSrc); 194 INCPN(byte_t, pDst, incDst); 195 INCPN(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); 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); 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; 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); 260 INCPN(byte_t, pDst, pDstRect->stride); 261 if (pSrcRect2) { 262 INCPN(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); 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; 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 ", 317 format->byteOrder, (unsigned) format->colorMap, format->depthBytes, 318 (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, 321 format->shift[i]); 322 } 323 printf("\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 }