b=419715, upgrade cairo to 1.6 or as-close-as-possible -- imported patch cairo-upgrade-more.patch ; r=me
authorvladimir@pobox.com
Sun, 06 Apr 2008 15:14:31 -0700
changeset 13974 dca881da922ddbbc1e50f1d765f85c391401df81
parent 13973 e4d65d55a17db08212ae995037888addf4d63fc4
child 13975 49b9478da86cd575d29994d4fb7aed7c6d9ba69d
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs419715
milestone1.9pre
b=419715, upgrade cairo to 1.6 or as-close-as-possible -- imported patch cairo-upgrade-more.patch ; r=me
gfx/cairo/README
gfx/cairo/cairo/src/cairo-cff-subset.c
gfx/cairo/cairo/src/cairo-pattern.c
gfx/cairo/cairo/src/cairo-pdf-operators.c
gfx/cairo/cairo/src/cairo-pdf-surface.c
gfx/cairo/cairo/src/cairo-ps-surface.c
gfx/cairo/cairo/src/cairo-scaled-font-subsets.c
gfx/cairo/cairo/src/cairo-surface.c
gfx/cairo/cairo/src/cairo-truetype-subset.c
gfx/cairo/cairo/src/cairo-type1-fallback.c
gfx/cairo/cairo/src/cairo-type1-subset.c
gfx/cairo/cairo/src/cairo-xlib-display.c
gfx/cairo/cairo/src/cairo-xlib-surface.c
gfx/cairo/cairo/src/cairo.c
gfx/cairo/cairo/src/cairo.h
gfx/cairo/cairo/src/cairoint.h
gfx/cairo/libpixman/src/pixman-combine.c
gfx/cairo/libpixman/src/pixman-image.c
gfx/cairo/libpixman/src/pixman-pict.c
gfx/cairo/libpixman/src/pixman-private.h
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -2,18 +2,18 @@ Snapshots of cairo and glitz for mozilla
 
 We only include the relevant parts of each release (generally, src/*.[ch]),
 as we have Makefile.in's that integrate into the Mozilla build system.  For
 documentation and similar, please see the official tarballs at
 http://www.cairographics.org/.
 
 VERSIONS:
 
-  cairo (1.6.x - 1.5.16-23-gbb76eb5)
-  pixman (0.10.x - pixman-0.10.0-5-g4cde088)
+  cairo (1.6.x - 1.5.18-3-g3d22902)
+  pixman (0.10.x - pixman-0.10.0-8-g0b207ae)
   glitz 0.5.2 (cvs - 2006-01-10)
 
 ***** NOTE FOR VISUAL C++ 6.0 *****
 
 VC6 is not supported.  Please upgrade to VC8.
 
 ==== Patches ====
 
--- a/gfx/cairo/cairo/src/cairo-cff-subset.c
+++ b/gfx/cairo/cairo/src/cairo-cff-subset.c
@@ -29,16 +29,21 @@
  *
  * The Initial Developer of the Original Code is Adrian Johnson.
  *
  * Contributor(s):
  *	Adrian Johnson <ajohnson@redneon.com>
  *      Eugeniy Meshcheryakov <eugen@debian.org>
  */
 
+/*
+ * Useful links:
+ * http://www.adobe.com/devnet/font/pdfs/5176.CFF.pdf
+ */
+
 #define _BSD_SOURCE /* for snprintf(), strdup() */
 #include "cairoint.h"
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-truetype-subset-private.h"
 #include <string.h>
 
 /* CFF Dict Operators. If the high byte is 0 the command is encoded
  * with a single byte. */
--- a/gfx/cairo/cairo/src/cairo-pattern.c
+++ b/gfx/cairo/cairo/src/cairo-pattern.c
@@ -1079,16 +1079,19 @@ cairo_pattern_get_filter (cairo_pattern_
  * cairo_pattern_set_extend:
  * @pattern: a #cairo_pattern_t
  * @extend: a #cairo_extend_t describing how the area outside of the
  * pattern will be drawn
  *
  * Sets the mode to be used for drawing outside the area of a pattern.
  * See #cairo_extend_t for details on the semantics of each extend
  * strategy.
+ *
+ * The default extend mode is %CAIRO_EXTEND_NONE for surface patterns
+ * and %CAIRO_EXTEND_PAD for gradient patterns.
  **/
 void
 cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
 {
     if (pattern->status)
 	return;
 
     pattern->extend = extend;
@@ -1975,60 +1978,75 @@ cairo_status_t
 	pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
     {
 	cairo_status_t status;
 	cairo_rectangle_int_t surface_extents;
 	cairo_surface_pattern_t *surface_pattern =
 	    (cairo_surface_pattern_t *) pattern;
 	cairo_surface_t *surface = surface_pattern->surface;
 	cairo_matrix_t imatrix;
-	double x, y;
-	/* Initialize to keep the compiler quiet. */
-	int left=0, right=0, top=0, bottom=0;
-	int lx, rx, ty, by;
-	int sx, sy;
-	cairo_bool_t set = FALSE;
+	double x1, y1, x2, y2;
 
 	status = _cairo_surface_get_extents (surface, &surface_extents);
 	if (status)
 	    return status;
 
+	x1 = surface_extents.x;
+	y1 = surface_extents.y;
+	x2 = x1 + surface_extents.width;
+	y2 = y1 + surface_extents.height;
+
+	/* The filter can effectively enlarge the extents of the
+	 * pattern, so extend as necessary. Note: We aren't doing any
+	 * backend-specific querying of filter box sizes at this time,
+	 * (since currently no specific backends that could do custom
+	 * filters are calling _cairo_pattern_get_extents). */
+	switch (pattern->filter) {
+	case CAIRO_FILTER_GOOD:
+	case CAIRO_FILTER_BEST:
+	case CAIRO_FILTER_BILINEAR:
+	    x1 -= 0.5;
+	    y1 -= 0.5;
+	    x2 += 0.5;
+	    y2 += 0.5;
+	    break;
+	case CAIRO_FILTER_FAST:
+	case CAIRO_FILTER_NEAREST:
+	case CAIRO_FILTER_GAUSSIAN:
+	default:
+	    /* Nothing to do */
+	    break;
+	}
+
 	imatrix = pattern->matrix;
 	status = cairo_matrix_invert (&imatrix);
 	/* cairo_pattern_set_matrix ensures the matrix is invertible */
 	assert (status == CAIRO_STATUS_SUCCESS);
 
-	/* XXX Use _cairo_matrix_transform_bounding_box here */
-	for (sy = 0; sy <= 1; sy++) {
-	    for (sx = 0; sx <= 1; sx++) {
-		x = surface_extents.x + sx * surface_extents.width;
-		y = surface_extents.y + sy * surface_extents.height;
-		cairo_matrix_transform_point (&imatrix, &x, &y);
-		if (x < 0) x = 0;
-		if (x > CAIRO_RECT_INT_MAX) x = CAIRO_RECT_INT_MAX;
-		if (y < 0) y = 0;
-		if (y > CAIRO_RECT_INT_MAX) y = CAIRO_RECT_INT_MAX;
-		lx = floor (x); rx = ceil (x);
-		ty = floor (y); by = ceil (y);
-		if (!set) {
-		    left = lx;
-		    right = rx;
-		    top = ty;
-		    bottom = by;
-		    set = TRUE;
-		} else {
-		    if (lx < left) left = lx;
-		    if (rx > right) right = rx;
-		    if (ty < top) top = ty;
-		    if (by > bottom) bottom = by;
-		}
-	    }
-	}
-	extents->x = left; extents->width = right - left;
-	extents->y = top; extents->height = bottom - top;
+	_cairo_matrix_transform_bounding_box (&imatrix,
+					      &x1, &y1, &x2, &y2,
+					      NULL);
+
+	x1 = floor (x1);
+	if (x1 < 0)
+	    x1 = 0;
+	y1 = floor (y1);
+	if (y1 < 0)
+	    y1 = 0;
+
+	x2 = ceil (x2);
+	if (x2 > CAIRO_RECT_INT_MAX)
+	    x2 = CAIRO_RECT_INT_MAX;
+	y2 = ceil (y2);
+	if (y2 > CAIRO_RECT_INT_MAX)
+	    y2 = CAIRO_RECT_INT_MAX;
+
+	extents->x = x1; extents->width = x2 - x1;
+	extents->y = y1; extents->height = y2 - y1;
+
 	return CAIRO_STATUS_SUCCESS;
     }
 
     /* XXX: We could optimize gradients with pattern->extend of NONE
      * here in some cases, (eg. radial gradients and 1 axis of
      * horizontal/vertical linear gradients).
      */
 
--- a/gfx/cairo/cairo/src/cairo-pdf-operators.c
+++ b/gfx/cairo/cairo/src/cairo-pdf-operators.c
@@ -941,17 +941,17 @@ cairo_int_status_t
                                                  subset_glyph.subset_glyph_index);
                     Tm_x += subset_glyph.x_advance;
                     in_TJ = FALSE;
                 } else {
                     if (i != 0) {
                         _cairo_output_stream_printf (word_wrap_stream,
                                                      "%f %f Td ",
                                                      (glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
-                                                     (glyphs[i].y - Tlm_y)/-scaled_font->scale.yy);
+                                                     (glyphs[i].y - Tlm_y)/scaled_font->scale.yy);
                         Tlm_x = glyphs[i].x;
                         Tlm_y = glyphs[i].y;
                         Tm_x = Tlm_x;
                     }
                     _cairo_output_stream_printf (word_wrap_stream,
                                                  "<%0*x> Tj ",
                                                  hex_width,
                                                  subset_glyph.subset_glyph_index);
--- a/gfx/cairo/cairo/src/cairo-pdf-surface.c
+++ b/gfx/cairo/cairo/src/cairo-pdf-surface.c
@@ -206,16 +206,28 @@ static void
 				  cairo_pdf_resource_t	 resource)
 {
     cairo_pdf_object_t *object;
 
     object = _cairo_array_index (&surface->objects, resource.id - 1);
     object->offset = _cairo_output_stream_get_position (surface->output);
 }
 
+static void
+cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t *surface,
+				     double		  width,
+				     double		  height)
+{
+    surface->width = width;
+    surface->height = height;
+    cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height);
+    _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
+						  &surface->cairo_to_pdf);
+}
+
 static cairo_surface_t *
 _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*output,
 					       double			 width,
 					       double			 height)
 {
     cairo_pdf_surface_t *surface;
     cairo_status_t status, status_ignored;
 
@@ -437,21 +449,19 @@ cairo_pdf_surface_set_size (cairo_surfac
     cairo_status_t status;
 
     status = _extract_pdf_surface (surface, &pdf_surface);
     if (status) {
 	status = _cairo_surface_set_error (surface, status);
 	return;
     }
 
-    pdf_surface->width = width_in_points;
-    pdf_surface->height = height_in_points;
-    cairo_matrix_init (&pdf_surface->cairo_to_pdf, 1, 0, 0, -1, 0, height_in_points);
-    _cairo_pdf_operators_set_cairo_to_pdf_matrix (&pdf_surface->pdf_operators,
-						  &pdf_surface->cairo_to_pdf);
+    cairo_pdf_surface_set_size_internal (pdf_surface,
+					 width_in_points,
+					 height_in_points);
     status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface,
 						width_in_points,
 						height_in_points);
     if (status)
 	status = _cairo_surface_set_error (surface, status);
 }
 
 static void
