[cairo] Rendering underlines / overbars with pangocairo

Peter Clifton pcjc2 at cam.ac.uk
Wed Dec 17 20:09:54 PST 2008


Hi,

Apologies for asking what is a pretty pango specific question on the
cairo list. I'm using cairo to render things, so hopefully you can bear
with me here.

I'm rendering text on an electronic CAD system canvas. When we zoom out,
the text gets really small, and it appears whatever the default hinting
is on my box kind-of gives up, and the text becomes fainter as the
strokes become narrower. (Possibly due to anti-aliasing I guess?)

I have a custom pango renderer subclass for drawing overbars. I borrow
geometry from the underline. Here is the draw_glyphs portion: 

static void
gschem_pango_renderer_draw_glyphs (PangoRenderer    *renderer,
                                   PangoFont        *font,
                                   PangoGlyphString *glyphs,
                                   int               x,
                                   int               y)
{
  GschemPangoRenderer *gschem_renderer = GSCHEM_PANGO_RENDERER (renderer);
  GschemPangoRendererPrivate *priv = gschem_renderer->priv;
  cairo_t *cr;

  cr = get_cairo_context (gschem_renderer,
                          PANGO_RENDER_PART_FOREGROUND);

  if (priv->overbar) {
    double rx, ry, rwidth, rheight, cheight;
    PangoFontMetrics *metrics;
    PangoRectangle logical;
    int underline_thickness;

    /* Make the thickness the same as for the font's underline */
    metrics = pango_font_get_metrics (font, NULL);
    underline_thickness = pango_font_metrics_get_underline_thickness (metrics);
    pango_font_metrics_unref (metrics);

    pango_glyph_string_extents (glyphs, font, NULL, &logical);

    rx = x;
    ry = y - logical.height * MAGIC_OVERBAR_POS_CONSTANT;
    rwidth = logical.width;
    rheight = underline_thickness;

    cheight = rheight / PANGO_SCALE;

    /* Allow the overbar to fade out as it becomes < 1px high */
    if (cheight > 1.0)
      cheight = (int)(cheight);

    cairo_rectangle (cr,
                     (int)(rx / PANGO_SCALE), (int)(ry / PANGO_SCALE),
                     (int)(rwidth / PANGO_SCALE), cheight);
    cairo_fill (cr);
  }

  cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE);
  pango_cairo_show_glyph_string (cr, font, glyphs);
}


However, it appears that the overbar doesn't fade out. When zoomed far
out, you see very bold pixel aligned overbars, with some faded
anti-aliased text in the few pixels below.

Poking in Pango, (and I'm a complete noob there), I'm wondering if the
font metrics are coming through pangogc-font.c 's get_face_metrics()
function. (The platform is Linux, and text is being rendered via
cairo). 

At the bottom of that function, we see:

  /* If hinting is on for this font, quantize the underline and strikethrough position
   * to integer values.
   */
  if (fcfont->is_hinted)
    {
      pango_quantize_line_geometry (&metrics->underline_thickness,
				    &metrics->underline_position);
      pango_quantize_line_geometry (&metrics->strikethrough_thickness,
				    &metrics->strikethrough_position);
    }

Which spoils the "trick" I was aiming for, that once the strike-through
had become < 1px height, it should allow a non-integer height such that
the rendering would fade.

Would such a thing be possible?

Is it something which could change in pango, or would the quantization
have to be worked around by my renderer. (Can I temporarily turn the
hinting off whilst I grab the underline thickness?)

Best wishes,

-- 
Peter Clifton

Electrical Engineering Division,
Engineering Department,
University of Cambridge,
9, JJ Thomson Avenue,
Cambridge
CB3 0FA

Tel: +44 (0)7729 980173 - (No signal in the lab!)



More information about the cairo mailing list