[cairo] Re: Rotated text bug on drawable target

graydon hoare graydon at redhat.com
Thu Nov 4 22:53:16 PST 2004


Carl Worth wrote:

> But with the code as in CVS the glyphs are positioned quite badly. Looks
> like rotations within the 1st quadrant are roughly correct. But
> rotations within the 3rd quadrant align the glyphs by their tops rather
> than along the baseline. Within the 2nd and 4th quadrants the positions
> transitions between the two extremes.

yeah, it was sort of a combination of a couple signage errors and the 
use of bearings rather than bounding box offsets in the render glyph 
loader. the attached patch seems to fix it, on my end (included a minor 
fix to the clip code too).

ok to commit?

-graydon

2004-11-05  Graydon Hoare  <graydon at redhat.com>

	* src/cairo_ft_font.c: Change the signs of a variety of
	metrics, which were backwards.
	* src/cairo_gstate.c (_cairo_gstate_clip): Return early if we
	found a rectangular clip at all, not just in error case.
	* src/cairo_xlib_surface.c
	(_xlib_glyphset_cache_create_entry): Give render glyphset entry
         the negative bbox offsets it wants, not the bearings.
-------------- next part --------------
--- src/cairo_ft_font.c	22 Oct 2004 01:40:50 -0000	1.25
+++ src/cairo_ft_font.c	5 Nov 2004 06:42:31 -0000
@@ -527,7 +527,7 @@
 	    continue;
 
         x += val->extents.x_advance;
-        y -= val->extents.y_advance;
+        y += val->extents.y_advance;
     }
     _cairo_unlock_global_image_glyph_cache ();
 
@@ -614,7 +614,7 @@
            cairo_ft_font_create_for_ft_face accept an
            FcPattern. */
 	glyph_min.x = glyphs[i].x + img->extents.x_bearing;
-	glyph_min.y = glyphs[i].y - img->extents.y_bearing;
+	glyph_min.y = glyphs[i].y + img->extents.y_bearing;
 	glyph_max.x = glyph_min.x + img->extents.width;
 	glyph_max.y = glyph_min.y + img->extents.height;
     
@@ -640,7 +640,7 @@
     extents->width     = total_max.x - total_min.x;
     extents->height    = total_max.y - total_min.y;
     extents->x_advance = glyphs[i-1].x + (img == NULL ? 0 : img->extents.x_advance) - origin.x;
-    extents->y_advance = glyphs[i-1].y + 0 - origin.y;
+    extents->y_advance = glyphs[i-1].y + (img == NULL ? 0 : img->extents.y_advance) - origin.y;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -688,7 +688,7 @@
 	    continue;
 
 	x1 = _cairo_fixed_from_double (glyphs[i].x + img->size.x);
-	y1 = _cairo_fixed_from_double (glyphs[i].y - img->size.y);
+	y1 = _cairo_fixed_from_double (glyphs[i].y + img->size.y);
 	x2 = x1 + _cairo_fixed_from_double (img->size.width);
 	y2 = y1 + _cairo_fixed_from_double (img->size.height);
 	
@@ -763,10 +763,10 @@
 					   &(img->image->base), 
 					   surface,
 					   source_x + x + img->size.x,
-					   source_y + y - img->size.y,
+					   source_y + y + img->size.y,
 					   0, 0, 
 					   x + img->size.x, 
-					   y - img->size.y, 
+					   y + img->size.y, 
 					   (double) img->size.width,
 					   (double) img->size.height);
 
@@ -928,12 +928,19 @@
     if (FT_Load_Glyph (font->val->face, val->key.index, FT_LOAD_DEFAULT) != 0)
 	return CAIRO_STATUS_NO_MEMORY;
 
+    /*
+     * Note: the font's coordinate system is upside down from ours, so the
+     * Y coordinates of the bearing and advance need to be negated.
+     */
+
     val->extents.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX);
-    val->extents.y_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingY);
+    val->extents.y_bearing = -DOUBLE_FROM_26_6 (metrics->horiBearingY);
+
     val->extents.width  = DOUBLE_FROM_26_6 (metrics->width);
     val->extents.height = DOUBLE_FROM_26_6 (metrics->height);
+
     val->extents.x_advance = DOUBLE_FROM_26_6 (font->val->face->glyph->advance.x);
-    val->extents.y_advance = DOUBLE_FROM_26_6 (font->val->face->glyph->advance.y);
+    val->extents.y_advance = -DOUBLE_FROM_26_6 (font->val->face->glyph->advance.y);
     
     outline = &glyphslot->outline;
 
@@ -983,10 +990,15 @@
 	_cairo_image_surface_assume_ownership_of_data (val->image);
     }
     
+    /*
+     * Note: the font's coordinate system is upside down from ours, so the
+     * Y coordinate of the control box needs to be negated.
+     */
+
     val->size.width = (unsigned short) width;
     val->size.height = (unsigned short) height;
     val->size.x = (short) (cbox.xMin >> 6);
-    val->size.y = (short) (cbox.yMax >> 6);
+    val->size.y = - (short) (cbox.yMax >> 6);
     
     return CAIRO_STATUS_SUCCESS;
 }
--- src/cairo_gstate.c	3 Nov 2004 23:05:24 -0000	1.63
+++ src/cairo_gstate.c	5 Nov 2004 06:42:31 -0000
@@ -1760,8 +1760,8 @@
 	
 	if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
 	    _cairo_traps_fini (&traps);
-	    return status;
 	}
+	return status;
     }
 
     /* Otherwise represent the clip as a mask surface. */
--- src/cairo_xlib_surface.c	22 Oct 2004 01:40:50 -0000	1.27
+++ src/cairo_xlib_surface.c	5 Nov 2004 06:42:31 -0000
@@ -839,8 +839,45 @@
 
     v->info.width = im->image ? im->image->stride : im->size.width;
     v->info.height = im->size.height;
-    v->info.x = - im->extents.x_bearing;
-    v->info.y = im->extents.y_bearing;
+
+    /*
+     *  Most of the font rendering system thinks of glyph tiles as having
+     *  an origin at (0,0) and an x and y bounding box "offset" which
+     *  extends possibly off into negative coordinates, like so:
+     *
+     *     
+     *       (x,y) <-- probably negative numbers
+     *         +----------------+
+     *         |      .         |
+     *         |      .         |
+     *         |......(0,0)     |
+     *         |                |
+     *         |                |
+     *         +----------------+
+     *                  (width+x,height+y)
+     *
+     *  This is a postscript-y model, where each glyph has its own
+     *  coordinate space, so it's what we expose in terms of metrics. It's
+     *  apparantly what everyone's expecting. Everyone except the Render
+     *  extension. Render wants to see a glyph tile starting at (0,0), with
+     *  an origin offset inside, like this:
+     *
+     *       (0,0)
+     *         +---------------+
+     *         |      .        |
+     *         |      .        |
+     *         |......(x,y)    |
+     *         |               |
+     *         |               |
+     *         +---------------+
+     *                   (width,height)
+     *
+     *  Luckily, this is just the negation of the numbers we already have
+     *  sitting around for x and y. 
+     */
+
+    v->info.x = -im->size.x;
+    v->info.y = -im->size.y;
     v->info.xOff = 0;
     v->info.yOff = 0;
 


More information about the cairo mailing list