/*
 * Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

#include "splashscreen_gfx_impl.h"

/* *INDENT-OFF* */
const byte_t baseDitherMatrix[DITHER_SIZE][DITHER_SIZE] = {
  /* Bayer's order-4 dither array.  Generated by the code given in
   * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I.
   */
  {   0,192, 48,240, 12,204, 60,252,  3,195, 51,243, 15,207, 63,255 },
  { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
  {  32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
  { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
  {   8,200, 56,248,  4,196, 52,244, 11,203, 59,251,  7,199, 55,247 },
  { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
  {  40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
  { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
  {   2,194, 50,242, 14,206, 62,254,  1,193, 49,241, 13,205, 61,253 },
  { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
  {  34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
  { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
  {  10,202, 58,250,  6,198, 54,246,  9,201, 57,249,  5,197, 53,245 },
  { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
  {  42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
  { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
};
/* *INDENT-ON* */

// FIXME: tinting on some colormaps (e.g. 1-2-1) means something is slightly wrong with
// colormap calculation... probably it's some rounding error

/*  calculates the colorTable for mapping from 0..255 to 0..numColors-1
    also calculates the dithering matrix, scaling baseDitherMatrix accordingly */
void
initDither(DitherSettings * pDither, int numColors, int scale)
{
    int i, j;

    pDither->numColors = numColors;
    for (i = 0; i < (MAX_COLOR_VALUE + 1) * 2; i++) {
        pDither->colorTable[i] =
            (((i > MAX_COLOR_VALUE) ? MAX_COLOR_VALUE : i) *
             (numColors - 1) / MAX_COLOR_VALUE) * scale;
    }
    for (i = 0; i < DITHER_SIZE; i++)
        for (j = 0; j < DITHER_SIZE; j++)
            pDither->matrix[i][j] =
                (int) baseDitherMatrix[i][j] / (numColors - 1);
}

/* scale a number on the range of 0..numColorsIn-1 to 0..numColorsOut-1
 0 maps to 0 and numColorsIn-1 maps to numColorsOut-1
 intermediate values are spread evenly between 0 and numColorsOut-1 */
INLINE int
scaleColor(int color, int numColorsIn, int numColorsOut)
{
    return (color * (numColorsOut - 1) + (numColorsIn - 1) / 2)
        / (numColorsIn - 1);
}

/*  build a colormap for a color cube and a dithering matrix. color cube is quantized
    according to the provided maximum number of colors */
int
quantizeColors(int maxNumColors, int *numColors)
{

    // static const int scale[3]={10000/11,10000/69,10000/30};
    // FIXME: sort out the adaptive color cube subdivision... realistic 11:69:30 is good on photos,
    // but would be bad on other pictures. A stupid approximation is used now.

    static const int scale[3] = { 8, 4, 6 };

    // maxNumColors should be at least 2x2x2=8, or we lose some color components completely
    numColors[0] = numColors[1] = numColors[2] = 2;

    while (1) {
        int idx[3] = { 0, 1, 2 };
        /* bubble sort the three indexes according to scaled numColors values */
#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; }
        SORT(0, 1);
        SORT(1, 2);
        SORT(0, 1);
        /* try increasing numColors for the first color */
        if ((numColors[idx[0]] + 1) * numColors[idx[1]] *
            numColors[idx[2]] <= maxNumColors) {
                numColors[idx[0]]++;
        } else if (numColors[idx[0]] * (numColors[idx[1]] + 1) *
            numColors[idx[2]] <= maxNumColors) {
            numColors[idx[1]]++;
        } else if (numColors[idx[0]] * numColors[idx[1]] *
            (numColors[idx[2]] + 1) <= maxNumColors) {
            numColors[idx[2]]++;
        } else {
            break;
        }
    }
    return numColors[0] * numColors[1] * numColors[2];
}

void
initColorCube(int *numColors, rgbquad_t * pColorMap, DitherSettings * pDithers,
              rgbquad_t * colorIndex)
{
    int r, g, b, n;

    n = 0;
    for (r = 0; r < numColors[2]; r++) {
        for (g = 0; g < numColors[1]; g++)
            for (b = 0; b < numColors[0]; b++) {
                pColorMap[colorIndex[n++]] =
                    scaleColor(b, numColors[0], MAX_COLOR_VALUE) +
                    (scaleColor(g, numColors[1], MAX_COLOR_VALUE) << 8) +
                    (scaleColor(r, numColors[2], MAX_COLOR_VALUE) << 16);
            }
    }
    initDither(pDithers + 0, numColors[0], 1);
    initDither(pDithers + 1, numColors[1], numColors[0]);
    initDither(pDithers + 2, numColors[2], numColors[1] * numColors[0]);
}

/*
    the function below is a line conversion loop

    incSrc and incDst are pSrc and pDst increment values for the loop, in bytes
    mode defines how the pixels should be processed

    mode==CVT_COPY means the pixels should be copied as is
    mode==CVT_ALPHATEST means pixels should be skipped when source pixel alpha is above the threshold
    mode==CVT_BLEND means alpha blending between source and destination should be performed, while
    destination alpha should be retained. source alpha is used for blending.
*/
void
convertLine(void *pSrc, int incSrc, void *pDst, int incDst, int numSamples,
            ImageFormat * srcFormat, ImageFormat * dstFormat, int doAlpha,
            void *pSrc2, int incSrc2, ImageFormat * srcFormat2,
            int row, int col)
{
    int i;

    switch (doAlpha) {
    case CVT_COPY:
        for (i = 0; i < numSamples; ++i) {
            putRGBADither(getRGBA(pSrc, srcFormat), pDst, dstFormat,
                row, col++);
            INCPN(byte_t, pSrc, incSrc);
            INCPN(byte_t, pDst, incDst);
        }
        break;
    case CVT_ALPHATEST:
        for (i = 0; i < numSamples; ++i) {
            rgbquad_t color = getRGBA(pSrc, srcFormat);

            if (color >= ALPHA_THRESHOLD) {     // test for alpha component >50%. that's an extra branch, and it's bad...
                putRGBADither(color, pDst, dstFormat, row, col++);
            }
            INCPN(byte_t, pSrc, incSrc);
            INCPN(byte_t, pDst, incDst);
        }
        break;
    case CVT_BLEND:
        for (i = 0; i < numSamples; ++i) {
            rgbquad_t src = getRGBA(pSrc, srcFormat);
            rgbquad_t src2 = getRGBA(pSrc2, srcFormat);

            putRGBADither(blendRGB(src, src2,
                QUAD_ALPHA(src2)) | (src & QUAD_ALPHA_MASK), pDst, dstFormat,
                row, col++);
            INCPN(byte_t, pSrc, incSrc);
            INCPN(byte_t, pDst, incDst);
            INCPN(byte_t, pSrc2, incSrc2);
        }
        break;
    }
}

/* initialize ImageRect structure according to function arguments */
void
initRect(ImageRect * pRect, int x, int y, int width, int height, int jump,
         int stride, void *pBits, ImageFormat * format)
{
    int depthBytes = format->depthBytes;

    pRect->pBits = pBits;
    INCPN(byte_t, pRect->pBits, y * stride + x * depthBytes);
    pRect->numLines = height;
    pRect->numSamples = width;
    pRect->stride = stride * jump;
    pRect->depthBytes = depthBytes;
    pRect->format = format;
    pRect->row = y;
    pRect->col = x;
    pRect->jump = jump;
}

/*  copy image rectangle from source to destination, or from two sources with blending */

int
convertRect(ImageRect * pSrcRect, ImageRect * pDstRect, int mode)
{
    return convertRect2(pSrcRect, pDstRect, mode, NULL);
}

int
convertRect2(ImageRect * pSrcRect, ImageRect * pDstRect, int mode,
             ImageRect * pSrcRect2)
{
    int numLines = pSrcRect->numLines;
    int numSamples = pSrcRect->numSamples;
    void *pSrc = pSrcRect->pBits;
    void *pDst = pDstRect->pBits;
    void *pSrc2 = NULL;
    int j, row;

    if (pDstRect->numLines < numLines)
        numLines = pDstRect->numLines;
    if (pDstRect->numSamples < numSamples) {
        numSamples = pDstRect->numSamples;
    }
    if (pSrcRect2) {
        if (pSrcRect2->numLines < numLines) {
            numLines = pSrcRect2->numLines;
        }
        if (pSrcRect2->numSamples < numSamples) {
            numSamples = pSrcRect2->numSamples;
        }
        pSrc2 = pSrcRect2->pBits;
    }
    row = pDstRect->row;
    for (j = 0; j < numLines; j++) {
        convertLine(pSrc, pSrcRect->depthBytes, pDst, pDstRect->depthBytes,
            numSamples, pSrcRect->format, pDstRect->format, mode,
            pSrc2, pSrcRect2 ? pSrcRect2->depthBytes : 0,
            pSrcRect2 ? pSrcRect2->format : 0, row, pDstRect->col);
        INCPN(byte_t, pSrc, pSrcRect->stride);
        INCPN(byte_t, pDst, pDstRect->stride);
        if (pSrcRect2) {
            INCPN(byte_t, pSrc2, pSrcRect2->stride);
        }
        row += pDstRect->jump;
    }
    return numLines * pSrcRect->stride;
}

int
fillRect(rgbquad_t color, ImageRect * pDstRect)
{
    int numLines = pDstRect->numLines;
    int numSamples = pDstRect->numSamples;
    void *pDst = pDstRect->pBits;
    int j, row;

    row = pDstRect->row;
    for (j = 0; j < numLines; j++) {
        fillLine(color, pDst, pDstRect->depthBytes, numSamples,
            pDstRect->format, row, pDstRect->col);
        INCPN(byte_t, pDst, pDstRect->stride);
        row += pDstRect->jump;
    }
    return numLines * pDstRect->stride;
}

/* init the masks; all other parameters are initialized to default values */
void
initFormat(ImageFormat * format, int redMask, int greenMask, int blueMask,
           int alphaMask)
{
    int i, shift, numBits;

    format->byteOrder = BYTE_ORDER_NATIVE;
    format->colorMap = NULL;
    format->depthBytes = 4;
    format->fixedBits = 0;
    format->premultiplied = 0;
    format->mask[0] = blueMask;
    format->mask[1] = greenMask;
    format->mask[2] = redMask;
    format->mask[3] = alphaMask;
    for (i = 0; i < 4; i++) {
        getMaskShift(format->mask[i], &shift, &numBits);
        format->shift[i] = shift + numBits - i * 8 - 8;
    }
}

/* dump the visual format */
void
dumpFormat(ImageFormat * format)
{
#ifdef _DEBUG
    int i;

    printf("byteorder=%d colormap=%08x depthBytes=%d fixedBits=%08x transparentColor=%u ",
        format->byteOrder, (unsigned) format->colorMap, format->depthBytes,
        (unsigned) format->fixedBits, (unsigned) format->transparentColor);
    for (i = 0; i < 4; i++) {
        printf("mask[%d]=%08x shift[%d]=%d\n", i, (unsigned) format->mask[i], i,
            format->shift[i]);
    }
    printf("\n");
#endif
}

/* optimize the format */
void
optimizeFormat(ImageFormat * format)
{
    if (platformByteOrder() == format->byteOrder && format->depthBytes != 3) {
        format->byteOrder = BYTE_ORDER_NATIVE;
    }
    /* FIXME: some advanced optimizations are possible, especially for format pairs */
}

int
platformByteOrder()
{
    int test = 1;

    *(char *) &test = 0;
    return test ? BYTE_ORDER_MSBFIRST : BYTE_ORDER_LSBFIRST;
}
