1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00
JUCE/src/gui/graphics/colour/juce_ColourGradient.cpp

213 lines
6.5 KiB
C++

/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-9 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
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.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#include "../../../core/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
#include "juce_ColourGradient.h"
//==============================================================================
ColourGradient::ColourGradient() throw()
{
#ifdef JUCE_DEBUG
x1 = 987654.0f;
#endif
}
ColourGradient::ColourGradient (const Colour& colour1,
const float x1_,
const float y1_,
const Colour& colour2,
const float x2_,
const float y2_,
const bool isRadial_) throw()
: x1 (x1_),
y1 (y1_),
x2 (x2_),
y2 (y2_),
isRadial (isRadial_)
{
colours.add (0);
colours.add (colour1.getARGB());
colours.add (1 << 16);
colours.add (colour2.getARGB());
}
ColourGradient::~ColourGradient() throw()
{
}
//==============================================================================
void ColourGradient::clearColours() throw()
{
colours.clear();
}
void ColourGradient::addColour (const double proportionAlongGradient,
const Colour& colour) throw()
{
// must be within the two end-points
jassert (proportionAlongGradient >= 0 && proportionAlongGradient <= 1.0);
const uint32 pos = jlimit (0, 65535, roundToInt (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.getARGB());
}
void ColourGradient::multiplyOpacity (const float multiplier) throw()
{
for (int i = 1; i < colours.size(); i += 2)
{
const Colour c (colours.getUnchecked(i));
colours.set (i, c.withMultipliedAlpha (multiplier).getARGB());
}
}
//==============================================================================
int ColourGradient::getNumColours() const throw()
{
return colours.size() >> 1;
}
double ColourGradient::getColourPosition (const int index) const throw()
{
return jlimit (0.0, 1.0, colours [index << 1] / 65535.0);
}
const Colour ColourGradient::getColour (const int index) const throw()
{
return Colour (colours [(index << 1) + 1]);
}
const Colour ColourGradient::getColourAtPosition (const float position) const throw()
{
jassert (colours.getUnchecked (0) == 0); // the first colour specified has to go at position 0
const int integerPos = jlimit (0, 65535, roundToInt (position * 65536.0f));
if (integerPos <= 0 || colours.size() <= 2)
return getColour (0);
int i = colours.size() - 2;
while (integerPos < (int) colours.getUnchecked(i))
i -= 2;
if (i >= colours.size() - 2)
return Colour (colours.getUnchecked(i));
const int pos1 = colours.getUnchecked (i);
const Colour col1 (colours.getUnchecked (i + 1));
const int pos2 = colours.getUnchecked (i + 2);
const Colour col2 (colours.getUnchecked (i + 3));
return col1.interpolatedWith (col2, (integerPos - pos1) / (float) (pos2 - pos1));
}
//==============================================================================
int ColourGradient::createLookupTable (const AffineTransform& transform, HeapBlock <PixelARGB>& lookupTable) const throw()
{
#ifdef JUCE_DEBUG
// trying to use the object without setting its co-ordinates? Have a careful read of
// the comments for the constructors.
jassert (x1 != 987654.0f);
#endif
const int numColours = colours.size() >> 1;
float tx1 = x1, ty1 = y1, tx2 = x2, ty2 = y2;
transform.transformPoint (tx1, ty1);
transform.transformPoint (tx2, ty2);
const double distance = juce_hypot (tx1 - tx2, ty1 - ty2);
const int numEntries = jlimit (1, (numColours - 1) << 8, 3 * (int) distance);
lookupTable.malloc (numEntries);
if (numColours >= 2)
{
jassert (colours.getUnchecked (0) == 0); // the first colour specified has to go at position 0
PixelARGB pix1 (colours.getUnchecked (1));
pix1.premultiply();
int index = 0;
for (int j = 2; j < colours.size(); j += 2)
{
const int numToDo = ((colours.getUnchecked (j) * (numEntries - 1)) >> 16) - index;
PixelARGB pix2 (colours.getUnchecked (j + 1));
pix2.premultiply();
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;
}
while (index < numEntries)
lookupTable [index++] = pix1;
}
else
{
jassertfalse // no colours specified!
}
return numEntries;
}
bool ColourGradient::isOpaque() const throw()
{
for (int i = 1; i < colours.size(); i += 2)
if (PixelARGB (colours.getUnchecked(i)).getAlpha() < 0xff)
return false;
return true;
}
bool ColourGradient::isInvisible() const throw()
{
for (int i = 1; i < colours.size(); i += 2)
if (PixelARGB (colours.getUnchecked(i)).getAlpha() > 0)
return false;
return true;
}
END_JUCE_NAMESPACE