Files
fastfetch/src/logo/spin/render.h
T
Carter Li 56f4dc00a2 Logo (Spin): adds a logo that turns in step with --watch
The builtin logo, or a text file in logo syntax, drawn as an extruded slab:
the front is the art as it is, the back is the art mirrored, and the side
walls are shaded with block glyphs. Rendering is pure: no terminal, no
input, no timer.

`--logo-type spin` hands every frame to the normal logo pipeline, so the
modules are laid out beside it exactly as they are for any other type, and
the first frame without --watch is byte-identical to the same art printed
as a builtin logo.

The rotation is driven by the `--watch` loop: `ffSpinTick()` runs once per
refresh and `ffLogoPrint()` is called only when it reports a step, so the
logo and the modules can never drift apart, and a build that never uses the
type costs one comparison per refresh.

Speed is set either as degrees per frame (--logo-spin-speed-per-frame,
default 10) or as seconds per revolution (--logo-spin-speed-per-round,
read from the clock and winning over the former when both are given). Both
take negative values to turn the other way, and --logo-spin-angle picks the
frame to start from.
2026-11-04 15:37:18 +08:00

55 lines
2.4 KiB
C

#pragma once
#include "common/FFstrbuf.h"
#include <stdbool.h>
#include <stdint.h>
#define FF_SPIN_PALETTE_MAX 32
// Palette slots 1..9 hold the logo's $1..$9 colors; raw SGR sequences found in
// custom logo files get the slots after that. Slot 0 is the terminal default.
#define FF_SPIN_PALETTE_LOGO_SLOTS 10
// A logo's ASCII art as a grid of cells. The renderer extrudes it into a slab.
typedef struct FFSpinArt {
uint32_t width;
uint32_t height;
uint32_t* glyphs; // Unicode code point per cell, 0 = empty
uint8_t* colors; // palette index per cell
uint32_t paletteCount;
FFstrbuf palette[FF_SPIN_PALETTE_MAX]; // SGR parameters, e.g. "1;34"
} FFSpinArt;
typedef struct FFSpinFrame {
uint32_t width;
uint32_t height;
uint32_t* glyphs;
uint8_t* colors;
} FFSpinFrame;
// `colors` holds the logo's $1..$9 colors (may be nullptr). Returns false for
// empty art or when memory runs out.
bool ffSpinArtParse(FFSpinArt* art, const char* text, const FFstrbuf* colors, uint32_t colorCount);
void ffSpinArtDestroy(FFSpinArt* art);
bool ffSpinFrameInit(FFSpinFrame* frame, uint32_t width, uint32_t height);
void ffSpinFrameDestroy(FFSpinFrame* frame);
// Frame size that keeps the art inside the frame at every yaw for this tilt.
// The art is centered; the extra space is the same on both sides.
void ffSpinFrameSize(const FFSpinArt* art, float tilt, uint32_t* width, uint32_t* height);
// Copies the art face-on into the center of the frame, exactly as authored.
void ffSpinFramePutArt(FFSpinFrame* frame, const FFSpinArt* art);
void ffSpinRenderArt(const FFSpinArt* art, float yaw, float tilt, FFSpinFrame* frame);
void ffSpinRotationMatrix(float yaw, float tilt, float out[3][3], float outInverse[3][3]);
bool ffSpinRotationIsOrthonormal(const float matrix[3][3], float epsilon);
uint32_t ffSpinMirrorGlyph(uint32_t glyph);
// Appends `count` cells starting at `index` with colors, ending in a reset.
void ffSpinAppendCells(FFstrbuf* out, const FFSpinFrame* frame, const FFSpinArt* art, uint32_t index, uint32_t count, bool color, bool bold);
// One line per frame row, each ending in '\n'. `trimRight` drops the empty cells at the end of a
// row, which is what the other text logo types print; a frame that is redrawn as it turns must
// keep its full width instead, or the information column would move with the angle.
void ffSpinFrameToAnsi(const FFSpinFrame* frame, const FFSpinArt* art, bool color, bool bold, bool trimRight, FFstrbuf* out);