[vte/wip/egmont/bidi: 1/2] mirrors chars with combining accents



commit 6066d69088c2c6c1c786f512731e26959a011ead
Author: Egmont Koblinger <egmont gmail com>
Date:   Sun Nov 11 13:21:29 2018 +0100

    mirrors chars with combining accents

 src/bidi.cc      | 44 +++++++++++++++++++++++++++++++++-----------
 src/bidi.hh      |  3 ++-
 src/vteunistr.cc | 14 ++++++++++++++
 src/vteunistr.h  | 10 ++++++++++
 4 files changed, 59 insertions(+), 12 deletions(-)
---
diff --git a/src/bidi.cc b/src/bidi.cc
index 6db2b92a..309295a9 100644
--- a/src/bidi.cc
+++ b/src/bidi.cc
@@ -509,7 +509,13 @@ next_line:
 }
 
 
-gboolean vte_bidi_get_mirror_char (gunichar ch, gboolean mirror_box_drawing, gunichar *mirrored_ch)
+/* Find the mirrored counterpart of a codepoint, just like
+ * fribidi_get_mirror_char() or g_unichar_get_mirror_char() does.
+ * Two additions:
+ * - works with vteunistr, that is, preserves combining accents;
+ * - optionally mirrors box drawing characters.
+ */
+gboolean vte_bidi_get_mirror_char (vteunistr unistr, gboolean mirror_box_drawing, vteunistr *out)
 {
         static const unsigned char mirrored_2500[0x80] = {
                 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x11, 0x12, 
0x13,
@@ -521,18 +527,34 @@ gboolean vte_bidi_get_mirror_char (gunichar ch, gboolean mirror_box_drawing, gun
                 0x63, 0x5e, 0x5f, 0x60, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6e, 0x6d, 
0x70,
                 0x6f, 0x72, 0x71, 0x73, 0x76, 0x75, 0x74, 0x77, 0x7a, 0x79, 0x78, 0x7b, 0x7e, 0x7d, 0x7c, 
0x7f };
 
-        if (G_UNLIKELY (mirror_box_drawing && ch >= 0x2500 && ch < 0x2580)) {
-                gunichar mir = 0x2500 + mirrored_2500[ch - 0x2500];
-                if (mirrored_ch)
-                        *mirrored_ch = mir;
-                return mir == ch;
-        }
+        GArray *s = g_array_new (FALSE, FALSE, sizeof (gunichar));
+        _vte_unistr_append_to_gunichars (unistr, s);
+        g_assert_cmpint(s->len, >=, 1);
+
+        gunichar base_ch = g_array_index (s, gunichar, 0);
+        gunichar base_ch_mirrored = base_ch;
 
+        if (G_UNLIKELY (base_ch >= 0x2500 && base_ch < 0x2580)) {
+                if (G_UNLIKELY (mirror_box_drawing))
+                        base_ch_mirrored = 0x2500 + mirrored_2500[base_ch - 0x2500];
+        } else {
 #ifdef WITH_FRIBIDI
-        /* Prefer the FriBidi variant as that's more likely to be in sync with the rest of our BiDi stuff. */
-        return fribidi_get_mirror_char (ch, mirrored_ch);
+                /* Prefer the FriBidi variant as that's more likely to be in sync with the rest of our BiDi 
stuff. */
+                fribidi_get_mirror_char (base_ch, &base_ch_mirrored);
 #else
-        /* Fall back to glib, so that we still get mirrored characters in explicit RTL mode. */
-        return g_unichar_get_mirror_char (ch, mirrored_ch);
+                /* Fall back to glib, so that we still get mirrored characters in explicit RTL mode without 
BiDi support. */
+                g_unichar_get_mirror_char (base_ch, &base_ch_mirrored);
 #endif
+        }
+
+        vteunistr unistr_mirrored = base_ch_mirrored;
+        for (glong i = 1; i < s->len; i++)
+                unistr_mirrored = _vte_unistr_append_unichar(unistr_mirrored, g_array_index (s, gunichar, 
i));
+
+        g_array_free (s, TRUE);
+
+        if (out)
+                *out = unistr_mirrored;
+
+        return unistr_mirrored == unistr;
 }
diff --git a/src/bidi.hh b/src/bidi.hh
index 7044af74..b1a8da7e 100644
--- a/src/bidi.hh
+++ b/src/bidi.hh
@@ -23,6 +23,7 @@
 #include "ring.hh"
 #include "vterowdata.hh"
 #include "vtetypes.hh"
+#include "vteunistr.h"
 
 namespace vte {
 
@@ -113,6 +114,6 @@ private:
 
 G_BEGIN_DECLS
 
-gboolean vte_bidi_get_mirror_char (gunichar ch, gboolean mirror_box_drawing, gunichar *mirrored_ch);
+gboolean vte_bidi_get_mirror_char (vteunistr unistr, gboolean mirror_box_drawing, vteunistr 
*unistr_mirrored);
 
 G_END_DECLS
diff --git a/src/vteunistr.cc b/src/vteunistr.cc
index 2e412e3e..916308e2 100644
--- a/src/vteunistr.cc
+++ b/src/vteunistr.cc
@@ -162,6 +162,20 @@ _vte_unistr_append_to_string (vteunistr s, GString *gs)
        g_string_append_unichar (gs, (gunichar) s);
 }
 
+void
+_vte_unistr_append_to_gunichars (vteunistr s, GArray *a)
+{
+        g_return_if_fail (s < unistr_next);
+        if (G_UNLIKELY (s >= VTE_UNISTR_START)) {
+                struct VteUnistrDecomp *decomp;
+                decomp = &DECOMP_FROM_UNISTR (s);
+                _vte_unistr_append_to_gunichars (decomp->prefix, a);
+                s = decomp->suffix;
+        }
+        gunichar val = (gunichar) s;
+        g_array_append_val (a, val);
+}
+
 int
 _vte_unistr_strlen (vteunistr s)
 {
diff --git a/src/vteunistr.h b/src/vteunistr.h
index 04aa9fb6..fff8fffa 100644
--- a/src/vteunistr.h
+++ b/src/vteunistr.h
@@ -71,6 +71,16 @@ _vte_unistr_get_base (vteunistr s);
 void
 _vte_unistr_append_to_string (vteunistr s, GString *gs);
 
+/**
+ * _vte_unistr_append_to_gunichars:
+ * @s: a #vteunistr
+ * @a: a #GArray of #gunichar items to append @s to
+ *
+ * Appends @s to @a.
+ **/
+void
+_vte_unistr_append_to_gunichars (vteunistr s, GArray *a);
+
 /**
  * _vte_unistr_strlen:
  * @s: a #vteunistr


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