summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Persch <chpe@src.gnome.org>2022-04-07 16:44:09 +0200
committerChristian Persch <chpe@src.gnome.org>2022-04-07 16:44:09 +0200
commit95a565d0e1f56a2638a617eaf198c95328e7d398 (patch)
tree5094ae0631ecf5f9b3d40c7fff4f9b9f290c0b0b
parentee9ff3be2e69ded81b79fbba8f149c143f688367 (diff)
downloadvte-95a565d0e1f56a2638a617eaf198c95328e7d398.tar.gz
minifont: Implement scanlines and connecting box drawings
FIXME: make this work for height = 5..8 and even for height < 5 (by dropping the alignment, maybe).
-rw-r--r--src/minifont.cc159
-rw-r--r--src/minifont.hh3
2 files changed, 161 insertions, 1 deletions
diff --git a/src/minifont.cc b/src/minifont.cc
index 24a3616b..5ff590d9 100644
--- a/src/minifont.cc
+++ b/src/minifont.cc
@@ -209,6 +209,69 @@ octant(cairo_t* cr,
cairo_fill(cr);
}
+inline constexpr int
+scanline_y(int value,
+ int height,
+ int line_width) noexcept
+{
+ /* There are 9 scanlines, but only the odd scanlines (1, 3, 5, 7,
+ * and 9) are actually in unicode.
+ * To get the space assigned to each scanline, we divide the
+ * height by 9 and distribute the remainder space in this order:
+ * scanline 5, 4, 7, 2, 6, 3, 8, 1.
+ * This ensures that the remainder is added first to the bottom
+ * half towards the centre, and that the spacing between the odd
+ * scanlines are at most 1px different.
+ *
+ * Since scanline 5 is unified with U+2500 BOX DRAWINGS LIGHT HORIZONTAL,
+ * the other scanlines are aligned so that scanline 5 coincides with
+ * U+2500, that is, has y position upper_half - light_line_width / 2.
+ */
+
+ // FIMXE: this doesn't work for height < 9. Since we only need the odd
+ // scanlines, we can make this work fine for height = 5..8, but for
+ // heights < 5, need to still at least align 1 to top, 5 to middle, and
+ // 9 to bottom
+
+ auto const h = height / 9;
+ auto const r = height % 9;
+ auto y = height / 2 - line_width / 2 + (value - 5) * h;
+
+ auto extra = [&r](int v) constexpr noexcept -> auto { return r >= v ? 1 : 0; };
+
+ switch (value) {
+ case 1: y -= extra(8); [[fallthrough]];
+ case 2: y -= extra(4); [[fallthrough]];
+ case 3: y -= extra(6); [[fallthrough]];
+ case 4: y -= extra(2); [[fallthrough]];
+ case 5: break;
+ case 9: y += extra(7); [[fallthrough]];
+ case 8: y += extra(3); [[fallthrough]];
+ case 7: y += extra(5); [[fallthrough]];
+ case 6: y += extra(1); break;
+ default: __builtin_unreachable(); break;
+ }
+
+ return y;
+}
+
+inline void
+scanline(cairo_t* cr,
+ int value,
+ int x,
+ int y,
+ int width,
+ int height,
+ int line_width) noexcept
+{
+ cairo_rectangle(cr,
+ x,
+ y + scanline_y(value, height, line_width),
+ width,
+ line_width);
+ cairo_fill(cr);
+}
+
static void
polygon(cairo_t* cr,
double x,
@@ -448,6 +511,35 @@ Minifont::draw_graphic(DrawingContext const& context,
switch (c) {
+ case 0x23b8: /* LEFT VERTICAL BOX LINE */
+ cairo_rectangle(cr,
+ x, y,
+ light_line_width, height);
+ cairo_fill(cr);
+ break;
+ case 0x23b9: /* RIGHT VERTICAL BOX LINE */
+ cairo_rectangle(cr,
+ x + width - light_line_width, y,
+ light_line_width, height);
+ cairo_fill(cr);
+ break;
+
+ case 0x23ba: /* HORIZONTAL SCAN LINE-1 */
+ scanline(cr, 1, x, y, width, height, light_line_width);
+ break;
+ case 0x23bb: /* HORIZONTAL SCAN LINE-3 */
+ scanline(cr, 3, x, y, width, height, light_line_width);
+ break;
+
+ /* Note: HORIZONTAL SCAN LINE-5 is unified with U+2500 BOX DRAWINGS LIGHT HORIZONTAL */
+
+ case 0x23bc: /* HORIZONTAL SCAN LINE-7 */
+ scanline(cr, 7, x, y, width, height, light_line_width);
+ break;
+ case 0x23bd: /* HORIZONTAL SCAN LINE-9 */
+ scanline(cr, 9, x, y, width, height, light_line_width);
+ break;
+
/* Box Drawing */
case 0x1fbaf: /* box drawings light horizontal with vertical stroke */
rectangle(cr, x + left_half - light_line_width / 2, y,
@@ -1634,6 +1726,73 @@ Minifont::draw_graphic(DrawingContext const& context,
break;
}
+ case 0x1cc1b: /* BOX DRAWING LIGHT HORIZONTAL AND UPPER RIGHT */
+ case 0x1cc1c: /* BOX DRAWING LIGHT HORIZONTAL AND LOWER RIGHT */ {
+ /* Apparently these have no LEFT counterparts; note that
+ * U+11CC1D..E below are *not* them!
+ */
+ auto const top = (c == 0x1cc1b);
+ cairo_rectangle(cr,
+ x, y + upper_half - light_line_width / 2,
+ width, light_line_width);
+ cairo_rectangle(cr,
+ x + width - light_line_width,
+ y + (top ? 0 : upper_half - light_line_width / 2),
+ light_line_width,
+ (top ? upper_half : height - upper_half) + light_line_width / 2);
+ cairo_fill(cr);
+ break;
+ }
+
+ case 0x1cc1d: /* BOX DRAWING LIGHT TOP AND UPPER LEFT */
+ case 0x1cc1e: /* BOX DRAWING LIGHT BOTTOM AND LOWER LEFT */ {
+ auto const top = (c == 0x1cc1d);
+ auto const ys = scanline_y(top ? 1 : 9, height, light_line_width);
+
+ cairo_rectangle(cr, x, y + ys, width, light_line_width);
+ cairo_rectangle(cr, x, y + (top ? ys : upper_half),
+ light_line_width,
+ top ? upper_half - ys : ys - upper_half + light_line_width);
+ cairo_fill(cr);
+ break;
+ }
+
+ case 0x1ce16: /* BOX DRAWING LIGHT VERTICAL AND TOP RIGHT */
+ case 0x1ce17: /* BOX DRAWING LIGHT VERTICAL AND BOTTOM RIGHT */
+ case 0x1ce18: /* BOX DRAWING LIGHT VERTICAL AND TOP LEFT */
+ case 0x1ce19: /* BOX DRAWING LIGHT VERTICAL AND BOTTOM LEFT */ {
+ auto const top = (c & 1) == 0;
+ auto const left = (c >= 0x1ce18);
+ auto const sy = scanline_y(top ? 1 : 9, height, light_line_width);
+
+ if (top)
+ cairo_rectangle(cr,
+ x + left_half - light_line_width / 2,
+ y + sy,
+ light_line_width,
+ height - sy);
+ else
+ cairo_rectangle(cr,
+ x + left_half - light_line_width / 2,
+ y,
+ light_line_width,
+ sy + light_line_width);
+ cairo_fill(cr);
+
+ if (left)
+ cairo_rectangle(cr,
+ x, y + sy,
+ left_half + light_line_width / 2,
+ light_line_width);
+ else
+ cairo_rectangle(cr,
+ x + left_half - light_line_width / 2, y + sy,
+ width - left_half + light_line_width / 2,
+ light_line_width);
+ cairo_fill(cr);
+
+ break;
+ }
default:
cairo_set_source_rgba (cr, 1., 0., 1., 1.);
diff --git a/src/minifont.hh b/src/minifont.hh
index cb32f545..a2678425 100644
--- a/src/minifont.hh
+++ b/src/minifont.hh
@@ -37,7 +37,8 @@ public:
unistr_is_local_graphic(vteunistr const c) noexcept
{
/* Box Drawing & Block Elements */
- return ((c >= 0x2500 && c <= 0x259f) ||
+ return ((c >= 0x23b8 && c <= 0x23bd) ||
+ (c >= 0x2500 && c <= 0x259f) ||
(c >= 0x25e2 && c <= 0x25e5) ||
(c >= 0x1fb00 && c <= 0x1fbebf) ||
(c >= 0x1cc00 && c <= 0x1ceaf));