[vte] all: Rearrange VteCellAttr to store all colours together in one uint64_t



commit 615d5fac3fa8009a11a3def7799af968d71bc4a9
Author: Christian Persch <chpe src gnome org>
Date:   Sat Jan 13 20:55:44 2018 +0100

    all: Rearrange VteCellAttr to store all colours together in one uint64_t
    
    This re-arranges the VteCellAttr struct to store the foreground,
    background and decoration colour together in one uint64_t. This will
    allow later optimising the *other* attributes.
    
    A 24-bit (8 bit per component) color is stored in 25 bits in vte
    (one extra bit is necessary to distinguish direct colours from
    index colors), so to fit 3 colours into 64 bits, it was necessary
    to reduce the depth of the (lesser used) decoration colour to
    4 bit per component.

 src/Makefile.am     |    1 +
 src/color-triple.hh |   92 +++++++++++++++++++++++++++++++++++++++++
 src/vte.cc          |  113 +++++++++++++++++++++++++++------------------------
 src/vtedefines.hh   |   19 +++++++--
 src/vteinternal.hh  |   10 +++-
 src/vterowdata.h    |  109 ++++++++++++++++++++++++++++---------------------
 src/vteseq.cc       |  100 +++++++++++++++++++++++++++------------------
 7 files changed, 298 insertions(+), 146 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 0f87a60..6f68b1e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -48,6 +48,7 @@ libvte_@VTE_API_MAJOR_VERSION@_@VTE_API_MINOR_VERSION@_la_SOURCES = \
        buffer.h \
        caps.hh \
        caps-list.hh \
+       color-triple.hh \
        debug.cc \
        debug.h \
        iso2022.cc \
diff --git a/src/color-triple.hh b/src/color-triple.hh
new file mode 100644
index 0000000..2321f4a
--- /dev/null
+++ b/src/color-triple.hh
@@ -0,0 +1,92 @@
+/*
+ * Copyright © 2018 Christian Persch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+typedef uint64_t vte_color_triple_t;
+
+#define VTE_COLOR_TRIPLE_FORE_SHIFT     (0)
+#define VTE_COLOR_TRIPLE_BACK_SHIFT     (25)
+#define VTE_COLOR_TRIPLE_DECO_SHIFT     (50)
+
+#define VTE_COLOR_TRIPLE_RGB_MASK(rb,gb,bb) ((1ULL << ((rb) + (gb) + (bb) + 1)) - 1)
+#define VTE_COLOR_TRIPLE_FORE_MASK      (VTE_COLOR_TRIPLE_RGB_MASK(8, 8, 8) << VTE_COLOR_TRIPLE_FORE_SHIFT)
+#define VTE_COLOR_TRIPLE_BACK_MASK      (VTE_COLOR_TRIPLE_RGB_MASK(8, 8, 8) << VTE_COLOR_TRIPLE_BACK_SHIFT)
+#define VTE_COLOR_TRIPLE_DECO_MASK      (VTE_COLOR_TRIPLE_RGB_MASK(4, 5, 4) << VTE_COLOR_TRIPLE_DECO_SHIFT)
+
+#define VTE_COLOR_TRIPLE_INIT(fg,bg,dc) (uint64_t(fg) << VTE_COLOR_TRIPLE_FORE_SHIFT | \
+                                         uint64_t(bg) << VTE_COLOR_TRIPLE_BACK_SHIFT | \
+                                         uint64_t(dc) << VTE_COLOR_TRIPLE_DECO_SHIFT)
+
+#define VTE_COLOR_TRIPLE_INIT_DEFAULT   (VTE_COLOR_TRIPLE_INIT(VTE_DEFAULT_FG, \
+                                                               VTE_DEFAULT_BG, \
+                                                               VTE_DEFAULT_FG))
+
+static constexpr inline vte_color_triple_t vte_color_triple_init(void)
+{
+        return VTE_COLOR_TRIPLE_INIT_DEFAULT;
+}
+
+static constexpr inline vte_color_triple_t vte_color_triple_copy(vte_color_triple_t ct)
+{
+        return ct;
+}
+
+static inline constexpr void vte_color_triple_set_fore(vte_color_triple_t* ct,
+                                                       uint32_t fore)
+{
+        *ct = (*ct & ~VTE_COLOR_TRIPLE_FORE_MASK) | (uint64_t(fore)) << VTE_COLOR_TRIPLE_FORE_SHIFT;
+}
+
+static inline constexpr void vte_color_triple_set_back(vte_color_triple_t* ct,
+                                                       uint32_t back)
+{
+        *ct = (*ct & ~VTE_COLOR_TRIPLE_BACK_MASK) | (uint64_t(back)) << VTE_COLOR_TRIPLE_BACK_SHIFT;
+}
+
+static inline constexpr void vte_color_triple_set_deco(vte_color_triple_t* ct,
+                                                       uint32_t deco)
+{
+        *ct = (*ct & ~VTE_COLOR_TRIPLE_DECO_MASK) | (uint64_t(deco)) << VTE_COLOR_TRIPLE_DECO_SHIFT;
+}
+
+static inline constexpr uint32_t vte_color_triple_get_fore(vte_color_triple_t ct)
+{
+        return uint32_t((ct >> VTE_COLOR_TRIPLE_FORE_SHIFT) & VTE_COLOR_TRIPLE_RGB_MASK(8, 8, 8));
+}
+
+static inline constexpr uint32_t vte_color_triple_get_back(vte_color_triple_t ct)
+{
+        return uint32_t((ct >> VTE_COLOR_TRIPLE_BACK_SHIFT) & VTE_COLOR_TRIPLE_RGB_MASK(8, 8, 8));
+}
+
+static inline constexpr uint32_t vte_color_triple_get_deco(vte_color_triple_t ct)
+{
+        return uint32_t((ct >> VTE_COLOR_TRIPLE_DECO_SHIFT) & VTE_COLOR_TRIPLE_RGB_MASK(4, 5, 4));
+}
+
+static inline constexpr void vte_color_triple_get(vte_color_triple_t ct,
+                                                  uint32_t* fore,
+                                                  uint32_t* back,
+                                                  uint32_t* deco)
+{
+        *fore = vte_color_triple_get_fore(ct);
+        *back = vte_color_triple_get_back(ct);
+        *deco = vte_color_triple_get_deco(ct);
+}
diff --git a/src/vte.cc b/src/vte.cc
index 5261eef..4d3cdda 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -232,13 +232,15 @@ VteTerminalPrivate::ring_insert(vte::grid::row_t position,
 {
        VteRowData *row;
        VteRing *ring = m_screen->row_data;
+        bool const not_default_bg = (m_fill_defaults.attr.back() != VTE_DEFAULT_BG);
+
        while (G_UNLIKELY (_vte_ring_next (ring) < position)) {
                row = _vte_ring_append (ring);
-                if (m_fill_defaults.attr.back != VTE_DEFAULT_BG)
+                if (not_default_bg)
                         _vte_row_data_fill (row, &m_fill_defaults, m_column_count);
        }
        row = _vte_ring_insert (ring, position);
-        if (fill && m_fill_defaults.attr.back != VTE_DEFAULT_BG)
+        if (fill && not_default_bg)
                 _vte_row_data_fill (row, &m_fill_defaults, m_column_count);
        return row;
 }
@@ -2862,7 +2864,9 @@ VteTerminalPrivate::cursor_down(bool explicit_sequence)
                  * only fill the new row with the background color if scrolling
                  * happens due to an explicit escape sequence, not due to autowrapping.
                  * See bug 754596 for details. */
