added support for bidirectional text
This commit is contained in:
parent
b1b2f47e7d
commit
ea98db4140
4 changed files with 94 additions and 24 deletions
27
configure.in
27
configure.in
|
@ -163,8 +163,6 @@ dnl Check if iconv uses const in prototype declaration
|
|||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
AC_CHECK_LIB(nsl, t_open, LIBS="$LIBS -lnsl")
|
||||
AC_CHECK_LIB(socket, socket, LIBS="$LIBS -lsocket")
|
||||
|
||||
|
@ -603,6 +601,31 @@ fi
|
|||
# )
|
||||
|
||||
|
||||
enableval="yes"
|
||||
AC_MSG_CHECKING([whether to have FRIBIDI support])
|
||||
AC_ARG_ENABLE(fribidi,
|
||||
AC_HELP_STRING([--enable-fribidi],
|
||||
[FRIBIDI support [default=yes]]), ,
|
||||
[enableval=yes])
|
||||
if test "x$enableval" = "xyes"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_CHECK_LIB(fribidi, fribidi_version_info,
|
||||
AC_MSG_CHECKING([for fribidi/fribidi.h])
|
||||
AC_TRY_COMPILE(
|
||||
#include <fribidi/fribidi.h>
|
||||
, fribidi_version_info,
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(HAVE_FRIBIDI, [1], [Define to 1 if you have FRIBIDI])
|
||||
LIBS="$LIBS -lfribidi",
|
||||
AC_MSG_RESULT([no])))
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
CONFIGOPTS="$CONFIGOPTS --disable-fribidi"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AC_ARG_WITH(
|
||||
menu,
|
||||
|
|
|
@ -45,6 +45,11 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
#ifdef HAVE_FRIBIDI
|
||||
#include <fribidi/fribidi.h>
|
||||
#endif
|
||||
|
||||
|
||||
using std::string;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -239,6 +244,37 @@ bool haveUTF8() {
|
|||
}
|
||||
|
||||
|
||||
#ifdef HAVE_FRIBIDI
|
||||
|
||||
FbString BidiLog2Vis (const FbString& src){
|
||||
FriBidiChar * us, * out_us;
|
||||
FriBidiCharType base;
|
||||
FbString r;
|
||||
char * out;
|
||||
|
||||
us = new FriBidiChar[src.size()+1];
|
||||
out_us = new FriBidiChar[src.size()+1];
|
||||
|
||||
unsigned int len = fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8, const_cast<char *>(src.c_str()), src.length(), us);
|
||||
|
||||
base = FRIBIDI_TYPE_N;
|
||||
fribidi_log2vis(us, len, &base, out_us, NULL, NULL, NULL);
|
||||
|
||||
out = new char[4*src.size()+1];
|
||||
|
||||
fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_UTF8, out_us, len, out);
|
||||
|
||||
r = out;
|
||||
|
||||
delete[] out_us;
|
||||
delete[] us;
|
||||
delete[] out;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // end namespace StringUtil
|
||||
|
||||
StringConvertor::StringConvertor(EncodingTarget target):
|
||||
|
@ -289,4 +325,5 @@ string StringConvertor::recode(const string &src) {
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
} // end namespace FbTk
|
||||
|
|
|
@ -52,6 +52,11 @@ std::string FbStrToX(const FbString &src);
|
|||
FbString LocaleStrToFb(const std::string &src);
|
||||
std::string FbStrToLocale(const FbString &src);
|
||||
|
||||
#ifdef HAVE_FRIBIDI
|
||||
/// Make Bidi
|
||||
FbString BidiLog2Vis (const FbString& src);
|
||||
#endif
|
||||
|
||||
bool haveUTF8();
|
||||
|
||||
} // namespace FbStringUtil
|
||||
|
|
|
@ -248,7 +248,13 @@ bool Font::load(const string &name) {
|
|||
}
|
||||
|
||||
unsigned int Font::textWidth(const FbString &text, unsigned int size) const {
|
||||
return m_fontimp->textWidth(text, size);
|
||||
#ifdef HAVE_FRIBIDI
|
||||
const FbString visualOrder(FbTk::FbStringUtil::BidiLog2Vis(text));
|
||||
#else
|
||||
const FbString &visualOrder = text;
|
||||
#endif
|
||||
|
||||
return m_fontimp->textWidth(visualOrder, size);
|
||||
}
|
||||
|
||||
unsigned int Font::height() const {
|
||||
|
@ -273,31 +279,30 @@ void Font::drawText(const FbDrawable &w, int screen, GC gc,
|
|||
if (text.empty() || len == 0)
|
||||
return;
|
||||
|
||||
// so we don't end up in a loop with m_shadow
|
||||
static bool first_run = true;
|
||||
#ifdef HAVE_FRIBIDI
|
||||
const FbString visualOrder(FbTk::FbStringUtil::BidiLog2Vis(text));
|
||||
#else
|
||||
const FbString &visualOrder = text;
|
||||
#endif
|
||||
|
||||
|
||||
// draw "effects" first
|
||||
if (first_run) {
|
||||
if (m_shadow) {
|
||||
FbTk::GContext shadow_gc(w);
|
||||
shadow_gc.setForeground(m_shadow_color);
|
||||
first_run = false;
|
||||
drawText(w, screen, shadow_gc.gc(), text, len,
|
||||
x + m_shadow_offx, y + m_shadow_offy, orient);
|
||||
first_run = true;
|
||||
} else if (m_halo) {
|
||||
FbTk::GContext halo_gc(w);
|
||||
halo_gc.setForeground(m_halo_color);
|
||||
first_run = false;
|
||||
drawText(w, screen, halo_gc.gc(), text, len, x + 1, y + 1, orient);
|
||||
drawText(w, screen, halo_gc.gc(), text, len, x - 1, y + 1, orient);
|
||||
drawText(w, screen, halo_gc.gc(), text, len, x - 1, y - 1, orient);
|
||||
drawText(w, screen, halo_gc.gc(), text, len, x + 1, y - 1, orient);
|
||||
first_run = true;
|
||||
}
|
||||
if (m_shadow) {
|
||||
FbTk::GContext shadow_gc(w);
|
||||
shadow_gc.setForeground(m_shadow_color);
|
||||
m_fontimp->drawText(w, screen, shadow_gc.gc(), visualOrder, len,
|
||||
x + m_shadow_offx, y + m_shadow_offy, orient);
|
||||
} else if (m_halo) {
|
||||
FbTk::GContext halo_gc(w);
|
||||
halo_gc.setForeground(m_halo_color);
|
||||
m_fontimp->drawText(w, screen, halo_gc.gc(), visualOrder, len, x + 1, y + 1, orient);
|
||||
m_fontimp->drawText(w, screen, halo_gc.gc(), visualOrder, len, x - 1, y + 1, orient);
|
||||
m_fontimp->drawText(w, screen, halo_gc.gc(), visualOrder, len, x - 1, y - 1, orient);
|
||||
m_fontimp->drawText(w, screen, halo_gc.gc(), visualOrder, len, x + 1, y - 1, orient);
|
||||
}
|
||||
|
||||
m_fontimp->drawText(w, screen, gc, text, len, x, y, orient);
|
||||
m_fontimp->drawText(w, screen, gc, visualOrder, len, x, y, orient);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue