[vte/wip/mosaic: 264/265] Revert "emulation: Remove 'separated mosaic' SGR"




commit 9bf650c7848562d8be046b8199371c8accd7d132
Author: Christian Persch <chpe src gnome org>
Date:   Sat Nov 14 22:46:43 2020 +0100

    Revert "emulation: Remove 'separated mosaic' SGR"
    
    This reverts commit adedb9c5ef222d52c6f66e3140de4d3cd4b7bc3d.

 src/attr.hh       |   8 +++-
 src/cell.hh       |   1 +
 src/minifont.cc   | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/parser-sgr.hh |   2 +
 src/vte.cc        |   3 +-
 src/vteseq.cc     |   6 +++
 6 files changed, 126 insertions(+), 2 deletions(-)
---
diff --git a/src/attr.hh b/src/attr.hh
index d3273afb..646d86d9 100644
--- a/src/attr.hh
+++ b/src/attr.hh
@@ -85,6 +85,11 @@
 #define VTE_ATTR_INVISIBLE_MASK        (VTE_ATTR_MASK(VTE_ATTR_INVISIBLE_SHIFT, VTE_ATTR_INVISIBLE_BITS))
 #define VTE_ATTR_INVISIBLE             (1U << VTE_ATTR_INVISIBLE_SHIFT)
 
+#define VTE_ATTR_SEPARATED_MOSAIC_SHIFT (VTE_ATTR_INVISIBLE_SHIFT + VTE_ATTR_INVISIBLE_BITS)
+#define VTE_ATTR_SEPARATED_MOSAIC_BITS  (1)
+#define VTE_ATTR_SEPARATED_MOSAIC_MASK  (VTE_ATTR_MASK(VTE_ATTR_SEPARATED_MOSAIC_SHIFT, 
VTE_ATTR_SEPARATED_MOSAIC_BITS))
+#define VTE_ATTR_SEPARATED_MOSAIC       (1U << VTE_ATTR_SEPARATED_MOSAIC_SHIFT)
+
 /* Used internally only */
 #define VTE_ATTR_BOXED_SHIFT           (31)
 #define VTE_ATTR_BOXED_BITS            (1)
@@ -99,7 +104,8 @@
                                         VTE_ATTR_OVERLINE_MASK | \
                                         VTE_ATTR_REVERSE_MASK | \
                                         VTE_ATTR_BLINK_MASK | \
-                                        VTE_ATTR_INVISIBLE_MASK)
+                                        VTE_ATTR_INVISIBLE_MASK | \
+                                        VTE_ATTR_SEPARATED_MOSAIC_MASK)
 
 #define VTE_ATTR_NONE                  (0U)
 #define VTE_ATTR_DEFAULT               (VTE_ATTR_COLUMNS(1))
diff --git a/src/cell.hh b/src/cell.hh
index 63b908c9..a1c6cebb 100644
--- a/src/cell.hh
+++ b/src/cell.hh
@@ -146,6 +146,7 @@ typedef struct _VTE_GNUC_PACKED VteCellAttr {
         CELL_ATTR_BOOL(blink, BLINK)
         CELL_ATTR_BOOL(dim, DIM)
         CELL_ATTR_BOOL(invisible, INVISIBLE)
+        CELL_ATTR_BOOL(separated_mosaic, SEPARATED_MOSAIC)
         /* ATTR_BOOL(boxed, BOXED) */
 } VteCellAttr;
 static_assert(sizeof (VteCellAttr) == 16, "VteCellAttr has wrong size");
diff --git a/src/minifont.cc b/src/minifont.cc
index c963f42b..5d106200 100644
--- a/src/minifont.cc
+++ b/src/minifont.cc
@@ -25,6 +25,99 @@
 #include "drawing-cairo.hh"
 #include "minifont.hh"
 
