From a7ed47575e8a4432359231fdf1299e6a56ba104a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 3 Mar 2023 12:45:52 +0530 Subject: [PATCH] Improve documentation for Unicode placeholders --- docs/changelog.rst | 4 +- docs/graphics-protocol.rst | 89 +++++++++++++++++++++++++++----------- kitty/graphics.c | 7 ++- 3 files changed, 69 insertions(+), 31 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 1a88497c6..041207024 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -40,6 +40,8 @@ Detailed list of changes - Text rendering: Use sRGB correct linear gamma blending for nicer font rendering and better color accuracy with transparent windows. See the option :opt:`text_composition_strategy` for details. The obsolete :opt:`macos_thicken_font` will make the font too thick and needs to be removed manually if it is configured. (:pull:`5969`) +- Graphics protocol: Add support for displaying images inside programs that do not support the protocol such as vim and tmux (:pull:`5664`) + - Fix a regression in 0.27.0 that broke ``kitty @ set-font-size 0`` (:iss:`5992`) - launch: When using ``--cwd=current`` for a remote system support running non shell commands as well (:disc:`5987`) @@ -156,8 +158,6 @@ Detailed list of changes - macOS: Export kitty selected text to the system for use with services that accept it (patch by Sertaç Ö. Yıldız) -- Image placement using Unicode placeholders (:pull:`5664`) - 0.26.5 [2022-11-07] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/graphics-protocol.rst b/docs/graphics-protocol.rst index 2979501a7..5ee16925c 100644 --- a/docs/graphics-protocol.rst +++ b/docs/graphics-protocol.rst @@ -475,35 +475,72 @@ z-index and the same id, then the behavior is undefined. Unicode placeholders ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. versionadded:: 0.27.0 - Unicode placeholders +.. versionadded:: 0.28.0 + Support for image display via Unicode placeholders You can also use a special Unicode character ``U+10EEEE`` as a placeholder for -an image. This approach is less flexible, but it works for any application that -supports Unicode and foreground colors (tmux, vim, etc). To use it, you need to -create a virtual image placement by specifying ``U=1`` and the desirable number -of lines and columns:: +an image. This approach is less flexible, but it allows using images inside +any host application that supports Unicode and foreground colors (tmux, vim, weechat, etc.) +and has a way to pass escape codes through to the underlying terminal. + +The central idea is that we use a single *Private Use* Unicode character as a +*placeholder* to indicate to the terminal that an image is supposed to be +displayed at that cell. Since this character is just normal text, Unicode aware +application will move it around as needed when they redraw their screens, +thereby automatically moving the displayed image as well, even though they know +nothing about the graphics protocol. So an image is first created using the +normal graphics protocol escape codes (albeit in quiet mode (``q=2``) so that there are +no responses from the terminal that could confuse the host application). Then, +the actual image is displayed by getting the host application to emit normal +text consisting of ``U+10EEEE`` and various diacritics (Unicode combining +characters) and colors. + +To use it, first create an image as you would normally with the graphics +protocol with (``q=2``), but do not create a placement for it, that is, do not +display it. Then, create a *virtual image placement* by specifying ``U=1`` and +the desired number of lines and columns:: _Ga=p,U=1,i=,c=,r=\ -The image will be fit to the specified rectangle, its aspect ratio preserved (in -the future more scaling modes may be added to the protocol). Now you can display -the image using the placeholder character, encoding the image ID in its -foreground color. The row and column values are specified with diacritics listed -in ``rowcolumn-diacritics.txt``. For example, here is how you can print a 2x2 -placeholder for image ID 42:: +The image will eventually be fit to the specified rectangle, its aspect ratio +preserved. Finally, the image can be actually displayed by using the +placeholder character, encoding the image ID in its foreground color. The row +and column values are specified with diacritics listed in +:download:`rowcolumn-diacritics.txt <../rowcolumn-diacritics.txt>`. For +example, here is how you can print a ``2x2`` placeholder for image ID ``42``: - printf "\e[38;5;42m\U10EEEE\U0305\U0305\U10EEEE\U0305\U030D\n" - printf "\e[38;5;42m\U10EEEE\U030D\U0305\U10EEEE\U030D\U030D\n" +.. code-block:: sh -By using only the foreground color you are limited to 8-bit IDs in 256 color -mode and to 24-bit IDs in true color mode. If you need more bits for the image -ID, you can specify the most significant byte via the third diacritic. For -example, this is the placeholder for the image ID ``738197504 = 42 + 2 << 24``:: + printf "\e[38;5;42m\U10EEEE\U0305\U0305\U10EEEE\U0305\U030D\e[39m\n" + printf "\e[38;5;42m\U10EEEE\U030D\U0305\U10EEEE\U030D\U030D\e[39m\n" + +Here, ``U+305`` is the diacritic corresponding to the number ``0`` +and ``U+30D`` corresponds to ``1``. So these two commands create the following +``2x2`` placeholder: + +========== ========== +(0, 0) (1, 0) +(1, 0) (1, 1) +========== ========== + +This will cause the image with ID ``42`` to be displayed in a ``2x2`` grid. +Ideally, you would print out as many cells as the number of rows and columns +specified when creating the virtual placement, but in case of a mismatch only +part of the image will be displayed. + +By using only the foreground color for image ID you are limited to either 8-bit IDs in 256 color +mode or 24-bit IDs in true color mode. Since IDs are in a global namespace +there can easily be collisions. If you need more bits for the image +ID, you can specify the most significant byte via a third diacritic. For +example, this is the placeholder for the image ID ``738197504 = 42 + (2 << 24)``: + +.. code-block:: sh printf "\e[38;5;42m\U10EEEE\U0305\U0305\U030E\U10EEEE\U0305\U030D\U030E\n" printf "\e[38;5;42m\U10EEEE\U030D\U0305\U030E\U10EEEE\U030D\U030D\U030E\n" +Here, ``U+30E`` is the diacritic corresponding to the number ``2``. + You can also specify a placement ID using the underline color (if it's omitted or zero, the terminal may choose any virtual placement of the given image). The background color is interpreted as the background color, visible if the image is @@ -511,7 +548,7 @@ transparent. Other text attributes are reserved for future use. Row, column and most significant byte diacritics may also be omitted, in which case the placeholder cell will inherit the missing values from the placeholder -cell to the left: +cell to the left, following the algorithm: - If no diacritics are present, and the previous placeholder cell has the same foreground and underline colors, then the row of the current cell will be the @@ -530,7 +567,9 @@ cell to the left: of the cell to the left. These rules are applied left-to-right, which allows specifying only row -diacritics of the first column, i.e. here is a 2 rows by 3 columns placeholder:: +diacritics of the first column, i.e. here is a 2 rows by 3 columns placeholder: + +.. code-block:: sh printf "\e[38;5;42m\U10EEEE\U0305\U10EEEE\U10EEEE\n" printf "\e[38;5;42m\U10EEEE\U030D\U10EEEE\U10EEEE\n" @@ -540,17 +579,17 @@ given rules will fail to guess the missing information. In such cases, the terminal may apply other heuristics (but it doesn't have to). It is important to distinguish between virtual image placements and real images -displayed on top of placeholders. Virtual placements are invisible and only play +displayed on top of Unicode placeholders. Virtual placements are invisible and only play the role of prototypes for real images. Virtual placements can be deleted by a deletion command only when the `d` key is equal to ``i``, ``I``, ``n`` or ``N``. The key values ``a``, ``c``, ``p``, ``q``, ``x``, ``y``, ``z`` and their capital variants never affect virtual placements because they do not have a physical location on the screen. -Real images displayed on top of placeholders are not considered placements from -the protocol perspective. They cannot be manipulated using graphics commands, -instead they should be moved, deleted, or modified by manipulating the -underlying placeholder as normal text. +Real images displayed on top of Unicode placeholders are not considered +placements from the protocol perspective. They cannot be manipulated using +graphics commands, instead they should be moved, deleted, or modified by +manipulating the underlying Unicode placeholder as normal text. Deleting images diff --git a/kitty/graphics.c b/kitty/graphics.c index f348ee921..479109c9f 100644 --- a/kitty/graphics.c +++ b/kitty/graphics.c @@ -747,17 +747,16 @@ Image *grman_put_cell_image(GraphicsManager *self, uint32_t screen_row, float x_offset, y_offset, x_scale, y_scale; // Fit the image to the box while preserving aspect ratio - if (img->width * img_rows * cell.height > - img->height * img_columns * cell.width) { + if (img->width * img_rows * cell.height > img->height * img_columns * cell.width) { // Fit to width and center vertically. x_offset = 0; - x_scale = (float)(img_columns * cell.width) / img->width; + x_scale = (float)(img_columns * cell.width) / MAX(1u, img->width); y_scale = x_scale; y_offset = (img_rows * cell.height - img->height * y_scale) / 2; } else { // Fit to height and center horizontally. y_offset = 0; - y_scale = (float)(img_rows * cell.height) / img->height; + y_scale = (float)(img_rows * cell.height) / MAX(1u, img->height); x_scale = y_scale; x_offset = (img_columns * cell.width - img->width * x_scale) / 2; }