[cairo-commit] 4 commits - src/cairo-analysis-surface.c src/cairo.c src/cairo.h src/cairoint.h src/cairo-meta-surface.c src/cairo-paginated-surface.c src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-win32.c src/Makefile.am

Adrian Johnson ajohnson at kemper.freedesktop.org
Fri Dec 28 06:28:34 PST 2007


 src/Makefile.am               |    3 -
 src/cairo-analysis-surface.c  |   44 ++++++++++++++----
 src/cairo-meta-surface.c      |   18 -------
 src/cairo-paginated-surface.c |    1 
 src/cairo-pdf-surface.c       |    4 +
 src/cairo-ps-surface.c        |   38 ++++++++++++----
 src/cairo-win32.c             |   98 ++++++++++++++++++++++++++++++++++++++++++
 src/cairo.c                   |    2 
 src/cairo.h                   |    4 +
 src/cairoint.h                |    6 ++
 10 files changed, 178 insertions(+), 40 deletions(-)

New commits:
commit 060f384310e887f7f431a98e847b8a36fc303a0c
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sat Dec 29 00:26:11 2007 +1030

    Fix PS/PDF meta surface patterns
    
    This was failing with more than one level of push/pop group.  The
    problem was that the meta surface replay in PS/PDF emit_meta_surface
    was replaying all the meta surface commands insteads of only the
    natively supported commands. The analysis surface has also been
    changed to replay meta surface patterns back to the one analysis
    surface instead of creating a separate analysis surface for each
    pattern. The analysis surface now transforms bounding boxes with the
    meta surface pattern matrix so that fallback regions are correctly
    tracked.

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 97b245e..1276a35 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -57,31 +57,37 @@ typedef struct {
     cairo_rectangle_int_t current_clip;
     cairo_box_t page_bbox;
 
+    cairo_bool_t has_ctm;
+    cairo_matrix_t ctm;
+
 } cairo_analysis_surface_t;
 
 static cairo_int_status_t
 _cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *surface,
 						      cairo_pattern_t	       *pattern)
 {
+    cairo_surface_t *analysis = &surface->base;
     cairo_surface_pattern_t *surface_pattern;
-    cairo_surface_t *meta_surface;
-    cairo_surface_t *analysis;
     cairo_status_t status;
+    cairo_bool_t old_has_ctm;
+    cairo_matrix_t old_ctm;
 
     assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
     surface_pattern = (cairo_surface_pattern_t *) pattern;
     assert (_cairo_surface_is_meta (surface_pattern->surface));
 
-    meta_surface = surface_pattern->surface;
-    analysis = _cairo_analysis_surface_create (surface->target,
-					       surface->width, surface->height);
-    if (analysis == NULL)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    old_ctm = surface->ctm;
+    old_has_ctm = surface->has_ctm;
+    cairo_matrix_multiply (&surface->ctm, &pattern->matrix, &surface->ctm);
+    surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
 
-    status = _cairo_meta_surface_replay_analyze_meta_pattern (meta_surface, analysis);
+    status = _cairo_meta_surface_replay_and_create_regions (surface_pattern->surface,
+							    analysis);
     if (status == CAIRO_STATUS_SUCCESS)
-	    status = analysis->status;
-    cairo_surface_destroy (analysis);
+	status = analysis->status;
+
+    surface->ctm = old_ctm;
+    surface->has_ctm = old_has_ctm;
 
     return status;
 }
