TICKIT_RENDERBUFFER(7)

✨ TICKIT_RENDERBUFFER ✨

okay so bestie, welcome to the TickitRenderBuffer page, straight outta the Miscellaneous Information Manual, section 7, iykyk πŸ’…


🌸 NAME 🌸

TickitRenderBuffer β€” the lil storage unit where your display content chills out before it gets drawn to the terminal πŸŽ€


πŸ¦‹ SYNOPSIS πŸ¦‹

#include <tickit.h>

typedef struct TickitRenderBuffer;

πŸ’– DESCRIPTION πŸ’–

okay so a TickitRenderBuffer instance is literally just a place that stores content waiting to be drawn to the terminal. it's giving efficient ✨. you build up your eventual display by applying drawing operations to it β€” operations that can alter and overwrite the pending content β€” and then eventually you flush the whole thing directly to the terminal in one efficient transfer of state. no cap.

the buffer stores plain text content along with rendering attributes, and it also stores line drawing info, so line segments can get merged correctly and rendered with Unicode characters. iconic behavior honestly 🫢

the main character purpose of the render buffer is storage of pending content to be displayed. the buffer is a grid of cells of the given size. each cell has a state, and neighbouring cells in the same state make up a region. every region is either in a skip state (where it will not affect the terminal display when it's flushed), or it has either textual content or an instruction to erase the display. in both of those cases, the region has an associated TickitPen instance giving it its display attributes. text regions can be given either by UTF-8 strings, individual Unicode codepoint numbers, or they get created as Unicode line-drawing characters by merging one or more effective line segments 🌈

so why would you use a TickitRenderBuffer instead of just firing plain drawing requests directly at the terminal? several reasons bestie:

  1. because the content is simply stored in memory until it's flushed to the terminal, it doesn't have to be rendered in screen order. you can build it up in any order that makes sense within the application, and when it's flushed to the terminal it'll be performed in an efficient top-to-bottom, left-to-right order ⭐
  2. the buffer understands horizontal and vertical line drawing using Unicode characters. while content is being built up, it keeps track of what kinds of lines meet in every cell in the buffer, so when it's flushed to the terminal it can pick the appropriate Unicode line-drawing characters to render these with πŸŽ€
  3. several features of the buffer are designed to easily support applications that divide the screen area into several possibly-overlapping regions managed by different parts of the application. clipping, translation and masking support the concept of independent areas of the buffer, and stored pens plus the state stack support the concept that these areas might be nested within each other β€” which lets rendering attributes be inherited from outer regions into inner ones πŸ’œ

🎯 VIRTUAL CURSOR 🎯

a TickitRenderBuffer instance maintains a virtual cursor position that application code can use to render at. it's virtual because it does not relate to the actual cursor in use on the terminal instance β€” it's just a position stored by the buffer state, periodt.

most of the content drawing functions come in pairs πŸ‘―: one uses and updates the cursor position, and the second operates directly on the buffer contents, without regard to the virtual cursor. you can spot the second kind by the _at suffix on their name. iykyk.

πŸ–ŠοΈ PEN πŸ–ŠοΈ

a TickitPen instance can be set on a TickitRenderBuffer, acting as a default pen for subsequent drawing functions. this is optionally combined with a pen instance given to individual drawing functions β€” if both are present, the attributes get combined, and the given pen's attributes take precedence over the ones in the stored pen πŸ‘‘

πŸ”„ TRANSLATION πŸ”„

a translation offset can be applied so the drawing functions store their output at some other location within the buffer. this translation only affects the drawing functions β€” the actual operation to flush the contents to the terminal is not affected, no cap.

βœ‚οΈ CLIPPING AND MASKING βœ‚οΈ

all of the drawing functions are also subject to restriction of their output, so they apply within a clipping region. initially the entire buffer is available for drawing, but the area can be restricted to a smaller rectangular area at any time. requests to draw content outside of this region get ignored πŸ™ˆ

on top of clipping, a buffer can also mask out arbitrary additional rectangular areas within the clipping region. these areas act with the clipping region by ignoring requests to draw inside them, while preserving any existing content within them.

masking and clipping are related but separate concepts, bestie. both place restrictions on where output functions can alter the pending content. whereas the clipping region is the rectangular area within which all drawing occurs, masking regions are areas in which drawing does not occur. πŸ’€

when combined with translation, these two features allow possibly-overlapping regions of content to be independently managed by separate pieces of code. to render each region of the screen, a render buffer can be set up with a translation offset and clipping rectangle to suit that region, so the rendering code never has to care about the exact on-screen geometry. and by using masking regions, these areas can be managed even when they overlap β€” by ensuring areas already drawn by "higher" regions are masked off, so "lower" regions don't overwrite them πŸ”₯

πŸ’Ύ SAVE STACK πŸ’Ύ

as further assistance to applications that wanna divide the screen area into nested regions, there's a set of functions to store the current auxiliary state of the buffer and later restore that state to its original values. and what counts as auxiliary state? literally all of the mutable attributes listed above, but without the actual pending content. main character energy.


πŸ› οΈ FUNCTIONS πŸ› οΈ

a new TickitRenderBuffer instance is created using tickit_renderbuffer_new(3). a render buffer instance stores a reference count to make it easier for applications to manage the lifetime of buffers. a new buffer starts with a count of one, and it can be adjusted using tickit_renderbuffer_ref(3) and tickit_renderbuffer_unref(3). when the count hits zero, the instance is destroyed πŸͺ¦

its size is fixed after creation and can be queried using tickit_renderbuffer_get_size(3). its contents can be entirely reset back to their original state using tickit_renderbuffer_reset(3).

a translation offset can be set using tickit_renderbuffer_translate(3), and the clipping region restricted using tickit_renderbuffer_clip(3). masks can be placed within the current clipping region using tickit_renderbuffer_mask(3).

the virtual cursor position can be set using tickit_renderbuffer_goto(3) and unset using tickit_renderbuffer_ungoto(3). it can be queried using tickit_renderbuffer_has_cursorpos(3) to determine if it's set, and tickit_renderbuffer_get_cursorpos(3) to return its position. a TickitPen instance can be set using tickit_renderbuffer_setpen(3) ✨

the auxiliary state can be saved to the state stack using tickit_renderbuffer_save(3) and later restored using tickit_renderbuffer_restore(3). a stack state consisting of just the pen with no other state can be saved using tickit_renderbuffer_savepen(3) πŸ–ŠοΈ

the stored content of a buffer can be copied to another buffer using tickit_renderbuffer_blit(3). this is useful for letting a window maintain a backing buffer that can be drawn to at any time and then copied to a destination buffer for display. obsessed 😭

the stored content can be flushed to a TickitTerm instance using tickit_renderbuffer_flush_to_term(3).


🎨 DRAWING OPERATIONS 🎨

the following functions all affect the stored content within the buffer, taking into account the clipping, translation, masking, stored pen, and optionally the virtual cursor position:


πŸ‘€ SEE ALSO πŸ‘€

tickit(7), tickit_pen(7), tickit_rect(7) tickit_term(7)


and that's the whole vibe bestie 🫢 this was TICKIT_RENDERBUFFER(7) from the Miscellaneous Information Manual β€” go forth and render, you're literally the main character of your terminal βœ¨πŸ’–πŸŽ€πŸ¦‹πŸŒΈπŸ’…πŸ‘‘πŸŒˆβ­