rpms/cairo/devel cairo-0.5.1-bitmap-fonts.patch, NONE, 1.1 cairo.spec, 1.13, 1.14

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Sun Jun 26 19:50:35 UTC 2005


Author: krh

Update of /cvs/dist/rpms/cairo/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv25152

Modified Files:
	cairo.spec 
Added Files:
	cairo-0.5.1-bitmap-fonts.patch 
Log Message:
* Sun Jun 26 2005 Kristian Høgsberg <krh at redhat.com> - 0.5.1-4
- Add more missing devel package requires (libpng-devel and
  xorg-x11-devel) (#161688)
- Add Owens patch (cairo-0.5.1-bitmap-fonts.patch) to make bitmap
  fonts work with cairo (#161653).



cairo-0.5.1-bitmap-fonts.patch:
 cairo-ft-font.c |  405 +++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 344 insertions(+), 61 deletions(-)

--- NEW FILE cairo-0.5.1-bitmap-fonts.patch ---
Patches from Owen to support bitmap fonts in cairo.  Should be merged
in the next cairo snapshot.

  http://lists.freedesktop.org/archives/cairo/2005-June/004387.html
  http://lists.freedesktop.org/archives/cairo/2005-June/004388.html

Index: src/cairo-ft-font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-ft-font.c,v
retrieving revision 1.65
diff -u -p -r1.65 cairo-ft-font.c
--- src/cairo-ft-font.c	15 Jun 2005 23:04:19 -0000	1.65
+++ src/cairo-ft-font.c	24 Jun 2005 20:50:24 -0000
@@ -34,6 +34,8 @@
  *	Owen Taylor <otaylor at redhat.com>
  */
 
+#include <float.h>
+
 #include "cairo-ft-private.h"
 
 #include <fontconfig/fontconfig.h>
@@ -448,6 +450,7 @@ _ft_unscaled_font_set_scale (ft_unscaled
 {
     ft_font_transform_t sf;
     FT_Matrix mat;
+    FT_UInt pixel_width, pixel_height;
 
     assert (unscaled->face != NULL);
     
@@ -472,10 +475,29 @@ _ft_unscaled_font_set_scale (ft_unscaled
     mat.yy = DOUBLE_TO_16_16(sf.shape[1][1]);
 
     FT_Set_Transform(unscaled->face, &mat, NULL);
-    
-    FT_Set_Pixel_Sizes(unscaled->face,
-		       (FT_UInt) sf.x_scale,
-		       (FT_UInt) sf.y_scale);
+
+    if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {
+	pixel_width = sf.x_scale;
+	pixel_height = sf.y_scale;
+    } else {
+	double min_distance = DBL_MAX;
+	int i;
+
+	pixel_width = pixel_height = 0;
+	
+	for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
+	    double size = unscaled->face->available_sizes[i].y_ppem / 64.;
+	    double distance = fabs (size - sf.y_scale);
+	    
+	    if (distance <= min_distance) {
+		min_distance = distance;
+		pixel_width = unscaled->face->available_sizes[i].x_ppem >> 6;
+		pixel_height = unscaled->face->available_sizes[i].y_ppem >> 6;
+	    }
+	}
+    }
+
+    FT_Set_Pixel_Sizes (unscaled->face, pixel_width, pixel_height);
 }
 
 static void 
@@ -515,59 +537,32 @@ _cairo_ft_unscaled_font_destroy (void *a
     }
 }
 
-static cairo_status_t 
-_cairo_ft_unscaled_font_create_glyph (void                            *abstract_font,
-				      cairo_image_glyph_cache_entry_t *val)
+/* Converts an outline FT_GlyphSlot into an image
+ * 
+ * This could go through _render_glyph_bitmap as well, letting
+ * FreeType convert the outline to a bitmap, but doing it ourselves
+ * has two minor advantages: first, we save a copy of the bitmap
+ * buffer: we can directly use the buffer that FreeType renders
+ * into.
+ *
+ * Second, it may help when we add support for subpixel
+ * rendering: the Xft code does it this way. (Keith thinks that
+ * it may also be possible to get the subpixel rendering with
+ * FT_Render_Glyph: something worth looking into in more detail
+ * when we add subpixel support. If so, we may want to eliminate
+ * this version of the code path entirely.
+ */
+static cairo_status_t
+_render_glyph_outline (FT_Face                          face,
+		       cairo_image_glyph_cache_entry_t *val)
 {
-    ft_unscaled_font_t *unscaled = abstract_font;
-    FT_GlyphSlot glyphslot;
+    FT_GlyphSlot glyphslot = face->glyph;
+    FT_Outline *outline = &glyphslot->outline;
     unsigned int width, height, stride;
-    FT_Face face;
-    FT_Outline *outline;
-    FT_BBox cbox;
     FT_Bitmap bitmap;
-    FT_Glyph_Metrics *metrics;
+    FT_BBox cbox;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
-    face = _ft_unscaled_font_lock_face (unscaled);
-    if (!face)
-	return CAIRO_STATUS_NO_MEMORY;
-
-    glyphslot = face->glyph;
-    metrics = &glyphslot->metrics;
-
-    _ft_unscaled_font_set_scale (unscaled, &val->key.scale);
-
-    if (FT_Load_Glyph (face, val->key.index, val->key.flags) != 0) {
-	status = CAIRO_STATUS_NO_MEMORY;
-	goto FAIL;
-    }
-
-    /*
-     * Note: the font's coordinate system is upside down from ours, so the
-     * Y coordinates of the bearing and advance need to be negated.
-     *
-     * Scale metrics back to glyph space from the scaled glyph space returned
-     * by FreeType
-     */
-
-    val->extents.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) / unscaled->x_scale;
-    val->extents.y_bearing = -DOUBLE_FROM_26_6 (metrics->horiBearingY) / unscaled->y_scale;
-
-    val->extents.width  = DOUBLE_FROM_26_6 (metrics->width) / unscaled->x_scale;
-    val->extents.height = DOUBLE_FROM_26_6 (metrics->height) / unscaled->y_scale;
-
-    /*
-     * use untransformed advance values
-     * XXX uses horizontal advance only at present;
-     should provide FT_LOAD_VERTICAL_LAYOUT
-     */
-
-    val->extents.x_advance = DOUBLE_FROM_26_6 (face->glyph->metrics.horiAdvance) / unscaled->x_scale;
-    val->extents.y_advance = 0 / unscaled->y_scale;
-    
-    outline = &glyphslot->outline;
-
     FT_Outline_Get_CBox (outline, &cbox);
 
     cbox.xMin &= -64;
@@ -583,7 +578,7 @@ _cairo_ft_unscaled_font_create_glyph (vo
 	val->image = NULL;
     } else  {
 
-	bitmap.pixel_mode = ft_pixel_mode_grays;
+	bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
 	bitmap.num_grays  = 256;
 	bitmap.width = width;
 	bitmap.rows = height;
@@ -591,16 +586,14 @@ _cairo_ft_unscaled_font_create_glyph (vo
 	bitmap.buffer = calloc (1, stride * height);
 	
 	if (bitmap.buffer == NULL) {
-	    status = CAIRO_STATUS_NO_MEMORY;
-	    goto FAIL;
+	    return CAIRO_STATUS_NO_MEMORY;
 	}
 	
 	FT_Outline_Translate (outline, -cbox.xMin, -cbox.yMin);
 	
 	if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
 	    free (bitmap.buffer);
-	    status = CAIRO_STATUS_NO_MEMORY;
-	    goto FAIL;
+	    return CAIRO_STATUS_NO_MEMORY;
 	}
 	
 	val->image = (cairo_image_surface_t *)
@@ -609,8 +602,7 @@ _cairo_ft_unscaled_font_create_glyph (vo
 					     width, height, stride);
 	if (val->image == NULL) {
 	    free (bitmap.buffer);
-	    status = CAIRO_STATUS_NO_MEMORY;
-	    goto FAIL;
+	    return CAIRO_STATUS_NO_MEMORY;
 	}
 	
 	_cairo_image_surface_assume_ownership_of_data (val->image);
@@ -625,10 +617,167 @@ _cairo_ft_unscaled_font_create_glyph (vo
     val->size.height = (unsigned short) height;
     val->size.x =   (short) (cbox.xMin >> 6);
     val->size.y = - (short) (cbox.yMax >> 6);
+
+    return status;
+}
+
+/* Converts a bitmap (or other) FT_GlyphSlot into an image
+ * 
+ * This could go through _render_glyph_bitmap as well, letting
+ * FreeType convert the outline to a bitmap, but doing it ourselves
+ * has two minor advantages: first, we save a copy of the bitmap
+ * buffer: we can directly use the buffer that FreeType renders
+ * into.
+ *
+ * Second, it may help when we add support for subpixel
+ * rendering: the Xft code does it this way. (Keith thinks that
+ * it may also be possible to get the subpixel rendering with
+ * FT_Render_Glyph: something worth looking into in more detail
+ * when we add subpixel support. If so, we may want to eliminate
+ * this version of the code path entirely.
+ */
+static cairo_status_t
+_render_glyph_bitmap (FT_Face                          face,
+		      cairo_image_glyph_cache_entry_t *val)
+{
+    FT_GlyphSlot glyphslot = face->glyph;
+    FT_Bitmap *bitmap;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    int width, height, stride;
+    unsigned char *data;
+    FT_Error error;
+    int i, j;
+
+    /* According to the FreeType docs, glyphslot->format could be
+     * something other than FT_GLYPH_FORMAT_OUTLINE or
+     * FT_GLYPH_FORMAT_BITMAP. Calling FT_Render_Glyph gives FreeType
+     * the opportunity to convert such to
+     * bitmap. FT_GLYPH_FORMAT_COMPOSITE will not be encountered since
+     * we avoid the FT_LOAD_NO_RECURSE flag.
+     */
+    error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
+    if (error)
+	return CAIRO_STATUS_NO_MEMORY;
+
+    bitmap = &glyphslot->bitmap;
+
+    width = bitmap->width;
+    height = bitmap->rows;
+
+    if (width * height == 0) {
+	val->image = NULL;
+    } else {
+	switch (bitmap->pixel_mode) {
+	case FT_PIXEL_MODE_MONO:
+	    stride = (width + 3) & ~3;
+	    data = calloc (stride * height, 1);
+	    if (!data)
+		return CAIRO_STATUS_NO_MEMORY;
+	    for (j = 0; j < height; j++) {
+		const unsigned char *p = bitmap->buffer + j * bitmap->pitch;
+		unsigned char *q = data + j * stride;
+		for (i = 0; i < width; i++) {
+		    /* FreeType bitmaps are always stored MSB */
+		    unsigned char byte = p[i >> 3];
+		    unsigned char bit = 1 << (7 - (i % 8));
+
+		    if (byte & bit)
+			q[i] = 0xff;
+		}
+	    }
+	    break;
+	case FT_PIXEL_MODE_GRAY:
+	    stride = bitmap->pitch;
+	    data = malloc (stride * height);
+	    if (!data)
+		return CAIRO_STATUS_NO_MEMORY;
+	    memcpy (data, bitmap->buffer, stride * height);
+	    break;
+	case FT_PIXEL_MODE_GRAY2:
+	case FT_PIXEL_MODE_GRAY4:
+	    /* These could be triggered by very rare types of TrueType fonts */
+	case FT_PIXEL_MODE_LCD:
+	case FT_PIXEL_MODE_LCD_V:
+	    /* These should never be triggered unless we ask for them */
+	default:
+	    return CAIRO_STATUS_NO_MEMORY;
+	}
+	
+	val->image = (cairo_image_surface_t *)
+	    cairo_image_surface_create_for_data (data,
+						 CAIRO_FORMAT_A8,
+						 width, height, stride);
+	if (val->image == NULL) {
+	    free (data);
+	    return CAIRO_STATUS_NO_MEMORY;
+	}
+
+	_cairo_image_surface_assume_ownership_of_data (val->image);
+    }
+
+    val->size.width = width;
+    val->size.height = height;
+    val->size.x = - glyphslot->bitmap_left;
+    val->size.y = - glyphslot->bitmap_top;
+    
+    return status;
+}
+
+static cairo_status_t 
+_cairo_ft_unscaled_font_create_glyph (void                            *abstract_font,
+				      cairo_image_glyph_cache_entry_t *val)
+{
+    ft_unscaled_font_t *unscaled = abstract_font;
+    FT_GlyphSlot glyphslot;
+    FT_Face face;
+    FT_Glyph_Metrics *metrics;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+    face = _ft_unscaled_font_lock_face (unscaled);
+    if (!face)
+	return CAIRO_STATUS_NO_MEMORY;
+
+    glyphslot = face->glyph;
+    metrics = &glyphslot->metrics;
+
+    _ft_unscaled_font_set_scale (unscaled, &val->key.scale);
+
+    if (FT_Load_Glyph (face, val->key.index, val->key.flags) != 0) {
+	status = CAIRO_STATUS_NO_MEMORY;
+	goto FAIL;
+    }
+
+    /*
+     * Note: the font's coordinate system is upside down from ours, so the
+     * Y coordinates of the bearing and advance need to be negated.
+     *
+     * Scale metrics back to glyph space from the scaled glyph space returned
+     * by FreeType
+     */
+
+    val->extents.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) / unscaled->x_scale;
+    val->extents.y_bearing = -DOUBLE_FROM_26_6 (metrics->horiBearingY) / unscaled->y_scale;
+
+    val->extents.width  = DOUBLE_FROM_26_6 (metrics->width) / unscaled->x_scale;
+    val->extents.height = DOUBLE_FROM_26_6 (metrics->height) / unscaled->y_scale;
+
+    /*
+     * use untransformed advance values
+     * XXX uses horizontal advance only at present;
+     should provide FT_LOAD_VERTICAL_LAYOUT
+     */
+
+    val->extents.x_advance = DOUBLE_FROM_26_6 (face->glyph->metrics.horiAdvance) / unscaled->x_scale;
+    val->extents.y_advance = 0 / unscaled->y_scale;
+
+    if (glyphslot->format == FT_GLYPH_FORMAT_OUTLINE)
+	status = _render_glyph_outline (face, val);
+    else
+	status = _render_glyph_bitmap (face, val);
     
  FAIL:
     _ft_unscaled_font_unlock_face (unscaled);
-    
+
     return status;
 }
 
Index: src/cairo-ft-font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-ft-font.c,v
retrieving revision 1.66
diff -u -p -r1.66 cairo-ft-font.c
--- src/cairo-ft-font.c	24 Jun 2005 22:06:41 -0000	1.66
+++ src/cairo-ft-font.c	24 Jun 2005 23:10:49 -0000
@@ -86,10 +86,11 @@ typedef struct {
     int id;
 
     /* We temporarily scale the unscaled font as neede */
-    int have_scale;
+    cairo_bool_t have_scale;
     cairo_matrix_t current_scale;
     double x_scale;		/* Extracted X scale factor */
     double y_scale;             /* Extracted Y scale factor */
+    cairo_bool_t have_shape;	/* true if the current scale has a non-scale component*/
     
     int lock;		/* count of how many times this font has been locked */
 
@@ -474,6 +475,11 @@ _ft_unscaled_font_set_scale (ft_unscaled
     mat.xy = - DOUBLE_TO_16_16(sf.shape[1][0]);
     mat.yy = DOUBLE_TO_16_16(sf.shape[1][1]);
 
+    unscaled->have_shape = (mat.xx != 0x10000 ||
+			    mat.yx != 0x00000 ||
+			    mat.xy != 0x00000 ||
+			    mat.yy != 0x10000);
+    
     FT_Set_Transform(unscaled->face, &mat, NULL);
 
     if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {
@@ -723,6 +729,125 @@ _render_glyph_bitmap (FT_Face           
     return status;
 }
 
+static cairo_status_t
+_transform_glyph_bitmap (cairo_image_glyph_cache_entry_t *val)
+{
+    ft_font_transform_t sf;
+    cairo_matrix_t original_to_transformed;
+    cairo_matrix_t transformed_to_original;
+    cairo_image_surface_t *old_image;
+    cairo_surface_t *image;
+    double x[4], y[4];
+    double origin_x, origin_y;
+    int i;
+    int x_min, y_min, x_max, y_max;
+    int width, height;
+    cairo_status_t status;
+    cairo_surface_pattern_t pattern;
+    
+    /* We want to compute a transform that takes the origin
+     * (val->size.x, val->size.y) to 0,0, then applies the "shape"
+     * portion of the font transform
+     */
+    _compute_transform (&sf, &val->key.scale);
+
+    cairo_matrix_init (&original_to_transformed,
+		       sf.shape[0][0], sf.shape[0][1],
+		       sf.shape[1][0], sf.shape[1][1],
+		       0, 0);
+
+    cairo_matrix_translate (&original_to_transformed,
+			    val->size.x, val->size.y);
+
+    /* Find the bounding box of the original bitmap under that
+     * transform
+     */
+    x[0] = 0;               y[0] = 0;
+    x[1] = val->size.width; y[1] = 0;
+    x[2] = val->size.width; y[2] = val->size.height;
+    x[3] = 0;               y[3] = val->size.height;
+
+    for (i = 0; i < 4; i++)
+      cairo_matrix_transform_point (&original_to_transformed,
+				    &x[i], &y[i]);
+
+    x_min = floor (x[0]);   y_min = floor (y[0]);
+    x_max =  ceil (x[0]);   y_max =  ceil (y[0]);
+    
+    for (i = 1; i < 4; i++) {
+	if (x[i] < x_min)
+	    x_min = floor (x[i]);
+	if (x[i] > x_max)
+	    x_max = ceil (x[i]);
+	if (y[i] < y_min)
+	    y_min = floor (y[i]);
+	if (y[i] > y_max)
+	    y_max = ceil (y[i]);
+    }
+
+    /* Adjust the transform so that the bounding box starts at 0,0 ...
+     * this gives our final transform from original bitmap to transformed
+     * bitmap.
+     */
+    original_to_transformed.x0 -= x_min;
+    original_to_transformed.y0 -= y_min;
+
+    /* Create the transformed bitmap
+     */
+    width = x_max - x_min;
+    height = y_max - y_min;
+
+    transformed_to_original = original_to_transformed;
+    status = cairo_matrix_invert (&transformed_to_original);
+    if (status)
+	return status;
+
+    /* We need to pad out the width to 32-bit intervals for cairo-xlib-surface.c */
+    width = (width + 3) & ~3;
+    image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
+    if (!image)
+	return CAIRO_STATUS_NO_MEMORY;
+
+    /* Initialize it to empty
+     */
+    _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_SOURCE,
+				   CAIRO_COLOR_TRANSPARENT,
+				   0, 0,
+				   width, height);
+
+    /* Draw the original bitmap transformed into the new bitmap
+     */
+    _cairo_pattern_init_for_surface (&pattern, &val->image->base);
+    cairo_pattern_set_matrix (&pattern.base, &transformed_to_original);
+
+    _cairo_surface_composite (CAIRO_OPERATOR_OVER,
+			      &pattern.base, NULL, image,
+			      0, 0, 0, 0, 0, 0,
+			      width,
+			      height);
+
+    _cairo_pattern_fini (&pattern.base);
+
+    /* Now update the cache entry for the new bitmap, recomputing
+     * the origin based on the final transform.
+     */
+    origin_x = - val->size.x;
+    origin_y = - val->size.y;
+    cairo_matrix_transform_point (&original_to_transformed,
+				  &origin_x, &origin_y);
+
+    old_image = val->image;
+    val->image = (cairo_image_surface_t *)image;
+    cairo_surface_destroy (&old_image->base);
+
+    val->size.width = width;
+    val->size.height = height;
+    val->size.x = - floor (origin_x + 0.5);
+    val->size.y = - floor (origin_y + 0.5);
+    
+    return status;
+}
+
 static cairo_status_t 
 _cairo_ft_unscaled_font_create_glyph (void                            *abstract_font,
 				      cairo_image_glyph_cache_entry_t *val)
@@ -775,7 +900,16 @@ _cairo_ft_unscaled_font_create_glyph (vo
     else
 	status = _render_glyph_bitmap (face, val);
     
+    if (unscaled->have_shape &&
+	(unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) == 0)
+	status = _transform_glyph_bitmap (val);
+
  FAIL:
+    if (status && val->image) {
+	cairo_surface_destroy (&val->image->base);
+	val->image = NULL;
+    }
+	    
     _ft_unscaled_font_unlock_face (unscaled);
 
     return status;


Index: cairo.spec
===================================================================
RCS file: /cvs/dist/rpms/cairo/devel/cairo.spec,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- cairo.spec	22 Jun 2005 20:30:17 -0000	1.13
+++ cairo.spec	26 Jun 2005 19:50:33 -0000	1.14
@@ -1,7 +1,11 @@
+%define freetype_version 2.1.3-3
+%define fontconfig_version 2.0
+%define libpixman_version 0.1.5
+
 Summary:   A vector graphics library
 Name:      cairo
 Version:   0.5.1
-Release:   3
+Release:   4
 URL:       http://cairographics.org
 Source0:   %{name}-%{version}.tar.gz
 License:   LGPL/MPL
@@ -10,9 +14,13 @@
 
 Requires: /sbin/ldconfig
 BuildRequires: pkgconfig
-BuildRequires: libpixman-devel >= 0.1.5
-BuildRequires: freetype-devel >= 2.1.3-3
-BuildRequires: fontconfig-devel >= 2.0
+BuildRequires: libpixman-devel >= %{libpixman_version}
+BuildRequires: xorg-x11-devel
+BuildRequires: libpng-devel
+BuildRequires: freetype-devel >= %{freetype_version}
+BuildRequires: fontconfig-devel >= %{fontconfig_version}
+
+Patch0: cairo-0.5.1-bitmap-fonts.patch
 
 %description 
 Cairo is a vector graphics library designed to provide high-quality
@@ -27,7 +35,11 @@
 Summary: Cairo developmental libraries and header files
 Group: Development/Libraries
 Requires: %{name} = %{version}-%{release}
-Requires: libpixman-devel
+Requires: libpixman-devel >= %{pixman_version}
+Requires: xorg-x11-devel
+Requires: libpng-devel
+Requires: freetype-devel >= %{freetype_version}
+Requires: fontconfig-devel >= %{fontconfig_version}
 
 %description devel
 Developmental libraries and header files required for developing or
@@ -37,6 +49,8 @@
 %prep
 %setup -q
 
+%patch0 -p0 -b .bitmap-fonts
+
 %build
 %configure --enable-warnings --disable-glitz --disable-quartz \
 	--disable-atsui --disable-xcb --disable-win32 \
@@ -70,6 +84,12 @@
 %{_datadir}/gtk-doc/*
 
 %changelog
+* Sun Jun 26 2005 Kristian Høgsberg <krh at redhat.com> - 0.5.1-4
+- Add more missing devel package requires (libpng-devel and
+  xorg-x11-devel) (#161688)
+- Add Owens patch (cairo-0.5.1-bitmap-fonts.patch) to make bitmap
+  fonts work with cairo (#161653).
+
 * Wed Jun 22 2005 Kristian Høgsberg <krh at redhat.com> 0.5.1-3
 - Add requirement on libpixman-devel for devel package.
 




More information about the fedora-cvs-commits mailing list