Merge branch 'box-drawing-line-thickness'

Closes #281
This commit is contained in:
Daniel Eklöf 2021-01-14 10:49:39 +01:00
commit 5acdc89952
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
5 changed files with 61 additions and 22 deletions

View file

@ -47,6 +47,8 @@
(https://codeberg.org/dnkl/foot/issues/270) (https://codeberg.org/dnkl/foot/issues/270)
* Double- or triple clicking then dragging now extends the selection * Double- or triple clicking then dragging now extends the selection
word- or line-wise (https://codeberg.org/dnkl/foot/issues/267). word- or line-wise (https://codeberg.org/dnkl/foot/issues/267).
* The line thickness of box drawing characters now depend on the font
size (https://codeberg.org/dnkl/foot/issues/281).
### Deprecated ### Deprecated

View file

@ -13,8 +13,10 @@
#include "util.h" #include "util.h"
#include "xmalloc.h" #include "xmalloc.h"
#define LIGHT 1.0 enum thickness {
#define HEAVY 2.0 LIGHT = 1,
HEAVY = 3,
};
struct buf { struct buf {
uint8_t *data; uint8_t *data;
@ -22,14 +24,16 @@ struct buf {
int height; int height;
int stride; int stride;
int dpi; int dpi;
float cell_size;
float base_thickness;
}; };
static int static int
_thickness(struct buf *buf, float pts) _thickness(struct buf *buf, enum thickness thick)
{ {
return max(pts * buf->dpi / 72.0, 1); return max((int)(buf->base_thickness * buf->dpi / 72.0 * buf->cell_size), 1) * thick;
} }
#define thickness(pts) _thickness(buf, pts) #define thickness(thick) _thickness(buf, thick)
static void NOINLINE static void NOINLINE
_hline(struct buf *buf, int x1, int x2, int y, int thick) _hline(struct buf *buf, int x1, int x2, int y, int thick)
@ -37,7 +41,7 @@ _hline(struct buf *buf, int x1, int x2, int y, int thick)
x1 = min(max(x1, 0), buf->width); x1 = min(max(x1, 0), buf->width);
x2 = min(max(x2, 0), buf->width); x2 = min(max(x2, 0), buf->width);
for (size_t row = max(y, 0); row < min(y + thick, buf->height); row++) { for (size_t row = max(y, 0); row < max(min(y + thick, buf->height), 0); row++) {
for (size_t col = x1; col < x2; col++) { for (size_t col = x1; col < x2; col++) {
size_t idx = col / 8; size_t idx = col / 8;
size_t bit_no = col % 8; size_t bit_no = col % 8;
@ -55,7 +59,7 @@ _vline(struct buf *buf, int y1, int y2, int x, int thick)
y2 = min(max(y2, 0), buf->height); y2 = min(max(y2, 0), buf->height);
for (size_t row = y1; row < y2; row++) { for (size_t row = y1; row < y2; row++) {
for (size_t col = max(x, 0); col < min(x + thick, buf->width); col++) { for (size_t col = max(x, 0); col < max(min(x + thick, buf->width), 0); col++) {
size_t idx = col / 8; size_t idx = col / 8;
size_t bit_no = col % 8; size_t bit_no = col % 8;
buf->data[row * buf->stride + idx] |= 1 << bit_no; buf->data[row * buf->stride + idx] |= 1 << bit_no;
@ -69,7 +73,7 @@ static void NOINLINE
_rect(struct buf *buf, int x1, int y1, int x2, int y2) _rect(struct buf *buf, int x1, int y1, int x2, int y2)
{ {
for (size_t row = max(y1, 0); row < min(y2, buf->height); row++) { for (size_t row = max(y1, 0); row < min(y2, buf->height); row++) {
for (size_t col = max(x1, 0); col < min(x2, buf->width); col++) { for (size_t col = max(x1, 0); col < max(min(x2, buf->width), 0); col++) {
size_t idx = col / 8; size_t idx = col / 8;
size_t bit_no = col % 8; size_t bit_no = col % 8;
buf->data[row * buf->stride + idx] |= 1 << bit_no; buf->data[row * buf->stride + idx] |= 1 << bit_no;
@ -80,14 +84,14 @@ _rect(struct buf *buf, int x1, int y1, int x2, int y2)
#define rect(x1, y1, x2, y2) _rect(buf, x1, y1, x2, y2) #define rect(x1, y1, x2, y2) _rect(buf, x1, y1, x2, y2)
static void NOINLINE static void NOINLINE
_hline_middle(struct buf *buf, float _thick) _hline_middle(struct buf *buf, enum thickness _thick)
{ {
int thick = thickness(_thick); int thick = thickness(_thick);
hline(0, buf->width, (buf->height - thick) / 2, thick); hline(0, buf->width, (buf->height - thick) / 2, thick);
} }
static void NOINLINE static void NOINLINE
_hline_middle_left(struct buf *buf, float _vthick, float _hthick) _hline_middle_left(struct buf *buf, enum thickness _vthick, enum thickness _hthick)
{ {
int vthick = thickness(_vthick); int vthick = thickness(_vthick);
int hthick = thickness(_hthick); int hthick = thickness(_hthick);
@ -95,7 +99,7 @@ _hline_middle_left(struct buf *buf, float _vthick, float _hthick)
} }
static void NOINLINE static void NOINLINE
_hline_middle_right(struct buf *buf, float _vthick, float _hthick) _hline_middle_right(struct buf *buf, enum thickness _vthick, enum thickness _hthick)
{ {
int vthick = thickness(_vthick); int vthick = thickness(_vthick);
int hthick = thickness(_hthick); int hthick = thickness(_hthick);
@ -103,14 +107,14 @@ _hline_middle_right(struct buf *buf, float _vthick, float _hthick)
} }
static void NOINLINE static void NOINLINE
_vline_middle(struct buf *buf, float _thick) _vline_middle(struct buf *buf, enum thickness _thick)
{ {
int thick = thickness(_thick); int thick = thickness(_thick);
vline(0, buf->height, (buf->width - thick) / 2, thick); vline(0, buf->height, (buf->width - thick) / 2, thick);
} }
static void NOINLINE static void NOINLINE
_vline_middle_up(struct buf *buf, float _vthick, float _hthick) _vline_middle_up(struct buf *buf, enum thickness _vthick, enum thickness _hthick)
{ {
int vthick = thickness(_vthick); int vthick = thickness(_vthick);
int hthick = thickness(_hthick); int hthick = thickness(_hthick);
@ -118,7 +122,7 @@ _vline_middle_up(struct buf *buf, float _vthick, float _hthick)
} }
static void NOINLINE static void NOINLINE
_vline_middle_down(struct buf *buf, float _vthick, float _hthick) _vline_middle_down(struct buf *buf, enum thickness _vthick, enum thickness _hthick)
{ {
int vthick = thickness(_vthick); int vthick = thickness(_vthick);
int hthick = thickness(_hthick); int hthick = thickness(_hthick);
@ -1303,8 +1307,8 @@ draw_box_drawings_light_arc(wchar_t wc, struct buf *buf)
assert(row_end > row_start); assert(row_end > row_start);
assert(col_end > col_start); assert(col_end > col_start);
for (int r = max(row_start, 0); r < min(row_end, buf->height); r++) { for (int r = max(row_start, 0); r < max(min(row_end, buf->height), 0); r++) {
for (int c = max(col_start, 0); c < min(col_end, buf->width); c++) { for (int c = max(col_start, 0); c < max(min(col_end, buf->width), 0); c++) {
size_t idx = c / 8; size_t idx = c / 8;
size_t bit_no = c % 8; size_t bit_no = c % 8;
buf->data[r * buf->stride + idx] |= 1 << bit_no; buf->data[r * buf->stride + idx] |= 1 << bit_no;
@ -1323,9 +1327,11 @@ draw_box_drawings_light_arc(wchar_t wc, struct buf *buf)
for (int y = 0; y < thick; y++) { for (int y = 0; y < thick; y++) {
int row = (buf->height - thick) / 2 + y; int row = (buf->height - thick) / 2 + y;
int col = buf->width - 1; int col = buf->width - 1;
size_t ofs = col / 8; if (row >= 0 && row < buf->height && col >= 0 && col < buf->width) {
size_t bit_no = col % 8; size_t ofs = col / 8;
buf->data[row * buf->stride + ofs] |= 1 << bit_no; size_t bit_no = col % 8;
buf->data[row * buf->stride + ofs] |= 1 << bit_no;
}
} }
} }
@ -1333,9 +1339,11 @@ draw_box_drawings_light_arc(wchar_t wc, struct buf *buf)
for (int x = 0; x < thick; x++) { for (int x = 0; x < thick; x++) {
int row = buf->height - 1; int row = buf->height - 1;
int col = (buf->width - thick) / 2 + x; int col = (buf->width - thick) / 2 + x;
size_t ofs = col / 8; if (row >= 0 && row < buf->height && col >= 0 && col < buf->width) {
size_t bit_no = col % 8; size_t ofs = col / 8;
buf->data[row * buf->stride + ofs] |= 1 << bit_no; size_t bit_no = col % 8;
buf->data[row * buf->stride + ofs] |= 1 << bit_no;
}
} }
} }
} }
@ -2061,7 +2069,13 @@ box_drawing(const struct terminal *term, wchar_t wc)
.height = height, .height = height,
.stride = stride, .stride = stride,
.dpi = term->font_dpi, .dpi = term->font_dpi,
.cell_size = sqrt(pow(term->cell_width, 2) + pow(term->cell_height, 2)),
.base_thickness = term->conf->tweak.box_drawing_base_thickness,
}; };
LOG_DBG("LIGHT=%d, HEAVY=%d",
_thickness(&buf, LIGHT), _thickness(&buf, HEAVY));
draw_glyph(wc, &buf); draw_glyph(wc, &buf);
struct fcft_glyph *glyph = xmalloc(sizeof(*glyph)); struct fcft_glyph *glyph = xmalloc(sizeof(*glyph));

View file

@ -1708,6 +1708,20 @@ parse_section_tweak(
(long long)conf->tweak.max_shm_pool_size); (long long)conf->tweak.max_shm_pool_size);
} }
else if (strcmp(key, "box-drawing-base-thickness") == 0) {
double base_thickness;
if (!str_to_double(value, &base_thickness)) {
LOG_AND_NOTIFY_ERR(
"%s:%d: [tweak]: box-drawing-base-thickness: "
"expected a decimal value, got '%s'", path, lineno, value);
return false;
}
conf->tweak.box_drawing_base_thickness = base_thickness;
LOG_WARN("tweak: box-drawing-base-thickness=%f",
conf->tweak.box_drawing_base_thickness);
}
else { else {
LOG_AND_NOTIFY_ERR("%s:%u: [tweak]: %s: invalid key", path, lineno, key); LOG_AND_NOTIFY_ERR("%s:%u: [tweak]: %s: invalid key", path, lineno, key);
return false; return false;
@ -2122,6 +2136,7 @@ config_load(struct config *conf, const char *conf_path,
.render_timer_osd = false, .render_timer_osd = false,
.render_timer_log = false, .render_timer_log = false,
.damage_whole_window = false, .damage_whole_window = false,
.box_drawing_base_thickness = 0.04,
}, },
.notifications = tll_init(), .notifications = tll_init(),

View file

@ -196,6 +196,7 @@ struct config {
uint64_t delayed_render_lower_ns; uint64_t delayed_render_lower_ns;
uint64_t delayed_render_upper_ns; uint64_t delayed_render_upper_ns;
off_t max_shm_pool_size; off_t max_shm_pool_size;
float box_drawing_base_thickness;
} tweak; } tweak;
user_notifications_t notifications; user_notifications_t notifications;

View file

@ -648,6 +648,13 @@ any of these options.
or both. Valid values are *none*, *osd*, *log* and or both. Valid values are *none*, *osd*, *log* and
*both*. Default: _none_. *both*. Default: _none_.
*box-drawing-base-thickness*
Line thickness to use for *LIGHT* box drawing line characters, in
points. This value is converted to pixels using the monitor's DPI,
and then multiplied with the cell size. The end result is that a
larger font (and thus larger cells) result in thicker
lines. Default: _0.04_.
*delayed-render-lower*, *delayed-render-upper* *delayed-render-lower*, *delayed-render-upper*
These two values control the timeouts (in nanoseconds) that are These two values control the timeouts (in nanoseconds) that are
used to mitigate screen flicker caused by clients writing large, used to mitigate screen flicker caused by clients writing large,