Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Tucos/6afb844041ac2a823bdb to your computer and use it in GitHub Desktop.
Save Tucos/6afb844041ac2a823bdb to your computer and use it in GitHub Desktop.
0001-Perform-proper-reordering-and-shaping-of-glyphs.patch
From 9fdb5a85b250cc0bb80deb9f2783a16c9dcc7777 Mon Sep 17 00:00:00 2001
From: Bas Pape <baspape@gmail.com>
Date: Sun, 28 Dec 2014 13:30:43 +0100
Subject: [PATCH] Perform proper reordering and shaping of glyphs
All RTL languages require reordering of the characters before drawing
them, and various scripts require positional shaping (e.g. Arabic and
Mongolian) as well. FriBidi [1] implements the Unicode Bidirectional
Algorithm (UAX#9, [2]) and has a simple API (a single function call) to
do both reordering and reshaping.
The fribidi_log2vis function is marked as deprecated, but is unlikely to
be removed and is just a convenient function for one-line paragraphs [3].
[1] http://fribidi.org/
[2] http://www.unicode.org/reports/tr9/
[3] http://lists.freedesktop.org/archives/fribidi/2008-January/000515.html
---
configure.ac.in | 15 ++++++++++++
src/conky.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 87 insertions(+), 2 deletions(-)
diff --git a/configure.ac.in b/configure.ac.in
index 313c92e..12a0bcf 100644
--- a/configure.ac.in
+++ b/configure.ac.in
@@ -668,6 +668,19 @@ if test x$want_xft = "xyes"; then
fi
dnl
+dnl fribidi
+dnl
+AC_ARG_ENABLE([fribidi],
+ AC_HELP_STRING([--disable-fribidi], [Disable if you do not want to use FriBidi, used for reordering Unicode strings @<:default=yes@:>@]),
+ [want_fribidi="$enableval"], [want_fribidi=yes])
+if test x"$want_fribidi" = "xyes"; then
+ PKG_CHECK_MODULES([fribidi], [fribidi])
+ conky_CFLAGS="$conky_CFLAGS $fribidi_CFLAGS"
+ conky_LIBS="$conky_LIBS $fribidi_LIBS"
+ AC_DEFINE(HAVE_FRIBIDI, 1, [Define for FriBidi support])
+fi
+
+dnl
dnl NVIDIA libXNVCtrl support
dnl
@@ -1008,6 +1021,7 @@ $PACKAGE $VERSION configured successfully:
XDamage support: $want_xdamage
XDBE support: $want_double_buffer
Xft support: $want_xft
+ FriBidi support: $want_fribidi
ARGB support $want_argb
* Music detection:
@@ -1043,4 +1057,5 @@ dnl OpenMP: $want_openmp
Cairo: $want_lua_cairo
Imlib2: $want_lua_imlib2
+
EOF
diff --git a/src/conky.c b/src/conky.c
index 0a10562..3cb934e 100644
--- a/src/conky.c
+++ b/src/conky.c
@@ -73,6 +73,9 @@
#ifdef HAVE_CURL
#include <curl/curl.h>
#endif
+#ifdef HAVE_FRIBIDI
+#include <fribidi.h>
+#endif
/* local headers */
#include "core.h"
@@ -214,6 +217,9 @@ static void print_version(void)
# ifdef USE_ARGB
" * ARGB visual\n"
# endif /* USE_ARGB */
+# ifdef HAVE_FRIBIDI
+ " * FriBidi\n"
+# endif /* HAVE_FRIBIDI */
#endif /* X11 */
"\n Music detection:\n"
#ifdef AUDACIOUS
@@ -2795,16 +2801,80 @@ static inline void set_foreground_color(long c)
return;
}
-static void draw_string(const char *s)
+#if HAVE_FRIBIDI
+static char *reorder_unicode_string(const char * const src)
+{
+ // 1. Convert to wchar array, which can be treated as FriBidiChar array
+ size_t nchars;
+ if ((nchars = mbstowcs(NULL, src, 1)) == (size_t)-1) {
+ NORM_ERR("Invalid byte sequence");
+ return NULL;
+ }
+
+ FriBidiChar *bidichars = calloc(nchars + 1, sizeof(FriBidiChar));
+ if (!bidichars || mbstowcs((wchar_t *)bidichars, src, nchars + 1) != nchars) {
+ NORM_ERR("Out of memory");
+ goto freebidi;
+ }
+
+
+ // 2. Reorder the character array and do Arabic joining
+ FriBidiChar *reordered = calloc(nchars + 1, sizeof(FriBidiChar));
+ if (!reordered) {
+ NORM_ERR("Out of memory");
+ goto freebidi;
+ }
+ FriBidiParType pbase_dir = FRIBIDI_PAR_ON;
+ if (!fribidi_log2vis(bidichars, nchars, &pbase_dir, reordered, NULL, NULL, NULL)) {
+ NORM_ERR("Failed to reorder the line");
+ goto freereordered;
+ }
+
+
+ // 3. Convert wchar array back to mb string
+ size_t len;
+ if ((len = wcstombs(NULL, (wchar_t *)reordered, 1)) == (size_t)-1) {
+ NORM_ERR("Invalid byte sequence after reordering");
+ goto freereordered;
+ }
+
+ char *ret = calloc(len + 1, 1);
+ if (!ret || wcstombs(ret, (wchar_t *)reordered, len + 1) != len) {
+ NORM_ERR("Out of memory");
+ goto freeret;
+ }
+
+ free(reordered);
+ free(bidichars);
+
+ return ret;
+
+freeret:
+ free(ret);
+freereordered:
+ free(reordered);
+freebidi:
+ free(bidichars);
+ return NULL;
+}
+#endif
+
+static void draw_string(const char *s1)
{
int i, i2, pos, width_of_s;
int max = 0;
int added;
- if (s[0] == '\0') {
+ if (s1[0] == '\0') {
return;
}
+ const char *s = NULL;
+#if HAVE_FRIBIDI
+ if (utf8_mode) s = reorder_unicode_string(s1);
+#endif
+ if (!s) s = s1;
+
width_of_s = get_string_width(s);
if ((output_methods & TO_STDOUT) && draw_mode == FG) {
printf("%s\n", s);
--
1.8.5.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment