[cairo-commit] 8 commits - src/cairo.c src/cairo-directfb-surface.c src/cairo-ft-font.c src/cairo-glitz-surface.c src/cairo-gstate.c src/cairoint.h src/cairo-matrix.c src/cairo-scaled-font.c src/cairo-win32-font.c src/cairo-win32-surface.c src/cairo-xcb-surface.c src/cairo-xlib-surface.c test/clip-operator.c

Carl Worth cworth at kemper.freedesktop.org
Wed Nov 22 16:26:37 PST 2006


 src/cairo-directfb-surface.c |   12 ++---
 src/cairo-ft-font.c          |    4 -
 src/cairo-glitz-surface.c    |    4 -
 src/cairo-gstate.c           |   92 +++++++++++++++++++++++++++++++++----------
 src/cairo-matrix.c           |   80 +++++++++++++++++++++----------------
 src/cairo-scaled-font.c      |   14 ++----
 src/cairo-win32-font.c       |   14 +++---
 src/cairo-win32-surface.c    |    7 +--
 src/cairo-xcb-surface.c      |   28 ++++++-------
 src/cairo-xlib-surface.c     |   16 +++----
 src/cairo.c                  |   25 +++++++++++
 src/cairoint.h               |    6 ++
 test/clip-operator.c         |    4 -
 13 files changed, 202 insertions(+), 104 deletions(-)

New commits:
diff-tree 11d21dbaa3604951f73b641e4d88723696157a8e (from 8a5e296239d1cac705c3c397ab1fd7f7f2ff8d58)
Author: Dan Amelang <dan at amelang.net>
Date:   Tue Nov 21 14:50:29 2006 -0800

    Change _cairo_matrix_to_pixman_matrix to use a pixman_transform_t as the template, thus avoiding a forced memcpy

diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index 7f43f23..d4f4bf7 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -725,16 +725,14 @@ void
 _cairo_matrix_to_pixman_matrix (const cairo_matrix_t	*matrix,
 				pixman_transform_t	*pixman_transform)
 {
-    static const pixman_fixed16_16_t pixman_identity_matrix[3][3] = {
+    static const pixman_transform_t pixman_identity_transform = {{
         {1 << 16,        0,       0},
         {       0, 1 << 16,       0},
         {       0,       0, 1 << 16}
-    };
+    }};
 
     if (_cairo_matrix_is_identity (matrix)) {
-        memcpy (pixman_transform->matrix,
-                &pixman_identity_matrix,
-                sizeof (pixman_identity_matrix));
+        *pixman_transform = pixman_identity_transform;
     }
     else {
         pixman_transform->matrix[0][0] = _cairo_fixed_from_double (matrix->xx);
diff-tree 8a5e296239d1cac705c3c397ab1fd7f7f2ff8d58 (from b7cd46ddc2a2523b4d33b22e07cdbdc09b90fa7d)
Author: Dan Amelang <dan at amelang.net>
Date:   Tue Nov 21 12:14:05 2006 -0800

    Optimize _cairo_matrix_to_pixman_matrix for the common case of an identity matrix

diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index ed5da92..7f43f23 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -725,15 +725,28 @@ void
 _cairo_matrix_to_pixman_matrix (const cairo_matrix_t	*matrix,
 				pixman_transform_t	*pixman_transform)
 {
-    pixman_transform->matrix[0][0] = _cairo_fixed_from_double (matrix->xx);
-    pixman_transform->matrix[0][1] = _cairo_fixed_from_double (matrix->xy);
-    pixman_transform->matrix[0][2] = _cairo_fixed_from_double (matrix->x0);
+    static const pixman_fixed16_16_t pixman_identity_matrix[3][3] = {
+        {1 << 16,        0,       0},
+        {       0, 1 << 16,       0},
+        {       0,       0, 1 << 16}
+    };
 
-    pixman_transform->matrix[1][0] = _cairo_fixed_from_double (matrix->yx);
-    pixman_transform->matrix[1][1] = _cairo_fixed_from_double (matrix->yy);
-    pixman_transform->matrix[1][2] = _cairo_fixed_from_double (matrix->y0);
+    if (_cairo_matrix_is_identity (matrix)) {
+        memcpy (pixman_transform->matrix,
+                &pixman_identity_matrix,
+                sizeof (pixman_identity_matrix));
+    }
+    else {
+        pixman_transform->matrix[0][0] = _cairo_fixed_from_double (matrix->xx);
+        pixman_transform->matrix[0][1] = _cairo_fixed_from_double (matrix->xy);
+        pixman_transform->matrix[0][2] = _cairo_fixed_from_double (matrix->x0);
 
-    pixman_transform->matrix[2][0] = 0;
-    pixman_transform->matrix[2][1] = 0;
-    pixman_transform->matrix[2][2] = _cairo_fixed_from_double (1);
+        pixman_transform->matrix[1][0] = _cairo_fixed_from_double (matrix->yx);
+        pixman_transform->matrix[1][1] = _cairo_fixed_from_double (matrix->yy);
+        pixman_transform->matrix[1][2] = _cairo_fixed_from_double (matrix->y0);
+
+        pixman_transform->matrix[2][0] = 0;
+        pixman_transform->matrix[2][1] = 0;
+        pixman_transform->matrix[2][2] = 1 << 16;
+    }
 }
diff-tree b7cd46ddc2a2523b4d33b22e07cdbdc09b90fa7d (from 6cfb4a01e005cb0f4f797ff9aa02e80b3d755a9e)
Author: Dan Amelang <dan at amelang.net>
Date:   Mon Nov 20 14:31:28 2006 -0800

    Add and incorporate _cairo_gstate_transform_glyphs_to_backend
    
    After changing _cairo_gstate_show_glyphs and _cairo_gstate_glyph_path to use
    this function, we see a significant speedup due to the elimination of redundant
    FP calculations.

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 8568186..d04c332 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -61,6 +61,12 @@ _cairo_gstate_ensure_scaled_font (cairo_
 static void
 _cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate);
 
+static void
+_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
+                                           const cairo_glyph_t *glyphs,
+                                           int                  num_glyphs,
+                                           cairo_glyph_t *transformed_glyphs);
+
 /**
  * _cairo_gstate_create:
  * @target: a #cairo_surface_t, not NULL
@@ -1466,7 +1472,6 @@ _cairo_gstate_show_glyphs (cairo_gstate_
     cairo_status_t status;
     cairo_pattern_union_t source_pattern;
     cairo_glyph_t *transformed_glyphs;
-    int i;
 
     if (gstate->source->status)
 	return gstate->source->status;
@@ -1483,15 +1488,8 @@ _cairo_gstate_show_glyphs (cairo_gstate_
     if (transformed_glyphs == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
-    for (i = 0; i < num_glyphs; ++i)
-    {
-	transformed_glyphs[i].index = glyphs[i].index;
-	transformed_glyphs[i].x = glyphs[i].x + gstate->font_matrix.x0;
-	transformed_glyphs[i].y = glyphs[i].y + gstate->font_matrix.y0;
-	_cairo_gstate_user_to_backend (gstate,
-				       &transformed_glyphs[i].x,
-				       &transformed_glyphs[i].y);
-    }
+    _cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
+                                               transformed_glyphs);
 
     _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
 
@@ -1515,7 +1513,6 @@ _cairo_gstate_glyph_path (cairo_gstate_t
 			  cairo_path_fixed_t *path)
 {
     cairo_status_t status;
-    int i;
     cairo_glyph_t *transformed_glyphs = NULL;
 
     status = _cairo_gstate_ensure_scaled_font (gstate);
@@ -1526,15 +1523,8 @@ _cairo_gstate_glyph_path (cairo_gstate_t
     if (transformed_glyphs == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
-    for (i = 0; i < num_glyphs; ++i)
-    {
-	transformed_glyphs[i].index = glyphs[i].index;
-	transformed_glyphs[i].x = glyphs[i].x + gstate->font_matrix.x0;
-	transformed_glyphs[i].y = glyphs[i].y + gstate->font_matrix.y0;
-	_cairo_gstate_user_to_backend (gstate,
-				       &(transformed_glyphs[i].x),
-				       &(transformed_glyphs[i].y));
-    }
+    _cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
+                                               transformed_glyphs);
 
     status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
 					    transformed_glyphs, num_glyphs,
@@ -1558,3 +1548,65 @@ _cairo_gstate_get_antialias (cairo_gstat
 {
     return gstate->antialias;
 }
+
+/**
+ * _cairo_gstate_transform_glyphs_to_backend:
+ * @gstate: a #cairo_gstate_t
+ * @glyphs: the array of #cairo_glyph_t objects to be transformed
+ * @num_glyphs: the number of elements in @glyphs
+ * @transformed_glyphs: a pre-allocated array of at least @num_glyphs
+ * #cairo_glyph_t objects
+ *
+ * Transform an array of glyphs to backend space by first adding the offset
+ * of the font matrix, then transforming from user space to backend space.
+ * The result of the transformation is placed in @transformed_glyphs.
+ **/
+static void
+_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
+                                           const cairo_glyph_t *glyphs,
+                                           int                  num_glyphs,
+                                           cairo_glyph_t *transformed_glyphs)
+{
+    int i;
+    cairo_matrix_t *ctm = &gstate->ctm;
+    cairo_matrix_t *device_transform = &gstate->target->device_transform;
+
+    if (_cairo_matrix_is_identity (ctm) &&
+        _cairo_matrix_is_identity (device_transform))
+    {
+        memcpy (transformed_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
+    }
+    else if (_cairo_matrix_is_translation (ctm) &&
+             _cairo_matrix_is_translation (device_transform))
+    {
+        double tx = gstate->font_matrix.x0 + ctm->x0 + device_transform->x0;
+        double ty = gstate->font_matrix.y0 + ctm->y0 + device_transform->y0;
+
+        for (i = 0; i < num_glyphs; i++)
+        {
+            transformed_glyphs[i].index = glyphs[i].index;
+            transformed_glyphs[i].x = glyphs[i].x + tx;
+            transformed_glyphs[i].y = glyphs[i].y + ty;
+        }
+    }
+    else
+    {
+        cairo_matrix_t aggregate_transform;
+
+        cairo_matrix_init_translate (&aggregate_transform,
+                                     gstate->font_matrix.x0,
+                                     gstate->font_matrix.y0);
+        cairo_matrix_multiply (&aggregate_transform,
+                               &aggregate_transform, ctm);
+        cairo_matrix_multiply (&aggregate_transform,
+                               &aggregate_transform, device_transform);
+
+        for (i = 0; i < num_glyphs; i++)
+        {
+            transformed_glyphs[i] = glyphs[i];
+            cairo_matrix_transform_point (&aggregate_transform,
+                                          &transformed_glyphs[i].x,
+                                          &transformed_glyphs[i].y);
+        }
+    }
+}
diff-tree 6cfb4a01e005cb0f4f797ff9aa02e80b3d755a9e (from ca79307bdf9bc8042c9afd570bf10d605d3dfc1e)
Author: Dan Amelang <dan at amelang.net>
Date:   Mon Nov 20 14:08:46 2006 -0800

    Refactor _cairo_matrix_is_integer_translation
    
    Now that we have _cairo_matrix_is_translation, we can change
    _cairo_matrix_is_integer_translation to use it and thus reduce code
    duplication.

diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index ee30058..ed5da92 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -556,31 +556,27 @@ _cairo_matrix_is_translation (const cair
 }
 
 cairo_bool_t
-_cairo_matrix_is_integer_translation(const cairo_matrix_t *m,
-				     int *itx, int *ity)
+_cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix,
+				      int *itx, int *ity)
 {
-    cairo_bool_t is_integer_translation;
-    cairo_fixed_t x0_fixed, y0_fixed;
+    if (_cairo_matrix_is_translation (matrix))
+    {
+        cairo_fixed_t x0_fixed = _cairo_fixed_from_double (matrix->x0);
+        cairo_fixed_t y0_fixed = _cairo_fixed_from_double (matrix->y0);
+
+        if (_cairo_fixed_is_integer (x0_fixed) &&
+            _cairo_fixed_is_integer (y0_fixed))
+        {
+            if (itx)
+                *itx = _cairo_fixed_integer_part (x0_fixed);
+            if (ity)
+                *ity = _cairo_fixed_integer_part (y0_fixed);
+
+            return TRUE;
+        }
+    }
 
-    x0_fixed = _cairo_fixed_from_double (m->x0);
-    y0_fixed = _cairo_fixed_from_double (m->y0);
-
-    is_integer_translation = ((m->xx == 1.0) &&
-			      (m->yx == 0.0) &&
-			      (m->xy == 0.0) &&
-			      (m->yy == 1.0) &&
-			      (_cairo_fixed_is_integer(x0_fixed)) &&
-			      (_cairo_fixed_is_integer(y0_fixed)));
-
-    if (! is_integer_translation)
-	return FALSE;
-
-    if (itx)
-	*itx = _cairo_fixed_integer_part(x0_fixed);
-    if (ity)
-	*ity = _cairo_fixed_integer_part(y0_fixed);
-
-    return TRUE;
+    return FALSE;
 }
 
 /*
diff-tree ca79307bdf9bc8042c9afd570bf10d605d3dfc1e (from 57fba8d9b6915fe4b0f506ecb2ef18a9002de370)
Author: Dan Amelang <dan at amelang.net>
Date:   Mon Nov 20 10:42:50 2006 -0800

    Add _cairo_matrix_is_translation

diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index e2f353b..ee30058 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -549,6 +549,13 @@ _cairo_matrix_is_identity (const cairo_m
 }
 
 cairo_bool_t
+_cairo_matrix_is_translation (const cairo_matrix_t *matrix)
+{
+    return (matrix->xx == 1.0 && matrix->yx == 0.0 &&
+	    matrix->xy == 0.0 && matrix->yy == 1.0);
+}
+
+cairo_bool_t
 _cairo_matrix_is_integer_translation(const cairo_matrix_t *m,
 				     int *itx, int *ity)
 {
diff --git a/src/cairoint.h b/src/cairoint.h
index dba5755..2ae9090 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2198,6 +2198,9 @@ cairo_private cairo_bool_t
 _cairo_matrix_is_identity (const cairo_matrix_t *matrix);
 
 cairo_private cairo_bool_t
+_cairo_matrix_is_translation (const cairo_matrix_t *matrix);
+
+cairo_private cairo_bool_t
 _cairo_matrix_is_integer_translation(const cairo_matrix_t *matrix,
 				     int *itx, int *ity);
 
diff-tree 57fba8d9b6915fe4b0f506ecb2ef18a9002de370 (from efb483c3a36f8168d52086c2f61162f5a0306c15)
Author: Daniel Amelang <dan at ereba.localdomain>
Date:   Thu Nov 2 22:24:34 2006 -0800

    Replace existing rounding code with _cairo_lround

diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index e724ed6..fc6cbef 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -889,10 +889,10 @@ _cairo_directfb_surface_composite (cairo
                 TRANSFORM_POINT (m, sr.x, sr.y, x1, y1);
                 TRANSFORM_POINT (m, sr.x+sr.w, sr.y+sr.h, x2, y2);
                 
-                dr.x = floor (x1+.5);
-                dr.y = floor (y1+.5);
-                dr.w = floor (x2-x1+.5);
-                dr.h = floor (y2-y1+.5);
+                dr.x = _cairo_lround (x1);
+                dr.y = _cairo_lround (y1);
+                dr.w = _cairo_lround (x2-x1);
+                dr.h = _cairo_lround (y2-y1);
         
                 D_DEBUG_AT (Cairo_DirectFB, "Running StretchBlit().\n");
 
@@ -1283,8 +1283,8 @@ _directfb_acquire_font_cache (cairo_dire
                 return CAIRO_INT_STATUS_UNSUPPORTED;
         }
         
-        points[n].x = floor (glyphs[i].x + img->base.device_transform.x0 + .5);
-        points[n].y = floor (glyphs[i].y + img->base.device_transform.y0 + .5);
+        points[n].x = _cairo_lround (glyphs[i].x + img->base.device_transform.x0);
+        points[n].y = _cairo_lround (glyphs[i].y + img->base.device_transform.y0);
         
         if (points[n].x >= surface->width  ||
             points[n].y >= surface->height ||
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 25fabc9..59a5acb 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -1178,8 +1178,8 @@ _transform_glyph_bitmap (cairo_matrix_t 
     cairo_surface_destroy (&old_image->base);
 
     cairo_surface_set_device_offset (&(*surface)->base,
-				     - floor (origin_x + 0.5),
-				     - floor (origin_y + 0.5));
+				     - _cairo_lround (origin_x),
+				     - _cairo_lround (origin_y));
     return status;
 }
 
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index febaa4a..a579511 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -2015,8 +2015,8 @@ _cairo_glitz_surface_old_show_glyphs (ca
 		x_offset = scaled_glyphs[i]->surface->base.device_transform.x0;
 		y_offset = scaled_glyphs[i]->surface->base.device_transform.y0;
 
-		x1 = floor (glyphs[i].x + 0.5) + x_offset;
-		y1 = floor (glyphs[i].y + 0.5) + y_offset;
+		x1 = _cairo_lround (glyphs[i].x) + x_offset;
+		y1 = _cairo_lround (glyphs[i].y) + y_offset;
 		x2 = x1 + glyph_private->area->width;
 		y2 = y1 + glyph_private->area->height;
 
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 0a96b9d..0b060fd 100755
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -855,8 +855,8 @@ _cairo_scaled_font_glyph_device_extents 
 	}
 
 	/* glyph images are snapped to pixel locations */
