|
FastLED 3.9.15
|
Directory dependency graph for gfx:Directories | |
| detail | |
| noise | |
Files | |
| _build.cpp.hpp | |
| Unity build for fl/gfx/ — graphics types, primitives, and simulators. | |
| blur.cpp.hpp | |
| blur.h | |
| canvas.h | |
| Canvas types for gfx primitives (implementation) | |
| clear.h | |
| colorutils.cpp.hpp | |
| colorutils.h | |
| Utility functions for color fill, palettes, blending, and more. | |
| colorutils_misc.h | |
| corkscrew.cpp.hpp | |
| corkscrew.h | |
| Corkscrew LED strip projection and rendering. | |
| crgb.h | |
| Defines the 8-bit red, green, and blue (RGB) pixel type in the fl namespace. | |
| crgb16.h | |
| crgb_extra.cpp.hpp | |
| downscale.cpp.hpp | |
| downscale.h | |
| draw_mode.h | |
| draw_visitor.h | |
| eorder.h | |
| fill.cpp.hpp | |
| fill.h | |
| five_bit_hd_gamma.cpp.hpp | |
| five_bit_hd_gamma.h | |
| Declares functions for five-bit gamma correction. | |
| gamma_lut.cpp.hpp | |
| Explicit instantiation of gamma LUT templates. | |
| gamma_lut.h | |
| gfx.h | |
| 2D antialiased graphics for LED matrices | |
| gradient.cpp.hpp | |
| gradient.h | |
| hsv.h | |
| Defines the hue, saturation, and value (HSV) pixel struct. | |
| hsv16.cpp.hpp | |
| hsv16.h | |
| leds.cpp.hpp | |
| leds.h | |
| pixel_iterator.h | |
| pixel_iterator_any.h | |
| primitives.h | |
| raster.h | |
| raster_sparse.cpp.hpp | |
| raster_sparse.h | |
| rectangular_draw_buffer.cpp.hpp | |
| rectangular_draw_buffer.h | |
| rgbw.cpp.hpp | |
| rgbw.h | |
| Functions for red, green, blue, white (RGBW) output. | |
| rgbw_colorimetric.cpp.hpp | |
| Heavy implementations for the colorimetric RGBW solvers (issue #2545). | |
| rgbw_colorimetric.h | |
| Chromaticity-aware RGBW solvers — strict sub-gamut + wx_lp_legacy white extraction + boosted overdrive + LUT + RGBCCT (issue #2545). | |
| rgbw_pixel.h | |
| Simple RGBW pixel data structure for encoders. | |
| rgbww.cpp.hpp | |
| Dispatch + implementations for the 5-channel RGB->RGBWW path (issue #2558, Phase 3 of #2545). | |
| rgbww.h | |
| 5-channel RGB + warm-W + cool-W (RGBWW / RGBCCT) configuration types (issue #2558, Phase 3 of #2545). | |
| rgbww_pixel.h | |
| Raw 5-channel RGBWW pixel data structure for encoders. | |
| sample.cpp.hpp | |
| sample.h | |
| 2D grid sampling with bilinear and nearest-neighbor interpolation | |
| splat.cpp.hpp | |
| splat.h | |
| tile2x2.cpp.hpp | |
| tile2x2.h | |
| upscale.cpp.hpp | |
| upscale.h | |
| xypath.cpp.hpp | |
| xypath.h | |
| xypath_impls.cpp.hpp | |
| xypath_impls.h | |
| xypath_renderer.cpp.hpp | |
| xypath_renderer.h | |
Antialiased lines, circles, and rings on rectangular pixel buffers. One header, four functions, any pixel type.
A canvas wraps a pixel buffer you already have. It doesn't allocate.
That's it. The pixels are written directly into leds[].
Every function takes color first, then coordinates. Coordinates can be float, int, or fixed-point — see Section 5.
Wu-style antialiased line. Diagonal lines get smooth subpixel blending. Axis-aligned lines with integer coords produce crisp 1px strokes.
Solid disc with a soft 1px antialiased edge. Pixels fully inside the radius get full color. Pixels at the boundary get partial brightness.
An annulus (donut). The band runs from innerRadius to innerRadius + thickness. Both edges are antialiased. Pixels inside innerRadius are not touched — the "hole" stays transparent.
A line with width. The thickness is the full width (a thickness of 3 means 1.5px on each side of the centerline). Edges use distance-based falloff for smooth antialiasing.
End cap styles:
| Style | What it does |
|---|---|
FLAT | Ends exactly at the endpoints (default) |
ROUND | Semicircle caps extending past each endpoint |
SQUARE | Rectangle caps extending half-thickness past each endpoint |
CanvasRGB is a convenience alias for Canvas<CRGB>. For other pixel types, use Canvas<T> directly (see Section 7).
Drawing is additive — each draw call adds to what's already there. To start a fresh frame, zero the buffer yourself:
This is intentional. Additive blending lets you layer shapes naturally:
A typical animation loop:
All draw functions are templated on coordinate type. Use whatever fits:
| Type | When to use | Example |
|---|---|---|
float | General purpose, smooth animation | 8.0f, 8.3f |
int | Pixel-aligned geometry, no AA needed | 0, 8, 15, 8 |
fl::s16x16 | No FPU, high precision (16-bit fraction) | fl::s16x16(8.5f) |
fl::s8x8 | No FPU, minimal RAM (8-bit fraction) | fl::s8x8(8.5f) |
All coordinates in a single call must be the same type — you can't mix float and int in one call.
s16x16, s8x8)On 8-bit MCUs (AVR, ATtiny) there is no FPU — every float operation compiles to a slow software routine. fl::s16x16 is a signed 16.16 fixed-point type that does all math with integer shifts and multiplies, giving deterministic, FPU-free rendering at full subpixel precision.
Blazing fast fixed integer drawing - Courtesy of https://www.reddit.com/user/sutaburosu/
All draw functions accept s16x16 coordinates anywhere you would use float. The only rule: every coordinate in a single call must be the same type — don't mix float and s16x16.
Always use float literals (3.25f, not 3.25 or 3) when constructing s16x16. The constructor is explicit, so implicit conversions from int or double won't compile.
s16x16 supports the standard operators. All intermediate math stays in fixed-point — no float conversions in the hot path.
Every canvas draw function works identically with s16x16:
Antialiasing, distance calculations, and bounding-box iteration all run in pure integer arithmetic internally — the graphics engine has specialized code paths for s16x16 (e.g. coordToU8, fromInt, fromFrac) that avoid any float conversion.
s8x8 — compact fixed-pointfl::s8x8 is a signed 8.8 fixed-point type stored in a 16-bit integer. It has half the range and precision of s16x16 but uses half the RAM per value — useful on the most memory-constrained targets.
The API is identical to s16x16 — same constructor, same operators, same to_int() / to_float() / raw() / from_raw() accessors.
Limits: integer part is -128..127, fractional resolution is 1/256. Coordinates or radii beyond ±127 will overflow. For larger canvases, use s16x16 instead.
float | s16x16 | s8x8 | |
|---|---|---|---|
| Best for | ARM Cortex-M4+, ESP32, desktop | AVR/ATtiny, high precision | AVR/ATtiny, tight RAM |
| Storage | 4 bytes | 4 bytes | 2 bytes |
| Integer range | ±3.4×10³⁸ | ±32767 | ±127 |
| Fractional bits | ~23 (mantissa) | 16 | 8 |
| Speed (no FPU) | Slow (software emulation) | Fast (native integer ops) | Fast (native integer ops) |
| Speed (with FPU) | Fast (hardware) | Comparable or slightly slower | Comparable or slightly slower |
| Determinism | Platform-dependent rounding | Bit-exact across platforms | Bit-exact across platforms |
Rule of thumb: if your target has a hardware FPU, use float. On FPU-less MCUs, use s16x16 for general use or s8x8 when RAM is critical and your canvas fits within ±127 pixels.
Canvas<T> works with any pixel type that satisfies this contract:
What each method does:
nscale8(scale) — multiply all channels by scale/256. Called for antialiased edges to blend partial-brightness pixels.operator+= — add another pixel's color, clamping to max. Called by every draw operation to write into the buffer (additive blending).fp — the underlying channel type. u8 for CRGB, u8x8 for CRGB16. Used by higher-level code to choose precision-appropriate scaling.CRGB16 uses u8x8 (8.8 unsigned fixed-point) channels instead of u8. That's 256x finer brightness steps per channel — useful when you need smooth fades, HDR accumulation, or antialiased compositing without banding.
CRGB16 also has nscale(u8x8) for full-precision scaling without truncating to 8 bits.
All primitives are safe with degenerate inputs — no crashes, no out-of-bounds writes:
| Input | Behavior |
|---|---|
| Zero radius or thickness | Draws nothing |
| Zero-length line | Draws nothing |
| Center off-screen | Clips to canvas bounds |
| Shape partially off-screen | Only visible pixels are written |
| Negative coordinates | Clipped — no wrap-around |
Buffer layout. Pixels are stored row-major: buffer[y * width + x]. This gives sequential memory access when iterating rows — optimal for cache performance on LED matrices.
Antialiasing. All primitives use distance-based antialiasing with a half-pixel soft zone:
drawLine — Wu's algorithm: each pixel along the line is split across two adjacent rows/columns based on fractional position.drawDisc — pixels within radius ± 0.5 get brightness proportional to (r_outer² - d²) / (r_outer² - r_inner²).drawRing — same AA math applied to both inner and outer edges.drawStrokeLine — perpendicular distance from centerline, with a precomputed 256-entry LUT for sqrt-based falloff.Performance. The primitives iterate only the bounding box of each shape (not the entire canvas). On a 32x32 canvas, 100 draw calls complete in under 100ms — roughly 10,000 calls/sec in release mode.
| File | What's in it |
|---|---|
gfx.h | Main include — brings in everything below |
canvas.h | Canvas<T> struct and method declarations |
primitives.h | Drawing algorithm implementations |
crgb16.h | CRGB16 pixel type with u8x8 channels |
detail/ | Internal helpers (distance LUT, integer math) |