[cairo-commit] src/cairo-ft-font.c

罗晶华 Jinghua Luo jinghua at kemper.freedesktop.org
Wed Jun 7 12:46:07 PDT 2006


 src/cairo-ft-font.c |  126 +++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 95 insertions(+), 31 deletions(-)

New commits:
diff-tree 5ae2a78a297730cd9d2f45be9f23fbf6e2bffe7d (from 6b5be506ed160675232bea31b17f458040f6b2d8)
Author: Jinghua Luo <sunmoon1997 at gmail.com>
Date:   Thu Jun 8 03:45:38 2006 +0800

    freetype: Fix for test case ft-text-vertial-layout.
    
    Fix scaled font metrics and glyph metrics calculation for vertical
    layout. Test case ft-text-vertial-layout passes now.

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 002466b..61a2c23 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -1461,19 +1461,28 @@ _cairo_ft_scaled_font_create (cairo_ft_u
 	fs_metrics.ascent =        DOUBLE_FROM_26_6(metrics->ascender) * y_factor;
 	fs_metrics.descent =       DOUBLE_FROM_26_6(- metrics->descender) * y_factor;
 	fs_metrics.height =        DOUBLE_FROM_26_6(metrics->height) * y_factor;
-	fs_metrics.max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) * x_factor;
+	if (!(scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT)) {
+	    fs_metrics.max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) * x_factor;
+	    fs_metrics.max_y_advance = 0;
+	} else {
+	    fs_metrics.max_x_advance = 0;
+	    fs_metrics.max_y_advance = DOUBLE_FROM_26_6(metrics->max_advance) * y_factor;
+	}
     } else {
 	double scale = face->units_per_EM;
 
 	fs_metrics.ascent =        face->ascender / scale;
 	fs_metrics.descent =       - face->descender / scale;
 	fs_metrics.height =        face->height / scale;
-	fs_metrics.max_x_advance = face->max_advance_width / scale;
+	if (!(scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT)) {
+	    fs_metrics.max_x_advance = face->max_advance_width / scale;
+	    fs_metrics.max_y_advance = 0;
+	} else {
+	    fs_metrics.max_x_advance = 0;
+	    fs_metrics.max_y_advance = face->max_advance_height / scale;
+	}
     }
 
-    /* FIXME: this doesn't do vertical layout atm. */
-    fs_metrics.max_y_advance = 0.0;
-
     _cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics);
 
     return &scaled_font->base;
@@ -1716,6 +1725,23 @@ _decompose_glyph_outline (FT_Face		  fac
     return CAIRO_STATUS_SUCCESS;
 }
 
