[cairo-commit] Branch 'ps-surface' - 72 commits - configure.in .gitignore INSTALL Makefile.am pixman/src RELEASING src/cairo-analysis-surface.c src/cairo-atsui-font.c src/cairo-base85-stream.c src/cairo-beos-surface.cpp src/cairo.c src/cairo-cache-private.h src/cairo-clip.c src/cairo-directfb-surface.c src/cairo-font.c src/cairo-ft-font.c src/cairo-glitz-surface.c src/cairo-hash-private.h src/cairo-image-surface.c src/cairoint.h src/cairo-lzw.c src/cairo-meta-surface.c src/cairo-meta-surface-private.h src/cairo-output-stream.c src/cairo-paginated-surface.c src/cairo-pattern.c src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-quartz-surface.c src/cairo-scaled-font.c src/cairo-surface.c src/cairo-surface-fallback.c src/cairo-svg-surface.c src/cairo-wideint.c src/cairo-wideint.h src/cairo-win32-font.c src/cairo-win32.h src/cairo-win32-private.h src/cairo-win32-surface.c src/cairo-xcb-surface.c src/cairo-xlib-surface.c src/Makefile.am src/test-fallback-surface.c src/test-meta-surface.c test/cairo-test.c test/font-face-get-type.c test/ft-font-create-for-ft-face.c test/.gitignore test/Makefile.am test/pattern-get-type.c test/show-glyphs-many.c test/show-glyphs-many-ref.png test/show-glyphs-many-rgb24-ref.png

Carl Worth cworth at kemper.freedesktop.org
Tue Apr 4 15:03:43 PDT 2006


 .gitignore                          |    1 
 INSTALL                             |    2 
 Makefile.am                         |   47 +++-
 RELEASING                           |   26 +-
 configure.in                        |    4 
 pixman/src/fbcompose.c              |   12 -
 pixman/src/fbedge.c                 |    2 
 pixman/src/fbedgeimp.h              |    2 
 pixman/src/fbpict.c                 |    6 
 pixman/src/fbpict.h                 |    2 
 pixman/src/icpixels.c               |    2 
 pixman/src/ictrap.c                 |    2 
 pixman/src/pixman-xserver-compat.h  |    2 
 pixman/src/pixman.h                 |    2 
 pixman/src/pixregion.c              |    6 
 pixman/src/pixregionint.h           |    2 
 pixman/src/renderedge.c             |    2 
 pixman/src/renderedge.h             |    2 
 src/Makefile.am                     |   14 -
 src/cairo-analysis-surface.c        |    1 
 src/cairo-atsui-font.c              |   36 ++-
 src/cairo-base85-stream.c           |  130 +++++++++++
 src/cairo-beos-surface.cpp          |  252 ++++++++++++++++------
 src/cairo-cache-private.h           |    2 
 src/cairo-clip.c                    |    4 
 src/cairo-directfb-surface.c        |    9 
 src/cairo-font.c                    |   18 +
 src/cairo-ft-font.c                 |   13 -
 src/cairo-glitz-surface.c           |   15 -
 src/cairo-hash-private.h            |    2 
 src/cairo-image-surface.c           |    1 
 src/cairo-lzw.c                     |  400 ++++++++++++++++++++++++++++++++++++
 src/cairo-meta-surface-private.h    |    2 
 src/cairo-meta-surface.c            |    1 
 src/cairo-output-stream.c           |  112 ++++++----
 src/cairo-paginated-surface.c       |   25 ++
 src/cairo-pattern.c                 |   12 +
 src/cairo-pdf-surface.c             |   19 +
 src/cairo-ps-surface.c              |  210 +++++++++++++-----
 src/cairo-quartz-surface.c          |   11 
 src/cairo-scaled-font.c             |   26 +-
 src/cairo-surface-fallback.c        |    3 
 src/cairo-surface.c                 |   40 +++
 src/cairo-svg-surface.c             |  137 ++++++++----
 src/cairo-wideint.c                 |    3 
 src/cairo-wideint.h                 |    3 
 src/cairo-win32-font.c              |    3 
 src/cairo-win32-private.h           |    7 
 src/cairo-win32-surface.c           |  253 +++++++++++++++-------
 src/cairo-win32.h                   |    8 
 src/cairo-xcb-surface.c             |    1 
 src/cairo-xlib-surface.c            |   50 +++-
 src/cairo.c                         |    3 
 src/cairoint.h                      |   67 +++++-
 src/test-fallback-surface.c         |    1 
 src/test-meta-surface.c             |    1 
 test/.gitignore                     |    3 
 test/Makefile.am                    |    6 
 test/cairo-test.c                   |  109 +++++++--
 test/font-face-get-type.c           |   64 +++++
 test/ft-font-create-for-ft-face.c   |   14 +
 test/pattern-get-type.c             |   74 ++++++
 test/show-glyphs-many-ref.png       |binary
 test/show-glyphs-many-rgb24-ref.png |binary
 test/show-glyphs-many.c             |  127 +++++++++++
 65 files changed, 1953 insertions(+), 463 deletions(-)

New commits:
diff-tree 66ed9811cc542d99cb5a6b6b792c9a9f0832fbf9 (from parents)
Merge: edb83e306bda8a78a8a72006f257922cda7adc69 45bbdf94cbac736c9f854012581e8f914a6e27df
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Apr 4 14:58:52 2006 -0700

    Merge branch 'cairo-origin' into analysis-surface
    
    With the string-array-stream stuff that this merge picks up, the
    analysis-surface branch is now passing all of the test suite again.

diff --cc src/cairo-analysis-surface.c
index 2bc51d3,0000000..76b84e1
mode 100644,000000..100644
@@@ -1,255 -1,0 +1,256 @@@
 +/*
 + * Copyright © 2006 Keith Packard
 + *
 + * This library is free software; you can redistribute it and/or
 + * modify it either under the terms of the GNU Lesser General Public
 + * License version 2.1 as published by the Free Software Foundation
 + * (the "LGPL") or, at your option, under the terms of the Mozilla
 + * Public License Version 1.1 (the "MPL"). If you do not alter this
 + * notice, a recipient may use your version of this file under either
 + * the MPL or the LGPL.
 + *
 + * You should have received a copy of the LGPL along with this library
 + * in the file COPYING-LGPL-2.1; if not, write to the Free Software
 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 + * You should have received a copy of the MPL along with this library
 + * in the file COPYING-MPL-1.1
 + *
 + * The contents of this file are subject to the Mozilla Public License
 + * Version 1.1 (the "License"); you may not use this file except in
 + * compliance with the License. You may obtain a copy of the License at
 + * http://www.mozilla.org/MPL/
 + *
 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
 + * OF ANY KIND, either express or implied. See the LGPL or the MPL for
 + * the specific language governing rights and limitations.
 + *
 + * The Original Code is the cairo graphics library.
 + *
 + * The Initial Developer of the Original Code is Keith Packard
 + *
 + * Contributor(s):
 + *      Keith Packard <keithp at keithp.com>
 + */
 +
 +#include "cairoint.h"
 +
 +#include "cairo-analysis-surface-private.h"
 +#include "cairo-paginated-surface-private.h"
 +
 +typedef struct {
 +    cairo_surface_t base;
 +    int width;
 +    int height;
 +
 +    cairo_surface_t	*target;
 +    
 +    cairo_bool_t fallback;
 +} cairo_analysis_surface_t;
 +
 +static cairo_int_status_t
 +_cairo_analysis_surface_get_extents (void	 	*abstract_surface,
 +				     cairo_rectangle_t	*rectangle)
 +{
 +    cairo_analysis_surface_t *surface = abstract_surface;
 +
 +    return _cairo_surface_get_extents (surface->target, rectangle);
 +}
 +
 +static cairo_int_status_t
 +_cairo_analysis_surface_paint (void			*abstract_surface,
 +			      cairo_operator_t		op,
 +			      cairo_pattern_t		*source)
 +{
 +    cairo_analysis_surface_t *surface = abstract_surface;
 +    cairo_status_t	     status;
 +
 +    if (!surface->target->backend->paint)
 +	status = CAIRO_INT_STATUS_UNSUPPORTED;
 +    else
 +	status = (*surface->target->backend->paint) (surface->target, op,
 +						     source);
 +    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
 +	surface->fallback = TRUE;
 +	status = CAIRO_STATUS_SUCCESS;
 +    }
 +    return status;
 +}
 +
 +static cairo_int_status_t
 +_cairo_analysis_surface_mask (void		*abstract_surface,
 +			      cairo_operator_t	 op,
 +			      cairo_pattern_t	*source,
 +			      cairo_pattern_t	*mask)
 +{
 +    cairo_analysis_surface_t *surface = abstract_surface;
 +    cairo_status_t	     status;
 +
 +    if (!surface->target->backend->mask)
 +	status = CAIRO_INT_STATUS_UNSUPPORTED;
 +    else
 +	status = (*surface->target->backend->mask) (surface->target, op,
 +						    source, mask);
 +    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
 +	surface->fallback = TRUE;
 +	status = CAIRO_STATUS_SUCCESS;
 +    }
 +    return status;
 +}
 +
 +static cairo_int_status_t
 +_cairo_analysis_surface_stroke (void			*abstract_surface,
 +				cairo_operator_t	 op,
 +				cairo_pattern_t		*source,
 +				cairo_path_fixed_t	*path,
 +				cairo_stroke_style_t	*style,
 +				cairo_matrix_t		*ctm,
 +				cairo_matrix_t		*ctm_inverse,
 +				double			 tolerance,
 +				cairo_antialias_t	 antialias)
 +{
 +    cairo_analysis_surface_t *surface = abstract_surface;
 +    cairo_status_t	     status;
 +
 +    if (!surface->target->backend->stroke)
 +	status = CAIRO_INT_STATUS_UNSUPPORTED;
 +    else
 +	status = (*surface->target->backend->stroke) (surface->target, op,
 +						      source, path, style,
 +						      ctm, ctm_inverse,
 +						      tolerance, antialias);
 +    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
 +	surface->fallback = TRUE;
 +	status = CAIRO_STATUS_SUCCESS;
 +    }
 +    return status;
 +}
 +
 +static cairo_int_status_t
 +_cairo_analysis_surface_fill (void			*abstract_surface,
 +			      cairo_operator_t		 op,
 +			      cairo_pattern_t		*source,
 +			      cairo_path_fixed_t	*path,
 +			      cairo_fill_rule_t	 	 fill_rule,
 +			      double			 tolerance,
 +			      cairo_antialias_t	 	 antialias)
 +{
 +    cairo_analysis_surface_t *surface = abstract_surface;
 +    cairo_status_t	     status;
 +
 +    if (!surface->target->backend->fill)
 +	status = CAIRO_INT_STATUS_UNSUPPORTED;
 +    else
 +	status = (*surface->target->backend->fill) (surface->target, op,
 +						    source, path, fill_rule,
 +						    tolerance, antialias);
 +    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
 +	surface->fallback = TRUE;
 +	status = CAIRO_STATUS_SUCCESS;
 +    }
 +    return status;
 +}
 +
 +static cairo_int_status_t
 +_cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
 +				     cairo_operator_t	   op,
 +				     cairo_pattern_t	  *source,
 +				     const cairo_glyph_t  *glyphs,
 +				     int		   num_glyphs,
 +				     cairo_scaled_font_t  *scaled_font)
 +{
 +    cairo_analysis_surface_t *surface = abstract_surface;
 +    cairo_status_t	     status;
 +
 +    if (!surface->target->backend->show_glyphs)
 +	status = CAIRO_INT_STATUS_UNSUPPORTED;
 +    else
 +	status = (*surface->target->backend->show_glyphs) (surface->target, op,
 +							   source,
 +							   glyphs, num_glyphs,
 +							   scaled_font);
 +    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
 +	surface->fallback = TRUE;
 +	status = CAIRO_STATUS_SUCCESS;
 +    }
 +    return status;
 +}
 +
 +static const cairo_surface_backend_t cairo_analysis_surface_backend = {
++    CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
 +    NULL, /* create_similar */
 +    NULL, /* finish_surface */
 +    NULL, /* acquire_source_image */
 +    NULL, /* release_source_image */
 +    NULL, /* acquire_dest_image */
 +    NULL, /* release_dest_image */
 +    NULL, /* clone_similar */
 +    NULL, /* composite */
 +    NULL, /* fill_rectangles */
 +    NULL, /* composite_trapezoids */
 +    NULL, /* copy_page */
 +    NULL, /* show_page */
 +    NULL, /* set_clip_region */
 +    NULL, /* clip_path */
 +    _cairo_analysis_surface_get_extents,
 +    NULL, /* old_show_glyphs */
 +    NULL, /* get_font_options */
 +    NULL, /* flush */
 +    NULL, /* mark_dirty_rectangle */
 +    NULL, /* scaled_font_fini */
 +    NULL, /* scaled_glyph_fini */
 +    _cairo_analysis_surface_paint,
 +    _cairo_analysis_surface_mask,
 +    _cairo_analysis_surface_stroke,
 +    _cairo_analysis_surface_fill,
 +    _cairo_analysis_surface_show_glyphs,
 +    NULL, /* snapshot */
 +};
 +
 +cairo_private cairo_surface_t *
 +_cairo_analysis_surface_create (cairo_surface_t		*target,
 +				int			 width,
 +				int			 height)
 +{
 +    cairo_analysis_surface_t *surface;
 +
 +    surface = malloc (sizeof (cairo_analysis_surface_t));
 +    if (surface == NULL)
 +	goto FAIL;
 +
 +    _cairo_surface_init (&surface->base, &cairo_analysis_surface_backend);
 +
 +    surface->width = width;
 +    surface->height = height;
 +
 +    surface->target = target;
 +    surface->fallback = FALSE;
 +
 +    return &surface->base;
 +FAIL:
 +    _cairo_error (CAIRO_STATUS_NO_MEMORY);
 +    return NULL;
 +}
 +
 +cairo_private pixman_region16_t *
 +_cairo_analysis_surface_get_supported (cairo_surface_t *abstract_surface)
 +{
 +    /* XXX */
 +    return NULL;
 +}
 +
 +cairo_private pixman_region16_t *
 +_cairo_analysis_surface_get_unsupported (cairo_surface_t *abstract_surface)
 +{
 +    /* XXX */
 +    return NULL;
 +}
 +
 +cairo_private cairo_bool_t
 +_cairo_analysis_surface_has_unsupported (cairo_surface_t *abstract_surface)
 +{
 +    cairo_analysis_surface_t	*surface = (cairo_analysis_surface_t *) abstract_surface;
 +
 +    return surface->fallback;
 +}
 +
 +
diff --cc src/cairo-ps-surface.c
index 305240a,99a1021..c8f5925
@@@ -643,48 -643,119 +643,129 @@@
  }
  
  static cairo_bool_t
 -pattern_operation_needs_fallback (cairo_operator_t op,
 -				  const cairo_pattern_t *pattern)
 +pattern_operation_supported (cairo_operator_t op,
 +			     const cairo_pattern_t *pattern)
  {
 -    if (! pattern_type_supported (pattern))
 -	return TRUE;
 -    if (operator_always_opaque (op))
 +    if (! pattern_supported (pattern))
  	return FALSE;
 -    if (operator_always_translucent (op))
 +    if (operator_always_opaque (op))
  	return TRUE;
 -    return pattern_is_translucent (pattern);
 +    if (operator_always_translucent (op))
 +	return FALSE;
 +    return pattern_is_opaque (pattern);
 +}
 +
 +static cairo_int_status_t
 +pattern_operation_analyze (cairo_operator_t op,
 +			   const cairo_pattern_t *pattern)
 +{
 +    if (pattern_operation_supported (op, pattern))
 +	return CAIRO_STATUS_SUCCESS;
 +    else
 +	return CAIRO_INT_STATUS_UNSUPPORTED;
  }
  
- /* PS Output - this section handles output of the parts of the meta
-  * surface we can render natively in PS. */
+ /* The "standard" implementation limit for PostScript string sizes is
+  * 65535 characters (see PostScript Language Reference, Appendix
+  * B). We go one short of that because we sometimes need two
+  * characters in a string to represent a single ASCII85 byte, (for the
+  * escape sequences "\\", "\(", and "\)") and we must not split these
+  * across two strings. So we'd be in trouble if we went right to the
+  * limit and one of these escape sequences just happened to land at
+  * the end.
+  */
+ #define STRING_ARRAY_MAX_STRING_SIZE (65535-1)
+ #define STRING_ARRAY_MAX_COLUMN	     72
  
- static void *
- compress_dup (const void *data, unsigned long data_size,
- 	      unsigned long *compressed_size)
- {
-     void *compressed;
- 
-     /* Bound calculation taken from zlib. */
-     *compressed_size = data_size + (data_size >> 12) + (data_size >> 14) + 11;
-     compressed = malloc (*compressed_size);
-     if (compressed == NULL)
- 	return NULL;
+ typedef struct _string_array_stream {
+     cairo_output_stream_t *output;
+     int column;
+     int string_size;
+ } string_array_stream_t;
+ 
+ static cairo_status_t
+ _string_array_stream_write (void		*closure,
+ 			    const unsigned char	*data,
+ 			    unsigned int	 length)
+ {
+     string_array_stream_t *stream = closure;
+     unsigned char c;
+     const unsigned char backslash = '\\';
+ 
+     if (length == 0)
+ 	return CAIRO_STATUS_SUCCESS;
+ 
+     while (length--) {
+ 	if (stream->string_size == 0) {
+ 	    _cairo_output_stream_printf (stream->output, "(");
+ 	    stream->column++;
+ 	}
+ 
+ 	c = *data++;
+ 	switch (c) {
+ 	case '\\':
+ 	case '(':
+ 	case ')':
+ 	    _cairo_output_stream_write (stream->output, &backslash, 1);
+ 	    stream->column++;
+ 	    stream->string_size++;
+ 	    break;
+ 	}
+ 	_cairo_output_stream_write (stream->output, &c, 1);
+ 	stream->column++;
+ 	stream->string_size++;
+ 
+ 	if (stream->string_size >= STRING_ARRAY_MAX_STRING_SIZE) {
+ 	    _cairo_output_stream_printf (stream->output, ")\n");
+ 	    stream->string_size = 0;
+ 	    stream->column = 0;
+ 	}
+ 	if (stream->column >= STRING_ARRAY_MAX_COLUMN) {
+ 	    _cairo_output_stream_printf (stream->output, "\n ");
+ 	    stream->string_size += 2;
+ 	    stream->column = 1;
+ 	}
+     }
+ 
+     return _cairo_output_stream_get_status (stream->output);
+ }
+ 
+ static cairo_status_t
+ _string_array_stream_close (void *closure)
+ {
+     cairo_status_t status;
+     string_array_stream_t *stream = closure;
+ 
+     _cairo_output_stream_printf (stream->output, ")\n");
+ 
+     status = _cairo_output_stream_get_status (stream->output);
+ 
+     free (stream);
+ 
+     return status;
+ }
  
-     compress (compressed, compressed_size, data, data_size);
+ static cairo_output_stream_t *
+ _string_array_stream_create (cairo_output_stream_t *output)
+ {
+     string_array_stream_t *stream;
  
-     return compressed;
+     stream = malloc (sizeof (string_array_stream_t));
+     if (stream == NULL)
+ 	return (cairo_output_stream_t *) &cairo_output_stream_nil;
+ 
+     stream->output = output;
+     stream->column = 0;
+     stream->string_size = 0;
+ 
+     return _cairo_output_stream_create (_string_array_stream_write,
+ 					_string_array_stream_close,
+ 					stream);
  }
  
+ /* PS Output - this section handles output of the parts of the meta
+  * surface we can render natively in PS. */
+ 
  static cairo_status_t
  emit_image (cairo_ps_surface_t    *surface,
  	    cairo_image_surface_t *image,
@@@ -768,28 -872,10 +871,10 @@@
      cairo_matrix_init (&d2i, 1, 0, 0, 1, 0, 0);
      cairo_matrix_multiply (&d2i, &d2i, matrix);
  
- #if 1
-     /* Construct a string holding the entire image (!) */
-     _cairo_output_stream_printf (surface->stream, "/%sString %d string def\n",
- 				 name, (int) rgb_size);
      _cairo_output_stream_printf (surface->stream,
- 				 "currentfile %sString readstring\n", name);
- #else
-     /* Construct a reusable stream decoder holding the image */
-     _cairo_output_stream_printf (surface->stream, "/%sString <<\n", name);
-     /* intent = image data */
-     _cairo_output_stream_printf (surface->stream, "\t/Intent 0\n");
- #endif    
-     /* Compressed image data */
-     _cairo_output_stream_write (surface->stream, rgb, rgb_size);
- 
-     _cairo_output_stream_printf (surface->stream,
- 				 "\n");
- 
-     _cairo_output_stream_printf (surface->stream, "/%s {\n", name);
-     _cairo_output_stream_printf (surface->stream,
- 				 "/DeviceRGB setcolorspace\n"
- 				 "<<\n"
 -				 "/%sImage {\n"
++				 "/%s {\n"
+ 				 "    /DeviceRGB setcolorspace\n"
+ 				 "    <<\n"
  				 "	/ImageType 1\n"
  				 "	/Width %d\n"
  				 "	/Height %d\n"
@@@ -805,9 -897,8 +896,8 @@@
  				 d2i.xx, d2i.yx,
  				 d2i.xy, d2i.yy,
  				 d2i.x0, d2i.y0);
-     _cairo_output_stream_printf (surface->stream, "} bind def\n");
 -    _cairo_output_stream_printf (surface->stream,
 -				 "%sImage\n", name);
 +
 +    status = CAIRO_STATUS_SUCCESS;
  
      free (compressed);
   bail2:
@@@ -839,40 -930,7 +929,41 @@@
  emit_surface_pattern (cairo_ps_surface_t *surface,
  		      cairo_surface_pattern_t *pattern)
  {
 -    /* XXX: NYI */
 +    cairo_rectangle_t		extents;
 +
 +    if (_cairo_surface_is_meta (pattern->surface)) {
 +	_cairo_output_stream_printf (surface->stream, "/MyPattern {\n");
 +	_cairo_meta_surface_replay (pattern->surface, &surface->base);
 +	extents.width = surface->width;
 +	extents.height = surface->height;
 +	_cairo_output_stream_printf (surface->stream, "} bind def\n");
 +    } else {
 +	cairo_image_surface_t	*image;
 +	void			*image_extra;
 +	cairo_status_t		status;
 +
 +	status = _cairo_surface_acquire_source_image (pattern->surface,
 +						      &image,
 +						      &image_extra);
 +	_cairo_surface_get_extents (&image->base, &extents);
 +	assert (status == CAIRO_STATUS_SUCCESS);
 +	emit_image (surface, image, &pattern->base.matrix, "MyPattern");
 +	_cairo_surface_release_source_image (pattern->surface, image,
 +					     image_extra);
 +    }
 +    _cairo_output_stream_printf (surface->stream,
- 				 "<< /PatternType 1 /PaintType 1 /TilingType 1\n");
++				 "<< /PatternType 1\n"
++				 "   /PaintType 1\n"
++				 "   /TilingType 1\n");
 +    _cairo_output_stream_printf (surface->stream,
- 				 "/BBox [0 0 %d %d]\n",
++				 "   /BBox [0 0 %d %d]\n",
 +				 extents.width, extents.height);
 +    _cairo_output_stream_printf (surface->stream,
- 				 "/XStep %d /YStep %d\n",
++				 "   /XStep %d /YStep %d\n",
 +				 extents.width, extents.height);
 +    _cairo_output_stream_printf (surface->stream,
- 				 "/PaintProc { begin MyPattern\n");
-     _cairo_output_stream_printf (surface->stream,
- 				 " end } bind >> matrix makepattern setpattern\n");
++				 "   /PaintProc { MyPattern } bind\n"
++				 ">> matrix makepattern setpattern\n");
  }
  
  static void
@@@ -1340,41 -1439,8 +1431,42 @@@
      return status;
  }
  
 +static cairo_int_status_t
 +_cairo_ps_surface_show_glyphs (void		     *abstract_surface,
 +			       cairo_operator_t	      op,
 +			       cairo_pattern_t	     *source,
 +			       const cairo_glyph_t   *glyphs,
 +			       int		      num_glyphs,
 +			       cairo_scaled_font_t   *scaled_font)
 +{
 +    cairo_ps_surface_t *surface = abstract_surface;
 +    cairo_output_stream_t *stream = surface->stream;
 +    cairo_int_status_t status;
 +    cairo_path_fixed_t *path;
 +
 +    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 +	return pattern_operation_analyze (op, source);
 +
 +    assert (pattern_operation_supported (op, source));
 +
 +    if (surface->need_start_page)
 +	_cairo_ps_surface_start_page (surface);
 +
 +    _cairo_output_stream_printf (stream,
 +				 "%% _cairo_ps_surface_show_glyphs\n");
 +
 +    path = _cairo_path_fixed_create ();
 +    _cairo_scaled_font_glyph_path (scaled_font, glyphs, num_glyphs, path);
 +    status = _cairo_ps_surface_fill (abstract_surface, op, source,
 +				     path, CAIRO_FILL_RULE_WINDING,
 +				     0.1, scaled_font->options.antialias);
 +    _cairo_path_fixed_destroy (path);
 +
 +    return CAIRO_STATUS_SUCCESS;
 +}
 +
  static const cairo_surface_backend_t cairo_ps_surface_backend = {
+     CAIRO_SURFACE_TYPE_PS,
      NULL, /* create_similar */
      _cairo_ps_surface_finish,
      NULL, /* acquire_source_image */
diff --cc src/cairoint.h
index 3d01e40,37998b7..6cd8bfb
@@@ -256,6 -260,14 +260,15 @@@
      CAIRO_INT_STATUS_CACHE_EMPTY
  } cairo_int_status_t;
  
+ typedef enum cairo_internal_surface_type {
+     CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000,
+     CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
++    CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
+     CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
+     CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+     CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
+ } cairo_internal_surface_type_t;
+ 
  typedef enum cairo_direction {
      CAIRO_DIRECTION_FORWARD,
      CAIRO_DIRECTION_REVERSE
diff --cc test/cairo-test.c
index 557ccb6,928ab63..0d8a961
@@@ -47,6 -47,20 +47,21 @@@
  #include "write-png.h"
  #include "xmalloc.h"
  
+ /* This is copied from cairoint.h. That makes it painful to keep in
+  * sync, but the slim stuff makes cairoint.h "hard" to include when
+  * not actually building the cairo library itself. Fortunately, since
+  * we're checking all these values, we do have a safeguard for keeping
+  * them in sync.
+  */
+ typedef enum cairo_internal_surface_type {
+     CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000,
+     CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
++    CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
+     CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
+     CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+     CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
+ } cairo_internal_surface_type_t;
+ 
  #ifdef _MSC_VER
  #define vsnprintf _vsnprintf
  #define access _access
diff-tree 45bbdf94cbac736c9f854012581e8f914a6e27df (from d1134cd7e25a78c70819df879336f895134bafe1)
Author: Carl Worth <cworth at raht.cworth.org>
Date:   Tue Apr 4 12:50:44 2006 -0700

    Break PostScript image data into chunks that each fit into a string.
    
    This solves the problem with the previous commit that made strings
    longer than the "standard" 65k implementation limit for strings.
    It's achieved by removing the line-wrapping from the base85 stream and
    instead adding a new string-array stream between the base85 stream and
    the output stream (the string-array stream does the line wrapping and
    enforces the 65k characters per string limit).

diff --git a/src/cairo-base85-stream.c b/src/cairo-base85-stream.c
index 4ea94ea..bd1a7ac 100644
--- a/src/cairo-base85-stream.c
+++ b/src/cairo-base85-stream.c
@@ -40,7 +40,6 @@ typedef struct _cairo_base85_stream {
     cairo_output_stream_t *output;
     unsigned char four_tuple[4];
     int pending;
-    int column;
 } cairo_base85_stream_t;
 
 static void
@@ -63,15 +62,6 @@ _expand_four_tuple_to_five (unsigned cha
     }
 }
 
