/*
 * Copyright (c) 2001, 2008, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include "awt.h"
#include "awt_Palette.h"
#include "awt_Component.h"
#include "img_util_md.h"
#include "awt_CustomPaletteDef.h"
#include "Trace.h"

BOOL AwtPalette::m_useCustomPalette = TRUE;

#define ERROR_GRAY (-1)
#define NON_GRAY 0
#define LINEAR_STATIC_GRAY 1
#define NON_LINEAR_STATIC_GRAY 2

/**
 * Select the palette into the given HDC.  This will
 * allow operations using this HDC to access the palette
 * colors/indices.
 */
HPALETTE AwtPalette::Select(HDC hDC)
{
    HPALETTE prevPalette = NULL;
    if (logicalPalette) {
        BOOL background = !(m_useCustomPalette);
        prevPalette = ::SelectPalette(hDC, logicalPalette, background);
    }
    return prevPalette;
}

/**
 * Realize the palette of the given HDC.  This will attempt to
 * install the palette of the HDC onto the device associated with
 * that HDC.
 */
void AwtPalette::Realize(HDC hDC)
{
    if (logicalPalette) {
        if (!m_useCustomPalette ||
            AwtComponent::QueryNewPaletteCalled() ||
            AwtToolkit::GetInstance().HasDisplayChanged()) {
            // Fix for bug 4178909, workaround for Windows bug.  Shouldn't
            // do a RealizePalette until the first QueryNewPalette message
            // has been processed.
            // But if we are switching the primary monitor from non-8bpp
            // to 8bpp mode, we may not get any palette messages during
            // the display change event.  Go ahead and realize the palette
            // now anyway in this situation.  This was especially noticeable
            // on win2k in multimon.  Note that there still seems to be some
            // problem with actually setting the palette on the primary
            // screen until after QNP is called, but at least the
            // secondary devices can correctly realize the palette.
            ::RealizePalette(hDC);
        }
    }
}

/**
 * Disable the use of our custom palette.  This method is called
 * during initialization if we detect that we are running inside
 * the plugin; we do not want to clobber our parent application's
 * palette with our own in that situation.
 */
void AwtPalette::DisableCustomPalette()
{
    m_useCustomPalette = FALSE;
}

/**
 * Returns whether we are currently using a custom palette.  Used
 * by AwtWin32GraphicsDevice when creating the colorModel of the
 * device.
 */
BOOL AwtPalette::UseCustomPalette()
{
    return m_useCustomPalette;
}


/**
 * Constructor.  Initialize the system and logical palettes.
 * used by this object.
 */
AwtPalette::AwtPalette(AwtWin32GraphicsDevice *device)
{
    this->device = device;
    Update();
    UpdateLogical();
}

/**
 * Retrieves system palette entries. Includes a workaround for for some
 * video drivers which may not support the GSPE call but may return
 * valid values from this procedure.
 */
int AwtPalette::FetchPaletteEntries(HDC hDC, PALETTEENTRY* pPalEntries)
{
    LOGPALETTE* pLogPal = 0;
    HPALETTE hPal = 0;
    HPALETTE hPalOld = 0;
    int numEntries;

    numEntries = ::GetSystemPaletteEntries(hDC, 0, 256, pPalEntries);

    if (numEntries > 0) {
        return numEntries;
    }
    // Workaround: some drivers do not support GetSysPalEntries

    pLogPal = (LOGPALETTE*) new char[sizeof(LOGPALETTE)
                                    + 256*sizeof(PALETTEENTRY)];
    if (pLogPal == NULL) {
        return 0;
    }

    pLogPal->palVersion = 0x300;
    pLogPal->palNumEntries = 256;
    int iEntry;
    PALETTEENTRY* pEntry;
    for (iEntry = 0; iEntry < 256; iEntry++) {
        pEntry = pLogPal->palPalEntry + iEntry;
        pEntry->peRed = iEntry;
        pEntry->peGreen = pEntry->peBlue = 0;
        pEntry->peFlags = PC_EXPLICIT;
    }
    hPal = ::CreatePalette(pLogPal);
    delete pLogPal;
    if ( hPal == 0 ) {
        return 0;
    }

    hPalOld = ::SelectPalette(hDC, hPal, 1);
    if (hPalOld == 0) {
        ::DeleteObject(hPal);
        return 0;
    }
    ::RealizePalette(hDC);

    COLORREF rgb;
    for (iEntry = 0; iEntry < 256; iEntry++) {
        rgb = ::GetNearestColor(hDC, PALETTEINDEX(iEntry));
        pPalEntries[iEntry].peRed = GetRValue(rgb);
        pPalEntries[iEntry].peGreen = GetGValue(rgb);
        pPalEntries[iEntry].peBlue = GetBValue(rgb);
    }

    ::SelectPalette(hDC, hPalOld, 0 );
    ::DeleteObject(hPal);
    ::RealizePalette(hDC);

    return 256;
}