@@ -97,6 +103,22 @@ _cairo_analysis_surface_add_operation  (cairo_analysis_surface_t *surface,
     if (rect->width == 0 || rect->height == 0)
 	return CAIRO_STATUS_SUCCESS;
 
+    if (surface->has_ctm) {
+	double x1, y1, x2, y2;
+
+	x1 = rect->x;
+	y1 = rect->y;
+	x2 = rect->x + rect->width;
+	y2 = rect->y + rect->height;
+	_cairo_matrix_transform_bounding_box (&surface->ctm,
+					      &x1, &y1, &x2, &y2,
+					      NULL);
+	rect->x = floor (x1);
+	rect->y = floor (x2);
+	rect->width = ceil (x2) - rect->x;
+	rect->height = ceil (y2) - rect->y;
+    }
+
     bbox.p1.x = _cairo_fixed_from_int (rect->x);
     bbox.p1.y = _cairo_fixed_from_int (rect->y);
     bbox.p2.x = _cairo_fixed_from_int (rect->x + rect->width);
@@ -577,6 +599,8 @@ _cairo_analysis_surface_create (cairo_surface_t		*target,
 
     surface->width = width;
     surface->height = height;
+    cairo_matrix_init_identity (&surface->ctm);
+    surface->has_ctm = FALSE;
 
     surface->target = target;
     surface->first_op  = TRUE;
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 89b06bb..5b4f4ff 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -61,8 +61,7 @@
 
 typedef enum {
     CAIRO_META_REPLAY,
-    CAIRO_META_CREATE_REGIONS,
-    CAIRO_META_ANALYZE_META_PATTERN
+    CAIRO_META_CREATE_REGIONS
 } cairo_meta_replay_type_t;
 
 static const cairo_surface_backend_t cairo_meta_surface_backend;
@@ -853,11 +852,6 @@ _cairo_meta_surface_replay_internal (cairo_surface_t	     *surface,
 	    }
 	}
 
-	if (type == CAIRO_META_ANALYZE_META_PATTERN) {
-	    if (status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY)
-		status = CAIRO_STATUS_SUCCESS;
-	}
-
 	if (status)
 	    break;
     }
@@ -877,16 +871,6 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
 						CAIRO_META_REGION_ALL);
 }
 
-cairo_status_t
-_cairo_meta_surface_replay_analyze_meta_pattern (cairo_surface_t *surface,
-						 cairo_surface_t *target)
-{
-    return _cairo_meta_surface_replay_internal (surface,
-						target,
-						CAIRO_META_ANALYZE_META_PATTERN,
-						CAIRO_META_REGION_ALL);
-}
-
 /* Replay meta to surface. When the return status of each operation is
  * one of CAIRO_STATUS_SUCCESS, CAIRO_INT_STATUS_UNSUPPORTED, or
  * CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY the status of each operation
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index d9fac1d..068a60c 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -341,6 +341,7 @@ _paint_page (cairo_paginated_surface_t *surface)
 	status = _cairo_meta_surface_replay_region (surface->meta,
 						    surface->target,
 						    CAIRO_META_REGION_NATIVE);
+	assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
 	if (status)
 	    goto FAIL;
     }
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 695e6e9..fd9c45e 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1620,7 +1620,9 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t  *surface,
 				     surface->height);
     }
 
-    status = _cairo_meta_surface_replay (meta_surface, &surface->base);
+    status = _cairo_meta_surface_replay_region (meta_surface, &surface->base,
+						CAIRO_META_REGION_NATIVE);
+    assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
     if (status)
 	goto CLEANUP_GROUP;
 
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 44b6442..db6165a 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1770,19 +1770,16 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t    *surface,
 	  op == CAIRO_OPERATOR_OVER))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if (op == CAIRO_OPERATOR_SOURCE)
-	return CAIRO_STATUS_SUCCESS;
-
     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
 	cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
 
 	if ( _cairo_surface_is_meta (surface_pattern->surface))
 	    return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
-	else
-	    return _cairo_ps_surface_analyze_surface_pattern_transparency (surface,
-									   surface_pattern);
     }
 
+    if (op == CAIRO_OPERATOR_SOURCE)
+	return CAIRO_STATUS_SUCCESS;
+
     /* CAIRO_OPERATOR_OVER is only supported for opaque patterns. If
      * the pattern contains transparency, we return
      * CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY to the analysis
@@ -1793,6 +1790,13 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t    *surface,
      * background to convert the pattern to opaque.
      */
 
+    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
+
+	return _cairo_ps_surface_analyze_surface_pattern_transparency (surface,
+								       surface_pattern);
+    }
+
     if (_cairo_pattern_is_opaque (pattern))
 	return CAIRO_STATUS_SUCCESS;
     else
@@ -2314,7 +2318,9 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t  *surface,
 				     surface->height);
     }
 
