Text not vertically aligned properly when replacing Xft/Cairo by Pango/Cairo



Hello,

I'm  trying to  replace Xft/Cairo  by  Pango/Cairo in  a window  manager
because I'm  porting it  from Xlib to  XCB and unfortunately  Xft hasn't
been ported  yet to XCB. I  wrote a small  program in order to  test the
code before adding it in the window manager:

#include <stdlib.h>
#include <error.h>
#include <unistd.h>
#include <errno.h>

#include <X11/Xlib.h>
#include <X11/Xft/Xft.h>

#include <cairo.h>
#include <cairo-xlib.h>
#include <cairo-ft.h>

#include <pango/pangocairo.h>

static void
pango_draw_text(cairo_t *cr,
                const char *fontname,
                const char *text)
{
  PangoLayout *layout = pango_cairo_create_layout(cr);
  PangoFontDescription *font_desc = pango_font_description_from_string(fontname);
 
  pango_layout_set_text(layout, text, -1);
  pango_layout_set_font_description(layout, font_desc);

  /* Get extents */
  PangoRectangle ext;
  pango_layout_get_pixel_extents(layout, NULL, &ext);

  PangoContext *context = pango_layout_get_context(layout);
  PangoFontMetrics *font_metrics = pango_context_get_metrics(context, font_desc, NULL);

  printf("==> PANGO\nx: %d\ny: %d\nwidth: %d\nheight: %d\nascent: %d\ndescent: %d\n",
         ext.x, ext.y, ext.width, ext.height,
         PANGO_PIXELS(pango_font_metrics_get_ascent(font_metrics)),
         PANGO_PIXELS(pango_font_metrics_get_descent(font_metrics)));

  cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
  cairo_move_to(cr, 0, 20);

  pango_cairo_update_layout(cr, layout);
  pango_cairo_update_context(cr, context);
  pango_cairo_show_layout(cr, layout);

  pango_font_description_free(font_desc);
  g_object_unref(layout);
}

static void
cairo_draw_text(Display *display,
                const int screen,
                cairo_t *cr,
                const char *fontname,
                const char *text)
{
  XftFont *font = XftFontOpenName(display, screen, fontname);

  cairo_font_face_t *font_face = cairo_ft_font_face_create_for_pattern(font->pattern);

  cairo_set_font_face(cr, font_face);
  cairo_set_font_size(cr, font->height);

  cairo_text_extents_t te;
  cairo_text_extents(cr, text, &te);

  printf("==> XFT\nx_bearing: %.2f\ny_bearing: %.2f\nwidth: %.2f\n"
         "height: %.2f\nx_advance: %.2f\ny_advance: %.2f\nascent: %d\ndescent: %d\n",
         te.x_bearing, te.y_bearing, te.width, te.height,
         te.x_advance, te.y_advance, font->ascent, font->descent);

  cairo_font_face_destroy(font_face);
  XftFontClose(display, font);
}

int
main(int argc, char **argv)
{
  if(argc < 2)
    error(EXIT_FAILURE, EINVAL, "[ERROR]: no xft font given");

  char *xft_font = argv[1];
  char *pango_font = strdup(xft_font);

  char *font_dash;
  if((font_dash = strchr(pango_font, '-')) == NULL)
    error(EXIT_FAILURE, EINVAL, "[ERROR]: font-size");

  *font_dash = ' ';

  Display *display;
  if(!(display = XOpenDisplay(NULL)))
    error(EXIT_FAILURE, 0, "Cannot open display");

  int screen = DefaultScreen(display);
  Window win = XCreateSimpleWindow(display,
                                   RootWindow(display, screen),
                                   1, 1,
                                   DisplayWidth(display, screen),
                                   DisplayHeight(display, screen),
                                   0,
                                   WhitePixel(display, screen),
                                   WhitePixel(display, screen));

  XStoreName(display, win, "hello");
  XMapWindow(display, win);

  cairo_surface_t *surface = cairo_xlib_surface_create(display, win,
                                                       DefaultVisual(display, screen),
                                                       DisplayWidth(display, screen),
                                                       DisplayHeight(display, screen));

  cairo_t *cr = cairo_create(surface);

  const char *text = "Text rendering using cairo";

  /* Display the text using xft and cairo */
  cairo_draw_text(display, screen, cr, xft_font, text);

  cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
  cairo_move_to(cr, 300, 20);
  cairo_show_text(cr, text);
  /* End drawing using xft and cairo */

  /* Display the text using pango and cairo */
  pango_draw_text(cr, pango_font, text);
  /* End drawing using pango and cairo */

  XSync(display, False);
  pause();

  free(pango_font);

  cairo_destroy(cr);
  cairo_surface_destroy(surface);

  XCloseDisplay(display);

  return EXIT_SUCCESS;
}
I get the following output when running this program using the same font
(sans-10):

==> XFT
x_bearing: 0.00
y_bearing: -10.00
width: 163.00
height: 13.00
x_advance: 164.00
y_advance: 0.00
ascent: 10
descent: 3
==> PANGO
x: 0
y: 0
width: 164
height: 17
ascent: 13
descent: 4

However I can't figure out why the text is not vertically aligned on the
same  line  than  Xft/Cairo  text  (actually, the  Pango/Cairo  text  is
displayed some pixels under Xft/Cairo  text) and why the height differs.
I have certainly  missed something...  I took a  look at PangoLayout and
PangoContext API but didn't find anything.

Regards,
Arnaud Fontaine


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]