From e3dcadde3099e744921018bbf9506ac169221db6 Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Sat, 11 Oct 2014 16:45:18 +0200 Subject: [PATCH] WINGs: Add optional Pango text layout support Currently WINGs renders text using Xft directly which does not support any advanced text layout that is needed for scripts like Arabic or Indic scripts (or even things like automatic ligature support for Latin script). With Pango we also get text fallback for free, so no more square boxes for characters not supported in the current font (unless no font on the system supports the specified character, of course). This patch introduces support for using Pango to render the text (though its Xft backed), to avoid forcing the additional dependency to everyone it is made off by default. Signed-off-by: Carlos R. Mafra --- WINGs/Makefile.am | 5 +-- WINGs/WINGs/WINGsP.h | 7 +++++ WINGs/get-wings-flags.in | 2 +- WINGs/wfont.c | 66 ++++++++++++++++++++++++++++++++++++++++ configure.ac | 21 +++++++++++++ 5 files changed, 98 insertions(+), 3 deletions(-) diff --git a/WINGs/Makefile.am b/WINGs/Makefile.am index 863ba791..03c6e289 100644 --- a/WINGs/Makefile.am +++ b/WINGs/Makefile.am @@ -13,7 +13,7 @@ lib_LTLIBRARIES = libWUtil.la libWINGs.la LDADD= libWUtil.la libWINGs.la $(top_builddir)/wrlib/libwraster.la @INTLIBS@ -libWINGs_la_LIBADD = libWUtil.la $(top_builddir)/wrlib/libwraster.la @XLIBS@ @XFTLIBS@ @FCLIBS@ @LIBM@ +libWINGs_la_LIBADD = libWUtil.la $(top_builddir)/wrlib/libwraster.la @XLIBS@ @XFTLIBS@ @FCLIBS@ @LIBM@ @PANGOLIBS@ libWUtil_la_LIBADD = @LIBBSD@ EXTRA_DIST = BUGS make-rgb Examples Extras Tests get-wings-flags.in get-wutil-flags.in @@ -106,7 +106,7 @@ WINGs.pc: Makefile @echo 'Version: $(VERSION)' >> $@ @echo 'Requires: wrlib WUtil' >> $@ @echo 'Libs: $(lib_search_path) -lWINGs' >> $@ - @echo 'Libs.private: $(XFTLIBS) $(XLIBS) -lm $(INTLIBS)' >> $@ + @echo 'Libs.private: $(XFTLIBS) $(PANGOLIBS) $(XLIBS) -lm $(INTLIBS)' >> $@ @echo 'Cflags: $(inc_search_path)' >> $@ get-wings-flags: get-wings-flags.in Makefile @@ -115,6 +115,7 @@ get-wings-flags: get-wings-flags.in Makefile -e 's#$${lib_search_path}#$(lib_search_path)#;' \ -e 's#$${GFXLIBS}#$(GFXLIBS)#;' \ -e 's#$${XFTLIBS}#$(XFTLIBS)#;' \ + -e 's#$${PANGOLIBS}#$(PANGOLIBS)#;' \ -e 's#$${INTLIBS}#$(INTLIBS)#;' \ -e 's#$${XLIBS}#$(XLIBS)#;' < $(abs_srcdir)/get-wings-flags.in > $@ @chmod 755 $@ diff --git a/WINGs/WINGs/WINGsP.h b/WINGs/WINGs/WINGsP.h index 5a6e6126..2484b25d 100644 --- a/WINGs/WINGs/WINGsP.h +++ b/WINGs/WINGs/WINGsP.h @@ -5,6 +5,9 @@ #include #include +#ifdef USE_PANGO +#include +#endif #include @@ -445,6 +448,10 @@ typedef struct W_Font { short y; short refCount; char *name; + +#ifdef USE_PANGO + PangoLayout *layout; +#endif } W_Font; #define W_FONTID(f) (f)->font->fid diff --git a/WINGs/get-wings-flags.in b/WINGs/get-wings-flags.in index a32569ee..7218e006 100644 --- a/WINGs/get-wings-flags.in +++ b/WINGs/get-wings-flags.in @@ -2,7 +2,7 @@ WCFLAGS="${inc_search_path}" WLFLAGS="${lib_search_path}" -WLIBS="-lWINGs -lWUtil -lwraster ${GFXLIBS} ${XFTLIBS} ${XLIBS} -lm ${INTLIBS}" +WLIBS="-lWINGs -lWUtil -lwraster ${GFXLIBS} ${XFTLIBS} ${XLIBS} -lm ${INTLIBS} ${PANGOLIBS}" usage="Usage: get-wings-flags [--cflags] [--ldflags] [--libs]" diff --git a/WINGs/wfont.c b/WINGs/wfont.c index 364df5f8..a5cff072 100644 --- a/WINGs/wfont.c +++ b/WINGs/wfont.c @@ -12,6 +12,12 @@ #include #include +#ifdef USE_PANGO +#include +#include +#include +#endif + #define DEFAULT_FONT "sans serif:pixelsize=12" #define DEFAULT_SIZE WINGsConfiguration.defaultFontSize @@ -120,6 +126,14 @@ WMFont *WMCreateFont(WMScreen * scrPtr, const char *fontName) Display *display = scrPtr->display; WMFont *font; char *fname; +#ifdef USE_PANGO + PangoFontMap *fontmap; + PangoContext *context; + PangoLayout *layout; + FcPattern *pattern; + PangoFontDescription *description; + double size; +#endif if (fontName[0] == '-') { fname = xlfdToFcName(fontName); @@ -156,6 +170,25 @@ WMFont *WMCreateFont(WMScreen * scrPtr, const char *fontName) font->name = fname; +#ifdef USE_PANGO + fontmap = pango_xft_get_font_map(scrPtr->display, scrPtr->screen); + context = pango_font_map_create_context(fontmap); + layout = pango_layout_new(context); + + pattern = FcNameParse((FcChar8 *) font->name); + description = pango_fc_font_description_from_pattern(pattern, FALSE); + + /* Pango examines FC_SIZE but not FC_PIXEL_SIZE of the patten, but + * font-name has only "pixelsize", so set the size manually here. + */ + if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &size) == FcResultMatch) + pango_font_description_set_absolute_size(description, size * PANGO_SCALE); + + pango_layout_set_font_description(layout, description); + + font->layout = layout; +#endif + assert(WMHashInsert(scrPtr->fontCache, font->name, font) == NULL); return font; @@ -252,18 +285,34 @@ WMFont *WMBoldSystemFontOfSize(WMScreen * scrPtr, int size) int WMWidthOfString(WMFont * font, const char *text, int length) { +#ifdef USE_PANGO + const char *previous_text; + int width; +#else XGlyphInfo extents; +#endif wassertrv(font != NULL && text != NULL, 0); +#ifdef USE_PANGO + previous_text = pango_layout_get_text(font->layout); + if ((previous_text == NULL) || (strcmp(text, previous_text) != 0)) + pango_layout_set_text(font->layout, text, length); + pango_layout_get_pixel_size(font->layout, &width, NULL); + return width; +#else XftTextExtentsUtf8(font->screen->display, font->font, (XftChar8 *) text, length, &extents); return extents.xOff; /* don't ask :P */ +#endif } void WMDrawString(WMScreen * scr, Drawable d, WMColor * color, WMFont * font, int x, int y, const char *text, int length) { XftColor xftcolor; +#ifdef USE_PANGO + const char *previous_text; +#endif wassertr(font != NULL); @@ -275,7 +324,14 @@ void WMDrawString(WMScreen * scr, Drawable d, WMColor * color, WMFont * font, in XftDrawChange(scr->xftdraw, d); +#ifdef USE_PANGO + previous_text = pango_layout_get_text(font->layout); + if ((previous_text == NULL) || (strcmp(text, previous_text) != 0)) + pango_layout_set_text(font->layout, text, length); + pango_xft_render_layout(scr->xftdraw, &xftcolor, font->layout, x * PANGO_SCALE, y * PANGO_SCALE); +#else XftDrawStringUtf8(scr->xftdraw, &xftcolor, font->font, x, y + font->y, (XftChar8 *) text, length); +#endif } void @@ -284,6 +340,9 @@ WMDrawImageString(WMScreen * scr, Drawable d, WMColor * color, WMColor * backgro { XftColor textColor; XftColor bgColor; +#ifdef USE_PANGO + const char *previous_text; +#endif wassertr(font != NULL); @@ -303,7 +362,14 @@ WMDrawImageString(WMScreen * scr, Drawable d, WMColor * color, WMColor * backgro XftDrawRect(scr->xftdraw, &bgColor, x, y, WMWidthOfString(font, text, length), font->height); +#ifdef USE_PANGO + previous_text = pango_layout_get_text(font->layout); + if ((previous_text == NULL) || (strcmp(text, previous_text) != 0)) + pango_layout_set_text(font->layout, text, length); + pango_xft_render_layout(scr->xftdraw, &textColor, font->layout, x * PANGO_SCALE, y * PANGO_SCALE); +#else XftDrawStringUtf8(scr->xftdraw, &textColor, font->font, x, y + font->y, (XftChar8 *) text, length); +#endif } WMFont *WMCopyFontWithStyle(WMScreen * scrPtr, WMFont * font, WMFontStyle style) diff --git a/configure.ac b/configure.ac index 65d46fa7..a73f7038 100644 --- a/configure.ac +++ b/configure.ac @@ -625,6 +625,26 @@ fi AC_SUBST(XFTFLAGS) AC_SUBST(XFTLIBS) +dnl PANGO support +dnl ============= +pango=no +AC_ARG_ENABLE(pango, AS_HELP_STRING([--enable-pango], [enable Pango text layout support]), + pango=$enableval, pango=no) + +PANGOFLAGS= +PANGOLIBS= +if test "$pango" = yes; then + PANGOLIBS=`$PKGCONFIG pangoxft --libs` + PANGOFLAGS=`$PKGCONFIG pangoxft --cflags` + if test "x$PANGOLIBS" = "x" ; then + AC_MSG_RESULT([not found]) + else + AC_DEFINE(USE_PANGO, 1, [Define if Pango is to be used]) + AC_MSG_RESULT([found]) + fi +fi +inc_search_path="$inc_search_path $PANGOFLAGS" +AC_SUBST(PANGOLIBS) dnl ============================================== dnl Graphic Format Libraries @@ -869,6 +889,7 @@ echo "Supported X extensions: :$supported_xext" echo "Supported graphic format libraries :$supported_gfx" echo "Unsupported features :$unsupported" echo "Antialiased text support in WINGs : $xft" +echo "Pango text layout support in WINGs : $pango" echo "Translated message files to install : $mof" dnl echo "Supported languages beside English : $languages" if test "x$MOFILES" != "x"; then