int AwtPalette::GetGSType(PALETTEENTRY* pPalEntries)
{
    int isGray = 1;
    int isLinearStaticGray = 1;
    int isNonLinearStaticGray = 1;
    int iEntry;
    char bUsed[256];
    BYTE r, g, b;

    memset(bUsed, 0, sizeof(bUsed));
    for (iEntry = 0; iEntry < 256; iEntry++) {
        r = pPalEntries[iEntry].peRed;
        g = pPalEntries[iEntry].peGreen;
        b = pPalEntries[iEntry].peBlue;
        if (r != g || r != b) {
            isGray = 0;
            break;
        } else {
            // the values are gray
            if (r != iEntry) {
                // it's not linear
                // but it could be non-linear static gray
                isLinearStaticGray = 0;
            }
            bUsed[r] = 1;
        }
    }

    if (isGray && !isLinearStaticGray) {
        // check if all 256 grays are there
        // if that's the case, it's non-linear static gray
        for (iEntry = 0; iEntry < 256; iEntry++ ) {
            if (!bUsed[iEntry]) {
                // not non-linear (not all 256 colors are used)
                isNonLinearStaticGray = 0;
                break;
            }
        }
    }

    if (!isGray) {
        J2dTraceLn(J2D_TRACE_INFO,
                   "Detected palette: NON_GRAY/USER-MODIFIABLE");
        return NON_GRAY;
    }
    if (isLinearStaticGray) {
        J2dTraceLn(J2D_TRACE_INFO,
                   "Detected palette: LINEAR_STATIC_GRAY");
        return LINEAR_STATIC_GRAY;
    }
    if (isNonLinearStaticGray) {
        J2dTraceLn(J2D_TRACE_INFO,
                   "Detected palette: NON_LINEAR_STATIC_GRAY");
        return NON_LINEAR_STATIC_GRAY;
    }

    J2dTraceLn(J2D_TRACE_ERROR,
               "Unable to detect palette type, non-gray is assumed");
    // not supposed to be here, error
    return ERROR_GRAY;
}

/**
 * Updates our system palette variables to make sure they match
 * the current state of the actual system palette.  This method
 * is called during AwtPalette creation and after palette changes.
 * Return whether there were any palette changes from the previous
 * system palette.
 */