-	x = (int) floor (glyphs[i].x + 0.5);
-	y = (int) floor (glyphs[i].y + 0.5);
+	x = _cairo_lround (glyphs[i].x);
+	y = _cairo_lround (glyphs[i].y);
 
 	left   = x + _cairo_fixed_integer_floor(scaled_glyph->bbox.p1.x);
 	top    = y + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
@@ -964,12 +964,10 @@ _cairo_scaled_font_show_glyphs (cairo_sc
 
 	/* round glyph locations to the nearest pixel */
 	/* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
-	x = (int) floor (glyphs[i].x +
-                         glyph_surface->base.device_transform.x0 +
-                         0.5);
-	y = (int) floor (glyphs[i].y +
-                         glyph_surface->base.device_transform.y0 +
-                         0.5);
+	x = _cairo_lround (glyphs[i].x +
+                           glyph_surface->base.device_transform.x0);
+	y = _cairo_lround (glyphs[i].y +
+                           glyph_surface->base.device_transform.y0);
 
 	_cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base);
 
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index ee8cd3e..58b4dd1 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -151,7 +151,8 @@ _compute_transform (cairo_win32_scaled_f
 	    scaled_font->y_scale = - scaled_font->y_scale;
 
 	scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale;
-	scaled_font->logical_size = WIN32_FONT_LOGICAL_SCALE * floor (scaled_font->y_scale + 0.5);
+	scaled_font->logical_size = WIN32_FONT_LOGICAL_SCALE *
+                                    _cairo_lround (scaled_font->y_scale);
     }
 
     /* The font matrix has x and y "scale" components which we extract and
@@ -165,7 +166,8 @@ _compute_transform (cairo_win32_scaled_f
 					     &scaled_font->x_scale, &scaled_font->y_scale,
 					     TRUE);	/* XXX: Handle vertical text */
 
-	scaled_font->logical_size = floor (WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale + 0.5);
+	scaled_font->logical_size = _cairo_lround (WIN32_FONT_LOGICAL_SCALE *
+                                                   scaled_font->y_scale);
 	scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale;
     }
 
