[vte/wip/egmont/bidi: 76/91] mirrors chars with combining accents
- From: Egmont Koblinger <egmontkob src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte/wip/egmont/bidi: 76/91] mirrors chars with combining accents
- Date: Tue, 5 Feb 2019 19:22:24 +0000 (UTC)
commit cbb51e91c9644d22e20fd3a3325e9b1b98d3ff05
Author: Egmont Koblinger <egmont gmail com>
Date: Sun Nov 11 13:21:29 2018 +0100
mirrors chars with combining accents
src/bidi.cc | 35 ++++++++++++++++++++++++-----------
src/bidi.hh | 3 ++-
src/vteunistr.cc | 33 +++++++++++++++++++++++++++++++++
src/vteunistr.h | 23 +++++++++++++++++++++++
4 files changed, 82 insertions(+), 12 deletions(-)
---
diff --git a/src/bidi.cc b/src/bidi.cc
index 6db2b92a..9646fd17 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,25 @@ 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;
- }
+ gunichar base_ch = _vte_unistr_get_base (unistr);
+ 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 = _vte_unistr_replace_base (unistr, base_ch_mirrored);
+
+ 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 69c47fe0..d60d2d01 100644
--- a/src/vteunistr.cc
+++ b/src/vteunistr.cc
@@ -162,6 +162,39 @@ _vte_unistr_get_base (vteunistr s)
return (gunichar) s;
}
+static void
+unistr_append_to_gunichars (vteunistr s, GArray *a)
+{
+ if (G_UNLIKELY (s >= VTE_UNISTR_START)) {
+ struct VteUnistrDecomp *decomp;
+ decomp = &DECOMP_FROM_UNISTR (s);
+ unistr_append_to_gunichars (decomp->prefix, a);
+ s = decomp->suffix;
+ }
+ gunichar val = (gunichar) s;
+ g_array_append_val (a, val);
+}
+
+vteunistr
+_vte_unistr_replace_base (vteunistr s, gunichar c)
+{
+ g_return_val_if_fail (s < unistr_next, s);
+
+ if (G_LIKELY (_vte_unistr_get_base(s) == c))
+ return s;
+
+ GArray *a = g_array_new (FALSE, FALSE, sizeof (gunichar));
+ unistr_append_to_gunichars (s, a);
+ g_assert_cmpint(a->len, >=, 1);
+
+ s = c;
+ for (glong i = 1; i < a->len; i++)
+ s = _vte_unistr_append_unichar (s, g_array_index (a, gunichar, i));
+
+ g_array_free (a, TRUE);
+ return s;
+}
+
void
_vte_unistr_append_to_string (vteunistr s, GString *gs)
{
diff --git a/src/vteunistr.h b/src/vteunistr.h
index 9bde6b2c..84cb0562 100644
--- a/src/vteunistr.h
+++ b/src/vteunistr.h
@@ -73,6 +73,19 @@ _vte_unistr_append_unistr (vteunistr s, vteunistr t);
gunichar
_vte_unistr_get_base (vteunistr s);
+/**
+ * _vte_unistr_append_to_string:
+ * @s: a #vteunistr
+ * @c: Unicode character to replace the base character of @s.
+ *
+ * Creates a vteunistr value where the base character from @s is
+ * replaced by @c, while the combining characters from @s are carried over.
+ *
+ * Returns: the new #vteunistr value
+ */
+vteunistr
+_vte_unistr_replace_base (vteunistr s, gunichar c);
+
/**
* _vte_unistr_append_to_string:
* @s: a #vteunistr
@@ -84,6 +97,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]