// $Id: LUTutil-OSX.cpp,v 1.13 2007/10/29 21:42:41 maolimu Exp $
//  Little cms Profiler
// Copyright (C) 2007 Hal Engel
//
// THIS SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
// EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
// WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
//
// IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
// INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
// OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
// LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
// OF THIS SOFTWARE.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program 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 for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// Version 1.11

// FIXME
// Currently this code only works on the Mac's main display:
//
//   CGDirectDisplayID dspID = CGMainDisplayID();
//
// Which is not what needs to happen.  This needs to be changed
// so that the screen value passed into gamma_ramp(int screen)
// when the gamma_ramp object is created is used to get the correct
// GDirectDisplayID for the display device that the calling Qt object
// is on.
//
// OK this should now work but is totally untested and may not even compile.
// need a Mac user to build and test this.

#include "LUTutil.h"

CGPoint point;

CGDirectDisplayID getDisplay()
{
    const int maxDisplays = 64;                  // 64 should be enough for any system
    CGDisplayErr displayStatus;
    CGDisplayCount displayCount;	         // Total number of display IDs
    CGDirectDisplayID displayIDs[maxDisplays];	 // Array of display IDs

    displayStatus = CGGetDisplaysWithPoint ( point, maxDisplays, displayIDs, &displayCount);
    if (displayStatus != kCGErrorSuccess || displayCount!= 1) 
    {
        printf("CGGetDisplaysWithPoint returned error or the wrong number of displays\n");
        return NULL;
    }
    else
        return displayIDs[0];
}

gamma_ramp::gamma_ramp(int Screen, int leftIn, int topIn)
{
    // screen = Screen;
    left = leftIn;
    top = topIn;
    point.y = float(top);
    point.x = float(left);
    
    display = getDisplay();
    screen = 0;
    if (display == NULL)
    {
        ramp_buffer = 0;
        red = 0;
        green = 0;
        blue = 0;
        printf("gamma_ramp::gamma_ramp - error failed to get display handle");
    }
    else
    {    
        size = getGammaRampSize();
        if (size > 0)
        {
            // now allocate the arrays
            ramp_buffer = new ramp_type_private[size*3];
    
            red = new ramp_type[size];
            green = new ramp_type[size];
            blue = new ramp_type[size];
        }
        else
        {
            printf("gamma ramp size not > 0");
            ramp_buffer = 0;
            red = 0;
            green = 0;
            blue = 0;
        }
    }
    // gamma_ramp -> size = 0 indicates
    // that the call to new gamma_ramp failed
}

gamma_ramp::~gamma_ramp()
{
    if (ramp_buffer != 0)
    {
        delete[] red;
        delete[] green;
        delete[] blue;
        delete[] ramp_buffer;
    }
}

int gamma_ramp::getGammaRampSize()
{
//     CGDirectDisplayID dspID = CGMainDisplayID();
// 
//         return CGDisplayGammaTableCapacity(dspID);
    return CGDisplayGammaTableCapacity(display);
}


static ramp_type interpol(ramp_type_private ramp[], int i, int size, int rampsize)
{
        int j = (i * rampsize) / size;
        if (j >= rampsize-1)
                return ramp[rampsize-1];
        else
                return ramp[j] + (ramp[j+1] - ramp[j]) * (double(i * rampsize) / size - j);
}

void gamma_ramp::getGammaRamp()
{
    CGTableCount count;
    CGDisplayErr error_code;
    // CGDirectDisplayID dspID = CGMainDisplayID();

    error_code = CGGetDisplayTransferByTable (display,
                                              (CGTableCount) size,
                                              &ramp_buffer[0],
                                              &ramp_buffer[size],
                                              &ramp_buffer[size*2],
                                              &count);

        for (int i=0; i < size; ++i)
        {
                red[i]   = interpol(ramp_buffer, i, size, count);
                green[i] = interpol(ramp_buffer + size, i, size, count);
                blue[i]  = interpol(ramp_buffer + size*2, i, size, count);
        }
}

void gamma_ramp::setGammaRamp()
{
    CGDisplayErr error_code;
    // CGDirectDisplayID dspID = CGMainDisplayID();

    // convertNormal2Apple(ramp_buffer, red, green, blue, size);
        for (int i=0; i < size; ++i)
        {
                ramp_buffer[i]          = red[i];
                ramp_buffer[size + i]   = green[i];
                ramp_buffer[size*2 + i] = blue[i];
        }

    error_code = CGSetDisplayTransferByTable (display,
                                              (CGTableCount) size,
                                              &ramp_buffer[0],
                                              &ramp_buffer[size],
                                              &ramp_buffer[size*2]);
}