@@ -864,8 +866,8 @@ _cairo_win32_scaled_font_glyph_bbox (voi
             glyph_index_option = 0;
 
 	for (i = 0; i < num_glyphs; i++) {
-	    int x = floor (0.5 + glyphs[i].x);
-	    int y = floor (0.5 + glyphs[i].y);
+	    int x = _cairo_lround (glyphs[i].x);
+	    int y = _cairo_lround (glyphs[i].y);
 
 	    GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | glyph_index_option,
 			     &metrics, 0, NULL, &matrix);
@@ -966,8 +968,8 @@ _add_glyph (cairo_glyph_state_t *state,
 
     cairo_matrix_transform_point (&state->scaled_font->device_to_logical, &user_x, &user_y);
 
-    logical_x = floor (user_x + 0.5);
-    logical_y = floor (user_y + 0.5);
+    logical_x = _cairo_lround (user_x);
+    logical_y = _cairo_lround (user_y);
 
     if (state->glyphs.num_elements > 0) {
 	int dx;
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index f11895a..a90f867 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -1541,7 +1541,8 @@ _cairo_win32_surface_show_glyphs (void		
 	if (i == num_glyphs - 1)
 	    dx_buf[i] = 0;
 	else
-	    dx_buf[i] = (int) floor(((glyphs[i+1].x - glyphs[i].x) * WIN32_FONT_LOGICAL_SCALE) + 0.5);
+	    dx_buf[i] = _cairo_lround ((glyphs[i+1].x - glyphs[i].x) *
+                                       WIN32_FONT_LOGICAL_SCALE);
 
 	if (i == num_glyphs - 1 || glyphs[i].y != glyphs[i+1].y) {
 	    const int offset = (i - output_count) + 1;
@@ -1552,8 +1553,8 @@ _cairo_win32_surface_show_glyphs (void		
 	    cairo_matrix_transform_point(&device_to_logical,
 					 &user_x, &user_y);
 
-	    logical_x = (int) floor(user_x + 0.5);
-	    logical_y = (int) floor(user_y + 0.5);
+	    logical_x = _cairo_lround (user_x);
+	    logical_y = _cairo_lround (user_y);
 
 	    win_result = ExtTextOutW(dst->dc,
 				     logical_x,
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 046c620..9c34879 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -2039,8 +2039,8 @@ _cairo_xcb_surface_add_glyph (xcb_connec
      */
 
     /* XXX: FRAGILE: We're ignore device_transform scaling here. A bug? */
-    glyph_info.x = - (int) floor(glyph_surface->base.device_transform.x0 + 0.5);
-    glyph_info.y = - (int) floor(glyph_surface->base.device_transform.y0 + 0.5);
+    glyph_info.x = - _cairo_lround (glyph_surface->base.device_transform.x0);
+    glyph_info.y = - _cairo_lround (glyph_surface->base.device_transform.y0);
     glyph_info.width = glyph_surface->width;
     glyph_info.height = glyph_surface->height;
     glyph_info.x_off = 0;
@@ -2148,8 +2148,8 @@ _cairo_xcb_surface_show_glyphs_8  (cairo
     stream = xcb_render_util_composite_text_stream (font_private->glyphset, num_glyphs, 0);
 
     for (i = 0; i < num_glyphs; ++i) {
-	thisX = (int) floor (glyphs[i].x + 0.5);
-	thisY = (int) floor (glyphs[i].y + 0.5);
+	thisX = _cairo_lround (glyphs[i].x);
+	thisY = _cairo_lround (glyphs[i].y);
 	glyph = glyphs[i].index;
 	xcb_render_util_glyphs_8 (stream, thisX - lastX, thisY - lastY, 1, &glyph);
 	lastX = thisX;
@@ -2161,8 +2161,8 @@ _cairo_xcb_surface_show_glyphs_8  (cairo
 			    src->src_picture,
 			    dst->dst_picture,
 			    font_private->xrender_format->id,
-                            src_x_offset + (int) floor (glyphs[0].x + 0.5),
-                            src_y_offset + (int) floor (glyphs[0].y + 0.5),
+                            src_x_offset + _cairo_lround (glyphs[0].x),
+                            src_y_offset + _cairo_lround (glyphs[0].y),
 			    stream);
 
     xcb_render_util_composite_text_free (stream);
@@ -2189,8 +2189,8 @@ _cairo_xcb_surface_show_glyphs_16 (cairo
     stream = xcb_render_util_composite_text_stream (font_private->glyphset, num_glyphs, 0);
 
     for (i = 0; i < num_glyphs; ++i) {
-	thisX = (int) floor (glyphs[i].x + 0.5);
-	thisY = (int) floor (glyphs[i].y + 0.5);
+	thisX = _cairo_lround (glyphs[i].x);
+	thisY = _cairo_lround (glyphs[i].y);
 	glyph = glyphs[i].index;
 	xcb_render_util_glyphs_16 (stream, thisX - lastX, thisY - lastY, 1, &glyph);
 	lastX = thisX;
@@ -2202,8 +2202,8 @@ _cairo_xcb_surface_show_glyphs_16 (cairo
 			    src->src_picture,
 			    dst->dst_picture,
 			    font_private->xrender_format->id,
-                            src_x_offset + (int) floor (glyphs[0].x + 0.5),
-                            src_y_offset + (int) floor (glyphs[0].y + 0.5),
+                            src_x_offset + _cairo_lround (glyphs[0].x),
+                            src_y_offset + _cairo_lround (glyphs[0].y),
 			    stream);
 
     xcb_render_util_composite_text_free (stream);
@@ -2230,8 +2230,8 @@ _cairo_xcb_surface_show_glyphs_32 (cairo
     stream = xcb_render_util_composite_text_stream (font_private->glyphset, num_glyphs, 0);
 
     for (i = 0; i < num_glyphs; ++i) {
-	thisX = (int) floor (glyphs[i].x + 0.5);
-	thisY = (int) floor (glyphs[i].y + 0.5);
+	thisX = _cairo_lround (glyphs[i].x);
+	thisY = _cairo_lround (glyphs[i].y);
 	glyph = glyphs[i].index;
 	xcb_render_util_glyphs_32 (stream, thisX - lastX, thisY - lastY, 1, &glyph);
 	lastX = thisX;
@@ -2243,8 +2243,8 @@ _cairo_xcb_surface_show_glyphs_32 (cairo
 			    src->src_picture,
 			    dst->dst_picture,
 			    font_private->xrender_format->id,
-                            src_x_offset + (int) floor (glyphs[0].x + 0.5),
-                            src_y_offset + (int) floor (glyphs[0].y + 0.5),
+                            src_x_offset + _cairo_lround (glyphs[0].x),
+                            src_y_offset + _cairo_lround (glyphs[0].y),
 			    stream);
 
     xcb_render_util_composite_text_free (stream);
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index aaf43e4..4e7f640 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2408,8 +2408,8 @@ _cairo_xlib_surface_add_glyph (Display *
      */
 
     /* XXX: FRAGILE: We're ignore device_transform scaling here. A bug? */
-    glyph_info.x = - (int) floor(glyph_surface->base.device_transform.x0 + 0.5);
-    glyph_info.y = - (int) floor(glyph_surface->base.device_transform.y0 + 0.5);
+    glyph_info.x = - _cairo_lround (glyph_surface->base.device_transform.x0);
+    glyph_info.y = - _cairo_lround (glyph_surface->base.device_transform.y0);
     glyph_info.width = glyph_surface->width;
     glyph_info.height = glyph_surface->height;
     glyph_info.xOff = 0;
@@ -2536,8 +2536,8 @@ _cairo_xlib_surface_show_glyphs8  (cairo
 	elts[i].chars = &(chars[i]);
 	elts[i].nchars = 1;
 	elts[i].glyphset = font_private->glyphset;
-	thisX = (int) floor (glyphs[i].x + 0.5);
-	thisY = (int) floor (glyphs[i].y + 0.5);
+	thisX = _cairo_lround (glyphs[i].x);
+	thisY = _cairo_lround (glyphs[i].y);
 	elts[i].xOff = thisX - lastX;
 	elts[i].yOff = thisY - lastY;
 	lastX = thisX;
@@ -2597,8 +2597,8 @@ _cairo_xlib_surface_show_glyphs16 (cairo
 	elts[i].chars = &(chars[i]);
 	elts[i].nchars = 1;
 	elts[i].glyphset = font_private->glyphset;
-	thisX = (int) floor (glyphs[i].x + 0.5);
-	thisY = (int) floor (glyphs[i].y + 0.5);
+	thisX = _cairo_lround (glyphs[i].x);
+	thisY = _cairo_lround (glyphs[i].y);
 	elts[i].xOff = thisX - lastX;
 	elts[i].yOff = thisY - lastY;
 	lastX = thisX;
@@ -2658,8 +2658,8 @@ _cairo_xlib_surface_show_glyphs32 (cairo
 	elts[i].chars = &(chars[i]);
 	elts[i].nchars = 1;
 	elts[i].glyphset = font_private->glyphset;
-	thisX = (int) floor (glyphs[i].x + 0.5);
-	thisY = (int) floor (glyphs[i].y + 0.5);
+	thisX = _cairo_lround (glyphs[i].x);
+	thisY = _cairo_lround (glyphs[i].y);
 	elts[i].xOff = thisX - lastX;
 	elts[i].yOff = thisY - lastY;
 	lastX = thisX;
diff-tree efb483c3a36f8168d52086c2f61162f5a0306c15 (from 166dffc96aa26b21f87f12af22b11630583cc85b)
Author: Daniel Amelang <dan at ereba.localdomain>
Date:   Thu Nov 2 22:22:17 2006 -0800

    Add _cairo_lround for much faster rounding
    
    This function uses the same "magic number" approach as _cairo_fixed_from_double.

diff --git a/src/cairo.c b/src/cairo.c
index 15230ed..ce6a728 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -3196,3 +3196,28 @@ _cairo_restrict_value (double *value, do
     else if (*value > max)
 	*value = max;
 }
+
+/* This function is identical to the C99 function lround, except that it
+ * uses banker's rounding instead of arithmetic rounding. This implementation
+ * is much faster (on the platforms we care about) than lround, round, rint,
+ * lrint or float (d + 0.5).
+ *
+ * For an explanation of the inner workings of this implemenation, see the
+ * documentation for _cairo_fixed_from_double.
+ */
+#define CAIRO_MAGIC_NUMBER_INT (6755399441055744.0)
+int
+_cairo_lround (double d)
+{
+    union {
+        double d;
+        int32_t i[2];
+    } u;
+
+    u.d = d + CAIRO_MAGIC_NUMBER_INT;
+#ifdef FLOAT_WORDS_BIGENDIAN
+    return u.i[1];
+#else
+    return u.i[0];
+#endif
+}
diff --git a/src/cairoint.h b/src/cairoint.h
index 1f86fba..dba5755 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1155,6 +1155,9 @@ typedef struct _cairo_stroke_face {
 cairo_private void
 _cairo_restrict_value (double *value, double min, double max);
 
+cairo_private int
+_cairo_lround (double d);
+
 /* cairo_fixed.c */
 cairo_private cairo_fixed_t
 _cairo_fixed_from_int (int i);
diff-tree 166dffc96aa26b21f87f12af22b11630583cc85b (from eaaeba170d4c8313443412d88ee63311723b546d)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Nov 21 20:57:01 2006 -0800

    test/clip-operator: Use round to pass only integers to cairo_show_glyphs
    
    We were previously passing half-integer values here, which will
    not be robust to changes in the rounding mode used for
    cairo_show_glyphs. Use round() to match the rounding expected
    by the reference images.

diff --git a/test/clip-operator.c b/test/clip-operator.c
index 4e533c6..22bdab0 100644
--- a/test/clip-operator.c
+++ b/test/clip-operator.c
@@ -76,8 +76,8 @@ draw_glyphs (cairo_t *cr, int x, int y)
 
     cairo_text_extents (cr, "FG", &extents);
     cairo_move_to (cr,
-		   x + (WIDTH - extents.width) / 2 - extents.x_bearing,
-		   y + (HEIGHT - extents.height) / 2 - extents.y_bearing);
+		   x + round ((WIDTH - extents.width) / 2) - extents.x_bearing,
+		   y + round ((HEIGHT - extents.height) / 2) - extents.y_bearing);
     cairo_show_text (cr, "FG");
 }
 


More information about the cairo-commit mailing list