@@ -726,16 +736,18 @@ static void
 _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group)
 {
     if (group->operation == PDF_FILL ||	group->operation == PDF_STROKE)
 	_cairo_path_fixed_fini (&group->path);
     if (group->source)
 	cairo_pattern_destroy (group->source);
     if (group->mask)
 	cairo_pattern_destroy (group->mask);
+    if (group->glyphs)
+	free (group->glyphs);
     if (group->scaled_font)
 	cairo_scaled_font_destroy (group->scaled_font);
     free (group);
 }
 
 static cairo_status_t
 _cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t     *surface,
 				    cairo_pdf_smask_group_t *group)
@@ -1476,43 +1488,38 @@ BAIL:
 }
 
 static cairo_status_t
 _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t  *surface,
 				      cairo_surface_t      *meta_surface,
 				      cairo_pdf_resource_t *resource)
 {
     double old_width, old_height;
-    cairo_matrix_t old_cairo_to_pdf;
     cairo_paginated_mode_t old_paginated_mode;
     cairo_clip_t *old_clip;
     cairo_rectangle_int_t meta_extents;
     cairo_status_t status, status2;
     int alpha = 0;
 
     status = _cairo_surface_get_extents (meta_surface, &meta_extents);
     if (status)
 	return status;
 
     old_width = surface->width;
     old_height = surface->height;
-    old_cairo_to_pdf = surface->cairo_to_pdf;
     old_paginated_mode = surface->paginated_mode;
     old_clip = _cairo_surface_get_clip (&surface->base);
-    surface->width = meta_extents.width;
-    surface->height = meta_extents.height;
+    cairo_pdf_surface_set_size_internal (surface,
+					 meta_extents.width,
+					 meta_extents.height);
     /* Patterns are emitted after fallback images. The paginated mode
      * needs to be set to _RENDER while the meta surface is replayed
      * back to this surface.
      */
     surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER;
-    cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, surface->height);
-    _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
-						  &surface->cairo_to_pdf);
-
     _cairo_pdf_group_resources_clear (&surface->resources);
     status = _cairo_pdf_surface_open_content_stream (surface, TRUE);
     if (status)
 	return status;
 
     *resource = surface->content;
     if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) {
 	status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
@@ -1530,27 +1537,24 @@ static cairo_status_t
 						CAIRO_META_REGION_NATIVE);
     assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
     if (status)
 	goto CLEANUP_GROUP;
 
     status = _cairo_pdf_surface_close_content_stream (surface);
 
  CLEANUP_GROUP:
-    surface->width = old_width;
-    surface->height = old_height;
+    cairo_pdf_surface_set_size_internal (surface,
+					 old_width,
+					 old_height);
     surface->paginated_mode = old_paginated_mode;
-    surface->cairo_to_pdf = old_cairo_to_pdf;
     status2 = _cairo_surface_set_clip (&surface->base, old_clip);
     if (status == CAIRO_STATUS_SUCCESS)
 	status = status2;
 
-    _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
-						  &surface->cairo_to_pdf);
-
     return status;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t	*surface,
 					 cairo_pdf_pattern_t	*pdf_pattern)
 {
     cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern;
@@ -2510,18 +2514,19 @@ static cairo_status_t
 static cairo_status_t
 _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern_t *pdf_pattern)
 {
     double old_width, old_height;
     cairo_status_t status;
 
     old_width = surface->width;
     old_height = surface->height;
-    surface->width = pdf_pattern->width;
-    surface->height = pdf_pattern->height;
+    cairo_pdf_surface_set_size_internal (surface,
+					 pdf_pattern->width,
+					 pdf_pattern->height);
 
     switch (pdf_pattern->pattern->type) {
     case CAIRO_PATTERN_TYPE_SOLID:
 	ASSERT_NOT_REACHED;
 	status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
 	break;
 
     case CAIRO_PATTERN_TYPE_SURFACE:
@@ -2537,18 +2542,19 @@ static cairo_status_t
 	break;
 
     default:
 	ASSERT_NOT_REACHED;
 	status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
 	break;
     }
 
-    surface->width = old_width;
-    surface->height = old_height;
+    cairo_pdf_surface_set_size_internal (surface,
+					 old_width,
+					 old_height);
 
     return status;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
 				   cairo_pattern_t     *pattern,
 				   cairo_pdf_resource_t pattern_res,
@@ -3816,28 +3822,23 @@ static cairo_status_t
     return _cairo_output_stream_get_status (surface->output);
 }
 
 static cairo_status_t
 _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t     *surface,
 				      cairo_pdf_smask_group_t *group)
 {
     double old_width, old_height;
-    cairo_matrix_t old_cairo_to_pdf;
     cairo_status_t status;
 
     old_width = surface->width;
     old_height = surface->height;
-    old_cairo_to_pdf = surface->cairo_to_pdf;
-    surface->width = group->width;
-    surface->height = group->height;
-    cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, surface->height);
-    _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
-						  &surface->cairo_to_pdf);
-
+    cairo_pdf_surface_set_size_internal (surface,
+					 group->width,
+					 group->height);
     /* _mask is a special case that requires two groups - source
      * and mask as well as a smask and gstate dictionary */
     if (group->operation == PDF_MASK)
 	return _cairo_pdf_surface_write_mask_group (surface, group);
 
     status = _cairo_pdf_surface_open_group (surface, &group->group_res);
     if (status)
 	return status;