+#ifdef WITH_SEPARATED_MOSAICS
+static bool
+_vte_draw_is_separable_mosaic(vteunistr c)
+{
+        // FIXMEchpe check from T.101 which characters should be separable
+        return ((c >= 0x1fb00 && c <= 0x1fb9f)||
+                (c >= 0x25e2 && c <= 0x25e5) ||
+                (c >= 0x2580 && c <= 0x259f));
+}
+
+/* Create separated mosaic pattern.
+ * Transparent pixels will not be drawn; opaque pixels will draw that part of the
+ * mosaic onto the target surface.
+ */
+static cairo_pattern_t*
+create_mosaic_separation_pattern(int width,
+                                 int height,
+                                 int line_thickness)
+{
+        auto surface = cairo_image_surface_create(CAIRO_FORMAT_A1, width, height);
+        // or CAIRO_FORMAT_A8, whichever is better/faster?
+
+        auto cr = cairo_create(surface);
+
+        /* It's not quite clear how the separated mosaics should be drawn.
+         *
+         * ITU-T T.101 Annex C, C.2.1.2, and Annex D, D.5.4, show the separation
+         * being done by blanking a line on the left and bottom parts only of each
+         * of the 3x2 blocks.
+         * The minitel specification STUM 1B, Schéma 2.7 also shows them drawn that
+         * way.
+         *
+         * On the other hand, ETS 300 706 §15.7.1, Table 47, shows the separation
+         * being done by blanking a line around all four sides of each of the
+         * 3x2 blocks.
+         * That is also how ITU-T T.100 §5.4.2.1, Figure 6, shows the separation.
+         *
+         * Each of these has its own drawbacks. The T.101 way makes the 3x2 blocks
+         * asymmetric, leaving differing amount of lit pixels for the smooth mosaics
+         * comparing a mosaic with its corresponding vertically mirrored mosaic. It
+         * keeps more lit pixels overall, which make it more suitable for low-resolution
+         * display, which is probably why minitel uses that.
+         * The ETS 300 706 way keeps symmetry, but removes even more lit pixels.
+         *
+         * Here we implement the T.101 way.
+         */
+
+        /* FIXMEchpe: Check that this fulfills [T.101 Appendix IV]:
+         * "All separated and contiguous mosaics shall be uniquely presented for character
+         * field sizes greater than or equal to dx = 6/256, dy = 8/256 [see D.8.3.3, item 7)]."
+         */
+
+        /* First, fill completely with transparent pixels */
+        cairo_set_source_rgba(cr, 0., 0., 0., 0.);
+        cairo_rectangle(cr, 0, 0, width, height);
+        cairo_fill(cr);
+
+        /* Now, fill the reduced blocks with opaque pixels */
+
+        auto const pel = line_thickness; /* see T.101 D.5.3.2.2.6 for definition of 'logical pel' */
+
+        if (width > 2 * pel && height > 3 * pel) {
+
+                auto const width_half = width / 2;
+                auto const height_thirds = height / 3;
+                auto const remaining_height = height - 3 * height_thirds;
+
+                int const y[4] = { 0, height_thirds, 2 * height_thirds + (remaining_height ? 1 : 0), height 
};
+                int const x[3] = { 0, width_half, width };
+                // FIXMEchpe: or use 2 * width_half instead of width, so that for width odd,
+                // the extra row of pixels is unlit, and the lit blocks have equal width?
+
+                cairo_set_source_rgba(cr, 0., 0., 0., 1.);
+                for (auto yi = 0; yi < 3; ++yi) {
+                        for (auto xi = 0; xi < 2; xi++) {
+                                cairo_rectangle(cr, x[xi] + pel, y[yi], x[xi+1] - x[xi] - pel, y[yi+1] - 
y[yi] - pel);
+                                cairo_fill(cr);
+                        }
+                }
+        }
+
+        cairo_destroy(cr);
+
+        auto pattern = cairo_pattern_create_for_surface(surface);
+        cairo_surface_destroy(surface);
+
+        cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
+        cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST);
+
+        return pattern;
+}
+#endif /* WITH_SEPARATED_MOSAICS */
+
 /* pixman data must have stride 0 mod 4 */
 static unsigned char const hatching_pattern_lr_data[16] = {
         0xff, 0x00, 0x00, 0x00,
@@ -184,6 +277,12 @@ Minifont::draw_graphic(DrawingContext const& context,
         xright = x + width;
         ybottom = y + height;
 
+#ifdef WITH_SEPARATED_MOSAICS
+        auto const separated = vte_attr_get_bool(attr, VTE_ATTR_SEPARATED_MOSAIC_SHIFT) 
&&_vte_draw_is_separable_mosaic(c);
+        if (separated)
+                cairo_push_group(cr);
+#endif
+
         switch (c) {
 
         /* Box Drawing */
@@ -1107,6 +1206,15 @@ Minifont::draw_graphic(DrawingContext const& context,
                 g_assert_not_reached();
         }
 
+#ifdef WITH_SEPARATED_MOSAICS
+        if (separated) {
+                cairo_pop_group_to_source(cr);
+                auto pattern = create_mosaic_separation_pattern(width, height, light_line_width);
+                cairo_mask(cr, pattern);
+                cairo_pattern_destroy(pattern);
+        }
+#endif
+
         cairo_restore(cr);
 }
 
diff --git a/src/parser-sgr.hh b/src/parser-sgr.hh
index c12e5ade..afa15266 100644
--- a/src/parser-sgr.hh
+++ b/src/parser-sgr.hh
@@ -40,6 +40,7 @@ SGR(SET, BACK_LEGACY_END, 47)
 SGR(SET, BACK_SPEC, 48)
 SGR(SET, OVERLINE, 53)
 SGR(SET, DECO_SPEC, 58)
+SGR(SET, SEPARATED_MOSAIC, 71)
 SGR(SET, FORE_LEGACY_BRIGHT_START, 90)
 SGR(SET, FORE_LEGACY_BRIGHT_END, 97)
 SGR(SET, BACK_LEGACY_BRIGHT_START, 100)
@@ -56,6 +57,7 @@ SGR(RESET, FORE, 39)
 SGR(RESET, BACK, 49)
 SGR(RESET, OVERLINE, 55)
 SGR(RESET, DECO, 59)
+SGR(RESET, SEPARATED_MOSAIC, 72)
 
 NGR(SET, FONT_FIRST, 10)
 NGR(SET, FONT_LAST, 19)
diff --git a/src/vte.cc b/src/vte.cc
index deb64fc7..dc42d7b5 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -8817,7 +8817,8 @@ Terminal::draw_rows(VteScreen *screen_,
                                                        VTE_ATTR_STRIKETHROUGH_MASK |
                                                        VTE_ATTR_OVERLINE_MASK |
                                                        VTE_ATTR_BLINK_MASK |
-                                                       VTE_ATTR_INVISIBLE_MASK)) ||  // FIXME or just simply 
"attr != nattr"?
+                                                       VTE_ATTR_INVISIBLE_MASK |
+                                                       VTE_ATTR_SEPARATED_MOSAIC_MASK)) ||  // FIXME or just 
simply "attr != nattr"?
                                     fore != nfore ||
                                     back != nback ||
                                     deco != ndeco ||
diff --git a/src/vteseq.cc b/src/vteseq.cc
index 9826ce0f..3ae5d5e4 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -7425,6 +7425,12 @@ Terminal::SGR(vte::parser::Sequence const& seq)
                                 m_defaults.attr.set_deco(deco);
                         break;
                 }
+                case VTE_SGR_SET_SEPARATED_MOSAIC:
+                        m_defaults.attr.set_separated_mosaic(true);
+                        break;
+                case VTE_SGR_RESET_SEPARATED_MOSAIC:
+                        m_defaults.attr.set_separated_mosaic(false);
+                        break;
                 case VTE_SGR_RESET_DECO:
                         /* default decoration color, that is, same as the cell's foreground */
                         m_defaults.attr.set_deco(VTE_DEFAULT_FG);


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