initial commit

This commit is contained in:
2026-02-12 00:45:31 -08:00
commit 5f168f370b
3024 changed files with 804889 additions and 0 deletions

View File

@@ -0,0 +1,147 @@
#include "fl/gradient.h"
#include "fl/assert.h"
#include "fl/colorutils.h"
namespace fl {
namespace {
struct Visitor {
Visitor(u8 index) : index(index) {}
void accept(const CRGBPalette16 *palette) {
CRGB c = ColorFromPalette(*palette, index);
return_val = c;
}
void accept(const CRGBPalette32 *palette) {
CRGB c = ColorFromPalette(*palette, index);
return_val = c;
}
void accept(const CRGBPalette256 *palette) {
CRGB c = ColorFromPaletteExtended(*palette, index);
return_val = c;
}
void accept(const Gradient::GradientFunction &func) {
CRGB c = func(index);
return_val = c;
}
template <typename T> void accept(const T &obj) {
// This should never be called, but we need to provide a default
// implementation to avoid compilation errors.
accept(&obj);
}
CRGB return_val;
u8 index;
};
struct VisitorFill {
VisitorFill(span<const u8> indices, span<CRGB> output)
: output(output), indices(indices) {
// This assert was triggering on the corkscrew example. Not sure why
// but the corrective action of taking the min was corrective action.
// FASTLED_ASSERT(
// indices.size() == output.size(),
// "Gradient::fill: indices and output must be the same size"
// "\nSize was" << indices.size() << " and " << output.size());
n = MIN(indices.size(), output.size());
}
void accept(const CRGBPalette16 *palette) {
for (fl::size i = 0; i < n; ++i) {
output[i] = ColorFromPalette(*palette, indices[i]);
}
}
void accept(const CRGBPalette32 *palette) {
for (fl::size i = 0; i < n; ++i) {
output[i] = ColorFromPalette(*palette, indices[i]);
}
}
void accept(const CRGBPalette256 *palette) {
for (fl::size i = 0; i < n; ++i) {
output[i] = ColorFromPaletteExtended(*palette, indices[i]);
}
}
void accept(const Gradient::GradientFunction &func) {
for (fl::size i = 0; i < n; ++i) {
output[i] = func(indices[i]);
}
}
template <typename T> void accept(const T &obj) {
// This should never be called, but we need to provide a default
// implementation to avoid compilation errors.
accept(&obj);
}
span<CRGB> output;
span<const u8> indices;
u8 n = 0;
};
} // namespace
CRGB Gradient::colorAt(u8 index) const {
Visitor visitor(index);
mVariant.visit(visitor);
return visitor.return_val;
}
template <typename T> Gradient::Gradient(T *palette) { set(palette); }
Gradient::Gradient(const Gradient &other) : mVariant(other.mVariant) {}
Gradient::Gradient(Gradient &&other) noexcept
: mVariant(move(other.mVariant)) {}
void Gradient::set(const CRGBPalette32 *palette) { mVariant = palette; }
void Gradient::set(const CRGBPalette256 *palette) { mVariant = palette; }
void Gradient::set(const CRGBPalette16 *palette) { mVariant = palette; }
void Gradient::set(const GradientFunction &func) { mVariant = func; }
Gradient &Gradient::operator=(const Gradient &other) {
if (this != &other) {
mVariant = other.mVariant;
}
return *this;
}
void Gradient::fill(span<const u8> input, span<CRGB> output) const {
VisitorFill visitor(input, output);
mVariant.visit(visitor);
}
CRGB GradientInlined::colorAt(u8 index) const {
Visitor visitor(index);
mVariant.visit(visitor);
return visitor.return_val;
}
void GradientInlined::fill(span<const u8> input,
span<CRGB> output) const {
VisitorFill visitor(input, output);
mVariant.visit(visitor);
}
Gradient::Gradient(const GradientInlined &other) {
// Visitor is cumbersome but guarantees all paths are handled.
struct Copy {
Copy(Gradient &owner) : mOwner(owner) {}
void accept(const CRGBPalette16 &palette) { mOwner.set(&palette); }
void accept(const CRGBPalette32 &palette) { mOwner.set(&palette); }
void accept(const CRGBPalette256 &palette) { mOwner.set(&palette); }
void accept(const GradientFunction &func) { mOwner.set(func); }
Gradient &mOwner;
};
Copy copy_to_self(*this);
other.variant().visit(copy_to_self);
}
} // namespace fl