@@ -3878,21 +3879,19 @@ static cairo_status_t
 	break;
     }
     if (status)
 	return status;
 
     _cairo_pdf_surface_unselect_pattern (surface);
     status = _cairo_pdf_surface_close_group (surface, NULL);
 
-    surface->width = old_width;
-    surface->height = old_height;
-    surface->cairo_to_pdf = old_cairo_to_pdf;
-    _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
-						  &surface->cairo_to_pdf);
+    cairo_pdf_surface_set_size_internal (surface,
+					 old_width,
+					 old_height);
 
     return status;
 }
 
 static cairo_status_t
 _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface)
 {
     cairo_pdf_pattern_t pattern;
@@ -4622,17 +4621,22 @@ static cairo_int_status_t
     if (gstate_res.id != 0) {
 	group = _cairo_pdf_surface_create_smask_group (surface);
 	if (group == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
 	group->operation = PDF_SHOW_GLYPHS;
 	group->source = cairo_pattern_reference (source);
 	group->source_res = pattern_res;
-	group->glyphs = glyphs;
+	group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
+	if (group->glyphs == NULL) {
+	    _cairo_pdf_smask_group_destroy (group);
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	}
+	memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
 	group->num_glyphs = num_glyphs;
 	group->scaled_font = cairo_scaled_font_reference (scaled_font);
 	status = _cairo_pdf_surface_add_smask_group (surface, group);
 	if (status) {
 	    _cairo_pdf_smask_group_destroy (group);
 	    return status;
 	}
 
--- a/gfx/cairo/cairo/src/cairo-ps-surface.c
+++ b/gfx/cairo/cairo/src/cairo-ps-surface.c
@@ -178,17 +178,18 @@ static void
 				 "/Tj { show } bind def\n"
 				 "/TJ {\n"
 				 "  {\n"
 				 "    dup\n"
 				 "    type /stringtype eq\n"
 				 "    { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse\n"
 				 "  } forall\n"
 				 "} bind def\n"
-				 "/Td { moveto } bind def\n"
+				 "/Td { matrix translate cairo_font_matrix matrix concatmatrix dup\n"
+				 "   /cairo_font_matrix exch def cairo_font exch selectfont 0 0 moveto } bind def\n"
 				 "/Tm { 6 array astore dup /cairo_font_matrix exch def\n"
 				 "      cairo_font exch selectfont 0 0 moveto } bind def\n"
 				 "/g { setgray } bind def\n"
 				 "/rg { setrgbcolor } bind def\n");
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "%%%%EndProlog\n");
 
--- a/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c
+++ b/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c
@@ -334,16 +334,17 @@ static cairo_status_t
 	    if (status)
 		return status;
 	}
 
         status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
                                              scaled_font_glyph_index,
                                              CAIRO_SCALED_GLYPH_INFO_METRICS,
                                              &scaled_glyph);
+	assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
 	if (status)
 	    return status;
 
         sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
 						       sub_font->current_subset,
 						       sub_font->num_glyphs_in_current_subset,
                                                        scaled_glyph->metrics.x_advance);
 	if (sub_font_glyph == NULL)
@@ -539,21 +540,31 @@ cairo_status_t
     {
         if (_cairo_sub_font_lookup_glyph (sub_font,
                                           scaled_font_glyph_index,
                                           subset_glyph))
             return CAIRO_STATUS_SUCCESS;
     }
 
     /* Glyph not found. Determine whether the glyph is outline or
-     * bitmap and add to the appropriate subset */
-    status = _cairo_scaled_glyph_lookup (scaled_font,
-                                         scaled_font_glyph_index,
-					 CAIRO_SCALED_GLYPH_INFO_PATH,
-                                         &scaled_glyph);
+     * bitmap and add to the appropriate subset.
+     *
+     * glyph_index 0 (the .notdef glyph) is a special case. Some fonts
+     * will return CAIRO_INT_STATUS_UNSUPPORTED when doing a
+     * _scaled_glyph_lookup(_GLYPH_INFO_PATH). Type1-fallback creates
+     * empty glyphs in this case so we can put the glyph in a unscaled
+     * subset. */
+    if (scaled_font_glyph_index == 0) {
+	status = CAIRO_STATUS_SUCCESS;
+    } else {
+	status = _cairo_scaled_glyph_lookup (scaled_font,
+					     scaled_font_glyph_index,
+					     CAIRO_SCALED_GLYPH_INFO_PATH,
+					     &scaled_glyph);
+    }
     if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
         return status;
 
     if (status == CAIRO_STATUS_SUCCESS &&
 	subsets->type != CAIRO_SUBSETS_SCALED)
     {
         /* Path available. Add to unscaled subset. */
         key.is_scaled = FALSE;
--- a/gfx/cairo/cairo/src/cairo-surface.c
+++ b/gfx/cairo/cairo/src/cairo-surface.c
@@ -882,16 +882,19 @@ slim_hidden_def (cairo_surface_get_devic
  * device resolution. So this function has no effect on those
  * backends.
  *
  * Note: The fallback resolution only takes effect at the time of
  * completing a page (with cairo_show_page() or cairo_copy_page()) so
  * there is currently no way to have more than one fallback resolution
  * in effect on a single page.
  *
+ * The default fallback resoultion is 300 pixels per inch in both
+ * dimensions.
+ *
  * Since: 1.2
  **/
 void
 cairo_surface_set_fallback_resolution (cairo_surface_t	*surface,
 				       double		 x_pixels_per_inch,
 				       double		 y_pixels_per_inch)
 {
     cairo_status_t status;
--- a/gfx/cairo/cairo/src/cairo-truetype-subset.c
+++ b/gfx/cairo/cairo/src/cairo-truetype-subset.c
@@ -29,16 +29,22 @@
  *
  * The Initial Developer of the Original Code is Red Hat, Inc.
  *
  * Contributor(s):
  *	Kristian Høgsberg <krh@redhat.com>
  *	Adrian Johnson <ajohnson@redneon.com>
  */
 
+/*
+ * Useful links:
+ * http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6.html
+ * http://www.microsoft.com/typography/specs/default.htm
+ */
+
 #define _BSD_SOURCE /* for snprintf(), strdup() */
 #include "cairoint.h"
 
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-truetype-subset-private.h"
 
 
 typedef struct subset_glyph subset_glyph_t;
@@ -494,56 +500,56 @@ cairo_truetype_font_write_generic_table 
 }
 
 static cairo_status_t
 cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t	*font,
 					   unsigned char		*buffer,
 					   unsigned long		 size)
 {
     tt_glyph_data_t *glyph_data;
-    tt_composite_glyph_t *composite_glyph, *last_glyph;
+    tt_composite_glyph_t *composite_glyph;
     int num_args;
     int has_more_components;
     unsigned short flags;
     unsigned short index;
     cairo_status_t status;
+    unsigned char *end = buffer + size;
 
     if (font->status)
 	return font->status;
 
-    if (size < sizeof (tt_glyph_data_t))
+    glyph_data = (tt_glyph_data_t *) buffer;
+    if ((unsigned char *)(&glyph_data->data) >= end)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    glyph_data = (tt_glyph_data_t *) buffer;
     if ((int16_t)be16_to_cpu (glyph_data->num_contours) >= 0)
         return CAIRO_STATUS_SUCCESS;
 
     composite_glyph = &glyph_data->glyph;
-    last_glyph = (tt_composite_glyph_t *) (buffer + size);
     do {
-        flags = be16_to_cpu (composite_glyph->flags);
+	if ((unsigned char *)(&composite_glyph->args[1]) >= end)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	flags = be16_to_cpu (composite_glyph->flags);
         has_more_components = flags & TT_MORE_COMPONENTS;
         status = cairo_truetype_font_use_glyph (font, be16_to_cpu (composite_glyph->index), &index);
 	if (status)
 	    return status;
 
         composite_glyph->index = cpu_to_be16 (index);
         num_args = 1;
         if (flags & TT_ARG_1_AND_2_ARE_WORDS)
             num_args += 1;
         if (flags & TT_WE_HAVE_A_SCALE)
             num_args += 1;
         else if (flags & TT_WE_HAVE_AN_X_AND_Y_SCALE)
             num_args += 2;
         else if (flags & TT_WE_HAVE_A_TWO_BY_TWO)
             num_args += 3;
         composite_glyph = (tt_composite_glyph_t *) &(composite_glyph->args[num_args]);
-
-	if (has_more_components && composite_glyph >= last_glyph)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
     } while (has_more_components);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
 				      unsigned long          tag)
@@ -1074,17 +1080,18 @@ cairo_status_t
 
     status = _cairo_truetype_font_create (font_subset, &font);
     if (status)
 	return status;
 
     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
 	unsigned short parent_glyph = font->scaled_font_subset->glyphs[i];
 	status = cairo_truetype_font_use_glyph (font, parent_glyph, &parent_glyph);
-	assert (status == CAIRO_STATUS_SUCCESS);
+	if (status)
+	    goto fail1;
     }
 
     cairo_truetype_font_create_truetype_table_list (font);
     status = cairo_truetype_font_generate (font, &data, &length,
                                            &string_offsets, &num_strings);
     if (status)
 	goto fail1;
 
