[vte/wip/l2-21235: 6/7] minifont: Implement scanlines and connecting box drawings




commit 95a565d0e1f56a2638a617eaf198c95328e7d398
Author: Christian Persch <chpe src gnome org>
Date:   Thu Apr 7 16:44:09 2022 +0200

    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).

 src/minifont.cc | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/minifont.hh |   3 +-
 2 files changed, 161 insertions(+), 1 deletion(-)
---
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));


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]