? ASDF
? pango-matrix.c.new
? pango-utils.c.new
Index: pango-layout.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-layout.c,v
retrieving revision 1.176
diff -u -p -d -r1.176 pango-layout.c
--- pango-layout.c	30 May 2006 04:23:40 -0000	1.176
+++ pango-layout.c	7 Jul 2006 05:01:30 -0000
@@ -2246,9 +2246,8 @@ pango_layout_get_extents (PangoLayout   
  *              layout or %NULL to indicate that the result is not needed.
  * 
  * Computes the logical and ink extents of @layout in device units.
- * See pango_layout_get_extents(); this function just calls
- * pango_layout_get_extents() and then converts the extents to
- * device units using the %PANGO_SCALE factor.
+ * This function just calls pango_layout_get_extents() followed by
+ * pango_rectangle_to_pixels().
  **/
 void
 pango_layout_get_pixel_extents (PangoLayout *layout,
@@ -2259,29 +2258,43 @@ pango_layout_get_pixel_extents (PangoLay
 
   pango_layout_get_extents (layout, ink_rect, logical_rect);
 
-  if (ink_rect)
-    {
-      int orig_x = ink_rect->x;
-      int orig_y = ink_rect->y;
+  pango_rectangle_to_pixels (ink_rect, logical_rect);
+}
 
-      ink_rect->x = PANGO_PIXELS_FLOOR (ink_rect->x);
-      ink_rect->y = PANGO_PIXELS_FLOOR (ink_rect->y);
+/**
+ * pango_layout_get_transformed_pixel_extents:
+ * @layout:   a #PangoLayout
+ * @ink_rect: rectangle used to store the transformed extents of the layout as drawn
+ *            or %NULL to indicate that the result is not needed.
+ * @logical_rect: rectangle used to store the transformed logical extents of the 
+ *              layout or %NULL to indicate that the result is not needed.
+ * 
+ * Computes the logical and ink extents of @layout in device units,
+ * transformed using the #PangoMatrix of the #PangoContext associated with
+ * @layout.
+ * This is equivalent to calling pango_layout_get_extents() followed by
+ * pango_matrix_transform_bounding_box_to_pixels() on both rectangles with the
+ * above-mentioned matrix.
+ *
+ * Since: 1.14
+ **/
+void
+pango_layout_get_transformed_pixel_extents (PangoLayout *layout,
+					    PangoRectangle *ink_rect,
+					    PangoRectangle *logical_rect)
+{
+  PangoContext *context;
+  const PangoMatrix *matrix;
 
-      ink_rect->width  = PANGO_PIXELS_CEIL (orig_x + ink_rect->width ) - ink_rect->x;
-      ink_rect->height = PANGO_PIXELS_CEIL (orig_y + ink_rect->height) - ink_rect->y;
-    }
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
 
-  if (logical_rect)
-    {
-      int orig_x = logical_rect->x;
-      int orig_y = logical_rect->y;
+  context = pango_layout_get_context (layout);
+  matrix = pango_context_get_matrix (context);
 
-      logical_rect->x = PANGO_PIXELS (logical_rect->x);
-      logical_rect->y = PANGO_PIXELS (logical_rect->y);
+  pango_layout_get_extents (layout, ink_rect, logical_rect);
 
-      logical_rect->width  = PANGO_PIXELS (orig_x + logical_rect->width ) - logical_rect->x;
-      logical_rect->height = PANGO_PIXELS (orig_y + logical_rect->height) - logical_rect->y;
-    }
+  pango_matrix_transform_bounding_box_to_pixels (matrix, ink_rect);
+  pango_matrix_transform_bounding_box_to_pixels (matrix, logical_rect);
 }
 
 /**
@@ -4100,11 +4113,9 @@ pango_layout_line_new (PangoLayout *layo
  * @logical_rect: rectangle used to store the logical extents of the glyph
  *               string, or %NULL
  * 
- * Computes the logical and ink extents of a layout line. See
- * pango_font_get_glyph_extents() for details about the interpretation
- * of the rectangles. The returned rectangles are in device units, as
- * opposed to pango_layout_line_get_extents(), which returns the extents in
- * #PangoGlyphUnit.
+ * Computes the logical and ink extents of @layout_line in device units.
+ * This function just calls pango_layout_line_get_extents() followed by
+ * pango_rectangle_to_pixels().
  **/
 void
 pango_layout_line_get_pixel_extents (PangoLayoutLine *layout_line,
@@ -4115,23 +4126,7 @@ pango_layout_line_get_pixel_extents (Pan
 
   pango_layout_line_get_extents (layout_line, ink_rect, logical_rect);
 
-  if (ink_rect)
-    {
-      ink_rect->width = (ink_rect->width + PANGO_SCALE / 2) / PANGO_SCALE;
-      ink_rect->height = (ink_rect->height + PANGO_SCALE / 2) / PANGO_SCALE;
-
-      ink_rect->x = PANGO_PIXELS (ink_rect->x);
-      ink_rect->y = PANGO_PIXELS (ink_rect->y);
-    }
-
-  if (logical_rect)
-    {
-      logical_rect->width = (logical_rect->width + PANGO_SCALE / 2) / PANGO_SCALE;
-      logical_rect->height = (logical_rect->height + PANGO_SCALE / 2) / PANGO_SCALE;
-
-      logical_rect->x = PANGO_PIXELS (logical_rect->x);
-      logical_rect->y = PANGO_PIXELS (logical_rect->y);
-    }
+  pango_rectangle_to_pixels (ink_rect, logical_rect);
 }
 
 /*
Index: pango-layout.h
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-layout.h,v
retrieving revision 1.37
diff -u -p -d -r1.37 pango-layout.h
--- pango-layout.h	4 Nov 2005 23:55:37 -0000	1.37
+++ pango-layout.h	7 Jul 2006 05:01:30 -0000
@@ -190,6 +190,10 @@ void     pango_layout_get_extents       
 void     pango_layout_get_pixel_extents    (PangoLayout    *layout,
 					    PangoRectangle *ink_rect,
 					    PangoRectangle *logical_rect);
+void     pango_layout_get_transformed_pixel_extents
+					   (PangoLayout    *layout,
+					    PangoRectangle *ink_rect,
+					    PangoRectangle *logical_rect);
 void     pango_layout_get_size             (PangoLayout    *layout,
 					    int            *width,
 					    int            *height);
Index: pango-matrix.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-matrix.c,v
retrieving revision 1.1
diff -u -p -d -r1.1 pango-matrix.c
--- pango-matrix.c	7 Jul 2006 05:01:06 -0000	1.1
+++ pango-matrix.c	7 Jul 2006 05:01:30 -0000
@@ -248,3 +248,150 @@ pango_matrix_get_font_scale_factor (cons
       return minor;
     }
 }
+
+/**
+ * pango_matrix_transform_distance:
+ * @matrix: a #PangoMatrix, or %NULL
+ * @dx: in/out X component of a distance vector
+ * @dy: yn/out Y component of a distance vector
+ *
+ * Transforms the distance vector (@dx,@dy) by @matrix. This is
+ * similar to pango_matrix_transform_point() except that the translation
+ * components of the transformation are ignored. The calculation of
+ * the returned vector is as follows:
+ *
+ * <programlisting>
+ * dx2 = dx1 * xx + dy1 * xy;
+ * dy2 = dx1 * yx + dy1 * yy;
+ * </programlisting>
+ *
+ * Affine transformations are position invariant, so the same vector
+ * always transforms to the same vector. If (@x1,@y1) transforms
+ * to (@x2,@y2) then (@x1+@dx1,@y1+@dy1) will transform to
+ * (@x1+@dx2,@y1+@dy2) for all values of @x1 and @x2.
+ *
+ * Since: 1.14
+ **/
+void
+pango_matrix_transform_distance (const PangoMatrix *matrix,
+				 double            *dx,
+				 double            *dy)
+{
+  if (matrix)
+    {
+      double new_x, new_y;
+
+      new_x = (matrix->xx * *dx + matrix->xy * *dy);
+      new_y = (matrix->yx * *dx + matrix->yy * *dy);
+
+      *dx = new_x;
+      *dy = new_y;
+    }
+}
+
+/**
+ * pango_matrix_transform_point:
+ * @matrix: a #PangoMatrix, or %NULL
+ * @x: in/out X position
+ * @y: in/out Y position
+ * 
+ * Transforms the point (@x, @y) by @matrix.
+ *
+ * Since: 1.14
+ **/
+void
+pango_matrix_transform_point (const PangoMatrix *matrix,
+			      double            *x,
+			      double            *y)
+{
+  if (matrix)
+    {
+      pango_matrix_transform_distance (matrix, x, y);
+
+      *x += matrix->x0;
+      *y += matrix->y0;
+    }
+}
+
+/**
+ * pango_matrix_transform_bounding_box_to_pixels:
+ * @matrix: a #PangoMatrix, or %NULL
+ * @rect: in/out bounding box, or %NULL
+ * 
+ * First transforms the @rect using @matrix, then calculates the bounding box
+ * of the transformed rectangle, and finally converts that to pixels, rounding
+ * such that the final bounding box completely contains the transformed
+ * rectangle (like the ink_rect parameter is rounded with
+ * pango_rectangle_to_pixels().)
+ *
+ * This function is useful for example when you want to draw a rotated
+ * @PangoLayout to an image buffer, and want to know how large the image
+ * should be and how much you should shift the layout when rendering.
+ *
+ * Note that the input rectangle is in Pango units, while the output is in
+ * pixels.  The input is typically one of the extents returned from
+ * pango_layout_get_extents(), depending on what you actually need.
+ *
+ * Since: 1.14
+ **/
+void
+pango_matrix_transform_bounding_box_to_pixels (const PangoMatrix *matrix,
+					       PangoRectangle    *rect)
+{
+  int i;
+  double quad_x[4], quad_y[4];
+  double dx1, dy1;
+  double dx2, dy2;
+  double min_x, max_x;
+  double min_y, max_y;
+
+  if (!rect)
+    return;
+
+  if (!matrix)
+    {
+      pango_rectangle_to_pixels (rect, NULL);
+      return;
+    }
+
+  quad_x[0] = (double)rect->x / PANGO_SCALE;
+  quad_y[0] = (double)rect->y / PANGO_SCALE;
+  pango_matrix_transform_point (matrix, &quad_x[0], &quad_y[0]);
+
+  dx1 = (double)rect->width / PANGO_SCALE;
+  dy1 = 0;
+  pango_matrix_transform_distance (matrix, &dx1, &dy1);
+  quad_x[1] = quad_x[0] + dx1;
+  quad_y[1] = quad_y[0] + dy1;
+
+  dx2 = 0;
+  dy2 = (double)rect->height / PANGO_SCALE;
+  pango_matrix_transform_distance (matrix, &dx2, &dy2);
+  quad_x[2] = quad_x[0] + dx2;
+  quad_y[2] = quad_y[0] + dy2;
+
+  quad_x[3] = quad_x[0] + dx1 + dx2;
+  quad_y[3] = quad_y[0] + dy1 + dy2;
+
+  min_x = max_x = quad_x[0];
+  min_y = max_y = quad_y[0];
+
+  for (i=1; i < 4; i++) {
+      if (quad_x[i] < min_x)
+	  min_x = quad_x[i];
+      if (quad_x[i] > max_x)
+	  max_x = quad_x[i];
+
+      if (quad_y[i] < min_y)
+	  min_y = quad_y[i];
+      if (quad_y[i] > max_y)
+	  max_y = quad_y[i];
+  }
+
+  rect->x      = PANGO_UNITS_FROM_DOUBLE (min_x);
+  rect->y      = PANGO_UNITS_FROM_DOUBLE (min_y);
+  rect->width  = PANGO_UNITS_FROM_DOUBLE (max_x - min_x);
+  rect->height = PANGO_UNITS_FROM_DOUBLE (max_y - min_y);
+
+  pango_rectangle_to_pixels (rect, NULL);
+}
Index: pango-types.h
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-types.h,v
retrieving revision 1.33
diff -u -p -d -r1.33 pango-types.h
--- pango-types.h	29 Apr 2006 19:41:23 -0000	1.33
+++ pango-types.h	7 Jul 2006 05:01:30 -0000
@@ -56,6 +56,9 @@ struct _PangoRectangle
   int height;
 };
 
+void pango_rectangle_to_pixels (PangoRectangle *ink_rect,
+			        PangoRectangle *logical_rect);
+
 /**
  * PangoMatrix:
  * @xx: 1st component of the transformation matrix
@@ -125,6 +128,15 @@ void pango_matrix_concat    (PangoMatrix
 			     const PangoMatrix *new_matrix);
 double pango_matrix_get_font_scale_factor (const PangoMatrix *matrix);
 
+void pango_matrix_transform_point    (const PangoMatrix *matrix,
+				      double            *x,
+				      double            *y);
+void pango_matrix_transform_distance (const PangoMatrix *matrix,
+				      double            *dx,
+				      double            *dy);
+void pango_matrix_transform_bounding_box_to_pixels (const PangoMatrix *matrix,
+					  	    PangoRectangle    *rect);
+
 #define PANGO_SCALE 1024
 #define PANGO_PIXELS(d) (((int)(d) + 512) >> 10)
 #define PANGO_PIXELS_FLOOR(d) (((int)(d)) >> 10)
@@ -135,6 +147,9 @@ double pango_matrix_get_font_scale_facto
  * more compact and faster than alternatives that work exactly for both
  * integers and floating point.
  */
+
+#define PANGO_UNITS_FROM_DOUBLE(Double) ((int)((Double) * PANGO_SCALE + 0.49999))
+#define PANGO_UNITS_TO_DOUBLE(Units) (((double)(Units)) / PANGO_SCALE)
 
 /* Macros to translate from extents rectangles to ascent/descent/lbearing/rbearing
  */
Index: pango-utils.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-utils.c,v
retrieving revision 1.90
diff -u -p -d -r1.90 pango-utils.c
--- pango-utils.c	7 Jul 2006 05:01:06 -0000	1.90
+++ pango-utils.c	7 Jul 2006 05:01:30 -0000
@@ -1631,3 +1631,49 @@ pango_quantize_line_geometry (int *thick
 
   *thickness = thickness_pixels * PANGO_SCALE;
 }
+
+/**
+ * pango_rectangle_to_pixels:
+ * @ink_rect: rectangle used to store the extents of the layout as drawn
+ *            or %NULL to indicate that the result is not needed.
+ * @logical_rect: rectangle used to store the logical extents of the 
+ *              layout or %NULL to indicate that the result is not needed.
+ * 
+ * Converts a rectangle from Pango units to device units, dividing by the
+ * %PANGO_SCALE factor and performing rounding.
+ *
+ * The ink rectangle is converted by flooring the x/y coordinates and extending
+ * width/height, such that the final rectangle completely includes the original
+ * rectangle.
+ *
+ * The logical rectangle is converted by essentially rounding the coordinates
+ * of the rectangle to the nearest device unit.
+ **/
+void
+pango_rectangle_to_pixels (PangoRectangle *ink_rect,
+			   PangoRectangle *logical_rect)
+{
+  if (ink_rect)
+    {
+      int orig_x = ink_rect->x;
+      int orig_y = ink_rect->y;
+
+      ink_rect->x = PANGO_PIXELS_FLOOR (ink_rect->x);
+      ink_rect->y = PANGO_PIXELS_FLOOR (ink_rect->y);
+
+      ink_rect->width  = PANGO_PIXELS_CEIL (orig_x + ink_rect->width ) - ink_rect->x;
+      ink_rect->height = PANGO_PIXELS_CEIL (orig_y + ink_rect->height) - ink_rect->y;
+    }
+
+  if (logical_rect)
+    {
+      int orig_x = logical_rect->x;
+      int orig_y = logical_rect->y;
+
+      logical_rect->x = PANGO_PIXELS (logical_rect->x);
+      logical_rect->y = PANGO_PIXELS (logical_rect->y);
+
+      logical_rect->width  = PANGO_PIXELS (orig_x + logical_rect->width ) - logical_rect->x;
+      logical_rect->height = PANGO_PIXELS (orig_y + logical_rect->height) - logical_rect->y;
+    }
+}
Index: pangocairo-fcfont.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangocairo-fcfont.c,v
retrieving revision 1.35
diff -u -p -d -r1.35 pangocairo-fcfont.c
--- pangocairo-fcfont.c	29 Apr 2006 20:03:17 -0000	1.35
+++ pangocairo-fcfont.c	7 Jul 2006 05:01:30 -0000
@@ -46,8 +46,6 @@ typedef struct _GlyphExtentsCacheEntry  
 #define GLYPH_CACHE_NUM_ENTRIES 256 /* should be power of two */
 #define GLYPH_CACHE_MASK (GLYPH_CACHE_NUM_ENTRIES - 1)
 
-#define PANGO_UNITS(Double) ((int)((Double) * PANGO_SCALE + 0.49999))
-
 /* An entry in the fixed-size cache for the glyph -> ink_rect mapping.
  * The cache is indexed by the lower N bits of the glyph (see
  * GLYPH_CACHE_NUM_ENTRIES).  For scripts with few glyphs,
@@ -269,8 +267,8 @@ pango_cairo_fc_font_glyph_extents_cache_
   cairo_scaled_font_extents (scaled_font, &font_extents);
 
   cffont->font_extents.x = 0;
-  cffont->font_extents.y = - PANGO_UNITS (font_extents.ascent);
-  cffont->font_extents.height = PANGO_UNITS (font_extents.ascent + font_extents.descent);
+  cffont->font_extents.y = - PANGO_UNITS_FROM_DOUBLE (font_extents.ascent);
+  cffont->font_extents.height = PANGO_UNITS_FROM_DOUBLE (font_extents.ascent + font_extents.descent);
   cffont->font_extents.width = 0;
 
   cffont->glyph_extents_cache = g_new0 (GlyphExtentsCacheEntry, GLYPH_CACHE_NUM_ENTRIES);
@@ -296,11 +294,11 @@ compute_glyph_extents (PangoCairoFcFont 
 				   &cairo_glyph, 1, &extents);
   
   entry->glyph = glyph;
-  entry->width = PANGO_UNITS (extents.x_advance);
-  entry->ink_rect.x = PANGO_UNITS (extents.x_bearing);
-  entry->ink_rect.y = PANGO_UNITS (extents.y_bearing);
-  entry->ink_rect.width = PANGO_UNITS (extents.width);
-  entry->ink_rect.height = PANGO_UNITS (extents.height);
+  entry->width = PANGO_UNITS_FROM_DOUBLE (extents.x_advance);
+  entry->ink_rect.x = PANGO_UNITS_FROM_DOUBLE (extents.x_bearing);
+  entry->ink_rect.y = PANGO_UNITS_FROM_DOUBLE (extents.y_bearing);
+  entry->ink_rect.width = PANGO_UNITS_FROM_DOUBLE (extents.width);
+  entry->ink_rect.height = PANGO_UNITS_FROM_DOUBLE (extents.height);
 }
      
 static GlyphExtentsCacheEntry *