+/*
+ * Translate glyph to match its metrics.
+ */
+static void
+_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (FT_GlyphSlot glyph)
+{
+    FT_Pos x = glyph->metrics.vertBearingX - glyph->metrics.horiBearingX;
+    FT_Pos y = -glyph->metrics.vertBearingY - glyph->metrics.horiBearingY;
+
+    if (glyph->format == FT_GLYPH_FORMAT_OUTLINE)
+	FT_Outline_Translate(&glyph->outline, x, y);
+    else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
+	glyph->bitmap_left += x / 64;
+	glyph->bitmap_top  += y / 64;
+    }
+}
+
 static cairo_status_t
 _cairo_ft_scaled_glyph_init (void			*abstract_font,
 			     cairo_scaled_glyph_t	*scaled_glyph,
@@ -1730,6 +1756,7 @@ _cairo_ft_scaled_glyph_init (void			*abs
     int load_flags = scaled_font->ft_options.load_flags;
     FT_Glyph_Metrics *metrics;
     double x_factor, y_factor;
+    cairo_bool_t vertical_layout = FALSE;
 
     face = cairo_ft_scaled_font_lock_face (abstract_font);
     if (!face)
@@ -1739,6 +1766,15 @@ _cairo_ft_scaled_glyph_init (void			*abs
 	(info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0)
 	load_flags |= FT_LOAD_NO_BITMAP;
 
+    /*
+     * Don't pass FT_LOAD_VERTICAL_LAYOUT to FT_Load_Glyph here as
+     * suggested by freetype people.
+     */
+    if (load_flags & FT_LOAD_VERTICAL_LAYOUT) {
+	load_flags &= ~FT_LOAD_VERTICAL_LAYOUT;
+	vertical_layout = TRUE;
+    }
+
     error = FT_Load_Glyph (scaled_font->unscaled->face,
 			   _cairo_scaled_glyph_index(scaled_glyph),
 			   load_flags);
@@ -1758,6 +1794,9 @@ _cairo_ft_scaled_glyph_init (void			*abs
 	FT_GlyphSlot_Embolden (glyph);
 #endif
 
+    if (vertical_layout)
+	_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (glyph);
+
     if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) {
 	/*
 	 * Compute font-space metrics
@@ -1791,35 +1830,57 @@ _cairo_ft_scaled_glyph_init (void			*abs
 	    FT_Pos x1, x2;
 	    FT_Pos y1, y2;
 	    FT_Pos advance;
+	    
+	    if (!vertical_layout) {
+		x1 = (metrics->horiBearingX) & -64;
+		x2 = (metrics->horiBearingX + metrics->width + 63) & -64;
+		y1 = (-metrics->horiBearingY) & -64;
+		y2 = (-metrics->horiBearingY + metrics->height + 63) & -64;
+		
+		advance = ((metrics->horiAdvance + 32) & -64);
+		
+		fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor;
+		fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor;
+		
+		fs_metrics.width  = DOUBLE_FROM_26_6 (x2 - x1) * x_factor;
+		fs_metrics.height  = DOUBLE_FROM_26_6 (y2 - y1) * y_factor;
 
-	    x1 = (metrics->horiBearingX) & -64;
-	    x2 = (metrics->horiBearingX + metrics->width + 63) & -64;
-	    y1 = (-metrics->horiBearingY) & -64;
-	    y2 = (-metrics->horiBearingY + metrics->height + 63) & -64;
-
-	    advance = ((metrics->horiAdvance + 32) & -64);
-
-	    fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor;
-	    fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor;
-
-	    fs_metrics.width  = DOUBLE_FROM_26_6 (x2 - x1) * x_factor;
-	    fs_metrics.height  = DOUBLE_FROM_26_6 (y2 - y1) * y_factor;
-
-	    /*
-	     * use untransformed advance values
-	     * XXX uses horizontal advance only at present; should provide FT_LOAD_VERTICAL_LAYOUT
-	     */
-	    fs_metrics.x_advance = DOUBLE_FROM_26_6 (advance) * x_factor;
-	    fs_metrics.y_advance = 0;
-	 } else {
-	     fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor;
-	     fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor;
+		fs_metrics.x_advance = DOUBLE_FROM_26_6 (advance) * x_factor;
+		fs_metrics.y_advance = 0;
+	    } else {
+		x1 = (metrics->vertBearingX) & -64;
+		x2 = (metrics->vertBearingX + metrics->width + 63) & -64;
+		y1 = (metrics->vertBearingY) & -64;
+		y2 = (metrics->vertBearingY + metrics->height + 63) & -64;
+		
+		advance = ((metrics->vertAdvance + 32) & -64);
+		
+		fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor;
+		fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor;
+		
+		fs_metrics.width  = DOUBLE_FROM_26_6 (x2 - x1) * x_factor;
+		fs_metrics.height  = DOUBLE_FROM_26_6 (y2 - y1) * y_factor;
 
-	     fs_metrics.width  = DOUBLE_FROM_26_6 (metrics->width) * x_factor;
-	     fs_metrics.height = DOUBLE_FROM_26_6 (metrics->height) * y_factor;
+		fs_metrics.x_advance = 0;
+		fs_metrics.y_advance = DOUBLE_FROM_26_6 (advance) * y_factor;
+	    }
+	 } else {
+	    fs_metrics.width  = DOUBLE_FROM_26_6 (metrics->width) * x_factor;
+	    fs_metrics.height = DOUBLE_FROM_26_6 (metrics->height) * y_factor;
 
-	     fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor;
-	     fs_metrics.y_advance = 0 * y_factor;
+	    if (!vertical_layout) {
+		fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor;
+		fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor;
+		
+		fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor;
+		fs_metrics.y_advance = 0 * y_factor;
+	    } else {
+		fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingX) * x_factor;
+		fs_metrics.y_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingY) * y_factor;
+		
+		fs_metrics.x_advance = 0 * x_factor;
+		fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor;
+	    }
 	 }
 
 	_cairo_scaled_glyph_set_metrics (scaled_glyph,
@@ -1862,6 +1923,9 @@ _cairo_ft_scaled_glyph_init (void			*abs
 		cairo_ft_scaled_font_unlock_face (abstract_font);
 		return CAIRO_STATUS_NO_MEMORY;
 	    }
+	    if (vertical_layout)
+		_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (glyph);
+
 	}
 	if (glyph->format == FT_GLYPH_FORMAT_OUTLINE)
 	    status = _decompose_glyph_outline (face, &scaled_font->base.options,


More information about the cairo-commit mailing list