[cairo] Writing a PangoLayoutLine on a line in cairo

Dov Grobgeld dov.grobgeld at gmail.com
Sat Feb 3 11:48:29 PST 2007


I'm trying to understand how to get the baseline information from a
single line PangoLayout or equivalently a PangoLayoutLine.

More concretely I would like to translate the following postscript
program into Pango/Cairo:

  %!
  1.0 0 0 setrgbcolor
  100 100 moveto
  150 0 rlineto stroke
  100 100 moveto
  /Helvetica findfont 36 scalefont setfont
  0 setgray
  (yd) show
  showpage

This programs draws a red line at position 100 100 from the lower
corner left of the page and then writes "yd" on it. Note that the
descender of the y descends below the y=100 line.

In pango_cairo_show_layout() on the other hand, the layout logical
upper left corner is aligned at the current cairo point when drawing,
and I could not find any PangoLayout call that gets the distance from
the top of the logical rectangle to the baseline position. Is this a
bug, or did I miss something?

Here is some pangocairo code that shows this alignment. So the
question is how can I get the distance from the top of the PangoLayout
to the baseline?

Regards,
Dov

//======================================================================
// Example that shows the relation between cairo coordinates and
// Pango coordinates.
//
// Dov Grobgeld <dov.grobgeld at gmail.com>
// Sat 2007-02-03 21:43
//
// This program is in the public domain
//
// Compile with:
//
//    gcc `pkg-config --cflags --libs pangocairo` -o pango-bbox  pango-bbox.c
//----------------------------------------------------------------------
#include <math.h>
#include <pango/pangocairo.h>

#define WIDTH 800
#define HEIGHT 300

static void
draw_text (cairo_t *cr,
           const char *text)
{
  PangoLayout *layout;
  PangoFontDescription *desc;
  PangoRectangle ink_rect, logical_rect;
  int width, height;
  double x, y;

  // Center coordinates on the middle of the region we are drawing
  cairo_translate (cr, WIDTH/2, HEIGHT/2);

  // Create a PangoLayout, set the font and text
  layout = pango_cairo_create_layout (cr);

  pango_layout_set_markup (layout, text, -1);
  desc = pango_font_description_from_string ("Serif 70");
  pango_layout_set_font_description (layout, desc);
  pango_font_description_free (desc);

  pango_layout_get_extents(layout,
                           &ink_rect,
                           &logical_rect);
  x = -((double)logical_rect.width / PANGO_SCALE) / 2;
  y = -((double)logical_rect.height / PANGO_SCALE) / 2;

  // Draw a green point at the current x,y position
  cairo_set_source_rgba (cr, 0.0, 1.0, 0.0, 0.5); // green
  cairo_arc(cr,
            x, y,
            5, 0, 2*M_PI);
  cairo_fill(cr);

  // Draw the logical rectangle
  cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 0.5); // blue
  cairo_rectangle(cr,
                  x+logical_rect.x/PANGO_SCALE,
                  y+logical_rect.y/PANGO_SCALE,
                  logical_rect.width/PANGO_SCALE,
                  logical_rect.height/PANGO_SCALE);
  cairo_stroke(cr);

  // Draw the text
  cairo_move_to (cr, x, y);
  cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); // black
  pango_cairo_show_layout (cr, layout);

  // Question: How can I draw a line at the baseline position?

  // free the layout object
  g_object_unref (layout);
}

int main (int argc, char **argv)
{
  cairo_t *cr;
  const char *filename = "pango-bbox.png";
  cairo_surface_t *surface;

  surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, WIDTH, HEIGHT);

  cr = cairo_create (surface);

  cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
  cairo_paint (cr);
  draw_text (cr,
             "yd"
             );
  cairo_show_page (cr);
  cairo_destroy (cr);

  cairo_surface_write_to_png(surface, filename);

  cairo_surface_destroy (surface);

  return 0;
}


More information about the cairo mailing list