/*
  ==============================================================================

   This file is part of the JUCE library - "Jules' Utility Class Extensions"
   Copyright 2004-6 by Raw Material Software ltd.

  ------------------------------------------------------------------------------

   JUCE can be redistributed and/or modified under the terms of the
   GNU General Public License, as published by the Free Software Foundation;
   either version 2 of the License, or (at your option) any later version.

   JUCE 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 JUCE; if not, visit www.gnu.org/licenses or write to the
   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
   Boston, MA 02111-1307 USA

  ------------------------------------------------------------------------------

   If you'd like to release a closed-source product which uses JUCE, commercial
   licenses are also available: visit www.rawmaterialsoftware.com/juce for
   more information.

  ==============================================================================
*/

#include "../../../../juce_core/basics/juce_StandardHeader.h"

BEGIN_JUCE_NAMESPACE


#include "juce_ColourGradient.h"


//==============================================================================
ColourGradient::ColourGradient()
    : colours (4)
{
}

ColourGradient::ColourGradient (const Colour& colour1,
                                const float x1_,
                                const float y1_,
                                const Colour& colour2,
                                const float x2_,
                                const float y2_,
                                const bool isRadial_)
    : x1 (x1_),
      y1 (y1_),
      x2 (x2_),
      y2 (y2_),
      isRadial (isRadial_),
      colours (4)
{
    colours.add (0);
    colours.add (colour1.getPixelARGB().getARGB());

    colours.add (1 << 16);
    colours.add (colour2.getPixelARGB().getARGB());
}

ColourGradient::~ColourGradient()
{
}

//==============================================================================
void ColourGradient::clearColours()
{
    colours.clear();
}

void ColourGradient::addColour (const double proportionAlongGradient,
                                const Colour& colour)
{
    // must be within the two end-points
    jassert (proportionAlongGradient >= 0 && proportionAlongGradient <= 1.0);

    const uint32 pos = jlimit (0, 65535, roundDoubleToInt (proportionAlongGradient * 65536.0));

    int i;
    for (i = 0; i < colours.size(); i += 2)
        if (colours.getUnchecked(i) > pos)
            break;

    colours.insert (i, pos);
    colours.insert (i + 1, colour.getPixelARGB().getARGB());
}

void ColourGradient::multiplyOpacity (const float multiplier)
{
    for (int i = 1; i < colours.size(); i += 2)
    {
        PixelARGB pix (colours.getUnchecked(i));
        pix.multiplyAlpha (multiplier);
        colours.set (i, pix.getARGB());
    }
}

//==============================================================================
PixelARGB* ColourGradient::createLookupTable (int& numEntries) const
{
    const int numColours = colours.size() >> 1;
    const double distance = juce_hypot (x1 - x2, y1 - y2);
    numEntries = jlimit (1, (numColours - 1) << 8, 3 * (int) distance);

    PixelARGB* const lookupTable = (PixelARGB*) juce_calloc (numEntries * sizeof (PixelARGB));

    if (numColours < 2)
    {
        jassertfalse // not enough colours have been specified!
    }
    else
    {
        jassert (colours.getUnchecked (0) == 0); // the first colour specified has to go at position 0

        PixelARGB pix1 (colours.getUnchecked (1));
        int index = 0;

        for (int i = 2; i < colours.size(); i += 2)
        {
            const int numToDo = ((colours.getUnchecked (i) * numEntries) >> 16) - index;
            const PixelARGB pix2 (colours.getUnchecked (i + 1));

            for (int i = 0; i < numToDo; ++i)
            {
                jassert (index >= 0 && index < numEntries);

                lookupTable[index] = pix1;
                lookupTable[index].tween (pix2, (i << 8) / numToDo);
                ++index;
            }

            pix1 = pix2;
        }
    }

    return lookupTable;
}

bool ColourGradient::isOpaque() const
{
    for (int i = 1; i < colours.size(); i += 2)
        if (PixelARGB (colours.getUnchecked(i)).getAlpha() < 0xff)
            return false;

    return true;
}


END_JUCE_NAMESPACE
