ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
sgr.c
Go to the documentation of this file.
1
4
5/* Storage capacities in elements; text buffers include the terminating NUL. */
6#define VIDEO_ASCII_SGR_SEQ_BUFFER_SIZE 12
7#define VIDEO_ASCII_SGR_BUF_BUFFER_SIZE 32
8
9#include <ascii-chat/common.h>
14#include <string.h>
15
24
25static _Thread_local sgr256_seq_t sgr256_fg_cache[256];
26static _Thread_local sgr256_seq_t sgr256_bg_cache[256];
27static _Thread_local bool sgr256_cache_initialized = false;
28
29// Build and cache all 256 foreground and background color sequences
30static void init_sgr256_cache(void) {
31 if (sgr256_cache_initialized)
32 return;
33
34 // Cache foreground colors: \e[38;5;NNNm
35 for (int i = 0; i < 256; i++) {
36 char *p = sgr256_fg_cache[i].seq;
37 *p++ = '\033';
38 *p++ = '[';
39 *p++ = '3';
40 *p++ = '8';
41 *p++ = ';';
42 *p++ = '5';
43 *p++ = ';';
44 p = write_u8(p, (uint8_t)i);
45 *p++ = 'm';
46 sgr256_fg_cache[i].len = (uint8_t)(p - sgr256_fg_cache[i].seq);
47 }
48
49 // Cache background colors: \e[48;5;NNNm
50 for (int i = 0; i < 256; i++) {
51 char *p = sgr256_bg_cache[i].seq;
52 *p++ = '\033';
53 *p++ = '[';
54 *p++ = '4';
55 *p++ = '8';
56 *p++ = ';';
57 *p++ = '5';
58 *p++ = ';';
59 p = write_u8(p, (uint8_t)i);
60 *p++ = 'm';
61 sgr256_bg_cache[i].len = (uint8_t)(p - sgr256_bg_cache[i].seq);
62 }
63
64 sgr256_cache_initialized = true;
65}
66
67// Generate "\e[38;5;NNN;48;5;NNNm" (foreground + background)
68static inline char *build_sgr256_fgbg(char *buf, uint8_t fg, uint8_t bg, uint8_t *len_out) {
69 char *p = buf;
70 *p++ = '\033';
71 *p++ = '[';
72 *p++ = '3';
73 *p++ = '8';
74 *p++ = ';';
75 *p++ = '5';
76 *p++ = ';';
77 p = write_u8(p, fg);
78 *p++ = ';';
79 *p++ = '4';
80 *p++ = '8';
81 *p++ = ';';
82 *p++ = '5';
83 *p++ = ';';
84 p = write_u8(p, bg);
85 *p++ = 'm';
86 *len_out = (uint8_t)(p - buf);
87 return buf;
88}
89
90// Public API wrappers
92 init_sgr256_cache();
93}
94
96 init_sgr256_cache();
97}
98
99// Fast SGR generation for SIMD implementations - uses cached sequences
101 if (!sgr256_cache_initialized) {
102 init_sgr256_cache();
103 }
104 *len_out = sgr256_fg_cache[fg].len;
105 return sgr256_fg_cache[fg].seq;
106}
107
109 if (!sgr256_cache_initialized) {
110 init_sgr256_cache();
111 }
112 *len_out = sgr256_bg_cache[bg].len;
113 return sgr256_bg_cache[bg].seq;
114}
115
117 // For FG+BG, still build on-demand since we'd need 256*256 cache
118 static __thread char buf[VIDEO_ASCII_SGR_BUF_BUFFER_SIZE];
119 return build_sgr256_fgbg(buf, fg, bg, len_out);
120}
121
122char *append_sgr_reset(char *dst) {
123 memcpy(dst, "\033[0m", 4);
124 return dst + 4;
125}
126
127static char *append_rgb_components(char *dst, uint8_t r, uint8_t g, uint8_t b) {
128 dst = write_u8(dst, r);
129 *dst++ = ';';
130 dst = write_u8(dst, g);
131 *dst++ = ';';
132 return write_u8(dst, b);
133}
134
135static char *append_rgb_sgr(char *dst, bool background, uint8_t r, uint8_t g, uint8_t b) {
136 memcpy(dst, background ? "\033[48;2;" : "\033[38;2;", 7);
137 dst = append_rgb_components(dst + 7, r, g, b);
138 *dst++ = 'm';
139 return dst;
140}
141
143 return append_rgb_sgr(dst, false, r, g, b);
144}
145
147 return append_rgb_sgr(dst, true, r, g, b);
148}
149
150char *append_sgr_truecolor_fg_bg(char *dst, uint8_t fr, uint8_t fg, uint8_t fb, uint8_t br, uint8_t bg, uint8_t bb) {
151 memcpy(dst, "\033[38;2;", 7);
152 dst = append_rgb_components(dst + 7, fr, fg, fb);
153 memcpy(dst, ";48;2;", 6);
154 dst = append_rgb_components(dst + 6, br, bg, bb);
155 *dst++ = 'm';
156 return dst;
157}
158
159char *image_print_color_simd(image_t *image, bool background, bool indexed, const char *palette) {
160 return ascii_render(image, palette, indexed ? ASCII_COLOR_256 : ASCII_COLOR_TRUE, background, false,
162}
const simd_cells_t * simd_cells_backend(void)
Definition cells.c:70
⚙️ Common definitions, error codes, macros, and types shared throughout the application
unsigned char uint8_t
Definition common.h:60
char * get_sgr256_fg_bg_string(uint8_t fg, uint8_t bg, uint8_t *len_out)
Get 256-color foreground/background ANSI sequence string.
Definition sgr.c:116
void prewarm_sgr256_cache(void)
Prewarm 256-color foreground/background cache for benchmarks.
Definition sgr.c:95
void prewarm_sgr256_fg_cache(void)
Prewarm 256-color foreground cache for benchmarks.
Definition sgr.c:91
char * get_sgr256_bg_string(uint8_t bg, uint8_t *len_out)
Get 256-color background ANSI sequence string.
Definition sgr.c:108
char * get_sgr256_fg_string(uint8_t fg, uint8_t *len_out)
Get 256-color foreground ANSI sequence string.
Definition sgr.c:100
char * image_print_color_simd(image_t *image, bool background, bool indexed, const char *palette)
Print image as ASCII with color using SIMD.
Definition sgr.c:159
char * ascii_render(const image_t *image, const char *palette, ascii_color_t mode, bool background, bool dither, const simd_cells_t *ops)
🔢 Number Formatting and Conversion Utilities
char * append_sgr_reset(char *dst)
Definition sgr.c:122
char * append_sgr_truecolor_fg_bg(char *dst, uint8_t fr, uint8_t fg, uint8_t fb, uint8_t br, uint8_t bg, uint8_t bb)
Definition sgr.c:150
#define VIDEO_ASCII_SGR_BUF_BUFFER_SIZE
Definition sgr.c:7
char * append_sgr_truecolor_bg(char *dst, uint8_t r, uint8_t g, uint8_t b)
Definition sgr.c:146
char * append_sgr_truecolor_fg(char *dst, uint8_t r, uint8_t g, uint8_t b)
Definition sgr.c:142
#define VIDEO_ASCII_SGR_SEQ_BUFFER_SIZE
Definition sgr.c:6
ANSI SGR (Select Graphic Rendition) color sequence generation.
🔤 String Manipulation and Shell Escaping Utilities
SIMD-friendly storage for one RGB pixel. r, g, and b hold the color channels and padding keeps the la...
Pre-computed 256-color ANSI SGR sequence.
Definition sgr.c:20
char seq[12]
ANSI sequence string (max 11 bytes for "\e[38;5;NNNm").
Definition sgr.c:21
uint8_t len
Length of sequence string.
Definition sgr.c:22
SIMD-optimized ASCII conversion interface.