-    status = _cairo_meta_surface_replay (meta_surface, &surface->base);
+    status = _cairo_meta_surface_replay_region (meta_surface, &surface->base,
+						CAIRO_META_REGION_NATIVE);
+    assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
     if (status)
 	return status;
 
commit 4fa46e3caaffb54f4419887418d8d0ea39816092
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sat Dec 29 00:15:03 2007 +1030

    Implement a win32 tmpfile() function
    
    Bug report and proposed patch at:
    http://lists.cairographics.org/archives/cairo/2007-December/012529.html
    
    On Windows the tmpfile() function creates the file in the root
    directory. This will fail if the user does not have write access to the
    root directory.
    
    Implement _cairo_win32_tmpfile() that is #defined as tmpfile() on
    Windows. This function uses GetTempPath() and GetTempFileName() to
    create the temporary file. CreateFile() is used to open the file so
    the DELETE_ON_CLOSE flag can be set.

diff --git a/src/Makefile.am b/src/Makefile.am
index 17cf681..e00bcfb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -73,12 +73,13 @@ libcairo_quartz_sources = cairo-quartz-surface.c cairo-quartz-private.h
 backend_pkgconfigs += cairo-quartz.pc
 endif
 
+libcairo_win32_sources =
 if OS_WIN32
+libcairo_win32_sources += cairo-win32.c
 export_symbols = -export-symbols cairo.def
 cairo_def_dependency = cairo.def
 endif
 
-libcairo_win32_sources =
 if CAIRO_HAS_WIN32_SURFACE
 libcairo_win32_headers = cairo-win32.h
 libcairo_win32_sources += cairo-win32-surface.c cairo-win32-printing-surface.c cairo-win32-private.h
diff --git a/src/cairo-win32.c b/src/cairo-win32.c
new file mode 100644
index 0000000..a656ff8
--- /dev/null
+++ b/src/cairo-win32.c
@@ -0,0 +1,98 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2007 Adrian Johnson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Adrian Johnson.
+ *
+ * Contributor(s):
+ *      Adrian Johnson <ajohnson at redneon.com>
+ */
+
+#define WIN32_LEAN_AND_MEAN
+/* We require Windows 2000 features such as ETO_PDY */
+#if !defined(WINVER) || (WINVER < 0x0500)
+# define WINVER 0x0500
+#endif
+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
+# define _WIN32_WINNT 0x0500
+#endif
+
+#include "cairoint.h"
+
+#include <windows.h>
+#include <io.h>
+
+/* tmpfile() replacment for Windows.
+ *
+ * On Windows tmpfile() creates the file in the root directory. This
+ * may fail due to unsufficient privileges.
+ */
+FILE *
+_cairo_win32_tmpfile (void)
+{
+    DWORD path_len;
+    WCHAR path_name[MAX_PATH + 1];
+    WCHAR file_name[MAX_PATH + 1];
+    HANDLE handle;
+    int fd;
+    FILE *fp;
+
+    path_len = GetTempPathW (MAX_PATH, path_name);
+    if (path_len <= 0 || path_len >= MAX_PATH)
+	return NULL;
+
+    if (GetTempFileNameW (path_name, L"ps_", 0, file_name) == 0)
+	return NULL;
+
+    handle = CreateFileW (file_name,
+			 GENERIC_READ | GENERIC_WRITE,
+			 0,
+			 NULL,
+			 CREATE_ALWAYS,
+			 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
+			 NULL);
+    if (handle == INVALID_HANDLE_VALUE) {
+	DeleteFileW (file_name);
+	return NULL;
+    }
+
+    fd = _open_osfhandle((intptr_t) handle, 0);
+    if (fd < 0) {
+	CloseHandle (handle);
+	return NULL;
+    }
+
+    fp = fdopen(fd, "w+b");
+    if (fp == NULL) {
+	_close(fd);
+	return NULL;
+    }
+
+    return fp;
+}
diff --git a/src/cairoint.h b/src/cairoint.h
index 4f8213a..40638db 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -81,6 +81,12 @@
 
 CAIRO_BEGIN_DECLS
 
