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 * ## Lifetime and Thread Safety
88 *
89 * All handles borrowed from the terminal (GhosttyKittyGraphics,
90 * GhosttyKittyGraphicsImage) are invalidated by any mutating terminal
91 * call. The placement iterator is independently owned and must be freed
92 * by the caller, but the data it yields is only valid while the
93 * underlying terminal is not mutated.
94 *
95 * ## Example
96 *
97 * The following example creates a terminal, sends a Kitty graphics
98 * image, then iterates placements and prints image metadata:
99 *
100 * @snippet c-vt-kitty-graphics/src/main.c kitty-graphics-main
101 *
102 * @{
103 */
104
105/**
106 * Queryable data kinds for ghostty_kitty_graphics_get().
107 *
108 * @ingroup kitty_graphics
109 */
110typedef enum GHOSTTY_ENUM_TYPED {
111 /** Invalid / sentinel value. */
112 GHOSTTY_KITTY_GRAPHICS_DATA_INVALID = 0,
113
114 /**
115 * Populate a pre-allocated placement iterator with placement data from
116 * the storage. Iterator data is only valid as long as the underlying
117 * terminal is not mutated.
118 *
119 * Output type: GhosttyKittyGraphicsPlacementIterator *
120 */
121 GHOSTTY_KITTY_GRAPHICS_DATA_PLACEMENT_ITERATOR = 1,
122 GHOSTTY_KITTY_GRAPHICS_DATA_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
123} GhosttyKittyGraphicsData;
124
125/**
126 * Queryable data kinds for ghostty_kitty_graphics_placement_get().
127 *
128 * @ingroup kitty_graphics
129 */
130typedef enum GHOSTTY_ENUM_TYPED {
131 /** Invalid / sentinel value. */
132 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_INVALID = 0,
133
134 /**
135 * The image ID this placement belongs to.
136 *
137 * Output type: uint32_t *
138 */
139 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_IMAGE_ID = 1,
140
141 /**
142 * The placement ID.
143 *
144 * Output type: uint32_t *
145 */
146 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_PLACEMENT_ID = 2,
147
148 /**
149 * Whether this is a virtual placement (unicode placeholder).
150 *
151 * Output type: bool *
152 */
153 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_IS_VIRTUAL = 3,
154
155 /**
156 * Pixel offset from the left edge of the cell.
157 *
158 * Output type: uint32_t *
159 */
160 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_X_OFFSET = 4,
161
162 /**
163 * Pixel offset from the top edge of the cell.
164 *
165 * Output type: uint32_t *
166 */
167 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_Y_OFFSET = 5,
168
169 /**
170 * Source rectangle x origin in pixels.
171 *
172 * Output type: uint32_t *
173 */
174 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_SOURCE_X = 6,
175
176 /**
177 * Source rectangle y origin in pixels.
178 *
179 * Output type: uint32_t *
180 */
181 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_SOURCE_Y = 7,
182
183 /**
184 * Source rectangle width in pixels (0 = full image width).
185 *
186 * Output type: uint32_t *
187 */
188 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_SOURCE_WIDTH = 8,
189
190 /**
191 * Source rectangle height in pixels (0 = full image height).
192 *
193 * Output type: uint32_t *
194 */
195 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_SOURCE_HEIGHT = 9,
196
197 /**
198 * Number of columns this placement occupies.
199 *
200 * Output type: uint32_t *
201 */
202 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_COLUMNS = 10,
203
204 /**
205 * Number of rows this placement occupies.
206 *
207 * Output type: uint32_t *
208 */
209 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_ROWS = 11,
210
211 /**
212 * Z-index for this placement.
213 *
214 * Output type: int32_t *
215 */
216 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_Z = 12,
217
218 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_DATA_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
219} GhosttyKittyGraphicsPlacementData;
220
221/**
222 * Z-layer classification for kitty graphics placements.
223 *
224 * Based on the kitty protocol z-index conventions:
225 * - BELOW_BG: z < INT32_MIN/2 (drawn below cell background)
226 * - BELOW_TEXT: INT32_MIN/2 <= z < 0 (above background, below text)
227 * - ABOVE_TEXT: z >= 0 (above text)
228 * - ALL: no filtering (current behavior)
229 *
230 * @ingroup kitty_graphics
231 */
232typedef enum GHOSTTY_ENUM_TYPED {
233 GHOSTTY_KITTY_PLACEMENT_LAYER_ALL = 0,
234 GHOSTTY_KITTY_PLACEMENT_LAYER_BELOW_BG = 1,
235 GHOSTTY_KITTY_PLACEMENT_LAYER_BELOW_TEXT = 2,
236 GHOSTTY_KITTY_PLACEMENT_LAYER_ABOVE_TEXT = 3,
237 GHOSTTY_KITTY_PLACEMENT_LAYER_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
238} GhosttyKittyPlacementLayer;
239
240/**
241 * Settable options for ghostty_kitty_graphics_placement_iterator_set().
242 *
243 * @ingroup kitty_graphics
244 */
245typedef enum GHOSTTY_ENUM_TYPED {
246 /**
247 * Set the z-layer filter for the iterator.
248 *
249 * Input type: GhosttyKittyPlacementLayer *
250 */
251 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_ITERATOR_OPTION_LAYER = 0,
252 GHOSTTY_KITTY_GRAPHICS_PLACEMENT_ITERATOR_OPTION_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
253} GhosttyKittyGraphicsPlacementIteratorOption;
254
255/**
256 * Pixel format of a Kitty graphics image.
257 *
258 * @ingroup kitty_graphics
259 */
260typedef enum GHOSTTY_ENUM_TYPED {
261 GHOSTTY_KITTY_IMAGE_FORMAT_RGB = 0,
262 GHOSTTY_KITTY_IMAGE_FORMAT_RGBA = 1,
263 GHOSTTY_KITTY_IMAGE_FORMAT_PNG = 2,
264 GHOSTTY_KITTY_IMAGE_FORMAT_GRAY_ALPHA = 3,
265 GHOSTTY_KITTY_IMAGE_FORMAT_GRAY = 4,
266 GHOSTTY_KITTY_IMAGE_FORMAT_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
267} GhosttyKittyImageFormat;
268
269/**
270 * Compression of a Kitty graphics image.
271 *
272 * @ingroup kitty_graphics
273 */
274typedef enum GHOSTTY_ENUM_TYPED {
275 GHOSTTY_KITTY_IMAGE_COMPRESSION_NONE = 0,
276 GHOSTTY_KITTY_IMAGE_COMPRESSION_ZLIB_DEFLATE = 1,
277 GHOSTTY_KITTY_IMAGE_COMPRESSION_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
278} GhosttyKittyImageCompression;
279
280/**
281 * Queryable data kinds for ghostty_kitty_graphics_image_get().
282 *
283 * @ingroup kitty_graphics
284 */
285typedef enum GHOSTTY_ENUM_TYPED {
286 /** Invalid / sentinel value. */
287 GHOSTTY_KITTY_IMAGE_DATA_INVALID = 0,
288
289 /**
290 * The image ID.
291 *
292 * Output type: uint32_t *
293 */
294 GHOSTTY_KITTY_IMAGE_DATA_ID = 1,
295
296 /**
297 * The image number.
298 *
299 * Output type: uint32_t *
300 */
301 GHOSTTY_KITTY_IMAGE_DATA_NUMBER = 2,
302
303 /**
304 * Image width in pixels.
305 *
306 * Output type: uint32_t *
307 */
308 GHOSTTY_KITTY_IMAGE_DATA_WIDTH = 3,
309
310 /**
311 * Image height in pixels.
312 *
313 * Output type: uint32_t *
314 */
315 GHOSTTY_KITTY_IMAGE_DATA_HEIGHT = 4,
316
317 /**
318 * Pixel format of the image.
319 *
320 * Output type: GhosttyKittyImageFormat *
321 */
322 GHOSTTY_KITTY_IMAGE_DATA_FORMAT = 5,
323
324 /**
325 * Compression of the image.
326 *
327 * Output type: GhosttyKittyImageCompression *
328 */
329 GHOSTTY_KITTY_IMAGE_DATA_COMPRESSION = 6,
330
331 /**
332 * Borrowed pointer to the raw pixel data. Valid as long as the
333 * underlying terminal is not mutated.
334 *
335 * Output type: const uint8_t **
336 */
337 GHOSTTY_KITTY_IMAGE_DATA_DATA_PTR = 7,
338
339 /**
340 * Length of the raw pixel data in bytes.
341 *
342 * Output type: size_t *
343 */
344 GHOSTTY_KITTY_IMAGE_DATA_DATA_LEN = 8,
345
346 GHOSTTY_KITTY_IMAGE_DATA_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
347} GhosttyKittyGraphicsImageData;
348
349/**
350 * Combined rendering geometry for a placement in a single sized struct.
351 *
352 * Combines the results of ghostty_kitty_graphics_placement_pixel_size(),
353 * ghostty_kitty_graphics_placement_grid_size(),
354 * ghostty_kitty_graphics_placement_viewport_pos(), and
355 * ghostty_kitty_graphics_placement_source_rect() into one call. This is
356 * an optimization over calling those four functions individually,
357 * particularly useful in environments with high per-call overhead such
358 * as FFI or Cgo.
359 *
360 * This struct uses the sized-struct ABI pattern. Initialize with
361 * GHOSTTY_INIT_SIZED(GhosttyKittyGraphicsPlacementRenderInfo) before calling
362 * ghostty_kitty_graphics_placement_render_info().
363 *
364 * @ingroup kitty_graphics
365 */
366typedef struct {
367 /** Size of this struct in bytes. Must be set to sizeof(GhosttyKittyGraphicsPlacementRenderInfo). */
368 size_t size;
369 /** Rendered width in pixels. */
370 uint32_t pixel_width;
371 /** Rendered height in pixels. */
372 uint32_t pixel_height;
373 /** Number of grid columns the placement occupies. */
374 uint32_t grid_cols;
375 /** Number of grid rows the placement occupies. */
376 uint32_t grid_rows;
377 /** Viewport-relative column (may be negative for partially visible placements). */
378 int32_t viewport_col;
379 /** Viewport-relative row (may be negative for partially visible placements). */
380 int32_t viewport_row;
381 /** False when the placement is fully off-screen or virtual. */
382 bool viewport_visible;
383 /** Resolved source rectangle x origin in pixels. */
384 uint32_t source_x;
385 /** Resolved source rectangle y origin in pixels. */
386 uint32_t source_y;
387 /** Resolved source rectangle width in pixels. */
388 uint32_t source_width;
389 /** Resolved source rectangle height in pixels. */
390 uint32_t source_height;
391} GhosttyKittyGraphicsPlacementRenderInfo;
392
393/**
394 * Get data from a kitty graphics storage instance.
395 *
396 * The output pointer must be of the appropriate type for the requested
397 * data kind.
398 *
399 * Returns GHOSTTY_NO_VALUE when Kitty graphics are disabled at build time.
400 *
401 * @param graphics The kitty graphics handle
402 * @param data The type of data to extract
403 * @param[out] out Pointer to store the extracted data
404 * @return GHOSTTY_SUCCESS on success
405 *
406 * @ingroup kitty_graphics
407 */
408GHOSTTY_API GhosttyResult ghostty_kitty_graphics_get(
409 GhosttyKittyGraphics graphics,
410 GhosttyKittyGraphicsData data,
411 void* out);
412
413/**
414 * Look up a Kitty graphics image by its image ID.
415 *
416 * Returns NULL if no image with the given ID exists or if Kitty graphics
417 * are disabled at build time.
418 *
419 * @param graphics The kitty graphics handle
420 * @param image_id The image ID to look up
421 * @return An opaque image handle, or NULL if not found
422 *
423 * @ingroup kitty_graphics
424 */
425GHOSTTY_API GhosttyKittyGraphicsImage ghostty_kitty_graphics_image(
426 GhosttyKittyGraphics graphics,
427 uint32_t image_id);
428
429/**
430 * Get data from a Kitty graphics image.
431 *
432 * The output pointer must be of the appropriate type for the requested
433 * data kind.
434 *
435 * @param image The image handle (NULL returns GHOSTTY_INVALID_VALUE)
436 * @param data The data kind to query
437 * @param[out] out Pointer to receive the queried value
438 * @return GHOSTTY_SUCCESS on success
439 *
440 * @ingroup kitty_graphics
441 */
442GHOSTTY_API GhosttyResult ghostty_kitty_graphics_image_get(
443 GhosttyKittyGraphicsImage image,
444 GhosttyKittyGraphicsImageData data,
445 void* out);
446
447/**
448 * Get multiple data fields from a Kitty graphics image in a single call.
449 *
450 * This is an optimization over calling ghostty_kitty_graphics_image_get()
451 * repeatedly, particularly useful in environments with high per-call
452 * overhead such as FFI or Cgo.
453 *
454 * Each element in the keys array specifies a data kind, and the
455 * corresponding element in the values array receives the result.
456 * The type of each values[i] pointer must match the output type
457 * documented for keys[i].
458 *
459 * Processing stops at the first error; on success out_written
460 * is set to count, on error it is set to the index of the
461 * failing key (i.e. the number of values successfully written).
462 *
463 * @param image The image handle (NULL returns GHOSTTY_INVALID_VALUE)
464 * @param count Number of key/value pairs
465 * @param keys Array of data kinds to query
466 * @param values Array of output pointers (types must match each key's
467 * documented output type)
468 * @param[out] out_written On return, receives the number of values
469 * successfully written (may be NULL)
470 * @return GHOSTTY_SUCCESS if all queries succeed
471 *
472 * @ingroup kitty_graphics
473 */
474GHOSTTY_API GhosttyResult ghostty_kitty_graphics_image_get_multi(
475 GhosttyKittyGraphicsImage image,
476 size_t count,
477 const GhosttyKittyGraphicsImageData* keys,
478 void** values,
479 size_t* out_written);
480
481/**
482 * Create a new placement iterator instance.
483 *
484 * All fields except the allocator are left undefined until populated
485 * via ghostty_kitty_graphics_get() with
486 * GHOSTTY_KITTY_GRAPHICS_DATA_PLACEMENT_ITERATOR.
487 *
488 * @param allocator Pointer to allocator, or NULL to use the default allocator
489 * @param[out] out_iterator On success, receives the created iterator handle
490 * @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_MEMORY on allocation
491 * failure
492 *
493 * @ingroup kitty_graphics
494 */
495GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_iterator_new(
496 const GhosttyAllocator* allocator,
497 GhosttyKittyGraphicsPlacementIterator* out_iterator);
498
499/**
500 * Free a placement iterator.
501 *
502 * @param iterator The iterator handle to free (may be NULL)
503 *
504 * @ingroup kitty_graphics
505 */
506GHOSTTY_API void ghostty_kitty_graphics_placement_iterator_free(
507 GhosttyKittyGraphicsPlacementIterator iterator);
508
509/**
510 * Set an option on a placement iterator.
511 *
512 * Use GHOSTTY_KITTY_GRAPHICS_PLACEMENT_ITERATOR_OPTION_LAYER with a
513 * GhosttyKittyPlacementLayer value to filter placements by z-layer.
514 * The filter is applied during iteration: ghostty_kitty_graphics_placement_next()
515 * will skip placements that do not match the configured layer.
516 *
517 * The default layer is GHOSTTY_KITTY_PLACEMENT_LAYER_ALL (no filtering).
518 *
519 * @param iterator The iterator handle (NULL returns GHOSTTY_INVALID_VALUE)
520 * @param option The option to set
521 * @param value Pointer to the value (type depends on option; NULL returns
522 * GHOSTTY_INVALID_VALUE)
523 * @return GHOSTTY_SUCCESS on success
524 *
525 * @ingroup kitty_graphics
526 */
527GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_iterator_set(
528 GhosttyKittyGraphicsPlacementIterator iterator,
529 GhosttyKittyGraphicsPlacementIteratorOption option,
530 const void* value);
531
532/**
533 * Advance the placement iterator to the next placement.
534 *
535 * If a layer filter has been set via
536 * ghostty_kitty_graphics_placement_iterator_set(), only placements
537 * matching that layer are returned.
538 *
539 * @param iterator The iterator handle (may be NULL)
540 * @return true if advanced to the next placement, false if at the end
541 *
542 * @ingroup kitty_graphics
543 */
544GHOSTTY_API bool ghostty_kitty_graphics_placement_next(
545 GhosttyKittyGraphicsPlacementIterator iterator);
546
547/**
548 * Get data from the current placement in a placement iterator.
549 *
550 * Call ghostty_kitty_graphics_placement_next() at least once before
551 * calling this function.
552 *
553 * @param iterator The iterator handle (NULL returns GHOSTTY_INVALID_VALUE)
554 * @param data The data kind to query
555 * @param[out] out Pointer to receive the queried value
556 * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the
557 * iterator is NULL or not positioned on a placement
558 *
559 * @ingroup kitty_graphics
560 */
561GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_get(
562 GhosttyKittyGraphicsPlacementIterator iterator,
563 GhosttyKittyGraphicsPlacementData data,
564 void* out);
565
566/**
567 * Get multiple data fields from the current placement in a single call.
568 *
569 * This is an optimization over calling ghostty_kitty_graphics_placement_get()
570 * repeatedly, particularly useful in environments with high per-call
571 * overhead such as FFI or Cgo.
572 *
573 * Each element in the keys array specifies a data kind, and the
574 * corresponding element in the values array receives the result.
575 * The type of each values[i] pointer must match the output type
576 * documented for keys[i].
577 *
578 * Processing stops at the first error; on success out_written
579 * is set to count, on error it is set to the index of the
580 * failing key (i.e. the number of values successfully written).
581 *
582 * @param iterator The iterator handle (NULL returns GHOSTTY_INVALID_VALUE)
583 * @param count Number of key/value pairs
584 * @param keys Array of data kinds to query
585 * @param values Array of output pointers (types must match each key's
586 * documented output type)
587 * @param[out] out_written On return, receives the number of values
588 * successfully written (may be NULL)
589 * @return GHOSTTY_SUCCESS if all queries succeed
590 *
591 * @ingroup kitty_graphics
592 */
593GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_get_multi(
594 GhosttyKittyGraphicsPlacementIterator iterator,
595 size_t count,
596 const GhosttyKittyGraphicsPlacementData* keys,
597 void** values,
598 size_t* out_written);
599
600/**
601 * Compute the grid rectangle occupied by the current placement.
602 *
603 * Uses the placement's pin, the image dimensions, and the terminal's
604 * cell/pixel geometry to calculate the bounding rectangle. Virtual
605 * placements (unicode placeholders) return GHOSTTY_NO_VALUE.
606 *
607 * @param terminal The terminal handle
608 * @param image The image handle for this placement's image
609 * @param iterator The placement iterator positioned on a placement
610 * @param[out] out_selection On success, receives the bounding rectangle
611 * as a selection with rectangle=true
612 * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if any handle
613 * is NULL or the iterator is not positioned, GHOSTTY_NO_VALUE for
614 * virtual placements or when Kitty graphics are disabled
615 *
616 * @ingroup kitty_graphics
617 */
618GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_rect(
619 GhosttyKittyGraphicsPlacementIterator iterator,
620 GhosttyKittyGraphicsImage image,
621 GhosttyTerminal terminal,
622 GhosttySelection* out_selection);
623
624/**
625 * Compute the rendered pixel size of the current placement.
626 *
627 * Takes into account the placement's source rectangle, specified
628 * columns/rows, and aspect ratio to calculate the final rendered
629 * pixel dimensions.
630 *
631 * @param iterator The placement iterator positioned on a placement
632 * @param image The image handle for this placement's image
633 * @param terminal The terminal handle
634 * @param[out] out_width On success, receives the width in pixels
635 * @param[out] out_height On success, receives the height in pixels
636 * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if any handle
637 * is NULL or the iterator is not positioned, GHOSTTY_NO_VALUE when
638 * Kitty graphics are disabled
639 *
640 * @ingroup kitty_graphics
641 */
642GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_pixel_size(
643 GhosttyKittyGraphicsPlacementIterator iterator,
644 GhosttyKittyGraphicsImage image,
645 GhosttyTerminal terminal,
646 uint32_t* out_width,
647 uint32_t* out_height);
648
649/**
650 * Compute the grid cell size of the current placement.
651 *
652 * Returns the number of columns and rows that the placement occupies
653 * in the terminal grid. If the placement specifies explicit columns
654 * and rows, those are returned directly; otherwise they are calculated
655 * from the pixel size and cell dimensions.
656 *
657 * @param iterator The placement iterator positioned on a placement
658 * @param image The image handle for this placement's image
659 * @param terminal The terminal handle
660 * @param[out] out_cols On success, receives the number of columns
661 * @param[out] out_rows On success, receives the number of rows
662 * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if any handle
663 * is NULL or the iterator is not positioned, GHOSTTY_NO_VALUE when
664 * Kitty graphics are disabled
665 *
666 * @ingroup kitty_graphics
667 */
668GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_grid_size(
669 GhosttyKittyGraphicsPlacementIterator iterator,
670 GhosttyKittyGraphicsImage image,
671 GhosttyTerminal terminal,
672 uint32_t* out_cols,
673 uint32_t* out_rows);
674
675/**
676 * Get the viewport-relative grid position of the current placement.
677 *
678 * Converts the placement's internal pin to viewport-relative column and
679 * row coordinates. The returned coordinates represent the top-left
680 * corner of the placement in the viewport's grid coordinate space.
681 *
682 * The row value can be negative when the placement's origin has
683 * scrolled above the top of the viewport. For example, a 4-row
684 * image that has scrolled up by 2 rows returns row=-2, meaning
685 * its top 2 rows are above the visible area but its bottom 2 rows
686 * are still on screen. Embedders should use these coordinates
687 * directly when computing the destination rectangle for rendering;
688 * the embedder is responsible for clipping the portion of the image
689 * that falls outside the viewport.
690 *
691 * Returns GHOSTTY_SUCCESS for any placement that is at least
692 * partially visible in the viewport. Returns GHOSTTY_NO_VALUE when
693 * the placement is completely outside the viewport (its bottom edge
694 * is above the viewport or its top edge is at or below the last
695 * viewport row), or when the placement is a virtual (unicode
696 * placeholder) placement.
697 *
698 * @param iterator The placement iterator positioned on a placement
699 * @param image The image handle for this placement's image
700 * @param terminal The terminal handle
701 * @param[out] out_col On success, receives the viewport-relative column
702 * @param[out] out_row On success, receives the viewport-relative row
703 * (may be negative for partially visible placements)
704 * @return GHOSTTY_SUCCESS on success, GHOSTTY_NO_VALUE if fully
705 * off-screen or virtual, GHOSTTY_INVALID_VALUE if any handle
706 * is NULL or the iterator is not positioned
707 *
708 * @ingroup kitty_graphics
709 */
710GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_viewport_pos(
711 GhosttyKittyGraphicsPlacementIterator iterator,
712 GhosttyKittyGraphicsImage image,
713 GhosttyTerminal terminal,
714 int32_t* out_col,
715 int32_t* out_row);
716
717/**
718 * Get the resolved source rectangle for the current placement.
719 *
720 * Applies kitty protocol semantics: a width or height of 0 in the
721 * placement means "use the full image dimension", and the resulting
722 * rectangle is clamped to the actual image bounds. The returned
723 * values are in pixels and are ready to use for texture sampling.
724 *
725 * @param iterator The placement iterator positioned on a placement
726 * @param image The image handle for this placement's image
727 * @param[out] out_x Source rect x origin in pixels
728 * @param[out] out_y Source rect y origin in pixels
729 * @param[out] out_width Source rect width in pixels
730 * @param[out] out_height Source rect height in pixels
731 * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if any
732 * handle is NULL or the iterator is not positioned
733 *
734 * @ingroup kitty_graphics
735 */
736GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_source_rect(
737 GhosttyKittyGraphicsPlacementIterator iterator,
738 GhosttyKittyGraphicsImage image,
739 uint32_t* out_x,
740 uint32_t* out_y,
741 uint32_t* out_width,
742 uint32_t* out_height);
743
744/**
745 * Get all rendering geometry for a placement in a single call.
746 *
747 * Combines pixel size, grid size, viewport position, and source
748 * rectangle into one struct. Initialize with
749 * GHOSTTY_INIT_SIZED(GhosttyKittyGraphicsPlacementRenderInfo).
750 *
751 * When viewport_visible is false, the placement is fully off-screen
752 * or is a virtual placement; viewport_col and viewport_row may
753 * contain meaningless values in that case.
754 *
755 * @param iterator The iterator positioned on a placement
756 * @param image The image handle for this placement's image
757 * @param terminal The terminal handle
758 * @param[out] out_info Pointer to receive the rendering geometry
759 * @return GHOSTTY_SUCCESS on success
760 *
761 * @ingroup kitty_graphics
762 */
763GHOSTTY_API GhosttyResult ghostty_kitty_graphics_placement_render_info(
764 GhosttyKittyGraphicsPlacementIterator iterator,
765 GhosttyKittyGraphicsImage image,
766 GhosttyTerminal terminal,
767 GhosttyKittyGraphicsPlacementRenderInfo* out_info);
768
769/** @} */
770
771#ifdef __cplusplus
772}
773#endif
774
775#endif /* GHOSTTY_VT_KITTY_GRAPHICS_H */