Path: blob/master/src/java.desktop/share/native/libsplashscreen/splashscreen_gfx_impl.c
41149 views
/*1* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include "splashscreen_gfx_impl.h"2627/* *INDENT-OFF* */28const byte_t baseDitherMatrix[DITHER_SIZE][DITHER_SIZE] = {29/* Bayer's order-4 dither array. Generated by the code given in30* Stephen Hawley's article "Ordered Dithering" in Graphics Gems I.31*/32{ 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 },33{ 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },34{ 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },35{ 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },36{ 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 },37{ 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },38{ 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },39{ 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },40{ 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 },41{ 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },42{ 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },43{ 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },44{ 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 },45{ 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },46{ 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },47{ 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }48};49/* *INDENT-ON* */5051// FIXME: tinting on some colormaps (e.g. 1-2-1) means something is slightly wrong with52// colormap calculation... probably it's some rounding error5354/* calculates the colorTable for mapping from 0..255 to 0..numColors-155also calculates the dithering matrix, scaling baseDitherMatrix accordingly */56void57initDither(DitherSettings * pDither, int numColors, int scale)58{59int i, j;6061pDither->numColors = numColors;62for (i = 0; i < (MAX_COLOR_VALUE + 1) * 2; i++) {63pDither->colorTable[i] =64(((i > MAX_COLOR_VALUE) ? MAX_COLOR_VALUE : i) *65(numColors - 1) / MAX_COLOR_VALUE) * scale;66}67for (i = 0; i < DITHER_SIZE; i++)68for (j = 0; j < DITHER_SIZE; j++)69pDither->matrix[i][j] =70(int) baseDitherMatrix[i][j] / (numColors - 1);71}7273/* scale a number on the range of 0..numColorsIn-1 to 0..numColorsOut-1740 maps to 0 and numColorsIn-1 maps to numColorsOut-175intermediate values are spread evenly between 0 and numColorsOut-1 */76INLINE int77scaleColor(int color, int numColorsIn, int numColorsOut)78{79return (color * (numColorsOut - 1) + (numColorsIn - 1) / 2)80/ (numColorsIn - 1);81}8283/* build a colormap for a color cube and a dithering matrix. color cube is quantized84according to the provided maximum number of colors */85int86quantizeColors(int maxNumColors, int *numColors)87{8889// static const int scale[3]={10000/11,10000/69,10000/30};90// FIXME: sort out the adaptive color cube subdivision... realistic 11:69:30 is good on photos,91// but would be bad on other pictures. A stupid approximation is used now.9293static const int scale[3] = { 8, 4, 6 };9495// maxNumColors should be at least 2x2x2=8, or we lose some color components completely96numColors[0] = numColors[1] = numColors[2] = 2;9798while (1) {99int idx[3] = { 0, 1, 2 };100/* bubble sort the three indexes according to scaled numColors values */101#define SORT(i,j) \102if (numColors[idx[i]]*scale[idx[i]]>numColors[idx[j]]*scale[idx[j]]) \103{ int t = idx[i]; idx[i] = idx[j]; idx[j] = t; }104SORT(0, 1);105SORT(1, 2);106SORT(0, 1);107/* try increasing numColors for the first color */108if ((numColors[idx[0]] + 1) * numColors[idx[1]] *109numColors[idx[2]] <= maxNumColors) {110numColors[idx[0]]++;111} else if (numColors[idx[0]] * (numColors[idx[1]] + 1) *112numColors[idx[2]] <= maxNumColors) {113numColors[idx[1]]++;114} else if (numColors[idx[0]] * numColors[idx[1]] *115(numColors[idx[2]] + 1) <= maxNumColors) {116numColors[idx[2]]++;117} else {118break;119}120}121return numColors[0] * numColors[1] * numColors[2];122}123124void125initColorCube(int *numColors, rgbquad_t * pColorMap, DitherSettings * pDithers,126rgbquad_t * colorIndex)127{128int r, g, b, n;129130n = 0;131for (r = 0; r < numColors[2]; r++) {132for (g = 0; g < numColors[1]; g++)133for (b = 0; b < numColors[0]; b++) {134pColorMap[colorIndex[n++]] =135scaleColor(b, numColors[0], MAX_COLOR_VALUE) +136(scaleColor(g, numColors[1], MAX_COLOR_VALUE) << 8) +137(scaleColor(r, numColors[2], MAX_COLOR_VALUE) << 16);138}139}140initDither(pDithers + 0, numColors[0], 1);141initDither(pDithers + 1, numColors[1], numColors[0]);142initDither(pDithers + 2, numColors[2], numColors[1] * numColors[0]);143}144145/*146the function below is a line conversion loop147148incSrc and incDst are pSrc and pDst increment values for the loop, in bytes149mode defines how the pixels should be processed150151mode==CVT_COPY means the pixels should be copied as is152mode==CVT_ALPHATEST means pixels should be skipped when source pixel alpha is above the threshold153mode==CVT_BLEND means alpha blending between source and destination should be performed, while154destination alpha should be retained. source alpha is used for blending.155*/156void157convertLine(void *pSrc, int incSrc, void *pDst, int incDst, int numSamples,158ImageFormat * srcFormat, ImageFormat * dstFormat, int doAlpha,159void *pSrc2, int incSrc2, ImageFormat * srcFormat2,160int row, int col)161{162int i;163164switch (doAlpha) {165case CVT_COPY:166for (i = 0; i < numSamples; ++i) {167putRGBADither(getRGBA(pSrc, srcFormat), pDst, dstFormat,168row, col++);169INCPN(byte_t, pSrc, incSrc);170INCPN(byte_t, pDst, incDst);171}172break;173case CVT_ALPHATEST:174for (i = 0; i < numSamples; ++i) {175rgbquad_t color = getRGBA(pSrc, srcFormat);176177if (color >= ALPHA_THRESHOLD) { // test for alpha component >50%. that's an extra branch, and it's bad...178putRGBADither(color, pDst, dstFormat, row, col++);179}180INCPN(byte_t, pSrc, incSrc);181INCPN(byte_t, pDst, incDst);182}183break;184case CVT_BLEND:185for (i = 0; i < numSamples; ++i) {186rgbquad_t src = getRGBA(pSrc, srcFormat);187rgbquad_t src2 = getRGBA(pSrc2, srcFormat);188189putRGBADither(blendRGB(src, src2,190QUAD_ALPHA(src2)) | (src & QUAD_ALPHA_MASK), pDst, dstFormat,191row, col++);192INCPN(byte_t, pSrc, incSrc);193INCPN(byte_t, pDst, incDst);194INCPN(byte_t, pSrc2, incSrc2);195}196break;197}198}199200/* initialize ImageRect structure according to function arguments */201void202initRect(ImageRect * pRect, int x, int y, int width, int height, int jump,203int stride, void *pBits, ImageFormat * format)204{205int depthBytes = format->depthBytes;206207pRect->pBits = pBits;208INCPN(byte_t, pRect->pBits, (intptr_t) y * stride + x * depthBytes);209pRect->numLines = height;210pRect->numSamples = width;211pRect->stride = stride * jump;212pRect->depthBytes = depthBytes;213pRect->format = format;214pRect->row = y;215pRect->col = x;216pRect->jump = jump;217}218219/* copy image rectangle from source to destination, or from two sources with blending */220221int222convertRect(ImageRect * pSrcRect, ImageRect * pDstRect, int mode)223{224return convertRect2(pSrcRect, pDstRect, mode, NULL);225}226227int228convertRect2(ImageRect * pSrcRect, ImageRect * pDstRect, int mode,229ImageRect * pSrcRect2)230{231int numLines = pSrcRect->numLines;232int numSamples = pSrcRect->numSamples;233void *pSrc = pSrcRect->pBits;234void *pDst = pDstRect->pBits;235void *pSrc2 = NULL;236int j, row;237238if (pDstRect->numLines < numLines)239numLines = pDstRect->numLines;240if (pDstRect->numSamples < numSamples) {241numSamples = pDstRect->numSamples;242}243if (pSrcRect2) {244if (pSrcRect2->numLines < numLines) {245numLines = pSrcRect2->numLines;246}247if (pSrcRect2->numSamples < numSamples) {248numSamples = pSrcRect2->numSamples;249}250pSrc2 = pSrcRect2->pBits;251}252row = pDstRect->row;253for (j = 0; j < numLines; j++) {254convertLine(pSrc, pSrcRect->depthBytes, pDst, pDstRect->depthBytes,255numSamples, pSrcRect->format, pDstRect->format, mode,256pSrc2, pSrcRect2 ? pSrcRect2->depthBytes : 0,257pSrcRect2 ? pSrcRect2->format : 0, row, pDstRect->col);258INCPN(byte_t, pSrc, pSrcRect->stride);259INCPN(byte_t, pDst, pDstRect->stride);260if (pSrcRect2) {261INCPN(byte_t, pSrc2, pSrcRect2->stride);262}263row += pDstRect->jump;264}265return numLines * pSrcRect->stride;266}267268int269fillRect(rgbquad_t color, ImageRect * pDstRect)270{271int numLines = pDstRect->numLines;272int numSamples = pDstRect->numSamples;273void *pDst = pDstRect->pBits;274int j, row;275276row = pDstRect->row;277for (j = 0; j < numLines; j++) {278fillLine(color, pDst, pDstRect->depthBytes, numSamples,279pDstRect->format, row, pDstRect->col);280INCPN(byte_t, pDst, pDstRect->stride);281row += pDstRect->jump;282}283return numLines * pDstRect->stride;284}285286/* init the masks; all other parameters are initialized to default values */287void288initFormat(ImageFormat * format, int redMask, int greenMask, int blueMask,289int alphaMask)290{291int i, shift, numBits;292293format->byteOrder = BYTE_ORDER_NATIVE;294format->colorMap = NULL;295format->depthBytes = 4;296format->fixedBits = 0;297format->premultiplied = 0;298format->mask[0] = blueMask;299format->mask[1] = greenMask;300format->mask[2] = redMask;301format->mask[3] = alphaMask;302for (i = 0; i < 4; i++) {303getMaskShift(format->mask[i], &shift, &numBits);304format->shift[i] = shift + numBits - i * 8 - 8;305}306}307308/* dump the visual format */309void310dumpFormat(ImageFormat * format)311{312#ifdef _DEBUG313int i;314315printf("byteorder=%d colormap=%08x depthBytes=%d fixedBits=%08x transparentColor=%u ",316format->byteOrder, (unsigned) format->colorMap, format->depthBytes,317(unsigned) format->fixedBits, (unsigned) format->transparentColor);318for (i = 0; i < 4; i++) {319printf("mask[%d]=%08x shift[%d]=%d\n", i, (unsigned) format->mask[i], i,320format->shift[i]);321}322printf("\n");323#endif324}325326/* optimize the format */327void328optimizeFormat(ImageFormat * format)329{330if (platformByteOrder() == format->byteOrder && format->depthBytes != 3) {331format->byteOrder = BYTE_ORDER_NATIVE;332}333/* FIXME: some advanced optimizations are possible, especially for format pairs */334}335336int337platformByteOrder()338{339int test = 1;340341*(char *) &test = 0;342return test ? BYTE_ORDER_MSBFIRST : BYTE_ORDER_LSBFIRST;343}344345346