[cairo-commit] Branch 'cairo-origin' - 36 commits - configure.in doc/public .gitignore pixman/src src/cairo.c src/cairo-glitz-surface.c src/cairo.h src/cairoint.h src/cairo-path.c src/cairo-path-stroke.c src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-svg-surface.c src/Makefile.am test/cairo-test.c test/cairo-test.h test/caps-joins-alpha.c test/caps-joins-alpha-ref.png test/caps-joins-alpha-rgb24-ref.png test/filter-nearest-offset.c test/.gitignore test/Makefile.am test/mask.c test/mask-ctm.c test/move-to-show-surface.c test/new-sub-path.c test/new-sub-path-ps-argb32-ref.png test/new-sub-path-ref.png test/new-sub-path-rgb24-ref.png test/paint-source-alpha.c test/paint-source-alpha-ref.png test/paint-source-alpha-rgb24-ref.png test/paint-with-alpha.c test/paint-with-alpha-ref.png test/paint-with-alpha-rgb24-ref.png test/scale-source-surface-paint.c test/scale-source-surface-paint-pdf-argb32-ref.png test/show-text-current-point-pdf-argb32-ref.png test/show-text-current-point-svg-argb32-ref.png test/show-text-current-point-svg-rgb24-ref.png test/source-surface-scale-paint.c test/text-antialias-gray-pdf-argb32-ref.png test/text-antialias-gray-svg-argb32-ref.png test/text-antialias-gray-svg-rgb24-ref.png test/text-antialias-none-pdf-argb32-ref.png test/text-antialias-none-svg-argb32-ref.png test/text-antialias-none-svg-rgb24-ref.png test/text-antialias-subpixel-pdf-argb32-ref.png test/text-antialias-subpixel-svg-argb32-ref.png test/text-antialias-subpixel-svg-rgb24-ref.png test/text-pattern-svg-argb32-ref.png test/text-pattern-svg-rgb24-ref.png test/translate-show-surface.c test/unantialiased-shapes-svg-argb32-ref.png test/unantialiased-shapes-svg-rgb24-ref.png

Behdad Esfahbod behdad at kemper.freedesktop.org
Tue Apr 25 04:43:02 PDT 2006


 .gitignore                                         |    1 
 configure.in                                       |  203 +--
 doc/public/tmpl/cairo-beos.sgml                    |    3 
 doc/public/tmpl/cairo-font-options.sgml            |    3 
 doc/public/tmpl/cairo-font.sgml                    |    3 
 doc/public/tmpl/cairo-ft.sgml                      |    3 
 doc/public/tmpl/cairo-glitz.sgml                   |    3 
 doc/public/tmpl/cairo-image.sgml                   |    3 
 doc/public/tmpl/cairo-matrix.sgml                  |    3 
 doc/public/tmpl/cairo-paths.sgml                   |    3 
 doc/public/tmpl/cairo-pattern.sgml                 |    3 
 doc/public/tmpl/cairo-pdf.sgml                     |    3 
 doc/public/tmpl/cairo-png.sgml                     |    3 
 doc/public/tmpl/cairo-ps.sgml                      |    3 
 doc/public/tmpl/cairo-quartz.sgml                  |    3 
 doc/public/tmpl/cairo-scaled-font.sgml             |    3 
 doc/public/tmpl/cairo-status.sgml                  |    3 
 doc/public/tmpl/cairo-surface.sgml                 |    3 
 doc/public/tmpl/cairo-text.sgml                    |    3 
 doc/public/tmpl/cairo-transforms.sgml              |    3 
 doc/public/tmpl/cairo-types.sgml                   |    3 
 doc/public/tmpl/cairo-version.sgml                 |    3 
 doc/public/tmpl/cairo-win32-fonts.sgml             |    3 
 doc/public/tmpl/cairo-win32.sgml                   |    3 
 doc/public/tmpl/cairo-xcb-xrender.sgml             |    3 
 doc/public/tmpl/cairo-xcb.sgml                     |    3 
 doc/public/tmpl/cairo-xlib-xrender.sgml            |    3 
 doc/public/tmpl/cairo-xlib.sgml                    |    3 
 doc/public/tmpl/cairo.sgml                         |    3 
 pixman/src/icpixels.c                              |    3 
 pixman/src/ictrap.c                                |    6 
 src/Makefile.am                                    |    1 
 src/cairo-glitz-surface.c                          |    4 
 src/cairo-path-stroke.c                            |   24 
 src/cairo-path.c                                   |   40 
 src/cairo-pdf-surface.c                            | 1075 +++++++++++----------
 src/cairo-ps-surface.c                             |   82 -
 src/cairo-svg-surface.c                            |  139 +-
 src/cairo.c                                        |   64 +
 src/cairo.h                                        |    3 
 src/cairoint.h                                     |    3 
 test/.gitignore                                    |    3 
 test/Makefile.am                                   |   12 
 test/cairo-test.c                                  |  102 +
 test/cairo-test.h                                  |    3 
 test/caps-joins-alpha-ref.png                      |binary
 test/caps-joins-alpha-rgb24-ref.png                |binary
 test/caps-joins-alpha.c                            |   94 +
 test/filter-nearest-offset.c                       |    2 
 test/mask-ctm.c                                    |    2 
 test/mask.c                                        |    8 
 test/move-to-show-surface.c                        |    2 
 test/new-sub-path-ps-argb32-ref.png                |binary
 test/new-sub-path-ref.png                          |binary
 test/new-sub-path-rgb24-ref.png                    |binary
 test/new-sub-path.c                                |   79 +
 test/paint-source-alpha-ref.png                    |binary
 test/paint-source-alpha-rgb24-ref.png              |binary
 test/paint-source-alpha.c                          |   67 +
 test/paint-with-alpha-ref.png                      |binary
 test/paint-with-alpha-rgb24-ref.png                |binary
 test/paint-with-alpha.c                            |   11 
 test/scale-source-surface-paint-pdf-argb32-ref.png |binary
 test/scale-source-surface-paint.c                  |    2 
 test/show-text-current-point-pdf-argb32-ref.png    |binary
 test/show-text-current-point-svg-argb32-ref.png    |binary
 test/show-text-current-point-svg-rgb24-ref.png     |binary
 test/source-surface-scale-paint.c                  |    2 
 test/text-antialias-gray-pdf-argb32-ref.png        |binary
 test/text-antialias-gray-svg-argb32-ref.png        |binary
 test/text-antialias-gray-svg-rgb24-ref.png         |binary
 test/text-antialias-none-pdf-argb32-ref.png        |binary
 test/text-antialias-none-svg-argb32-ref.png        |binary
 test/text-antialias-none-svg-rgb24-ref.png         |binary
 test/text-antialias-subpixel-pdf-argb32-ref.png    |binary
 test/text-antialias-subpixel-svg-argb32-ref.png    |binary
 test/text-antialias-subpixel-svg-rgb24-ref.png     |binary
 test/text-pattern-svg-argb32-ref.png               |binary
 test/text-pattern-svg-rgb24-ref.png                |binary
 test/translate-show-surface.c                      |    2 
 test/unantialiased-shapes-svg-argb32-ref.png       |binary
 test/unantialiased-shapes-svg-rgb24-ref.png        |binary
 82 files changed, 1352 insertions(+), 768 deletions(-)

New commits:
diff-tree d195f1d1e164b0fae5b9be7aaf2064068ea66206 (from parents)
Merge: 8d635a3aa967b16de5047eceadf3d350d1169a76 05fc4ca32363366a3637443d525834bc91b5203d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Apr 25 07:41:17 2006 -0400

    Merge branch 'configure-backends'

diff-tree 05fc4ca32363366a3637443d525834bc91b5203d (from 134c508bf04d8674af632644095b78256f2e350d)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Apr 25 07:30:16 2006 -0400

    Unified handling of --enable-backend options.

diff --git a/configure.in b/configure.in
index 020b394..bff05d2 100644
--- a/configure.in
+++ b/configure.in
@@ -86,23 +86,56 @@ dnl ====================================
 PKG_PROG_PKG_CONFIG
 
 dnl ===========================================================================
