[vte/wip/egmont/bidi: 71/78] mirrors chars with combining accents
- From: Egmont Koblinger <egmontkob src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte/wip/egmont/bidi: 71/78] mirrors chars with combining accents
- Date: Fri, 7 Dec 2018 12:39:07 +0000 (UTC)
commit d53edc47f4f6510ff97437df9ecb00132f41491d
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 2e412e3e..143cdd8f 100644
--- a/src/vteunistr.cc
+++ b/src/vteunistr.cc
@@ -149,6 +149,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 04aa9fb6..861d8b66 100644
--- a/src/vteunistr.h
+++ b/src/vteunistr.h
@@ -60,6 +60,19 @@ _vte_unistr_append_unichar (vteunistr s, gunichar c);
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
@@ -71,6 +84,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]