+#ifdef _WIN32
+cairo_private FILE *
+_cairo_win32_tmpfile (void);
+#define tmpfile() _cairo_win32_tmpfile()
+#endif
+
 #undef MIN
 #define MIN(a, b) ((a) < (b) ? (a) : (b))
 
commit dcacad932334bbcc3cf6b1df3b37412db5017116
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sat Dec 29 00:13:24 2007 +1030

    PS: Use _TEMP_FILE_ERROR for temp file errors

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 3dda7ce..44b6442 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -884,15 +884,20 @@ BAIL:
     return status;
 }
 
-static void
+static cairo_status_t
 _cairo_ps_surface_emit_body (cairo_ps_surface_t *surface)
 {
     char    buf[4096];
     int	    n;
 
+    if (ferror (surface->tmpfile) != 0)
+	return CAIRO_STATUS_TEMP_FILE_ERROR;
+
     rewind (surface->tmpfile);
     while ((n = fread (buf, 1, sizeof (buf), surface->tmpfile)) > 0)
 	_cairo_output_stream_write (surface->final_stream, buf, n);
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void
@@ -932,8 +937,10 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
     surface->final_stream = stream;
 
     surface->tmpfile = tmpfile ();
-    if (surface->tmpfile == NULL)
+    if (surface->tmpfile == NULL) {
+	status = CAIRO_STATUS_TEMP_FILE_ERROR;
 	goto CLEANUP_SURFACE;
+    }
 
     surface->stream = _cairo_output_stream_create_for_file (surface->tmpfile);
     status = _cairo_output_stream_get_status (surface->stream);
@@ -1490,11 +1497,16 @@ _cairo_ps_surface_finish (void *abstract_surface)
     _cairo_ps_surface_emit_header (surface);
 
     status = _cairo_ps_surface_emit_font_subsets (surface);
+    if (status)
+	goto CLEANUP;
 
-    _cairo_ps_surface_emit_body (surface);
+    status = _cairo_ps_surface_emit_body (surface);
+    if (status)
+	goto CLEANUP;
 
     _cairo_ps_surface_emit_footer (surface);
 
+CLEANUP:
     status2 = _cairo_output_stream_destroy (surface->stream);
     if (status == CAIRO_STATUS_SUCCESS)
 	status = status2;
commit bd44d114a6d4271a4a15cf7d70a996e73a86751c
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sat Dec 29 00:12:44 2007 +1030

    Add CAIRO_STATUS_TEMP_FILE_ERROR

diff --git a/src/cairo.c b/src/cairo.c
index 617cd25..34d7537 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -3553,6 +3553,8 @@ cairo_status_to_string (cairo_status_t status)
 	return "invalid index passed to getter";
     case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
         return "clip region not representable in desired format";
+    case CAIRO_STATUS_TEMP_FILE_ERROR:
+	return "error creating or writing to a temporary file";
     }
 
     return "<unknown error status>";
diff --git a/src/cairo.h b/src/cairo.h
index 65d8b36..d612093 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -201,6 +201,7 @@ typedef struct _cairo_user_data_key {
  * @CAIRO_STATUS_INVALID_DSC_COMMENT: invalid value for a DSC comment (Since 1.2)
  * @CAIRO_STATUS_INVALID_INDEX: invalid index passed to getter (Since 1.4)
  * @CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: clip region not representable in desired format (Since 1.4)
+ * @CAIRO_STATUS_TEMP_FILE_ERROR: error creating or writing to a temporary file (Since 1.6)
  *
  * #cairo_status_t is used to indicate errors that can occur when
  * using Cairo. In some cases it is returned directly by functions.
@@ -233,7 +234,8 @@ typedef enum _cairo_status {
     CAIRO_STATUS_INVALID_DASH,
     CAIRO_STATUS_INVALID_DSC_COMMENT,
     CAIRO_STATUS_INVALID_INDEX,
-    CAIRO_STATUS_CLIP_NOT_REPRESENTABLE
+    CAIRO_STATUS_CLIP_NOT_REPRESENTABLE,
+    CAIRO_STATUS_TEMP_FILE_ERROR
 } cairo_status_t;
 
 /**


More information about the cairo-commit mailing list