-static void
-_cairo_base85_wrap_perhaps (cairo_base85_stream_t *stream)
-{
-    if (stream->column >= 72) {
-	_cairo_output_stream_write (stream->output, "\n", 1);
-	stream->column = 0;
-    }
-}
-
 static cairo_status_t
 _cairo_base85_stream_write_data (void			*closure,
 				 const unsigned char	*data,
@@ -87,14 +77,10 @@ _cairo_base85_stream_write_data (void			
 	length--;
 	if (stream->pending == 4) {
 	    _expand_four_tuple_to_five (stream->four_tuple, five_tuple, &is_zero);
-	    if (is_zero) {
+	    if (is_zero)
 		_cairo_output_stream_write (stream->output, "z", 1);
-		stream->column += 1;
-	    } else {
+	    else
 		_cairo_output_stream_write (stream->output, five_tuple, 5);
-		stream->column += 5;
-	    }
-	    _cairo_base85_wrap_perhaps (stream);
 	    stream->pending = 0;
 	}
     }
@@ -105,6 +91,7 @@ _cairo_base85_stream_write_data (void			
 static cairo_status_t
 _cairo_base85_stream_close (void *closure)
 {
+    cairo_status_t status;
     cairo_base85_stream_t *stream = closure;
     unsigned char five_tuple[5];
 
@@ -112,14 +99,16 @@ _cairo_base85_stream_close (void *closur
 	memset (stream->four_tuple + stream->pending, 0, 4 - stream->pending);
 	_expand_four_tuple_to_five (stream->four_tuple, five_tuple, NULL);
 	_cairo_output_stream_write (stream->output, five_tuple, stream->pending + 1);
-	stream->column += stream->pending + 1;
-	_cairo_base85_wrap_perhaps (stream);
     }
 
     /* Mark end of base85 data */
-    _cairo_output_stream_printf (stream->output, "~>\n");
+    _cairo_output_stream_printf (stream->output, "~>");
 
-    return _cairo_output_stream_get_status (stream->output);
+    status = _cairo_output_stream_get_status (stream->output);
+
+    free (stream);
+
+    return status;
 }
 
 cairo_output_stream_t *
@@ -133,7 +122,6 @@ _cairo_base85_stream_create (cairo_outpu
 
     stream->output = output;
     stream->pending = 0;
-    stream->column = 0;
 
     return _cairo_output_stream_create (_cairo_base85_stream_write_data,
 					_cairo_base85_stream_close,
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 11e346d..99a1021 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -655,6 +655,104 @@ pattern_operation_needs_fallback (cairo_
     return pattern_is_translucent (pattern);
 }
 
+/* The "standard" implementation limit for PostScript string sizes is
+ * 65535 characters (see PostScript Language Reference, Appendix
+ * B). We go one short of that because we sometimes need two
+ * characters in a string to represent a single ASCII85 byte, (for the
+ * escape sequences "\\", "\(", and "\)") and we must not split these
+ * across two strings. So we'd be in trouble if we went right to the
+ * limit and one of these escape sequences just happened to land at
+ * the end.
+ */
+#define STRING_ARRAY_MAX_STRING_SIZE (65535-1)
+#define STRING_ARRAY_MAX_COLUMN	     72
+
+typedef struct _string_array_stream {
+    cairo_output_stream_t *output;
+    int column;
+    int string_size;
+} string_array_stream_t;
+
+static cairo_status_t
+_string_array_stream_write (void		*closure,
+			    const unsigned char	*data,
+			    unsigned int	 length)
+{
+    string_array_stream_t *stream = closure;
+    unsigned char c;
+    const unsigned char backslash = '\\';
+
+    if (length == 0)
+	return CAIRO_STATUS_SUCCESS;
+
+    while (length--) {
+	if (stream->string_size == 0) {
+	    _cairo_output_stream_printf (stream->output, "(");
+	    stream->column++;
+	}
+
+	c = *data++;
+	switch (c) {
+	case '\\':
+	case '(':
+	case ')':
+	    _cairo_output_stream_write (stream->output, &backslash, 1);
+	    stream->column++;
+	    stream->string_size++;
+	    break;
+	}
+	_cairo_output_stream_write (stream->output, &c, 1);
+	stream->column++;
+	stream->string_size++;
+
+	if (stream->string_size >= STRING_ARRAY_MAX_STRING_SIZE) {
+	    _cairo_output_stream_printf (stream->output, ")\n");
+	    stream->string_size = 0;
+	    stream->column = 0;
+	}
+	if (stream->column >= STRING_ARRAY_MAX_COLUMN) {
+	    _cairo_output_stream_printf (stream->output, "\n ");
+	    stream->string_size += 2;
+	    stream->column = 1;
+	}
+    }
+
+    return _cairo_output_stream_get_status (stream->output);
+}
+
+static cairo_status_t
+_string_array_stream_close (void *closure)
+{
+    cairo_status_t status;
+    string_array_stream_t *stream = closure;
+
+    _cairo_output_stream_printf (stream->output, ")\n");
+
+    status = _cairo_output_stream_get_status (stream->output);
+
+    free (stream);
+
+    return status;
+}
+
+static cairo_output_stream_t *
+_string_array_stream_create (cairo_output_stream_t *output)
+{
+    string_array_stream_t *stream;
+
+    stream = malloc (sizeof (string_array_stream_t));
+    if (stream == NULL)
+	return (cairo_output_stream_t *) &cairo_output_stream_nil;
+
+    stream->output = output;
+    stream->column = 0;
+    stream->string_size = 0;
+
+    return _cairo_output_stream_create (_string_array_stream_write,
+					_string_array_stream_close,
+					stream);
+}
+
 /* PS Output - this section handles output of the parts of the meta
  * surface we can render natively in PS. */
 
@@ -683,7 +781,7 @@ emit_image (cairo_ps_surface_t    *surfa
     cairo_pattern_union_t pattern;
     cairo_matrix_t d2i;
     int x, y, i;
-    cairo_output_stream_t *base85_stream;
+    cairo_output_stream_t *base85_stream, *string_array_stream;
 
     /* PostScript can not represent the alpha channel, so we blend the
        current image over a white RGB surface to eliminate it. */
@@ -741,6 +839,8 @@ emit_image (cairo_ps_surface_t    *surfa
 	}
     }
 
+    /* XXX: Should fix cairo-lzw to provide a stream-based interface
+     * instead. */
     compressed_size = rgb_size;
     compressed = _cairo_lzw_compress (rgb, &compressed_size);
     if (compressed == NULL) {
@@ -751,22 +851,20 @@ emit_image (cairo_ps_surface_t    *surfa
     /* First emit the image data as a base85-encoded string which will
      * be used as the data source for the image operator later. */
     _cairo_output_stream_printf (surface->stream,
-				 "/%sData\n", name);
-    _cairo_output_stream_printf (surface->stream,
-				 "<~\n");
-    base85_stream = _cairo_base85_stream_create (surface->stream);
+				 "/%sData [\n", name);
 
-    _cairo_output_stream_write (base85_stream, compressed, compressed_size);
-    _cairo_output_stream_close (base85_stream);
+    string_array_stream = _string_array_stream_create (surface->stream);
+    base85_stream = _cairo_base85_stream_create (string_array_stream);
 
-    status = _cairo_output_stream_get_status (base85_stream);
-    if (status)
-	goto bail3;
+    _cairo_output_stream_write (base85_stream, compressed, compressed_size);
 
     _cairo_output_stream_destroy (base85_stream);
+    _cairo_output_stream_destroy (string_array_stream);
 
     _cairo_output_stream_printf (surface->stream,
-				 " def\n");
+				 "] def\n");
+    _cairo_output_stream_printf (surface->stream,
+				 "/%sDataIndex 0 def\n", name);
 
     /* matrix transforms from user space to image space.  We need to
      * transform from device space to image space to compensate for
@@ -783,7 +881,11 @@ emit_image (cairo_ps_surface_t    *surfa
 				 "	/Height %d\n"
 				 "	/BitsPerComponent 8\n"
 				 "	/Decode [ 0 1 0 1 0 1 ]\n"
-				 "	/DataSource %sData /LZWDecode filter \n"
+				 "	/DataSource {\n"
+				 "	    %sData %sDataIndex get\n"
+				 "	    /%sDataIndex %sDataIndex 1 add def\n"
+				 "	    %sDataIndex %sData length 1 sub gt { /%sDataIndex 0 def } if\n"
+				 "	} /ASCII85Decode filter /LZWDecode filter\n"
 				 "	/ImageMatrix [ %f %f %f %f %f %f ]\n"
 				 "    >>\n"
 				 "    image\n"
@@ -791,14 +893,13 @@ emit_image (cairo_ps_surface_t    *surfa
 				 name,
 				 opaque_image->width,
 				 opaque_image->height,
-				 name,
+				 name, name, name, name, name, name, name,
 				 d2i.xx, d2i.yx,
 				 d2i.xy, d2i.yy,
 				 d2i.x0, d2i.y0);
     _cairo_output_stream_printf (surface->stream,
 				 "%sImage\n", name);
 
- bail3:
     free (compressed);
  bail2:
     free (rgb);
diff-tree d1134cd7e25a78c70819df879336f895134bafe1 (from 0114393a132471cbf87bc3abc2f298b4ca38c69c)
Author: Carl Worth <cworth at raht.cworth.org>
Date:   Tue Apr 4 11:21:17 2006 -0700

    Emit images into PostScript output as strings rather than inline.
    
    This is a baby step toward having shared source patterns in the
    PostScript output. This patch is based on original work by Keith
    Packard in the following commit:
    
    	06b83b89fc4271060c63b284d7909162b92152f1
    
    One problem with this approach is that it attempts to put an entire
    image into a PostScript string object. However, PostScript strings are
    typically limited to 65k bytes. So, as is, this commit causes a few
    failures for tests in the suite with large output images.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 7689205..11e346d 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -663,6 +663,18 @@ emit_image (cairo_ps_surface_t    *surfa
 	    cairo_image_surface_t *image,
 	    cairo_matrix_t	  *matrix)
 {
+    /* Using a single name for all images is fine since we immediately
+     * use the image and never again reference it. Later calls will
+     * re-use the same name which will just store new image data under
+     * the same entries in the PostScript dictionaries.
+     *
+     * Eventually, we'll want to emit a shared image once into the
+     * PostScript output and re-use it. In order to do that, we'll
+     * need to support multiple images "in flight" at the same time,
+     * which means we'll need to have unique names here one way or
+     * another.
+     */
+    const char name[] = "Fallback";
     cairo_status_t status;
     unsigned char *rgb, *compressed;
     unsigned long rgb_size, compressed_size;
@@ -736,6 +748,26 @@ emit_image (cairo_ps_surface_t    *surfa
 	goto bail2;
     }
 
+    /* First emit the image data as a base85-encoded string which will
+     * be used as the data source for the image operator later. */
+    _cairo_output_stream_printf (surface->stream,
+				 "/%sData\n", name);
+    _cairo_output_stream_printf (surface->stream,
+				 "<~\n");
+    base85_stream = _cairo_base85_stream_create (surface->stream);
+
+    _cairo_output_stream_write (base85_stream, compressed, compressed_size);
+    _cairo_output_stream_close (base85_stream);
+
+    status = _cairo_output_stream_get_status (base85_stream);
+    if (status)
+	goto bail3;
+
+    _cairo_output_stream_destroy (base85_stream);
+
+    _cairo_output_stream_printf (surface->stream,
+				 " def\n");
+
     /* matrix transforms from user space to image space.  We need to
      * transform from device space to image space to compensate for
      * postscripts coordinate system. */
@@ -743,32 +775,28 @@ emit_image (cairo_ps_surface_t    *surfa
     cairo_matrix_multiply (&d2i, &d2i, matrix);
 
     _cairo_output_stream_printf (surface->stream,
-				 "/DeviceRGB setcolorspace\n"
-				 "<<\n"
+				 "/%sImage {\n"
+				 "    /DeviceRGB setcolorspace\n"
+				 "    <<\n"
 				 "	/ImageType 1\n"
 				 "	/Width %d\n"
 				 "	/Height %d\n"
 				 "	/BitsPerComponent 8\n"
 				 "	/Decode [ 0 1 0 1 0 1 ]\n"
-				 "	/DataSource currentfile /ASCII85Decode filter /LZWDecode filter \n"
+				 "	/DataSource %sData /LZWDecode filter \n"
 				 "	/ImageMatrix [ %f %f %f %f %f %f ]\n"
-				 ">>\n"
-				 "image\n",
+				 "    >>\n"
+				 "    image\n"
+				 "} def\n",
+				 name,
 				 opaque_image->width,
 				 opaque_image->height,
+				 name,
 				 d2i.xx, d2i.yx,
 				 d2i.xy, d2i.yy,
 				 d2i.x0, d2i.y0);
-
-    /* Compressed image data (Base85 encoded) */
-    base85_stream = _cairo_base85_stream_create (surface->stream);
-
-    _cairo_output_stream_write (base85_stream, compressed, compressed_size);
-    _cairo_output_stream_close (base85_stream);
-
-    status = _cairo_output_stream_get_status (base85_stream);
-
-    _cairo_output_stream_destroy (base85_stream);
+    _cairo_output_stream_printf (surface->stream,
+				 "%sImage\n", name);
 
  bail3:
     free (compressed);
diff-tree 0114393a132471cbf87bc3abc2f298b4ca38c69c (from dd67cf6616c2e819e7e8e4452c1e14e68b4a66bd)
Author: Carl Worth <cworth at raht.cworth.org>
Date:   Tue Apr 4 11:17:25 2006 -0700

    Explicitly remove the output png image before creating it during testing.
    
    What was happening here is that some backends (such as the PS surface
    backend) directly generate an output file, and then run a conversion
    process to generate the png file. Some bugs were such that a broken
    file would successfully be generated, the conversion would fail (the
    failure was unnoticed), and the test suite would happily verify the
    old image from a previously successful run.
    
    This fix eliminates this source of false positives.

diff --git a/test/cairo-test.c b/test/cairo-test.c
index d782a92..928ab63 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -1440,6 +1440,7 @@ cairo_test_for_target (cairo_test_t *tes
     /* Skip image check for tests with no image (width,height == 0,0) */
     if (test->width != 0 && test->height != 0) {
 	int pixels_changed;
+	xunlink (png_name);
 	(target->write_to_png) (surface, png_name);
 	if (target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
 	    pixels_changed = image_diff_flattened (png_name, ref_name, diff_name);
diff-tree dd67cf6616c2e819e7e8e4452c1e14e68b4a66bd (from 5a06133eb2e13a4c0354dad7f7da414c85733c4e)
Author: Carl Worth <cworth at raht.cworth.org>
Date:   Tue Apr 4 10:45:38 2006 -0700

    Implement proper cairo-style error-handling for cairo_output_stream_t.
    
    The cairo_output_stream_t object already had an internal status value,
    but it was annoyingly returning status values from various functions.
    It also was missing proper shutdown-on-error as well as nil-create
    semantics.
    
    This fixes those shortcomings and adjusts all callers for the new
    semantics, (leading to simpler and more correct calling
    code---particularly in the case of cairo-base85-stream.c).

diff --git a/src/cairo-base85-stream.c b/src/cairo-base85-stream.c
index 6adfa16..4ea94ea 100644
--- a/src/cairo-base85-stream.c
+++ b/src/cairo-base85-stream.c
@@ -63,19 +63,13 @@ _expand_four_tuple_to_five (unsigned cha
     }
 }
 
-static cairo_status_t
+static void
 _cairo_base85_wrap_perhaps (cairo_base85_stream_t *stream)
 {
-    cairo_status_t status;
-
     if (stream->column >= 72) {
-	status = _cairo_output_stream_write (stream->output, "\n", 1);
-	if (status)
-	    return status;
+	_cairo_output_stream_write (stream->output, "\n", 1);
 	stream->column = 0;
     }
-
-    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
@@ -83,7 +77,6 @@ _cairo_base85_stream_write_data (void			
 				 const unsigned char	*data,
 				 unsigned int		 length)
 {
-    cairo_status_t status;
     cairo_base85_stream_t *stream = closure;
     const unsigned char *ptr = data;
     unsigned char five_tuple[5];
@@ -95,49 +88,38 @@ _cairo_base85_stream_write_data (void			
 	if (stream->pending == 4) {
 	    _expand_four_tuple_to_five (stream->four_tuple, five_tuple, &is_zero);
 	    if (is_zero) {
-		status = _cairo_output_stream_write (stream->output, "z", 1);
+		_cairo_output_stream_write (stream->output, "z", 1);
 		stream->column += 1;
 	    } else {
-		status = _cairo_output_stream_write (stream->output, five_tuple, 5);
+		_cairo_output_stream_write (stream->output, five_tuple, 5);
 		stream->column += 5;
 	    }
-	    if (status)
-		return status;
-	    status = _cairo_base85_wrap_perhaps (stream);
-	    if (status)
-		return status;
+	    _cairo_base85_wrap_perhaps (stream);
 	    stream->pending = 0;
 	}
     }
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_output_stream_get_status (stream->output);
 }
 
 static cairo_status_t
 _cairo_base85_stream_close (void *closure)
 {
-    cairo_status_t status;
     cairo_base85_stream_t *stream = closure;
     unsigned char five_tuple[5];
 
     if (stream->pending) {
 	memset (stream->four_tuple + stream->pending, 0, 4 - stream->pending);
 	_expand_four_tuple_to_five (stream->four_tuple, five_tuple, NULL);
-	status = _cairo_output_stream_write (stream->output, five_tuple, stream->pending + 1);
-	if (status)
-	    return status;
+	_cairo_output_stream_write (stream->output, five_tuple, stream->pending + 1);
 	stream->column += stream->pending + 1;
-	status = _cairo_base85_wrap_perhaps (stream);
-	if (status)
-	    return status;
+	_cairo_base85_wrap_perhaps (stream);
     }
 
     /* Mark end of base85 data */
-    status = _cairo_output_stream_printf (stream->output, "~>\n");
-    if (status)
-	return status;
+    _cairo_output_stream_printf (stream->output, "~>\n");
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_output_stream_get_status (stream->output);
 }
 
 cairo_output_stream_t *
@@ -147,7 +129,7 @@ _cairo_base85_stream_create (cairo_outpu
 
     stream = malloc (sizeof (cairo_base85_stream_t));
     if (stream == NULL)
-	return NULL;
+	return (cairo_output_stream_t *) &cairo_output_stream_nil;
 
     stream->output = output;
     stream->pending = 0;
diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
index 1ed569c..adc00b8 100644
--- a/src/cairo-output-stream.c
+++ b/src/cairo-output-stream.c
@@ -49,6 +49,25 @@ struct _cairo_output_stream {
     void			*closure;
     unsigned long		position;
     cairo_status_t		status;
+    cairo_bool_t		closed;
+};
+
+const cairo_output_stream_t cairo_output_stream_nil = {
+    NULL, /* write_data */
+    NULL, /* close_func */
+    NULL, /* closure */
+    0,    /* position */
+    CAIRO_STATUS_NO_MEMORY,
+    FALSE /* closed */
+};
+
+static const cairo_output_stream_t cairo_output_stream_nil_write_error = {
+    NULL, /* write_data */
+    NULL, /* close_func */
+    NULL, /* closure */
+    0,    /* position */
+    CAIRO_STATUS_WRITE_ERROR,
+    FALSE /* closed */
 };
 
 cairo_output_stream_t *
@@ -60,41 +79,54 @@ _cairo_output_stream_create (cairo_write
 
     stream = malloc (sizeof (cairo_output_stream_t));
     if (stream == NULL)
-	return NULL;
+	return (cairo_output_stream_t *) &cairo_output_stream_nil;
 
     stream->write_data = write_data;
     stream->close_func = close_func;
     stream->closure = closure;
     stream->position = 0;
     stream->status = CAIRO_STATUS_SUCCESS;
+    stream->closed = FALSE;
 
     return stream;
 }
 
-cairo_status_t
-_cairo_output_stream_destroy (cairo_output_stream_t *stream)
+void
+_cairo_output_stream_close (cairo_output_stream_t *stream)
 {
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_status_t status;
 
-    if (stream->close_func)
+    if (stream->closed)
+	return;
+
+    if (stream->close_func) {
 	status = stream->close_func (stream->closure);
+	if (status)
+	    stream->status = status;
+    }
 
-    free (stream);
+    stream->closed = TRUE;
+}
 
-    return status;
+void
+_cairo_output_stream_destroy (cairo_output_stream_t *stream)
+{
+    _cairo_output_stream_close (stream);
+    free (stream);
 }
 
-cairo_status_t
+void
 _cairo_output_stream_write (cairo_output_stream_t *stream,
 			    const void *data, size_t length)
 {
     if (length == 0)
-	return CAIRO_STATUS_SUCCESS;
+	return;
+
+    if (stream->status)
+	return;
 
     stream->status = stream->write_data (stream->closure, data, length);
     stream->position += length;
-
-    return stream->status;
 }
 
 void
@@ -106,6 +138,9 @@ _cairo_output_stream_write_hex_string (c
     char buffer[2];
     int i, column;
 
+    if (stream->status)
+	return;
+
     for (i = 0, column = 0; i < length; i++, column++) {
 	if (column == 38) {
 	    _cairo_output_stream_write (stream, "\n", 1);
@@ -178,8 +213,7 @@ enum {
  * formatting.  This functionality is only for internal use and we
  * only implement the formats we actually use.
  */
-
-cairo_status_t
+void
 _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
 			      const char *fmt, va_list ap)
 {
@@ -188,6 +222,9 @@ _cairo_output_stream_vprintf (cairo_outp
     const char *f;
     int length_modifier;
 
+    if (stream->status)
+	return;
+
     f = fmt;
     p = buffer;
     while (*f != '\0') {
@@ -250,24 +287,19 @@ _cairo_output_stream_vprintf (cairo_outp
     }
     
     _cairo_output_stream_write (stream, buffer, p - buffer);
-
-    return stream->status;
 }
 
-cairo_status_t
+void
 _cairo_output_stream_printf (cairo_output_stream_t *stream,
 			     const char *fmt, ...)
 {
     va_list ap;
-    cairo_status_t status;    
 
     va_start (ap, fmt);
 
-    status = _cairo_output_stream_vprintf (stream, fmt, ap);
+    _cairo_output_stream_vprintf (stream, fmt, ap);
 
     va_end (ap);
-
-    return status;
 }
 
 long
@@ -312,16 +344,10 @@ cairo_output_stream_t *
 _cairo_output_stream_create_for_file (const char *filename)
 {
     FILE *file;
-    cairo_output_stream_t *stream;
 
     file = fopen (filename, "wb");
     if (file == NULL)
-	return NULL;
+	return (cairo_output_stream_t *) &cairo_output_stream_nil_write_error;
     
-    stream = _cairo_output_stream_create (stdio_write, stdio_close, file);
-
-    if (stream == NULL)
-	fclose (file);
-
-    return stream;
+    return _cairo_output_stream_create (stdio_write, stdio_close, file);
 }
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 4a783b5..cbccd64 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -333,11 +333,13 @@ cairo_pdf_surface_create_for_stream (cai
 				     double			 width_in_points,
 				     double			 height_in_points)
 {
+    cairo_status_t status;
     cairo_output_stream_t *stream;
 
     stream = _cairo_output_stream_create (write, NULL, closure);
-    if (stream == NULL) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+    status = _cairo_output_stream_get_status (stream);
+    if (status) {
+	_cairo_error (status);
 	return (cairo_surface_t*) &_cairo_surface_nil;
     }
 
@@ -368,11 +370,13 @@ cairo_pdf_surface_create (const char		*f
 			  double		 width_in_points,
 			  double		 height_in_points)
 {
+    cairo_status_t status;
     cairo_output_stream_t *stream;
 
     stream = _cairo_output_stream_create_for_file (filename);
-    if (stream == NULL) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+    status = _cairo_output_stream_get_status (stream);
+    if (status) {
+	_cairo_error (status);
 	return (cairo_surface_t*) &_cairo_surface_nil;
     }
 
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 4242a1e..7689205 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -178,11 +178,13 @@ cairo_ps_surface_create (const char		*fi
 			 double			 width_in_points,
 			 double			 height_in_points)
 {
+    cairo_status_t status;
     cairo_output_stream_t *stream;
 
     stream = _cairo_output_stream_create_for_file (filename);
-    if (stream == NULL) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+    status = _cairo_output_stream_get_status (stream);
+    if (status) {
+	_cairo_error (status);
 	return (cairo_surface_t*) &_cairo_surface_nil;
     }
 
@@ -216,11 +218,13 @@ cairo_ps_surface_create_for_stream (cair
 				    double		width_in_points,
 				    double		height_in_points)
 {
+    cairo_status_t status;
     cairo_output_stream_t *stream;
 
     stream = _cairo_output_stream_create (write_func, NULL, closure);
-    if (stream == NULL) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+    status = _cairo_output_stream_get_status (stream);
+    if (status) {
+	_cairo_error (status);
 	return (cairo_surface_t*) &_cairo_surface_nil;
     }
 
@@ -758,18 +762,13 @@ emit_image (cairo_ps_surface_t    *surfa
 
     /* Compressed image data (Base85 encoded) */
     base85_stream = _cairo_base85_stream_create (surface->stream);
-    if (base85_stream == NULL) {
-	status = CAIRO_STATUS_NO_MEMORY;
-	goto bail3;
-    }
 
-    status = _cairo_output_stream_write (base85_stream, compressed, compressed_size);
-    if (status) {
-	_cairo_output_stream_destroy (base85_stream);
-	goto bail3;
-    }
+    _cairo_output_stream_write (base85_stream, compressed, compressed_size);
+    _cairo_output_stream_close (base85_stream);
+
+    status = _cairo_output_stream_get_status (base85_stream);
 
-    status = _cairo_output_stream_destroy (base85_stream);
+    _cairo_output_stream_destroy (base85_stream);
 
  bail3:
     free (compressed);
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 7c38464..253055a 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -143,11 +143,15 @@ cairo_svg_surface_create_for_stream (cai
 				     double			width,
 				     double			height)
 {
+    cairo_status_t status;
     cairo_output_stream_t *stream;
 
     stream = _cairo_output_stream_create (write, NULL, closure);
-    if (stream == NULL)
-	return NULL;
+    status = _cairo_output_stream_get_status (stream);
+    if (status) {
+	_cairo_error (status);
+	return (cairo_surface_t *) &cairo_surface_nil;
+    }
 
     return _cairo_svg_surface_create_for_stream_internal (stream, width, height);
 }
@@ -157,11 +161,15 @@ cairo_svg_surface_create (const char	*fi
 			  double	width,
 			  double	height)
 {
+    cairo_status_t status;
     cairo_output_stream_t *stream;
 
     stream = _cairo_output_stream_create_for_file (filename);
-    if (stream == NULL)
-	return NULL;
+    status = _cairo_output_stream_get_status (stream);
+    if (status) {
+	_cairo_error (status);
+	return (cairo_surface_t *) &cairo_surface_nil;
+    }
 
     return _cairo_svg_surface_create_for_stream_internal (stream, width, height);
 }
diff --git a/src/cairoint.h b/src/cairoint.h
index 4203599..37998b7 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2124,6 +2124,8 @@ _cairo_utf8_to_utf16 (const unsigned cha
 
 typedef struct _cairo_output_stream cairo_output_stream_t;
 
+extern const cairo_private cairo_output_stream_t cairo_output_stream_nil;
+
 /* We already have the following declared in cairo.h:
 
 typedef cairo_status_t (*cairo_write_func_t) (void		  *closure,
@@ -2132,18 +2134,27 @@ typedef cairo_status_t (*cairo_write_fun
 */
 typedef cairo_status_t (*cairo_close_func_t) (void *closure);
 
+
+/* This function never returns NULL. If an error occurs (NO_MEMORY)
+ * while trying to create the output stream this function returns a
+ * valid pointer to a nil output stream.
+ *
+ * Note that even with a nil surface, the close_func callback will be
+ * called by a call to _cairo_output_stream_close or
+ * _cairo_output_stream_destroy.
+ */
 cairo_private cairo_output_stream_t *
 _cairo_output_stream_create (cairo_write_func_t		write_func,
 			     cairo_close_func_t		close_func,
 			     void			*closure);
 
-/* Most cairo destroy functions don't return a status, but we do here
- * to allow the return status from the close_func callback to be
- * captured. */
-cairo_private cairo_status_t
+cairo_private void
+_cairo_output_stream_close (cairo_output_stream_t *stream);
+
+cairo_private void
 _cairo_output_stream_destroy (cairo_output_stream_t *stream);
 
-cairo_private cairo_status_t
+cairo_private void
 _cairo_output_stream_write (cairo_output_stream_t *stream,
 			    const void *data, size_t length);
 
@@ -2152,14 +2163,14 @@ _cairo_output_stream_write_hex_string (c
 				       const char *data,
 				       size_t length);
 
-unsigned char *
+cairo_private unsigned char *
 _cairo_lzw_compress (unsigned char *data, unsigned long *data_size_in_out);
 
-cairo_private cairo_status_t
+cairo_private void
 _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
 			      const char *fmt, va_list ap);
 
-cairo_private cairo_status_t
+cairo_private void
 _cairo_output_stream_printf (cairo_output_stream_t *stream,
 			     const char *fmt, ...) CAIRO_PRINTF_FORMAT(2, 3);
 
@@ -2169,6 +2180,14 @@ _cairo_output_stream_get_position (cairo
 cairo_private cairo_status_t
 _cairo_output_stream_get_status (cairo_output_stream_t *stream);
 
+/* This function never returns NULL. If an error occurs (NO_MEMORY or
+ * WRITE_ERROR) while trying to create the output stream this function
+ * returns a valid pointer to a nil output stream.
+ *
+ * NOTE: Even if a nil surface is returned, the caller should still
+ * call _cairo_output_stream_destroy (or _cairo_output_stream_close at
+ * least) in order to ensure that everything is properly cleaned up.
+ */
 cairo_private cairo_output_stream_t *
 _cairo_output_stream_create_for_file (const char *filename);
 
diff-tree 5a06133eb2e13a4c0354dad7f7da414c85733c4e (from 57fe9b17b0a1a36acf0d8d524df05215ea48361f)
Author: Carl Worth <cworth at raht.cworth.org>
Date:   Mon Apr 3 23:44:51 2006 -0700

    Implement cairo-base85-stream as a filtering output stream not just a write function.
    
    Now _cairo_output_stream_create accepts a new close callback, (which
    the base85 stream uses to write its trailer). This eliminates the
    former kludge used to fclose the stdio output streams, and required a
    bit of touchup to the pdf, ps, and svg-surface usage of streams.

diff --git a/src/cairo-base85-stream.c b/src/cairo-base85-stream.c
index 0bb6f32..6adfa16 100644
--- a/src/cairo-base85-stream.c
+++ b/src/cairo-base85-stream.c
@@ -36,63 +36,125 @@
 
 #include "cairoint.h"
 
-static cairo_bool_t
-_convert_four_tuple (const unsigned char *four_tuple, char five_tuple[5])
+typedef struct _cairo_base85_stream {
+    cairo_output_stream_t *output;
+    unsigned char four_tuple[4];
+    int pending;
+    int column;
+} cairo_base85_stream_t;
+
+static void
+_expand_four_tuple_to_five (unsigned char four_tuple[4],
+			    unsigned char five_tuple[5],
+			    cairo_bool_t *all_zero)
 {
-    cairo_bool_t all_zero;
     uint32_t value;
     int digit, i;
     
     value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3];
-    all_zero = TRUE;
+    if (all_zero)
+	*all_zero = TRUE;
     for (i = 0; i < 5; i++) {
 	digit = value % 85;
-	if (digit != 0)
-	    all_zero = FALSE;
+	if (digit != 0 && all_zero)
+	    *all_zero = FALSE;
 	five_tuple[4-i] = digit + 33;
 	value = value / 85;
     }
-    return all_zero;
 }
 
-void
-_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream,
-					  const char *data,
-					  size_t length)
+static cairo_status_t
+_cairo_base85_wrap_perhaps (cairo_base85_stream_t *stream)
 {
-    unsigned char *ptr;
-    unsigned char four_tuple[4];
-    char five_tuple[5];
-    int column;
-    
-    ptr = (unsigned char *)data;
-    column = 0;
-    while (length > 0) {
-	if (length >= 4) {
-	    if (_convert_four_tuple (ptr, five_tuple)) {
-		column += 1;
-		_cairo_output_stream_write (stream, "z", 1);
+    cairo_status_t status;
+
+    if (stream->column >= 72) {
+	status = _cairo_output_stream_write (stream->output, "\n", 1);
+	if (status)
+	    return status;
+	stream->column = 0;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_base85_stream_write_data (void			*closure,
+				 const unsigned char	*data,
+				 unsigned int		 length)
+{
+    cairo_status_t status;
+    cairo_base85_stream_t *stream = closure;
+    const unsigned char *ptr = data;
+    unsigned char five_tuple[5];
+    cairo_bool_t is_zero;
+
+    while (length) {
+	stream->four_tuple[stream->pending++] = *ptr++;
+	length--;
+	if (stream->pending == 4) {
+	    _expand_four_tuple_to_five (stream->four_tuple, five_tuple, &is_zero);
+	    if (is_zero) {
+		status = _cairo_output_stream_write (stream->output, "z", 1);
+		stream->column += 1;
 	    } else {
-		column += 5;
-		_cairo_output_stream_write (stream, five_tuple, 5);
+		status = _cairo_output_stream_write (stream->output, five_tuple, 5);
+		stream->column += 5;
 	    }
-	    length -= 4;
-	    ptr += 4;
-	} else { /* length < 4 */
-	    memset (four_tuple, 0, 4);
-	    memcpy (four_tuple, ptr, length);
-	    _convert_four_tuple (four_tuple, five_tuple);
-	    column += length + 1;
-	    _cairo_output_stream_write (stream, five_tuple, length + 1);
-	    length = 0;
-	}
-	if (column >= 72) {
-	    _cairo_output_stream_write (stream, "\n", 1);
-	    column = 0;
+	    if (status)
+		return status;
+	    status = _cairo_base85_wrap_perhaps (stream);
+	    if (status)
+		return status;
+	    stream->pending = 0;
 	}
     }
 
-    if (column > 0) {
-	_cairo_output_stream_write (stream, "\n", 1);
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_base85_stream_close (void *closure)
+{
+    cairo_status_t status;
+    cairo_base85_stream_t *stream = closure;
+    unsigned char five_tuple[5];
+
+    if (stream->pending) {
+	memset (stream->four_tuple + stream->pending, 0, 4 - stream->pending);
+	_expand_four_tuple_to_five (stream->four_tuple, five_tuple, NULL);
+	status = _cairo_output_stream_write (stream->output, five_tuple, stream->pending + 1);
+	if (status)
+	    return status;
+	stream->column += stream->pending + 1;
+	status = _cairo_base85_wrap_perhaps (stream);
+	if (status)
+	    return status;
     }
+
+    /* Mark end of base85 data */
+    status = _cairo_output_stream_printf (stream->output, "~>\n");
+    if (status)
+	return status;
+
+    return CAIRO_STATUS_SUCCESS;
 }
+
+cairo_output_stream_t *
+_cairo_base85_stream_create (cairo_output_stream_t *output)
+{
+    cairo_base85_stream_t *stream;
+
+    stream = malloc (sizeof (cairo_base85_stream_t));
+    if (stream == NULL)
+	return NULL;
+
+    stream->output = output;
+    stream->pending = 0;
+    stream->column = 0;
+
+    return _cairo_output_stream_create (_cairo_base85_stream_write_data,
+					_cairo_base85_stream_close,
+					stream);
+}
+
diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
index b07423c..1ed569c 100644
--- a/src/cairo-output-stream.c
+++ b/src/cairo-output-stream.c
@@ -45,14 +45,15 @@
 
 struct _cairo_output_stream {
     cairo_write_func_t		write_data;
+    cairo_close_func_t		close_func;
     void			*closure;
-    cairo_bool_t		owns_closure_is_file;
     unsigned long		position;
     cairo_status_t		status;
 };
 
 cairo_output_stream_t *
 _cairo_output_stream_create (cairo_write_func_t		write_data,
+			     cairo_close_func_t		close_func,
 			     void			*closure)
 {
     cairo_output_stream_t *stream;
@@ -62,23 +63,25 @@ _cairo_output_stream_create (cairo_write
 	return NULL;
 
     stream->write_data = write_data;
+    stream->close_func = close_func;
     stream->closure = closure;
-    stream->owns_closure_is_file = FALSE;
     stream->position = 0;
     stream->status = CAIRO_STATUS_SUCCESS;
 
     return stream;
 }
 
-void
+cairo_status_t
 _cairo_output_stream_destroy (cairo_output_stream_t *stream)
 {
-    if (stream->owns_closure_is_file) {
-	FILE *file = stream->closure;
-	fflush (file);
-	fclose (file);
-    }
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+    if (stream->close_func)
+	status = stream->close_func (stream->closure);
+
     free (stream);
+
+    return status;
 }
 
 cairo_status_t
@@ -286,30 +289,39 @@ _cairo_output_stream_get_status (cairo_o
 static cairo_status_t
 stdio_write (void *closure, const unsigned char *data, unsigned int length)
 {
-    FILE *fp = closure;
+    FILE *file = closure;
 
-    if (fwrite (data, 1, length, fp) == length)
-	return CAIRO_STATUS_SUCCESS;
+    if (fwrite (data, 1, length, file) != length)
+	return CAIRO_STATUS_WRITE_ERROR;
 
-    return CAIRO_STATUS_WRITE_ERROR;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+stdio_close (void *closure)
+{
+    FILE *file = closure;
+
+    fflush (file);
+    fclose (file);
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_output_stream_t *
 _cairo_output_stream_create_for_file (const char *filename)
 {
-    FILE *fp;
+    FILE *file;
     cairo_output_stream_t *stream;
 
-    fp = fopen (filename, "wb");
-    if (fp == NULL)
+    file = fopen (filename, "wb");
+    if (file == NULL)
 	return NULL;
     
-    stream = _cairo_output_stream_create (stdio_write, fp);
+    stream = _cairo_output_stream_create (stdio_write, stdio_close, file);
 
-    if (stream)
-	stream->owns_closure_is_file = TRUE;
-    else
-	fclose (fp);
+    if (stream == NULL)
+	fclose (file);
 
     return stream;
 }
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 6d18196..4a783b5 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -335,7 +335,7 @@ cairo_pdf_surface_create_for_stream (cai
 {
     cairo_output_stream_t *stream;
 
-    stream = _cairo_output_stream_create (write, closure);
+    stream = _cairo_output_stream_create (write, NULL, closure);
     if (stream == NULL) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_surface_t*) &_cairo_surface_nil;
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index a646d45..4242a1e 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -218,7 +218,7 @@ cairo_ps_surface_create_for_stream (cair
 {
     cairo_output_stream_t *stream;
 
-    stream = _cairo_output_stream_create (write_func, closure);
+    stream = _cairo_output_stream_create (write_func, NULL, closure);
     if (stream == NULL) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_surface_t*) &_cairo_surface_nil;
@@ -667,6 +667,7 @@ emit_image (cairo_ps_surface_t    *surfa
     cairo_pattern_union_t pattern;
     cairo_matrix_t d2i;
     int x, y, i;
+    cairo_output_stream_t *base85_stream;
 
     /* PostScript can not represent the alpha channel, so we blend the
        current image over a white RGB surface to eliminate it. */
@@ -756,12 +757,21 @@ emit_image (cairo_ps_surface_t    *surfa
 				 d2i.x0, d2i.y0);
 
     /* Compressed image data (Base85 encoded) */
-    _cairo_output_stream_write_base85_string (surface->stream, (char *)compressed, compressed_size);
-    status = CAIRO_STATUS_SUCCESS;
+    base85_stream = _cairo_base85_stream_create (surface->stream);
+    if (base85_stream == NULL) {
+	status = CAIRO_STATUS_NO_MEMORY;
+	goto bail3;
+    }
 
-    /* Mark end of base85 data */
-    _cairo_output_stream_printf (surface->stream,
-				 "~>\n");
+    status = _cairo_output_stream_write (base85_stream, compressed, compressed_size);
+    if (status) {
+	_cairo_output_stream_destroy (base85_stream);
+	goto bail3;
+    }
+
+    status = _cairo_output_stream_destroy (base85_stream);
+
+ bail3:
     free (compressed);
  bail2:
     free (rgb);
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index d413408..7c38464 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -145,7 +145,7 @@ cairo_svg_surface_create_for_stream (cai
 {
     cairo_output_stream_t *stream;
 
-    stream = _cairo_output_stream_create (write, closure);
+    stream = _cairo_output_stream_create (write, NULL, closure);
     if (stream == NULL)
 	return NULL;
 
diff --git a/src/cairoint.h b/src/cairoint.h
index 3dc0f7e..4203599 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2124,11 +2124,23 @@ _cairo_utf8_to_utf16 (const unsigned cha
 
 typedef struct _cairo_output_stream cairo_output_stream_t;
 
+/* We already have the following declared in cairo.h:
+
+typedef cairo_status_t (*cairo_write_func_t) (void		  *closure,
+					      const unsigned char *data,
+					      unsigned int	   length);
+*/
+typedef cairo_status_t (*cairo_close_func_t) (void *closure);
+
 cairo_private cairo_output_stream_t *
 _cairo_output_stream_create (cairo_write_func_t		write_func,
+			     cairo_close_func_t		close_func,
 			     void			*closure);
 
-cairo_private void
+/* Most cairo destroy functions don't return a status, but we do here
+ * to allow the return status from the close_func callback to be
+ * captured. */
+cairo_private cairo_status_t
 _cairo_output_stream_destroy (cairo_output_stream_t *stream);
 
 cairo_private cairo_status_t
@@ -2140,11 +2152,6 @@ _cairo_output_stream_write_hex_string (c
 				       const char *data,
 				       size_t length);
 
-cairo_private void
-_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream,
-					  const char *data,
-					  size_t length);
-
 unsigned char *
 _cairo_lzw_compress (unsigned char *data, unsigned long *data_size_in_out);
 
@@ -2165,6 +2172,10 @@ _cairo_output_stream_get_status (cairo_o
 cairo_private cairo_output_stream_t *
 _cairo_output_stream_create_for_file (const char *filename);
 
+/* cairo_base85_stream.c */
+cairo_output_stream_t *
+_cairo_base85_stream_create (cairo_output_stream_t *output);
+
 cairo_private void
 _cairo_error (cairo_status_t status);
 
diff-tree 57fe9b17b0a1a36acf0d8d524df05215ea48361f (from 9bdb4f6ff713db0d101a0c0735dbb27e54fd7846)
Author: Carl Worth <cworth at raht.cworth.org>
Date:   Mon Apr 3 15:26:17 2006 -0700

    Move base85 code out of cairo-output-stream.c into new cairo-base85-stream.c

diff --git a/src/Makefile.am b/src/Makefile.am
index ad18568..5b3d75f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -134,6 +134,7 @@ libcairo_la_SOURCES =				\
 	cairo-arc.c				\
 	cairo-arc-private.h			\
 	cairo-array.c				\
+	cairo-base85-stream.c			\
 	cairo-cache.c				\
 	cairo-cache-private.h			\
 	cairo-clip.c				\
diff --git a/src/cairo-base85-stream.c b/src/cairo-base85-stream.c
new file mode 100644
index 0000000..0bb6f32
--- /dev/null
+++ b/src/cairo-base85-stream.c
@@ -0,0 +1,98 @@
+/* cairo_output_stream.c: Output stream abstraction
+ * 
+ * Copyright © 2005 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is cairo_output_stream.c as distributed with the
+ *   cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Author(s):
+ *	Kristian Høgsberg <krh at redhat.com>
+ */
+
+#include "cairoint.h"
+
+static cairo_bool_t
+_convert_four_tuple (const unsigned char *four_tuple, char five_tuple[5])
+{
+    cairo_bool_t all_zero;
+    uint32_t value;
+    int digit, i;
+    
+    value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3];
+    all_zero = TRUE;
+    for (i = 0; i < 5; i++) {
+	digit = value % 85;
+	if (digit != 0)
+	    all_zero = FALSE;
+	five_tuple[4-i] = digit + 33;
+	value = value / 85;
+    }
+    return all_zero;
+}
+
+void
+_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream,
+					  const char *data,
+					  size_t length)
+{
+    unsigned char *ptr;
+    unsigned char four_tuple[4];
+    char five_tuple[5];
+    int column;
+    
+    ptr = (unsigned char *)data;
+    column = 0;
+    while (length > 0) {
+	if (length >= 4) {
+	    if (_convert_four_tuple (ptr, five_tuple)) {
+		column += 1;
+		_cairo_output_stream_write (stream, "z", 1);
+	    } else {
+		column += 5;
+		_cairo_output_stream_write (stream, five_tuple, 5);
+	    }
+	    length -= 4;
+	    ptr += 4;
+	} else { /* length < 4 */
+	    memset (four_tuple, 0, 4);
+	    memcpy (four_tuple, ptr, length);
+	    _convert_four_tuple (four_tuple, five_tuple);
+	    column += length + 1;
+	    _cairo_output_stream_write (stream, five_tuple, length + 1);
+	    length = 0;
+	}
+	if (column >= 72) {
+	    _cairo_output_stream_write (stream, "\n", 1);
+	    column = 0;
+	}
+    }
+
+    if (column > 0) {
+	_cairo_output_stream_write (stream, "\n", 1);
+    }
+}
diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
index 6fd6181..b07423c 100644
--- a/src/cairo-output-stream.c
+++ b/src/cairo-output-stream.c
@@ -114,69 +114,6 @@ _cairo_output_stream_write_hex_string (c
     }
 }
 
-static cairo_bool_t
-convert_four_tuple (const unsigned char *four_tuple, char five_tuple[5])
-{
-    cairo_bool_t all_zero;
-    uint32_t value;
-    int digit, i;
-    
-    value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3];
-    all_zero = TRUE;
-    for (i = 0; i < 5; i++) {
-	digit = value % 85;
-	if (digit != 0)
-	    all_zero = FALSE;
-	five_tuple[4-i] = digit + 33;
-	value = value / 85;
-    }
-    return all_zero;
-}
-
-void
-_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream,
-					  const char *data,
-					  size_t length)
-{
-    unsigned char *ptr;
-    unsigned char four_tuple[4];
-    char five_tuple[5];
-    int column;
-    
-    ptr = (unsigned char *)data;
-    column = 0;
-    while (length > 0) {
-	if (length >= 4) {
-	    if (convert_four_tuple (ptr, five_tuple)) {
-		column += 1;
-		_cairo_output_stream_write (stream, "z", 1);
-	    } else {
-		column += 5;
-		_cairo_output_stream_write (stream, five_tuple, 5);
-	    }
-	    length -= 4;
-	    ptr += 4;
-	} else { /* length < 4 */
-	    memset (four_tuple, 0, 4);
-	    memcpy (four_tuple, ptr, length);
-	    convert_four_tuple (four_tuple, five_tuple);
-	    column += length + 1;
-	    _cairo_output_stream_write (stream, five_tuple, length + 1);
-	    length = 0;
-	}
-	if (column >= 72) {
-	    _cairo_output_stream_write (stream, "\n", 1);
-	    column = 0;
-	}
-    }
-
-    if (column > 0) {
-	_cairo_output_stream_write (stream, "\n", 1);
-    }
-}
-
-
-
 /* Format a double in a locale independent way and trim trailing
  * zeros.  Based on code from Alex Larson <alexl at redhat.com>.
  * http://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00087.html
diff-tree 9bdb4f6ff713db0d101a0c0735dbb27e54fd7846 (from 03eb1b85a906fac4acfbf3ee2839d13ccac97668)
Author: Christian Biesinger <cbiesinger at web.de>
Date:   Sun Apr 2 15:55:27 2006 +0200

    Use more portable shell syntax
    
    Reported by Dave Yeo in
    http://lists.freedesktop.org/archives/cairo/2006-April/006600.html
    
    Fixed for the other tests in 0883155111ab9597d335c7d43ae47c163b5c0e4d

diff --git a/configure.in b/configure.in
index 44783bd..020b394 100644
--- a/configure.in
+++ b/configure.in
@@ -810,6 +810,6 @@ if test x"$use_beos" = "xyes" ; then
    echo "$WARNING_MESSAGE" | sed 's/@BACKEND@/BeOS/'
 fi
 
-if test x"$use_directfb" == "xyes" ; then
+if test x"$use_directfb" = "xyes" ; then
      echo "$WARNING_MESSAGE" | sed 's/@BACKEND@/DirectFB/'
 fi
diff-tree 03eb1b85a906fac4acfbf3ee2839d13ccac97668 (from 6a430478f508361767bff91132c3978234b76e95)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Fri Mar 10 11:57:41 2006 -0800

    [win32] Add missing depth-16 format check
    (cherry picked from 969d624db8d32d35361bbcc89dbcc354f3d48eaa commit)

diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 3e88ec5..310561a 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -996,6 +996,8 @@ cairo_win32_surface_create (HDC hdc)
 	    format = CAIRO_FORMAT_ARGB32;
 	else if (depth == 24)
 	    format = CAIRO_FORMAT_RGB24;
+        else if (depth == 16)
+            format = CAIRO_FORMAT_RGB24;
 	else if (depth == 8)
 	    format = CAIRO_FORMAT_A8;
 	else if (depth == 1)
diff-tree 6a430478f508361767bff91132c3978234b76e95 (from 8fbd0d448dbdf8f556315366b64abe2468588ea6)
Author: Christian Biesinger <cbiesinger at web.de>
Date:   Tue Mar 14 13:25:51 2006 +0100

    Add an assert for the unsupported image surface formats

diff --git a/src/cairo-beos-surface.cpp b/src/cairo-beos-surface.cpp
index dfb0217..312bd88 100644
--- a/src/cairo-beos-surface.cpp
+++ b/src/cairo-beos-surface.cpp
@@ -367,6 +367,7 @@ _cairo_image_surface_to_bitmap (cairo_im
 	    return data;
 	}
 	default:
+	    assert(0);
 	    return NULL;
     }
 }
diff-tree 8fbd0d448dbdf8f556315366b64abe2468588ea6 (from 3259efed7690670754d7c1e76176ff26464111c3)
Author: Christian Biesinger <cbiesinger at web.de>
Date:   Mon Mar 27 02:31:51 2006 +0200

    Implement create_similar for BeOS

diff --git a/src/cairo-beos-surface.cpp b/src/cairo-beos-surface.cpp
index 6347ba7..dfb0217 100644
--- a/src/cairo-beos-surface.cpp
+++ b/src/cairo-beos-surface.cpp
@@ -70,6 +70,9 @@ struct cairo_beos_surface_t {
     BBitmap* bitmap;
 
 
+    // If true, surface and view should be deleted when this surface is
+    // destroyed
+    bool owns_bitmap_view;
 };
 
 class AutoLockView {
@@ -92,6 +95,11 @@ class AutoLockView {
 	bool   mOK;
 };
 
+static cairo_surface_t *
+_cairo_beos_surface_create_internal (BView*   view,
+				     BBitmap* bmp,
+				     bool     owns_bitmap_view = false);
+
 static BRect
 _cairo_rect_to_brect (const cairo_rectangle_t* rect)
 {
@@ -414,10 +422,76 @@ _cairo_op_to_be_op (cairo_operator_t cai
     };
 }
 
+static cairo_surface_t *
+_cairo_beos_surface_create_similar (void            *abstract_surface,
+				    cairo_content_t  content,
+				    int              width,
+				    int              height)
+{
+    fprintf(stderr, "Creating similar\n");
+
+    cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
+							abstract_surface);
+
+    if (width <= 0)
+	width = 1;
+    if (height <= 0)
+	height = 1;
+
+    BRect rect(0.0, 0.0, width - 1, height - 1);
+    BBitmap* bmp;
+    switch (content) {
+	case CAIRO_CONTENT_ALPHA:
+	    // Can't support this natively
+	    return _cairo_image_surface_create_with_content(content, width,
+							    height);
+	case CAIRO_CONTENT_COLOR_ALPHA:
+	    bmp = new BBitmap(rect, B_RGBA32, true);
+	    break;
+	case CAIRO_CONTENT_COLOR:
+	    // Match the color depth
+	    if (surface->bitmap) {
+		color_space space = surface->bitmap->ColorSpace();
+		// No alpha was requested -> make sure not to return
+		// a surface with alpha
+		if (space == B_RGBA32)
+		    space = B_RGB32;
+		if (space == B_RGBA15)
+		    space = B_RGB15;
+		bmp = new BBitmap(rect, space, true);
+	    } else {
+		BScreen scr(surface->view->Window());
+		color_space space = B_RGB32;
+		if (scr.IsValid())
+		    space = scr.ColorSpace();
+		bmp = new BBitmap(rect, space, true);
+	    }
+	    break;
+	default:
+	    assert(0);
+	    return NULL;
+	    
+    };
+    BView* view = new BView(rect, "Cairo bitmap view", B_FOLLOW_ALL_SIDES, 0);
+    bmp->AddChild(view);
+    return _cairo_beos_surface_create_internal(view, bmp, true);
+}
+
 static cairo_status_t
 _cairo_beos_surface_finish (void *abstract_surface)
 {
-    // Nothing to do
+    cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
+							abstract_surface);
+    if (surface->owns_bitmap_view) {
+	if (surface->bitmap)
+	    surface->bitmap->RemoveChild(surface->view);
+
+	delete surface->view;
+	delete surface->bitmap;
+
+	surface->view = NULL;
+	surface->bitmap = NULL;
+    }
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -549,13 +623,12 @@ _cairo_beos_surface_release_dest_image (
 
     cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
 							abstract_surface);
+
     AutoLockView locker(surface->view);
     if (!locker)
 	return;
 
-
     BBitmap* bitmap_to_draw = _cairo_image_surface_to_bitmap(image);
-
     surface->view->PushState();
 
 	surface->view->SetDrawingMode(B_OP_COPY);
@@ -617,46 +690,78 @@ _cairo_beos_surface_composite (cairo_ope
 
     cairo_surface_t* src_surface = reinterpret_cast<cairo_surface_pattern_t*>(src)->
 					surface;
-    if (_cairo_surface_is_image(src_surface)) {
-    	fprintf(stderr, "Composite\n");
 
-	// Draw it on screen.
+    // Get a bitmap
+    BBitmap* bmp = NULL;
+    bool free_bmp = false;
+    if (_cairo_surface_is_image(src_surface)) {
 	cairo_image_surface_t* img_surface =
 	    reinterpret_cast<cairo_image_surface_t*>(src_surface);
 
-	BBitmap* bmp = _cairo_image_surface_to_bitmap(img_surface);
-	surface->view->PushState();
+	bmp = _cairo_image_surface_to_bitmap(img_surface);
+	free_bmp = true;
+    } else if (src_surface->backend == surface->base.backend) {
+	cairo_beos_surface_t *beos_surface =
+	    reinterpret_cast<cairo_beos_surface_t*>(src_surface);
+	if (beos_surface->bitmap) {
+	    AutoLockView locker(beos_surface->view);
+	    if (locker)
+		beos_surface->view->Sync();
+	    bmp = beos_surface->bitmap;
+	} else {
+	    _cairo_beos_view_to_bitmap(surface->view, &bmp);
+	    free_bmp = true;
+	}
+    }
+
+    if (!bmp)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-	    // If our image rect is only a subrect of the desired size, and we
-	    // aren't using B_OP_ALPHA, then we need to fill the rect first.
-	    if (mode == B_OP_COPY && !bmp->Bounds().Contains(srcRect)) {
-		rgb_color black = { 0, 0, 0, 0 };
-
-		surface->view->SetDrawingMode(mode);
-		surface->view->SetHighColor(black);
-		surface->view->FillRect(dstRect);
-	    }
+    // So, BeOS seems to screw up painting an opaque bitmap onto a
+    // translucent one (it makes them partly transparent). Just return
+    // unsupported.
+    if (bmp->ColorSpace() == B_RGB32 && surface->bitmap &&
+	surface->bitmap->ColorSpace() == B_RGBA32 &&
+	(mode == B_OP_COPY || mode == B_OP_ALPHA))
+    {
+	if (free_bmp)
+	    delete bmp;
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
 
-	    if (mode == B_OP_ALPHA && img_surface->format != CAIRO_FORMAT_ARGB32) {
-		mode = B_OP_COPY;
+    fprintf(stderr, "Composite\n");
+
+    // Draw it on screen.
+    surface->view->PushState();
+
+	// If our image rect is only a subrect of the desired size, and we
+	// aren't using B_OP_ALPHA, then we need to fill the rect first.
+	if (mode == B_OP_COPY && !bmp->Bounds().Contains(srcRect)) {
+	    rgb_color black = { 0, 0, 0, 0 };
 
-	    }
 	    surface->view->SetDrawingMode(mode);
+	    surface->view->SetHighColor(black);
+	    surface->view->FillRect(dstRect);
+	}
 
-	    if (surface->bitmap && surface->bitmap->ColorSpace() == B_RGBA32)
-		surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
-	    else
-		surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
+	if (mode == B_OP_ALPHA && bmp->ColorSpace() == B_RGB32) {
+	    mode = B_OP_COPY;
+	}
+	surface->view->SetDrawingMode(mode);
 
-	    surface->view->DrawBitmap(bmp, srcRect, dstRect);
+	if (surface->bitmap && surface->bitmap->ColorSpace() == B_RGBA32)
+	    surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
+	else
+	    surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
 
-	surface->view->PopState();
-	delete bmp;
+	surface->view->DrawBitmap(bmp, srcRect, dstRect);
 
-	return CAIRO_INT_STATUS_SUCCESS;
-    }
+    surface->view->PopState();
 
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+    if (free_bmp)
+	delete bmp;
+
+    return CAIRO_INT_STATUS_SUCCESS;
 }
 
 
@@ -778,7 +883,7 @@ _cairo_beos_surface_get_extents (void   
 
 static const struct _cairo_surface_backend cairo_beos_surface_backend = {
     CAIRO_SURFACE_TYPE_BEOS,
-    NULL, /* create_similar */
+    _cairo_beos_surface_create_similar,
     _cairo_beos_surface_finish,
     _cairo_beos_surface_acquire_source_image,
     _cairo_beos_surface_release_source_image,
@@ -807,6 +912,28 @@ static const struct _cairo_surface_backe
     NULL  /* show_glyphs */
 };
 
+static cairo_surface_t *
+_cairo_beos_surface_create_internal (BView*   view,
+				     BBitmap* bmp,
+				     bool     owns_bitmap_view)
+{
+    // Must use malloc, because cairo code will use free() on the surface
+    cairo_beos_surface_t *surface = static_cast<cairo_beos_surface_t*>(
+					malloc(sizeof(cairo_beos_surface_t)));
+    if (surface == NULL) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+        return const_cast<cairo_surface_t*>(&_cairo_surface_nil);
+    }
+
+    _cairo_surface_init(&surface->base, &cairo_beos_surface_backend);
+
+    surface->view = view;
+    surface->bitmap = bmp;
+    surface->owns_bitmap_view = owns_bitmap_view;
+
+    return (cairo_surface_t *) surface;
+}
+
 /**
  * cairo_beos_surface_create:
  * @view: The view to draw on
@@ -843,20 +970,7 @@ cairo_surface_t *
 cairo_beos_surface_create_for_bitmap (BView*   view,
 				      BBitmap* bmp)
 {
-    // Must use malloc, because cairo code will use free() on the surface
-    cairo_beos_surface_t *surface = static_cast<cairo_beos_surface_t*>(
-					malloc(sizeof(cairo_beos_surface_t)));
-    if (surface == NULL) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-        return const_cast<cairo_surface_t*>(&_cairo_surface_nil);
-    }
-
-    _cairo_surface_init(&surface->base, &cairo_beos_surface_backend);
-
-    surface->view = view;
-    surface->bitmap = bmp;
-
-    return (cairo_surface_t *) surface;
+    return _cairo_beos_surface_create_internal(view, bmp);
 }
 
 // ---------------------------------------------------------------------------
diff-tree 3259efed7690670754d7c1e76176ff26464111c3 (from bcfe344608150aa56b1cb37dbc774455bfcf6830)
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Mar 23 15:36:41 2006 -0800

    _cairo_lzw_compress: Remove unused code which we had for testing
    conformance with the LZW compression from libtiff.

diff --git a/src/cairo-lzw.c b/src/cairo-lzw.c
index 1de618c..2a4a8e1 100644
--- a/src/cairo-lzw.c
+++ b/src/cairo-lzw.c
@@ -370,19 +370,6 @@ _cairo_lzw_compress (unsigned char *data
 
 	LZW_SYMBOL_SET_CODE (*slot, code_next++, prev, next);
 
-	/* The libtiff code detects a full table and clears it a bit
-	 * earlier than strictly necessary. Here is the code to do
-	 * that which might be useful in doing correctness comparisons
-	 * against the output of libtiff. */
-#if CLEAR_TABLE_EARLY_FOR_IDENTICAL_OUTPUT_COMPAREED_TO_LIBTIFF
-	if (code_next == LZW_BITS_BOUNDARY(LZW_BITS_MAX) - 1) {
-	    _lzw_symbol_table_init (&table);
-	    _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits);
-	    code_bits = LZW_BITS_MIN;
-	    code_next = LZW_CODE_FIRST;
-	}
-#endif
-
 	if (code_next > LZW_BITS_BOUNDARY(code_bits))
 	{
 	    code_bits++;
diff-tree bcfe344608150aa56b1cb37dbc774455bfcf6830 (from 639c2fe4df880546d71b2c73ea972fb08b609603)
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Mar 23 15:27:00 2006 -0800

    Optimize the implementation of _cairo_lzw_compress.
    
    This switches the implementation of _cairo_lzw_compress from using
    cairo-hash.c to a custom implementation of the same algorithm that
    takes advantage of the specific details of what is needed here.
    
    This final version now has comparable performance to the libtiff code,
    but should hopefully be easier to understand.
    
    Add a bunch of comments explaining how the various pieces work.

diff --git a/src/cairo-lzw.c b/src/cairo-lzw.c
index 67a41bd..1de618c 100644
--- a/src/cairo-lzw.c
+++ b/src/cairo-lzw.c
@@ -36,10 +36,9 @@
 
 #include "cairoint.h"
 
-static unsigned long
-_cairo_hash_bytes (const unsigned char *c, int size);
-
 typedef struct _lzw_buf {
+    cairo_status_t status;
+
     unsigned char *data;
     int data_size;
     int num_data;
@@ -52,46 +51,56 @@ typedef struct _lzw_buf {
  *
  * Initialize an lzw_buf_t to the given size in bytes.
  *
- * Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY.
+ * To store objects into the lzw_buf_t, call _lzw_buf_store_bits and
+ * when finished, call _lzw_buf_store_pending, (which flushes out the
+ * last few bits that hadn't yet made a complete byte yet).
+ *
+ * Instead of returning failure from any functions, lzw_buf_t provides
+ * a status value that the caller can query, (and should query at
+ * least once when done with the object). The status value will be
+ * either CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY;
  */
-static cairo_status_t
+static void
 _lzw_buf_init (lzw_buf_t *buf, int size)
 {
     if (size == 0)
 	size = 16;
 
+    buf->status = CAIRO_STATUS_SUCCESS;
+
     buf->data = malloc (size);
     if (buf->data == NULL) {
 	buf->data_size = 0;
-	return CAIRO_STATUS_NO_MEMORY;
+	buf->status = CAIRO_STATUS_NO_MEMORY;
+	return;
     }
 
     buf->data_size = size;
     buf->num_data = 0;
     buf->pending = 0;
     buf->pending_bits = 0;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_lzw_buf_fini (lzw_buf_t *buf)
-{
-    assert (buf->pending_bits == 0);
-
-    free (buf->data);
-    buf->data = 0;
 }
 
+/* Increase the buffer size by doubling.
+ *
+ * Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY
+ */
 static cairo_status_t
 _lzw_buf_grow (lzw_buf_t *buf)
 {
     int new_size = buf->data_size * 2;
     unsigned char *new_data;
 
+    if (buf->status)
+	return buf->status;
+
     new_data = realloc (buf->data, new_size);
-    if (new_data == NULL)
-	return CAIRO_STATUS_NO_MEMORY;
+    if (new_data == NULL) {
+	free (buf->data);
+	buf->data_size = 0;
+	buf->status = CAIRO_STATUS_NO_MEMORY;
+	return buf->status;
+    }
 
     buf->data = new_data;
     buf->data_size = new_size;
@@ -107,17 +116,17 @@ _lzw_buf_grow (lzw_buf_t *buf)
  * See also _lzw_buf_store_pending which must be called after the last
  * call to _lzw_buf_store_bits.
  *
- * Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY.
+ * Sets buf->status to either CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY.
  */
-static cairo_status_t
+static void
 _lzw_buf_store_bits (lzw_buf_t *buf, uint16_t value, int num_bits)
 {
     cairo_status_t status;
 
     assert (value <= (1 << num_bits) - 1);
 
-    if (getenv ("CAIRO_DEBUG_LZW"))
-	printf ("%d(%d) ", value, num_bits);
+    if (buf->status)
+	return;
 
     buf->pending = (buf->pending << num_bits) | value;
     buf->pending_bits += num_bits;
@@ -126,13 +135,11 @@ _lzw_buf_store_bits (lzw_buf_t *buf, uin
 	if (buf->num_data >= buf->data_size) {
 	    status = _lzw_buf_grow (buf);
 	    if (status)
-		return status;
+		return;
 	}
 	buf->data[buf->num_data++] = buf->pending >> (buf->pending_bits - 8);
 	buf->pending_bits -= 8;
     }
-
-    return CAIRO_STATUS_SUCCESS;
 }
 
 /* Store the last remaining pending bits into the buffer.
@@ -140,217 +147,267 @@ _lzw_buf_store_bits (lzw_buf_t *buf, uin
  * NOTE: This function must be called after the last call to
  * _lzw_buf_store_bits.
  *
- * Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY.
+ * Sets buf->status to either CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY.
  */
-static cairo_status_t
+static void
 _lzw_buf_store_pending  (lzw_buf_t *buf)
 {
     cairo_status_t status;
 
+    if (buf->status)
+	return;
+
     if (buf->pending_bits == 0)
-	return CAIRO_STATUS_SUCCESS;
+	return;
 
     assert (buf->pending_bits < 8);
 
     if (buf->num_data >= buf->data_size) {
 	status = _lzw_buf_grow (buf);
 	if (status)
-	    return status;
+	    return;
     }
 
     buf->data[buf->num_data++] = buf->pending << (8 - buf->pending_bits);
     buf->pending_bits = 0;
-
-    return CAIRO_STATUS_SUCCESS;
 }
 
-typedef struct _lzw_symbol {
-    cairo_hash_entry_t hash_entry;
+/* LZW defines a few magic code values */
+#define LZW_CODE_CLEAR_TABLE	256
+#define LZW_CODE_EOD		257
+#define LZW_CODE_FIRST		258
 
-    /* "key" is the symbol */
-    unsigned char *data;
-    int size;
-    /* "value" is the code */
-    int value;
-} lzw_symbol_t;
+/* We pack three separate values into a symbol as follows:
+ *
+ * 12 bits (31 down to 20):	CODE: code value used to represent this symbol
+ * 12 bits (19 down to  8):	PREV: previous code value in chain
+ *  8 bits ( 7 down to  0):	NEXT: next byte value in chain
+ */
+typedef uint32_t lzw_symbol_t;
+
+#define LZW_SYMBOL_SET(sym, prev, next)			((sym) = ((prev) << 8)|(next))
+#define LZW_SYMBOL_SET_CODE(sym, code, prev, next)	((sym) = ((code << 20)|(prev) << 8)|(next))
+#define LZW_SYMBOL_GET_CODE(sym)			(((sym) >> 20))
+#define LZW_SYMBOL_GET_PREV(sym)			(((sym) >>  8) & 0x7ff)
+#define LZW_SYMBOL_GET_BYTE(sym)			(((sym) >>  0) & 0x0ff)
 
+/* The PREV+NEXT fields can be seen as the key used to fetch values
+ * from the hash table, while the code is the value fetched.
+ */
+#define LZW_SYMBOL_KEY_MASK	0x000fffff
+
+/* Since code values are only stored starting with 258 we can safely
+ * use a zero value to represent free slots in the hash table. */
+#define LZW_SYMBOL_FREE		0x00000000
+
+/* These really aren't very free for modifying. First, the PostScript
+ * specification sets the 9-12 bit range. Second, the encoding of
+ * lzw_symbol_t above also relies on 2 of LZW_BITS_MAX plus one byte
+ * fitting within 32 bits.
+ *
+ * But other than that, the LZW compression scheme could function with
+ * more bits per code.
+ */
 #define LZW_BITS_MIN		9
 #define LZW_BITS_MAX		12
 #define LZW_BITS_BOUNDARY(bits)	((1<<(bits))-1)
 #define LZW_MAX_SYMBOLS		(1<<LZW_BITS_MAX)
 
-typedef struct _lzw_symbols {
-    lzw_symbol_t symbols[LZW_MAX_SYMBOLS];
-    int num_symbols;
-
-    cairo_hash_table_t *table;
-} lzw_symbols_t;
-
-static cairo_bool_t
-_lzw_symbols_equal (const void *key_a, const void *key_b)
-{
-    const lzw_symbol_t *symbol_a = key_a;
-    const lzw_symbol_t *symbol_b = key_b;
-
-    if (symbol_a->size != symbol_b->size)
-	return FALSE;
-
-    return ! memcmp (symbol_a->data, symbol_b->data, symbol_a->size);
-}
-
-static cairo_status_t
-_lzw_symbols_init (lzw_symbols_t *symbols)
-{
-    symbols->num_symbols = 0;
-
-    symbols->table = _cairo_hash_table_create (_lzw_symbols_equal);
-    if (symbols->table == NULL)
-	return CAIRO_STATUS_NO_MEMORY;
-
-    return CAIRO_STATUS_SUCCESS;
-}
+#define LZW_SYMBOL_TABLE_SIZE	9013
+#define LZW_SYMBOL_MOD1		LZW_SYMBOL_TABLE_SIZE
+#define LZW_SYMBOL_MOD2		9011
+
+typedef struct _lzw_symbol_table {
+    lzw_symbol_t table[LZW_SYMBOL_TABLE_SIZE];
+} lzw_symbol_table_t;
 
+/* Initialize the hash table to entirely empty */
 static void
-_lzw_symbols_fini (lzw_symbols_t *symbols)
+_lzw_symbol_table_init (lzw_symbol_table_t *table)
 {
-    int i;
-
-    for (i=0; i < symbols->num_symbols; i++)
-	_cairo_hash_table_remove (symbols->table, &symbols->symbols[i].hash_entry);
-
-    symbols->num_symbols = 0;
-
-    _cairo_hash_table_destroy (symbols->table);
+    memset (table->table, 0, LZW_SYMBOL_TABLE_SIZE * sizeof (lzw_symbol_t));
 }
 
+/* Lookup a symbol in the symbol table. The PREV and NEXT fields of
+ * symbol form the key for the lookup.
+ *
+ * If succesful, then this function returns TRUE and slot_ret will be
+ * left pointing at the result that will have the CODE field of
+ * interest.
+ *
+ * If the lookup fails, then this function returns FALSE and slot_ret
+ * will be pointing at the location in the table to which a new CODE
+ * value should be stored along with PREV and NEXT.
+ */
 static cairo_bool_t
-_lzw_symbols_has (lzw_symbols_t *symbols,
-		  lzw_symbol_t  *symbol,
-		  lzw_symbol_t **code)
-{
-    symbol->hash_entry.hash = _cairo_hash_bytes (symbol->data, symbol->size);
-
-    return _cairo_hash_table_lookup (symbols->table,
-				     &symbol->hash_entry,
-				     (cairo_hash_entry_t **) code);
-}
-
-static cairo_status_t
-_lzw_symbols_store (lzw_symbols_t *symbols,
-		    lzw_symbol_t  *symbol)
-{
-    cairo_status_t status;
-
-    symbol->hash_entry.hash = _cairo_hash_bytes (symbol->data, symbol->size);
-
-    symbols->symbols[symbols->num_symbols] = *symbol;
+_lzw_symbol_table_lookup (lzw_symbol_table_t	 *table,
+			  lzw_symbol_t		  symbol,
+			  lzw_symbol_t		**slot_ret)
+{
+    /* The algorithm here is identical to that in cairo-hash.c. We
+     * copy it here to allow for a rather more efficient
+     * implementation due to several circumstances that do not apply
+     * to the more general case:
+     *
+     * 1) We have a known bound on the total number of symbols, so we
+     *    have a fixed-size table without any copying when growing
+     *
+     * 2) We never delete any entries, so we don't need to
+     *    support/check for DEAD entries during lookup.
+     *
+     * 3) The object fits in 32 bits so we store each object in its
+     *    entirety within the table rather than storing objects
+     *    externally and putting pointers in the table, (which here
+     *    would just double the storage requirements and have negative
+     *    impacts on memory locality).
+     */
+    int i, idx, step, hash = symbol & LZW_SYMBOL_KEY_MASK;
+    lzw_symbol_t candidate;
+
+    idx = hash % LZW_SYMBOL_MOD1;
+    step = 0;
+
+    *slot_ret = NULL;
+    for (i = 0; i < LZW_SYMBOL_TABLE_SIZE; i++)
+    {
+	candidate = table->table[idx];
+	if (candidate == LZW_SYMBOL_FREE)
+	{
+	    *slot_ret = &table->table[idx];
+	    return FALSE;
+	}
+	else /* candidate is LIVE */
+	{
+	    if ((candidate & LZW_SYMBOL_KEY_MASK) ==
+		(symbol & LZW_SYMBOL_KEY_MASK))
+	    {
+		*slot_ret = &table->table[idx];
+		return TRUE;
+	    }
+	}
 
-    status = _cairo_hash_table_insert (symbols->table, &symbols->symbols[symbols->num_symbols].hash_entry);
-    if (status)
-	return status;
+	if (step == 0) {
+	    step = hash % LZW_SYMBOL_MOD2;
+	    if (step == 0)
+		step = 1;
+	}
 
-    symbols->num_symbols++;
+	idx += step;
+	if (idx >= LZW_SYMBOL_TABLE_SIZE)
+	    idx -= LZW_SYMBOL_TABLE_SIZE;
+    }
 
-    return CAIRO_STATUS_SUCCESS;
+    return FALSE;
 }
 
-#define LZW_CODE_CLEAR_TABLE	256
-#define LZW_CODE_EOD		257
-#define LZW_CODE_FIRST		258
-
-unsigned char *
+/* Compress a bytestream using the LZW algorithm.
+ *
+ * This is an original implementation based on reading the
+ * specification of the LZWDecode filter in the PostScript Language
+ * Reference. The free parameters in the LZW algorithm are set to the
+ * values mandated by PostScript, (symbols encoded with widths from 9
+ * to 12 bits).
+ *
+ * This function returns a pointer to a newly allocated buffer holding
+ * the compressed data, or NULL if an out-of-memory situation
+ * occurs.
+ *
+ * Notice that any one of the _lzw_buf functions called here could
+ * trigger an out-of-memory condition. But lzw_buf_t uses cairo's
+ * shutdown-on-error idiom, so it's safe to continue to call into
+ * lzw_buf without having to check for errors, (until a final check at
+ * the end).
+ */
+cairo_public unsigned char *
 _cairo_lzw_compress (unsigned char *data, unsigned long *size_in_out)
 {
-    cairo_status_t status;
     int bytes_remaining = *size_in_out;
-    lzw_symbols_t symbols;
-    lzw_symbol_t symbol, *tmp, *code;
     lzw_buf_t buf;
+    lzw_symbol_table_t table;
+    lzw_symbol_t symbol, *slot;
     int code_next = LZW_CODE_FIRST;
     int code_bits = LZW_BITS_MIN;
+    int prev, next;
 
-    status = _lzw_buf_init (&buf, *size_in_out / 4);
-    if (status)
+    if (*size_in_out == 0)
 	return NULL;
 
-    status = _lzw_symbols_init (&symbols);
-    if (status) {
-	_lzw_buf_fini (&buf);
-	return NULL;
-    }
+    _lzw_buf_init (&buf, *size_in_out);
 
-    _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits);
+    _lzw_symbol_table_init (&table);
     
-    symbol.data = data;
-    symbol.size = 2;
+    /* The LZW header is a clear table code. */
+    _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits);
 
-    while (bytes_remaining) {
-	code = NULL;
-	while (symbol.size <= bytes_remaining &&
-	       _lzw_symbols_has (&symbols, &symbol, &tmp))
-	{
-	    code = tmp;
-	    symbol.size++;
+    while (1) {
+
+	/* Find the longest existing code in the symbol table that
+	 * matches the current input, if any. */
+	prev = *data++;
+	bytes_remaining--;
+	if (bytes_remaining) {
+	    do
+	    {
+		next = *data++;
+		bytes_remaining--;
+		LZW_SYMBOL_SET (symbol, prev, next);
+		if (_lzw_symbol_table_lookup (&table, symbol, &slot))
+		    prev = LZW_SYMBOL_GET_CODE (*slot);
+	    } while (bytes_remaining && *slot != LZW_SYMBOL_FREE);
+	    if (*slot == LZW_SYMBOL_FREE) {
+		data--;
+		bytes_remaining++;
+	    }
 	}
 
-	if (code)
-	    _lzw_buf_store_bits (&buf, code->value, code_bits);
-	else
-	    _lzw_buf_store_bits (&buf, symbol.data[0], code_bits);
+	/* Write the code into the output. This is either a byte read
+	 * directly from the input, or a code from the last successful
+	 * lookup. */
+	_lzw_buf_store_bits (&buf, prev, code_bits);
 
-	if (symbol.size == bytes_remaining + 1)
+	if (bytes_remaining == 0)
 	    break;
 
-	symbol.value = code_next++;
-	_lzw_symbols_store (&symbols, &symbol);
+	LZW_SYMBOL_SET_CODE (*slot, code_next++, prev, next);
 
-	/* XXX: This is just for compatibility testing against libtiff. */
+	/* The libtiff code detects a full table and clears it a bit
+	 * earlier than strictly necessary. Here is the code to do
+	 * that which might be useful in doing correctness comparisons
+	 * against the output of libtiff. */
+#if CLEAR_TABLE_EARLY_FOR_IDENTICAL_OUTPUT_COMPAREED_TO_LIBTIFF
 	if (code_next == LZW_BITS_BOUNDARY(LZW_BITS_MAX) - 1) {
-	    _lzw_symbols_fini (&symbols);
-	    _lzw_symbols_init (&symbols);
+	    _lzw_symbol_table_init (&table);
 	    _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits);
 	    code_bits = LZW_BITS_MIN;
 	    code_next = LZW_CODE_FIRST;
 	}
+#endif
 
 	if (code_next > LZW_BITS_BOUNDARY(code_bits))
 	{
 	    code_bits++;
 	    if (code_bits > LZW_BITS_MAX) {
-		_lzw_symbols_fini (&symbols);
-		_lzw_symbols_init (&symbols);
-		_lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits);
+		_lzw_symbol_table_init (&table);
+		_lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits - 1);
 		code_bits = LZW_BITS_MIN;
 		code_next = LZW_CODE_FIRST;
 	    }
 	}
-
-	if (code) {
-	    symbol.data += (symbol.size - 1);
-	    bytes_remaining -= (symbol.size - 1);
-	} else {
-	    symbol.data += 1;
-	    bytes_remaining -= 1;
-	}
-	symbol.size = 2;
     }
 
+    /* The LZW footer is an end-of-data code. */
     _lzw_buf_store_bits (&buf, LZW_CODE_EOD, code_bits);
 
     _lzw_buf_store_pending (&buf);
 
-    _lzw_symbols_fini (&symbols);
+    /* See if we ever ran out of memory while writing to buf. */
+    if (buf.status == CAIRO_STATUS_NO_MEMORY) {
+	*size_in_out = 0;
+	return NULL;
+    }
+
+    assert (buf.status == CAIRO_STATUS_SUCCESS);
 
     *size_in_out = buf.num_data;
     return buf.data;
 }
-
-static unsigned long
-_cairo_hash_bytes (const unsigned char *c, int size)
-{
-    /* This is the djb2 hash. */
-    unsigned long hash = 5381;
-    while (size--)
-	hash = ((hash << 5) + hash) + *c++;
-    return hash;
-}
diff-tree 639c2fe4df880546d71b2c73ea972fb08b609603 (from ec60bb0a606cadf3120d1cebc88e248a3e056c19)
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Mar 23 15:23:29 2006 -0800

    cairo-lzw: Replace LZW code from libtiff with an original implementation.
    
    This new implementation is an entirely original work directly from the
    description of the LZWDecode filter in the PostScript Language
    Reference, (and in spite of the bugs in the examples provided in that
    reference).
    
    This implementation uses the existing cairo-hash.c for the symbol
    table. This implementation is somewhat easier to read than the libtiff
    code, and avoids any code that may have an advertising clause
    attached. This new implementation is the simplest thing I could
    implement. It is not as efficient as the libtiff code, (though I did
    expect better things from cairo-hash.c).

diff --git a/src/cairo-lzw.c b/src/cairo-lzw.c
index a0d737e..67a41bd 100644
--- a/src/cairo-lzw.c
+++ b/src/cairo-lzw.c
@@ -1,6 +1,6 @@
 /* cairo - a vector graphics library with display and print output
  *
- * Copyright © 2006 Red Hat, Inc
+ * Copyright © 2006 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
@@ -27,473 +27,330 @@
  *
  * The Original Code is the cairo graphics library.
  *
- * Contributor(s):
- *	Alexander Larsson <alexl at redhat.com>
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
  *
- * This code is derived from tif_lzw.c in libtiff 3.8.0.
- * The original copyright notice appears below in its entirety.
+ * Contributor(s):
+ *	Carl D. Worth <cworth at cworth.org>
  */
 
 #include "cairoint.h"
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <string.h>
-
-/*
- * Copyright (c) 1988-1997 Sam Leffler
- * Copyright (c) 1991-1997 Silicon Graphics, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and 
- * its documentation for any purpose is hereby granted without fee, provided
- * that (i) the above copyright notices and this permission notice appear in
- * all copies of the software and related documentation, and (ii) the names of
- * Sam Leffler and Silicon Graphics may not be used in any advertising or
- * publicity relating to the software without the specific, prior written
- * permission of Sam Leffler and Silicon Graphics.
- * 
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
- * 
- * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
- * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
- * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
- * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
- * OF THIS SOFTWARE.
- */
+static unsigned long
+_cairo_hash_bytes (const unsigned char *c, int size);
+
+typedef struct _lzw_buf {
+    unsigned char *data;
+    int data_size;
+    int num_data;
+    uint32_t pending;
+    int pending_bits;
+} lzw_buf_t;
 
-/*
- * TIFF Library.
- * Rev 5.0 Lempel-Ziv & Welch Compression Support
- *
- * This code is derived from the compress program whose code is
- * derived from software contributed to Berkeley by James A. Woods,
- * derived from original work by Spencer Thomas and Joseph Orost.
+/* An lzw_buf_t is a simple, growable chunk of memory for holding
+ * variable-size objects of up to 16 bits each.
  *
- * The original Berkeley copyright notice appears below in its entirety.
+ * Initialize an lzw_buf_t to the given size in bytes.
+ *
+ * Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY.
  */
+static cairo_status_t
+_lzw_buf_init (lzw_buf_t *buf, int size)
+{
+    if (size == 0)
+	size = 16;
+
+    buf->data = malloc (size);
+    if (buf->data == NULL) {
+	buf->data_size = 0;
+	return CAIRO_STATUS_NO_MEMORY;
+    }
+
+    buf->data_size = size;
+    buf->num_data = 0;
+    buf->pending = 0;
+    buf->pending_bits = 0;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_lzw_buf_fini (lzw_buf_t *buf)
+{
+    assert (buf->pending_bits == 0);
+
+    free (buf->data);
+    buf->data = 0;
+}
+
+static cairo_status_t
+_lzw_buf_grow (lzw_buf_t *buf)
+{
+    int new_size = buf->data_size * 2;
+    unsigned char *new_data;
+
+    new_data = realloc (buf->data, new_size);
+    if (new_data == NULL)
+	return CAIRO_STATUS_NO_MEMORY;
+
+    buf->data = new_data;
+    buf->data_size = new_size;
 
-#define MAXCODE(n)	((1L<<(n))-1)
-/*
- * The TIFF spec specifies that encoded bit
- * strings range from 9 to 12 bits.
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/* Store the lowest num_bits bits of values into buf.
+ *
+ * NOTE: The bits of value above size_in_bits must be 0, (so don't lie
+ * about the size).
+ *
+ * See also _lzw_buf_store_pending which must be called after the last
+ * call to _lzw_buf_store_bits.
+ *
+ * Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY.
  */
-#define	BITS_MIN	9		/* start with 9 bits */
-#define	BITS_MAX	12		/* max of 12 bit strings */
-/* predefined codes */
-#define	CODE_CLEAR	256		/* code to clear string table */
-#define	CODE_EOI	257		/* end-of-information code */
-#define CODE_FIRST	258		/* first free code entry */
-#define	CODE_MAX	MAXCODE(BITS_MAX)
-#define	HSIZE		9001L		/* 91% occupancy */
-#define	HSHIFT		(13-8)
-#ifdef LZW_COMPAT
-/* NB: +1024 is for compatibility with old files */
-#define	CSIZE		(MAXCODE(BITS_MAX)+1024L)
-#else
-#define	CSIZE		(MAXCODE(BITS_MAX)+1L)
-#endif
-
-typedef uint16_t hcode_t;			/* codes fit in 16 bits */
-typedef struct {
-	long	hash;
-	hcode_t	code;
-} hash_t;
-
-typedef struct {
-	/* Out buffer */
-	unsigned char  *out_buffer;		/* compressed out buffer */
-	size_t		out_buffer_size;	/* # of allocated bytes in out buffer */
-	unsigned char  *out_buffer_pos;		/* current spot in out buffer */
-	size_t		out_buffer_bytes;	/* # of data bytes in out buffer */
-	unsigned char  *out_buffer_end;		/* bound on out_buffer */
-	
-	unsigned short	nbits;		/* # of bits/code */
-	unsigned short	maxcode;	/* maximum code for lzw_nbits */
-	unsigned short	free_ent;	/* next free entry in hash table */
-	long		nextdata;	/* next bits of i/o */
-	long		nextbits;	/* # of valid bits in lzw_nextdata */
-
-	int	enc_oldcode;		/* last code encountered */
-	long	enc_checkpoint;		/* point at which to clear table */
-#define CHECK_GAP	10000		/* enc_ratio check interval */
-	long	enc_ratio;		/* current compression ratio */
-	long	enc_incount;		/* (input) data bytes encoded */
-	long	enc_outcount;		/* encoded (output) bytes */
-	hash_t*	enc_hashtab;		/* kept separate for small machines */
-} LZWCodecState;
+static cairo_status_t
+_lzw_buf_store_bits (lzw_buf_t *buf, uint16_t value, int num_bits)
+{
+    cairo_status_t status;
 
-static  void cl_hash(LZWCodecState*);
+    assert (value <= (1 << num_bits) - 1);
 
-/*
- * LZW Encoding.
+    if (getenv ("CAIRO_DEBUG_LZW"))
+	printf ("%d(%d) ", value, num_bits);
+
+    buf->pending = (buf->pending << num_bits) | value;
+    buf->pending_bits += num_bits;
+
+    while (buf->pending_bits >= 8) {
+	if (buf->num_data >= buf->data_size) {
+	    status = _lzw_buf_grow (buf);
+	    if (status)
+		return status;
+	}
+	buf->data[buf->num_data++] = buf->pending >> (buf->pending_bits - 8);
+	buf->pending_bits -= 8;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/* Store the last remaining pending bits into the buffer.
+ *
+ * NOTE: This function must be called after the last call to
+ * _lzw_buf_store_bits.
+ *
+ * Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY.
  */
+static cairo_status_t
+_lzw_buf_store_pending  (lzw_buf_t *buf)
+{
+    cairo_status_t status;
+
+    if (buf->pending_bits == 0)
+	return CAIRO_STATUS_SUCCESS;
+
+    assert (buf->pending_bits < 8);
+
+    if (buf->num_data >= buf->data_size) {
+	status = _lzw_buf_grow (buf);
+	if (status)
+	    return status;
+    }
+
+    buf->data[buf->num_data++] = buf->pending << (8 - buf->pending_bits);
+    buf->pending_bits = 0;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+typedef struct _lzw_symbol {
+    cairo_hash_entry_t hash_entry;
+
+    /* "key" is the symbol */
+    unsigned char *data;
+    int size;
+    /* "value" is the code */
+    int value;
+} lzw_symbol_t;
+
+#define LZW_BITS_MIN		9
+#define LZW_BITS_MAX		12
+#define LZW_BITS_BOUNDARY(bits)	((1<<(bits))-1)
+#define LZW_MAX_SYMBOLS		(1<<LZW_BITS_MAX)
+
+typedef struct _lzw_symbols {
+    lzw_symbol_t symbols[LZW_MAX_SYMBOLS];
+    int num_symbols;
+
+    cairo_hash_table_t *table;
+} lzw_symbols_t;
 
-static unsigned char *
-grow_out_buffer (LZWCodecState *sp, unsigned char *op)
+static cairo_bool_t
+_lzw_symbols_equal (const void *key_a, const void *key_b)
 {
-    size_t cc;
-    
-    cc = (size_t)(op - sp->out_buffer);
-    
-    sp->out_buffer_size = sp->out_buffer_size * 2;
-    sp->out_buffer = realloc (sp->out_buffer, sp->out_buffer_size);
-    /*
-     * The 4 here insures there is space for 2 max-sized
-     * codes in LZWEncode and LZWPostDecode.
-     */
-    sp->out_buffer_end = sp->out_buffer + sp->out_buffer_size-1 - 4;
-    
-    return sp->out_buffer + cc;
+    const lzw_symbol_t *symbol_a = key_a;
+    const lzw_symbol_t *symbol_b = key_b;
+
+    if (symbol_a->size != symbol_b->size)
+	return FALSE;
+
+    return ! memcmp (symbol_a->data, symbol_b->data, symbol_a->size);
 }
 
-static int
-LZWSetupEncode (LZWCodecState* sp)
+static cairo_status_t
+_lzw_symbols_init (lzw_symbols_t *symbols)
 {
-    memset (sp, 0, sizeof (LZWCodecState));
-    sp->enc_hashtab = (hash_t*) malloc (HSIZE * sizeof (hash_t));
-    if (sp->enc_hashtab == NULL)
-	return 0;
-    return 1;
+    symbols->num_symbols = 0;
+
+    symbols->table = _cairo_hash_table_create (_lzw_symbols_equal);
+    if (symbols->table == NULL)
+	return CAIRO_STATUS_NO_MEMORY;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void
-LZWFreeEncode (LZWCodecState* sp)
+_lzw_symbols_fini (lzw_symbols_t *symbols)
 {
-    if (sp->enc_hashtab)
-	free (sp->enc_hashtab);
+    int i;
+
+    for (i=0; i < symbols->num_symbols; i++)
+	_cairo_hash_table_remove (symbols->table, &symbols->symbols[i].hash_entry);
+
+    symbols->num_symbols = 0;
+
+    _cairo_hash_table_destroy (symbols->table);
 }
 
+static cairo_bool_t
+_lzw_symbols_has (lzw_symbols_t *symbols,
+		  lzw_symbol_t  *symbol,
+		  lzw_symbol_t **code)
+{
+    symbol->hash_entry.hash = _cairo_hash_bytes (symbol->data, symbol->size);
 
-/*
- * Reset encoding state at the start of a strip.
- */
-static void
-LZWPreEncode (LZWCodecState *sp)
+    return _cairo_hash_table_lookup (symbols->table,
+				     &symbol->hash_entry,
+				     (cairo_hash_entry_t **) code);
+}
+
+static cairo_status_t
+_lzw_symbols_store (lzw_symbols_t *symbols,
+		    lzw_symbol_t  *symbol)
 {
-    sp->nbits = BITS_MIN;
-    sp->maxcode = MAXCODE(BITS_MIN);
-    sp->free_ent = CODE_FIRST;
-    sp->nextbits = 0;
-    sp->nextdata = 0;
-    sp->enc_checkpoint = CHECK_GAP;
-    sp->enc_ratio = 0;
-    sp->enc_incount = 0;
-    sp->enc_outcount = 0;
-    /*
-     * The 4 here insures there is space for 2 max-sized
-     * codes in LZWEncode and LZWPostDecode.
-     */
-    sp->out_buffer_end = sp->out_buffer + sp->out_buffer_size-1 - 4;
-    cl_hash(sp); 			/* clear hash table */
-    sp->enc_oldcode = (hcode_t) -1;	/* generates CODE_CLEAR in LZWEncode */
-}
-
-#define	CALCRATIO(sp, rat) {					\
-    if (incount > 0x007fffff) { /* NB: shift will overflow */	\
-	rat = outcount >> 8;					\
-	rat = (rat == 0 ? 0x7fffffff : incount/rat);		\
-    } else							\
-	rat = (incount << 8) / outcount;			\
-}
-#define	PutNextCode(op, c) {					\
-    nextdata = (nextdata << nbits) | c;				\
-    nextbits += nbits;						\
-    *op++ = (unsigned char)(nextdata >> (nextbits-8));		\
-    nextbits -= 8;						\
-    if (nextbits >= 8) {					\
-	*op++ = (unsigned char)(nextdata >> (nextbits-8));	\
-	nextbits -= 8;						\
-    }								\
-    outcount += nbits;						\
-}
-
-/*
- * Encode a chunk of pixels.
- *
- * Uses an open addressing double hashing (no chaining) on the 
- * prefix code/next character combination.  We do a variant of
- * Knuth's algorithm D (vol. 3, sec. 6.4) along with G. Knott's
- * relatively-prime secondary probe.  Here, the modular division
- * first probe is gives way to a faster exclusive-or manipulation. 
- * Also do block compression with an adaptive reset, whereby the
- * code table is cleared when the compression ratio decreases,
- * but after the table fills.  The variable-length output codes
- * are re-sized at this point, and a CODE_CLEAR is generated
- * for the decoder. 
- */
-static int
-LZWEncode (LZWCodecState *sp,
-	   unsigned char *bp,
-	   size_t cc)
-{
-    register long fcode;
-    register hash_t *hp;
-    register int h, c;
-    hcode_t ent;
-    long disp;
-    long incount, outcount, checkpoint;
-    long nextdata, nextbits;
-    int free_ent, maxcode, nbits;
-    unsigned char *op;
-    
-    /*
-     * Load local state.
-     */
-    incount = sp->enc_incount;
-    outcount = sp->enc_outcount;
-    checkpoint = sp->enc_checkpoint;
-    nextdata = sp->nextdata;
-    nextbits = sp->nextbits;
-    free_ent = sp->free_ent;
-    maxcode = sp->maxcode;
-    nbits = sp->nbits;
-    op = sp->out_buffer_pos;
-    ent = sp->enc_oldcode;
-    
-    if (ent == (hcode_t) -1 && cc > 0) {
-	/*
-	 * NB: This is safe because it can only happen
-	 *     at the start of a strip where we know there
-	 *     is space in the data buffer.
-	 */
-	PutNextCode(op, CODE_CLEAR);
-	ent = *bp++; cc--; incount++;
+    cairo_status_t status;
+
+    symbol->hash_entry.hash = _cairo_hash_bytes (symbol->data, symbol->size);
+
+    symbols->symbols[symbols->num_symbols] = *symbol;
+
+    status = _cairo_hash_table_insert (symbols->table, &symbols->symbols[symbols->num_symbols].hash_entry);
+    if (status)
+	return status;
+
+    symbols->num_symbols++;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+#define LZW_CODE_CLEAR_TABLE	256
+#define LZW_CODE_EOD		257
+#define LZW_CODE_FIRST		258
+
+unsigned char *
+_cairo_lzw_compress (unsigned char *data, unsigned long *size_in_out)
+{
+    cairo_status_t status;
+    int bytes_remaining = *size_in_out;
+    lzw_symbols_t symbols;
+    lzw_symbol_t symbol, *tmp, *code;
+    lzw_buf_t buf;
+    int code_next = LZW_CODE_FIRST;
+    int code_bits = LZW_BITS_MIN;
+
+    status = _lzw_buf_init (&buf, *size_in_out / 4);
+    if (status)
+	return NULL;
+
+    status = _lzw_symbols_init (&symbols);
+    if (status) {
+	_lzw_buf_fini (&buf);
+	return NULL;
     }
-    while (cc > 0) {
-	c = *bp++; cc--; incount++;
-	fcode = ((long)c << BITS_MAX) + ent;
-	h = (c << HSHIFT) ^ ent;	/* xor hashing */
-#ifdef _WINDOWS
-	/*
-	 * Check hash index for an overflow.
-	 */
-	if (h >= HSIZE)
-	    h -= HSIZE;
-#endif
-	hp = &sp->enc_hashtab[h];
-	if (hp->hash == fcode) {
-	    ent = hp->code;
-	    continue;
+
+    _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits);
+    
+    symbol.data = data;
+    symbol.size = 2;
+
+    while (bytes_remaining) {
+	code = NULL;
+	while (symbol.size <= bytes_remaining &&
+	       _lzw_symbols_has (&symbols, &symbol, &tmp))
+	{
+	    code = tmp;
+	    symbol.size++;
 	}
-	if (hp->hash >= 0) {
-	    /*
-	     * Primary hash failed, check secondary hash.
-	     */
-	    disp = HSIZE - h;
-	    if (h == 0)
-		disp = 1;
-	    do {
-		/*
-		 * Avoid pointer arithmetic 'cuz of
-		 * wraparound problems with segments.
-		 */
-		if ((h -= disp) < 0)
-		    h += HSIZE;
-		hp = &sp->enc_hashtab[h];
-		if (hp->hash == fcode) {
-		    ent = hp->code;
-		    goto hit;
-		}
-	    } while (hp->hash >= 0);
+
+	if (code)
+	    _lzw_buf_store_bits (&buf, code->value, code_bits);
+	else
+	    _lzw_buf_store_bits (&buf, symbol.data[0], code_bits);
+
+	if (symbol.size == bytes_remaining + 1)
+	    break;
+
+	symbol.value = code_next++;
+	_lzw_symbols_store (&symbols, &symbol);
+
+	/* XXX: This is just for compatibility testing against libtiff. */
+	if (code_next == LZW_BITS_BOUNDARY(LZW_BITS_MAX) - 1) {
+	    _lzw_symbols_fini (&symbols);
+	    _lzw_symbols_init (&symbols);
+	    _lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits);
+	    code_bits = LZW_BITS_MIN;
+	    code_next = LZW_CODE_FIRST;
 	}
-	/*
-	 * New entry, emit code and add to table.
-	 */
-	/*
-	 * Verify there is space in the buffer for the code
-	 * and any potential Clear code that might be emitted
-	 * below.  The value of limit is setup so that there
-	 * are at least 4 bytes free--room for 2 codes.
-	 */
-	if (op > sp->out_buffer_end) {
-	    op = grow_out_buffer (sp, op);
-	    if (sp->out_buffer == NULL) {
-		return 0;
+
+	if (code_next > LZW_BITS_BOUNDARY(code_bits))
+	{
+	    code_bits++;
+	    if (code_bits > LZW_BITS_MAX) {
+		_lzw_symbols_fini (&symbols);
+		_lzw_symbols_init (&symbols);
+		_lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits);
+		code_bits = LZW_BITS_MIN;
+		code_next = LZW_CODE_FIRST;
 	    }
 	}
-	PutNextCode(op, ent);
-	ent = c;
-	hp->code = free_ent++;
-	hp->hash = fcode;
-	if (free_ent == CODE_MAX-1) {
-	    /* table is full, emit clear code and reset */
-	    cl_hash(sp);
-	    sp->enc_ratio = 0;
-	    incount = 0;
-	    outcount = 0;
-	    free_ent = CODE_FIRST;
-	    PutNextCode(op, CODE_CLEAR);
-	    nbits = BITS_MIN;
-	    maxcode = MAXCODE(BITS_MIN);
+
+	if (code) {
+	    symbol.data += (symbol.size - 1);
+	    bytes_remaining -= (symbol.size - 1);
 	} else {
-	    /*
-	     * If the next entry is going to be too big for
-	     * the code size, then increase it, if possible.
-	     */
-	    if (free_ent > maxcode) {
-		nbits++;
-		assert(nbits <= BITS_MAX);
-		maxcode = (int) MAXCODE(nbits);
-	    } else if (incount >= checkpoint) {
-		long rat;
-		/*
-		 * Check compression ratio and, if things seem
-		 * to be slipping, clear the hash table and
-		 * reset state.  The compression ratio is a
-		 * 24+8-bit fractional number.
-		 */
-		checkpoint = incount+CHECK_GAP;
-		CALCRATIO(sp, rat);
-		if (rat <= sp->enc_ratio) {
-		    cl_hash(sp);
-		    sp->enc_ratio = 0;
-		    incount = 0;
-		    outcount = 0;
-		    free_ent = CODE_FIRST;
-		    PutNextCode(op, CODE_CLEAR);
-		    nbits = BITS_MIN;
-		    maxcode = MAXCODE(BITS_MIN);
-		} else
-		    sp->enc_ratio = rat;
-	    }
+	    symbol.data += 1;
+	    bytes_remaining -= 1;
 	}
-    hit:
-	;
+	symbol.size = 2;
     }
-    
-    /*
-     * Restore global state.
-     */
-    sp->enc_incount = incount;
-    sp->enc_outcount = outcount;
-    sp->enc_checkpoint = checkpoint;
-    sp->enc_oldcode = ent;
-    sp->nextdata = nextdata;
-    sp->nextbits = nextbits;
-    sp->free_ent = free_ent;
-    sp->maxcode = maxcode;
-    sp->nbits = nbits;
-    sp->out_buffer_pos = op;
-    return 1;
-}
-
-/*
- * Finish off an encoded strip by flushing the last
- * string and tacking on an End Of Information code.
- */
-static int
-LZWPostEncode (LZWCodecState *sp)
-{
-    unsigned char *op = sp->out_buffer_pos;
-    long nextbits = sp->nextbits;
-    long nextdata = sp->nextdata;
-    long outcount = sp->enc_outcount;
-    int nbits = sp->nbits;
-    
-    if (op > sp->out_buffer_end) {
-	op = grow_out_buffer (sp, op);
-	if (sp->out_buffer == NULL) {
-	    return 0;
-	}
-    }
-    if (sp->enc_oldcode != (hcode_t) -1) {
-	PutNextCode(op, sp->enc_oldcode);
-	sp->enc_oldcode = (hcode_t) -1;
-    }
-    PutNextCode(op, CODE_EOI);
-    if (nextbits > 0) 
-	*op++ = (unsigned char)(nextdata << (8-nextbits));
-    sp->out_buffer_bytes = (size_t)(op - sp->out_buffer);
-    return 1;
-}
 
-/*
- * Reset encoding hash table.
- */
-static void
-cl_hash (LZWCodecState* sp)
-{
-    register hash_t *hp = &sp->enc_hashtab[HSIZE-1];
-    register long i = HSIZE-8;
-    
-    do {
-	i -= 8;
-	hp[-7].hash = -1;
-	hp[-6].hash = -1;
-	hp[-5].hash = -1;
-	hp[-4].hash = -1;
-	hp[-3].hash = -1;
-	hp[-2].hash = -1;
-	hp[-1].hash = -1;
-	hp[ 0].hash = -1;
-	hp -= 8;
-    } while (i >= 0);
-    for (i += 8; i > 0; i--, hp--)
-	hp->hash = -1;
-}
-
-/*
- * Copyright (c) 1985, 1986 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * James A. Woods, derived from original work by Spencer Thomas
- * and Joseph Orost.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
+    _lzw_buf_store_bits (&buf, LZW_CODE_EOD, code_bits);
 
-void *
-_cairo_lzw_compress (void *data, unsigned long *data_size_in_out)
-{
-    LZWCodecState state;
-    
-    if (!LZWSetupEncode (&state))
-	goto bail0;
-    
-    state.out_buffer_size = *data_size_in_out/4;
-    /* We need *some* space at least */
-    if (state.out_buffer_size < 256)
-	state.out_buffer_size = 256;
-    state.out_buffer = malloc (state.out_buffer_size);
-    if (state.out_buffer == NULL)
-	goto bail1;
-    
-    state.out_buffer_pos = state.out_buffer;
-    state.out_buffer_bytes = 0;
-    
-    LZWPreEncode (&state);
-    if (!LZWEncode (&state, data, *data_size_in_out))
-	goto bail2;
-    if (!LZWPostEncode(&state))
-	goto bail2;
-    
-    LZWFreeEncode(&state);
+    _lzw_buf_store_pending (&buf);
 
-    *data_size_in_out = state.out_buffer_bytes;
-    return state.out_buffer;
-    
- bail2:
-    if (state.out_buffer)
-	free (state.out_buffer);
- bail1:
-    LZWFreeEncode(&state);
- bail0:    
-    return NULL;
+    _lzw_symbols_fini (&symbols);
+
+    *size_in_out = buf.num_data;
+    return buf.data;
+}
+
+static unsigned long
+_cairo_hash_bytes (const unsigned char *c, int size)
+{
+    /* This is the djb2 hash. */
+    unsigned long hash = 5381;
+    while (size--)
+	hash = ((hash << 5) + hash) + *c++;
+    return hash;
 }
diff --git a/src/cairoint.h b/src/cairoint.h
index fdb8fc5..3dc0f7e 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2145,8 +2145,8 @@ _cairo_output_stream_write_base85_string
 					  const char *data,
 					  size_t length);
 
-cairo_private void *
-_cairo_lzw_compress (void *data, unsigned long *data_size_in_out);
+unsigned char *
+_cairo_lzw_compress (unsigned char *data, unsigned long *data_size_in_out);
 
 cairo_private cairo_status_t
 _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
diff-tree ec60bb0a606cadf3120d1cebc88e248a3e056c19 (from cabe94a15c277bb8a5f0c71f25cc8bc9e22ecb41)
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Mar 23 15:00:40 2006 -0800

    Rename _cairo_compress_lzw to _cairo_lzw_compress and tighten the parameter list.

diff --git a/src/cairo-lzw.c b/src/cairo-lzw.c
index bb764f3..a0d737e 100644
--- a/src/cairo-lzw.c
+++ b/src/cairo-lzw.c
@@ -460,14 +460,14 @@ cl_hash (LZWCodecState* sp)
  */
 
 void *
-_cairo_compress_lzw (void *data, unsigned long data_size, unsigned long *compressed_size)
+_cairo_lzw_compress (void *data, unsigned long *data_size_in_out)
 {
     LZWCodecState state;
     
     if (!LZWSetupEncode (&state))
 	goto bail0;
     
-    state.out_buffer_size = data_size/4;
+    state.out_buffer_size = *data_size_in_out/4;
     /* We need *some* space at least */
     if (state.out_buffer_size < 256)
 	state.out_buffer_size = 256;
@@ -479,14 +479,14 @@ _cairo_compress_lzw (void *data, unsigne
     state.out_buffer_bytes = 0;
     
     LZWPreEncode (&state);
-    if (!LZWEncode (&state, data, data_size))
+    if (!LZWEncode (&state, data, *data_size_in_out))
 	goto bail2;
     if (!LZWPostEncode(&state))
 	goto bail2;
     
     LZWFreeEncode(&state);
 
-    *compressed_size = state.out_buffer_bytes;
+    *data_size_in_out = state.out_buffer_bytes;
     return state.out_buffer;
     
  bail2:
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index ff4f0e8..a646d45 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -724,7 +724,8 @@ emit_image (cairo_ps_surface_t    *surfa
 	}
     }
 
-    compressed = _cairo_compress_lzw (rgb, rgb_size, &compressed_size);
+    compressed_size = rgb_size;
+    compressed = _cairo_lzw_compress (rgb, &compressed_size);
     if (compressed == NULL) {
 	status = CAIRO_STATUS_NO_MEMORY;
 	goto bail2;
diff --git a/src/cairoint.h b/src/cairoint.h
index d5abfc7..fdb8fc5 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2146,9 +2146,7 @@ _cairo_output_stream_write_base85_string
 					  size_t length);
 
 cairo_private void *
-_cairo_compress_lzw (void *data,
-		     unsigned long data_size,
-		     unsigned long *compressed_size);
+_cairo_lzw_compress (void *data, unsigned long *data_size_in_out);
 
 cairo_private cairo_status_t
 _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
diff-tree cabe94a15c277bb8a5f0c71f25cc8bc9e22ecb41 (from a193f70b94667808f573caa5b82a1bf50281555e)
Author: Carl Worth <cworth at raht.cworth.org>
Date:   Wed Mar 22 23:12:23 2006 -0800

    Make all hash/cache keys_equal function accept const pointers.

diff --git a/src/cairo-cache-private.h b/src/cairo-cache-private.h
index a75e8c0..566dbe2 100644
--- a/src/cairo-cache-private.h
+++ b/src/cairo-cache-private.h
@@ -88,7 +88,7 @@ typedef struct _cairo_cache_entry {
 } cairo_cache_entry_t;
 
 typedef cairo_bool_t
-(*cairo_cache_keys_equal_func_t) (void *key_a, void *key_b);
+(*cairo_cache_keys_equal_func_t) (const void *key_a, const void *key_b);
 
 typedef void
 (*cairo_cache_callback_func_t) (void *entry,
diff --git a/src/cairo-font.c b/src/cairo-font.c
index 6512480..425021a 100644
--- a/src/cairo-font.c
+++ b/src/cairo-font.c
@@ -210,8 +210,8 @@ cairo_font_face_set_user_data (cairo_fon
 static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
 
 static int
-_cairo_toy_font_face_keys_equal (void *key_a,
-				 void *key_b);
+_cairo_toy_font_face_keys_equal (const void *key_a,
+				 const void *key_b);
 
 /* We maintain a hash table from family/weight/slant =>
  * cairo_font_face_t for cairo_toy_font_t. The primary purpose of
@@ -312,11 +312,11 @@ _cairo_toy_font_face_fini (cairo_toy_fon
 }
 
 static int
-_cairo_toy_font_face_keys_equal (void *key_a,
-				 void *key_b)
+_cairo_toy_font_face_keys_equal (const void *key_a,
+				 const void *key_b)
 {
-    cairo_toy_font_face_t *face_a = key_a;
-    cairo_toy_font_face_t *face_b = key_b;
+    const cairo_toy_font_face_t *face_a = key_a;
+    const cairo_toy_font_face_t *face_b = key_b;
 
     return (strcmp (face_a->family, face_b->family) == 0 &&
 	    face_a->slant == face_b->slant &&
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 092838a..a23388a 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -103,8 +103,8 @@ struct _cairo_ft_unscaled_font {
 };
 
 static int
-_cairo_ft_unscaled_font_keys_equal (void *key_a,
-				    void *key_b);
+_cairo_ft_unscaled_font_keys_equal (const void *key_a,
+				    const void *key_b);
 
 static void
 _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled);
@@ -365,11 +365,11 @@ _cairo_ft_unscaled_font_fini (cairo_ft_u
 }
 
 static int
-_cairo_ft_unscaled_font_keys_equal (void *key_a,
-				    void *key_b)
+_cairo_ft_unscaled_font_keys_equal (const void *key_a,
+				    const void *key_b)
 {
-    cairo_ft_unscaled_font_t *unscaled_a = key_a;
-    cairo_ft_unscaled_font_t *unscaled_b = key_b;
+    const cairo_ft_unscaled_font_t *unscaled_a = key_a;
+    const cairo_ft_unscaled_font_t *unscaled_b = key_b;
 
     return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0 &&
 	    unscaled_a->id == unscaled_b->id);
diff --git a/src/cairo-hash-private.h b/src/cairo-hash-private.h
index 6dc9c90..617b841 100644
--- a/src/cairo-hash-private.h
+++ b/src/cairo-hash-private.h
@@ -85,7 +85,7 @@ typedef struct _cairo_hash_entry {
 } cairo_hash_entry_t;
 
 typedef cairo_bool_t
-(*cairo_hash_keys_equal_func_t) (void *key_a, void *key_b);
+(*cairo_hash_keys_equal_func_t) (const void *key_a, const void *key_b);
 
 typedef cairo_bool_t
 (*cairo_hash_predicate_func_t) (void *entry);
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index a046904..afefac4 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -39,10 +39,10 @@
 #include "cairoint.h"
 
 static cairo_bool_t
-_cairo_scaled_glyph_keys_equal (void *abstract_key_a, void *abstract_key_b)
+_cairo_scaled_glyph_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
 {
-    cairo_scaled_glyph_t *key_a = abstract_key_a;
-    cairo_scaled_glyph_t *key_b = abstract_key_b;
+    const cairo_scaled_glyph_t *key_a = abstract_key_a;
+    const cairo_scaled_glyph_t *key_b = abstract_key_b;
 
     return (_cairo_scaled_glyph_index (key_a) ==
 	    _cairo_scaled_glyph_index (key_b));
@@ -180,7 +180,7 @@ static cairo_scaled_font_map_t *cairo_sc
 CAIRO_MUTEX_DECLARE (cairo_scaled_font_map_mutex);
 
 static int
-_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b);
+_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b);
 
 static cairo_scaled_font_map_t *
 _cairo_scaled_font_map_lock (void)
@@ -298,10 +298,10 @@ _cairo_scaled_font_init_key (cairo_scale
 }
 
 static cairo_bool_t
-_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b)
+_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
 {
-    cairo_scaled_font_t *key_a = abstract_key_a;
-    cairo_scaled_font_t *key_b = abstract_key_b;
+    const cairo_scaled_font_t *key_a = abstract_key_a;
+    const cairo_scaled_font_t *key_b = abstract_key_b;
 
     return (key_a->font_face == key_b->font_face &&
 	    memcmp ((unsigned char *)(&key_a->font_matrix.xx),
diff-tree a193f70b94667808f573caa5b82a1bf50281555e (from ef04471b1b90057c00ec51e1f3d7c7ed4ab1e34c)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date:   Wed Mar 22 11:48:44 2006 +0100

    SVG: return len in _cairo_svg_document_write when operation succeed.

diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 5d569bd..d413408 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -1349,6 +1349,8 @@ _cairo_svg_document_write (cairo_output_
 {
     if (_cairo_output_stream_write (output_stream, buffer, len) != CAIRO_STATUS_SUCCESS)
 	return -1;
+
+    return len;
 }
 
 
diff-tree ef04471b1b90057c00ec51e1f3d7c7ed4ab1e34c (from 69acfa6576e8d2b97e3e3b8c06badf5486ae0315)
Author: Christian Biesinger <cbiesinger at web.de>
Date:   Sat Mar 18 18:08:20 2006 +0100

    More consistent naming for the BeOS surface functions

diff --git a/src/cairo-beos-surface.cpp b/src/cairo-beos-surface.cpp
index 5cd4277..6347ba7 100644
--- a/src/cairo-beos-surface.cpp
+++ b/src/cairo-beos-surface.cpp
@@ -570,18 +570,18 @@ _cairo_beos_surface_release_dest_image (
 }
 
 static cairo_int_status_t
-_cairo_beos_composite (cairo_operator_t		op,
-		       cairo_pattern_t	       *src,
-		       cairo_pattern_t	       *mask,
-		       void		       *dst,
-		       int		 	src_x,
-		       int			src_y,
-		       int			mask_x,
-		       int			mask_y,
-		       int			dst_x,
-		       int			dst_y,
-		       unsigned int		width,
-		       unsigned int		height)
+_cairo_beos_surface_composite (cairo_operator_t		op,
+			       cairo_pattern_t	       *src,
+			       cairo_pattern_t	       *mask,
+			       void		       *dst,
+			       int		 	src_x,
+			       int			src_y,
+			       int			mask_x,
+			       int			mask_y,
+			       int			dst_x,
+			       int			dst_y,
+			       unsigned int		width,
+			       unsigned int		height)
 {
     cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
 							dst);
@@ -661,19 +661,19 @@ _cairo_beos_composite (cairo_operator_t	
 
 
 static void
-_cairo_beos_fill_rectangle (cairo_beos_surface_t *surface,
-			    cairo_rectangle_t    *rect)
+_cairo_beos_surface_fill_rectangle (cairo_beos_surface_t *surface,
+				    cairo_rectangle_t    *rect)
 {
     BRect brect(_cairo_rect_to_brect(rect));
     surface->view->FillRect(brect);
 }
 
 static cairo_int_status_t
-_cairo_beos_fill_rectangles (void                *abstract_surface,
-			     cairo_operator_t     op,
-			     const cairo_color_t *color,
-			     cairo_rectangle_t   *rects,
-			     int                  num_rects)
+_cairo_beos_surface_fill_rectangles (void                *abstract_surface,
+				     cairo_operator_t     op,
+				     const cairo_color_t *color,
+				     cairo_rectangle_t   *rects,
+				     int                  num_rects)
 {
     fprintf(stderr, "Drawing %i rectangles\n", num_rects);
     cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
@@ -716,7 +716,7 @@ _cairo_beos_fill_rectangles (void       
 	    surface->view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
 
 	for (int i = 0; i < num_rects; ++i) {
-	    _cairo_beos_fill_rectangle(surface, &rects[i]);
+	    _cairo_beos_surface_fill_rectangle(surface, &rects[i]);
 	}
 
     surface->view->PopState();
@@ -785,8 +785,8 @@ static const struct _cairo_surface_backe
     _cairo_beos_surface_acquire_dest_image,
     _cairo_beos_surface_release_dest_image,
     NULL, /* clone_similar */
-    _cairo_beos_composite, /* composite */
-    _cairo_beos_fill_rectangles,
+    _cairo_beos_surface_composite, /* composite */
+    _cairo_beos_surface_fill_rectangles,
     NULL, /* composite_trapezoids */
     NULL, /* copy_page */
     NULL, /* show_page */
diff-tree 69acfa6576e8d2b97e3e3b8c06badf5486ae0315 (from 0623f8a7d1452c27892f938fe28e6e173e67e136)
Author: Christian Biesinger <cbiesinger at web.de>
Date:   Fri Mar 17 21:26:27 2006 +0100

    Don't link to C++ libraries on non-BeOS systems

diff --git a/src/Makefile.am b/src/Makefile.am
index a7efc1e..ad18568 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -56,6 +56,11 @@ libcairo_beos_sources =
 if CAIRO_HAS_BEOS_SURFACE
 libcairo_beos_headers = cairo-beos.h
 libcairo_beos_sources += cairo-beos-surface.cpp
+
+noinst_LTLIBRARIES = libcairo_beos.la
+libcairo_beos_la_SOURCES = $(libcairo_beos_sources)
+# BeOS system headers trigger this warning
+libcairo_beos_la_CXXFLAGS = -Wno-multichar
 endif
 
 if CAIRO_HAS_GLITZ_SURFACE
@@ -187,20 +192,16 @@ libcairo_la_SOURCES =				\
 	$(libcairo_xcb_sources)			\
 	$(libcairo_glitz_sources)		\
 	$(libcairo_win32_sources)		\
-	$(libcairo_beos_sources)		\
 	$(libcairo_directfb_sources)	\
 	cairoint.h
 
 libcairo_la_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined $(export_symbols)
-# this -Wno-multichar line is really just for the beos surface, because the
-# system headers trigger this warning.
-libcairo_la_CXXFLAGS = -Wno-multichar
 
 INCLUDES = -I$(srcdir) -I$(top_srcdir)/pixman/src $(CAIRO_CFLAGS)
 
-libcairo_la_LIBADD = $(top_builddir)/pixman/src/libpixman.la $(CAIRO_LIBS)
+libcairo_la_LIBADD = $(top_builddir)/pixman/src/libpixman.la $(CAIRO_LIBS) $(noinst_LTLIBRARIES)
 
-libcairo_la_DEPENDENCIES = $(cairo_def_dependency) $(top_builddir)/pixman/src/libpixman.la
+libcairo_la_DEPENDENCIES = $(cairo_def_dependency) $(top_builddir)/pixman/src/libpixman.la $(noinst_LTLIBRARIES)
 
 EXTRA_DIST = \
 	cairo.def
diff-tree 0623f8a7d1452c27892f938fe28e6e173e67e136 (from parents)
Merge: 26b06b3638ec768da01839cfa3c75e9807b14ee8 a7f58f886253f4ae66c9b0ed4472f575eaf2ec1d
Author: Behdad Esfahbod <behdad at home.(none)>
Date:   Wed Mar 15 15:25:59 2006 -0500

    Merge branch 'master' of git+ssh://git.cairographics.org/git/cairo

diff-tree 26b06b3638ec768da01839cfa3c75e9807b14ee8 (from f5013b6dc6442493ea38949fdcc137e5c44b6872)
Author: Behdad Esfahbod <behdad at home.(none)>
Date:   Wed Mar 15 15:17:26 2006 -0500

    Clarify that git tag -s does GPG signing.
    (cherry picked from e94251861565ed154e15ca3a7198ffe3828536fe commit)

diff --git a/RELEASING b/RELEASING
index 8020404..49dd82c 100644
--- a/RELEASING
+++ b/RELEASING
@@ -68,8 +68,13 @@ Here are the steps to follow to create a
 	* scp the three files to appear on http://cairographics.org/releases
 	* Place local copies of the three files in the releases directory
 	* Create a LATEST-package-version file (after deleting any old one)
-	* Tag the entire source tree with a tag of the form X.Y.Z
+	* Tag the entire source tree with a tag of the form X.Y.Z, and sign
+	  the tag with your GPG key (asks for your GPG password, and you
+	  may need to set GIT_COMMITTER_NAME and GIT_COMMITTER_EMAIL to match
+	  your public-key's setting or this fails.)
 	* Provide some text for the release announcement (see below).
+	  If for some reason you lost this message, "make release-publish-message"
+	  prints it for you.
 
 7) Increment cairo_version_micro to the next larger (odd) number in
    configure, and commit.
diff-tree f5013b6dc6442493ea38949fdcc137e5c44b6872 (from 46e5ed66d3329f1608950d817e7248c91087893a)
Author: Behdad Esfahbod <behdad at home.(none)>
Date:   Wed Mar 15 14:19:08 2006 -0500

    Add a release-publish-message target to only get the message.
    (cherry picked from 98facc6c2d0f57f05de7b98c2aaa592c895d1a09 commit)

diff --git a/Makefile.am b/Makefile.am
index 47bedef..165f9c3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -145,7 +145,7 @@ release-upload: release-check $(tar_file
 	ssh $(RELEASE_UPLOAD_HOST) "rm -f $(RELEASE_UPLOAD_DIR)/LATEST-$(PACKAGE)-[0-9]* && ln -s $(tar_file) $(RELEASE_UPLOAD_DIR)/LATEST-$(PACKAGE)-$(VERSION)"
 	git tag -s $(CAIRO_VERSION_MAJOR).$(CAIRO_VERSION_MINOR).$(CAIRO_VERSION_MICRO)
 
-release-publish: release-upload releases/$(sha1_file)
+release-publish-message: releases/$(sha1_file)
 	@echo ""
 	@echo "Please send an announcement to $(RELEASE_ANNOUNCE_LIST)"
 	@echo "including the following:"
@@ -172,6 +172,8 @@ release-publish: release-upload releases
 	@echo "Last but not least, do not forget to bump up the micro"
 	@echo "version component to the next (odd) number and commit."
 
+release-publish: release-upload release-publish-message
+
 # XXX: Depending on all here is rather overkill. We don't really need
 # the library built in order to create the documentation.
 docs-publish: all
diff-tree 46e5ed66d3329f1608950d817e7248c91087893a (from f00a1833341699135e792e3a77e19dca0d1dba86)
Author: Behdad Esfahbod <behdad at home.(none)>
Date:   Wed Mar 15 11:25:02 2006 -0500

    Note using "git diff" instead of "git status" as the latter is a bit tricky when it says nothing to commit...
    (cherry picked from a1621eadb655806de8bb47c2e701de6eaa9d2090 commit)

diff --git a/RELEASING b/RELEASING
index bf7317b..8020404 100644
--- a/RELEASING
+++ b/RELEASING
@@ -1,7 +1,7 @@
 Here are the steps to follow to create a new cairo release:
 
 1) Ensure that there are no local, uncommitted modifications.
-   It's probably good enough if "git status" says so.
+   It's probably good enough if "git diff" doesn't output anything.
 
 2) Verify that the code passes "make distcheck"
 
diff-tree f00a1833341699135e792e3a77e19dca0d1dba86 (from 037732cac9ff402e51d80d6ed54cc32d669aa0d9)
Author: Behdad Esfahbod <behdad at home.(none)>
Date:   Wed Mar 15 11:18:40 2006 -0500

    Update release infra to reflect git transition.
    (cherry picked from 508b0be5f2023dabe9561f4ca62481d6a4c8c5ae commit)

diff --git a/INSTALL b/INSTALL
index 4a49f00..ab82781 100644
--- a/INSTALL
+++ b/INSTALL
@@ -16,7 +16,7 @@ This final step may require temporary ro
 you don't have write permission to the directory in which cairo will
 be installed.
 
-NOTE: If you are working with source from CVS rather than from a tar
+NOTE: If you are working with source from git/cvs rather than from a tar
 file, then you should use ./autogen.sh in place of ./configure
 anywhere it is mentioned in these instructions.
 
diff --git a/Makefile.am b/Makefile.am
index 1b209da..47bedef 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -121,7 +121,7 @@ release-verify-newer:
 	@echo -n "Checking that no $(VERSION) release already exists..."
 	@ssh $(RELEASE_UPLOAD_HOST) test ! -e $(RELEASE_UPLOAD_DIR)/$(tar_file) \
 		|| (echo "Ouch." && echo "Found: $(RELEASE_UPLOAD_HOST):$(RELEASE_UPLOAD_DIR)/$(tar_file)" \
-		&& echo "Are you sure you have an updated CVS checkout?" \
+		&& echo "Are you sure you have an updated checkout?" \
 		&& echo "This should never happen." \
 		&& false)
 	@echo "Good."
@@ -143,7 +143,7 @@ release-upload: release-check $(tar_file
 	scp $(tar_file) $(sha1_file) $(gpg_file) $(RELEASE_UPLOAD_HOST):$(RELEASE_UPLOAD_DIR)
 	mv $(tar_file) $(sha1_file) $(gpg_file) releases
 	ssh $(RELEASE_UPLOAD_HOST) "rm -f $(RELEASE_UPLOAD_DIR)/LATEST-$(PACKAGE)-[0-9]* && ln -s $(tar_file) $(RELEASE_UPLOAD_DIR)/LATEST-$(PACKAGE)-$(VERSION)"
-	$(CVS) tag RELEASE_$(CAIRO_VERSION_MAJOR)_$(CAIRO_VERSION_MINOR)_$(CAIRO_VERSION_MICRO)
+	git tag -s $(CAIRO_VERSION_MAJOR).$(CAIRO_VERSION_MINOR).$(CAIRO_VERSION_MICRO)
 
 release-publish: release-upload releases/$(sha1_file)
 	@echo ""
diff --git a/RELEASING b/RELEASING
index df87e38..bf7317b 100644
--- a/RELEASING
+++ b/RELEASING
@@ -1,12 +1,7 @@
 Here are the steps to follow to create a new cairo release:
 
-1) Ensure that there are no local, uncommitted modifications. The best
-   thing to do here may be to begin with a fresh checkout from CVS:
-
-	cvs -d cairographics.org:/cvs/cairo co cairo
-
-   But it's probably good enough if "cvs -q update -Ad" generates no
-   output.
+1) Ensure that there are no local, uncommitted modifications.
+   It's probably good enough if "git status" says so.
 
 2) Verify that the code passes "make distcheck"
 
@@ -32,7 +27,10 @@ Here are the steps to follow to create a
 	previous release tag:
 
 		find src/ -name '*.h' -not -name '*-private.h' -not -name 'cairoint.h' | \
-		xargs cvs diff -r RELEASE_X_Y_Z
+		xargs git diff X.Y.Z --
+	
+	Note that for older releases made under CVS, the tag name is
+	RELEASE_X_Y_Z instead.
 
 4) Increment cairo_version_{minor|micro} and LT_{CURRENT|VERSION|AGE}
    in configure.in:
@@ -55,9 +53,8 @@ Here are the steps to follow to create a
 
 5) Commit the changes to NEWS and configure.in
 
-	Don't forget to fill out the ChangeLog just like with any
-	other commit. It's especially important to mention the new
-	version number in the ChangeLog.
+	It's especially important to mention the new version number in your
+	commit log.
 
 6) Run "make release-publish" which will perform the following steps
    for you:
@@ -71,7 +68,7 @@ Here are the steps to follow to create a
 	* scp the three files to appear on http://cairographics.org/releases
 	* Place local copies of the three files in the releases directory
 	* Create a LATEST-package-version file (after deleting any old one)
-	* Tag the entire source tree with a tag of the form RELEASE_X_Y_Z
+	* Tag the entire source tree with a tag of the form X.Y.Z
 	* Provide some text for the release announcement (see below).
 
 7) Increment cairo_version_micro to the next larger (odd) number in
diff --git a/configure.in b/configure.in
index b957ada..44783bd 100644
--- a/configure.in
+++ b/configure.in
@@ -1,7 +1,7 @@
 AC_PREREQ(2.54)
 
 # cairo package version number, (as distinct from shared library version)
-# An odd micro number indicates in-progress development, (eg. from CVS)
+# An odd micro number indicates in-progress development, (eg. from git/cvs)
 # An even micro number indicates a released version.
 m4_define(cairo_version_major, 1)
 m4_define(cairo_version_minor, 1)
diff-tree 037732cac9ff402e51d80d6ed54cc32d669aa0d9 (from 2af29f720faac0a9ee3961a81b81acae9a716220)
Author: Behdad Esfahbod <behdad at home.(none)>
Date:   Wed Mar 15 10:59:59 2006 -0500

    Add make bits to autogenerate ChangeLog
    (cherry picked from 393000021c2e082d4b3c235939009a90035b0daf commit)

diff --git a/.gitignore b/.gitignore
index aaa9f03..ebcd093 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+ChangeLog
 Makefile
 Makefile.in
 aclocal.m4
diff --git a/Makefile.am b/Makefile.am
index ab5ca24..1b209da 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,6 +11,21 @@ EXTRA_DIST = \
 	COPYING-LGPL-2.1 \
 	COPYING-MPL-1.1 \
 	cairo.pc.in
+MAINTAINERCLEANFILES = \
+	$(srcdir)/INSTALL \
+	$(srcdir)/aclocal.m4 \
+	$(srcdir)/autoscan.log \
+	$(srcdir)/compile \
+	$(srcdir)/config.guess \
+	$(srcdir)/config.h.in \
+	$(srcdir)/config.sub \
+	$(srcdir)/configure.scan \
+	$(srcdir)/depcomp \
+	$(srcdir)/install-sh \
+	$(srcdir)/ltmain.sh \
+	$(srcdir)/missing \
+	$(srcdir)/mkinstalldirs \
+	`find "$(srcdir)" -type f -name Makefile.in -print`
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = cairo.pc
@@ -20,6 +35,30 @@ check-valgrind: all
 
 DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc
 
+# Creating ChangeLog from git log:
+
+MAINTAINERCLEANFILES += ChangeLog
+
+EXTRA_DIST += ChangeLog
+
+ChangeLog: $(srcdir)/ChangeLog
+
+$(srcdir)/ChangeLog:
+	@if test -d "$(srcdir)/.git"; then \
+	  (cd "$(srcdir)" && \
+	  ./missing --run git-log) | fmt --split-only > $@.tmp \
+	  && mv -f $@.tmp $@ \
+	  || ($(RM) $@.tmp; \
+	      echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \
+	      (test -f $@ || echo git-log is required to generate this file >> $@)); \
+	else \
+	  test -f $@ || \
+	  (echo A git checkout and git-log is required to generate ChangeLog >&2 && \
+	  echo A git checkout and git-log is required to generate this file >> $@); \
+	fi
+
+.PHONY: ChangeLog $(srcdir)/ChangeLog
+
 # Some custom targets to make it easier to release things.
 # Use either:
 #		make release-check
diff-tree a7f58f886253f4ae66c9b0ed4472f575eaf2ec1d (from d6f8df7417bdab75dbcfe9658616dd3367276ed0)
Author: Alexander Larsson <alexl at redhat.com>
Date:   Wed Mar 15 10:44:09 2006 -0800

    Add LZW image compression and ASCII85 encoding for PostScript image output.
    
    * src/Makefile.am:
    Add cairo-lzw.c to sources
    Remove erronous space at start of line
    
    * src/cairo-lzw.c:
    New file implementing _cairo_compress_lzw which does Lempel-Ziv & Welch
    compression as used by postscript. Based on code from libtiff.
    
    * src/cairo-output-stream.c:
    Add _cairo_output_stream_write_base85_string which implements
    an encoder for the ASCII85Decode postscript filter.
    
    * src/cairoint.h:
    Add _cairo_compress_lzw and _cairo_output_stream_write_base85_string.
    
    * src/cairo-ps-surface.c:
    Write Images LZW + Base85 encoded.
    Change ps level to 2 (we only needed level 3 for FlateDecode).
    Change DocumentData to Clean7Bit as we don't include binary data
    anymore.

diff --git a/src/Makefile.am b/src/Makefile.am
index 908bcb2..a7efc1e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -145,6 +145,7 @@ libcairo_la_SOURCES =				\
 	cairo-hash-private.h			\
 	cairo-hull.c				\
 	cairo-image-surface.c			\
+	cairo-lzw.c				\
 	cairo-matrix.c				\
 	cairo-path.c				\
 	cairo-path-bounds.c			\
@@ -187,7 +188,7 @@ libcairo_la_SOURCES =				\
 	$(libcairo_glitz_sources)		\
 	$(libcairo_win32_sources)		\
 	$(libcairo_beos_sources)		\
- 	$(libcairo_directfb_sources)	\
+	$(libcairo_directfb_sources)	\
 	cairoint.h
 
 libcairo_la_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined $(export_symbols)
diff --git a/src/cairo-lzw.c b/src/cairo-lzw.c
new file mode 100644
index 0000000..bb764f3
--- /dev/null
+++ b/src/cairo-lzw.c
@@ -0,0 +1,499 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2006 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * Contributor(s):
+ *	Alexander Larsson <alexl at redhat.com>
+ *
+ * This code is derived from tif_lzw.c in libtiff 3.8.0.
+ * The original copyright notice appears below in its entirety.
+ */
+
+#include "cairoint.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and 
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ * 
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ * Rev 5.0 Lempel-Ziv & Welch Compression Support
+ *
+ * This code is derived from the compress program whose code is
+ * derived from software contributed to Berkeley by James A. Woods,
+ * derived from original work by Spencer Thomas and Joseph Orost.
+ *
+ * The original Berkeley copyright notice appears below in its entirety.
+ */
+
+#define MAXCODE(n)	((1L<<(n))-1)
+/*
+ * The TIFF spec specifies that encoded bit
+ * strings range from 9 to 12 bits.
+ */
+#define	BITS_MIN	9		/* start with 9 bits */
+#define	BITS_MAX	12		/* max of 12 bit strings */
+/* predefined codes */
+#define	CODE_CLEAR	256		/* code to clear string table */
+#define	CODE_EOI	257		/* end-of-information code */
+#define CODE_FIRST	258		/* first free code entry */
+#define	CODE_MAX	MAXCODE(BITS_MAX)
+#define	HSIZE		9001L		/* 91% occupancy */
+#define	HSHIFT		(13-8)
+#ifdef LZW_COMPAT
+/* NB: +1024 is for compatibility with old files */
+#define	CSIZE		(MAXCODE(BITS_MAX)+1024L)
+#else
+#define	CSIZE		(MAXCODE(BITS_MAX)+1L)
+#endif
+
+typedef uint16_t hcode_t;			/* codes fit in 16 bits */
+typedef struct {
+	long	hash;
+	hcode_t	code;
+} hash_t;
+
+typedef struct {
+	/* Out buffer */
+	unsigned char  *out_buffer;		/* compressed out buffer */
+	size_t		out_buffer_size;	/* # of allocated bytes in out buffer */
+	unsigned char  *out_buffer_pos;		/* current spot in out buffer */
+	size_t		out_buffer_bytes;	/* # of data bytes in out buffer */
+	unsigned char  *out_buffer_end;		/* bound on out_buffer */
+	
+	unsigned short	nbits;		/* # of bits/code */
+	unsigned short	maxcode;	/* maximum code for lzw_nbits */
+	unsigned short	free_ent;	/* next free entry in hash table */
+	long		nextdata;	/* next bits of i/o */
+	long		nextbits;	/* # of valid bits in lzw_nextdata */
+
+	int	enc_oldcode;		/* last code encountered */
+	long	enc_checkpoint;		/* point at which to clear table */
+#define CHECK_GAP	10000		/* enc_ratio check interval */
+	long	enc_ratio;		/* current compression ratio */
+	long	enc_incount;		/* (input) data bytes encoded */
+	long	enc_outcount;		/* encoded (output) bytes */
+	hash_t*	enc_hashtab;		/* kept separate for small machines */
+} LZWCodecState;
+
+static  void cl_hash(LZWCodecState*);
+
+/*
+ * LZW Encoding.
+ */
+
+static unsigned char *
+grow_out_buffer (LZWCodecState *sp, unsigned char *op)
+{
+    size_t cc;
+    
+    cc = (size_t)(op - sp->out_buffer);
+    
+    sp->out_buffer_size = sp->out_buffer_size * 2;
+    sp->out_buffer = realloc (sp->out_buffer, sp->out_buffer_size);
+    /*
+     * The 4 here insures there is space for 2 max-sized
+     * codes in LZWEncode and LZWPostDecode.
+     */
+    sp->out_buffer_end = sp->out_buffer + sp->out_buffer_size-1 - 4;
+    
+    return sp->out_buffer + cc;
+}
+
+static int
+LZWSetupEncode (LZWCodecState* sp)
+{
+    memset (sp, 0, sizeof (LZWCodecState));
+    sp->enc_hashtab = (hash_t*) malloc (HSIZE * sizeof (hash_t));
+    if (sp->enc_hashtab == NULL)
+	return 0;
+    return 1;
+}
+
+static void
+LZWFreeEncode (LZWCodecState* sp)
+{
+    if (sp->enc_hashtab)
+	free (sp->enc_hashtab);
+}
+
+
+/*
+ * Reset encoding state at the start of a strip.
+ */
+static void
+LZWPreEncode (LZWCodecState *sp)
+{
+    sp->nbits = BITS_MIN;
+    sp->maxcode = MAXCODE(BITS_MIN);
+    sp->free_ent = CODE_FIRST;
+    sp->nextbits = 0;
+    sp->nextdata = 0;
+    sp->enc_checkpoint = CHECK_GAP;
+    sp->enc_ratio = 0;
+    sp->enc_incount = 0;
+    sp->enc_outcount = 0;
+    /*
+     * The 4 here insures there is space for 2 max-sized
+     * codes in LZWEncode and LZWPostDecode.
+     */
+    sp->out_buffer_end = sp->out_buffer + sp->out_buffer_size-1 - 4;
+    cl_hash(sp); 			/* clear hash table */
+    sp->enc_oldcode = (hcode_t) -1;	/* generates CODE_CLEAR in LZWEncode */
+}
+
+#define	CALCRATIO(sp, rat) {					\
+    if (incount > 0x007fffff) { /* NB: shift will overflow */	\
+	rat = outcount >> 8;					\
+	rat = (rat == 0 ? 0x7fffffff : incount/rat);		\
+    } else							\
+	rat = (incount << 8) / outcount;			\
+}
+#define	PutNextCode(op, c) {					\
+    nextdata = (nextdata << nbits) | c;				\
+    nextbits += nbits;						\
+    *op++ = (unsigned char)(nextdata >> (nextbits-8));		\
+    nextbits -= 8;						\
+    if (nextbits >= 8) {					\
+	*op++ = (unsigned char)(nextdata >> (nextbits-8));	\
+	nextbits -= 8;						\
+    }								\
+    outcount += nbits;						\
+}
+
+/*
+ * Encode a chunk of pixels.
+ *
+ * Uses an open addressing double hashing (no chaining) on the 
+ * prefix code/next character combination.  We do a variant of
+ * Knuth's algorithm D (vol. 3, sec. 6.4) along with G. Knott's
+ * relatively-prime secondary probe.  Here, the modular division
+ * first probe is gives way to a faster exclusive-or manipulation. 
+ * Also do block compression with an adaptive reset, whereby the
+ * code table is cleared when the compression ratio decreases,
+ * but after the table fills.  The variable-length output codes
+ * are re-sized at this point, and a CODE_CLEAR is generated
+ * for the decoder. 
+ */
+static int
+LZWEncode (LZWCodecState *sp,
+	   unsigned char *bp,
+	   size_t cc)
+{
+    register long fcode;
+    register hash_t *hp;
+    register int h, c;
+    hcode_t ent;
+    long disp;
+    long incount, outcount, checkpoint;
+    long nextdata, nextbits;
+    int free_ent, maxcode, nbits;
+    unsigned char *op;
+    
+    /*
+     * Load local state.
+     */
+    incount = sp->enc_incount;
+    outcount = sp->enc_outcount;
+    checkpoint = sp->enc_checkpoint;
+    nextdata = sp->nextdata;
+    nextbits = sp->nextbits;
+    free_ent = sp->free_ent;
+    maxcode = sp->maxcode;
+    nbits = sp->nbits;
+    op = sp->out_buffer_pos;
+    ent = sp->enc_oldcode;
+    
+    if (ent == (hcode_t) -1 && cc > 0) {
+	/*
+	 * NB: This is safe because it can only happen
+	 *     at the start of a strip where we know there
+	 *     is space in the data buffer.
+	 */
+	PutNextCode(op, CODE_CLEAR);
+	ent = *bp++; cc--; incount++;
+    }
+    while (cc > 0) {
+	c = *bp++; cc--; incount++;
+	fcode = ((long)c << BITS_MAX) + ent;
+	h = (c << HSHIFT) ^ ent;	/* xor hashing */
+#ifdef _WINDOWS
+	/*
+	 * Check hash index for an overflow.
+	 */
+	if (h >= HSIZE)
+	    h -= HSIZE;
+#endif
+	hp = &sp->enc_hashtab[h];
+	if (hp->hash == fcode) {
+	    ent = hp->code;
+	    continue;
+	}
+	if (hp->hash >= 0) {
+	    /*
+	     * Primary hash failed, check secondary hash.
+	     */
+	    disp = HSIZE - h;
+	    if (h == 0)
+		disp = 1;
+	    do {
+		/*
+		 * Avoid pointer arithmetic 'cuz of
+		 * wraparound problems with segments.
+		 */
+		if ((h -= disp) < 0)
+		    h += HSIZE;
+		hp = &sp->enc_hashtab[h];
+		if (hp->hash == fcode) {
+		    ent = hp->code;
+		    goto hit;
+		}
+	    } while (hp->hash >= 0);
+	}
+	/*
+	 * New entry, emit code and add to table.
+	 */
+	/*
+	 * Verify there is space in the buffer for the code
+	 * and any potential Clear code that might be emitted
+	 * below.  The value of limit is setup so that there
+	 * are at least 4 bytes free--room for 2 codes.
+	 */
+	if (op > sp->out_buffer_end) {
+	    op = grow_out_buffer (sp, op);
+	    if (sp->out_buffer == NULL) {
+		return 0;
+	    }
+	}
+	PutNextCode(op, ent);
+	ent = c;
+	hp->code = free_ent++;
+	hp->hash = fcode;
+	if (free_ent == CODE_MAX-1) {
+	    /* table is full, emit clear code and reset */
+	    cl_hash(sp);
+	    sp->enc_ratio = 0;
+	    incount = 0;
+	    outcount = 0;
+	    free_ent = CODE_FIRST;
+	    PutNextCode(op, CODE_CLEAR);
+	    nbits = BITS_MIN;
+	    maxcode = MAXCODE(BITS_MIN);
+	} else {
+	    /*
+	     * If the next entry is going to be too big for
+	     * the code size, then increase it, if possible.
+	     */
+	    if (free_ent > maxcode) {
+		nbits++;
+		assert(nbits <= BITS_MAX);
+		maxcode = (int) MAXCODE(nbits);
+	    } else if (incount >= checkpoint) {
+		long rat;
+		/*
+		 * Check compression ratio and, if things seem
+		 * to be slipping, clear the hash table and
+		 * reset state.  The compression ratio is a
+		 * 24+8-bit fractional number.
+		 */
+		checkpoint = incount+CHECK_GAP;
+		CALCRATIO(sp, rat);
+		if (rat <= sp->enc_ratio) {
+		    cl_hash(sp);
+		    sp->enc_ratio = 0;
+		    incount = 0;
+		    outcount = 0;
+		    free_ent = CODE_FIRST;
+		    PutNextCode(op, CODE_CLEAR);
+		    nbits = BITS_MIN;
+		    maxcode = MAXCODE(BITS_MIN);
+		} else
+		    sp->enc_ratio = rat;
+	    }
+	}
+    hit:
+	;
+    }
+    
+    /*
+     * Restore global state.
+     */
+    sp->enc_incount = incount;
+    sp->enc_outcount = outcount;
+    sp->enc_checkpoint = checkpoint;
+    sp->enc_oldcode = ent;
+    sp->nextdata = nextdata;
+    sp->nextbits = nextbits;
+    sp->free_ent = free_ent;
+    sp->maxcode = maxcode;
+    sp->nbits = nbits;
+    sp->out_buffer_pos = op;
+    return 1;
+}
+
+/*
+ * Finish off an encoded strip by flushing the last
+ * string and tacking on an End Of Information code.
+ */
+static int
+LZWPostEncode (LZWCodecState *sp)
+{
+    unsigned char *op = sp->out_buffer_pos;
+    long nextbits = sp->nextbits;
+    long nextdata = sp->nextdata;
+    long outcount = sp->enc_outcount;
+    int nbits = sp->nbits;
+    
+    if (op > sp->out_buffer_end) {
+	op = grow_out_buffer (sp, op);
+	if (sp->out_buffer == NULL) {
+	    return 0;
+	}
+    }
+    if (sp->enc_oldcode != (hcode_t) -1) {
+	PutNextCode(op, sp->enc_oldcode);
+	sp->enc_oldcode = (hcode_t) -1;
+    }
+    PutNextCode(op, CODE_EOI);
+    if (nextbits > 0) 
+	*op++ = (unsigned char)(nextdata << (8-nextbits));
+    sp->out_buffer_bytes = (size_t)(op - sp->out_buffer);
+    return 1;
+}
+
+/*
+ * Reset encoding hash table.
+ */
+static void
+cl_hash (LZWCodecState* sp)
+{
+    register hash_t *hp = &sp->enc_hashtab[HSIZE-1];
+    register long i = HSIZE-8;
+    
+    do {
+	i -= 8;
+	hp[-7].hash = -1;
+	hp[-6].hash = -1;
+	hp[-5].hash = -1;
+	hp[-4].hash = -1;
+	hp[-3].hash = -1;
+	hp[-2].hash = -1;
+	hp[-1].hash = -1;
+	hp[ 0].hash = -1;
+	hp -= 8;
+    } while (i >= 0);
+    for (i += 8; i > 0; i--, hp--)
+	hp->hash = -1;
+}
+
+/*
+ * Copyright (c) 1985, 1986 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James A. Woods, derived from original work by Spencer Thomas
+ * and Joseph Orost.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+void *
+_cairo_compress_lzw (void *data, unsigned long data_size, unsigned long *compressed_size)
+{
+    LZWCodecState state;
+    
+    if (!LZWSetupEncode (&state))
+	goto bail0;
+    
+    state.out_buffer_size = data_size/4;
+    /* We need *some* space at least */
+    if (state.out_buffer_size < 256)
+	state.out_buffer_size = 256;
+    state.out_buffer = malloc (state.out_buffer_size);
+    if (state.out_buffer == NULL)
+	goto bail1;
+    
+    state.out_buffer_pos = state.out_buffer;
+    state.out_buffer_bytes = 0;
+    
+    LZWPreEncode (&state);
+    if (!LZWEncode (&state, data, data_size))
+	goto bail2;
+    if (!LZWPostEncode(&state))
+	goto bail2;
+    
+    LZWFreeEncode(&state);
+
+    *compressed_size = state.out_buffer_bytes;
+    return state.out_buffer;
+    
+ bail2:
+    if (state.out_buffer)
+	free (state.out_buffer);
+ bail1:
+    LZWFreeEncode(&state);
+ bail0:    
+    return NULL;
+}
diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
index b07423c..6fd6181 100644
--- a/src/cairo-output-stream.c
+++ b/src/cairo-output-stream.c
@@ -114,6 +114,69 @@ _cairo_output_stream_write_hex_string (c
     }
 }
 
+static cairo_bool_t
+convert_four_tuple (const unsigned char *four_tuple, char five_tuple[5])
+{
+    cairo_bool_t all_zero;
+    uint32_t value;
+    int digit, i;
+    
+    value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3];
+    all_zero = TRUE;
+    for (i = 0; i < 5; i++) {
+	digit = value % 85;
+	if (digit != 0)
+	    all_zero = FALSE;
+	five_tuple[4-i] = digit + 33;
+	value = value / 85;
+    }
+    return all_zero;
+}
+
+void
+_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream,
+					  const char *data,
+					  size_t length)
+{
+    unsigned char *ptr;
+    unsigned char four_tuple[4];
+    char five_tuple[5];
+    int column;
+    
+    ptr = (unsigned char *)data;
+    column = 0;
+    while (length > 0) {
+	if (length >= 4) {
+	    if (convert_four_tuple (ptr, five_tuple)) {
+		column += 1;
+		_cairo_output_stream_write (stream, "z", 1);
+	    } else {
+		column += 5;
+		_cairo_output_stream_write (stream, five_tuple, 5);
+	    }
+	    length -= 4;
+	    ptr += 4;
+	} else { /* length < 4 */
+	    memset (four_tuple, 0, 4);
+	    memcpy (four_tuple, ptr, length);
+	    convert_four_tuple (four_tuple, five_tuple);
+	    column += length + 1;
+	    _cairo_output_stream_write (stream, five_tuple, length + 1);
+	    length = 0;
+	}
+	if (column >= 72) {
+	    _cairo_output_stream_write (stream, "\n", 1);
+	    column = 0;
+	}
+    }
+
+    if (column > 0) {
+	_cairo_output_stream_write (stream, "\n", 1);
+    }
+}
+
+
+
 /* Format a double in a locale independent way and trim trailing
  * zeros.  Based on code from Alex Larson <alexl at redhat.com>.
  * http://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00087.html
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 6028b6d..ff4f0e8 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -50,8 +50,6 @@
  *
  * - Add document structure convention comments where appropriate.
  *
- * - Fix image compression.
- *
  * - Create a set of procs to use... specifically a trapezoid proc.
  */
 
@@ -101,11 +99,9 @@ _cairo_ps_surface_emit_header (cairo_ps_
 				 surface->width,
 				 surface->height);
 
-    /* The "/FlateDecode filter" currently used is a feature of
-     * LanguageLevel 3 */
     _cairo_output_stream_printf (surface->stream,
-				 "%%%%DocumentData: Binary\n"
-				 "%%%%LanguageLevel: 3\n"
+				 "%%%%DocumentData: Clean7Bit\n"
+				 "%%%%LanguageLevel: 2\n"
 				 "%%%%Orientation: Portrait\n"
 				 "%%%%EndComments\n");
 }
@@ -658,23 +654,6 @@ pattern_operation_needs_fallback (cairo_
 /* PS Output - this section handles output of the parts of the meta
  * surface we can render natively in PS. */
 
-static void *
-compress_dup (const void *data, unsigned long data_size,
-	      unsigned long *compressed_size)
-{
-    void *compressed;
-
-    /* Bound calculation taken from zlib. */
-    *compressed_size = data_size + (data_size >> 12) + (data_size >> 14) + 11;
-    compressed = malloc (*compressed_size);
-    if (compressed == NULL)
-	return NULL;
-
-    compress (compressed, compressed_size, data, data_size);
-
-    return compressed;
-}
-
 static cairo_status_t
 emit_image (cairo_ps_surface_t    *surface,
 	    cairo_image_surface_t *image,
@@ -745,7 +724,7 @@ emit_image (cairo_ps_surface_t    *surfa
 	}
     }
 
-    compressed = compress_dup (rgb, rgb_size, &compressed_size);
+    compressed = _cairo_compress_lzw (rgb, rgb_size, &compressed_size);
     if (compressed == NULL) {
 	status = CAIRO_STATUS_NO_MEMORY;
 	goto bail2;
@@ -765,7 +744,7 @@ emit_image (cairo_ps_surface_t    *surfa
 				 "	/Height %d\n"
 				 "	/BitsPerComponent 8\n"
 				 "	/Decode [ 0 1 0 1 0 1 ]\n"
-				 "	/DataSource currentfile\n"
+				 "	/DataSource currentfile /ASCII85Decode filter /LZWDecode filter \n"
 				 "	/ImageMatrix [ %f %f %f %f %f %f ]\n"
 				 ">>\n"
 				 "image\n",
@@ -775,13 +754,13 @@ emit_image (cairo_ps_surface_t    *surfa
 				 d2i.xy, d2i.yy,
 				 d2i.x0, d2i.y0);
 
-    /* Compressed image data */
-    _cairo_output_stream_write (surface->stream, rgb, rgb_size);
+    /* Compressed image data (Base85 encoded) */
+    _cairo_output_stream_write_base85_string (surface->stream, (char *)compressed, compressed_size);
     status = CAIRO_STATUS_SUCCESS;
 
+    /* Mark end of base85 data */
     _cairo_output_stream_printf (surface->stream,
-				 "\n");
-
+				 "~>\n");
     free (compressed);
  bail2:
     free (rgb);
diff --git a/src/cairoint.h b/src/cairoint.h
index 04096c5..d5abfc7 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2140,6 +2140,16 @@ _cairo_output_stream_write_hex_string (c
 				       const char *data,
 				       size_t length);
 
+cairo_private void
+_cairo_output_stream_write_base85_string (cairo_output_stream_t *stream,
+					  const char *data,
+					  size_t length);
+
+cairo_private void *
+_cairo_compress_lzw (void *data,
+		     unsigned long data_size,
+		     unsigned long *compressed_size);
+
 cairo_private cairo_status_t
 _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
 			      const char *fmt, va_list ap);
diff-tree d6f8df7417bdab75dbcfe9658616dd3367276ed0 (from 2af29f720faac0a9ee3961a81b81acae9a716220)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Mar 15 07:31:48 2006 -0800

    Remove annoyinc RCS magic lines that are not being used, but cause conflicts.

diff --git a/pixman/src/fbedge.c b/pixman/src/fbedge.c
index 2ee6e6c..f1289b3 100644
--- a/pixman/src/fbedge.c
+++ b/pixman/src/fbedge.c
@@ -1,6 +1,4 @@
 /*
- * $Id: fbedge.c,v 1.3 2005-08-02 01:01:24 vektor Exp $
- *
  * Copyright © 2004 Keith Packard
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
diff --git a/pixman/src/fbedgeimp.h b/pixman/src/fbedgeimp.h
index 87691fa..aa9ca90 100644
--- a/pixman/src/fbedgeimp.h
+++ b/pixman/src/fbedgeimp.h
@@ -1,6 +1,4 @@
 /*
- * $Id: fbedgeimp.h,v 1.2 2005-01-21 18:38:42 cworth Exp $
- *
  * Copyright © 2004 Keith Packard
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
diff --git a/pixman/src/fbpict.c b/pixman/src/fbpict.c
index ef7f4e2..a091740 100644
--- a/pixman/src/fbpict.c
+++ b/pixman/src/fbpict.c
@@ -1,6 +1,4 @@
 /*
- * $Id: fbpict.c,v 1.8 2006-01-21 17:39:11 biesi Exp $
- *
  * Copyright © 2000 SuSE, Inc.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
diff --git a/pixman/src/fbpict.h b/pixman/src/fbpict.h
index 95742ed..fbf00ed 100644
--- a/pixman/src/fbpict.h
+++ b/pixman/src/fbpict.h
@@ -1,6 +1,4 @@
 /*
- * $Id: fbpict.h,v 1.2 2005-09-12 12:55:11 otaylor Exp $
- *
  * Copyright © 2000 Keith Packard
  *             2005 Lars Knoll & Zack Rusin, Trolltech
  *
diff --git a/pixman/src/icpixels.c b/pixman/src/icpixels.c
index 7b3798e..cdec492 100644
--- a/pixman/src/icpixels.c
+++ b/pixman/src/icpixels.c
@@ -1,6 +1,4 @@
 /*
- * $Id: icpixels.c,v 1.9 2005-06-25 03:13:19 jrmuizel Exp $
- *
  * Copyright © 1998 Keith Packard
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
diff --git a/pixman/src/ictrap.c b/pixman/src/ictrap.c
index 0ac51ca..08bd024 100644
--- a/pixman/src/ictrap.c
+++ b/pixman/src/ictrap.c
@@ -1,6 +1,4 @@
 /*
- * $Id: ictrap.c,v 1.27 2005-08-28 02:32:57 vektor Exp $
- *
  * Copyright © 2002 Keith Packard
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
diff --git a/pixman/src/pixman.h b/pixman/src/pixman.h
index bd5194e..ecba78a 100644
--- a/pixman/src/pixman.h
+++ b/pixman/src/pixman.h
@@ -54,8 +54,6 @@ ARISING OUT OF OR IN CONNECTION WITH THE
 SOFTWARE.
 
 ******************************************************************/
-/* $Id: pixman.h,v 1.25 2006-01-05 00:26:10 cworth Exp $ */
-
 /* libic.h */
 
 /*
diff --git a/pixman/src/pixregionint.h b/pixman/src/pixregionint.h
index 86ff8e6..e47c455 100644
--- a/pixman/src/pixregionint.h
+++ b/pixman/src/pixregionint.h
@@ -44,8 +44,6 @@ ARISING OUT OF OR IN CONNECTION WITH THE
 SOFTWARE.
 
 ******************************************************************/
-/* $Id: pixregionint.h,v 1.7 2004-04-16 15:32:53 cworth Exp $ */
-
 #ifndef _PIXREGIONINT_H_
 #define _PIXREGIONINT_H_
 
diff --git a/pixman/src/renderedge.c b/pixman/src/renderedge.c
index 525ea73..56fcfb3 100644
--- a/pixman/src/renderedge.c
+++ b/pixman/src/renderedge.c
@@ -1,6 +1,4 @@
 /*
- * $Id: renderedge.c,v 1.2 2005-01-21 18:26:28 cworth Exp $
- *
  * Copyright © 2004 Keith Packard
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
diff --git a/pixman/src/renderedge.h b/pixman/src/renderedge.h
index 5c7c1e5..522e503 100644
--- a/pixman/src/renderedge.h
+++ b/pixman/src/renderedge.h
@@ -1,6 +1,4 @@
 /*
- * $Id: renderedge.h,v 1.3 2005-02-21 21:29:22 cworth Exp $
- *
  * Copyright © 2004 Keith Packard
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
diff-tree 2af29f720faac0a9ee3961a81b81acae9a716220 (from 5d89faf6b37bb0367c8ba8f8637fc80bd745c888)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date:   Tue Mar 14 23:02:39 2006 +0100

    SVG: use xmlOutputBuffer for file creation, instead of dumping xml tree in a memory buffer.

diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 58faa32..5d569bd 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -1342,21 +1342,32 @@ _cairo_svg_document_destroy (cairo_svg_d
     free (document);
 }
 
+static int
+_cairo_svg_document_write (cairo_output_stream_t *output_stream,
+			   const char * buffer,
+			   int len)
+{
+    if (_cairo_output_stream_write (output_stream, buffer, len) != CAIRO_STATUS_SUCCESS)
+	return -1;
+}
+
+
 static cairo_status_t
 _cairo_svg_document_finish (cairo_svg_document_t *document)
 {
     cairo_status_t status;
     cairo_output_stream_t *output = document->output_stream;
-    xmlChar *xml_buffer;
-    int xml_buffer_size;
+    xmlOutputBufferPtr xml_output_buffer;
 
     if (document->finished)
 	return CAIRO_STATUS_SUCCESS;
 
-    /* FIXME: Dumping xml tree in memory is silly. */
-    xmlDocDumpFormatMemoryEnc (document->xml_doc, &xml_buffer, &xml_buffer_size, "UTF-8", 1);
-    _cairo_output_stream_write (document->output_stream, xml_buffer, xml_buffer_size);
-    xmlFree(xml_buffer);
+    xml_output_buffer = xmlOutputBufferCreateIO ((xmlOutputWriteCallback) _cairo_svg_document_write,
+						 (xmlOutputCloseCallback) NULL,
+						 (void *) document->output_stream, 
+						 NULL);
+    xmlSaveFormatFileTo (xml_output_buffer, document->xml_doc, "UTF-8", 1);
+
     xmlFreeDoc (document->xml_doc);
 
     status = _cairo_output_stream_get_status (output);
diff-tree 5d89faf6b37bb0367c8ba8f8637fc80bd745c888 (from 6f0d8eedc504e8af2224c502be25dc82b5df70f4)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Mar 13 13:20:29 2006 -0800

    fbCompositeTrans_0888xnx0888: Fix suspicious logical negation of pointer value.
    
    Surely, the ! instead of ~ here was just a typo. I'd feel better if I
    had a failing test case for this though, (time to break out gcov
    again).
    
    Fixes bug #6185:
    
    	Strange pointer operations in fbCompositeTrans_0888xnx0888 (pixman/src/fbpict.c)
    	https://bugs.freedesktop.org/show_bug.cgi?id=6185

diff --git a/pixman/src/fbpict.c b/pixman/src/fbpict.c
index e074174..ef7f4e2 100644
--- a/pixman/src/fbpict.c
+++ b/pixman/src/fbpict.c
@@ -1151,7 +1151,7 @@ fbCompositeTrans_0888xnx0888(pixman_oper
 				setupPackedReader(ws,wt,isrc,wsrc,workingSource);
 
 				/* get to word aligned */
-				switch(!(long)dst&3)
+				switch(~(long)dst&3)
 				{
 					case 1:
 						readPackedSource(rs);
@@ -1227,7 +1227,7 @@ fbCompositeTrans_0888xnx0888(pixman_oper
 				srcLine += srcStride;
 				w = width*3;
 				/* get to word aligned */
-				switch(!(long)src&3)
+				switch(~(long)src&3)
 				{
 					case 1:
 						rd=alphamaskCombine24(*src++, *dst)>>8;
diff-tree 6f0d8eedc504e8af2224c502be25dc82b5df70f4 (from 79075b2cb1ce1397506fc10572df96f6fd00ecc3)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Mar 13 12:25:25 2006 -0800

    _clip_and_composite_trapezoids: Avoid NULL pointer dereference due to OOM.
    
    This closes bug #6197:
    
    	Null pointer dereference on OOM in _clip_and_composite_trapezoids()
    	https://bugs.freedesktop.org/show_bug.cgi?id=6197

diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 9dde31f..9b6cfd6 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -549,6 +549,9 @@ _clip_and_composite_trapezoids (cairo_pa
 		return status;
 	    
 	    clear_region = _cairo_region_create_from_rectangle (&extents);
+	    if (clear_region == NULL)
+		return CAIRO_STATUS_NO_MEMORY;
+
 	    status = _cairo_clip_intersect_to_region (clip, clear_region);
 	    if (status)
 		return status;
diff-tree 79075b2cb1ce1397506fc10572df96f6fd00ecc3 (from fc51a78a1ed5f7649ce55ab30fc42939a9b295d1)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Mar 13 12:20:23 2006 -0800

    cairo-clip: Fix memory leak during OOM handling.
    
    This closes bug #6196:
    
    	Memory leak in _cairo_clip_intersect_path (src/cairo-clip.c)
    	https://bugs.freedesktop.org/show_bug.cgi?id=6196

diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index c76ebdc..0c862a3 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -248,8 +248,10 @@ _cairo_clip_intersect_path (cairo_clip_t
 	return CAIRO_STATUS_NO_MEMORY;
 
     status = _cairo_path_fixed_init_copy (&clip_path->path, path);
-    if (status)
+    if (status) {
+	free (clip_path);
 	return status;
+    }
 
     clip_path->ref_count = 1;
     clip_path->fill_rule = fill_rule;
diff-tree fc51a78a1ed5f7649ce55ab30fc42939a9b295d1 (from 25cccaaa1f6d337a1a0423a298f94456e72a820a)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Mar 13 12:14:47 2006 -0800

    cairo-pdf-surface: Close memory leak during OOM handling.
    
    This fixes bug #6186:
    
    	Memory leak in emit_image_rgb_data (src/cairo-pdf-surface.c)
    	https://bugs.freedesktop.org/show_bug.cgi?id=6186

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index cb8287b..6d18196 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -654,8 +654,10 @@ emit_image_rgb_data (cairo_pdf_document_
 	opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
 					     image->width,
 					     image->height);
-	if (opaque->status)
+	if (opaque->status) {
+	    free (rgb);
 	    return 0;
+	}
     
 	_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
     
diff-tree 25cccaaa1f6d337a1a0423a298f94456e72a820a (from parents)
Merge: c780f4a5624f27a6cbf7829e10e8cd3544ae4f38 118f71b43870551db520ad56234c650aa4b61296
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Mar 13 12:05:37 2006 -0800

    Merge branch 'cairo-origin' into cairo

diff-tree c780f4a5624f27a6cbf7829e10e8cd3544ae4f38 (from 92e09ee72fdde9059300b2b63d87e2bbd4286605)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Mar 13 12:05:13 2006 -0800

    cairo-output-stream: Don't dereference a NULL pointer due to OOM.
    
    This close bug #6176:
    
    	Null pointer dereference on OOM in _cairo_output_stream_create_for_file()
    	https://bugs.freedesktop.org/show_bug.cgi?id=6176

diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
index a6db091..b07423c 100644
--- a/src/cairo-output-stream.c
+++ b/src/cairo-output-stream.c
@@ -305,9 +305,11 @@ _cairo_output_stream_create_for_file (co
 	return NULL;
     
     stream = _cairo_output_stream_create (stdio_write, fp);
-    if (stream == NULL)
+
+    if (stream)
+	stream->owns_closure_is_file = TRUE;
+    else
 	fclose (fp);
-    stream->owns_closure_is_file = TRUE;
 
     return stream;
 }
diff-tree 118f71b43870551db520ad56234c650aa4b61296 (from parents)
Merge: 66599911e0664afd145975e3afb0f580e6d1bb3c 92e09ee72fdde9059300b2b63d87e2bbd4286605
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date:   Sun Mar 12 19:30:29 2006 +0100

    Merge branch 'master' of git+ssh://emmanuel@git.cairographics.org/git/cairo

diff-tree 66599911e0664afd145975e3afb0f580e6d1bb3c (from 7563a23921a4d6f9f826a13b42d61f3ba3c31c10)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date:   Thu Mar 9 22:09:14 2006 +0100

    Don't duplicate unmodified SVG surfaces

diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index b5cee75..58faa32 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -91,6 +91,9 @@ struct cairo_svg_surface {
     xmlNodePtr  xml_root_node;
 
     unsigned int clip_level;
+
+    cairo_bool_t modified;
+    unsigned int previous_id;
 };
 
 static cairo_svg_document_t *
@@ -217,6 +220,9 @@ _cairo_svg_surface_create_for_document (
     xmlSetProp (surface->xml_node, CC2XML ("id"), C2XML (buffer));
     snprintf (buffer, sizeof buffer, "url(#clip%d)", clip_id);
     xmlSetProp (surface->xml_node, CC2XML ("clip-path"), C2XML (buffer));
+
+    surface->modified = TRUE;
+    surface->previous_id = surface->id;
     
     return &surface->base;
 }
@@ -459,10 +465,11 @@ emit_composite_svg_pattern (xmlNodePtr n
     xmlNodePtr child;
     char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
 
-    xmlAddChild (document->xml_node_defs, xmlCopyNode (surface->xml_root_node, 1));
+    if (surface->modified)
+	    xmlAddChild (document->xml_node_defs, xmlCopyNode (surface->xml_root_node, 1));
     
     child = xmlNewChild (node, NULL, CC2XML("use"), NULL);
-    snprintf (buffer, sizeof buffer, "#surface%d", surface->id);
+    snprintf (buffer, sizeof buffer, "#surface%d", surface->previous_id);
     xmlSetProp (child, CC2XML ("xlink:href"), C2XML (buffer));
 
     if (!is_pattern) {
@@ -476,9 +483,13 @@ emit_composite_svg_pattern (xmlNodePtr n
     if (height != NULL)
 	    *height = surface->height;
 
-    surface->id = document->surface_id++;
-    snprintf (buffer, sizeof buffer, "surface%d", surface->id);
-    xmlSetProp (surface->xml_root_node, CC2XML ("id"), C2XML (buffer));
+    if (surface->modified) {
+	    surface->modified = FALSE;
+	    surface->previous_id = surface->id;
+	    surface->id = document->surface_id++;
+	    snprintf (buffer, sizeof buffer, "surface%d", surface->id);
+	    xmlSetProp (surface->xml_root_node, CC2XML ("id"), C2XML (buffer));
+    }
 
     return child;
 }
@@ -925,6 +936,7 @@ _cairo_svg_surface_fill (void			*abstrac
     xmlBufferFree (info.path);
     xmlBufferFree (style);
 
+    surface->modified = TRUE;
     return status;
 }
 
@@ -987,8 +999,10 @@ _cairo_svg_surface_paint (void		    *abs
 			  cairo_pattern_t   *source)
 {
     cairo_svg_surface_t *surface = abstract_surface;
-    
+
     emit_paint (surface->xml_node, surface, op, source);
+    
+    surface->modified = TRUE;
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -1017,6 +1031,7 @@ _cairo_svg_surface_mask (void		    *abst
 
     document->mask_id++;
 
+    surface->modified = TRUE;
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -1122,6 +1137,7 @@ _cairo_svg_surface_stroke (void			*abstr
     xmlBufferFree (info.path);
     xmlBufferFree (style);
 
+    surface->modified = TRUE;
     return status;
 }
 
@@ -1133,6 +1149,7 @@ _cairo_svg_surface_show_glyphs (void			*
 				int			 num_glyphs,
 				cairo_scaled_font_t	*scaled_font)
 {
+    cairo_svg_surface_t *surface = abstract_surface;
     cairo_path_fixed_t path;
     cairo_status_t status;
 
@@ -1156,6 +1173,7 @@ _cairo_svg_surface_show_glyphs (void			*
 
     _cairo_path_fixed_fini (&path);
 
+    surface->modified = TRUE;
     return status;
 }
 
diff-tree 92e09ee72fdde9059300b2b63d87e2bbd4286605 (from 1cffb39ff04bbb29bb070e42c51aa1ae6aaf5a4c)
Author: Mart Raudsepp <leio at dustbite.net>
Date:   Thu Mar 9 08:23:43 2006 -0800

    Complete the CAIRO_PATTERN_TYPE renaming
    
    This fixes compilation of the glitz backend, and also fixes missing
    renames in win32, atsui, and directfb backends.

diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index a4c2dc2..cab7843 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -602,7 +602,7 @@ _cairo_atsui_font_old_show_glyphs (void	
     CGContextSetFontSize(myBitmapContext, 1.0);
     CGContextSetTextMatrix(myBitmapContext, textTransform);
 
-    if (pattern->type == CAIRO_PATTERN_SOLID &&
+    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID &&
 	_cairo_pattern_is_opaque_solid(pattern))
     {
 	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern;
diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index 4c3e9cd..fcd5dd7 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -483,9 +483,9 @@ _cairo_directfb_surface_composite (cairo
 	if( _dfb_set_operator(op,surface->buffer) == DFB_UNSUPPORTED ) 
 		return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if (src_pattern->type == CAIRO_PATTERN_SOLID ) { 
+    if (src_pattern->type == CAIRO_PATTERN_TYPE_SOLID ) { 
 
-    } else if (src_pattern->type != CAIRO_PATTERN_SURFACE ||
+    } else if (src_pattern->type != CAIRO_PATTERN_TYPE_SURFACE ||
 			src_pattern->extend != CAIRO_EXTEND_NONE) {
 		return CAIRO_INT_STATUS_UNSUPPORTED;
 	}
@@ -494,7 +494,7 @@ _cairo_directfb_surface_composite (cairo
 	/* FIXME: When we fully support RENDER style 4-channel
 	 * masks we need to check r/g/b != 1.0.
 	 */
-	if (mask_pattern->type != CAIRO_PATTERN_SOLID)
+	if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID)
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 
 		alpha = ((cairo_solid_pattern_t *)mask_pattern)->color.alpha_short >> 8;
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index 667e231..c000917 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -551,8 +551,8 @@ _cairo_glitz_pattern_acquire_surface (ca
     attr->acquired = FALSE;
 
     switch (pattern->type) {
-    case CAIRO_PATTERN_LINEAR:
-    case CAIRO_PATTERN_RADIAL: {
+    case CAIRO_PATTERN_TYPE_LINEAR:
+    case CAIRO_PATTERN_TYPE_RADIAL: {
 	cairo_gradient_pattern_t    *gradient =
 	    (cairo_gradient_pattern_t *) pattern;
 	char			    *data;
@@ -587,7 +587,7 @@ _cairo_glitz_pattern_acquire_surface (ca
 	if (!CAIRO_GLITZ_FEATURE_OK (dst->surface, FRAGMENT_PROGRAM))
 	    break;
 
-	if (pattern->type == CAIRO_PATTERN_RADIAL)
+	if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
 	    n_base_params = 6;
 	else
 	    n_base_params = 4;
@@ -639,7 +639,7 @@ _cairo_glitz_pattern_acquire_surface (ca
 
 	glitz_buffer_destroy (buffer);
 
-	if (pattern->type == CAIRO_PATTERN_LINEAR)
+	if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR)
 	{
 	    cairo_linear_pattern_t *grad = (cairo_linear_pattern_t *) pattern;
 
@@ -776,8 +776,8 @@ _cairo_glitz_pattern_acquire_surfaces (c
      * information in mask, so this will need to change when we
      * support RENDER-style 4-channel masks. */
 
-    if (src->type == CAIRO_PATTERN_SOLID &&
-	mask->type == CAIRO_PATTERN_SOLID)
+    if (src->type == CAIRO_PATTERN_TYPE_SOLID &&
+	mask->type == CAIRO_PATTERN_TYPE_SOLID)
     {
 	cairo_color_t combined;
 	cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src;
@@ -1018,7 +1018,7 @@ _cairo_glitz_surface_composite_trapezoid
     if (_glitz_ensure_target (dst->surface))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if (pattern->type == CAIRO_PATTERN_SURFACE)
+    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
     {
 	_cairo_pattern_init_copy (&tmp_src_pattern.base, pattern);
 
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 5e1e342..3e88ec5 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -631,7 +631,7 @@ _cairo_win32_surface_composite (cairo_op
     int integer_transform;
     int itx, ity;
 
-    if (pattern->type != CAIRO_PATTERN_SURFACE ||
+    if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE ||
 	pattern->extend != CAIRO_EXTEND_NONE)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
@@ -639,7 +639,7 @@ _cairo_win32_surface_composite (cairo_op
 	/* FIXME: When we fully support RENDER style 4-channel
 	 * masks we need to check r/g/b != 1.0.
 	 */
-	if (mask_pattern->type != CAIRO_PATTERN_SOLID)
+	if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID)
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 
 	alpha = ((cairo_solid_pattern_t *)mask_pattern)->color.alpha_short >> 8;
diff-tree 1cffb39ff04bbb29bb070e42c51aa1ae6aaf5a4c (from 3333bba82d26a0b11961af3cb5c29c79a1a0d07b)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Mar 8 08:16:49 2006 -0800

    cairo_show_glyphs: Do nothing if num_glyphs == 0

diff --git a/src/cairo.c b/src/cairo.c
index 96cd504..d0dd4ec 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -2155,6 +2155,9 @@ cairo_show_glyphs (cairo_t *cr, cairo_gl
     if (cr->status)
 	return;
 
+    if (num_glyphs == 0)
+	return;
+
     cr->status = _cairo_gstate_show_glyphs (cr->gstate, glyphs, num_glyphs);
     if (cr->status)
 	_cairo_set_error (cr, cr->status);
diff-tree 7563a23921a4d6f9f826a13b42d61f3ba3c31c10 (from 3333bba82d26a0b11961af3cb5c29c79a1a0d07b)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date:   Sun Mar 5 23:49:38 2006 +0100

    Fix self-copy test

diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 76e7c6a..b5cee75 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -88,6 +88,7 @@ struct cairo_svg_surface {
     cairo_svg_document_t *document;
 
     xmlNodePtr  xml_node;
+    xmlNodePtr  xml_root_node;
 
     unsigned int clip_level;
 };
@@ -209,10 +210,8 @@ _cairo_svg_surface_create_for_document (
     _cairo_dtostr (buffer, sizeof buffer, height);
     xmlSetProp (clip_rect, CC2XML ("height"), C2XML (buffer));
     
-    surface->xml_node = xmlNewChild (surface->id == 0 ? 
-				     document->xml_node_main : 
-				     document->xml_node_defs, 
-				     NULL, CC2XML ("g"), NULL);
+    surface->xml_node = xmlNewNode (NULL, CC2XML ("g"));
+    surface->xml_root_node = surface->xml_node;
 	
     snprintf (buffer, sizeof buffer, "surface%d", surface->id);
     xmlSetProp (surface->xml_node, CC2XML ("id"), C2XML (buffer));
@@ -240,14 +239,19 @@ _cairo_svg_surface_finish (void *abstrac
     cairo_status_t status;
     cairo_svg_surface_t *surface = abstract_surface;
     cairo_svg_document_t *document = surface->document;
+    
 
-    if (document->owner == &surface->base)
+    if (document->owner == &surface->base) {
+	xmlAddChild (document->xml_node_main, xmlCopyNode (surface->xml_root_node, 1));
 	status = _cairo_svg_document_finish (document);
-    else
+    } else
 	status = CAIRO_STATUS_SUCCESS;
 
     _cairo_svg_document_destroy (document);
 
+    xmlFreeNode (surface->xml_root_node);
+    surface->xml_node = NULL;
+
     return status;
 }
 
@@ -450,13 +454,12 @@ emit_composite_svg_pattern (xmlNodePtr n
 			    cairo_bool_t is_pattern)
 {
     cairo_svg_surface_t *surface = (cairo_svg_surface_t *) pattern->surface;
+    cairo_svg_document_t *document = surface->document;
     cairo_matrix_t p2u;
     xmlNodePtr child;
     char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
 
-    /* FIXME: self copy is not supported yet */
-    if (surface->id == 0)
-	return NULL;
+    xmlAddChild (document->xml_node_defs, xmlCopyNode (surface->xml_root_node, 1));
     
     child = xmlNewChild (node, NULL, CC2XML("use"), NULL);
     snprintf (buffer, sizeof buffer, "#surface%d", surface->id);
@@ -473,6 +476,10 @@ emit_composite_svg_pattern (xmlNodePtr n
     if (height != NULL)
 	    *height = surface->height;
 
+    surface->id = document->surface_id++;
+    snprintf (buffer, sizeof buffer, "surface%d", surface->id);
+    xmlSetProp (surface->xml_root_node, CC2XML ("id"), C2XML (buffer));
+
     return child;
 }
 
@@ -1167,10 +1174,8 @@ _cairo_svg_surface_intersect_clip_path (
     char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
 
     if (path == NULL) {
-	while (surface->clip_level > 0) {
-	    surface->xml_node = surface->xml_node->parent;
-	    surface->clip_level--;
-	}
+	surface->xml_node = surface->xml_root_node;
+	surface->clip_level = 0;
 	return CAIRO_STATUS_SUCCESS;
     }
 
diff-tree 3333bba82d26a0b11961af3cb5c29c79a1a0d07b (from parents)
Merge: 62812b25c7f0c11aa6c973b722fa8e1bd088d4b8 3370cd631858cac0fd3ce33c74db3af40991e6f1
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Mar 3 15:41:14 2006 -0800

    Merge branch 'show-glyphs-many' into cairo

diff-tree 3370cd631858cac0fd3ce33c74db3af40991e6f1 (from 34a4ad1e5bca8db34933718db245a232ebe30ce2)
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Mar 3 15:40:58 2006 -0800

    _cairo_xlib_surface_old_show_glyphs: Break up rendering into chunks to fit
    into X max request length protocol limits.
    
    This fixes bug #5528:
    
    	_XError from XRenderCompositeText8
    	https://bugs.freedesktop.org/show_bug.cgi?id=5528
    (cherry picked from 7d498ca91279a4e793d704c5b878f070be4c878f commit)

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index a62afed..6def998 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -41,6 +41,7 @@
 #include "cairo-xlib-test.h"
 #include "cairo-xlib-private.h"
 #include <X11/extensions/Xrender.h>
+#include <X11/extensions/renderproto.h>
 
 /* Xlib doesn't define a typedef, so define one ourselves */
 typedef int (*cairo_xlib_error_func_t) (Display     *display,
@@ -2404,6 +2405,8 @@ _cairo_xlib_surface_old_show_glyphs (cai
     cairo_int_status_t		status;
     cairo_xlib_surface_t *self = abstract_surface;
     cairo_xlib_surface_t *src;
+    const cairo_glyph_t *glyphs_chunk;
+    int glyphs_remaining, chunk_size, max_chunk_size;
     composite_operation_t operation;
     cairo_scaled_glyph_t *scaled_glyph;
     cairo_xlib_surface_font_private_t *font_private;
@@ -2458,23 +2461,41 @@ _cairo_xlib_surface_old_show_glyphs (cai
     }
     
     _cairo_xlib_surface_ensure_dst_picture (self);
-    /* Call the appropriate sub-function. */
 
+    max_chunk_size = XMaxRequestSize (self->dpy);
     if (max_index < 256)
-	status = _cairo_xlib_surface_old_show_glyphs8 (scaled_font, op, src, self,
-						   source_x + attributes.x_offset - dest_x,
-						   source_y + attributes.y_offset - dest_y, 
-						   glyphs, num_glyphs);
+	max_chunk_size -= sz_xRenderCompositeGlyphs8Req;
     else if (max_index < 65536)
-	status = _cairo_xlib_surface_old_show_glyphs16 (scaled_font, op, src, self,
-						    source_x + attributes.x_offset - dest_x,
-						    source_y + attributes.y_offset - dest_y, 
-						    glyphs, num_glyphs);
-    else 
-	status = _cairo_xlib_surface_old_show_glyphs32 (scaled_font, op, src, self,
-						    source_x + attributes.x_offset - dest_x,
-						    source_y + attributes.y_offset - dest_y, 
-						    glyphs, num_glyphs);
+	max_chunk_size -= sz_xRenderCompositeGlyphs16Req;
+    else
+	max_chunk_size -= sz_xRenderCompositeGlyphs32Req;
+    max_chunk_size /= sz_xGlyphElt;
+
+    for (glyphs_remaining = num_glyphs, glyphs_chunk = glyphs;
+	 glyphs_remaining;
+	 glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size)
+    {
+	chunk_size = MIN (glyphs_remaining, max_chunk_size);
+
+	/* Call the appropriate sub-function. */
+	if (max_index < 256)
+	    status = _cairo_xlib_surface_old_show_glyphs8 (scaled_font, op, src, self,
+					      source_x + attributes.x_offset - dest_x,
+					      source_y + attributes.y_offset - dest_y, 
+					      glyphs_chunk, chunk_size);
+	else if (max_index < 65536)
+	    status = _cairo_xlib_surface_old_show_glyphs16 (scaled_font, op, src, self,
+					       source_x + attributes.x_offset - dest_x,
+					       source_y + attributes.y_offset - dest_y, 
+					       glyphs_chunk, chunk_size);
+	else 
+	    status = _cairo_xlib_surface_old_show_glyphs32 (scaled_font, op, src, self,
+					       source_x + attributes.x_offset - dest_x,
+					       source_y + attributes.y_offset - dest_y, 
+					       glyphs_chunk, chunk_size);
+	if (status != CAIRO_STATUS_SUCCESS)
+	    break;
+    }
 
     if (status == CAIRO_STATUS_SUCCESS && !_cairo_operator_bounded_by_mask (op)) {
 	cairo_rectangle_t   extents;
diff-tree 34a4ad1e5bca8db34933718db245a232ebe30ce2 (from 3490ed989672eaf2c08468ba81e3376fa362e41f)
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Mar 2 10:32:38 2006 -0800

    test/show-glyphs-many: New test case to demonstrate bug #5528
    
    This demonstrates an Xlib crash when rendering many glyphs. See:
    
    	_XError from XRenderCompositeText8
    	https://bugs.freedesktop.org/show_bug.cgi?id=5528
    
    for more details.

diff --git a/test/.gitignore b/test/.gitignore
index 65741ca..8a1a8ac 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -61,6 +61,7 @@ select-font-no-show-text
 self-copy
 self-intersecting
 set-source
+show-glyphs-many
 show-text-current-point
 source-clip
 source-surface-scale-paint
diff --git a/test/Makefile.am b/test/Makefile.am
index 8a67fc5..f1fe6f5 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -44,6 +44,7 @@ select-font-no-show-text	\
 self-copy			\
 self-intersecting		\
 set-source			\
+show-glyphs-many		\
 show-text-current-point		\
 source-clip			\
 source-surface-scale-paint	\
@@ -331,6 +332,7 @@ select_font_no_show_text_LDADD = $(LDADD
 self_copy_LDADD = $(LDADDS)
 self_intersecting_LDADD = $(LDADDS)
 set_source_LDADD = $(LDADDS)
+show_glyphs_many_LDADD = $(LDADDS)
 show_text_current_point_LDADD = $(LDADDS)
 source_clip_LDADD = $(LDADDS)
 source_surface_scale_paint_LDADD = $(LDADDS)
diff --git a/test/show-glyphs-many-ref.png b/test/show-glyphs-many-ref.png
new file mode 100644
index 0000000..b61c5f7
Binary files /dev/null and b/test/show-glyphs-many-ref.png differ
diff --git a/test/show-glyphs-many-rgb24-ref.png b/test/show-glyphs-many-rgb24-ref.png
new file mode 100644
index 0000000..450e8e0
Binary files /dev/null and b/test/show-glyphs-many-rgb24-ref.png differ
diff --git a/test/show-glyphs-many.c b/test/show-glyphs-many.c
new file mode 100644
index 0000000..3c44411
--- /dev/null
+++ b/test/show-glyphs-many.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright © 2006 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl D. Worth <cworth at cworth.org>
+ */
+
+#include "cairo-test.h"
+
+#include <string.h>
+
+/* Bug history
+ *
+ * 2006-01-07  Jon Hellan  <hellan at acm.org>
+ *
+ *   Jon opened the following bug report:
+ *
+ *	_XError from XRenderCompositeText8
+ *	https://bugs.freedesktop.org/show_bug.cgi?id=5528
+ *
+ * 2006-03-02  Carl Worth  <cworth at cworth.org>
+ *
+ *   I wrote this test case to demonstrate the bug.
+ *
+ *   Approach:
+ *
+ *	Draw 65535 glyphs white-on-white all on top of each other.
+ *
+ *   Rationale:
+ *
+ *	The number 65535 comes from the original bug report.
+ *
+ *	I would use cairo_show_text with a long string of 'x's say,
+ *	but then the surface would need to be enormous to contain
+ *	them. A smaller surface could be used, but I fear that at some
+ *	point the off-surface glyph drawing would be optimized away
+ *	and not exercise the bug.
+ *
+ *	So, to keep the surface size under control, I use
+ *	cairo_show_glyphs which allows me to place the glyphs all on
+ *	top of each other. But, since cairo doesn't provide any
+ *	character-to-glyphs mapping, I can't get a reliable glyph
+ *	index (for character 'x' for example). So I just "guess" a
+ *	glyph index and use white-on-white drawing to ignore the
+ *	result. (I don't care what's drawn---I just want to ensure
+ *	that things don't crash.)
+ *
+ *  Status: I replicated bug. The largest value of NUM_GLYPHS for
+ *      which I saw success is 21842.
+ */
+
+#define TEXT_SIZE 12
+#define NUM_GLYPHS 65535
+
+/* This is the index into the font for what glyph we'll draw. Since we
+ * don't guarantee we'll get any particular font, we can't relibably
+ * get any particular glyph. But we don't care what we draw anyway,
+ * (see discussion of white-on-white drawing above). For what it's
+ * worth, this appears to be giving me 'M' with Bitstream Vera
+ * Sans Mono. */
+#define GLYPH_INDEX 48
+
+cairo_test_t test = {
+    "show-glyphs-many",
+    "Test that cairo_show_glyps works when handed 'many' glyphs",
+    9, 11
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    cairo_glyph_t glyphs[NUM_GLYPHS];
+    cairo_font_options_t *font_options;
+    int i;
+
+    /* Initialize our giant array of glyphs. */
+    for (i=0; i < NUM_GLYPHS; i++) {
+	glyphs[i].index = GLYPH_INDEX;
+	glyphs[i].x = 1.0;
+	glyphs[i].y = height - 1;
+    }
+
+    /* Paint white background. */
+    cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
+    cairo_paint (cr);
+
+    cairo_select_font_face (cr, "Bitstream Vera Sans Mono",
+			    CAIRO_FONT_SLANT_NORMAL,
+			    CAIRO_FONT_WEIGHT_NORMAL);
+    cairo_set_font_size (cr, TEXT_SIZE);
+
+    font_options = cairo_font_options_create ();
+
+    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
+    cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_GRAY);
+
+    cairo_set_font_options (cr, font_options);
+    cairo_font_options_destroy (font_options);
+
+    cairo_show_glyphs (cr, glyphs, NUM_GLYPHS);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+    return cairo_test (&test, draw);
+}
diff-tree 62812b25c7f0c11aa6c973b722fa8e1bd088d4b8 (from 2fb016c75b950b3b1fe077dc349713f61118fd7c)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date:   Thu Mar 2 14:54:37 2006 +0100

    Fix gcc 4.0 signedness warnings

diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 2ad2137..76e7c6a 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -263,22 +263,22 @@ emit_transform (xmlNodePtr node, 
     xmlBufferCat (matrix_buffer, CC2XML ("matrix("));
     _cairo_dtostr (buffer, sizeof buffer, matrix->xx);
     xmlBufferCat (matrix_buffer, C2XML (buffer));
-    xmlBufferCat (matrix_buffer, ",");
+    xmlBufferCat (matrix_buffer, CC2XML (","));
     _cairo_dtostr (buffer, sizeof buffer, matrix->yx);
     xmlBufferCat (matrix_buffer, C2XML (buffer));
-    xmlBufferCat (matrix_buffer, ",");
+    xmlBufferCat (matrix_buffer, CC2XML (","));
     _cairo_dtostr (buffer, sizeof buffer, matrix->xy);
     xmlBufferCat (matrix_buffer, C2XML (buffer));
-    xmlBufferCat (matrix_buffer, ",");
+    xmlBufferCat (matrix_buffer, CC2XML (","));
     _cairo_dtostr (buffer, sizeof buffer, matrix->yy);
     xmlBufferCat (matrix_buffer, C2XML (buffer));
-    xmlBufferCat (matrix_buffer, ",");
+    xmlBufferCat (matrix_buffer, CC2XML (","));
     _cairo_dtostr (buffer, sizeof buffer, matrix->x0);
     xmlBufferCat (matrix_buffer, C2XML (buffer));
-    xmlBufferCat (matrix_buffer, ",");
+    xmlBufferCat (matrix_buffer, CC2XML(","));
     _cairo_dtostr (buffer, sizeof buffer, matrix->y0);
     xmlBufferCat (matrix_buffer, C2XML (buffer));
-    xmlBufferCat (matrix_buffer, ")");
+    xmlBufferCat (matrix_buffer, CC2XML (")"));
     xmlSetProp (node, CC2XML (attribute_str), C2XML (xmlBufferContent (matrix_buffer)));
     xmlBufferFree (matrix_buffer);
 }
@@ -292,7 +292,7 @@ typedef struct {
     unsigned int trailing;
 } base64_write_closure_t;
 
-static unsigned char const *base64_table =
+static char const *base64_table =
 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
 static cairo_status_t
@@ -325,7 +325,7 @@ base64_write_func (void *closure, 
 	info->count++;
 	if (info->count >= 18) {
 	    info->count = 0;
-	    xmlBufferCat (info->buffer, "\r\n");
+	    xmlBufferCat (info->buffer, CC2XML ("\r\n"));
 	}
 	dst[0] = base64_table[src[0] >> 2];
 	dst[1] = base64_table[(src[0] & 0x03) << 4 | src[1] >> 4];
@@ -898,9 +898,9 @@ _cairo_svg_surface_fill (void			*abstrac
     
     style = xmlBufferCreate ();
     emit_pattern (surface, source, style, 0);
-    xmlBufferCat (style, " stroke: none;");
-    xmlBufferCat (style, " fill-rule: ");
-    xmlBufferCat (style, fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? "evenodd;" : "nonzero;");
+    xmlBufferCat (style, CC2XML (" stroke: none;"));
+    xmlBufferCat (style, CC2XML (" fill-rule: "));
+    xmlBufferCat (style, fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? CC2XML("evenodd;") : CC2XML ("nonzero;"));
 
     status = _cairo_path_fixed_interpret (path,
 					  CAIRO_DIRECTION_FORWARD,
@@ -957,7 +957,7 @@ emit_paint (xmlNodePtr node,
 
     style = xmlBufferCreate ();
     emit_pattern (surface, source, style, 0);
-    xmlBufferCat (style, " stroke: none;");
+    xmlBufferCat (style, CC2XML (" stroke: none;"));
 
     child = xmlNewChild (node, NULL, CC2XML ("rect"), NULL);
     xmlSetProp (child, CC2XML ("x"), CC2XML ("0"));
@@ -1076,21 +1076,21 @@ _cairo_svg_surface_stroke (void			*abstr
 	xmlBufferCat (style, CC2XML (" stroke-dasharray: "));
 	for (i = 0; i < stroke_style->num_dashes; i++) {
 	    if (i != 0)
-		xmlBufferCat (style, ",");
+		xmlBufferCat (style, CC2XML (","));
 	    /* FIXME: Is is really what we want ? */
 	    rx = ry = stroke_style->dash[i];
 	    cairo_matrix_transform_distance (ctm, &rx, &ry);
 	    _cairo_dtostr (buffer, sizeof buffer, sqrt ((rx * rx + ry * ry) / 2.0));
 	    xmlBufferCat (style, C2XML (buffer));
 	}
-	xmlBufferCat (style, ";");
+	xmlBufferCat (style, CC2XML (";"));
 	if (stroke_style->dash_offset != 0.0) {
 	    xmlBufferCat (style, CC2XML (" stroke-dashoffset: "));
 	    rx = ry = stroke_style->dash_offset;
 	    cairo_matrix_transform_distance (ctm, &rx, &ry);
 	    _cairo_dtostr (buffer, sizeof buffer, sqrt ((rx * rx + ry * ry) / 2.0));
 	    xmlBufferCat (style, C2XML (buffer));
-	    xmlBufferCat (style, ";");
+	    xmlBufferCat (style, CC2XML (";"));
 	}
     }
 
diff-tree 3490ed989672eaf2c08468ba81e3376fa362e41f (from f5566c9b20edf04b44f60bba164c226f2718a935)
Author: Christian Biesinger <cbiesinger at web.de>
Date:   Wed Mar 1 19:16:01 2006 +0100

    Remove trailing comma in enumeration
    
    This fixes a gcc -pedantic warning and compilation with the xlc compiler.

diff --git a/src/cairo-meta-surface-private.h b/src/cairo-meta-surface-private.h
index e571509..eafe3f4 100644
--- a/src/cairo-meta-surface-private.h
+++ b/src/cairo-meta-surface-private.h
@@ -53,7 +53,7 @@ typedef enum {
      * fallbacks should never get triggered). So the plan is to
      * eliminate as many of these as possible. */
 
-    CAIRO_COMMAND_INTERSECT_CLIP_PATH,
+    CAIRO_COMMAND_INTERSECT_CLIP_PATH
 
 } cairo_command_type_t;
 
diff-tree 2fb016c75b950b3b1fe077dc349713f61118fd7c (from parents)
Merge: 8176c93bc481414c1584bf4721ac1680ed827d97 3490ed989672eaf2c08468ba81e3376fa362e41f
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Wed Mar 1 11:26:48 2006 +0100

    Merge branch 'master' of git+ssh://git.cairographics.org/git/cairo

diff-tree 8176c93bc481414c1584bf4721ac1680ed827d97 (from f5566c9b20edf04b44f60bba164c226f2718a935)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Wed Mar 1 11:26:30 2006 +0100

    Revert "Remove ft-font's usage of device offset surface fields for storing bearings"
    
    Bogus fix; misunderstood the relationship between the font bearings
    and the computed device offsets.  Real fix on my device offsets branch.
    
    This reverts 49b4fe10d0acdf6b9776d2908e98f2f0c596fbe5 commit.

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 92b60c7..092838a 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -1021,6 +1021,14 @@ _render_glyph_outline (FT_Face          
 	    return status;
     }
 
+    /*
+     * Note: the font's coordinate system is upside down from ours, so the
+     * Y coordinate of the control box needs to be negated.
+     */
+
+    (*surface)->base.device_x_offset = floor ((double) cbox.xMin / 64.0);
+    (*surface)->base.device_y_offset = floor (-(double) cbox.yMax / 64.0);
+
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -1059,7 +1067,19 @@ _render_glyph_bitmap (FT_Face		      fac
     if (error)
 	return CAIRO_STATUS_NO_MEMORY;
 
-    return _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface);
+    status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface);
+    if (status)
+	return status;
+    
+    /*
+     * Note: the font's coordinate system is upside down from ours, so the
+     * Y coordinate of the control box needs to be negated.
+     */
+
+    (*surface)->base.device_x_offset = glyphslot->bitmap_left;
+    (*surface)->base.device_y_offset = -glyphslot->bitmap_top;
+
+    return status;
 }
 
 #if 0
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index cb0171b..a046904 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -858,7 +858,7 @@ _cairo_scaled_font_show_glyphs (cairo_sc
      * they are implemented in terms of other operators in cairo-gstate.c
      */
     assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR);
-
+    
     if (scaled_font->status)
 	return scaled_font->status;
 
@@ -920,10 +920,10 @@ _cairo_scaled_font_show_glyphs (cairo_sc
 	
 	/* round glyph locations to the nearest pixel */
 	x = (int) floor (glyphs[i].x + 
-                         scaled_glyph->metrics.x_bearing +
+			 glyph_surface->base.device_x_offset +
 			 0.5);
 	y = (int) floor (glyphs[i].y +
-                         scaled_glyph->metrics.y_bearing +
+			 glyph_surface->base.device_y_offset +
 			 0.5);
 	
 	_cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base);
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index a62afed..dc7d394 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2119,8 +2119,8 @@ _cairo_xlib_surface_add_glyph (Display *
      *  sitting around for x and y. 
      */
 
-    glyph_info.x = -(int) floor(scaled_glyph->metrics.x_bearing + 0.5);
-    glyph_info.y = -(int) floor(scaled_glyph->metrics.y_bearing + 0.5);
+    glyph_info.x = -(int) glyph_surface->base.device_x_offset;
+    glyph_info.y = -(int) glyph_surface->base.device_y_offset;
     glyph_info.width = glyph_surface->width;
     glyph_info.height = glyph_surface->height;
     glyph_info.xOff = 0;
diff-tree f5566c9b20edf04b44f60bba164c226f2718a935 (from parents)
Merge: 49b4fe10d0acdf6b9776d2908e98f2f0c596fbe5 d985a9d6696f1ed653a48d95bc401ede3ba86d5f
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Feb 28 16:29:45 2006 +0100

    Merge branch 'master' of git+ssh://git.cairographics.org/git/cairo

diff-tree d985a9d6696f1ed653a48d95bc401ede3ba86d5f (from 566bb18dfee2daaaaf86e7a22e8a7883e81efd97)
Author: Christian Biesinger <cbiesinger at web.de>
Date:   Wed Mar 1 00:40:35 2006 +0100

    Fixing BeOS surface part II

diff --git a/src/cairo-beos-surface.cpp b/src/cairo-beos-surface.cpp
index c952e01..5cd4277 100644
--- a/src/cairo-beos-surface.cpp
+++ b/src/cairo-beos-surface.cpp
@@ -598,7 +598,7 @@ _cairo_beos_composite (cairo_operator_t	
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     // XXX should eventually support the others
-    if (src->type != CAIRO_PATTERN_SURFACE ||
+    if (src->type != CAIRO_PATTERN_TYPE_SURFACE ||
 	src->extend != CAIRO_EXTEND_NONE)
     {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
diff-tree 566bb18dfee2daaaaf86e7a22e8a7883e81efd97 (from a69b3f211654d1f221859f8e7f9608f8030e1ac4)
Author: Christian Biesinger <cbiesinger at web.de>
Date:   Wed Mar 1 00:06:43 2006 +0100

    Updating BeOS surface per the get_type changes

diff --git a/src/cairo-beos-surface.cpp b/src/cairo-beos-surface.cpp
index b6448fa..c952e01 100644
--- a/src/cairo-beos-surface.cpp
+++ b/src/cairo-beos-surface.cpp
@@ -777,6 +777,7 @@ _cairo_beos_surface_get_extents (void   
 }
 
 static const struct _cairo_surface_backend cairo_beos_surface_backend = {
+    CAIRO_SURFACE_TYPE_BEOS,
     NULL, /* create_similar */
     _cairo_beos_surface_finish,
     _cairo_beos_surface_acquire_source_image,
diff-tree a69b3f211654d1f221859f8e7f9608f8030e1ac4 (from 0341305fd2f303a23d10b448ac385a981b8b35fe)
Author: manu <manu at hobbes.localdomain>
Date:   Tue Feb 28 23:44:01 2006 +0100

    s/CAIRO_PATTERN/CAIRO_PATTERN_TYPE/

diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index a5b02c9..2ad2137 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -762,19 +762,19 @@ emit_pattern (cairo_svg_surface_t *surfa
 	      xmlBufferPtr style, int is_stroke)
 {
     switch (pattern->type) {
-    case CAIRO_PATTERN_SOLID:	
+    case CAIRO_PATTERN_TYPE_SOLID:	
 	emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern, style, is_stroke);
 	break;
 
-    case CAIRO_PATTERN_SURFACE:
+    case CAIRO_PATTERN_TYPE_SURFACE:
 	emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, style, is_stroke);
 	break;
 
-    case CAIRO_PATTERN_LINEAR:
+    case CAIRO_PATTERN_TYPE_LINEAR:
 	emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, style, is_stroke);
 	break;
 
-    case CAIRO_PATTERN_RADIAL:
+    case CAIRO_PATTERN_TYPE_RADIAL:
 	emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, style, is_stroke);
 	break;	    
     }
@@ -950,7 +950,7 @@ emit_paint (xmlNodePtr node,
     xmlBufferPtr style;
     char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
 
-    if (source->type == CAIRO_PATTERN_SURFACE)
+    if (source->type == CAIRO_PATTERN_TYPE_SURFACE)
 	return emit_composite_pattern (node, 
 				       (cairo_surface_pattern_t *) source, 
 				       NULL, NULL, FALSE);
diff-tree 0341305fd2f303a23d10b448ac385a981b8b35fe (from ef1c5c3961c2dff1a48606a45a6c9877924e5f15)
Author: manu <manu at hobbes.localdomain>
Date:   Tue Feb 28 23:33:00 2006 +0100

    Revert "Git test"
    
    This reverts ef1c5c3961c2dff1a48606a45a6c9877924e5f15 commit.

diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index e31a40b..a5b02c9 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -36,8 +36,6 @@
  * 	Emmanuel Pacaud <emmanuel.pacaud at univ-poitiers.fr>
  */
 
-/* test line */
-
 #include "cairoint.h"
 #include "cairo-svg.h"
 #include "cairo-path-fixed-private.h"
diff-tree ef1c5c3961c2dff1a48606a45a6c9877924e5f15 (from 6fe93cbf5b368a9a6daf54370aa0e7735b411474)
Author: manu <manu at hobbes.localdomain>
Date:   Tue Feb 28 22:52:45 2006 +0100

    Git test

diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index a5b02c9..e31a40b 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -36,6 +36,8 @@
  * 	Emmanuel Pacaud <emmanuel.pacaud at univ-poitiers.fr>
  */
 
+/* test line */
+
 #include "cairoint.h"
 #include "cairo-svg.h"
 #include "cairo-path-fixed-private.h"
diff-tree 49b4fe10d0acdf6b9776d2908e98f2f0c596fbe5 (from 6fe93cbf5b368a9a6daf54370aa0e7735b411474)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Feb 28 16:21:46 2006 +0100

    Remove ft-font's usage of device offset surface fields for storing bearings
    
    cairo-ft-font was being naughty and storing glyph bearings in the
    surface device_[xy]_offset fields -- this had no effect previously,
    because _cairo_surface_composite ignored those fields, but once it
    starts handling device offsets itself, this causes ft text rendering
    to break.

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 092838a..92b60c7 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -1021,14 +1021,6 @@ _render_glyph_outline (FT_Face          
 	    return status;
     }
 
-    /*
-     * Note: the font's coordinate system is upside down from ours, so the
-     * Y coordinate of the control box needs to be negated.
-     */
-
-    (*surface)->base.device_x_offset = floor ((double) cbox.xMin / 64.0);
-    (*surface)->base.device_y_offset = floor (-(double) cbox.yMax / 64.0);
-
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -1067,19 +1059,7 @@ _render_glyph_bitmap (FT_Face		      fac
     if (error)
 	return CAIRO_STATUS_NO_MEMORY;
 
-    status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface);
-    if (status)
-	return status;
-    
-    /*
-     * Note: the font's coordinate system is upside down from ours, so the
-     * Y coordinate of the control box needs to be negated.
-     */
-
-    (*surface)->base.device_x_offset = glyphslot->bitmap_left;
-    (*surface)->base.device_y_offset = -glyphslot->bitmap_top;
-
-    return status;
+    return _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface);
 }
 
 #if 0
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index a046904..cb0171b 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -858,7 +858,7 @@ _cairo_scaled_font_show_glyphs (cairo_sc
      * they are implemented in terms of other operators in cairo-gstate.c
      */
     assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR);
-    
+
     if (scaled_font->status)
 	return scaled_font->status;
 
@@ -920,10 +920,10 @@ _cairo_scaled_font_show_glyphs (cairo_sc
 	
 	/* round glyph locations to the nearest pixel */
 	x = (int) floor (glyphs[i].x + 
-			 glyph_surface->base.device_x_offset +
+                         scaled_glyph->metrics.x_bearing +
 			 0.5);
 	y = (int) floor (glyphs[i].y +
-			 glyph_surface->base.device_y_offset +
+                         scaled_glyph->metrics.y_bearing +
 			 0.5);
 	
 	_cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base);
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index dc7d394..a62afed 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2119,8 +2119,8 @@ _cairo_xlib_surface_add_glyph (Display *
      *  sitting around for x and y. 
      */
 
-    glyph_info.x = -(int) glyph_surface->base.device_x_offset;
-    glyph_info.y = -(int) glyph_surface->base.device_y_offset;
+    glyph_info.x = -(int) floor(scaled_glyph->metrics.x_bearing + 0.5);
+    glyph_info.y = -(int) floor(scaled_glyph->metrics.y_bearing + 0.5);
     glyph_info.width = glyph_surface->width;
     glyph_info.height = glyph_surface->height;
     glyph_info.xOff = 0;
diff-tree 6fe93cbf5b368a9a6daf54370aa0e7735b411474 (from parents)
Merge: f2245a7932b857ff70dc0476490090d906ae61f8 210dd59a7441424f71658ca248f6657482c74c7e
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Feb 28 02:36:45 2006 -0800

    Merge branch 'get-type' into cairo

diff --cc src/cairo-win32-surface.c
index c7f4555,9dacd1d..5e1e342
@@@ -1082,32 -1029,8 +1082,33 @@@
      return surface->backend == &cairo_win32_surface_backend;
  }
  
 +/**
 + * cairo_win32_surface_get_dc
 + * @surface: a #cairo_surface_t
 + *
 + * Returns the HDC associated with this surface, or NULL if none.
 + * Also returns NULL if the surface is not a win32 surface.
 + *
 + * Return value: HDC or NULL if no HDC available.
 + **/
 +HDC
 +cairo_win32_surface_get_dc (cairo_surface_t *surface)
 +{
 +    cairo_win32_surface_t *winsurf;
 +
 +    if (surface == NULL)
 +	return NULL;
 +
 +    if (!_cairo_surface_is_win32(surface))
 +	return NULL;
 +
 +    winsurf = (cairo_win32_surface_t *) surface;
 +
 +    return winsurf->dc;
 +}
 +
  static const cairo_surface_backend_t cairo_win32_surface_backend = {
+     CAIRO_SURFACE_TYPE_WIN32,
      _cairo_win32_surface_create_similar,
      _cairo_win32_surface_finish,
      _cairo_win32_surface_acquire_source_image,
diff-tree 210dd59a7441424f71658ca248f6657482c74c7e (from bd2136a23f8a3d5f6a1306d18499fdcfc1e87f48)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Feb 28 02:30:27 2006 -0800

    Add some basic testing of cairo_font_face_get_type and
    cairo_scaled_font_get_type.

diff --git a/test/.gitignore b/test/.gitignore
index 30554c8..65741ca 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -24,6 +24,7 @@ fill-and-stroke
 fill-rule
 filter-nearest-offset
 ft-font-create-for-ft-face
+font-face-get-type
 get-and-set
 gradient-alpha
 imagediff
diff --git a/test/Makefile.am b/test/Makefile.am
index 0d86636..8a67fc5 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -20,6 +20,7 @@ extend-reflect			\
 fill-and-stroke			\
 fill-rule			\
 filter-nearest-offset		\
+font-face-get-type		\
 get-and-set			\
 gradient-alpha			\
 leaky-polygon			\
@@ -300,6 +301,7 @@ dash_offset_negative_LDADD = $(LDADDS)
 extend_reflect_LDADD = $(LDADDS)
 fill_and_stroke_LDADD = $(LDADDS)
 fill_rule_LDADD = $(LDADDS)
+font_face_get_type_LDADD = $(LDADDS)
 filter_nearest_offset_LDADD = $(LDADDS)
 ft_font_create_for_ft_face_LDADD = $(LDADDS)
 get_and_set_LDADD = $(LDADDS)
diff --git a/test/font-face-get-type.c b/test/font-face-get-type.c
new file mode 100644
index 0000000..c21d5c2
--- /dev/null
+++ b/test/font-face-get-type.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2006 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl D. Worth <cworth at cworth.org>
+ */
+
+#include "cairo-test.h"
+
+int
+main (void)
+{
+    cairo_surface_t *surface;
+    cairo_t *cr;
+    cairo_font_face_t *font_face;
+
+    cairo_test_init ("font-face-get-type");
+
+    cairo_test_log ("Creating cairo context and obtaining a font face\n");
+
+    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
+    cr = cairo_create (surface);
+
+    cairo_select_font_face (cr, "Bitstream Vera Sans",
+			    CAIRO_FONT_SLANT_NORMAL,
+			    CAIRO_FONT_WEIGHT_NORMAL);
+
+    font_face = cairo_get_font_face (cr);
+
+    cairo_test_log ("Testing return value of cairo_font_face_get_type\n");
+
+    if (cairo_font_face_get_type (font_face) != CAIRO_FONT_TYPE_TOY) {
+	cairo_test_log ("Unexpected value %d from cairo_font_face_get_type (expected %d)\n",
+			cairo_font_face_get_type (font_face), CAIRO_FONT_TYPE_TOY);
+	return CAIRO_TEST_FAILURE;
+    }
+
+    cairo_destroy (cr);
+    cairo_surface_destroy (surface);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+
+
+    
diff --git a/test/ft-font-create-for-ft-face.c b/test/ft-font-create-for-ft-face.c
index bf668b9..0bb3b8c 100644
--- a/test/ft-font-create-for-ft-face.c
+++ b/test/ft-font-create-for-ft-face.c
@@ -64,6 +64,13 @@ draw (cairo_t *cr, int width, int height
 
     font_face = cairo_ft_font_face_create_for_pattern (resolved);
 
+    if (cairo_font_face_get_type (font_face) != CAIRO_FONT_TYPE_FT) {
+	cairo_test_log ("Unexpected value from cairo_font_face_get_type: %d (expected %d)\n",
+			cairo_font_face_get_type (font_face), CAIRO_FONT_TYPE_FT);
+	cairo_font_face_destroy (font_face);
+	return CAIRO_TEST_FAILURE;
+    }
+
     cairo_matrix_init_identity (&font_matrix);
 
     cairo_get_matrix (cr, &ctm);
@@ -82,6 +89,13 @@ draw (cairo_t *cr, int width, int height
     FcPatternDestroy (pattern);
     FcPatternDestroy (resolved);
 
+    if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_FT) {
+	cairo_test_log ("Unexpected value from cairo_scaled_font_get_type: %d (expected %d)\n",
+			cairo_scaled_font_get_type (scaled_font), CAIRO_FONT_TYPE_FT);
+	cairo_scaled_font_destroy (scaled_font);
+	return CAIRO_TEST_FAILURE;
+    }
+
     if (!ft_face) {
 	cairo_test_log ("Failed to get an ft_face with cairo_ft_scaled_font_lock_face\n");
 	cairo_scaled_font_destroy (scaled_font);
diff-tree bd2136a23f8a3d5f6a1306d18499fdcfc1e87f48 (from f9534c856a71b0f56a1e5bc58141b7bc192a27e8)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Feb 28 01:31:15 2006 -0800

    Correct copyright date

diff --git a/test/pattern-get-type.c b/test/pattern-get-type.c
index 0e8fe25..a6aba03 100644
--- a/test/pattern-get-type.c
+++ b/test/pattern-get-type.c
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2005 Red Hat, Inc.
+ * Copyright © 2006 Red Hat, Inc.
  *
  * Permission to use, copy, modify, distribute, and sell this software
  * and its documentation for any purpose is hereby granted without
diff-tree f9534c856a71b0f56a1e5bc58141b7bc192a27e8 (from 1dd6e417c10c90894c87565d4f7fa3f63e97f212)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Feb 28 01:30:58 2006 -0800

    test/pattern-get-type: Add new test case for cairo_pattern_get_type.

diff --git a/test/.gitignore b/test/.gitignore
index 5173349..30554c8 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -43,6 +43,7 @@ operator-source
 paint
 paint-with-alpha
 path-data
+pattern-get-type
 pdf2png
 png-flatten
 svg2png
diff --git a/test/Makefile.am b/test/Makefile.am
index 0da8b5a..0d86636 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -35,6 +35,7 @@ operator-source			\
 paint				\
 paint-with-alpha		\
 path-data			\
+pattern-get-type		\
 pixman-rotate			\
 rectangle-rounding-error	\
 scale-source-surface-paint	\
@@ -317,6 +318,7 @@ operator_source_LDADD = $(LDADDS)
 paint_LDADD = $(LDADDS)
 paint_with_alpha_LDADD = $(LDADDS)
 path_data_LDADD = $(LDADDS)
+pattern_get_type_LDADD = $(LDADDS)
 svg_surface_LDADD = $(LDADDS)
 svg_clip_LDADD = $(LDADDS)
 pixman_rotate_LDADD = $(LDADDS)
diff --git a/test/pattern-get-type.c b/test/pattern-get-type.c
new file mode 100644
index 0000000..0e8fe25
--- /dev/null
+++ b/test/pattern-get-type.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl D. Worth <cworth at cworth.org>
+ */
+
+#include "cairo-test.h"
+
+int
+main (void)
+{
+    cairo_surface_t *surface;
+    cairo_pattern_t *solid_rgb, *solid_rgba, *surface_pattern, *linear, *radial;
+
+    cairo_test_init ("pattern-get-type");
+
+    cairo_test_log ("Creating patterns of all types\n");
+
+    solid_rgb = cairo_pattern_create_rgb (0.0, 0.1, 0.2);
+    solid_rgba = cairo_pattern_create_rgba (0.3, 0.4, 0.5, 0.6);
+    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+					  1, 1);
+    surface_pattern = cairo_pattern_create_for_surface (surface);
+    linear = cairo_pattern_create_linear (0.0, 0.0, 10.0, 10.0);
+    radial = cairo_pattern_create_radial (10.0, 10.0, 0.1,
+					  10.0, 10.0, 1.0);
+
+    cairo_test_log ("Verifying return values of cairo_pattern_get_type\n");
+
+    if (cairo_pattern_get_type (solid_rgb) != CAIRO_PATTERN_TYPE_SOLID)
+	return CAIRO_TEST_FAILURE;
+
+    if (cairo_pattern_get_type (solid_rgba) != CAIRO_PATTERN_TYPE_SOLID)
+	return CAIRO_TEST_FAILURE;
+
+    if (cairo_pattern_get_type (surface_pattern) != CAIRO_PATTERN_TYPE_SURFACE)
+	return CAIRO_TEST_FAILURE;
+
+    if (cairo_pattern_get_type (linear) != CAIRO_PATTERN_TYPE_LINEAR)
+	return CAIRO_TEST_FAILURE;
+
+    if (cairo_pattern_get_type (radial) != CAIRO_PATTERN_TYPE_RADIAL)
+	return CAIRO_TEST_FAILURE;
+
+    cairo_test_log ("Cleaning up\n");
+
+    cairo_pattern_destroy (solid_rgb);
+    cairo_pattern_destroy (solid_rgba);
+    cairo_pattern_destroy (surface_pattern);
+    cairo_surface_destroy (surface);
+    cairo_pattern_destroy (linear);
+    cairo_pattern_destroy (radial);
+
+    return CAIRO_TEST_SUCCESS;
+}
diff-tree 1dd6e417c10c90894c87565d4f7fa3f63e97f212 (from cd84e2ab32fe4648f9d172cdefe08798336938d2)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Feb 28 00:55:27 2006 -0800

    Add testing for cairo_surface_get_type.
    
    All test targets now list an expected cairo_surface_type_t. Add notes
    on current limitations of PDF/PS/meta-surface support that causes
    CAIRO_CONTENT_COLOR similar surfaces of PDF and PS surfaces to be
    returned as image surfaces.
    
    Add cairo_internal_surface_type_t for the meta, paginated, and various
    test surfaces.

diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index 4bb8572..acfe44a 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -97,6 +97,24 @@ const cairo_private cairo_surface_backen
 static cairo_int_status_t
 _cairo_paginated_surface_show_page (void *abstract_surface);
 
+/* XXX: This would seem the natural thing to do here. But currently,
+ * PDF and PS surfaces do not yet work as source surfaces. So instead,
+ * we don't implement create_similar for the paginate_surface which
+ * means that any create_similar() call on a paginated_surfacae will
+ * result in a new image surface. */
+#if 0
+static cairo_surface_t *
+_cairo_paginated_surface_create_similar (void			*abstract_surface,
+					 cairo_content_t	 content,
+					 int			 width,
+					 int			 height)
+{
+    cairo_paginated_surface_t *surface = abstract_surface;
+    return cairo_surface_create_similar (surface->target, content,
+					 width, height);
+}
+#endif
+
 cairo_surface_t *
 _cairo_paginated_surface_create (cairo_surface_t	*target,
 				 cairo_content_t	 content,
@@ -386,7 +404,7 @@ _cairo_paginated_surface_snapshot (void 
 
 const cairo_surface_backend_t cairo_paginated_surface_backend = {
     CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
-    NULL, /* create_similar */
+    NULL, /* create_similar --- see note for _cairo_paginated_surface_create_similar */
     _cairo_paginated_surface_finish,
     _cairo_paginated_surface_acquire_source_image,
     _cairo_paginated_surface_release_source_image,
diff --git a/src/cairoint.h b/src/cairoint.h
index 1246123..8db52ae 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -258,7 +258,10 @@ typedef enum cairo_int_status {
 
 typedef enum cairo_internal_surface_type {
     CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000,
-    CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED
+    CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
+    CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
+    CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+    CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
 } cairo_internal_surface_type_t;
 
 typedef enum cairo_direction {
@@ -2157,7 +2160,6 @@ cairo_private int
 _cairo_dtostr (char *buffer, size_t size, double d);
 
 /* Avoid unnecessary PLT entries.  */
-
 slim_hidden_proto(cairo_get_current_point)
 slim_hidden_proto(cairo_fill_preserve)
 slim_hidden_proto(cairo_clip_preserve)
diff --git a/src/test-fallback-surface.c b/src/test-fallback-surface.c
index fe0cc6f..cb8fd92 100644
--- a/src/test-fallback-surface.c
+++ b/src/test-fallback-surface.c
@@ -175,6 +175,7 @@ _test_fallback_surface_get_extents (void
 }
 
 const cairo_surface_backend_t test_fallback_surface_backend = {
+    CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
     _test_fallback_surface_create_similar,
     _test_fallback_surface_finish,
     _test_fallback_surface_acquire_source_image,
diff --git a/src/test-meta-surface.c b/src/test-meta-surface.c
index bdabf31..6d36fca 100644
--- a/src/test-meta-surface.c
+++ b/src/test-meta-surface.c
@@ -296,6 +296,7 @@ _test_meta_surface_snapshot (void *abstr
 }
 
 const cairo_surface_backend_t test_meta_surface_backend = {
+    CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
     NULL, /* create_similar */
     _test_meta_surface_finish,
     _test_meta_surface_acquire_source_image,
diff --git a/test/cairo-test.c b/test/cairo-test.c
index 557ccb6..d782a92 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -47,6 +47,20 @@
 #include "write-png.h"
 #include "xmalloc.h"
 
+/* This is copied from cairoint.h. That makes it painful to keep in
+ * sync, but the slim stuff makes cairoint.h "hard" to include when
+ * not actually building the cairo library itself. Fortunately, since
+ * we're checking all these values, we do have a safeguard for keeping
+ * them in sync.
+ */
+typedef enum cairo_internal_surface_type {
+    CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000,
+    CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
+    CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
+    CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+    CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
+} cairo_internal_surface_type_t;
+
 #ifdef _MSC_VER
 #define vsnprintf _vsnprintf
 #define access _access
@@ -163,6 +177,7 @@ typedef void
 typedef struct _cairo_test_target
 {
     const char		       	       *name;
+    cairo_surface_type_t		expected_type;
     cairo_content_t			content;
     cairo_test_create_target_surface_t	create_target_surface;
     cairo_test_write_to_png_t		write_to_png;
@@ -1387,6 +1402,13 @@ cairo_test_for_target (cairo_test_t *tes
 	goto UNWIND_STRINGS;
     }
 
+    if (cairo_surface_get_type (surface) != target->expected_type) {
+	cairo_test_log ("Error: Created surface is of type %d (expected %d)\n",
+			cairo_surface_get_type (surface), target->expected_type);
+	ret = CAIRO_TEST_FAILURE;
+	goto UNWIND_SURFACE;
+    }
+
     cr = cairo_create (surface);
 
     /* Clear to transparent (or black) depending on whether the target
@@ -1436,6 +1458,7 @@ cairo_test_for_target (cairo_test_t *tes
 
 UNWIND_CAIRO:
     cairo_destroy (cr);
+UNWIND_SURFACE:
     cairo_surface_destroy (surface);
 
     cairo_debug_reset_static_data ();
@@ -1461,102 +1484,128 @@ cairo_test_expecting (cairo_test_t *test
     cairo_test_target_t **targets_to_test;
     cairo_test_target_t targets[] = 
 	{
-	    { "image", CAIRO_CONTENT_COLOR_ALPHA,
+	    { "image", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR_ALPHA,
 	      create_image_surface, cairo_surface_write_to_png, NULL},
-	    { "image", CAIRO_CONTENT_COLOR,
+	    { "image", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR,
 	      create_image_surface, cairo_surface_write_to_png, NULL},
 #ifdef CAIRO_HAS_TEST_SURFACES
-	    { "test-fallback", CAIRO_CONTENT_COLOR_ALPHA,
+	    { "test-fallback", CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+	      CAIRO_CONTENT_COLOR_ALPHA,
 	      create_test_fallback_surface, cairo_surface_write_to_png, NULL },
-	    { "test-fallback", CAIRO_CONTENT_COLOR,
+	    { "test-fallback", CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+	      CAIRO_CONTENT_COLOR,
 	      create_test_fallback_surface, cairo_surface_write_to_png, NULL },
-	    { "test-meta", CAIRO_CONTENT_COLOR_ALPHA,
+	    { "test-meta", CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
+	      CAIRO_CONTENT_COLOR_ALPHA,
 	      create_test_meta_surface, cairo_surface_write_to_png, NULL },
-	    { "test-meta", CAIRO_CONTENT_COLOR,
+	    { "test-meta", CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
+	      CAIRO_CONTENT_COLOR,
 	      create_test_meta_surface, cairo_surface_write_to_png, NULL },
-	    { "test-paginated", CAIRO_CONTENT_COLOR_ALPHA,
+	    { "test-paginated", CAIRO_SURFACE_TYPE_IMAGE,
+	      CAIRO_CONTENT_COLOR_ALPHA,
 	      create_test_paginated_surface,
 	      test_paginated_write_to_png,
 	      cleanup_test_paginated },
-	    { "test-paginated", CAIRO_CONTENT_COLOR,
+	    { "test-paginated", CAIRO_SURFACE_TYPE_IMAGE,
+	      CAIRO_CONTENT_COLOR,
 	      create_test_paginated_surface,
 	      test_paginated_write_to_png,
 	      cleanup_test_paginated },
 #endif
 #ifdef CAIRO_HAS_GLITZ_SURFACE
 #if CAIRO_CAN_TEST_GLITZ_GLX_SURFACE
-	    { "glitz-glx", CAIRO_CONTENT_COLOR_ALPHA,
+	    { "glitz-glx", CAIRO_SURFACE_TYPE_GLITZ,CAIRO_CONTENT_COLOR_ALPHA,
 		create_cairo_glitz_glx_surface, cairo_surface_write_to_png,
 		cleanup_cairo_glitz_glx }, 
-	    { "glitz-glx", CAIRO_CONTENT_COLOR,
+	    { "glitz-glx", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR,
 		create_cairo_glitz_glx_surface, cairo_surface_write_to_png,
 		cleanup_cairo_glitz_glx }, 
 #endif
 #if CAIRO_CAN_TEST_GLITZ_AGL_SURFACE
-	    { "glitz-agl", CAIRO_CONTENT_COLOR_ALPHA,
+	    { "glitz-agl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA,
 		create_cairo_glitz_agl_surface, cairo_surface_write_to_png,
 		cleanup_cairo_glitz_agl }, 
-	    { "glitz-agl", CAIRO_CONTENT_COLOR,
+	    { "glitz-agl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR,
 		create_cairo_glitz_agl_surface, cairo_surface_write_to_png,
 		cleanup_cairo_glitz_agl }, 
 #endif
 #if CAIRO_CAN_TEST_GLITZ_WGL_SURFACE
-	    { "glitz-wgl", CAIRO_CONTENT_COLOR_ALPHA,
+	    { "glitz-wgl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA,
 		create_cairo_glitz_wgl_surface, cairo_surface_write_to_png,
 		cleanup_cairo_glitz_wgl }, 
-	    { "glitz-wgl", CAIRO_CONTENT_COLOR,
+	    { "glitz-wgl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR,
 		create_cairo_glitz_wgl_surface, cairo_surface_write_to_png,
 		cleanup_cairo_glitz_wgl }, 
 #endif
 #endif /* CAIRO_HAS_GLITZ_SURFACE */
 #if 0 && CAIRO_HAS_QUARTZ_SURFACE
-	    { "quartz", CAIRO_CONTENT_COLOR,
+	    { "quartz", CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_CONTENT_COLOR,
 		create_quartz_surface, cairo_surface_write_to_png,
 		cleanup_quartz },
 #endif
 #if CAIRO_HAS_WIN32_SURFACE
-	    { "win32", CAIRO_CONTENT_COLOR,
+	    { "win32", CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR,
 		create_win32_surface, cairo_surface_write_to_png, cleanup_win32 },
 #endif
 #if CAIRO_HAS_XCB_SURFACE
-	    { "xcb", CAIRO_CONTENT_COLOR_ALPHA,
+	    { "xcb", CAIRO_SURFACE_TYPE_XCB, CAIRO_CONTENT_COLOR_ALPHA,
 		create_xcb_surface, cairo_surface_write_to_png, cleanup_xcb},
 #endif
 #if CAIRO_HAS_XLIB_SURFACE
-	    { "xlib", CAIRO_CONTENT_COLOR_ALPHA,
+	    { "xlib", CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR_ALPHA,
 		create_xlib_surface, cairo_surface_write_to_png, cleanup_xlib},
-	    { "xlib", CAIRO_CONTENT_COLOR,
+	    { "xlib", CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR,
 		create_xlib_surface, cairo_surface_write_to_png, cleanup_xlib},
 #endif
 #if CAIRO_HAS_PS_SURFACE
-	    { "ps", CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED,
+	    { "ps", CAIRO_SURFACE_TYPE_PS,
+	        CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED,
 		create_ps_surface, ps_surface_write_to_png, cleanup_ps },
-	    { "ps", CAIRO_CONTENT_COLOR,
+
+	    /* XXX: We expect type image here only due to a limitation in
+	     * the current PS/meta-surface code. A PS surface is
+	     * "naturally" COLOR_ALPHA, so the COLOR-only variant goes
+	     * through create_similar in create_ps_surface which results
+	     * in the similar surface being used as a source. We do not yet
+	     * have source support for PS/meta-surfaces, so the
+	     * create_similar path for all paginated surfaces currently
+	     * returns an image surface.*/
+	    { "ps", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR,
 		create_ps_surface, ps_surface_write_to_png, cleanup_ps },
 #endif
 #if CAIRO_HAS_PDF_SURFACE && CAIRO_CAN_TEST_PDF_SURFACE
-	    { "pdf", CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED,
+	    { "pdf", CAIRO_SURFACE_TYPE_PDF,
+	        CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED,
 		create_pdf_surface, pdf_surface_write_to_png, cleanup_pdf },
-	    { "pdf", CAIRO_CONTENT_COLOR,
+
+	    /* XXX: We expect type image here only due to a limitation in
+	     * the current PDF/meta-surface code. A PDF surface is
+	     * "naturally" COLOR_ALPHA, so the COLOR-only variant goes
+	     * through create_similar in create_pdf_surface which results
+	     * in the similar surface being used as a source. We do not yet
+	     * have source support for PDF/meta-surfaces, so the
+	     * create_similar path for all paginated surfaces currently
+	     * returns an image surface.*/
+	    { "pdf", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR,
 		create_pdf_surface, pdf_surface_write_to_png, cleanup_pdf },
 #endif
 #if CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE
-	    { "svg", CAIRO_CONTENT_COLOR_ALPHA,
+	    { "svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA,
 		    create_svg_surface, svg_surface_write_to_png, cleanup_svg },
 #endif
 #if CAIRO_HAS_BEOS_SURFACE
-	    { "beos", CAIRO_CONTENT_COLOR,
+	    { "beos", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR,
 		create_beos_surface, cairo_surface_write_to_png, cleanup_beos},
-	    { "beos_bitmap", CAIRO_CONTENT_COLOR,
+	    { "beos_bitmap", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR,
 		create_beos_bitmap_surface, cairo_surface_write_to_png, cleanup_beos_bitmap},
-	    { "beos_bitmap", CAIRO_CONTENT_COLOR_ALPHA,
+	    { "beos_bitmap", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR_ALPHA,
 		create_beos_bitmap_surface, cairo_surface_write_to_png, cleanup_beos_bitmap},
 #endif
 
 #if CAIRO_HAS_DIRECTFB_SURFACE
-	    { "directfb", CAIRO_CONTENT_COLOR,
+	    { "directfb", CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR,
 		create_directfb_surface, cairo_surface_write_to_png, cleanup_directfb},
-	    { "directfb_bitmap", CAIRO_CONTENT_COLOR_ALPHA,
+	    { "directfb_bitmap", CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR_ALPHA,
 		create_directfb_bitmap_surface, cairo_surface_write_to_png,cleanup_directfb},
 #endif
 	};
diff-tree cd84e2ab32fe4648f9d172cdefe08798336938d2 (from 5797f814852bb4f6ef559890640b8cd24ec5fa45)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Feb 27 23:15:45 2006 -0800

    Add documentation for cairo_font_face_get_type,
    cairo_scaled_font_get_type, cairo_surface_get_type, and
    cairo_pattern_get_type.

diff --git a/src/cairo-font.c b/src/cairo-font.c
index bb184c4..6512480 100644
--- a/src/cairo-font.c
+++ b/src/cairo-font.c
@@ -130,6 +130,12 @@ cairo_font_face_destroy (cairo_font_face
     free (font_face);
 }
 
+/**
+ * cairo_font_face_get_type:
+ * @font_face: a #cairo_font_face_t
+ * 
+ * Return value: The type of @font_face. See #cairo_font_type_t.
+ **/
 cairo_font_type_t
 cairo_font_face_get_type (cairo_font_face_t *font_face)
 {
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index a9628a3..8aa2969 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -524,6 +524,12 @@ cairo_pattern_reference (cairo_pattern_t
     return pattern;
 }
 
+/**
+ * cairo_pattern_get_type:
+ * @pattern: a #cairo_pattern_t
+ * 
+ * Return value: The type of @pattern. See #cairo_pattern_type_t.
+ **/
 cairo_pattern_type_t
 cairo_pattern_get_type (cairo_pattern_t *pattern)
 {
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 46e1cac..a046904 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -118,6 +118,12 @@ _cairo_scaled_font_set_error (cairo_scal
     _cairo_error (status);
 }
 
+/**
+ * cairo_scaled_font_get_type:
+ * @scaled_font: a #cairo_scaled_font_t
+ * 
+ * Return value: The type of @scaled_font. See #cairo_font_type_t.
+ **/
 cairo_font_type_t
 cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font)
 {
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index a317e5b..b1a36df 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -121,6 +121,12 @@ _cairo_surface_set_error (cairo_surface_
     _cairo_error (status);
 }
 
+/**
+ * cairo_surface_get_type:
+ * @surface: a #cairo_surface_t
+ * 
+ * Return value: The type of @surface. See #cairo_surface_type_t.
+ **/
 cairo_surface_type_t
 cairo_surface_get_type (cairo_surface_t *surface)
 {
diff-tree 5797f814852bb4f6ef559890640b8cd24ec5fa45 (from 5ae0b9f912b7f5fd1700cbf18763a05493f55b62)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Feb 27 23:12:43 2006 -0800

    Implement cairo_pattern_get_type

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 27ede9a..a9628a3 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -524,6 +524,12 @@ cairo_pattern_reference (cairo_pattern_t
     return pattern;
 }
 
+cairo_pattern_type_t
+cairo_pattern_get_type (cairo_pattern_t *pattern)
+{
+    return pattern->type;
+}
+
 /**
  * cairo_pattern_status:
  * @pattern: a #cairo_pattern_t
diff-tree 5ae0b9f912b7f5fd1700cbf18763a05493f55b62 (from 1769830e6eea08744830c1c7ea9220d56808831a)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Feb 27 23:11:32 2006 -0800

    Implement cairo_surface_get_type

diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index be17915..a02e56b 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -662,6 +662,7 @@ _cairo_directfb_surface_scaled_glyph_fin
 
 
 static const cairo_surface_backend_t cairo_directfb_surface_backend = {
+		CAIRO_SURFACE_TYPE_DIRECTFB,    
 		_cairo_directfb_surface_create_similar,
 		_cairo_directfb_surface_finish,
 		_cairo_directfb_surface_acquire_source_image,
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index b625472..667e231 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -2121,6 +2121,7 @@ _cairo_glitz_surface_flush (void *abstra
 }
 
 static const cairo_surface_backend_t cairo_glitz_surface_backend = {
+    CAIRO_SURFACE_TYPE_GLITZ,
     _cairo_glitz_surface_create_similar,
     _cairo_glitz_surface_finish,
     _cairo_glitz_surface_acquire_source_image,
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 108e89b..0621946 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -903,6 +903,7 @@ _cairo_surface_is_image (const cairo_sur
 }
 
 const cairo_surface_backend_t cairo_image_surface_backend = {
+    CAIRO_SURFACE_TYPE_IMAGE,
     _cairo_image_surface_create_similar,
     _cairo_image_surface_finish,
     _cairo_image_surface_acquire_source_image,
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 6f82463..f7aeb71 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -557,6 +557,7 @@ _cairo_surface_is_meta (const cairo_surf
 }
 
 static const cairo_surface_backend_t cairo_meta_surface_backend = {
+    CAIRO_INTERNAL_SURFACE_TYPE_META,
     _cairo_meta_surface_create_similar,
     _cairo_meta_surface_finish,
     _cairo_meta_surface_acquire_source_image,
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index 6317d70..4bb8572 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -111,6 +111,10 @@ _cairo_paginated_surface_create (cairo_s
 
     _cairo_surface_init (&surface->base, &cairo_paginated_surface_backend);
 
+    /* Override surface->base.type with target's type so we don't leak
+     * evidence of the paginated wrapper out to the user. */
+    surface->base.type = cairo_surface_get_type (target);
+
     surface->content = content;
     surface->width = width;
     surface->height = height;
@@ -381,6 +385,7 @@ _cairo_paginated_surface_snapshot (void 
 }
 
 const cairo_surface_backend_t cairo_paginated_surface_backend = {
+    CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
     NULL, /* create_similar */
     _cairo_paginated_surface_finish,
     _cairo_paginated_surface_acquire_source_image,
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 289eeb9..cb8287b 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1657,6 +1657,7 @@ _cairo_pdf_surface_get_font_options (voi
 }
 
 static const cairo_surface_backend_t cairo_pdf_surface_backend = {
+    CAIRO_SURFACE_TYPE_PDF,
     _cairo_pdf_surface_create_similar,
     _cairo_pdf_surface_finish,
     NULL, /* acquire_source_image */
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 371290c..6028b6d 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1322,6 +1322,7 @@ _cairo_ps_surface_fill (void			*abstract
 }
 
 static const cairo_surface_backend_t cairo_ps_surface_backend = {
+    CAIRO_SURFACE_TYPE_PS,
     NULL, /* create_similar */
     _cairo_ps_surface_finish,
     NULL, /* acquire_source_image */
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 52aeafe..a317e5b 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -43,6 +43,7 @@
 
 const cairo_surface_t _cairo_surface_nil = {
     &cairo_image_surface_backend,	/* backend */
+    CAIRO_SURFACE_TYPE_IMAGE,
     -1,					/* ref_count */
     CAIRO_STATUS_NO_MEMORY,		/* status */
     FALSE,				/* finished */
@@ -59,6 +60,7 @@ const cairo_surface_t _cairo_surface_nil
 
 const cairo_surface_t _cairo_surface_nil_file_not_found = {
     &cairo_image_surface_backend,	/* backend */
+    CAIRO_SURFACE_TYPE_IMAGE,
     -1,					/* ref_count */
     CAIRO_STATUS_FILE_NOT_FOUND,	/* status */
     FALSE,				/* finished */
@@ -75,6 +77,7 @@ const cairo_surface_t _cairo_surface_nil
 
 const cairo_surface_t _cairo_surface_nil_read_error = {
     &cairo_image_surface_backend,	/* backend */
+    CAIRO_SURFACE_TYPE_IMAGE,
     -1,					/* ref_count */
     CAIRO_STATUS_READ_ERROR,		/* status */
     FALSE,				/* finished */
@@ -118,6 +121,16 @@ _cairo_surface_set_error (cairo_surface_
     _cairo_error (status);
 }
 
+cairo_surface_type_t
+cairo_surface_get_type (cairo_surface_t *surface)
+{
+    /* We don't use surface->backend->type here so that some of the
+     * special "wrapper" surfaces such as cairo_paginated_surface_t
+     * can override surface->type with the type of the "child"
+     * surface. */
+    return surface->type;
+}
+
 /**
  * cairo_surface_status:
  * @surface: a #cairo_surface_t
@@ -141,6 +154,8 @@ _cairo_surface_init (cairo_surface_t			*
 		     const cairo_surface_backend_t	*backend)
 {
     surface->backend = backend;
+    
+    surface->type = backend->type;
 
     surface->ref_count = 1;
     surface->status = CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 5a2c92f..a5b02c9 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -1221,6 +1221,7 @@ _cairo_svg_surface_get_font_options (voi
 
 
 static const cairo_surface_backend_t cairo_svg_surface_backend = {
+	CAIRO_SURFACE_TYPE_SVG,
 	_cairo_svg_surface_create_similar,
 	_cairo_svg_surface_finish,
 	NULL, /* acquire_source_image */
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index b1811a1..9dacd1d 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -1030,6 +1030,7 @@ _cairo_surface_is_win32 (cairo_surface_t
 }
 
 static const cairo_surface_backend_t cairo_win32_surface_backend = {
+    CAIRO_SURFACE_TYPE_WIN32,
     _cairo_win32_surface_create_similar,
     _cairo_win32_surface_finish,
     _cairo_win32_surface_acquire_source_image,
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index faa207c..78eafc0 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -1025,6 +1025,7 @@ _cairo_xcb_surface_get_extents (void		  
 }
 
 static const cairo_surface_backend_t cairo_xcb_surface_backend = {
+    CAIRO_SURFACE_TYPE_XCB,
     _cairo_xcb_surface_create_similar,
     _cairo_xcb_surface_finish,
     _cairo_xcb_surface_acquire_source_image,
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 1ce7e89..dc7d394 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1675,6 +1675,7 @@ _cairo_xlib_surface_scaled_glyph_fini (c
 				       cairo_scaled_font_t  *scaled_font);
 
 static const cairo_surface_backend_t cairo_xlib_surface_backend = {
+    CAIRO_SURFACE_TYPE_XLIB,
     _cairo_xlib_surface_create_similar,
     _cairo_xlib_surface_finish,
     _cairo_xlib_surface_acquire_source_image,
diff --git a/src/cairoint.h b/src/cairoint.h
index a1978a9..1246123 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -256,6 +256,11 @@ typedef enum cairo_int_status {
     CAIRO_INT_STATUS_CACHE_EMPTY
 } cairo_int_status_t;
 
+typedef enum cairo_internal_surface_type {
+    CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000,
+    CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED
+} cairo_internal_surface_type_t;
+
 typedef enum cairo_direction {
     CAIRO_DIRECTION_FORWARD,
     CAIRO_DIRECTION_REVERSE
@@ -604,6 +609,8 @@ typedef struct _cairo_stroke_style {
 } cairo_stroke_style_t;
 
 struct _cairo_surface_backend {
+    cairo_surface_type_t type;
+
     cairo_surface_t *
     (*create_similar)		(void			*surface,
 				 cairo_content_t	 content,
@@ -834,6 +841,11 @@ typedef struct _cairo_format_masks {
 struct _cairo_surface {
     const cairo_surface_backend_t *backend;
 
+    /* We allow surfaces to override the backend->type by shoving something
+     * else into surface->type. This is for "wrapper" surfaces that want to
+     * hide their internal type from the user-level API. */
+    cairo_surface_type_t type;
+
     unsigned int ref_count;
     cairo_status_t status;
     cairo_bool_t finished;
diff-tree 1769830e6eea08744830c1c7ea9220d56808831a (from 5a3c30eafe0b77f69434e139a2e247c8eb4230d7)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Feb 27 17:22:45 2006 -0800

    Implement cairo_scaled_font_get_type

diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index 572359f..9c55851 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -664,6 +664,7 @@ _cairo_atsui_font_old_show_glyphs (void	
 }
 
 const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = {
+    CAIRO_FONT_TYPE_ATSUI,
     _cairo_atsui_font_create_toy,
     _cairo_atsui_font_fini,
     _cairo_atsui_font_scaled_glyph_init,
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index e159826..092838a 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -1901,6 +1901,7 @@ _cairo_ft_show_glyphs (void		       *abs
 }
 
 const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
+    CAIRO_FONT_TYPE_FT,
     _cairo_ft_scaled_font_create_toy,
     _cairo_ft_scaled_font_fini,
     _cairo_ft_scaled_glyph_init,
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 8ebbf45..46e1cac 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -118,6 +118,12 @@ _cairo_scaled_font_set_error (cairo_scal
     _cairo_error (status);
 }
 
+cairo_font_type_t
+cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font)
+{
+    return scaled_font->backend->type;
+}
+
 /**
  * cairo_scaled_font_status:
  * @scaled_font: a #cairo_scaled_font_t
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index ca8e4a6..a3289fc 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -1355,6 +1355,7 @@ CLEANUP_FONT:
 }
 
 const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend = {
+    CAIRO_FONT_TYPE_WIN32,
     _cairo_win32_scaled_font_create_toy,
     _cairo_win32_scaled_font_fini,
     _cairo_win32_scaled_font_glyph_init,
diff --git a/src/cairoint.h b/src/cairoint.h
index 401114c..a1978a9 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -509,6 +509,8 @@ typedef enum _cairo_scaled_glyph_info {
 } cairo_scaled_glyph_info_t;
 
 struct _cairo_scaled_font_backend {
+    cairo_font_type_t type;
+
     cairo_status_t
     (*create_toy)  (cairo_toy_font_face_t	*toy_face,
 		    const cairo_matrix_t	*font_matrix,
diff-tree f2245a7932b857ff70dc0476490090d906ae61f8 (from 1a1441912604c89e2912ec764fe26b7a9db995a3)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Feb 27 17:07:22 2006 -0800

    Remove unused RCS $Id:$ tags.

diff --git a/src/cairo-wideint.c b/src/cairo-wideint.c
index 9e4914e..89df00b 100644
--- a/src/cairo-wideint.c
+++ b/src/cairo-wideint.c
@@ -1,5 +1,4 @@
-/*
- * $Id: cairo-wideint.c,v 1.6 2005-07-30 19:57:54 keithp Exp $
+/* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2004 Keith Packard
  *
diff --git a/src/cairo-wideint.h b/src/cairo-wideint.h
index b008b5d..795cde7 100644
--- a/src/cairo-wideint.h
+++ b/src/cairo-wideint.h
@@ -1,5 +1,4 @@
-/*
- * $Id: cairo-wideint.h,v 1.12 2005-08-05 14:48:19 cworth Exp $
+/* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2004 Keith Packard
  *
diff-tree 1a1441912604c89e2912ec764fe26b7a9db995a3 (from 2d784815ffac1ca8c10dac12525f2e8d0b412c1a)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Fri Feb 17 23:37:54 2006 -0800

    Win32: Handle BitBlt in get_image failure and AlphaBlend not being supported
    
    If the BitBlt in get_image fails, we pretty much can't do anything -- so
    fill the destination with white and hope for the best.  This enables
    somewhat accurate printing of complex operations.  Also, check the
    destination device caps before calling AlphaBlend; return UNSUPPORTED if
    the destination DC can't do AlphaBlend.
    (cherry picked from 9831de538e347a624af5b0ca38242b198b64bd45 commit)

diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index d27185d..c7f4555 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -364,8 +364,18 @@ _cairo_win32_surface_get_subimage (cairo
 		 width, height,
 		 surface->dc,
 		 x, y,
-		 SRCCOPY))
-	goto FAIL;
+		 SRCCOPY)) {
+	/* If we fail to BitBlt here, most likely the source is a printer.
+	 * You can't reliably get bits from a printer DC, so just fill in
+	 * the surface as white (common case for printing).
+	 */
+
+	RECT r;
+	r.left = r.top = 0;
+	r.right = width;
+	r.bottom = height;
+	FillRect(local->dc, &r, (HBRUSH)GetStockObject(WHITE_BRUSH));
+    }
 
     *local_out = local;
     
@@ -580,6 +590,8 @@ _composite_alpha_blend (cairo_win32_surf
 
     if (alpha_blend == NULL)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
+    if (GetDeviceCaps(dst->dc, SHADEBLENDCAPS) == SB_NONE)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
     
     blend_function.BlendOp = AC_SRC_OVER;
     blend_function.BlendFlags = 0;
@@ -913,7 +925,7 @@ _cairo_win32_surface_set_clip_region (vo
 	    return CAIRO_STATUS_NO_MEMORY;
 
 	/* Combine the new region with the original clip */
-	    
+
 	if (surface->saved_clip) {
 	    if (CombineRgn (gdi_region, gdi_region, surface->saved_clip, RGN_AND) == ERROR)
 		goto FAIL;
diff-tree 2d784815ffac1ca8c10dac12525f2e8d0b412c1a (from 68ed40b6da242816a43cd68cc2c7feb779cf0acf)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Fri Feb 17 23:34:51 2006 -0800

    Win32: Set surface format based on device caps
    
    If the DC is a display DC, inspect its depth and set out local format
    appropriately.  If it's not a display DC, assume RGB24.
    (cherry picked from 6dd0a70d271f93df95f4bcaff5073b9bf90cecb6 commit)

diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 57f5aa5..d27185d 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -31,6 +31,8 @@
  *
  * Contributor(s):
  *	Owen Taylor <otaylor at redhat.com>
+ *	Stuart Parmenter <stuart at mozilla.com>
+ *	Vladimir Vukicevic <vladimir at pobox.com>
  */
 
 #include <stdio.h>
@@ -964,6 +966,8 @@ cairo_win32_surface_create (HDC hdc)
 {
     cairo_win32_surface_t *surface;
     RECT rect;
+    int depth;
+    cairo_format_t format;
 
     /* Try to figure out the drawing bounds for the Device context
      */
@@ -973,7 +977,26 @@ cairo_win32_surface_create (HDC hdc)
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	return &_cairo_surface_nil;
     }
-    
+
+    if (GetDeviceCaps(hdc, TECHNOLOGY) == DT_RASDISPLAY) {
+	depth = GetDeviceCaps(hdc, BITSPIXEL);
+	if (depth == 32)
+	    format = CAIRO_FORMAT_ARGB32;
+	else if (depth == 24)
+	    format = CAIRO_FORMAT_RGB24;
+	else if (depth == 8)
+	    format = CAIRO_FORMAT_A8;
+	else if (depth == 1)
+	    format = CAIRO_FORMAT_A1;
+	else {
+	    _cairo_win32_print_gdi_error("cairo_win32_surface_create(bad BITSPIXEL)");
+	    _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    return &_cairo_surface_nil;
+	}
+    } else {
+	format = CAIRO_FORMAT_RGB24;
+    }
+
     surface = malloc (sizeof (cairo_win32_surface_t));
     if (surface == NULL) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -981,7 +1004,7 @@ cairo_win32_surface_create (HDC hdc)
     }
 
     surface->image = NULL;
-    surface->format = CAIRO_FORMAT_RGB24;
+    surface->format = format;
     
     surface->dc = hdc;
     surface->bitmap = NULL;
diff-tree 68ed40b6da242816a43cd68cc2c7feb779cf0acf (from 0852cd449259eb9a52bfa63f19428c47c78baf91)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Fri Feb 17 23:24:06 2006 -0800

    Win32: Fix up src coords before calling AlphaBlend/BitBlt to avoid invalid calls
    
    Fixes up src coords and width/height before calling AlphaBlend/BitBlt; it's
    an error to try to use a region that extents outside of the source surface
    as a source DC.
    
    Doesn't repair the extra region relative to the operator -- e.g. regions
    outside of an ARGB source surface with SOURCE operator should be cleared
    to fully transparent black in the destination.
    (cherry picked from bc19c5b64b0e38e9d20045907d7b47d79f6afc60 commit)

diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index eb0456d..57f5aa5 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -643,6 +643,33 @@ _cairo_win32_surface_composite (cairo_op
     if (!integer_transform)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
+    /* Fix up src coordinates; the src coords and size must be within the
+     * bounds of the source surface.
+     * XXX the region not covered should be appropriately rendered!
+     * - for OVER/SOURCE with RGB24 source -> opaque black
+     * - for SOURCE with ARGB32 source -> 100% transparent black
+     */
+    src_x += itx;
+    src_y += ity;
+
+    if (src_x < 0) {
+        width += src_x;
+        dst_x -= src_x;
+        src_x = 0;
+    }
+
+    if (src_y < 0) {
+        height += src_y;
+        dst_y -= src_y;
+        src_y = 0;
+    }
+
+    if (src_x + width > src->extents.width)
+        width = src->extents.width - src_x;
+
+    if (src_y + height > src->extents.height)
+        height = src->extents.height - src_y;
+
     if (alpha == 255 &&
 	src->format == dst->format &&
 	(op == CAIRO_OPERATOR_SOURCE ||
@@ -652,7 +679,7 @@ _cairo_win32_surface_composite (cairo_op
 		     dst_x, dst_y,
 		     width, height,
 		     src->dc,
-		     src_x + itx, src_y + ity,
+		     src_x, src_y,
 		     SRCCOPY))
 	    return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite");
 
@@ -664,7 +691,7 @@ _cairo_win32_surface_composite (cairo_op
 	       op == CAIRO_OPERATOR_OVER) {
 
 	return _composite_alpha_blend (dst, src, alpha,
-				       src_x + itx, src_y + ity,
+				       src_x, src_y,
 				       dst_x, dst_y, width, height);
     }
     
diff-tree 0852cd449259eb9a52bfa63f19428c47c78baf91 (from 0fe8a93d95ab0b2235133fa089be8ec99d1a5248)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Mon Feb 27 12:49:27 2006 +0100

    Win32: rename cairo_surface_create_dib to cairo_surface_create_with_dib
    
    Also adds some documentation for the win32 creation functions.
    (cherry picked from 3a148bd620d709237d98a72f65118759bfc5a76d commit)

diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 1c9d3bf..841459f 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -1159,7 +1159,7 @@ _cairo_win32_scaled_font_show_glyphs (vo
 	cairo_surface_pattern_t mask;
 	RECT r;
 
-	tmp_surface = (cairo_win32_surface_t *)cairo_win32_surface_create_dib (CAIRO_FORMAT_ARGB32, width, height);
+	tmp_surface = (cairo_win32_surface_t *)cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, width, height);
 	if (tmp_surface->base.status)
 	    return CAIRO_STATUS_NO_MEMORY;
 
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 888dadd..eb0456d 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -316,27 +316,6 @@ _cairo_win32_surface_create_similar (voi
     return _cairo_win32_surface_create_for_dc (src->dc, format, width, height);
 }
 
-/**
- * _cairo_win32_surface_create_dib:
- * @format: format of pixels in the surface to create 
- * @width: width of the surface, in pixels
- * @height: height of the surface, in pixels
- * 
- * Creates a device-independent-bitmap surface not associated with
- * any particular existing surface or device context. The created
- * bitmap will be unititialized.
- * 
- * Return value: the newly created surface, or %NULL if it couldn't
- *   be created (probably because of lack of memory)
- **/
-cairo_surface_t *
-cairo_win32_surface_create_dib (cairo_format_t format,
-				int	       width,
-				int	       height)
-{
-    return _cairo_win32_surface_create_for_dc (NULL, format, width, height);
-}
-
 static cairo_status_t
 _cairo_win32_surface_finish (void *abstract_surface)
 {
@@ -941,6 +920,18 @@ _cairo_win32_surface_flush (void *abstra
     return _cairo_surface_reset_clip (abstract_surface);
 }
 
+/**
+ * cairo_win32_surface_create:
+ * @hdc: the DC to create a surface for
+ * 
+ * Creates a cairo surface that targets the given DC.  The DC will be
+ * queried for its initial clip extents, and this will be used as the
+ * size of the cairo surface.  Also, if the DC is a raster DC, it will
+ * be queried for its pixel format and the cairo surface format will
+ * be set appropriately.
+ * 
+ * Return value: the newly created surface
+ **/
 cairo_surface_t *
 cairo_win32_surface_create (HDC hdc)
 {
@@ -994,6 +985,28 @@ cairo_win32_surface_create (HDC hdc)
 }
 
 /**
+ * cairo_win32_surface_create_with_dib:
+ * @format: format of pixels in the surface to create 
+ * @width: width of the surface, in pixels
+ * @height: height of the surface, in pixels
+ * 
+ * Creates a device-independent-bitmap surface not associated with
+ * any particular existing surface or device context. The created
+ * bitmap will be unititialized.
+ * 
+ * Return value: the newly created surface
+ *
+ **/
+cairo_surface_t *
+cairo_win32_surface_create_with_dib (cairo_format_t format,
+                                     int	    width,
+                                     int	    height)
+{
+    return _cairo_win32_surface_create_for_dc (NULL, format, width, height);
+}
+
+
+/**
  * _cairo_surface_is_win32:
  * @surface: a #cairo_surface_t
  * 
diff --git a/src/cairo-win32.h b/src/cairo-win32.h
index a631820..6ba37de 100644
--- a/src/cairo-win32.h
+++ b/src/cairo-win32.h
@@ -48,9 +48,9 @@ cairo_public cairo_surface_t *
 cairo_win32_surface_create (HDC hdc);
 
 cairo_public cairo_surface_t *
-cairo_win32_surface_create_dib (cairo_format_t format,
-				int width,
-				int height);
+cairo_win32_surface_create_with_dib (cairo_format_t format,
+                                     int width,
+                                     int height);
 
 cairo_public HDC
 cairo_win32_surface_get_dc (cairo_surface_t *surface);
diff-tree 0fe8a93d95ab0b2235133fa089be8ec99d1a5248 (from f4b34df6b6c07024a1b552236d8e0db959771b15)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Fri Feb 17 23:17:23 2006 -0800

    Win32: expose win32 DIB (image) surface creation function, and DC getter
    
    Adds cairo_win32_surface_create_dib() for creating a win32 DIB-backed
    surface with a particular format.  Also exposes
    cairo_win32_surface_get_dc() to obtain the DC of a win32 surface.
    (cherry picked from 0813a1b9b6f35d786fe8cb0d4748771023956cde commit)

diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 3343abf..1c9d3bf 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -1159,7 +1159,7 @@ _cairo_win32_scaled_font_show_glyphs (vo
 	cairo_surface_pattern_t mask;
 	RECT r;
 
-	tmp_surface = (cairo_win32_surface_t *)_cairo_win32_surface_create_dib (CAIRO_FORMAT_ARGB32, width, height);
+	tmp_surface = (cairo_win32_surface_t *)cairo_win32_surface_create_dib (CAIRO_FORMAT_ARGB32, width, height);
 	if (tmp_surface->base.status)
 	    return CAIRO_STATUS_NO_MEMORY;
 
diff --git a/src/cairo-win32-private.h b/src/cairo-win32-private.h
index b3143c9..fd66424 100644
--- a/src/cairo-win32-private.h
+++ b/src/cairo-win32-private.h
@@ -70,11 +70,6 @@ typedef struct _cairo_win32_surface {
 cairo_status_t
 _cairo_win32_print_gdi_error (const char *context);
 
-cairo_surface_t *
-_cairo_win32_surface_create_dib (cairo_format_t format,
-				 int            width,
-				 int            height);
-
 cairo_bool_t
 _cairo_surface_is_win32 (cairo_surface_t *surface);
 
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 9c46efe..888dadd 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -330,9 +330,9 @@ _cairo_win32_surface_create_similar (voi
  *   be created (probably because of lack of memory)
  **/
 cairo_surface_t *
-_cairo_win32_surface_create_dib (cairo_format_t format,
-				 int	        width,
-				 int	        height)
+cairo_win32_surface_create_dib (cairo_format_t format,
+				int	       width,
+				int	       height)
 {
     return _cairo_win32_surface_create_for_dc (NULL, format, width, height);
 }
@@ -1007,6 +1007,31 @@ _cairo_surface_is_win32 (cairo_surface_t
     return surface->backend == &cairo_win32_surface_backend;
 }
 
+/**
+ * cairo_win32_surface_get_dc
+ * @surface: a #cairo_surface_t
+ *
+ * Returns the HDC associated with this surface, or NULL if none.
+ * Also returns NULL if the surface is not a win32 surface.
+ *
+ * Return value: HDC or NULL if no HDC available.
+ **/
+HDC
+cairo_win32_surface_get_dc (cairo_surface_t *surface)
+{
+    cairo_win32_surface_t *winsurf;
+
+    if (surface == NULL)
+	return NULL;
+
+    if (!_cairo_surface_is_win32(surface))
+	return NULL;
+
+    winsurf = (cairo_win32_surface_t *) surface;
+
+    return winsurf->dc;
+}
+
 static const cairo_surface_backend_t cairo_win32_surface_backend = {
     _cairo_win32_surface_create_similar,
     _cairo_win32_surface_finish,
diff --git a/src/cairo-win32.h b/src/cairo-win32.h
index 8d43bb7..a631820 100644
--- a/src/cairo-win32.h
+++ b/src/cairo-win32.h
@@ -47,6 +47,14 @@ CAIRO_BEGIN_DECLS
 cairo_public cairo_surface_t *
 cairo_win32_surface_create (HDC hdc);
 
+cairo_public cairo_surface_t *
+cairo_win32_surface_create_dib (cairo_format_t format,
+				int width,
+				int height);
+
+cairo_public HDC
+cairo_win32_surface_get_dc (cairo_surface_t *surface);
+
 cairo_public cairo_font_face_t *
 cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont);
 
diff-tree f4b34df6b6c07024a1b552236d8e0db959771b15 (from e0f4eecb91c8f7f09ef4977703d4ca21b06797a9)
Author: Vladimir Vukicevic <vladimir at h-216.office.mozilla.org>
Date:   Wed Feb 15 13:14:52 2006 -0800

    Have mark_dirty always invalidate the last clip set on the surface
    
    mark_dirty will force cairo to set its own clip the next time the cairo clip
    is applied after mark_dirty; otherwise we run the risk of cairo's cached
    clip and the device clip getting out of sync if any clip-related functions
    are used on the native device back-end.
    (cherry picked from 1935a28949da8569f924e37714ec19571fa95987 commit)
    (cherry picked from ef8b472f0ffab7b8b828d7297c7e454bb22bd5ec commit)

diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 2982017..93095fc 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -502,6 +502,10 @@ cairo_surface_mark_dirty (cairo_surface_
  * Like cairo_surface_mark_dirty(), but drawing has been done only to
  * the specified rectangle, so that cairo can retain cached contents
  * for other parts of the surface.
+ *
+ * Any cached clip set on the surface will be reset by this function,
+ * to make sure that future cairo calls have the clip set that they
+ * expect.
  */
 void
 cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
@@ -520,6 +524,13 @@ cairo_surface_mark_dirty_rectangle (cair
 	return;
     }
 
+    /* Always reset the clip here, to avoid having external calls to
+     * clip manipulation functions of the underlying device clip result
+     * in a desync between the cairo clip and the backend clip, due to
+     * the clip caching.
+     */
+    surface->current_clip_serial = -1;
+
     if (surface->backend->mark_dirty_rectangle) {
 	cairo_status_t status;
 	
@@ -1329,6 +1340,12 @@ _cairo_surface_set_clip (cairo_surface_t
     if (!surface)
 	return CAIRO_STATUS_NULL_POINTER;
 
+    if (surface->status)
+	return surface->status;
+
+    if (surface->finished)
+	return CAIRO_STATUS_SURFACE_FINISHED;
+
     if (clip) {
 	serial = clip->serial;
 	if (serial == 0)
@@ -1336,7 +1353,7 @@ _cairo_surface_set_clip (cairo_surface_t
     }
     
     surface->clip = clip;
-    
+
     if (serial == _cairo_surface_get_current_clip_serial (surface))
 	return CAIRO_STATUS_SUCCESS;
 
diff-tree e0f4eecb91c8f7f09ef4977703d4ca21b06797a9 (from f6b4fabaf59227d6cafcdd7e27cf0d8e26b4eeb8)
Author: Vladimir Vukicevic <vladimir at h\-216.office.mozilla.org>
Date:   Wed Feb 15 12:43:01 2006 -0800

    Win32: Rework clip and extents handling
    
    - Save extents at surface creation and always return these
    - Simplify clipping paths
    (cherry picked from a67722b3d7280e6c2375778c2d46556cca261bfc commit)
    (cherry picked from 7ce09732a978749a4da814feb77f50161dc42c91 commit)

diff --git a/src/cairo-win32-private.h b/src/cairo-win32-private.h
index a229147..b3143c9 100644
--- a/src/cairo-win32-private.h
+++ b/src/cairo-win32-private.h
@@ -62,9 +62,9 @@ typedef struct _cairo_win32_surface {
     
     cairo_rectangle_t clip_rect;
 
-    int set_clip;
     HRGN saved_clip;
 
+    cairo_rectangle_t extents;
 } cairo_win32_surface_t;
 
 cairo_status_t
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index b1811a1..9c46efe 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -274,9 +274,14 @@ _cairo_win32_surface_create_for_dc (HDC 
     surface->clip_rect.width = width;
     surface->clip_rect.height = height;
 
-    surface->set_clip = 0;
-    surface->saved_clip = NULL;
-    
+    surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
+    if (GetClipRgn (surface->dc, surface->saved_clip) == 0) {
+        DeleteObject(surface->saved_clip);
+        surface->saved_clip = NULL;
+    }
+
+    surface->extents = surface->clip_rect;
+
     _cairo_surface_init (&surface->base, &cairo_win32_surface_backend);
 
     return (cairo_surface_t *)surface;
@@ -340,9 +345,8 @@ _cairo_win32_surface_finish (void *abstr
     if (surface->image)
 	cairo_surface_destroy (surface->image);
 
-    if (surface->saved_clip) {
+    if (surface->saved_clip)
 	DeleteObject (surface->saved_clip);
-    }
 
     /* If we created the Bitmap and DC, destroy them */
     if (surface->bitmap) {
@@ -403,7 +407,7 @@ _cairo_win32_surface_acquire_source_imag
     cairo_win32_surface_t *surface = abstract_surface;
     cairo_win32_surface_t *local = NULL;
     cairo_status_t status;
-        
+
     if (surface->image) {
 	*image_out = (cairo_image_surface_t *)surface->image;
 	*image_extra = NULL;
@@ -446,7 +450,7 @@ _cairo_win32_surface_acquire_dest_image 
     cairo_status_t status;
     RECT clip_box;
     int x1, y1, x2, y2;
-        
+
     if (surface->image) {
 	image_rect->x = 0;
 	image_rect->y = 0;
@@ -461,12 +465,12 @@ _cairo_win32_surface_acquire_dest_image 
 
     if (GetClipBox (surface->dc, &clip_box) == ERROR)
 	return _cairo_win32_print_gdi_error ("_cairo_win3_surface_acquire_dest_image");
-    
+
     x1 = clip_box.left;
     x2 = clip_box.right;
     y1 = clip_box.top;
     y2 = clip_box.bottom;
-    
+
     if (interest_rect->x > x1)
 	x1 = interest_rect->x;
     if (interest_rect->y > y1)
@@ -855,19 +859,9 @@ _cairo_win32_surface_set_clip_region (vo
 
     if (region == NULL) {
 	/* Clear any clip set by cairo, return to the original */
-	
-	if (surface->set_clip) {
-	    if (SelectClipRgn (surface->dc, surface->saved_clip) == ERROR)
-		return _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region");
-
-	    if (surface->saved_clip) {
-		DeleteObject (surface->saved_clip);
-		surface->saved_clip = NULL;
-	    }
+	if (SelectClipRgn (surface->dc, surface->saved_clip) == ERROR)
+	    return _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region (reset)");
 
-	    surface->set_clip = 0;
-	}
-	    
 	return CAIRO_STATUS_SUCCESS;
     
     } else {
@@ -910,36 +904,16 @@ _cairo_win32_surface_set_clip_region (vo
 	if (!gdi_region)
 	    return CAIRO_STATUS_NO_MEMORY;
 
-	if (surface->set_clip) {
-	    /* Combine the new region with the original clip */
+	/* Combine the new region with the original clip */
 	    
-	    if (surface->saved_clip) {
-		if (CombineRgn (gdi_region, gdi_region, surface->saved_clip, RGN_AND) == ERROR)
-		    goto FAIL;
-	    }
-
-	    if (SelectClipRgn (surface->dc, gdi_region) == ERROR)
+	if (surface->saved_clip) {
+	    if (CombineRgn (gdi_region, gdi_region, surface->saved_clip, RGN_AND) == ERROR)
 		goto FAIL;
-		
-	} else {
-	    /* Save the the current region */
-
-	    surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
-	    if (!surface->saved_clip) {
-		goto FAIL;	    }
-
-	    /* This function has no error return! */
-	    if (GetClipRgn (surface->dc, surface->saved_clip) == 0) { /* No clip */
-		DeleteObject (surface->saved_clip);
-		surface->saved_clip = NULL;
-	    }
-		
-	    if (ExtSelectClipRgn (surface->dc, gdi_region, RGN_AND) == ERROR)
-		goto FAIL;
-
-	    surface->set_clip = 1;
 	}
 
+	if (SelectClipRgn (surface->dc, gdi_region) == ERROR)
+	    goto FAIL;
+
 	DeleteObject (gdi_region);
 	return CAIRO_STATUS_SUCCESS;
 
@@ -955,15 +929,8 @@ _cairo_win32_surface_get_extents (void		
 				  cairo_rectangle_t *rectangle)
 {
     cairo_win32_surface_t *surface = abstract_surface;
-    RECT clip_box;
 
-    if (GetClipBox (surface->dc, &clip_box) == ERROR)
-	return _cairo_win32_print_gdi_error ("_cairo_win3_surface_acquire_dest_image");
-
-    rectangle->x = clip_box.left;
-    rectangle->y = clip_box.top;
-    rectangle->width  = clip_box.right  - clip_box.left;
-    rectangle->height = clip_box.bottom - clip_box.top;
+    *rectangle = surface->extents;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1007,8 +974,19 @@ cairo_win32_surface_create (HDC hdc)
     surface->clip_rect.width = rect.right - rect.left;
     surface->clip_rect.height = rect.bottom - rect.top;
 
-    surface->set_clip = 0;
-    surface->saved_clip = NULL;
+    if (surface->clip_rect.width == 0 ||
+        surface->clip_rect.height == 0)
+    {
+        surface->saved_clip = NULL;
+    } else {
+        surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
+        if (GetClipRgn (hdc, surface->saved_clip) == 0) {
+            DeleteObject(surface->saved_clip);
+            surface->saved_clip = NULL;
+        }
+    }
+
+    surface->extents = surface->clip_rect;
 
     _cairo_surface_init (&surface->base, &cairo_win32_surface_backend);
 
diff-tree f6b4fabaf59227d6cafcdd7e27cf0d8e26b4eeb8 (from dba214b944a16dd7ee781f495cd5fbe83f678451)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Feb 14 11:55:00 2006 -0800

    Misc compilation fixes (C++-style comments, M_PI decls, etc.)
    (cherry picked from d0cc56b9a24fa59febc15ac5de073da0e785e1cc commit)
    (cherry picked from a6a054abe45287eb950c294e20366594313138f5 commit)

diff --git a/pixman/src/fbcompose.c b/pixman/src/fbcompose.c
index c14986c..e316c6d 100644
--- a/pixman/src/fbcompose.c
+++ b/pixman/src/fbcompose.c
@@ -33,8 +33,16 @@
 
 #include "pixregionint.h"
 
+#ifdef _MSC_VER
+#define _USE_MATH_DEFINES
+#endif
+
 #include <math.h>
 
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
 /* #define PIXMAN_CONVOLUTION */
 /* #define PIXMAN_INDEXED_FORMATS */
 
diff --git a/pixman/src/pixregion.c b/pixman/src/pixregion.c
index 9c122f5..e566096 100644
--- a/pixman/src/pixregion.c
+++ b/pixman/src/pixregion.c
@@ -60,7 +60,7 @@ SOFTWARE.
 #endif
 
 #undef assert
-#ifdef DEBUG
+#ifdef DEBUG_PIXREGION
 #define assert(expr) {if (!(expr)) \
 		FatalError("Assertion failed file %s, line %d: expr\n", \
 			__FILE__, __LINE__); }
@@ -208,7 +208,7 @@ if (((numRects) < ((reg)->data->size >> 
 }
 
 
-#ifdef DEBUG
+#ifdef DEBUG_PIXREGION
 int
 pixman_region16_print(rgn)
     pixman_region16_t * rgn;
@@ -302,7 +302,7 @@ pixman_region16_valid(reg)
     }
 }
 
-#endif /* DEBUG */
+#endif /* DEBUG_PIXREGION */
 
 
 /*	Create a new empty region	*/
diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index 12cd329..74a4fca 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -40,6 +40,16 @@
 #include "cairo.h"
 #include "cairo-quartz-private.h"
 
+/*
+ * FixedToFloat/FloatToFixed are 10.3+ SDK items - include definitions
+ * here so we can use older SDKs.
+ */
+#ifndef FixedToFloat
+#define fixed1              ((Fixed) 0x00010000L)
+#define FixedToFloat(a)     ((float)(a) / fixed1)
+#define FloatToFixed(a)     ((Fixed)((float)(a) * fixed1))
+#endif
+
 typedef struct _cairo_atsui_font_face cairo_atsui_font_face_t;
 typedef struct _cairo_atsui_font cairo_atsui_font_t;
 
diff --git a/src/cairoint.h b/src/cairoint.h
index 88fccae..2581bc6 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -184,6 +184,10 @@ cairo_private void _cairo_beos_unlock(vo
 #define TRUE 1
 #endif
 
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
 #define ASSERT_NOT_REACHED		\
 do {					\
     static const int NOT_REACHED = 0;	\
diff-tree dba214b944a16dd7ee781f495cd5fbe83f678451 (from d0e02a948e83e3b1b330c9cb0aa4930b42bf485c)
Author: Christian Biesinger <cbiesinger at web.de>
Date:   Sun Feb 26 10:46:04 2006 +0100

    Use C-style comments rather than C++-style

diff --git a/pixman/src/fbcompose.c b/pixman/src/fbcompose.c
index 2289cee..c14986c 100644
--- a/pixman/src/fbcompose.c
+++ b/pixman/src/fbcompose.c
@@ -35,8 +35,8 @@
 
 #include <math.h>
 
-// #define PIXMAN_CONVOLUTION
-// #define PIXMAN_INDEXED_FORMATS
+/* #define PIXMAN_CONVOLUTION */
+/* #define PIXMAN_INDEXED_FORMATS */
 
 static Bool
 PictureTransformPoint3d (pixman_transform_t *transform,
diff --git a/pixman/src/pixman-xserver-compat.h b/pixman/src/pixman-xserver-compat.h
index 46e2825..5113abd 100644
--- a/pixman/src/pixman-xserver-compat.h
+++ b/pixman/src/pixman-xserver-compat.h
@@ -72,8 +72,8 @@ typedef pixman_triangle_t	xTriangle;
 #define FB_SHIFT IC_SHIFT 
 #define FB_MASK IC_MASK
 #define FB_ALLONES IC_ALLONES
+#define FbMaskBits IcMaskBits
 */
-//#define FbMaskBits IcMaskBits
 
 /* XXX: We changed some function and field names which makes for some
  * ugly hacks... */
diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index 9f3b54d..12cd329 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -132,7 +132,7 @@ CreateSizedCopyOfStyle(ATSUStyle inStyle
     ATSUStyle style;
     OSStatus err;
 
-    // Set the style's size
+    /* Set the style's size */
     CGAffineTransform theTransform =
         CGAffineTransformMakeWithCairoFontScale(scale);
     Fixed theSize =
@@ -174,7 +174,7 @@ _cairo_atsui_font_set_metrics (cairo_ats
             extents.height = metrics.capHeight;
             extents.max_x_advance = metrics.maxAdvanceWidth;
 
-            // The FT backend doesn't handle max_y_advance either, so we'll ignore it for now. 
+            /* The FT backend doesn't handle max_y_advance either, so we'll ignore it for now. */
             extents.max_y_advance = 0.0;
 
 	    	_cairo_scaled_font_set_metrics (&font->base, &extents);
@@ -275,7 +275,7 @@ _cairo_atsui_font_create_toy(cairo_toy_f
                                kFontNoLanguageCode, &fontID);
 
     if (err != noErr) {
-	// couldn't get the font - remap css names and try again
+	/* couldn't get the font - remap css names and try again */
 
 	if (!strcmp(family, "serif"))
 	    family = "Times";
@@ -287,7 +287,7 @@ _cairo_atsui_font_create_toy(cairo_toy_f
 	    family = "Gadget";
 	else if (!strcmp(family, "monospace"))
 	    family = "Courier";
-	else // anything else - return error instead?
+	else /* anything else - return error instead? */
 	    family = "Courier";
 
 	err = ATSUFindFontFromName(family, strlen(family),
@@ -504,7 +504,7 @@ _cairo_atsui_font_text_to_glyphs (void		
 
     err = ATSUSetTextPointerLocation(textLayout, utf16, 0, n16, n16);
 
-    // Set the style for all of the text
+    /* Set the style for all of the text */
     err = ATSUSetRunStyle(textLayout,
 			  font->style, kATSUFromTextBeginning, kATSUToTextEnd);
 
@@ -565,7 +565,7 @@ _cairo_atsui_font_old_show_glyphs (void	
 				      &rect,
 				      &extra);
 
-    // Create a CGBitmapContext for the dest surface for drawing into
+    /* Create a CGBitmapContext for the dest surface for drawing into */
     colorSpace = CGColorSpaceCreateDeviceRGB();
 
     myBitmapContext = CGBitmapContextCreate(destImageSurface->data,
@@ -633,11 +633,12 @@ _cairo_atsui_font_old_show_glyphs (void	
 		/* XXX: Need to get the text clipped */
 	}
 	
-    // TODO - bold and italic text
-    //
-    // We could draw the text using ATSUI and get bold, italics
-    // etc. for free, but ATSUI does a lot of text layout work
-    // that we don't really need...
+    /* TODO - bold and italic text
+     *
+     * We could draw the text using ATSUI and get bold, italics
+     * etc. for free, but ATSUI does a lot of text layout work
+     * that we don't really need...
+     */
 
 	
     for (i = 0; i < num_glyphs; i++) {
diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index be17915..45db4dd 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -150,7 +150,7 @@ static inline int cairo_to_directfb_form
 						return DSPF_A1; 
 				default:
 				{
-						//assert(0);
+						/*assert(0);*/
 						return DSPF_UNKNOWN; 
 				}
 		}
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index d7defc9..c65ca46 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -73,10 +73,11 @@ _cairo_quartz_surface_acquire_source_ima
     UInt32 imageDataSize, rowBytes;
     CGDataProviderRef dataProvider;
 
-    // We keep a cached (cairo_image_surface_t *) in the cairo_quartz_surface_t
-    // struct. If the window is ever drawn to without going through Cairo, then
-    // we would need to refetch the pixel data from the window into the cached
-    // image surface. 
+    /* We keep a cached (cairo_image_surface_t *) in the cairo_quartz_surface_t
+     * struct. If the window is ever drawn to without going through Cairo, then
+     * we would need to refetch the pixel data from the window into the cached
+     * image surface. 
+     */
     if (surface->image) {
         cairo_surface_reference(&surface->image->base);
 
@@ -257,7 +258,7 @@ cairo_surface_t *cairo_quartz_surface_cr
 	surface->clip_region = NULL;
     surface->flipped = flipped;
 
-    // Set up the image surface which Cairo draws into and we blit to & from.
+    /* Set up the image surface which Cairo draws into and we blit to & from. */
     void *foo;
     _cairo_quartz_surface_acquire_source_image(surface, &surface->image, &foo);
 


More information about the cairo-commit mailing list