Merge branch 'master' into releases/1.8

This commit is contained in:
Daniel Eklöf 2021-07-01 20:13:49 +02:00
commit fd974e139e
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
24 changed files with 1509 additions and 193 deletions

View file

@ -1,5 +1,6 @@
# Changelog # Changelog
* [Unreleased](#unreleased)
* [1.8.0](#1-8-0) * [1.8.0](#1-8-0)
* [1.7.2](#1-7-2) * [1.7.2](#1-7-2)
* [1.7.1](#1-7-1) * [1.7.1](#1-7-1)
@ -26,6 +27,40 @@
* [1.2.0](#1-2-0) * [1.2.0](#1-2-0)
## Unreleased
### Added
* `--log-level=none` command-line option.
* `Tc`, `setrgbf` and `setrgbb` capabilities in `foot` and `foot-direct`
terminfo entries. This should make 24-bit RGB colors work in tmux and
neovim, without the need for config hacks or detection heuristics
(https://codeberg.org/dnkl/foot/issues/615).
### Changed
* Grapheme cluster width is now limited to two cells by default. This
may cause cursor synchronization issues with many applications. You
can set `[tweak].grapheme-width-method=wcswidth` to revert to the
behavior from foot-1.8.0.
### Deprecated
### Removed
### Fixed
* Grapheme cluster state being reset between codepoints.
* Regression: custom URL key bindings not working
(https://codeberg.org/dnkl/foot/issues/614).
### Security
### Contributors
* [craigbarnes](https://codeberg.org/craigbarnes)
## 1.8.0 ## 1.8.0
### Grapheme shaping ### Grapheme shaping

View file

@ -58,22 +58,22 @@ print_usage(const char *prog_name)
printf("Usage: %s [OPTIONS...] command [ARGS...]\n", prog_name); printf("Usage: %s [OPTIONS...] command [ARGS...]\n", prog_name);
printf("\n"); printf("\n");
printf("Options:\n"); printf("Options:\n");
printf(" -t,--term=TERM value to set the environment variable TERM to (foot)\n" printf(" -t,--term=TERM value to set the environment variable TERM to (foot)\n"
" -T,--title=TITLE initial window title (foot)\n" " -T,--title=TITLE initial window title (foot)\n"
" -a,--app-id=ID window application ID (foot)\n" " -a,--app-id=ID window application ID (foot)\n"
" -w,--window-size-pixels=WIDTHxHEIGHT initial width and height, in pixels\n" " -w,--window-size-pixels=WIDTHxHEIGHT initial width and height, in pixels\n"
" -W,--window-size-chars=WIDTHxHEIGHT initial width and height, in characters\n" " -W,--window-size-chars=WIDTHxHEIGHT initial width and height, in characters\n"
" -m,--maximized start in maximized mode\n" " -m,--maximized start in maximized mode\n"
" -F,--fullscreen start in fullscreen mode\n" " -F,--fullscreen start in fullscreen mode\n"
" -L,--login-shell start shell as a login shell\n" " -L,--login-shell start shell as a login shell\n"
" -D,--working-directory=DIR directory to start in (CWD)\n" " -D,--working-directory=DIR directory to start in (CWD)\n"
" -s,--server-socket=PATH path to the server UNIX domain socket (default=$XDG_RUNTIME_DIR/foot-$WAYLAND_DISPLAY.sock)\n" " -s,--server-socket=PATH path to the server UNIX domain socket (default=$XDG_RUNTIME_DIR/foot-$WAYLAND_DISPLAY.sock)\n"
" -H,--hold remain open after child process exits\n" " -H,--hold remain open after child process exits\n"
" -N,--no-wait detach the client process from the running terminal, exiting immediately\n" " -N,--no-wait detach the client process from the running terminal, exiting immediately\n"
" -o,--override=[section.]key=value override configuration option\n" " -o,--override=[section.]key=value override configuration option\n"
" -d,--log-level={info|warning|error} log level (info)\n" " -d,--log-level={info|warning|error|none} log level (info)\n"
" -l,--log-colorize=[{never|always|auto}] enable/disable colorization of log output on stderr\n" " -l,--log-colorize=[{never|always|auto}] enable/disable colorization of log output on stderr\n"
" -v,--version show the version number and quit\n"); " -v,--version show the version number and quit\n");
} }
static bool NOINLINE static bool NOINLINE

View file

@ -68,7 +68,7 @@ _foot()
which fc-list > /dev/null || return 1 which fc-list > /dev/null || return 1
COMPREPLY=( $(compgen -W "$(fc-list : family | sed 's/,/\n/g' | uniq | tr -d ' ')" -- ${cur}) ) COMPREPLY=( $(compgen -W "$(fc-list : family | sed 's/,/\n/g' | uniq | tr -d ' ')" -- ${cur}) )
elif [[ ${prev} == '--log-level' ]] ; then elif [[ ${prev} == '--log-level' ]] ; then
COMPREPLY=( $(compgen -W "error warning info" -- ${cur}) ) COMPREPLY=( $(compgen -W "none error warning info" -- ${cur}) )
elif [[ ${prev} == '--log-colorize' ]] ; then elif [[ ${prev} == '--log-colorize' ]] ; then
COMPREPLY=( $(compgen -W "never always auto" -- ${cur}) ) COMPREPLY=( $(compgen -W "never always auto" -- ${cur}) )
elif [[ ${prev} =~ ^(--app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels|--check-config)$ ]] ; then elif [[ ${prev} =~ ^(--app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels|--check-config)$ ]] ; then

View file

@ -59,7 +59,7 @@ _footclient()
which toe > /dev/null || return 1 which toe > /dev/null || return 1
COMPREPLY=( $(compgen -W "$(toe -a | awk '$1 ~ /[+]/ {next}; {print $1}')" -- ${cur}) ) COMPREPLY=( $(compgen -W "$(toe -a | awk '$1 ~ /[+]/ {next}; {print $1}')" -- ${cur}) )
elif [[ ${prev} == '--log-level' ]] ; then elif [[ ${prev} == '--log-level' ]] ; then
COMPREPLY=( $(compgen -W "error warning info" -- ${cur}) ) COMPREPLY=( $(compgen -W "none error warning info" -- ${cur}) )
elif [[ ${prev} == '--log-colorize' ]] ; then elif [[ ${prev} == '--log-colorize' ]] ; then
COMPREPLY=( $(compgen -W "never always auto" -- ${cur}) ) COMPREPLY=( $(compgen -W "never always auto" -- ${cur}) )
elif [[ ${prev} =~ ^(--app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels|)$ ]] ; then elif [[ ${prev} =~ ^(--app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels|)$ ]] ; then

View file

@ -15,7 +15,7 @@ complete -c foot -x -s W -l window-size-chars
complete -c foot -F -s s -l server -d "run as server; open terminals by running footclient" complete -c foot -F -s s -l server -d "run as server; open terminals by running footclient"
complete -c foot -s H -l hold -d "remain open after child process exits" complete -c foot -s H -l hold -d "remain open after child process exits"
complete -c foot -r -s p -l print-pid -d "print PID to this file or FD when up and running (server mode only)" complete -c foot -r -s p -l print-pid -d "print PID to this file or FD when up and running (server mode only)"
complete -c foot -x -s d -l log-level -a "info warning error" -d "log-level (info)" complete -c foot -x -s d -l log-level -a "info warning error none" -d "log-level (info)"
complete -c foot -x -s l -l log-colorize -a "always never auto" -d "enable or disable colorization of log output on stderr" complete -c foot -x -s l -l log-colorize -a "always never auto" -d "enable or disable colorization of log output on stderr"
complete -c foot -s S -l log-no-syslog -d "disable syslog logging (server mode only)" complete -c foot -s S -l log-no-syslog -d "disable syslog logging (server mode only)"
complete -c foot -s v -l version -d "show the version number and quit" complete -c foot -s v -l version -d "show the version number and quit"

View file

@ -12,7 +12,7 @@ complete -c footclient -F -s s -l server-socket
complete -c footclient -s H -l hold -d "remain open after child process exits" complete -c footclient -s H -l hold -d "remain open after child process exits"
complete -c footclient -s N -l no-wait -d "detach the client process from the running terminal, exiting immediately" complete -c footclient -s N -l no-wait -d "detach the client process from the running terminal, exiting immediately"
complete -c footclient -x -s o -l override -d "configuration option to override, in form SECTION.KEY=VALUE" complete -c footclient -x -s o -l override -d "configuration option to override, in form SECTION.KEY=VALUE"
complete -c footclient -x -s d -l log-level -a "info warning error" -d "log-level (info)" complete -c footclient -x -s d -l log-level -a "info warning error none" -d "log-level (info)"
complete -c footclient -x -s l -l log-colorize -a "always never auto" -d "enable or disable colorization of log output on stderr" complete -c footclient -x -s l -l log-colorize -a "always never auto" -d "enable or disable colorization of log output on stderr"
complete -c footclient -s v -l version -d "show the version number and quit" complete -c footclient -s v -l version -d "show the version number and quit"
complete -c footclient -s h -l help -d "show help message and quit" complete -c footclient -s h -l help -d "show help message and quit"

View file

@ -18,7 +18,7 @@ _arguments \
'(-s --server)'{-s,--server}'[run as server; open terminals by running footclient]:server:_files' \ '(-s --server)'{-s,--server}'[run as server; open terminals by running footclient]:server:_files' \
'(-H --hold)'{-H,--hold}'[remain open after child process exits]' \ '(-H --hold)'{-H,--hold}'[remain open after child process exits]' \
'(-p --print-pid)'{-p,--print-pid}'[print PID to this file or FD when up and running (server mode only)]:pidfile:_files' \ '(-p --print-pid)'{-p,--print-pid}'[print PID to this file or FD when up and running (server mode only)]:pidfile:_files' \
'(-d --log-level)'{-d,--log-level}'[log level (info)]:loglevel:(info warning error)' \ '(-d --log-level)'{-d,--log-level}'[log level (info)]:loglevel:(info warning error none)' \
'(-l --log-colorize)'{-l,--log-colorize}'[enable or disable colorization of log output on stderr]:logcolor:(never always auto)' \ '(-l --log-colorize)'{-l,--log-colorize}'[enable or disable colorization of log output on stderr]:logcolor:(never always auto)' \
'(-S --log-no-syslog)'{-s,--log-no-syslog}'[disable syslog logging (server mode only)]' \ '(-S --log-no-syslog)'{-s,--log-no-syslog}'[disable syslog logging (server mode only)]' \
'(-v --version)'{-v,--version}'[show the version number and quit]' \ '(-v --version)'{-v,--version}'[show the version number and quit]' \

View file

@ -15,7 +15,7 @@ _arguments \
'(-H --hold)'{-H,--hold}'[remain open after child process exits]' \ '(-H --hold)'{-H,--hold}'[remain open after child process exits]' \
'(-N --no-wait)'{-N,--no-wait}'[detach the client process from the running terminal, exiting immediately]' \ '(-N --no-wait)'{-N,--no-wait}'[detach the client process from the running terminal, exiting immediately]' \
'(-o --override)'{-o,--override}'[configuration option to override, in form SECTION.KEY=VALUE]:()' \ '(-o --override)'{-o,--override}'[configuration option to override, in form SECTION.KEY=VALUE]:()' \
'(-d --log-level)'{-d,--log-level}'[log level (info)]:loglevel:(info warning error)' \ '(-d --log-level)'{-d,--log-level}'[log level (info)]:loglevel:(info warning error none)' \
'(-l --log-colorize)'{-l,--log-colorize}'[enable or disable colorization of log output on stderr]:logcolor:(never always auto)' \ '(-l --log-colorize)'{-l,--log-colorize}'[enable or disable colorization of log output on stderr]:logcolor:(never always auto)' \
'(-v --version)'{-v,--version}'[show the version number and quit]' \ '(-v --version)'{-v,--version}'[show the version number and quit]' \
'(-h --help)'{-h,--help}'[show help message and quit]' \ '(-h --help)'{-h,--help}'[show help message and quit]' \

201
config.c
View file

@ -103,8 +103,10 @@ log_and_notify(struct config *conf, enum log_class log_class,
case LOG_CLASS_INFO: case LOG_CLASS_INFO:
case LOG_CLASS_DEBUG: case LOG_CLASS_DEBUG:
BUG("unsupported log class: %d", log_class); case LOG_CLASS_NONE:
break; default:
BUG("unsupported log class: %d", (int)log_class);
return;
} }
va_list va1, va2; va_list va1, va2;
@ -191,7 +193,7 @@ struct path_component {
}; };
typedef tll(struct path_component) path_components_t; typedef tll(struct path_component) path_components_t;
static void static void NOINLINE
path_component_add(path_components_t *components, const char *comp, int fd) path_component_add(path_components_t *components, const char *comp, int fd)
{ {
xassert(comp != NULL); xassert(comp != NULL);
@ -201,14 +203,14 @@ path_component_add(path_components_t *components, const char *comp, int fd)
tll_push_back(*components, pc); tll_push_back(*components, pc);
} }
static void static void NOINLINE
path_component_destroy(struct path_component *component) path_component_destroy(struct path_component *component)
{ {
xassert(component->fd >= 0); xassert(component->fd >= 0);
close(component->fd); close(component->fd);
} }
static void static void NOINLINE
path_components_destroy(path_components_t *components) path_components_destroy(path_components_t *components)
{ {
tll_foreach(*components, it) { tll_foreach(*components, it) {
@ -1660,6 +1662,43 @@ pipe_argv_from_string(const char *value, char ***argv,
return remove_len; return remove_len;
} }
static void NOINLINE
remove_action_from_key_bindings_list(struct config_key_binding_list *bindings,
int action, char **pipe_argv)
{
size_t remove_first_idx = 0;
size_t remove_count = 0;
for (size_t i = 0; i < bindings->count; i++) {
struct config_key_binding *binding = &bindings->arr[i];
if (binding->action == action &&
((binding->pipe.argv.args == NULL && pipe_argv == NULL) ||
(binding->pipe.argv.args != NULL && pipe_argv != NULL &&
argv_compare(binding->pipe.argv.args, pipe_argv) == 0)))
{
if (remove_count++ == 0)
remove_first_idx = i;
xassert(remove_first_idx + remove_count - 1 == i);
if (binding->pipe.master_copy)
free_argv(&binding->pipe.argv);
}
}
if (remove_count == 0)
return;
size_t move_count = bindings->count - (remove_first_idx + remove_count);
memmove(
&bindings->arr[remove_first_idx],
&bindings->arr[remove_first_idx + remove_count],
move_count * sizeof(bindings->arr[0]));
bindings->count -= remove_count;
}
static bool NOINLINE static bool NOINLINE
parse_key_binding_section( parse_key_binding_section(
const char *section, const char *key, const char *value, const char *section, const char *key, const char *value,
@ -1686,17 +1725,7 @@ parse_key_binding_section(
/* Unset binding */ /* Unset binding */
if (strcasecmp(value, "none") == 0) { if (strcasecmp(value, "none") == 0) {
for (size_t i = 0; i < bindings->count; i++) { remove_action_from_key_bindings_list(bindings, action, pipe_argv);
struct config_key_binding *binding = &bindings->arr[i];
if (binding->action != action)
continue;
if (binding->pipe.master_copy)
free_argv(&binding->pipe.argv);
binding->action = BIND_ACTION_NONE;
}
free(pipe_argv); free(pipe_argv);
return true; return true;
} }
@ -1713,21 +1742,7 @@ parse_key_binding_section(
return false; return false;
} }
/* Remove existing bindings for this action+pipe */ remove_action_from_key_bindings_list(bindings, action, pipe_argv);
for (size_t i = 0; i < bindings->count; i++) {
struct config_key_binding *binding = &bindings->arr[i];
if (binding->action == action &&
((binding->pipe.argv.args == NULL && pipe_argv == NULL) ||
(binding->pipe.argv.args != NULL && pipe_argv != NULL &&
argv_compare(binding->pipe.argv.args, pipe_argv) == 0)))
{
if (binding->pipe.master_copy)
free_argv(&binding->pipe.argv);
binding->action = BIND_ACTION_NONE;
}
}
/* Emit key bindings */ /* Emit key bindings */
size_t ofs = bindings->count; size_t ofs = bindings->count;
@ -1765,6 +1780,90 @@ parse_key_binding_section(
return false; return false;
} }
UNITTEST
{
enum test_actions {
TEST_ACTION_NONE,
TEST_ACTION_FOO,
TEST_ACTION_BAR,
TEST_ACTION_COUNT,
};
const char *const map[] = {
[TEST_ACTION_NONE] = NULL,
[TEST_ACTION_FOO] = "foo",
[TEST_ACTION_BAR] = "bar",
};
struct config conf = {0};
struct config_key_binding_list bindings = {0};
/*
* ADD foo=Escape
*
* This verifies we can bind a single key combo to an action.
*/
xassert(parse_key_binding_section(
"", "foo", "Escape", ALEN(map), map, &bindings, &conf, "", 0));
xassert(bindings.count == 1);
xassert(bindings.arr[0].action == TEST_ACTION_FOO);
xassert(bindings.arr[0].sym == XKB_KEY_Escape);
/*
* ADD bar=Control+g Control+Shift+x
*
* This verifies we can bind multiple key combos to an action.
*/
xassert(parse_key_binding_section(
"", "bar", "Control+g Control+Shift+x", ALEN(map), map,
&bindings, &conf, "", 0));
xassert(bindings.count == 3);
xassert(bindings.arr[0].action == TEST_ACTION_FOO);
xassert(bindings.arr[1].action == TEST_ACTION_BAR);
xassert(bindings.arr[1].sym == XKB_KEY_g);
xassert(bindings.arr[1].modifiers.ctrl);
xassert(bindings.arr[2].action == TEST_ACTION_BAR);
xassert(bindings.arr[2].sym == XKB_KEY_x);
xassert(bindings.arr[2].modifiers.ctrl && bindings.arr[2].modifiers.shift);
/*
* REPLACE foo with foo=Mod+v Shift+q
*
* This verifies we can update a single-combo action with multiple
* key combos.
*/
xassert(parse_key_binding_section(
"", "foo", "Mod1+v Shift+q", ALEN(map), map,
&bindings, &conf, "", 0));
xassert(bindings.count == 4);
xassert(bindings.arr[0].action == TEST_ACTION_BAR);
xassert(bindings.arr[1].action == TEST_ACTION_BAR);
xassert(bindings.arr[2].action == TEST_ACTION_FOO);
xassert(bindings.arr[2].sym == XKB_KEY_v);
xassert(bindings.arr[2].modifiers.alt);
xassert(bindings.arr[3].action == TEST_ACTION_FOO);
xassert(bindings.arr[3].sym == XKB_KEY_q);
xassert(bindings.arr[3].modifiers.shift);
/*
* REMOVE bar
*/
xassert(parse_key_binding_section(
"", "bar", "none", ALEN(map), map, &bindings, &conf, "", 0));
xassert(bindings.count == 2);
xassert(bindings.arr[0].action == TEST_ACTION_FOO);
xassert(bindings.arr[1].action == TEST_ACTION_FOO);
/*
* REMOVE foo
*/
xassert(parse_key_binding_section(
"", "foo", "none", ALEN(map), map, &bindings, &conf, "", 0));
xassert(bindings.count == 0);
free(bindings.arr);
}
static bool static bool
parse_section_key_bindings( parse_section_key_bindings(
const char *key, const char *value, struct config *conf, const char *key, const char *value, struct config *conf,
@ -2156,6 +2255,15 @@ parse_section_tweak(
LOG_WARN("tweak: grapheme shaping"); LOG_WARN("tweak: grapheme shaping");
} }
else if (strcmp(key, "grapheme-width-method") == 0) {
if (strcmp(value, "double-width") == 0)
conf->tweak.grapheme_width_method = GRAPHEME_WIDTH_DOUBLE;
else if (strcmp(value, "wcswidth") == 0)
conf->tweak.grapheme_width_method = GRAPHEME_WIDTH_WCSWIDTH;
LOG_WARN("%s:%d [tweak]: grapheme-width-method=%s", path, lineno, value);
}
else if (strcmp(key, "render-timer") == 0) { else if (strcmp(key, "render-timer") == 0) {
if (strcmp(value, "none") == 0) { if (strcmp(value, "none") == 0) {
conf->tweak.render_timer_osd = false; conf->tweak.render_timer_osd = false;
@ -2724,6 +2832,7 @@ config_load(struct config *conf, const char *conf_path,
.fcft_filter = FCFT_SCALING_FILTER_LANCZOS3, .fcft_filter = FCFT_SCALING_FILTER_LANCZOS3,
.allow_overflowing_double_width_glyphs = true, .allow_overflowing_double_width_glyphs = true,
.grapheme_shaping = false, .grapheme_shaping = false,
.grapheme_width_method = GRAPHEME_WIDTH_DOUBLE,
.delayed_render_lower_ns = 500000, /* 0.5ms */ .delayed_render_lower_ns = 500000, /* 0.5ms */
.delayed_render_upper_ns = 16666666 / 2, /* half a frame period (60Hz) */ .delayed_render_upper_ns = 16666666 / 2, /* half a frame period (60Hz) */
.max_shm_pool_size = 512 * 1024 * 1024, .max_shm_pool_size = 512 * 1024 * 1024,
@ -2850,6 +2959,15 @@ out:
} }
} }
#if defined(_DEBUG)
for (size_t i = 0; i < conf->bindings.key.count; i++)
xassert(conf->bindings.key.arr[i].action != BIND_ACTION_NONE);
for (size_t i = 0; i < conf->bindings.search.count; i++)
xassert(conf->bindings.search.arr[i].action != BIND_ACTION_SEARCH_NONE);
for (size_t i = 0; i < conf->bindings.url.count; i++)
xassert(conf->bindings.url.arr[i].action != BIND_ACTION_URL_NONE);
#endif
free(conf_file.path); free(conf_file.path);
if (conf_file.fd >= 0) if (conf_file.fd >= 0)
close(conf_file.fd); close(conf_file.fd);
@ -3032,6 +3150,27 @@ config_clone(const struct config *old)
return conf; return conf;
} }
UNITTEST
{
struct config original;
user_notifications_t nots = tll_init();
config_override_t overrides = tll_init();
bool ret = config_load(&original, "/dev/null", &nots, &overrides, false);
xassert(ret);
struct config *clone = config_clone(&original);
xassert(clone != NULL);
xassert(clone != &original);
config_free(original);
config_free(*clone);
free(clone);
tll_free(overrides);
tll_free(nots);
}
void void
config_free(struct config conf) config_free(struct config conf)
{ {

View file

@ -246,6 +246,7 @@ struct config {
enum fcft_scaling_filter fcft_filter; enum fcft_scaling_filter fcft_filter;
bool allow_overflowing_double_width_glyphs; bool allow_overflowing_double_width_glyphs;
bool grapheme_shaping; bool grapheme_shaping;
enum {GRAPHEME_WIDTH_WCSWIDTH, GRAPHEME_WIDTH_DOUBLE} grapheme_width_method;
bool render_timer_osd; bool render_timer_osd;
bool render_timer_log; bool render_timer_log;
bool damage_whole_window; bool damage_whole_window;

View file

@ -0,0 +1,550 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<svg
width="1000" height="750"
viewBox="0 0 1000 750"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<title>Gnuplot</title>
<desc>Produced by GNUPLOT 5.4 patchlevel 2 </desc>
<g id="gnuplot_canvas">
<rect x="0" y="0" width="1000" height="750" fill="#ffffff"/>
<defs>
<circle id='gpDot' r='0.5' stroke-width='0.5' stroke='currentColor'/>
<path id='gpPt0' stroke-width='0.222' stroke='currentColor' d='M-1,0 h2 M0,-1 v2'/>
<path id='gpPt1' stroke-width='0.222' stroke='currentColor' d='M-1,-1 L1,1 M1,-1 L-1,1'/>
<path id='gpPt2' stroke-width='0.222' stroke='currentColor' d='M-1,0 L1,0 M0,-1 L0,1 M-1,-1 L1,1 M-1,1 L1,-1'/>
<rect id='gpPt3' stroke-width='0.222' stroke='currentColor' x='-1' y='-1' width='2' height='2'/>
<rect id='gpPt4' stroke-width='0.222' stroke='currentColor' fill='currentColor' x='-1' y='-1' width='2' height='2'/>
<circle id='gpPt5' stroke-width='0.222' stroke='currentColor' cx='0' cy='0' r='1'/>
<use xlink:href='#gpPt5' id='gpPt6' fill='currentColor' stroke='none'/>
<path id='gpPt7' stroke-width='0.222' stroke='currentColor' d='M0,-1.33 L-1.33,0.67 L1.33,0.67 z'/>
<use xlink:href='#gpPt7' id='gpPt8' fill='currentColor' stroke='none'/>
<use xlink:href='#gpPt7' id='gpPt9' stroke='currentColor' transform='rotate(180)'/>
<use xlink:href='#gpPt9' id='gpPt10' fill='currentColor' stroke='none'/>
<use xlink:href='#gpPt3' id='gpPt11' stroke='currentColor' transform='rotate(45)'/>
<use xlink:href='#gpPt11' id='gpPt12' fill='currentColor' stroke='none'/>
<path id='gpPt13' stroke-width='0.222' stroke='currentColor' d='M0,1.330 L1.265,0.411 L0.782,-1.067 L-0.782,-1.076 L-1.265,0.411 z'/>
<use xlink:href='#gpPt13' id='gpPt14' fill='currentColor' stroke='none'/>
<filter id='textbox' filterUnits='objectBoundingBox' x='0' y='0' height='1' width='1'>
<feFlood flood-color='#FFFFFF' flood-opacity='1' result='bgnd'/>
<feComposite in='SourceGraphic' in2='bgnd' operator='atop'/>
</filter>
<filter id='greybox' filterUnits='objectBoundingBox' x='0' y='0' height='1' width='1'>
<feFlood flood-color='lightgrey' flood-opacity='1' result='grey'/>
<feComposite in='SourceGraphic' in2='grey' operator='atop'/>
</filter>
</defs>
<g fill="none" color="#FFFFFF" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,559.96 L89.92,559.96 M974.82,559.96 L965.82,559.96 '/> <g transform="translate(72.53,563.86)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 0</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,485.11 L89.92,485.11 M974.82,485.11 L965.82,485.11 '/> <g transform="translate(72.53,489.01)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 200</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,410.26 L89.92,410.26 M974.82,410.26 L965.82,410.26 '/> <g transform="translate(72.53,414.16)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 400</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,335.41 L89.92,335.41 M974.82,335.41 L965.82,335.41 '/> <g transform="translate(72.53,339.31)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 600</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,260.56 L89.92,260.56 M974.82,260.56 L965.82,260.56 '/> <g transform="translate(72.53,264.46)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 800</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,185.71 L89.92,185.71 M974.82,185.71 L965.82,185.71 '/> <g transform="translate(72.53,189.61)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 1000</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,110.86 L89.92,110.86 M974.82,110.86 L965.82,110.86 '/> <g transform="translate(72.53,114.76)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 1200</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,36.01 L89.92,36.01 M974.82,36.01 L965.82,36.01 '/> <g transform="translate(72.53,39.91)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 1400</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M115.76,559.96 M115.76,36.01 '/> <g transform="translate(113.00,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>cursor_motion</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M204.70,559.96 M204.70,36.01 '/> <g transform="translate(201.94,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>dense_cells</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M293.65,559.96 M293.65,36.01 '/> <g transform="translate(290.89,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>light_cells</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M382.59,559.96 M382.59,36.01 '/> <g transform="translate(379.83,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>scrolling</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M471.54,559.96 M471.54,36.01 '/> <g transform="translate(468.78,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>scrolling_bottom_region</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M560.48,559.96 M560.48,36.01 '/> <g transform="translate(557.72,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>scrolling_bottom_small_region</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M649.43,559.96 M649.43,36.01 '/> <g transform="translate(646.67,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>scrolling_fullscreen</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M738.37,559.96 M738.37,36.01 '/> <g transform="translate(735.61,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>scrolling_top_region</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M827.32,559.96 M827.32,36.01 '/> <g transform="translate(824.56,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>scrolling_top_small_region</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M916.26,559.96 M916.26,36.01 '/> <g transform="translate(913.50,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>unicode</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,36.01 L80.92,559.96 L974.82,559.96 L974.82,36.01 L80.92,36.01 Z '/> <path stroke='rgb(136, 136, 136)' stroke-dasharray='1.0,2.5' d='M175.06,559.95 L175.06,36.00 M264.01,559.95 L264.01,36.00 M352.95,559.95 L352.95,36.00 M441.90,559.95 L441.90,36.00
M530.84,559.95 L530.84,36.00 M619.79,559.95 L619.79,36.00 M708.74,559.95 L708.74,36.00 M797.68,559.95 L797.68,36.00
M886.63,559.95 L886.63,36.00 '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g transform="translate(19.18,297.99) rotate(270)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="middle">
<text>milliseconds (lower is better)</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g id="gnuplot_plot_1" ><title>gnuplot_plot_1</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g transform="translate(241.08,21.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text>foot-pgo</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '249.47,22.50 292.03,22.50 292.03,13.50 249.47,13.50 '/>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '94.26,555.47 107.60,555.47 107.60,555.09 94.26,555.09 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M94.26,555.47 L107.60,555.47 L107.60,555.09 L94.26,555.09 L94.26,555.47 Z '/> <path stroke='rgb(148, 0, 211)' d='M94.26,555.09 L107.60,555.09 M100.93,555.84 L100.93,555.47 M100.93,555.09 L100.93,554.72 M91.93,554.72 L109.93,554.72
M91.93,555.84 L109.93,555.84 '/></g>
</g>
<g id="gnuplot_plot_2" ><title>gnuplot_plot_2</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '183.21,545.74 196.55,545.74 196.55,544.99 183.21,544.99 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M183.21,545.74 L196.55,545.74 L196.55,544.99 L183.21,544.99 L183.21,545.74 Z '/> <path stroke='rgb(148, 0, 211)' d='M183.21,545.36 L196.55,545.36 M189.88,546.49 L189.88,545.74 M189.88,544.99 L189.88,543.87 M180.88,543.87 L198.88,543.87
M180.88,546.49 L198.88,546.49 '/></g>
</g>
<g id="gnuplot_plot_3" ><title>gnuplot_plot_3</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '272.15,558.09 285.49,558.09 285.49,557.71 272.15,557.71 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M272.15,558.09 L285.49,558.09 L285.49,557.71 L272.15,557.71 L272.15,558.09 Z '/> <path stroke='rgb(148, 0, 211)' d='M272.15,558.09 L285.49,558.09 M278.82,558.09 M278.82,557.71 M269.82,557.71 L287.82,557.71 M269.82,558.09 L287.82,558.09
'/></g>
</g>
<g id="gnuplot_plot_4" ><title>gnuplot_plot_4</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '361.10,506.82 374.44,506.82 374.44,504.95 361.10,504.95 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M361.10,506.82 L374.44,506.82 L374.44,504.95 L361.10,504.95 L361.10,506.82 Z '/> <path stroke='rgb(148, 0, 211)' d='M361.10,505.69 L374.44,505.69 M367.77,509.44 L367.77,506.82 M367.77,504.95 L367.77,503.45 M358.77,503.45 L376.77,503.45
M358.77,509.44 L376.77,509.44 '/></g>
</g>
<g id="gnuplot_plot_5" ><title>gnuplot_plot_5</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '450.04,512.43 463.38,512.43 463.38,509.06 450.04,509.06 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M450.04,512.43 L463.38,512.43 L463.38,509.06 L450.04,509.06 L450.04,512.43 Z '/> <path stroke='rgb(148, 0, 211)' d='M450.04,510.56 L463.38,510.56 M456.71,514.30 L456.71,512.43 M456.71,509.06 L456.71,507.94 M447.71,507.94 L465.71,507.94
M447.71,514.30 L465.71,514.30 '/></g>
</g>
<g id="gnuplot_plot_6" ><title>gnuplot_plot_6</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '538.99,507.56 552.33,507.56 552.33,505.69 538.99,505.69 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M538.99,507.56 L552.33,507.56 L552.33,505.69 L538.99,505.69 L538.99,507.56 Z '/> <path stroke='rgb(148, 0, 211)' d='M538.99,506.26 L552.33,506.26 M545.66,509.81 L545.66,507.56 M545.66,505.69 L545.66,503.82 M536.66,503.82 L554.66,503.82
M536.66,509.81 L554.66,509.81 '/></g>
</g>
<g id="gnuplot_plot_7" ><title>gnuplot_plot_7</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '627.93,558.09 641.29,558.09 641.29,557.71 627.93,557.71 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M627.93,558.09 L641.29,558.09 L641.29,557.71 L627.93,557.71 L627.93,558.09 Z '/> <path stroke='rgb(148, 0, 211)' d='M627.93,558.09 L641.29,558.09 M634.61,558.46 L634.61,558.09 M634.61,557.71 L634.61,557.34 M625.61,557.34 L643.61,557.34
M625.61,558.46 L643.61,558.46 '/></g>
</g>
<g id="gnuplot_plot_8" ><title>gnuplot_plot_8</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '716.88,512.43 730.22,512.43 730.22,510.93 716.88,510.93 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M716.88,512.43 L730.22,512.43 L730.22,510.93 L716.88,510.93 L716.88,512.43 Z '/> <path stroke='rgb(148, 0, 211)' d='M716.88,511.68 L730.22,511.68 M723.55,514.30 L723.55,512.43 M723.55,510.93 L723.55,509.44 M714.55,509.44 L732.55,509.44
M714.55,514.30 L732.55,514.30 '/></g>
</g>
<g id="gnuplot_plot_9" ><title>gnuplot_plot_9</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '805.82,521.41 819.18,521.41 819.18,507.94 805.82,507.94 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M805.82,521.41 L819.18,521.41 L819.18,507.94 L805.82,507.94 L805.82,521.41 Z '/> <path stroke='rgb(148, 0, 211)' d='M805.82,510.00 L819.18,510.00 M812.50,534.14 L812.50,521.41 M812.50,507.94 L812.50,504.57 M803.50,504.57 L821.50,504.57
M803.50,534.14 L821.50,534.14 '/></g>
</g>
<g id="gnuplot_plot_10" ><title>gnuplot_plot_10</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '894.77,556.22 908.11,556.22 908.11,555.84 894.77,555.84 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M894.77,556.22 L908.11,556.22 L908.11,555.84 L894.77,555.84 L894.77,556.22 Z '/> <path stroke='rgb(148, 0, 211)' d='M894.77,555.84 L908.11,555.84 M901.44,556.22 M901.44,555.84 L901.44,555.47 M892.44,555.47 L910.44,555.47 M892.44,556.22
L910.44,556.22 '/></g>
</g>
<g id="gnuplot_plot_11" ><title>gnuplot_plot_11</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g transform="translate(392.71,21.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text>foot-no-pgo</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '401.10,22.50 443.66,22.50 443.66,13.50 401.10,13.50 '/>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '109.09,554.35 122.43,554.35 122.43,553.97 109.09,553.97 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M109.09,554.35 L122.43,554.35 L122.43,553.97 L109.09,553.97 L109.09,554.35 Z '/> <path stroke='rgb( 0, 158, 115)' d='M109.09,554.35 L122.43,554.35 M115.76,554.72 L115.76,554.35 M115.76,553.97 L115.76,553.60 M106.76,553.60 L124.76,553.60
M106.76,554.72 L124.76,554.72 '/></g>
</g>
<g id="gnuplot_plot_12" ><title>gnuplot_plot_12</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '198.03,542.37 211.37,542.37 211.37,542.00 198.03,542.00 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M198.03,542.37 L211.37,542.37 L211.37,542.00 L198.03,542.00 L198.03,542.37 Z '/> <path stroke='rgb( 0, 158, 115)' d='M198.03,542.37 L211.37,542.37 M204.70,542.74 L204.70,542.37 M204.70,542.00 M195.70,542.00 L213.70,542.00 M195.70,542.74
L213.70,542.74 '/></g>
</g>
<g id="gnuplot_plot_13" ><title>gnuplot_plot_13</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '286.98,557.71 300.32,557.71 300.32,557.34 286.98,557.34 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M286.98,557.71 L300.32,557.71 L300.32,557.34 L286.98,557.34 L286.98,557.71 Z '/> <path stroke='rgb( 0, 158, 115)' d='M286.98,557.71 L300.32,557.71 M293.65,557.71 M293.65,557.34 L293.65,556.97 M284.65,556.97 L302.65,556.97 M284.65,557.71
L302.65,557.71 '/></g>
</g>
<g id="gnuplot_plot_14" ><title>gnuplot_plot_14</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '375.92,509.06 389.26,509.06 389.26,506.63 375.92,506.63 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M375.92,509.06 L389.26,509.06 L389.26,506.63 L375.92,506.63 L375.92,509.06 Z '/> <path stroke='rgb( 0, 158, 115)' d='M375.92,507.56 L389.26,507.56 M382.59,512.43 L382.59,509.06 M382.59,506.63 L382.59,503.45 M373.59,503.45 L391.59,503.45
M373.59,512.43 L391.59,512.43 '/></g>
</g>
<g id="gnuplot_plot_15" ><title>gnuplot_plot_15</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '464.87,514.30 478.21,514.30 478.21,511.87 464.87,511.87 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M464.87,514.30 L478.21,514.30 L478.21,511.87 L464.87,511.87 L464.87,514.30 Z '/> <path stroke='rgb( 0, 158, 115)' d='M464.87,512.80 L478.21,512.80 M471.54,515.80 L471.54,514.30 M471.54,511.87 L471.54,510.18 M462.54,510.18 L480.54,510.18
M462.54,515.80 L480.54,515.80 '/></g>
</g>
<g id="gnuplot_plot_16" ><title>gnuplot_plot_16</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '553.81,513.55 567.15,513.55 567.15,510.56 553.81,510.56 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M553.81,513.55 L567.15,513.55 L567.15,510.56 L553.81,510.56 L553.81,513.55 Z '/> <path stroke='rgb( 0, 158, 115)' d='M553.81,512.06 L567.15,512.06 M560.48,516.92 L560.48,513.55 M560.48,510.56 L560.48,508.69 M551.48,508.69 L569.48,508.69
M551.48,516.92 L569.48,516.92 '/></g>
</g>
<g id="gnuplot_plot_17" ><title>gnuplot_plot_17</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '642.76,558.09 656.10,558.09 656.10,558.09 642.76,558.09 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M642.76,558.09 L656.10,558.09 L642.76,558.09 Z '/> <path stroke='rgb( 0, 158, 115)' d='M642.76,558.09 L656.10,558.09 M649.43,558.09 M640.43,558.09 L658.43,558.09 M640.43,558.09 L658.43,558.09 '/></g>
</g>
<g id="gnuplot_plot_18" ><title>gnuplot_plot_18</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '731.70,516.55 745.04,516.55 745.04,512.80 731.70,512.80 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M731.70,516.55 L745.04,516.55 L745.04,512.80 L731.70,512.80 L731.70,516.55 Z '/> <path stroke='rgb( 0, 158, 115)' d='M731.70,513.93 L745.04,513.93 M738.37,518.79 L738.37,516.55 M738.37,512.80 L738.37,511.68 M729.37,511.68 L747.37,511.68
M729.37,518.79 L747.37,518.79 '/></g>
</g>
<g id="gnuplot_plot_19" ><title>gnuplot_plot_19</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '820.65,519.92 833.99,519.92 833.99,518.42 820.65,518.42 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M820.65,519.92 L833.99,519.92 L833.99,518.42 L820.65,518.42 L820.65,519.92 Z '/> <path stroke='rgb( 0, 158, 115)' d='M820.65,519.17 L833.99,519.17 M827.32,521.04 L827.32,519.92 M827.32,518.42 L827.32,516.55 M818.32,516.55 L836.32,516.55
M818.32,521.04 L836.32,521.04 '/></g>
</g>
<g id="gnuplot_plot_20" ><title>gnuplot_plot_20</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '909.59,556.22 922.95,556.22 922.95,555.84 909.59,555.84 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M909.59,556.22 L922.95,556.22 L922.95,555.84 L909.59,555.84 L909.59,556.22 Z '/> <path stroke='rgb( 0, 158, 115)' d='M909.59,555.84 L922.95,555.84 M916.27,556.22 M916.27,555.84 L916.27,555.47 M907.27,555.47 L925.27,555.47 M907.27,556.22
L925.27,556.22 '/></g>
</g>
<g id="gnuplot_plot_21" ><title>gnuplot_plot_21</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g transform="translate(544.34,21.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text>alacritty</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '552.73,22.50 595.29,22.50 595.29,13.50 552.73,13.50 '/>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '123.91,550.23 137.25,550.23 137.25,549.86 123.91,549.86 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M123.91,550.23 L137.25,550.23 L137.25,549.86 L123.91,549.86 L123.91,550.23 Z '/> <path stroke='rgb( 86, 180, 233)' d='M123.91,549.86 L137.25,549.86 M130.58,550.60 L130.58,550.23 M130.58,549.86 L130.58,549.48 M121.58,549.48 L139.58,549.48
M121.58,550.60 L139.58,550.60 '/></g>
</g>
<g id="gnuplot_plot_22" ><title>gnuplot_plot_22</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '212.86,527.77 226.20,527.77 226.20,527.03 212.86,527.03 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M212.86,527.77 L226.20,527.77 L226.20,527.03 L212.86,527.03 L212.86,527.77 Z '/> <path stroke='rgb( 86, 180, 233)' d='M212.86,527.40 L226.20,527.40 M219.53,528.90 L219.53,527.77 M219.53,527.03 L219.53,526.28 M210.53,526.28 L228.53,526.28
M210.53,528.90 L228.53,528.90 '/></g>
</g>
<g id="gnuplot_plot_23" ><title>gnuplot_plot_23</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '301.80,555.09 315.14,555.09 315.14,555.09 301.80,555.09 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M301.80,555.09 L315.14,555.09 L301.80,555.09 Z '/> <path stroke='rgb( 86, 180, 233)' d='M301.80,555.09 L315.14,555.09 M308.47,555.09 M299.47,555.09 L317.47,555.09 M299.47,555.09 L317.47,555.09 '/></g>
</g>
<g id="gnuplot_plot_24" ><title>gnuplot_plot_24</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '390.75,511.31 404.09,511.31 404.09,508.31 390.75,508.31 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M390.75,511.31 L404.09,511.31 L404.09,508.31 L390.75,508.31 L390.75,511.31 Z '/> <path stroke='rgb( 86, 180, 233)' d='M390.75,509.44 L404.09,509.44 M397.42,515.42 L397.42,511.31 M397.42,508.31 L397.42,505.32 M388.42,505.32 L406.42,505.32
M388.42,515.42 L406.42,515.42 '/></g>
</g>
<g id="gnuplot_plot_25" ><title>gnuplot_plot_25</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '479.69,516.92 493.03,516.92 493.03,515.80 479.69,515.80 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M479.69,516.92 L493.03,516.92 L493.03,515.80 L479.69,515.80 L479.69,516.92 Z '/> <path stroke='rgb( 86, 180, 233)' d='M479.69,516.17 L493.03,516.17 M486.36,518.42 L486.36,516.92 M486.36,515.80 L486.36,514.68 M477.36,514.68 L495.36,514.68
M477.36,518.42 L495.36,518.42 '/></g>
</g>
<g id="gnuplot_plot_26" ><title>gnuplot_plot_26</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '568.64,513.55 581.98,513.55 581.98,511.31 568.64,511.31 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M568.64,513.55 L581.98,513.55 L581.98,511.31 L568.64,511.31 L568.64,513.55 Z '/> <path stroke='rgb( 86, 180, 233)' d='M568.64,512.43 L581.98,512.43 M575.31,516.55 L575.31,513.55 M575.31,511.31 L575.31,508.69 M566.31,508.69 L584.31,508.69
M566.31,516.55 L584.31,516.55 '/></g>
</g>
<g id="gnuplot_plot_27" ><title>gnuplot_plot_27</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '657.58,555.47 670.92,555.47 670.92,555.47 657.58,555.47 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M657.58,555.47 L670.92,555.47 L657.58,555.47 Z '/> <path stroke='rgb( 86, 180, 233)' d='M657.58,555.47 L670.92,555.47 M664.25,555.47 M655.25,555.47 L673.25,555.47 M655.25,555.47 L673.25,555.47 '/></g>
</g>
<g id="gnuplot_plot_28" ><title>gnuplot_plot_28</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '746.53,515.80 759.87,515.80 759.87,513.18 746.53,513.18 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M746.53,515.80 L759.87,515.80 L759.87,513.18 L746.53,513.18 L746.53,515.80 Z '/> <path stroke='rgb( 86, 180, 233)' d='M746.53,514.30 L759.87,514.30 M753.20,519.54 L753.20,515.80 M753.20,513.18 L753.20,511.31 M744.20,511.31 L762.20,511.31
M744.20,519.54 L762.20,519.54 '/></g>
</g>
<g id="gnuplot_plot_29" ><title>gnuplot_plot_29</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '835.47,509.81 848.81,509.81 848.81,507.19 835.47,507.19 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M835.47,509.81 L848.81,509.81 L848.81,507.19 L835.47,507.19 L835.47,509.81 Z '/> <path stroke='rgb( 86, 180, 233)' d='M835.47,508.69 L848.81,508.69 M842.14,512.06 L842.14,509.81 M842.14,507.19 L842.14,503.82 M833.14,503.82 L851.14,503.82
M833.14,512.06 L851.14,512.06 '/></g>
</g>
<g id="gnuplot_plot_30" ><title>gnuplot_plot_30</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '924.42,554.72 937.76,554.72 937.76,554.72 924.42,554.72 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M924.42,554.72 L937.76,554.72 L924.42,554.72 Z '/> <path stroke='rgb( 86, 180, 233)' d='M924.42,554.72 L937.76,554.72 M931.09,554.72 M922.09,554.72 L940.09,554.72 M922.09,554.72 L940.09,554.72 '/></g>
</g>
<g id="gnuplot_plot_31" ><title>gnuplot_plot_31</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g transform="translate(695.97,21.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text>urxvt</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '704.36,22.50 746.92,22.50 746.92,13.50 704.36,13.50 '/>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '138.73,551.35 152.09,551.35 152.09,550.98 138.73,550.98 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M138.73,551.35 L152.09,551.35 L152.09,550.98 L138.73,550.98 L138.73,551.35 Z '/> <path stroke='rgb(230, 159, 0)' d='M138.73,551.35 L152.09,551.35 M145.41,551.35 M145.41,550.98 M136.41,550.98 L154.41,550.98 M136.41,551.35 L154.41,551.35
'/></g>
</g>
<g id="gnuplot_plot_32" ><title>gnuplot_plot_32</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
<g id="gnuplot_plot_33" ><title>gnuplot_plot_33</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '316.62,553.97 329.98,553.97 329.98,553.97 316.62,553.97 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M316.62,553.97 L329.98,553.97 L316.62,553.97 Z '/> <path stroke='rgb(230, 159, 0)' d='M316.62,553.97 L329.98,553.97 M323.30,553.97 M314.30,553.97 L332.30,553.97 M314.30,553.97 L332.30,553.97 '/></g>
</g>
<g id="gnuplot_plot_34" ><title>gnuplot_plot_34</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '405.57,516.92 418.91,516.92 418.91,515.05 405.57,515.05 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M405.57,516.92 L418.91,516.92 L418.91,515.05 L405.57,515.05 L405.57,516.92 Z '/> <path stroke='rgb(230, 159, 0)' d='M405.57,516.17 L418.91,516.17 M412.24,518.42 L412.24,516.92 M412.24,515.05 L412.24,513.55 M403.24,513.55 L421.24,513.55
M403.24,518.42 L421.24,518.42 '/></g>
</g>
<g id="gnuplot_plot_35" ><title>gnuplot_plot_35</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '494.52,517.30 507.86,517.30 507.86,514.30 494.52,514.30 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M494.52,517.30 L507.86,517.30 L507.86,514.30 L494.52,514.30 L494.52,517.30 Z '/> <path stroke='rgb(230, 159, 0)' d='M494.52,516.17 L507.86,516.17 M501.19,519.92 L501.19,517.30 M501.19,514.30 L501.19,513.18 M492.19,513.18 L510.19,513.18
M492.19,519.92 L510.19,519.92 '/></g>
</g>
<g id="gnuplot_plot_36" ><title>gnuplot_plot_36</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '583.46,512.06 596.80,512.06 596.80,507.56 583.46,507.56 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M583.46,512.06 L596.80,512.06 L596.80,507.56 L583.46,507.56 L583.46,512.06 Z '/> <path stroke='rgb(230, 159, 0)' d='M583.46,510.18 L596.80,510.18 M590.13,515.05 L590.13,512.06 M590.13,507.56 L590.13,500.83 M581.13,500.83 L599.13,500.83
M581.13,515.05 L599.13,515.05 '/></g>
</g>
<g id="gnuplot_plot_37" ><title>gnuplot_plot_37</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '672.41,555.47 685.75,555.47 685.75,555.47 672.41,555.47 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M672.41,555.47 L685.75,555.47 L672.41,555.47 Z '/> <path stroke='rgb(230, 159, 0)' d='M672.41,555.47 L685.75,555.47 M679.08,555.47 M670.08,555.47 L688.08,555.47 M670.08,555.47 L688.08,555.47 '/></g>
</g>
<g id="gnuplot_plot_38" ><title>gnuplot_plot_38</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '761.35,432.34 774.69,432.34 774.69,431.59 761.35,431.59 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M761.35,432.34 L774.69,432.34 L774.69,431.59 L761.35,431.59 L761.35,432.34 Z '/> <path stroke='rgb(230, 159, 0)' d='M761.35,432.15 L774.69,432.15 M768.02,433.09 L768.02,432.34 M768.02,431.59 L768.02,430.47 M759.02,430.47 L777.02,430.47
M759.02,433.09 L777.02,433.09 '/></g>
</g>
<g id="gnuplot_plot_39" ><title>gnuplot_plot_39</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '850.30,480.24 863.64,480.24 863.64,471.26 850.30,471.26 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M850.30,480.24 L863.64,480.24 L863.64,471.26 L850.30,471.26 L850.30,480.24 Z '/> <path stroke='rgb(230, 159, 0)' d='M850.30,479.87 L863.64,479.87 M856.97,480.62 L856.97,480.24 M856.97,471.26 L856.97,470.51 M847.97,470.51 L865.97,470.51
M847.97,480.62 L865.97,480.62 '/></g>
</g>
<g id="gnuplot_plot_40" ><title>gnuplot_plot_40</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '939.24,409.14 952.58,409.14 952.58,183.46 939.24,183.46 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M939.24,409.14 L952.58,409.14 L952.58,183.46 L939.24,183.46 L939.24,409.14 Z '/> <path stroke='rgb(230, 159, 0)' d='M939.24,315.20 L952.58,315.20 M945.91,475.75 L945.91,409.14 M945.91,183.46 L945.91,128.45 M936.91,128.45 L954.91,128.45
M936.91,475.75 L954.91,475.75 '/></g>
</g>
<g id="gnuplot_plot_41" ><title>gnuplot_plot_41</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g transform="translate(847.60,21.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text>xterm</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(240, 228, 66)' fill-opacity = '0.250000' points = '855.99,22.50 898.55,22.50 898.55,13.50 855.99,13.50 '/>
<polygon fill = 'rgb(240, 228, 66)' fill-opacity = '0.250000' points = '153.56,72.31 166.90,72.31 166.90,71.00 153.56,71.00 '/>
</g>
<path stroke='rgb(240, 228, 66)' d='M153.56,72.31 L166.90,72.31 L166.90,71.00 L153.56,71.00 L153.56,72.31 Z '/> <path stroke='rgb(240, 228, 66)' d='M153.56,71.38 L166.90,71.38 M160.23,73.43 L160.23,72.31 M160.23,71.00 L160.23,70.82 M151.23,70.82 L169.23,70.82
M151.23,73.43 L169.23,73.43 '/></g>
</g>
<g id="gnuplot_plot_42" ><title>gnuplot_plot_42</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
<g id="gnuplot_plot_43" ><title>gnuplot_plot_43</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(240, 228, 66)' fill-opacity = '0.250000' points = '331.45,537.50 344.79,537.50 344.79,537.50 331.45,537.50 '/>
</g>
<path stroke='rgb(240, 228, 66)' d='M331.45,537.50 L344.79,537.50 L331.45,537.50 Z '/> <path stroke='rgb(240, 228, 66)' d='M331.45,537.50 L344.79,537.50 M338.12,537.50 M329.12,537.50 L347.12,537.50 M329.12,537.50 L347.12,537.50 '/></g>
</g>
<g id="gnuplot_plot_44" ><title>gnuplot_plot_44</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
<g id="gnuplot_plot_45" ><title>gnuplot_plot_45</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
<g id="gnuplot_plot_46" ><title>gnuplot_plot_46</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
<g id="gnuplot_plot_47" ><title>gnuplot_plot_47</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(240, 228, 66)' fill-opacity = '0.250000' points = '687.23,515.80 700.57,515.80 700.57,515.05 687.23,515.05 '/>
</g>
<path stroke='rgb(240, 228, 66)' d='M687.23,515.80 L700.57,515.80 L700.57,515.05 L687.23,515.05 L687.23,515.80 Z '/> <path stroke='rgb(240, 228, 66)' d='M687.23,515.42 L700.57,515.42 M693.90,516.55 L693.90,515.80 M693.90,515.05 L693.90,514.30 M684.90,514.30 L702.90,514.30
M684.90,516.55 L702.90,516.55 '/></g>
</g>
<g id="gnuplot_plot_48" ><title>gnuplot_plot_48</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
<g id="gnuplot_plot_49" ><title>gnuplot_plot_49</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
<g id="gnuplot_plot_50" ><title>gnuplot_plot_50</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
<g fill="none" color="#FFFFFF" stroke="rgb(240, 228, 66)" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g fill="none" color="black" stroke="black" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,36.01 L80.92,559.96 L974.82,559.96 L974.82,36.01 L80.92,36.01 Z '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 42 KiB

View file

@ -0,0 +1,572 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<svg
width="1000" height="750"
viewBox="0 0 1000 750"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<title>Gnuplot</title>
<desc>Produced by GNUPLOT 5.4 patchlevel 2 </desc>
<g id="gnuplot_canvas">
<rect x="0" y="0" width="1000" height="750" fill="#ffffff"/>
<defs>
<circle id='gpDot' r='0.5' stroke-width='0.5' stroke='currentColor'/>
<path id='gpPt0' stroke-width='0.222' stroke='currentColor' d='M-1,0 h2 M0,-1 v2'/>
<path id='gpPt1' stroke-width='0.222' stroke='currentColor' d='M-1,-1 L1,1 M1,-1 L-1,1'/>
<path id='gpPt2' stroke-width='0.222' stroke='currentColor' d='M-1,0 L1,0 M0,-1 L0,1 M-1,-1 L1,1 M-1,1 L1,-1'/>
<rect id='gpPt3' stroke-width='0.222' stroke='currentColor' x='-1' y='-1' width='2' height='2'/>
<rect id='gpPt4' stroke-width='0.222' stroke='currentColor' fill='currentColor' x='-1' y='-1' width='2' height='2'/>
<circle id='gpPt5' stroke-width='0.222' stroke='currentColor' cx='0' cy='0' r='1'/>
<use xlink:href='#gpPt5' id='gpPt6' fill='currentColor' stroke='none'/>
<path id='gpPt7' stroke-width='0.222' stroke='currentColor' d='M0,-1.33 L-1.33,0.67 L1.33,0.67 z'/>
<use xlink:href='#gpPt7' id='gpPt8' fill='currentColor' stroke='none'/>
<use xlink:href='#gpPt7' id='gpPt9' stroke='currentColor' transform='rotate(180)'/>
<use xlink:href='#gpPt9' id='gpPt10' fill='currentColor' stroke='none'/>
<use xlink:href='#gpPt3' id='gpPt11' stroke='currentColor' transform='rotate(45)'/>
<use xlink:href='#gpPt11' id='gpPt12' fill='currentColor' stroke='none'/>
<path id='gpPt13' stroke-width='0.222' stroke='currentColor' d='M0,1.330 L1.265,0.411 L0.782,-1.067 L-0.782,-1.076 L-1.265,0.411 z'/>
<use xlink:href='#gpPt13' id='gpPt14' fill='currentColor' stroke='none'/>
<filter id='textbox' filterUnits='objectBoundingBox' x='0' y='0' height='1' width='1'>
<feFlood flood-color='#FFFFFF' flood-opacity='1' result='bgnd'/>
<feComposite in='SourceGraphic' in2='bgnd' operator='atop'/>
</filter>
<filter id='greybox' filterUnits='objectBoundingBox' x='0' y='0' height='1' width='1'>
<feFlood flood-color='lightgrey' flood-opacity='1' result='grey'/>
<feComposite in='SourceGraphic' in2='grey' operator='atop'/>
</filter>
</defs>
<g fill="none" color="#FFFFFF" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,559.96 L89.92,559.96 M974.82,559.96 L965.82,559.96 '/> <g transform="translate(72.53,563.86)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 0</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,507.56 L89.92,507.56 M974.82,507.56 L965.82,507.56 '/> <g transform="translate(72.53,511.46)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 200</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,455.17 L89.92,455.17 M974.82,455.17 L965.82,455.17 '/> <g transform="translate(72.53,459.07)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 400</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,402.77 L89.92,402.77 M974.82,402.77 L965.82,402.77 '/> <g transform="translate(72.53,406.67)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 600</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,350.38 L89.92,350.38 M974.82,350.38 L965.82,350.38 '/> <g transform="translate(72.53,354.28)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 800</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,297.98 L89.92,297.98 M974.82,297.98 L965.82,297.98 '/> <g transform="translate(72.53,301.88)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 1000</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,245.59 L89.92,245.59 M974.82,245.59 L965.82,245.59 '/> <g transform="translate(72.53,249.49)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 1200</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,193.19 L89.92,193.19 M974.82,193.19 L965.82,193.19 '/> <g transform="translate(72.53,197.09)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 1400</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,140.80 L89.92,140.80 M974.82,140.80 L965.82,140.80 '/> <g transform="translate(72.53,144.70)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 1600</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,88.40 L89.92,88.40 M974.82,88.40 L965.82,88.40 '/> <g transform="translate(72.53,92.30)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 1800</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,36.01 L89.92,36.01 M974.82,36.01 L965.82,36.01 '/> <g transform="translate(72.53,39.91)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text> 2000</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M115.76,559.96 M115.76,36.01 '/> <g transform="translate(113.00,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>cursor_motion</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M204.70,559.96 M204.70,36.01 '/> <g transform="translate(201.94,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>dense_cells</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M293.65,559.96 M293.65,36.01 '/> <g transform="translate(290.89,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>light_cells</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M382.59,559.96 M382.59,36.01 '/> <g transform="translate(379.83,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>scrolling</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M471.54,559.96 M471.54,36.01 '/> <g transform="translate(468.78,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>scrolling_bottom_region</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M560.48,559.96 M560.48,36.01 '/> <g transform="translate(557.72,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>scrolling_bottom_small_region</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M649.43,559.96 M649.43,36.01 '/> <g transform="translate(646.67,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>scrolling_fullscreen</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M738.37,559.96 M738.37,36.01 '/> <g transform="translate(735.61,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>scrolling_top_region</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M827.32,559.96 M827.32,36.01 '/> <g transform="translate(824.56,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>scrolling_top_small_region</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M916.26,559.96 M916.26,36.01 '/> <g transform="translate(913.50,571.11) rotate(-315)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="start">
<text>unicode</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,36.01 L80.92,559.96 L974.82,559.96 L974.82,36.01 L80.92,36.01 Z '/> <path stroke='rgb(136, 136, 136)' stroke-dasharray='1.0,2.5' d='M175.06,559.95 L175.06,36.00 M264.01,559.95 L264.01,36.00 M352.95,559.95 L352.95,36.00 M441.90,559.95 L441.90,36.00
M530.84,559.95 L530.84,36.00 M619.79,559.95 L619.79,36.00 M708.74,559.95 L708.74,36.00 M797.68,559.95 L797.68,36.00
M886.63,559.95 L886.63,36.00 '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g transform="translate(19.18,297.99) rotate(270)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="middle">
<text>milliseconds (lower is better)</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g id="gnuplot_plot_1" ><title>gnuplot_plot_1</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g transform="translate(241.08,21.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text>foot-pgo</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '249.47,22.50 292.03,22.50 292.03,13.50 249.47,13.50 '/>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '94.26,556.55 107.60,556.55 107.60,556.03 94.26,556.03 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M94.26,556.55 L107.60,556.55 L107.60,556.03 L94.26,556.03 L94.26,556.55 Z '/> <path stroke='rgb(148, 0, 211)' d='M94.26,556.29 L107.60,556.29 M100.93,556.82 L100.93,556.55 M100.93,556.03 L100.93,555.24 M91.93,555.24 L109.93,555.24
M91.93,556.82 L109.93,556.82 '/></g>
</g>
<g id="gnuplot_plot_2" ><title>gnuplot_plot_2</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '183.21,550.27 196.55,550.27 196.55,548.43 183.21,548.43 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M183.21,550.27 L196.55,550.27 L196.55,548.43 L183.21,548.43 L183.21,550.27 Z '/> <path stroke='rgb(148, 0, 211)' d='M183.21,549.74 L196.55,549.74 M189.88,550.79 L189.88,550.27 M189.88,548.43 L189.88,547.12 M180.88,547.12 L198.88,547.12
M180.88,550.79 L198.88,550.79 '/></g>
</g>
<g id="gnuplot_plot_3" ><title>gnuplot_plot_3</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '272.15,558.13 285.49,558.13 285.49,557.86 272.15,557.86 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M272.15,558.13 L285.49,558.13 L285.49,557.86 L272.15,557.86 L272.15,558.13 Z '/> <path stroke='rgb(148, 0, 211)' d='M272.15,557.86 L285.49,557.86 M278.82,558.39 L278.82,558.13 M278.82,557.86 L278.82,557.60 M269.82,557.60 L287.82,557.60
M269.82,558.39 L287.82,558.39 '/></g>
</g>
<g id="gnuplot_plot_4" ><title>gnuplot_plot_4</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '361.10,521.45 374.44,521.45 374.44,516.47 361.10,516.47 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M361.10,521.45 L374.44,521.45 L374.44,516.47 L361.10,516.47 L361.10,521.45 Z '/> <path stroke='rgb(148, 0, 211)' d='M361.10,518.83 L374.44,518.83 M367.77,524.33 L367.77,521.45 M367.77,516.47 L367.77,510.71 M358.77,510.71 L376.77,510.71
M358.77,524.33 L376.77,524.33 '/></g>
</g>
<g id="gnuplot_plot_5" ><title>gnuplot_plot_5</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '450.04,523.02 463.38,523.02 463.38,516.47 450.04,516.47 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M450.04,523.02 L463.38,523.02 L463.38,516.47 L450.04,516.47 L450.04,523.02 Z '/> <path stroke='rgb(148, 0, 211)' d='M450.04,519.62 L463.38,519.62 M456.71,526.43 L456.71,523.02 M456.71,516.47 L456.71,508.61 M447.71,508.61 L465.71,508.61
M447.71,526.43 L465.71,526.43 '/></g>
</g>
<g id="gnuplot_plot_6" ><title>gnuplot_plot_6</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '538.99,527.21 552.33,527.21 552.33,519.88 538.99,519.88 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M538.99,527.21 L552.33,527.21 L552.33,519.88 L538.99,519.88 L538.99,527.21 Z '/> <path stroke='rgb(148, 0, 211)' d='M538.99,521.19 L552.33,521.19 M545.66,528.52 L545.66,527.21 M545.66,519.88 L545.66,514.64 M536.66,514.64 L554.66,514.64
M536.66,528.52 L554.66,528.52 '/></g>
</g>
<g id="gnuplot_plot_7" ><title>gnuplot_plot_7</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '627.93,557.08 641.29,557.08 641.29,556.82 627.93,556.82 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M627.93,557.08 L641.29,557.08 L641.29,556.82 L627.93,556.82 L627.93,557.08 Z '/> <path stroke='rgb(148, 0, 211)' d='M627.93,557.08 L641.29,557.08 M634.61,557.34 L634.61,557.08 M634.61,556.82 L634.61,556.55 M625.61,556.55 L643.61,556.55
M625.61,557.34 L643.61,557.34 '/></g>
</g>
<g id="gnuplot_plot_8" ><title>gnuplot_plot_8</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '716.88,524.33 730.22,524.33 730.22,517.78 716.88,517.78 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M716.88,524.33 L730.22,524.33 L730.22,517.78 L716.88,517.78 L716.88,524.33 Z '/> <path stroke='rgb(148, 0, 211)' d='M716.88,521.45 L730.22,521.45 M723.55,526.17 L723.55,524.33 M723.55,517.78 L723.55,511.23 M714.55,511.23 L732.55,511.23
M714.55,526.17 L732.55,526.17 '/></g>
</g>
<g id="gnuplot_plot_9" ><title>gnuplot_plot_9</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '805.82,525.38 819.18,525.38 819.18,519.88 805.82,519.88 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M805.82,525.38 L819.18,525.38 L819.18,519.88 L805.82,519.88 L805.82,525.38 Z '/> <path stroke='rgb(148, 0, 211)' d='M805.82,521.32 L819.18,521.32 M812.50,528.26 L812.50,525.38 M812.50,519.88 L812.50,513.59 M803.50,513.59 L821.50,513.59
M803.50,528.26 L821.50,528.26 '/></g>
</g>
<g id="gnuplot_plot_10" ><title>gnuplot_plot_10</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(148, 0, 211)' fill-opacity = '0.250000' points = '894.77,555.24 908.11,555.24 908.11,554.46 894.77,554.46 '/>
</g>
<path stroke='rgb(148, 0, 211)' d='M894.77,555.24 L908.11,555.24 L908.11,554.46 L894.77,554.46 L894.77,555.24 Z '/> <path stroke='rgb(148, 0, 211)' d='M894.77,554.98 L908.11,554.98 M901.44,555.77 L901.44,555.24 M901.44,554.46 L901.44,553.41 M892.44,553.41 L910.44,553.41
M892.44,555.77 L910.44,555.77 '/></g>
</g>
<g id="gnuplot_plot_11" ><title>gnuplot_plot_11</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g transform="translate(392.71,21.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text>foot-no-pgo</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '401.10,22.50 443.66,22.50 443.66,13.50 401.10,13.50 '/>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '109.09,556.03 122.43,556.03 122.43,555.51 109.09,555.51 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M109.09,556.03 L122.43,556.03 L122.43,555.51 L109.09,555.51 L109.09,556.03 Z '/> <path stroke='rgb( 0, 158, 115)' d='M109.09,555.77 L122.43,555.77 M115.76,556.29 L115.76,556.03 M115.76,555.51 L115.76,554.98 M106.76,554.98 L124.76,554.98
M106.76,556.29 L124.76,556.29 '/></g>
</g>
<g id="gnuplot_plot_12" ><title>gnuplot_plot_12</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '198.03,547.12 211.37,547.12 211.37,545.81 198.03,545.81 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M198.03,547.12 L211.37,547.12 L211.37,545.81 L198.03,545.81 L198.03,547.12 Z '/> <path stroke='rgb( 0, 158, 115)' d='M198.03,546.60 L211.37,546.60 M204.70,547.91 L204.70,547.12 M204.70,545.81 L204.70,543.98 M195.70,543.98 L213.70,543.98
M195.70,547.91 L213.70,547.91 '/></g>
</g>
<g id="gnuplot_plot_13" ><title>gnuplot_plot_13</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '286.98,557.86 300.32,557.86 300.32,557.60 286.98,557.60 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M286.98,557.86 L300.32,557.86 L300.32,557.60 L286.98,557.60 L286.98,557.86 Z '/> <path stroke='rgb( 0, 158, 115)' d='M286.98,557.86 L300.32,557.86 M293.65,558.13 L293.65,557.86 M293.65,557.60 L293.65,557.34 M284.65,557.34 L302.65,557.34
M284.65,558.13 L302.65,558.13 '/></g>
</g>
<g id="gnuplot_plot_14" ><title>gnuplot_plot_14</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '375.92,521.19 389.26,521.19 389.26,515.95 375.92,515.95 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M375.92,521.19 L389.26,521.19 L389.26,515.95 L375.92,515.95 L375.92,521.19 Z '/> <path stroke='rgb( 0, 158, 115)' d='M375.92,518.57 L389.26,518.57 M382.59,525.12 L382.59,521.19 M382.59,515.95 L382.59,511.23 M373.59,511.23 L391.59,511.23
M373.59,525.12 L391.59,525.12 '/></g>
</g>
<g id="gnuplot_plot_15" ><title>gnuplot_plot_15</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '464.87,523.55 478.21,523.55 478.21,518.04 464.87,518.04 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M464.87,523.55 L478.21,523.55 L478.21,518.04 L464.87,518.04 L464.87,523.55 Z '/> <path stroke='rgb( 0, 158, 115)' d='M464.87,520.93 L478.21,520.93 M471.54,525.90 L471.54,523.55 M471.54,518.04 L471.54,512.02 M462.54,512.02 L480.54,512.02
M462.54,525.90 L480.54,525.90 '/></g>
</g>
<g id="gnuplot_plot_16" ><title>gnuplot_plot_16</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '553.81,526.69 567.15,526.69 567.15,519.88 553.81,519.88 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M553.81,526.69 L567.15,526.69 L567.15,519.88 L553.81,519.88 L553.81,526.69 Z '/> <path stroke='rgb( 0, 158, 115)' d='M553.81,524.07 L567.15,524.07 M560.48,528.26 L560.48,526.69 M560.48,519.88 L560.48,512.28 M551.48,512.28 L569.48,512.28
M551.48,528.26 L569.48,528.26 '/></g>
</g>
<g id="gnuplot_plot_17" ><title>gnuplot_plot_17</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '642.76,557.08 656.10,557.08 656.10,556.55 642.76,556.55 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M642.76,557.08 L656.10,557.08 L656.10,556.55 L642.76,556.55 L642.76,557.08 Z '/> <path stroke='rgb( 0, 158, 115)' d='M642.76,556.82 L656.10,556.82 M649.43,557.86 L649.43,557.08 M649.43,556.55 L649.43,555.77 M640.43,555.77 L658.43,555.77
M640.43,557.86 L658.43,557.86 '/></g>
</g>
<g id="gnuplot_plot_18" ><title>gnuplot_plot_18</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '731.70,524.72 745.04,524.72 745.04,518.57 731.70,518.57 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M731.70,524.72 L745.04,524.72 L745.04,518.57 L731.70,518.57 L731.70,524.72 Z '/> <path stroke='rgb( 0, 158, 115)' d='M731.70,522.24 L745.04,522.24 M738.37,526.69 L738.37,524.72 M738.37,518.57 L738.37,509.92 M729.37,509.92 L747.37,509.92
M729.37,526.69 L747.37,526.69 '/></g>
</g>
<g id="gnuplot_plot_19" ><title>gnuplot_plot_19</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '820.65,522.50 833.99,522.50 833.99,518.83 820.65,518.83 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M820.65,522.50 L833.99,522.50 L833.99,518.83 L820.65,518.83 L820.65,522.50 Z '/> <path stroke='rgb( 0, 158, 115)' d='M820.65,520.40 L833.99,520.40 M827.32,526.95 L827.32,522.50 M827.32,518.83 L827.32,514.90 M818.32,514.90 L836.32,514.90
M818.32,526.95 L836.32,526.95 '/></g>
</g>
<g id="gnuplot_plot_20" ><title>gnuplot_plot_20</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 0, 158, 115)' fill-opacity = '0.250000' points = '909.59,554.98 922.95,554.98 922.95,554.20 909.59,554.20 '/>
</g>
<path stroke='rgb( 0, 158, 115)' d='M909.59,554.98 L922.95,554.98 L922.95,554.20 L909.59,554.20 L909.59,554.98 Z '/> <path stroke='rgb( 0, 158, 115)' d='M909.59,554.72 L922.95,554.72 M916.27,555.51 L916.27,554.98 M916.27,554.20 L916.27,553.15 M907.27,553.15 L925.27,553.15
M907.27,555.51 L925.27,555.51 '/></g>
</g>
<g id="gnuplot_plot_21" ><title>gnuplot_plot_21</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g transform="translate(544.34,21.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text>alacritty</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '552.73,22.50 595.29,22.50 595.29,13.50 552.73,13.50 '/>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '123.91,553.41 137.25,553.41 137.25,552.62 123.91,552.62 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M123.91,553.41 L137.25,553.41 L137.25,552.62 L123.91,552.62 L123.91,553.41 Z '/> <path stroke='rgb( 86, 180, 233)' d='M123.91,553.02 L137.25,553.02 M130.58,554.20 L130.58,553.41 M130.58,552.62 L130.58,551.58 M121.58,551.58 L139.58,551.58
M121.58,554.20 L139.58,554.20 '/></g>
</g>
<g id="gnuplot_plot_22" ><title>gnuplot_plot_22</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '212.86,539.00 226.20,539.00 226.20,531.93 212.86,531.93 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M212.86,539.00 L226.20,539.00 L226.20,531.93 L212.86,531.93 L212.86,539.00 Z '/> <path stroke='rgb( 86, 180, 233)' d='M212.86,536.91 L226.20,536.91 M219.53,540.31 L219.53,539.00 M219.53,531.93 L219.53,530.09 M210.53,530.09 L228.53,530.09
M210.53,540.31 L228.53,540.31 '/></g>
</g>
<g id="gnuplot_plot_23" ><title>gnuplot_plot_23</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '301.80,554.46 315.14,554.46 315.14,554.20 301.80,554.20 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M301.80,554.46 L315.14,554.46 L315.14,554.20 L301.80,554.20 L301.80,554.46 Z '/> <path stroke='rgb( 86, 180, 233)' d='M301.80,554.46 L315.14,554.46 M308.47,554.72 L308.47,554.46 M308.47,554.20 L308.47,553.93 M299.47,553.93 L317.47,553.93
M299.47,554.72 L317.47,554.72 '/></g>
</g>
<g id="gnuplot_plot_24" ><title>gnuplot_plot_24</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '390.75,524.59 404.09,524.59 404.09,517.78 390.75,517.78 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M390.75,524.59 L404.09,524.59 L404.09,517.78 L390.75,517.78 L390.75,524.59 Z '/> <path stroke='rgb( 86, 180, 233)' d='M390.75,520.66 L404.09,520.66 M397.42,527.74 L397.42,524.59 M397.42,517.78 L397.42,515.16 M388.42,515.16 L406.42,515.16
M388.42,527.74 L406.42,527.74 '/></g>
</g>
<g id="gnuplot_plot_25" ><title>gnuplot_plot_25</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '479.69,524.33 493.03,524.33 493.03,522.24 479.69,522.24 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M479.69,524.33 L493.03,524.33 L493.03,522.24 L479.69,522.24 L479.69,524.33 Z '/> <path stroke='rgb( 86, 180, 233)' d='M479.69,523.02 L493.03,523.02 M486.36,526.43 L486.36,524.33 M486.36,522.24 L486.36,519.09 M477.36,519.09 L495.36,519.09
M477.36,526.43 L495.36,526.43 '/></g>
</g>
<g id="gnuplot_plot_26" ><title>gnuplot_plot_26</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '568.64,517.78 581.98,517.78 581.98,515.42 568.64,515.42 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M568.64,517.78 L581.98,517.78 L581.98,515.42 L568.64,515.42 L568.64,517.78 Z '/> <path stroke='rgb( 86, 180, 233)' d='M568.64,516.21 L581.98,516.21 M575.31,521.19 L575.31,517.78 M575.31,515.42 L575.31,513.85 M566.31,513.85 L584.31,513.85
M566.31,521.19 L584.31,521.19 '/></g>
</g>
<g id="gnuplot_plot_27" ><title>gnuplot_plot_27</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '657.58,554.20 670.92,554.20 670.92,553.67 657.58,553.67 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M657.58,554.20 L670.92,554.20 L670.92,553.67 L657.58,553.67 L657.58,554.20 Z '/> <path stroke='rgb( 86, 180, 233)' d='M657.58,553.93 L670.92,553.93 M664.25,554.72 L664.25,554.20 M664.25,553.67 L664.25,552.89 M655.25,552.89 L673.25,552.89
M655.25,554.72 L673.25,554.72 '/></g>
</g>
<g id="gnuplot_plot_28" ><title>gnuplot_plot_28</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '746.53,521.45 759.87,521.45 759.87,516.47 746.53,516.47 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M746.53,521.45 L759.87,521.45 L759.87,516.47 L746.53,516.47 L746.53,521.45 Z '/> <path stroke='rgb( 86, 180, 233)' d='M746.53,518.31 L759.87,518.31 M753.20,528.52 L753.20,521.45 M753.20,516.47 L753.20,514.64 M744.20,514.64 L762.20,514.64
M744.20,528.52 L762.20,528.52 '/></g>
</g>
<g id="gnuplot_plot_29" ><title>gnuplot_plot_29</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '835.47,520.40 848.81,520.40 848.81,515.69 835.47,515.69 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M835.47,520.40 L848.81,520.40 L848.81,515.69 L835.47,515.69 L835.47,520.40 Z '/> <path stroke='rgb( 86, 180, 233)' d='M835.47,516.21 L848.81,516.21 M842.14,526.95 L842.14,520.40 M842.14,515.69 L842.14,508.61 M833.14,508.61 L851.14,508.61
M833.14,526.95 L851.14,526.95 '/></g>
</g>
<g id="gnuplot_plot_30" ><title>gnuplot_plot_30</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb( 86, 180, 233)' fill-opacity = '0.250000' points = '924.42,553.41 937.76,553.41 937.76,553.15 924.42,553.15 '/>
</g>
<path stroke='rgb( 86, 180, 233)' d='M924.42,553.41 L937.76,553.41 L937.76,553.15 L924.42,553.15 L924.42,553.41 Z '/> <path stroke='rgb( 86, 180, 233)' d='M924.42,553.15 L937.76,553.15 M931.09,553.67 L931.09,553.41 M931.09,553.15 L931.09,552.89 M922.09,552.89 L940.09,552.89
M922.09,553.67 L940.09,553.67 '/></g>
</g>
<g id="gnuplot_plot_31" ><title>gnuplot_plot_31</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g transform="translate(695.97,21.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text>urxvt</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '704.36,22.50 746.92,22.50 746.92,13.50 704.36,13.50 '/>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '138.73,554.20 152.09,554.20 152.09,553.67 138.73,553.67 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M138.73,554.20 L152.09,554.20 L152.09,553.67 L138.73,553.67 L138.73,554.20 Z '/> <path stroke='rgb(230, 159, 0)' d='M138.73,553.93 L152.09,553.93 M145.41,554.20 M145.41,553.67 L145.41,552.89 M136.41,552.89 L154.41,552.89 M136.41,554.20
L154.41,554.20 '/></g>
</g>
<g id="gnuplot_plot_32" ><title>gnuplot_plot_32</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '227.68,217.56 241.02,217.56 241.02,100.98 227.68,100.98 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M227.68,217.56 L241.02,217.56 L241.02,100.98 L227.68,100.98 L227.68,217.56 Z '/> <path stroke='rgb(230, 159, 0)' d='M227.68,176.95 L241.02,176.95 M234.35,273.88 L234.35,217.56 M234.35,100.98 L234.35,76.09 M225.35,76.09 L243.35,76.09
M225.35,273.88 L243.35,273.88 '/></g>
</g>
<g id="gnuplot_plot_33" ><title>gnuplot_plot_33</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '316.62,554.72 329.98,554.72 329.98,554.46 316.62,554.46 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M316.62,554.72 L329.98,554.72 L329.98,554.46 L316.62,554.46 L316.62,554.72 Z '/> <path stroke='rgb(230, 159, 0)' d='M316.62,554.72 L329.98,554.72 M323.30,554.98 L323.30,554.72 M323.30,554.46 L323.30,554.20 M314.30,554.20 L332.30,554.20
M314.30,554.98 L332.30,554.98 '/></g>
</g>
<g id="gnuplot_plot_34" ><title>gnuplot_plot_34</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '405.57,525.51 418.91,525.51 418.91,520.40 405.57,520.40 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M405.57,525.51 L418.91,525.51 L418.91,520.40 L405.57,520.40 L405.57,525.51 Z '/> <path stroke='rgb(230, 159, 0)' d='M405.57,523.68 L418.91,523.68 M412.24,531.93 L412.24,525.51 M412.24,520.40 L412.24,516.47 M403.24,516.47 L421.24,516.47
M403.24,531.93 L421.24,531.93 '/></g>
</g>
<g id="gnuplot_plot_35" ><title>gnuplot_plot_35</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '494.52,522.24 507.86,522.24 507.86,518.57 494.52,518.57 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M494.52,522.24 L507.86,522.24 L507.86,518.57 L494.52,518.57 L494.52,522.24 Z '/> <path stroke='rgb(230, 159, 0)' d='M494.52,519.35 L507.86,519.35 M501.19,527.48 L501.19,522.24 M501.19,518.57 L501.19,516.21 M492.19,516.21 L510.19,516.21
M492.19,527.48 L510.19,527.48 '/></g>
</g>
<g id="gnuplot_plot_36" ><title>gnuplot_plot_36</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '583.46,513.59 596.80,513.59 596.80,506.12 583.46,506.12 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M583.46,513.59 L596.80,513.59 L596.80,506.12 L583.46,506.12 L583.46,513.59 Z '/> <path stroke='rgb(230, 159, 0)' d='M583.46,510.97 L596.80,510.97 M590.13,515.69 L590.13,513.59 M590.13,506.12 L590.13,495.25 M581.13,495.25 L599.13,495.25
M581.13,515.69 L599.13,515.69 '/></g>
</g>
<g id="gnuplot_plot_37" ><title>gnuplot_plot_37</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '672.41,554.72 685.75,554.72 685.75,553.93 672.41,553.93 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M672.41,554.72 L685.75,554.72 L685.75,553.93 L672.41,553.93 L672.41,554.72 Z '/> <path stroke='rgb(230, 159, 0)' d='M672.41,554.46 L685.75,554.46 M679.08,554.98 L679.08,554.72 M679.08,553.93 L679.08,553.15 M670.08,553.15 L688.08,553.15
M670.08,554.98 L688.08,554.98 '/></g>
</g>
<g id="gnuplot_plot_38" ><title>gnuplot_plot_38</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '761.35,438.40 774.69,438.40 774.69,430.81 761.35,430.81 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M761.35,438.40 L774.69,438.40 L774.69,430.81 L761.35,430.81 L761.35,438.40 Z '/> <path stroke='rgb(230, 159, 0)' d='M761.35,434.21 L774.69,434.21 M768.02,446.00 L768.02,438.40 M768.02,430.81 L768.02,427.14 M759.02,427.14 L777.02,427.14
M759.02,446.00 L777.02,446.00 '/></g>
</g>
<g id="gnuplot_plot_39" ><title>gnuplot_plot_39</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(230, 159, 0)' fill-opacity = '0.250000' points = '850.30,480.58 863.64,480.58 863.64,470.89 850.30,470.89 '/>
</g>
<path stroke='rgb(230, 159, 0)' d='M850.30,480.58 L863.64,480.58 L863.64,470.89 L850.30,470.89 L850.30,480.58 Z '/> <path stroke='rgb(230, 159, 0)' d='M850.30,476.39 L863.64,476.39 M856.97,484.51 L856.97,480.58 M856.97,470.89 L856.97,464.86 M847.97,464.86 L865.97,464.86
M847.97,484.51 L865.97,484.51 '/></g>
</g>
<g id="gnuplot_plot_40" ><title>gnuplot_plot_40</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
<g id="gnuplot_plot_41" ><title>gnuplot_plot_41</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g transform="translate(847.60,21.90)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
<text>xterm</text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(240, 228, 66)' fill-opacity = '0.250000' points = '855.99,22.50 898.55,22.50 898.55,13.50 855.99,13.50 '/>
<polygon fill = 'rgb(240, 228, 66)' fill-opacity = '0.250000' points = '153.56,222.01 166.90,222.01 166.90,215.07 153.56,215.07 '/>
</g>
<path stroke='rgb(240, 228, 66)' d='M153.56,222.01 L166.90,222.01 L166.90,215.07 L153.56,215.07 L153.56,222.01 Z '/> <path stroke='rgb(240, 228, 66)' d='M153.56,215.59 L166.90,215.59 M160.23,226.99 L160.23,222.01 M160.23,215.07 L160.23,214.94 M151.23,214.94 L169.23,214.94
M151.23,226.99 L169.23,226.99 '/></g>
</g>
<g id="gnuplot_plot_42" ><title>gnuplot_plot_42</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
<g id="gnuplot_plot_43" ><title>gnuplot_plot_43</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(240, 228, 66)' fill-opacity = '0.250000' points = '331.45,532.71 344.79,532.71 344.79,528.26 331.45,528.26 '/>
</g>
<path stroke='rgb(240, 228, 66)' d='M331.45,532.71 L344.79,532.71 L344.79,528.26 L331.45,528.26 L331.45,532.71 Z '/> <path stroke='rgb(240, 228, 66)' d='M331.45,532.19 L344.79,532.19 M338.12,537.17 L338.12,532.71 M338.12,528.26 L338.12,521.97 M329.12,521.97 L347.12,521.97
M329.12,537.17 L347.12,537.17 '/></g>
</g>
<g id="gnuplot_plot_44" ><title>gnuplot_plot_44</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
<g id="gnuplot_plot_45" ><title>gnuplot_plot_45</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
<g id="gnuplot_plot_46" ><title>gnuplot_plot_46</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
<g id="gnuplot_plot_47" ><title>gnuplot_plot_47</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g stroke='none' shape-rendering='crispEdges'>
<polygon fill = 'rgb(240, 228, 66)' fill-opacity = '0.250000' points = '687.23,483.73 700.57,483.73 700.57,477.44 687.23,477.44 '/>
</g>
<path stroke='rgb(240, 228, 66)' d='M687.23,483.73 L700.57,483.73 L700.57,477.44 L687.23,477.44 L687.23,483.73 Z '/> <path stroke='rgb(240, 228, 66)' d='M687.23,480.32 L700.57,480.32 M693.90,483.73 M693.90,477.44 L693.90,476.91 M684.90,476.91 L702.90,476.91 M684.90,483.73
L702.90,483.73 '/></g>
</g>
<g id="gnuplot_plot_48" ><title>gnuplot_plot_48</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
<g id="gnuplot_plot_49" ><title>gnuplot_plot_49</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
<g id="gnuplot_plot_50" ><title>gnuplot_plot_50</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
<g fill="none" color="#FFFFFF" stroke="rgb(240, 228, 66)" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g fill="none" color="black" stroke="black" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M80.92,36.01 L80.92,559.96 L974.82,559.96 L974.82,36.01 L80.92,36.01 Z '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 43 KiB

View file

@ -5,20 +5,10 @@
All benchmarks are done using [vtebench](https://github.com/alacritty/vtebench): All benchmarks are done using [vtebench](https://github.com/alacritty/vtebench):
```sh ```sh
vtebench -h $(tput lines) -w $(tput cols) -b 104857600 alt-screen-random-write > ~/alt-random ./target/release/vtebench -b ./benchmarks --dat /tmp/<terminal>
vtebench -c -h $(tput lines) -w $(tput cols) -b 104857600 alt-screen-random-write > ~/alt-random-colors
vtebench -h $(tput lines) -w $(tput cols) -b 10485760 scrolling > ~/scrolling
vtebench -h $(tput lines) -w $(tput cols) -b 104857600 scrolling --fill-lines > ~/scrolling-filled-lines
vtebench -h $(tput lines) -w $(tput cols) -b 10485760 unicode-random-write > ~/unicode-random
``` ```
They were "executed" using [benchmark.py](../scripts/benchmark.py), ## 2021-06-25
which will load each file into memory, and then print it to the
terminal. This is done **20** times for each test. Then it calculates
the _mean_ and _standard deviation_ for each test.
## 2021-03-20
### System ### System
@ -40,14 +30,21 @@ Scrollback: 10000 lines
### Results ### Results
| Benchmark (times in ms) | Foot (GCC+PGO) 1.8.0 | Foot 1.8.0 | Alacritty 0.8.0 | URxvt 9.26 | XTerm 368 |
|-------------------------------|---------------------:|-----------:|----------------:|-----------:|----------:|
| cursor motion | 12.93 | 15.37 | 26.47 | 23.41 | 1304.00 |
| dense cells | 39.16 | 47.19 | 87.26 | 9110.00 | 10883.00 |
| light cells | 5.34 | 6.42 | 12.76 | 16.00 | 60.00 |
| scrollling | 144.26 | 139.93 | 133.98 | 117.52 | 3772.67 |
| scrolling bottom region | 130.81 | 125.34 | 116.10 | 117.31 | 3574.67 |
| scrolling bottom small region | 142.46 | 127.52 | 127.32 | 135.18 | 3572.67 |
| scrolling fullscreen | 5.43 | 5.27 | 12.06 | 11.97 | 118.62 |
| scrolling top region | 129.05 | 120.24 | 121.65 | 341.70 | 3567.33 |
| scrolling top small region | 121.59 | 109.82 | 137.03 | 219.96 | 3558.67 |
| unicode | 12.03 | 11.95 | 13.94 | 667.67 | 4905.67 |
| Benchmark | Foot (GCC+PGO) 1.7.0.r2 | Foot 1.7.0.r2 | Alacritty 0.7.2 | URxvt 9.22 | XTerm 366 |
|------------------------|------------------------:|--------------:|-------------------:|---------------:|---------------:| ![Graph of benchmark results for a beefy desktop system](benchmark-results-desktop.svg)
| alt-random | 0.382s ±0.003 | 0.550s ±0.007 | 0.995s ±0.010 | 1.201s ±0.006 | 12.756s ±0.045 |
| alt-random-colors | 0.380s ±0.002 | 0.543s ±0.003 | 1.017s ±0.013 | 1.399s ±0.018 | 11.591s ±0.141 |
| scrolling | 1.302s ±0.019 | 1.284s ±0.052 | 1.107s ±0.028 | 1.097s ±0.015 | 37.537s ±0.121 |
| scrolling-filled-lines | 0.646s ±0.016 | 0.610s ±0.003 | 1.290s ±0.012 | 1.325s ±0.037 | 6.817s ±0.084 |
| unicode-random | 0.167s ±0.001 | 0.276s ±0.445 | 0.097s ±0.002 [^1] | 18.032s ±0.334 | 29.731s ±3.746 |
## 2021-03-20 ## 2021-03-20
@ -73,32 +70,17 @@ Scrollback=10000 lines
### Results ### Results
| Benchmark | Foot (GCC+PGO) 1.7.0.r2 | Foot (no PGO) 1.7.0.r2 | Alacritty 0.7.2 | URxvt 9.22 | St 0.8.4 | XTerm 366 | | Benchmark (times in ms) | Foot (GCC+PGO) 1.8.0 | Foot 1.8.0 | Alacritty 0.8.0 | URxvt 9.26 | XTerm 368 |
|------------------------|------------------------:|-----------------------:|-------------------:|-----------------:|--------------:|----------------:| |-------------------------------|---------------------:|-----------:|----------------:|-----------:|----------:|
| alt-random | 0.714s ±0.047 | 0.900s ±0.041 | 1.586s ±0.045 | 1.684s ±0.034 | 2.054s ±0.121 | 37.205s ±0.252 | | cursor motion | 14.49 | 16.60 | 26.89 | 23.45 | 1303.38 |
| alt-random-colors | 0.736s ±0.054 | 0.950s ±0.082 | 1.565s ±0.043 | 2.150s ±0.137 | 2.195s ±0.154 | 33.112s ±0.167 | | dense cells | 41.00 | 52.45 | 92.02 | 1486.57 | 11957.00 |
| scrolling | 1.593s ±0.070 | 1.559s ±0.055 | 1.517s ±0.079 | 1.462s ±0.052 | 3.308s ±0.133 | 134.432s ±0.436 | | light cells | 7.97 | 8.54 | 21.43 | 20.45 | 111.96 |
| scrolling-filled-lines | 1.178s ±0.044 | 1.309s ±0.045 | 2.281s ±0.086 | 2.044s ±0.060 | 2.732s ±0.056 | 20.753s ±0.067 | | scrollling | 158.85 | 158.90 | 148.06 | 138.98 | 10083.00 |
| unicode-random | 0.349s ±0.009 | 0.352s ±0.007 | 0.148s ±0.010 [^1] | 19.090s ±0.363 | crashed | 15.579s ±0.093 | | scrolling bottom region | 153.83 | 151.38 | 142.13 | 151.30 | 9988.50 |
| scrolling bottom small region | 143.51 | 141.46 | 162.03 | 192.37 | 9938.00 |
| scrolling fullscreen | 11.56 | 11.75 | 22.96 | 21.49 | 295.40 |
| scrolling top region | 148.96 | 148.18 | 155.05 | 482.05 | 10036.00 |
| scrolling top small region | 144.26 | 149.76 | 159.40 | 321.69 | 9942.50 |
| unicode | 21.02 | 22.09 | 25.79 | 14959.00 | 88697.00 |
[^1]: [Alacritty and "unicode-random"](#alacritty-and-unicode-random) ![Graph of benchmark results for a laptop](benchmark-results-laptop.svg)
# Alacritty and "unicode-random"
Alacritty is actually **really** slow at rendering this (whether it is
fallback fonts in general, emojis, or something else, I don't know).
I believe the reason it finishes the benchmark so quickly is because
it reads from the PTY in a separate thread, into a larger receive
buffer which is then consumed by the main thread. This allows the
client program to write its output much faster since it is no longer
stalling on a blocked PTY.
This means Alacritty only needs to render a couple of frames since it
can reach the final VT state almost immediately.
On the other hand, `cat`:ing the `unicode-random` test file in an
endless loop, or just manually scrolling up after the benchmark is
done is **slow**, which besides being felt (input lag), can be seen by
setting `debug.render_timer = true` in `alacritty.yml`.

View file

@ -126,7 +126,7 @@ the foot command line
This option can only be used in combination with *-s*,*--server*. This option can only be used in combination with *-s*,*--server*.
*-d*,*--log-level*={*info*,*warning*,*error*} *-d*,*--log-level*={*info*,*warning*,*error*,*none*}
Log level, used both for log output on stderr as well as Log level, used both for log output on stderr as well as
syslog. Default: _info_. syslog. Default: _info_.

View file

@ -997,8 +997,26 @@ any of these options.
but is necessary to not break cursor synchronization with the but is necessary to not break cursor synchronization with the
application running in foot. application running in foot.
See also: *grapheme-width-method*.
Default: _no_ Default: _no_
*grapheme-width-method*
Selects which method to use when calculating the width
(i.e. number of columns) of a grapheme cluster. One of
*double-width* and *wcswidth*.
*wcswidth* simply adds together the individual width of all
codepoints making up the cluster.
*double-width* does the same, but limits the maximum number of
columns to 2. This is more correct, but is likely to break
applications since applications typically use *wcswidth*(3)
internally to calculate the width. This results in cursor
de-synchronization issues.
Default: _double-width_
*max-shm-pool-size-mb* *max-shm-pool-size-mb*
This option controls the amount of virtual address space used by This option controls the amount of virtual address space used by
the pixmap memory to which the terminal screen content is the pixmap memory to which the terminal screen content is

View file

@ -69,7 +69,7 @@ terminal has terminated.
Override an option set in the configuration file. If _SECTION_ is not Override an option set in the configuration file. If _SECTION_ is not
given, defaults to _main_. given, defaults to _main_.
*-d*,*--log-level*={*info*,*warning*,*error*} *-d*,*--log-level*={*info*,*warning*,*error*,*none*}
Log level, used both for log output on stderr as well as Log level, used both for log output on stderr as well as
syslog. Default: _info_. syslog. Default: _info_.

View file

@ -24,6 +24,7 @@ foot+base|foot base fragment,
xenl, xenl,
AX, AX,
XT, XT,
Tc,
cols#80, cols#80,
it#8, it#8,
lines#24, lines#24,
@ -255,6 +256,8 @@ foot+base|foot base fragment,
rs1=\Ec, rs1=\Ec,
rs2=\E[!p\E[?3;4l\E[4l\E>, rs2=\E[!p\E[?3;4l\E[4l\E>,
sc=\E7, sc=\E7,
setrgbb=\E[48\:2\:\:%p1%d\:%p2%d\:%p3%dm,
setrgbf=\E[38\:2\:\:%p1%d\:%p2%d\:%p3%dm,
sgr0=\E(B\E[m, sgr0=\E(B\E[m,
sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p5%t;2%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m, sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p5%t;2%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m,
sitm=\E[3m, sitm=\E[3m,

View file

@ -529,8 +529,6 @@ convert_key_bindings(const struct config *conf, struct seat *seat)
{ {
for (size_t i = 0; i < conf->bindings.key.count; i++) { for (size_t i = 0; i < conf->bindings.key.count; i++) {
const struct config_key_binding *binding = &conf->bindings.key.arr[i]; const struct config_key_binding *binding = &conf->bindings.key.arr[i];
if (binding->action == BIND_ACTION_NONE)
continue;
convert_key_binding(seat, binding, &seat->kbd.bindings.key); convert_key_binding(seat, binding, &seat->kbd.bindings.key);
} }
} }
@ -540,8 +538,6 @@ convert_search_bindings(const struct config *conf, struct seat *seat)
{ {
for (size_t i = 0; i < conf->bindings.search.count; i++) { for (size_t i = 0; i < conf->bindings.search.count; i++) {
const struct config_key_binding *binding = &conf->bindings.search.arr[i]; const struct config_key_binding *binding = &conf->bindings.search.arr[i];
if (binding->action == BIND_ACTION_SEARCH_NONE)
continue;
convert_key_binding(seat, binding, &seat->kbd.bindings.search); convert_key_binding(seat, binding, &seat->kbd.bindings.search);
} }
} }
@ -551,10 +547,6 @@ convert_url_bindings(const struct config *conf, struct seat *seat)
{ {
for (size_t i = 0; i < conf->bindings.url.count; i++) { for (size_t i = 0; i < conf->bindings.url.count; i++) {
const struct config_key_binding *binding = &conf->bindings.url.arr[i]; const struct config_key_binding *binding = &conf->bindings.url.arr[i];
#if 0
if (binding->action == BIND_ACTION_URL_NONE)
continue;
#endif
convert_key_binding(seat, binding, &seat->kbd.bindings.url); convert_key_binding(seat, binding, &seat->kbd.bindings.url);
} }
} }

88
log.c
View file

@ -3,6 +3,7 @@
#include <errno.h> #include <errno.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -15,15 +16,19 @@
static bool colorize = false; static bool colorize = false;
static bool do_syslog = true; static bool do_syslog = true;
static enum log_class log_level = LOG_CLASS_INFO; static enum log_class log_level = LOG_CLASS_NONE;
static const char log_level_map[][8] = { static const struct {
[LOG_CLASS_ERROR] = "error", const char name[8];
[LOG_CLASS_WARNING] = "warning", const char log_prefix[7];
[LOG_CLASS_INFO] = "info", uint8_t color;
#if defined(_DEBUG) int syslog_equivalent;
[LOG_CLASS_DEBUG] = "debug", } log_level_map[] = {
#endif [LOG_CLASS_NONE] = {"none", "none", 5, -1},
[LOG_CLASS_ERROR] = {"error", " err", 31, LOG_ERR},
[LOG_CLASS_WARNING] = {"warning", "warn", 33, LOG_WARNING},
[LOG_CLASS_INFO] = {"info", "info", 97, LOG_INFO},
[LOG_CLASS_DEBUG] = {"debug", " dbg", 36, LOG_DEBUG},
}; };
void void
@ -35,20 +40,14 @@ log_init(enum log_colorize _colorize, bool _do_syslog,
[LOG_FACILITY_DAEMON] = LOG_DAEMON, [LOG_FACILITY_DAEMON] = LOG_DAEMON,
}; };
static const int level_map[] = {
[LOG_CLASS_ERROR] = LOG_ERR,
[LOG_CLASS_WARNING] = LOG_WARNING,
[LOG_CLASS_INFO] = LOG_INFO,
[LOG_CLASS_DEBUG] = LOG_DEBUG,
};
colorize = _colorize == LOG_COLORIZE_NEVER ? false : _colorize == LOG_COLORIZE_ALWAYS ? true : isatty(STDERR_FILENO); colorize = _colorize == LOG_COLORIZE_NEVER ? false : _colorize == LOG_COLORIZE_ALWAYS ? true : isatty(STDERR_FILENO);
do_syslog = _do_syslog; do_syslog = _do_syslog;
log_level = _log_level; log_level = _log_level;
if (do_syslog) { int slvl = log_level_map[_log_level].syslog_equivalent;
if (do_syslog && slvl != -1) {
openlog(NULL, /*LOG_PID*/0, facility_map[syslog_facility]); openlog(NULL, /*LOG_PID*/0, facility_map[syslog_facility]);
setlogmask(LOG_UPTO(level_map[_log_level])); setlogmask(LOG_UPTO(slvl));
} }
} }
@ -63,34 +62,31 @@ static void
_log(enum log_class log_class, const char *module, const char *file, int lineno, _log(enum log_class log_class, const char *module, const char *file, int lineno,
const char *fmt, int sys_errno, va_list va) const char *fmt, int sys_errno, va_list va)
{ {
xassert(log_class > LOG_CLASS_NONE);
xassert(log_class < ALEN(log_level_map));
if (log_class > log_level) if (log_class > log_level)
return; return;
const char *class = "abcd"; const char *prefix = log_level_map[log_class].log_prefix;
int class_clr = 0; unsigned int class_clr = log_level_map[log_class].color;
switch (log_class) {
case LOG_CLASS_ERROR: class = " err"; class_clr = 31; break;
case LOG_CLASS_WARNING: class = "warn"; class_clr = 33; break;
case LOG_CLASS_INFO: class = "info"; class_clr = 97; break;
case LOG_CLASS_DEBUG: class = " dbg"; class_clr = 36; break;
}
char clr[16]; char clr[16];
snprintf(clr, sizeof(clr), "\033[%dm", class_clr); xsnprintf(clr, sizeof(clr), "\033[%um", class_clr);
fprintf(stderr, "%s%s%s: ", colorize ? clr : "", class, colorize ? "\033[0m" : ""); fprintf(stderr, "%s%s%s: ", colorize ? clr : "", prefix, colorize ? "\033[0m" : "");
if (colorize) if (colorize)
fprintf(stderr, "\033[2m"); fputs("\033[2m", stderr);
fprintf(stderr, "%s:%d: ", file, lineno); fprintf(stderr, "%s:%d: ", file, lineno);
if (colorize) if (colorize)
fprintf(stderr, "\033[0m"); fputs("\033[0m", stderr);
vfprintf(stderr, fmt, va); vfprintf(stderr, fmt, va);
if (sys_errno != 0) if (sys_errno != 0)
fprintf(stderr, ": %s", strerror(sys_errno)); fprintf(stderr, ": %s", strerror(sys_errno));
fprintf(stderr, "\n"); fputc('\n', stderr);
} }
static void static void
@ -98,19 +94,14 @@ _sys_log(enum log_class log_class, const char *module,
const char UNUSED *file, int UNUSED lineno, const char UNUSED *file, int UNUSED lineno,
const char *fmt, int sys_errno, va_list va) const char *fmt, int sys_errno, va_list va)
{ {
xassert(log_class > LOG_CLASS_NONE);
xassert(log_class < ALEN(log_level_map));
if (!do_syslog) if (!do_syslog)
return; return;
/* Map our log level to syslog's level */ /* Map our log level to syslog's level */
int level = -1; int level = log_level_map[log_class].syslog_equivalent;
switch (log_class) {
case LOG_CLASS_ERROR: level = LOG_ERR; break;
case LOG_CLASS_WARNING: level = LOG_WARNING; break;
case LOG_CLASS_INFO: level = LOG_INFO; break;
case LOG_CLASS_DEBUG: level = LOG_DEBUG; break;
}
xassert(level != -1);
char msg[4096]; char msg[4096];
int n = vsnprintf(msg, sizeof(msg), fmt, va); int n = vsnprintf(msg, sizeof(msg), fmt, va);
@ -185,14 +176,25 @@ log_errno_provided(enum log_class log_class, const char *module,
va_end(va); va_end(va);
} }
static size_t
map_len(void)
{
size_t len = ALEN(log_level_map);
#ifndef _DEBUG
/* Exclude "debug" entry for non-debug builds */
len--;
#endif
return len;
}
int int
log_level_from_string(const char *str) log_level_from_string(const char *str)
{ {
if (unlikely(str[0] == '\0')) if (unlikely(str[0] == '\0'))
return -1; return -1;
for (int i = 0, n = ALEN(log_level_map); i < n; i++) for (int i = 0, n = map_len(); i < n; i++)
if (strcmp(str, log_level_map[i]) == 0) if (strcmp(str, log_level_map[i].name) == 0)
return i; return i;
return -1; return -1;
@ -205,8 +207,8 @@ log_level_string_hint(void)
if (buf[0] != '\0') if (buf[0] != '\0')
return buf; return buf;
for (size_t i = 0, pos = 0, n = ALEN(log_level_map); i < n; i++) { for (size_t i = 0, pos = 0, n = map_len(); i < n; i++) {
const char *entry = log_level_map[i]; const char *entry = log_level_map[i].name;
const char *delim = (i + 1 < n) ? ", " : ""; const char *delim = (i + 1 < n) ? ", " : "";
pos += xsnprintf(buf + pos, sizeof(buf) - pos, "'%s'%s", entry, delim); pos += xsnprintf(buf + pos, sizeof(buf) - pos, "'%s'%s", entry, delim);
} }

9
log.h
View file

@ -5,7 +5,14 @@
enum log_colorize { LOG_COLORIZE_NEVER, LOG_COLORIZE_ALWAYS, LOG_COLORIZE_AUTO }; enum log_colorize { LOG_COLORIZE_NEVER, LOG_COLORIZE_ALWAYS, LOG_COLORIZE_AUTO };
enum log_facility { LOG_FACILITY_USER, LOG_FACILITY_DAEMON }; enum log_facility { LOG_FACILITY_USER, LOG_FACILITY_DAEMON };
enum log_class { LOG_CLASS_ERROR, LOG_CLASS_WARNING, LOG_CLASS_INFO, LOG_CLASS_DEBUG };
enum log_class {
LOG_CLASS_NONE,
LOG_CLASS_ERROR,
LOG_CLASS_WARNING,
LOG_CLASS_INFO,
LOG_CLASS_DEBUG
};
void log_init(enum log_colorize colorize, bool do_syslog, void log_init(enum log_colorize colorize, bool do_syslog,
enum log_facility syslog_facility, enum log_class log_level); enum log_facility syslog_facility, enum log_class log_level);

49
main.c
View file

@ -61,27 +61,27 @@ print_usage(const char *prog_name)
"Usage: %s [OPTIONS...] command [ARGS...]\n" "Usage: %s [OPTIONS...] command [ARGS...]\n"
"\n" "\n"
"Options:\n" "Options:\n"
" -c,--config=PATH load configuration from PATH ($XDG_CONFIG_HOME/foot/foot.ini)\n" " -c,--config=PATH load configuration from PATH ($XDG_CONFIG_HOME/foot/foot.ini)\n"
" -C,--check-config verify configuration, exit with 0 if ok, otherwise exit with 1\n" " -C,--check-config verify configuration, exit with 0 if ok, otherwise exit with 1\n"
" -o,--override=[section.]key=value override configuration option\n" " -o,--override=[section.]key=value override configuration option\n"
" -f,--font=FONT comma separated list of fonts in fontconfig format (monospace)\n" " -f,--font=FONT comma separated list of fonts in fontconfig format (monospace)\n"
" -t,--term=TERM value to set the environment variable TERM to (%s)\n" " -t,--term=TERM value to set the environment variable TERM to (%s)\n"
" -T,--title=TITLE initial window title (foot)\n" " -T,--title=TITLE initial window title (foot)\n"
" -a,--app-id=ID window application ID (foot)\n" " -a,--app-id=ID window application ID (foot)\n"
" -m,--maximized start in maximized mode\n" " -m,--maximized start in maximized mode\n"
" -F,--fullscreen start in fullscreen mode\n" " -F,--fullscreen start in fullscreen mode\n"
" -L,--login-shell start shell as a login shell\n" " -L,--login-shell start shell as a login shell\n"
" -D,--working-directory=DIR directory to start in (CWD)\n" " -D,--working-directory=DIR directory to start in (CWD)\n"
" -w,--window-size-pixels=WIDTHxHEIGHT initial width and height, in pixels\n" " -w,--window-size-pixels=WIDTHxHEIGHT initial width and height, in pixels\n"
" -W,--window-size-chars=WIDTHxHEIGHT initial width and height, in characters\n" " -W,--window-size-chars=WIDTHxHEIGHT initial width and height, in characters\n"
" -s,--server[=PATH] run as a server (use 'footclient' to start terminals).\n" " -s,--server[=PATH] run as a server (use 'footclient' to start terminals).\n"
" Without PATH, $XDG_RUNTIME_DIR/foot-$WAYLAND_DISPLAY.sock will be used.\n" " Without PATH, $XDG_RUNTIME_DIR/foot-$WAYLAND_DISPLAY.sock will be used.\n"
" -H,--hold remain open after child process exits\n" " -H,--hold remain open after child process exits\n"
" -p,--print-pid=FILE|FD print PID to file or FD (only applicable in server mode)\n" " -p,--print-pid=FILE|FD print PID to file or FD (only applicable in server mode)\n"
" -d,--log-level={info|warning|error} log level (info)\n" " -d,--log-level={info|warning|error|none} log level (info)\n"
" -l,--log-colorize=[{never|always|auto}] enable/disable colorization of log output on stderr\n" " -l,--log-colorize=[{never|always|auto}] enable/disable colorization of log output on stderr\n"
" -s,--log-no-syslog disable syslog logging (only applicable in server mode)\n" " -s,--log-no-syslog disable syslog logging (only applicable in server mode)\n"
" -v,--version show the version number and quit\n", " -v,--version show the version number and quit\n",
prog_name, prog_name, DEFAULT_TERM); prog_name, prog_name, DEFAULT_TERM);
} }
@ -383,11 +383,14 @@ main(int argc, char *const *argv)
log_init(log_colorize, as_server && log_syslog, log_init(log_colorize, as_server && log_syslog,
as_server ? LOG_FACILITY_DAEMON : LOG_FACILITY_USER, log_level); as_server ? LOG_FACILITY_DAEMON : LOG_FACILITY_USER, log_level);
_Static_assert(LOG_CLASS_ERROR + 1 == FCFT_LOG_CLASS_ERROR, _Static_assert((int)LOG_CLASS_ERROR == (int)FCFT_LOG_CLASS_ERROR,
"fcft log level enum offset"); "fcft log level enum offset");
_Static_assert((int)LOG_COLORIZE_ALWAYS == (int)FCFT_LOG_COLORIZE_ALWAYS, _Static_assert((int)LOG_COLORIZE_ALWAYS == (int)FCFT_LOG_COLORIZE_ALWAYS,
"fcft colorize enum mismatch"); "fcft colorize enum mismatch");
fcft_log_init((enum fcft_log_colorize)log_colorize, as_server && log_syslog, log_level + 1); fcft_log_init(
(enum fcft_log_colorize)log_colorize,
as_server && log_syslog,
(enum fcft_log_class)log_level);
argc -= optind; argc -= optind;
argv += optind; argv += optind;

View file

@ -617,7 +617,7 @@ render_cell(struct terminal *term, pixman_image_t *pix,
*/ */
if (term->conf->tweak.allow_overflowing_double_width_glyphs && if (term->conf->tweak.allow_overflowing_double_width_glyphs &&
((glyph_count > 0 && ((glyph_count > 0 &&
glyphs[0]->cols == 1 && cell_cols == 1 &&
glyphs[0]->width >= term->cell_width * 15 / 10 && glyphs[0]->width >= term->cell_width * 15 / 10 &&
glyphs[0]->width < 3 * term->cell_width && glyphs[0]->width < 3 * term->cell_width &&
col < term->cols - 1) || col < term->cols - 1) ||

View file

@ -1425,10 +1425,10 @@ term_destroy(struct terminal *term)
} }
mtx_unlock(&term->render.workers.lock); mtx_unlock(&term->render.workers.lock);
urls_reset(term);
free(term->vt.osc.data); free(term->vt.osc.data);
free(term->vt.osc8.uri); free(term->vt.osc8.uri);
grid_free(&term->normal);
grid_free(&term->alt);
composed_free(term->composed); composed_free(term->composed);
@ -1471,9 +1471,11 @@ term_destroy(struct terminal *term)
sixel_fini(term); sixel_fini(term);
urls_reset(term);
term_ime_reset(term); term_ime_reset(term);
grid_free(&term->normal);
grid_free(&term->alt);
free(term->foot_exe); free(term->foot_exe);
free(term->cwd); free(term->cwd);

34
vt.c
View file

@ -639,10 +639,10 @@ action_utf8_print(struct terminal *term, wchar_t wc)
#if defined(FOOT_GRAPHEME_CLUSTERING) #if defined(FOOT_GRAPHEME_CLUSTERING)
if (grapheme_clustering) { if (grapheme_clustering) {
/* Check if we're on a grapheme cluster break */ /* Check if we're on a grapheme cluster break */
/* Note: utf8proc fails to ZWJ */ if (utf8proc_grapheme_break_stateful(
if (utf8proc_grapheme_break_stateful(last, wc, &term->vt.grapheme_state) && last, wc, &term->vt.grapheme_state))
last != 0x200d /* ZWJ */)
{ {
term_reset_grapheme_state(term);
goto out; goto out;
} }
} }
@ -682,6 +682,7 @@ action_utf8_print(struct terminal *term, wchar_t wc)
{ {
wc = precomposed; wc = precomposed;
width = precomposed_width; width = precomposed_width;
term_reset_grapheme_state(term);
goto out; goto out;
} }
} }
@ -746,6 +747,7 @@ action_utf8_print(struct terminal *term, wchar_t wc)
* character chains. Fall through here and print the * character chains. Fall through here and print the
* current zero-width character to the current cell */ * current zero-width character to the current cell */
LOG_WARN("maximum number of composed characters reached"); LOG_WARN("maximum number of composed characters reached");
term_reset_grapheme_state(term);
goto out; goto out;
} }
@ -762,28 +764,36 @@ action_utf8_print(struct terminal *term, wchar_t wc)
(wanted_count - 2) * sizeof(new_cc->chars[0])); (wanted_count - 2) * sizeof(new_cc->chars[0]));
} }
int grapheme_width = composed != NULL ? composed->width : base_width; const int grapheme_width =
composed != NULL ? composed->width : base_width;
if (wc == 0xfe0f && grapheme_width < 2) switch (term->conf->tweak.grapheme_width_method) {
grapheme_width = 2; case GRAPHEME_WIDTH_DOUBLE:
else if (unlikely(wc == 0xfe0f))
grapheme_width += width; width = 2;
new_cc->width = grapheme_width; new_cc->width = min(grapheme_width + width, 2);
break;
case GRAPHEME_WIDTH_WCSWIDTH:
new_cc->width = grapheme_width + width;
break;
}
term->composed_count++; term->composed_count++;
composed_insert(&term->composed, new_cc); composed_insert(&term->composed, new_cc);
wc = CELL_COMB_CHARS_LO + key; wc = CELL_COMB_CHARS_LO + key;
width = grapheme_width; width = new_cc->width;
xassert(wc >= CELL_COMB_CHARS_LO); xassert(wc >= CELL_COMB_CHARS_LO);
xassert(wc <= CELL_COMB_CHARS_HI); xassert(wc <= CELL_COMB_CHARS_HI);
goto out; goto out;
} }
} } else
term_reset_grapheme_state(term);
out: out:
term_reset_grapheme_state(term);
if (width > 0) if (width > 0)
term_print(term, wc, width); term_print(term, wc, width);
} }