[hb-view] Use Chafa for terminal graphics if available
This produces high-quality terminal graphics using symbols or sixels according to the detected terminal capabilities. Fixes #2430.
This commit is contained in:
parent
425ba1f4ab
commit
8298c2f93b
19
configure.ac
19
configure.ac
@ -214,6 +214,24 @@ AM_CONDITIONAL(HAVE_CAIRO_FT, $have_cairo_ft)
|
|||||||
|
|
||||||
dnl ==========================================================================
|
dnl ==========================================================================
|
||||||
|
|
||||||
|
AC_ARG_WITH(chafa,
|
||||||
|
[AS_HELP_STRING([--with-chafa=@<:@yes/no/auto@:>@],
|
||||||
|
[Use chafa @<:@default=auto@:>@])],,
|
||||||
|
[with_chafa=auto])
|
||||||
|
have_chafa=false
|
||||||
|
if test "x$with_chafa" = "xyes" -o "x$with_chafa" = "xauto"; then
|
||||||
|
PKG_CHECK_MODULES(CHAFA, chafa >= 1.6.0, have_chafa=true, :)
|
||||||
|
fi
|
||||||
|
if test "x$with_chafa" = "xyes" -a "x$have_chafa" != "xtrue"; then
|
||||||
|
AC_MSG_ERROR([chafa support requested but not found])
|
||||||
|
fi
|
||||||
|
if $have_chafa; then
|
||||||
|
AC_DEFINE(HAVE_CHAFA, 1, [Have chafa terminal graphics library])
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(HAVE_CHAFA, $have_chafa)
|
||||||
|
|
||||||
|
dnl ==========================================================================
|
||||||
|
|
||||||
AC_ARG_WITH(icu,
|
AC_ARG_WITH(icu,
|
||||||
[AS_HELP_STRING([--with-icu=@<:@yes/no/builtin/auto@:>@],
|
[AS_HELP_STRING([--with-icu=@<:@yes/no/builtin/auto@:>@],
|
||||||
[Use ICU @<:@default=auto@:>@])],,
|
[Use ICU @<:@default=auto@:>@])],,
|
||||||
@ -448,6 +466,7 @@ Font callbacks (the more the merrier):
|
|||||||
|
|
||||||
Tools used for command-line utilities:
|
Tools used for command-line utilities:
|
||||||
Cairo: ${have_cairo}
|
Cairo: ${have_cairo}
|
||||||
|
Chafa: ${have_chafa}
|
||||||
|
|
||||||
Additional shapers:
|
Additional shapers:
|
||||||
Graphite2: ${have_graphite2}
|
Graphite2: ${have_graphite2}
|
||||||
|
@ -154,6 +154,8 @@ if not get_option('cairo').disabled()
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
chafa_dep = dependency('chafa', version: '>= 1.6.0', required: get_option('chafa'))
|
||||||
|
|
||||||
conf = configuration_data()
|
conf = configuration_data()
|
||||||
incconfig = include_directories('.')
|
incconfig = include_directories('.')
|
||||||
|
|
||||||
@ -181,6 +183,10 @@ if cairo_ft_dep.found()
|
|||||||
conf.set('HAVE_CAIRO_FT', 1)
|
conf.set('HAVE_CAIRO_FT', 1)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if chafa_dep.found()
|
||||||
|
conf.set('HAVE_CHAFA', 1)
|
||||||
|
endif
|
||||||
|
|
||||||
if graphite2_dep.found()
|
if graphite2_dep.found()
|
||||||
conf.set('HAVE_GRAPHITE2', 1)
|
conf.set('HAVE_GRAPHITE2', 1)
|
||||||
endif
|
endif
|
||||||
@ -363,6 +369,7 @@ build_summary = {
|
|||||||
},
|
},
|
||||||
'Dependencies used for command-line utilities':
|
'Dependencies used for command-line utilities':
|
||||||
{'Cairo': conf.get('HAVE_CAIRO', 0) == 1,
|
{'Cairo': conf.get('HAVE_CAIRO', 0) == 1,
|
||||||
|
'Chafa': conf.get('HAVE_CHAFA', 0) == 1,
|
||||||
},
|
},
|
||||||
'Additional shapers':
|
'Additional shapers':
|
||||||
{'Graphite2': conf.get('HAVE_GRAPHITE2', 0) == 1,
|
{'Graphite2': conf.get('HAVE_GRAPHITE2', 0) == 1,
|
||||||
|
@ -5,6 +5,8 @@ option('gobject', type: 'feature', value: 'auto',
|
|||||||
description: 'Enable GObject bindings')
|
description: 'Enable GObject bindings')
|
||||||
option('cairo', type: 'feature', value: 'auto',
|
option('cairo', type: 'feature', value: 'auto',
|
||||||
description: 'Use Cairo graphics library')
|
description: 'Use Cairo graphics library')
|
||||||
|
option('chafa', type: 'feature', value: 'auto',
|
||||||
|
description: 'Use Chafa terminal graphics library')
|
||||||
option('icu', type: 'feature', value: 'auto',
|
option('icu', type: 'feature', value: 'auto',
|
||||||
description: 'Enable ICU library unicode functions')
|
description: 'Enable ICU library unicode functions')
|
||||||
option('graphite', type: 'feature', value: 'disabled',
|
option('graphite', type: 'feature', value: 'disabled',
|
||||||
|
@ -25,6 +25,7 @@ AM_CPPFLAGS = \
|
|||||||
$(GLIB_CFLAGS) \
|
$(GLIB_CFLAGS) \
|
||||||
$(FREETYPE_CFLAGS) \
|
$(FREETYPE_CFLAGS) \
|
||||||
$(CAIRO_FT_CFLAGS) \
|
$(CAIRO_FT_CFLAGS) \
|
||||||
|
$(CHAFA_CFLAGS) \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
LDADD = \
|
LDADD = \
|
||||||
$(top_builddir)/src/libharfbuzz.la \
|
$(top_builddir)/src/libharfbuzz.la \
|
||||||
@ -42,6 +43,7 @@ hb_view_LDADD = \
|
|||||||
$(LDADD) \
|
$(LDADD) \
|
||||||
$(CAIRO_LIBS) \
|
$(CAIRO_LIBS) \
|
||||||
$(CAIRO_FT_LIBS) \
|
$(CAIRO_FT_LIBS) \
|
||||||
|
$(CHAFA_LIBS) \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
bin_PROGRAMS += hb-view
|
bin_PROGRAMS += hb-view
|
||||||
endif # HAVE_CAIRO_FT
|
endif # HAVE_CAIRO_FT
|
||||||
|
@ -26,9 +26,102 @@
|
|||||||
|
|
||||||
#include "helper-cairo-ansi.hh"
|
#include "helper-cairo-ansi.hh"
|
||||||
#include "options.hh"
|
#include "options.hh"
|
||||||
|
|
||||||
#include "ansi-print.hh"
|
#include "ansi-print.hh"
|
||||||
|
|
||||||
|
#ifdef HAVE_CHAFA
|
||||||
|
# include <chafa.h>
|
||||||
|
|
||||||
|
/* Similar to ansi-print.cc */
|
||||||
|
# define CELL_W 8
|
||||||
|
# define CELL_H (2 * CELL_W)
|
||||||
|
|
||||||
|
static void
|
||||||
|
chafa_print_image_rgb24 (const void *data, int width, int height, int stride)
|
||||||
|
{
|
||||||
|
ChafaTermInfo *term_info;
|
||||||
|
ChafaSymbolMap *symbol_map;
|
||||||
|
ChafaCanvasConfig *config;
|
||||||
|
ChafaCanvas *canvas;
|
||||||
|
GString *gs;
|
||||||
|
unsigned int cols = (width + CELL_W - 1) / CELL_W;
|
||||||
|
unsigned int rows = (height + CELL_H - 1) / CELL_H;
|
||||||
|
gchar **environ;
|
||||||
|
ChafaCanvasMode mode;
|
||||||
|
ChafaPixelMode pixel_mode;
|
||||||
|
|
||||||
|
/* Adapt to terminal; use sixels if available, and fall back to symbols
|
||||||
|
* with as many colors as are supported */
|
||||||
|
|
||||||
|
environ = g_get_environ ();
|
||||||
|
term_info = chafa_term_db_detect (chafa_term_db_get_default (),
|
||||||
|
environ);
|
||||||
|
|
||||||
|
pixel_mode = CHAFA_PIXEL_MODE_SYMBOLS;
|
||||||
|
|
||||||
|
if (chafa_term_info_have_seq (term_info, CHAFA_TERM_SEQ_BEGIN_SIXELS))
|
||||||
|
{
|
||||||
|
pixel_mode = CHAFA_PIXEL_MODE_SIXELS;
|
||||||
|
mode = CHAFA_CANVAS_MODE_TRUECOLOR;
|
||||||
|
}
|
||||||
|
else if (chafa_term_info_have_seq (term_info, CHAFA_TERM_SEQ_SET_COLOR_FGBG_DIRECT))
|
||||||
|
mode = CHAFA_CANVAS_MODE_TRUECOLOR;
|
||||||
|
else if (chafa_term_info_have_seq (term_info, CHAFA_TERM_SEQ_SET_COLOR_FGBG_256))
|
||||||
|
mode = CHAFA_CANVAS_MODE_INDEXED_240;
|
||||||
|
else if (chafa_term_info_have_seq (term_info, CHAFA_TERM_SEQ_SET_COLOR_FGBG_16))
|
||||||
|
mode = CHAFA_CANVAS_MODE_INDEXED_16;
|
||||||
|
else if (chafa_term_info_have_seq (term_info, CHAFA_TERM_SEQ_INVERT_COLORS))
|
||||||
|
mode = CHAFA_CANVAS_MODE_FGBG_BGFG;
|
||||||
|
else
|
||||||
|
mode = CHAFA_CANVAS_MODE_FGBG;
|
||||||
|
|
||||||
|
/* Create the configuration */
|
||||||
|
|
||||||
|
symbol_map = chafa_symbol_map_new ();
|
||||||
|
chafa_symbol_map_add_by_tags (symbol_map,
|
||||||
|
(ChafaSymbolTags) (CHAFA_SYMBOL_TAG_BLOCK
|
||||||
|
| CHAFA_SYMBOL_TAG_SPACE));
|
||||||
|
|
||||||
|
config = chafa_canvas_config_new ();
|
||||||
|
chafa_canvas_config_set_canvas_mode (config, mode);
|
||||||
|
chafa_canvas_config_set_pixel_mode (config, pixel_mode);
|
||||||
|
chafa_canvas_config_set_cell_geometry (config, 10, 20);
|
||||||
|
chafa_canvas_config_set_geometry (config, cols, rows);
|
||||||
|
chafa_canvas_config_set_symbol_map (config, symbol_map);
|
||||||
|
chafa_canvas_config_set_color_extractor (config, CHAFA_COLOR_EXTRACTOR_MEDIAN);
|
||||||
|
chafa_canvas_config_set_work_factor (config, 1.0f);
|
||||||
|
|
||||||
|
/* Create canvas, draw to it and render output string */
|
||||||
|
|
||||||
|
canvas = chafa_canvas_new (config);
|
||||||
|
chafa_canvas_draw_all_pixels (canvas,
|
||||||
|
/* Cairo byte order is host native */
|
||||||
|
G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
? CHAFA_PIXEL_BGRA8_PREMULTIPLIED
|
||||||
|
: CHAFA_PIXEL_ARGB8_PREMULTIPLIED,
|
||||||
|
(const guint8 *) data,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
stride);
|
||||||
|
gs = chafa_canvas_print (canvas, term_info);
|
||||||
|
|
||||||
|
/* Print the string */
|
||||||
|
|
||||||
|
fwrite (gs->str, sizeof (char), gs->len, stdout);
|
||||||
|
|
||||||
|
if (pixel_mode != CHAFA_PIXEL_MODE_SIXELS)
|
||||||
|
fputc ('\n', stdout);
|
||||||
|
|
||||||
|
/* Free resources */
|
||||||
|
|
||||||
|
g_string_free (gs, TRUE);
|
||||||
|
chafa_canvas_unref (canvas);
|
||||||
|
chafa_canvas_config_unref (config);
|
||||||
|
chafa_symbol_map_unref (symbol_map);
|
||||||
|
chafa_term_info_unref (term_info);
|
||||||
|
g_strfreev (environ);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_CHAFA */
|
||||||
|
|
||||||
cairo_status_t
|
cairo_status_t
|
||||||
helper_cairo_surface_write_to_ansi_stream (cairo_surface_t *surface,
|
helper_cairo_surface_write_to_ansi_stream (cairo_surface_t *surface,
|
||||||
@ -95,7 +188,14 @@ helper_cairo_surface_write_to_ansi_stream (cairo_surface_t *surface,
|
|||||||
height++; /* Add one last blank row for padding. */
|
height++; /* Add one last blank row for padding. */
|
||||||
|
|
||||||
if (width && height)
|
if (width && height)
|
||||||
ansi_print_image_rgb24 (data, width, height, stride / 4);
|
{
|
||||||
|
#ifdef HAVE_CHAFA
|
||||||
|
if (true)
|
||||||
|
chafa_print_image_rgb24 (data, width, height, stride);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
ansi_print_image_rgb24 (data, width, height, stride / 4);
|
||||||
|
}
|
||||||
|
|
||||||
cairo_surface_destroy (surface);
|
cairo_surface_destroy (surface);
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
@ -31,7 +31,7 @@ if conf.get('HAVE_GLIB', 0) == 1
|
|||||||
hb_view = executable('hb-view', hb_view_sources,
|
hb_view = executable('hb-view', hb_view_sources,
|
||||||
cpp_args: cpp_args,
|
cpp_args: cpp_args,
|
||||||
include_directories: [incconfig, incsrc],
|
include_directories: [incconfig, incsrc],
|
||||||
dependencies: util_deps,
|
dependencies: [util_deps, chafa_dep],
|
||||||
link_with: [libharfbuzz],
|
link_with: [libharfbuzz],
|
||||||
install: true,
|
install: true,
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user