1/**
2 * @file kitty_graphics.h
3 *
4 * Kitty graphics protocol
5 *
6 * See @ref kitty_graphics for a full usage guide.
7 */
8
9#ifndef GHOSTTY_VT_KITTY_GRAPHICS_H
10#define GHOSTTY_VT_KITTY_GRAPHICS_H
11
12#include <stdbool.h>
13#include <stdint.h>
14#include <ghostty/vt/allocator.h>
15#include <ghostty/vt/selection.h>
16#include <ghostty/vt/types.h>
17
18#ifdef __cplusplus
19extern "C" {
20#endif
21
22/** @defgroup kitty_graphics Kitty Graphics
23 *
24 * API for inspecting images and placements stored via the
25 * [Kitty graphics protocol](https://sw.kovidgoyal.net/kitty/graphics-protocol/).
26 *
27 * The central object is @ref GhosttyKittyGraphics, an opaque handle to
28 * the image storage associated with a terminal's active screen. From it
29 * you can iterate over placements and look up individual images.
30 *
31 * ## Obtaining a KittyGraphics Handle
32 *
33 * A @ref GhosttyKittyGraphics handle is obtained from a terminal via
34 * ghostty_terminal_get() with @ref GHOSTTY_TERMINAL_DATA_KITTY_GRAPHICS.
35 * The handle is borrowed from the terminal and remains valid until the
36 * next mutating terminal call (e.g. ghostty_terminal_vt_write() or
37 * ghostty_terminal_reset()).
38 *
39 * Before images can be stored, Kitty graphics must be enabled on the
40 * terminal by setting a non-zero storage limit with
41 * @ref GHOSTTY_TERMINAL_OPT_KITTY_IMAGE_STORAGE_LIMIT, and a PNG
42 * decoder callback must be installed via ghostty_sys_set() with
43 * @ref GHOSTTY_SYS_OPT_DECODE_PNG.
44 *
45 * @snippet c-vt-kitty-graphics/src/main.c kitty-graphics-decode-png
46 *
47 * ## Iterating Placements
48 *
49 * Placements are inspected through a @ref GhosttyKittyGraphicsPlacementIterator.
50 * The typical workflow is:
51 *
52 * 1. Create an iterator with ghostty_kitty_graphics_placement_iterator_new().
53 * 2. Populate it from the storage with ghostty_kitty_graphics_get() using
54 * @ref GHOSTTY_KITTY_GRAPHICS_DATA_PLACEMENT_ITERATOR.
55 * 3. Optionally filter by z-layer with
56 * ghostty_kitty_graphics_placement_iterator_set().
57 * 4. Advance with ghostty_kitty_graphics_placement_next() and read
58 * per-placement data with ghostty_kitty_graphics_placement_get().
59 * 5. For each placement, look up its image with
60 * ghostty_kitty_graphics_image() to access pixel data and dimensions.
61 * 6. Free the iterator with ghostty_kitty_graphics_placement_iterator_free().
62 *
63 * ## Looking Up Images
64 *
65 * Given an image ID (obtained from a placement via
66 * @ref GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_IMAGE_ID), call
67 * ghostty_kitty_graphics_image() to get a @ref GhosttyKittyGraphicsImage
68 * handle. From this handle, ghostty_kitty_graphics_image_get() provides
69 * the image dimensions, pixel format, compression, and a borrowed pointer
70 * to the raw pixel data.
71 *
72 * ## Rendering Helpers
73 *
74 * Several functions assist with rendering a placement:
75 *
76 * - ghostty_kitty_graphics_placement_pixel_size() — rendered pixel
77 * dimensions accounting for source rect and aspect ratio.
78 * - ghostty_kitty_graphics_placement_grid_size() — number of grid
79 * columns and rows the placement occupies.
80 * - ghostty_kitty_graphics_placement_viewport_pos() — viewport-relative
81 * grid position (may be negative for partially scrolled placements).
82 * - ghostty_kitty_graphics_placement_source_rect() — resolved source
83 * rectangle in pixels, clamped to image bounds.
84 * - ghostty_kitty_graphics_placement_rect() — bounding rectangle as a
85 * @ref GhosttySelection.
86 *
87 * ## Change Detection
88 *
89 * Generation stamps allow renderers to cheaply detect whether Kitty
90 * graphics state changed between frames:
91 *
92 * - @ref GHOSTTY_KITTY_GRAPHICS_DATA_GENERATION is a storage-wide stamp
93 * updated on any transmit, placement, or delete. If unchanged, the
94 * placement set and all image data are identical and both placement
95 * snapshots and per-image staleness checks can be skipped. Placement
96 * geometry can still change independently (scrolling moves
97 * placements), so ghostty_kitty_graphics_placement_render_info()
98 * should still be recomputed on dirty frames.
99 * - @ref GHOSTTY_KITTY_IMAGE_DATA_GENERATION is a per-image stamp
100 * changed on every add/replace of that image ID. Texture caches
101 * should treat a cached texture as stale when this differs from the
102 * cached value; dimension/length heuristics cannot detect a
103 * same-sized retransmission.
104 *
105 * Stamps are unique and monotonically increasing process-wide, so
106 * caches keyed on a generation value never alias across screens
107 * (main/alternate), resets, or terminals.
108 *
109 * ## Lifetime and Thread Safety
110 *
111 * All handles borrowed from the terminal (GhosttyKittyGraphics,
112 * GhosttyKittyGraphicsImage) are invalidated by any mutating terminal
113 * call. The placement iterator is independently owned and must be freed
114 * by the caller, but the data it yields is only valid while the
115 * underlying terminal is not mutated.
116 *
117 * ## Example
118 *
119 * The following example creates a terminal, sends a Kitty graphics
120 * image, then iterates placements and prints image metadata:
121 *
122 * @snippet c-vt-kitty-graphics/src/main.c kitty-graphics-main
123 *
124 * @{
125 */
126
127/**
128 * Queryable data kinds for ghostty_kitty_graphics_get().
129 *
130 * @ingroup kitty_graphics
131 */
132typedef enum GHOSTTY_ENUM_TYPED {
133 /** Invalid / sentinel value. */
134 GHOSTTY_KITTY_GRAPHICS_DATA_INVALID = 0,
135
136 /**
137 * Populate a pre-allocated placement iterator with placement data from
138 * the storage. Iterator data is only valid as long as the underlying
139 * terminal is not mutated.
140 *
141 * Output type: GhosttyKittyGraphicsPlacementIterator *
142 */
143 GHOSTTY_KITTY_GRAPHICS_DATA_PLACEMENT_ITERATOR = 1,
144
145 /**
146 * Generation stamp of the last content mutation to this storage:
147 * any image transmit/replace, placement add, or delete. Zero means
148 * the storage has never been mutated (and is therefore empty).
149 *
150 * If the generation is unchanged since a previous query, the set of
151 * placements and all image data are identical, so placement iteration
152 * and image staleness checks can be skipped entirely. Note that
153 * placement *geometry* may still have changed (scrolling and resizing
154 * move placements without changing the storage contents), so rendering
155 * geometry such as ghostty_kitty_graphics_placement_render_info()
156 * must still be recomputed for frames marked dirty.
157 *
158 * Stamps are unique and monotonically increasing process-wide: a
159 * value observed from any storage never recurs for different content,
160 * even across screen switches (main vs. alternate screen have
161 * independent storages) or terminal resets. It is therefore safe to
162 * key caches on this value alone.
163 *
164 * Output type: uint64_t *
165 */
166 GHOSTTY_KITTY_GRAPHICS_DATA_GENERATION = 2,
167 GHOSTTY_KITTY_GRAPHICS_DATA_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
168} GhosttyKittyGraphicsData;
169
170/**
171 * Queryable data kinds for ghostty_kitty_graphics_placement_get().
172 *
173 * @ingroup kitty_graphics
174 */
175typedef enum GHOSTTY_ENUM_TYPED {
176 /** Invalid / sentinel value. */
177 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_INVALID = 0,
178
179 /**
180 * The image ID this placement belongs to.
181 *
182 * Output type: uint32_t *
183 */
184 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_IMAGE_ID = 1,
185
186 /**
187 * The placement ID.
188 *
189 * Output type: uint32_t *
190 */
191 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_PLACEMENT_ID = 2,
192
193 /**
194 * Whether this is a virtual placement (unicode placeholder).
195 *
196 * Output type: bool *
197 */
198 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_IS_VIRTUAL = 3,
199
200 /**
201 * Pixel offset from the left edge of the cell.
202 *
203 * Output type: uint32_t *
204 */
205 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_X_OFFSET = 4,
206
207 /**
208 * Pixel offset from the top edge of the cell.
209 *
210 * Output type: uint32_t *
211 */
212 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_Y_OFFSET = 5,
213
214 /**
215 * Source rectangle x origin in pixels.
216 *
217 * Output type: uint32_t *
218 */
219 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_SOURCE_X = 6,
220
221 /**
222 * Source rectangle y origin in pixels.
223 *
224 * Output type: uint32_t *
225 */
226 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_SOURCE_Y = 7,
227
228 /**
229 * Source rectangle width in pixels (0 = full image width).
230 *
231 * Output type: uint32_t *
232 */
233 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_SOURCE_WIDTH = 8,
234
235 /**
236 * Source rectangle height in pixels (0 = full image height).
237 *
238 * Output type: uint32_t *
239 */
240 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_SOURCE_HEIGHT = 9,
241
242 /**
243 * Number of columns this placement occupies.
244 *
245 * Output type: uint32_t *
246 */
247 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_COLUMNS = 10,
248
249 /**
250 * Number of rows this placement occupies.
251 *
252 * Output type: uint32_t *
253 */
254 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_ROWS = 11,
255
256 /**
257 * Z-index for this placement.
258 *
259 * Output type: int32_t *
260 */
261 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_Z = 12,
262
263 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
264} GhosttyKittyGraphicsPlacementData;
265
266/**
267 * Z-layer classification for kitty graphics placements.
268 *
269 * Based on the kitty protocol z-index conventions:
270 * - BELOW_BG: z < INT32_MIN/2 (drawn below cell background)
271 * - BELOW_TEXT: INT32_MIN/2 <= z < 0 (above background, below text)
272 * - ABOVE_TEXT: z >= 0 (above text)
273 * - ALL: no filtering (current behavior)
274 *
275 * @ingroup kitty_graphics
276 */
277typedef enum GHOSTTY_ENUM_TYPED {
278 GHOSTTY_KITTY_PLACEMENT_LAYER_ALL = 0,
279 GHOSTTY_KITTY_PLACEMENT_LAYER_BELOW_BG = 1,
280 GHOSTTY_KITTY_PLACEMENT_LAYER_BELOW_TEXT = 2,
281 GHOSTTY_KITTY_PLACEMENT_LAYER_ABOVE_TEXT = 3,
282 GHOSTTY_KITTY_PLACEMENT_LAYER_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
283} GhosttyKittyPlacementLayer;
284
285/**
286 * Settable options for ghostty_kitty_graphics_placement_iterator_set().
287 *
288 * @ingroup kitty_graphics
289 */
290typedef enum GHOSTTY_ENUM_TYPED {
291 /**
292 * Set the z-layer filter for the iterator.
293 *
294 * Input type: GhosttyKittyPlacementLayer *
295 */
296 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_ITERATOR_OPTION_LAYER = 0,
297 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_ITERATOR_OPTION_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
298} GhosttyKittyGraphicsPlacementIteratorOption;
299
300/**
301 * Pixel format of a Kitty graphics image.
302 *
303 * Note that stored images are always fully decoded:
304 * GHOSTTY_KITTY_IMAGE_FORMAT_PNG is never returned by
305 * ghostty_kitty_graphics_image_get() because PNG payloads are decoded
306 * to GHOSTTY_KITTY_IMAGE_FORMAT_RGBA before storage. The PNG value
307 * exists only for protocol-level completeness.
308 *
309 * @ingroup kitty_graphics
310 */
311typedef enum GHOSTTY_ENUM_TYPED {
312 GHOSTTY_KITTY_IMAGE_FORMAT_RGB = 0,
313 GHOSTTY_KITTY_IMAGE_FORMAT_RGBA = 1,
314 GHOSTTY_KITTY_IMAGE_FORMAT_PNG = 2,
315 GHOSTTY_KITTY_IMAGE_FORMAT_GRAY_ALPHA = 3,
316 GHOSTTY_KITTY_IMAGE_FORMAT_GRAY = 4,
317 GHOSTTY_KITTY_IMAGE_FORMAT_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
318} GhosttyKittyImageFormat;
319
320/**
321 * Compression of a Kitty graphics image.
322 *
323 * Note that stored images are always decompressed:
324 * GHOSTTY_KITTY_IMAGE_COMPRESSION_ZLIB_DEFLATE payloads are inflated
325 * before storage, so ghostty_kitty_graphics_image_get() always reports
326 * GHOSTTY_KITTY_IMAGE_COMPRESSION_NONE. Consumers never need to
327 * inflate image data themselves.
328 *
329 * @ingroup kitty_graphics
330 */
331typedef enum GHOSTTY_ENUM_TYPED {
332 GHOSTTY_KITTY_IMAGE_COMPRESSION_NONE = 0,
333 GHOSTTY_KITTY_IMAGE_COMPRESSION_ZLIB_DEFLATE = 1,
334 GHOSTTY_KITTY_IMAGE_COMPRESSION_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
335} GhosttyKittyImageCompression;
336
337/**
338 * Queryable data kinds for ghostty_kitty_graphics_image_get().
339 *
340 * @ingroup kitty_graphics
341 */
342typedef enum GHOSTTY_ENUM_TYPED {
343 /** Invalid / sentinel value. */
344 GHOSTTY_KITTY_IMAGE_DATA_INVALID = 0,
345
346 /**
347 * The image ID.
348 *
349 * Output type: uint32_t *
350 */
351 GHOSTTY_KITTY_IMAGE_DATA_ID = 1,
352
353 /**
354 * The image number.
355 *
356 * Output type: uint32_t *
357 */
358 GHOSTTY_KITTY_IMAGE_DATA_NUMBER = 2,
359
360 /**
361 * Image width in pixels.
362 *
363 * Output type: uint32_t *
364 */
365 GHOSTTY_KITTY_IMAGE_DATA_WIDTH = 3,
366
367 /**
368 * Image height in pixels.
369 *
370 * Output type: uint32_t *
371 */
372 GHOSTTY_KITTY_IMAGE_DATA_HEIGHT = 4,
373
374 /**
375 * Pixel format of the image. Never GHOSTTY_KITTY_IMAGE_FORMAT_PNG;
376 * PNG payloads are decoded to RGBA before storage.
377 *
378 * Output type: GhosttyKittyImageFormat *
379 */
380 GHOSTTY_KITTY_IMAGE_DATA_FORMAT = 5,
381
382 /**
383 * Compression of the image. Always
384 * GHOSTTY_KITTY_IMAGE_COMPRESSION_NONE; compressed payloads are
385 * inflated before storage.
386 *
387 * Output type: GhosttyKittyImageCompression *
388 */
389 GHOSTTY_KITTY_IMAGE_DATA_COMPRESSION = 6,
390
391 /**
392 * Borrowed pointer to the raw pixel data. Valid as long as the
393 * underlying terminal is not mutated.
394 *
395 * The data is always fully decoded, uncompressed pixels in the
396 * format reported by GHOSTTY_KITTY_IMAGE_DATA_FORMAT: zlib payloads
397 * are inflated and PNG payloads are decoded to RGBA at transmission
398 * time, before the image is stored. Consumers can upload this
399 * directly to the GPU without any decode step.
400 *
401 * Output type: const uint8_t **
402 */
403 GHOSTTY_KITTY_IMAGE_DATA_DATA_PTR = 7,
404
405 /**
406 * Length of the raw pixel data in bytes. Always equal to
407 * width * height * bytes-per-pixel for the reported format.
408 *
409 * Output type: size_t *
410 */
411 GHOSTTY_KITTY_IMAGE_DATA_DATA_LEN = 8,
412
413 /**
414 * Generation stamp assigned when this image was added to (or
415 * replaced in) the storage. A changed generation for a given image
416 * ID means the pixel contents may have changed even when the
417 * dimensions, format, and data length are identical (e.g. a
418 * retransmission of the same image ID), so texture caches must key
419 * staleness on this value rather than on size heuristics.
420 *
421 * Stamps are unique and monotonically increasing process-wide and
422 * are drawn from the same sequence as
423 * GHOSTTY_KITTY_GRAPHICS_DATA_GENERATION. Never zero for a stored
424 * image, so zero can be used as an "empty" sentinel by callers.
425 *
426 * Output type: uint64_t *
427 */
428 GHOSTTY_KITTY_IMAGE_DATA_GENERATION = 9,
429
430 GHOSTTY_KITTY_IMAGE_DATA_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
431} GhosttyKittyGraphicsImageData;
432
433/**
434 * Combined rendering geometry for a placement in a single sized struct.
435 *
436 * Combines the results of ghostty_kitty_graphics_placement_pixel_size(),
437 * ghostty_kitty_graphics_placement_grid_size(),
438 * ghostty_kitty_graphics_placement_viewport_pos(), and
439 * ghostty_kitty_graphics_placement_source_rect() into one call. This is
440 * an optimization over calling those four functions individually,
441 * particularly useful in environments with high per-call overhead such
442 * as FFI or Cgo.
443 *
444 * This struct uses the sized-struct ABI pattern. Initialize with
445 * GHOSTTY_INIT_SIZED(GhosttyKittyGraphicsPlacementRenderInfo) before calling
446 * ghostty_kitty_graphics_placement_render_info().
447 *
448 * @ingroup kitty_graphics
449 */
450typedef struct {
451 /** Size of this struct in bytes. Must be set to sizeof(GhosttyKittyGraphicsPlacementRenderInfo). */
452 size_t size;
453 /** Rendered width in pixels. */
454 uint32_t pixel_width;
455 /** Rendered height in pixels. */
456 uint32_t pixel_height;
457 /** Number of grid columns the placement occupies. */
458 uint32_t grid_cols;
459 /** Number of grid rows the placement occupies. */
460 uint32_t grid_rows;
461 /** Viewport-relative column (may be negative for partially visible placements). */
462 int32_t viewport_col;
463 /** Viewport-relative row (may be negative for partially visible placements). */
464 int32_t viewport_row;
465 /** False when the placement is fully off-screen or virtual. */
466 bool viewport_visible;
467 /** Resolved source rectangle x origin in pixels. */
468 uint32_t source_x;
469 /** Resolved source rectangle y origin in pixels. */
470 uint32_t source_y;
471 /** Resolved source rectangle width in pixels. */
472 uint32_t source_width;
473 /** Resolved source rectangle height in pixels. */
474 uint32_t source_height;
475} GhosttyKittyGraphicsPlacementRenderInfo;
476
477/**
478 * Get data from a kitty graphics storage instance.
479 *
480 * The output pointer must be of the appropriate type for the requested
481 * data kind.
482 *
483 * Returns GHOSTTY_NO_VALUE when Kitty graphics are disabled at build time.
484 *
485 * @param graphics The kitty graphics handle
486 * @param data The type of data to extract
487 * @param[out] out Pointer to store the extracted data
488 * @return GHOSTTY_SUCCESS on success
489 *
490 * @ingroup kitty_graphics
491 */
492GHOSTTY_API GhosttyResult ghostty_kitty_graphics_get(
493 GhosttyKittyGraphics graphics,
494 GhosttyKittyGraphicsData data,
495 void* out);
496
497/**
498 * Look up a Kitty graphics image by its image ID.
499 *
500 * Returns NULL if no image with the given ID exists or if Kitty graphics
501 * are disabled at build time.
502 *
503 * @param graphics The kitty graphics handle
504 * @param image_id The image ID to look up
505 * @return An opaque image handle, or NULL if not found
506 *
507 * @ingroup kitty_graphics
508 */
509GHOSTTY_API GhosttyKittyGraphicsImage ghostty_kitty_graphics_image(
510 GhosttyKittyGraphics graphics,
511 uint32_t image_id);
512
513/**
514 * Get data from a Kitty graphics image.
515 *
516 * The output pointer must be of the appropriate type for the requested
517 * data kind.
518 *
519 * @param image The image handle (NULL returns GHOSTTY_INVALID_VALUE)
520 * @param data The data kind to query
521 * @param[out] out Pointer to receive the queried value
522 * @return GHOSTTY_SUCCESS on success
523 *
524 * @ingroup kitty_graphics
525 */
526GHOSTTY_API GhosttyResult ghostty_kitty_graphics_image_get(
527 GhosttyKittyGraphicsImage image,
528 GhosttyKittyGraphicsImageData data,
529 void* out);
530
531/**
532 * Get multiple data fields from a Kitty graphics image in a single call.
533 *
534 * This is an optimization over calling ghostty_kitty_graphics_image_get()
535 * repeatedly, particularly useful in environments with high per-call
536 * overhead such as FFI or Cgo.
537 *
538 * Each element in the keys array specifies a data kind, and the
539 * corresponding element in the values array receives the result.
540 * The type of each values[i] pointer must match the output type
541 * documented for keys[i].
542 *
543 * Processing stops at the first error; on success out_written
544 * is set to count, on error it is set to the index of the
545 * failing key (i.e. the number of values successfully written).
546 *
547 * @param image The image handle (NULL returns GHOSTTY_INVALID_VALUE)
548 * @param count Number of key/value pairs
549 * @param keys Array of data kinds to query
550 * @param values Array of output pointers (types must match each key's
551 * documented output type)
552 * @param[out] out_written On return, receives the number of values
553 * successfully written (may be NULL)
554 * @return GHOSTTY_SUCCESS if all queries succeed
555 *
556 * @ingroup kitty_graphics
557 */
558GHOSTTY_API GhosttyResult ghostty_kitty_graphics_image_get_multi(
559 GhosttyKittyGraphicsImage image,
560 size_t count,
561 const GhosttyKittyGraphicsImageData* keys,
562 void** values,
563 size_t* out_written);
564
565/**
566 * Create a new placement iterator instance.
567 *
568 * All fields except the allocator are left undefined until populated
569 * via ghostty_kitty_graphics_get() with
570 * GHOSTTY_KITTY_GRAPHICS_DATA_PLACEMENT_ITERATOR.
571 *
572 * @param allocator Pointer to allocator, or NULL to use the default allocator
573 * @param[out] out_iterator On success, receives the created iterator handle
574 * @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_MEMORY on allocation
575 * failure
576 *
577 * @ingroup kitty_graphics
578 */
579GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_iterator_new(
580 const GhosttyAllocator* allocator,
581 GhosttyKittyGraphicsPlacementIterator* out_iterator);
582
583/**
584 * Free a placement iterator.
585 *
586 * @param iterator The iterator handle to free (may be NULL)
587 *
588 * @ingroup kitty_graphics
589 */
590GHOSTTY_API void ghostty_kitty_graphics_placement_iterator_free(
591 GhosttyKittyGraphicsPlacementIterator iterator);
592
593/**
594 * Set an option on a placement iterator.
595 *
596 * Use GHOSTTY_KITTY_GRAPHICS_PLACEMENT_ITERATOR_OPTION_LAYER with a
597 * GhosttyKittyPlacementLayer value to filter placements by z-layer.
598 * The filter is applied during iteration: ghostty_kitty_graphics_placement_next()
599 * will skip placements that do not match the configured layer.
600 *
601 * The default layer is GHOSTTY_KITTY_PLACEMENT_LAYER_ALL (no filtering).
602 *
603 * @param iterator The iterator handle (NULL returns GHOSTTY_INVALID_VALUE)
604 * @param option The option to set
605 * @param value Pointer to the value (type depends on option; NULL returns
606 * GHOSTTY_INVALID_VALUE)
607 * @return GHOSTTY_SUCCESS on success
608 *
609 * @ingroup kitty_graphics
610 */
611GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_iterator_set(
612 GhosttyKittyGraphicsPlacementIterator iterator,
613 GhosttyKittyGraphicsPlacementIteratorOption option,
614 const void* value);
615
616/**
617 * Advance the placement iterator to the next placement.
618 *
619 * If a layer filter has been set via
620 * ghostty_kitty_graphics_placement_iterator_set(), only placements
621 * matching that layer are returned.
622 *
623 * @param iterator The iterator handle (may be NULL)
624 * @return true if advanced to the next placement, false if at the end
625 *
626 * @ingroup kitty_graphics
627 */
628GHOSTTY_API bool ghostty_kitty_graphics_placement_next(
629 GhosttyKittyGraphicsPlacementIterator iterator);
630
631/**
632 * Get data from the current placement in a placement iterator.
633 *
634 * Call ghostty_kitty_graphics_placement_next() at least once before
635 * calling this function.
636 *
637 * @param iterator The iterator handle (NULL returns GHOSTTY_INVALID_VALUE)
638 * @param data The data kind to query
639 * @param[out] out Pointer to receive the queried value
640 * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the
641 * iterator is NULL or not positioned on a placement
642 *
643 * @ingroup kitty_graphics
644 */
645GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_get(
646 GhosttyKittyGraphicsPlacementIterator iterator,
647 GhosttyKittyGraphicsPlacementData data,
648 void* out);
649
650/**
651 * Get multiple data fields from the current placement in a single call.
652 *
653 * This is an optimization over calling ghostty_kitty_graphics_placement_get()
654 * repeatedly, particularly useful in environments with high per-call
655 * overhead such as FFI or Cgo.
656 *
657 * Each element in the keys array specifies a data kind, and the
658 * corresponding element in the values array receives the result.
659 * The type of each values[i] pointer must match the output type
660 * documented for keys[i].
661 *
662 * Processing stops at the first error; on success out_written
663 * is set to count, on error it is set to the index of the
664 * failing key (i.e. the number of values successfully written).
665 *
666 * @param iterator The iterator handle (NULL returns GHOSTTY_INVALID_VALUE)
667 * @param count Number of key/value pairs
668 * @param keys Array of data kinds to query
669 * @param values Array of output pointers (types must match each key's
670 * documented output type)
671 * @param[out] out_written On return, receives the number of values
672 * successfully written (may be NULL)
673 * @return GHOSTTY_SUCCESS if all queries succeed
674 *
675 * @ingroup kitty_graphics
676 */
677GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_get_multi(
678 GhosttyKittyGraphicsPlacementIterator iterator,
679 size_t count,
680 const GhosttyKittyGraphicsPlacementData* keys,
681 void** values,
682 size_t* out_written);
683
684/**
685 * Compute the grid rectangle occupied by the current placement.
686 *
687 * Uses the placement's pin, the image dimensions, and the terminal's
688 * cell/pixel geometry to calculate the bounding rectangle. Virtual
689 * placements (unicode placeholders) return GHOSTTY_NO_VALUE.
690 *
691 * @param terminal The terminal handle
692 * @param image The image handle for this placement's image
693 * @param iterator The placement iterator positioned on a placement
694 * @param[out] out_selection On success, receives the bounding rectangle
695 * as a selection with rectangle=true
696 * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if any handle
697 * is NULL or the iterator is not positioned, GHOSTTY_NO_VALUE for
698 * virtual placements or when Kitty graphics are disabled
699 *
700 * @ingroup kitty_graphics
701 */
702GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_rect(
703 GhosttyKittyGraphicsPlacementIterator iterator,
704 GhosttyKittyGraphicsImage image,
705 GhosttyTerminal terminal,
706 GhosttySelection* out_selection);
707
708/**
709 * Compute the rendered pixel size of the current placement.
710 *
711 * Takes into account the placement's source rectangle, specified
712 * columns/rows, and aspect ratio to calculate the final rendered
713 * pixel dimensions.
714 *
715 * @param iterator The placement iterator positioned on a placement
716 * @param image The image handle for this placement's image
717 * @param terminal The terminal handle
718 * @param[out] out_width On success, receives the width in pixels
719 * @param[out] out_height On success, receives the height in pixels
720 * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if any handle
721 * is NULL or the iterator is not positioned, GHOSTTY_NO_VALUE when
722 * Kitty graphics are disabled
723 *
724 * @ingroup kitty_graphics
725 */
726GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_pixel_size(
727 GhosttyKittyGraphicsPlacementIterator iterator,
728 GhosttyKittyGraphicsImage image,
729 GhosttyTerminal terminal,
730 uint32_t* out_width,
731 uint32_t* out_height);
732
733/**
734 * Compute the grid cell size of the current placement.
735 *
736 * Returns the number of columns and rows that the placement occupies
737 * in the terminal grid. If the placement specifies explicit columns
738 * and rows, those are returned directly; otherwise they are calculated
739 * from the pixel size and cell dimensions.
740 *
741 * @param iterator The placement iterator positioned on a placement
742 * @param image The image handle for this placement's image
743 * @param terminal The terminal handle
744 * @param[out] out_cols On success, receives the number of columns
745 * @param[out] out_rows On success, receives the number of rows
746 * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if any handle
747 * is NULL or the iterator is not positioned, GHOSTTY_NO_VALUE when
748 * Kitty graphics are disabled
749 *
750 * @ingroup kitty_graphics
751 */
752GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_grid_size(
753 GhosttyKittyGraphicsPlacementIterator iterator,
754 GhosttyKittyGraphicsImage image,
755 GhosttyTerminal terminal,
756 uint32_t* out_cols,
757 uint32_t* out_rows);
758
759/**
760 * Get the viewport-relative grid position of the current placement.
761 *
762 * Converts the placement's internal pin to viewport-relative column and
763 * row coordinates. The returned coordinates represent the top-left
764 * corner of the placement in the viewport's grid coordinate space.
765 *
766 * The row value can be negative when the placement's origin has
767 * scrolled above the top of the viewport. For example, a 4-row
768 * image that has scrolled up by 2 rows returns row=-2, meaning
769 * its top 2 rows are above the visible area but its bottom 2 rows
770 * are still on screen. Embedders should use these coordinates
771 * directly when computing the destination rectangle for rendering;
772 * the embedder is responsible for clipping the portion of the image
773 * that falls outside the viewport.
774 *
775 * Returns GHOSTTY_SUCCESS for any placement that is at least
776 * partially visible in the viewport. Returns GHOSTTY_NO_VALUE when
777 * the placement is completely outside the viewport (its bottom edge
778 * is above the viewport or its top edge is at or below the last
779 * viewport row), or when the placement is a virtual (unicode
780 * placeholder) placement.
781 *
782 * @param iterator The placement iterator positioned on a placement
783 * @param image The image handle for this placement's image
784 * @param terminal The terminal handle
785 * @param[out] out_col On success, receives the viewport-relative column
786 * @param[out] out_row On success, receives the viewport-relative row
787 * (may be negative for partially visible placements)
788 * @return GHOSTTY_SUCCESS on success, GHOSTTY_NO_VALUE if fully
789 * off-screen or virtual, GHOSTTY_INVALID_VALUE if any handle
790 * is NULL or the iterator is not positioned
791 *
792 * @ingroup kitty_graphics
793 */
794GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_viewport_pos(
795 GhosttyKittyGraphicsPlacementIterator iterator,
796 GhosttyKittyGraphicsImage image,
797 GhosttyTerminal terminal,
798 int32_t* out_col,
799 int32_t* out_row);
800
801/**
802 * Get the resolved source rectangle for the current placement.
803 *
804 * Applies kitty protocol semantics: a width or height of 0 in the
805 * placement means "use the full image dimension", and the resulting
806 * rectangle is clamped to the actual image bounds. The returned
807 * values are in pixels and are ready to use for texture sampling.
808 *
809 * @param iterator The placement iterator positioned on a placement
810 * @param image The image handle for this placement's image
811 * @param[out] out_x Source rect x origin in pixels
812 * @param[out] out_y Source rect y origin in pixels
813 * @param[out] out_width Source rect width in pixels
814 * @param[out] out_height Source rect height in pixels
815 * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if any
816 * handle is NULL or the iterator is not positioned
817 *
818 * @ingroup kitty_graphics
819 */
820GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_source_rect(
821 GhosttyKittyGraphicsPlacementIterator iterator,
822 GhosttyKittyGraphicsImage image,
823 uint32_t* out_x,
824 uint32_t* out_y,
825 uint32_t* out_width,
826 uint32_t* out_height);
827
828/**
829 * Get all rendering geometry for a placement in a single call.
830 *
831 * Combines pixel size, grid size, viewport position, and source
832 * rectangle into one struct. Initialize with
833 * GHOSTTY_INIT_SIZED(GhosttyKittyGraphicsPlacementRenderInfo).
834 *
835 * When viewport_visible is false, the placement is fully off-screen
836 * or is a virtual placement; viewport_col and viewport_row may
837 * contain meaningless values in that case.
838 *
839 * @param iterator The iterator positioned on a placement
840 * @param image The image handle for this placement's image
841 * @param terminal The terminal handle
842 * @param[out] out_info Pointer to receive the rendering geometry
843 * @return GHOSTTY_SUCCESS on success
844 *
845 * @ingroup kitty_graphics
846 */
847GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_render_info(
848 GhosttyKittyGraphicsPlacementIterator iterator,
849 GhosttyKittyGraphicsImage image,
850 GhosttyTerminal terminal,
851 GhosttyKittyGraphicsPlacementRenderInfo* out_info);
852
853/** @} */
854
855#ifdef __cplusplus
856}
857#endif
858
859#endif /* GHOSTTY_VT_KITTY_GRAPHICS_H */