--- a/gfx/cairo/cairo/src/cairo-type1-fallback.c
+++ b/gfx/cairo/cairo/src/cairo-type1-fallback.c
@@ -327,60 +327,44 @@ charstring_encrypt (cairo_array_t *data)
 	p = *d;
 	c = p ^ (r >> 8);
 	r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
         *d++ = c;
     }
 }
 
 static cairo_int_status_t
-create_notdef_charstring (cairo_array_t *data, cairo_charstring_type_t type)
-{
-    cairo_status_t status;
-
-    /* We're passing constants below, so we know the 0 values will
-     * only use 1 byte each, and the 500 values will use 2 bytes
-     * each. Then 2 more for each of the commands is 10 total. */
-    status = _cairo_array_grow_by (data, 10);
-    if (status)
-        return status;
-
-    if (type == CAIRO_CHARSTRING_TYPE1) {
-        charstring_encode_integer (data, 0, type);
-        charstring_encode_integer (data, 0, type);
-
-        /* The width is arbitrary. */
-        charstring_encode_integer (data, 500, type);
-        charstring_encode_integer (data, 0, type);
-        charstring_encode_command (data, CHARSTRING_sbw);
-    }
-
-    charstring_encode_command (data, CHARSTRING_endchar);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
 cairo_type1_font_create_charstring (cairo_type1_font_t      *font,
                                     int                      subset_index,
                                     int                      glyph_index,
                                     cairo_charstring_type_t  type,
                                     cairo_array_t           *data)
 {
     cairo_int_status_t status;
     cairo_scaled_glyph_t *scaled_glyph;
     t1_path_info_t path_info;
     cairo_text_extents_t *metrics;
+    cairo_bool_t emit_path = TRUE;
 
     /* This call may return CAIRO_INT_STATUS_UNSUPPORTED for bitmap fonts. */
     status = _cairo_scaled_glyph_lookup (font->type1_scaled_font,
 					 glyph_index,
 					 CAIRO_SCALED_GLYPH_INFO_METRICS|
 					 CAIRO_SCALED_GLYPH_INFO_PATH,
 					 &scaled_glyph);
+
+    /* It is ok for the .notdef glyph to not have a path available. We
+     * just need the metrics to emit an empty glyph.  */
+    if (glyph_index == 0 && status == CAIRO_INT_STATUS_UNSUPPORTED) {
+	emit_path = FALSE;
+	status = _cairo_scaled_glyph_lookup (font->type1_scaled_font,
+					     glyph_index,
+					     CAIRO_SCALED_GLYPH_INFO_METRICS,
+					     &scaled_glyph);
+    }
     if (status)
         return status;
 
     metrics = &scaled_glyph->metrics;
     if (subset_index == 0) {
         font->x_min = metrics->x_bearing;
         font->y_min = metrics->y_bearing;
         font->x_max = metrics->x_bearing + metrics->width;
@@ -406,32 +390,34 @@ cairo_type1_font_create_charstring (cair
         charstring_encode_integer (data, (int) scaled_glyph->metrics.y_bearing, type);
         charstring_encode_integer (data, (int) scaled_glyph->metrics.x_advance, type);
         charstring_encode_integer (data, (int) scaled_glyph->metrics.y_advance, type);
         charstring_encode_command (data, CHARSTRING_sbw);
 
         path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
         path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
     } else {
-        charstring_encode_integer (data, (int) scaled_glyph->metrics.width, type);
+        charstring_encode_integer (data, (int) scaled_glyph->metrics.x_advance, type);
 
         path_info.current_x = 0;
         path_info.current_y = 0;
     }
     path_info.data = data;
     path_info.type = type;
-    status = _cairo_path_fixed_interpret (scaled_glyph->path,
-                                          CAIRO_DIRECTION_FORWARD,
-                                          _charstring_move_to,
-                                          _charstring_line_to,
-                                          _charstring_curve_to,
-                                          _charstring_close_path,
-                                          &path_info);
-    if (status)
-        return status;
+    if (emit_path) {
+	status = _cairo_path_fixed_interpret (scaled_glyph->path,
+					      CAIRO_DIRECTION_FORWARD,
+					      _charstring_move_to,
+					      _charstring_line_to,
+					      _charstring_curve_to,
+					      _charstring_close_path,
+					      &path_info);
+	if (status)
+	    return status;
+    }
 
     status = _cairo_array_grow_by (data, 1);
     if (status)
         return status;
     charstring_encode_command (path_info.data, CHARSTRING_endchar);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -450,17 +436,17 @@ cairo_type1_font_write_charstrings (cair
     status = _cairo_array_grow_by (&data, 1024);
     if (status)
         goto fail;
 
     _cairo_output_stream_printf (encrypted_output,
                                  "2 index /CharStrings %d dict dup begin\n",
                                  font->scaled_font_subset->num_glyphs + 1);
 
-    for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
+    for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
         _cairo_array_truncate (&data, 0);
         /* four "random" bytes required by encryption algorithm */
         status = _cairo_array_append_multiple (&data, zeros, 4);
         if (status)
             goto fail;
         status = cairo_type1_font_create_charstring (font, i,
 						     font->scaled_font_subset->glyphs[i],
                                                      CAIRO_CHARSTRING_TYPE1,
@@ -468,43 +454,27 @@ cairo_type1_font_write_charstrings (cair
         if (status)
             goto fail;
         charstring_encrypt (&data);
         length = _cairo_array_num_elements (&data);
 	if (font->scaled_font_subset->glyph_names != NULL) {
 	    _cairo_output_stream_printf (encrypted_output, "/%s %d RD ",
 					 font->scaled_font_subset->glyph_names[i],
 					 length);
+	} else if (i == 0) {
+	    _cairo_output_stream_printf (encrypted_output, "/.notdef %d RD ", length);
 	} else {
 	    _cairo_output_stream_printf (encrypted_output, "/g%d %d RD ", i, length);
 	}
         _cairo_output_stream_write (encrypted_output,
                                     _cairo_array_index (&data, 0),
                                     length);
         _cairo_output_stream_printf (encrypted_output, " ND\n");
     }
 
-    /* All type 1 fonts must have a /.notdef charstring */
-
-    _cairo_array_truncate (&data, 0);
-    /* four "random" bytes required by encryption algorithm */
-    status = _cairo_array_append_multiple (&data, zeros, 4);
-    if (status)
-        goto fail;
-    status = create_notdef_charstring (&data, CAIRO_CHARSTRING_TYPE1);
-    if (status)
-        goto fail;
-    charstring_encrypt (&data);
-    length = _cairo_array_num_elements (&data);
-    _cairo_output_stream_printf (encrypted_output, "/.notdef %d RD ", length);
-    _cairo_output_stream_write (encrypted_output,
-                                _cairo_array_index (&data, 0),
-                                length);
-    _cairo_output_stream_printf (encrypted_output, " ND\n");
-
 fail:
     _cairo_array_fini (&data);
     return status;
 }
 
 static void
 cairo_type1_font_write_header (cairo_type1_font_t *font,
                                const char         *name)
@@ -851,24 +821,20 @@ cairo_status_t
     }
 
     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
         _cairo_array_init (&charstring, sizeof (unsigned char));
         status = _cairo_array_grow_by (&charstring, 32);
         if (status)
             goto fail2;
 
-        if (i == 0) {
-            status = create_notdef_charstring (&charstring, CAIRO_CHARSTRING_TYPE2);
-        } else {
-            status = cairo_type1_font_create_charstring (font, i,
-                                                         font->scaled_font_subset->glyphs[i],
-                                                         CAIRO_CHARSTRING_TYPE2,
-                                                         &charstring);
-        }
+	status = cairo_type1_font_create_charstring (font, i,
+						     font->scaled_font_subset->glyphs[i],
+						     CAIRO_CHARSTRING_TYPE2,
+						     &charstring);
         if (status)
             goto fail2;
 
         status = _cairo_array_append (&type2_subset->charstrings, &charstring);
         if (status)
             goto fail2;
     }
 
--- a/gfx/cairo/cairo/src/cairo-type1-subset.c
+++ b/gfx/cairo/cairo/src/cairo-type1-subset.c
@@ -28,16 +28,21 @@
  * The Original Code is the cairo graphics library.
  *
  * The Initial Developer of the Original Code is Red Hat, Inc.
  *
  * Contributor(s):
  *	Kristian Høgsberg <krh@redhat.com>
  */
 
+/*
+ * Useful links:
+ * http://partners.adobe.com/public/developer/en/font/T1_SPEC.PDF
+ */
+
 #define _BSD_SOURCE /* for snprintf(), strdup() */
 #include "cairoint.h"
 #include "cairo-type1-private.h"
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-output-stream-private.h"
 
 /* XXX: Eventually, we need to handle other font backends */
 #include "cairo-ft-private.h"
--- a/gfx/cairo/cairo/src/cairo-xlib-display.c
+++ b/gfx/cairo/cairo/src/cairo-xlib-display.c
@@ -295,16 +295,27 @@ cairo_xlib_display_t *
 	 * bogusly reset to a very small number, without any change in
 	 * the ServerVendor string. We avoid considering the new
 	 * servers with the small number as buggy by restricting the
 	 * test to known bad releases. But there could be a problem
 	 * again in the future if X.Org server versions ever climb
 	 * back up to 6.7 or 6.8. */
 	if (VendorRelease (dpy) >= 60700000 && VendorRelease (dpy) <= 60802000)
 	    display->buggy_repeat = TRUE;
+
+	/* But even the new modular server has bugs, (bad enough to
+	 * crash the X server), that it so happens we can avoid with
+	 * the exact same buggy_repeat workaround. We've verified that
+	 * this bug exists as least as late as version 1.3.0.0, (which
+	 * is in Fedora 8), and is gone again in version 1.4.99.901
+	 * (from a Fedora 9 Beta). Versions between those are still
+	 * unknown, but until we learn more, we'll assume that any 1.3
+	 * version is buggy.  */
+	if (VendorRelease (dpy) < 10400000)
+	    display->buggy_repeat = TRUE;
     } else if (strstr (ServerVendor (dpy), "XFree86") != NULL) {
 	if (VendorRelease (dpy) <= 40500000)
 	    display->buggy_repeat = TRUE;
     }
 
     /* XXX workaround; see https://bugzilla.mozilla.org/show_bug.cgi?id=413583 */
     if (buggy_repeat_force == -1) {
         if (getenv("MOZ_CAIRO_NO_BUGGY_REPEAT"))
--- a/gfx/cairo/cairo/src/cairo-xlib-surface.c
+++ b/gfx/cairo/cairo/src/cairo-xlib-surface.c
@@ -2920,16 +2920,30 @@ static cairo_status_t
 
 	scaled_glyph = *pscaled_glyph;
 	glyph_surface = scaled_glyph->surface;
 	already_had_glyph_surface = FALSE;
     } else {
 	already_had_glyph_surface = TRUE;
     }
 
+    /* XXX XRenderAddGlyph does not handle a glyph surface larger than the
+     * maximum XRequest size.
+     */
+    {
+	/* pessimistic length estimation in case we need to change formats */
+	int len = 4 * glyph_surface->width * glyph_surface->height;
+	int max_request_size = XMaxRequestSize (dpy)  -
+	                       sz_xRenderAddGlyphsReq -
+	                       sz_xGlyphInfo          -
+			       4;
+	if (len >= max_request_size)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
     if (scaled_font->surface_private == NULL) {
 	status = _cairo_xlib_surface_font_init (dpy, scaled_font);
 	if (status)
 	    return status;
     }
     font_private = scaled_font->surface_private;
 
     glyphset_info = _cairo_xlib_scaled_font_get_glyphset_info_for_format (scaled_font,
--- a/gfx/cairo/cairo/src/cairo.c
+++ b/gfx/cairo/cairo/src/cairo.c
@@ -629,19 +629,17 @@ slim_hidden_def(cairo_pop_group_to_sourc
  * cairo_set_operator:
  * @cr: a #cairo_t
  * @op: a compositing operator, specified as a #cairo_operator_t
  *
  * Sets the compositing operator to be used for all drawing
  * operations. See #cairo_operator_t for details on the semantics of
  * each available compositing operator.
  *
- * XXX: I'd also like to direct the reader's attention to some
- * (not-yet-written) section on cairo's imaging model. How would I do
- * that if such a section existed? (cworth).
+ * The default operator is %CAIRO_OPERATOR_OVER.
  **/
 void
 cairo_set_operator (cairo_t *cr, cairo_operator_t op)
 {
     cairo_status_t status;
 
     if (cr->status)
 	return;
@@ -661,16 +659,19 @@ slim_hidden_def (cairo_set_operator);
  *
  * Sets the source pattern within @cr to an opaque color. This opaque
  * color will then be used for any subsequent drawing operation until
  * a new source pattern is set.
  *
  * The color components are floating point numbers in the range 0 to
  * 1. If the values passed in are outside that range, they will be
  * clamped.
+ *
+ * The default source pattern is opaque black, (that is, it is
+ * equivalent to cairo_set_source_rgb (cr, 0.0, 0.0, 0.0)).
  **/
 void
 cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue)
 {
     cairo_pattern_t *pattern;
 
     if (cr->status)
 	return;
@@ -693,16 +694,19 @@ cairo_set_source_rgb (cairo_t *cr, doubl
  *
  * Sets the source pattern within @cr to a translucent color. This
  * color will then be used for any subsequent drawing operation until
  * a new source pattern is set.
  *
  * The color and alpha components are floating point numbers in the
  * range 0 to 1. If the values passed in are outside that range, they
  * will be clamped.
+ *
+ * The default source pattern is opaque black, (that is, it is
+ * equivalent to cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0)).
  **/
 void
 cairo_set_source_rgba (cairo_t *cr,
 		       double red, double green, double blue,
 		       double alpha)
 {
     cairo_pattern_t *pattern;
 
@@ -775,19 +779,19 @@ slim_hidden_def (cairo_set_source_surfac
  * will then be used for any subsequent drawing operation until a new
  * source pattern is set.
  *
  * Note: The pattern's transformation matrix will be locked to the
  * user space in effect at the time of cairo_set_source(). This means
  * that further modifications of the current transformation matrix
  * will not affect the source pattern. See cairo_pattern_set_matrix().
  *
- * XXX: I'd also like to direct the reader's attention to some
- * (not-yet-written) section on cairo's imaging model. How would I do
- * that if such a section existed? (cworth).
+ * The default source pattern is a solid pattern that is opaque black,
+ * (that is, it is equivalent to cairo_set_source_rgb (cr, 0.0, 0.0,
+ * 0.0)).
  **/
 void
 cairo_set_source (cairo_t *cr, cairo_pattern_t *source)
 {
     cairo_status_t status;
 
     if (cr->status)
 	return;
@@ -886,16 +890,18 @@ cairo_set_antialias (cairo_t *cr, cairo_
  * @cr: a #cairo_t
  * @fill_rule: a fill rule, specified as a #cairo_fill_rule_t
  *
  * Set the current fill rule within the cairo context. The fill rule
  * is used to determine which regions are inside or outside a complex
  * (potentially self-intersecting) path. The current fill rule affects
  * both cairo_fill() and cairo_clip(). See #cairo_fill_rule_t for details
  * on the semantics of each available fill rule.
+ *
+ * The default fill rule is %CAIRO_FILL_RULE_WINDING.
  **/
 void
 cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule)
 {
     cairo_status_t status;
 
     if (cr->status)
 	return;
@@ -954,16 +960,18 @@ cairo_set_line_width (cairo_t *cr, doubl
  * Sets the current line cap style within the cairo context. See
  * #cairo_line_cap_t for details about how the available line cap
  * styles are drawn.
  *
  * As with the other stroke parameters, the current line cap style is
  * examined by cairo_stroke(), cairo_stroke_extents(), and
  * cairo_stroke_to_path(), but does not have any effect during path
  * construction.
+ *
+ * The default line cap style is %CAIRO_LINE_CAP_BUTT.
  **/
 void
 cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
 {
     cairo_status_t status;
 
     if (cr->status)
 	return;
@@ -971,26 +979,28 @@ cairo_set_line_cap (cairo_t *cr, cairo_l
     status = _cairo_gstate_set_line_cap (cr->gstate, line_cap);
     if (status)
 	_cairo_set_error (cr, status);
 }
 
 /**
  * cairo_set_line_join:
  * @cr: a cairo context
- * @line_join: a line joint style
+ * @line_join: a line join style
  *
  * Sets the current line join style within the cairo context. See
  * #cairo_line_join_t for details about how the available line join
  * styles are drawn.
  *
  * As with the other stroke parameters, the current line join style is
  * examined by cairo_stroke(), cairo_stroke_extents(), and
  * cairo_stroke_to_path(), but does not have any effect during path
  * construction.
+ *
+ * The default line join style is %CAIRO_LINE_JOIN_MITER.
  **/
 void
 cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join)
 {
     cairo_status_t status;
 
     if (cr->status)
 	return;
@@ -1111,16 +1121,25 @@ cairo_get_dash (cairo_t *cr,
  * Cairo divides the length of the miter by the line width.
  * If the result is greater than the miter limit, the style is
  * converted to a bevel.
  *
  * As with the other stroke parameters, the current line miter limit is
  * examined by cairo_stroke(), cairo_stroke_extents(), and
  * cairo_stroke_to_path(), but does not have any effect during path
  * construction.
+ *
+ * The default miter limit value is 10.0, which will convert joins
+ * with interior angles less than 11 degrees to bevels instead of
+ * miters. For reference, a miter limit of 2.0 makes the miter cutoff
+ * at 60 degrees, and a miter limit of 1.414 makes the cutoff at 90
+ * degrees.
+ *
+ * A miter limit for a desired angle can be computed as: miter limit =
+ * 1/sin(angle/2)
  **/
 void
 cairo_set_miter_limit (cairo_t *cr, double limit)
 {
     cairo_status_t status;
 
     if (cr->status)
 	return;
@@ -2566,23 +2585,48 @@ cairo_copy_clip_rectangle_list (cairo_t 
 
 /**
  * cairo_select_font_face:
  * @cr: a #cairo_t
  * @family: a font family name, encoded in UTF-8
  * @slant: the slant for the font
  * @weight: the weight for the font
  *
+ * Note: The cairo_select_font_face() function call is part of what
+ * the cairo designers call the "toy" text API. It is convenient for
+ * short demos and simple programs, but it is not expected to be
+ * adequate for serious text-using applications.
+ *
  * Selects a family and style of font from a simplified description as
- * a family name, slant and weight. This function is meant to be used
- * only for applications with simple font needs: Cairo doesn't provide
- * for operations such as listing all available fonts on the system,
- * and it is expected that most applications will need to use a more
- * comprehensive font handling and text layout library in addition to
- * cairo.
+ * a family name, slant and weight. Cairo provides no operation to
+ * list available family names on the system (this is a "toy",
+ * remember"), but the standard CSS2 generic family names, ("serif",
+ * "sans-serif", "cursive", "fantasy", "monospace"), are likely to
+ * work as expected.
+ *
+ * For "real" font selection, see the font-backend-specific
+ * font_face_create functions for the font backend you are using. (For
+ * example, if you are using the freetype-based cairo-ft font backend,
+ * see cairo_ft_font_face_create_for_ft_face() or
+ * cairo_ft_font_face_create_for_pattern().) The resulting font face
+ * could then be used with cairo_scaled_font_create() and
+ * cairo_set_scaled_font().
+ *
+ * Similarly, when using the "real" font support, you can call
+ * directly into the underlying font system, (such as fontconfig or
+ * freetype), for operations such as listing available fonts, etc.
+ *
+ * It is expected that most applications will need to use a more
+ * comprehensive font handling and text layout library, (for example,
+ * pango), in conjunction with cairo.
+ *
+ * If text is drawn without a call to cairo_select_font_face(), (nor
+ * cairo_set_font_face() nor cairo_set_scaled_font()), the default
+ * family is "sans", slant is %CAIRO_FONT_SLANT_NORMAL, and weight is
+ * %CAIRO_FONT_WEIGHT_NORMAL.
  **/
 void
 cairo_select_font_face (cairo_t              *cr,
 			const char           *family,
 			cairo_font_slant_t    slant,
 			cairo_font_weight_t   weight)
 {
     cairo_status_t status;
@@ -2687,16 +2731,20 @@ cairo_get_font_face (cairo_t *cr)
  * @cr: a #cairo_t
  * @size: the new font size, in user space units
  *
  * Sets the current font matrix to a scale by a factor of @size, replacing
  * any font matrix previously set with cairo_set_font_size() or
  * cairo_set_font_matrix(). This results in a font size of @size user space
  * units. (More precisely, this matrix will result in the font's
  * em-square being a @size by @size square in user space.)
+ *
+ * If text is drawn without a call to cairo_set_font_size(), (nor
+ * cairo_set_font_matrix() nor cairo_set_scaled_font()), the default
+ * font size is 10.0.
  **/
 void
 cairo_set_font_size (cairo_t *cr, double size)
 {
     cairo_status_t status;
 
     if (cr->status)
 	return;
--- a/gfx/cairo/cairo/src/cairo.h
+++ b/gfx/cairo/cairo/src/cairo.h
@@ -368,16 +368,18 @@ cairo_pop_group_to_source (cairo_t *cr);
  * one of them
  * @CAIRO_OPERATOR_ADD: source and destination layers are accumulated
  * @CAIRO_OPERATOR_SATURATE: like over, but assuming source and dest are
  * disjoint geometries
  *
  * #cairo_operator_t is used to set the compositing operator for all cairo
  * drawing operations.
  *
+ * The default operator is %CAIRO_OPERATOR_OVER.
+ *
  * The operators marked as <firstterm>unbounded</firstterm> modify their
  * destination even outside of the mask layer (that is, their effect is not
  * bound by the mask layer).  However, their effect can still be limited by
  * way of clipping.
  *
  * To keep things simple, the operator descriptions here
  * document the behavior for when both source and destination are either fully
  * transparent or fully opaque.  The actual implementation works for
@@ -468,16 +470,18 @@ cairo_set_antialias (cairo_t *cr, cairo_
  * fill rules, whether or not a point is included in the fill is
  * determined by taking a ray from that point to infinity and looking
  * at intersections with the path. The ray can be in any direction,
  * as long as it doesn't pass through the end point of a segment
  * or have a tricky intersection such as intersecting tangent to the path.
  * (Note that filling is not actually implemented in this way. This
  * is just a description of the rule that is applied.)
  *
+ * The default fill rule is %CAIRO_FILL_RULE_WINDING.
+ *
  * New entries may be added in future versions.
  **/
 typedef enum _cairo_fill_rule {
     CAIRO_FILL_RULE_WINDING,
     CAIRO_FILL_RULE_EVEN_ODD
 } cairo_fill_rule_t;
 
 cairo_public void
@@ -487,17 +491,19 @@ cairo_public void
 cairo_set_line_width (cairo_t *cr, double width);
 
 /**
  * cairo_line_cap_t:
  * @CAIRO_LINE_CAP_BUTT: start(stop) the line exactly at the start(end) point
  * @CAIRO_LINE_CAP_ROUND: use a round ending, the center of the circle is the end point
  * @CAIRO_LINE_CAP_SQUARE: use squared ending, the center of the square is the end point
  *
- * Specifies how to render the endpoint of a line when stroking.
+ * Specifies how to render the endpoints of the path when stroking.
+ *
+ * The default line cap style is %CAIRO_LINE_CAP_BUTT.
  **/
 typedef enum _cairo_line_cap {
     CAIRO_LINE_CAP_BUTT,
     CAIRO_LINE_CAP_ROUND,
     CAIRO_LINE_CAP_SQUARE
 } cairo_line_cap_t;
 
 cairo_public void
@@ -508,16 +514,18 @@ cairo_set_line_cap (cairo_t *cr, cairo_l
  * @CAIRO_LINE_JOIN_MITER: use a sharp (angled) corner, see
  * cairo_set_miter_limit()
  * @CAIRO_LINE_JOIN_ROUND: use a rounded join, the center of the circle is the
  * joint point
  * @CAIRO_LINE_JOIN_BEVEL: use a cut-off join, the join is cut off at half
  * the line width from the joint point
  *
  * Specifies how to render the junction of two lines when stroking.
+ *
+ * The default line join style is %CAIRO_LINE_JOIN_MITER.
  **/
 typedef enum _cairo_line_join {
     CAIRO_LINE_JOIN_MITER,
     CAIRO_LINE_JOIN_ROUND,
     CAIRO_LINE_JOIN_BEVEL
 } cairo_line_join_t;
 
 cairo_public void
@@ -1784,23 +1792,28 @@ cairo_pattern_get_matrix (cairo_pattern_
 			  cairo_matrix_t  *matrix);
 
 /**
  * cairo_extend_t:
  * @CAIRO_EXTEND_NONE: pixels outside of the source pattern
  *   are fully transparent
  * @CAIRO_EXTEND_REPEAT: the pattern is tiled by repeating
  * @CAIRO_EXTEND_REFLECT: the pattern is tiled by reflecting
- *   at the edges (not implemented for surface patterns currently)
+ *   at the edges (Implemented for surface patterns since 1.6)
  * @CAIRO_EXTEND_PAD: pixels outside of the pattern copy
- *   the closest pixel from the source (Since 1.2; not implemented
- *   for surface patterns currently)
+ *   the closest pixel from the source (Since 1.2; but only
+ *   implemented for surface patterns since 1.6)
  *
- * #cairo_extend_t is used to describe how the area outside
- * of a pattern will be drawn.
+ * #cairo_extend_t is used to describe how pattern color/alpha will be
+ * determined for areas "outside" the pattern's natural area, (for
+ * example, outside the surface bounds or outside the gradient
+ * geometry).
+ *
+ * The default extend mode is %CAIRO_EXTEND_NONE for surface patterns
+ * and %CAIRO_EXTEND_PAD for gradient patterns.
  *
  * New entries may be added in future versions.
  **/
 typedef enum _cairo_extend {
     CAIRO_EXTEND_NONE,
     CAIRO_EXTEND_REPEAT,
     CAIRO_EXTEND_REFLECT,
     CAIRO_EXTEND_PAD
--- a/gfx/cairo/cairo/src/cairoint.h
+++ b/gfx/cairo/cairo/src/cairoint.h
@@ -763,17 +763,17 @@ struct _cairo_color {
     unsigned short red_short;
     unsigned short green_short;
     unsigned short blue_short;
     unsigned short alpha_short;
 };
 
 #define CAIRO_EXTEND_SURFACE_DEFAULT CAIRO_EXTEND_NONE
 #define CAIRO_EXTEND_GRADIENT_DEFAULT CAIRO_EXTEND_PAD
-#define CAIRO_FILTER_DEFAULT CAIRO_FILTER_BEST
+#define CAIRO_FILTER_DEFAULT CAIRO_FILTER_GOOD
 
 struct _cairo_pattern {
     cairo_pattern_type_t	type;
     cairo_reference_count_t	ref_count;
     cairo_status_t		status;
     cairo_user_data_array_t	user_data;
 
     cairo_matrix_t		matrix;
--- a/gfx/cairo/libpixman/src/pixman-combine.c
+++ b/gfx/cairo/libpixman/src/pixman-combine.c
@@ -8,17 +8,16 @@
 /*
  * There are two ways of handling alpha -- either as a single unified value or
  * a separate value for each component, hence each macro must have two
  * versions.  The unified alpha version has a 'U' at the end of the name,
  * the component version has a 'C'.  Similarly, functions which deal with
  * this difference will have two versions using the same convention.
  */
 
-
 /*
  * Combine src and mask
  */
 FASTCALL static void
 pixman_fbCombineMaskU (uint32_t *src, const uint32_t *mask, int width)
 {
     int i;
     for (i = 0; i < width; ++i) {
@@ -1205,16 +1204,17 @@ static CombineFuncU pixman_fbCombineFunc
     fbCombineConjointOverReverseU,
     fbCombineConjointInU,
     fbCombineConjointInReverseU,
     fbCombineConjointOutU,
     fbCombineConjointOutReverseU,
     fbCombineConjointAtopU,
     fbCombineConjointAtopReverseU,
     fbCombineConjointXorU,
+    NULL /* Noop */
 };
 
 static CombineFuncC pixman_fbCombineFuncC[] = {
     fbCombineClearC,
     fbCombineSrcC,
     NULL, /* Dest */
     fbCombineOverC,
     fbCombineOverReverseC,
@@ -1252,15 +1252,16 @@ static CombineFuncC pixman_fbCombineFunc
     fbCombineConjointOverReverseC,
     fbCombineConjointInC,
     fbCombineConjointInReverseC,
     fbCombineConjointOutC,
     fbCombineConjointOutReverseC,
     fbCombineConjointAtopC,
     fbCombineConjointAtopReverseC,
     fbCombineConjointXorC,
+    NULL /* Noop */
 };
 
 FbComposeFunctions pixman_composeFunctions = {
     pixman_fbCombineFuncU,
     pixman_fbCombineFuncC,
     pixman_fbCombineMaskU
 };
--- a/gfx/cairo/libpixman/src/pixman-image.c
+++ b/gfx/cairo/libpixman/src/pixman-image.c
@@ -712,8 +712,92 @@ pixman_image_fill_rectangles (pixman_op_
 				rect->x, rect->y,
 				rect->width, rect->height);
     }
 
     pixman_image_unref (solid);
 
     return TRUE;
 }
+
+pixman_bool_t
+pixman_image_can_get_solid (pixman_image_t *image)
+{
+    if (image->type == SOLID)
+	return TRUE;
+
+    if (image->type != BITS	||
+	image->bits.width != 1	||
+	image->bits.height != 1)
+    {
+	return FALSE;
+    }
+
+    if (image->common.repeat != PIXMAN_REPEAT_NORMAL)
+	return FALSE;
+
+    switch (image->bits.format)
+    {
+    case PIXMAN_a8r8g8b8:
+    case PIXMAN_x8r8g8b8:
+    case PIXMAN_a8b8g8r8:
+    case PIXMAN_x8b8g8r8:
+    case PIXMAN_r8g8b8:
+    case PIXMAN_b8g8r8:
+    case PIXMAN_r5g6b5:
+    case PIXMAN_b5g6r5:
+	return TRUE;
+    default:
+	return FALSE;
+    }
+}
+
+pixman_bool_t
+pixman_image_is_opaque(pixman_image_t *image)
+{
+    int i = 0;
+    int gradientNumberOfColors = 0;
+
+    if(image->common.alpha_map)
+        return FALSE;
+
+    switch(image->type)
+    {
+    case BITS:
+        if(PIXMAN_FORMAT_A(image->bits.format))
+            return FALSE;
+        break;
+
+    case LINEAR:
+    case CONICAL:
+    case RADIAL:
+        gradientNumberOfColors = image->gradient.n_stops;
+        i=0;
+        while(i<gradientNumberOfColors)
+        {
+            if(image->gradient.stops[i].color.alpha != 0xffff)
+                return FALSE;
+            i++;
+        }
+        break;
+
+    case SOLID:
+         if(Alpha(image->solid.color) != 0xff)
+            return FALSE;
+        break;
+    }
+
+    /* Convolution filters can introduce translucency if the sum of the weights
+       is lower than 1. */
+    if (image->common.filter == PIXMAN_FILTER_CONVOLUTION)
+         return FALSE;
+
+    if (image->common.repeat == PIXMAN_REPEAT_NONE)
+    {
+        if (image->common.filter != PIXMAN_FILTER_NEAREST)
+            return FALSE;
+
+        if (image->common.transform)
+            return FALSE;
+    }
+
+     return TRUE;
+}
\ No newline at end of file
--- a/gfx/cairo/libpixman/src/pixman-pict.c
+++ b/gfx/cairo/libpixman/src/pixman-pict.c
@@ -1256,48 +1256,16 @@ pixman_walk_composite_region (pixman_op_
 	    y_msk += h_this;
 	    y_dst += h_this;
 	}
 	pbox++;
     }
     pixman_region_fini (&reg);
 }
 
-static pixman_bool_t
-can_get_solid (pixman_image_t *image)
-{
-    if (image->type == SOLID)
-	return TRUE;
-
-    if (image->type != BITS	||
-	image->bits.width != 1	||
-	image->bits.height != 1)
-    {
-	return FALSE;
-    }
-
-    if (image->common.repeat != PIXMAN_REPEAT_NORMAL)
-	return FALSE;
-
-    switch (image->bits.format)
-    {
-    case PIXMAN_a8r8g8b8:
-    case PIXMAN_x8r8g8b8:
-    case PIXMAN_a8b8g8r8:
-    case PIXMAN_x8b8g8r8:
-    case PIXMAN_r8g8b8:
-    case PIXMAN_b8g8r8:
-    case PIXMAN_r5g6b5:
-    case PIXMAN_b5g6r5:
-	return TRUE;
-    default:
-	return FALSE;
-    }
-}
-
 #define SCANLINE_BUFFER_LENGTH 2048
 
 static void
 pixman_image_composite_rect  (pixman_op_t                   op,
 			      pixman_image_t               *src,
 			      pixman_image_t               *mask,
 			      pixman_image_t               *dest,
 			      int16_t                       src_x,
@@ -1549,17 +1517,17 @@ get_fast_path (const FastPathInfo *fast_
     for (info = fast_paths; info->op != PIXMAN_OP_NONE; info++)
     {
 	pixman_bool_t valid_src		= FALSE;
 	pixman_bool_t valid_mask	= FALSE;
 
 	if (info->op != op)
 	    continue;
 
-	if ((info->src_format == PIXMAN_solid && can_get_solid (pSrc))		||
+	if ((info->src_format == PIXMAN_solid && pixman_image_can_get_solid (pSrc))		||
 	    (pSrc->type == BITS && info->src_format == pSrc->bits.format))
 	{
 	    valid_src = TRUE;
 	}
 
 	if (!valid_src)
 	    continue;
 
@@ -1591,16 +1559,92 @@ get_fast_path (const FastPathInfo *fast_
 	    continue;
 
 	return info;
     }
 
     return NULL;
 }
 
+/*
+ * Operator optimizations based on source or destination opacity
+ */
+typedef struct
+{
+    pixman_op_t			op;
+    pixman_op_t			opSrcDstOpaque;
+    pixman_op_t			opSrcOpaque;
+    pixman_op_t			opDstOpaque;
+} OptimizedOperatorInfo;
+
+static const OptimizedOperatorInfo optimized_operators[] =
+{
+    /* Input Operator           SRC&DST Opaque          SRC Opaque              DST Opaque      */
+    { PIXMAN_OP_OVER,           PIXMAN_OP_SRC,          PIXMAN_OP_SRC,          PIXMAN_OP_OVER },
+    { PIXMAN_OP_OVER_REVERSE,   PIXMAN_OP_DST,          PIXMAN_OP_OVER_REVERSE, PIXMAN_OP_DST },
+    { PIXMAN_OP_IN,             PIXMAN_OP_SRC,          PIXMAN_OP_IN,           PIXMAN_OP_SRC },
+    { PIXMAN_OP_IN_REVERSE,     PIXMAN_OP_DST,          PIXMAN_OP_DST,          PIXMAN_OP_IN_REVERSE },
+    { PIXMAN_OP_OUT,            PIXMAN_OP_CLEAR,        PIXMAN_OP_OUT,          PIXMAN_OP_CLEAR },
+    { PIXMAN_OP_OUT_REVERSE,    PIXMAN_OP_CLEAR,        PIXMAN_OP_CLEAR,        PIXMAN_OP_OUT_REVERSE },
+    { PIXMAN_OP_ATOP,           PIXMAN_OP_SRC,          PIXMAN_OP_IN,           PIXMAN_OP_OVER },
+    { PIXMAN_OP_ATOP_REVERSE,   PIXMAN_OP_DST,          PIXMAN_OP_OVER_REVERSE, PIXMAN_OP_IN_REVERSE },
+    { PIXMAN_OP_XOR,            PIXMAN_OP_CLEAR,        PIXMAN_OP_OUT,          PIXMAN_OP_OUT_REVERSE },
+    { PIXMAN_OP_SATURATE,       PIXMAN_OP_DST,          PIXMAN_OP_OVER_REVERSE, PIXMAN_OP_DST },
+    { PIXMAN_OP_NONE }
+};
+
+
+/*
+ * Check if the current operator could be optimized
+ */
+static const OptimizedOperatorInfo*
+pixman_operator_can_be_optimized(pixman_op_t op)
+{
+    const OptimizedOperatorInfo *info;
+
+    for (info = optimized_operators; info->op != PIXMAN_OP_NONE; info++)
+    {
+        if(info->op == op)
+            return info;
+    }
+    return NULL;
+}
+
+/*
+ * Optimize the current operator based on opacity of source or destination
+ * The output operator should be mathematically equivalent to the source.
+ */
+static pixman_op_t
+pixman_optimize_operator(pixman_op_t op, pixman_image_t *pSrc, pixman_image_t *pMask, pixman_image_t *pDst )
+{
+    pixman_bool_t is_source_opaque;
+    pixman_bool_t is_dest_opaque;
+    const OptimizedOperatorInfo *info = pixman_operator_can_be_optimized(op);
+
+    if(!info || pMask)
+        return op;
+
+    is_source_opaque = pixman_image_is_opaque(pSrc);
+    is_dest_opaque = pixman_image_is_opaque(pDst);
+
+    if(is_source_opaque == FALSE && is_dest_opaque == FALSE)
+        return op;
+
+    if(is_source_opaque && is_dest_opaque)
+        return info->opSrcDstOpaque;
+    else if(is_source_opaque)
+        return info->opSrcOpaque;
+    else if(is_dest_opaque)
+        return info->opDstOpaque;
+
+    return op;
+
+}
+
+
 void
 pixman_image_composite (pixman_op_t      op,
 			pixman_image_t * pSrc,
 			pixman_image_t * pMask,
 			pixman_image_t * pDst,
 			int16_t      xSrc,
 			int16_t      ySrc,
 			int16_t      xMask,
@@ -1647,17 +1691,25 @@ pixman_image_composite (pixman_op_t     
 	if (maskRepeat && maskTransform &&
 	    pMask->bits.width == 1 &&
 	    pMask->bits.height == 1)
 	{
 	    maskTransform = FALSE;
 	}
     }
 
-    if ((pSrc->type == BITS || can_get_solid (pSrc)) && (!pMask || pMask->type == BITS)
+    /*
+    * Check if we can replace our operator by a simpler one if the src or dest are opaque
+    * The output operator should be mathematically equivalent to the source.
+    */
+    op = pixman_optimize_operator(op, pSrc, pMask, pDst);
+    if(op == PIXMAN_OP_DST)
+        return;
+
+    if ((pSrc->type == BITS || pixman_image_can_get_solid (pSrc)) && (!pMask || pMask->type == BITS)
         && !srcTransform && !maskTransform
         && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap
         && (pSrc->common.filter != PIXMAN_FILTER_CONVOLUTION)
         && (pSrc->common.repeat != PIXMAN_REPEAT_PAD)
         && (!pMask || (pMask->common.filter != PIXMAN_FILTER_CONVOLUTION && pMask->common.repeat != PIXMAN_REPEAT_PAD))
 	&& !pSrc->common.read_func && !pSrc->common.write_func
 	&& !(pMask && pMask->common.read_func) && !(pMask && pMask->common.write_func)
 	&& !pDst->common.read_func && !pDst->common.write_func)
@@ -1748,16 +1800,17 @@ pixman_image_composite (pixman_op_t     
     }
 
     pixman_walk_composite_region (op, pSrc, pMask, pDst, xSrc, ySrc,
 				  xMask, yMask, xDst, yDst, width, height,
 				  srcRepeat, maskRepeat, func);
 }
 
 
+
 #ifdef USE_MMX
 /* The CPU detection code needs to be in a file not compiled with
  * "-mmmx -msse", as gcc would generate CMOV instructions otherwise
  * that would lead to SIGILL instructions on old CPUs that don't have
  * it.
  */
 #if !defined(__amd64__) && !defined(__x86_64__)
 
--- a/gfx/cairo/libpixman/src/pixman-private.h
+++ b/gfx/cairo/libpixman/src/pixman-private.h
@@ -834,16 +834,22 @@ union pixman_image
 
 void
 pixman_rasterize_edges_accessors (pixman_image_t *image,
 				  pixman_edge_t	*l,
 				  pixman_edge_t	*r,
 				  pixman_fixed_t	t,
 				  pixman_fixed_t	b);
 
+pixman_bool_t
+pixman_image_is_opaque(pixman_image_t *image);
+
+pixman_bool_t
+pixman_image_can_get_solid (pixman_image_t *image);
+
 
 #ifdef PIXMAN_TIMING
 
 /* Timing */
 static inline uint64_t
 oil_profile_stamp_rdtsc (void)
 {
     uint64_t ts;