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

ColourGradient: Create lookup tables using non-premultiplied colours

The OpenGL renderer uses ColourGradient::createLookupTable to generate
gradient textures. However, the tweening method used was different to
the tweening used by CoreGraphics gradients, and by the software
renderer.

Gradient tweening is now computed using non-premultiplied colours, to
ensure consistency between gradients rendered using OpenGL, and with
other renderers.
This commit is contained in:
reuk 2023-02-07 13:58:49 +00:00
parent 9cfbccca8e
commit a59cba010b
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C
6 changed files with 61 additions and 17 deletions

View file

@ -291,13 +291,18 @@ Colour::Colour (PixelAlpha alpha) noexcept
}
//==============================================================================
const PixelARGB Colour::getPixelARGB() const noexcept
PixelARGB Colour::getPixelARGB() const noexcept
{
PixelARGB p (argb);
p.premultiply();
return p;
}
PixelARGB Colour::getNonPremultipliedPixelARGB() const noexcept
{
return argb;
}
uint32 Colour::getARGB() const noexcept
{
return argb.getInARGBMaskOrder();

View file

@ -194,7 +194,11 @@ public:
/** Returns a premultiplied ARGB pixel object that represents this colour.
*/
const PixelARGB getPixelARGB() const noexcept;
PixelARGB getPixelARGB() const noexcept;
/** Returns an ARGB pixel object that represents this colour.
*/
PixelARGB getNonPremultipliedPixelARGB() const noexcept;
/** Returns a 32-bit integer that represents this colour.

View file

@ -201,29 +201,28 @@ void ColourGradient::createLookupTable (PixelARGB* const lookupTable, const int
jassert (numEntries > 0);
jassert (colours.getReference(0).position == 0.0); // The first colour specified has to go at position 0
auto pix1 = colours.getReference (0).colour.getPixelARGB();
int index = 0;
for (int j = 1; j < colours.size(); ++j)
for (int j = 0; j < colours.size() - 1; ++j)
{
auto& p = colours.getReference (j);
auto numToDo = roundToInt (p.position * (numEntries - 1)) - index;
auto pix2 = p.colour.getPixelARGB();
const auto& o = colours.getReference (j + 0);
const auto& p = colours.getReference (j + 1);
const auto numToDo = roundToInt (p.position * (numEntries - 1)) - index;
const auto pix1 = o.colour.getNonPremultipliedPixelARGB();
const auto pix2 = p.colour.getNonPremultipliedPixelARGB();
for (int i = 0; i < numToDo; ++i)
for (auto i = 0; i < numToDo; ++i)
{
jassert (index >= 0 && index < numEntries);
auto blended = pix1;
blended.tween (pix2, (uint32) ((i << 8) / numToDo));
blended.premultiply();
lookupTable[index] = pix1;
lookupTable[index].tween (pix2, (uint32) ((i << 8) / numToDo));
++index;
jassert (0 <= index && index < numEntries);
lookupTable[index++] = blended;
}
pix1 = pix2;
}
while (index < numEntries)
lookupTable [index++] = pix1;
std::fill (lookupTable + index, lookupTable + numEntries, colours.getLast().colour.getPixelARGB());
}
int ColourGradient::createLookupTable (const AffineTransform& transform, HeapBlock<PixelARGB>& lookupTable) const

View file

@ -185,6 +185,17 @@ public:
*/
void createLookupTable (PixelARGB* resultLookupTable, int numEntries) const noexcept;
/** Creates a set of interpolated premultiplied ARGB values.
This will fill an array of a user-specified size with the gradient, interpolating to fit.
When calling this, the ColourGradient must have at least 2 colour stops specified.
*/
template <size_t NumEntries>
void createLookupTable (PixelARGB (&resultLookupTable)[NumEntries]) const noexcept
{
static_assert (NumEntries != 0);
createLookupTable (resultLookupTable, NumEntries);
}
/** Returns true if all colours are opaque. */
bool isOpaque() const noexcept;