[vte/wip/egmont/bidi: 91/104] etap3
- From: Egmont Koblinger <egmontkob src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte/wip/egmont/bidi: 91/104] etap3
- Date: Wed, 29 May 2019 08:41:21 +0000 (UTC)
commit 4fe7c0c84a79bf8c407cf856df55378d5046b7ac
Author: Egmont Koblinger <egmont gmail com>
Date: Fri May 24 01:35:14 2019 +0200
etap3
src/bidi.cc | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++---------
src/bidi.hh | 7 ++--
2 files changed, 108 insertions(+), 21 deletions(-)
---
diff --git a/src/bidi.cc b/src/bidi.cc
index c7411a2f..4514ac8b 100644
--- a/src/bidi.cc
+++ b/src/bidi.cc
@@ -42,6 +42,7 @@ using namespace vte::base;
BidiRow::BidiRow()
{
+ /* The value of 0 is a valid representation of the trivial LTR mapping. */
m_width = 0;
/* These will be initialized / allocated on demand, when some RTL is encountered. */
@@ -144,7 +145,7 @@ bool BidiRow::base_is_rtl() const
return m_base_rtl;
}
-/* Whether the paragraph contains a foreign directionality character.
+/* Whether the implicit paragraph contains a foreign directionality character.
* This is used in the cursor, showing the character's directionality. */
bool BidiRow::has_foreign() const
{
@@ -159,8 +160,33 @@ BidiRunner::BidiRunner(RingView *ringview)
BidiRunner::~BidiRunner() {}
-/* Set up the mapping according to explicit mode for a given line. */
-void BidiRunner::explicit_line(vte::grid::row_t row, bool rtl)
+/* Returns whether there's an Arabic character in the row so that shaping might be required. */
+bool BidiRunner::needs_shaping(vte::grid::row_t row)
+{
+ const gulong MIN_SHAPING = 0x0600;
+ const gulong MAX_SHAPING = 0x06FF;
+
+ const VteRowData *row_data = m_ringview->get_row(row);
+
+ for (int i = 0; i < row_data->len; i++) {
+ const VteCell *cell = _vte_row_data_get(row_data, i);
+ if (cell != nullptr) {
+ gunichar c = _vte_unistr_get_base(cell->c);
+ if (G_UNLIKELY (c >= MIN_SHAPING && c <= MAX_SHAPING))
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Set up the mapping according to explicit mode for a given line.
+ *
+ * If @shape then perform Arabic shaping on the visual string, independently
+ * from the paragraph direction (the @rtl parameter). This is done using
+ * presentation form characters, until we have something better (e.g. HarfBuzz)
+ * in place.
+ */
+void BidiRunner::explicit_line(vte::grid::row_t row, bool rtl, bool shape)
{
int i;
@@ -170,27 +196,87 @@ void BidiRunner::explicit_line(vte::grid::row_t row, bool rtl)
bidirow->m_base_rtl = rtl;
bidirow->m_has_foreign = false;
- if (G_UNLIKELY (rtl)) {
- auto width = m_ringview->get_width();
+ auto width = m_ringview->get_width();
+
+ if (G_LIKELY (!rtl)) {
+ if (!shape || !needs_shaping(row)) {
+ /* Shortcut notation: a width of 0 means the trivial LTR mapping. */
+ bidirow->set_width(0);
+ return;
+ }
+ bidirow->set_width(width);
+ for (i = 0; i < width; i++) {
+ bidirow->m_log2vis[i] = bidirow->m_vis2log[i] = i;
+ bidirow->m_vis_rtl[i] = false;
+ bidirow->m_vis_shaped_char[i] = 0;
+ }
+ } else {
bidirow->set_width(width);
for (i = 0; i < width; i++) {
bidirow->m_log2vis[i] = bidirow->m_vis2log[i] = width - 1 - i;
bidirow->m_vis_rtl[i] = true;
bidirow->m_vis_shaped_char[i] = 0;
}
- } else {
- /* Shortcut: bidirow->m_width == 0 might denote a fully LTR line,
- * m_width_alloc might even be 0 along with log2vis and friends being nullptr in this case.
*/
- bidirow->set_width(0);
+ if (!shape || !needs_shaping(row)) {
+ return;
+ }
+ }
+
+ /* Perform Arabic shaping on an explicit line (which could be explicit LTR or explicit RTL).
+ * Don't do shaping across (soft) linebreaks (I'm unsure about it).
+ * The FriBiDi API doesn't have such a method, so we need to extract Arabic words ourselves,
+ * by walking in the visual order from right to left. */
+
+ // FIXME this is going to be freaking cumbersome.
+
+#if 0 // bleeeeh
+ GArray *fribidi_chars_array = nullptr;
+
+ VteCell *cell;
+ gunichar c;
+ gunichar base;
+ i = width - 1;
+ while (i >= 0) {
+ cell = _vte_row_data_get(row_data, bidirow->m_vis2log[i]);
+ c = cell->c;
+ base = _vte_unistr_get_base(c);
+ if (base < MIN_SHAPING || base > MAX_SHAPING) {
+ i--;
+ continue;
+ }
+
+ /* Found an Arabic character. Keep walking to the left, extracting the word. */
+ fribidi_chars_array = g_array_new (FALSE, FALSE, sizeof (FriBidiChar));
+ j = i;
+ do {
+ auto prev_len = fribidi_chars_array->len;
+ _vte_unistr_append_to_gunichars (cell->c, fribidi_chars_array);
+ g_assert_cmpint (fribidi_chars_array->len, >, prev_len);
+
+ j--;
+ if (j >= 0) {
+ cell = _vte_row_data_get(row_data, bidirow->m_vis2log[j]);
+ c = cell->c;
+ base = _vte_unistr_get_base(c);
+ } else {
+ base = 0;
+ }
+ } while (base >= MIN_SHAPING && base <= MAX_SHAPING);
+
+
+
}
+#endif
+
+
}
/* Set up the mapping according to explicit mode, for all the lines
* of a paragraph between the given lines. */
-void BidiRunner::explicit_paragraph(vte::grid::row_t start, vte::grid::row_t end, bool rtl)
+void BidiRunner::explicit_paragraph(vte::grid::row_t start, vte::grid::row_t end, bool rtl, bool shape)
{
for (; start < end; start++) {
- explicit_line(start, rtl);
+ explicit_line(start, rtl, shape);
}
}
@@ -199,7 +285,7 @@ void BidiRunner::paragraph(vte::grid::row_t start, vte::grid::row_t end)
{
#ifndef WITH_FRIBIDI
const VteRowData *row_data = m_ringview->get_row(start);
- explicit_paragraph(start, end, row_data->attr.bidi_flags & VTE_BIDI_RTL);
+ explicit_paragraph(start, end, row_data->attr.bidi_flags & VTE_BIDI_RTL, false);
#else
const VteCell *cell;
const VteRowData *row_data;
@@ -222,7 +308,7 @@ void BidiRunner::paragraph(vte::grid::row_t start, vte::grid::row_t end)
row_data = m_ringview->get_row(start);
if (!(row_data->attr.bidi_flags & VTE_BIDI_IMPLICIT) ||
end - start > VTE_RINGVIEW_PARAGRAPH_LENGTH_MAX) {
- explicit_paragraph(start, end, row_data->attr.bidi_flags & VTE_BIDI_RTL);
+ explicit_paragraph(start, end, row_data->attr.bidi_flags & VTE_BIDI_RTL, true);
return;
}
@@ -366,7 +452,7 @@ void BidiRunner::paragraph(vte::grid::row_t start, vte::grid::row_t end)
g_array_free (fribidi_chars_array, TRUE);
g_array_free (fribidi_map_array, TRUE);
g_array_free (fribidi_to_term_array, TRUE);
- explicit_paragraph (start, end, rtl);
+ explicit_paragraph (start, end, rtl, true);
return;
}
#endif
@@ -396,7 +482,7 @@ void BidiRunner::paragraph(vte::grid::row_t start, vte::grid::row_t end)
g_array_free (fribidi_chars_array, TRUE);
g_array_free (fribidi_map_array, TRUE);
g_array_free (fribidi_to_term_array, TRUE);
- explicit_paragraph (start, end, rtl);
+ explicit_paragraph (start, end, rtl, false);
return;
}
@@ -429,7 +515,7 @@ void BidiRunner::paragraph(vte::grid::row_t start, vte::grid::row_t end)
g_array_free (fribidi_chars_array, TRUE);
g_array_free (fribidi_map_array, TRUE);
g_array_free (fribidi_to_term_array, TRUE);
- explicit_paragraph (start, end, false);
+ explicit_paragraph (start, end, false, false);
return;
}
@@ -456,14 +542,14 @@ void BidiRunner::paragraph(vte::grid::row_t start, vte::grid::row_t end)
if (level == 0) {
/* error, what should we do? */
- explicit_line (row, rtl);
+ explicit_line (row, rtl, true);
bidirow->m_has_foreign = true;
continue;
}
if (!rtl && level == 1) {
/* Fast shortcut for LTR-only lines. */
- explicit_line (row, false);
+ explicit_line (row, false, false);
bidirow->m_has_foreign = true;
continue;
}
diff --git a/src/bidi.hh b/src/bidi.hh
index a257f7d9..b0c277a7 100644
--- a/src/bidi.hh
+++ b/src/bidi.hh
@@ -73,7 +73,7 @@ private:
};
-/* BidiRunner is not a real class, rather the collection of methods that run the BiDi algorithm. */
+/* BidiRunner is not a "real" class, rather the collection of methods that run the BiDi algorithm. */
class BidiRunner {
public:
BidiRunner(RingView *ringview);
@@ -92,8 +92,9 @@ public:
private:
RingView *m_ringview;
- void explicit_line(vte::grid::row_t row, bool rtl);
- void explicit_paragraph(vte::grid::row_t start, vte::grid::row_t end, bool rtl);
+ bool needs_shaping(vte::grid::row_t row);
+ void explicit_line(vte::grid::row_t row, bool rtl, bool shape);
+ void explicit_paragraph(vte::grid::row_t start, vte::grid::row_t end, bool rtl, bool shape);
};
}; /* namespace base */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]