Skip to content

Commit

Permalink
chafa: Improvements to relative mode
Browse files Browse the repository at this point in the history
  • Loading branch information
hpjansson committed Jun 25, 2023
1 parent bb13c48 commit 906ed6b
Showing 1 changed file with 63 additions and 34 deletions.
97 changes: 63 additions & 34 deletions tools/chafa/chafa.c
Expand Up @@ -52,6 +52,9 @@
# include <io.h>
#endif

/* Maximum size of stack-allocated read/write buffer */
#define BUFFER_MAX 4096

#define ANIM_FPS_MAX 100000.0
#define FILE_DURATION_DEFAULT 0.0
#define SCALE_MAX 9999.0
Expand Down Expand Up @@ -1946,35 +1949,56 @@ write_gstrings_to_stdout (GString **gsa)
return TRUE;
}

#define PAD_SPACES_MAX 4096

static gboolean
write_pad_spaces (gint n)
{
gchar buf [PAD_SPACES_MAX];
gchar buf [BUFFER_MAX];
gint i;

g_assert (n >= 0);

n = MIN (n, PAD_SPACES_MAX);
n = MIN (n, BUFFER_MAX);
for (i = 0; i < n; i++)
buf [i] = ' ';

return write_to_stdout (buf, n);
}

static gboolean
write_cursor_down_scroll_n (gint n)
{
gchar buf [BUFFER_MAX];
gchar *p0 = buf;

if (n == 0)
return TRUE;

for ( ; n; n--)
{
p0 = chafa_term_info_emit_cursor_down_scroll (options.term_info, p0);
if (p0 - buf + CHAFA_TERM_SEQ_LENGTH_MAX > BUFFER_MAX)
{
write_to_stdout (buf, p0 - buf);
p0 = buf;
}
}

return write_to_stdout (buf, p0 - buf);
}

/* Write out the image data, possibly centering it */
static gboolean
write_image (GString **gsa, gint dest_width)
{
gchar buf [CHAFA_TERM_SEQ_LENGTH_MAX * 2 + 3];
gchar buf [CHAFA_TERM_SEQ_LENGTH_MAX * 3 + 3];
gchar *p0 = buf;
gint left_space;
gboolean result = FALSE;

left_space = options.center ? (options.view_width - dest_width) / 2 : 0;

/* Indent top left corner: Common for all modes */

if (left_space > 0)
{
if (options.relative)
Expand All @@ -1998,22 +2022,18 @@ write_image (GString **gsa, gint dest_width)

for (i = 0; gsa [i]; i++)
{
if (gsa [i + 1] && options.relative)
{
p0 = chafa_term_info_emit_save_cursor_pos (options.term_info, buf);
if (!write_to_stdout (buf, p0 - buf))
goto out;
}

if (!write_gstring_to_stdout (gsa [i]))
goto out;

if (gsa [i + 1])
{
if (options.relative)
{
p0 = chafa_term_info_emit_restore_cursor_pos (options.term_info, buf);
p0 = chafa_term_info_emit_cursor_left (options.term_info, buf, left_space + dest_width);
p0 = chafa_term_info_emit_cursor_down_scroll (options.term_info, p0);

if (left_space > 0)
p0 = chafa_term_info_emit_cursor_right (options.term_info, p0, left_space);
if (!write_to_stdout (buf, p0 - buf))
goto out;
}
Expand Down Expand Up @@ -2121,11 +2141,24 @@ pixel_to_cell_dimensions (gdouble scale,
}

static gboolean
write_image_prologue (gboolean is_first_file, gboolean is_first_frame, gint dest_height)
write_image_prologue (gboolean is_first_file, gboolean is_first_frame,
gboolean is_animation, gint dest_height)
{
gchar buf [CHAFA_TERM_SEQ_LENGTH_MAX * 4 + 3];
gchar buf [CHAFA_TERM_SEQ_LENGTH_MAX * 2];
gchar *p0 = buf;

/* Insert a blank line between files in continuous (!clear) mode */
if (is_first_frame && !options.clear && !is_first_file)
{
if (!options.have_parking_row)
p0 = emit_vertical_space (p0);
p0 = emit_vertical_space (p0);

if (!write_to_stdout (buf, p0 - buf))
return FALSE;
p0 = buf;
}

if (options.clear)
{
if (is_first_frame)
Expand All @@ -2137,18 +2170,19 @@ write_image_prologue (gboolean is_first_file, gboolean is_first_frame, gint dest
/* Home cursor between frames */
p0 = chafa_term_info_emit_cursor_to_top_left (options.term_info, p0);
}
else if (!is_first_frame)
else if (is_first_frame && is_animation)
{
/* Cursor to top left of image rectangle, always relative positioning */
p0 = chafa_term_info_emit_cursor_up (options.term_info, p0, dest_height - (options.have_parking_row ? 0 : 1));
}
/* Start animation: reserve space and save image origin */
if (!write_cursor_down_scroll_n (dest_height))
return FALSE;

/* Put a blank line between files in continuous (!clear) mode */
if (is_first_frame && !options.clear && !is_first_file)
p0 = chafa_term_info_emit_cursor_up (options.term_info, p0, dest_height);
p0 = chafa_term_info_emit_save_cursor_pos (options.term_info, p0);
}
else if (!is_first_frame)
{
if (!options.have_parking_row)
p0 = emit_vertical_space (p0);
p0 = emit_vertical_space (p0);
/* Subsequent animation frames: cursor to image origin */
p0 = chafa_term_info_emit_restore_cursor_pos (options.term_info, p0);
}

return write_to_stdout (buf, p0 - buf);
Expand All @@ -2175,9 +2209,8 @@ write_image_epilogue (gint dest_width)
else if (!options.relative)
{
/* We need this because absolute mode relies on emit_vertical_space()
* producing an \n that implies a CR with Unix semantics. */
if (!write_to_stdout ("\r", 1))
return FALSE;
* producing an \n that implies a CR with Unix semantics */
*(p0++) = '\r';
}

if (options.relative)
Expand All @@ -2186,9 +2219,7 @@ write_image_epilogue (gint dest_width)
}
else /* CHAFA_PIXEL_MODE_SIXELS */
{
/* Sixel mode leaves cursor below the leftmost column (typical default,
* enforceable with --polite off). That's where we want it, in the
* parking row. */
/* Sixel mode leaves cursor somewhere at or below the leftmost column */

if (left_space > 0)
{
Expand All @@ -2199,13 +2230,11 @@ write_image_epilogue (gint dest_width)
}
else
{
if (!write_to_stdout ("\r", 1))
return FALSE;
*(p0++) = '\r';
}
}
}


return write_to_stdout (buf, p0 - buf);
}

Expand Down Expand Up @@ -2316,7 +2345,7 @@ run_generic (const gchar *filename, gboolean is_first_file, gboolean is_first_fr
dest_width, dest_height,
is_animation);

if (!write_image_prologue (is_first_file, is_first_frame, dest_height)
if (!write_image_prologue (is_first_file, is_first_frame, is_animation, dest_height)
|| !write_image (gsa, dest_width)
|| !write_image_epilogue (dest_width)
|| fflush (stdout) != 0)
Expand Down

0 comments on commit 906ed6b

Please sign in to comment.