+dnl
+dnl Define a macro to enable backends.
+dnl  - Macro: CAIRO_BACKEND_ENABLE (BACKEND-ID, BACKEND-NAME, DEFAULT, COMMANDS-TO-CHECK-IT)
+dnl
+dnl Where COMMANDS should set use_BACKEND-ID to something other than yes if the
+dnl backend cannot be built.
+dnl
+AC_DEFUN([CAIRO_BACKEND_ENABLE],
+         [AC_ARG_ENABLE([$1],
+                         AS_HELP_STRING([--enable-$1=@<:@no/auto/yes@:>@],
+                                        [Enable cairo's $2 backend @<:@default=$3@:>@]),
+                         use_$1=$enableval, use_$1=$3)
+	  if test "x$use_$1" '!=' xno; then
+            AC_CACHE_CHECK([for cairo's $1 backend], cairo_cv_use_$1,
+	    		   [echo
+			    saved_use_$1=$use_$1
+			    use_$1=yes
+			    $4
+			    cairo_cv_use_$1=$use_$1
+			    use_$1=$saved_use_$1
+			    AC_MSG_CHECKING([whether cairo's $1 backend could be enabled])])
+	    case $use_$1 in
+	      yes)
+	        if test "x$cairo_cv_use_$1" = xyes; then
+		  use_$1=yes
+		else
+	          AC_MSG_ERROR(requested $2 backend could not be enabled)
+		fi
+		;;
+	      auto)
+	        use_$1=$cairo_cv_use_$1
+		;;
+	      *)
+	        AC_MSG_ERROR(invalid argument passed to --enable-$1: $use_$1, should be one of @<:@no/auto/yes@:>@)
+		;;
+	    esac
+	  fi])
 
-AC_ARG_ENABLE(xlib,
-[  --disable-xlib          Disable cairo's Xlib backend],
-[use_xlib=$enableval], [use_xlib=yes])
+dnl ===========================================================================
 
-if test "x$use_xlib" = "xyes"; then
+CAIRO_BACKEND_ENABLE(xlib, Xlib, auto, [
   dnl Check for Xrender header files if the Xrender package is not installed:
   PKG_CHECK_MODULES(XRENDER, xrender >= 0.6, [
-    XRENDER_REQUIRES=xrender
-    use_xlib=yes], [
+    XRENDER_REQUIRES=xrender], [
       AC_CHECK_HEADER(X11/extensions/Xrender.h, [
       AC_PATH_XTRA
-      XRENDER_LIBS="$X_LIBS -lXrender -lXext -lX11 $X_EXTRA_LIBS"
-      use_xlib=yes], [
+      XRENDER_LIBS="$X_LIBS -lXrender -lXext -lX11 $X_EXTRA_LIBS"], [
 		use_xlib="no (requires Xrender http://freedesktop.org/Software/xlibs)"])])
   _CHECK_FUNCS_WITH_FLAGS(XrmFinalize, $XRENDER_CFLAGS, $XRENDER_LIBS)
-fi
+])
 
 AM_CONDITIONAL(CAIRO_HAS_XLIB_SURFACE, test "x$use_xlib" = "xyes")
 if test "x$use_xlib" = "xyes"; then
@@ -115,14 +148,10 @@ AC_SUBST(XRENDER_REQUIRES)
 CAIRO_CFLAGS="$CAIRO_CFLAGS $XRENDER_CFLAGS"
 CAIRO_LIBS="$CAIRO_LIBS $XRENDER_LIBS"
 
-AC_ARG_ENABLE(quartz,
-  [  --enable-quartz         Enable cairo's Quartz backend],
-  [use_quartz=$enableval], [use_quartz=no])
-
-if test "x$use_quartz" = "xyes"; then
+CAIRO_BACKEND_ENABLE(quartz, Quartz, no, [
   dnl There is no pkgconfig for quartz; lets do a header check
-  AC_CHECK_HEADER(Carbon/Carbon.h, [use_quartz=yes], [use_quartz=no])
-fi
+  AC_CHECK_HEADER(Carbon/Carbon.h, [use_quartz=yes], [use_quartz="no (Carbon headers not found)"])
+])
 
 AM_CONDITIONAL(CAIRO_HAS_QUARTZ_SURFACE, test "x$use_quartz" = "xyes")
 if test "x$use_quartz" = "xyes"; then
@@ -134,14 +163,10 @@ CAIRO_LIBS="$CAIRO_LIBS $QUARTZ_LIBS"
 
 dnl ===========================================================================
 
-AC_ARG_ENABLE(xcb,
-  [  --enable-xcb            Enable cairo's XCB backend],
-  [use_xcb=$enableval], [use_xcb=no])
-
-if test "x$use_xcb" = "xyes"; then
+CAIRO_BACKEND_ENABLE(xcb, XCB, no, [
   PKG_CHECK_MODULES(XCB, xcb, [use_xcb=yes], [
   use_xcb="no (requires XCB http://xcb.freedesktop.org)"])
-fi
+])
 
 AM_CONDITIONAL(CAIRO_HAS_XCB_SURFACE, test "x$use_xcb" = "xyes")
 if test "x$use_xcb" = "xyes"; then
@@ -155,7 +180,6 @@ CAIRO_LIBS="$CAIRO_LIBS $XCB_LIBS"
 
 dnl ===========================================================================
 
-AC_MSG_CHECKING([for some Win32 platform])
 case "$host" in
   *-*-mingw*|*-*-cygwin*)
     cairo_platform_win32=yes
@@ -164,15 +188,18 @@ case "$host" in
     cairo_platform_win32=no
     ;;
 esac
-AC_MSG_RESULT([$cairo_platform_win32])
 
-AC_ARG_ENABLE(win32,
-  [  --disable-win32         Disable cairo's Microsoft Windows backend],
-  [use_win32=$enableval], [use_win32="yes"])
+CAIRO_BACKEND_ENABLE(win32, Microsoft Windows, auto, [
+  case "$host" in
+    *-*-mingw*|*-*-cygwin*)
+      use_win32=yes
+      ;;
+    *)
+      use_win32="no (the Microsoft Windows backend requires a Win32 platform)"
+      ;;
+  esac
+])
 
-if test "x$cairo_platform_win32" != "xyes" ; then
-  use_win32=no
-fi
 
 if test "x$use_win32" = "xyes"; then
    CAIRO_LIBS="$CAIRO_LIBS -lgdi32 -lmsimg32"
@@ -194,27 +221,16 @@ AC_SUBST(WIN32_FONT_FEATURE)
 dnl ===========================================================================
 
 
-AC_MSG_CHECKING([for BeOS/Zeta])
-case "$host" in
-  *-*-beos)
-    cairo_platform_beos=yes
-    ;;
-  *)
-    cairo_platform_beos=no
-    ;;
-esac
-AC_MSG_RESULT([$cairo_platform_beos])
-
-AC_ARG_ENABLE(beos,
-  [  --enable-beos            Disable cairo's BeOS/Zeta backend],
-  [use_beos=$enableval], [use_beos=no])
-
-if test "x$cairo_platform_beos" != "xyes" ; then
-  if test "x$use_beos" = "xyes"; then
-    AC_MSG_WARN([The BeOS backend requires a BeOS platform; disabling])
-    use_beos=no
-  fi
-fi
+CAIRO_BACKEND_ENABLE(beos, BeOS/Zeta, no, [
+  case "$host" in
+    *-*-beos)
+      use_beos=yes
+      ;;
+    *)
+      use_beos="no (the BeOS backend requires a BeOS platform)"
+      ;;
+  esac
+])
 
 if test "x$use_beos" = "xyes"; then
   AC_PROG_CXX
@@ -232,11 +248,7 @@ AC_SUBST(BEOS_SURFACE_FEATURE)
 
 dnl ===========================================================================
 
-AC_ARG_ENABLE(png,
-  [  --disable-png           Disable cairo's PNG functions],
-  [use_png=$enableval], [use_png=yes])
-
-if test "x$use_png" = "xyes"; then
+CAIRO_BACKEND_ENABLE(png, PNG, yes, [
   use_png=no
   # libpng13 is GnuWin32's libpng-1.2.8 :-(
   for l in libpng12 libpng13 libpng10 ; do
@@ -253,7 +265,7 @@ if test "x$use_png" = "xyes"; then
   else
     AC_MSG_WARN([Could not find libpng in the pkg-config search path])
   fi    
-fi
+])
 
 AM_CONDITIONAL(CAIRO_HAS_PNG_FUNCTIONS, test "x$use_png" = "xyes")
 if test "x$use_png" = "xyes"; then
@@ -270,15 +282,11 @@ AC_SUBST(PNG_REQUIRES)
 
 dnl ===========================================================================
 
-AC_ARG_ENABLE(glitz,
-  [  --enable-glitz          Enable cairo's glitz backend],
-  [use_glitz=$enableval], [use_glitz=no])
-
-if test "x$use_glitz" = "xyes"; then
+CAIRO_BACKEND_ENABLE(glitz, glitz, no, [
   PKG_CHECK_MODULES(GLITZ, glitz >= 0.5.1, [
     GLITZ_REQUIRES=glitz
     use_glitz=yes], [use_glitz="no (requires glitz http://freedesktop.org/Software/glitz)"])
-fi
+])
 
 if test "x$use_glitz" = "xyes";then
   PKG_CHECK_MODULES(GLITZ_AGL, glitz-agl >= 0.5.1,
@@ -322,14 +330,10 @@ AC_SUBST(GLITZ_REQUIRES)
 
 dnl ===========================================================================
 
-AC_ARG_ENABLE(directfb,
-  [  --enable-directfb           Enable cairo's directfb backend],
-  [use_directfb=$enableval], [use_directfb=no])
-
-if test "x$use_directfb" = "xyes"; then
+CAIRO_BACKEND_ENABLE(directfb, directfb, no, [
   PKG_CHECK_MODULES(DIRECTFB, directfb, [use_directfb=yes], [
   use_directfb="no (requires directfb http://www.directfb.org)"])
-fi
+])
 
 AM_CONDITIONAL(CAIRO_HAS_DIRECTFB_SURFACE, test "x$use_directfb" = "xyes")
 if test "x$use_directfb" = "xyes"; then
@@ -342,15 +346,11 @@ CAIRO_LIBS="$CAIRO_LIBS $DIRECTFB_LIBS"
 
 dnl ===========================================================================
 
-AC_ARG_ENABLE(freetype,
-  [  --disable-freetype      Disable cairo's freetype font backend],
-  [use_freetype=$enableval], [use_freetype=yes])
-
-if test "x$use_freetype" = "xyes"; then
+CAIRO_BACKEND_ENABLE(freetype, freetype font, auto, [
   PKG_CHECK_MODULES(FONTCONFIG, fontconfig, 
                     [use_freetype=yes], [use_freetype=no])
   _CHECK_FUNCS_WITH_FLAGS(FcFini, $FONTCONFIG_CFLAGS, $FONTCONFIG_LIBS)
-fi
+])
 
 CAIRO_CFLAGS="$CAIRO_CFLAGS $FONTCONFIG_CFLAGS"
 CAIRO_LIBS="$CAIRO_LIBS $FONTCONFIG_LIBS"
@@ -460,14 +460,11 @@ AM_CONDITIONAL(HAVE_PTHREAD, test "x$hav
 
 dnl ===========================================================================
 
-AC_ARG_ENABLE(ps,
-  [  --disable-ps            Disable cairo's PostScript backend],
-  [use_ps=$enableval], [use_ps=yes])
-
-if test x"$have_ft_load_sfnt_table" != "xyes" ; then
-  AC_MSG_WARN([PS backend requires FreeType 2.1.4 or newer, disabling])
-  use_ps=no
-fi
+CAIRO_BACKEND_ENABLE(ps, PostScript, auto, [
+  if test x"$have_ft_load_sfnt_table" != "xyes" ; then
+    use_ps="no (PS backend requires FreeType 2.1.4 or newer)"
+  fi
+])
 
 # The postscript module requires zlib.
 AC_CHECK_LIB(z, compress,
@@ -488,14 +485,11 @@ AC_SUBST(PS_LIBS)
 
 dnl ===========================================================================
 
-AC_ARG_ENABLE(pdf,
-  [  --disable-pdf           Disable cairo's PDF backend],
-  [use_pdf=$enableval], [use_pdf=yes])
-
-if test x"$have_ft_load_sfnt_table" != "xyes" ; then
-  AC_MSG_WARN([PDF backend requires FreeType 2.1.4 or newer, disabling])
-  use_pdf=no
-fi
+CAIRO_BACKEND_ENABLE(pdf, PDF, auto, [
+  if test x"$have_ft_load_sfnt_table" != "xyes" ; then
+    use_pdf="no (PDF backend requires FreeType 2.1.4 or newer)"
+  fi
+])
 
 test_pdf=no
 AM_CONDITIONAL(CAIRO_HAS_PDF_SURFACE, test "x$use_pdf" = "xyes")
@@ -523,14 +517,11 @@ AC_SUBST(PDF_LIBS)
 
 dnl ===========================================================================
 
-AC_ARG_ENABLE(svg,
-  [  --enable-svg           Enable cairo's SVG backend],
-  [use_svg=$enableval], [use_svg=no])
-
-if test x"$have_ft_load_sfnt_table" != "xyes" ; then
-  AC_MSG_WARN([SVG backend requires FreeType 2.1.4 or newer, disabling])
-  use_svg=no
-fi
+CAIRO_BACKEND_ENABLE(svg, SVG, no, [
+  if test x"$have_ft_load_sfnt_table" != "xyes" ; then
+    use_svg="no (SVG backend requires FreeType 2.1.4 or newer)"
+  fi
+])
 
 if test "x$use_svg" = "xyes" ; then
 	use_svg=no
@@ -567,14 +558,10 @@ dnl ====================================
 dnl This check should default to 'yes' once we have code to actually
 dnl check for the atsui font backend.
 
-AC_ARG_ENABLE(atsui,
-  [  --enable-atsui          Enable cairo's atsui font backend],
-  [use_atsui=$enableval], [use_atsui=no])
-
-if test "x$use_atsui" = "xyes"; then
+CAIRO_BACKEND_ENABLE(atsui, atsui font, no, [
   dnl There is no pkgconfig for atsui; lets do a header check
   AC_CHECK_HEADER(Carbon/Carbon.h, [use_atsui=yes], [use_atsui=no])
-fi
+])
 
 AM_CONDITIONAL(CAIRO_HAS_ATSUI_FONT, test "x$use_atsui" = "xyes")
 if test "x$use_atsui" = "xyes"; then
@@ -653,7 +640,8 @@ AM_CONDITIONAL(USE_MMX, test $have_mmx_i
 dnl ===========================================================================
 
 AC_ARG_ENABLE(gcov,
-  [  --enable-gcov           Enable gcov],
+  AS_HELP_STRING([--enable-gcov],
+		 [Enable gcov]),
   [use_gcov=$enableval], [use_gcov=no])
 
 if test "x$use_gcov" = "xyes"; then
@@ -718,7 +706,8 @@ fi
 dnl ===========================================================================
 
 AC_ARG_ENABLE(test-surfaces,
-  [  --enable-test-surfaces  Add backends for more test suite coverage (no additional public functionality)],
+  AS_HELP_STRING([--enable-test-surfaces],
+		 [Add backends for more test suite coverage (no additional public functionality)]),
   [use_test_surfaces=$enableval], [use_test_surfaces=no])
 
 AM_CONDITIONAL(CAIRO_HAS_TEST_SURFACES, test "x$use_test_surfaces" = "xyes")
diff-tree 8d635a3aa967b16de5047eceadf3d350d1169a76 (from 134c508bf04d8674af632644095b78256f2e350d)
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 25 04:04:10 2006 -0700

    PDF: Execute entire path in user coordinates when stroking so that line params are interpreted correctly

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index d752a23..fb3c7e1 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1353,6 +1353,75 @@ _cairo_pdf_surface_get_extents (void		  
     return CAIRO_STATUS_SUCCESS;
 }
 
+typedef struct _pdf_stroke {
+    cairo_output_stream_t   *output_stream;
+    cairo_matrix_t	    *ctm_inverse;
+} pdf_stroke_t;
+
+static cairo_status_t
+_cairo_pdf_stroke_move_to (void *closure, cairo_point_t *point)
+{
+    pdf_stroke_t *stroke = closure;
+    double x = _cairo_fixed_to_double (point->x);
+    double y = _cairo_fixed_to_double (point->y);
+
+    cairo_matrix_transform_point (stroke->ctm_inverse, &x, &y);
+
+    _cairo_output_stream_printf (stroke->output_stream,
+				 "%f %f m ", x, y);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_pdf_stroke_line_to (void *closure, cairo_point_t *point)
+{
+    pdf_stroke_t *stroke = closure;
+    double x = _cairo_fixed_to_double (point->x);
+    double y = _cairo_fixed_to_double (point->y);
+
+    cairo_matrix_transform_point (stroke->ctm_inverse, &x, &y);
+
+    _cairo_output_stream_printf (stroke->output_stream,
+				 "%f %f l ", x, y);
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_pdf_stroke_curve_to (void          *closure,
+			    cairo_point_t *b,
+			    cairo_point_t *c,
+			    cairo_point_t *d)
+{
+    pdf_stroke_t *stroke = closure;
+    double bx = _cairo_fixed_to_double (b->x);
+    double by = _cairo_fixed_to_double (b->y);
+    double cx = _cairo_fixed_to_double (c->x);
+    double cy = _cairo_fixed_to_double (c->y);
+    double dx = _cairo_fixed_to_double (d->x);
+    double dy = _cairo_fixed_to_double (d->y);
+
+    cairo_matrix_transform_point (stroke->ctm_inverse, &bx, &by);
+    cairo_matrix_transform_point (stroke->ctm_inverse, &cx, &cy);
+    cairo_matrix_transform_point (stroke->ctm_inverse, &dx, &dy);
+
+    _cairo_output_stream_printf (stroke->output_stream,
+				 "%f %f %f %f %f %f c ",
+				 bx, by, cx, cy, dx, dy);
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_pdf_stroke_close_path (void *closure)
+{
+    pdf_stroke_t *stroke = closure;
+
+    _cairo_output_stream_printf (stroke->output_stream,
+				 "h\r\n");
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static cairo_int_status_t
 _cairo_pdf_surface_intersect_clip_path (void			*dst,
 					cairo_path_fixed_t	*path,
@@ -2046,6 +2115,7 @@ _cairo_pdf_surface_stroke (void			*abstr
 {
     cairo_pdf_surface_t *surface = abstract_surface;
     cairo_pdf_document_t *document = surface->document;
+    pdf_stroke_t stroke;
     cairo_status_t status;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
@@ -2069,21 +2139,28 @@ _cairo_pdf_surface_stroke (void			*abstr
     assert (document->current_stream != NULL &&
 	    document->current_stream == surface->current_stream);
 
+    stroke.output_stream = document->output_stream;
+    stroke.ctm_inverse = ctm_inverse;
+    status = _cairo_path_fixed_interpret (path,
+					  CAIRO_DIRECTION_FORWARD,
+					  _cairo_pdf_stroke_move_to,
+					  _cairo_pdf_stroke_line_to,
+					  _cairo_pdf_stroke_curve_to,
+					  _cairo_pdf_stroke_close_path,
+					  &stroke);
+				 
+    _cairo_output_stream_printf (document->output_stream,
+				 "q %f %f %f %f %f %f cm\r\n",
+				 ctm->xx, ctm->yx, ctm->xy, ctm->yy,
+				 ctm->x0, ctm->y0);
+
     status = _cairo_pdf_surface_emit_stroke_style (surface,
 						   document->output_stream,
 						   style);
     if (status)
 	return status;
 
-    status = _cairo_path_fixed_interpret (path,
-					  CAIRO_DIRECTION_FORWARD,
-					  _cairo_pdf_path_move_to,
-					  _cairo_pdf_path_line_to,
-					  _cairo_pdf_path_curve_to,
-					  _cairo_pdf_path_close_path,
-					  document->output_stream);
-
-    _cairo_output_stream_printf (document->output_stream, "S\r\n");
+    _cairo_output_stream_printf (document->output_stream, "S Q\r\n");
 
     return status;
 }
diff-tree 134c508bf04d8674af632644095b78256f2e350d (from c0721190438826d7222ed87c36b4e48e57ad0323)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Apr 25 03:45:37 2006 -0700

    PDF: Add SMask output and simplify analysis to support all OVER operations.
    
    With this SMask support, the PDF backend is now able to handle a very
    large subset of the things that are likely to be thrown at it in
    common operation, (for example, when handling images and text from web
    pages).

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 984967b..d752a23 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -601,108 +601,199 @@ compress_dup (const void *data, unsigned
     return compressed;
 }
 
+/* Emit alpha channel from the image into the given data, providing
+ * and id that can be used to reference the resulting SMask object.
+ *
+ * In the case that the alpha channel happens to be all opaque, then
+ * no SMask object will be emitted and *id_ret will be set to 0.
+ */
+static cairo_status_t
+emit_smask (cairo_pdf_document_t	*document,
+	    cairo_image_surface_t	*image,
+	    unsigned int		*id_ret)
+{
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_output_stream_t *output = document->output_stream;
+    cairo_pdf_stream_t *smask_stream;
+    char *alpha, *alpha_compressed;
+    unsigned long alpha_size, alpha_compressed_size;
+    pixman_bits_t *pixel;
+    int i, x, y;
+    cairo_bool_t opaque;
+    uint8_t a;
+
+    /* This is the only image format we support, which simplfies things. */
+    assert (image->format == CAIRO_FORMAT_ARGB32);
+
+    alpha_size = image->height * image->width;
+    alpha = malloc (alpha_size);
+    if (alpha == NULL) {
+	status = CAIRO_STATUS_NO_MEMORY;
+	goto CLEANUP;
+    }
+
+    opaque = TRUE;
+    i = 0;
+    for (y = 0; y < image->height; y++) {
+	pixel = (pixman_bits_t *) (image->data + y * image->stride);
+
+	for (x = 0; x < image->width; x++, pixel++) {
+	    a = (*pixel & 0xff000000) >> 24;
+	    alpha[i++] = a;
+	    if (a != 0xff)
+		opaque = FALSE;
+	}
+    }
+
+    /* Bail out without emitting smask if it's all opaque. */
+    if (opaque) {
+	*id_ret = 0;
+	goto CLEANUP_ALPHA;
+    }
+
+    alpha_compressed = compress_dup (alpha, alpha_size, &alpha_compressed_size);
+    if (alpha_compressed == NULL) {
+	status = CAIRO_STATUS_NO_MEMORY;
+	goto CLEANUP_ALPHA;
+	
+    }
+
+    smask_stream = _cairo_pdf_document_open_stream (document,
+						    "   /Type /XObject\r\n"
+						    "   /Subtype /Image\r\n"
+						    "   /Width %d\r\n"
+						    "   /Height %d\r\n"
+						    "   /ColorSpace /DeviceGray\r\n"
+						    "   /BitsPerComponent 8\r\n"
+						    "   /Filter /FlateDecode\r\n",
+						    image->width, image->height);
+    _cairo_output_stream_write (output, alpha_compressed, alpha_compressed_size);
+    _cairo_output_stream_printf (output, "\r\n");
+    _cairo_pdf_document_close_stream (document);
+
+    *id_ret = smask_stream->id;
+
+    free (alpha_compressed);
+ CLEANUP_ALPHA:
+    free (alpha);
+ CLEANUP:
+    return status;
+}
+
+
 /* Emit image data into the given document, providing an id that can
  * be used to reference the data in id_ret. */
 static cairo_status_t
-emit_image_rgb_data (cairo_pdf_document_t	*document,
-		     cairo_image_surface_t	*image,
-		     unsigned int		*id_ret)
+emit_image (cairo_pdf_document_t	*document,
+	    cairo_image_surface_t	*image,
+	    unsigned int		*id_ret)
 {
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_output_stream_t *output = document->output_stream;
-    cairo_pdf_stream_t *stream;
+    cairo_pdf_stream_t *image_stream;
     char *rgb, *compressed;
-    int i, x, y;
     unsigned long rgb_size, compressed_size;
     pixman_bits_t *pixel;
-    cairo_surface_t *opaque;
-    cairo_image_surface_t *opaque_image;
-    cairo_pattern_union_t pattern;
+    int i, x, y;
+    unsigned int smask_id;
+    cairo_bool_t need_smask;
+
+    /* These are the only image formats we currently support, (which
+     * makes things a lot simpler here). This is enforeced through
+     * _analyze_operation which only accept source surfaces of
+     * CONTENT_COLOR or CONTENT_COLOR_ALPHA. 
+     */
+    assert (image->format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_ARGB32);
 
     rgb_size = image->height * image->width * 3;
     rgb = malloc (rgb_size);
-    if (rgb == NULL)
-	return CAIRO_STATUS_NO_MEMORY;
-
-    /* XXX: We could actually output the alpha channels through PDF
-     * 1.4's SMask. But for now, all we support is opaque image data,
-     * so we must flatten any ARGB image by blending over white
-     * first. */
-    if (image->format != CAIRO_FORMAT_RGB24) {
-	opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
-					     image->width,
-					     image->height);
-	if (opaque->status) {
-	    free (rgb);
-	    return opaque->status;
-	}
-    
-	_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
-    
-	_cairo_surface_fill_rectangle (opaque,
-				       CAIRO_OPERATOR_SOURCE,
-				       CAIRO_COLOR_WHITE,
-				       0, 0, image->width, image->height);
-
-	_cairo_surface_composite (CAIRO_OPERATOR_OVER,
-				  &pattern.base,
-				  NULL,
-				  opaque,
-				  0, 0,
-				  0, 0,
-				  0, 0,
-				  image->width,
-				  image->height);
-    
-	_cairo_pattern_fini (&pattern.base);
-	opaque_image = (cairo_image_surface_t *) opaque;
-    } else {
-	opaque = &image->base;
-	opaque_image = image;
+    if (rgb == NULL) {
+	status = CAIRO_STATUS_NO_MEMORY;
+	goto CLEANUP;
     }
 
     i = 0;
     for (y = 0; y < image->height; y++) {
-	pixel = (pixman_bits_t *) (opaque_image->data + y * opaque_image->stride);
+	pixel = (pixman_bits_t *) (image->data + y * image->stride);
 
-	for (x = 0; x < opaque_image->width; x++, pixel++) {
-	    rgb[i++] = (*pixel & 0x00ff0000) >> 16;
-	    rgb[i++] = (*pixel & 0x0000ff00) >>  8;
-	    rgb[i++] = (*pixel & 0x000000ff) >>  0;
+	for (x = 0; x < image->width; x++, pixel++) {
+	    /* XXX: We're un-premultiplying alpha here. My reading of the PDF
+	     * specification suggests that we should be able to avoid having
+	     * to do this by filling in the SMask's Matte dictionary
+	     * appropriately, but my attempts to do that so far have
+	     * failed. */
+	    if (image->format == CAIRO_FORMAT_ARGB32) {
+		uint8_t a;
+		a = (*pixel & 0xff000000) >> 24;
+		if (a == 0) {
+		    rgb[i++] = 0;
+		    rgb[i++] = 0;
+		    rgb[i++] = 0;
+		} else {
+		    rgb[i++] = (((*pixel & 0xff0000) >> 16) * 255 + a / 2) / a;
+		    rgb[i++] = (((*pixel & 0x00ff00) >>  8) * 255 + a / 2) / a;
+		    rgb[i++] = (((*pixel & 0x0000ff) >>  0) * 255 + a / 2) / a;
+		}
+	    } else {
+		rgb[i++] = (*pixel & 0x00ff0000) >> 16;
+		rgb[i++] = (*pixel & 0x0000ff00) >>  8;
+		rgb[i++] = (*pixel & 0x000000ff) >>  0;
+	    }
 	}
     }
 
+    _cairo_pdf_document_close_stream (document);
+
     compressed = compress_dup (rgb, rgb_size, &compressed_size);
     if (compressed == NULL) {
-	free (rgb);
-	return CAIRO_STATUS_NO_MEMORY;
+	status = CAIRO_STATUS_NO_MEMORY;
+	goto CLEANUP_RGB;
     }
 
-    _cairo_pdf_document_close_stream (document);
+    need_smask = FALSE;
+    if (image->format == CAIRO_FORMAT_ARGB32) {
+	status = emit_smask (document, image, &smask_id);
+	if (status)
+	    goto CLEANUP_COMPRESSED;
 
-    stream = _cairo_pdf_document_open_stream (document, 
-					      "   /Type /XObject\r\n"
-					      "   /Subtype /Image\r\n"
-					      "   /Width %d\r\n"
-					      "   /Height %d\r\n"
-					      "   /ColorSpace /DeviceRGB\r\n"
-					      "   /BitsPerComponent 8\r\n"
-					      "   /Filter /FlateDecode\r\n",
-					      image->width, image->height);
+	if (smask_id)
+	    need_smask = TRUE;
+    }
 
-    _cairo_output_stream_write (output, compressed, compressed_size);
-    _cairo_output_stream_printf (output,
-				 "\r\n");
-    _cairo_pdf_document_close_stream (document);
+#define IMAGE_DICTIONARY	"   /Type /XObject\r\n"		\
+				"   /Subtype /Image\r\n"	\
+				"   /Width %d\r\n"		\
+				"   /Height %d\r\n"		\
+				"   /ColorSpace /DeviceRGB\r\n"	\
+				"   /BitsPerComponent 8\r\n"	\
+				"   /Filter /FlateDecode\r\n"
+
+
+    if (need_smask)
+	image_stream = _cairo_pdf_document_open_stream (document,
+							IMAGE_DICTIONARY
+							"   /SMask %d 0 R\r\n",
+							image->width, image->height,
+							smask_id);
+    else
+	image_stream = _cairo_pdf_document_open_stream (document,
+							IMAGE_DICTIONARY,
+							image->width, image->height);
 
-    free (rgb);
-    free (compressed);
+#undef IMAGE_DICTIONARY
 
-    if (opaque_image != image)
-	cairo_surface_destroy (opaque);
+    _cairo_output_stream_write (output, compressed, compressed_size);
+    _cairo_output_stream_printf (output, "\r\n");
+    _cairo_pdf_document_close_stream (document);
 
-    *id_ret = stream->id;
+    *id_ret = image_stream->id;
 
-    return CAIRO_STATUS_SUCCESS;
+ CLEANUP_COMPRESSED:
+    free (compressed);
+ CLEANUP_RGB:
+    free (rgb);
+ CLEANUP:
+    return status;
 }
 
 static cairo_status_t
@@ -748,10 +839,7 @@ emit_surface_pattern (cairo_pdf_surface_
     int xstep, ystep;
     cairo_rectangle_t dst_extents;
 
-    /* XXX: This is broken. We need new code here to actually emit the
-     * PDF surface. */
-    if (pattern->surface->backend == &cairo_pdf_surface_backend)
-	return CAIRO_STATUS_SUCCESS;
+    /* XXX: Should do something clever here for PDF source surfaces ? */
 
     status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
     if (status)
@@ -759,7 +847,7 @@ emit_surface_pattern (cairo_pdf_surface_
 
     _cairo_pdf_document_close_stream (document);
 
-    status = emit_image_rgb_data (dst->document, image, &id);
+    status = emit_image (dst->document, image, &id);
     if (status)
 	goto BAIL;
 
@@ -1756,22 +1844,44 @@ _cairo_pdf_document_add_page (cairo_pdf_
 }
 
 static cairo_bool_t
-_surface_pattern_supported (const cairo_surface_pattern_t *pattern)
+_surface_pattern_supported (cairo_surface_pattern_t *pattern)
 {
-    if (pattern->surface->backend->acquire_source_image != NULL)
+    cairo_extend_t extend;
+
+    if (pattern->surface->backend->acquire_source_image == NULL)
+	return FALSE;
+
+    /* Does an ALPHA-only source surface even make sense? Maybe, but I
+     * don't think it's worth the extra code to support it. */
+
+/* XXX: Need to write this function here...
+    content = cairo_surface_get_content (pattern->surface);
+    if (content == CAIRO_CONTENT_ALPHA)
+	return FALSE;
+*/
+
+    extend = cairo_pattern_get_extend (&pattern->base);
+    switch (extend) {
+    case CAIRO_EXTEND_NONE:
+    case CAIRO_EXTEND_REPEAT:
 	return TRUE;
+    case CAIRO_EXTEND_REFLECT:
+    case CAIRO_EXTEND_PAD:
+	return FALSE;
+    }
 
+    ASSERT_NOT_REACHED;
     return FALSE;
 }
 
 static cairo_bool_t
-_pattern_supported (const cairo_pattern_t *pattern)
+_pattern_supported (cairo_pattern_t *pattern)
 {
     if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
 	return TRUE;
 
     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
-	return _surface_pattern_supported ((const cairo_surface_pattern_t *) pattern);
+	return _surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
 	
     return FALSE;
 }
@@ -1779,24 +1889,23 @@ _pattern_supported (const cairo_pattern_
 static cairo_int_status_t
 _operation_supported (cairo_pdf_surface_t *surface,
 		      cairo_operator_t op,
-		      const cairo_pattern_t *pattern)
+		      cairo_pattern_t *pattern)
 {
     if (! _pattern_supported (pattern))
 	return FALSE;
 
-    if (_cairo_operator_always_opaque (op))
+    /* XXX: We can probably support a fair amount more than just OVER,
+     * but this should cover many common cases at least. */
+    if (op == CAIRO_OPERATOR_OVER)
 	return TRUE;
 
-    if (_cairo_operator_always_translucent (op))
-	return FALSE;
-
-    return _cairo_pattern_is_opaque (pattern);
+    return FALSE;
 }
 
 static cairo_int_status_t
 _analyze_operation (cairo_pdf_surface_t *surface,
 		    cairo_operator_t op,
-		    const cairo_pattern_t *pattern)
+		    cairo_pattern_t *pattern)
 {
     if (_operation_supported (surface, op, pattern))
 	return CAIRO_STATUS_SUCCESS;
diff-tree c0721190438826d7222ed87c36b4e48e57ad0323 (from bef621e870e3d4038e00ed56ad40d726d5a7ca77)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Apr 25 02:33:18 2006 -0700

    PDF: Remove unused backend functions.
    
    Since the switch to using paginated, we have a guarantee that the following functions
    will never be called. So we drop them now:
    
    	_cairo_pdf_surface_composite
    	_cairo_pdf_surface_fill_rectangles
    	_cairo_pdf_surface_composite_trapezoids
    	_cairo_pdf_surface_old_show_glyphs

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index a2e7c95..984967b 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -237,24 +237,6 @@ _cairo_pdf_surface_add_pattern (cairo_pd
     _cairo_array_append (&surface->patterns, &resource);
 }
 
-static void
-_cairo_pdf_surface_add_xobject (cairo_pdf_surface_t *surface, unsigned int id)
-{
-    cairo_pdf_resource_t resource;
-    int i, num_resources;
-
-    num_resources = _cairo_array_num_elements (&surface->xobjects);
-    for (i = 0; i < num_resources; i++) {
-	_cairo_array_copy_element (&surface->xobjects, i, &resource);
-	if (resource.id == id)
-	    return;
-    }
-
-    resource.id = id;
-    /* XXX: Should be checking the return value here. */
-    _cairo_array_append (&surface->xobjects, &resource);
-}
-
 static unsigned int
 _cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface, double alpha)
 {
@@ -273,24 +255,6 @@ _cairo_pdf_surface_add_alpha (cairo_pdf_
     return _cairo_array_num_elements (&surface->alphas) - 1;
 }
 
-static void
-_cairo_pdf_surface_add_font (cairo_pdf_surface_t *surface, unsigned int id)
-{
-    cairo_pdf_resource_t resource;
-    int i, num_fonts;
-
-    num_fonts = _cairo_array_num_elements (&surface->fonts);
-    for (i = 0; i < num_fonts; i++) {
-	_cairo_array_copy_element (&surface->fonts, i, &resource);
-	if (resource.id == id)
-	    return;
-    }
-
-    resource.id = id;
-    /* XXX: Should be checking the return value here. */
-    _cairo_array_append (&surface->fonts, &resource);
-}
-
 static cairo_surface_t *
 _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*stream,
 					       double			 width,
@@ -741,158 +705,6 @@ emit_image_rgb_data (cairo_pdf_document_
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_int_status_t
-_cairo_pdf_surface_composite_image (cairo_pdf_surface_t	*dst,
-				    cairo_surface_pattern_t *pattern)
-{
-    cairo_pdf_document_t *document = dst->document;
-    cairo_output_stream_t *output = document->output_stream;
-    unsigned id;
-    cairo_matrix_t i2u;
-    cairo_status_t status;
-    cairo_image_surface_t *image;
-    cairo_surface_t *src;
-    void *image_extra;
-
-    src = pattern->surface;
-    status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
-    if (status)
-	return status;
-
-    status = emit_image_rgb_data (dst->document, image, &id);
-    if (status)
-	goto bail;
-
-    _cairo_pdf_surface_add_xobject (dst, id);
-
-    _cairo_pdf_surface_ensure_stream (dst);
-
-    i2u = pattern->base.matrix;
-    cairo_matrix_invert (&i2u);
-    cairo_matrix_translate (&i2u, 0, image->height);
-    cairo_matrix_scale (&i2u, image->width, -image->height);
-
-    _cairo_output_stream_printf (output,
-				 "q %f %f %f %f %f %f cm /res%d Do Q\r\n",
-				 i2u.xx, i2u.yx,
-				 i2u.xy, i2u.yy,
-				 i2u.x0, i2u.y0,
-				 id);
-
- bail:
-    _cairo_surface_release_source_image (src, image, image_extra);
-
-    return status;
-}
-
-/* The contents of the surface is already transformed into PDF units,
- * but when we composite the surface we may want to use a different
- * space.  The problem I see now is that the show_surface snippet
- * creates a surface 1x1, which in the snippet environment is the
- * entire surface.  When compositing the surface, cairo gives us the
- * 1x1 to 256x256 matrix.  This would be fine if cairo didn't actually
- * also transform the drawing to the surface.  Should the CTM be part
- * of the current target surface?
- */
-
-static cairo_int_status_t
-_cairo_pdf_surface_composite_pdf (cairo_pdf_surface_t *dst,
-				  cairo_surface_pattern_t *pattern)
-{
-    cairo_pdf_document_t *document = dst->document;
-    cairo_output_stream_t *output = document->output_stream;
-    cairo_matrix_t i2u;
-    cairo_pdf_stream_t *stream;
-    int num_streams, i;
-    cairo_pdf_surface_t *src;
-
-    _cairo_pdf_surface_ensure_stream (dst);
-
-    src = (cairo_pdf_surface_t *) pattern->surface;
-
-    i2u = pattern->base.matrix;
-    cairo_matrix_invert (&i2u);
-    cairo_matrix_scale (&i2u, 1.0 / src->width, 1.0 / src->height);
-
-    _cairo_output_stream_printf (output,
-				 "q %f %f %f %f %f %f cm",
-				 i2u.xx, i2u.yx,
-				 i2u.xy, i2u.yy,
-				 i2u.x0, i2u.y0);
-
-    num_streams = _cairo_array_num_elements (&src->streams);
-    for (i = 0; i < num_streams; i++) {
-	_cairo_array_copy_element (&src->streams, i, &stream);
-	_cairo_output_stream_printf (output,
-				     " /res%d Do",
-				     stream->id);
-
-	_cairo_pdf_surface_add_xobject (dst, stream->id);
-
-    }
-	
-    _cairo_output_stream_printf (output, " Q\r\n");
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-_cairo_pdf_surface_composite (cairo_operator_t	op,
-			      cairo_pattern_t	*src_pattern,
-			      cairo_pattern_t	*mask_pattern,
-			      void		*abstract_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_pdf_surface_t *dst = abstract_dst;
-    cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) src_pattern;
-
-    if (mask_pattern)
- 	return CAIRO_STATUS_SUCCESS;
-    
-    if (src_pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (src->surface->backend == &cairo_pdf_surface_backend)
-	return _cairo_pdf_surface_composite_pdf (dst, src);
-    else
-	return _cairo_pdf_surface_composite_image (dst, src);
-}
-
-static cairo_int_status_t
-_cairo_pdf_surface_fill_rectangles (void		*abstract_surface,
-				    cairo_operator_t	op,
-				    const cairo_color_t	*color,
-				    cairo_rectangle_t	*rects,
-				    int			num_rects)
-{
-    cairo_pdf_surface_t *surface = abstract_surface;
-    cairo_pdf_document_t *document = surface->document;
-    cairo_output_stream_t *output = document->output_stream;
-    int i;
-
-    _cairo_pdf_surface_ensure_stream (surface);
-
-    _cairo_output_stream_printf (output,
-				 "%f %f %f rg\r\n",
-				 color->red, color->green, color->blue);
-
-    for (i = 0; i < num_rects; i++) {
-	_cairo_output_stream_printf (output,
-				     "%d %d %d %d re f\r\n",
-				     rects[i].x, rects[i].y,
-				     rects[i].width, rects[i].height);
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
 static cairo_status_t
 emit_solid_pattern (cairo_pdf_surface_t *surface,
 		    cairo_solid_pattern_t *pattern)
@@ -1352,15 +1164,6 @@ emit_pattern (cairo_pdf_surface_t *surfa
     return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
 }
 
-static double
-intersect (cairo_line_t *line, cairo_fixed_t y)
-{
-    return _cairo_fixed_to_double (line->p1.x) +
-	_cairo_fixed_to_double (line->p2.x - line->p1.x) *
-	_cairo_fixed_to_double (y - line->p1.y) /
-	_cairo_fixed_to_double (line->p2.y - line->p1.y);
-}
-
 static cairo_status_t
 _cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
 {
@@ -1419,57 +1222,6 @@ _cairo_pdf_path_close_path (void *closur
 }
 
 static cairo_int_status_t
-_cairo_pdf_surface_composite_trapezoids (cairo_operator_t	op,
-					 cairo_pattern_t	*pattern,
-					 void			*abstract_dst,
-					 cairo_antialias_t	antialias,
-					 int			x_src,
-					 int			y_src,
-					 int			x_dst,
-					 int			y_dst,
-					 unsigned int		width,
-					 unsigned int		height,
-					 cairo_trapezoid_t	*traps,
-					 int			num_traps)
-{
-    cairo_pdf_surface_t *surface = abstract_dst;
-    cairo_pdf_document_t *document = surface->document;
-    cairo_output_stream_t *output = document->output_stream;
-    cairo_int_status_t status;
-    int i;
-
-    status = emit_pattern (surface, pattern);
-    if (status)
-	return status;
-
-    /* After the above switch the current stream should belong to this
-     * surface, so no need to _cairo_pdf_surface_ensure_stream() */
-    assert (document->current_stream != NULL &&
-	    document->current_stream == surface->current_stream);
-
-    for (i = 0; i < num_traps; i++) {
-	double left_x1, left_x2, right_x1, right_x2;
-
-	left_x1  = intersect (&traps[i].left, traps[i].top);
-	left_x2  = intersect (&traps[i].left, traps[i].bottom);
-	right_x1 = intersect (&traps[i].right, traps[i].top);
-	right_x2 = intersect (&traps[i].right, traps[i].bottom);
-
-	_cairo_output_stream_printf (output,
-				     "%f %f m %f %f l %f %f l %f %f l h\r\n",
-				     left_x1, _cairo_fixed_to_double (traps[i].top),
-				     left_x2, _cairo_fixed_to_double (traps[i].bottom),
-				     right_x2, _cairo_fixed_to_double (traps[i].bottom),
-				     right_x1, _cairo_fixed_to_double (traps[i].top));
-    }
-
-    _cairo_output_stream_printf (output,
-				 "f\r\n");
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
 _cairo_pdf_surface_copy_page (void *abstract_surface)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
@@ -1513,111 +1265,6 @@ _cairo_pdf_surface_get_extents (void		  
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_font_subset_t *
-_cairo_pdf_document_get_font (cairo_pdf_document_t	*document,
-			      cairo_scaled_font_t	*scaled_font)
-{
-    cairo_status_t status;
-    cairo_unscaled_font_t *unscaled_font;
-    cairo_font_subset_t *pdf_font;
-    unsigned int num_fonts, i;
-
-    /* XXX: Need to fix this to work with a general cairo_scaled_font_t. */
-    if (! _cairo_scaled_font_is_ft (scaled_font))
-	return NULL;
-
-    /* XXX Why is this an ft specific function? */
-    unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font);
-
-    num_fonts = _cairo_array_num_elements (&document->fonts);
-    for (i = 0; i < num_fonts; i++) {
-	_cairo_array_copy_element (&document->fonts, i, &pdf_font);
-	if (pdf_font->unscaled_font == unscaled_font)
-	    return pdf_font;
-    }
-
-    /* FIXME: Figure out here which font backend is in use and call
-     * the appropriate constructor. */
-    pdf_font = _cairo_font_subset_create (unscaled_font);
-    if (pdf_font == NULL)
-	return NULL;
-
-    pdf_font->font_id = _cairo_pdf_document_new_object (document);
-
-    status = _cairo_array_append (&document->fonts, &pdf_font);
-    if (status) {
-	_cairo_font_subset_destroy (pdf_font);
-	return NULL;
-    }
-
-    return pdf_font;
-}
-
-static cairo_int_status_t
-_cairo_pdf_surface_old_show_glyphs (cairo_scaled_font_t	*scaled_font,
-				    cairo_operator_t	 op,
-				    cairo_pattern_t	*pattern,
-				    void		*abstract_surface,
-				    int			 source_x,
-				    int			 source_y,
-				    int			 dest_x,
-				    int			 dest_y,
-				    unsigned int	 width,
-				    unsigned int	 height,
-				    const cairo_glyph_t	*glyphs,
-				    int			 num_glyphs)
-{
-    cairo_pdf_surface_t *surface = abstract_surface;
-    cairo_pdf_document_t *document = surface->document;
-    cairo_output_stream_t *output = document->output_stream;
-    cairo_font_subset_t *pdf_font;
-    cairo_int_status_t status;
-    int i, index;
-    double det;
-
-    /* XXX: Need to fix this to work with a general cairo_scaled_font_t. */
-    if (! _cairo_scaled_font_is_ft (scaled_font))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    pdf_font = _cairo_pdf_document_get_font (document, scaled_font);
-    if (pdf_font == NULL)
-	return CAIRO_STATUS_NO_MEMORY;
-
-    /* Some PDF viewers (at least older versions of xpdf) have trouble with
-     * size 0 fonts. If the font size is less than 1/1000pt, ignore the
-     * font */
-    _cairo_matrix_compute_determinant (&scaled_font->scale, &det);
-    if (fabs (det) < 0.000001)
-	return CAIRO_STATUS_SUCCESS;
-    
-    status = emit_pattern (surface, pattern);
-    if (status)
-	return status;
-
-    _cairo_output_stream_printf (output,
-				 "BT /res%u 1 Tf", pdf_font->font_id);
-    for (i = 0; i < num_glyphs; i++) {
-
-	index = _cairo_font_subset_use_glyph (pdf_font, glyphs[i].index);
-
-	_cairo_output_stream_printf (output,
-				     " %f %f %f %f %f %f Tm (\\%o) Tj",
-				     scaled_font->scale.xx,
-				     scaled_font->scale.yx,
-				     -scaled_font->scale.xy,
-				     -scaled_font->scale.yy,
-				     glyphs[i].x,
-				     glyphs[i].y,
-				     index);
-    }
-    _cairo_output_stream_printf (output,
-				 " ET\r\n");
-
-    _cairo_pdf_surface_add_font (surface, pdf_font->font_id);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
 static cairo_int_status_t
 _cairo_pdf_surface_intersect_clip_path (void			*dst,
 					cairo_path_fixed_t	*path,
@@ -2179,11 +1826,6 @@ _cairo_pdf_surface_paint (void			*abstra
     assert (_operation_supported (op, source));
     */
 
-#if 0
-    if (source->type == CAIRO_PATTERN_TYPE_SURFACE)
-	return _cairo_pdf_surface_composite_image (surface, (cairo_surface_pattern_t *) source);
-#endif
-
     status = emit_pattern (surface, source);
     if (status)
 	return status;
@@ -2454,15 +2096,15 @@ static const cairo_surface_backend_t cai
     NULL, /* acquire_dest_image */
     NULL, /* release_dest_image */
     NULL, /* clone_similar */
-    _cairo_pdf_surface_composite,
-    _cairo_pdf_surface_fill_rectangles,
-    _cairo_pdf_surface_composite_trapezoids,
+    NULL, /* composite */
+    NULL, /* fill_rectangles */
+    NULL, /* composite_trapezoids */
     _cairo_pdf_surface_copy_page,
     _cairo_pdf_surface_show_page,
     NULL, /* set_clip_region */
     _cairo_pdf_surface_intersect_clip_path,
     _cairo_pdf_surface_get_extents,
-    _cairo_pdf_surface_old_show_glyphs,
+    NULL, /* old_show_glyphs */
     _cairo_pdf_surface_get_font_options,
     NULL, /* flush */
     NULL, /* mark_dirty_rectangle */
diff-tree bef621e870e3d4038e00ed56ad40d726d5a7ca77 (from a5afc59d0ad90125c0593ab60c8e1e01f51bdc3c)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Apr 25 01:56:51 2006 -0700

    Augment tests to do better testing of paths/images with alpha.
    
    Add a new cairo_test_paint_checkered function so that tests that draw
    with alpha can easily put an easy-to-see checkered background in place
    first.
    
    Add new tests caps-joins-alpha and paint-source-alpha that do simple
    tests of strokes and image painting with source pattern alpha.
    
    Also, add the checkered background to paint-with-alpha for
    consistency.

diff --git a/test/.gitignore b/test/.gitignore
index c124fc6..5ec8798 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -4,6 +4,7 @@ Makefile
 Makefile.in
 a8-mask
 caps-joins
+caps-joins-alpha
 caps-sub-paths
 clip-all
 clip-fill-rule
@@ -44,6 +45,7 @@ nil-surface
 operator-clear
 operator-source
 paint
+paint-source-alpha
 paint-with-alpha
 path-data
 pattern-get-type
diff --git a/test/Makefile.am b/test/Makefile.am
index 044dc08..d348ab2 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -2,6 +2,7 @@
 TESTS = 			\
 a8-mask				\
 caps-joins			\
+caps-joins-alpha		\
 caps-sub-paths			\
 clip-all			\
 clip-fill-rule			\
@@ -36,6 +37,7 @@ nil-surface			\
 operator-clear			\
 operator-source			\
 paint				\
+paint-source-alpha		\
 paint-with-alpha		\
 path-data			\
 pattern-get-type		\
@@ -113,6 +115,8 @@ a8-mask-rgb24-ref.png					\
 caps-joins-ps-rgb24-ref.png				\
 caps-joins-ref.png					\
 caps-joins-rgb24-ref.png				\
+caps-joins-alpha-ref.png				\
+caps-joins-alpha-rgb24-ref.png				\
 caps-sub-paths-ref.png					\
 caps-sub-paths-rgb24-ref.png				\
 clip-all-ref.png					\
@@ -178,6 +182,8 @@ operator-source-ref.png					\
 operator-source-rgb24-ref.png				\
 paint-ref.png						\
 paint-rgb24-ref.png					\
+paint-source-alpha-ref.png				\
+paint-source-alpha-rgb24-ref.png			\
 paint-with-alpha-ref.png				\
 paint-with-alpha-rgb24-ref.png				\
 path-data-ref.png					\
@@ -309,6 +315,7 @@ endif
 # from autogen.sh. My, but this is painful...
 a8_mask_LDADD = $(LDADDS)
 caps_joins_LDADD = $(LDADDS)
+caps_joins_alpha_LDADD = $(LDADDS)
 caps_sub_paths_LDADD = $(LDADDS)
 clip_all_LDADD = $(LDADDS)
 clip_fill_rule_LDADD = $(LDADDS)
@@ -345,6 +352,7 @@ nil_surface_LDADD = $(LDADDS)
 operator_clear_LDADD = $(LDADDS)
 operator_source_LDADD = $(LDADDS)
 paint_LDADD = $(LDADDS)
+paint_source_alpha_LDADD = $(LDADDS)
 paint_with_alpha_LDADD = $(LDADDS)
 path_data_LDADD = $(LDADDS)
 pattern_get_type_LDADD = $(LDADDS)
diff --git a/test/cairo-test.c b/test/cairo-test.c
index 00d3fd6..c61cb0e 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -1803,3 +1803,48 @@ cairo_test_create_pattern_from_png (cons
 
     return pattern;
 }
+
+static cairo_status_t
+_draw_check (cairo_surface_t *surface, int width, int height)
+{
+    cairo_t *cr;
+    cairo_status_t status;
+
+    cr = cairo_create (surface);
+    cairo_set_source_rgb (cr, 0.75, 0.75, 0.75); /* light gray */
+    cairo_paint (cr);
+
+    cairo_set_source_rgb (cr, 0.25, 0.25, 0.25); /* dark gray */
+    cairo_rectangle (cr, width / 2,  0, width / 2, height / 2);
+    cairo_rectangle (cr, 0, height / 2, width / 2, height / 2);
+    cairo_fill (cr);
+
+    status = cairo_status (cr);
+
+    cairo_destroy (cr);
+
+    return status;
+}
+
+cairo_status_t
+cairo_test_paint_checkered (cairo_t *cr)
+{
+    cairo_status_t status;
+    cairo_surface_t *check;
+
+    check = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 12, 12);
+    status = _draw_check (check, 12, 12);
+    if (status)
+	return status;
+
+    cairo_save (cr);
+    cairo_set_source_surface (cr, check, 0, 0);
+    cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
+    cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
+    cairo_paint (cr);
+    cairo_restore (cr);
+
+    cairo_surface_destroy (check);
+
+    return CAIRO_STATUS_SUCCESS;
+}
diff --git a/test/cairo-test.h b/test/cairo-test.h
index 1ba5e5f..ea5101d 100644
--- a/test/cairo-test.h
+++ b/test/cairo-test.h
@@ -138,6 +138,9 @@ cairo_test_create_surface_from_png (cons
 cairo_pattern_t *
 cairo_test_create_pattern_from_png (const char *filename);
 
+cairo_status_t
+cairo_test_paint_checkered (cairo_t *cr);
+
 void
 xasprintf (char **strp, const char *fmt, ...);
 
diff --git a/test/caps-joins-alpha-ref.png b/test/caps-joins-alpha-ref.png
new file mode 100644
index 0000000..85cccf2
Binary files /dev/null and b/test/caps-joins-alpha-ref.png differ
diff --git a/test/caps-joins-alpha-rgb24-ref.png b/test/caps-joins-alpha-rgb24-ref.png
new file mode 100644
index 0000000..60163dd
Binary files /dev/null and b/test/caps-joins-alpha-rgb24-ref.png differ
diff --git a/test/caps-joins-alpha.c b/test/caps-joins-alpha.c
new file mode 100644
index 0000000..c28482d
--- /dev/null
+++ b/test/caps-joins-alpha.c
@@ -0,0 +1,94 @@
+/*
+ * 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
+ * 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"
+
+#define LINE_WIDTH 	10.
+#define SIZE 		(5 * LINE_WIDTH)
+#define PAD		(2 * LINE_WIDTH)
+
+cairo_test_t test = {
+    "caps-joins-alpha",
+    "Test caps and joins with some source alpha",
+    3 * (PAD + SIZE) + PAD,
+    PAD + SIZE + PAD
+};
+
+static void
+make_path (cairo_t *cr)
+{
+    cairo_move_to (cr, 0., 0.);
+    cairo_rel_line_to (cr, 0., SIZE);
+    cairo_rel_line_to (cr, SIZE, 0.);
+    cairo_close_path (cr);
+
+    cairo_move_to (cr, 2 * LINE_WIDTH, 0.);
+    cairo_rel_line_to (cr, 3 * LINE_WIDTH, 0.);
+    cairo_rel_line_to (cr, 0., 3 * LINE_WIDTH);
+}
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    /* First draw a checkered background */
+    cairo_test_paint_checkered (cr);
+
+    /* Then draw the original caps-joins test but with a bit of alphs thrown in. */
+    cairo_set_line_width (cr, LINE_WIDTH);
+
+    cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.5); /* 50% red */
+    cairo_translate (cr, PAD, PAD);
+
+    make_path (cr);
+    cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
+    cairo_set_line_join (cr, CAIRO_LINE_JOIN_BEVEL);
+    cairo_stroke (cr);
+
+    cairo_set_source_rgba (cr, 0.0, 1.0, 0.0, 0.5); /* 50% green */
+    cairo_translate (cr, SIZE + PAD, 0.);
+
+    make_path (cr);
+    cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+    cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+    cairo_stroke (cr);
+
+    cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 0.5); /* 50% blue */
+
+    cairo_translate (cr, SIZE + PAD, 0.);
+
+    make_path (cr);
+    cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
+    cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
+    cairo_stroke (cr);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+    return cairo_test (&test, draw);
+}
diff --git a/test/paint-source-alpha-ref.png b/test/paint-source-alpha-ref.png
new file mode 100644
index 0000000..32a3eed
Binary files /dev/null and b/test/paint-source-alpha-ref.png differ
diff --git a/test/paint-source-alpha-rgb24-ref.png b/test/paint-source-alpha-rgb24-ref.png
new file mode 100644
index 0000000..4907470
Binary files /dev/null and b/test/paint-source-alpha-rgb24-ref.png differ
diff --git a/test/paint-source-alpha.c b/test/paint-source-alpha.c
new file mode 100644
index 0000000..8971939
--- /dev/null
+++ b/test/paint-source-alpha.c
@@ -0,0 +1,67 @@
+/*
+ * 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
+ * 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"
+
+cairo_test_t test = {
+    "paint-source-alpha",
+    "Simple test of cairo_paint with a source surface with non-opaque alpha",
+    32, 32
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    cairo_surface_t *surface;
+    static uint32_t data[16] = {
+	0x80808080, 0x80808080,		0x80800000, 0x80800000,
+	0x80808080, 0x80808080,		0x80800000, 0x80800000,
+
+	0x80008000, 0x80008000,		0x80000080, 0x80000080,
+	0x80008000, 0x80008000,		0x80000080, 0x80000080
+    };
+
+    surface = cairo_image_surface_create_for_data ((unsigned char *) data,
+						   CAIRO_FORMAT_ARGB32, 4, 4, 16);
+
+    cairo_test_paint_checkered (cr);
+
+    cairo_scale (cr, 4, 4);
+
+    cairo_set_source_surface (cr, surface, 2 , 2);
+    cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
+    cairo_paint (cr);
+
+    cairo_surface_destroy (surface);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+    return cairo_test (&test, draw);
+}
diff --git a/test/paint-with-alpha-ref.png b/test/paint-with-alpha-ref.png
index d821b5e..3e3942a 100644
Binary files a/test/paint-with-alpha-ref.png and b/test/paint-with-alpha-ref.png differ
diff --git a/test/paint-with-alpha-rgb24-ref.png b/test/paint-with-alpha-rgb24-ref.png
index b5cf0a7..228a78a 100644
Binary files a/test/paint-with-alpha-rgb24-ref.png and b/test/paint-with-alpha-rgb24-ref.png differ
diff --git a/test/paint-with-alpha.c b/test/paint-with-alpha.c
index 3292d5f..b204b08 100644
--- a/test/paint-with-alpha.c
+++ b/test/paint-with-alpha.c
@@ -1,5 +1,6 @@
 /*
  * 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
@@ -28,7 +29,7 @@
 cairo_test_t test = {
     "paint-with-alpha",
     "Simple test of cairo_paint_with_alpha",
-    12, 12
+    32, 32
 };
 
 static cairo_test_status_t
@@ -46,9 +47,11 @@ draw (cairo_t *cr, int width, int height
     surface = cairo_image_surface_create_for_data ((unsigned char *) data,
 						   CAIRO_FORMAT_RGB24, 4, 4, 16);
 
-    cairo_scale (cr, 2, 2);
+    cairo_test_paint_checkered (cr);
 
-    cairo_set_source_surface (cr, surface, 1 , 1);
+    cairo_scale (cr, 4, 4);
+
+    cairo_set_source_surface (cr, surface, 2 , 2);
     cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
     cairo_paint_with_alpha (cr, 0.5);
 
diff-tree a5afc59d0ad90125c0593ab60c8e1e01f51bdc3c (from 32a7edc42dae507678e4eed98fcb41802b8ee69c)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Apr 24 16:16:19 2006 -0700

    Add PDF-specific reference image for scale-source-surface-paint
    
    It only fails because the PDF ouput doesn't preserve the NEAREST filter attribute.
    There might be a way to get something like this in the PDF, but it's not the point
    of the test.

diff --git a/test/scale-source-surface-paint-pdf-argb32-ref.png b/test/scale-source-surface-paint-pdf-argb32-ref.png
new file mode 100644
index 0000000..bb940f8
Binary files /dev/null and b/test/scale-source-surface-paint-pdf-argb32-ref.png differ
diff-tree 32a7edc42dae507678e4eed98fcb41802b8ee69c (from a1bba71eb9442a1c3a5f9fb227353971d58cecba)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Apr 24 16:11:21 2006 -0700

    PDF: Fix surface pattern transformation and support for EXTEND_NONE.
    
    There's a bunch of careful matrix transformation here needed to
    resolve the differences between cairo and PDF pattern matrices,
    (primarily due to the different location for the origin).
    
    This fixes the several PDF test suite failures that recently appeared
    when we switched from ARGB32 to RGB24 source surface patterns.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 046a4d1..a2e7c95 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -931,7 +931,10 @@ emit_surface_pattern (cairo_pdf_surface_
     void *image_extra;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     unsigned int id, alpha;
-    cairo_matrix_t i2u;
+    cairo_matrix_t cairo_p2d, pdf_p2d;
+    cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
+    int xstep, ystep;
+    cairo_rectangle_t dst_extents;
 
     /* XXX: This is broken. We need new code here to actually emit the
      * PDF surface. */
@@ -948,29 +951,85 @@ emit_surface_pattern (cairo_pdf_surface_
     if (status)
 	goto BAIL;
 
-    /* BBox must be smaller than XStep by YStep or acroread wont
-     * display the pattern. */
+    _cairo_surface_get_extents (&dst->base, &dst_extents);
+
+    /* In PDF, (as far as I can tell), all patterns are repeating. So
+     * we support cairo's EXTEND_NONE semantics by setting the repeat
+     * step size to the larger of the image size and the extents of
+     * the destination surface. That way we guarantee the pattern will
+     * not repeat.
+     */
+    switch (extend) {
+    case CAIRO_EXTEND_NONE:
+	xstep = MAX(image->width, dst_extents.width);
+	ystep = MAX(image->height, dst_extents.height);
+	break;
+    case CAIRO_EXTEND_REPEAT:
+	xstep = image->width;
+	ystep = image->height;
+	break;
+    default:
+	ASSERT_NOT_REACHED; /* all others should be analyzed away */
+	xstep = 0;
+	ystep = 0;
+    }
+
+    /* At this point, (that is, within the surface backend interface),
+     * the pattern's matrix maps from cairo's device space to cairo's
+     * pattern space, (both with their origin at the upper-left, and
+     * cairo's pattern space of size width,height).
+     *
+     * Then, we must emit a PDF pattern object that maps from its own
+     * pattern space, (which has a size that we establish in the BBox
+     * dictionary entry), to the PDF page's *initial* space, (which
+     * does not benefit from the Y-axis flipping matrix that we emit
+     * on each page). So the PDF patterns patrix maps from a
+     * (width,height) pattern space to a device space with the origin
+     * in the lower-left corner.
+     *
+     * So to handle all of that, we start with an identity matrix for
+     * the PDF pattern to device matrix. We translate it up by the
+     * image height then flip it in the Y direction, (moving us from
+     * the PDF origin to cairo's origin). We then multiply in the
+     * inverse of the cairo pattern matrix, (since it maps from device
+     * to pattern, while we're setting up pattern to device). Finally,
+     * we translate back down by the image height and flip again to
+     * end up at the lower-left origin that PDF expects.
+     *
+     * Additionally, within the stream that paints the pattern itself,
+     * we are using a PDF image object that has a size of (1,1) so we
+     * have to scale it up by the image width and height to fill our
+     * pattern cell.
+     */
+    cairo_p2d = pattern->base.matrix;
+    cairo_matrix_invert (&cairo_p2d);
+
+    cairo_matrix_init_identity (&pdf_p2d);
+    cairo_matrix_translate (&pdf_p2d, 0.0, dst_extents.height);
+    cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
+    cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
+    cairo_matrix_translate (&pdf_p2d, 0.0, image->height);
+    cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
+
     stream = _cairo_pdf_document_open_stream (document,
-					      "   /BBox [ 0 0 %d %d ]\r\n"
+					      "   /BBox [0 0 %d %d]\r\n"
 					      "   /XStep %d\r\n"
 					      "   /YStep %d\r\n"
 					      "   /PatternType 1\r\n"
 					      "   /TilingType 1\r\n"
 					      "   /PaintType 1\r\n"
+					      "   /Matrix [ %f %f %f %f %f %f ]\r\n"
 					      "   /Resources << /XObject << /res%d %d 0 R >> >>\r\n",
 					      image->width, image->height,
-					      image->width, image->height,
+					      xstep, ystep,
+					      pdf_p2d.xx, pdf_p2d.yx,
+					      pdf_p2d.xy, pdf_p2d.yy,
+					      pdf_p2d.x0, pdf_p2d.y0,
 					      id, id);
 
-    i2u = pattern->base.matrix;
-    cairo_matrix_invert (&i2u);
-    cairo_matrix_scale (&i2u, image->width, image->height);
-
     _cairo_output_stream_printf (output,
-				 "q %f %f %f %f %f %f cm /res%d Do Q\r\n",
-				 i2u.xx, i2u.yx,
-				 i2u.xy, i2u.yy,
-				 i2u.x0, i2u.y0,
+				 "q %d 0 0 %d 0 0 cm /res%d Do Q\r\n",
+				 image->width, image->height,
 				 id);
 
     _cairo_pdf_surface_add_pattern (dst, stream->id);
diff-tree a1bba71eb9442a1c3a5f9fb227353971d58cecba (from 893239248a9a6ef1a7b9f770aec334f20c5c0861)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Apr 24 14:51:31 2006 -0700

    Trivial indentation fix

diff --git a/test/mask-ctm.c b/test/mask-ctm.c
index 99c67ed..1196e4d 100644
--- a/test/mask-ctm.c
+++ b/test/mask-ctm.c
@@ -43,7 +43,7 @@ draw (cairo_t *cr, int width, int height
     cairo_matrix_t matrix;
 
     mask_surface = cairo_image_surface_create_for_data ((unsigned char *) data,
-						CAIRO_FORMAT_ARGB32, 2, 2, 8);
+							CAIRO_FORMAT_ARGB32, 2, 2, 8);
     mask = cairo_pattern_create_for_surface (mask_surface);
     cairo_surface_destroy (mask_surface);
 
diff-tree 893239248a9a6ef1a7b9f770aec334f20c5c0861 (from 28e25e1cce0a4e4c612743effb8927c5cb6b3c5b)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Apr 24 14:50:52 2006 -0700

    Prefer RGB24 over ARGB32 for source surfaces in tests.
    
    Some tests were using source surfaces created as ARGB32 even though all
    alpha values are entirely opaque. This meant these tests were triggering
    more fallbacks than strictly necessary for what the tests are ttrying to
    do.

diff --git a/test/filter-nearest-offset.c b/test/filter-nearest-offset.c
index d7373c7..f664fbf 100644
--- a/test/filter-nearest-offset.c
+++ b/test/filter-nearest-offset.c
@@ -62,7 +62,7 @@ draw (cairo_t *cr, int width, int height
     cairo_stroke (cr);
 
     surface = cairo_image_surface_create_for_data ((unsigned char *) data,
-						   CAIRO_FORMAT_ARGB32,
+						   CAIRO_FORMAT_RGB24,
 						   STAMP_WIDTH,
 						   STAMP_HEIGHT,
 						   STAMP_WIDTH * 4);
diff --git a/test/move-to-show-surface.c b/test/move-to-show-surface.c
index 74bf51b..74cf3a0 100644
--- a/test/move-to-show-surface.c
+++ b/test/move-to-show-surface.c
@@ -63,7 +63,7 @@ draw (cairo_t *cr, int width, int height
 
     for (i=0; i < 4; i++) {
 	surface = cairo_image_surface_create_for_data ((unsigned char *) &colors[i],
-						       CAIRO_FORMAT_ARGB32,
+						       CAIRO_FORMAT_RGB24,
 						       1, 1, 4);
 	cairo_set_source_surface (cr, surface,
 				  i % 2, i / 2);
diff --git a/test/paint-with-alpha.c b/test/paint-with-alpha.c
index c35f679..3292d5f 100644
--- a/test/paint-with-alpha.c
+++ b/test/paint-with-alpha.c
@@ -44,7 +44,7 @@ draw (cairo_t *cr, int width, int height
     };
 
     surface = cairo_image_surface_create_for_data ((unsigned char *) data,
-					      CAIRO_FORMAT_ARGB32, 4, 4, 16);
+						   CAIRO_FORMAT_RGB24, 4, 4, 16);
 
     cairo_scale (cr, 2, 2);
 
diff --git a/test/scale-source-surface-paint.c b/test/scale-source-surface-paint.c
index 9553b9f..c2b76d3 100644
--- a/test/scale-source-surface-paint.c
+++ b/test/scale-source-surface-paint.c
@@ -44,7 +44,7 @@ draw (cairo_t *cr, int width, int height
     };
 
     surface = cairo_image_surface_create_for_data ((unsigned char *) data,
-					      CAIRO_FORMAT_ARGB32, 4, 4, 16);
+						   CAIRO_FORMAT_RGB24, 4, 4, 16);
 
     cairo_scale (cr, 2, 2);
 
diff --git a/test/source-surface-scale-paint.c b/test/source-surface-scale-paint.c
index e5676c9..472630c 100644
--- a/test/source-surface-scale-paint.c
+++ b/test/source-surface-scale-paint.c
@@ -44,7 +44,7 @@ draw (cairo_t *cr, int width, int height
     };
 
     surface = cairo_image_surface_create_for_data ((unsigned char *) data,
-					      CAIRO_FORMAT_ARGB32, 4, 4, 16);
+						   CAIRO_FORMAT_RGB24, 4, 4, 16);
 
     cairo_set_source_surface (cr, surface, 2, 2);
     cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
diff --git a/test/translate-show-surface.c b/test/translate-show-surface.c
index d81ed1a..cc0cb07 100644
--- a/test/translate-show-surface.c
+++ b/test/translate-show-surface.c
@@ -61,7 +61,7 @@ draw (cairo_t *cr, int width, int height
 
     for (i=0; i < 4; i++) {
 	surface = cairo_image_surface_create_for_data ((unsigned char *) &colors[i],
-						       CAIRO_FORMAT_ARGB32,
+						       CAIRO_FORMAT_RGB24,
 						       1, 1, 4);
 	cairo_save (cr);
 	{
diff-tree 28e25e1cce0a4e4c612743effb8927c5cb6b3c5b (from 12c4c375af7efe367bb6128babd14b4c1d05be65)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Apr 24 12:40:30 2006 -0700

    Fix broken error-checking in cairo_{ps,pdf}_surface_set_dpi

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index f4b928d..046a4d1 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -425,7 +425,7 @@ cairo_pdf_surface_set_dpi (cairo_surface
 
     target = _cairo_paginated_surface_get_target (surface);
 
-    if (! _cairo_surface_is_pdf (surface)) {
+    if (! _cairo_surface_is_pdf (target)) {
 	_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 	return;
     }
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 1d73495..33aa663 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -670,7 +670,7 @@ cairo_ps_surface_set_dpi (cairo_surface_
 
     target = _cairo_paginated_surface_get_target (surface);
 
-    if (! _cairo_surface_is_ps (surface)) {
+    if (! _cairo_surface_is_ps (target)) {
 	_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 	return;
     }
diff-tree 12c4c375af7efe367bb6128babd14b4c1d05be65 (from e0bf1378044d606273ee876663498878e0b2edd4)
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Apr 21 02:46:20 2006 -0700

    Fix invalid restore that was causing subsequent pages after first to be inverted

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 7cb9d13..f4b928d 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1944,8 +1944,10 @@ _cairo_pdf_document_add_page (cairo_pdf_
 
     _cairo_pdf_surface_ensure_stream (surface);
 
-    if (surface->has_clip)
+    if (surface->has_clip) {
 	_cairo_output_stream_printf (output, "Q\r\n");
+	surface->has_clip = FALSE;
+    }
 
     _cairo_pdf_document_close_stream (document);
 
diff-tree e0bf1378044d606273ee876663498878e0b2edd4 (from 810d9d19854f671d6a5d985b950d7442e59176e3)
Author: Christian Biesinger <cbiesinger at web.de>
Date:   Sun Apr 23 21:20:55 2006 +0200

    Fix create_xcb_surface signature

diff --git a/test/cairo-test.c b/test/cairo-test.c
index fce38fe..00d3fd6 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -955,8 +955,12 @@ _format_from_cairo(XCBConnection *c, cai
 }
 
 static cairo_surface_t *
-create_xcb_surface (int width, int height, void **closure)
+create_xcb_surface (cairo_test_t	 *test,
+		    cairo_content_t	  content,
+		    void		**closure)
 {
+    int width = test->width;
+    int height = test->height;
     XCBSCREEN *root;
     xcb_target_closure_t *xtc;
     cairo_surface_t *surface;
diff-tree 810d9d19854f671d6a5d985b950d7442e59176e3 (from 7fa8bfd738f939c06480c40162e347a2ecadd4d6)
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Apr 20 10:54:01 2006 -0700

    PDF: Fix reference images inadvertently committed as PDF not PNG

diff --git a/test/text-antialias-gray-pdf-argb32-ref.png b/test/text-antialias-gray-pdf-argb32-ref.png
index fd0e716..bd039b3 100644
Binary files a/test/text-antialias-gray-pdf-argb32-ref.png and b/test/text-antialias-gray-pdf-argb32-ref.png differ
diff --git a/test/text-antialias-none-pdf-argb32-ref.png b/test/text-antialias-none-pdf-argb32-ref.png
index fd0e716..bd039b3 100644
Binary files a/test/text-antialias-none-pdf-argb32-ref.png and b/test/text-antialias-none-pdf-argb32-ref.png differ
diff --git a/test/text-antialias-subpixel-pdf-argb32-ref.png b/test/text-antialias-subpixel-pdf-argb32-ref.png
index fd0e716..bd039b3 100644
Binary files a/test/text-antialias-subpixel-pdf-argb32-ref.png and b/test/text-antialias-subpixel-pdf-argb32-ref.png differ
diff-tree 7fa8bfd738f939c06480c40162e347a2ecadd4d6 (from c5d5687ac09049ca5b942993fc259e54ad5b6721)
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Apr 20 10:01:45 2006 -0700

    PDF: Cleanup error handling of emit_image_rgb_data

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 8c2252a..7cb9d13 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -637,12 +637,12 @@ compress_dup (const void *data, unsigned
     return compressed;
 }
 
-/* XXX: This should be rewritten to use the standard cairo_status_t
- * return and the error paths here need to be checked for memory
- * leaks. */
-static unsigned int
-emit_image_rgb_data (cairo_pdf_document_t *document,
-		     cairo_image_surface_t *image)
+/* Emit image data into the given document, providing an id that can
+ * be used to reference the data in id_ret. */
+static cairo_status_t
+emit_image_rgb_data (cairo_pdf_document_t	*document,
+		     cairo_image_surface_t	*image,
+		     unsigned int		*id_ret)
 {
     cairo_output_stream_t *output = document->output_stream;
     cairo_pdf_stream_t *stream;
@@ -657,7 +657,7 @@ emit_image_rgb_data (cairo_pdf_document_
     rgb_size = image->height * image->width * 3;
     rgb = malloc (rgb_size);
     if (rgb == NULL)
-	return 0;
+	return CAIRO_STATUS_NO_MEMORY;
 
     /* XXX: We could actually output the alpha channels through PDF
      * 1.4's SMask. But for now, all we support is opaque image data,
@@ -669,7 +669,7 @@ emit_image_rgb_data (cairo_pdf_document_
 					     image->height);
 	if (opaque->status) {
 	    free (rgb);
-	    return 0;
+	    return opaque->status;
 	}
     
 	_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
@@ -710,7 +710,7 @@ emit_image_rgb_data (cairo_pdf_document_
     compressed = compress_dup (rgb, rgb_size, &compressed_size);
     if (compressed == NULL) {
 	free (rgb);
-	return 0;
+	return CAIRO_STATUS_NO_MEMORY;
     }
 
     _cairo_pdf_document_close_stream (document);
@@ -736,7 +736,9 @@ emit_image_rgb_data (cairo_pdf_document_
     if (opaque_image != image)
 	cairo_surface_destroy (opaque);
 
-    return stream->id;
+    *id_ret = stream->id;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
@@ -757,11 +759,9 @@ _cairo_pdf_surface_composite_image (cair
     if (status)
 	return status;
 
-    id = emit_image_rgb_data (dst->document, image);
-    if (id == 0) {
-	status = CAIRO_STATUS_NO_MEMORY;
+    status = emit_image_rgb_data (dst->document, image, &id);
+    if (status)
 	goto bail;
-    }
 
     _cairo_pdf_surface_add_xobject (dst, id);
 
@@ -929,7 +929,7 @@ emit_surface_pattern (cairo_pdf_surface_
     cairo_pdf_stream_t *stream;
     cairo_image_surface_t *image;
     void *image_extra;
-    cairo_status_t status;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
     unsigned int id, alpha;
     cairo_matrix_t i2u;
 
@@ -944,7 +944,9 @@ emit_surface_pattern (cairo_pdf_surface_
 
     _cairo_pdf_document_close_stream (document);
 
-    id = emit_image_rgb_data (dst->document, image);
+    status = emit_image_rgb_data (dst->document, image, &id);
+    if (status)
+	goto BAIL;
 
     /* BBox must be smaller than XStep by YStep or acroread wont
      * display the pattern. */
@@ -983,9 +985,10 @@ emit_surface_pattern (cairo_pdf_surface_
 				 "/a%d gs\r\n",
 				 stream->id, stream->id, alpha);
 
+ BAIL:
     _cairo_surface_release_source_image (pattern->surface, image, image_extra);
 
-    return CAIRO_STATUS_SUCCESS;
+    return status;
 }
 
 
diff-tree c5d5687ac09049ca5b942993fc259e54ad5b6721 (from ab2546009ff246bd0e7bbc07437330cf307e00f7)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Apr 19 11:04:37 2006 -0700

    PDF: Add simple implementation of _cairo_pdf_surface_show_glyphs (text as paths).
    
    This isn't very exciting text output---it simply turns every call to
    cairo_show_glyphs into a single filled path. But at the very least,
    text will no longer trigger image fallbacks for the PDF backend.
    
    With this commit, the following tests change from all-fallback to
    all-native for the PDF backend:
    
    	show-text-current-point
    	text-antialias-gray
    	text-antialias-none
    	text-antialias-subpixel
    	text-cache-crash
    	text-rotate
    
    There are rasterization differences in the output (cairo vs. freetype)
    so this commit also adds new PDF-specific reference images for some of
    those tests so that the suite continues to report PASS.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 64b5641..8c2252a 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -41,6 +41,7 @@
 #include "cairo-font-subset-private.h"
 #include "cairo-ft-private.h"
 #include "cairo-paginated-surface-private.h"
+#include "cairo-path-fixed-private.h"
 
 #include <time.h>
 #include <zlib.h>
@@ -2342,13 +2343,33 @@ _cairo_pdf_surface_show_glyphs (void			*
 				cairo_scaled_font_t	*scaled_font)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
+    cairo_pdf_document_t *document = surface->document;
+    cairo_path_fixed_t path;
+    cairo_status_t status;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+	return _analyze_operation (surface, op, source);
 
-    ASSERT_NOT_REACHED;
+    assert (_operation_supported (surface, op, source));
 
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+    status = emit_pattern (surface, source);
+    if (status)
+	return status;
+
+    /* After emitting the pattern the current stream should belong to
+     * this surface, so no need to _cairo_pdf_surface_ensure_stream()
+     */
+    assert (document->current_stream != NULL &&
+	    document->current_stream == surface->current_stream);
+
+    _cairo_path_fixed_init (&path);
+    _cairo_scaled_font_glyph_path (scaled_font, glyphs, num_glyphs, &path);
+    status = _cairo_pdf_surface_fill (surface, op, source,
+				      &path, CAIRO_FILL_RULE_WINDING,
+				      0.1, scaled_font->options.antialias);
+    _cairo_path_fixed_fini (&path);
+
+    return status;
 }
 
 static void
diff --git a/test/show-text-current-point-pdf-argb32-ref.png b/test/show-text-current-point-pdf-argb32-ref.png
new file mode 100644
index 0000000..c024a4d
Binary files /dev/null and b/test/show-text-current-point-pdf-argb32-ref.png differ
diff --git a/test/text-antialias-gray-pdf-argb32-ref.png b/test/text-antialias-gray-pdf-argb32-ref.png
new file mode 100644
index 0000000..fd0e716
--- /dev/null
+++ b/test/text-antialias-gray-pdf-argb32-ref.png
@@ -0,0 +1,80 @@
+%PDF-1.4
+2 0 obj
+<< /Length 3 0 R
+   /Type /XObject
+   /Subtype /Form
+   /BBox [ 0 0 31 22 ]
+>>
+stream
+1 0 0 -1 0 22 cm
+1 1 1 RG 1 1 1 rg /a0 gs
+0 0 31 22 re f
+0 0 0 RG 0 0 0 rg /a0 gs
+0 0 0 RG 0 0 0 rg /a0 gs
+4.84375 6.71875 m 4.84375 5.927094 4.677078 5.307297 4.34375 4.859375 c 4.020828 4.411469 3.57811 4.1875 3.015625 4.1875 c 2.442703 4.1875 1.989578 4.411469 1.65625 4.859375 c 1.333328 5.307297 1.171875 5.927094 1.171875 6.71875 c 1.171875 7.510422 1.333328 8.135422 1.65625 8.59375 c 1.989578 9.041672 2.442703 9.265625 3.015625 9.265625 c 3.57811 9.265625 4.020828 9.041672 4.34375 8.59375 c 4.677078 8.135422 4.84375 7.510422 4.84375 6.71875 c h
+1.171875 4.4375 m 1.401031 4.041672 1.6875 3.75 2.03125 3.5625 c 2.374985 3.375015 2.786453 3.28125 3.265625 3.28125 c 4.067703 3.28125 4.71875 3.598969 5.21875 4.234375 c 5.718735 4.859375 5.96875 5.687515 5.96875 6.71875 c 5.96875 7.75 5.718735 8.583344 5.21875 9.21875 c 4.71875 9.854172 4.067703 10.171875 3.265625 10.171875 c 2.786453 10.171875 2.374985 10.07811 2.03125 9.890625 c 1.6875 9.692719 1.401031 9.401047 1.171875 9.015625 c 1.171875 10 l 0.09375 10 l 0.09375 0.875 l 1.171875 0.875 l 1.171875 4.4375 l h
+8.125 0.875 m 9.203125 0.875 l 9.203125 10 l 8.125 10 l 8.125 0.875 l h
+14.109375 6.703125 m 13.244781 6.703125 12.64061 6.802094 12.296875 7 c 11.963531 7.197922 11.796875 7.536469 11.796875 8.015625 c 11.796875 8.401047 11.921875 8.708344 12.171875 8.9375 c 12.432281 9.15625 12.776031 9.265625 13.203125 9.265625 c 13.807281 9.265625 14.286453 9.057297 14.640625 8.640625 c 15.005203 8.213547 15.1875 7.645844 15.1875 6.9375 c 15.1875 6.703125 l 14.109375 6.703125 l h
+16.265625 6.25 m 16.265625 10 l 15.1875 10 l 15.1875 9 l 14.9375 9.395844 14.630203 9.692719 14.265625 9.890625 c 13.901031 10.07811 13.45311 10.171875 12.921875 10.171875 c 12.244781 10.171875 11.708328 9.984375 11.3125 9.609375 c 10.916656 9.223969 10.71875 8.71875 10.71875 8.09375 c 10.71875 7.354172 10.963531 6.796875 11.453125 6.421875 c 11.95311 6.04689 12.692703 5.859375 13.671875 5.859375 c 15.1875 5.859375 l 15.1875 5.75 l 15.1875 5.250015 15.020828 4.864594 14.6875 4.59375 c 14.364578 4.322922 13.911453 4.1875 13.328125 4.1875 c 12.953125 4.1875 12.583328 4.23439 12.21875 4.328125 c 11.864578 4.421875 11.526031 4.557297 11.203125 4.734375 c 11.203125 3.734375 l 11.598953 3.57814 11.979156 3.463547 12.34375 3.390625 c 12.718735 3.317719 13.083328 3.28125 13.4375 3.28125 c 14.385406 3.28125 15.09375 3.526047 15.5625 4.015625 c 16.031235 4.505219 16.265625 5.250015 16.265625 6.25 c h
+22.859375 3.6875 m 22.859375 4.703125 l 22.546875 4.526047 22.239578 4.395844 21.9375 4.3125 c 21.635406 4.229172 21.32811 4.1875 21.015625 4.1875 c 20.307281 4.1875 19.760406 4.411469 19.375 4.859375 c 18.989578 5.296875 18.796875 5.916672 18.796875 6.71875 c 18.796875 7.520844 18.989578 8.145844 19.375 8.59375 c 19.760406 9.03125 20.307281 9.25 21.015625 9.25 c 21.32811 9.25 21.635406 9.208344 21.9375 9.125 c 22.239578 9.041672 22.546875 8.916672 22.859375 8.75 c 22.859375 9.75 l 22.557281 9.885422 22.244781 9.989594 21.921875 10.0625 c 21.598953 10.135406 21.255203 10.171875 20.890625 10.171875 c 19.901031 10.171875 19.114578 9.864594 18.53125 9.25 c 17.947906 8.625015 17.65625 7.78125 17.65625 6.71875 c 17.65625 5.656265 17.947906 4.817719 18.53125 4.203125 c 19.124985 3.588547 19.9375 3.28125 20.96875 3.28125 c 21.291656 3.28125 21.609375 3.317719 21.921875 3.390625 c 22.244781 3.453125 22.557281 3.552094 22.859375 3.6875 c h
+25.09375 0.875 m 26.171875 0.875 l 26.171875 6.265625 l 29.390625 3.4375 l 30.765625 3.4375 l 27.28125 6.5 l 30.921875 10 l 29.515625 10 l 26.171875 6.796875 l 26.171875 10 l 25.09375 10 l 25.09375 0.875 l h
+f
+0 0 1 RG 0 0 1 rg /a0 gs
+0 0 1 RG 0 0 1 rg /a0 gs
+4.84375 17.71875 m 4.84375 16.927094 4.677078 16.307297 4.34375 15.859375 c 4.020828 15.411469 3.57811 15.1875 3.015625 15.1875 c 2.442703 15.1875 1.989578 15.411469 1.65625 15.859375 c 1.333328 16.307297 1.171875 16.927094 1.171875 17.71875 c 1.171875 18.510422 1.333328 19.135422 1.65625 19.59375 c 1.989578 20.041672 2.442703 20.265625 3.015625 20.265625 c 3.57811 20.265625 4.020828 20.041672 4.34375 19.59375 c 4.677078 19.135422 4.84375 18.510422 4.84375 17.71875 c h
+1.171875 15.4375 m 1.401031 15.041672 1.6875 14.75 2.03125 14.5625 c 2.374985 14.375015 2.786453 14.28125 3.265625 14.28125 c 4.067703 14.28125 4.71875 14.598969 5.21875 15.234375 c 5.718735 15.859375 5.96875 16.687515 5.96875 17.71875 c 5.96875 18.75 5.718735 19.583344 5.21875 20.21875 c 4.71875 20.854172 4.067703 21.171875 3.265625 21.171875 c 2.786453 21.171875 2.374985 21.07811 2.03125 20.890625 c 1.6875 20.692719 1.401031 20.401047 1.171875 20.015625 c 1.171875 21 l 0.09375 21 l 0.09375 11.875 l 1.171875 11.875 l 1.171875 15.4375 l h
+8.125 11.875 m 9.203125 11.875 l 9.203125 21 l 8.125 21 l 8.125 11.875 l h
+11.015625 18.40625 m 11.015625 14.4375 l 12.09375 14.4375 l 12.09375 18.375 l 12.09375 18.989594 12.213531 19.45314 12.453125 19.765625 c 12.70311 20.078125 13.067703 20.234375 13.546875 20.234375 c 14.130203 20.234375 14.588531 20.052094 14.921875 19.6875 c 15.26561 19.312515 15.4375 18.802094 15.4375 18.15625 c 15.4375 14.4375 l 16.515625 14.4375 l 16.515625 21 l 15.4375 21 l 15.4375 19.984375 l 15.177078 20.390625 14.874985 20.692719 14.53125 20.890625 c 14.1875 21.07811 13.786453 21.171875 13.328125 21.171875 c 12.567703 21.171875 11.989578 20.9375 11.59375 20.46875 c 11.208328 20.000015 11.015625 19.3125 11.015625 18.40625 c h
+24.75 17.453125 m 24.75 17.96875 l 19.78125 17.96875 l 19.833328 18.71875 20.057281 19.286469 20.453125 19.671875 c 20.85936 20.057297 21.416656 20.25 22.125 20.25 c 22.541656 20.25 22.942703 20.203125 23.328125 20.109375 c 23.723953 20.005219 24.114578 19.848969 24.5 19.640625 c 24.5 20.671875 l 24.104156 20.828125 23.70311 20.947922 23.296875 21.03125 c 22.890625 21.124985 22.479156 21.171875 22.0625 21.171875 c 21.020828 21.171875 20.192703 20.869797 19.578125 20.265625 c 18.963531 19.651047 18.65625 18.822922 18.65625 17.78125 c 18.65625 16.708344 18.947906 15.859375 19.53125 15.234375 c 20.114578 14.598969 20.895828 14.28125 21.875 14.28125 c 22.760406 14.28125 23.458328 14.567719 23.96875 15.140625 c 24.489578 15.703125 24.75 16.473969 24.75 17.453125 c h
+23.671875 17.125 m 23.661453 16.541672 23.494781 16.072922 23.171875 15.71875 c 22.848953 15.364594 22.42186 15.1875 21.890625 15.1875 c 21.286453 15.1875 20.802078 15.35939 20.4375 15.703125 c 20.083328 16.046875 19.880203 16.526047 19.828125 17.140625 c 23.671875 17.125 l h
+f
+endstream
+endobj
+3 0 obj
+   6465
+endobj
+4 0 obj
+<< /Type /Page
+   /Parent 1 0 R
+   /Contents [ 2 0 R ]
+   /Resources <<
+      /ExtGState <<
+         /a0 << /CA 1 /ca 1 >>
+      >>
+   >>
+>>
+endobj
+1 0 obj
+<< /Type /Pages
+   /Kids [ 4 0 R ]
+   /Count 1
+   /MediaBox [ 0 0 31 22 ]
+>>
+endobj
+5 0 obj
+<< /Creator (cairographics.org)
+   /Producer (cairographics.org)
+>>
+endobj
+6 0 obj
+<< /Type /Catalog
+   /Pages 1 0 R
+>>
+endobj
+xref
+0 7
+0000000000 65535 f
+0000006788 00000 n
+0000000010 00000 n
+0000006595 00000 n
+0000006621 00000 n
+0000006887 00000 n
+0000006975 00000 n
+trailer
+<< /Size 7
+   /Root 6 0 R
+   /Info 5 0 R
+>>
+startxref
+7032
+%%EOF
diff --git a/test/text-antialias-none-pdf-argb32-ref.png b/test/text-antialias-none-pdf-argb32-ref.png
new file mode 100644
index 0000000..fd0e716
--- /dev/null
+++ b/test/text-antialias-none-pdf-argb32-ref.png
@@ -0,0 +1,80 @@
+%PDF-1.4
+2 0 obj
+<< /Length 3 0 R
+   /Type /XObject
+   /Subtype /Form
+   /BBox [ 0 0 31 22 ]
+>>
+stream
+1 0 0 -1 0 22 cm
+1 1 1 RG 1 1 1 rg /a0 gs
+0 0 31 22 re f
+0 0 0 RG 0 0 0 rg /a0 gs
+0 0 0 RG 0 0 0 rg /a0 gs
+4.84375 6.71875 m 4.84375 5.927094 4.677078 5.307297 4.34375 4.859375 c 4.020828 4.411469 3.57811 4.1875 3.015625 4.1875 c 2.442703 4.1875 1.989578 4.411469 1.65625 4.859375 c 1.333328 5.307297 1.171875 5.927094 1.171875 6.71875 c 1.171875 7.510422 1.333328 8.135422 1.65625 8.59375 c 1.989578 9.041672 2.442703 9.265625 3.015625 9.265625 c 3.57811 9.265625 4.020828 9.041672 4.34375 8.59375 c 4.677078 8.135422 4.84375 7.510422 4.84375 6.71875 c h
+1.171875 4.4375 m 1.401031 4.041672 1.6875 3.75 2.03125 3.5625 c 2.374985 3.375015 2.786453 3.28125 3.265625 3.28125 c 4.067703 3.28125 4.71875 3.598969 5.21875 4.234375 c 5.718735 4.859375 5.96875 5.687515 5.96875 6.71875 c 5.96875 7.75 5.718735 8.583344 5.21875 9.21875 c 4.71875 9.854172 4.067703 10.171875 3.265625 10.171875 c 2.786453 10.171875 2.374985 10.07811 2.03125 9.890625 c 1.6875 9.692719 1.401031 9.401047 1.171875 9.015625 c 1.171875 10 l 0.09375 10 l 0.09375 0.875 l 1.171875 0.875 l 1.171875 4.4375 l h
+8.125 0.875 m 9.203125 0.875 l 9.203125 10 l 8.125 10 l 8.125 0.875 l h
+14.109375 6.703125 m 13.244781 6.703125 12.64061 6.802094 12.296875 7 c 11.963531 7.197922 11.796875 7.536469 11.796875 8.015625 c 11.796875 8.401047 11.921875 8.708344 12.171875 8.9375 c 12.432281 9.15625 12.776031 9.265625 13.203125 9.265625 c 13.807281 9.265625 14.286453 9.057297 14.640625 8.640625 c 15.005203 8.213547 15.1875 7.645844 15.1875 6.9375 c 15.1875 6.703125 l 14.109375 6.703125 l h
+16.265625 6.25 m 16.265625 10 l 15.1875 10 l 15.1875 9 l 14.9375 9.395844 14.630203 9.692719 14.265625 9.890625 c 13.901031 10.07811 13.45311 10.171875 12.921875 10.171875 c 12.244781 10.171875 11.708328 9.984375 11.3125 9.609375 c 10.916656 9.223969 10.71875 8.71875 10.71875 8.09375 c 10.71875 7.354172 10.963531 6.796875 11.453125 6.421875 c 11.95311 6.04689 12.692703 5.859375 13.671875 5.859375 c 15.1875 5.859375 l 15.1875 5.75 l 15.1875 5.250015 15.020828 4.864594 14.6875 4.59375 c 14.364578 4.322922 13.911453 4.1875 13.328125 4.1875 c 12.953125 4.1875 12.583328 4.23439 12.21875 4.328125 c 11.864578 4.421875 11.526031 4.557297 11.203125 4.734375 c 11.203125 3.734375 l 11.598953 3.57814 11.979156 3.463547 12.34375 3.390625 c 12.718735 3.317719 13.083328 3.28125 13.4375 3.28125 c 14.385406 3.28125 15.09375 3.526047 15.5625 4.015625 c 16.031235 4.505219 16.265625 5.250015 16.265625 6.25 c h
+22.859375 3.6875 m 22.859375 4.703125 l 22.546875 4.526047 22.239578 4.395844 21.9375 4.3125 c 21.635406 4.229172 21.32811 4.1875 21.015625 4.1875 c 20.307281 4.1875 19.760406 4.411469 19.375 4.859375 c 18.989578 5.296875 18.796875 5.916672 18.796875 6.71875 c 18.796875 7.520844 18.989578 8.145844 19.375 8.59375 c 19.760406 9.03125 20.307281 9.25 21.015625 9.25 c 21.32811 9.25 21.635406 9.208344 21.9375 9.125 c 22.239578 9.041672 22.546875 8.916672 22.859375 8.75 c 22.859375 9.75 l 22.557281 9.885422 22.244781 9.989594 21.921875 10.0625 c 21.598953 10.135406 21.255203 10.171875 20.890625 10.171875 c 19.901031 10.171875 19.114578 9.864594 18.53125 9.25 c 17.947906 8.625015 17.65625 7.78125 17.65625 6.71875 c 17.65625 5.656265 17.947906 4.817719 18.53125 4.203125 c 19.124985 3.588547 19.9375 3.28125 20.96875 3.28125 c 21.291656 3.28125 21.609375 3.317719 21.921875 3.390625 c 22.244781 3.453125 22.557281 3.552094 22.859375 3.6875 c h
+25.09375 0.875 m 26.171875 0.875 l 26.171875 6.265625 l 29.390625 3.4375 l 30.765625 3.4375 l 27.28125 6.5 l 30.921875 10 l 29.515625 10 l 26.171875 6.796875 l 26.171875 10 l 25.09375 10 l 25.09375 0.875 l h
+f
+0 0 1 RG 0 0 1 rg /a0 gs
+0 0 1 RG 0 0 1 rg /a0 gs
+4.84375 17.71875 m 4.84375 16.927094 4.677078 16.307297 4.34375 15.859375 c 4.020828 15.411469 3.57811 15.1875 3.015625 15.1875 c 2.442703 15.1875 1.989578 15.411469 1.65625 15.859375 c 1.333328 16.307297 1.171875 16.927094 1.171875 17.71875 c 1.171875 18.510422 1.333328 19.135422 1.65625 19.59375 c 1.989578 20.041672 2.442703 20.265625 3.015625 20.265625 c 3.57811 20.265625 4.020828 20.041672 4.34375 19.59375 c 4.677078 19.135422 4.84375 18.510422 4.84375 17.71875 c h
+1.171875 15.4375 m 1.401031 15.041672 1.6875 14.75 2.03125 14.5625 c 2.374985 14.375015 2.786453 14.28125 3.265625 14.28125 c 4.067703 14.28125 4.71875 14.598969 5.21875 15.234375 c 5.718735 15.859375 5.96875 16.687515 5.96875 17.71875 c 5.96875 18.75 5.718735 19.583344 5.21875 20.21875 c 4.71875 20.854172 4.067703 21.171875 3.265625 21.171875 c 2.786453 21.171875 2.374985 21.07811 2.03125 20.890625 c 1.6875 20.692719 1.401031 20.401047 1.171875 20.015625 c 1.171875 21 l 0.09375 21 l 0.09375 11.875 l 1.171875 11.875 l 1.171875 15.4375 l h
+8.125 11.875 m 9.203125 11.875 l 9.203125 21 l 8.125 21 l 8.125 11.875 l h
+11.015625 18.40625 m 11.015625 14.4375 l 12.09375 14.4375 l 12.09375 18.375 l 12.09375 18.989594 12.213531 19.45314 12.453125 19.765625 c 12.70311 20.078125 13.067703 20.234375 13.546875 20.234375 c 14.130203 20.234375 14.588531 20.052094 14.921875 19.6875 c 15.26561 19.312515 15.4375 18.802094 15.4375 18.15625 c 15.4375 14.4375 l 16.515625 14.4375 l 16.515625 21 l 15.4375 21 l 15.4375 19.984375 l 15.177078 20.390625 14.874985 20.692719 14.53125 20.890625 c 14.1875 21.07811 13.786453 21.171875 13.328125 21.171875 c 12.567703 21.171875 11.989578 20.9375 11.59375 20.46875 c 11.208328 20.000015 11.015625 19.3125 11.015625 18.40625 c h
+24.75 17.453125 m 24.75 17.96875 l 19.78125 17.96875 l 19.833328 18.71875 20.057281 19.286469 20.453125 19.671875 c 20.85936 20.057297 21.416656 20.25 22.125 20.25 c 22.541656 20.25 22.942703 20.203125 23.328125 20.109375 c 23.723953 20.005219 24.114578 19.848969 24.5 19.640625 c 24.5 20.671875 l 24.104156 20.828125 23.70311 20.947922 23.296875 21.03125 c 22.890625 21.124985 22.479156 21.171875 22.0625 21.171875 c 21.020828 21.171875 20.192703 20.869797 19.578125 20.265625 c 18.963531 19.651047 18.65625 18.822922 18.65625 17.78125 c 18.65625 16.708344 18.947906 15.859375 19.53125 15.234375 c 20.114578 14.598969 20.895828 14.28125 21.875 14.28125 c 22.760406 14.28125 23.458328 14.567719 23.96875 15.140625 c 24.489578 15.703125 24.75 16.473969 24.75 17.453125 c h
+23.671875 17.125 m 23.661453 16.541672 23.494781 16.072922 23.171875 15.71875 c 22.848953 15.364594 22.42186 15.1875 21.890625 15.1875 c 21.286453 15.1875 20.802078 15.35939 20.4375 15.703125 c 20.083328 16.046875 19.880203 16.526047 19.828125 17.140625 c 23.671875 17.125 l h
+f
+endstream
+endobj
+3 0 obj
+   6465
+endobj
+4 0 obj
+<< /Type /Page
+   /Parent 1 0 R
+   /Contents [ 2 0 R ]
+   /Resources <<
+      /ExtGState <<
+         /a0 << /CA 1 /ca 1 >>
+      >>
+   >>
+>>
+endobj
+1 0 obj
+<< /Type /Pages
+   /Kids [ 4 0 R ]
+   /Count 1
+   /MediaBox [ 0 0 31 22 ]
+>>
+endobj
+5 0 obj
+<< /Creator (cairographics.org)
+   /Producer (cairographics.org)
+>>
+endobj
+6 0 obj
+<< /Type /Catalog
+   /Pages 1 0 R
+>>
+endobj
+xref
+0 7
+0000000000 65535 f
+0000006788 00000 n
+0000000010 00000 n
+0000006595 00000 n
+0000006621 00000 n
+0000006887 00000 n
+0000006975 00000 n
+trailer
+<< /Size 7
+   /Root 6 0 R
+   /Info 5 0 R
+>>
+startxref
+7032
+%%EOF
diff --git a/test/text-antialias-subpixel-pdf-argb32-ref.png b/test/text-antialias-subpixel-pdf-argb32-ref.png
new file mode 100644
index 0000000..fd0e716
--- /dev/null
+++ b/test/text-antialias-subpixel-pdf-argb32-ref.png
@@ -0,0 +1,80 @@
+%PDF-1.4
+2 0 obj
+<< /Length 3 0 R
+   /Type /XObject
+   /Subtype /Form
+   /BBox [ 0 0 31 22 ]
+>>
+stream
+1 0 0 -1 0 22 cm
+1 1 1 RG 1 1 1 rg /a0 gs
+0 0 31 22 re f
+0 0 0 RG 0 0 0 rg /a0 gs
+0 0 0 RG 0 0 0 rg /a0 gs
+4.84375 6.71875 m 4.84375 5.927094 4.677078 5.307297 4.34375 4.859375 c 4.020828 4.411469 3.57811 4.1875 3.015625 4.1875 c 2.442703 4.1875 1.989578 4.411469 1.65625 4.859375 c 1.333328 5.307297 1.171875 5.927094 1.171875 6.71875 c 1.171875 7.510422 1.333328 8.135422 1.65625 8.59375 c 1.989578 9.041672 2.442703 9.265625 3.015625 9.265625 c 3.57811 9.265625 4.020828 9.041672 4.34375 8.59375 c 4.677078 8.135422 4.84375 7.510422 4.84375 6.71875 c h
+1.171875 4.4375 m 1.401031 4.041672 1.6875 3.75 2.03125 3.5625 c 2.374985 3.375015 2.786453 3.28125 3.265625 3.28125 c 4.067703 3.28125 4.71875 3.598969 5.21875 4.234375 c 5.718735 4.859375 5.96875 5.687515 5.96875 6.71875 c 5.96875 7.75 5.718735 8.583344 5.21875 9.21875 c 4.71875 9.854172 4.067703 10.171875 3.265625 10.171875 c 2.786453 10.171875 2.374985 10.07811 2.03125 9.890625 c 1.6875 9.692719 1.401031 9.401047 1.171875 9.015625 c 1.171875 10 l 0.09375 10 l 0.09375 0.875 l 1.171875 0.875 l 1.171875 4.4375 l h
+8.125 0.875 m 9.203125 0.875 l 9.203125 10 l 8.125 10 l 8.125 0.875 l h
+14.109375 6.703125 m 13.244781 6.703125 12.64061 6.802094 12.296875 7 c 11.963531 7.197922 11.796875 7.536469 11.796875 8.015625 c 11.796875 8.401047 11.921875 8.708344 12.171875 8.9375 c 12.432281 9.15625 12.776031 9.265625 13.203125 9.265625 c 13.807281 9.265625 14.286453 9.057297 14.640625 8.640625 c 15.005203 8.213547 15.1875 7.645844 15.1875 6.9375 c 15.1875 6.703125 l 14.109375 6.703125 l h
+16.265625 6.25 m 16.265625 10 l 15.1875 10 l 15.1875 9 l 14.9375 9.395844 14.630203 9.692719 14.265625 9.890625 c 13.901031 10.07811 13.45311 10.171875 12.921875 10.171875 c 12.244781 10.171875 11.708328 9.984375 11.3125 9.609375 c 10.916656 9.223969 10.71875 8.71875 10.71875 8.09375 c 10.71875 7.354172 10.963531 6.796875 11.453125 6.421875 c 11.95311 6.04689 12.692703 5.859375 13.671875 5.859375 c 15.1875 5.859375 l 15.1875 5.75 l 15.1875 5.250015 15.020828 4.864594 14.6875 4.59375 c 14.364578 4.322922 13.911453 4.1875 13.328125 4.1875 c 12.953125 4.1875 12.583328 4.23439 12.21875 4.328125 c 11.864578 4.421875 11.526031 4.557297 11.203125 4.734375 c 11.203125 3.734375 l 11.598953 3.57814 11.979156 3.463547 12.34375 3.390625 c 12.718735 3.317719 13.083328 3.28125 13.4375 3.28125 c 14.385406 3.28125 15.09375 3.526047 15.5625 4.015625 c 16.031235 4.505219 16.265625 5.250015 16.265625 6.25 c h
+22.859375 3.6875 m 22.859375 4.703125 l 22.546875 4.526047 22.239578 4.395844 21.9375 4.3125 c 21.635406 4.229172 21.32811 4.1875 21.015625 4.1875 c 20.307281 4.1875 19.760406 4.411469 19.375 4.859375 c 18.989578 5.296875 18.796875 5.916672 18.796875 6.71875 c 18.796875 7.520844 18.989578 8.145844 19.375 8.59375 c 19.760406 9.03125 20.307281 9.25 21.015625 9.25 c 21.32811 9.25 21.635406 9.208344 21.9375 9.125 c 22.239578 9.041672 22.546875 8.916672 22.859375 8.75 c 22.859375 9.75 l 22.557281 9.885422 22.244781 9.989594 21.921875 10.0625 c 21.598953 10.135406 21.255203 10.171875 20.890625 10.171875 c 19.901031 10.171875 19.114578 9.864594 18.53125 9.25 c 17.947906 8.625015 17.65625 7.78125 17.65625 6.71875 c 17.65625 5.656265 17.947906 4.817719 18.53125 4.203125 c 19.124985 3.588547 19.9375 3.28125 20.96875 3.28125 c 21.291656 3.28125 21.609375 3.317719 21.921875 3.390625 c 22.244781 3.453125 22.557281 3.552094 22.859375 3.6875 c h
+25.09375 0.875 m 26.171875 0.875 l 26.171875 6.265625 l 29.390625 3.4375 l 30.765625 3.4375 l 27.28125 6.5 l 30.921875 10 l 29.515625 10 l 26.171875 6.796875 l 26.171875 10 l 25.09375 10 l 25.09375 0.875 l h
+f
+0 0 1 RG 0 0 1 rg /a0 gs
+0 0 1 RG 0 0 1 rg /a0 gs
+4.84375 17.71875 m 4.84375 16.927094 4.677078 16.307297 4.34375 15.859375 c 4.020828 15.411469 3.57811 15.1875 3.015625 15.1875 c 2.442703 15.1875 1.989578 15.411469 1.65625 15.859375 c 1.333328 16.307297 1.171875 16.927094 1.171875 17.71875 c 1.171875 18.510422 1.333328 19.135422 1.65625 19.59375 c 1.989578 20.041672 2.442703 20.265625 3.015625 20.265625 c 3.57811 20.265625 4.020828 20.041672 4.34375 19.59375 c 4.677078 19.135422 4.84375 18.510422 4.84375 17.71875 c h
+1.171875 15.4375 m 1.401031 15.041672 1.6875 14.75 2.03125 14.5625 c 2.374985 14.375015 2.786453 14.28125 3.265625 14.28125 c 4.067703 14.28125 4.71875 14.598969 5.21875 15.234375 c 5.718735 15.859375 5.96875 16.687515 5.96875 17.71875 c 5.96875 18.75 5.718735 19.583344 5.21875 20.21875 c 4.71875 20.854172 4.067703 21.171875 3.265625 21.171875 c 2.786453 21.171875 2.374985 21.07811 2.03125 20.890625 c 1.6875 20.692719 1.401031 20.401047 1.171875 20.015625 c 1.171875 21 l 0.09375 21 l 0.09375 11.875 l 1.171875 11.875 l 1.171875 15.4375 l h
+8.125 11.875 m 9.203125 11.875 l 9.203125 21 l 8.125 21 l 8.125 11.875 l h
+11.015625 18.40625 m 11.015625 14.4375 l 12.09375 14.4375 l 12.09375 18.375 l 12.09375 18.989594 12.213531 19.45314 12.453125 19.765625 c 12.70311 20.078125 13.067703 20.234375 13.546875 20.234375 c 14.130203 20.234375 14.588531 20.052094 14.921875 19.6875 c 15.26561 19.312515 15.4375 18.802094 15.4375 18.15625 c 15.4375 14.4375 l 16.515625 14.4375 l 16.515625 21 l 15.4375 21 l 15.4375 19.984375 l 15.177078 20.390625 14.874985 20.692719 14.53125 20.890625 c 14.1875 21.07811 13.786453 21.171875 13.328125 21.171875 c 12.567703 21.171875 11.989578 20.9375 11.59375 20.46875 c 11.208328 20.000015 11.015625 19.3125 11.015625 18.40625 c h
+24.75 17.453125 m 24.75 17.96875 l 19.78125 17.96875 l 19.833328 18.71875 20.057281 19.286469 20.453125 19.671875 c 20.85936 20.057297 21.416656 20.25 22.125 20.25 c 22.541656 20.25 22.942703 20.203125 23.328125 20.109375 c 23.723953 20.005219 24.114578 19.848969 24.5 19.640625 c 24.5 20.671875 l 24.104156 20.828125 23.70311 20.947922 23.296875 21.03125 c 22.890625 21.124985 22.479156 21.171875 22.0625 21.171875 c 21.020828 21.171875 20.192703 20.869797 19.578125 20.265625 c 18.963531 19.651047 18.65625 18.822922 18.65625 17.78125 c 18.65625 16.708344 18.947906 15.859375 19.53125 15.234375 c 20.114578 14.598969 20.895828 14.28125 21.875 14.28125 c 22.760406 14.28125 23.458328 14.567719 23.96875 15.140625 c 24.489578 15.703125 24.75 16.473969 24.75 17.453125 c h
+23.671875 17.125 m 23.661453 16.541672 23.494781 16.072922 23.171875 15.71875 c 22.848953 15.364594 22.42186 15.1875 21.890625 15.1875 c 21.286453 15.1875 20.802078 15.35939 20.4375 15.703125 c 20.083328 16.046875 19.880203 16.526047 19.828125 17.140625 c 23.671875 17.125 l h
+f
+endstream
+endobj
+3 0 obj
+   6465
+endobj
+4 0 obj
+<< /Type /Page
+   /Parent 1 0 R
+   /Contents [ 2 0 R ]
+   /Resources <<
+      /ExtGState <<
+         /a0 << /CA 1 /ca 1 >>
+      >>
+   >>
+>>
+endobj
+1 0 obj
+<< /Type /Pages
+   /Kids [ 4 0 R ]
+   /Count 1
+   /MediaBox [ 0 0 31 22 ]
+>>
+endobj
+5 0 obj
+<< /Creator (cairographics.org)
+   /Producer (cairographics.org)
+>>
+endobj
+6 0 obj
+<< /Type /Catalog
+   /Pages 1 0 R
+>>
+endobj
+xref
+0 7
+0000000000 65535 f
+0000006788 00000 n
+0000000010 00000 n
+0000006595 00000 n
+0000006621 00000 n
+0000006887 00000 n
+0000006975 00000 n
+trailer
+<< /Size 7
+   /Root 6 0 R
+   /Info 5 0 R
+>>
+startxref
+7032
+%%EOF
diff-tree ab2546009ff246bd0e7bbc07437330cf307e00f7 (from 241c6480cd9a5f63ea67f8cb1407f22503697ca3)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Apr 18 23:31:16 2006 -0700

    Use fallbacks in PDF backend for CAIRO_ANTIALIAS_NONE.
    
    Perhaps there's a way to preserve that hint in PDF output, but until
    we have code that actually does that, the correct thing to do is to
    call it unsupported and let the fallbacks do their thing.
    
    With this commit, the two regressions that were recently introduced
    now pass again. Specifically:
    
    	rectangle-rounding-error
    	unantialiased-shapes

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 027e2cb..64b5641 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -2232,8 +2232,14 @@ _cairo_pdf_surface_stroke (void			*abstr
     cairo_pdf_document_t *document = surface->document;
     cairo_status_t status;
 
-    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
+	/* XXX: Does PDF provide a way we can preserve this hint? For now,
+	 * this will trigger a fallback. */
+	if (antialias == CAIRO_ANTIALIAS_NONE)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+
 	return _analyze_operation (surface, op, source);
+    }
 
     assert (_operation_supported (surface, op, source));
 
@@ -2280,8 +2286,14 @@ _cairo_pdf_surface_fill (void			*abstrac
     const char *pdf_operator;
     cairo_status_t status;
 
-    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
+	/* XXX: Does PDF provide a way we can preserve this hint? For now,
+	 * this will trigger a fallback. */
+	if (antialias == CAIRO_ANTIALIAS_NONE)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+
 	return _analyze_operation (surface, op, source);
+    }
 
     assert (_operation_supported (surface, op, source));
 
diff-tree 241c6480cd9a5f63ea67f8cb1407f22503697ca3 (from 8be1697f2bd8026b28f2f24c2fab967ee01b6d8c)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Apr 18 23:24:14 2006 -0700

    Add implementation of _cairo_pdf_surface_paint (and fix emit_surface_pattern).
    
    Fix general broken-ness in emit_surface_pattern, enough so that a new
    implementation of _cairo_pdf_surface_paint does something useful. With
    this commit, the following tests switch from all-fallback to
    all-native and still pass the test suite with flying colors:
    
    	caps-joins
    	caps-sub-paths
    	clip-fill-rule
    	clip-fill-rule-pixel-aligned
    	clip-nesting
    	clip-twice
    	dash-caps-joins
    	dash-offset-negative
    	leaky-polygon
    	line-width
    	paint
    	path-data
    	transforms
    
    Meanwhile, the following two tests also switch from fallback to
    native, but cause the test suite to complain about failures. These
    both look like a mostly harmless failure to respect the ANTIALIAS_NONE
    hint in the PDF output:
    
    	rectangle-rounding-error-pdf-argb32-out.pdf
    	unantialiased-shapes-pdf-argb32-out.pdf

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index ef08ffc..027e2cb 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -175,7 +175,7 @@ _cairo_pdf_surface_clear (cairo_pdf_surf
 static cairo_pdf_stream_t *
 _cairo_pdf_document_open_stream (cairo_pdf_document_t	*document,
 				 const char		*fmt,
-				 ...);
+				 ...) CAIRO_PRINTF_FORMAT(2, 3);
 static void
 _cairo_pdf_document_close_stream (cairo_pdf_document_t	*document);
 
@@ -930,7 +930,7 @@ emit_surface_pattern (cairo_pdf_surface_
     void *image_extra;
     cairo_status_t status;
     unsigned int id, alpha;
-    cairo_matrix_t pm;
+    cairo_matrix_t i2u;
 
     /* XXX: This is broken. We need new code here to actually emit the
      * PDF surface. */
@@ -947,25 +947,27 @@ emit_surface_pattern (cairo_pdf_surface_
 
     /* BBox must be smaller than XStep by YStep or acroread wont
      * display the pattern. */
-
-    cairo_matrix_init_identity (&pm);
-    cairo_matrix_scale (&pm, image->width, image->height);
-    pm = pattern->base.matrix;
-    cairo_matrix_invert (&pm);
-
     stream = _cairo_pdf_document_open_stream (document,
-					      "   /BBox [ 0 0 256 256 ]\r\n"
-					      "   /XStep 256\r\n"
-					      "   /YStep 256\r\n"
+					      "   /BBox [ 0 0 %d %d ]\r\n"
+					      "   /XStep %d\r\n"
+					      "   /YStep %d\r\n"
 					      "   /PatternType 1\r\n"
 					      "   /TilingType 1\r\n"
 					      "   /PaintType 1\r\n"
 					      "   /Resources << /XObject << /res%d %d 0 R >> >>\r\n",
+					      image->width, image->height,
+					      image->width, image->height,
 					      id, id);
 
+    i2u = pattern->base.matrix;
+    cairo_matrix_invert (&i2u);
+    cairo_matrix_scale (&i2u, image->width, image->height);
 
     _cairo_output_stream_printf (output,
-				 " /res%d Do\r\n",
+				 "q %f %f %f %f %f %f cm /res%d Do Q\r\n",
+				 i2u.xx, i2u.yx,
+				 i2u.xy, i2u.yy,
+				 i2u.x0, i2u.y0,
 				 id);
 
     _cairo_pdf_surface_add_pattern (dst, stream->id);
@@ -2096,17 +2098,42 @@ _cairo_pdf_surface_paint (void			*abstra
 			  cairo_pattern_t	*source)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
+    cairo_pdf_document_t *document = surface->document;
+    cairo_status_t status;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+	return _analyze_operation (surface, op, source);
 
-    /* One would think that since we analyzed this away as unsupported
-     * that it would never be called after analyzing. But in fact,
-     * paint is called to paint the actual fallback surface. So we
-     * must not ASSERT_NOT_REACHED as we do for the other drawing
-     * operations. */
+    /* XXX: It would be nice to be able to assert this condition
+     * here. But, we actually allow one 'cheat' that is used when
+     * painting the final image-based fallbacks. The final fallbacks
+     * do have alpha which we support by blending with white. This is
+     * possible only because there is nothing between the fallback
+     * images and the paper, nor is anything painted above. */
+    /*
+    assert (_operation_supported (op, source));
+    */
+
+#if 0
+    if (source->type == CAIRO_PATTERN_TYPE_SURFACE)
+	return _cairo_pdf_surface_composite_image (surface, (cairo_surface_pattern_t *) source);
+#endif
 
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+    status = emit_pattern (surface, source);
+    if (status)
+	return status;
+
+    /* After emitting the pattern the current stream should belong to
+     * this surface, so no need to _cairo_pdf_surface_ensure_stream()
+     */
+    assert (document->current_stream != NULL &&
+	    document->current_stream == surface->current_stream);
+
+    _cairo_output_stream_printf (document->output_stream,
+				 "0 0 %f %f re f\r\n",
+				 surface->width, surface->height);
+
+    return _cairo_output_stream_get_status (document->output_stream);
 }
 
 static cairo_int_status_t
diff-tree 8be1697f2bd8026b28f2f24c2fab967ee01b6d8c (from a98b44a1deab5fd15607b50df63189a74a269909)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Apr 18 23:18:39 2006 -0700

    Fix stale code in comment.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 29b6882..1d73495 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1370,7 +1370,7 @@ _cairo_ps_surface_paint (void			*abstrac
      * possible only because there is nothing between the fallback
      * images and the paper, nor is anything painted above. */
     /*
-    assert (pattern_operation_supported (op, source));
+    assert (_operation_supported (op, source));
     */
     
     _cairo_output_stream_printf (stream,
diff-tree a98b44a1deab5fd15607b50df63189a74a269909 (from b1b699593b820ac4e011f89ad700f052b2f20205)
Author: Christian Biesinger <cbiesinger at web.de>
Date:   Wed Apr 19 02:34:24 2006 +0200

    Fixing bad merge
    
    The merge in 66ed9811cc542d99cb5a6b6b792c9a9f0832fbf9
    re-added this line, which makes cairo link to C++
    libraries even on non-BeOS systems.
    
    This was originally fixed in 69acfa6576e8d2b97e3e3b8c06badf5486ae0315

diff --git a/src/Makefile.am b/src/Makefile.am
index 4ccf327..a74338f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -196,7 +196,6 @@ libcairo_la_SOURCES =				\
 	$(libcairo_xcb_sources)			\
 	$(libcairo_glitz_sources)		\
 	$(libcairo_win32_sources)		\
-	$(libcairo_beos_sources)		\
 	$(libcairo_directfb_sources)		\
 	cairoint.h
 
diff-tree b1b699593b820ac4e011f89ad700f052b2f20205 (from efbe40bb8f770fbf60de794488803d3edacd7ed6)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Apr 18 16:53:23 2006 -0700

    Add support for _cairo_pdf_surface_stroke.
    
    Generalize all functions that emit a source pattern to emit both
    for the stroking and non-stroking PDF properties. Also add an
    implementation of _cairo_pdf_surface_stroke.
    
    With this commit in place, the following tests change from
    all-fallback to all-native output while no tests report any new
    failures:
    
    	dash-zero-legnth
    	fill-and-stroke
    	multi-page
    	new-sub-path
    	rel-path
    	self-intersecting

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 68c0271..ef08ffc 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1,6 +1,7 @@
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2004 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
@@ -32,6 +33,7 @@
  *
  * Contributor(s):
  *	Kristian Høgsberg <krh at redhat.com>
+ *	Carl Worth <cworth at cworth.org>
  */
 
 #include "cairoint.h"
@@ -897,11 +899,18 @@ emit_solid_pattern (cairo_pdf_surface_t 
     cairo_pdf_document_t *document = surface->document;
     cairo_output_stream_t *output = document->output_stream;
     unsigned int alpha;
-    
+
     alpha = _cairo_pdf_surface_add_alpha (surface, pattern->color.alpha);
     _cairo_pdf_surface_ensure_stream (surface);
+    /* With some work, we could separate the stroking
+     * or non-stroking color here as actually needed. */
     _cairo_output_stream_printf (output,
-				 "%f %f %f rg /a%d gs\r\n",
+				 "%f %f %f RG "
+				 "%f %f %f rg "
+				 "/a%d gs\r\n",
+				 pattern->color.red,
+				 pattern->color.green,
+				 pattern->color.blue,
 				 pattern->color.red,
 				 pattern->color.green,
 				 pattern->color.blue,
@@ -963,9 +972,13 @@ emit_surface_pattern (cairo_pdf_surface_
 
     _cairo_pdf_surface_ensure_stream (dst);
     alpha = _cairo_pdf_surface_add_alpha (dst, 1.0);
+    /* With some work, we could separate the stroking
+     * or non-stroking pattern here as actually needed. */
     _cairo_output_stream_printf (output,
-				 "/Pattern cs /res%d scn /a%d gs\r\n",
-				 stream->id, alpha);
+				 "/Pattern CS /res%d SCN "
+				 "/Pattern cs /res%d scn "
+				 "/a%d gs\r\n",
+				 stream->id, stream->id, alpha);
 
     _cairo_surface_release_source_image (pattern->surface, image, image_extra);
 
@@ -1167,9 +1180,13 @@ emit_linear_pattern (cairo_pdf_surface_t
     alpha = _cairo_pdf_surface_add_alpha (surface, 1.0);
 
     /* Use pattern */
+    /* With some work, we could separate the stroking
+     * or non-stroking pattern here as actually needed. */
     _cairo_output_stream_printf (output,
-				 "/Pattern cs /res%d scn /a%d gs\r\n",
-				 pattern_id, alpha);
+				 "/Pattern CS /res%d SCN "
+				 "/Pattern cs /res%d scn "
+				 "/a%d gs\r\n",
+				 pattern_id, pattern_id, alpha);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1238,13 +1255,17 @@ emit_radial_pattern (cairo_pdf_surface_t
     alpha = _cairo_pdf_surface_add_alpha (surface, 1.0);
 
     /* Use pattern */
+    /* With some work, we could separate the stroking
+     * or non-stroking pattern here as actually needed. */
     _cairo_output_stream_printf (output,
-				 "/Pattern cs /res%d scn /a%d gs\r\n",
-				 pattern_id, alpha);
+				 "/Pattern CS /res%d SCN "
+				 "/Pattern cs /res%d scn "
+				 "/a%d gs\r\n",
+				 pattern_id, pattern_id, alpha);
 
     return CAIRO_STATUS_SUCCESS;
 }
-	
+
 static cairo_status_t
 emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern)
 {
@@ -1965,10 +1986,12 @@ _cairo_pdf_document_add_page (cairo_pdf_
 				     "      /ExtGState <<\r\n");
 
 	for (i = 0; i < num_alphas; i++) {
+	    /* With some work, we could separate the stroking
+	     * or non-stroking alpha here as actually needed. */
 	    _cairo_array_copy_element (&surface->alphas, i, &alpha);
 	    _cairo_output_stream_printf (output,
-					 "         /a%d << /ca %f >>\r\n",
-					 i, alpha);
+					 "         /a%d << /CA %f /ca %f >>\r\n",
+					 i, alpha, alpha);
 	}
 
 	_cairo_output_stream_printf (output,
@@ -2102,6 +2125,71 @@ _cairo_pdf_surface_mask	(void			*abstrac
     return CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
+static int
+_cairo_pdf_line_cap (cairo_line_cap_t cap)
+{
+    switch (cap) {
+    case CAIRO_LINE_CAP_BUTT:
+	return 0;
+    case CAIRO_LINE_CAP_ROUND:
+	return 1;
+    case CAIRO_LINE_CAP_SQUARE:
+	return 2;
+    default:
+	ASSERT_NOT_REACHED;
+	return 0;
+    }
+}
+
+static int
+_cairo_pdf_line_join (cairo_line_join_t join)
+{
+    switch (join) {
+    case CAIRO_LINE_JOIN_MITER:
+	return 0;
+    case CAIRO_LINE_JOIN_ROUND:
+	return 1;
+    case CAIRO_LINE_JOIN_BEVEL:
+	return 2;
+    default:
+	ASSERT_NOT_REACHED;
+	return 0;
+    }
+}
+
+static cairo_status_t
+_cairo_pdf_surface_emit_stroke_style (cairo_pdf_surface_t	*surface,
+				      cairo_output_stream_t	*stream,
+				      cairo_stroke_style_t	*style)
+{
+    _cairo_output_stream_printf (stream,
+				 "%f w\r\n",
+				 style->line_width);
+
+    _cairo_output_stream_printf (stream,
+				 "%d J\r\n",
+				 _cairo_pdf_line_cap (style->line_cap));
+
+    _cairo_output_stream_printf (stream, 
+				 "%d j\r\n",
+				 _cairo_pdf_line_join (style->line_join));
+
+    if (style->num_dashes) {
+	int d;
+	_cairo_output_stream_printf (stream, "[");
+	for (d = 0; d < style->num_dashes; d++)
+	    _cairo_output_stream_printf (stream, " %f", style->dash[d]);
+	_cairo_output_stream_printf (stream, "] %f d\r\n",
+				     style->dash_offset);
+    }
+
+    _cairo_output_stream_printf (stream,
+				 "%f M ",
+				 style->miter_limit);
+
+    return _cairo_output_stream_get_status (stream);
+}
+
 static cairo_int_status_t
 _cairo_pdf_surface_stroke (void			*abstract_surface,
 			   cairo_operator_t	 op,
@@ -2114,13 +2202,41 @@ _cairo_pdf_surface_stroke (void			*abstr
 			   cairo_antialias_t	 antialias)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
+    cairo_pdf_document_t *document = surface->document;
+    cairo_status_t status;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+	return _analyze_operation (surface, op, source);
 
-    ASSERT_NOT_REACHED;
+    assert (_operation_supported (surface, op, source));
 
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+    status = emit_pattern (surface, source);
+    if (status)
+	return status;
+
+    /* After emitting the pattern the current stream should belong to
+     * this surface, so no need to _cairo_pdf_surface_ensure_stream()
+     */
+    assert (document->current_stream != NULL &&
+	    document->current_stream == surface->current_stream);
+
+    status = _cairo_pdf_surface_emit_stroke_style (surface,
+						   document->output_stream,
+						   style);
+    if (status)
+	return status;
+
+    status = _cairo_path_fixed_interpret (path,
+					  CAIRO_DIRECTION_FORWARD,
+					  _cairo_pdf_path_move_to,
+					  _cairo_pdf_path_line_to,
+					  _cairo_pdf_path_curve_to,
+					  _cairo_pdf_path_close_path,
+					  document->output_stream);
+
+    _cairo_output_stream_printf (document->output_stream, "S\r\n");
+
+    return status;
 }
 
 static cairo_int_status_t
diff-tree efbe40bb8f770fbf60de794488803d3edacd7ed6 (from eadb26a1c13da1af292f0262e108878133cbadf0)
Author: Christian Biesinger <cbiesinger at web.de>
Date:   Wed Apr 19 00:29:48 2006 +0200

    Use calloc rather than malloc+memset

diff --git a/pixman/src/icpixels.c b/pixman/src/icpixels.c
index 2ad34f4..c5efae9 100644
--- a/pixman/src/icpixels.c
+++ b/pixman/src/icpixels.c
@@ -65,12 +65,11 @@ FbPixelsCreate (int width, int height, i
 	adjust = 8 - (base & 7);
     buf_size += adjust;
 
-    pixels = malloc(base + buf_size);
+    pixels = calloc(base + buf_size, 1);
     if (!pixels)
 	return NULL;
 
     buf = (pixman_bits_t *) ((char *)pixels + base + adjust);
-    memset (buf, 0, height * stride);
 
     FbPixelsInit (pixels, buf, width, height, depth, bpp, stride);
 
diff --git a/pixman/src/ictrap.c b/pixman/src/ictrap.c
index 08bd024..72616f3 100644
--- a/pixman/src/ictrap.c
+++ b/pixman/src/ictrap.c
@@ -45,16 +45,12 @@ FbCreateAlphaPicture (pixman_image_t	*ds
 	    return NULL;
     }
 
+    /* pixman_image_create zeroes out the pixels, so we don't have to */
     image = pixman_image_create (format, width, height); 
 
     if (own_format)
 	pixman_format_destroy (format);
 
-    /* XXX: Is this a reasonable way to clear the image? Would
-       probably be preferable to use pixman_image_fill_rectangle once such a
-       beast exists. */
-    memset (image->pixels->data, 0, height * image->pixels->stride);
-
     return image;
 }
 
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index c000917..ab2d6eb 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -1140,7 +1140,7 @@ _cairo_glitz_surface_composite_trapezoid
 	int		      stride;
 
 	stride = (width + 3) & -4;
-	data = malloc (stride * height);
+	data = calloc (stride * height, 1);
 	if (!data)
 	{
 	    _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
@@ -1149,8 +1149,6 @@ _cairo_glitz_surface_composite_trapezoid
 	    return CAIRO_STATUS_NO_MEMORY;
 	}
 
-	memset (data, 0, stride * height);
-
 	/* using negative stride */
 	ptr = (unsigned char *) data + stride * (height - 1);
 
diff-tree eadb26a1c13da1af292f0262e108878133cbadf0 (from 448e904b2a64769aa9cfd8ea011c2b5fb6ec883b)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Apr 18 15:19:36 2006 -0700

    Add new PS-specific reference image for new-sub-path.

diff --git a/test/new-sub-path-ps-argb32-ref.png b/test/new-sub-path-ps-argb32-ref.png
new file mode 100644
index 0000000..23b7e75
Binary files /dev/null and b/test/new-sub-path-ps-argb32-ref.png differ
diff-tree 448e904b2a64769aa9cfd8ea011c2b5fb6ec883b (from parents)
Merge: cb778760cb87e727a701603bcea3a2cdc063d785 ffab2592fc5d0ccd498aff2f4e645eefe351b61b
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Apr 18 15:18:31 2006 -0700

    Merge branch 'cairo' into new-sub-path
    
    Conflicts:
    
    	src/cairo-path-stroke.c
    	src/cairo-pdf-surface.c
    	src/cairo-ps-surface.c

diff --cc src/cairo-path-stroke.c
index e817099,d6044a3..7ca6ab8
@@@ -620,7 -636,11 +633,8 @@@
      cairo_stroke_face_t start, end;
      cairo_point_t *p1 = &stroker->current_point;
      cairo_point_t *p2 = point;
+     cairo_slope_t slope;
  
 -    if (!stroker->has_current_point)
 -	return _cairo_stroker_move_to (stroker, point);
 -
      if (p1->x == p2->x && p1->y == p2->y) {
  	/* XXX: Need to rethink how this case should be handled, (both
             here and in cairo_stroker_add_sub_edge and in _compute_face). The
@@@ -667,6 -689,20 +683,17 @@@
      cairo_stroke_face_t sub_start, sub_end;
      cairo_point_t *p1 = &stroker->current_point;
      cairo_point_t *p2 = point;
+     cairo_slope_t slope;
+ 
 -    if (!stroker->has_current_point)
 -	return _cairo_stroker_move_to (stroker, point);
 -
+     if (p1->x == p2->x && p1->y == p2->y) {
+ 	/* XXX: Need to rethink how this case should be handled, (both
+            here and in cairo_stroker_add_sub_edge and in _compute_face). The
+            key behavior is that degenerate paths should draw as much
+            as possible. */
+ 	return CAIRO_STATUS_SUCCESS;
+     }
+ 
+     _cairo_slope_init (&slope, p1, p2);
  
      dx = _cairo_fixed_to_double (p2->x - p1->x);
      dy = _cairo_fixed_to_double (p2->y - p1->y);
diff --cc src/cairo-pdf-surface.c
index 0c024a2,836b3ae..68c0271
@@@ -2086,3 -2037,233 +2017,229 @@@
  
      return CAIRO_STATUS_SUCCESS;
  }
+ 
+ static cairo_bool_t
+ _surface_pattern_supported (const cairo_surface_pattern_t *pattern)
+ {
+     if (pattern->surface->backend->acquire_source_image != NULL)
+ 	return TRUE;
+ 
+     return FALSE;
+ }
+ 
+ static cairo_bool_t
+ _pattern_supported (const cairo_pattern_t *pattern)
+ {
+     if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
+ 	return TRUE;
+ 
+     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
+ 	return _surface_pattern_supported ((const cairo_surface_pattern_t *) pattern);
+ 	
+     return FALSE;
+ }
+ 
+ static cairo_int_status_t
+ _operation_supported (cairo_pdf_surface_t *surface,
+ 		      cairo_operator_t op,
+ 		      const cairo_pattern_t *pattern)
+ {
+     if (! _pattern_supported (pattern))
+ 	return FALSE;
+ 
+     if (_cairo_operator_always_opaque (op))
+ 	return TRUE;
+ 
+     if (_cairo_operator_always_translucent (op))
+ 	return FALSE;
+ 
+     return _cairo_pattern_is_opaque (pattern);
+ }
+ 
+ static cairo_int_status_t
+ _analyze_operation (cairo_pdf_surface_t *surface,
+ 		    cairo_operator_t op,
+ 		    const cairo_pattern_t *pattern)
+ {
+     if (_operation_supported (surface, op, pattern))
+ 	return CAIRO_STATUS_SUCCESS;
+     else
+ 	return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+ 
+ static cairo_int_status_t
+ _cairo_pdf_surface_paint (void			*abstract_surface,
+ 			  cairo_operator_t	 op,
+ 			  cairo_pattern_t	*source)
+ {
+     cairo_pdf_surface_t *surface = abstract_surface;
+ 
+     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ 	return CAIRO_INT_STATUS_UNSUPPORTED;
+ 
+     /* One would think that since we analyzed this away as unsupported
+      * that it would never be called after analyzing. But in fact,
+      * paint is called to paint the actual fallback surface. So we
+      * must not ASSERT_NOT_REACHED as we do for the other drawing
+      * operations. */
+ 
+     return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+ 
+ static cairo_int_status_t
+ _cairo_pdf_surface_mask	(void			*abstract_surface,
+ 			 cairo_operator_t	 op,
+ 			 cairo_pattern_t	*source,
+ 			 cairo_pattern_t	*mask)
+ {
+     cairo_pdf_surface_t *surface = abstract_surface;
+ 
+     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ 	return CAIRO_INT_STATUS_UNSUPPORTED;
+ 
+     ASSERT_NOT_REACHED;
+ 
+     return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+ 
+ static cairo_int_status_t
+ _cairo_pdf_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_pdf_surface_t *surface = abstract_surface;
+ 
+     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ 	return CAIRO_INT_STATUS_UNSUPPORTED;
+ 
+     ASSERT_NOT_REACHED;
+ 
+     return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+ 
+ static cairo_int_status_t
+ _cairo_pdf_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_pdf_surface_t *surface = abstract_surface;
+     cairo_pdf_document_t *document = surface->document;
+     const char *pdf_operator;
+     cairo_status_t status;
 -    pdf_path_info_t info;
+ 
+     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ 	return _analyze_operation (surface, op, source);
+ 
+     assert (_operation_supported (surface, op, source));
+ 
+     status = emit_pattern (surface, source);
+     if (status)
+ 	return status;
+ 
+     /* After emitting the pattern the current stream should belong to
+      * this surface, so no need to _cairo_pdf_surface_ensure_stream()
+      */
+     assert (document->current_stream != NULL &&
+ 	    document->current_stream == surface->current_stream);
+ 
 -    info.output_stream = document->output_stream;
 -    info.has_current_point = FALSE;
 -
+     status = _cairo_path_fixed_interpret (path,
+ 					  CAIRO_DIRECTION_FORWARD,
+ 					  _cairo_pdf_path_move_to,
+ 					  _cairo_pdf_path_line_to,
+ 					  _cairo_pdf_path_curve_to,
+ 					  _cairo_pdf_path_close_path,
 -					  &info);
++					  document->output_stream);
+ 
+     switch (fill_rule) {
+     case CAIRO_FILL_RULE_WINDING:
+ 	pdf_operator = "f";
+ 	break;
+     case CAIRO_FILL_RULE_EVEN_ODD:
+ 	pdf_operator = "f*";
+ 	break;
+     default:
+ 	ASSERT_NOT_REACHED;
+     }
+ 
+     _cairo_output_stream_printf (document->output_stream,
+ 				 "%s\r\n",
+ 				 pdf_operator);
+ 
+     return status;
+ }
+ 
+ static cairo_int_status_t
+ _cairo_pdf_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_pdf_surface_t *surface = abstract_surface;
+ 
+     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ 	return CAIRO_INT_STATUS_UNSUPPORTED;
+ 
+     ASSERT_NOT_REACHED;
+ 
+     return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+ 
+ static void
+ _cairo_pdf_surface_set_paginated_mode (void			*abstract_surface,
+ 				       cairo_paginated_mode_t	 paginated_mode)
+ {
+     cairo_pdf_surface_t *surface = abstract_surface;
+ 
+     surface->paginated_mode = paginated_mode;
+ }
+ 
+ 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 */
+     NULL, /* release_source_image */
+     NULL, /* acquire_dest_image */
+     NULL, /* release_dest_image */
+     NULL, /* clone_similar */
+     _cairo_pdf_surface_composite,
+     _cairo_pdf_surface_fill_rectangles,
+     _cairo_pdf_surface_composite_trapezoids,
+     _cairo_pdf_surface_copy_page,
+     _cairo_pdf_surface_show_page,
+     NULL, /* set_clip_region */
+     _cairo_pdf_surface_intersect_clip_path,
+     _cairo_pdf_surface_get_extents,
+     _cairo_pdf_surface_old_show_glyphs,
+     _cairo_pdf_surface_get_font_options,
+     NULL, /* flush */
+     NULL, /* mark_dirty_rectangle */
+     NULL, /* scaled_font_fini */
+     NULL, /* scaled_glyph_fini */
+ 
+     /* Here are the drawing functions */
+ 
+     _cairo_pdf_surface_paint,
+     _cairo_pdf_surface_mask,
+     _cairo_pdf_surface_stroke,
+     _cairo_pdf_surface_fill,
+     _cairo_pdf_surface_show_glyphs,
+     NULL, /* snapshot */
+ };
+ 
+ static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = {
+     NULL, /* start_page */
+     _cairo_pdf_surface_set_paginated_mode
+ };
diff --cc src/cairo-ps-surface.c
index 37053e9,19a835b..29b6882
@@@ -78,10 -107,79 +107,62 @@@
  
  #define PS_SURFACE_DPI_DEFAULT 300.0
  
- #if DONE_ADDING_FONTS_SUPPORT_BACK_AFTER_SWITCHING_TO_PAGINATED
- static cairo_int_status_t
- _cairo_ps_surface_write_font_subsets (cairo_ps_surface_t *surface);
- #endif
 -typedef struct
 -{
 -    cairo_output_stream_t *output_stream;
 -    cairo_bool_t has_current_point;
 -} cairo_ps_surface_path_info_t;
 -
+ static cairo_status_t
+ _cairo_ps_surface_path_move_to (void *closure, cairo_point_t *point)
+ {
 -    cairo_ps_surface_path_info_t *info = closure;
++    cairo_output_stream_t *output_stream = closure;
+ 
 -    _cairo_output_stream_printf (info->output_stream,
 -				 "%f %f M ",
++    _cairo_output_stream_printf (output_stream,
++				 "%f %f moveto ",
+ 				 _cairo_fixed_to_double (point->x),
+ 				 _cairo_fixed_to_double (point->y));
 -    info->has_current_point = TRUE;
+     
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
+ static cairo_status_t
+ _cairo_ps_surface_path_line_to (void *closure, cairo_point_t *point)
+ {
 -    cairo_ps_surface_path_info_t *info = closure;
 -    const char *ps_operator;
++    cairo_output_stream_t *output_stream = closure;
+ 
 -    if (info->has_current_point)
 -	ps_operator = "L";
 -    else
 -	ps_operator = "M";
 -    
 -    _cairo_output_stream_printf (info->output_stream,
 -				 "%f %f %s ",
++    _cairo_output_stream_printf (output_stream,
++				 "%f %f lineto ",
+ 				 _cairo_fixed_to_double (point->x),
 -				 _cairo_fixed_to_double (point->y),
 -				 ps_operator);
 -    info->has_current_point = TRUE;
++				 _cairo_fixed_to_double (point->y));
+ 
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
+ static cairo_status_t
+ _cairo_ps_surface_path_curve_to (void          *closure,
 -			  cairo_point_t *b,
 -			  cairo_point_t *c,
 -			  cairo_point_t *d)
++				 cairo_point_t *b,
++				 cairo_point_t *c,
++				 cairo_point_t *d)
+ {
 -    cairo_ps_surface_path_info_t *info = closure;
++    cairo_output_stream_t *output_stream = closure;
+ 
 -    _cairo_output_stream_printf (info->output_stream,
 -				 "%f %f %f %f %f %f C ",
++    _cairo_output_stream_printf (output_stream,
++				 "%f %f %f %f %f %f curveto ",
+ 				 _cairo_fixed_to_double (b->x),
+ 				 _cairo_fixed_to_double (b->y),
+ 				 _cairo_fixed_to_double (c->x),
+ 				 _cairo_fixed_to_double (c->y),
+ 				 _cairo_fixed_to_double (d->x),
+ 				 _cairo_fixed_to_double (d->y));
+     
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
+ static cairo_status_t
+ _cairo_ps_surface_path_close_path (void *closure)
+ {
 -    cairo_ps_surface_path_info_t *info = closure;
++    cairo_output_stream_t *output_stream = closure;
+     
 -    if (info->has_current_point)
 -        _cairo_output_stream_printf (info->output_stream,
 -				     "P\n");
 -    info->has_current_point = FALSE;
++    _cairo_output_stream_printf (output_stream,
++				 "closepath\n");
+ 
+     return CAIRO_STATUS_SUCCESS;
+ }
  
  static void
  _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
@@@ -101,13 -200,325 +183,321 @@@
  				 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"
+     _cairo_output_stream_printf (surface->final_stream,
+ 				 "%%%%DocumentData: Clean7Bit\n"
+ 				 "%%%%LanguageLevel: 2\n"
  				 "%%%%Orientation: Portrait\n"
  				 "%%%%EndComments\n");
+ 
+     _cairo_output_stream_printf (surface->final_stream,
+ 				 "%%%%BeginProlog\n"
+ 				 "/C{curveto}bind def\n"
+ 				 "/F{fill}bind def\n"
+ 				 "/G{setgray}bind def\n"
+ 				 "/L{lineto}bind def\n"
+ 				 "/M{moveto}bind def\n"
+ 				 "/P{closepath}bind def\n"
+ 				 "/R{setrgbcolor}bind def\n"
+ 				 "/S{show}bind def\n"
+ 				 "%%%%EndProlog\n");
+ }
+ 
+ static cairo_bool_t
+ _cairo_ps_glyph_equal (const void *key_a, const void *key_b)
+ {
+     const cairo_ps_glyph_t   *ps_glyph_a = key_a;
+     const cairo_ps_glyph_t   *ps_glyph_b = key_b;
+ 
+     return ps_glyph_a->base.hash == ps_glyph_b->base.hash;
+ }
+ 
+ static void
+ _cairo_ps_glyph_key_init (cairo_ps_glyph_t  *ps_glyph,
+ 			  unsigned long	    index)
+ {
+     ps_glyph->base.hash = index;
+ }
+ 
+ static cairo_ps_glyph_t *
+ _cairo_ps_glyph_create (cairo_ps_font_t *ps_font,
+ 			unsigned long index)
+ {
+     cairo_ps_glyph_t	*ps_glyph = malloc (sizeof (cairo_ps_glyph_t));
+ 
+     if (!ps_glyph)
+ 	return NULL;
+     _cairo_ps_glyph_key_init (ps_glyph, index);
+     ps_glyph->output_glyph = ps_font->max_glyph++;
+     return ps_glyph;
+ }
+ 
+ static void
+ _cairo_ps_glyph_destroy (cairo_ps_glyph_t *ps_glyph)
+ {
+     free (ps_glyph);
+ }
+ 
+ static cairo_status_t
+ _cairo_ps_glyph_find (cairo_ps_font_t	    *font,
+ 		      cairo_scaled_font_t   *scaled_font,
+ 		      unsigned long	    index,
+ 		      cairo_ps_glyph_t	    **result)
+ {
+     cairo_ps_glyph_t	key;
+     cairo_ps_glyph_t	*ps_glyph;
+     cairo_status_t	status;
+ 
+     _cairo_ps_glyph_key_init (&key, index);
+     if (!_cairo_hash_table_lookup (font->glyphs, 
+ 				   &key.base, 
+ 				   (cairo_hash_entry_t **) &ps_glyph)) {
+ 	ps_glyph = _cairo_ps_glyph_create (font, index);
+ 	if (!ps_glyph)
+ 	    return CAIRO_STATUS_NO_MEMORY;
+ 	status = _cairo_hash_table_insert (font->glyphs, &ps_glyph->base);
+ 	if (status)
+ 	    return status;
+     }
+     *result = ps_glyph;
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
+ static cairo_bool_t
+ _cairo_ps_font_equal (const void *key_a, const void *key_b)
+ {
+     const cairo_ps_font_t   *ps_font_a = key_a;
+     const cairo_ps_font_t   *ps_font_b = key_b;
+ 
+     return ps_font_a->scaled_font == ps_font_b->scaled_font;
+ }
+ 
+ static void
+ _cairo_ps_font_key_init (cairo_ps_font_t	*ps_font,
+ 			 cairo_scaled_font_t	*scaled_font)
+ {
+     ps_font->base.hash = (unsigned long) scaled_font;
+     ps_font->scaled_font = scaled_font;
+ }
+ 
+ static cairo_ps_font_t *
+ _cairo_ps_font_create (cairo_ps_surface_t   *surface,
+ 		       cairo_scaled_font_t  *scaled_font)
+ {
+     cairo_ps_font_t *ps_font = malloc (sizeof (cairo_ps_font_t));
+     if (!ps_font)
+ 	return NULL;
+     _cairo_ps_font_key_init (ps_font, scaled_font);
+     ps_font->glyphs = _cairo_hash_table_create (_cairo_ps_glyph_equal);
+     if (!ps_font->glyphs) {
+ 	free (ps_font);
+ 	return NULL;
+     }
+     ps_font->max_glyph = 0;
+     ps_font->output_font = surface->max_font++;
+     cairo_scaled_font_reference (ps_font->scaled_font);
+     return ps_font;
+ }
+ 
+ static void
+ _cairo_ps_font_destroy_glyph (void *entry, void *closure)
+ {
+     cairo_ps_glyph_t	*ps_glyph = entry;
+     cairo_ps_font_t	*ps_font = closure;
+     
+     _cairo_hash_table_remove (ps_font->glyphs, &ps_glyph->base);
+     _cairo_ps_glyph_destroy (ps_glyph);
+ }
+ 
+ static void
+ _cairo_ps_font_destroy (cairo_ps_font_t *ps_font)
+ {
+     _cairo_hash_table_foreach (ps_font->glyphs,
+ 			       _cairo_ps_font_destroy_glyph,
+ 			       ps_font);
+     _cairo_hash_table_destroy (ps_font->glyphs);
+     cairo_scaled_font_destroy (ps_font->scaled_font);
+     free (ps_font);
+ }
+ 
+ static void
+ _cairo_ps_surface_destroy_font (cairo_ps_surface_t *surface,
+ 				cairo_ps_font_t *ps_font)
+ {
+     _cairo_hash_table_remove (surface->fonts, &ps_font->base);
+     _cairo_ps_font_destroy (ps_font);
+ }
+ 
+ static cairo_status_t
+ _cairo_ps_font_find (cairo_ps_surface_t	    *surface,
+ 		     cairo_scaled_font_t    *scaled_font,
+ 		     cairo_ps_font_t	    **result)
+ {
+     cairo_ps_font_t	key;
+     cairo_ps_font_t	*ps_font;
+     cairo_status_t	status;
+ 
+     _cairo_ps_font_key_init (&key, scaled_font);
+     if (!_cairo_hash_table_lookup (surface->fonts, &key.base,
+ 				   (cairo_hash_entry_t **) &ps_font)) 
+     {
+ 	ps_font = _cairo_ps_font_create (surface, scaled_font);
+ 	if (!ps_font)
+ 	    return CAIRO_STATUS_NO_MEMORY;
+ 	status = _cairo_hash_table_insert (surface->fonts,
+ 					   &ps_font->base);
+ 	if (status)
+ 	    return status;
+     }
+     *result = ps_font;
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
+ typedef struct _cairo_ps_font_glyph_select {
+     cairo_ps_glyph_t	**glyphs;
+     int			subfont;
+     int			numglyph;
+ } cairo_ps_font_glyph_select_t;
+ 
+ static void
+ _cairo_ps_font_select_glyphs (void *entry, void *closure)
+ {
+     cairo_ps_glyph_t		    *ps_glyph = entry;
+     cairo_ps_font_glyph_select_t    *ps_glyph_select = closure;
+ 
+     if (ps_glyph->output_glyph >> 8 == ps_glyph_select->subfont) {
+ 	unsigned long	sub_glyph = ps_glyph->output_glyph & 0xff;
+ 	ps_glyph_select->glyphs[sub_glyph] = ps_glyph;
+ 	if (sub_glyph >= ps_glyph_select->numglyph)
+ 	    ps_glyph_select->numglyph = sub_glyph + 1;
+     }
+ }
+ 
+ static cairo_status_t
+ _cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface,
+ 			      cairo_ps_font_t *ps_font,
+ 			      cairo_ps_glyph_t *ps_glyph)
+ {
+     cairo_scaled_glyph_t    *scaled_glyph;
+     cairo_status_t	    status;
 -    cairo_ps_surface_path_info_t info;
+     
+     _cairo_output_stream_printf (surface->final_stream,
+ 				 "\t\t{ %% %d\n", ps_glyph->output_glyph);
+     status = _cairo_scaled_glyph_lookup (ps_font->scaled_font,
+ 					 ps_glyph->base.hash,
+ 					 CAIRO_SCALED_GLYPH_INFO_METRICS|
+ 					 CAIRO_SCALED_GLYPH_INFO_PATH,
+ 					 &scaled_glyph);
+     /*
+      * If that fails, try again but ask for an image instead
+      */
+     if (status)
+ 	status = _cairo_scaled_glyph_lookup (ps_font->scaled_font,
+ 					     ps_glyph->base.hash,
+ 					     CAIRO_SCALED_GLYPH_INFO_METRICS|
+ 					     CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ 					     &scaled_glyph);
+     if (status) {
+ 	_cairo_output_stream_printf (surface->final_stream, "\t\t}\n");
+ 	return status;
+     }
+     _cairo_output_stream_printf (surface->final_stream,
+ 				 "%f %f %f %f 0 0 setcachedevice\n",
+ 				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
+ 				 -_cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
+ 				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
+ 				 -_cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
+     
 -    info.output_stream = surface->final_stream;
 -    info.has_current_point = FALSE;
 -
+     status = _cairo_path_fixed_interpret (scaled_glyph->path,
+ 					  CAIRO_DIRECTION_FORWARD,
+ 					  _cairo_ps_surface_path_move_to,
+ 					  _cairo_ps_surface_path_line_to,
+ 					  _cairo_ps_surface_path_curve_to,
+ 					  _cairo_ps_surface_path_close_path,
 -					  &info);
++					  surface->final_stream);
+     
+     _cairo_output_stream_printf (surface->final_stream,
+ 				 "F\n");
+     
+     _cairo_output_stream_printf (surface->final_stream,
+ 				 "\t\t}\n");
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
+ static void
+ _cairo_ps_surface_emit_font (void *entry, void *closure)
+ {
+     cairo_ps_font_t *ps_font = entry;
+     cairo_ps_surface_t *surface = closure;
+     cairo_ps_font_glyph_select_t glyph_select;
+     cairo_ps_glyph_t *ps_glyphs[256], *ps_glyph;
+     int glyph, numglyph;
+     int subfont, nsubfont;
+ 
+     _cairo_output_stream_printf (surface->final_stream,
+ 				 "%% _cairo_ps_surface_emit_font\n");
+     nsubfont = (ps_font->max_glyph >> 8) + 1;
+     for (subfont = 0; subfont < nsubfont; subfont++) {
+ 	_cairo_output_stream_printf (surface->final_stream,
+ 				     "/CairoFont-%d-%d <<\n",
+ 				     ps_font->output_font,
+ 				     subfont);
+ 	memset (ps_glyphs, '\0', sizeof (ps_glyphs));
+         glyph_select.glyphs = ps_glyphs;
+ 	glyph_select.numglyph = 0;
+ 	glyph_select.subfont = subfont;
+ 	_cairo_hash_table_foreach (ps_font->glyphs, 
+ 				   _cairo_ps_font_select_glyphs,
+ 				   &glyph_select);
+ 	_cairo_output_stream_printf (surface->final_stream,
+ 				     "\t/FontType\t3\n"
+ 				     "\t/FontMatrix\t[1 0 0 1 0 0]\n"
+ 				     "\t/Encoding\t[0]\n"
+ 				     "\t/FontBBox\t[0 0 10 10]\n"
+ 				     "\t/Glyphs [\n");
+ 	numglyph = glyph_select.numglyph;
+ 	for (glyph = 0; glyph < numglyph; glyph++) {
+ 	    ps_glyph = ps_glyphs[glyph];
+ 	    if (ps_glyph) {
+ 		_cairo_ps_surface_emit_glyph (surface,
+ 					      ps_font,
+ 					      ps_glyph);
+ 	    } else {
+ 		_cairo_output_stream_printf (surface->final_stream,
+ 					     "\t\t{ } %% %d\n", glyph);
+ 	    }
+ 	    _cairo_ps_font_destroy_glyph (ps_glyph, ps_font);
+ 	}
+ 	_cairo_output_stream_printf (surface->final_stream,
+ 				     "\t]\n"
+ 				     "\t/BuildChar {\n"
+ 				     "\t\texch /Glyphs get\n"
+ 				     "\t\texch get exec\n"
+ 				     "\t}\n"
+ 				     ">> definefont pop\n");
+     }
+     _cairo_ps_surface_destroy_font (surface, ps_font);
+ }
+ 
+ 
+ static void
+ _cairo_ps_surface_emit_fonts (cairo_ps_surface_t *surface)
+ {
+     _cairo_hash_table_foreach (surface->fonts, 
+ 			       _cairo_ps_surface_emit_font,
+ 			       surface);
+     _cairo_hash_table_destroy (surface->fonts);
+     surface->fonts = NULL;
+ }
+ 
+ static void
+ _cairo_ps_surface_emit_body (cairo_ps_surface_t *surface)
+ {
+     char    buf[4096];
+     int	    n;
+     
+     rewind (surface->tmpfile);
+     while ((n = fread (buf, 1, sizeof (buf), surface->tmpfile)) > 0)
+ 	_cairo_output_stream_write (surface->final_stream, buf, n);
  }
  
  static void
@@@ -1117,8 -1315,12 +1294,11 @@@
      cairo_ps_surface_t *surface = abstract_surface;
      cairo_output_stream_t *stream = surface->stream;
      cairo_status_t status;
 -    cairo_ps_surface_path_info_t info;
      const char *ps_operator;
  
+     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ 	return CAIRO_STATUS_SUCCESS;
+ 
      _cairo_output_stream_printf (stream,
  				 "%% _cairo_ps_surface_intersect_clip_path\n");
  
@@@ -1189,64 -1384,146 +1359,137 @@@
  {
      cairo_ps_surface_t *surface = abstract_surface;
      cairo_output_stream_t *stream = surface->stream;
-     cairo_font_subset_t *subset;
-     int i, subset_index;
 -    cairo_ps_surface_path_info_t info;
  
-     if (surface->fallback)
- 	return CAIRO_STATUS_SUCCESS;
+     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ 	return _analyze_operation (surface, op, source);
  
-     if (surface->need_start_page)
- 	_cairo_ps_surface_start_page (surface);
+     /* XXX: It would be nice to be able to assert this condition
+      * here. But, we actually allow one 'cheat' that is used when
+      * painting the final image-based fallbacks. The final fallbacks
+      * do have alpha which we support by blending with white. This is
+      * possible only because there is nothing between the fallback
+      * images and the paper, nor is anything painted above. */
+     /*
+     assert (pattern_operation_supported (op, source));
+     */
+     
+     _cairo_output_stream_printf (stream,
+ 				 "%% _cairo_ps_surface_paint\n");
  
-     /* XXX: Need to fix this to work with a general cairo_scaled_font_t. */
-     if (! _cairo_scaled_font_is_ft (scaled_font))
- 	return CAIRO_INT_STATUS_UNSUPPORTED;
+     emit_pattern (surface, source);
  
-     if (surface->fallback)
- 	return CAIRO_STATUS_SUCCESS;
 -    info.output_stream = stream;
 -    info.has_current_point = FALSE;
 -
+     _cairo_output_stream_printf (stream, "0 0 M\n");
+     _cairo_output_stream_printf (stream, "%f 0 L\n", surface->width);
+     _cairo_output_stream_printf (stream, "%f %f L\n",
+ 				 surface->width, surface->height);
+     _cairo_output_stream_printf (stream, "0 %f L\n", surface->height);
+     _cairo_output_stream_printf (stream, "P F\n");
+     return CAIRO_STATUS_SUCCESS;
+ }
  
-     if (pattern_operation_needs_fallback (op, pattern))
- 	return _cairo_ps_surface_add_fallback_area (surface, dest_x, dest_y, width, height);
+ static int
+ _cairo_ps_line_cap (cairo_line_cap_t cap)
+ {
+     switch (cap) {
+     case CAIRO_LINE_CAP_BUTT:
+ 	return 0;
+     case CAIRO_LINE_CAP_ROUND:
+ 	return 1;
+     case CAIRO_LINE_CAP_SQUARE:
+ 	return 2;
+     default:
+ 	ASSERT_NOT_REACHED;
+ 	return 0;
+     }
+ }
  
-     _cairo_output_stream_printf (stream,
- 				 "%% _cairo_ps_surface_old_show_glyphs\n");
+ static int
+ _cairo_ps_line_join (cairo_line_join_t join)
+ {
+     switch (join) {
+     case CAIRO_LINE_JOIN_MITER:
+ 	return 0;
+     case CAIRO_LINE_JOIN_ROUND:
+ 	return 1;
+     case CAIRO_LINE_JOIN_BEVEL:
+ 	return 2;
+     default:
+ 	ASSERT_NOT_REACHED;
+ 	return 0;
+     }
+ }
  
-     emit_pattern (surface, pattern);
+ static cairo_int_status_t
+ _cairo_ps_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_ps_surface_t *surface = abstract_surface;
+     cairo_output_stream_t *stream = surface->stream;
+     cairo_int_status_t status;
 -    cairo_ps_surface_path_info_t info;
  
-     /* FIXME: Need to optimize this so we only do this sequence if the
-      * font isn't already set. */
+     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ 	return _analyze_operation (surface, op, source);
  
-     subset = _cairo_ps_surface_get_font (surface, scaled_font);
+     assert (operation_supported (surface, op, source));
+     
      _cairo_output_stream_printf (stream,
- 				 "/f%d findfont\n"
- 				 "[ %f %f %f %f 0 0 ] makefont\n"
- 				 "setfont\n",
- 				 subset->font_id,
- 				 scaled_font->scale.xx,
- 				 scaled_font->scale.yx,
- 				 scaled_font->scale.xy,
- 				 -scaled_font->scale.yy);
- 
-     /* FIXME: Need to optimize per glyph code.  Should detect when
-      * glyphs share the same baseline and when the spacing corresponds
-      * to the glyph widths. */
+ 				 "%% _cairo_ps_surface_stroke\n");
  
-     for (i = 0; i < num_glyphs; i++) {
- 	subset_index = _cairo_font_subset_use_glyph (subset, glyphs[i].index);
- 	_cairo_output_stream_printf (stream,
- 				     "%f %f moveto (\\%o) show\n",
- 				     glyphs[i].x,
- 				     glyphs[i].y,
- 				     subset_index);
- 	
-     }
+     emit_pattern (surface, source);
  
-     return CAIRO_STATUS_SUCCESS;
 -    
 -    info.output_stream = stream;
 -    info.has_current_point = FALSE;
 -
+     _cairo_output_stream_printf (stream,
+ 				 "gsave\n");
+     status = _cairo_path_fixed_interpret (path,
+ 					  CAIRO_DIRECTION_FORWARD,
+ 					  _cairo_ps_surface_path_move_to,
+ 					  _cairo_ps_surface_path_line_to,
+ 					  _cairo_ps_surface_path_curve_to,
+ 					  _cairo_ps_surface_path_close_path,
 -					  &info);
++					  stream);
+ 
+     /*
+      * Switch to user space to set line parameters
+      */
+     _cairo_output_stream_printf (stream,
+ 				 "[%f %f %f %f 0 0] concat\n",
+ 				 ctm->xx, ctm->yx, ctm->xy, ctm->yy);
+     /* line width */
+     _cairo_output_stream_printf (stream, "%f setlinewidth\n",
+ 				 style->line_width);
+     /* line cap */
+     _cairo_output_stream_printf (stream, "%d setlinecap\n",
+ 				 _cairo_ps_line_cap (style->line_cap));
+     /* line join */
+     _cairo_output_stream_printf (stream, "%d setlinejoin\n",
+ 				 _cairo_ps_line_join (style->line_join));
+     /* dashes */
+     if (style->num_dashes) {
+ 	int d;
+ 	_cairo_output_stream_printf (stream, "[");
+ 	for (d = 0; d < style->num_dashes; d++)
+ 	    _cairo_output_stream_printf (stream, " %f", style->dash[d]);
+ 	_cairo_output_stream_printf (stream, "] %f setdash\n",
+ 				     style->dash_offset);
+     }
+     /* miter limit */
+     _cairo_output_stream_printf (stream, "%f setmiterlimit\n",
+ 				 style->miter_limit);
+     _cairo_output_stream_printf (stream,
+ 				 "stroke\n");
+     _cairo_output_stream_printf (stream,
+ 				 "grestore\n");
+     return status;
  }
- #endif
  
  static cairo_int_status_t
- _cairo_ps_surface_fill (void			*abstract_surface,
+ _cairo_ps_surface_fill (void		*abstract_surface,
  		 cairo_operator_t	 op,
  		 cairo_pattern_t	*source,
  		 cairo_path_fixed_t	*path,
@@@ -1257,17 -1534,14 +1500,13 @@@
      cairo_ps_surface_t *surface = abstract_surface;
      cairo_output_stream_t *stream = surface->stream;
      cairo_int_status_t status;
 -    cairo_ps_surface_path_info_t info;
      const char *ps_operator;
  
-     if (pattern_operation_needs_fallback (op, source))
- 	return _cairo_ps_surface_add_fallback_area (surface,
- 					     0, 0,
- 					     surface->width,
- 					     surface->height);
- 
-     if (surface->need_start_page)
- 	_cairo_ps_surface_start_page (surface);
+     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ 	return _analyze_operation (surface, op, source);
  
+     assert (operation_supported (surface, op, source));
+     
      _cairo_output_stream_printf (stream,
  				 "%% _cairo_ps_surface_fill\n");
  
diff-tree ffab2592fc5d0ccd498aff2f4e645eefe351b61b (from 9c65dee86b469c1eedf2690334d5a2b4afc849c8)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date:   Tue Apr 18 21:52:06 2006 +0200

    Clear completely the temporary surface between each subtest in mask.c
    
    That helps SVG backend to pass this test, since CAIRO_OPERATOR_CLEAR on a part of a surface use "comp-op" element which is not supported with current librsvg.

diff --git a/test/mask.c b/test/mask.c
index a9414e0..6d0e458 100644
--- a/test/mask.c
+++ b/test/mask.c
@@ -213,12 +213,10 @@ draw (cairo_t *cr, int width, int height
 		int x = i * (WIDTH + PAD) + PAD;
 		int y = (ARRAY_SIZE (mask_funcs) * k + j) * (HEIGHT + PAD) + PAD;
 		
-		/* Clear area we are going to be drawing onto */
+		/* Clear intermediate surface we are going to be drawing onto */
 		cairo_save (cr2);
-		cairo_set_source_rgba (cr2, 0, 0, 0, 0); /* transparent */
-		cairo_set_operator (cr2, CAIRO_OPERATOR_SOURCE);
-		cairo_rectangle (cr2, x, y, WIDTH, HEIGHT);
-		cairo_fill (cr2);
+		cairo_set_operator (cr2, CAIRO_OPERATOR_CLEAR);
+		cairo_paint (cr2);
 		cairo_restore (cr2);
 
 		/* draw */
diff-tree 9c65dee86b469c1eedf2690334d5a2b4afc849c8 (from parents)
Merge: 36fb36fe8c4d8b2ac2b2de3f53842ae196bdca04 3f84df97ddd639c9e1d3706be7c9c86eba22c5bb
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date:   Tue Apr 18 21:23:59 2006 +0200

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

diff-tree 36fb36fe8c4d8b2ac2b2de3f53842ae196bdca04 (from 170a028bfa00286324d8598d831e570d868a26f1)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date:   Tue Apr 18 21:22:58 2006 +0200

    SVG: Add validating ref file for unantialias tests.
    
    Antialias property is not directly supported by SVG, and probably not the most wanted feature. In the future, we could use an image fallback in order to emulate it, or try to use text-rendering, shape-rendering and image-rendering
    properties (http://www.w3.org/TR/SVG/painting.html#RenderingProperties).

diff --git a/test/text-antialias-none-svg-argb32-ref.png b/test/text-antialias-none-svg-argb32-ref.png
new file mode 100644
index 0000000..aa64fbb
Binary files /dev/null and b/test/text-antialias-none-svg-argb32-ref.png differ
diff --git a/test/text-antialias-none-svg-rgb24-ref.png b/test/text-antialias-none-svg-rgb24-ref.png
new file mode 100644
index 0000000..aa64fbb
Binary files /dev/null and b/test/text-antialias-none-svg-rgb24-ref.png differ
diff --git a/test/text-antialias-subpixel-svg-argb32-ref.png b/test/text-antialias-subpixel-svg-argb32-ref.png
new file mode 100644
index 0000000..aa64fbb
Binary files /dev/null and b/test/text-antialias-subpixel-svg-argb32-ref.png differ
diff --git a/test/text-antialias-subpixel-svg-rgb24-ref.png b/test/text-antialias-subpixel-svg-rgb24-ref.png
new file mode 100644
index 0000000..aa64fbb
Binary files /dev/null and b/test/text-antialias-subpixel-svg-rgb24-ref.png differ
diff --git a/test/unantialiased-shapes-svg-argb32-ref.png b/test/unantialiased-shapes-svg-argb32-ref.png
new file mode 100644
index 0000000..da29773
Binary files /dev/null and b/test/unantialiased-shapes-svg-argb32-ref.png differ
diff --git a/test/unantialiased-shapes-svg-rgb24-ref.png b/test/unantialiased-shapes-svg-rgb24-ref.png
new file mode 100644
index 0000000..da29773
Binary files /dev/null and b/test/unantialiased-shapes-svg-rgb24-ref.png differ
diff-tree 3f84df97ddd639c9e1d3706be7c9c86eba22c5bb (from 170a028bfa00286324d8598d831e570d868a26f1)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Apr 18 11:31:59 2006 -0700

    Enable real analysis for _cairo_pdf_surface_paint.
    
    After this patch we have three PDF tests passing with native output:
    
    	clip-all
    	fill-rule
    	nil-surface

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 9f4e590..836b3ae 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -2038,6 +2038,55 @@ _cairo_pdf_document_add_page (cairo_pdf_
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_bool_t
+_surface_pattern_supported (const cairo_surface_pattern_t *pattern)
+{
+    if (pattern->surface->backend->acquire_source_image != NULL)
+	return TRUE;
+
+    return FALSE;
+}
+
+static cairo_bool_t
+_pattern_supported (const cairo_pattern_t *pattern)
+{
+    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
+	return TRUE;
+
+    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
+	return _surface_pattern_supported ((const cairo_surface_pattern_t *) pattern);
+	
+    return FALSE;
+}
+
+static cairo_int_status_t
+_operation_supported (cairo_pdf_surface_t *surface,
+		      cairo_operator_t op,
+		      const cairo_pattern_t *pattern)
+{
+    if (! _pattern_supported (pattern))
+	return FALSE;
+
+    if (_cairo_operator_always_opaque (op))
+	return TRUE;
+
+    if (_cairo_operator_always_translucent (op))
+	return FALSE;
+
+    return _cairo_pattern_is_opaque (pattern);
+}
+
+static cairo_int_status_t
+_analyze_operation (cairo_pdf_surface_t *surface,
+		    cairo_operator_t op,
+		    const cairo_pattern_t *pattern)
+{
+    if (_operation_supported (surface, op, pattern))
+	return CAIRO_STATUS_SUCCESS;
+    else
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
 static cairo_int_status_t
 _cairo_pdf_surface_paint (void			*abstract_surface,
 			  cairo_operator_t	 op,
@@ -2109,18 +2158,18 @@ _cairo_pdf_surface_fill (void			*abstrac
     cairo_status_t status;
     pdf_path_info_t info;
 
-    /* XXX: Temporarily disabling all "native" PDF output---will be
-     * switching to real analysis shortly. */
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    ASSERT_NOT_REACHED;
+	return _analyze_operation (surface, op, source);
+
+    assert (_operation_supported (surface, op, source));
 
     status = emit_pattern (surface, source);
     if (status)
 	return status;
 
-    /* After the above switch the current stream should belong to this
-     * surface, so no need to _cairo_pdf_surface_ensure_stream() */
+    /* After emitting the pattern the current stream should belong to
+     * this surface, so no need to _cairo_pdf_surface_ensure_stream()
+     */
     assert (document->current_stream != NULL &&
 	    document->current_stream == surface->current_stream);
 
diff-tree 170a028bfa00286324d8598d831e570d868a26f1 (from 9e2a2ea0da93065c46a6d6249f98a319ee6158dd)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date:   Mon Apr 17 23:26:30 2006 +0200

    SVG: Fix mask and try to support CAIRO_CONTENT_ALPHA.
    
    Cairo and SVG differ in their implementation of mask. Cairo only uses alpha channel where SVG uses all channels. So, before using a surface for masking, we use a filter that sets RGB channels to 1.0.
    
    Support for CAIRO_CONTENT_ALPHA is similar and use the same filter when a SVG alpha surface is composited.

diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index da38a1e..447abf8 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -75,6 +75,8 @@ struct cairo_svg_document {
     unsigned int filter_id;
     unsigned int clip_id;
     unsigned int mask_id;
+
+    cairo_bool_t alpha_filter;
 };
 
 struct cairo_svg_surface {
@@ -332,6 +334,29 @@ _cairo_svg_surface_finish (void *abstrac
 }
 
 static void
+emit_alpha_filter (cairo_svg_document_t *document)
+{
+    if (!document->alpha_filter) {
+	xmlNodePtr node;
+	xmlNodePtr child;
+
+	node = xmlNewChild (document->xml_node_defs, NULL,
+			    CC2XML ("filter"), NULL);
+	xmlSetProp (node, CC2XML ("id"), CC2XML ("alpha"));
+	xmlSetProp (node, CC2XML ("filterUnits"), CC2XML ("objectBoundingBox"));
+	xmlSetProp (node, CC2XML ("x"), CC2XML ("0%"));
+	xmlSetProp (node, CC2XML ("y"), CC2XML ("0%"));
+	xmlSetProp (node, CC2XML ("width"), CC2XML ("100%"));
+	xmlSetProp (node, CC2XML ("height"), CC2XML ("100%"));
+	child = xmlNewChild (node, NULL, CC2XML ("feColorMatrix"), NULL);
+	xmlSetProp (child, CC2XML("type"), CC2XML ("matrix"));
+	xmlSetProp (child, CC2XML("in"), CC2XML ("SourceGraphic"));
+	xmlSetProp (child, CC2XML("values"), CC2XML ("0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0")); 
+	document->alpha_filter = TRUE;
+    }
+}
+
+static void
 emit_transform (xmlNodePtr node, 
 		char const *attribute_str, 
 		cairo_matrix_t *matrix)
@@ -528,8 +553,13 @@ emit_composite_svg_pattern (xmlNodePtr n
     xmlNodePtr child;
     char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
 
-    if (surface->modified)
-	    xmlAddChild (document->xml_node_defs, xmlCopyNode (surface->xml_root_node, 1));
+    if (surface->modified) {
+	    if (surface->content == CAIRO_CONTENT_ALPHA) 
+		emit_alpha_filter (document);
+	    child = xmlAddChild (document->xml_node_defs, xmlCopyNode (surface->xml_root_node, 1));
+	    if (surface->content == CAIRO_CONTENT_ALPHA) 
+		    xmlSetProp (child, CC2XML ("filter"), CC2XML("url(#alpha)"));
+    }
     
     child = xmlNewChild (node, NULL, CC2XML("use"), NULL);
     snprintf (buffer, sizeof buffer, "#surface%d", 
@@ -1033,7 +1063,8 @@ emit_paint (xmlNodePtr node,
     xmlBufferPtr style;
     char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
 
-    if (source->type == CAIRO_PATTERN_TYPE_SURFACE)
+    if (source->type == CAIRO_PATTERN_TYPE_SURFACE && 
+	source->extend == CAIRO_EXTEND_NONE)
 	return emit_composite_pattern (node, 
 				       (cairo_surface_pattern_t *) source, 
 				       NULL, NULL, FALSE);
@@ -1112,10 +1143,16 @@ _cairo_svg_surface_mask (void		    *abst
     xmlNodePtr child, mask_node;
     char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
 
-    mask_node = xmlNewChild (document->xml_node_defs, NULL, CC2XML ("mask"), NULL);
+    emit_alpha_filter (document);
+
+    mask_node = xmlNewNode (NULL, CC2XML ("mask"));
     snprintf (buffer, sizeof buffer, "mask%d", document->mask_id);
     xmlSetProp (mask_node, CC2XML ("id"), C2XML (buffer));
-    emit_paint (mask_node, surface, op, mask);
+    child = xmlNewChild (mask_node, NULL, CC2XML ("g"), NULL);
+    xmlSetProp (child, CC2XML ("filter"), CC2XML ("url(#alpha)"));
+    emit_paint (child, surface, op, mask);
+
+    xmlAddChild (document->xml_node_defs, mask_node);
 
     child = emit_paint (surface->xml_node, surface, op, source);
 
@@ -1416,6 +1453,8 @@ _cairo_svg_document_create (cairo_output
     xmlSetProp (node, CC2XML ("xmlns:xlink"), CC2XML ("http://www.w3.org/1999/xlink"));
     xmlSetProp (node, CC2XML ("version"), CC2XML ("1.2"));
 
+    document->alpha_filter = FALSE;
+
     return document;
 }
 
diff-tree 9e2a2ea0da93065c46a6d6249f98a319ee6158dd (from c01805bafd5ad68263a3e644787cd7c04838124b)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date:   Mon Apr 17 11:07:15 2006 +0200

    SVG: Don't insert /n/r in base64 encoded image data
    
    That doesn't work since libxml replace them by &#10;&#13;
    They were intended to ease readability of generated files.

diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index b65796e..da38a1e 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -368,7 +368,6 @@ typedef struct {
     unsigned int in_mem;
     unsigned char src[3];
     unsigned char dst[5];
-    unsigned int count;
     unsigned int trailing;
 } base64_write_closure_t;
 
@@ -402,11 +401,6 @@ base64_write_func (void *closure, 
 	    data++;
 	    length--;
 	}
-	info->count++;
-	if (info->count >= 18) {
-	    info->count = 0;
-	    xmlBufferCat (info->buffer, CC2XML ("\r\n"));
-	}
 	dst[0] = base64_table[src[0] >> 2];
 	dst[1] = base64_table[(src[0] & 0x03) << 4 | src[1] >> 4];
 	dst[2] = base64_table[(src[1] & 0x0f) << 2 | src[2] >> 6];
@@ -446,7 +440,6 @@ _cairo_surface_base64_encode (cairo_surf
     
     info.buffer = xmlBufferCreate();
     info.in_mem = 0;
-    info.count = 0;
     info.trailing = 0;
     memset (info.dst, '\x0', 5);
     *buffer = info.buffer;
diff-tree c01805bafd5ad68263a3e644787cd7c04838124b (from 62d2f7cbf3718cfc982286ec62878c9d6eff09fa)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date:   Mon Apr 17 10:21:50 2006 +0200

    SVG: Don't check for content type in create_similar, and mark surface as modified when clearing it.

diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index eb01214..b65796e 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -305,10 +305,6 @@ _cairo_svg_surface_create_similar (void	
 {
     cairo_svg_surface_t *template = abstract_src;
 
-    if (content != CAIRO_CONTENT_COLOR_ALPHA &&
-	content != CAIRO_CONTENT_COLOR)
-	    return (cairo_surface_t *) &_cairo_surface_nil;
-
     return _cairo_svg_surface_create_for_document (template->document,
 						   content, width, height);
 }
@@ -1101,6 +1097,7 @@ _cairo_svg_surface_paint (void		    *abs
 		xmlSetProp (rect, CC2XML ("height"), C2XML (buffer));
 		xmlSetProp (rect, CC2XML ("style"), CC2XML ("opacity:1; stroke:none; fill:rgb(0,0,0);"));
 	    } 
+	    surface->modified = TRUE;
 	    return CAIRO_STATUS_SUCCESS;
 	}
     }
diff-tree 62d2f7cbf3718cfc982286ec62878c9d6eff09fa (from 347083b3f0be2f07d1953278b8516774253752f1)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date:   Mon Apr 17 09:54:03 2006 +0200

    SVG: Return UNTESTED for test involving operators.
    
    unbounded-operator, operator-clear, operator-source, clip-operator

diff --git a/test/cairo-test.c b/test/cairo-test.c
index 9105a1b..fce38fe 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -183,7 +183,7 @@ typedef struct _cairo_test_target
     cairo_test_create_target_surface_t	create_target_surface;
     cairo_test_write_to_png_t		write_to_png;
     cairo_test_cleanup_target_t		cleanup_target;
-    void		       	       *closure;
+    void			       *closure;
 } cairo_test_target_t;
 
 static char *
@@ -1298,6 +1298,14 @@ cleanup_pdf (void *closure)
 #if CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE
 #include "cairo-svg.h"
 
+static const char *svg_ignored_tests[] = {
+    "operator-source",
+    "operator-clear",
+    "clip-operator",
+    "unbounded-operator",
+    NULL
+};
+
 cairo_user_data_key_t	svg_closure_key;
 
 typedef struct _svg_target_closure
@@ -1314,9 +1322,14 @@ create_svg_surface (cairo_test_t	 *test,
 {
     int width = test->width;
     int height = test->height;
+    int i;
     svg_target_closure_t *ptc;
     cairo_surface_t *surface;
 
+    for (i = 0; svg_ignored_tests[i] != NULL; i++)
+	if (strcmp (test->name, svg_ignored_tests[i]) == 0)	   
+	    return NULL;
+
     *closure = ptc = xmalloc (sizeof (svg_target_closure_t));
 
     ptc->width = width;
diff-tree 347083b3f0be2f07d1953278b8516774253752f1 (from 714bb88832f0e6324cd4737aaa37a4ba39f8d14e)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date:   Sun Apr 16 16:00:27 2006 +0200

    SVG: Add reference files for antialiased text tests.
    
    Currently, text are rendered as paths in SVG files, so, when rendered to png through librsvg, they don't match general reference images.

diff --git a/test/show-text-current-point-svg-argb32-ref.png b/test/show-text-current-point-svg-argb32-ref.png
new file mode 100644
index 0000000..717ad7e
Binary files /dev/null and b/test/show-text-current-point-svg-argb32-ref.png differ
diff --git a/test/show-text-current-point-svg-rgb24-ref.png b/test/show-text-current-point-svg-rgb24-ref.png
new file mode 100644
index 0000000..717ad7e
Binary files /dev/null and b/test/show-text-current-point-svg-rgb24-ref.png differ
diff --git a/test/text-antialias-gray-svg-argb32-ref.png b/test/text-antialias-gray-svg-argb32-ref.png
new file mode 100644
index 0000000..aa64fbb
Binary files /dev/null and b/test/text-antialias-gray-svg-argb32-ref.png differ
diff --git a/test/text-antialias-gray-svg-rgb24-ref.png b/test/text-antialias-gray-svg-rgb24-ref.png
new file mode 100644
index 0000000..aa64fbb
Binary files /dev/null and b/test/text-antialias-gray-svg-rgb24-ref.png differ
diff --git a/test/text-pattern-svg-argb32-ref.png b/test/text-pattern-svg-argb32-ref.png
new file mode 100644
index 0000000..e4b5f75
Binary files /dev/null and b/test/text-pattern-svg-argb32-ref.png differ
diff --git a/test/text-pattern-svg-rgb24-ref.png b/test/text-pattern-svg-rgb24-ref.png
new file mode 100644
index 0000000..6f3510c
Binary files /dev/null and b/test/text-pattern-svg-rgb24-ref.png differ
diff-tree 714bb88832f0e6324cd4737aaa37a4ba39f8d14e (from d0356a87f7b274a0721c2644c4a62a8424923eb9)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date:   Sun Apr 16 15:42:49 2006 +0200

    SVG: Add support for CAIRO_CONTENT_COLOR in create_similar.
    
    Also add support for testing this feature in test/cairo-test.c
    And a bunch of unwanted commit of sgml files.

diff --git a/doc/public/tmpl/cairo-beos.sgml b/doc/public/tmpl/cairo-beos.sgml
index b3ea139..707d7e1 100644
--- a/doc/public/tmpl/cairo-beos.sgml
+++ b/doc/public/tmpl/cairo-beos.sgml
@@ -14,3 +14,6 @@ BeOS surface support
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
diff --git a/doc/public/tmpl/cairo-font-options.sgml b/doc/public/tmpl/cairo-font-options.sgml
index f800642..e87b550 100644
--- a/doc/public/tmpl/cairo-font-options.sgml
+++ b/doc/public/tmpl/cairo-font-options.sgml
@@ -14,6 +14,9 @@ How a font should be rendered
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### TYPEDEF cairo_font_options_t ##### -->
 <para>
 
diff --git a/doc/public/tmpl/cairo-font.sgml b/doc/public/tmpl/cairo-font.sgml
index fff13cd..b65281e 100644
--- a/doc/public/tmpl/cairo-font.sgml
+++ b/doc/public/tmpl/cairo-font.sgml
@@ -14,6 +14,9 @@ Base class for fonts
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### TYPEDEF cairo_font_face_t ##### -->
 <para>
 
diff --git a/doc/public/tmpl/cairo-ft.sgml b/doc/public/tmpl/cairo-ft.sgml
index d5ee69c..275f7af 100644
--- a/doc/public/tmpl/cairo-ft.sgml
+++ b/doc/public/tmpl/cairo-ft.sgml
@@ -14,3 +14,6 @@ Font support for FreeType
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
diff --git a/doc/public/tmpl/cairo-glitz.sgml b/doc/public/tmpl/cairo-glitz.sgml
index 0d204de..437c71e 100644
--- a/doc/public/tmpl/cairo-glitz.sgml
+++ b/doc/public/tmpl/cairo-glitz.sgml
@@ -14,3 +14,6 @@ OpenGL accelerated rendering using the G
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
diff --git a/doc/public/tmpl/cairo-image.sgml b/doc/public/tmpl/cairo-image.sgml
index 761627e..8e8dc86 100644
--- a/doc/public/tmpl/cairo-image.sgml
+++ b/doc/public/tmpl/cairo-image.sgml
@@ -17,6 +17,9 @@ Rendering to memory buffers
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### ENUM cairo_format_t ##### -->
 <para>
 
diff --git a/doc/public/tmpl/cairo-matrix.sgml b/doc/public/tmpl/cairo-matrix.sgml
index 19b3abc..3effbd2 100644
--- a/doc/public/tmpl/cairo-matrix.sgml
+++ b/doc/public/tmpl/cairo-matrix.sgml
@@ -29,6 +29,9 @@ Generic matrix operations
     
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT cairo_matrix_t ##### -->
 <para>
 
diff --git a/doc/public/tmpl/cairo-paths.sgml b/doc/public/tmpl/cairo-paths.sgml
index b06bc0e..01bf12d 100644
--- a/doc/public/tmpl/cairo-paths.sgml
+++ b/doc/public/tmpl/cairo-paths.sgml
@@ -14,6 +14,9 @@ Creating paths and manipulating path dat
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT cairo_path_t ##### -->
 <para>
 
diff --git a/doc/public/tmpl/cairo-pattern.sgml b/doc/public/tmpl/cairo-pattern.sgml
index 8319858..f7f29b1 100644
--- a/doc/public/tmpl/cairo-pattern.sgml
+++ b/doc/public/tmpl/cairo-pattern.sgml
@@ -14,6 +14,9 @@ Gradients and filtered sources
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### TYPEDEF cairo_pattern_t ##### -->
 <para>
 
diff --git a/doc/public/tmpl/cairo-pdf.sgml b/doc/public/tmpl/cairo-pdf.sgml
index efef4a6..4f7dbd7 100644
--- a/doc/public/tmpl/cairo-pdf.sgml
+++ b/doc/public/tmpl/cairo-pdf.sgml
@@ -14,3 +14,6 @@ Rendering PDF documents
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
diff --git a/doc/public/tmpl/cairo-png.sgml b/doc/public/tmpl/cairo-png.sgml
index d2d6d38..cba1516 100644
--- a/doc/public/tmpl/cairo-png.sgml
+++ b/doc/public/tmpl/cairo-png.sgml
@@ -14,6 +14,9 @@ Reading and writing PNG images
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### USER_FUNCTION cairo_read_func_t ##### -->
 <para>
 
diff --git a/doc/public/tmpl/cairo-ps.sgml b/doc/public/tmpl/cairo-ps.sgml
index 087f464..a3d5765 100644
--- a/doc/public/tmpl/cairo-ps.sgml
+++ b/doc/public/tmpl/cairo-ps.sgml
@@ -14,3 +14,6 @@ Rendering PostScript documents
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
diff --git a/doc/public/tmpl/cairo-quartz.sgml b/doc/public/tmpl/cairo-quartz.sgml
index 226dabe..02a69d9 100644
--- a/doc/public/tmpl/cairo-quartz.sgml
+++ b/doc/public/tmpl/cairo-quartz.sgml
@@ -14,3 +14,6 @@ Rendering to Quartz surfaces
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
diff --git a/doc/public/tmpl/cairo-scaled-font.sgml b/doc/public/tmpl/cairo-scaled-font.sgml
index 9202ade..0656454 100644
--- a/doc/public/tmpl/cairo-scaled-font.sgml
+++ b/doc/public/tmpl/cairo-scaled-font.sgml
@@ -14,6 +14,9 @@ Caching metrics for a particular font si
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### TYPEDEF cairo_scaled_font_t ##### -->
 <para>
 
diff --git a/doc/public/tmpl/cairo-status.sgml b/doc/public/tmpl/cairo-status.sgml
index 1a9d86f..de5f35f 100644
--- a/doc/public/tmpl/cairo-status.sgml
+++ b/doc/public/tmpl/cairo-status.sgml
@@ -14,6 +14,9 @@ Decoding cairo's status
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### ENUM cairo_status_t ##### -->
 <para>
 
diff --git a/doc/public/tmpl/cairo-surface.sgml b/doc/public/tmpl/cairo-surface.sgml
index bbd829d..69d63d2 100644
--- a/doc/public/tmpl/cairo-surface.sgml
+++ b/doc/public/tmpl/cairo-surface.sgml
@@ -14,6 +14,9 @@ Base class for surfaces
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### TYPEDEF cairo_surface_t ##### -->
 <para>
 
diff --git a/doc/public/tmpl/cairo-text.sgml b/doc/public/tmpl/cairo-text.sgml
index 8514789..56678b1 100644
--- a/doc/public/tmpl/cairo-text.sgml
+++ b/doc/public/tmpl/cairo-text.sgml
@@ -14,6 +14,9 @@ Rendering text and sets of glyphs
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT cairo_glyph_t ##### -->
 <para>
 
diff --git a/doc/public/tmpl/cairo-transforms.sgml b/doc/public/tmpl/cairo-transforms.sgml
index 14351e2..65199c8 100644
--- a/doc/public/tmpl/cairo-transforms.sgml
+++ b/doc/public/tmpl/cairo-transforms.sgml
@@ -14,3 +14,6 @@ Manipulating the current transformation 
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
diff --git a/doc/public/tmpl/cairo-types.sgml b/doc/public/tmpl/cairo-types.sgml
index 66a3098..9e6f6b5 100644
--- a/doc/public/tmpl/cairo-types.sgml
+++ b/doc/public/tmpl/cairo-types.sgml
@@ -14,6 +14,9 @@ Generic data types used in the cairo API
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### FUNCTION cairo_bool_t ##### -->
 <para>
 
diff --git a/doc/public/tmpl/cairo-version.sgml b/doc/public/tmpl/cairo-version.sgml
index 329a2f4..42eb58e 100644
--- a/doc/public/tmpl/cairo-version.sgml
+++ b/doc/public/tmpl/cairo-version.sgml
@@ -114,6 +114,9 @@ if (cairo_version() >= %CAIRO_VERSION_EN
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### MACRO CAIRO_VERSION ##### -->
 <para>
 
diff --git a/doc/public/tmpl/cairo-win32-fonts.sgml b/doc/public/tmpl/cairo-win32-fonts.sgml
index d686ace..3652ccb 100644
--- a/doc/public/tmpl/cairo-win32-fonts.sgml
+++ b/doc/public/tmpl/cairo-win32-fonts.sgml
@@ -14,3 +14,6 @@ Font support for Microsoft Windows
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
diff --git a/doc/public/tmpl/cairo-win32.sgml b/doc/public/tmpl/cairo-win32.sgml
index 6cc1cd8..b486ba8 100644
--- a/doc/public/tmpl/cairo-win32.sgml
+++ b/doc/public/tmpl/cairo-win32.sgml
@@ -14,3 +14,6 @@ Microsoft Windows surface support
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
diff --git a/doc/public/tmpl/cairo-xcb-xrender.sgml b/doc/public/tmpl/cairo-xcb-xrender.sgml
index 635fa3c..fc24323 100644
--- a/doc/public/tmpl/cairo-xcb-xrender.sgml
+++ b/doc/public/tmpl/cairo-xcb-xrender.sgml
@@ -14,3 +14,6 @@ X Window System rendering using the XCB 
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
diff --git a/doc/public/tmpl/cairo-xcb.sgml b/doc/public/tmpl/cairo-xcb.sgml
index 635fa3c..fc24323 100644
--- a/doc/public/tmpl/cairo-xcb.sgml
+++ b/doc/public/tmpl/cairo-xcb.sgml
@@ -14,3 +14,6 @@ X Window System rendering using the XCB 
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
diff --git a/doc/public/tmpl/cairo-xlib-xrender.sgml b/doc/public/tmpl/cairo-xlib-xrender.sgml
index df970a2..c99d784 100644
--- a/doc/public/tmpl/cairo-xlib-xrender.sgml
+++ b/doc/public/tmpl/cairo-xlib-xrender.sgml
@@ -14,3 +14,6 @@ XLib/Xrender Backend
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
diff --git a/doc/public/tmpl/cairo-xlib.sgml b/doc/public/tmpl/cairo-xlib.sgml
index 7480fad..f931a50 100644
--- a/doc/public/tmpl/cairo-xlib.sgml
+++ b/doc/public/tmpl/cairo-xlib.sgml
@@ -14,3 +14,6 @@ X Window System rendering using XLib
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
diff --git a/doc/public/tmpl/cairo.sgml b/doc/public/tmpl/cairo.sgml
index 32fd94f..04480e7 100644
--- a/doc/public/tmpl/cairo.sgml
+++ b/doc/public/tmpl/cairo.sgml
@@ -24,6 +24,9 @@ The cairo drawing context
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### TYPEDEF cairo_t ##### -->
 <para>
 
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index accbe00..eb01214 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -80,6 +80,8 @@ struct cairo_svg_document {
 struct cairo_svg_surface {
     cairo_surface_t base;
 
+    cairo_content_t content;
+
     unsigned int id;
 
     double width;
@@ -112,8 +114,9 @@ _cairo_svg_document_reference (cairo_svg
 
 static cairo_surface_t *
 _cairo_svg_surface_create_for_document (cairo_svg_document_t	*document,
-					double			width,
-					double			height);
+					cairo_content_t		 content,
+					double			 width,
+					double			 height);
 
 static const cairo_surface_backend_t cairo_svg_surface_backend;
 
@@ -129,7 +132,8 @@ _cairo_svg_surface_create_for_stream_int
     if (document == NULL)
       return NULL;
 
-    surface = _cairo_svg_surface_create_for_document (document, width, height);
+    surface = _cairo_svg_surface_create_for_document (document, CAIRO_CONTENT_COLOR_ALPHA, 
+						      width, height);
 
     document->owner = surface;
     _cairo_svg_document_destroy (document);
@@ -234,11 +238,12 @@ cairo_svg_surface_set_dpi (cairo_surface
 
 static cairo_surface_t *
 _cairo_svg_surface_create_for_document (cairo_svg_document_t	*document,
-					double			width,
-					double			height)
+					cairo_content_t		 content,
+					double			 width,
+					double			 height)
 {
     cairo_svg_surface_t *surface;
-    xmlNodePtr clip, clip_rect;
+    xmlNodePtr clip, rect;
     int clip_id;
     char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
 
@@ -262,11 +267,11 @@ _cairo_svg_surface_create_for_document (
     clip = xmlNewChild (document->xml_node_defs, NULL, CC2XML ("clipPath"), NULL);
     snprintf (buffer, sizeof buffer, "clip%d", clip_id);
     xmlSetProp (clip, CC2XML ("id"), C2XML (buffer));
-    clip_rect = xmlNewChild (clip, NULL, CC2XML ("rect"), NULL);
+    rect = xmlNewChild (clip, NULL, CC2XML ("rect"), NULL);
     _cairo_dtostr (buffer, sizeof buffer, width);
-    xmlSetProp (clip_rect, CC2XML ("width"), C2XML (buffer));
+    xmlSetProp (rect, CC2XML ("width"), C2XML (buffer));
     _cairo_dtostr (buffer, sizeof buffer, height);
-    xmlSetProp (clip_rect, CC2XML ("height"), C2XML (buffer));
+    xmlSetProp (rect, CC2XML ("height"), C2XML (buffer));
     
     surface->xml_node = xmlNewNode (NULL, CC2XML ("g"));
     surface->xml_root_node = surface->xml_node;
@@ -276,9 +281,19 @@ _cairo_svg_surface_create_for_document (
     snprintf (buffer, sizeof buffer, "url(#clip%d)", clip_id);
     xmlSetProp (surface->xml_node, CC2XML ("clip-path"), C2XML (buffer));
 
+    if (content == CAIRO_CONTENT_COLOR) {
+	rect = xmlNewChild (surface->xml_node, NULL, CC2XML ("rect"), NULL);
+	_cairo_dtostr (buffer, sizeof buffer, width);
+	xmlSetProp (rect, CC2XML ("width"), C2XML (buffer));
+	_cairo_dtostr (buffer, sizeof buffer, height);
+	xmlSetProp (rect, CC2XML ("height"), C2XML (buffer));
+	xmlSetProp (rect, CC2XML ("style"), CC2XML ("opacity:1; stroke:none; fill:rgb(0,0,0);"));
+    }
+
     surface->modified = TRUE;
     surface->previous_id = surface->id;
-    
+    surface->content = content;
+
     return &surface->base;
 }
 
@@ -290,8 +305,12 @@ _cairo_svg_surface_create_similar (void	
 {
     cairo_svg_surface_t *template = abstract_src;
 
+    if (content != CAIRO_CONTENT_COLOR_ALPHA &&
+	content != CAIRO_CONTENT_COLOR)
+	    return (cairo_surface_t *) &_cairo_surface_nil;
+
     return _cairo_svg_surface_create_for_document (template->document,
-						   width, height);
+						   content, width, height);
 }
 
 static cairo_status_t
@@ -524,7 +543,8 @@ emit_composite_svg_pattern (xmlNodePtr n
 	    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->previous_id);
+    snprintf (buffer, sizeof buffer, "#surface%d", 
+	      surface->modified ? surface->id : surface->previous_id);
     xmlSetProp (child, CC2XML ("xlink:href"), C2XML (buffer));
 
     if (!is_pattern) {
@@ -1061,9 +1081,28 @@ _cairo_svg_surface_paint (void		    *abs
     if (surface->clip_level == 0 &&
 	(op == CAIRO_OPERATOR_CLEAR ||
 	 op == CAIRO_OPERATOR_SOURCE)) {
-	    xmlFreeNode (surface->xml_root_node->children);
-	    if (op == CAIRO_OPERATOR_CLEAR)
-		    return CAIRO_STATUS_SUCCESS;
+	xmlNodePtr child = surface->xml_root_node->children;
+	
+	while (child != NULL) {
+	    xmlUnlinkNode (child);
+	    xmlFreeNode (child);
+	    child = surface->xml_root_node->children;
+	}
+
+	if (op == CAIRO_OPERATOR_CLEAR) {
+	    if (surface->content == CAIRO_CONTENT_COLOR) {
+		xmlNodePtr rect;
+		char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
+
+		rect = xmlNewChild (surface->xml_node, NULL, CC2XML ("rect"), NULL);
+		_cairo_dtostr (buffer, sizeof buffer, surface->width);
+		xmlSetProp (rect, CC2XML ("width"), C2XML (buffer));
+		_cairo_dtostr (buffer, sizeof buffer, surface->height);
+		xmlSetProp (rect, CC2XML ("height"), C2XML (buffer));
+		xmlSetProp (rect, CC2XML ("style"), CC2XML ("opacity:1; stroke:none; fill:rgb(0,0,0);"));
+	    } 
+	    return CAIRO_STATUS_SUCCESS;
+	}
     }
 
     emit_paint (surface->xml_node, surface, op, source);
diff --git a/test/cairo-test.c b/test/cairo-test.c
index 59b55f7..9105a1b 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -1304,6 +1304,7 @@ typedef struct _svg_target_closure
 {
     char    *filename;
     int	    width, height;
+    cairo_surface_t	*target;
 } svg_target_closure_t;
 
 static cairo_surface_t *
@@ -1330,7 +1331,19 @@ create_svg_surface (cairo_test_t	 *test,
 	free (ptc);
 	return NULL;
     }
+    cairo_svg_surface_set_dpi (surface, 72., 72.);
+
+    if (content == CAIRO_CONTENT_COLOR) {
+	ptc->target = surface;
+	surface = cairo_surface_create_similar (ptc->target, 
+						CAIRO_CONTENT_COLOR,
+						width, height);
+    } else {
+	ptc->target = NULL;
+    }
+
     cairo_surface_set_user_data (surface, &svg_closure_key, ptc, NULL);
+
     return surface;
 }
 
@@ -1340,15 +1353,26 @@ svg_surface_write_to_png (cairo_surface_
     svg_target_closure_t *ptc = cairo_surface_get_user_data (surface, &svg_closure_key);
     char    command[4096];
 
-    cairo_surface_finish (surface);
+    if (ptc->target) {
+	cairo_t *cr;
+	cr = cairo_create (ptc->target);
+	cairo_set_source_surface (cr, surface, 0, 0);
+	cairo_paint (cr);
+	cairo_show_page (cr);
+	cairo_destroy (cr);
+
+	cairo_surface_finish (surface);
+	surface = ptc->target;
+    }
 
+    cairo_surface_finish (surface);
     sprintf (command, "./svg2png %s %s",
 	     ptc->filename, filename);
 
     if (system (command) != 0)
 	return CAIRO_STATUS_WRITE_ERROR;
     
-    return CAIRO_STATUS_WRITE_ERROR;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void
@@ -1593,10 +1617,14 @@ cairo_test_expecting (cairo_test_t *test
 		create_pdf_surface, pdf_surface_write_to_png, cleanup_pdf },
 #endif
 #if CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE
-	    { "svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR,
-		    create_svg_surface, svg_surface_write_to_png, cleanup_svg },
 	    { "svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA,
 		    create_svg_surface, svg_surface_write_to_png, cleanup_svg },
+
+	    /* A SVG surface is COLOR_APLHA by default, and currently a create
+	     * similar with content != COLOR_ALPHA will return a nil surface.
+	     * So don't test COLOR for now. */
+	    { "svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR,
+		    create_svg_surface, svg_surface_write_to_png, cleanup_svg },
 #endif
 #if CAIRO_HAS_BEOS_SURFACE
 	    { "beos", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR,
diff-tree cb778760cb87e727a701603bcea3a2cdc063d785 (from 1dc1b57b4eaa55b7a5cafe39f818f7c87352ea6d)
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Feb 23 22:07:13 2006 -0800

    cairo_close_path: Document that there will be a current point after
    cairo_close_path.

diff --git a/src/cairo.c b/src/cairo.c
index 6a94d0f..3319e2b 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -1417,7 +1417,8 @@ cairo_stroke_to_path (cairo_t *cr)
  * 
  * Adds a line segment to the path from the current point to the
  * beginning of the current subpath, (the most recent point passed to
- * cairo_move_to()), and closes this subpath.
+ * cairo_move_to()), and closes this subpath. After this call the
+ * current point will be at the joined endpoint of the subpath.
  *
  * The behavior of cairo_close_path() is distinct from simply calling
  * cairo_line_to() with the equivalent coordinate in the case of
@@ -1425,7 +1426,8 @@ cairo_stroke_to_path (cairo_t *cr)
  * the ends of the subpath. Instead, there is a line join connecting
  * the final and initial segments of the subpath.
  *
- * If there is no current point, this function will have no effect.
+ * If there is no current point before the call to cairo_close_path,
+ * this function will have no effect.
  **/
 void
 cairo_close_path (cairo_t *cr)
diff-tree 1dc1b57b4eaa55b7a5cafe39f818f7c87352ea6d (from 0354956a09cf5a45feed256c1d880bbb9b7c7c42)
Author: Carl Worth <cworth at cworth.org>
Date:   Thu Feb 23 22:01:07 2006 -0800

    cairo_new_sub_path: Making cairo_arc easier to use and more.
    
    This adds a new function which has as its only effect the elimination
    of
    the current point. This makes it much easier to use the various
    cairo_arc calls when the initial line_to is not actually desired.
    
    This function also unifies and generalizes the long-existing behavior
    of cairo_line_to being treated as cairo_move_to when there is no
    current point. With the addition of cairo_new_sub_path this becomes a
    documented feature with similar behavior in cairo_curve_to as well.

diff --git a/.gitignore b/.gitignore
index aaa9f03..73e1e4e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,4 @@ stamp-h
 stamp-h1
 stamp-h.in
 *~
+*.orig
diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 96664ce..e817099 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -47,7 +47,6 @@ typedef struct cairo_stroker {
 
     cairo_pen_t	  pen;
 
-    cairo_bool_t has_current_point;
     cairo_point_t current_point;
     cairo_point_t first_point;
 
@@ -159,7 +158,6 @@ _cairo_stroker_init (cairo_stroker_t		*s
 		     stroke_style->line_width / 2.0,
 		     tolerance, ctm);
     
-    stroker->has_current_point = FALSE;
     stroker->has_current_face = FALSE;
     stroker->has_first_face = FALSE;
 
@@ -607,7 +605,6 @@ _cairo_stroker_move_to (void *closure, c
 
     stroker->first_point = *point;
     stroker->current_point = *point;
-    stroker->has_current_point = 1;
 
     stroker->has_first_face = 0;
     stroker->has_current_face = 0;
@@ -624,9 +621,6 @@ _cairo_stroker_line_to (void *closure, c
     cairo_point_t *p1 = &stroker->current_point;
     cairo_point_t *p2 = point;
 
-    if (!stroker->has_current_point)
-	return _cairo_stroker_move_to (stroker, point);
-
     if (p1->x == p2->x && p1->y == p2->y) {
 	/* XXX: Need to rethink how this case should be handled, (both
            here and in cairo_stroker_add_sub_edge and in _compute_face). The
@@ -674,9 +668,6 @@ _cairo_stroker_line_to_dashed (void *clo
     cairo_point_t *p1 = &stroker->current_point;
     cairo_point_t *p2 = point;
 
-    if (!stroker->has_current_point)
-	return _cairo_stroker_move_to (stroker, point);
-    
     dx = _cairo_fixed_to_double (p2->x - p1->x);
     dy = _cairo_fixed_to_double (p2->y - p1->y);
 
@@ -914,14 +905,12 @@ _cairo_stroker_close_path (void *closure
     cairo_status_t status;
     cairo_stroker_t *stroker = closure;
 
-    if (stroker->has_current_point) {
-	if (stroker->dashed)
-	    status = _cairo_stroker_line_to_dashed (stroker, &stroker->first_point);
-	else
-	    status = _cairo_stroker_line_to (stroker, &stroker->first_point);
-	if (status)
-	    return status;
-    }
+    if (stroker->dashed)
+	status = _cairo_stroker_line_to_dashed (stroker, &stroker->first_point);
+    else
+	status = _cairo_stroker_line_to (stroker, &stroker->first_point);
+    if (status)
+	return status;
 
     if (stroker->has_first_face && stroker->has_current_face) {
 	status = _cairo_stroker_join (stroker, &stroker->current_face, &stroker->first_face);
@@ -931,7 +920,6 @@ _cairo_stroker_close_path (void *closure
 
     stroker->has_first_face = 0;
     stroker->has_current_face = 0;
-    stroker->has_current_point = 0;
 
     return CAIRO_STATUS_SUCCESS;
 }
diff --git a/src/cairo-path.c b/src/cairo-path.c
index 669e587..7358bee 100644
--- a/src/cairo-path.c
+++ b/src/cairo-path.c
@@ -87,7 +87,7 @@ _cairo_path_fixed_init (cairo_path_fixed
 
     path->current_point.x = 0;
     path->current_point.y = 0;
-    path->has_current_point = 0;
+    path->has_current_point = FALSE;
     path->last_move_point = path->current_point;
 }
 
@@ -163,7 +163,7 @@ _cairo_path_fixed_fini (cairo_path_fixed
     }
     path->arg_buf_tail = NULL;
 
-    path->has_current_point = 0;
+    path->has_current_point = FALSE;
 }
 
 void
@@ -189,12 +189,18 @@ _cairo_path_fixed_move_to (cairo_path_fi
 	return status;
 
     path->current_point = point;
-    path->has_current_point = 1;
+    path->has_current_point = TRUE;
     path->last_move_point = path->current_point;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
+void
+_cairo_path_fixed_new_sub_path (cairo_path_fixed_t *path)
+{
+    path->has_current_point = FALSE;
+}
+
 cairo_status_t
 _cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
 			       cairo_fixed_t	   dx,
@@ -202,7 +208,7 @@ _cairo_path_fixed_rel_move_to (cairo_pat
 {
     cairo_fixed_t x, y;
 
-    if (!path->has_current_point)
+    if (! path->has_current_point)
 	return CAIRO_STATUS_NO_CURRENT_POINT;
 
     x = path->current_point.x + dx;
@@ -222,12 +228,16 @@ _cairo_path_fixed_line_to (cairo_path_fi
     point.x = x;
     point.y = y;
 
-    status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
+    if (! path->has_current_point)
+	status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
+    else
+	status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
+
     if (status)
 	return status;
 
     path->current_point = point;
-    path->has_current_point = 1;
+    path->has_current_point = TRUE;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -239,7 +249,7 @@ _cairo_path_fixed_rel_line_to (cairo_pat
 {
     cairo_fixed_t x, y;
 
-    if (!path->has_current_point)
+    if (! path->has_current_point)
 	return CAIRO_STATUS_NO_CURRENT_POINT;
 
     x = path->current_point.x + dx;
@@ -261,12 +271,19 @@ _cairo_path_fixed_curve_to (cairo_path_f
     point[1].x = x1; point[1].y = y1;
     point[2].x = x2; point[2].y = y2;
 
+    if (! path->has_current_point) {
+	status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO,
+					&point[0], 1);
+	if (status)
+	    return status;
+    }
+
     status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3);
     if (status)
 	return status;
 
     path->current_point = point[2];
-    path->has_current_point = 1;
+    path->has_current_point = TRUE;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -281,7 +298,7 @@ _cairo_path_fixed_rel_curve_to (cairo_pa
     cairo_fixed_t x1, y1;
     cairo_fixed_t x2, y2;
 
-    if (!path->has_current_point)
+    if (! path->has_current_point)
 	return CAIRO_STATUS_NO_CURRENT_POINT;
 
     x0 = path->current_point.x + dx0;
@@ -304,13 +321,16 @@ _cairo_path_fixed_close_path (cairo_path
 {
     cairo_status_t status;
 
+    if (! path->has_current_point)
+	return CAIRO_STATUS_SUCCESS;
+
     status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CLOSE_PATH, NULL, 0);
     if (status)
 	return status;
 
     path->current_point.x = path->last_move_point.x;
     path->current_point.y = path->last_move_point.y;
-    path->has_current_point = 1;
+    path->has_current_point = TRUE;
 
     return CAIRO_STATUS_SUCCESS;
 }
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index ee5c482..0c024a2 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1263,22 +1263,15 @@ intersect (cairo_line_t *line, cairo_fix
 	_cairo_fixed_to_double (line->p2.y - line->p1.y);
 }
 
-typedef struct
-{
-    cairo_output_stream_t *output_stream;
-    cairo_bool_t has_current_point;
-} pdf_path_info_t;
-
 static cairo_status_t
 _cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
 {
-    pdf_path_info_t *info = closure;
+    cairo_output_stream_t *output_stream = closure;
 
-    _cairo_output_stream_printf (info->output_stream,
+    _cairo_output_stream_printf (output_stream,
 				 "%f %f m ",
 				 _cairo_fixed_to_double (point->x),
 				 _cairo_fixed_to_double (point->y));
-    info->has_current_point = TRUE;
     
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1286,20 +1279,12 @@ _cairo_pdf_path_move_to (void *closure, 
 static cairo_status_t
 _cairo_pdf_path_line_to (void *closure, cairo_point_t *point)
 {
-    pdf_path_info_t *info = closure;
-    const char *pdf_operator;
-
-    if (info->has_current_point)
-	pdf_operator = "l";
-    else
-	pdf_operator = "m";
+    cairo_output_stream_t *output_stream = closure;
     
-    _cairo_output_stream_printf (info->output_stream,
-				 "%f %f %s ",
+    _cairo_output_stream_printf (output_stream,
+				 "%f %f l ",
 				 _cairo_fixed_to_double (point->x),
-				 _cairo_fixed_to_double (point->y),
-				 pdf_operator);
-    info->has_current_point = TRUE;
+				 _cairo_fixed_to_double (point->y));
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1310,9 +1295,9 @@ _cairo_pdf_path_curve_to (void          
 			  cairo_point_t *c,
 			  cairo_point_t *d)
 {
-    pdf_path_info_t *info = closure;
+    cairo_output_stream_t *output_stream = closure;
 
-    _cairo_output_stream_printf (info->output_stream,
+    _cairo_output_stream_printf (output_stream,
 				 "%f %f %f %f %f %f c ",
 				 _cairo_fixed_to_double (b->x),
 				 _cairo_fixed_to_double (b->y),
@@ -1327,11 +1312,10 @@ _cairo_pdf_path_curve_to (void          
 static cairo_status_t
 _cairo_pdf_path_close_path (void *closure)
 {
-    pdf_path_info_t *info = closure;
+    cairo_output_stream_t *output_stream = closure;
     
-    _cairo_output_stream_printf (info->output_stream,
+    _cairo_output_stream_printf (output_stream,
 				 "h\r\n");
-    info->has_current_point = FALSE;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1349,7 +1333,6 @@ _cairo_pdf_surface_fill (void			*abstrac
     cairo_pdf_document_t *document = surface->document;
     const char *pdf_operator;
     cairo_status_t status;
-    pdf_path_info_t info;
 
     status = emit_pattern (surface, pattern);
     if (status)
@@ -1360,16 +1343,13 @@ _cairo_pdf_surface_fill (void			*abstrac
     assert (document->current_stream != NULL &&
 	    document->current_stream == surface->current_stream);
 
-    info.output_stream = document->output_stream;
-    info.has_current_point = FALSE;
-
     status = _cairo_path_fixed_interpret (path,
 					  CAIRO_DIRECTION_FORWARD,
 					  _cairo_pdf_path_move_to,
 					  _cairo_pdf_path_line_to,
 					  _cairo_pdf_path_curve_to,
 					  _cairo_pdf_path_close_path,
-					  &info);
+					  document->output_stream);
 
     switch (fill_rule) {
     case CAIRO_FILL_RULE_WINDING:
@@ -1600,7 +1580,6 @@ _cairo_pdf_surface_intersect_clip_path (
     cairo_pdf_document_t *document = surface->document;
     cairo_output_stream_t *output = document->output_stream;
     cairo_status_t status;
-    pdf_path_info_t info;
     const char *pdf_operator;
 
     _cairo_pdf_surface_ensure_stream (surface);
@@ -1617,16 +1596,13 @@ _cairo_pdf_surface_intersect_clip_path (
 	surface->has_clip = TRUE;
     }
 
-    info.output_stream = document->output_stream;
-    info.has_current_point = FALSE;
-
     status = _cairo_path_fixed_interpret (path,
 					  CAIRO_DIRECTION_FORWARD,
 					  _cairo_pdf_path_move_to,
 					  _cairo_pdf_path_line_to,
 					  _cairo_pdf_path_curve_to,
 					  _cairo_pdf_path_close_path,
-					  &info);
+					  document->output_stream);
 
     switch (fill_rule) {
     case CAIRO_FILL_RULE_WINDING:
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 6cf8621..37053e9 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1049,22 +1049,16 @@ _cairo_ps_surface_composite_trapezoids (
     return CAIRO_STATUS_SUCCESS;
 }
 
-typedef struct
-{
-    cairo_output_stream_t *output_stream;
-    cairo_bool_t has_current_point;
-} cairo_ps_surface_path_info_t;
 
 static cairo_status_t
 _cairo_ps_surface_path_move_to (void *closure, cairo_point_t *point)
 {
-    cairo_ps_surface_path_info_t *info = closure;
+    cairo_output_stream_t *output_stream = closure;
 
-    _cairo_output_stream_printf (info->output_stream,
+    _cairo_output_stream_printf (output_stream,
 				 "%f %f moveto ",
 				 _cairo_fixed_to_double (point->x),
 				 _cairo_fixed_to_double (point->y));
-    info->has_current_point = TRUE;
     
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1072,33 +1066,25 @@ _cairo_ps_surface_path_move_to (void *cl
 static cairo_status_t
 _cairo_ps_surface_path_line_to (void *closure, cairo_point_t *point)
 {
-    cairo_ps_surface_path_info_t *info = closure;
-    const char *ps_operator;
+    cairo_output_stream_t *output_stream = closure;
 
-    if (info->has_current_point)
-	ps_operator = "lineto";
-    else
-	ps_operator = "moveto";
-    
-    _cairo_output_stream_printf (info->output_stream,
-				 "%f %f %s ",
+    _cairo_output_stream_printf (output_stream,
+				 "%f %f lineto ",
 				 _cairo_fixed_to_double (point->x),
-				 _cairo_fixed_to_double (point->y),
-				 ps_operator);
-    info->has_current_point = TRUE;
+				 _cairo_fixed_to_double (point->y));
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_ps_surface_path_curve_to (void          *closure,
-			  cairo_point_t *b,
-			  cairo_point_t *c,
-			  cairo_point_t *d)
+				 cairo_point_t *b,
+				 cairo_point_t *c,
+				 cairo_point_t *d)
 {
-    cairo_ps_surface_path_info_t *info = closure;
+    cairo_output_stream_t *output_stream = closure;
 
-    _cairo_output_stream_printf (info->output_stream,
+    _cairo_output_stream_printf (output_stream,
 				 "%f %f %f %f %f %f curveto ",
 				 _cairo_fixed_to_double (b->x),
 				 _cairo_fixed_to_double (b->y),
@@ -1113,11 +1099,10 @@ _cairo_ps_surface_path_curve_to (void   
 static cairo_status_t
 _cairo_ps_surface_path_close_path (void *closure)
 {
-    cairo_ps_surface_path_info_t *info = closure;
+    cairo_output_stream_t *output_stream = closure;
     
-    _cairo_output_stream_printf (info->output_stream,
+    _cairo_output_stream_printf (output_stream,
 				 "closepath\n");
-    info->has_current_point = FALSE;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1132,7 +1117,6 @@ _cairo_ps_surface_intersect_clip_path (v
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_output_stream_t *stream = surface->stream;
     cairo_status_t status;
-    cairo_ps_surface_path_info_t info;
     const char *ps_operator;
 
     _cairo_output_stream_printf (stream,
@@ -1143,16 +1127,13 @@ _cairo_ps_surface_intersect_clip_path (v
 	return CAIRO_STATUS_SUCCESS;
     }
 
-    info.output_stream = stream;
-    info.has_current_point = FALSE;
-
     status = _cairo_path_fixed_interpret (path,
 					  CAIRO_DIRECTION_FORWARD,
 					  _cairo_ps_surface_path_move_to,
 					  _cairo_ps_surface_path_line_to,
 					  _cairo_ps_surface_path_curve_to,
 					  _cairo_ps_surface_path_close_path,
-					  &info);
+					  stream);
 
     switch (fill_rule) {
     case CAIRO_FILL_RULE_WINDING:
@@ -1276,7 +1257,6 @@ _cairo_ps_surface_fill (void			*abstract
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_output_stream_t *stream = surface->stream;
     cairo_int_status_t status;
-    cairo_ps_surface_path_info_t info;
     const char *ps_operator;
 
     if (pattern_operation_needs_fallback (op, source))
@@ -1293,16 +1273,13 @@ _cairo_ps_surface_fill (void			*abstract
 
     emit_pattern (surface, source);
 
-    info.output_stream = stream;
-    info.has_current_point = FALSE;
-
     status = _cairo_path_fixed_interpret (path,
 					  CAIRO_DIRECTION_FORWARD,
 					  _cairo_ps_surface_path_move_to,
 					  _cairo_ps_surface_path_line_to,
 					  _cairo_ps_surface_path_curve_to,
 					  _cairo_ps_surface_path_close_path,
-					  &info);
+					  stream);
 
     switch (fill_rule) {
     case CAIRO_FILL_RULE_WINDING:
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 5a2c92f..9297005 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -783,7 +783,6 @@ emit_pattern (cairo_svg_surface_t *surfa
 typedef struct
 {
     cairo_svg_document_t *document;
-    cairo_bool_t has_current_point;
     xmlBufferPtr path;
 } svg_path_info_t;
 
@@ -801,7 +800,6 @@ _cairo_svg_path_move_to (void *closure, 
     _cairo_dtostr (buffer, sizeof buffer, _cairo_fixed_to_double (point->y));
     xmlBufferCat (path, CC2XML (buffer));
     xmlBufferCat (path, CC2XML (" "));
-    info->has_current_point = TRUE;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -813,10 +811,7 @@ _cairo_svg_path_line_to (void *closure, 
     xmlBufferPtr path = info->path;
     char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
 
-    if (info->has_current_point)
-	xmlBufferCat (path, CC2XML ("L "));
-    else
-	xmlBufferCat (path, CC2XML ("M "));
+    xmlBufferCat (path, CC2XML ("L "));
 
     _cairo_dtostr (buffer, sizeof buffer, _cairo_fixed_to_double (point->x));
     xmlBufferCat (path, CC2XML (buffer));
@@ -825,8 +820,6 @@ _cairo_svg_path_line_to (void *closure, 
     xmlBufferCat (path, CC2XML (buffer));
     xmlBufferCat (path, CC2XML (" "));
 
-    info->has_current_point = TRUE;
-
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -868,10 +861,7 @@ _cairo_svg_path_close_path (void *closur
 {
     svg_path_info_t *info = closure;
 
-    if (info->has_current_point)
-	    xmlBufferCat (info->path, CC2XML ("Z "));
-
-    info->has_current_point = FALSE;
+    xmlBufferCat (info->path, CC2XML ("Z "));
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -893,7 +883,6 @@ _cairo_svg_surface_fill (void			*abstrac
     xmlBufferPtr style;
 
     info.document = document;
-    info.has_current_point = FALSE;
     info.path = xmlBufferCreate ();
     
     style = xmlBufferCreate ();
@@ -1035,7 +1024,6 @@ _cairo_svg_surface_stroke (void			*abstr
     char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
     
     info.document = document;
-    info.has_current_point = FALSE;
     info.path = xmlBufferCreate ();
 
     rx = ry = stroke_style->line_width;
@@ -1176,7 +1164,6 @@ _cairo_svg_surface_intersect_clip_path (
 
     if (path != NULL) {
 	info.document = document;
-	info.has_current_point = FALSE;
 	info.path = xmlBufferCreate ();
 
 	group = xmlNewChild (surface->xml_node, NULL, CC2XML ("g"), NULL);
diff --git a/src/cairo.c b/src/cairo.c
index 96cd504..6a94d0f 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -957,8 +957,8 @@ cairo_device_to_user_distance (cairo_t *
  * cairo_new_path:
  * @cr: a cairo context
  *
- * Clears the current path. After this call there will be no current
- * point.
+ * Clears the current path. After this call there will be no path and
+ * no current point.
  **/
 void
 cairo_new_path (cairo_t *cr)
@@ -976,8 +976,8 @@ slim_hidden_def(cairo_new_path);
  * @x: the X coordinate of the new position
  * @y: the Y coordinate of the new position
  *
- * If the current subpath is not empty, begin a new subpath. After
- * this call the current point will be (@x, @y).
+ * Begin a new subpath. After this call the current point will be (@x,
+ * @y).
  **/
 void
 cairo_move_to (cairo_t *cr, double x, double y)
@@ -998,6 +998,31 @@ cairo_move_to (cairo_t *cr, double x, do
 slim_hidden_def(cairo_move_to);
 
 /**
+ * cairo_new_sub_path:
+ * @cr: a cairo context
+ * 
+ * Begin a new subpath. Note that the existing path is not
+ * affected. After this call there will be no current point.
+ *
+ * In many cases, this call is not needed since new subpaths are
+ * frequently started with cairo_move_to().
+ *
+ * A call to cairo_new_sub_path() is particularly useful when
+ * beginning a new subpath with one of the cairo_arc() calls. This
+ * makes things easier as it is no longer necessary to manually
+ * compute the arc's initial coordinates for a call to
+ * cairo_move_to().
+ **/
+void
+cairo_new_sub_path (cairo_t *cr)
+{
+    if (cr->status)
+	return;
+
+    _cairo_path_fixed_new_sub_path (&cr->path);
+}
+
+/**
  * cairo_line_to:
  * @cr: a cairo context
  * @x: the X coordinate of the end of the new line
@@ -1006,6 +1031,9 @@ slim_hidden_def(cairo_move_to);
  * Adds a line to the path from the current point to position (@x, @y)
  * in user-space coordinates. After this call the current point
  * will be (@x, @y).
+ *
+ * If there is no current point before the call to cairo_line_to()
+ * this function will behave as cairo_move_to (@cr, @x, @y).
  **/
 void
 cairo_line_to (cairo_t *cr, double x, double y)
@@ -1038,6 +1066,10 @@ cairo_line_to (cairo_t *cr, double x, do
  * position (@x3, @y3) in user-space coordinates, using (@x1, @y1) and
  * (@x2, @y2) as the control points. After this call the current point
  * will be (@x3, @y3).
+ *
+ * If there is no current point before the call to cairo_curve_to()
+ * this function will behave as if preceded by a call to
+ * cairo_move_to (@cr, @x1, @y1).
  **/
 void
 cairo_curve_to (cairo_t *cr,
@@ -1208,11 +1240,15 @@ cairo_arc_to (cairo_t *cr,
  * @dx: the X offset
  * @dy: the Y offset
  *
- * If the current subpath is not empty, begin a new subpath. After
- * this call the current point will offset by (@x, @y).
+ * Begin a new subpath. After this call the current point will offset
+ * by (@x, @y).
  *
  * Given a current point of (x, y), cairo_rel_move_to(@cr, @dx, @dy)
  * is logically equivalent to cairo_move_to (@cr, x + @dx, y + @dy).
+ *
+ * It is an error to call this function with no current point. Doing
+ * so will cause @cr to shutdown with a status of
+ * CAIRO_STATUS_NO_CURRENT_POINT.
  **/
 void
 cairo_rel_move_to (cairo_t *cr, double dx, double dy)
@@ -1244,6 +1280,10 @@ cairo_rel_move_to (cairo_t *cr, double d
  *
  * Given a current point of (x, y), cairo_rel_line_to(@cr, @dx, @dy)
  * is logically equivalent to cairo_line_to (@cr, x + @dx, y + @dy).
+ *
+ * It is an error to call this function with no current point. Doing
+ * so will cause @cr to shutdown with a status of
+ * CAIRO_STATUS_NO_CURRENT_POINT.
  **/
 void
 cairo_rel_line_to (cairo_t *cr, double dx, double dy)
@@ -1284,6 +1324,10 @@ slim_hidden_def(cairo_rel_line_to);
  * @dy1, @dx2, @dy2, @dx3, @dy3) is logically equivalent to
  * cairo_curve_to (@cr, x + @dx1, y + @dy1, x + @dx2, y + @dy2, x +
  * @dx3, y + @dy3).
+ *
+ * It is an error to call this function with no current point. Doing
+ * so will cause @cr to shutdown with a status of
+ * CAIRO_STATUS_NO_CURRENT_POINT.
  **/
 void
 cairo_rel_curve_to (cairo_t *cr,
@@ -1378,8 +1422,10 @@ cairo_stroke_to_path (cairo_t *cr)
  * The behavior of cairo_close_path() is distinct from simply calling
  * cairo_line_to() with the equivalent coordinate in the case of
  * stroking. When a closed subpath is stroked, there are no caps on
- * the ends of the subpath. Instead, their is a line join connecting
+ * the ends of the subpath. Instead, there is a line join connecting
  * the final and initial segments of the subpath.
+ *
+ * If there is no current point, this function will have no effect.
  **/
 void
 cairo_close_path (cairo_t *cr)
diff --git a/src/cairo.h b/src/cairo.h
index fbb3620..6dd2742 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -436,6 +436,9 @@ cairo_public void
 cairo_move_to (cairo_t *cr, double x, double y);
 
 cairo_public void
+cairo_new_sub_path (cairo_t *cr);
+
+cairo_public void
 cairo_line_to (cairo_t *cr, double x, double y);
 
 cairo_public void
diff --git a/src/cairoint.h b/src/cairoint.h
index 88fccae..d51b994 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1394,6 +1394,9 @@ _cairo_path_fixed_move_to (cairo_path_fi
 			   cairo_fixed_t	x,
 			   cairo_fixed_t	y);
 
+cairo_private void
+_cairo_path_fixed_new_sub_path (cairo_path_fixed_t *path);
+
 cairo_private cairo_status_t
 _cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
 			       cairo_fixed_t	   dx,
diff --git a/test/.gitignore b/test/.gitignore
index 5173349..1a12122 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -37,6 +37,7 @@ move-to-show-surface
 multi-page
 multi-page.pdf
 multi-page.ps
+new-sub-path
 nil-surface
 operator-clear
 operator-source
diff --git a/test/Makefile.am b/test/Makefile.am
index 0da8b5a..0ea0624 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -29,6 +29,7 @@ mask				\
 mask-ctm			\
 mask-surface-ctm		\
 move-to-show-surface		\
+new-sub-path			\
 nil-surface			\
 operator-clear			\
 operator-source			\
@@ -143,6 +144,8 @@ mask-surface-ctm-ref.png				\
 mask-surface-ctm-rgb24-ref.png				\
 move-to-show-surface-ref.png				\
 move-to-show-surface-rgb24-ref.png			\
+new-sub-path-ref.png					\
+new-sub-path-rgb24-ref.png				\
 nil-surface-ref.png					\
 nil-surface-rgb24-ref.png				\
 operator-clear-ref.png					\
@@ -311,6 +314,7 @@ mask_ctm_LDADD = $(LDADDS)
 mask_surface_ctm_LDADD = $(LDADDS)
 multi_page_LDADD = $(LDADDS)
 move_to_show_surface_LDADD = $(LDADDS)
+new_sub_path_LDADD = $(LDADDS)
 nil_surface_LDADD = $(LDADDS)
 operator_clear_LDADD = $(LDADDS)
 operator_source_LDADD = $(LDADDS)
diff --git a/test/new-sub-path-ref.png b/test/new-sub-path-ref.png
new file mode 100644
index 0000000..7319ab3
Binary files /dev/null and b/test/new-sub-path-ref.png differ
diff --git a/test/new-sub-path-rgb24-ref.png b/test/new-sub-path-rgb24-ref.png
new file mode 100644
index 0000000..8cbc731
Binary files /dev/null and b/test/new-sub-path-rgb24-ref.png differ
diff --git a/test/new-sub-path.c b/test/new-sub-path.c
new file mode 100644
index 0000000..90e0c73
--- /dev/null
+++ b/test/new-sub-path.c
@@ -0,0 +1,79 @@
+/*
+ * 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"
+
+#define SIZE 10
+
+cairo_test_t test = {
+    "new-sub-path",
+    "Test the cairo_new_sub_path call",
+    8 * SIZE,
+    3 * SIZE
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); /* blue */
+
+    /* Test cairo_new_sub_path followed by several different
+     * path-modification functions in turn...
+     */
+
+    /* ... cairo_move_to */
+    cairo_new_sub_path (cr);
+    cairo_move_to (cr, SIZE, SIZE);
+    cairo_line_to (cr, SIZE, 2 * SIZE);
+
+    /* ... cairo_line_to */
+    cairo_new_sub_path (cr);
+    cairo_line_to (cr, 2 * SIZE, 1.5 * SIZE);
+    cairo_line_to (cr, 3 * SIZE, 1.5 * SIZE);
+
+    /* ... cairo_curve_to */
+    cairo_new_sub_path (cr);
+    cairo_curve_to (cr,
+		    4.0 * SIZE, 1.5 * SIZE,
+		    4.5 * SIZE, 1.0 * SIZE,
+		    5.0 * SIZE, 1.5 * SIZE);
+
+    /* ... cairo_arc */
+    cairo_new_sub_path (cr);
+    cairo_arc (cr,
+	       6.5 * SIZE, 1.5 * SIZE,
+	       0.5 * SIZE,
+	       0.0, 2.0 * M_PI);
+
+    cairo_stroke (cr);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+    return cairo_test (&test, draw);
+}


More information about the cairo-commit mailing list