BOOL AwtPalette::Update()
{
    PALETTEENTRY pe[256];
    int numEntries = 0;
    int bitsPerPixel;
    int i;
    HDC hDC;

    hDC = device->GetDC();
    if (!hDC) {
        return FALSE;
    }
    bitsPerPixel = ::GetDeviceCaps(hDC, BITSPIXEL);
    device->ReleaseDC(hDC);
    if (8 != bitsPerPixel) {
        return FALSE;
    }

    hDC = device->GetDC();
    numEntries = FetchPaletteEntries(hDC, pe);

    device->ReleaseDC(hDC);

    if ((numEntries == numSystemEntries) &&
        (0 == memcmp(pe, systemEntriesWin32, numEntries * sizeof(PALETTEENTRY))))
    {
        return FALSE;
    }

    // make this system palette the new cached win32 palette
    numEntries = (numEntries > 256)? 256: numEntries;
    memcpy(systemEntriesWin32, pe, numEntries * sizeof(PALETTEENTRY));
    numSystemEntries = numEntries;

    // Create jdk-style system palette
    int startIndex = 0, endIndex = numEntries-1;
    int staticGrayType = GetGSType(systemEntriesWin32);

    if (staticGrayType == LINEAR_STATIC_GRAY) {
        device->SetGrayness(GS_STATICGRAY);
    } else if (staticGrayType == NON_LINEAR_STATIC_GRAY) {
        device->SetGrayness(GS_NONLINGRAY);
    } else if (getenv("FORCEGRAY")) {
        J2dTraceLn(J2D_TRACE_INFO,
                    "Gray Palette Forced via FORCEGRAY");
        // Need to zero first and last ten
        // palette entries. Otherwise in UpdateDynamicColorModel
        // we could set non-gray values to the palette.
        for (i = 0; i < 10; i++) {
            systemEntries[i] = 0x00000000;
            systemEntries[i+246] = 0x00000000;
        }
        numEntries -= 20;
        startIndex = 10;
        endIndex -= 10;
        device->SetGrayness(GS_INDEXGRAY);
    } else {
        device->SetGrayness(GS_NOTGRAY);
    }

    for (i = startIndex; i <= endIndex; i++) {
        systemEntries[i] =  0xff000000
                        | (pe[i].peRed << 16)
                        | (pe[i].peGreen << 8)
                        | (pe[i].peBlue);
    }

    systemInverseLUT =
        initCubemap((int *)systemEntries, numEntries, 32);

    ColorData *cData = device->GetColorData();
    if ((device->GetGrayness() == GS_NONLINGRAY ||
         device->GetGrayness() == GS_INDEXGRAY) &&
        cData != NULL) {

        if (cData->pGrayInverseLutData != NULL) {
            free(cData->pGrayInverseLutData);
            cData->pGrayInverseLutData = NULL;
        }
        initInverseGrayLut((int*)systemEntries, 256, device->GetColorData());
    }

    return TRUE;
}


/**
 * Creates our custom palette based on: the current system palette,
 * the grayscale-ness of the system palette, and the state of the
 * primary device.
 */
void AwtPalette::UpdateLogical()
{
    // Create and initialize a palette
    int nEntries = 256;
    char *buf = NULL;
    buf = new char[sizeof(LOGPALETTE) + nEntries *
        sizeof(PALETTEENTRY)];

    LOGPALETTE *pLogPal = (LOGPALETTE*)buf;
    PALETTEENTRY *pPalEntries = (PALETTEENTRY *)(&(pLogPal->palPalEntry[0]));

    memcpy(pPalEntries, systemEntriesWin32, 256 * sizeof(PALETTEENTRY));

    PALETTEENTRY *pPal = pPalEntries;
    int i;
    int staticGrayType = device->GetGrayness();
    if (staticGrayType == GS_INDEXGRAY) {
        float m = 255.0f / 235.0f;
        float g = 0.5f;
        pPal = &pPalEntries[10];
        for (i = 10; i < 246; i++, pPal++) {
            pPal->peRed = pPal->peGreen = pPal->peBlue =
                (int)g;
            g += m;
            pPal->peFlags = PC_NOCOLLAPSE;
        }
    } else if (staticGrayType == GS_NOTGRAY) {
        for (i = 10; i < 246; i++) {
            pPalEntries[i] = customPalette[i-10];
        }
    }
    pLogPal->palNumEntries = 256;
    pLogPal->palVersion = 0x300;
    logicalPalette = ::CreatePalette(pLogPal);

    for (i = 0; i < nEntries; i++) {
        logicalEntries[i] =  0xff000000
                        | (pPalEntries[i].peRed << 16)
                        | (pPalEntries[i].peGreen << 8)
                        | (pPalEntries[i].peBlue);
    }
    delete [] buf;
}