-                if (explicit_sequence && m_fill_defaults.attr.back != VTE_DEFAULT_BG) {
+                bool const not_default_bg = (m_fill_defaults.attr.back() != VTE_DEFAULT_BG);
+
+                if (explicit_sequence && not_default_bg) {
                        VteRowData *rowdata = ensure_row();
                         _vte_row_data_fill (rowdata, &m_fill_defaults, m_column_count);
                }
@@ -3013,10 +3017,9 @@ VteTerminalPrivate::insert_char(gunichar c,
        }
 
        _vte_debug_print(VTE_DEBUG_PARSE,
-                       "Inserting %ld '%c' (%d/%d) (%ld+%d, %ld), delta = %ld; ",
+                       "Inserting %ld '%c' (colors %" G_GUINT64_FORMAT ") (%ld+%d, %ld), delta = %ld; ",
                        (long)c, c < 256 ? c : ' ',
-                         (int)m_color_defaults.attr.fore,
-                         (int)m_color_defaults.attr.back,
+                         m_color_defaults.attr.colors(),
                         col, columns, (long)m_screen->cursor.row,
                        (long)m_screen->insert_delta);
 
@@ -3103,9 +3106,7 @@ VteTerminalPrivate::insert_char(gunichar c,
        }
 
         attr = m_defaults.attr;
-        attr.fore = m_color_defaults.attr.fore;
-        attr.back = m_color_defaults.attr.back;
-        attr.deco = m_color_defaults.attr.deco;
+        attr.copy_colors(m_color_defaults.attr);
        attr.columns = columns;
 
        {
@@ -5954,12 +5955,15 @@ VteTerminalPrivate::widget_clipboard_requested(GtkClipboard *target_clipboard,
 }
 
 /* Convert the internal color code (either index or RGB) into RGB. */
+template <unsigned int redbits,
+          unsigned int greenbits,
+          unsigned int bluebits>
 void
 VteTerminalPrivate::rgb_from_index(guint index,
                                    vte::color::rgb& color) const
 {
         bool dim = false;
-        if (!(index & VTE_RGB_COLOR) && (index & VTE_DIM_COLOR)) {
+        if (!(index & VTE_RGB_COLOR_MASK(redbits, greenbits, bluebits)) && (index & VTE_DIM_COLOR)) {
                 index &= ~VTE_DIM_COLOR;
                 dim = true;
         }
@@ -5974,10 +5978,10 @@ VteTerminalPrivate::rgb_from_index(guint index,
                         color.green = color.green * 2 / 3;
                         color.blue = color.blue * 2 / 3;
                 }
-       } else if (index & VTE_RGB_COLOR) {
-               color.red = ((index >> 16) & 0xFF) * 257;
-               color.green = ((index >> 8) & 0xFF) * 257;
-               color.blue = (index & 0xFF) * 257;
+       } else if (index & VTE_RGB_COLOR_MASK(redbits, greenbits, bluebits)) {
+                color.red   = VTE_RGB_COLOR_GET_COMPONENT(index, greenbits + bluebits, redbits) * 0x101U;
+                color.green = VTE_RGB_COLOR_GET_COMPONENT(index, bluebits, greenbits) * 0x101U;
+                color.blue  = VTE_RGB_COLOR_GET_COMPONENT(index, 0, bluebits) * 0x101U;
        } else {
                g_assert_not_reached();
        }
@@ -6033,8 +6037,11 @@ VteTerminalPrivate::get_text(vte::grid::row_t start_row,
                                 * the selection. */
                                if (!pcell->attr.fragment) {
                                        /* Store the attributes of this character. */
-                                       rgb_from_index(pcell->attr.fore, fore);
-                                       rgb_from_index(pcell->attr.back, back);
+                                        // FIXMEchpe shouldn't this use determine_colors?
+                                        uint32_t fg, bg, dc;
+                                        vte_color_triple_get(pcell->attr.colors(), &fg, &bg, &dc);
+                                        rgb_from_index<8, 8, 8>(fg, fore);
+                                        rgb_from_index<8, 8, 8>(bg, back);
                                        attr.fore.red = fore.red;
                                        attr.fore.green = fore.green;
                                        attr.fore.blue = fore.blue;
@@ -6169,14 +6176,12 @@ VteTerminalPrivate::get_selected_text(GArray *attributes)
  */
 // FIXMEchpe: make VteCellAttr a class with operator==
 static bool
-vte_terminal_cellattr_equal(VteCellAttr const *attr1,
+vte_terminal_cellattr_equal(VteCellAttr const* attr1,
                             VteCellAttr const* attr2)
 {
        return (attr1->bold          == attr2->bold      &&
                attr1->italic        == attr2->italic    &&
-               attr1->fore          == attr2->fore      &&
-               attr1->back          == attr2->back      &&
-                attr1->deco          == attr2->deco      &&
+                attr1->colors()      == attr2->colors()  &&
                attr1->underline     == attr2->underline &&
                attr1->strikethrough == attr2->strikethrough &&
                 attr1->overline      == attr2->overline  &&
@@ -6215,10 +6220,10 @@ VteTerminalPrivate::cellattr_to_html(VteCellAttr const* attr,
                 static const char styles[][7] = {"", "single", "double", "wavy"};
                 char *tag, *colorattr;
 
-                if (attr->deco != VTE_DEFAULT_FG) {
+                if (deco != VTE_DEFAULT_FG) {
                         vte::color::rgb color;
 
-                        rgb_from_index(attr->deco, color);
+                        rgb_from_index<4, 5, 4>(deco, color);
                         colorattr = g_strdup_printf(";text-decoration-color:#%02X%02X%02X",
                                                     color.red >> 8,
                                                     color.green >> 8,
@@ -6235,11 +6240,11 @@ VteTerminalPrivate::cellattr_to_html(VteCellAttr const* attr,
                 g_free(colorattr);
                 g_string_append(string, "</u>");
         }
-       if (attr->fore != VTE_DEFAULT_FG || attr->reverse) {
+       if (fore != VTE_DEFAULT_FG || attr->reverse) {
                vte::color::rgb color;
                 char *tag;
 
-                rgb_from_index(attr->fore, color);
+                rgb_from_index<8, 8, 8>(fore, color);
                tag = g_strdup_printf("<font color=\"#%02X%02X%02X\">",
                                       color.red >> 8,
                                       color.green >> 8,
@@ -6248,11 +6253,11 @@ VteTerminalPrivate::cellattr_to_html(VteCellAttr const* attr,
                g_free(tag);
                g_string_append(string, "</font>");
        }
-       if (attr->back != VTE_DEFAULT_BG || attr->reverse) {
+       if (back != VTE_DEFAULT_BG || attr->reverse) {
                vte::color::rgb color;
                 char *tag;
 
-                rgb_from_index(attr->back, color);
+                rgb_from_index<8, 8, 8>(back, color);
                tag = g_strdup_printf("<span style=\"background-color:#%02X%02X%02X\">",
                                       color.red >> 8,
                                       color.green >> 8,
@@ -8862,9 +8867,7 @@ VteTerminalPrivate::determine_colors(VteCellAttr const* attr,
         g_assert(attr);
 
        /* Start with cell colors */
-       fore = attr->fore;
-       back = attr->back;
-        deco = attr->deco;
+        vte_color_triple_get(attr->colors(), &fore, &back, &deco);
 
        /* Reverse-mode switches default fore and back colors */
         if (G_UNLIKELY (m_reverse_mode)) {
@@ -8886,7 +8889,7 @@ VteTerminalPrivate::determine_colors(VteCellAttr const* attr,
         /* Handle dim colors.  Only apply to palette colors, dimming direct RGB wouldn't make sense.
          * Apply to the foreground color only, but do this before handling reverse/highlight so that
          * those can be used to dim the background instead. */
-        if (attr->dim && !(fore & VTE_RGB_COLOR)) {
+        if (attr->dim && !(fore & VTE_RGB_COLOR_MASK(8, 8, 8))) {
                fore |= VTE_DIM_COLOR;
         }
 
@@ -8932,7 +8935,8 @@ VteTerminalPrivate::determine_colors(VteCellAttr const* attr,
          * Instead, draw_cells() is not called from draw_rows().
          * That is required for the foreground to be transparent if so is the background. */
        if (attr->invisible) {
-                fore = deco = back;
+                fore = back;
+                deco = VTE_DEFAULT_FG;
        }
 
        *pfore = fore;
@@ -8976,9 +8980,9 @@ invalidate_text_blink_cb(VteTerminalPrivate *that)
 void
 VteTerminalPrivate::draw_cells(struct _vte_draw_text_request *items,
                                gssize n,
-                               guint fore,
-                               guint back,
-                               guint deco,
+                               uint32_t fore,
+                               uint32_t back,
+                               uint32_t deco,
                                bool clear,
                                bool draw_default_bg,
                                bool bold,
@@ -9015,9 +9019,13 @@ VteTerminalPrivate::draw_cells(struct _vte_draw_text_request *items,
        }
 
        bold = bold && m_allow_bold;
-       rgb_from_index(fore, fg);
-       rgb_from_index(back, bg);
-        rgb_from_index(deco == VTE_DEFAULT_FG ? fore : deco, dc);
+        rgb_from_index<8, 8, 8>(fore, fg);
+        rgb_from_index<8, 8, 8>(back, bg);
+        // FIXMEchpe defer resolving deco color until we actually need to draw an underline?
+        if (deco == VTE_DEFAULT_FG)
+                dc = fg;
+        else
+                rgb_from_index<4, 5, 4>(deco, dc);
 
        i = 0;
        do {
@@ -9221,8 +9229,7 @@ VteTerminalPrivate::fudge_pango_colors(GSList *attributes,
                                (props[i].bg.red == 0) &&
                                (props[i].bg.green == 0) &&
                                (props[i].bg.blue == 0)) {
-                        cells[i].attr.fore = m_color_defaults.attr.fore;
-                        cells[i].attr.back = m_color_defaults.attr.back;
+                        cells[i].attr.copy_colors(m_color_defaults.attr);
                        cells[i].attr.reverse = TRUE;
                }
        }
@@ -9242,18 +9249,18 @@ VteTerminalPrivate::apply_pango_attr(PangoAttribute *attr,
        case PANGO_ATTR_FOREGROUND:
        case PANGO_ATTR_BACKGROUND:
                attrcolor = (PangoAttrColor*) attr;
-               ival = VTE_RGB_COLOR |
-                      ((attrcolor->color.red & 0xFF00) << 8) |
-                      ((attrcolor->color.green & 0xFF00)) |
-                      ((attrcolor->color.blue & 0xFF00) >> 8);
+                ival = VTE_RGB_COLOR(8, 8, 8,
+                                     ((attrcolor->color.red & 0xFF00) >> 8),
+                                     ((attrcolor->color.green & 0xFF00) >> 8),
+                                     ((attrcolor->color.blue & 0xFF00) >> 8));
                for (i = attr->start_index;
                     i < attr->end_index && i < n_cells;
                     i++) {
                        if (attr->klass->type == PANGO_ATTR_FOREGROUND) {
-                               cells[i].attr.fore = ival;
+                                cells[i].attr.set_fore(ival);
                        }
                        if (attr->klass->type == PANGO_ATTR_BACKGROUND) {
-                               cells[i].attr.back = ival;
+                                cells[i].attr.set_back(ival);
                        }
                }
                break;
@@ -9465,7 +9472,7 @@ VteTerminalPrivate::draw_rows(VteScreen *screen_,
                                        vte::color::rgb bg;
                                        gint bold_offset = _vte_draw_has_bold(m_draw,
                                                                                        VTE_DRAW_BOLD) ? 0 : 
bold;
-                                       rgb_from_index(back, bg);
+                                        rgb_from_index<8, 8, 8>(back, bg);
                                        _vte_draw_fill_rectangle (
                                                        m_draw,
                                                        x + i * column_width,
@@ -9492,7 +9499,7 @@ VteTerminalPrivate::draw_rows(VteScreen *screen_,
                                 determine_colors(nullptr, selected, &fore, &back, &deco);
                                if (back != VTE_DEFAULT_BG) {
                                        vte::color::rgb bg;
-                                       rgb_from_index(back, bg);
+                                        rgb_from_index<8, 8, 8>(back, bg);
                                        _vte_draw_fill_rectangle (m_draw,
                                                                  x + i *column_width,
                                                                  y,
@@ -9847,7 +9854,7 @@ VteTerminalPrivate::paint_cursor()
 
        selected = cell_is_selected(col, drow);
         determine_cursor_colors(cell, selected, &fore, &back, &deco);
-       rgb_from_index(back, bg);
+        rgb_from_index<8, 8, 8>(back, bg);
 
        x = item.x;
        y = item.y;
@@ -9959,7 +9966,6 @@ VteTerminalPrivate::paint_im_preedit_string()
        int col, columns;
        long width, height;
        int i, len;
-        guint fore, back, deco;
 
        if (!m_im_preedit)
                return;
@@ -10002,20 +10008,21 @@ VteTerminalPrivate::paint_im_preedit_string()
                                height,
                                 m_background_operator,
                                 get_color(VTE_DEFAULT_BG), m_background_alpha);
-                fore = m_color_defaults.attr.fore;
-                back = m_color_defaults.attr.back;
-                deco = m_color_defaults.attr.deco;
                draw_cells_with_attributes(
                                                        items, len,
                                                        m_im_preedit_attrs,
                                                        TRUE,
                                                        width, height);
                preedit_cursor = m_im_preedit_cursor;
+
                if (preedit_cursor >= 0 && preedit_cursor < len) {
+                        uint32_t fore, back, deco;
+                        vte_color_triple_get(m_color_defaults.attr.colors(), &fore, &back, &deco);
+
                        /* Cursored letter in reverse. */
                        draw_cells(
                                                &items[preedit_cursor], 1,
-                                                back, fore, deco,
+                                                fore, back, deco,
                                                 TRUE,  /* clear */
                                                 TRUE,  /* draw_default_bg */
                                                 FALSE, /* bold */
diff --git a/src/vtedefines.hh b/src/vtedefines.hh
index 89e6416..115081b 100644
--- a/src/vtedefines.hh
+++ b/src/vtedefines.hh
@@ -24,7 +24,7 @@
 #define VTE_COLUMNS                    80
 
 /*
- * Colors are encoded in 25 bits as follows:
+ * R8G8B8 colors are encoded in 25 bits as follows:
  *
  * 0 .. 255:
  *   Colors set by SGR 256-color extension (38/48;5;index).
@@ -45,14 +45,25 @@
  * VTE_RGB_COLOR (2^24) .. VTE_RGB_COLOR + 16Mi - 1 (2^25 - 1):
  *   Colors set by SGR truecolor extension (38/48;2;red;green;blue)
  *   These are direct RGB values.
+ *
+ * R4G5B4-bit-per-component colours are encoded the same, except for
+ * direct colours which are reduced to 13-bit colours and stored as
+ * direct values with bit 1 << 13 set.
  */
-#define VTE_LEGACY_COLORS_OFFSET       512
+
+#define VTE_LEGACY_COLORS_OFFSET       (1U << 9)
 #define VTE_LEGACY_COLOR_SET_SIZE      8
 #define VTE_LEGACY_FULL_COLOR_SET_SIZE 16
 #define VTE_COLOR_PLAIN_OFFSET         0
 #define VTE_COLOR_BRIGHT_OFFSET                8
-#define VTE_DIM_COLOR                  (1 << 10)
-#define VTE_RGB_COLOR                  (1 << 24)
+#define VTE_DIM_COLOR                   (1U << 10)
+#define VTE_RGB_COLOR_MASK(rb,gb,bb)    (1U << ((rb) + (gb) + (bb)))
+#define VTE_RGB_COLOR(bb,gb,rb,r,g,b)   (VTE_RGB_COLOR_MASK(rb,gb,bb) |   \
+                                         ((((r) >> (8 - (rb))) & ((1U << (rb)) -  1U)) << ((gb) + (bb))) | \
+                                         ((((g) >> (8 - (gb))) & ((1U << (gb)) -  1U)) << (bb)) | \
+                                         (((b) >> (8 - (bb))) & ((1U << (bb)) -  1U)))
+#define VTE_RGB_COLOR_GET_COMPONENT(packed,shift,bits) \
+        ((((packed) >> (shift)) & ((1U << (bits)) - 1U)) << (8 - bits) | ((1U << (8 - bits)) >> 1))
 
 #define VTE_DEFAULT_FG                 256
 #define VTE_DEFAULT_BG                 257
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index 5d8731e..41c1824 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -843,9 +843,9 @@ public:
         void paint_im_preedit_string();
         void draw_cells(struct _vte_draw_text_request *items,
                         gssize n,
-                        guint fore,
-                        guint back,
-                        guint deco,
+                        uint32_t fore,
+                        uint32_t back,
+                        uint32_t deco,
                         bool clear,
                         bool draw_default_bg,
                         bool bold,
@@ -993,6 +993,7 @@ public:
 
         GString* get_selected_text(GArray* attributes = nullptr);
 
+        template<unsigned int redbits, unsigned int greenbits, unsigned int bluebits>
         inline void rgb_from_index(guint index,
                                    vte::color::rgb& color) const;
         inline void determine_colors(VteCellAttr const* attr,
@@ -1332,9 +1333,12 @@ public:
         inline void move_cursor_down(vte::grid::row_t rows);
         inline void erase_characters(long count);
         inline void insert_blank_character();
+
+        template<unsigned int redbits, unsigned int greenbits, unsigned int bluebits>
         inline int32_t parse_sgr_38_48_parameters(vte::parser::Params const& params,
                                                   unsigned int *index,
                                                   bool might_contain_color_space_id);
+
         inline void move_cursor_backward(vte::grid::column_t columns);
         inline void move_cursor_forward(vte::grid::column_t columns);
         inline void move_cursor_tab();
diff --git a/src/vterowdata.h b/src/vterowdata.h
index da474fb..d600ba9 100644
--- a/src/vterowdata.h
+++ b/src/vterowdata.h
@@ -21,11 +21,14 @@
 #ifndef vterowdata_h_included
 #define vterowdata_h_included
 
+#include <cstdint>
+
 #include <string.h>
 
 #include "vteunistr.h"
 #include "vtemacros.h"
 #include "vtedefines.hh"
+#include "color-triple.hh"
 
 G_BEGIN_DECLS
 
@@ -42,38 +45,57 @@ G_BEGIN_DECLS
  * Also don't forget to update basic_cell below!
  */
 
-typedef struct _VteCellAttr {
-       guint64 fragment: 1;    /* A continuation cell. */
-       guint64 columns: VTE_TAB_WIDTH_BITS;    /* Number of visible columns
-                                                  (as determined by g_unicode_iswide(c)).
-                                                  Also abused for tabs; bug 353610
-                                                  */
-       guint64 bold: 1;
-       guint64 italic: 1;
-       guint64 fore: 25;       /* Index into color palette, or direct RGB, */
-       /* 4-byte boundary */
-       guint64 back: 25;       /* see vtedefines.hh */
-
-        guint64 underline: 2;   /* 0: none, 1: single, 2: double, 3: curly */
-       guint64 strikethrough: 1;
-
-       guint64 reverse: 1;
-       guint64 blink: 1;
-       guint64 dim: 1;         /* also known as faint, half intensity etc. */
-
-       guint64 invisible: 1;
-        /* 8-byte boundary */
-        guint32 deco: 25;       /* decoration color (currently for underline) */
-        guint32 overline: 1;
-        guint32 padding_unused: 6;
-        /* 12-byte boundary */
-        guint32 hyperlink_idx;  /* a unique hyperlink index at a time for the ring's cells,
+typedef struct _VTE_GNUC_PACKED VteCellAttr {
+        uint32_t fragment : 1;                 /* A continuation cell. */
+        uint32_t columns : VTE_TAB_WIDTH_BITS; /* Number of visible columns
+                                                * (as determined by g_unicode_iswide(c)).
+                                                * Also abused for tabs; bug 353610
+                                                */
+        uint32_t bold : 1;
+        uint32_t italic : 1;
+        uint32_t underline : 2;                /* 0: none, 1: single, 2: double, 3: curly */
+        uint32_t strikethrough : 1;
+        uint32_t reverse : 1;
+        uint32_t blink : 1;
+        uint32_t dim : 1;                      /* also known as faint, half intensity etc. */
+        uint32_t invisible : 1;
+        uint32_t overline : 1;
+        uint32_t padding_unused : 17;
+
+       /* 4-byte boundary (8-byte boundary in VteCell) */
+        uint64_t m_colors;                     /* fore, back and deco (underline) colour */
+
+        /* 12-byte boundary (16-byte boundary in VteCell) */
+        uint32_t hyperlink_idx; /* a unique hyperlink index at a time for the ring's cells,
                                    0 means not a hyperlink, VTE_HYPERLINK_IDX_TARGET_IN_STREAM
                                    means the target is irrelevant/unknown at the moment.
                                    If bitpacking, choose a size big enough to hold a different idx
                                    for every cell in the ring but not yet in the stream
                                    (currently the height rounded up to the next power of two, times width)
                                    for supported VTE sizes, and update VTE_HYPERLINK_IDX_TARGET_IN_STREAM. */
+
+        inline constexpr uint64_t colors() const { return m_colors; }
+
+        inline constexpr void copy_colors(VteCellAttr const& other)
+        {
+                m_colors = vte_color_triple_copy(other.colors());
+        }
+
+#define CELL_ATTR_COLOR(name) \
+        inline constexpr void set_##name(uint32_t value) \
+        { \
+                vte_color_triple_set_##name(&m_colors, value); \
+        } \
+        \
+        inline constexpr uint32_t name() const \
+        { \
+                return vte_color_triple_get_##name(m_colors); \
+        }
+
+        CELL_ATTR_COLOR(fore)
+        CELL_ATTR_COLOR(back)
+        CELL_ATTR_COLOR(deco)
+#undef CELL_ATTR_COLOR
 } VteCellAttr;
 G_STATIC_ASSERT (sizeof (VteCellAttr) == 16);
 G_STATIC_ASSERT (offsetof (VteCellAttr, hyperlink_idx) == VTE_CELL_ATTR_COMMON_BYTES);
@@ -86,13 +108,13 @@ G_STATIC_ASSERT (offsetof (VteCellAttr, hyperlink_idx) == VTE_CELL_ATTR_COMMON_B
  */
 
 typedef struct _VTE_GNUC_PACKED _VteStreamCellAttr {
-        guint64 fragment: 1;
-        guint64 columns: VTE_TAB_WIDTH_BITS;
-        guint64 remaining_main_attributes_1: 59;  /* All the non-hyperlink related attributes from 
VteCellAttr, part 1.
+        uint32_t fragment : 1;
+        uint32_t columns : VTE_TAB_WIDTH_BITS;
+        uint32_t remaining_main_attributes_1 : 27; /* All the non-hyperlink related attributes from 
VteCellAttr, part 1.
                                                      We don't individually access them in the stream, so 
there's
                                                      no point in repeating each field separately. */
-        /* 8-byte boundary */
-        guint32 remaining_main_attributes_2;      /* Non-hyperlink related attributes, part 2. */
+        /* 4-byte boundary */
+        uint64_t colors;
         /* 12-byte boundary */
         guint16 hyperlink_length;       /* make sure it fits VTE_HYPERLINK_TOTAL_LENGTH_MAX */
 } VteStreamCellAttr;
@@ -112,24 +134,19 @@ G_STATIC_ASSERT (sizeof (VteCell) == 20);
 static const VteCell basic_cell = {
        0,
        {
-               0, /* fragment */
-               1, /* columns */
-               0, /* bold */
-               0, /* italic */
-               VTE_DEFAULT_FG, /* fore */
-               VTE_DEFAULT_BG, /* back */
-
-               0, /* underline */
-               0, /* strikethrough */
-
-               0, /* reverse */
-               0, /* blink */
-               0, /* half */
-
+                0, /* fragment */
+                1, /* columns */
+                0, /* bold */
+                0, /* italic */
+                0, /* underline */
+                0, /* strikethrough */
+                0, /* reverse */
+                0, /* blink */
+                0, /* dim */
                 0, /* invisible */
-                VTE_DEFAULT_FG, /* deco */
                 0, /* overline */
                 0, /* padding_unused */
+                VTE_COLOR_TRIPLE_INIT_DEFAULT, /* colors */
                 0, /* hyperlink_idx */
        }
 };
diff --git a/src/vteseq.cc b/src/vteseq.cc
index 197081e..3f25b1b 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -1018,6 +1018,8 @@ VteTerminalPrivate::clear_below_current()
                        _vte_row_data_shrink (rowdata, 0);
        }
        /* Now fill the cleared areas. */
+        bool const not_default_bg = (m_fill_defaults.attr.back() != VTE_DEFAULT_BG);
+
         for (i = m_screen->cursor.row;
             i < m_screen->insert_delta + m_row_count;
             i++) {
@@ -1029,7 +1031,7 @@ VteTerminalPrivate::clear_below_current()
                        rowdata = ring_append(false);
                }
                /* Pad out the row. */
-                if (m_fill_defaults.attr.back != VTE_DEFAULT_BG) {
+                if (not_default_bg) {
                         _vte_row_data_fill(rowdata, &m_fill_defaults, m_column_count);
                }
                rowdata->attr.soft_wrapped = 0;
@@ -1066,7 +1068,9 @@ VteTerminalPrivate::clear_to_eol()
                /* We've modified the display.  Make a note of it. */
                m_text_deleted_flag = TRUE;
        }
-        if (m_fill_defaults.attr.back != VTE_DEFAULT_BG) {
+        bool const not_default_bg = (m_fill_defaults.attr.back() != VTE_DEFAULT_BG);
+
+        if (not_default_bg) {
                /* Add enough cells to fill out the row. */
                 _vte_row_data_fill(rowdata, &m_fill_defaults, m_column_count);
        }
@@ -1283,7 +1287,9 @@ VteTerminalPrivate::delete_character()
                         /* Clean up Tab/CJK fragments. */
                         cleanup_fragments(col, col + 1);
                        _vte_row_data_remove (rowdata, col);
-                        if (m_fill_defaults.attr.back != VTE_DEFAULT_BG) {
+                        bool const not_default_bg = (m_fill_defaults.attr.back() != VTE_DEFAULT_BG);
+
+                        if (not_default_bg) {
                                 _vte_row_data_fill(rowdata, &m_fill_defaults, m_column_count);
                                 len = m_column_count;
                        }
@@ -1804,6 +1810,8 @@ VteTerminalPrivate::seq_vertical_tab(vte::parser::Params const& params)
  * seq_character_attributes() to understand the different accepted formats.
  * Returns the color index, or -1 on error.
  * Increments @index to point to the last consumed parameter (not beyond). */
+
+template<unsigned int redbits, unsigned int greenbits, unsigned int bluebits>
 int32_t
 VteTerminalPrivate::parse_sgr_38_48_parameters(vte::parser::Params const& params,
                                                unsigned int *index,
@@ -1831,7 +1839,8 @@ VteTerminalPrivate::parse_sgr_38_48_parameters(vte::parser::Params const& params
                        if (G_UNLIKELY (param1 < 0 || param1 >= 256 || param2 < 0 || param2 >= 256 || param3 
< 0 || param3 >= 256))
                                return -1;
                        *index += 3;
-                       return VTE_RGB_COLOR | (param1 << 16) | (param2 << 8) | param3;
+
+                       return VTE_RGB_COLOR(redbits, greenbits, bluebits, param1, param2, param3);
                 }
                 case 5: {
                         long param1;
@@ -1872,21 +1881,25 @@ VteTerminalPrivate::seq_character_attributes(vte::parser::Params const& params)
                                 if (subparams.number_at(1, param1) && param1 >= 0 && param1 <= 3)
                                         m_defaults.attr.underline = param1;
                                 break;
-                        case 38:
-                        case 48:
-                        case 58:
-                        {
+                        case 38: {
                                 unsigned int index = 1;
-                                auto color = parse_sgr_38_48_parameters(subparams, &index, true);
-                                if (G_LIKELY (color != -1)) {
-                                        if (param0 == 38) {
-                                                m_defaults.attr.fore = color;
-                                        } else if (param0 == 48) {
-                                                m_defaults.attr.back = color;
-                                        } else {
-                                                m_defaults.attr.deco = color;
-                                        }
-                                }
+                                auto color = parse_sgr_38_48_parameters<8, 8, 8>(subparams, &index, true);
+                                if (G_LIKELY (color != -1))
+                                        m_defaults.attr.set_fore(color);
+                                break;
+                        }
+                        case 48: {
+                                unsigned int index = 1;
+                                auto color = parse_sgr_38_48_parameters<8, 8, 8>(subparams, &index, true);
+                                if (G_LIKELY (color != -1))
+                                        m_defaults.attr.set_back(color);
+                                break;
+                        }
+                        case 58: {
+                                unsigned int index = 1;
+                                auto color = parse_sgr_38_48_parameters<4, 5, 4>(subparams, &index, true);
+                                if (G_LIKELY (color != -1))
+                                        m_defaults.attr.set_deco(color);
                                 break;
                         }
                         }
@@ -1959,7 +1972,7 @@ VteTerminalPrivate::seq_character_attributes(vte::parser::Params const& params)
                case 35:
                case 36:
                case 37:
-                        m_defaults.attr.fore = VTE_LEGACY_COLORS_OFFSET + param - 30;
+                        m_defaults.attr.set_fore(VTE_LEGACY_COLORS_OFFSET + (param - 30));
                        break;
                case 38:
                case 48:
@@ -1978,22 +1991,31 @@ VteTerminalPrivate::seq_character_attributes(vte::parser::Params const& params)
                          * This branch here is reached when the separators are semicolons. */
                        if ((i + 1) < n_params) {
                                 ++i;
-                                auto color = parse_sgr_38_48_parameters(params, &i, false);
-                               if (G_LIKELY (color != -1)) {
-                                       if (param == 38) {
-                                                m_defaults.attr.fore = color;
-                                        } else if (param == 48) {
-                                                m_defaults.attr.back = color;
-                                        } else {
-                                                m_defaults.attr.deco = color;
-                                       }
+                                int32_t color;
+                                switch (param) {
+                                case 38:
+                                        color = parse_sgr_38_48_parameters<8 ,8 ,8>(params, &i, false);
+                                        if (G_LIKELY (color != -1))
+                                                m_defaults.attr.set_fore(color);
+                                        break;
+                                case 48:
+                                        color = parse_sgr_38_48_parameters<8, 8, 8>(params, &i, false);
+                                        if (G_LIKELY (color != -1))
+                                                m_defaults.attr.set_back(color);
+                                        break;
+                                case 58:
+                                        color = parse_sgr_38_48_parameters<4, 5, 4>(params, &i, false);
+                                        g_printerr("Parsed semicoloned deco colour: %x\n", color);
+                                        if (G_LIKELY (color != -1))
+                                                m_defaults.attr.set_deco(color);
+                                        break;
                                }
                        }
                        break;
                }
                case 39:
                        /* default foreground */
-                        m_defaults.attr.fore = VTE_DEFAULT_FG;
+                        m_defaults.attr.set_fore(VTE_DEFAULT_FG);
                        break;
                case 40:
                case 41:
@@ -2003,12 +2025,12 @@ VteTerminalPrivate::seq_character_attributes(vte::parser::Params const& params)
                case 45:
                case 46:
                case 47:
-                        m_defaults.attr.back = VTE_LEGACY_COLORS_OFFSET + param - 40;
+                        m_defaults.attr.set_back(VTE_LEGACY_COLORS_OFFSET + (param - 40));
                        break;
             /* case 48: was handled above at 38 to avoid code duplication */
                case 49:
                        /* default background */
-                        m_defaults.attr.back = VTE_DEFAULT_BG;
+                        m_defaults.attr.set_back(VTE_DEFAULT_BG);
                        break;
                 case 53:
                         m_defaults.attr.overline = 1;
@@ -2019,7 +2041,7 @@ VteTerminalPrivate::seq_character_attributes(vte::parser::Params const& params)
              /* case 58: was handled above at 38 to avoid code duplication */
                 case 59:
                         /* default decoration color, that is, same as the cell's foreground */
-                        m_defaults.attr.deco = VTE_DEFAULT_FG;
+                        m_defaults.attr.set_deco(VTE_DEFAULT_FG);
                         break;
                case 90:
                case 91:
@@ -2029,7 +2051,8 @@ VteTerminalPrivate::seq_character_attributes(vte::parser::Params const& params)
                case 95:
                case 96:
                case 97:
-                        m_defaults.attr.fore = VTE_LEGACY_COLORS_OFFSET + param - 90 + 
VTE_COLOR_BRIGHT_OFFSET;
+                        m_defaults.attr.set_fore(VTE_LEGACY_COLORS_OFFSET + (param - 90) +
+                                                 VTE_COLOR_BRIGHT_OFFSET);
                        break;
                case 100:
                case 101:
@@ -2039,7 +2062,8 @@ VteTerminalPrivate::seq_character_attributes(vte::parser::Params const& params)
                case 105:
                case 106:
                case 107:
-                        m_defaults.attr.back = VTE_LEGACY_COLORS_OFFSET + param - 100 + 
VTE_COLOR_BRIGHT_OFFSET;
+                        m_defaults.attr.set_back(VTE_LEGACY_COLORS_OFFSET + (param - 100) +
+                                                 VTE_COLOR_BRIGHT_OFFSET);
                        break;
                }
        }
@@ -2048,12 +2072,8 @@ VteTerminalPrivate::seq_character_attributes(vte::parser::Params const& params)
                 reset_default_attributes(false);
        }
        /* Save the new colors. */
-        m_color_defaults.attr.fore = m_defaults.attr.fore;
-        m_color_defaults.attr.back = m_defaults.attr.back;
-        m_color_defaults.attr.deco = m_defaults.attr.deco;
-        m_fill_defaults.attr.fore = m_defaults.attr.fore;
-        m_fill_defaults.attr.back = m_defaults.attr.back;
-        m_fill_defaults.attr.deco = m_defaults.attr.deco;
+        m_color_defaults.attr.copy_colors(m_defaults.attr);
+        m_fill_defaults.attr.copy_colors(m_defaults.attr);
 }
 
 /* Move the cursor to the given column in the top row, 1-based. */



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