<p dir="ltr"><br>
On Oct 4, 2014 4:37 AM, "Ryo Munakata" <<a href="mailto:ryomnktml@gmail.com">ryomnktml@gmail.com</a>> wrote:<br>
><br>
> cairo-util has used sans font family for title fonts so far.<br>
> But sans doesn't support glyphs of some non-ascii characters.<br>
> So now let users choose a font family for titles.<br>
><br>
> To show texts correctly now using pangocairo for redering fonts.<br>
> If any single font in 'fonts' entry doesn't contain all the needed glyphs,<br>
> we use the fallback mode of pango.<br>
><br>
> This pangocairo support is enabled if configure finds pangocairo<br>
> on the build environment.<br>
> Otherwise fall back to plain cairo rendering.<br>
><br>
> The entry name is generic, 'fonts' so that other places<br>
> where draw texts can use this entry too.<br>
><br>
> Signed-off-by: Ryo Munakata <<a href="mailto:ryomnktml@gmail.com">ryomnktml@gmail.com</a>><br>
> ---<br>
>  Makefile.am               |   4 ++<br>
>  clients/window.c          |  18 +++--<br>
>  <a href="http://configure.ac">configure.ac</a>              |   5 +-<br>
>  man/weston.ini.man        |   3 +<br>
>  shared/cairo-util.c       | 180 ++++++++++++++++++++++++++++++++++++++++++++--<br>
>  shared/cairo-util.h       |   5 ++<br>
>  src/compositor-wayland.c  |   9 ++-<br>
>  <a href="http://weston.ini.in">weston.ini.in</a>             |   1 +<br>
>  xwayland/window-manager.c |   7 +-<br>
>  9 files changed, 216 insertions(+), 16 deletions(-)<br>
><br>
> diff --git a/Makefile.am b/Makefile.am<br>
> index 10be920..db3f423 100644<br>
> --- a/Makefile.am<br>
> +++ b/Makefile.am<br>
> @@ -829,6 +829,10 @@ libshared_cairo_la_SOURCES =                       \<br>
>         shared/frame.c                          \<br>
>         shared/cairo-util.h<br>
><br>
> +if HAVE_PANGO<br>
> +libshared_cairo_la_CFLAGS += $(PANGO_CFLAGS)<br>
> +libshared_cairo_la_LIBADD += $(PANGO_LIBS)<br>
> +endif<br>
><br>
>  #<br>
>  # tests subdirectory<br>
> diff --git a/clients/window.c b/clients/window.c<br>
> index 139c7f9..d9cbb9e 100644<br>
> --- a/clients/window.c<br>
> +++ b/clients/window.c<br>
> @@ -113,6 +113,8 @@ struct display {<br>
><br>
>         struct theme *theme;<br>
><br>
> +       struct weston_config *config;<br>
> +<br>
>         struct wl_cursor_theme *cursor_theme;<br>
>         struct wl_cursor **cursors;<br>
><br>
> @@ -1279,18 +1281,15 @@ static const struct cursor_alternatives cursors[] = {<br>
>  static void<br>
>  create_cursors(struct display *display)<br>
>  {<br>
> -       struct weston_config *config;<br>
>         struct weston_config_section *s;<br>
>         int size;<br>
>         char *theme = NULL;<br>
>         unsigned int i, j;<br>
>         struct wl_cursor *cursor;<br>
><br>
> -       config = weston_config_parse("weston.ini");<br>
> -       s = weston_config_get_section(config, "shell", NULL, NULL);<br>
> +       s = weston_config_get_section(display->config, "shell", NULL, NULL);<br>
>         weston_config_section_get_string(s, "cursor-theme", &theme, NULL);<br>
>         weston_config_section_get_int(s, "cursor-size", &size, 32);<br>
> -       weston_config_destroy(config);<br>
><br>
>         display->cursor_theme = wl_cursor_theme_load(theme, size, display->shm);<br>
>         if (!display->cursor_theme) {<br>
> @@ -5439,6 +5438,8 @@ struct display *<br>
>  display_create(int *argc, char *argv[])<br>
>  {<br>
>         struct display *d;<br>
> +       char *fonts;<br>
> +       struct weston_config_section *s;<br>
><br>
>         wl_log_set_handler_client(log_handler);<br>
><br>
> @@ -5488,9 +5489,14 @@ display_create(int *argc, char *argv[])<br>
>                         "falling back to software rendering and wl_shm.\n");<br>
>  #endif<br>
><br>
> +       d->config = weston_config_parse("weston.ini");<br>
> +<br>
>         create_cursors(d);<br>
><br>
> -       d->theme = theme_create();<br>
> +       s = weston_config_get_section(d->config, "shell", NULL, NULL);<br>
> +       weston_config_section_get_string(s, "fonts", &fonts, NULL);<br>
> +       d->theme = theme_create_with_fonts(fonts);<br>
> +       free(fonts);<br>
><br>
>         wl_list_init(&d->window_list);<br>
><br>
> @@ -5566,6 +5572,8 @@ display_destroy(struct display *display)<br>
>             !(display->display_fd_events & EPOLLHUP))<br>
>                 wl_display_flush(display->display);<br>
><br>
> +       weston_config_destroy(display->config);<br>
> +<br>
>         wl_display_disconnect(display->display);<br>
>         free(display);<br>
>  }<br>
> diff --git a/<a href="http://configure.ac">configure.ac</a> b/<a href="http://configure.ac">configure.ac</a><br>
> index 1c133bd..8b703bd 100644<br>
> --- a/<a href="http://configure.ac">configure.ac</a><br>
> +++ b/<a href="http://configure.ac">configure.ac</a><br>
> @@ -272,6 +272,9 @@ PKG_CHECK_MODULES(PNG, [libpng])<br>
>  PKG_CHECK_MODULES(WEBP, [libwebp], [have_webp=yes], [have_webp=no])<br>
>  AS_IF([test "x$have_webp" = "xyes"],<br>
>        [AC_DEFINE([HAVE_WEBP], [1], [Have webp])])<br>
> +PKG_CHECK_MODULES(PANGO, [pangocairo], [have_pango=yes], [have_pango=no])<br>
> +AS_IF([test "x$have_pango" = "xyes"],<br>
> +      [AC_DEFINE([HAVE_PANGO], [1], [Have pango support])])<br>
><br>
>  AC_ARG_ENABLE(vaapi-recorder, [  --enable-vaapi-recorder],,<br>
>               enable_vaapi_recorder=auto)<br>
> @@ -335,8 +338,6 @@ if test x$enable_clients = xyes; then<br>
>           [AC_DEFINE([HAVE_CAIRO_EGL], [1], [Have cairo-egl])],<br>
>           [AC_ERROR([cairo-egl not used because $CAIRO_EGL_PKG_ERRORS])])],<br>
>    [have_cairo_egl=no])<br>
> -<br>
> -  PKG_CHECK_MODULES(PANGO, [pangocairo], [have_pango=yes], [have_pango=no])<br>
>  fi<br>
><br>
>  AC_ARG_ENABLE(resize-optimization,<br>
> diff --git a/man/weston.ini.man b/man/weston.ini.man<br>
> index c05a221..73e32d7 100644<br>
> --- a/man/weston.ini.man<br>
> +++ b/man/weston.ini.man<br>
> @@ -260,6 +260,9 @@ sets the path to lock screen background image (string). (tablet shell only)<br>
>  .TP 7<br>
>  .BI "homescreen=" path<br>
>  sets the path to home screen background image (string). (tablet shell only)<br>
> +.TP 7<br>
> +.BI "fonts=" font-families<br>
> +sets the font family nams separated by commas (string). (title fonts only for now)<br>
>  .RE<br>
>  .SH "LAUNCHER SECTION"<br>
>  There can be multiple launcher sections, one for each launcher.<br>
> diff --git a/shared/cairo-util.c b/shared/cairo-util.c<br>
> index 26286c5..9c9957a 100644<br>
> --- a/shared/cairo-util.c<br>
> +++ b/shared/cairo-util.c<br>
> @@ -33,9 +33,42 @@<br>
>  #include "cairo-util.h"<br>
><br>
>  #include "image-loader.h"<br>
> -#include "config-parser.h"<br>
> +#include "zalloc.h"<br>
><br>
>  #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])<br>
> +#define DEFAULT_FONT_FAMILY "sans"<br>
> +#define DEFAULT_FONT_SIZE 14<br>
> +<br>
> +struct font_entry {<br>
> +       struct wl_list link;<br>
> +       char *name;<br>
> +};<br>
> +<br>
> +static struct font_entry *<br>
> +font_entry_create(char *fontname)<br>
> +{<br>
> +       struct font_entry *font = zalloc(sizeof *font);<br>
> +<br>
> +       if (!font)<br>
> +               return NULL;<br>
> +<br>
> +       font->name = strdup(fontname);<br>
> +       return font;<br>
> +}<br>
> +<br>
> +static void<br>
> +font_entry_destroy(struct font_entry *font)<br>
> +{<br>
> +       free(font->name);<br>
> +       free(font);<br>
> +}<br>
> +<br>
> +static struct font_entry *<br>
> +font_entry_list_front(struct wl_list *list)<br>
> +{<br>
> +       struct font_entry *font;<br>
> +       return wl_container_of(list, font, link);<br>
> +}<br>
><br>
>  void<br>
>  surface_flush_device(cairo_surface_t *surface)<br>
> @@ -337,8 +370,29 @@ theme_set_background_source(struct theme *t, cairo_t *cr, uint32_t flags)<br>
>         }<br>
>  }<br>
><br>
> +static void<br>
> +insert_font_family_list(struct wl_list *title_fonts, const char *fonts)<br>
> +{<br>
> +       char *fontlist, *str, *token, *saveptr;<br>
> +       struct wl_list *current = title_fonts;<br>
> +<br>
> +       if (!fonts || !(fontlist = strdup(fonts)))<br>
> +               return;<br>
> +<br>
> +       for (str = fontlist; (token = strtok_r(str, ",", &saveptr)) != NULL;) {<br>
> +               struct font_entry *font = font_entry_create(token);<br>
> +<br>
> +               if (font) {<br>
> +                       wl_list_insert(current, &font->link);<br>
> +                       current = &font->link;<br>
> +               }<br>
> +               str = NULL;<br>
> +       }<br>
> +       free(fontlist);<br>
> +}<br>
> +<br>
>  struct theme *<br>
> -theme_create(void)<br>
> +theme_create_with_fonts(const char *fonts)<br>
>  {<br>
>         struct theme *t;<br>
>         cairo_t *cr;<br>
> @@ -347,6 +401,10 @@ theme_create(void)<br>
>         if (t == NULL)<br>
>                 return NULL;<br>
><br>
> +       wl_list_init(&t->title_fonts);<br>
> +       insert_font_family_list(&t->title_fonts,<br>
> +               fonts ? fonts : DEFAULT_FONT_FAMILY);<br>
> +<br>
>         t->margin = 32;<br>
>         t->width = 6;<br>
>         t->titlebar_height = 27;<br>
> @@ -402,25 +460,113 @@ theme_create(void)<br>
>         return NULL;<br>
>  }<br>
><br>
> +struct theme *<br>
> +theme_create(void)<br>
> +{<br>
> +       return theme_create_with_fonts(NULL);<br>
> +}<br>
> +<br>
>  void<br>
>  theme_destroy(struct theme *t)<br>
>  {<br>
> +       struct font_entry *font, *next;<br>
> +<br>
> +       wl_list_for_each_safe(font, next, &t->title_fonts, link)<br>
> +               font_entry_destroy(font);<br>
>         cairo_surface_destroy(t->active_frame);<br>
>         cairo_surface_destroy(t->inactive_frame);<br>
>         cairo_surface_destroy(t->shadow);<br>
>         free(t);<br>
>  }<br>
><br>
> +#ifdef HAVE_PANGO<br>
> +#include <pango/pangocairo.h><br>
> +<br>
> +#define DEFAULT_FONT_WEIGHT PANGO_WEIGHT_BOLD<br>
> +<br>
> +static void<br>
> +pango_layout_set_fallback(PangoLayout *layout, gboolean fallback)<br>
> +{<br>
> +       PangoAttrList *list = pango_layout_get_attributes(layout);<br>
> +       PangoAttrList *attr_list = list ? list : pango_attr_list_new();<br>
> +<br>
> +       if (!attr_list)<br>
> +               return;<br>
> +<br>
> +       PangoAttribute *fb_attr = pango_attr_fallback_new(fallback);<br>
> +       pango_attr_list_change(attr_list, fb_attr);<br>
> +       pango_layout_set_attributes(layout, attr_list);<br>
> +<br>
> +       if (!list)<br>
> +               pango_attr_list_unref(attr_list);<br>
> +}<br>
> +<br>
> +static PangoFontDescription *<br>
> +pango_font_description_create(const char *font,<br>
> +                       double size, PangoWeight weight)<br>
> +{<br>
> +       PangoFontDescription *fontdesc =<br>
> +               pango_font_description_from_string(font);<br>
> +<br>
> +       pango_font_description_set_weight(fontdesc, weight);<br>
> +       pango_font_description_set_absolute_size(fontdesc, size * PANGO_SCALE);<br>
> +       return fontdesc;<br>
> +}<br>
> +<br>
> +static void</p>
<p dir="ltr">Why not just make the default font description be something like "12 Sans"?</p>
<p dir="ltr">This seems like a lot of infrastructure that's basically rewriting Pango. I assume that desktop-shell can't hard-depend on Pango?</p>
<p dir="ltr">+pango_layout_set_best_font(PangoLayout *layout,<br>
> +               struct wl_list *fonts, const char *text)<br>
> +{<br>
> +       struct font_entry *font, *first_font = NULL, *best_font = NULL;<br>
> +<br>
> +       pango_layout_set_text(layout, text, -1);<br>
> +       pango_layout_set_fallback(layout, FALSE);<br>
> +<br>
> +       wl_list_for_each(font, fonts, link) {<br>
> +               PangoFontDescription *fontdesc =<br>
> +                       pango_font_description_create(font->name,<br>
> +                               DEFAULT_FONT_SIZE, DEFAULT_FONT_WEIGHT);<br>
> +<br>
> +               pango_layout_set_font_description(layout, fontdesc);<br>
> +               pango_font_description_free(fontdesc);<br>
> +               if (!pango_layout_get_unknown_glyphs_count(layout)) {<br>
> +                       best_font = font;<br>
> +                       break;<br>
> +               }<br>
> +<br>
> +               if (!first_font)<br>
> +                       first_font = font;<br>
> +       }<br>
> +<br>
> +       if (!best_font && first_font) {<br>
> +               PangoFontDescription *fontdesc =<br>
> +                       pango_font_description_create(first_font->name,<br>
> +                               DEFAULT_FONT_SIZE, DEFAULT_FONT_WEIGHT);<br>
> +<br>
> +               pango_layout_set_font_description(layout, fontdesc);<br>
> +               pango_font_description_free(fontdesc);<br>
> +       }<br>
> +<br>
> +       pango_layout_set_fallback(layout, TRUE);<br>
> +}<br>
> +#endif<br>
> +<br>
>  void<br>
>  theme_render_frame(struct theme *t,<br>
>                    cairo_t *cr, int width, int height,<br>
>                    const char *title, struct wl_list *buttons,<br>
>                    uint32_t flags)<br>
>  {<br>
> +       cairo_surface_t *source;<br>
> +#ifdef HAVE_PANGO<br>
> +       PangoLayout *layout = pango_cairo_create_layout(cr);<br>
> +       PangoRectangle extents;<br>
> +       int x, y, margin, top_margin;<br>
> +#else<br>
>         cairo_text_extents_t extents;<br>
>         cairo_font_extents_t font_extents;<br>
> -       cairo_surface_t *source;<br>
>         int x, y, margin, top_margin;<br>
> +#endif<br>
><br>
>         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);<br>
>         cairo_set_source_rgba(cr, 0, 0, 0, 0);<br>
> @@ -458,31 +604,53 @@ theme_render_frame(struct theme *t,<br>
>                 cairo_clip(cr);<br>
><br>
>                 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);<br>
> -               cairo_select_font_face(cr, "sans",<br>
> +#ifdef HAVE_PANGO<br>
> +               pango_layout_set_best_font(layout, &t->title_fonts, title);<br>
> +               pango_layout_get_pixel_extents(layout, NULL, &extents);<br>
> +               x = (width - extents.width) / 2;<br>
> +               y = margin + (t->titlebar_height - extents.height) / 2;<br>
> +#else<br>
> +               cairo_select_font_face(cr,<br>
> +                                      font_entry_list_front(&t->title_fonts)->name,<br>
>                                        CAIRO_FONT_SLANT_NORMAL,<br>
>                                        CAIRO_FONT_WEIGHT_BOLD);<br>
> -               cairo_set_font_size(cr, 14);<br>
> +               cairo_set_font_size(cr, DEFAULT_FONT_SIZE);<br>
>                 cairo_text_extents(cr, title, &extents);<br>
>                 cairo_font_extents (cr, &font_extents);<br>
>                 x = (width - extents.width) / 2;<br>
>                 y = margin +<br>
>                         (t->titlebar_height -<br>
> -                        font_extents.ascent - font_extents.descent) / 2 +<br>
> +                       font_extents.ascent - font_extents.descent) / 2 +<br>
>                         font_extents.ascent;<br>
> +#endif<br>
><br>
>                 if (flags & THEME_FRAME_ACTIVE) {<br>
>                         cairo_move_to(cr, x + 1, y  + 1);<br>
>                         cairo_set_source_rgb(cr, 1, 1, 1);<br>
> +#ifdef HAVE_PANGO<br>
> +                       pango_cairo_show_layout(cr, layout);<br>
> +                       cairo_move_to(cr, x, y);<br>
> +                       cairo_set_source_rgb(cr, 0, 0, 0);<br>
> +                       pango_cairo_show_layout(cr, layout);<br>
> +#else<br>
>                         cairo_show_text(cr, title);<br>
>                         cairo_move_to(cr, x, y);<br>
>                         cairo_set_source_rgb(cr, 0, 0, 0);<br>
>                         cairo_show_text(cr, title);<br>
> +#endif<br>
>                 } else {<br>
>                         cairo_move_to(cr, x, y);<br>
>                         cairo_set_source_rgb(cr, 0.4, 0.4, 0.4);<br>
> +#ifdef HAVE_PANGO<br>
> +                       pango_cairo_show_layout(cr, layout);<br>
> +#else<br>
>                         cairo_show_text(cr, title);<br>
> +#endif<br>
>                 }<br>
>         }<br>
> +#ifdef HAVE_PANGO<br>
> +       g_object_unref(layout);<br>
> +#endif<br>
>  }<br>
><br>
>  enum theme_location<br>
> diff --git a/shared/cairo-util.h b/shared/cairo-util.h<br>
> index 11d11d1..db10140 100644<br>
> --- a/shared/cairo-util.h<br>
> +++ b/shared/cairo-util.h<br>
> @@ -53,10 +53,15 @@ struct theme {<br>
>         int margin;<br>
>         int width;<br>
>         int titlebar_height;<br>
> +       struct wl_list title_fonts;<br>
>  };<br>
><br>
>  struct theme *<br>
>  theme_create(void);<br>
> +<br>
> +struct theme *<br>
> +theme_create_with_fonts(const char *fonts);<br>
> +<br>
>  void<br>
>  theme_destroy(struct theme *t);<br>
><br>
> diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c<br>
> index bf71a76..7cf002c 100644<br>
> --- a/src/compositor-wayland.c<br>
> +++ b/src/compositor-wayland.c<br>
> @@ -738,7 +738,8 @@ wayland_output_set_windowed(struct wayland_output *output)<br>
>         struct wayland_compositor *c =<br>
>                 (struct wayland_compositor *)output->base.compositor;<br>
>         int tlen;<br>
> -       char *title;<br>
> +       char *title, *fonts;<br>
> +       struct weston_config_section *s;<br>
><br>
>         if (output->frame)<br>
>                 return 0;<br>
> @@ -755,7 +756,11 @@ wayland_output_set_windowed(struct wayland_output *output)<br>
>         }<br>
><br>
>         if (!c->theme) {<br>
> -               c->theme = theme_create();<br>
> +               s = weston_config_get_section(c->base.config, "shell", NULL, NULL);<br>
> +               weston_config_section_get_string(s, "fonts", &fonts, "");<br>
> +               c->theme = theme_create_with_fonts(fonts);<br>
> +               free(fonts);<br>
> +<br>
>                 if (!c->theme) {<br>
>                         free(title);<br>
>                         return -1;<br>
> diff --git a/<a href="http://weston.ini.in">weston.ini.in</a> b/<a href="http://weston.ini.in">weston.ini.in</a><br>
> index 4fca0bb..26192da 100644<br>
> --- a/<a href="http://weston.ini.in">weston.ini.in</a><br>
> +++ b/<a href="http://weston.ini.in">weston.ini.in</a><br>
> @@ -15,6 +15,7 @@ startup-animation=fade<br>
>  #num-workspaces=6<br>
>  #cursor-theme=whiteglass<br>
>  #cursor-size=24<br>
> +#fonts=sans<br>
><br>
>  #lockscreen-icon=/usr/share/icons/gnome/256x256/actions/lock.png<br>
>  #lockscreen=/usr/share/backgrounds/gnome/Garden.jpg<br>
> diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c<br>
> index 4e91f9d..a1b3094 100644<br>
> --- a/xwayland/window-manager.c<br>
> +++ b/xwayland/window-manager.c<br>
> @@ -2031,6 +2031,8 @@ weston_wm_create(struct weston_xserver *wxs, int fd)<br>
>         xcb_screen_iterator_t s;<br>
>         uint32_t values[1];<br>
>         xcb_atom_t supported[3];<br>
> +       char *fonts;<br>
> +       struct weston_config_section *section;<br>
><br>
>         wm = zalloc(sizeof *wm);<br>
>         if (wm == NULL)<br>
> @@ -2076,7 +2078,10 @@ weston_wm_create(struct weston_xserver *wxs, int fd)<br>
>         xcb_composite_redirect_subwindows(wm->conn, wm->screen->root,<br>
>                                           XCB_COMPOSITE_REDIRECT_MANUAL);<br>
><br>
> -       wm->theme = theme_create();<br>
> +       section = weston_config_get_section(wxs->compositor->config, "shell", NULL, NULL);<br>
> +       weston_config_section_get_string(section, "fonts", &fonts, NULL);<br>
> +       wm->theme = theme_create_with_fonts(fonts);<br>
> +       free(fonts);<br>
><br>
>         supported[0] = wm->atom.net_wm_moveresize;<br>
>         supported[1] = wm->atom.net_wm_state;<br>
> --<br>
> 2.1.2<br>
><br>
> _______________________________________________<br>
> wayland-devel mailing list<br>
> <a href="mailto:wayland-devel@lists.freedesktop.org">wayland-devel@lists.freedesktop.org</a><br>
> <a href="http://lists.freedesktop.org/mailman/listinfo/wayland-devel">http://lists.freedesktop.org/mailman/listinfo/wayland-devel</a></p>