summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2009-06-02 00:37:19 -0700
committerEric Anholt <eric@anholt.net>2009-06-02 00:56:39 -0700
commitf59f44c140e5f60d336423e0585d2bb8a6c0ea01 (patch)
treeb0e1369a4aedfb6ee288fd29264177e881021850
parent2da78fd4666faa27d037ae3625ca83353a6e7629 (diff)
parent4232719af968ed05636fe34f2ffe2520dc02d737 (diff)
Merge commit 'origin/master' into gl
Felt like pulling the latest stuff, since I branched back in February. Conflicts: build/configure.ac.features src/cairo.h util/cairo-script/csi-replay.c
-rw-r--r--AUTHORS2
-rw-r--r--NEWS20
-rw-r--r--boilerplate/Makefile.sources3
-rw-r--r--boilerplate/Makefile.win322
-rw-r--r--boilerplate/Makefile.win32.features20
-rw-r--r--boilerplate/cairo-boilerplate-sdl-private.h56
-rw-r--r--boilerplate/cairo-boilerplate-sdl.c69
-rw-r--r--boilerplate/cairo-boilerplate-test-surfaces-private.h11
-rw-r--r--boilerplate/cairo-boilerplate-test-surfaces.c16
-rw-r--r--boilerplate/cairo-boilerplate.c49
-rw-r--r--build/.gitignore2
-rw-r--r--build/Makefile.am.gtk-doc4
-rw-r--r--build/Makefile.win32.common8
-rw-r--r--build/Makefile.win32.features2
-rw-r--r--build/Makefile.win32.features-h6
-rw-r--r--build/aclocal.dolt.m41
-rw-r--r--build/aclocal.shave.m477
-rw-r--r--build/configure.ac.analysis39
-rw-r--r--build/configure.ac.features3
-rw-r--r--build/configure.ac.system4
-rw-r--r--build/shave-libtool.in69
-rw-r--r--build/shave.in82
-rw-r--r--configure.ac40
-rw-r--r--doc/public/cairo-sections.txt1
-rw-r--r--doc/public/tmpl/cairo-ft.sgml9
-rw-r--r--doc/public/tmpl/cairo-status.sgml3
-rw-r--r--doc/public/tmpl/cairo-surface.sgml1
-rw-r--r--perf/Makefile.am6
-rw-r--r--perf/box-outline.c3
-rw-r--r--perf/cairo-perf.c41
-rw-r--r--perf/cairo-perf.h4
-rw-r--r--perf/composite-checker.c3
-rw-r--r--perf/dragon.c3
-rw-r--r--perf/fill.c24
-rw-r--r--perf/intersections.c3
-rw-r--r--perf/long-dashed-lines.c3
-rw-r--r--perf/long-lines.c3
-rw-r--r--perf/mosaic.c3
-rw-r--r--perf/paint-with-alpha.c3
-rw-r--r--perf/paint.c3
-rw-r--r--perf/pattern_create_radial.c3
-rw-r--r--perf/pythagoras-tree.c3
-rw-r--r--perf/rectangles.c3
-rw-r--r--perf/rounded-rectangles.c3
-rw-r--r--perf/spiral.c3
-rw-r--r--perf/stroke.c3
-rw-r--r--perf/subimage_copy.c3
-rw-r--r--perf/tessellate.c3
-rw-r--r--perf/text.c10
-rw-r--r--perf/twin.c3
-rw-r--r--perf/unaligned-clip.c3
-rw-r--r--perf/world-map.c3
-rw-r--r--perf/zrusin.c3
-rw-r--r--src/Makefile.am7
-rw-r--r--src/Makefile.am.analysis2
-rw-r--r--src/Makefile.sources6
-rw-r--r--src/Makefile.win322
-rw-r--r--src/Makefile.win32.features28
-rw-r--r--src/cairo-analysis-surface.c19
-rw-r--r--src/cairo-array.c39
-rw-r--r--src/cairo-bentley-ottmann.c3
-rw-r--r--src/cairo-cache-private.h5
-rw-r--r--src/cairo-cache.c39
-rw-r--r--src/cairo-clip-private.h4
-rw-r--r--src/cairo-clip.c149
-rw-r--r--src/cairo-compiler-private.h26
-rw-r--r--src/cairo-debug.c42
-rw-r--r--src/cairo-directfb-surface.c35
-rw-r--r--src/cairo-font-face-twin.c179
-rw-r--r--src/cairo-ft-font.c183
-rw-r--r--src/cairo-ft.h23
-rw-r--r--src/cairo-gl-surface.c6
-rw-r--r--src/cairo-glitz-surface.c3
-rw-r--r--src/cairo-gstate.c3
-rw-r--r--src/cairo-hash-private.h6
-rw-r--r--src/cairo-hash.c55
-rw-r--r--src/cairo-hull.c3
-rw-r--r--src/cairo-image-surface.c34
-rw-r--r--src/cairo-malloc-private.h7
-rw-r--r--src/cairo-misc.c24
-rw-r--r--src/cairo-os2-surface.c6
-rw-r--r--src/cairo-paginated-surface.c43
-rw-r--r--src/cairo-path-fixed.c2
-rw-r--r--src/cairo-path-in-fill.c31
-rw-r--r--src/cairo-path-stroke.c3
-rw-r--r--src/cairo-path.c76
-rw-r--r--src/cairo-pattern.c124
-rw-r--r--src/cairo-pdf-surface.c40
-rw-r--r--src/cairo-pen.c9
-rw-r--r--src/cairo-png.c63
-rw-r--r--src/cairo-polygon.c5
-rw-r--r--src/cairo-ps-surface.c8
-rw-r--r--src/cairo-quartz-surface.c1
-rw-r--r--src/cairo-region-private.h117
-rw-r--r--src/cairo-region.c596
-rw-r--r--src/cairo-scaled-font-private.h8
-rw-r--r--src/cairo-scaled-font-subsets.c69
-rw-r--r--src/cairo-scaled-font.c422
-rw-r--r--src/cairo-sdl-surface.c421
-rw-r--r--src/cairo-skiplist.c4
-rw-r--r--src/cairo-spans.c2
-rw-r--r--src/cairo-spline.c2
-rw-r--r--src/cairo-stroke-style.c3
-rw-r--r--src/cairo-surface-fallback-private.h1
-rw-r--r--src/cairo-surface-fallback.c108
-rw-r--r--src/cairo-surface-private.h1
-rw-r--r--src/cairo-surface.c213
-rw-r--r--src/cairo-svg-surface.c2
-rw-r--r--src/cairo-tor-scan-converter.c5
-rw-r--r--src/cairo-toy-font-face.c1
-rw-r--r--src/cairo-traps.c57
-rw-r--r--src/cairo-truetype-subset-private.h2
-rw-r--r--src/cairo-truetype-subset.c40
-rw-r--r--src/cairo-type1-fallback.c6
-rw-r--r--src/cairo-type3-glyph-surface.c36
-rw-r--r--src/cairo-types-private.h45
-rw-r--r--src/cairo-user-font.c14
-rw-r--r--src/cairo-win32-font.c11
-rw-r--r--src/cairo-win32-printing-surface.c6
-rw-r--r--src/cairo-win32-private.h1
-rw-r--r--src/cairo-win32-surface.c67
-rw-r--r--src/cairo-xcb-surface.c41
-rw-r--r--src/cairo-xlib-display.c2
-rw-r--r--src/cairo-xlib-screen.c23
-rw-r--r--src/cairo-xlib-surface.c151
-rw-r--r--src/cairo.c20
-rw-r--r--src/cairo.h113
-rw-r--r--src/cairoint.h113
-rw-r--r--src/test-fallback-surface.c1
-rw-r--r--src/test-fallback16-surface.c236
-rw-r--r--src/test-fallback16-surface.h (renamed from src/cairo-sdl.h)32
-rw-r--r--test/Makefile.am260
-rw-r--r--test/Makefile.sources254
-rw-r--r--test/Makefile.win32128
-rw-r--r--test/any2ppm.c7
-rw-r--r--test/cairo-test-runner.c20
-rw-r--r--test/cairo-test.c89
-rw-r--r--test/cairo-test.h20
-rw-r--r--test/create-from-png.c164
-rw-r--r--test/fallback-resolution.c2
-rw-r--r--test/ft-font-create-for-ft-face.c109
-rw-r--r--test/get-clip.c1
-rw-r--r--test/get-path-extents.c17
-rw-r--r--test/in-fill-trapezoid.c77
-rw-r--r--test/invalid-matrix.c10
-rw-r--r--test/path-append.c81
-rw-r--r--test/path-append.ps.ref.pngbin0 -> 4516 bytes
-rw-r--r--test/path-append.ref.pngbin0 -> 6165 bytes
-rw-r--r--test/path-append.test-fallback.ref.pngbin0 -> 6461 bytes
-rw-r--r--test/path-append.xlib-fallback.ref.pngbin0 -> 6357 bytes
-rw-r--r--test/path-append.xlib.ref.pngbin0 -> 6461 bytes
-rw-r--r--test/path-precision.c20
-rw-r--r--test/pattern-getters.c29
-rw-r--r--test/pdiff/Makefile.win322
-rw-r--r--test/rel-path.c19
-rw-r--r--test/rotate-image-surface-paint.ref.pngbin190 -> 191 bytes
-rw-r--r--test/show-glyphs-many.c13
-rw-r--r--test/solid-pattern-cache-stress.c41
-rw-r--r--test/surface-finish-twice.c17
-rw-r--r--test/surface-source.c1
-rw-r--r--test/test-fallback16-surface-source.c43
-rw-r--r--test/test-fallback16-surface-source.ref.pngbin0 -> 268 bytes
-rw-r--r--test/toy-font-face.c19
-rw-r--r--test/truetype-tables.c63
-rw-r--r--test/twin.c11
-rw-r--r--test/twin.ps.ref.pngbin1114 -> 2197 bytes
-rw-r--r--test/twin.ref.pngbin1492 -> 4038 bytes
-rw-r--r--test/twin.svg.ref.pngbin1487 -> 3027 bytes
-rw-r--r--test/user-font-mask.c18
-rw-r--r--test/user-font-proxy.c10
-rw-r--r--test/user-font-rescale.c2
-rw-r--r--test/user-font.c10
-rw-r--r--util/cairo-script/cairo-script-file.c3
-rw-r--r--util/cairo-script/cairo-script-hash.c7
-rw-r--r--util/cairo-script/cairo-script-objects.c7
-rw-r--r--util/cairo-script/cairo-script-operators.c15
-rw-r--r--util/cairo-script/cairo-script-private.h8
-rw-r--r--util/cairo-script/cairo-script-scanner.c5
-rw-r--r--util/cairo-script/cairo-script-stack.c7
-rw-r--r--util/cairo-script/csi-replay.c122
-rw-r--r--util/cairo-trace/cairo-trace.in21
-rw-r--r--util/cairo-trace/trace.c31
182 files changed, 4170 insertions, 2695 deletions
diff --git a/AUTHORS b/AUTHORS
index 289fecba..8c061743 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -86,7 +86,7 @@ Travis Spencer <tspencer@cs.pdx.edu> XCB backend fix
Bill Spitzak <spitzak@d2.com> Build fix to find Xrender.h without xrender.pc
Zhe Su <james.su@gmail.com> Add support for fontconfig's embeddedbitmap option
Owen Taylor <otaylor@redhat.com> Font rewrite, documentation, win32 backend
-Karl Tomlinson <karlt+@karlt.net>
+Karl Tomlinson <karlt+@karlt.net> Optimisation and obscure bug fixes (mozilla)
Alp Toker <alp@atoker.com> Fix several code/comment typos
Malcolm Tredinnick <malcolm@commsecure.com.au> Documentation fixes
David Turner <david@freetype.org> Optimize gradient calculations
diff --git a/NEWS b/NEWS
index cd694d87..0b485df7 100644
--- a/NEWS
+++ b/NEWS
@@ -10,9 +10,27 @@ API additions:
"image/jpeg" is understood by PDF,PS,SVG,win32-printing.
"image/png" is understood by SVG.
-New backend:
+ cairo_pdf_version_t
+ cairo_pdf_surface_restrict_to_version()
+ cairo_pdf_get_versions()
+ cairo_pdf_version_to_string()
+ Similar to restrict to version and level found in SVG and PS, these
+ limit the features used in the output to comply with the PDF specification
+ for that version.
+
+ CAIRO_STATUS_INVALID_SIZE
+ Indicates that the request surface size is not supported by the backend.
+ This generally indicates that the request is too large.
+
+ The built-in twin font is now called "@cairo:" and supports a limited set
+ of options like "@cairo:mono". Where are these specified?
+
+ cairo_in_fill() now uses flash semantics... OTOH, top and left are outside.
+
+New experimental backends:
Simple DirectMedia Layer
+ CairoScript
New utility:
diff --git a/boilerplate/Makefile.sources b/boilerplate/Makefile.sources
index d3c0fa15..971c7e1b 100644
--- a/boilerplate/Makefile.sources
+++ b/boilerplate/Makefile.sources
@@ -46,9 +46,6 @@ cairo_boilerplate_quartz_sources = cairo-boilerplate-quartz.c
cairo_boilerplate_script_private = cairo-boilerplate-script-private.h
cairo_boilerplate_script_sources = cairo-boilerplate-script.c
-cairo_boilerplate_sdl_private = cairo-boilerplate-sdl-private.h
-cairo_boilerplate_sdl_sources = cairo-boilerplate-sdl.c
-
cairo_boilerplate_svg_private = cairo-boilerplate-svg-private.h
cairo_boilerplate_svg_sources = cairo-boilerplate-svg.c
diff --git a/boilerplate/Makefile.win32 b/boilerplate/Makefile.win32
index 84075dab..286ea2b1 100644
--- a/boilerplate/Makefile.win32
+++ b/boilerplate/Makefile.win32
@@ -13,7 +13,7 @@ SOURCES = \
$(enabled_cairo_boilerplate_sources) \
$(NULL)
-OBJECTS = $(patsubst %.c, $(CFG)/%.obj, $(SOURCES))
+OBJECTS = $(patsubst %.c, $(CFG)/%-static.obj, $(SOURCES))
all: $(CFG)/boiler.lib
diff --git a/boilerplate/Makefile.win32.features b/boilerplate/Makefile.win32.features
index fd08ed60..a2efcd88 100644
--- a/boilerplate/Makefile.win32.features
+++ b/boilerplate/Makefile.win32.features
@@ -119,16 +119,6 @@ enabled_cairo_boilerplate_private += $(cairo_boilerplate_beos_private)
enabled_cairo_boilerplate_sources += $(cairo_boilerplate_beos_sources)
endif
-unsupported_cairo_boilerplate_headers += $(cairo_boilerplate_sdl_headers)
-all_cairo_boilerplate_headers += $(cairo_boilerplate_sdl_headers)
-all_cairo_boilerplate_private += $(cairo_boilerplate_sdl_private)
-all_cairo_boilerplate_sources += $(cairo_boilerplate_sdl_sources)
-ifeq ($(CAIRO_HAS_SDL_SURFACE),1)
-enabled_cairo_boilerplate_headers += $(cairo_boilerplate_sdl_headers)
-enabled_cairo_boilerplate_private += $(cairo_boilerplate_sdl_private)
-enabled_cairo_boilerplate_sources += $(cairo_boilerplate_sdl_sources)
-endif
-
supported_cairo_boilerplate_headers += $(cairo_boilerplate_png_headers)
all_cairo_boilerplate_headers += $(cairo_boilerplate_png_headers)
all_cairo_boilerplate_private += $(cairo_boilerplate_png_private)
@@ -209,6 +199,16 @@ enabled_cairo_boilerplate_private += $(cairo_boilerplate_ft_private)
enabled_cairo_boilerplate_sources += $(cairo_boilerplate_ft_sources)
endif
+supported_cairo_boilerplate_headers += $(cairo_boilerplate_fc_headers)
+all_cairo_boilerplate_headers += $(cairo_boilerplate_fc_headers)
+all_cairo_boilerplate_private += $(cairo_boilerplate_fc_private)
+all_cairo_boilerplate_sources += $(cairo_boilerplate_fc_sources)
+ifeq ($(CAIRO_HAS_FC_FONT),1)
+enabled_cairo_boilerplate_headers += $(cairo_boilerplate_fc_headers)
+enabled_cairo_boilerplate_private += $(cairo_boilerplate_fc_private)
+enabled_cairo_boilerplate_sources += $(cairo_boilerplate_fc_sources)
+endif
+
supported_cairo_boilerplate_headers += $(cairo_boilerplate_ps_headers)
all_cairo_boilerplate_headers += $(cairo_boilerplate_ps_headers)
all_cairo_boilerplate_private += $(cairo_boilerplate_ps_private)
diff --git a/boilerplate/cairo-boilerplate-sdl-private.h b/boilerplate/cairo-boilerplate-sdl-private.h
deleted file mode 100644
index 9b5bdf79..00000000
--- a/boilerplate/cairo-boilerplate-sdl-private.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Cairo - a vector graphics library with display and print output
- *
- * Copyright © 2008 Chris Wilson
- *
- * 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 Chris Wilson.
- */
-
-#ifndef CAIRO_BOILERPLATE_SDL_PRIVATE_H
-#define CAIRO_BOILERPLATE_SDL_PRIVATE_H
-
-#include <cairo.h>
-
-CAIRO_BEGIN_DECLS
-
-extern cairo_surface_t *
-_cairo_boilerplate_sdl_create_surface (const char *name,
- cairo_content_t content,
- int width,
- int height,
- int max_width,
- int max_height,
- cairo_boilerplate_mode_t mode,
- int id,
- void **closure);
-
-extern void
-_cairo_boilerplate_sdl_cleanup (void* closure);
-
-CAIRO_END_DECLS
-
-#endif /* CAIRO_BOILERPLATE_SDL_PRIVATE_H */
diff --git a/boilerplate/cairo-boilerplate-sdl.c b/boilerplate/cairo-boilerplate-sdl.c
deleted file mode 100644
index 407c2ee4..00000000
--- a/boilerplate/cairo-boilerplate-sdl.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Cairo - a vector graphics library with display and print output
- *
- * Copyright © 2008 Chris Wilson
- *
- * 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 Chris Wilson.
- */
-
-#include "cairo-boilerplate.h"
-#include "cairo-boilerplate-sdl-private.h"
-
-#include <cairo-sdl.h>
-
-void
-_cairo_boilerplate_sdl_cleanup (void *closure)
-{
- SDL_Quit ();
-}
-
-cairo_surface_t *
-_cairo_boilerplate_sdl_create_surface (const char *name,
- cairo_content_t content,
- int width,
- int height,
- int max_width,
- int max_height,
- cairo_boilerplate_mode_t mode,
- int id,
- void **closure)
-{
- SDL_Surface *screen;
- cairo_surface_t *surface;
-
- if (SDL_Init (SDL_INIT_VIDEO) < 0)
- return NULL;
-
- screen = SDL_SetVideoMode (width, height, 24, SDL_SWSURFACE);
- if (screen == NULL)
- return NULL;
-
- surface = cairo_sdl_surface_create (screen);
- SDL_FreeSurface (screen);
-
- return surface;
-}
diff --git a/boilerplate/cairo-boilerplate-test-surfaces-private.h b/boilerplate/cairo-boilerplate-test-surfaces-private.h
index 481b531e..24a1ae81 100644
--- a/boilerplate/cairo-boilerplate-test-surfaces-private.h
+++ b/boilerplate/cairo-boilerplate-test-surfaces-private.h
@@ -38,6 +38,17 @@ _cairo_boilerplate_test_fallback_create_surface (const char *name,
int id,
void **closure);
+cairo_surface_t *
+_cairo_boilerplate_test_fallback16_create_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ int max_width,
+ int max_height,
+ cairo_boilerplate_mode_t mode,
+ int id,
+ void **closure);
+
cairo_surface_t *
_cairo_boilerplate_test_meta_create_surface (const char *name,
diff --git a/boilerplate/cairo-boilerplate-test-surfaces.c b/boilerplate/cairo-boilerplate-test-surfaces.c
index f6fd63af..644b2787 100644
--- a/boilerplate/cairo-boilerplate-test-surfaces.c
+++ b/boilerplate/cairo-boilerplate-test-surfaces.c
@@ -28,6 +28,7 @@
#include "cairo-boilerplate-test-surfaces-private.h"
#include <test-fallback-surface.h>
+#include <test-fallback16-surface.h>
#include <test-meta-surface.h>
#include <test-paginated-surface.h>
@@ -49,6 +50,21 @@ _cairo_boilerplate_test_fallback_create_surface (const char *name,
}
cairo_surface_t *
+_cairo_boilerplate_test_fallback16_create_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ int max_width,
+ int max_height,
+ cairo_boilerplate_mode_t mode,
+ int id,
+ void **closure)
+{
+ *closure = NULL;
+ return _cairo_test_fallback16_surface_create (content, width, height);
+}
+
+cairo_surface_t *
_cairo_boilerplate_test_meta_create_surface (const char *name,
cairo_content_t content,
int width,
diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
index 09859bab..993401ed 100644
--- a/boilerplate/cairo-boilerplate.c
+++ b/boilerplate/cairo-boilerplate.c
@@ -53,9 +53,6 @@
#if CAIRO_HAS_SCRIPT_SURFACE
#include "cairo-boilerplate-script-private.h"
#endif
-#if CAIRO_HAS_SDL_SURFACE
-#include "cairo-boilerplate-sdl-private.h"
-#endif
#if CAIRO_HAS_SVG_SURFACE
#include "cairo-boilerplate-svg-private.h"
#endif
@@ -82,6 +79,7 @@
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
+#include <errno.h>
#if HAVE_UNISTD_H && HAVE_FCNTL_H && HAVE_SIGNAL_H && HAVE_SYS_STAT_H && HAVE_SYS_SOCKET_H && HAVE_SYS_UN_H
#include <unistd.h>
@@ -176,6 +174,9 @@ _cairo_boilerplate_get_image_surface (cairo_surface_t *src,
cairo_surface_t *surface;
cairo_t *cr;
+ if (cairo_surface_status (src))
+ return cairo_surface_reference (src);
+
#if 0
if (cairo_surface_get_type (src) == CAIRO_SURFACE_TYPE_IMAGE) {
int ww = cairo_image_surface_get_width (src);
@@ -313,6 +314,24 @@ static cairo_boilerplate_target_t targets[] =
cairo_surface_write_to_png
},
{
+ "test-fallback16", "image", NULL,
+ CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+ CAIRO_CONTENT_COLOR_ALPHA, 0,
+ _cairo_boilerplate_test_fallback16_create_surface, NULL,
+ NULL,
+ _cairo_boilerplate_get_image_surface,
+ cairo_surface_write_to_png
+ },
+ {
+ "test-fallback16", "image", NULL,
+ CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+ CAIRO_CONTENT_COLOR, 0,
+ _cairo_boilerplate_test_fallback16_create_surface, NULL,
+ NULL,
+ _cairo_boilerplate_get_image_surface,
+ cairo_surface_write_to_png
+ },
+ {
"test-meta", "image", NULL,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
CAIRO_CONTENT_COLOR_ALPHA, 0,
@@ -748,18 +767,6 @@ static cairo_boilerplate_target_t targets[] =
_cairo_boilerplate_directfb_cleanup
},
#endif
-
-#if CAIRO_HAS_SDL_SURFACE
- {
- "sdl", "sdl", NULL,
- CAIRO_SURFACE_TYPE_SDL, CAIRO_CONTENT_COLOR, 0,
- _cairo_boilerplate_sdl_create_surface, NULL,
- NULL,
- _cairo_boilerplate_get_image_surface,
- cairo_surface_write_to_png,
- _cairo_boilerplate_sdl_cleanup
- },
-#endif
};
cairo_boilerplate_target_t **
@@ -1013,7 +1020,7 @@ cairo_boilerplate_image_surface_create_from_ppm_stream (FILE *file)
goto FAIL;
}
if (cairo_surface_status (image))
- goto FAIL;
+ return image;
data = cairo_image_surface_get_data (image);
stride = cairo_image_surface_get_stride (image);
@@ -1057,8 +1064,14 @@ cairo_boilerplate_convert_to_image (const char *filename, int page)
RETRY:
file = cairo_boilerplate_open_any2ppm (filename, page, flags);
- if (file == NULL)
- return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_READ_ERROR);
+ if (file == NULL) {
+ switch (errno) {
+ case ENOMEM:
+ return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
+ default:
+ return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_READ_ERROR);
+ }
+ }
image = cairo_boilerplate_image_surface_create_from_ppm_stream (file);
ret = pclose (file);
diff --git a/build/.gitignore b/build/.gitignore
index 53f31d77..ce1256a5 100644
--- a/build/.gitignore
+++ b/build/.gitignore
@@ -10,3 +10,5 @@ mkinstalldirs
#Makefile.win32.features-h
libtool.m4
lt*.m4
+shave
+shave-libtool
diff --git a/build/Makefile.am.gtk-doc b/build/Makefile.am.gtk-doc
index cb815991..50cd6279 100644
--- a/build/Makefile.am.gtk-doc
+++ b/build/Makefile.am.gtk-doc
@@ -10,8 +10,8 @@
####################################
if GTK_DOC_USE_LIBTOOL
-GTKDOC_CC = $(LIBTOOL) --mode=compile $(CC) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-GTKDOC_LD = $(LIBTOOL) --mode=link $(CC) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
+GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
else
GTKDOC_CC = $(CC) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
GTKDOC_LD = $(CC) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
diff --git a/build/Makefile.win32.common b/build/Makefile.win32.common
index 2fa3255c..c1f0cb84 100644
--- a/build/Makefile.win32.common
+++ b/build/Makefile.win32.common
@@ -27,17 +27,19 @@ PIXMAN_LIBS := $(top_builddir)/../pixman/pixman/$(CFG)/pixman-1.lib
CAIRO_LIBS = gdi32.lib msimg32.lib user32.lib
ifeq ($(CAIRO_HAS_PNG_FUNCTIONS),1)
-CAIRO_LIBS += libpng.lib
+LIBPNG_CFLAGS += -I$(top_srcdir)/../libpng/
+CAIRO_LIBS += $(top_builddir)/../libpng/libpng.lib
endif
ifeq ($(CAIRO_HAS_PS_SURFACE)$(CAIRO_HAS_PDF_SURFACE),00)
else
-CAIRO_LIBS += zdll.lib
+ZLIB_CFLAGS += -I$(top_srcdir)/../zlib/
+CAIRO_LIBS += $(top_builddir)/../zlib/zdll.lib
endif
DEFAULT_CFLAGS = -nologo $(MS_MDFLAGS) $(OPT)
DEFAULT_CFLAGS += -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
DEFAULT_CFLAGS += -I. -I$(top_srcdir)
-DEFAULT_CFLAGS += $(PIXMAN_CFLAGS)
+DEFAULT_CFLAGS += $(PIXMAN_CFLAGS) $(LIBPNG_CFLAGS) $(ZLIB_CFLAGS)
CAIRO_CFLAGS = $(DEFAULT_CFLAGS) $(CFLAGS)
diff --git a/build/Makefile.win32.features b/build/Makefile.win32.features
index f9e064de..9e722246 100644
--- a/build/Makefile.win32.features
+++ b/build/Makefile.win32.features
@@ -10,7 +10,6 @@ CAIRO_HAS_WIN32_SURFACE=1
CAIRO_HAS_WIN32_FONT=1
CAIRO_HAS_OS2_SURFACE=0
CAIRO_HAS_BEOS_SURFACE=0
-CAIRO_HAS_SDL_SURFACE=0
CAIRO_HAS_PNG_FUNCTIONS=1
CAIRO_HAS_GL_SURFACE=0
CAIRO_HAS_GL_GLX_SURFACE=0
@@ -19,6 +18,7 @@ CAIRO_HAS_GLITZ_SURFACE=0
CAIRO_HAS_DIRECTFB_SURFACE=0
CAIRO_HAS_SCRIPT_SURFACE=0
CAIRO_HAS_FT_FONT=0
+CAIRO_HAS_FC_FONT=0
CAIRO_HAS_PS_SURFACE=1
CAIRO_HAS_PDF_SURFACE=1
CAIRO_HAS_SVG_SURFACE=1
diff --git a/build/Makefile.win32.features-h b/build/Makefile.win32.features-h
index da80593d..57514b48 100644
--- a/build/Makefile.win32.features-h
+++ b/build/Makefile.win32.features-h
@@ -35,9 +35,6 @@ endif
ifeq ($(CAIRO_HAS_BEOS_SURFACE),1)
@echo "#define CAIRO_HAS_BEOS_SURFACE 1" >> src/cairo-features.h
endif
-ifeq ($(CAIRO_HAS_SDL_SURFACE),1)
- @echo "#define CAIRO_HAS_SDL_SURFACE 1" >> src/cairo-features.h
-endif
ifeq ($(CAIRO_HAS_PNG_FUNCTIONS),1)
@echo "#define CAIRO_HAS_PNG_FUNCTIONS 1" >> src/cairo-features.h
endif
@@ -62,6 +59,9 @@ endif
ifeq ($(CAIRO_HAS_FT_FONT),1)
@echo "#define CAIRO_HAS_FT_FONT 1" >> src/cairo-features.h
endif
+ifeq ($(CAIRO_HAS_FC_FONT),1)
+ @echo "#define CAIRO_HAS_FC_FONT 1" >> src/cairo-features.h
+endif
ifeq ($(CAIRO_HAS_PS_SURFACE),1)
@echo "#define CAIRO_HAS_PS_SURFACE 1" >> src/cairo-features.h
endif
diff --git a/build/aclocal.dolt.m4 b/build/aclocal.dolt.m4
index 8f94582f..ece5eea9 100644
--- a/build/aclocal.dolt.m4
+++ b/build/aclocal.dolt.m4
@@ -155,6 +155,7 @@ modeok=false
tagok=false
for arg in "$[]@"; do
case "$arg" in
+ --silent) ;;
--mode=compile) modeok=true ;;
--tag=CC|--tag=CXX) tagok=true ;;
*) args@<:@${#args[@]}@:>@="$arg" ;;
diff --git a/build/aclocal.shave.m4 b/build/aclocal.shave.m4
new file mode 100644
index 00000000..0a3509e5
--- /dev/null
+++ b/build/aclocal.shave.m4
@@ -0,0 +1,77 @@
+dnl Make automake/libtool output more friendly to humans
+dnl Damien Lespiau <damien.lespiau@gmail.com>
+dnl
+dnl SHAVE_INIT([shavedir],[default_mode])
+dnl
+dnl shavedir: the directory where the shave scripts are, it defaults to
+dnl $(top_builddir)
+dnl default_mode: (enable|disable) default shave mode. This parameter
+dnl controls shave's behaviour when no option has been
+dnl given to configure. It defaults to disable.
+dnl
+dnl * SHAVE_INIT should be called late in your configure.(ac|in) file (just
+dnl before AC_CONFIG_FILE/AC_OUTPUT is perfect. This macro rewrites CC and
+dnl LIBTOOL, you don't want the configure tests to have these variables
+dnl re-defined.
+dnl * This macro requires GNU make's -s option.
+
+AC_DEFUN([_SHAVE_ARG_ENABLE],
+[
+ AC_ARG_ENABLE([shave],
+ AS_HELP_STRING(
+ [--enable-shave],
+ [use shave to make the build pretty [[default=$1]]]),,
+ [enable_shave=$1]
+ )
+])
+
+AC_DEFUN([SHAVE_INIT],
+[
+ dnl you can tweak the default value of enable_shave
+ m4_if([$2], [enable], [_SHAVE_ARG_ENABLE(yes)], [_SHAVE_ARG_ENABLE(no)])
+
+ if test x"$enable_shave" = xyes; then
+ dnl where can we find the shave scripts?
+ m4_if([$1],,
+ [shavedir="$ac_pwd"],
+ [shavedir="$ac_pwd/$1"])
+ AC_SUBST(shavedir)
+
+ dnl make is now quiet
+ AC_SUBST([MAKEFLAGS], [-s])
+ AC_SUBST([AM_MAKEFLAGS], ['`test -z $V && echo -s`'])
+
+ dnl we need sed
+ AC_CHECK_PROG(SED,sed,sed,false)
+
+ dnl substitute libtool
+ SHAVE_SAVED_LIBTOOL=$LIBTOOL
+ LIBTOOL="${SHELL} ${shavedir}/shave-libtool '${SHAVE_SAVED_LIBTOOL}'"
+ AC_SUBST(LIBTOOL)
+
+ dnl substitute cc/cxx
+ SHAVE_SAVED_CC=$CC
+ SHAVE_SAVED_CXX=$CXX
+ SHAVE_SAVED_FC=$FC
+ SHAVE_SAVED_F77=$F77
+ SHAVE_SAVED_OBJC=$OBJC
+ CC="${SHELL} ${shavedir}/shave cc ${SHAVE_SAVED_CC}"
+ CXX="${SHELL} ${shavedir}/shave cxx ${SHAVE_SAVED_CXX}"
+ FC="${SHELL} ${shavedir}/shave fc ${SHAVE_SAVED_FC}"
+ F77="${SHELL} ${shavedir}/shave f77 ${SHAVE_SAVED_F77}"
+ OBJC="${SHELL} ${shavedir}/shave objc ${SHAVE_SAVED_OBJC}"
+ AC_SUBST(CC)
+ AC_SUBST(CXX)
+ AC_SUBST(FC)
+ AC_SUBST(F77)
+ AC_SUBST(OBJC)
+
+ V=@
+ else
+ V=1
+ fi
+ Q='$(V:1=)'
+ AC_SUBST(V)
+ AC_SUBST(Q)
+])
+
diff --git a/build/configure.ac.analysis b/build/configure.ac.analysis
index 49928a56..4e8a02da 100644
--- a/build/configure.ac.analysis
+++ b/build/configure.ac.analysis
@@ -25,7 +25,7 @@ if test "x$use_gcov" = "xyes"; then
AC_MSG_ERROR([ccache must be disabled when --enable-gcov option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.])
fi
- ltp_version_list="1.6 1.5 1.4"
+ ltp_version_list="1.7 1.6 1.5 1.4"
AC_CHECK_PROG(LTP, lcov, lcov)
AC_CHECK_PROG(LTP_GENHTML, genhtml, genhtml)
@@ -82,18 +82,25 @@ AM_CONDITIONAL(CAIRO_HAS_LCOV, test "x$cairo_has_lcov" = "xyes")
dnl ===========================================================================
dnl Check for some custom valgrind modules
-PKG_CHECK_MODULES(VALGRIND, valgrind, [
- _save_CFLAGS="$CFLAGS"
- _save_CPPFLAGS="$CPPFLAGS"
- CFLAGS="$CFLAGS $VALGRIND_CFLAGS"
- CPPFLAGS="$CPPFLAGS $VALGRIND_CFLAGS"
- AC_CHECK_HEADER([valgrind.h], [AC_DEFINE([HAVE_VALGRIND], [1],
- [Define to 1 if you have Valgrind])])
- AC_CHECK_HEADER([lockdep.h], [AC_DEFINE([HAVE_LOCKDEP], [1],
- [Define to 1 if you have the Valgrind lockdep tool])])
- AC_CHECK_HEADER([memfault.h], [AC_DEFINE([HAVE_MEMFAULT], [1],
- [Define to 1 if you have the Valgrind memfault tool])])
- CAIRO_CFLAGS="$VALGRIND_CFLAGS $CAIRO_CFLAGS"
- CFLAGS="$_save_CFLAGS"
- CPPFLAGS="$_save_CPPFLAGS"
- ], AC_MSG_RESULT(no))
+AC_ARG_ENABLE(valgrind,
+ AS_HELP_STRING([--disable-valgrind],
+ [Disable valgrind support]),
+ [use_valgrind=$enableval], [use_valgrind=yes])
+
+if test "x$use_valgrind" = "xyes"; then
+ PKG_CHECK_MODULES(VALGRIND, valgrind, [
+ _save_CFLAGS="$CFLAGS"
+ _save_CPPFLAGS="$CPPFLAGS"
+ CFLAGS="$CFLAGS $VALGRIND_CFLAGS"
+ CPPFLAGS="$CPPFLAGS $VALGRIND_CFLAGS"
+ AC_CHECK_HEADER([valgrind.h], [AC_DEFINE([HAVE_VALGRIND], [1],
+ [Define to 1 if you have Valgrind])])
+ AC_CHECK_HEADER([lockdep.h], [AC_DEFINE([HAVE_LOCKDEP], [1],
+ [Define to 1 if you have the Valgrind lockdep tool])])
+ AC_CHECK_HEADER([memfault.h], [AC_DEFINE([HAVE_MEMFAULT], [1],
+ [Define to 1 if you have the Valgrind memfault tool])])
+ CAIRO_CFLAGS="$VALGRIND_CFLAGS $CAIRO_CFLAGS"
+ CFLAGS="$_save_CFLAGS"
+ CPPFLAGS="$_save_CPPFLAGS"
+ ], AC_MSG_RESULT(no))
+fi
diff --git a/build/configure.ac.features b/build/configure.ac.features
index f4774143..ce79546f 100644
--- a/build/configure.ac.features
+++ b/build/configure.ac.features
@@ -376,7 +376,6 @@ AC_DEFUN([CAIRO_REPORT],
echo " glitz: $use_glitz"
echo " BeOS: $use_beos"
echo " DirectFB: $use_directfb"
- echo " SDL: $use_sdl"
echo " GL: $use_gl"
echo " GL/GLX: $use_gl_glx"
echo " GL/EGL: $use_gl_egl"
@@ -384,6 +383,7 @@ AC_DEFUN([CAIRO_REPORT],
echo "The following font backends:"
echo " User: yes (always builtin)"
echo " FreeType: $use_ft"
+ echo " Fontconfig: $use_fc"
echo " Win32: $use_win32_font"
echo " Quartz: $use_quartz_font"
echo ""
@@ -391,6 +391,7 @@ AC_DEFUN([CAIRO_REPORT],
echo " PNG functions: $use_png"
echo ""
echo "And the following internal features:"
+ echo " gtk-doc: $enable_gtk_doc"
echo " gcov support: $use_gcov"
echo " test surfaces: $use_test_surfaces"
echo " ps testing: $test_ps"
diff --git a/build/configure.ac.system b/build/configure.ac.system
index 4544a54f..2ee0cc42 100644
--- a/build/configure.ac.system
+++ b/build/configure.ac.system
@@ -65,7 +65,7 @@ AC_CHECK_HEADERS([sched.h],
dnl check for GNU-extensions to fenv
AC_CHECK_HEADER(fenv.h,
- [AC_CHECK_FUNCS(feenableexcept fedisableexcept)])
+ [AC_CHECK_FUNCS(feenableexcept fedisableexcept feclearexcept)])
dnl check for misc headers and functions
AC_CHECK_HEADERS([libgen.h byteswap.h signal.h setjmp.h])
@@ -81,7 +81,7 @@ AC_CHECK_FUNC(mkdir,
[AC_MSG_CHECKING([mkdir variant])
mkdir_variant="unknown"
save_CFLAGS="$CFLAGS"
- CFLAGS="-Werror -Wall $CFLAGS" # non-gcc compilers?
+ CFLAGS=$WARN_CFLAGS
AC_TRY_COMPILE([
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
diff --git a/build/shave-libtool.in b/build/shave-libtool.in
new file mode 100644
index 00000000..1f3a720c
--- /dev/null
+++ b/build/shave-libtool.in
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+# we need sed
+SED=@SED@
+if test -z "$SED" ; then
+SED=sed
+fi
+
+lt_unmangle ()
+{
+ last_result=`echo $1 | $SED -e 's#.libs/##' -e 's#[0-9a-zA-Z_\-\.]*_la-##'`
+}
+
+# the real libtool to use
+LIBTOOL="$1"
+shift
+
+# if 1, don't print anything, the underlaying wrapper will do it
+pass_though=0
+
+# scan the arguments, keep the right ones for libtool, and discover the mode
+preserved_args=
+while test "$#" -gt 0; do
+ opt="$1"
+ shift
+
+ case $opt in
+ --mode=*)
+ mode=`echo $opt | $SED -e 's/[-_a-zA-Z0-9]*=//'`
+ preserved_args="$preserved_args $opt"
+ ;;
+ -o)
+ lt_output="$1"
+ preserved_args="$preserved_args $opt"
+ ;;
+ *)
+ preserved_args="$preserved_args $opt"
+ ;;
+ esac
+done
+
+case "$mode" in
+compile)
+ # shave will be called and print the actual CC/CXX/LINK line
+ preserved_args="$preserved_args --shave-mode=$mode"
+ pass_though=1
+ ;;
+link)
+ preserved_args="$preserved_args --shave-mode=$mode"
+ Q=" LINK "
+ ;;
+*)
+ # let's u
+ # echo "*** libtool: Unimplemented mode: $mode, fill a bug report"
+ ;;
+esac
+
+lt_unmangle "$lt_output"
+output=$last_result
+
+if test -z $V; then
+ if test $pass_though -eq 0; then
+ echo "$Q$output"
+ fi
+ $LIBTOOL --silent $preserved_args
+else
+ echo $LIBTOOL $preserved_args
+ $LIBTOOL $preserved_args
+fi
diff --git a/build/shave.in b/build/shave.in
new file mode 100644
index 00000000..cedccd47
--- /dev/null
+++ b/build/shave.in
@@ -0,0 +1,82 @@
+#!/bin/sh
+
+# we need sed
+SED=@SED@
+if test -z "$SED" ; then
+SED=sed
+fi
+
+lt_unmangle ()
+{
+ last_result=`echo $1 | $SED -e 's#.libs/##' -e 's#[0-9a-zA-Z_\-\.]*_la-##'`
+}
+
+# the tool to wrap (cc, cxx, ar, ranlib, ..)
+tool="$1"
+shift
+
+# the reel tool (to call)
+REEL_TOOL="$1"
+shift
+
+pass_through=0
+preserved_args=
+while test "$#" -gt 0; do
+ opt="$1"
+ shift
+
+ case $opt in
+ --shave-mode=*)
+ mode=`echo $opt | $SED -e 's/[-_a-zA-Z0-9]*=//'`
+ ;;
+ -o)
+ lt_output="$1"
+ preserved_args="$preserved_args $opt"
+ ;;
+ *)
+ preserved_args="$preserved_args $opt"
+ ;;
+ esac
+done
+
+# mode=link is handled in the libtool wrapper
+case "$mode,$tool" in
+link,*)
+ pass_through=1
+ ;;
+*,cxx)
+ Q=" CXX "
+ ;;
+*,cc)
+ Q=" CC "
+ ;;
+*,fc)
+ Q=" FC "
+ ;;
+*,f77)
+ Q=" F77 "
+ ;;
+*,objc)
+ Q=" OBJC "
+ ;;
+*,*)
+ # should not happen
+ Q=" CC "
+ ;;
+esac
+
+lt_unmangle "$lt_output"
+output=$last_result
+
+if test -z $V; then
+ if test $output = "/dev/null"; then
+ pass_through=1
+ fi
+ if test $pass_through -eq 0; then
+ echo "$Q$output"
+ fi
+ $REEL_TOOL $preserved_args
+else
+ echo $REEL_TOOL $preserved_args
+ $REEL_TOOL $preserved_args
+fi
diff --git a/configure.ac b/configure.ac
index 821545ff..606fc3ad 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,9 +19,9 @@ dnl The order of the includes here is rather important
dnl
m4_include(build/configure.ac.version) dnl macros setting up various version declares
m4_include(build/configure.ac.tools) dnl checks for tools we use
-m4_include(build/configure.ac.system) dnl checks for system functions, headers, libs
m4_include(build/configure.ac.features) dnl macros for backend/feature handling
m4_include(build/configure.ac.warnings) dnl checks for compiler warning
+m4_include(build/configure.ac.system) dnl checks for system functions, headers, libs
m4_include(build/configure.ac.analysis) dnl checks for analysis tools (lcov, etc)
m4_include(build/configure.ac.noversion) dnl disable builtin libtool versioning
AC_CACHE_SAVE
@@ -160,14 +160,6 @@ CAIRO_ENABLE_SURFACE_BACKEND(beos, BeOS/Zeta, no, [
dnl ===========================================================================
-CAIRO_ENABLE_SURFACE_BACKEND(sdl, SDL, no, [
- sdl_REQUIRES="sdl >= 1.2"
- PKG_CHECK_MODULES(sdl, $sdl_REQUIRES, , [AC_MSG_RESULT(no)
- use_sdl="no (requires $sdl_REQUIRES http://www.libsdl.org)"])
-])
-
-dnl ===========================================================================
-
CAIRO_ENABLE_FUNCTIONS(png, PNG, yes, [
use_png=no
AC_ARG_VAR([png_REQUIRES], [module name for libpng to search for using pkg-config])
@@ -309,13 +301,6 @@ FREETYPE_MIN_RELEASE=2.1.9
FREETYPE_MIN_VERSION=9.7.3
CAIRO_ENABLE_FONT_BACKEND(ft, FreeType, auto, [
- ft_REQUIRES="fontconfig"
- PKG_CHECK_MODULES(FONTCONFIG, $ft_REQUIRES,,
- [AC_MSG_RESULT(no); use_ft="no (requires $ft_REQUIRES)"])
-
- if test "x$use_ft" = "xyes"; then
-
- CAIRO_CHECK_FUNCS_WITH_FLAGS(FcFini, [$FONTCONFIG_CFLAGS], [$FONTCONFIG_LIBS])
PKG_CHECK_MODULES(FREETYPE, freetype2 >= $FREETYPE_MIN_VERSION,
[freetype_pkgconfig=yes],
@@ -343,9 +328,20 @@ CAIRO_ENABLE_FONT_BACKEND(ft, FreeType, auto, [
use_ft="no ($FREETYPE_VERSION found; version $FREETYPE_MIN_VERSION from release $FREETYPE_MIN_RELEASE required)"])
fi
fi
+
+ ft_CFLAGS="$FREETYPE_CFLAGS"
+ ft_LIBS="$FREETYPE_LIBS"
+])
+
+CAIRO_ENABLE_FONT_BACKEND(fc, Fontconfig, auto, [
+ use_fc=$use_ft
+ if test "x$use_fc" = "xyes"; then
+ fc_REQUIRES="fontconfig"
+ PKG_CHECK_MODULES(FONTCONFIG, $fc_REQUIRES,,
+ [AC_MSG_RESULT(no); use_fc="no (requires $fc_REQUIRES)"])
fi
- ft_CFLAGS="$FREETYPE_CFLAGS $FONTCONFIG_CFLAGS"
- ft_LIBS="$FREETYPE_LIBS $FONTCONFIG_LIBS"
+ fc_CFLAGS="$FONTCONFIG_CFLAGS"
+ fc_LIBS="$FONTCONFIG_LIBS"
])
if test "x$use_ft" = "xyes"; then
@@ -367,6 +363,10 @@ if test "x$use_ft" = "xyes"; then
CFLAGS="$_save_cflags"
fi
+if test "x$use_fc" = "xyes"; then
+ CAIRO_CHECK_FUNCS_WITH_FLAGS(FcFini, [$FONTCONFIG_CFLAGS], [$FONTCONFIG_LIBS])
+fi
+
dnl ===========================================================================
AC_ARG_ENABLE(pthread,
@@ -581,7 +581,11 @@ dnl ===========================================================================
# We use GTK+ for some utility/debugging tools
PKG_CHECK_MODULES(gtk, "gtk+-2.0",, AC_MSG_RESULT(no))
+SHAVE_INIT([build], [enable]) # dnl Make the output pretty
+
AC_CONFIG_FILES([
+build/shave
+build/shave-libtool
Makefile
boilerplate/Makefile
src/Makefile
diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt
index bb64cd68..ff89db71 100644
--- a/doc/public/cairo-sections.txt
+++ b/doc/public/cairo-sections.txt
@@ -2,6 +2,7 @@
<FILE>cairo-ft</FILE>
<TITLE>ft-font</TITLE>
CAIRO_HAS_FT_FONT
+CAIRO_HAS_FC_FONT
cairo_ft_font_face_create_for_ft_face
cairo_ft_font_face_create_for_pattern
cairo_ft_font_options_substitute
diff --git a/doc/public/tmpl/cairo-ft.sgml b/doc/public/tmpl/cairo-ft.sgml
index 68a3fd43..307d632f 100644
--- a/doc/public/tmpl/cairo-ft.sgml
+++ b/doc/public/tmpl/cairo-ft.sgml
@@ -28,6 +28,15 @@ This macro can be used to conditionally compile backend-specific code.
+<!-- ##### MACRO CAIRO_HAS_FC_FONT ##### -->
+<para>
+Defined if the Fontconfig-specific functions of the FreeType font backend
+are available.
+This macro can be used to conditionally compile backend-specific code.
+</para>
+
+
+
<!-- ##### FUNCTION cairo_ft_font_face_create_for_ft_face ##### -->
<para>
diff --git a/doc/public/tmpl/cairo-status.sgml b/doc/public/tmpl/cairo-status.sgml
index fcc17a9c..aed8aa64 100644
--- a/doc/public/tmpl/cairo-status.sgml
+++ b/doc/public/tmpl/cairo-status.sgml
@@ -70,6 +70,9 @@ code is required before or after each individual cairo function call.
@CAIRO_STATUS_INVALID_CLUSTERS:
@CAIRO_STATUS_INVALID_SLANT:
@CAIRO_STATUS_INVALID_WEIGHT:
+@CAIRO_STATUS_INVALID_SIZE:
+@CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
+@CAIRO_STATUS_LAST_STATUS:
<!-- ##### FUNCTION cairo_status_to_string ##### -->
<para>
diff --git a/doc/public/tmpl/cairo-surface.sgml b/doc/public/tmpl/cairo-surface.sgml
index f32dd49e..f7df8296 100644
--- a/doc/public/tmpl/cairo-surface.sgml
+++ b/doc/public/tmpl/cairo-surface.sgml
@@ -214,7 +214,6 @@ The Portable Network Graphics image file format (ISO/IEC 15948). Since 1.10
@CAIRO_SURFACE_TYPE_OS2:
@CAIRO_SURFACE_TYPE_WIN32_PRINTING:
@CAIRO_SURFACE_TYPE_QUARTZ_IMAGE:
-@CAIRO_SURFACE_TYPE_SDL:
@CAIRO_SURFACE_TYPE_SCRIPT:
<!-- ##### FUNCTION cairo_surface_get_type ##### -->
diff --git a/perf/Makefile.am b/perf/Makefile.am
index 59271999..08f9cc00 100644
--- a/perf/Makefile.am
+++ b/perf/Makefile.am
@@ -7,6 +7,8 @@ AM_CPPFLAGS = \
-I$(top_builddir)/src \
$(CAIRO_CFLAGS)
+AM_LDFLAGS = $(CAIRO_LDFLAGS)
+
EXTRA_PROGRAMS += cairo-perf \
cairo-perf-diff-files \
cairo-perf-compare-backends \
@@ -61,10 +63,6 @@ endif
endif
cairo_perf_LDADD = $(LDADD)
-if CAIRO_HAS_SDL_SURFACE
-cairo_perf_LDADD += $(sdl_LIBS)
-endif
-
libcairoperf_la_SOURCES = \
cairo-perf-report.c \
cairo-stats.c \
diff --git a/perf/box-outline.c b/perf/box-outline.c
index 74dd19ad..2d826e68 100644
--- a/perf/box-outline.c
+++ b/perf/box-outline.c
@@ -88,6 +88,9 @@ box_outline_fill (cairo_t *cr, int width, int height)
void
box_outline (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "box-outline"))
+ return;
+
cairo_perf_run (perf, "box-outline-stroke", box_outline_stroke);
cairo_perf_run (perf, "box-outline-fill", box_outline_fill);
}
diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index 6d93eb42..a0abee61 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -33,10 +33,6 @@
#include "cairo-boilerplate-getopt.h"
-#if CAIRO_HAS_SDL_SURFACE
-#include <SDL_main.h>
-#endif
-
/* For basename */
#ifdef HAVE_LIBGEN_H
#include <libgen.h>
@@ -135,6 +131,9 @@ cairo_perf_has_similar (cairo_perf_t *perf)
{
cairo_surface_t *target = cairo_get_target (perf->cr);
+ if (getenv ("CAIRO_TEST_IGNORE_SIMILAR"))
+ return FALSE;
+
/* exclude the image backend */
if (cairo_surface_get_type (target) == CAIRO_SURFACE_TYPE_IMAGE)
return FALSE;
@@ -142,6 +141,22 @@ cairo_perf_has_similar (cairo_perf_t *perf)
return TRUE;
}
+cairo_bool_t
+cairo_perf_can_run (cairo_perf_t *perf,
+ const char *name)
+{
+ unsigned int i;
+
+ if (perf->num_names == 0)
+ return TRUE;
+
+ for (i = 0; i < perf->num_names; i++)
+ if (strstr (name, perf->names[i]))
+ return TRUE;
+
+ return FALSE;
+}
+
void
cairo_perf_run (cairo_perf_t *perf,
const char *name,
@@ -153,14 +168,6 @@ cairo_perf_run (cairo_perf_t *perf,
cairo_stats_t stats = {0.0, 0.0};
int low_std_dev_count;
- if (perf->num_names) {
- for (i = 0; i < perf->num_names; i++)
- if (strstr (name, perf->names[i]))
- goto NAME_FOUND;
- return;
- }
- NAME_FOUND:
-
if (perf->list_only) {
printf ("%s\n", name);
return;
@@ -445,11 +452,11 @@ main (int argc, char *argv[])
}
const cairo_perf_case_t perf_cases[] = {
- { paint, 256, 512},
- { paint_with_alpha, 256, 512},
- { fill, 64, 256},
- { stroke, 64, 256},
- { text, 64, 256},
+ { paint, 64, 512},
+ { paint_with_alpha, 64, 512},
+ { fill, 64, 512},
+ { stroke, 64, 512},
+ { text, 64, 512},
{ tessellate, 100, 100},
{ subimage_copy, 16, 512},
{ pattern_create_radial, 16, 16},
diff --git a/perf/cairo-perf.h b/perf/cairo-perf.h
index 8c44c9ae..7e792ad8 100644
--- a/perf/cairo-perf.h
+++ b/perf/cairo-perf.h
@@ -89,6 +89,10 @@ typedef struct _cairo_perf {
typedef cairo_perf_ticks_t
(*cairo_perf_func_t) (cairo_t *cr, int width, int height);
+cairo_bool_t
+cairo_perf_can_run (cairo_perf_t *perf,
+ const char *name);
+
void
cairo_perf_run (cairo_perf_t *perf,
const char *name,
diff --git a/perf/composite-checker.c b/perf/composite-checker.c
index 69f48a08..e978990a 100644
--- a/perf/composite-checker.c
+++ b/perf/composite-checker.c
@@ -81,6 +81,9 @@ composite_checker (cairo_perf_t *perf,
{
cairo_surface_t *image;
+ if (! cairo_perf_can_run (perf, "composite-checker"))
+ return;
+
/* Create the checker pattern. We don't actually need to draw
* anything on it since that wouldn't affect performance.
*/
diff --git a/perf/dragon.c b/perf/dragon.c
index a6167cb3..1866c9ac 100644
--- a/perf/dragon.c
+++ b/perf/dragon.c
@@ -201,6 +201,9 @@ do_dragon_solid (cairo_t *cr, int width, int height)
void
dragon (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "dragon"))
+ return;
+
cairo_perf_run (perf, "dragon-solid", do_dragon_solid);
cairo_perf_run (perf, "dragon", do_dragon);
}
diff --git a/perf/fill.c b/perf/fill.c
index 2a413558..f068561a 100644
--- a/perf/fill.c
+++ b/perf/fill.c
@@ -42,8 +42,32 @@ do_fill (cairo_t *cr, int width, int height)
return cairo_perf_timer_elapsed ();
}
+static cairo_perf_ticks_t
+do_fill_eo_noaa (cairo_t *cr, int width, int height)
+{
+ cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
+ cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+
+ cairo_arc (cr,
+ width/2.0, height/2.0,
+ width/3.0,
+ 0, 2 * M_PI);
+
+ cairo_perf_timer_start ();
+
+ cairo_fill (cr);
+
+ cairo_perf_timer_stop ();
+
+ return cairo_perf_timer_elapsed ();
+}
+
void
fill (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "fill"))
+ return;
+
cairo_perf_cover_sources_and_operators (perf, "fill", do_fill);
+ cairo_perf_cover_sources_and_operators (perf, "fill-eo-noaa", do_fill_eo_noaa);
}
diff --git a/perf/intersections.c b/perf/intersections.c
index 5e410366..347c4a53 100644
--- a/perf/intersections.c
+++ b/perf/intersections.c
@@ -92,6 +92,9 @@ random_nz (cairo_t *cr, int width, int height)
void
intersections (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "intersections"))
+ return;
+
cairo_perf_run (perf, "intersections-nz-fill", random_nz);
cairo_perf_run (perf, "intersections-eo-fill", random_eo);
}
diff --git a/perf/long-dashed-lines.c b/perf/long-dashed-lines.c
index 31ddfe66..3520a197 100644
--- a/perf/long-dashed-lines.c
+++ b/perf/long-dashed-lines.c
@@ -63,5 +63,8 @@ do_long_dashed_lines (cairo_t *cr, int width, int height)
void
long_dashed_lines (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "long-dashed-lines"))
+ return;
+
cairo_perf_run (perf, "long-dashed-lines", do_long_dashed_lines);
}
diff --git a/perf/long-lines.c b/perf/long-lines.c
index 62e8e16f..03592018 100644
--- a/perf/long-lines.c
+++ b/perf/long-lines.c
@@ -112,6 +112,9 @@ long_lines_cropped (cairo_t *cr, int width, int height)
void
long_lines (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "long-lines"))
+ return;
+
cairo_perf_run (perf, "long-lines-uncropped", long_lines_uncropped);
cairo_perf_run (perf, "long-lines-cropped", long_lines_cropped);
}
diff --git a/perf/mosaic.c b/perf/mosaic.c
index 7172a9d3..257a3626 100644
--- a/perf/mosaic.c
+++ b/perf/mosaic.c
@@ -161,6 +161,9 @@ mosaic_tessellate_curves (cairo_t *cr, int width, int height)
void
mosaic (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "mosaic"))
+ return;
+
cairo_perf_run (perf, "mosaic_fill_curves", mosaic_fill_curves);
cairo_perf_run (perf, "mosaic_fill_lines", mosaic_fill_lines);
cairo_perf_run (perf, "mosaic_tessellate_curves", mosaic_tessellate_curves);
diff --git a/perf/paint-with-alpha.c b/perf/paint-with-alpha.c
index d4d860ef..6ffe8bb1 100644
--- a/perf/paint-with-alpha.c
+++ b/perf/paint-with-alpha.c
@@ -40,6 +40,9 @@ do_paint_with_alpha (cairo_t *cr, int width, int height)
void
paint_with_alpha (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "paint-with-alpha"))
+ return;
+
cairo_perf_cover_sources_and_operators (perf, "paint-with-alpha",
do_paint_with_alpha);
}
diff --git a/perf/paint.c b/perf/paint.c
index 6f75016c..a60d132b 100644
--- a/perf/paint.c
+++ b/perf/paint.c
@@ -40,5 +40,8 @@ do_paint (cairo_t *cr, int width, int height)
void
paint (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "paint"))
+ return;
+
cairo_perf_cover_sources_and_operators (perf, "paint", do_paint);
}
diff --git a/perf/pattern_create_radial.c b/perf/pattern_create_radial.c
index 09f15a82..8fa683b8 100644
--- a/perf/pattern_create_radial.c
+++ b/perf/pattern_create_radial.c
@@ -82,6 +82,9 @@ pattern_create_radial (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
int i;
+ if (! cairo_perf_can_run (perf, "pattern_create_radial"))
+ return;
+
srand (time (0));
for (i = 0; i < RADIALS_COUNT; i++)
{
diff --git a/perf/pythagoras-tree.c b/perf/pythagoras-tree.c
index 5a78d8a7..750e83b2 100644
--- a/perf/pythagoras-tree.c
+++ b/perf/pythagoras-tree.c
@@ -82,5 +82,8 @@ do_pythagoras_tree (cairo_t *cr, int width, int height)
void
pythagoras_tree (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "pythagoras_tree"))
+ return;
+
cairo_perf_run (perf, "pythagoras_tree", do_pythagoras_tree);
}
diff --git a/perf/rectangles.c b/perf/rectangles.c
index 374e3644..c224968f 100644
--- a/perf/rectangles.c
+++ b/perf/rectangles.c
@@ -96,6 +96,9 @@ rectangles (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
int i;
+ if (! cairo_perf_can_run (perf, "rectangles"))
+ return;
+
srand (8478232);
for (i = 0; i < RECTANGLE_COUNT; i++)
{
diff --git a/perf/rounded-rectangles.c b/perf/rounded-rectangles.c
index 7d20825d..25133f38 100644
--- a/perf/rounded-rectangles.c
+++ b/perf/rounded-rectangles.c
@@ -98,6 +98,9 @@ rounded_rectangles (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
int i;
+ if (! cairo_perf_can_run (perf, "rounded-rectangles"))
+ return;
+
srand (8478232);
for (i = 0; i < RECTANGLE_COUNT; i++) {
rects[i].x = rand () % width;
diff --git a/perf/spiral.c b/perf/spiral.c
index f26d0a2b..fb2af61d 100644
--- a/perf/spiral.c
+++ b/perf/spiral.c
@@ -189,6 +189,9 @@ draw_spiral_nz_na_di (cairo_t *cr, int width, int height)
void
spiral (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "spiral"))
+ return;
+
cairo_perf_run (perf, "spiral-diag-nonalign-evenodd-fill", draw_spiral_eo_na_di);
cairo_perf_run (perf, "spiral-diag-nonalign-nonzero-fill", draw_spiral_nz_na_di);
cairo_perf_run (perf, "spiral-diag-pixalign-evenodd-fill", draw_spiral_eo_pa_di);
diff --git a/perf/stroke.c b/perf/stroke.c
index 0b4ea8e6..7b3990d5 100644
--- a/perf/stroke.c
+++ b/perf/stroke.c
@@ -47,5 +47,8 @@ do_stroke (cairo_t *cr, int width, int height)
void
stroke (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "stroke"))
+ return;
+
cairo_perf_cover_sources_and_operators (perf, "stroke", do_stroke);
}
diff --git a/perf/subimage_copy.c b/perf/subimage_copy.c
index 54f596f4..722705b4 100644
--- a/perf/subimage_copy.c
+++ b/perf/subimage_copy.c
@@ -55,6 +55,9 @@ subimage_copy (cairo_perf_t *perf, cairo_t *cr, int width, int height)
cairo_surface_t *image;
cairo_t *cr2;
+ if (! cairo_perf_can_run (perf, "subimage_copy"))
+ return;
+
cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
cairo_paint (cr);
diff --git a/perf/tessellate.c b/perf/tessellate.c
index fc97db70..4af38411 100644
--- a/perf/tessellate.c
+++ b/perf/tessellate.c
@@ -143,6 +143,9 @@ tessellate_256 (cairo_t *cr, int width, int height)
void
tessellate (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "tessellate"))
+ return;
+
cairo_perf_run (perf, "tessellate-16", tessellate_16);
cairo_perf_run (perf, "tessellate-64", tessellate_64);
cairo_perf_run (perf, "tessellate-256", tessellate_256);
diff --git a/perf/text.c b/perf/text.c
index efe7d913..4448802a 100644
--- a/perf/text.c
+++ b/perf/text.c
@@ -31,21 +31,20 @@ do_text (cairo_t *cr, int width, int height)
const char text[] = "the jay, pig, fox, zebra and my wolves quack";
int len = strlen (text);
double x, y;
- int i = 0;
+ int i = 0, j = 0;
cairo_perf_timer_start ();
cairo_set_font_size (cr, 9);
do {
- cairo_move_to (cr, 0, i * 10);
+ cairo_move_to (cr, 0, j++ * 10);
cairo_show_text (cr, text + i);
cairo_get_current_point (cr, &x, &y);
while (x < width && cairo_status (cr) == CAIRO_STATUS_SUCCESS) {
cairo_show_text (cr, text);
cairo_get_current_point (cr, &x, &y);
}
- i++;
- if (i >= len)
+ if (++i >= len)
i = 0;
} while (y < height && cairo_status (cr) == CAIRO_STATUS_SUCCESS);
@@ -57,5 +56,8 @@ do_text (cairo_t *cr, int width, int height)
void
text (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "text"))
+ return;
+
cairo_perf_cover_sources_and_operators (perf, "text", do_text);
}
diff --git a/perf/twin.c b/perf/twin.c
index 84ac7598..f65cccf8 100644
--- a/perf/twin.c
+++ b/perf/twin.c
@@ -46,5 +46,8 @@ twin (cairo_perf_t *perf,
int width,
int height)
{
+ if (! cairo_perf_can_run (perf, "twin"))
+ return;
+
cairo_perf_run (perf, "twin", do_twin);
}
diff --git a/perf/unaligned-clip.c b/perf/unaligned-clip.c
index 6d2b1797..a757fa67 100644
--- a/perf/unaligned-clip.c
+++ b/perf/unaligned-clip.c
@@ -59,5 +59,8 @@ do_unaligned_clip (cairo_t *cr, int width, int height)
void
unaligned_clip (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "unaligned-clip"))
+ return;
+
cairo_perf_run (perf, "unaligned_clip", do_unaligned_clip);
}
diff --git a/perf/world-map.c b/perf/world-map.c
index fe6d42d5..5b8be453 100644
--- a/perf/world-map.c
+++ b/perf/world-map.c
@@ -105,5 +105,8 @@ do_world_map (cairo_t *cr, int width, int height)
void
world_map (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "world_map"))
+ return;
+
cairo_perf_run (perf, "world_map", do_world_map);
}
diff --git a/perf/zrusin.c b/perf/zrusin.c
index 68407751..21956159 100644
--- a/perf/zrusin.c
+++ b/perf/zrusin.c
@@ -85,6 +85,9 @@ zrusin_another_fill (cairo_t *cr, int width, int height)
void
zrusin (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
+ if (! cairo_perf_can_run (perf, "zrusin"))
+ return;
+
cairo_perf_run (perf, "zrusin_another_tessellate", zrusin_another_tessellate);
cairo_perf_run (perf, "zrusin_another_fill", zrusin_another_fill);
}
diff --git a/src/Makefile.am b/src/Makefile.am
index eb82a149..b017c17a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,9 +14,6 @@ export_symbols = -export-symbols cairo.def
cairo_def_dependency = cairo.def
endif
-EXTRA_DIST += cairo-supported-features.h
-MAINTAINERCLEANFILES += cairo-supported-features.h
-
$(top_builddir)/config.h: $(top_srcdir)/config.h.in
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) config.h
@@ -36,9 +33,11 @@ libcairo_la_DEPENDENCIES = $(cairo_def_dependency)
# Special headers
cairoinclude_HEADERS += $(top_srcdir)/cairo-version.h
+libcairo_la_SOURCES += cairo-version.h
nodist_cairoinclude_HEADERS = cairo-features.h
-libcairo_la_SOURCES += cairo-version.h cairo-features.h
+nodist_libcairo_la_SOURCES = cairo-features.h
BUILT_SOURCES += cairo-features.h cairo-supported-features.h
+DISTCLEANFILES += cairo-features.h cairo-supported-features.h
cairo-features.h cairo-supported-features.h:
cd $(top_builddir) && ./config.status src/$@
diff --git a/src/Makefile.am.analysis b/src/Makefile.am.analysis
index 4d527bf1..ea9caec4 100644
--- a/src/Makefile.am.analysis
+++ b/src/Makefile.am.analysis
@@ -23,7 +23,7 @@ uno:
headers-standalone: $(enabled_cairo_headers) $(enabled_cairo_private)
@echo Checking that enabled public/private headers can be compiled standalone
@status=true; for f in $(enabled_cairo_headers) $(enabled_cairo_private); do \
- echo $(COMPILE) -o /dev/null $(srcdir)/$$f; \
+ echo " CHECK $$f"; \
$(COMPILE) -o /dev/null $(srcdir)/$$f || status=false; \
done; $$status
@touch $@
diff --git a/src/Makefile.sources b/src/Makefile.sources
index a9260640..d5289786 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -78,7 +78,6 @@ cairo_private = \
cairo-path-private.h \
cairo-private.h \
cairo-reference-count-private.h \
- cairo-region-private.h \
cairo-scaled-font-private.h \
cairo-skiplist-private.h \
cairo-spans-private.h \
@@ -191,11 +190,13 @@ cairo_ft_sources = cairo-ft-font.c
# These are private, even though they look like public headers
cairo_test_surfaces_private = \
test-fallback-surface.h \
+ test-fallback16-surface.h \
test-meta-surface.h \
test-paginated-surface.h \
$(NULL)
cairo_test_surfaces_sources = \
test-fallback-surface.c \
+ test-fallback16-surface.c \
test-meta-surface.c \
test-paginated-surface.c \
$(NULL)
@@ -257,8 +258,5 @@ cairo_glitz_sources = cairo-glitz-surface.c
cairo_directfb_headers = cairo-directfb.h
cairo_directfb_sources = cairo-directfb-surface.c
-cairo_sdl_headers = cairo-sdl.h
-cairo_sdl_sources = cairo-sdl-surface.c
-
cairo_script_headers = cairo-script.h
cairo_script_sources = cairo-script-surface.c
diff --git a/src/Makefile.win32 b/src/Makefile.win32
index ee589296..6fdc3956 100644
--- a/src/Makefile.win32
+++ b/src/Makefile.win32
@@ -13,7 +13,7 @@ static: inform $(CFG)/cairo-static.lib
dynamic: inform $(CFG)/cairo.dll
$(CFG)/cairo.dll: $(OBJECTS)
- $(CC) $(MS_MDFLAGS) $(MS_LDFLAGS) -Fe$@ $(PIXMAN_LIBS) $(OBJECTS) -link $(CAIRO_LIBS)
+ $(CC) $(OPT) $(MS_MDFLAGS) $(MS_LDFLAGS) -Fe$@ $(PIXMAN_LIBS) $(OBJECTS) -link $(CAIRO_LIBS)
$(CFG)/cairo-static.lib: $(OBJECTS_STATIC)
lib -NOLOGO -OUT:$@ $(PIXMAN_LIBS) $(OBJECTS_STATIC)
diff --git a/src/Makefile.win32.features b/src/Makefile.win32.features
index f90c36b8..3967de40 100644
--- a/src/Makefile.win32.features
+++ b/src/Makefile.win32.features
@@ -161,20 +161,6 @@ ifeq ($(CAIRO_HAS_BEOS_SURFACE),1)
enabled_cairo_pkgconf += cairo-beos.pc
endif
-unsupported_cairo_headers += $(cairo_sdl_headers)
-all_cairo_headers += $(cairo_sdl_headers)
-all_cairo_private += $(cairo_sdl_private)
-all_cairo_sources += $(cairo_sdl_sources)
-ifeq ($(CAIRO_HAS_SDL_SURFACE),1)
-enabled_cairo_headers += $(cairo_sdl_headers)
-enabled_cairo_private += $(cairo_sdl_private)
-enabled_cairo_sources += $(cairo_sdl_sources)
-endif
-all_cairo_pkgconf += cairo-sdl.pc
-ifeq ($(CAIRO_HAS_SDL_SURFACE),1)
-enabled_cairo_pkgconf += cairo-sdl.pc
-endif
-
supported_cairo_headers += $(cairo_png_headers)
all_cairo_headers += $(cairo_png_headers)
all_cairo_private += $(cairo_png_private)
@@ -287,6 +273,20 @@ ifeq ($(CAIRO_HAS_FT_FONT),1)
enabled_cairo_pkgconf += cairo-ft.pc
endif
+supported_cairo_headers += $(cairo_fc_headers)
+all_cairo_headers += $(cairo_fc_headers)
+all_cairo_private += $(cairo_fc_private)
+all_cairo_sources += $(cairo_fc_sources)
+ifeq ($(CAIRO_HAS_FC_FONT),1)
+enabled_cairo_headers += $(cairo_fc_headers)
+enabled_cairo_private += $(cairo_fc_private)
+enabled_cairo_sources += $(cairo_fc_sources)
+endif
+all_cairo_pkgconf += cairo-fc.pc
+ifeq ($(CAIRO_HAS_FC_FONT),1)
+enabled_cairo_pkgconf += cairo-fc.pc
+endif
+
supported_cairo_headers += $(cairo_ps_headers)
all_cairo_headers += $(cairo_ps_headers)
all_cairo_private += $(cairo_ps_private)
diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 1be592e9..c767d07c 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -38,7 +38,6 @@
#include "cairo-analysis-surface-private.h"
#include "cairo-paginated-private.h"
-#include "cairo-region-private.h"
#include "cairo-meta-surface-private.h"
typedef struct {
@@ -215,7 +214,7 @@ _add_operation (cairo_analysis_surface_t *surface,
* region there is no benefit in emitting a native operation as
* the fallback image will be painted on top.
*/
- if (_cairo_region_contains_rectangle (&surface->fallback_region, rect) == PIXMAN_REGION_IN)
+ if (cairo_region_contains_rectangle (&surface->fallback_region, rect) == CAIRO_REGION_OVERLAP_IN)
return CAIRO_INT_STATUS_IMAGE_FALLBACK;
if (backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY) {
@@ -226,7 +225,7 @@ _add_operation (cairo_analysis_surface_t *surface,
* natively supported and the backend will blend the
* transparency into the white background.
*/
- if (_cairo_region_contains_rectangle (&surface->supported_region, rect) == PIXMAN_REGION_OUT)
+ if (cairo_region_contains_rectangle (&surface->supported_region, rect) == CAIRO_REGION_OVERLAP_OUT)
backend_status = CAIRO_STATUS_SUCCESS;
}
@@ -235,9 +234,7 @@ _add_operation (cairo_analysis_surface_t *surface,
* this region will be emitted as native operations.
*/
surface->has_supported = TRUE;
- status = _cairo_region_union_rect (&surface->supported_region,
- &surface->supported_region,
- rect);
+ status = cairo_region_union_rectangle (&surface->supported_region, rect);
return status;
}
@@ -246,9 +243,7 @@ _add_operation (cairo_analysis_surface_t *surface,
* emitted.
*/
surface->has_unsupported = TRUE;
- status = _cairo_region_union_rect (&surface->fallback_region,
- &surface->fallback_region,
- rect);
+ status = cairo_region_union_rectangle (&surface->fallback_region, rect);
/* The status CAIRO_INT_STATUS_IMAGE_FALLBACK is used to indicate
* unsupported operations to the meta surface as using
@@ -778,14 +773,14 @@ _cairo_analysis_surface_create (cairo_surface_t *target,
surface->has_supported = FALSE;
surface->has_unsupported = FALSE;
+ _cairo_region_init (&surface->supported_region);
+ _cairo_region_init (&surface->fallback_region);
+
surface->page_bbox.p1.x = 0;
surface->page_bbox.p1.y = 0;
surface->page_bbox.p2.x = 0;
surface->page_bbox.p2.y = 0;
- _cairo_region_init (&surface->supported_region);
- _cairo_region_init (&surface->fallback_region);
-
if (width == -1 && height == -1) {
surface->current_clip.x = CAIRO_RECT_INT_MIN;
surface->current_clip.y = CAIRO_RECT_INT_MIN;
diff --git a/src/cairo-array.c b/src/cairo-array.c
index 9c084b9e..77e575ff 100644
--- a/src/cairo-array.c
+++ b/src/cairo-array.c
@@ -125,6 +125,9 @@ _cairo_array_grow_by (cairo_array_t *array, unsigned int additional)
if (required_size > INT_MAX || required_size < array->num_elements)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (CAIRO_INJECT_FAULT ())
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
if (required_size <= old_size)
return CAIRO_STATUS_SUCCESS;
@@ -494,3 +497,39 @@ _cairo_user_data_array_set_data (cairo_user_data_array_t *array,
return CAIRO_STATUS_SUCCESS;
}
+
+cairo_status_t
+_cairo_user_data_array_copy (cairo_user_data_array_t *dst,
+ cairo_user_data_array_t *src)
+{
+ /* discard any existing user-data */
+ if (dst->num_elements != 0) {
+ _cairo_user_data_array_fini (dst);
+ _cairo_user_data_array_init (dst);
+ }
+
+ if (src->num_elements == 0)
+ return CAIRO_STATUS_SUCCESS;
+
+ return _cairo_array_append_multiple (dst,
+ _cairo_array_index (src, 0),
+ src->num_elements);
+}
+
+void
+_cairo_user_data_array_foreach (cairo_user_data_array_t *array,
+ void (*func) (const void *key,
+ void *elt,
+ void *closure),
+ void *closure)
+{
+ cairo_user_data_slot_t *slots;
+ int i, num_slots;
+
+ num_slots = array->num_elements;
+ slots = _cairo_array_index (array, 0);
+ for (i = 0; i < num_slots; i++) {
+ if (slots[i].user_data != NULL)
+ func (slots[i].key, slots[i].user_data, closure);
+ }
+}
diff --git a/src/cairo-bentley-ottmann.c b/src/cairo-bentley-ottmann.c
index 81eed1d6..1d59d703 100644
--- a/src/cairo-bentley-ottmann.c
+++ b/src/cairo-bentley-ottmann.c
@@ -1660,6 +1660,9 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
if (0 == polygon->num_edges)
return CAIRO_STATUS_SUCCESS;
+ if (CAIRO_INJECT_FAULT ())
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
has_limits = _cairo_traps_get_limit (traps, &limit);
edges = stack_edges;
diff --git a/src/cairo-cache-private.h b/src/cairo-cache-private.h
index 8ad0c774..25858e54 100644
--- a/src/cairo-cache-private.h
+++ b/src/cairo-cache-private.h
@@ -97,6 +97,7 @@ typedef void
cairo_private cairo_cache_t *
_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
+ cairo_cache_predicate_func_t predicate,
cairo_destroy_func_t entry_destroy,
unsigned long max_size);
@@ -113,10 +114,6 @@ cairo_private void *
_cairo_cache_lookup (cairo_cache_t *cache,
cairo_cache_entry_t *key);
-cairo_private void *
-_cairo_cache_steal (cairo_cache_t *cache,
- cairo_cache_entry_t *key);
-
cairo_private cairo_status_t
_cairo_cache_insert (cairo_cache_t *cache,
cairo_cache_entry_t *entry);
diff --git a/src/cairo-cache.c b/src/cairo-cache.c
index cab6e1e9..7542242d 100644
--- a/src/cairo-cache.c
+++ b/src/cairo-cache.c
@@ -42,9 +42,16 @@ static void
_cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
unsigned long additional);
+static cairo_bool_t
+_cairo_cache_entry_is_non_zero (const void *entry)
+{
+ return ((const cairo_cache_entry_t *) entry)->size;
+}
+
static cairo_status_t
_cairo_cache_init (cairo_cache_t *cache,
cairo_cache_keys_equal_func_t keys_equal,
+ cairo_cache_predicate_func_t predicate,
cairo_destroy_func_t entry_destroy,
unsigned long max_size)
{
@@ -52,6 +59,9 @@ _cairo_cache_init (cairo_cache_t *cache,
if (unlikely (cache->hash_table == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (predicate == NULL)
+ predicate = _cairo_cache_entry_is_non_zero;
+ cache->predicate = predicate;
cache->entry_destroy = entry_destroy;
cache->max_size = max_size;
@@ -114,6 +124,7 @@ _cairo_cache_fini (cairo_cache_t *cache)
**/
cairo_cache_t *
_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
+ cairo_cache_predicate_func_t predicate,
cairo_destroy_func_t entry_destroy,
unsigned long max_size)
{
@@ -126,7 +137,11 @@ _cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
return NULL;
}
- status = _cairo_cache_init (cache, keys_equal, entry_destroy, max_size);
+ status = _cairo_cache_init (cache,
+ keys_equal,
+ predicate,
+ entry_destroy,
+ max_size);
if (unlikely (status)) {
free (cache);
return NULL;
@@ -221,26 +236,6 @@ _cairo_cache_lookup (cairo_cache_t *cache,
(cairo_hash_entry_t *) key);
}
-void *
-_cairo_cache_steal (cairo_cache_t *cache,
- cairo_cache_entry_t *key)
-{
- cairo_cache_entry_t *entry;
-
- entry = _cairo_hash_table_steal (cache->hash_table,
- (cairo_hash_entry_t *) key);
- if (entry != NULL)
- cache->size -= entry->size;
-
- return entry;
-}
-
-static cairo_bool_t
-_cairo_cache_entry_is_non_zero (void *entry)
-{
- return ((cairo_cache_entry_t *)entry)->size;
-}
-
/**
* _cairo_cache_remove_random:
* @cache: a cache
@@ -256,7 +251,7 @@ _cairo_cache_remove_random (cairo_cache_t *cache)
cairo_cache_entry_t *entry;
entry = _cairo_hash_table_random_entry (cache->hash_table,
- _cairo_cache_entry_is_non_zero);
+ cache->predicate);
if (unlikely (entry == NULL))
return FALSE;
diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h
index 36c0fbdc..4229e4fb 100644
--- a/src/cairo-clip-private.h
+++ b/src/cairo-clip-private.h
@@ -40,7 +40,6 @@
#include "cairo-compiler-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-reference-count-private.h"
-#include "cairo-region-private.h"
extern const cairo_private cairo_rectangle_list_t _cairo_rectangles_nil;
@@ -78,8 +77,7 @@ struct _cairo_clip {
/*
* A clip region that can be placed in the surface
*/
- cairo_region_t region;
- cairo_bool_t has_region;
+ cairo_region_t *region;
/*
* If the surface supports path clipping, we store the list of
* clipping paths that has been set here as a linked list.
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index a64d524f..bb04a9e2 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -64,8 +64,7 @@ _cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
clip->serial = 0;
- _cairo_region_init (&clip->region);
- clip->has_region = FALSE;
+ clip->region = NULL;
clip->path = NULL;
}
@@ -76,28 +75,29 @@ _cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
clip->mode = other->mode;
clip->all_clipped = other->all_clipped;
-
+
clip->surface = cairo_surface_reference (other->surface);
clip->surface_rect = other->surface_rect;
clip->serial = other->serial;
- _cairo_region_init (&clip->region);
-
- if (other->has_region) {
+ if (other->region) {
cairo_status_t status;
+
+ clip->region = cairo_region_copy (other->region);
- status = _cairo_region_copy (&clip->region, &other->region);
+ status = cairo_region_status (clip->region);
if (unlikely (status)) {
- _cairo_region_fini (&clip->region);
cairo_surface_destroy (clip->surface);
+ cairo_region_destroy (clip->region);
+ clip->region = NULL;
+
return status;
}
- clip->has_region = TRUE;
} else {
- clip->has_region = FALSE;
+ clip->region = NULL;
}
-
+
clip->path = _cairo_clip_path_reference (other->path);
return CAIRO_STATUS_SUCCESS;
@@ -114,14 +114,10 @@ _cairo_clip_reset (cairo_clip_t *clip)
clip->serial = 0;
- if (clip->has_region) {
- /* _cairo_region_fini just releases the resources used but
- * doesn't bother with leaving the region in a valid state.
- * So _cairo_region_init has to be called afterwards. */
- _cairo_region_fini (&clip->region);
- _cairo_region_init (&clip->region);
+ if (clip->region) {
+ cairo_region_destroy (clip->region);
- clip->has_region = FALSE;
+ clip->region = NULL;
}
_cairo_clip_path_destroy (clip->path);
@@ -178,10 +174,10 @@ _cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
return status;
}
- if (clip->has_region) {
+ if (clip->region) {
cairo_rectangle_int_t extents;
- _cairo_region_get_extents (&clip->region, &extents);
+ cairo_region_get_extents (clip->region, &extents);
is_empty = _cairo_rectangle_intersect (rectangle, &extents);
if (is_empty)
return CAIRO_STATUS_SUCCESS;
@@ -194,7 +190,7 @@ _cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
}
cairo_status_t
-_cairo_clip_intersect_to_region (cairo_clip_t *clip,
+_cairo_clip_intersect_to_region (cairo_clip_t *clip,
cairo_region_t *region)
{
cairo_status_t status;
@@ -202,40 +198,21 @@ _cairo_clip_intersect_to_region (cairo_clip_t *clip,
if (!clip)
return CAIRO_STATUS_SUCCESS;
- if (clip->all_clipped) {
- cairo_region_t clip_rect;
-
- _cairo_region_init_rect (&clip_rect, &clip->surface_rect);
-
- status = _cairo_region_intersect (region, &clip_rect, region);
-
- _cairo_region_fini (&clip_rect);
-
- return status;
- }
+ if (clip->all_clipped)
+ return cairo_region_intersect_rectangle (region, &clip->surface_rect);
if (clip->path) {
/* Intersect clip path into region. */
}
- if (clip->has_region) {
- status = _cairo_region_intersect (region, &clip->region, region);
+ if (clip->region) {
+ status = cairo_region_intersect (region, clip->region);
if (unlikely (status))
return status;
}
- if (clip->surface) {
- cairo_region_t clip_rect;
-
- _cairo_region_init_rect (&clip_rect, &clip->surface_rect);
-
- status = _cairo_region_intersect (region, &clip_rect, region);
-
- _cairo_region_fini (&clip_rect);
-
- if (unlikely (status))
- return status;
- }
+ if (clip->surface)
+ return cairo_region_intersect_rectangle (region, &clip->surface_rect);
return CAIRO_STATUS_SUCCESS;
}
@@ -344,7 +321,7 @@ _cairo_clip_intersect_region (cairo_clip_t *clip,
cairo_traps_t *traps,
cairo_surface_t *target)
{
- cairo_region_t region;
+ cairo_region_t *region;
cairo_int_status_t status;
if (clip->all_clipped)
@@ -357,29 +334,21 @@ _cairo_clip_intersect_region (cairo_clip_t *clip,
if (status)
return status;
- if (!clip->has_region) {
- status = _cairo_region_copy (&clip->region, &region);
- if (status == CAIRO_STATUS_SUCCESS)
- clip->has_region = TRUE;
+ if (clip->region) {
+ status = cairo_region_intersect (clip->region, region);
} else {
- cairo_region_t intersection;
-
- _cairo_region_init (&intersection);
-
- status = _cairo_region_intersect (&intersection,
- &clip->region,
- &region);
+ clip->region = cairo_region_copy (region);
- if (status == CAIRO_STATUS_SUCCESS)
- status = _cairo_region_copy (&clip->region, &intersection);
-
- _cairo_region_fini (&intersection);
+ assert (clip->region != NULL);
+
+ if ((status = cairo_region_status (clip->region)))
+ clip->region = NULL;
}
clip->serial = _cairo_surface_allocate_clip_serial (target);
- _cairo_region_fini (&region);
+ cairo_region_destroy (region);
- if (! _cairo_region_not_empty (&clip->region))
+ if (!clip->region || cairo_region_is_empty (clip->region))
_cairo_clip_set_all_clipped (clip, target);
return status;
@@ -736,10 +705,10 @@ _cairo_clip_translate (cairo_clip_t *clip,
if (clip->all_clipped)
return;
- if (clip->has_region) {
- _cairo_region_translate (&clip->region,
- _cairo_fixed_integer_part (tx),
- _cairo_fixed_integer_part (ty));
+ if (clip->region) {
+ cairo_region_translate (clip->region,
+ _cairo_fixed_integer_part (tx),
+ _cairo_fixed_integer_part (ty));
}
if (clip->surface) {
@@ -794,17 +763,16 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip,
/* We should reapply the original clip path in this case, and let
* whatever the right handling is happen */
} else {
- if (other->has_region) {
- status = _cairo_region_copy (&clip->region, &other->region);
- if (unlikely (status))
+ if (other->region) {
+ clip->region = cairo_region_copy (other->region);
+ if (unlikely ((status = cairo_region_status (clip->region))))
goto BAIL;
-
- clip->has_region = TRUE;
}
if (other->surface) {
int dx, dy;
status = _cairo_surface_clone_similar (target, other->surface,
+ CAIRO_CONTENT_ALPHA,
0,
0,
other->surface_rect.width,
@@ -831,8 +799,8 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip,
return CAIRO_STATUS_SUCCESS;
BAIL:
- if (clip->has_region)
- _cairo_region_fini (&clip->region);
+ if (clip->region)
+ cairo_region_destroy (clip->region);
if (clip->surface)
cairo_surface_destroy (clip->surface);
@@ -873,7 +841,7 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
{
cairo_rectangle_list_t *list;
cairo_rectangle_t *rectangles = NULL;
- int n_boxes = 0;
+ int n_rects = 0;
if (clip->all_clipped)
goto DONE;
@@ -883,43 +851,34 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
}
- if (clip->has_region) {
- cairo_box_int_t *boxes;
+ if (clip->region) {
int i;
- if (_cairo_region_get_boxes (&clip->region, &n_boxes, &boxes))
- return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
+ n_rects = cairo_region_num_rectangles (clip->region);
- if (n_boxes) {
- rectangles = _cairo_malloc_ab (n_boxes, sizeof (cairo_rectangle_t));
+ if (n_rects) {
+ rectangles = _cairo_malloc_ab (n_rects, sizeof (cairo_rectangle_t));
if (unlikely (rectangles == NULL)) {
- _cairo_region_boxes_fini (&clip->region, boxes);
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
}
- for (i = 0; i < n_boxes; ++i) {
- cairo_rectangle_int_t clip_rect;
-
- clip_rect.x = boxes[i].p1.x;
- clip_rect.y = boxes[i].p1.y;
- clip_rect.width = boxes[i].p2.x - boxes[i].p1.x;
- clip_rect.height = boxes[i].p2.y - boxes[i].p1.y;
+ for (i = 0; i < n_rects; ++i) {
+ cairo_rectangle_int_t clip_rect;
+ cairo_region_get_rectangle (clip->region, i, &clip_rect);
+
if (!_cairo_clip_int_rect_to_user(gstate, &clip_rect, &rectangles[i])) {
_cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
- _cairo_region_boxes_fini (&clip->region, boxes);
free (rectangles);
return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
}
}
}
-
- _cairo_region_boxes_fini (&clip->region, boxes);
} else {
cairo_rectangle_int_t extents;
- n_boxes = 1;
+ n_rects = 1;
rectangles = malloc(sizeof (cairo_rectangle_t));
if (unlikely (rectangles == NULL)) {
@@ -946,7 +905,7 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
list->status = CAIRO_STATUS_SUCCESS;
list->rectangles = rectangles;
- list->num_rectangles = n_boxes;
+ list->num_rectangles = n_rects;
return list;
}
diff --git a/src/cairo-compiler-private.h b/src/cairo-compiler-private.h
index 44d9de30..403c3f7a 100644
--- a/src/cairo-compiler-private.h
+++ b/src/cairo-compiler-private.h
@@ -164,6 +164,8 @@
#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
#define snprintf _snprintf
#define popen _popen
+#define pclose _pclose
+#define hypot _hypot
#endif
#ifdef _MSC_VER
@@ -171,6 +173,30 @@
#define inline __inline
#endif
+#if defined(_MSC_VER) && defined(_M_IX86)
+/* When compiling with /Gy and /OPT:ICF identical functions will be folded in together.
+ The CAIRO_ENSURE_UNIQUE macro ensures that a function is always unique and
+ will never be folded into another one. Something like this might eventually
+ be needed for GCC but it seems fine for now. */
+#define CAIRO_ENSURE_UNIQUE \
+ do { \
+ char func[] = __FUNCTION__; \
+ char file[] = __FILE__; \
+ __asm { \
+ __asm jmp __internal_skip_line_no \
+ __asm _emit (__LINE__ & 0xff) \
+ __asm _emit ((__LINE__>>8) & 0xff) \
+ __asm _emit ((__LINE__>>16) & 0xff) \
+ __asm _emit ((__LINE__>>24) & 0xff) \
+ __asm lea eax, func \
+ __asm lea eax, file \
+ __asm __internal_skip_line_no: \
+ }; \
+ } while (0)
+#else
+#define CAIRO_ENSURE_UNIQUE do { } while (0)
+#endif
+
#ifdef __STRICT_ANSI__
#undef inline
#define inline __inline__
diff --git a/src/cairo-debug.c b/src/cairo-debug.c
index 5100a855..d463be29 100644
--- a/src/cairo-debug.c
+++ b/src/cairo-debug.c
@@ -77,3 +77,45 @@ cairo_debug_reset_static_data (void)
CAIRO_MUTEX_FINALIZE ();
}
+
+#if HAVE_VALGRIND
+#include <memcheck.h>
+
+void
+_cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface)
+{
+ const cairo_image_surface_t *image = (cairo_image_surface_t *) surface;
+ const uint8_t *bits;
+ int row, width;
+
+ if (surface == NULL)
+ return;
+
+ if (! RUNNING_ON_VALGRIND)
+ return;
+
+ bits = image->data;
+ switch (image->format) {
+ case CAIRO_FORMAT_A1:
+ width = (image->width + 7)/8;
+ break;
+ case CAIRO_FORMAT_A8:
+ width = image->width;
+ break;
+ case CAIRO_FORMAT_RGB24:
+ case CAIRO_FORMAT_ARGB32:
+ width = image->width*4;
+ break;
+ default:
+ ASSERT_NOT_REACHED;
+ return;
+ }
+
+ for (row = 0; row < image->height; row++) {
+ VALGRIND_CHECK_MEM_IS_DEFINED (bits, width);
+ /* and then silence any future valgrind warnings */
+ VALGRIND_MAKE_MEM_DEFINED (bits, width);
+ bits += image->stride;
+ }
+}
+#endif
diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index ecce1792..df9c0e98 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -617,6 +617,7 @@ _cairo_directfb_surface_release_dest_image (void *abstract_surf
static cairo_status_t
_cairo_directfb_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
+ cairo_content_t content,
int src_x,
int src_y,
int width,
@@ -763,6 +764,7 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst,
}
status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
+ CAIRO_CONTENT_COLOR_ALPHA,
*src_x, *src_y, width, height,
(cairo_surface_t **) &src,
&src_attr);
@@ -1299,43 +1301,40 @@ _cairo_directfb_surface_set_clip_region (void *abstract_surface,
__FUNCTION__, surface, region);
if (region) {
- cairo_box_int_t *boxes;
- int n_boxes;
+ int n_rects;
cairo_status_t status;
int i;
surface->has_clip = TRUE;
- n_boxes = 0;
- status = _cairo_region_get_boxes (region, &n_boxes, &boxes);
- if (status)
- return status;
+ n_rects = cairo_region_num_rectangles (region);
- if (n_boxes == 0)
+ if (n_rects == 0)
return CAIRO_STATUS_SUCCESS;
- if (surface->n_clips != n_boxes) {
+ if (surface->n_clips != n_rects) {
if (surface->clips)
free (surface->clips);
- surface->clips = _cairo_malloc_ab (n_boxes, sizeof (DFBRegion));
+ surface->clips = _cairo_malloc_ab (n_rects, sizeof (DFBRegion));
if (!surface->clips) {
surface->n_clips = 0;
- _cairo_region_boxes_fini (region, boxes);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
- surface->n_clips = n_boxes;
+ surface->n_clips = n_rects;
}
- for (i = 0; i < n_boxes; i++) {
- surface->clips[i].x1 = boxes[i].p1.x;
- surface->clips[i].y1 = boxes[i].p1.y;
- surface->clips[i].x2 = boxes[i].p2.x - 1;
- surface->clips[i].y2 = boxes[i].p2.y - 1;
- }
+ for (i = 0; i < n_rects; i++) {
+ cairo_rectangle_int_t rect;
- _cairo_region_boxes_fini (region, boxes);
+ cairo_region_get_rectangle (region, i, &rect);
+
+ surface->clips[i].x1 = rect.x;
+ surface->clips[i].y1 = rect.y;
+ surface->clips[i].x2 = rect.x + rect.width - 1;
+ surface->clips[i].y2 = rect.y + rect.height - 1;
+ }
} else {
surface->has_clip = FALSE;
if (surface->clips) {
diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index b8343221..712ca0dc 100644
--- a/src/cairo-font-face-twin.c
+++ b/src/cairo-font-face-twin.c
@@ -34,8 +34,6 @@
* Behdad Esfahbod <behdad@behdad.org>
*/
-#define _ISOC99_SOURCE /* for round() */
-
#include "cairoint.h"
#include <math.h>
@@ -59,16 +57,21 @@ static cairo_user_data_key_t twin_properties_key;
/* We synthesize multiple faces from the twin data. Here is the parameters. */
+/* The following tables and matching code are copied from Pango */
+
/* CSS weight */
typedef enum {
+ TWIN_WEIGHT_THIN = 100,
TWIN_WEIGHT_ULTRALIGHT = 200,
TWIN_WEIGHT_LIGHT = 300,
+ TWIN_WEIGHT_BOOK = 380,
TWIN_WEIGHT_NORMAL = 400,
TWIN_WEIGHT_MEDIUM = 500,
TWIN_WEIGHT_SEMIBOLD = 600,
TWIN_WEIGHT_BOLD = 700,
TWIN_WEIGHT_ULTRABOLD = 800,
- TWIN_WEIGHT_HEAVY = 900
+ TWIN_WEIGHT_HEAVY = 900,
+ TWIN_WEIGHT_ULTRAHEAVY = 1000
} twin_face_weight_t;
/* CSS stretch */
@@ -84,6 +87,64 @@ typedef enum {
TWIN_STRETCH_ULTRA_EXPANDED
} twin_face_stretch_t;
+typedef struct
+{
+ int value;
+ const char str[16];
+} FieldMap;
+
+static const FieldMap slant_map[] = {
+ { CAIRO_FONT_SLANT_NORMAL, "" },
+ { CAIRO_FONT_SLANT_NORMAL, "Roman" },
+ { CAIRO_FONT_SLANT_OBLIQUE, "Oblique" },
+ { CAIRO_FONT_SLANT_ITALIC, "Italic" }
+};
+
+static const FieldMap smallcaps_map[] = {
+ { FALSE, "" },
+ { TRUE, "Small-Caps" }
+};
+
+static const FieldMap weight_map[] = {
+ { TWIN_WEIGHT_THIN, "Thin" },
+ { TWIN_WEIGHT_ULTRALIGHT, "Ultra-Light" },
+ { TWIN_WEIGHT_ULTRALIGHT, "Extra-Light" },
+ { TWIN_WEIGHT_LIGHT, "Light" },
+ { TWIN_WEIGHT_BOOK, "Book" },
+ { TWIN_WEIGHT_NORMAL, "" },
+ { TWIN_WEIGHT_NORMAL, "Regular" },
+ { TWIN_WEIGHT_MEDIUM, "Medium" },
+ { TWIN_WEIGHT_SEMIBOLD, "Semi-Bold" },
+ { TWIN_WEIGHT_SEMIBOLD, "Demi-Bold" },
+ { TWIN_WEIGHT_BOLD, "Bold" },
+ { TWIN_WEIGHT_ULTRABOLD, "Ultra-Bold" },
+ { TWIN_WEIGHT_ULTRABOLD, "Extra-Bold" },
+ { TWIN_WEIGHT_HEAVY, "Heavy" },
+ { TWIN_WEIGHT_HEAVY, "Black" },
+ { TWIN_WEIGHT_ULTRAHEAVY, "Ultra-Heavy" },
+ { TWIN_WEIGHT_ULTRAHEAVY, "Extra-Heavy" },
+ { TWIN_WEIGHT_ULTRAHEAVY, "Ultra-Black" },
+ { TWIN_WEIGHT_ULTRAHEAVY, "Extra-Black" }
+};
+
+static const FieldMap stretch_map[] = {
+ { TWIN_STRETCH_ULTRA_CONDENSED, "Ultra-Condensed" },
+ { TWIN_STRETCH_EXTRA_CONDENSED, "Extra-Condensed" },
+ { TWIN_STRETCH_CONDENSED, "Condensed" },
+ { TWIN_STRETCH_SEMI_CONDENSED, "Semi-Condensed" },
+ { TWIN_STRETCH_NORMAL, "" },
+ { TWIN_STRETCH_SEMI_EXPANDED, "Semi-Expanded" },
+ { TWIN_STRETCH_EXPANDED, "Expanded" },
+ { TWIN_STRETCH_EXTRA_EXPANDED, "Extra-Expanded" },
+ { TWIN_STRETCH_ULTRA_EXPANDED, "Ultra-Expanded" }
+};
+
+static const FieldMap monospace_map[] = {
+ { FALSE, "" },
+ { TRUE, "Mono" },
+ { TRUE, "Monospace" }
+};
+
typedef struct _twin_face_properties {
cairo_font_slant_t slant;
@@ -123,41 +184,84 @@ field_matches (const char *s1,
return len == 0 && *s1 == '\0';
}
+static cairo_bool_t
+parse_int (const char *word,
+ size_t wordlen,
+ int *out)
+{
+ char *end;
+ long val = strtol (word, &end, 10);
+ int i = val;
+
+ if (end != word && (end == word + wordlen) && val >= 0 && val == i)
+ {
+ if (out)
+ *out = i;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static cairo_bool_t
+find_field (const char *what,
+ const FieldMap *map,
+ int n_elements,
+ const char *str,
+ int len,
+ int *val)
+{
+ int i;
+ cairo_bool_t had_prefix = FALSE;
+
+ if (what)
+ {
+ i = strlen (what);
+ if (len > i && 0 == strncmp (what, str, i) && str[i] == '=')
+ {
+ str += i + 1;
+ len -= i + 1;
+ had_prefix = TRUE;
+ }
+ }
+
+ for (i=0; i<n_elements; i++)
+ {
+ if (map[i].str[0] && field_matches (map[i].str, str, len))
+ {
+ if (val)
+ *val = map[i].value;
+ return TRUE;
+ }
+ }
+
+ if (!what || had_prefix)
+ return parse_int (str, len, val);
+
+ return FALSE;
+}
static void
parse_field (twin_face_properties_t *props,
- const char *s,
+ const char *str,
int len)
{
-#define MATCH(s1, var, value) \
- if (field_matches (s1, s, len)) var = value
-
- if (0) ;
-
- else MATCH ("oblique", props->slant, CAIRO_FONT_SLANT_OBLIQUE);
- else MATCH ("italic", props->slant, CAIRO_FONT_SLANT_ITALIC);
-
- else MATCH ("ultra-light", props->weight, TWIN_WEIGHT_ULTRALIGHT);
- else MATCH ("light", props->weight, TWIN_WEIGHT_LIGHT);
- else MATCH ("medium", props->weight, TWIN_WEIGHT_NORMAL);
- else MATCH ("semi-bold", props->weight, TWIN_WEIGHT_SEMIBOLD);
- else MATCH ("bold", props->weight, TWIN_WEIGHT_BOLD);
- else MATCH ("ultra-bold", props->weight, TWIN_WEIGHT_ULTRABOLD);
- else MATCH ("heavy", props->weight, TWIN_WEIGHT_HEAVY);
-
- else MATCH ("ultra-condensed", props->stretch, TWIN_STRETCH_ULTRA_CONDENSED);
- else MATCH ("extra-condensed", props->stretch, TWIN_STRETCH_EXTRA_CONDENSED);
- else MATCH ("condensed", props->stretch, TWIN_STRETCH_CONDENSED);
- else MATCH ("semi-condensed", props->stretch, TWIN_STRETCH_SEMI_CONDENSED);
- else MATCH ("semi-expanded", props->stretch, TWIN_STRETCH_SEMI_EXPANDED);
- else MATCH ("expanded", props->stretch, TWIN_STRETCH_EXPANDED);
- else MATCH ("extra-expanded", props->stretch, TWIN_STRETCH_EXTRA_EXPANDED);
- else MATCH ("ultra-expanded", props->stretch, TWIN_STRETCH_ULTRA_EXPANDED);
-
- else MATCH ("mono", props->monospace, TRUE);
- else MATCH ("monospace", props->monospace, TRUE);
-
- else MATCH ("small-caps", props->smallcaps, TRUE);
+ if (field_matches ("Normal", str, len))
+ return;
+
+#define FIELD(NAME) \
+ if (find_field (STRINGIFY (NAME), NAME##_map, ARRAY_LENGTH (NAME##_map), str, len, \
+ (int *)(void *)&props->NAME)) \
+ return; \
+
+ FIELD (weight);
+ FIELD (slant);
+ FIELD (stretch);
+ FIELD (smallcaps);
+ FIELD (monospace);
+
+#undef FIELD
}
static void
@@ -166,11 +270,8 @@ face_props_parse (twin_face_properties_t *props,
{
const char *start, *end;
-#define ISALPHA(c) \
- (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
-
for (start = end = s; *end; end++) {
- if (ISALPHA (*end) || *end == '-')
+ if (*end != ' ' && *end != ':')
continue;
if (start < end)
@@ -255,8 +356,8 @@ compute_hinting_scales (cairo_t *cr,
compute_hinting_scale (cr, x, y, y_scale, y_scale_inv);
}
-#define SNAPXI(p) (round ((p) * x_scale) * x_scale_inv)
-#define SNAPYI(p) (round ((p) * y_scale) * y_scale_inv)
+#define SNAPXI(p) (_cairo_round ((p) * x_scale) * x_scale_inv)
+#define SNAPYI(p) (_cairo_round ((p) * y_scale) * y_scale_inv)
/* This controls the global font size */
#define F(g) ((g) / 72.)
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 4295d250..6c642846 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -45,8 +45,10 @@
#include <float.h>
+#if CAIRO_HAS_FC_FONT
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcfreetype.h>
+#endif
#include <ft2build.h>
#include FT_FREETYPE_H
@@ -117,10 +119,6 @@ _cairo_ft_unscaled_font_keys_equal (const void *key_a,
static void
_cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled);
-static cairo_status_t
-_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
- FcPattern *pattern);
-
typedef enum _cairo_ft_extra_flags {
CAIRO_FT_OPTIONS_HINT_METRICS = (1 << 0),
CAIRO_FT_OPTIONS_EMBOLDEN = (1 << 1)
@@ -139,11 +137,18 @@ struct _cairo_ft_font_face {
cairo_ft_options_t ft_options;
cairo_ft_font_face_t *next;
+#if CAIRO_HAS_FC_FONT
FcPattern *pattern; /* if pattern is set, the above fields will be NULL */
+#endif
};
static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend;
+#if CAIRO_HAS_FC_FONT
+static cairo_status_t
+_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
+ FcPattern *pattern);
+
static cairo_status_t
_cairo_ft_resolve_pattern (FcPattern *pattern,
const cairo_matrix_t *font_matrix,
@@ -152,6 +157,7 @@ _cairo_ft_resolve_pattern (FcPattern *pattern,
cairo_ft_unscaled_font_t **unscaled,
cairo_ft_options_t *ft_options);
+#endif
/*
* We maintain a hash table to map file/id => #cairo_ft_unscaled_font_t.
@@ -408,11 +414,12 @@ _cairo_ft_unscaled_font_keys_equal (const void *key_a,
/* Finds or creates a #cairo_ft_unscaled_font_t for the filename/id from
* pattern. Returns a new reference to the unscaled font.
*/
-static cairo_ft_unscaled_font_t *
+static cairo_status_t
_cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face,
char *filename,
int id,
- FT_Face font_face)
+ FT_Face font_face,
+ cairo_ft_unscaled_font_t **out)
{
cairo_ft_unscaled_font_t key, *unscaled;
cairo_ft_unscaled_font_map_t *font_map;
@@ -420,7 +427,7 @@ _cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face,
font_map = _cairo_ft_unscaled_font_map_lock ();
if (unlikely (font_map == NULL))
- goto UNWIND;
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_ft_unscaled_font_init_key (&key, from_face, filename, id, font_face);
@@ -429,14 +436,13 @@ _cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face,
&key.base.hash_entry);
if (unscaled != NULL) {
_cairo_unscaled_font_reference (&unscaled->base);
- _cairo_ft_unscaled_font_map_unlock ();
- return unscaled;
+ goto DONE;
}
/* Otherwise create it and insert into hash table. */
unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
if (unlikely (unscaled == NULL)) {
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto UNWIND_FONT_MAP_LOCK;
}
@@ -444,14 +450,16 @@ _cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face,
if (unlikely (status))
goto UNWIND_UNSCALED_MALLOC;
+ assert (unscaled->base.hash_entry.hash == key.base.hash_entry.hash);
status = _cairo_hash_table_insert (font_map->hash_table,
&unscaled->base.hash_entry);
if (unlikely (status))
goto UNWIND_UNSCALED_FONT_INIT;
+DONE:
_cairo_ft_unscaled_font_map_unlock ();
-
- return unscaled;
+ *out = unscaled;
+ return CAIRO_STATUS_SUCCESS;
UNWIND_UNSCALED_FONT_INIT:
_cairo_ft_unscaled_font_fini (unscaled);
@@ -459,38 +467,54 @@ UNWIND_UNSCALED_MALLOC:
free (unscaled);
UNWIND_FONT_MAP_LOCK:
_cairo_ft_unscaled_font_map_unlock ();
-UNWIND:
- return NULL;
+ return status;
}
-static cairo_ft_unscaled_font_t *
-_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
+#if CAIRO_HAS_FC_FONT
+static cairo_status_t
+_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern,
+ cairo_ft_unscaled_font_t **out)
{
FT_Face font_face = NULL;
char *filename = NULL;
int id = 0;
+ FcResult ret;
- if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &font_face) == FcResultMatch)
+ ret = FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &font_face);
+ if (ret == FcResultMatch)
goto DONE;
+ if (ret == FcResultOutOfMemory)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- if (FcPatternGetString (pattern, FC_FILE, 0, (FcChar8 **) &filename) == FcResultMatch) {
+ ret = FcPatternGetString (pattern, FC_FILE, 0, (FcChar8 **) &filename);
+ if (ret == FcResultOutOfMemory)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (ret == FcResultMatch) {
/* If FC_INDEX is not set, we just use 0 */
- FcPatternGetInteger (pattern, FC_INDEX, 0, &id);
+ ret = FcPatternGetInteger (pattern, FC_INDEX, 0, &id);
+ if (ret == FcResultOutOfMemory)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
goto DONE;
}
- return NULL;
+ /* The pattern contains neither a face nor a filename, resolve it later. */
+ *out = NULL;
+ return CAIRO_STATUS_SUCCESS;
DONE:
- return _cairo_ft_unscaled_font_create_internal (font_face != NULL, filename, id, font_face);
-
+ return _cairo_ft_unscaled_font_create_internal (font_face != NULL,
+ filename, id, font_face,
+ out);
}
+#endif
-static cairo_ft_unscaled_font_t *
-_cairo_ft_unscaled_font_create_from_face (FT_Face face)
+static cairo_status_t
+_cairo_ft_unscaled_font_create_from_face (FT_Face face,
+ cairo_ft_unscaled_font_t **out)
{
- return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, 0, face);
+ return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, 0, face, out);
}
static void
@@ -519,8 +543,10 @@ _cairo_ft_unscaled_font_destroy (void *abstract_font)
/* See comments in _ft_font_face_destroy about the "zombie" state
* for a _ft_font_face.
*/
- if (unscaled->faces && !unscaled->faces->unscaled)
+ if (unscaled->faces && unscaled->faces->unscaled == NULL) {
+ assert (unscaled->faces->next == NULL);
cairo_font_face_destroy (&unscaled->faces->base);
+ }
} else {
_font_map_release_face_lock_held (font_map, unscaled);
}
@@ -532,9 +558,9 @@ _cairo_ft_unscaled_font_destroy (void *abstract_font)
}
static cairo_bool_t
-_has_unlocked_face (void *entry)
+_has_unlocked_face (const void *entry)
{
- cairo_ft_unscaled_font_t *unscaled = entry;
+ const cairo_ft_unscaled_font_t *unscaled = entry;
return (!unscaled->from_face && unscaled->lock_count == 0 && unscaled->face);
}
@@ -970,6 +996,8 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
_cairo_image_surface_assume_ownership_of_data ((*surface));
+ _cairo_debug_check_image_surface_is_defined (&(*surface)->base);
+
return CAIRO_STATUS_SUCCESS;
}
@@ -1291,6 +1319,7 @@ typedef struct _cairo_ft_scaled_font {
static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend;
+#if CAIRO_HAS_FC_FONT
/* The load flags passed to FT_Load_Glyph control aspects like hinting and
* antialiasing. Here we compute them from the fields of a FcPattern.
*/
@@ -1426,6 +1455,7 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
*ret = ft_options;
}
+#endif
static void
_cairo_ft_options_merge (cairo_ft_options_t *options,
@@ -1894,7 +1924,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
FT_Pos x1, x2;
FT_Pos y1, y2;
FT_Pos advance;
-
+
if (!vertical_layout) {
x1 = (metrics->horiBearingX) & -64;
x2 = (metrics->horiBearingX + metrics->width + 63) & -64;
@@ -1949,7 +1979,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor;
else
- fs_metrics.y_advance = DOUBLE_FROM_26_6 (glyph->linearVertAdvance) * y_factor;
+ fs_metrics.y_advance = DOUBLE_FROM_16_16 (glyph->linearVertAdvance) * y_factor;
}
}
@@ -2044,9 +2074,11 @@ _cairo_ft_ucs4_to_index (void *abstract_font,
if (!face)
return 0;
- /* If making this compile without fontconfig, use:
- * index = FT_Get_Char_Index (face, ucs4); */
+#if CAIRO_HAS_FC_FONT
index = FcFreeTypeCharIndex (face, ucs4);
+#else
+ index = FT_Get_Char_Index (face, ucs4);
+#endif
_cairo_ft_unscaled_font_unlock_face (unscaled);
return index;
@@ -2125,6 +2157,7 @@ static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
/* #cairo_ft_font_face_t */
+#if CAIRO_HAS_FC_FONT
static cairo_status_t
_cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
cairo_font_face_t **out);
@@ -2191,6 +2224,7 @@ _cairo_ft_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
return status;
}
+#endif
static void
_cairo_ft_font_face_destroy (void *abstract_face)
@@ -2203,9 +2237,10 @@ _cairo_ft_font_face_destroy (void *abstract_face)
if (font_face == NULL)
return;
- /* When destroying the face created by cairo_ft_font_face_create_for_ft_face,
+ /* When destroying a face created by cairo_ft_font_face_create_for_ft_face,
* we have a special "zombie" state for the face when the unscaled font
- * is still alive but there are no public references to the font face.
+ * is still alive but there are no other references to a font face with
+ * the same FT_Face.
*
* We go from:
*
@@ -2219,6 +2254,8 @@ _cairo_ft_font_face_destroy (void *abstract_face)
if (font_face->unscaled &&
font_face->unscaled->from_face &&
+ font_face->next == NULL &&
+ font_face->unscaled->faces == font_face &&
CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count) > 1)
{
cairo_font_face_reference (&font_face->base);
@@ -2249,8 +2286,10 @@ _cairo_ft_font_face_destroy (void *abstract_face)
font_face->unscaled = NULL;
}
+#if CAIRO_HAS_FC_FONT
if (font_face->pattern)
FcPatternDestroy (font_face->pattern);
+#endif
}
static cairo_status_t
@@ -2274,6 +2313,7 @@ _cairo_ft_font_face_scaled_font_create (void *abstract_face,
* flags and ignore the options.
*/
+#if CAIRO_HAS_FC_FONT
/* If we have an unresolved pattern, resolve it and create
* unscaled font. Otherwise, use the ones stored in font_face.
*/
@@ -2294,26 +2334,32 @@ _cairo_ft_font_face_scaled_font_create (void *abstract_face,
*scaled_font = _cairo_scaled_font_create_in_error (status);
return CAIRO_STATUS_SUCCESS;
}
-
- } else {
+ } else
+#endif
+ {
unscaled = font_face->unscaled;
ft_options = font_face->ft_options;
}
- return _cairo_ft_scaled_font_create (unscaled,
- &font_face->base,
- font_matrix, ctm,
- options, ft_options,
- scaled_font);
+ return _cairo_ft_scaled_font_create (unscaled,
+ &font_face->base,
+ font_matrix, ctm,
+ options, ft_options,
+ scaled_font);
}
const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
CAIRO_FONT_TYPE_FT,
+#if CAIRO_HAS_FC_FONT
_cairo_ft_font_face_create_for_toy,
+#else
+ NULL,
+#endif
_cairo_ft_font_face_destroy,
_cairo_ft_font_face_scaled_font_create
};
+#if CAIRO_HAS_FC_FONT
static cairo_status_t
_cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
cairo_font_face_t **out)
@@ -2328,7 +2374,7 @@ _cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
font_face->next = NULL;
font_face->pattern = FcPatternDuplicate (pattern);
- if (unlikely (pattern == NULL)) {
+ if (unlikely (font_face->pattern == NULL)) {
free (font_face);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
@@ -2338,6 +2384,7 @@ _cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
*out = &font_face->base;
return CAIRO_STATUS_SUCCESS;
}
+#endif
static cairo_font_face_t *
_cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
@@ -2354,12 +2401,21 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
font_face->ft_options.extra_flags == ft_options->extra_flags &&
cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base))
{
- if (font_face->base.status == CAIRO_STATUS_SUCCESS)
- return cairo_font_face_reference (&font_face->base);
+ if (font_face->base.status) {
+ /* The font_face has been left in an error state, abandon it. */
+ *prev_font_face = font_face->next;
+ break;
+ }
- /* The font_face has been left in an error state, abandon it. */
- *prev_font_face = font_face->next;
- break;
+ if (font_face->unscaled == NULL) {
+ /* Resurrect this "zombie" font_face (from
+ * _cairo_ft_font_face_destroy), switching its unscaled_font
+ * from owner to ownee. */
+ font_face->unscaled = unscaled;
+ _cairo_unscaled_font_reference (&unscaled->base);
+ return &font_face->base;
+ } else
+ return cairo_font_face_reference (&font_face->base);
}
}
@@ -2375,10 +2431,20 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
font_face->ft_options = *ft_options;
+ if (unscaled->faces && unscaled->faces->unscaled == NULL) {
+ /* This "zombie" font_face (from _cairo_ft_font_face_destroy)
+ * is no longer needed. */
+ assert (unscaled->from_face && unscaled->faces->next == NULL);
+ cairo_font_face_destroy (&unscaled->faces->base);
+ unscaled->faces = NULL;
+ }
+
font_face->next = unscaled->faces;
unscaled->faces = font_face;
+#if CAIRO_HAS_FC_FONT
font_face->pattern = NULL;
+#endif
_cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
@@ -2387,6 +2453,7 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
/* implement the platform-specific interface */
+#if CAIRO_HAS_FC_FONT
static cairo_status_t
_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
FcPattern *pattern)
@@ -2530,6 +2597,8 @@ _cairo_ft_resolve_pattern (FcPattern *pattern,
return status;
pattern = FcPatternDuplicate (pattern);
+ if (pattern == NULL)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
if (! FcPatternAddDouble (pattern, FC_PIXEL_SIZE, sf.y_scale)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -2553,11 +2622,9 @@ _cairo_ft_resolve_pattern (FcPattern *pattern,
goto FREE_PATTERN;
}
- *unscaled = _cairo_ft_unscaled_font_create_for_pattern (resolved);
- if (!*unscaled) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ status = _cairo_ft_unscaled_font_create_for_pattern (resolved, unscaled);
+ if (unlikely (status))
goto FREE_RESOLVED;
- }
_get_pattern_ft_options (resolved, ft_options);
@@ -2613,10 +2680,12 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
cairo_ft_unscaled_font_t *unscaled;
cairo_font_face_t *font_face;
cairo_ft_options_t ft_options;
+ cairo_status_t status;
- unscaled = _cairo_ft_unscaled_font_create_for_pattern (pattern);
+ status = _cairo_ft_unscaled_font_create_for_pattern (pattern, &unscaled);
+ if (unlikely (status))
+ return (cairo_font_face_t *) &_cairo_font_face_nil;
if (unlikely (unscaled == NULL)) {
- cairo_status_t status;
/* Store the pattern. We will resolve it and create unscaled
* font when creating scaled fonts */
status = _cairo_ft_font_face_create_for_pattern (pattern,
@@ -2633,6 +2702,7 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
return font_face;
}
+#endif
/**
* cairo_ft_font_face_create_for_ft_face:
@@ -2687,12 +2757,11 @@ cairo_ft_font_face_create_for_ft_face (FT_Face face,
cairo_ft_unscaled_font_t *unscaled;
cairo_font_face_t *font_face;
cairo_ft_options_t ft_options;
+ cairo_status_t status;
- unscaled = _cairo_ft_unscaled_font_create_from_face (face);
- if (unlikely (unscaled == NULL)) {
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ status = _cairo_ft_unscaled_font_create_from_face (face, &unscaled);
+ if (unlikely (status))
return (cairo_font_face_t *)&_cairo_font_face_nil;
- }
ft_options.load_flags = load_flags;
ft_options.extra_flags = 0;
diff --git a/src/cairo-ft.h b/src/cairo-ft.h
index 91e2db89..b7178d35 100644
--- a/src/cairo-ft.h
+++ b/src/cairo-ft.h
@@ -43,18 +43,14 @@
/* Fontconfig/Freetype platform-specific font interface */
-#include <fontconfig/fontconfig.h>
#include <ft2build.h>
#include FT_FREETYPE_H
-CAIRO_BEGIN_DECLS
-
-cairo_public cairo_font_face_t *
-cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
+#if CAIRO_HAS_FC_FONT
+#include <fontconfig/fontconfig.h>
+#endif
-cairo_public void
-cairo_ft_font_options_substitute (const cairo_font_options_t *options,
- FcPattern *pattern);
+CAIRO_BEGIN_DECLS
cairo_public cairo_font_face_t *
cairo_ft_font_face_create_for_ft_face (FT_Face face,
@@ -66,6 +62,17 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *scaled_font);
cairo_public void
cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *scaled_font);
+#if CAIRO_HAS_FC_FONT
+
+cairo_public cairo_font_face_t *
+cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
+
+cairo_public void
+cairo_ft_font_options_substitute (const cairo_font_options_t *options,
+ FcPattern *pattern);
+
+#endif
+
CAIRO_END_DECLS
#else /* CAIRO_HAS_FT_FONT */
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 2d601eed..3897ed4c 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -551,7 +551,7 @@ _cairo_gl_surface_get_image (cairo_gl_surface_t *surface,
cairo_rectangle_int_t extents;
GLenum err;
char *temp_data;
- unsigned int y;
+ int y;
unsigned int cpp;
GLenum format, type;
cairo_format_t cairo_format;
@@ -703,6 +703,7 @@ _cairo_gl_surface_release_dest_image (void *abstract_surface,
static cairo_status_t
_cairo_gl_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
+ cairo_content_t content,
int src_x,
int src_y,
int width,
@@ -729,7 +730,7 @@ _cairo_gl_surface_clone_similar (void *abstract_surface,
clone = (cairo_gl_surface_t *)
_cairo_gl_surface_create_similar (&surface->base,
- src->content,
+ content,
width, height);
if (clone == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1035,6 +1036,7 @@ _cairo_gl_pattern_texture_setup (cairo_gl_composite_operand_t *operand,
}
status = _cairo_pattern_acquire_surface (src, &dst->base,
+ CAIRO_CONTENT_COLOR_ALPHA,
src_x, src_y,
width, height,
(cairo_surface_t **)
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index 284198b2..9ee8a88b 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -352,6 +352,7 @@ _cairo_glitz_surface_release_dest_image (void *abstract_surfa
static cairo_status_t
_cairo_glitz_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
+ cairo_content_t content,
int src_x,
int src_y,
int width,
@@ -716,6 +717,7 @@ _cairo_glitz_pattern_acquire_surface (const cairo_pattern_t *pattern,
cairo_int_status_t status;
status = _cairo_pattern_acquire_surface (pattern, &dst->base,
+ CAIRO_CONTENT_COLOR_ALPHA,
x, y, width, height,
(cairo_surface_t **) &src,
&attr->base);
@@ -2133,6 +2135,7 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
status =
_cairo_glitz_surface_clone_similar (abstract_surface,
image,
+ CAIRO_CONTENT_COLOR_ALPHA,
0,
0,
glyph_width,
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 9ee31b07..c7c4cf55 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -222,6 +222,9 @@ _cairo_gstate_save (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
cairo_gstate_t *top;
cairo_status_t status;
+ if (CAIRO_INJECT_FAULT ())
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
top = *freelist;
if (top == NULL) {
top = malloc (sizeof (cairo_gstate_t));
diff --git a/src/cairo-hash-private.h b/src/cairo-hash-private.h
index 8ab08582..32078bd2 100644
--- a/src/cairo-hash-private.h
+++ b/src/cairo-hash-private.h
@@ -51,7 +51,7 @@ typedef cairo_bool_t
(*cairo_hash_keys_equal_func_t) (const void *key_a, const void *key_b);
typedef cairo_bool_t
-(*cairo_hash_predicate_func_t) (void *entry);
+(*cairo_hash_predicate_func_t) (const void *entry);
typedef void
(*cairo_hash_callback_func_t) (void *entry,
@@ -68,10 +68,6 @@ _cairo_hash_table_lookup (cairo_hash_table_t *hash_table,
cairo_hash_entry_t *key);
cairo_private void *
-_cairo_hash_table_steal (cairo_hash_table_t *hash_table,
- cairo_hash_entry_t *key);
-
-cairo_private void *
_cairo_hash_table_random_entry (cairo_hash_table_t *hash_table,
cairo_hash_predicate_func_t predicate);
diff --git a/src/cairo-hash.c b/src/cairo-hash.c
index c0c9f7d8..51303f5a 100644
--- a/src/cairo-hash.c
+++ b/src/cairo-hash.c
@@ -346,61 +346,6 @@ _cairo_hash_table_lookup (cairo_hash_table_t *hash_table,
}
/**
- * _cairo_hash_table_steal:
- * @hash_table: a hash table
- * @key: the key of interest
- *
- * Performs a lookup in @hash_table looking for an entry which has a
- * key that matches @key, (as determined by the keys_equal() function
- * passed to _cairo_hash_table_create) and removes that entry from the
- * hash table.
- *
- * Return value: the matching entry, of %NULL if no match was found.
- **/
-void *
-_cairo_hash_table_steal (cairo_hash_table_t *hash_table,
- cairo_hash_entry_t *key)
-{
- cairo_hash_entry_t *entry;
- unsigned long table_size, i, idx, step;
-
- table_size = hash_table->arrangement->size;
- idx = key->hash % table_size;
-
- entry = hash_table->entries[idx];
- if (ENTRY_IS_LIVE (entry)) {
- if (hash_table->keys_equal (key, entry)) {
- hash_table->entries[idx] = DEAD_ENTRY;
- hash_table->live_entries--;
- return entry;
- }
- } else if (ENTRY_IS_FREE (entry))
- return NULL;
-
- i = 1;
- step = key->hash % hash_table->arrangement->rehash;
- if (step == 0)
- step = 1;
- do {
- idx += step;
- if (idx >= table_size)
- idx -= table_size;
-
- entry = hash_table->entries[idx];
- if (ENTRY_IS_LIVE (entry)) {
- if (hash_table->keys_equal (key, entry)) {
- hash_table->entries[idx] = DEAD_ENTRY;
- hash_table->live_entries--;
- return entry;
- }
- } else if (ENTRY_IS_FREE (entry))
- return NULL;
- } while (++i < table_size);
-
- return NULL;
-}
-
-/**
* _cairo_hash_table_random_entry:
* @hash_table: a hash table
* @predicate: a predicate function.
diff --git a/src/cairo-hull.c b/src/cairo-hull.c
index a699a524..1fa919bf 100644
--- a/src/cairo-hull.c
+++ b/src/cairo-hull.c
@@ -198,6 +198,9 @@ _cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices)
cairo_hull_t *hull;
int num_hull = *num_vertices;
+ if (CAIRO_INJECT_FAULT ())
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
if (num_hull > ARRAY_LENGTH (hull_stack)) {
hull = _cairo_malloc_ab (num_hull, sizeof (cairo_hull_t));
if (unlikely (hull == NULL))
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index e9e544dc..cf233934 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -569,7 +569,7 @@ cairo_image_surface_get_format (cairo_surface_t *surface)
if (! _cairo_surface_is_image (surface)) {
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
- return 0;
+ return CAIRO_FORMAT_INVALID;
}
return image_surface->format;
@@ -784,6 +784,7 @@ _cairo_image_surface_release_dest_image (void *abstract_surfa
static cairo_status_t
_cairo_image_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
+ cairo_content_t content,
int src_x,
int src_y,
int width,
@@ -962,6 +963,7 @@ _cairo_image_surface_composite (cairo_operator_t op,
status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern,
&dst->base,
+ CAIRO_CONTENT_COLOR_ALPHA,
src_x, src_y,
mask_x, mask_y,
width, height,
@@ -1044,6 +1046,9 @@ _cairo_image_surface_fill_rectangles (void *abstract_surface,
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
+ if (CAIRO_INJECT_FAULT ())
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
pixman_color.red = color->red_short;
pixman_color.green = color->green_short;
pixman_color.blue = color->blue_short;
@@ -1112,6 +1117,9 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
if (height == 0 || width == 0)
return CAIRO_STATUS_SUCCESS;
+ if (CAIRO_INJECT_FAULT ())
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
/* Convert traps to pixman traps */
if (num_traps > ARRAY_LENGTH (stack_traps)) {
pixman_traps = _cairo_malloc_ab (num_traps, sizeof (pixman_trapezoid_t));
@@ -1158,6 +1166,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
}
status = _cairo_pattern_acquire_surface (pattern, &dst->base,
+ CAIRO_CONTENT_COLOR_ALPHA,
src_x, src_y, width, height,
(cairo_surface_t **) &src,
&attributes);
@@ -1392,6 +1401,7 @@ _cairo_image_surface_create_span_renderer (cairo_operator_t op,
status = _cairo_pattern_acquire_surface (
renderer->pattern, &renderer->dst->base,
+ CAIRO_CONTENT_COLOR_ALPHA,
rects->src.x, rects->src.y,
width, height,
(cairo_surface_t **) &renderer->src,
@@ -1427,7 +1437,7 @@ _cairo_image_surface_set_clip_region (void *abstract_surface,
{
cairo_image_surface_t *surface = (cairo_image_surface_t *) abstract_surface;
- if (! pixman_image_set_clip_region32 (surface->pixman_image, &region->rgn))
+ if (! pixman_image_set_clip_region32 (surface->pixman_image, region? &region->rgn : NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
surface->has_clip = region != NULL;
@@ -1570,16 +1580,19 @@ _cairo_image_analyze_transparency (cairo_image_surface_t *image)
if (image->transparency != CAIRO_IMAGE_UNKNOWN)
return image->transparency;
- if (image->format == CAIRO_FORMAT_RGB24) {
- image->transparency = CAIRO_IMAGE_IS_OPAQUE;
- return CAIRO_IMAGE_IS_OPAQUE;
- }
+ if ((image->base.content & CAIRO_CONTENT_ALPHA) == 0)
+ return image->transparency = CAIRO_IMAGE_IS_OPAQUE;
- if (image->format != CAIRO_FORMAT_ARGB32) {
- image->transparency = CAIRO_IMAGE_HAS_ALPHA;
- return CAIRO_IMAGE_HAS_ALPHA;
+ if ((image->base.content & CAIRO_CONTENT_COLOR) == 0) {
+ if (image->format == CAIRO_FORMAT_A1)
+ return image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
+ else
+ return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
}
+ if (image->format != CAIRO_FORMAT_ARGB32)
+ return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
+
image->transparency = CAIRO_IMAGE_IS_OPAQUE;
for (y = 0; y < image->height; y++) {
uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
@@ -1587,8 +1600,7 @@ _cairo_image_analyze_transparency (cairo_image_surface_t *image)
for (x = 0; x < image->width; x++, pixel++) {
int a = (*pixel & 0xff000000) >> 24;
if (a > 0 && a < 255) {
- image->transparency = CAIRO_IMAGE_HAS_ALPHA;
- return CAIRO_IMAGE_HAS_ALPHA;
+ return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
} else if (a == 0) {
image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
}
diff --git a/src/cairo-malloc-private.h b/src/cairo-malloc-private.h
index f8094f91..d812058f 100644
--- a/src/cairo-malloc-private.h
+++ b/src/cairo-malloc-private.h
@@ -39,6 +39,13 @@
#include "cairo-wideint-private.h"
+#if HAVE_MEMFAULT
+#include <memfault.h>
+#define CAIRO_INJECT_FAULT() MEMFAULT_INJECT_FAULT()
+#else
+#define CAIRO_INJECT_FAULT() 0
+#endif
+
/**
* _cairo_malloc:
* @size: size in bytes
diff --git a/src/cairo-misc.c b/src/cairo-misc.c
index 2ed14139..20f0ef1b 100644
--- a/src/cairo-misc.c
+++ b/src/cairo-misc.c
@@ -123,9 +123,12 @@ cairo_status_to_string (cairo_status_t status)
return "invalid value for an input #cairo_font_weight_t";
case CAIRO_STATUS_INVALID_SIZE:
return "invalid value for the size of the input (surface, pattern, etc.)";
+ case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
+ return "user-font method not implemented";
+ default:
+ case CAIRO_STATUS_LAST_STATUS:
+ return "<unknown error status>";
}
-
- return "<unknown error status>";
}
@@ -384,15 +387,6 @@ _cairo_operator_bounded_by_source (cairo_operator_t op)
}
-void
-_cairo_restrict_value (double *value, double min, double max)
-{
- if (*value < min)
- *value = min;
- else if (*value > max)
- *value = max;
-}
-
/* This function is identical to the C99 function lround(), except that it
* performs arithmetic rounding (floor(d + .5) instead of away-from-zero rounding) and
* has a valid input range of (INT_MIN, INT_MAX] instead of
@@ -619,10 +613,12 @@ _cairo_lround (double d)
#include <windows.h>
#include <io.h>
+#if !_WIN32_WCE
/* tmpfile() replacement for Windows.
*
* On Windows tmpfile() creates the file in the root directory. This
- * may fail due to unsufficient privileges.
+ * may fail due to unsufficient privileges. However, this isn't a
+ * problem on Windows CE so we don't use it there.
*/
FILE *
_cairo_win32_tmpfile (void)
@@ -667,6 +663,7 @@ _cairo_win32_tmpfile (void)
return fp;
}
+#endif /* !_WIN32_WCE */
#endif /* _WIN32 */
@@ -709,6 +706,9 @@ _cairo_intern_string (const char **str_inout, int len)
cairo_intern_string_t tmpl, *istring;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ if (CAIRO_INJECT_FAULT ())
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
if (len < 0)
len = strlen (str);
tmpl.hash_entry.hash = _intern_string_hash (str, len);
diff --git a/src/cairo-os2-surface.c b/src/cairo-os2-surface.c
index fa678bd2..82bab3be 100644
--- a/src/cairo-os2-surface.c
+++ b/src/cairo-os2-surface.c
@@ -39,7 +39,9 @@
#include "cairo-os2-private.h"
+#if CAIRO_HAS_FC_FONT
#include <fontconfig/fontconfig.h>
+#endif
#include <float.h>
#ifdef BUILD_CAIRO_DLL
@@ -101,7 +103,7 @@ cairo_os2_init (void)
DisableFPUException ();
-#if CAIRO_HAS_FT_FONT
+#if CAIRO_HAS_FC_FONT
/* Initialize FontConfig */
FcInit ();
#endif
@@ -132,7 +134,7 @@ cairo_os2_fini (void)
cairo_debug_reset_static_data ();
-#if CAIRO_HAS_FT_FONT
+#if CAIRO_HAS_FC_FONT
# if HAVE_FCFINI
/* Uninitialize FontConfig */
FcFini ();
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index 5d4e08fa..b84fbffe 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -244,7 +244,7 @@ _cairo_paginated_surface_release_source_image (void *abstract_surface,
static cairo_int_status_t
_paint_fallback_image (cairo_paginated_surface_t *surface,
- cairo_box_int_t *box)
+ cairo_rectangle_int_t *rect)
{
double x_scale = surface->base.x_fallback_resolution / surface->target->x_resolution;
double y_scale = surface->base.y_fallback_resolution / surface->target->y_resolution;
@@ -254,10 +254,10 @@ _paint_fallback_image (cairo_paginated_surface_t *surface,
cairo_surface_t *image;
cairo_surface_pattern_t pattern;
- x = box->p1.x;
- y = box->p1.y;
- width = box->p2.x - x;
- height = box->p2.y - y;
+ x = rect->x;
+ y = rect->y;
+ width = rect->width;
+ height = rect->height;
image = _cairo_paginated_surface_create_image_surface (surface,
ceil (width * x_scale),
ceil (height * y_scale));
@@ -365,24 +365,23 @@ _paint_page (cairo_paginated_surface_t *surface)
}
if (has_page_fallback) {
- cairo_box_int_t box;
+ cairo_rectangle_int_t rect;
surface->backend->set_paginated_mode (surface->target,
CAIRO_PAGINATED_MODE_FALLBACK);
- box.p1.x = 0;
- box.p1.y = 0;
- box.p2.x = surface->width;
- box.p2.y = surface->height;
- status = _paint_fallback_image (surface, &box);
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = surface->width;
+ rect.height = surface->height;
+ status = _paint_fallback_image (surface, &rect);
if (unlikely (status))
goto FAIL;
}
if (has_finegrained_fallback) {
cairo_region_t *region;
- cairo_box_int_t *boxes;
- int num_boxes, i;
+ int num_rects, i;
surface->backend->set_paginated_mode (surface->target,
CAIRO_PAGINATED_MODE_FALLBACK);
@@ -398,19 +397,17 @@ _paint_page (cairo_paginated_surface_t *surface)
region = _cairo_analysis_surface_get_unsupported (analysis);
- num_boxes = 0;
- status = _cairo_region_get_boxes (region, &num_boxes, &boxes);
- if (unlikely (status))
- goto FAIL;
+ num_rects = cairo_region_num_rectangles (region);
+ for (i = 0; i < num_rects; i++) {
+ cairo_rectangle_int_t rect;
- for (i = 0; i < num_boxes; i++) {
- status = _paint_fallback_image (surface, &boxes[i]);
- if (unlikely (status)) {
- _cairo_region_boxes_fini (region, boxes);
+ cairo_region_get_rectangle (region, i, &rect);
+
+ status = _paint_fallback_image (surface, &rect);
+
+ if (unlikely (status))
goto FAIL;
- }
}
- _cairo_region_boxes_fini (region, boxes);
}
FAIL:
diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index 41096f12..a90c317d 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -1240,7 +1240,7 @@ _cprt_move_to (void *closure,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
-/**
+/*
* Check whether the given path is representable as a region.
* That is, if the path contains only axis aligned lines between
* integer coordinates in device space.
diff --git a/src/cairo-path-in-fill.c b/src/cairo-path-in-fill.c
index 431f005b..24f43ca5 100644
--- a/src/cairo-path-in-fill.c
+++ b/src/cairo-path-in-fill.c
@@ -41,6 +41,7 @@ typedef struct cairo_in_fill {
int winding;
cairo_fixed_t x, y;
+ cairo_bool_t on_edge;
cairo_bool_t has_current_point;
cairo_point_t current_point;
@@ -58,6 +59,7 @@ _cairo_in_fill_init (cairo_in_fill_t *in_fill,
in_fill->x = _cairo_fixed_from_double (x);
in_fill->y = _cairo_fixed_from_double (y);
+ in_fill->on_edge = FALSE;
in_fill->has_current_point = FALSE;
in_fill->current_point.x = 0;
@@ -103,6 +105,9 @@ _cairo_in_fill_add_edge (cairo_in_fill_t *in_fill,
{
int dir;
+ if (in_fill->on_edge)
+ return;
+
/* count the number of edge crossing to -∞ */
dir = 1;
@@ -116,6 +121,18 @@ _cairo_in_fill_add_edge (cairo_in_fill_t *in_fill,
dir = -1;
}
+ /* First check whether the query is on an edge */
+ if ((p1->x == in_fill->x && p1->y == in_fill->y) ||
+ (p2->x == in_fill->x && p2->y == in_fill->y) ||
+ (! (p2->y < in_fill->y || p1->y > in_fill->y ||
+ (p1->x > in_fill->x && p2->x > in_fill->x) ||
+ (p1->x < in_fill->x && p2->x < in_fill->x)) &&
+ edge_compare_for_y_against_x (p1, p2, in_fill->y, in_fill->x) == 0))
+ {
+ in_fill->on_edge = TRUE;
+ return;
+ }
+
/* edge is entirely above or below, note the shortening rule */
if (p2->y <= in_fill->y || p1->y > in_fill->y)
return;
@@ -184,15 +201,19 @@ _cairo_in_fill_curve_to (void *closure,
if (c->y > bot) bot = c->y;
if (d->y < top) top = d->y;
if (d->y > bot) bot = d->y;
- if (bot < in_fill->y || top > in_fill->y)
+ if (bot < in_fill->y || top > in_fill->y) {
+ in_fill->current_point = *d;
return CAIRO_STATUS_SUCCESS;
+ }
left = in_fill->current_point.x;
if (b->x < left) left = b->x;
if (c->x < left) left = c->x;
if (d->x < left) left = d->x;
- if (left > in_fill->x)
+ if (left > in_fill->x) {
+ in_fill->current_point = *d;
return CAIRO_STATUS_SUCCESS;
+ }
/* XXX Investigate direct inspection of the inflections? */
if (! _cairo_spline_init (&spline,
@@ -244,7 +265,11 @@ _cairo_path_fixed_in_fill (cairo_path_fixed_t *path,
&in_fill);
assert (status == CAIRO_STATUS_SUCCESS);
- switch (fill_rule) {
+ _cairo_in_fill_close_path (&in_fill);
+
+ if (in_fill.on_edge) {
+ *is_inside = TRUE;
+ } else switch (fill_rule) {
case CAIRO_FILL_RULE_EVEN_ODD:
*is_inside = in_fill.winding & 1;
break;
diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index d6e5790c..79bf09b0 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -35,6 +35,7 @@
* Carl D. Worth <cworth@cworth.org>
*/
+#define _BSD_SOURCE /* for hypot() */
#include "cairoint.h"
#include "cairo-path-fixed-private.h"
@@ -1278,6 +1279,8 @@ _cairo_rectilinear_stroker_add_segment (cairo_rectilinear_stroker_t *stroker,
cairo_bool_t is_horizontal,
cairo_bool_t has_join)
{
+ if (CAIRO_INJECT_FAULT ())
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
if (stroker->num_segments == stroker->segments_size) {
int new_size = stroker->segments_size * 2;
diff --git a/src/cairo-path.c b/src/cairo-path.c
index 6572da9c..05445054 100644
--- a/src/cairo-path.c
+++ b/src/cairo-path.c
@@ -36,6 +36,7 @@
#include "cairoint.h"
+#include "cairo-private.h"
#include "cairo-path-private.h"
#include "cairo-path-fixed-private.h"
@@ -441,43 +442,82 @@ cairo_status_t
_cairo_path_append_to_context (const cairo_path_t *path,
cairo_t *cr)
{
- int i;
- cairo_path_data_t *p;
+ const cairo_path_data_t *p, *end;
+ cairo_fixed_t x1_fixed, y1_fixed;
+ cairo_fixed_t x2_fixed, y2_fixed;
+ cairo_fixed_t x3_fixed, y3_fixed;
+ cairo_matrix_t user_to_backend;
cairo_status_t status;
+ double x, y;
+
+ user_to_backend = cr->gstate->ctm;
+ cairo_matrix_multiply (&user_to_backend,
+ &user_to_backend,
+ &cr->gstate->target->device_transform);
- for (i=0; i < path->num_data; i += path->data[i].header.length) {
- p = &path->data[i];
+ end = &path->data[path->num_data];
+ for (p = &path->data[0]; p < end; p += p->header.length) {
switch (p->header.type) {
case CAIRO_PATH_MOVE_TO:
- if (p->header.length < 2)
+ if (unlikely (p->header.length < 2))
return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
- cairo_move_to (cr,
- p[1].point.x, p[1].point.y);
+
+ x = p[1].point.x, y = p[1].point.y;
+ cairo_matrix_transform_point (&user_to_backend, &x, &y);
+ x1_fixed = _cairo_fixed_from_double (x);
+ y1_fixed = _cairo_fixed_from_double (y);
+
+ status = _cairo_path_fixed_move_to (cr->path, x1_fixed, y1_fixed);
break;
+
case CAIRO_PATH_LINE_TO:
- if (p->header.length < 2)
+ if (unlikely (p->header.length < 2))
return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
- cairo_line_to (cr,
- p[1].point.x, p[1].point.y);
+
+ x = p[1].point.x, y = p[1].point.y;
+ cairo_matrix_transform_point (&user_to_backend, &x, &y);
+ x1_fixed = _cairo_fixed_from_double (x);
+ y1_fixed = _cairo_fixed_from_double (y);
+
+ status = _cairo_path_fixed_line_to (cr->path, x1_fixed, y1_fixed);
break;
+
case CAIRO_PATH_CURVE_TO:
- if (p->header.length < 4)
+ if (unlikely (p->header.length < 4))
return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
- cairo_curve_to (cr,
- p[1].point.x, p[1].point.y,
- p[2].point.x, p[2].point.y,
- p[3].point.x, p[3].point.y);
+
+ x = p[1].point.x, y = p[1].point.y;
+ cairo_matrix_transform_point (&user_to_backend, &x, &y);
+ x1_fixed = _cairo_fixed_from_double (x);
+ y1_fixed = _cairo_fixed_from_double (y);
+
+ x = p[2].point.x, y = p[2].point.y;
+ cairo_matrix_transform_point (&user_to_backend, &x, &y);
+ x2_fixed = _cairo_fixed_from_double (x);
+ y2_fixed = _cairo_fixed_from_double (y);
+
+ x = p[3].point.x, y = p[3].point.y;
+ cairo_matrix_transform_point (&user_to_backend, &x, &y);
+ x3_fixed = _cairo_fixed_from_double (x);
+ y3_fixed = _cairo_fixed_from_double (y);
+
+ status = _cairo_path_fixed_curve_to (cr->path,
+ x1_fixed, y1_fixed,
+ x2_fixed, y2_fixed,
+ x3_fixed, y3_fixed);
break;
+
case CAIRO_PATH_CLOSE_PATH:
- if (p->header.length < 1)
+ if (unlikely (p->header.length < 1))
return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
- cairo_close_path (cr);
+
+ status = _cairo_path_fixed_close_path (cr->path);
break;
+
default:
return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
}
- status = cairo_status (cr);
if (unlikely (status))
return status;
}
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 9f367b5e..654989f8 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -119,6 +119,9 @@ static cairo_status_t
_cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
const cairo_gradient_pattern_t *other)
{
+ if (CAIRO_INJECT_FAULT ())
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
if (other->base.type == CAIRO_PATTERN_TYPE_LINEAR)
{
cairo_linear_pattern_t *dst = (cairo_linear_pattern_t *) pattern;
@@ -250,9 +253,10 @@ _cairo_pattern_fini (cairo_pattern_t *pattern)
}
cairo_status_t
-_cairo_pattern_create_copy (cairo_pattern_t **pattern,
+_cairo_pattern_create_copy (cairo_pattern_t **pattern_out,
const cairo_pattern_t *other)
{
+ cairo_pattern_t *pattern;
cairo_status_t status;
if (other->status)
@@ -260,29 +264,32 @@ _cairo_pattern_create_copy (cairo_pattern_t **pattern,
switch (other->type) {
case CAIRO_PATTERN_TYPE_SOLID:
- *pattern = malloc (sizeof (cairo_solid_pattern_t));
+ pattern = malloc (sizeof (cairo_solid_pattern_t));
break;
case CAIRO_PATTERN_TYPE_SURFACE:
- *pattern = malloc (sizeof (cairo_surface_pattern_t));
+ pattern = malloc (sizeof (cairo_surface_pattern_t));
break;
case CAIRO_PATTERN_TYPE_LINEAR:
- *pattern = malloc (sizeof (cairo_linear_pattern_t));
+ pattern = malloc (sizeof (cairo_linear_pattern_t));
break;
case CAIRO_PATTERN_TYPE_RADIAL:
- *pattern = malloc (sizeof (cairo_radial_pattern_t));
+ pattern = malloc (sizeof (cairo_radial_pattern_t));
break;
+ default:
+ ASSERT_NOT_REACHED;
+ return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
}
- if (unlikely (*pattern == NULL))
+ if (unlikely (pattern == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- status = _cairo_pattern_init_copy (*pattern, other);
+ status = _cairo_pattern_init_copy (pattern, other);
if (unlikely (status)) {
- free (*pattern);
+ free (pattern);
return status;
}
- CAIRO_REFERENCE_COUNT_INIT (&(*pattern)->ref_count, 1);
-
+ CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
+ *pattern_out = pattern;
return CAIRO_STATUS_SUCCESS;
}
@@ -453,9 +460,9 @@ cairo_pattern_create_rgb (double red, double green, double blue)
{
cairo_color_t color;
- _cairo_restrict_value (&red, 0.0, 1.0);
- _cairo_restrict_value (&green, 0.0, 1.0);
- _cairo_restrict_value (&blue, 0.0, 1.0);
+ red = _cairo_restrict_value (red, 0.0, 1.0);
+ green = _cairo_restrict_value (green, 0.0, 1.0);
+ blue = _cairo_restrict_value (blue, 0.0, 1.0);
_cairo_color_init_rgb (&color, red, green, blue);
@@ -492,10 +499,10 @@ cairo_pattern_create_rgba (double red, double green, double blue,
{
cairo_color_t color;
- _cairo_restrict_value (&red, 0.0, 1.0);
- _cairo_restrict_value (&green, 0.0, 1.0);
- _cairo_restrict_value (&blue, 0.0, 1.0);
- _cairo_restrict_value (&alpha, 0.0, 1.0);
+ red = _cairo_restrict_value (red, 0.0, 1.0);
+ green = _cairo_restrict_value (green, 0.0, 1.0);
+ blue = _cairo_restrict_value (blue, 0.0, 1.0);
+ alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
_cairo_color_init_rgba (&color, red, green, blue, alpha);
@@ -837,6 +844,9 @@ _cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
return CAIRO_STATUS_SUCCESS;
}
+ if (CAIRO_INJECT_FAULT ())
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
assert (pattern->n_stops <= pattern->stops_size);
if (pattern->stops == pattern->stops_embedded) {
@@ -949,10 +959,10 @@ cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
return;
}
- _cairo_restrict_value (&offset, 0.0, 1.0);
- _cairo_restrict_value (&red, 0.0, 1.0);
- _cairo_restrict_value (&green, 0.0, 1.0);
- _cairo_restrict_value (&blue, 0.0, 1.0);
+ offset = _cairo_restrict_value (offset, 0.0, 1.0);
+ red = _cairo_restrict_value (red, 0.0, 1.0);
+ green = _cairo_restrict_value (green, 0.0, 1.0);
+ blue = _cairo_restrict_value (blue, 0.0, 1.0);
_cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
offset, red, green, blue, 1.0);
@@ -1003,11 +1013,11 @@ cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
return;
}
- _cairo_restrict_value (&offset, 0.0, 1.0);
- _cairo_restrict_value (&red, 0.0, 1.0);
- _cairo_restrict_value (&green, 0.0, 1.0);
- _cairo_restrict_value (&blue, 0.0, 1.0);
- _cairo_restrict_value (&alpha, 0.0, 1.0);
+ offset = _cairo_restrict_value (offset, 0.0, 1.0);
+ red = _cairo_restrict_value (red, 0.0, 1.0);
+ green = _cairo_restrict_value (green, 0.0, 1.0);
+ blue = _cairo_restrict_value (blue, 0.0, 1.0);
+ alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
_cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
offset, red, green, blue, alpha);
@@ -1246,6 +1256,7 @@ _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pat
pixman_transform_t pixman_transform;
cairo_status_t status;
cairo_bool_t repeat = FALSE;
+ cairo_bool_t opaque = TRUE;
pixman_gradient_stop_t pixman_stops_static[2];
pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
@@ -1253,6 +1264,9 @@ _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pat
int clone_offset_x, clone_offset_y;
cairo_matrix_t matrix = pattern->base.matrix;
+ if (CAIRO_INJECT_FAULT ())
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
pixman_stops = _cairo_malloc_ab (pattern->n_stops,
sizeof(pixman_gradient_stop_t));
@@ -1266,6 +1280,8 @@ _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pat
pixman_stops[i].color.green = pattern->stops[i].color.green_short;
pixman_stops[i].color.blue = pattern->stops[i].color.blue_short;
pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
+ if (! CAIRO_ALPHA_SHORT_IS_OPAQUE (pixman_stops[i].color.alpha))
+ opaque = FALSE;
}
if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR)
@@ -1436,7 +1452,12 @@ _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pat
pixman_image_unref (pixman_image);
+ _cairo_debug_check_image_surface_is_defined (&image->base);
+
status = _cairo_surface_clone_similar (dst, &image->base,
+ opaque ?
+ CAIRO_CONTENT_COLOR :
+ CAIRO_CONTENT_COLOR_ALPHA,
0, 0, width, height,
&clone_offset_x,
&clone_offset_y,
@@ -1768,6 +1789,7 @@ _pixman_nearest_sample (double d)
static cairo_int_status_t
_cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t *pattern,
cairo_surface_t *dst,
+ cairo_content_t content,
int x,
int y,
unsigned int width,
@@ -1842,7 +1864,7 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t *pat
if (unlikely (status))
goto BAIL;
- status = _cairo_surface_clone_similar (dst, surface,
+ status = _cairo_surface_clone_similar (dst, surface, content,
extents.x, extents.y,
extents.width, extents.height,
&extents.x, &extents.y, &src);
@@ -1950,13 +1972,28 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t *pat
/* Never acquire a larger area than the source itself */
is_empty = _cairo_rectangle_intersect (&extents, &sampled_area);
} else {
+ int trim = 0;
+
if (sampled_area.x >= extents.x &&
- sampled_area.y >= extents.y &&
- sampled_area.x + (int) sampled_area.width <= extents.x + (int) extents.width &&
+ sampled_area.x + (int) sampled_area.width <= extents.x + (int) extents.width)
+ {
+ /* source is horizontally contained within extents, trim */
+ extents.x = sampled_area.x;
+ extents.width = sampled_area.width;
+ trim |= 0x1;
+ }
+
+ if (sampled_area.y >= extents.y &&
sampled_area.y + (int) sampled_area.height <= extents.y + (int) extents.height)
{
+ /* source is vertically contained within extents, trim */
+ extents.y = sampled_area.y;
+ extents.height = sampled_area.height;
+ trim |= 0x2;
+ }
+
+ if (trim == 0x3) {
/* source is wholly contained within extents, drop the REPEAT */
- extents = sampled_area;
attr->extend = CAIRO_EXTEND_NONE;
}
@@ -1965,7 +2002,7 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t *pat
/* XXX can we use is_empty? */
- status = _cairo_surface_clone_similar (dst, surface,
+ status = _cairo_surface_clone_similar (dst, surface, content,
extents.x, extents.y,
extents.width, extents.height,
&x, &y, out);
@@ -2039,6 +2076,7 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t *pat
cairo_int_status_t
_cairo_pattern_acquire_surface (const cairo_pattern_t *pattern,
cairo_surface_t *dst,
+ cairo_content_t content,
int x,
int y,
unsigned int width,
@@ -2131,6 +2169,7 @@ _cairo_pattern_acquire_surface (const cairo_pattern_t *pattern,
cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) pattern;
status = _cairo_pattern_acquire_surface_for_surface (src, dst,
+ content,
x, y, width, height,
surface_out,
attributes);
@@ -2163,6 +2202,7 @@ cairo_int_status_t
_cairo_pattern_acquire_surfaces (const cairo_pattern_t *src,
const cairo_pattern_t *mask,
cairo_surface_t *dst,
+ cairo_content_t src_content,
int src_x,
int src_y,
int mask_x,
@@ -2199,13 +2239,14 @@ _cairo_pattern_acquire_surfaces (const cairo_pattern_t *src,
_cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
_cairo_pattern_init_solid (&src_tmp.solid, &combined,
- src_solid->content | mask_solid->content);
+ (src_solid->content | mask_solid->content) & src_content);
src = &src_tmp.base;
mask = NULL;
}
status = _cairo_pattern_acquire_surface (src, dst,
+ src_content,
src_x, src_y,
width, height,
src_out, src_attributes);
@@ -2218,6 +2259,7 @@ _cairo_pattern_acquire_surfaces (const cairo_pattern_t *src,
}
status = _cairo_pattern_acquire_surface (mask, dst,
+ CAIRO_CONTENT_ALPHA,
mask_x, mask_y,
width, height,
mask_out, mask_attributes);
@@ -2597,6 +2639,9 @@ cairo_pattern_get_rgba (cairo_pattern_t *pattern,
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
double r0, g0, b0, a0;
+ if (pattern->status)
+ return pattern->status;
+
if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
@@ -2635,6 +2680,9 @@ cairo_pattern_get_surface (cairo_pattern_t *pattern,
{
cairo_surface_pattern_t *spat = (cairo_surface_pattern_t*) pattern;
+ if (pattern->status)
+ return pattern->status;
+
if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
@@ -2673,6 +2721,9 @@ cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
{
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
+ if (pattern->status)
+ return pattern->status;
+
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
@@ -2714,6 +2765,9 @@ cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
{
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
+ if (pattern->status)
+ return pattern->status;
+
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
@@ -2747,6 +2801,9 @@ cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
{
cairo_linear_pattern_t *linear = (cairo_linear_pattern_t*) pattern;
+ if (pattern->status)
+ return pattern->status;
+
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR)
return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
@@ -2788,6 +2845,9 @@ cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
{
cairo_radial_pattern_t *radial = (cairo_radial_pattern_t*) pattern;
+ if (pattern->status)
+ return pattern->status;
+
if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index a9012744..b1458d8e 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1015,18 +1015,21 @@ _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
static cairo_status_t
_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_status_t status;
long length;
if (! surface->pdf_stream.active)
return CAIRO_STATUS_SUCCESS;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
- if (unlikely (status))
- return status;
if (surface->pdf_stream.compressed) {
- status = _cairo_output_stream_destroy (surface->output);
+ cairo_status_t status2;
+
+ status2 = _cairo_output_stream_destroy (surface->output);
+ if (likely (status == CAIRO_STATUS_SUCCESS))
+ status = status2;
+
surface->output = surface->pdf_stream.old_output;
_cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
surface->pdf_stream.old_output = NULL;
@@ -1051,7 +1054,7 @@ _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
surface->pdf_stream.active = FALSE;
- if (status == CAIRO_STATUS_SUCCESS)
+ if (likely (status == CAIRO_STATUS_SUCCESS))
status = _cairo_output_stream_get_status (surface->output);
return status;
@@ -1324,10 +1327,12 @@ _cairo_pdf_surface_finish (void *abstract_surface)
"%%%%EOF\n",
offset);
- status2 = _cairo_pdf_operators_fini (&surface->pdf_operators);
/* pdf_operators has already been flushed when the last stream was
- * closed so we should never be writing anything here. */
- assert(status2 == CAIRO_STATUS_SUCCESS);
+ * closed so we should never be writing anything here - however,
+ * the stream may itself be in an error state. */
+ status2 = _cairo_pdf_operators_fini (&surface->pdf_operators);
+ if (status == CAIRO_STATUS_SUCCESS)
+ status = status2;
/* close any active streams still open due to fatal errors */
status2 = _cairo_pdf_surface_close_stream (surface);
@@ -1543,7 +1548,7 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
int i, x, y;
cairo_pdf_resource_t smask = {0}; /* squelch bogus compiler warning */
cairo_bool_t need_smask;
- const char *interpolate;
+ const char *interpolate = "true";
/* These are the only image formats we currently support, (which
* makes things a lot simpler here). This is enforced through
@@ -1723,6 +1728,8 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
&mime_data, &mime_data_length);
+ if (unlikely (source->status))
+ return source->status;
if (mime_data == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1790,7 +1797,7 @@ _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface,
status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
if (unlikely (status))
- goto BAIL;
+ return status;
pad_image = &image->base;
if (cairo_pattern_get_extend (&pattern->base) == CAIRO_EXTEND_PAD) {
@@ -1840,10 +1847,10 @@ _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface,
*origin_x = x;
*origin_y = y;
+BAIL:
if (pad_image != &image->base)
cairo_surface_destroy (pad_image);
-BAIL:
_cairo_surface_release_source_image (pattern->surface, image, image_extra);
return status;
@@ -3927,6 +3934,11 @@ _cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_su
null_stream,
_cairo_pdf_emit_imagemask,
surface->font_subsets);
+ if (unlikely (type3_surface->status)) {
+ status2 = _cairo_output_stream_destroy (null_stream);
+ return type3_surface->status;
+ }
+
_cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
_cairo_pdf_surface_add_font,
surface);
@@ -3983,6 +3995,12 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
NULL,
_cairo_pdf_emit_imagemask,
surface->font_subsets);
+ if (unlikely (type3_surface->status)) {
+ free (glyphs);
+ free (widths);
+ return type3_surface->status;
+ }
+
_cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
_cairo_pdf_surface_add_font,
surface);
diff --git a/src/cairo-pen.c b/src/cairo-pen.c
index 9d5e8959..eb66b1a0 100644
--- a/src/cairo-pen.c
+++ b/src/cairo-pen.c
@@ -55,6 +55,9 @@ _cairo_pen_init (cairo_pen_t *pen,
int i;
int reflect;
+ if (CAIRO_INJECT_FAULT ())
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
pen->radius = radius;
pen->tolerance = tolerance;
@@ -109,6 +112,9 @@ _cairo_pen_init_copy (cairo_pen_t *pen, const cairo_pen_t *other)
{
*pen = *other;
+ if (CAIRO_INJECT_FAULT ())
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
pen->vertices = pen->vertices_embedded;
if (pen->num_vertices) {
if (pen->num_vertices > ARRAY_LENGTH (pen->vertices_embedded)) {
@@ -132,6 +138,9 @@ _cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *point, int num_points)
int num_vertices;
int i;
+ if (CAIRO_INJECT_FAULT ())
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
num_vertices = pen->num_vertices + num_points;
if (num_vertices > ARRAY_LENGTH (pen->vertices_embedded) ||
pen->vertices != pen->vertices_embedded)
diff --git a/src/cairo-png.c b/src/cairo-png.c
index 6f4213f8..d4f04760 100644
--- a/src/cairo-png.c
+++ b/src/cairo-png.c
@@ -143,6 +143,7 @@ write_png (cairo_surface_t *surface,
int i;
cairo_status_t status;
cairo_image_surface_t *image;
+ cairo_image_surface_t * volatile clone;
void *image_extra;
png_struct *png;
png_info *info;
@@ -166,40 +167,52 @@ write_png (cairo_surface_t *surface,
goto BAIL1;
}
- rows = _cairo_malloc_ab (image->height, sizeof (png_byte*));
+ /* Handle the various fallback formats (e.g. low bit-depth XServers)
+ * by coercing them to a simpler format using pixman.
+ */
+ if (image->format == CAIRO_FORMAT_INVALID) {
+ clone = _cairo_image_surface_coerce (image,
+ _cairo_format_from_content (image->base.content));
+ status = clone->base.status;
+ if (unlikely (status))
+ goto BAIL1;
+ } else
+ clone = image;
+
+ rows = _cairo_malloc_ab (clone->height, sizeof (png_byte*));
if (unlikely (rows == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto BAIL1;
+ goto BAIL2;
}
- for (i = 0; i < image->height; i++)
- rows[i] = (png_byte *) image->data + i * image->stride;
+ for (i = 0; i < clone->height; i++)
+ rows[i] = (png_byte *) clone->data + i * clone->stride;
png = png_create_write_struct (PNG_LIBPNG_VER_STRING, &status,
png_simple_error_callback,
png_simple_warning_callback);
if (unlikely (png == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto BAIL2;
+ goto BAIL3;
}
info = png_create_info_struct (png);
if (unlikely (info == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto BAIL3;
+ goto BAIL4;
}
#ifdef PNG_SETJMP_SUPPORTED
if (setjmp (png_jmpbuf (png)))
- goto BAIL3;
+ goto BAIL4;
#endif
png_set_write_fn (png, closure, write_func, png_simple_output_flush_fn);
- switch (image->format) {
+ switch (clone->format) {
case CAIRO_FORMAT_ARGB32:
depth = 8;
- if (_cairo_image_analyze_transparency (image) == CAIRO_IMAGE_IS_OPAQUE)
+ if (_cairo_image_analyze_transparency (clone) == CAIRO_IMAGE_IS_OPAQUE)
png_color_type = PNG_COLOR_TYPE_RGB;
else
png_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
@@ -221,12 +234,12 @@ write_png (cairo_surface_t *surface,
break;
default:
status = _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
- goto BAIL3;
+ goto BAIL4;
}
png_set_IHDR (png, info,
- image->width,
- image->height, depth,
+ clone->width,
+ clone->height, depth,
png_color_type,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
@@ -259,10 +272,13 @@ write_png (cairo_surface_t *surface,
png_write_image (png, rows);
png_write_end (png, info);
-BAIL3:
+BAIL4:
png_destroy_write_struct (&png, &info);
-BAIL2:
+BAIL3:
free (rows);
+BAIL2:
+ if (clone != image)
+ cairo_surface_destroy (&clone->base);
BAIL1:
_cairo_surface_release_source_image (surface, image, image_extra);
@@ -638,6 +654,8 @@ read_png (struct png_read_closure_t *png_closure)
_cairo_image_surface_assume_ownership_of_data ((cairo_image_surface_t*)surface);
data = NULL;
+ _cairo_debug_check_image_surface_is_defined (surface);
+
status = _cairo_memory_stream_destroy (png_closure->png_data,
&mime_data,
&mime_data_length);
@@ -692,6 +710,10 @@ read_png (struct png_read_closure_t *png_closure)
* %CAIRO_STATUS_NO_MEMORY
* %CAIRO_STATUS_FILE_NOT_FOUND
* %CAIRO_STATUS_READ_ERROR
+ *
+ * Alternatively, you can allow errors to propagate through the drawing
+ * operations and check the status on the context upon completion
+ * using cairo_status().
**/
cairo_surface_t *
cairo_image_surface_create_from_png (const char *filename)
@@ -734,8 +756,17 @@ cairo_image_surface_create_from_png (const char *filename)
* via the @read_func function.
*
* Return value: a new #cairo_surface_t initialized with the contents
- * of the PNG file or %NULL if the data read is not a valid PNG image or
- * memory could not be allocated for the operation.
+ * of the PNG file or a "nil" surface if the data read is not a valid PNG image
+ * or memory could not be allocated for the operation. A nil
+ * surface can be checked for with cairo_surface_status(surface) which
+ * may return one of the following values:
+ *
+ * %CAIRO_STATUS_NO_MEMORY
+ * %CAIRO_STATUS_READ_ERROR
+ *
+ * Alternatively, you can allow errors to propagate through the drawing
+ * operations and check the status on the context upon completion
+ * using cairo_status().
**/
cairo_surface_t *
cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func,
diff --git a/src/cairo-polygon.c b/src/cairo-polygon.c
index 0b0fa991..d74d098d 100644
--- a/src/cairo-polygon.c
+++ b/src/cairo-polygon.c
@@ -64,6 +64,11 @@ _cairo_polygon_grow (cairo_polygon_t *polygon)
int old_size = polygon->edges_size;
int new_size = 4 * old_size;
+ if (CAIRO_INJECT_FAULT ()) {
+ polygon->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return FALSE;
+ }
+
if (polygon->edges == polygon->edges_embedded) {
new_edges = _cairo_malloc_ab (new_size, sizeof (cairo_edge_t));
if (new_edges != NULL)
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 169a539a..0037905a 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -505,6 +505,9 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
NULL,
_cairo_ps_emit_imagemask,
surface->font_subsets);
+ status = type3_surface->status;
+ if (unlikely (status))
+ return status;
for (i = 0; i < font_subset->num_glyphs; i++) {
if (font_subset->glyph_names != NULL) {
@@ -2135,6 +2138,8 @@ _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t *surface,
cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
&mime_data, &mime_data_length);
+ if (unlikely (source->status))
+ return source->status;
if (mime_data == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -3312,6 +3317,9 @@ _cairo_ps_surface_stroke (void *abstract_surface,
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
+ if (unlikely (status))
+ return status;
+
return _cairo_pdf_operators_stroke (&surface->pdf_operators,
path,
style,
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index c827f97a..982ede42 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1598,6 +1598,7 @@ _cairo_quartz_surface_create_similar (void *abstract_surface,
static cairo_status_t
_cairo_quartz_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
+ cairo_content_t content,
int src_x,
int src_y,
int width,
diff --git a/src/cairo-region-private.h b/src/cairo-region-private.h
deleted file mode 100644
index 588762e5..00000000
--- a/src/cairo-region-private.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/* -*- 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 Mozilla Corporation
- *
- * 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 Mozilla Corporation
- *
- * Contributor(s):
- * Vladimir Vukicevic <vladimir@pobox.com>
- */
-
-#ifndef CAIRO_REGION_PRIVATE_H
-#define CAIRO_REGION_PRIVATE_H
-
-#include "cairo-compiler-private.h"
-#include "cairo-types-private.h"
-
-#include <pixman.h>
-
-CAIRO_BEGIN_DECLS
-
-/* #cairo_region_t is defined in cairoint.h */
-
-struct _cairo_region {
- pixman_region32_t rgn;
-};
-
-cairo_private void
-_cairo_region_init (cairo_region_t *region);
-
-cairo_private void
-_cairo_region_init_rect (cairo_region_t *region,
- cairo_rectangle_int_t *rect);
-
-cairo_private cairo_int_status_t
-_cairo_region_init_boxes (cairo_region_t *region,
- cairo_box_int_t *boxes,
- int count);
-
-cairo_private void
-_cairo_region_fini (cairo_region_t *region);
-
-cairo_private cairo_int_status_t
-_cairo_region_copy (cairo_region_t *dst,
- cairo_region_t *src);
-
-cairo_private int
-_cairo_region_num_boxes (cairo_region_t *region);
-
-cairo_private cairo_int_status_t
-_cairo_region_get_boxes (cairo_region_t *region,
- int *num_boxes,
- cairo_box_int_t **boxes);
-
-cairo_private void
-_cairo_region_boxes_fini (cairo_region_t *region,
- cairo_box_int_t *boxes);
-
-cairo_private void
-_cairo_region_get_extents (cairo_region_t *region,
- cairo_rectangle_int_t *extents);
-
-cairo_private cairo_int_status_t
-_cairo_region_subtract (cairo_region_t *dst,
- cairo_region_t *a,
- cairo_region_t *b);
-
-cairo_private cairo_int_status_t
-_cairo_region_intersect (cairo_region_t *dst,
- cairo_region_t *a,
- cairo_region_t *b);
-
-cairo_private cairo_int_status_t
-_cairo_region_union_rect (cairo_region_t *dst,
- cairo_region_t *src,
- cairo_rectangle_int_t *rect);
-
-cairo_private cairo_bool_t
-_cairo_region_not_empty (cairo_region_t *region);
-
-cairo_private void
-_cairo_region_translate (cairo_region_t *region,
- int x, int y);
-
-cairo_private pixman_region_overlap_t
-_cairo_region_contains_rectangle (cairo_region_t *region,
- const cairo_rectangle_int_t *box);
-
-
-CAIRO_END_DECLS
-
-#endif /* CAIRO_REGION_PRIVATE_H */
diff --git a/src/cairo-region.c b/src/cairo-region.c
index 53a359b3..5d1f2c5f 100644
--- a/src/cairo-region.c
+++ b/src/cairo-region.c
@@ -33,190 +33,578 @@
* Contributor(s):
* Owen Taylor <otaylor@redhat.com>
* Vladimir Vukicevic <vladimir@pobox.com>
+ * Søren Sandmann <sandmann@daimi.au.dk>
*/
#include "cairoint.h"
+static const cairo_region_t _cairo_region_nil = {
+ CAIRO_STATUS_NO_MEMORY, /* status */
+};
+
+/**
+ * _cairo_region_set_error:
+ * @region: a region
+ * @status: a status value indicating an error
+ *
+ * Atomically sets region->status to @status and calls _cairo_error;
+ * Does nothing if status is %CAIRO_STATUS_SUCCESS or any of the internal
+ * status values.
+ *
+ * All assignments of an error status to region->status should happen
+ * through _cairo_region_set_error(). Note that due to the nature of
+ * the atomic operation, it is not safe to call this function on the
+ * nil objects.
+ *
+ * The purpose of this function is to allow the user to set a
+ * breakpoint in _cairo_error() to generate a stack trace for when the
+ * user causes cairo to detect an error.
+ *
+ * Return value: the error status.
+ **/
+static cairo_status_t
+_cairo_region_set_error (cairo_region_t *region,
+ cairo_status_t status)
+{
+ if (! _cairo_status_is_error (status))
+ return status;
+
+ /* Don't overwrite an existing error. This preserves the first
+ * error, which is the most significant. */
+ _cairo_status_set_error (&region->status, status);
+
+ return _cairo_error (status);
+}
+
void
_cairo_region_init (cairo_region_t *region)
{
+ region->status = CAIRO_STATUS_SUCCESS;
pixman_region32_init (&region->rgn);
}
void
-_cairo_region_init_rect (cairo_region_t *region,
- cairo_rectangle_int_t *rect)
+_cairo_region_init_rectangle (cairo_region_t *region,
+ const cairo_rectangle_int_t *rectangle)
{
+ region->status = CAIRO_STATUS_SUCCESS;
pixman_region32_init_rect (&region->rgn,
- rect->x, rect->y,
- rect->width, rect->height);
+ rectangle->x, rectangle->y,
+ rectangle->width, rectangle->height);
}
-cairo_int_status_t
-_cairo_region_init_boxes (cairo_region_t *region,
- cairo_box_int_t *boxes,
- int count)
+void
+_cairo_region_fini (cairo_region_t *region)
{
- pixman_box32_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box32_t)];
- pixman_box32_t *pboxes = stack_pboxes;
- cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
- int i;
+ pixman_region32_fini (&region->rgn);
+}
- if (count > ARRAY_LENGTH (stack_pboxes)) {
- pboxes = _cairo_malloc_ab (count, sizeof (pixman_box32_t));
- if (unlikely (pboxes == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
+/**
+ * cairo_region_create:
+ *
+ * Allocates a new empty region object.
+ *
+ * Return value: A newly allocated #cairo_region_t. Free with
+ * cairo_region_destroy(). This function always returns a
+ * valid pointer; if memory cannot be allocated, then a special
+ * error object is returned where all operations on the object do nothing.
+ * You can check for this with cairo_region_status().
+ *
+ * Since: 1.10
+ **/
+cairo_region_t *
+cairo_region_create (void)
+{
+ cairo_region_t *region;
- for (i = 0; i < count; i++) {
- pboxes[i].x1 = boxes[i].p1.x;
- pboxes[i].y1 = boxes[i].p1.y;
- pboxes[i].x2 = boxes[i].p2.x;
- pboxes[i].y2 = boxes[i].p2.y;
- }
+ region = _cairo_malloc (sizeof (cairo_region_t));
+ if (region == NULL)
+ return (cairo_region_t *) &_cairo_region_nil;
- if (! pixman_region32_init_rects (&region->rgn, pboxes, count))
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ region->status = CAIRO_STATUS_SUCCESS;
- if (pboxes != stack_pboxes)
- free (pboxes);
+ pixman_region32_init (&region->rgn);
- return status;
+ return region;
}
+slim_hidden_def (cairo_region_create);
-void
-_cairo_region_fini (cairo_region_t *region)
+/**
+ * cairo_region_create_rectangle:
+ * @rectangle: a #cairo_rectangle_int_t
+ *
+ * Allocates a new region object containing @rectangle.
+ *
+ * Return value: A newly allocated #cairo_region_t. Free with
+ * cairo_region_destroy(). This function always returns a
+ * valid pointer; if memory cannot be allocated, then a special
+ * error object is returned where all operations on the object do nothing.
+ * You can check for this with cairo_region_status().
+ *
+ * Since: 1.10
+ **/
+cairo_region_t *
+cairo_region_create_rectangle (const cairo_rectangle_int_t *rectangle)
{
- pixman_region32_fini (&region->rgn);
+ cairo_region_t *region;
+
+ region = _cairo_malloc (sizeof (cairo_region_t));
+ if (region == NULL)
+ return (cairo_region_t *) &_cairo_region_nil;
+
+ region->status = CAIRO_STATUS_SUCCESS;
+
+ pixman_region32_init_rect (&region->rgn,
+ rectangle->x, rectangle->y,
+ rectangle->width, rectangle->height);
+
+ return region;
}
+slim_hidden_def (cairo_region_create_rectangle);
-cairo_int_status_t
-_cairo_region_copy (cairo_region_t *dst, cairo_region_t *src)
+/**
+ * cairo_region_copy:
+ * @original: a #cairo_region_t
+ *
+ * Allocates a new region object copying the area from @original.
+ *
+ * Return value: A newly allocated #cairo_region_t. Free with
+ * cairo_region_destroy(). This function always returns a
+ * valid pointer; if memory cannot be allocated, then a special
+ * error object is returned where all operations on the object do nothing.
+ * You can check for this with cairo_region_status().
+ *
+ * Since: 1.10
+ **/
+cairo_region_t *
+cairo_region_copy (cairo_region_t *original)
{
- if (!pixman_region32_copy (&dst->rgn, &src->rgn))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ cairo_region_t *copy;
- return CAIRO_STATUS_SUCCESS;
+ if (original->status)
+ return (cairo_region_t *) &_cairo_region_nil;
+
+ copy = cairo_region_create ();
+ if (copy->status)
+ return copy;
+
+ if (! pixman_region32_copy (&copy->rgn, &original->rgn)) {
+ cairo_region_destroy (copy);
+ return (cairo_region_t *) &_cairo_region_nil;
+ }
+
+ return copy;
}
+slim_hidden_def (cairo_region_copy);
+
+/**
+ * cairo_region_destroy:
+ * @region: a #cairo_region_t
+ *
+ * Destroys a #cairo_region_t object created with
+ * cairo_region_create(), cairo_region_copy(), or
+ * or cairo_region_create_rectangle().
+ *
+ * Since: 1.10
+ **/
+void
+cairo_region_destroy (cairo_region_t *region)
+{
+ if (region == (cairo_region_t *) &_cairo_region_nil)
+ return;
+ pixman_region32_fini (&region->rgn);
+ free (region);
+}
+slim_hidden_def (cairo_region_destroy);
+
+/**
+ * cairo_region_num_rectangles:
+ * @region: a #cairo_region_t
+ *
+ * Returns the number of rectangles contained in @region.
+ *
+ * Return value: The number of rectangles contained in @region.
+ *
+ * Since: 1.10
+ **/
int
-_cairo_region_num_boxes (cairo_region_t *region)
+cairo_region_num_rectangles (cairo_region_t *region)
{
+ if (region->status)
+ return 0;
+
return pixman_region32_n_rects (&region->rgn);
}
+slim_hidden_def (cairo_region_num_rectangles);
-cairo_int_status_t
-_cairo_region_get_boxes (cairo_region_t *region, int *num_boxes, cairo_box_int_t **boxes)
+/**
+ * cairo_region_get_rectangle:
+ * @region: a #cairo_region_t
+ * @nth: a number indicating which rectangle should be returned
+ * @rectangle: return location for a #cairo_rectangle_int_t
+ *
+ * Stores the @nth rectangle from the region in @rectangle.
+ *
+ * Since: 1.10
+ **/
+void
+cairo_region_get_rectangle (cairo_region_t *region,
+ int nth,
+ cairo_rectangle_int_t *rectangle)
{
- int nboxes;
- pixman_box32_t *pboxes;
- cairo_box_int_t *cboxes;
- int i;
+ pixman_box32_t *pbox;
- pboxes = pixman_region32_rectangles (&region->rgn, &nboxes);
- if (nboxes == 0) {
- *num_boxes = 0;
- return CAIRO_STATUS_SUCCESS;
+ if (region->status) {
+ rectangle->x = rectangle->y = 0;
+ rectangle->width = rectangle->height = 0;
+ return;
}
- if (nboxes > *num_boxes) {
- cboxes = _cairo_malloc_ab (nboxes, sizeof (cairo_box_int_t));
- if (unlikely (cboxes == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- } else
- cboxes = *boxes;
-
- for (i = 0; i < nboxes; i++) {
- cboxes[i].p1.x = pboxes[i].x1;
- cboxes[i].p1.y = pboxes[i].y1;
- cboxes[i].p2.x = pboxes[i].x2;
- cboxes[i].p2.y = pboxes[i].y2;
- }
-
- *num_boxes = nboxes;
- *boxes = cboxes;
-
- return CAIRO_STATUS_SUCCESS;
-}
+ pbox = pixman_region32_rectangles (&region->rgn, NULL) + nth;
-void
-_cairo_region_boxes_fini (cairo_region_t *region, cairo_box_int_t *boxes)
-{
- free (boxes);
+ rectangle->x = pbox->x1;
+ rectangle->y = pbox->y1;
+ rectangle->width = pbox->x2 - pbox->x1;
+ rectangle->height = pbox->y2 - pbox->y1;
}
+slim_hidden_def (cairo_region_get_rectangle);
/**
- * _cairo_region_get_extents:
+ * cairo_region_get_extents:
* @region: a #cairo_region_t
- * @rect: rectangle into which to store the extents
+ * @rectangle: rectangle into which to store the extents
+ *
+ * Gets the bounding rectangle of @region as a #cairo_rectangle_int_t
*
- * Gets the bounding box of a region as a #cairo_rectangle_int_t
+ * Since: 1.10
**/
void
-_cairo_region_get_extents (cairo_region_t *region, cairo_rectangle_int_t *extents)
+cairo_region_get_extents (cairo_region_t *region,
+ cairo_rectangle_int_t *extents)
{
- pixman_box32_t *pextents = pixman_region32_extents (&region->rgn);
+ pixman_box32_t *pextents;
+
+ if (region->status) {
+ extents->x = extents->y = 0;
+ extents->width = extents->height = 0;
+ return;
+ }
+
+ pextents = pixman_region32_extents (&region->rgn);
extents->x = pextents->x1;
extents->y = pextents->y1;
extents->width = pextents->x2 - pextents->x1;
extents->height = pextents->y2 - pextents->y1;
}
+slim_hidden_def (cairo_region_get_extents);
-cairo_int_status_t
-_cairo_region_subtract (cairo_region_t *dst, cairo_region_t *a, cairo_region_t *b)
+/**
+ * cairo_region_status:
+ * @region: a #cairo_region_t
+ *
+ * Checks whether an error has previous occured for this
+ * region object.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
+ *
+ * Since: 1.10
+ **/
+cairo_status_t
+cairo_region_status (cairo_region_t *region)
{
- if (!pixman_region32_subtract (&dst->rgn, &a->rgn, &b->rgn))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return region->status;
+}
+slim_hidden_def (cairo_region_status);
+
+/**
+ * cairo_region_subtract:
+ * @dst: a #cairo_region_t
+ * @other: another #cairo_region_t
+ *
+ * Subtracts @other from @dst and places the result in @dst
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
+ *
+ * Since: 1.10
+ **/
+cairo_status_t
+cairo_region_subtract (cairo_region_t *dst, cairo_region_t *other)
+{
+ if (dst->status)
+ return dst->status;
+
+ if (other->status)
+ return _cairo_region_set_error (dst, other->status);
+
+ if (! pixman_region32_subtract (&dst->rgn, &dst->rgn, &other->rgn))
+ return _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
}
+slim_hidden_def (cairo_region_subtract);
-cairo_int_status_t
-_cairo_region_intersect (cairo_region_t *dst, cairo_region_t *a, cairo_region_t *b)
+/**
+ * cairo_region_subtract_rectangle:
+ * @dst: a #cairo_region_t
+ * @rectangle: a #cairo_rectangle_int_t
+ *
+ * Subtracts @rectangle from @dst and places the result in @dst
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
+ *
+ * Since: 1.10
+ **/
+cairo_status_t
+cairo_region_subtract_rectangle (cairo_region_t *dst,
+ const cairo_rectangle_int_t *rectangle)
+{
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ pixman_region32_t region;
+
+ if (dst->status)
+ return dst->status;
+
+ pixman_region32_init_rect (&region,
+ rectangle->x, rectangle->y,
+ rectangle->width, rectangle->height);
+
+ if (! pixman_region32_subtract (&dst->rgn, &dst->rgn, &region))
+ status = _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY);
+
+ pixman_region32_fini (&region);
+
+ return status;
+}
+slim_hidden_def (cairo_region_subtract_rectangle);
+
+/**
+ * cairo_region_intersect:
+ * @dst: a #cairo_region_t
+ * @other: another #cairo_region_t
+ *
+ * Computes the intersection of @dst with @other and places the result in @dst
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
+ *
+ * Since: 1.10
+ **/
+cairo_status_t
+cairo_region_intersect (cairo_region_t *dst, cairo_region_t *other)
{
- if (!pixman_region32_intersect (&dst->rgn, &a->rgn, &b->rgn))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (dst->status)
+ return dst->status;
+
+ if (other->status)
+ return _cairo_region_set_error (dst, other->status);
+
+ if (! pixman_region32_intersect (&dst->rgn, &dst->rgn, &other->rgn))
+ return _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
}
+slim_hidden_def (cairo_region_intersect);
+
+/**
+ * cairo_region_intersect_rectangle:
+ * @dst: a #cairo_region_t
+ * @rectangle: a #cairo_rectangle_int_t
+ *
+ * Computes the intersection of @dst with @rectangle and places the
+ * result in @dst
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
+ *
+ * Since: 1.10
+ **/
+cairo_status_t
+cairo_region_intersect_rectangle (cairo_region_t *dst,
+ const cairo_rectangle_int_t *rectangle)
+{
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ pixman_region32_t region;
-cairo_int_status_t
-_cairo_region_union_rect (cairo_region_t *dst,
- cairo_region_t *src,
- cairo_rectangle_int_t *rect)
+ if (dst->status)
+ return dst->status;
+
+ pixman_region32_init_rect (&region,
+ rectangle->x, rectangle->y,
+ rectangle->width, rectangle->height);
+
+ if (! pixman_region32_intersect (&dst->rgn, &dst->rgn, &region))
+ status = _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY);
+
+ pixman_region32_fini (&region);
+
+ return status;
+}
+slim_hidden_def (cairo_region_intersect_rectangle);
+
+/**
+ * cairo_region_union:
+ * @dst: a #cairo_region_t
+ * @other: another #cairo_region_t
+ *
+ * Computes the union of @dst with @other and places the result in @dst
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
+ *
+ * Since: 1.10
+ **/
+cairo_status_t
+cairo_region_union (cairo_region_t *dst,
+ cairo_region_t *other)
{
- if (!pixman_region32_union_rect (&dst->rgn, &src->rgn,
- rect->x, rect->y,
- rect->width, rect->height))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (dst->status)
+ return dst->status;
+
+ if (other->status)
+ return _cairo_region_set_error (dst, other->status);
+
+ if (! pixman_region32_union (&dst->rgn, &dst->rgn, &other->rgn))
+ return _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
}
+slim_hidden_def (cairo_region_union);
+
+/**
+ * cairo_region_union_rectangle:
+ * @dst: a #cairo_region_t
+ * @rectangle: a #cairo_rectangle_int_t
+ *
+ * Computes the union of @dst with @rectangle and places the result in @dst.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
+ *
+ * Since: 1.10
+ **/
+cairo_status_t
+cairo_region_union_rectangle (cairo_region_t *dst,
+ const cairo_rectangle_int_t *rectangle)
+{
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ pixman_region32_t region;
+
+ if (dst->status)
+ return dst->status;
+
+ pixman_region32_init_rect (&region,
+ rectangle->x, rectangle->y,
+ rectangle->width, rectangle->height);
+ if (! pixman_region32_union (&dst->rgn, &dst->rgn, &region))
+ status = _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY);
+
+ pixman_region32_fini (&region);
+
+ return status;
+}
+slim_hidden_def (cairo_region_union_rectangle);
+
+/**
+ * cairo_region_is_empty:
+ * @region: a #cairo_region_t
+ *
+ * Checks whether @region is empty.
+ *
+ * Return value: %TRUE if @region is empty, %FALSE if it isn't.
+ *
+ * Since: 1.10
+ **/
cairo_bool_t
-_cairo_region_not_empty (cairo_region_t *region)
+cairo_region_is_empty (cairo_region_t *region)
{
- return (cairo_bool_t) pixman_region32_not_empty (&region->rgn);
+ if (region->status)
+ return TRUE;
+
+ return ! pixman_region32_not_empty (&region->rgn);
}
+slim_hidden_def (cairo_region_is_empty);
+/**
+ * cairo_region_translate:
+ * @region: a #cairo_region_t
+ * @dx: Amount to translate in the x direction
+ * @dy: Amount to translate in the y direction
+ *
+ * Translates @region by (@dx, @dy).
+ *
+ * Since: 1.10
+ **/
void
-_cairo_region_translate (cairo_region_t *region,
- int x, int y)
+cairo_region_translate (cairo_region_t *region,
+ int dx, int dy)
{
- pixman_region32_translate (&region->rgn, x, y);
+ if (region->status)
+ return;
+
+ pixman_region32_translate (&region->rgn, dx, dy);
}
+slim_hidden_def (cairo_region_translate);
-pixman_region_overlap_t
-_cairo_region_contains_rectangle (cairo_region_t *region,
- const cairo_rectangle_int_t *rect)
+/**
+ * cairo_region_contains_rectangle:
+ * @region: a #cairo_region_t
+ * @rectangle: a #cairo_rectangle_int_t
+ *
+ * Checks whether @rectangle is inside, outside or partially contained
+ * in @region
+ *
+ * Return value:
+ * %CAIRO_REGION_OVERLAP_IN if @rectangle is entirely inside @region,
+ * %CAIRO_REGION_OVERLAP_OUT if @rectangle is entirely outside @region, or
+ * %CAIRO_REGION_OVERLAP_PART if @rectangle is partially inside and partially outside @region.
+ *
+ * Since: 1.10
+ **/
+cairo_region_overlap_t
+cairo_region_contains_rectangle (cairo_region_t *region,
+ const cairo_rectangle_int_t *rectangle)
{
pixman_box32_t pbox;
+ pixman_region_overlap_t poverlap;
+
+ if (region->status)
+ return CAIRO_REGION_OVERLAP_OUT;
+
+ pbox.x1 = rectangle->x;
+ pbox.y1 = rectangle->y;
+ pbox.x2 = rectangle->x + rectangle->width;
+ pbox.y2 = rectangle->y + rectangle->height;
+
+ poverlap = pixman_region32_contains_rectangle (&region->rgn, &pbox);
+ switch (poverlap) {
+ default:
+ case PIXMAN_REGION_OUT: return CAIRO_REGION_OVERLAP_OUT;
+ case PIXMAN_REGION_IN: return CAIRO_REGION_OVERLAP_IN;
+ case PIXMAN_REGION_PART: return CAIRO_REGION_OVERLAP_PART;
+ }
+}
+slim_hidden_def (cairo_region_contains_rectangle);
- pbox.x1 = rect->x;
- pbox.y1 = rect->y;
- pbox.x2 = rect->x + rect->width;
- pbox.y2 = rect->y + rect->height;
+/**
+ * cairo_region_contains_point:
+ * @region: a #cairo_region_t
+ * @x: the x coordinate of a point
+ * @y: the y coordinate of a point
+ *
+ * Checks whether (@x, @y) is contained in @region.
+ *
+ * Return value: %TRUE if (@x, @y) is contained in @region, %FALSE if it is not.
+ *
+ * Since: 1.10
+ **/
+cairo_bool_t
+cairo_region_contains_point (cairo_region_t *region,
+ int x, int y)
+{
+ pixman_box32_t box;
+
+ if (region->status)
+ return FALSE;
- return pixman_region32_contains_rectangle (&region->rgn, &pbox);
+ return pixman_region32_contains_point (&region->rgn, x, y, &box);
}
+slim_hidden_def (cairo_region_contains_point);
diff --git a/src/cairo-scaled-font-private.h b/src/cairo-scaled-font-private.h
index 13d89ebe..f6c97488 100644
--- a/src/cairo-scaled-font-private.h
+++ b/src/cairo-scaled-font-private.h
@@ -84,6 +84,8 @@ struct _cairo_scaled_font {
cairo_reference_count_t ref_count;
cairo_user_data_array_t user_data;
+ cairo_font_face_t *original_font_face; /* may be NULL */
+
/* hash key members */
cairo_font_face_t *font_face; /* may be NULL */
cairo_matrix_t font_matrix; /* font space => user space */
@@ -104,8 +106,10 @@ struct _cairo_scaled_font {
/* The mutex protects modification to all subsequent fields. */
cairo_mutex_t mutex;
- int cache_frozen;
- cairo_scaled_glyph_page_t *mru_page;
+ cairo_hash_table_t *glyphs;
+ cairo_scaled_glyph_page_t *glyph_pages;
+ cairo_bool_t cache_frozen;
+ cairo_bool_t global_cache_frozen;
/*
* One surface backend may store data in each glyph.
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index c802c314..02b32aa7 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -372,13 +372,16 @@ _cairo_sub_font_glyph_lookup_unicode (cairo_sub_font_glyph_t *sub_font_glyph,
return CAIRO_STATUS_SUCCESS;
}
-static cairo_bool_t
+static cairo_status_t
_cairo_sub_font_glyph_map_to_unicode (cairo_sub_font_glyph_t *sub_font_glyph,
const char *utf8,
- int utf8_len)
+ int utf8_len,
+ cairo_bool_t *is_mapped)
{
+ *is_mapped = FALSE;
+
if (utf8_len < 0)
- return FALSE;
+ return CAIRO_STATUS_SUCCESS;
if (utf8 != NULL && utf8_len != 0 && utf8[utf8_len - 1] == '\0')
utf8_len--;
@@ -389,28 +392,25 @@ _cairo_sub_font_glyph_map_to_unicode (cairo_sub_font_glyph_t *sub_font_glyph,
memcmp (utf8, sub_font_glyph->utf8, utf8_len) == 0)
{
/* Requested utf8 mapping matches the existing mapping */
- return TRUE;
- }
- else
- {
- /* Requested utf8 mapping does not match the existing mapping */
- return FALSE;
+ *is_mapped = TRUE;
}
} else {
/* No existing mapping. Use the requested mapping */
sub_font_glyph->utf8 = malloc (utf8_len + 1);
+ if (unlikely (sub_font_glyph->utf8 == NULL))
+ return CAIRO_STATUS_NO_MEMORY;
+
memcpy (sub_font_glyph->utf8, utf8, utf8_len);
sub_font_glyph->utf8[utf8_len] = 0;
sub_font_glyph->utf8_len = utf8_len;
- return TRUE;
+ *is_mapped = TRUE;
}
}
- /* No mapping was requested. */
- return FALSE;
+ return CAIRO_STATUS_SUCCESS;
}
-static cairo_bool_t
+static cairo_int_status_t
_cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
unsigned long scaled_font_glyph_index,
const char *utf8,
@@ -418,6 +418,7 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
cairo_sub_font_glyph_t key, *sub_font_glyph;
+ cairo_int_status_t status;
_cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
sub_font_glyph = _cairo_hash_table_lookup (sub_font->sub_font_glyphs,
@@ -430,13 +431,15 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
subset_glyph->is_composite = sub_font->is_composite;
subset_glyph->x_advance = sub_font_glyph->x_advance;
subset_glyph->y_advance = sub_font_glyph->y_advance;
- subset_glyph->utf8_is_mapped = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph, utf8, utf8_len);
+ status = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph,
+ utf8, utf8_len,
+ &subset_glyph->utf8_is_mapped);
subset_glyph->unicode = sub_font_glyph->unicode;
- return TRUE;
+ return status;
}
- return FALSE;
+ return CAIRO_INT_STATUS_UNSUPPORTED;
}
static cairo_status_t
@@ -524,10 +527,12 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
subset_glyph->is_composite = sub_font->is_composite;
subset_glyph->x_advance = sub_font_glyph->x_advance;
subset_glyph->y_advance = sub_font_glyph->y_advance;
- subset_glyph->utf8_is_mapped = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph, utf8, utf8_len);
+ status = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph,
+ utf8, utf8_len,
+ &subset_glyph->utf8_is_mapped);
subset_glyph->unicode = sub_font_glyph->unicode;
- return CAIRO_STATUS_SUCCESS;
+ return status;
}
static void
@@ -542,6 +547,10 @@ _cairo_sub_font_collect (void *entry, void *closure)
if (collection->status)
return;
+ collection->status = sub_font->scaled_font->status;
+ if (collection->status)
+ return;
+
for (i = 0; i <= sub_font->current_subset; i++) {
collection->subset_id = i;
collection->num_glyphs = 0;
@@ -682,11 +691,12 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
sub_font = _cairo_hash_table_lookup (subsets->unscaled_sub_fonts,
&key.base);
if (sub_font != NULL) {
- if (_cairo_sub_font_lookup_glyph (sub_font,
- scaled_font_glyph_index,
- utf8, utf8_len,
- subset_glyph))
- return CAIRO_STATUS_SUCCESS;
+ status = _cairo_sub_font_lookup_glyph (sub_font,
+ scaled_font_glyph_index,
+ utf8, utf8_len,
+ subset_glyph);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
}
}
@@ -696,11 +706,12 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
sub_font = _cairo_hash_table_lookup (subsets->scaled_sub_fonts,
&key.base);
if (sub_font != NULL) {
- if (_cairo_sub_font_lookup_glyph (sub_font,
- scaled_font_glyph_index,
- utf8, utf8_len,
- subset_glyph))
- return CAIRO_STATUS_SUCCESS;
+ status = _cairo_sub_font_lookup_glyph (sub_font,
+ scaled_font_glyph_index,
+ utf8, utf8_len,
+ subset_glyph);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
}
/* Glyph not found. Determine whether the glyph is outline or
@@ -1021,7 +1032,7 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
if (utf8 && *utf8) {
status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
if (unlikely (status))
- return status; /* FIXME */
+ goto CLEANUP_HASH;
}
if (utf16_len == 1) {
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 7096a01e..dbe2de8d 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -49,21 +49,30 @@
#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */
#endif
-#define CAIRO_SCALED_GLYPH_PAGE_SHIFT 7
-#define CAIRO_SCALED_GLYPH_PAGE_SIZE (1 << CAIRO_SCALED_GLYPH_PAGE_SHIFT)
-#define CAIRO_SCALED_GLYPH_PAGE_INDEX(I) \
- ((I) & (CAIRO_SCALED_GLYPH_PAGE_SIZE - 1))
-#define CAIRO_SCALED_GLYPH_PAGE_BASE_INDEX(I) ((I) & -CAIRO_SCALED_GLYPH_PAGE_SIZE)
-#define CAIRO_SCALED_GLYPH_PAGE_HAS_INDEX(P, I) \
- ((I) - (P)->base_index < CAIRO_SCALED_GLYPH_PAGE_SIZE)
-typedef struct _cairo_scaled_glyph_page_key {
- cairo_cache_entry_t cache_entry;
- cairo_scaled_font_t *scaled_font;
-} cairo_scaled_glyph_page_key_t;
+/* Global Glyph Cache
+ *
+ * We maintain a global pool of glyphs split between all active fonts. This
+ * allows a heavily used individual font to cache more glyphs than we could
+ * manage if we used per-font glyph caches, but at the same time maintains
+ * fairness across all fonts and provides a cap on the maximum number of
+ * global glyphs.
+ *
+ * The glyphs are allocated in pages, which are capped in the global pool.
+ * Using pages means we can reduce the frequency at which we have to probe the
+ * global pool and ameliorates the memory allocation pressure.
+ */
+/* XXX: This number is arbitrary---we've never done any measurement of this. */
+#define MAX_GLYPH_PAGES_CACHED 512
+static cairo_cache_t *cairo_scaled_glyph_page_cache;
+
+#define CAIRO_SCALED_GLYPH_PAGE_SIZE 32
struct _cairo_scaled_glyph_page {
- cairo_scaled_glyph_page_key_t key;
- unsigned long base_index;
+ cairo_cache_entry_t cache_entry;
+
+ struct _cairo_scaled_glyph_page *prev, *next;
+
+ unsigned int num_glyphs;
cairo_scaled_glyph_t glyphs[CAIRO_SCALED_GLYPH_PAGE_SIZE];
};
@@ -176,13 +185,9 @@ static void
_cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font);
static void
-_cairo_scaled_glyph_page_cache_remove_scaled_font (cairo_scaled_font_t
- *scaled_font);
-
-static void
-_cairo_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph)
+_cairo_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
+ cairo_scaled_glyph_t *scaled_glyph)
{
- cairo_scaled_font_t *scaled_font = scaled_glyph->scaled_font;
const cairo_surface_backend_t *surface_backend = scaled_font->surface_backend;
if (surface_backend != NULL && surface_backend->scaled_glyph_fini != NULL)
@@ -196,8 +201,6 @@ _cairo_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph)
if (scaled_glyph->meta_surface != NULL)
cairo_surface_destroy (scaled_glyph->meta_surface);
-
- scaled_glyph->scaled_font = NULL;
}
#define ZOMBIE 0
@@ -206,6 +209,7 @@ static const cairo_scaled_font_t _cairo_scaled_font_nil = {
CAIRO_STATUS_NO_MEMORY, /* status */
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
{ 0, 0, 0, NULL }, /* user_data */
+ NULL, /* original_font_face */
NULL, /* font_face */
{ 1., 0., 0., 1., 0, 0}, /* font_matrix */
{ 1., 0., 0., 1., 0, 0}, /* ctm */
@@ -221,8 +225,10 @@ static const cairo_scaled_font_t _cairo_scaled_font_nil = {
{ 0., 0., 0., 0., 0. }, /* extents */
{ 0., 0., 0., 0., 0. }, /* fs_extents */
CAIRO_MUTEX_NIL_INITIALIZER,/* mutex */
+ NULL, /* glyphs */
+ NULL, /* pages */
FALSE, /* cache_frozen */
- NULL, /* mru_page */
+ FALSE, /* global_cache_frozen */
NULL, /* surface_backend */
NULL, /* surface_private */
NULL /* backend */
@@ -418,112 +424,29 @@ _cairo_scaled_font_map_destroy (void)
CLEANUP_MUTEX_LOCK:
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
}
-
-/* Global Glyph Cache
- *
- * We maintain a global pool of glyphs split between all open fonts. This
- * allows a heavily used individual font to cache more glyphs than we could
- * manage if we used per-font glyph caches, but at the same time maintains
- * fairness across all fonts and provides a cap on the maximum number of
- * global glyphs.
- *
- * The glyphs are allocated in pages, which are cached in the global pool.
- * Using pages means we can exploit spatial locality within the font (nearby
- * indices are typically used in clusters) to reduce frequency of small
- * allocations and allow the scaled font to reserve a single MRU page of
- * glyphs.
- */
-
-/* XXX: This number is arbitrary---we've never done any measurement of this. */
-#define MAX_GLYPH_PAGES_CACHED 512
-
-static cairo_cache_t *cairo_scaled_glyph_page_cache;
-
-static cairo_bool_t
-_cairo_scaled_glyph_pages_equal (const void *key_a, const void *key_b)
-{
- const cairo_scaled_glyph_page_key_t *a = key_a;
- const cairo_scaled_glyph_page_key_t *b = key_b;
-
- return
- a->cache_entry.hash == b->cache_entry.hash &&
- a->scaled_font == b->scaled_font;
-}
-
static void
_cairo_scaled_glyph_page_destroy (void *closure)
{
cairo_scaled_glyph_page_t *page = closure;
- int n;
-
- for (n = 0; n < CAIRO_SCALED_GLYPH_PAGE_SIZE; n++) {
- if (page->glyphs[n].scaled_font != NULL)
- _cairo_scaled_glyph_fini (&page->glyphs[n]);
- }
-
- free (page);
-}
-
-static cairo_scaled_glyph_page_t *
-_cairo_scaled_glyph_page_cache_lookup (cairo_scaled_font_t *scaled_font,
- unsigned long index)
-{
- cairo_scaled_glyph_page_key_t key;
- cairo_scaled_glyph_page_t *page;
-
- key.cache_entry.hash =
- (index >> CAIRO_SCALED_GLYPH_PAGE_SHIFT) ^
- (unsigned long) scaled_font;
- key.scaled_font = scaled_font;
+ cairo_scaled_font_t *scaled_font;
+ unsigned int n;
- if (scaled_font->cache_frozen) {
- CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
- page = _cairo_cache_steal (cairo_scaled_glyph_page_cache,
- &key.cache_entry);
- CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
- } else
- page = NULL;
-
- if (page == NULL) {
- /* On miss, create glyph page and insert into cache */
- page = malloc (sizeof (cairo_scaled_glyph_page_t));
- if (unlikely (page == NULL))
- return NULL;
-
- page->key.cache_entry.hash = key.cache_entry.hash;
- /* We currently don't differentiate on glyph size at all */
- page->key.cache_entry.size = 1;
- page->key.scaled_font = scaled_font;
- page->base_index = CAIRO_SCALED_GLYPH_PAGE_BASE_INDEX (index);
-
- memset (page->glyphs, 0, sizeof (page->glyphs));
+ scaled_font = (cairo_scaled_font_t *) page->cache_entry.hash;
+ for (n = 0; n < page->num_glyphs; n++) {
+ _cairo_hash_table_remove (scaled_font->glyphs,
+ &page->glyphs[n].hash_entry);
+ _cairo_scaled_glyph_fini (scaled_font, &page->glyphs[n]);
}
- return page;
-}
-
-static void
-_cairo_scaled_glyph_page_cache_remove_scaled_font_cb (void *entry,
- void *closure)
-{
- cairo_scaled_glyph_page_key_t *key = entry;
-
- if (key->scaled_font == closure)
- _cairo_cache_remove (cairo_scaled_glyph_page_cache, entry);
-}
-
-static void
-_cairo_scaled_glyph_page_cache_remove_scaled_font (cairo_scaled_font_t *scaled_font)
-{
- CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
+ if (page->prev != NULL)
+ page->prev->next = page->next;
+ else
+ scaled_font->glyph_pages = page->next;
- if (cairo_scaled_glyph_page_cache != NULL) {
- _cairo_cache_foreach (cairo_scaled_glyph_page_cache,
- _cairo_scaled_glyph_page_cache_remove_scaled_font_cb,
- scaled_font);
- }
+ if (page->next != NULL)
+ page->next->prev = page->prev;
- CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
+ free (page);
}
/* If a scaled font wants to unlock the font map while still being
@@ -701,19 +624,32 @@ _cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font,
}
static cairo_bool_t
-_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
+_cairo_scaled_font_keys_equal (const void *abstract_key_a,
+ const void *abstract_key_b)
{
const cairo_scaled_font_t *key_a = abstract_key_a;
const cairo_scaled_font_t *key_b = abstract_key_b;
- return (key_a->font_face == key_b->font_face &&
+ if (key_a->hash_entry.hash != key_b->hash_entry.hash)
+ return FALSE;
+
+ return key_a->font_face == key_b->font_face &&
memcmp ((unsigned char *)(&key_a->font_matrix.xx),
(unsigned char *)(&key_b->font_matrix.xx),
sizeof(cairo_matrix_t)) == 0 &&
memcmp ((unsigned char *)(&key_a->ctm.xx),
(unsigned char *)(&key_b->ctm.xx),
sizeof(cairo_matrix_t)) == 0 &&
- cairo_font_options_equal (&key_a->options, &key_b->options));
+ cairo_font_options_equal (&key_a->options, &key_b->options);
+}
+
+static cairo_bool_t
+_cairo_scaled_glyphs_equal (const void *abstract_a, const void *abstract_b)
+{
+ const cairo_scaled_glyph_t *a = abstract_a;
+ const cairo_scaled_glyph_t *b = abstract_b;
+
+ return a->hash_entry.hash == b->hash_entry.hash;
}
/*
@@ -765,19 +701,25 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
return status;
}
- scaled_font->finished = FALSE;
+ scaled_font->glyphs = _cairo_hash_table_create (_cairo_scaled_glyphs_equal);
+ if (unlikely (scaled_font->glyphs == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ scaled_font->glyph_pages = NULL;
scaled_font->cache_frozen = FALSE;
+ scaled_font->global_cache_frozen = FALSE;
+
+ scaled_font->finished = FALSE;
CAIRO_REFERENCE_COUNT_INIT (&scaled_font->ref_count, 1);
_cairo_user_data_array_init (&scaled_font->user_data);
cairo_font_face_reference (font_face);
+ scaled_font->original_font_face = NULL;
CAIRO_MUTEX_INIT (scaled_font->mutex);
- scaled_font->mru_page = NULL;
-
scaled_font->surface_backend = NULL;
scaled_font->surface_private = NULL;
@@ -793,17 +735,20 @@ _cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font)
assert (scaled_font->status == CAIRO_STATUS_SUCCESS);
CAIRO_MUTEX_LOCK (scaled_font->mutex);
+ scaled_font->cache_frozen = TRUE;
}
void
_cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font)
{
- if (scaled_font->cache_frozen) {
+ scaled_font->cache_frozen = FALSE;
+
+ if (scaled_font->global_cache_frozen) {
CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
_cairo_cache_thaw (cairo_scaled_glyph_page_cache);
CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
- scaled_font->cache_frozen = FALSE;
+ scaled_font->global_cache_frozen = FALSE;
}
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
@@ -812,14 +757,14 @@ _cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font)
void
_cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font)
{
- assert (CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex));
+ assert (! scaled_font->cache_frozen);
- if (scaled_font->mru_page != NULL) {
- _cairo_scaled_glyph_page_destroy (scaled_font->mru_page);
- scaled_font->mru_page = NULL;
+ CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
+ while (scaled_font->glyph_pages != NULL) {
+ _cairo_cache_remove (cairo_scaled_glyph_page_cache,
+ &scaled_font->glyph_pages->cache_entry);
}
-
- _cairo_scaled_glyph_page_cache_remove_scaled_font (scaled_font);
+ CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
}
cairo_status_t
@@ -856,15 +801,11 @@ _cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font)
{
scaled_font->finished = TRUE;
- if (scaled_font->mru_page != NULL) {
- _cairo_scaled_glyph_page_destroy (scaled_font->mru_page);
- scaled_font->mru_page = NULL;
- }
-
- _cairo_scaled_glyph_page_cache_remove_scaled_font (scaled_font);
+ _cairo_scaled_font_reset_cache (scaled_font);
+ _cairo_hash_table_destroy (scaled_font->glyphs);
- if (scaled_font->font_face != NULL)
- cairo_font_face_destroy (scaled_font->font_face);
+ cairo_font_face_destroy (scaled_font->font_face);
+ cairo_font_face_destroy (scaled_font->original_font_face);
CAIRO_MUTEX_FINI (scaled_font->mutex);
@@ -916,6 +857,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
{
cairo_status_t status;
cairo_scaled_font_map_t *font_map;
+ cairo_font_face_t *original_font_face = font_face;
cairo_scaled_font_t key, *old = NULL, *scaled_font = NULL;
double det;
@@ -1051,6 +993,10 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
return scaled_font;
}
+ scaled_font->original_font_face =
+ cairo_font_face_reference (original_font_face);
+
+ assert (scaled_font->hash_entry.hash == key.hash_entry.hash);
status = _cairo_hash_table_insert (font_map->hash_table,
&scaled_font->hash_entry);
if (likely (status == CAIRO_STATUS_SUCCESS)) {
@@ -2463,6 +2409,9 @@ _cairo_scaled_glyph_set_surface (cairo_scaled_glyph_t *scaled_glyph,
{
if (scaled_glyph->surface != NULL)
cairo_surface_destroy (&scaled_glyph->surface->base);
+
+ /* sanity check the backend glyph contents */
+ _cairo_debug_check_image_surface_is_defined (&surface->base);
scaled_glyph->surface = surface;
}
@@ -2486,6 +2435,92 @@ _cairo_scaled_glyph_set_meta_surface (cairo_scaled_glyph_t *scaled_glyph,
scaled_glyph->meta_surface = meta_surface;
}
+static cairo_bool_t
+_cairo_scaled_glyph_page_can_remove (const void *closure)
+{
+ const cairo_scaled_glyph_page_t *page = closure;
+ const cairo_scaled_font_t *scaled_font;
+
+ scaled_font = (cairo_scaled_font_t *) page->cache_entry.hash;
+ return scaled_font->cache_frozen == 0;
+}
+
+static cairo_status_t
+_cairo_scaled_font_allocate_glyph (cairo_scaled_font_t *scaled_font,
+ cairo_scaled_glyph_t **scaled_glyph)
+{
+ cairo_scaled_glyph_page_t *page;
+ cairo_status_t status;
+
+ /* only the first page in the list may contain available slots */
+ page = scaled_font->glyph_pages;
+ if (page != NULL && page->num_glyphs < CAIRO_SCALED_GLYPH_PAGE_SIZE) {
+ *scaled_glyph = &page->glyphs[page->num_glyphs++];
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ page = malloc (sizeof (cairo_scaled_glyph_page_t));
+ if (unlikely (page == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ page->cache_entry.hash = (unsigned long) scaled_font;
+ page->cache_entry.size = 1; /* XXX occupancy weighting? */
+ page->num_glyphs = 0;
+
+ CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
+ if (scaled_font->global_cache_frozen == FALSE) {
+ if (unlikely (cairo_scaled_glyph_page_cache == NULL)) {
+ cairo_scaled_glyph_page_cache =
+ _cairo_cache_create (NULL,
+ _cairo_scaled_glyph_page_can_remove,
+ _cairo_scaled_glyph_page_destroy,
+ MAX_GLYPH_PAGES_CACHED);
+ if (unlikely (cairo_scaled_glyph_page_cache == NULL)) {
+ CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
+ free (page);
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+ }
+
+ _cairo_cache_freeze (cairo_scaled_glyph_page_cache);
+ scaled_font->global_cache_frozen = TRUE;
+ }
+
+ status = _cairo_cache_insert (cairo_scaled_glyph_page_cache,
+ &page->cache_entry);
+ CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
+ if (unlikely (status)) {
+ free (page);
+ return status;
+ }
+
+ page->next = scaled_font->glyph_pages;
+ page->prev = NULL;
+ if (scaled_font->glyph_pages != NULL)
+ scaled_font->glyph_pages->prev = page;
+ scaled_font->glyph_pages = page;
+
+ *scaled_glyph = &page->glyphs[page->num_glyphs++];
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_scaled_font_free_last_glyph (cairo_scaled_font_t *scaled_font,
+ cairo_scaled_glyph_t *scaled_glyph)
+{
+ cairo_scaled_glyph_page_t *page;
+
+ page = scaled_font->glyph_pages;
+ assert (page != NULL && scaled_glyph == &page->glyphs[page->num_glyphs-1]);
+
+ _cairo_scaled_glyph_fini (scaled_font, scaled_glyph);
+
+ if (--page->num_glyphs == 0) {
+ _cairo_cache_remove (cairo_scaled_glyph_page_cache, &page->cache_entry);
+ assert (scaled_font->glyph_pages != page);
+ }
+}
+
/**
* _cairo_scaled_glyph_lookup:
* @scaled_font: a #cairo_scaled_font_t
@@ -2519,66 +2554,43 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
cairo_scaled_glyph_info_t info,
cairo_scaled_glyph_t **scaled_glyph_ret)
{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
- cairo_scaled_glyph_page_t *page;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_scaled_glyph_t *scaled_glyph;
- cairo_scaled_glyph_info_t need_info;
+ cairo_scaled_glyph_info_t need_info;
if (unlikely (scaled_font->status))
return scaled_font->status;
- page = scaled_font->mru_page;
- if (page != NULL && ! CAIRO_SCALED_GLYPH_PAGE_HAS_INDEX (page, index)) {
- CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
- if (! scaled_font->cache_frozen) {
- if (cairo_scaled_glyph_page_cache == NULL) {
- cairo_scaled_glyph_page_cache =
- _cairo_cache_create (_cairo_scaled_glyph_pages_equal,
- _cairo_scaled_glyph_page_destroy,
- MAX_GLYPH_PAGES_CACHED);
- if (unlikely (cairo_scaled_glyph_page_cache == NULL)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto BAIL;
- }
- }
-
- _cairo_cache_freeze (cairo_scaled_glyph_page_cache);
- scaled_font->cache_frozen = TRUE;
- }
- status = _cairo_cache_insert (cairo_scaled_glyph_page_cache,
- &page->key.cache_entry);
- BAIL:
- CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
- if (unlikely (status))
- return _cairo_scaled_font_set_error (scaled_font, status);
-
- page = scaled_font->mru_page = NULL;
- }
-
- if (page == NULL) {
- page = _cairo_scaled_glyph_page_cache_lookup (scaled_font, index);
- if (unlikely (page == NULL)) {
- return _cairo_scaled_font_set_error (scaled_font,
- _cairo_error (CAIRO_STATUS_NO_MEMORY));
- }
- }
-
- scaled_font->mru_page = page;
+ if (CAIRO_INJECT_FAULT ())
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
/*
* Check cache for glyph
*/
- info |= CAIRO_SCALED_GLYPH_INFO_METRICS;
- scaled_glyph = &page->glyphs[CAIRO_SCALED_GLYPH_PAGE_INDEX (index)];
- if (scaled_glyph->scaled_font == NULL) {
- scaled_glyph->index = index;
- scaled_glyph->scaled_font = scaled_font;
+ scaled_glyph = _cairo_hash_table_lookup (scaled_font->glyphs,
+ (cairo_hash_entry_t *) &index);
+ if (scaled_glyph == NULL) {
+ status = _cairo_scaled_font_allocate_glyph (scaled_font, &scaled_glyph);
+ if (unlikely (status))
+ goto CLEANUP;
+
+ memset (scaled_glyph, 0, sizeof (cairo_scaled_glyph_t));
+ _cairo_scaled_glyph_set_index (scaled_glyph, index);
/* ask backend to initialize metrics and shape fields */
- status = (*scaled_font->backend->
- scaled_glyph_init) (scaled_font, scaled_glyph, info);
+ status =
+ scaled_font->backend->scaled_glyph_init (scaled_font,
+ scaled_glyph,
+ info | CAIRO_SCALED_GLYPH_INFO_METRICS);
+ if (unlikely (status)) {
+ _cairo_scaled_font_free_last_glyph (scaled_font, scaled_glyph);
+ goto CLEANUP;
+ }
+
+ status = _cairo_hash_table_insert (scaled_font->glyphs,
+ &scaled_glyph->hash_entry);
if (unlikely (status)) {
- _cairo_scaled_glyph_fini (scaled_glyph);
+ _cairo_scaled_font_free_last_glyph (scaled_font, scaled_glyph);
goto CLEANUP;
}
}
@@ -2590,19 +2602,26 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
need_info = 0;
if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0 &&
scaled_glyph->surface == NULL)
+ {
need_info |= CAIRO_SCALED_GLYPH_INFO_SURFACE;
+ }
- if (((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
- scaled_glyph->path == NULL))
+ if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
+ scaled_glyph->path == NULL)
+ {
need_info |= CAIRO_SCALED_GLYPH_INFO_PATH;
+ }
- if (((info & CAIRO_SCALED_GLYPH_INFO_META_SURFACE) != 0 &&
- scaled_glyph->meta_surface == NULL))
+ if ((info & CAIRO_SCALED_GLYPH_INFO_META_SURFACE) != 0 &&
+ scaled_glyph->meta_surface == NULL)
+ {
need_info |= CAIRO_SCALED_GLYPH_INFO_META_SURFACE;
+ }
if (need_info) {
- status = (*scaled_font->backend->
- scaled_glyph_init) (scaled_font, scaled_glyph, need_info);
+ status = scaled_font->backend->scaled_glyph_init (scaled_font,
+ scaled_glyph,
+ need_info);
if (unlikely (status))
goto CLEANUP;
@@ -2612,19 +2631,22 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
* glyph info. */
if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0 &&
- scaled_glyph->surface == NULL) {
+ scaled_glyph->surface == NULL)
+ {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto CLEANUP;
}
if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
- scaled_glyph->path == NULL) {
+ scaled_glyph->path == NULL)
+ {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto CLEANUP;
}
if ((info & CAIRO_SCALED_GLYPH_INFO_META_SURFACE) != 0 &&
- scaled_glyph->meta_surface == NULL) {
+ scaled_glyph->meta_surface == NULL)
+ {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto CLEANUP;
}
@@ -2703,8 +2725,8 @@ slim_hidden_def (cairo_scaled_font_get_font_matrix);
*
* Stores the CTM with which @scaled_font was created into @ctm.
* Note that the translation offsets (x0, y0) of the CTM are ignored
- * by cairo_scaled_font_create(). So, the matrix this function
- * returns always has 0,0 as x0,y0.
+ * by cairo_scaled_font_create(). So, the matrix this
+ * function returns always has 0,0 as x0,y0.
*
* Since: 1.2
**/
diff --git a/src/cairo-sdl-surface.c b/src/cairo-sdl-surface.c
deleted file mode 100644
index 1f97fb47..00000000
--- a/src/cairo-sdl-surface.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/* Cairo - a vector graphics library with display and print output
- *
- * Copyright © 2008 Chris Wilson
- *
- * 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 Chris Wilson.
- */
-
-#include "cairoint.h"
-
-#include "cairo-sdl.h"
-
-typedef struct _cairo_sdl_surface {
- cairo_surface_t base;
-
- SDL_Surface *sdl;
- cairo_image_surface_t *image;
-
- cairo_region_t update;
-} cairo_sdl_surface_t;
-
-static const cairo_surface_backend_t _cairo_sdl_surface_backend;
-
-static cairo_surface_t *
-_cairo_sdl_surface_create_internal (SDL_Surface *sdl,
- cairo_surface_t *image)
-{
- cairo_sdl_surface_t *surface;
-
- surface = malloc (sizeof (cairo_sdl_surface_t));
- if (unlikely (surface == NULL))
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-
- _cairo_surface_init (&surface->base,
- &_cairo_sdl_surface_backend,
- image->content);
-
- surface->sdl = sdl;
- sdl->refcount++;
- surface->image = (cairo_image_surface_t *) cairo_surface_reference (image);
-
- _cairo_region_init (&surface->update);
-
- return &surface->base;
-}
-
-static cairo_surface_t *
-_cairo_sdl_surface_create_similar (void *abstract_src,
- cairo_content_t content,
- int width,
- int height)
-{
- return _cairo_image_surface_create_with_content (content, width, height);
-}
-
-static cairo_status_t
-_cairo_sdl_surface_finish (void *abstract_surface)
-{
- cairo_sdl_surface_t *surface = abstract_surface;
-
- cairo_surface_destroy (&surface->image->base);
- SDL_FreeSurface (surface->sdl);
-
- _cairo_region_fini (&surface->update);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_sdl_surface_acquire_source_image (void *abstract_surface,
- cairo_image_surface_t **image_out,
- void **image_extra)
-{
- cairo_sdl_surface_t *surface = abstract_surface;
-
- SDL_LockSurface (surface->sdl);
-
- *image_out = surface->image;
- *image_extra = NULL;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_sdl_surface_release_source_image (void *abstract_surface,
- cairo_image_surface_t *image,
- void *image_extra)
-{
- cairo_sdl_surface_t *surface = abstract_surface;
-
- SDL_UnlockSurface (surface->sdl);
-}
-
-static cairo_status_t
-_cairo_sdl_surface_acquire_dest_image (void *abstract_surface,
- cairo_rectangle_int_t *interest_rect,
- cairo_image_surface_t **image_out,
- cairo_rectangle_int_t *image_rect_out,
- void **image_extra)
-{
- cairo_sdl_surface_t *surface = abstract_surface;
-
- SDL_LockSurface (surface->sdl);
-
- image_rect_out->x = 0;
- image_rect_out->y = 0;
- image_rect_out->width = surface->image->width;
- image_rect_out->height = surface->image->height;
-
- *image_out = surface->image;
- *image_extra = NULL;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_sdl_surface_release_dest_image (void *abstract_surface,
- cairo_rectangle_int_t *interest_rect,
- cairo_image_surface_t *image,
- cairo_rectangle_int_t *image_rect,
- void *image_extra)
-{
- cairo_sdl_surface_t *surface = abstract_surface;
- cairo_status_t status;
-
- SDL_UnlockSurface (surface->sdl);
-
- status = _cairo_region_union_rect (&surface->update,
- &surface->update,
- interest_rect);
- status = _cairo_surface_set_error (&surface->base, status);
-}
-
-static cairo_status_t
-_cairo_sdl_surface_clone_similar (void *abstract_surface,
- cairo_surface_t *src,
- int src_x,
- int src_y,
- int width,
- int height,
- int *clone_offset_x,
- int *clone_offset_y,
- cairo_surface_t **clone_out)
-{
- cairo_sdl_surface_t *surface = abstract_surface;
-
- if (src->backend == surface->base.backend) {
- *clone_offset_x = *clone_offset_y = 0;
- *clone_out = cairo_surface_reference (src);
-
- return CAIRO_STATUS_SUCCESS;
- } else if (_cairo_surface_is_image (src)) {
- cairo_image_surface_t *image = (cairo_image_surface_t *) src;
- cairo_format_masks_t masks;
- cairo_surface_t *clone;
- SDL_Surface *sdl;
-
- _pixman_format_to_masks (image->pixman_format, &masks);
-
- sdl = SDL_CreateRGBSurfaceFrom (image->data,
- image->width,
- image->height,
- masks.bpp,
- image->stride,
- masks.red_mask,
- masks.green_mask,
- masks.blue_mask,
- masks.alpha_mask);
- if (sdl == NULL)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- clone = _cairo_sdl_surface_create_internal (sdl, &image->base);
- SDL_FreeSurface (sdl);
-
- if (clone->status)
- return clone->status;
-
- *clone_offset_x = *clone_offset_y = 0;
- *clone_out = clone;
- return CAIRO_STATUS_SUCCESS;
- }
-
- return CAIRO_INT_STATUS_UNSUPPORTED;
-}
-
-static cairo_int_status_t
-_cairo_sdl_surface_composite (cairo_operator_t op,
- const cairo_pattern_t *src_pattern,
- const 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_sdl_surface_t *dst = abstract_dst;
- cairo_sdl_surface_t *src;
- cairo_surface_attributes_t src_attr;
- cairo_bool_t is_integer_translation;
- int itx, ity;
- cairo_int_status_t status;
-
- /* under a few conditions we can perform a (hardware) blit...*/
- if (op != CAIRO_OPERATOR_SOURCE)
- return CAIRO_INT_STATUS_UNSUPPORTED;
- if (mask_pattern)
- return CAIRO_INT_STATUS_UNSUPPORTED;
- if (dst->base.current_clip_serial != 0)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
- src_x, src_y, width, height,
- (cairo_surface_t **) &src,
- &src_attr);
- if (unlikely (status))
- return status;
-
- is_integer_translation =
- _cairo_matrix_is_integer_translation (&src_attr.matrix, &itx, &ity);
-
- status = CAIRO_INT_STATUS_UNSUPPORTED;
- if (is_integer_translation &&
- src_attr.extend == CAIRO_EXTEND_NONE &&
- src_attr.filter == CAIRO_FILTER_NEAREST)
- {
- SDL_Rect src_rect;
- SDL_Rect dst_rect;
- cairo_rectangle_int_t rect;
-
- src_rect.x = src_x + src_attr.x_offset + itx;
- src_rect.y = src_y + src_attr.y_offset + ity;
- src_rect.w = width;
- src_rect.h = height;
-
- dst_rect.x = dst_x;
- dst_rect.y = dst_y;
- dst_rect.w = width;
- dst_rect.h = height;
-
- SDL_BlitSurface (src->sdl, &src_rect, dst->sdl, &dst_rect);
-
- rect.x = dst_x;
- rect.y = dst_y;
- rect.width = width;
- rect.height = height;
- status = _cairo_region_union_rect (&dst->update,
- &dst->update,
- &rect);
- }
-
- _cairo_pattern_release_surface (src_pattern, &src->base, &src_attr);
- return status;
-}
-
-static cairo_int_status_t
-_cairo_sdl_surface_set_clip_region (void *abstract_surface,
- cairo_region_t *region)
-{
- cairo_sdl_surface_t *surface = abstract_surface;
-
- return _cairo_surface_set_clip_region (&surface->image->base,
- region,
- surface->base.current_clip_serial);
-}
-
-static cairo_int_status_t
-_cairo_sdl_surface_get_extents (void *abstract_surface,
- cairo_rectangle_int_t *rectangle)
-{
- cairo_sdl_surface_t *surface = abstract_surface;
-
- rectangle->x = 0;
- rectangle->y = 0;
- rectangle->width = surface->image->width;
- rectangle->height = surface->image->height;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_sdl_surface_get_font_options (void *abstract_surface,
- cairo_font_options_t *options)
-{
- cairo_sdl_surface_t *surface = abstract_surface;
-
- cairo_surface_get_font_options (&surface->image->base, options);
-}
-
-static cairo_status_t
-_cairo_sdl_surface_flush (void *abstract_surface)
-{
- cairo_sdl_surface_t *surface = abstract_surface;
- cairo_box_int_t *boxes;
- int n_boxes, i;
- cairo_status_t status;
-
- n_boxes = 0;
- status = _cairo_region_get_boxes (&surface->update, &n_boxes, &boxes);
- if (unlikely (status))
- return status;
- if (n_boxes == 0)
- return CAIRO_STATUS_SUCCESS;
-
- for (i = 0; i < n_boxes; i++) {
- SDL_UpdateRect (surface->sdl,
- boxes[i].p1.x,
- boxes[i].p1.y,
- boxes[i].p2.x - boxes[i].p1.x,
- boxes[i].p2.y - boxes[i].p1.y);
- }
-
- _cairo_region_boxes_fini (&surface->update, boxes);
-
- _cairo_region_fini (&surface->update);
- _cairo_region_init (&surface->update);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static const cairo_surface_backend_t _cairo_sdl_surface_backend = {
- CAIRO_SURFACE_TYPE_SDL,
- _cairo_sdl_surface_create_similar,
- _cairo_sdl_surface_finish,
- _cairo_sdl_surface_acquire_source_image,
- _cairo_sdl_surface_release_source_image,
- _cairo_sdl_surface_acquire_dest_image,
- _cairo_sdl_surface_release_dest_image,
- _cairo_sdl_surface_clone_similar,
- _cairo_sdl_surface_composite,
- NULL, /* fill rectangles */
- NULL, /* composite traps */
- NULL, /* create_span_renderer */
- NULL, /* check_span_renderer */
- NULL, /* copy_page */
- NULL, /* show_page */
- _cairo_sdl_surface_set_clip_region,
- NULL, /* intersect_clip_path */
- _cairo_sdl_surface_get_extents,
- NULL, /* old_show_glyphs */
- _cairo_sdl_surface_get_font_options,
- _cairo_sdl_surface_flush, /* flush */
- NULL, /* mark_dirty_rectangle */
- NULL, /* font_fini */
- NULL, /* glyph_fini */
-
- NULL, /* paint */
- NULL, /* mask */
- NULL, /* stroke */
- NULL, /* fill */
- NULL, /* show_glyphs */
- NULL, /* snapshot */
- NULL, /* is_similar */
-
- NULL, /* reset */
-};
-
-static cairo_surface_t *
-_cairo_image_surface_create_for_sdl (SDL_Surface *surface)
-{
- cairo_format_masks_t masks;
- pixman_format_code_t format;
-
- masks.bpp = surface->format->BitsPerPixel;
- masks.alpha_mask = surface->format->Amask;
- masks.red_mask = surface->format->Rmask;
- masks.green_mask = surface->format->Gmask;
- masks.blue_mask = surface->format->Bmask;
-
- if (! _pixman_format_from_masks (&masks, &format))
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
-
- return _cairo_image_surface_create_with_pixman_format (surface->pixels,
- format,
- surface->w,
- surface->h,
- surface->pitch);
-}
-
-cairo_surface_t *
-cairo_sdl_surface_create (SDL_Surface *sdl)
-{
- cairo_surface_t *image;
- cairo_surface_t *surface;
-
- image = _cairo_image_surface_create_for_sdl (sdl);
- if (image->status)
- return image;
-
- surface = _cairo_sdl_surface_create_internal (sdl, image);
- cairo_surface_destroy (image);
-
- return surface;
-}
diff --git a/src/cairo-skiplist.c b/src/cairo-skiplist.c
index 5c2c477e..18d69ca6 100644
--- a/src/cairo-skiplist.c
+++ b/src/cairo-skiplist.c
@@ -25,6 +25,10 @@
#include "cairo-skiplist-private.h"
+#if HAVE_FFS
+#include <strings.h> /* ffs() */
+#endif
+
#define ELT_DATA(elt) (void *) ((char*) (elt) - list->data_size)
#define NEXT_TO_ELT(next) (skip_elt_t *) ((char *) (next) - offsetof (skip_elt_t, next))
diff --git a/src/cairo-spans.c b/src/cairo-spans.c
index b6ac2c56..625f83f1 100644
--- a/src/cairo-spans.c
+++ b/src/cairo-spans.c
@@ -255,6 +255,7 @@ _cairo_scan_converter_create_in_error (cairo_status_t status)
}
switch (status) {
case CAIRO_STATUS_SUCCESS:
+ case CAIRO_STATUS_LAST_STATUS:
ASSERT_NOT_REACHED;
break;
case CAIRO_STATUS_INVALID_RESTORE: RETURN_NIL;
@@ -359,6 +360,7 @@ _cairo_span_renderer_create_in_error (cairo_status_t status)
}
switch (status) {
case CAIRO_STATUS_SUCCESS:
+ case CAIRO_STATUS_LAST_STATUS:
ASSERT_NOT_REACHED;
break;
case CAIRO_STATUS_INVALID_RESTORE: RETURN_NIL;
diff --git a/src/cairo-spline.c b/src/cairo-spline.c
index 948516e1..45eedbd6 100644
--- a/src/cairo-spline.c
+++ b/src/cairo-spline.c
@@ -289,7 +289,7 @@ _cairo_spline_bound (cairo_spline_add_point_func_t add_point_func,
* 0 < (-b±√delta)/a < 1 \
*/ \
if (_2ab >= 0) \
- feasible = delta > b2 && delta < a*a + b2 - _2ab; \
+ feasible = delta > b2 && delta < a*a + b2 + _2ab; \
else if (-b / a >= 1) \
feasible = delta < b2 && delta > a*a + b2 + _2ab; \
else \
diff --git a/src/cairo-stroke-style.c b/src/cairo-stroke-style.c
index d808ad8b..462b868a 100644
--- a/src/cairo-stroke-style.c
+++ b/src/cairo-stroke-style.c
@@ -52,6 +52,9 @@ cairo_status_t
_cairo_stroke_style_init_copy (cairo_stroke_style_t *style,
cairo_stroke_style_t *other)
{
+ if (CAIRO_INJECT_FAULT ())
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
style->line_width = other->line_width;
style->line_cap = other->line_cap;
style->line_join = other->line_join;
diff --git a/src/cairo-surface-fallback-private.h b/src/cairo-surface-fallback-private.h
index 61e5b903..cd181780 100644
--- a/src/cairo-surface-fallback-private.h
+++ b/src/cairo-surface-fallback-private.h
@@ -121,6 +121,7 @@ _cairo_surface_fallback_composite_trapezoids (cairo_operator_t op,
cairo_private cairo_status_t
_cairo_surface_fallback_clone_similar (cairo_surface_t *surface,
cairo_surface_t *src,
+ cairo_content_t content,
int src_x,
int src_y,
int width,
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index bcbc9846..469e9b3e 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -417,7 +417,7 @@ _composite_trap_region (cairo_clip_t *clip,
cairo_status_t status;
cairo_solid_pattern_t solid_pattern;
cairo_surface_pattern_t mask;
- int num_rects = _cairo_region_num_boxes (trap_region);
+ int num_rects = cairo_region_num_rectangles (trap_region);
unsigned int clip_serial;
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
@@ -520,10 +520,8 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
cairo_antialias_t antialias)
{
cairo_status_t status;
- cairo_region_t trap_region;
- cairo_region_t clear_region;
- cairo_bool_t has_trap_region = FALSE;
- cairo_bool_t has_clear_region = FALSE;
+ cairo_region_t *trap_region = NULL;
+ cairo_region_t *clear_region = NULL;
cairo_rectangle_int_t extents;
cairo_composite_traps_info_t traps_info;
@@ -535,23 +533,18 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
return status;
status = _cairo_traps_extract_region (traps, &trap_region);
- if (CAIRO_INT_STATUS_UNSUPPORTED == status) {
- has_trap_region = FALSE;
- } else if (status) {
- return status;
- } else {
- has_trap_region = TRUE;
- }
+ if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
if (_cairo_operator_bounded_by_mask (op)) {
cairo_rectangle_int_t trap_extents;
- if (has_trap_region) {
- status = _cairo_clip_intersect_to_region (clip, &trap_region);
+ if (trap_region) {
+ status = _cairo_clip_intersect_to_region (clip, trap_region);
if (unlikely (status))
goto out;
- _cairo_region_get_extents (&trap_region, &trap_extents);
+ cairo_region_get_extents (trap_region, &trap_extents);
} else {
cairo_box_t trap_box;
_cairo_traps_extents (traps, &trap_box);
@@ -569,27 +562,30 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
} else {
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
- if (has_trap_region && !clip_surface) {
+ if (trap_region && !clip_surface) {
/* If we optimize drawing with an unbounded operator to
* _cairo_surface_fill_rectangles() or to drawing with a
* clip region, then we have an additional region to clear.
*/
- _cairo_region_init_rect (&clear_region, &extents);
+ clear_region = cairo_region_create_rectangle (&extents);
- has_clear_region = TRUE;
- status = _cairo_clip_intersect_to_region (clip, &clear_region);
+ status = cairo_region_status (clear_region);
+ if (unlikely (status))
+ goto out;
+
+ status = _cairo_clip_intersect_to_region (clip, clear_region);
if (unlikely (status))
goto out;
- _cairo_region_get_extents (&clear_region, &extents);
+ cairo_region_get_extents (clear_region, &extents);
- status = _cairo_region_subtract (&clear_region, &clear_region, &trap_region);
+ status = cairo_region_subtract (clear_region, trap_region);
if (unlikely (status))
goto out;
- if (!_cairo_region_not_empty (&clear_region)) {
- _cairo_region_fini (&clear_region);
- has_clear_region = FALSE;
+ if (cairo_region_is_empty (clear_region)) {
+ cairo_region_destroy (clear_region);
+ clear_region = NULL;
}
} else {
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
@@ -599,7 +595,7 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
if (unlikely (status))
goto out;
- if (has_trap_region) {
+ if (trap_region) {
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
if ((src->type == CAIRO_PATTERN_TYPE_SOLID ||
@@ -613,12 +609,13 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
}
/* Solid rectangles special case */
- status = _cairo_surface_fill_region (dst, op, color, &trap_region);
+ status = _cairo_surface_fill_region (dst, op, color, trap_region);
- if (!status && has_clear_region)
+ if (!status && clear_region) {
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
- &clear_region);
+ clear_region);
+ }
goto out;
}
@@ -641,13 +638,13 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
* regions. In that case, we fall through.
*/
status = _composite_trap_region (clip, src, op, dst,
- &trap_region, &extents);
+ trap_region, &extents);
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
- if (!status && has_clear_region)
+ if (!status && clear_region)
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
- &clear_region);
+ clear_region);
goto out;
}
}
@@ -661,10 +658,10 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
&traps_info, dst, &extents);
out:
- if (has_trap_region)
- _cairo_region_fini (&trap_region);
- if (has_clear_region)
- _cairo_region_fini (&clear_region);
+ if (trap_region)
+ cairo_region_destroy (trap_region);
+ if (clear_region)
+ cairo_region_destroy (clear_region);
return status;
}
@@ -1118,32 +1115,32 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
{
cairo_surface_t *snapshot;
cairo_status_t status;
+ cairo_format_t format;
cairo_surface_pattern_t pattern;
cairo_image_surface_t *image;
void *image_extra;
- const char *mime_types[] = {
- CAIRO_MIME_TYPE_JPEG,
- CAIRO_MIME_TYPE_PNG,
- CAIRO_MIME_TYPE_JP2,
- NULL
- }, **mime_type;
status = _cairo_surface_acquire_source_image (surface,
&image, &image_extra);
if (unlikely (status))
return _cairo_surface_create_in_error (status);
- snapshot = cairo_image_surface_create (image->format,
+ format = image->format;
+ if (format == CAIRO_FORMAT_INVALID) {
+ /* Non-standard images formats can be generated when retrieving
+ * images from unusual xservers, for example.
+ */
+ format = _cairo_format_from_content (image->base.content);
+ }
+ snapshot = cairo_image_surface_create (format,
image->width,
image->height);
if (cairo_surface_status (snapshot)) {
- _cairo_surface_release_source_image (surface,
- image, image_extra);
+ _cairo_surface_release_source_image (surface, image, image_extra);
return snapshot;
}
_cairo_pattern_init_for_surface (&pattern, &image->base);
-
status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
&pattern.base,
NULL,
@@ -1153,29 +1150,13 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
0, 0,
image->width,
image->height);
-
_cairo_pattern_fini (&pattern.base);
- _cairo_surface_release_source_image (surface,
- image, image_extra);
-
+ _cairo_surface_release_source_image (surface, image, image_extra);
if (unlikely (status)) {
cairo_surface_destroy (snapshot);
return _cairo_surface_create_in_error (status);
}
- snapshot->device_transform = surface->device_transform;
- snapshot->device_transform_inverse = surface->device_transform_inverse;
-
- for (mime_type = mime_types; *mime_type; mime_type++) {
- status = _cairo_surface_copy_mime_data (snapshot, surface, *mime_type);
- if (unlikely (status)) {
- cairo_surface_destroy (snapshot);
- return _cairo_surface_create_in_error (status);
- }
- }
-
- snapshot->is_snapshot = TRUE;
-
return snapshot;
}
@@ -1355,6 +1336,7 @@ _cairo_surface_fallback_composite_trapezoids (cairo_operator_t op,
cairo_status_t
_cairo_surface_fallback_clone_similar (cairo_surface_t *surface,
cairo_surface_t *src,
+ cairo_content_t content,
int src_x,
int src_y,
int width,
@@ -1368,7 +1350,7 @@ _cairo_surface_fallback_clone_similar (cairo_surface_t *surface,
cairo_status_t status;
new_surface = _cairo_surface_create_similar_scratch (surface,
- src->content,
+ src->content & content,
width, height);
if (new_surface->status)
return new_surface->status;
diff --git a/src/cairo-surface-private.h b/src/cairo-surface-private.h
index efd4365e..12b38f01 100644
--- a/src/cairo-surface-private.h
+++ b/src/cairo-surface-private.h
@@ -57,6 +57,7 @@ struct _cairo_surface {
cairo_status_t status;
cairo_bool_t finished;
cairo_user_data_array_t user_data;
+ cairo_user_data_array_t mime_data;
cairo_matrix_t device_transform;
cairo_matrix_t device_transform_inverse;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 3b1dfe27..fc994b0c 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -51,6 +51,7 @@ const cairo_surface_t name = { \
status, /* status */ \
FALSE, /* finished */ \
{ 0, 0, 0, NULL, }, /* user_data */ \
+ { 0, 0, 0, NULL, }, /* mime_data */ \
{ 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, /* device_transform */ \
{ 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, /* device_transform_inverse */ \
0.0, /* x_resolution */ \
@@ -78,6 +79,7 @@ static DEFINE_NIL_SURFACE(CAIRO_STATUS_TEMP_FILE_ERROR, _cairo_surface_nil_temp_
static DEFINE_NIL_SURFACE(CAIRO_STATUS_READ_ERROR, _cairo_surface_nil_read_error);
static DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error);
static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_STRIDE, _cairo_surface_nil_invalid_stride);
+static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_SIZE, _cairo_surface_nil_invalid_size);
static cairo_status_t
_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t **pattern,
@@ -194,6 +196,7 @@ _cairo_surface_init (cairo_surface_t *surface,
surface->finished = FALSE;
_cairo_user_data_array_init (&surface->user_data);
+ _cairo_user_data_array_init (&surface->mime_data);
cairo_matrix_init_identity (&surface->device_transform);
cairo_matrix_init_identity (&surface->device_transform_inverse);
@@ -437,6 +440,7 @@ cairo_surface_destroy (cairo_surface_t *surface)
cairo_surface_finish (surface);
_cairo_user_data_array_fini (&surface->user_data);
+ _cairo_user_data_array_fini (&surface->mime_data);
free (surface);
}
@@ -459,6 +463,7 @@ _cairo_surface_reset (cairo_surface_t *surface)
assert (CAIRO_REFERENCE_COUNT_GET_VALUE (&surface->ref_count) == 1);
_cairo_user_data_array_fini (&surface->user_data);
+ _cairo_user_data_array_fini (&surface->mime_data);
if (surface->backend->reset != NULL) {
cairo_status_t status = surface->backend->reset (surface);
@@ -620,7 +625,7 @@ cairo_surface_get_mime_data (cairo_surface_t *surface,
return;
}
- mime_data = _cairo_user_data_array_get_data (&surface->user_data,
+ mime_data = _cairo_user_data_array_get_data (&surface->mime_data,
(cairo_user_data_key_t *) mime_type);
if (mime_data == NULL)
return;
@@ -696,7 +701,7 @@ cairo_surface_set_mime_data (cairo_surface_t *surface,
} else
mime_data = NULL;
- status = _cairo_user_data_array_set_data (&surface->user_data,
+ status = _cairo_user_data_array_set_data (&surface->mime_data,
(cairo_user_data_key_t *) mime_type,
mime_data,
_cairo_mime_data_destroy);
@@ -711,13 +716,19 @@ cairo_surface_set_mime_data (cairo_surface_t *surface,
}
slim_hidden_def (cairo_surface_set_mime_data);
+static void
+_cairo_mime_data_reference (const void *key, void *elt, void *closure)
+{
+ cairo_mime_data_t *mime_data = elt;
+
+ _cairo_reference_count_inc (&mime_data->ref_count);
+}
+
cairo_status_t
_cairo_surface_copy_mime_data (cairo_surface_t *dst,
- cairo_surface_t *src,
- const char *mime_type)
+ cairo_surface_t *src)
{
cairo_status_t status;
- cairo_mime_data_t *mime_data;
if (dst->status)
return dst->status;
@@ -725,25 +736,15 @@ _cairo_surface_copy_mime_data (cairo_surface_t *dst,
if (src->status)
return _cairo_surface_set_error (dst, src->status);
- status = _cairo_intern_string (&mime_type, -1);
+ /* first copy the mime-data, discarding any already set on dst */
+ status = _cairo_user_data_array_copy (&dst->mime_data, &src->mime_data);
if (unlikely (status))
return _cairo_surface_set_error (dst, status);
- mime_data = _cairo_user_data_array_get_data (&src->user_data,
- (cairo_user_data_key_t *) mime_type);
- if (mime_data == NULL)
- return CAIRO_STATUS_SUCCESS;
-
- _cairo_reference_count_inc (&mime_data->ref_count);
-
- status = _cairo_user_data_array_set_data (&dst->user_data,
- (cairo_user_data_key_t *) mime_type,
- mime_data,
- _cairo_mime_data_destroy);
- if (unlikely (status)) {
- _cairo_mime_data_destroy (mime_data);
- return _cairo_surface_set_error (dst, status);
- }
+ /* now increment the reference counters for the copies */
+ _cairo_user_data_array_foreach (&dst->mime_data,
+ _cairo_mime_data_reference,
+ NULL);
return CAIRO_STATUS_SUCCESS;
}
@@ -1153,6 +1154,8 @@ _cairo_surface_acquire_source_image (cairo_surface_t *surface,
cairo_image_surface_t **image_out,
void **image_extra)
{
+ cairo_status_t status;
+
if (surface->status)
return surface->status;
@@ -1161,9 +1164,14 @@ _cairo_surface_acquire_source_image (cairo_surface_t *surface,
if (surface->backend->acquire_source_image == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
- return _cairo_surface_set_error (surface,
- surface->backend->acquire_source_image (surface,
- image_out, image_extra));
+ status = surface->backend->acquire_source_image (surface,
+ image_out, image_extra);
+ if (unlikely (status))
+ return _cairo_surface_set_error (surface, status);
+
+ _cairo_debug_check_image_surface_is_defined (&(*image_out)->base);
+
+ return CAIRO_STATUS_SUCCESS;
}
/**
@@ -1222,6 +1230,8 @@ _cairo_surface_acquire_dest_image (cairo_surface_t *surface,
cairo_rectangle_int_t *image_rect,
void **image_extra)
{
+ cairo_status_t status;
+
if (surface->status)
return surface->status;
@@ -1230,12 +1240,17 @@ _cairo_surface_acquire_dest_image (cairo_surface_t *surface,
if (surface->backend->acquire_dest_image == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
- return _cairo_surface_set_error (surface,
- surface->backend->acquire_dest_image (surface,
- interest_rect,
- image_out,
- image_rect,
- image_extra));
+ status = surface->backend->acquire_dest_image (surface,
+ interest_rect,
+ image_out,
+ image_rect,
+ image_extra);
+ if (unlikely (status))
+ return _cairo_surface_set_error (surface, status);
+
+ _cairo_debug_check_image_surface_is_defined (&(*image_out)->base);
+
+ return CAIRO_STATUS_SUCCESS;
}
/**
@@ -1268,6 +1283,7 @@ _cairo_surface_release_dest_image (cairo_surface_t *surface,
* _cairo_surface_clone_similar:
* @surface: a #cairo_surface_t
* @src: the source image
+ * @content: target content mask
* @src_x: extent for the rectangle in src we actually care about
* @src_y: extent for the rectangle in src we actually care about
* @width: extent for the rectangle in src we actually care about
@@ -1287,6 +1303,7 @@ _cairo_surface_release_dest_image (cairo_surface_t *surface,
cairo_status_t
_cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_surface_t *src,
+ cairo_content_t content,
int src_x,
int src_y,
int width,
@@ -1307,6 +1324,7 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
if (surface->backend->clone_similar) {
status = surface->backend->clone_similar (surface, src,
+ content,
src_x, src_y,
width, height,
clone_offset_x,
@@ -1314,12 +1332,15 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
clone_out);
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+ if (_cairo_surface_is_image (src))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
/* First check to see if we can replay to a similar surface */
if (_cairo_surface_is_meta (src)) {
cairo_surface_t *similar;
similar = cairo_surface_create_similar (surface,
- src->content,
+ src->content & content,
width, height);
status = similar->status;
if (unlikely (status))
@@ -1344,6 +1365,7 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
if (status == CAIRO_STATUS_SUCCESS) {
status =
surface->backend->clone_similar (surface, &image->base,
+ content,
src_x, src_y,
width, height,
clone_offset_x,
@@ -1356,14 +1378,16 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
}
/* If we're still unsupported, hit our fallback path to get a clone */
- if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
status =
_cairo_surface_fallback_clone_similar (surface, src,
+ content,
src_x, src_y,
width, height,
clone_offset_x,
clone_offset_y,
clone_out);
+ }
/* We should never get UNSUPPORTED here, so if we have an error, bail. */
if (unlikely (status))
@@ -1399,16 +1423,40 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_surface_t *
_cairo_surface_snapshot (cairo_surface_t *surface)
{
+ cairo_surface_t *snapshot;
+ cairo_status_t status;
+
if (surface->status)
return _cairo_surface_create_in_error (surface->status);
if (surface->finished)
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
- if (surface->backend->snapshot)
- return surface->backend->snapshot (surface);
+ if (surface->is_snapshot)
+ return cairo_surface_reference (surface);
+
+ snapshot = NULL;
+ if (surface->backend->snapshot != NULL)
+ snapshot = surface->backend->snapshot (surface);
+
+ if (snapshot == NULL)
+ snapshot = _cairo_surface_fallback_snapshot (surface);
+
+ if (unlikely (snapshot->status))
+ return snapshot;
+
+ status = _cairo_surface_copy_mime_data (snapshot, surface);
+ if (unlikely (status)) {
+ cairo_surface_destroy (snapshot);
+ return _cairo_surface_create_in_error (status);
+ }
- return _cairo_surface_fallback_snapshot (surface);
+ snapshot->device_transform = surface->device_transform;
+ snapshot->device_transform_inverse = surface->device_transform_inverse;
+
+ snapshot->is_snapshot = TRUE;
+
+ return snapshot;
}
/**
@@ -1546,16 +1594,14 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
*
* Return value: %CAIRO_STATUS_SUCCESS or the error that occurred
**/
-COMPILE_TIME_ASSERT (sizeof (cairo_box_int_t) <= sizeof (cairo_rectangle_int_t));
cairo_status_t
_cairo_surface_fill_region (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_region_t *region)
{
- int num_boxes;
+ int num_rects;
cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
- cairo_box_int_t *boxes = (cairo_box_int_t *) stack_rects;
cairo_rectangle_int_t *rects = stack_rects;
cairo_status_t status;
int i;
@@ -1565,41 +1611,24 @@ _cairo_surface_fill_region (cairo_surface_t *surface,
assert (! surface->is_snapshot);
- num_boxes = _cairo_region_num_boxes (region);
- if (num_boxes == 0)
+ num_rects = cairo_region_num_rectangles (region);
+ if (num_rects == 0)
return CAIRO_STATUS_SUCCESS;
- /* handle the common case of a single box without allocation */
- if (num_boxes > 1) {
- num_boxes = sizeof (stack_rects) / sizeof (cairo_box_int_t);
- status = _cairo_region_get_boxes (region, &num_boxes, &boxes);
- if (unlikely (status))
- return status;
-
- if (num_boxes > ARRAY_LENGTH (stack_rects)) {
- rects = _cairo_malloc_ab (num_boxes,
- sizeof (cairo_rectangle_int_t));
- if (rects == NULL) {
- _cairo_region_boxes_fini (region, boxes);
- return _cairo_surface_set_error (surface,
- _cairo_error (CAIRO_STATUS_NO_MEMORY));
- }
+ if (num_rects > ARRAY_LENGTH (stack_rects)) {
+ rects = _cairo_malloc_ab (num_rects,
+ sizeof (cairo_rectangle_int_t));
+ if (rects == NULL) {
+ return _cairo_surface_set_error (surface,
+ _cairo_error (CAIRO_STATUS_NO_MEMORY));
}
+ }
- for (i = 0; i < num_boxes; i++) {
- rects[i].x = boxes[i].p1.x;
- rects[i].y = boxes[i].p1.y;
- rects[i].width = boxes[i].p2.x - rects[i].x;
- rects[i].height = boxes[i].p2.y - rects[i].y;
- }
- } else
- _cairo_region_get_extents (region, &rects[0]);
+ for (i = 0; i < num_rects; i++)
+ cairo_region_get_rectangle (region, i, &rects[i]);
status = _cairo_surface_fill_rectangles (surface, op,
- color, rects, num_boxes);
-
- if (boxes != (cairo_box_int_t *) stack_rects)
- _cairo_region_boxes_fini (region, boxes);
+ color, rects, num_rects);
if (rects != stack_rects)
free (rects);
@@ -2187,10 +2216,10 @@ _cairo_surface_reset_clip (cairo_surface_t *surface)
cairo_status_t
_cairo_surface_set_clip_region (cairo_surface_t *surface,
cairo_region_t *region,
- unsigned int serial)
+ unsigned int serial)
{
cairo_status_t status;
-
+
if (surface->status)
return surface->status;
@@ -2367,7 +2396,7 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
if (surface->backend->set_clip_region != NULL)
return _cairo_surface_set_clip_region (surface,
- &clip->region,
+ clip->region,
clip->serial);
} else {
if (clip->path)
@@ -2375,9 +2404,9 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
clip->path,
clip->serial);
- if (clip->has_region)
+ if (clip->region)
return _cairo_surface_set_clip_region (surface,
- &clip->region,
+ clip->region,
clip->serial);
}
}
@@ -2673,53 +2702,44 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst,
unsigned int height)
{
cairo_rectangle_int_t dst_rectangle;
- cairo_rectangle_int_t drawn_rectangle;
- cairo_bool_t has_drawn_region = FALSE;
- cairo_region_t drawn_region;
- cairo_region_t clear_region;
+ cairo_region_t *clear_region;
cairo_status_t status;
- /* The area that was drawn is the area in the destination rectangle but not within
- * the source or the mask.
+ /* The area that was drawn is the area in the destination rectangle but
+ * not within the source or the mask.
*/
dst_rectangle.x = dst_x;
dst_rectangle.y = dst_y;
dst_rectangle.width = width;
dst_rectangle.height = height;
- _cairo_region_init_rect (&clear_region, &dst_rectangle);
- drawn_rectangle = dst_rectangle;
+ clear_region = cairo_region_create_rectangle (&dst_rectangle);
+ status = clear_region->status;
+ if (unlikely (status))
+ goto CLEANUP_REGIONS;
if (src_rectangle) {
- if (! _cairo_rectangle_intersect (&drawn_rectangle, src_rectangle))
+ if (! _cairo_rectangle_intersect (&dst_rectangle, src_rectangle))
goto EMPTY;
}
if (mask_rectangle) {
- if (! _cairo_rectangle_intersect (&drawn_rectangle, mask_rectangle))
+ if (! _cairo_rectangle_intersect (&dst_rectangle, mask_rectangle))
goto EMPTY;
}
- /* Now compute the area that is in dst_rectangle but not in drawn_rectangle
- */
- _cairo_region_init_rect (&drawn_region, &drawn_rectangle);
- has_drawn_region = TRUE;
-
- status = _cairo_region_subtract (&clear_region,
- &clear_region,
- &drawn_region);
+ /* Now compute the area that is in dst but not drawn */
+ status = cairo_region_subtract_rectangle (clear_region, &dst_rectangle);
if (unlikely (status))
goto CLEANUP_REGIONS;
EMPTY:
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_SOURCE,
CAIRO_COLOR_TRANSPARENT,
- &clear_region);
+ clear_region);
CLEANUP_REGIONS:
- if (has_drawn_region)
- _cairo_region_fini (&drawn_region);
- _cairo_region_fini (&clear_region);
+ cairo_region_destroy (clear_region);
return _cairo_surface_set_error (dst, status);
}
@@ -2952,7 +2972,10 @@ _cairo_surface_create_in_error (cairo_status_t status)
return (cairo_surface_t *) &_cairo_surface_nil_temp_file_error;
case CAIRO_STATUS_INVALID_STRIDE:
return (cairo_surface_t *) &_cairo_surface_nil_invalid_stride;
+ case CAIRO_STATUS_INVALID_SIZE:
+ return (cairo_surface_t *) &_cairo_surface_nil_invalid_size;
case CAIRO_STATUS_SUCCESS:
+ case CAIRO_STATUS_LAST_STATUS:
ASSERT_NOT_REACHED;
/* fall-through */
case CAIRO_STATUS_INVALID_RESTORE:
@@ -2977,7 +3000,7 @@ _cairo_surface_create_in_error (cairo_status_t status)
case CAIRO_STATUS_INVALID_CLUSTERS:
case CAIRO_STATUS_INVALID_SLANT:
case CAIRO_STATUS_INVALID_WEIGHT:
- case CAIRO_STATUS_INVALID_SIZE:
+ case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
default:
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t *) &_cairo_surface_nil;
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index db554a10..7a35fab9 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -1025,6 +1025,8 @@ _cairo_surface_base64_encode_png (cairo_surface_t *surface,
cairo_surface_get_mime_data (surface, CAIRO_MIME_TYPE_PNG,
&mime_data, &mime_data_length);
+ if (unlikely (surface->status))
+ return surface->status;
if (mime_data == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
diff --git a/src/cairo-tor-scan-converter.c b/src/cairo-tor-scan-converter.c
index 087f0108..4abafc41 100644
--- a/src/cairo-tor-scan-converter.c
+++ b/src/cairo-tor-scan-converter.c
@@ -320,7 +320,6 @@ struct _pool_chunk {
struct _pool_chunk *prev_chunk;
/* Actual data starts here. Well aligned for pointers. */
- unsigned char data[0];
};
/* A memory pool. This is supposed to be embedded on the stack or
@@ -623,7 +622,7 @@ _pool_alloc_from_new_chunk(
}
pool->current = chunk;
- obj = &chunk->data[chunk->size];
+ obj = ((unsigned char*)chunk + sizeof(*chunk) + chunk->size);
chunk->size += size;
return obj;
}
@@ -642,7 +641,7 @@ pool_alloc(
struct _pool_chunk *chunk = pool->current;
if (size <= chunk->capacity - chunk->size) {
- void *obj = &chunk->data[chunk->size];
+ void *obj = ((unsigned char*)chunk + sizeof(*chunk) + chunk->size);
chunk->size += size;
return obj;
}
diff --git a/src/cairo-toy-font-face.c b/src/cairo-toy-font-face.c
index 05ad495d..b2d41af3 100644
--- a/src/cairo-toy-font-face.c
+++ b/src/cairo-toy-font-face.c
@@ -325,6 +325,7 @@ cairo_toy_font_face_create (const char *family,
if (unlikely (status))
goto UNWIND_FONT_FACE_MALLOC;
+ assert (font_face->base.hash_entry.hash == key.base.hash_entry.hash);
status = _cairo_hash_table_insert (hash_table, &font_face->base.hash_entry);
if (unlikely (status))
goto UNWIND_FONT_FACE_INIT;
diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index 0afdce23..fed3f101 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -131,6 +131,11 @@ _cairo_traps_grow (cairo_traps_t *traps)
cairo_trapezoid_t *new_traps;
int new_size = 2 * MAX (traps->traps_size, 16);
+ if (CAIRO_INJECT_FAULT ()) {
+ traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return FALSE;
+ }
+
if (traps->traps == traps->traps_embedded) {
new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
if (new_traps != NULL)
@@ -600,7 +605,7 @@ _cairo_traps_extents (const cairo_traps_t *traps,
* Determines if a set of trapezoids are exactly representable as a
* cairo region. If so, the passed-in region is initialized to
* the area representing the given traps. It should be finalized
- * with _cairo_region_fini(). If not, %CAIRO_INT_STATUS_UNSUPPORTED
+ * with cairo_region_fini(). If not, %CAIRO_INT_STATUS_UNSUPPORTED
* is returned.
*
* Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
@@ -608,17 +613,11 @@ _cairo_traps_extents (const cairo_traps_t *traps,
**/
cairo_int_status_t
_cairo_traps_extract_region (const cairo_traps_t *traps,
- cairo_region_t *region)
+ cairo_region_t **region)
{
- cairo_box_int_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (cairo_box_int_t)];
- cairo_box_int_t *boxes = stack_boxes;
- int i, box_count;
cairo_int_status_t status;
-
- if (traps->num_traps == 0) {
- _cairo_region_init (region);
- return CAIRO_STATUS_SUCCESS;
- }
+ cairo_region_t *r;
+ int i;
for (i = 0; i < traps->num_traps; i++) {
if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x ||
@@ -632,16 +631,13 @@ _cairo_traps_extract_region (const cairo_traps_t *traps,
}
}
- if (traps->num_traps > ARRAY_LENGTH (stack_boxes)) {
- boxes = _cairo_malloc_ab (traps->num_traps, sizeof (cairo_box_int_t));
-
- if (unlikely (boxes == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
-
- box_count = 0;
+ r = cairo_region_create ();
+ if (unlikely (r->status))
+ return r->status;
for (i = 0; i < traps->num_traps; i++) {
+ cairo_rectangle_int_t rect;
+
int x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
int y1 = _cairo_fixed_integer_part (traps->traps[i].top);
int x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
@@ -653,23 +649,20 @@ _cairo_traps_extract_region (const cairo_traps_t *traps,
if (x1 == x2 || y1 == y2)
continue;
- boxes[box_count].p1.x = x1;
- boxes[box_count].p1.y = y1;
- boxes[box_count].p2.x = x2;
- boxes[box_count].p2.y = y2;
+ rect.x = x1;
+ rect.y = y1;
+ rect.width = x2 - x1;
+ rect.height = y2 - y1;
- box_count++;
+ status = cairo_region_union_rectangle (r, &rect);
+ if (unlikely (status)) {
+ cairo_region_destroy (r);
+ return status;
+ }
}
- status = _cairo_region_init_boxes (region, boxes, box_count);
-
- if (boxes != stack_boxes)
- free (boxes);
-
- if (unlikely (status))
- _cairo_region_fini (region);
-
- return status;
+ *region = r;
+ return CAIRO_STATUS_SUCCESS;
}
/* moves trap points such that they become the actual corners of the trapezoid */
diff --git a/src/cairo-truetype-subset-private.h b/src/cairo-truetype-subset-private.h
index 397a9f38..978256f6 100644
--- a/src/cairo-truetype-subset-private.h
+++ b/src/cairo-truetype-subset-private.h
@@ -185,7 +185,7 @@ typedef struct _tt_name {
typedef struct _tt_composite_glyph {
uint16_t flags;
uint16_t index;
- uint16_t args[7]; /* 1 to 7 arguments depending on value of flags */
+ uint16_t args[6]; /* 1 to 6 arguments depending on value of flags */
} tt_composite_glyph_t;
typedef struct _tt_glyph_data {
diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index d01b0895..92c05477 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -94,6 +94,21 @@ struct _cairo_truetype_font {
};
+/*
+ * Test that the structs we define for TrueType tables have the
+ * correct size, ie. they are not padded.
+ */
+#define check(T, S) COMPILE_TIME_ASSERT (sizeof (T) == (S))
+check (tt_head_t, 54);
+check (tt_hhea_t, 36);
+check (tt_maxp_t, 32);
+check (tt_name_record_t, 12);
+check (tt_name_t, 18);
+check (tt_name_t, 18);
+check (tt_composite_glyph_t, 16);
+check (tt_glyph_data_t, 26);
+#undef check
+
static cairo_status_t
cairo_truetype_font_use_glyph (cairo_truetype_font_t *font,
unsigned short glyph,
@@ -480,7 +495,7 @@ cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font,
composite_glyph = &glyph_data->glyph;
do {
- if ((unsigned char *)(&composite_glyph->args[1]) >= end)
+ if ((unsigned char *)(&composite_glyph->args[1]) > end)
return CAIRO_INT_STATUS_UNSUPPORTED;
flags = be16_to_cpu (composite_glyph->flags);
@@ -493,13 +508,15 @@ cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font,
num_args = 1;
if (flags & TT_ARG_1_AND_2_ARE_WORDS)
num_args += 1;
- if (flags & TT_WE_HAVE_A_SCALE)
+
+ if (flags & TT_WE_HAVE_A_SCALE)
num_args += 1;
else if (flags & TT_WE_HAVE_AN_X_AND_Y_SCALE)
num_args += 2;
else if (flags & TT_WE_HAVE_A_TWO_BY_TWO)
- num_args += 3;
- composite_glyph = (tt_composite_glyph_t *) &(composite_glyph->args[num_args]);
+ num_args += 4;
+
+ composite_glyph = (tt_composite_glyph_t *) &(composite_glyph->args[num_args]);
} while (has_more_components);
return CAIRO_STATUS_SUCCESS;
@@ -630,7 +647,7 @@ cairo_truetype_font_write_head_table (cairo_truetype_font_t *font,
if (unlikely (status))
return _cairo_truetype_font_set_error (font, status);
- /* set checkSumAdjustment to 0 for table checksum calcualtion */
+ /* set checkSumAdjustment to 0 for table checksum calculation */
*(uint32_t *)(buffer + 8) = 0;
return CAIRO_STATUS_SUCCESS;
@@ -1314,8 +1331,8 @@ _cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font,
tt_name_record_t *record;
unsigned long size;
int i, j;
- char *ps_name;
- char *font_name;
+ char *ps_name = NULL;
+ char *font_name = NULL;
backend = scaled_font->backend;
if (!backend->load_truetype_table)
@@ -1345,8 +1362,6 @@ _cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font,
* name. It should be extended to use any suitable font name in
* the name table.
*/
- ps_name = NULL;
- font_name = NULL;
for (i = 0; i < be16_to_cpu(name->num_records); i++) {
record = &(name->records[i]);
if ((be16_to_cpu (record->platform) == 1) &&
@@ -1400,6 +1415,13 @@ _cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font,
fail:
free (name);
+
+ if (ps_name != NULL)
+ free (ps_name);
+
+ if (font_name != NULL)
+ free (font_name);
+
*ps_name_out = NULL;
*font_name_out = NULL;
diff --git a/src/cairo-type1-fallback.c b/src/cairo-type1-fallback.c
index 2b6768dc..1023bbdc 100644
--- a/src/cairo-type1-fallback.c
+++ b/src/cairo-type1-fallback.c
@@ -449,14 +449,14 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
/* four "random" bytes required by encryption algorithm */
status = _cairo_array_append_multiple (&data, zeros, 4);
if (unlikely (status))
- goto fail;
+ break;
status = cairo_type1_font_create_charstring (font, i,
font->scaled_font_subset->glyphs[i],
CAIRO_CHARSTRING_TYPE1,
&data);
if (unlikely (status))
- goto fail;
+ break;
charstring_encrypt (&data);
length = _cairo_array_num_elements (&data);
@@ -474,9 +474,9 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
length);
_cairo_output_stream_printf (encrypted_output, " ND\n");
}
+ _cairo_scaled_font_thaw_cache (font->type1_scaled_font);
fail:
- _cairo_scaled_font_thaw_cache (font->type1_scaled_font);
_cairo_array_fini (&data);
return status;
}
diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index 3ff5003b..104da53d 100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -46,14 +46,17 @@
static const cairo_surface_backend_t cairo_type3_glyph_surface_backend;
cairo_surface_t *
-_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
- cairo_output_stream_t *stream,
+_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
+ cairo_output_stream_t *stream,
cairo_type3_glyph_surface_emit_image_t emit_image,
- cairo_scaled_font_subsets_t *font_subsets)
+ cairo_scaled_font_subsets_t *font_subsets)
{
cairo_type3_glyph_surface_t *surface;
cairo_matrix_t invert_y_axis;
+ if (unlikely (stream != NULL && stream->status))
+ return _cairo_surface_create_in_error (stream->status);
+
surface = malloc (sizeof (cairo_type3_glyph_surface_t));
if (unlikely (surface == NULL))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
@@ -88,6 +91,12 @@ _cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface,
{
cairo_status_t status;
+ /* The only image type supported by Type 3 fonts are 1-bit masks */
+ image = _cairo_image_surface_coerce (image, CAIRO_FORMAT_A1);
+ status = image->base.status;
+ if (unlikely (status))
+ return status;
+
_cairo_output_stream_printf (surface->stream,
"q %f %f %f %f %f %f cm\n",
image_matrix->xx,
@@ -97,8 +106,6 @@ _cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface,
image_matrix->x0,
image_matrix->y0);
- /* The only image type supported by Type 3 fonts are 1-bit masks */
- image = _cairo_image_surface_coerce (image, CAIRO_FORMAT_A1);
status = surface->emit_image (image, surface->stream);
cairo_surface_destroy (&image->base);
@@ -278,6 +285,8 @@ _cairo_type3_glyph_surface_show_glyphs (void *abstract_surface,
&scaled_font->font_matrix,
&new_ctm,
&scaled_font->options);
+ if (unlikely (font->status))
+ return font->status;
status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
NULL, 0,
@@ -375,6 +384,9 @@ _cairo_type3_glyph_surface_set_font_subsets_callback (void *abstract
{
cairo_type3_glyph_surface_t *surface = abstract_surface;
+ if (unlikely (surface->base.status))
+ return;
+
_cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
use_font_subset,
closure);
@@ -389,7 +401,13 @@ _cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface,
cairo_status_t status, status2;
cairo_output_stream_t *null_stream;
+ if (unlikely (surface->base.status))
+ return surface->base.status;
+
null_stream = _cairo_null_stream_create ();
+ if (unlikely (null_stream->status))
+ return null_stream->status;
+
_cairo_type3_glyph_surface_set_stream (surface, null_stream);
_cairo_scaled_font_freeze_cache (surface->scaled_font);
@@ -442,6 +460,9 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
double x_advance, y_advance;
cairo_matrix_t font_matrix_inverse;
+ if (unlikely (surface->base.status))
+ return surface->base.status;
+
_cairo_type3_glyph_surface_set_stream (surface, stream);
_cairo_scaled_font_freeze_cache (surface->scaled_font);
@@ -492,6 +513,10 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
cairo_output_stream_t *mem_stream;
mem_stream = _cairo_memory_stream_create ();
+ status = mem_stream->status;
+ if (unlikely (status))
+ goto FAIL;
+
_cairo_type3_glyph_surface_set_stream (surface, mem_stream);
_cairo_output_stream_printf (surface->stream, "q\n");
@@ -516,6 +541,7 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
status = _cairo_type3_glyph_surface_emit_fallback_image (surface, glyph_index);
+ FAIL:
_cairo_scaled_font_thaw_cache (surface->scaled_font);
return status;
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index 149d894e..bb62351d 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -59,7 +59,6 @@ typedef struct _cairo_output_stream cairo_output_stream_t;
typedef struct _cairo_paginated_surface_backend cairo_paginated_surface_backend_t;
typedef struct _cairo_path_fixed cairo_path_fixed_t;
typedef struct _cairo_rectangle_int16 cairo_glyph_size_t;
-typedef struct _cairo_region cairo_region_t;
typedef struct _cairo_scaled_font_backend cairo_scaled_font_backend_t;
typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t;
typedef struct _cairo_solid_pattern cairo_solid_pattern_t;
@@ -123,9 +122,12 @@ struct _cairo_font_options {
cairo_hint_metrics_t hint_metrics;
};
+typedef cairo_bool_t (*cairo_cache_predicate_func_t) (const void *entry);
+
struct _cairo_cache {
cairo_hash_table_t *hash_table;
+ cairo_cache_predicate_func_t predicate;
cairo_destroy_func_t entry_destroy;
unsigned long max_size;
@@ -215,43 +217,12 @@ typedef struct _cairo_trapezoid {
cairo_line_t left, right;
} cairo_trapezoid_t;
-struct _cairo_rectangle_int16 {
- int16_t x, y;
- uint16_t width, height;
-};
-
-struct _cairo_rectangle_int32 {
- int32_t x, y;
- uint32_t width, height;
-};
-
-struct _cairo_point_int16 {
- int16_t x, y;
-};
-
-struct _cairo_point_int32 {
- int32_t x, y;
-};
-
-#if CAIRO_FIXED_BITS == 32 && CAIRO_FIXED_FRAC_BITS >= 16
-typedef struct _cairo_rectangle_int16 cairo_rectangle_int_t;
-typedef struct _cairo_point_int16 cairo_point_int_t;
-#define CAIRO_RECT_INT_MIN (INT16_MIN >> (CAIRO_FIXED_FRAC_BITS - 16))
-#define CAIRO_RECT_INT_MAX (INT16_MAX >> (CAIRO_FIXED_FRAC_BITS - 16))
-#elif CAIRO_FIXED_BITS == 32
-typedef struct _cairo_rectangle_int32 cairo_rectangle_int_t;
-typedef struct _cairo_point_int32 cairo_point_int_t;
-#define CAIRO_RECT_INT_MIN (INT32_MIN >> CAIRO_FIXED_FRAC_BITS)
-#define CAIRO_RECT_INT_MAX (INT32_MAX >> CAIRO_FIXED_FRAC_BITS)
-#else
-#error Not sure how to pick a cairo_rectangle_int_t and cairo_point_int_t for your CAIRO_FIXED_BITS!
-#endif
-
-typedef struct _cairo_box_int {
- cairo_point_int_t p1;
- cairo_point_int_t p2;
-} cairo_box_int_t;
+typedef struct _cairo_point_int {
+ int x, y;
+} cairo_point_int_t;
+#define CAIRO_RECT_INT_MIN (INT_MIN >> CAIRO_FIXED_FRAC_BITS)
+#define CAIRO_RECT_INT_MAX (INT_MAX >> CAIRO_FIXED_FRAC_BITS)
/* Rectangles that take part in a composite operation.
*
diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index fe475ab4..6b4f0d43 100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -118,7 +118,7 @@ _cairo_user_scaled_glyph_init (void *abstract_font,
_cairo_scaled_glyph_index(scaled_glyph),
cr, &extents);
else
- status = CAIRO_STATUS_USER_FONT_ERROR;
+ status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
if (status == CAIRO_STATUS_SUCCESS)
status = cairo_status (cr);
@@ -260,12 +260,16 @@ _cairo_user_ucs4_to_index (void *abstract_font,
status = face->scaled_font_methods.unicode_to_glyph (&scaled_font->base,
ucs4, &glyph);
+ if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
+ goto not_implemented;
+
if (status != CAIRO_STATUS_SUCCESS) {
status = _cairo_scaled_font_set_error (&scaled_font->base, status);
glyph = 0;
}
} else {
+not_implemented:
glyph = ucs4;
}
@@ -300,10 +304,11 @@ _cairo_user_text_to_glyphs (void *abstract_font,
glyphs, num_glyphs,
clusters, num_clusters, cluster_flags);
- if (status != CAIRO_STATUS_SUCCESS)
+ if (status != CAIRO_STATUS_SUCCESS &&
+ status != CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
return status;
- if (*num_glyphs < 0) {
+ if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED || *num_glyphs < 0) {
if (orig_glyphs != *glyphs) {
cairo_glyph_free (*glyphs);
*glyphs = orig_glyphs;
@@ -434,6 +439,9 @@ _cairo_user_font_face_scaled_font_create (void *abstract_
cr,
&font_extents);
+ if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
+ status = CAIRO_STATUS_SUCCESS;
+
if (status == CAIRO_STATUS_SUCCESS)
status = cairo_status (cr);
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index e9abfda0..d99c2613 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -1180,12 +1180,12 @@ _add_glyph (cairo_glyph_state_t *state,
if (status)
return status;
state->start_x = logical_x;
+ } else {
+ dx = logical_x - state->last_x;
+ status = _cairo_array_append (&state->dx, &dx);
+ if (status)
+ return status;
}
-
- dx = logical_x - state->last_x;
- status = _cairo_array_append (&state->dx, &dx);
- if (status)
- return status;
} else {
state->start_x = logical_x;
}
@@ -1543,6 +1543,7 @@ _cairo_win32_scaled_font_index_to_ucs4 (void *abstract_font,
goto exit1;
}
+ *ucs4 = (uint32_t) -1;
for (i = 0; i < glyph_set->cRanges; i++) {
num_glyphs = glyph_set->ranges[i].cGlyphs;
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 989f0186..e7ff3bb6 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -722,7 +722,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
_cairo_matrix_to_win32_xform (&m, &xform);
if (! SetWorldTransform (surface->dc, &xform)) {
- status = _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform");
+ status = _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint_image_pattern");
goto CLEANUP_OPAQUE_IMAGE;
}
@@ -1451,6 +1451,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
* If we are printing a bitmap font, use fallback images to
* ensure the font is not substituted.
*/
+#if CAIRO_HAS_WIN32_FONT
if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32) {
if (_cairo_win32_scaled_font_is_bitmap (scaled_font))
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1472,6 +1473,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
if (status)
return status;
}
+#endif
return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
}
@@ -1490,6 +1492,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
source = opaque;
}
+#if CAIRO_HAS_WIN32_FONT
if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32 &&
source->type == CAIRO_PATTERN_TYPE_SOLID)
{
@@ -1554,6 +1557,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
return status;
}
+#endif
SaveDC (surface->dc);
old_ctm = surface->ctm;
diff --git a/src/cairo-win32-private.h b/src/cairo-win32-private.h
index 51564d04..40ed20ef 100644
--- a/src/cairo-win32-private.h
+++ b/src/cairo-win32-private.h
@@ -163,6 +163,7 @@ _cairo_win32_surface_create_similar (void *abstract_src,
cairo_status_t
_cairo_win32_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
+ cairo_content_t content,
int src_x,
int src_y,
int width,
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 03a8f61a..389515be 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -431,6 +431,7 @@ _cairo_win32_surface_create_similar (void *abstract_src,
cairo_status_t
_cairo_win32_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
+ cairo_content_t content,
int src_x,
int src_y,
int width,
@@ -444,7 +445,7 @@ _cairo_win32_surface_clone_similar (void *abstract_surface,
cairo_status_t status;
cairo_surface_pattern_t pattern;
- src_content = cairo_surface_get_content(src);
+ src_content = src->content & content;
new_surface =
_cairo_win32_surface_create_similar_internal (abstract_surface,
src_content,
@@ -1461,38 +1462,36 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
/* Then combine any new region with it */
if (region) {
cairo_rectangle_int_t extents;
- cairo_box_int_t *boxes;
- int num_boxes;
+ int num_rects;
RGNDATA *data;
size_t data_size;
RECT *rects;
int i;
HRGN gdi_region;
+ cairo_rectangle_int_t rect0;
/* Create a GDI region for the cairo region */
- _cairo_region_get_extents (region, &extents);
- num_boxes = 0;
- status = _cairo_region_get_boxes (region, &num_boxes, &boxes);
- if (status)
- return status;
-
- if (num_boxes == 1 &&
- boxes[0].p1.x == 0 &&
- boxes[0].p1.y == 0 &&
- boxes[0].p2.x == surface->extents.width &&
- boxes[0].p2.y == surface->extents.height)
+ cairo_region_get_extents (region, &extents);
+ num_rects = cairo_region_num_rectangles (region);
+
+ if (num_rects == 1)
+ cairo_region_get_rectangle (region, 0, &rect0);
+
+ if (num_rects == 1 &&
+ rect0.x == 0 &&
+ rect0.y == 0 &&
+ rect0.width == surface->extents.width &&
+ rect0.width == surface->extents.height)
{
gdi_region = NULL;
-
+
SelectClipRgn (surface->dc, NULL);
IntersectClipRect (surface->dc,
- boxes[0].p1.x,
- boxes[0].p1.y,
- boxes[0].p2.x,
- boxes[0].p2.y);
-
- _cairo_region_boxes_fini (region, boxes);
+ rect0.x,
+ rect0.y,
+ rect0.x + rect0.width,
+ rect0.y + rect0.height);
} else {
/* XXX see notes in _cairo_win32_save_initial_clip --
* this code will interact badly with a HDC which had an initial
@@ -1501,31 +1500,31 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
* logical units (unlike IntersectClipRect).
*/
- data_size = sizeof (RGNDATAHEADER) + num_boxes * sizeof (RECT);
+ data_size = sizeof (RGNDATAHEADER) + num_rects * sizeof (RECT);
data = malloc (data_size);
- if (!data) {
- _cairo_region_boxes_fini (region, boxes);
+ if (!data)
return _cairo_error(CAIRO_STATUS_NO_MEMORY);
- }
rects = (RECT *)data->Buffer;
data->rdh.dwSize = sizeof (RGNDATAHEADER);
data->rdh.iType = RDH_RECTANGLES;
- data->rdh.nCount = num_boxes;
- data->rdh.nRgnSize = num_boxes * sizeof (RECT);
+ data->rdh.nCount = num_rects;
+ data->rdh.nRgnSize = num_rects * sizeof (RECT);
data->rdh.rcBound.left = extents.x;
data->rdh.rcBound.top = extents.y;
data->rdh.rcBound.right = extents.x + extents.width;
data->rdh.rcBound.bottom = extents.y + extents.height;
- for (i = 0; i < num_boxes; i++) {
- rects[i].left = boxes[i].p1.x;
- rects[i].top = boxes[i].p1.y;
- rects[i].right = boxes[i].p2.x;
- rects[i].bottom = boxes[i].p2.y;
- }
+ for (i = 0; i < num_rects; i++) {
+ cairo_rectangle_int_t rect;
- _cairo_region_boxes_fini (region, boxes);
+ cairo_region_get_rectangle (region, i, &rect);
+
+ rects[i].left = rect.x;
+ rects[i].top = rect.y;
+ rects[i].right = rect.x + rect.width;
+ rects[i].bottom = rect.y + rect.height;
+ }
gdi_region = ExtCreateRegion (NULL, data_size, data);
free (data);
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 2ae7dcf3..c21e6000 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -671,6 +671,7 @@ _cairo_xcb_surface_same_screen (cairo_xcb_surface_t *dst,
static cairo_status_t
_cairo_xcb_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
+ cairo_content_t content,
int src_x,
int src_y,
int width,
@@ -1119,6 +1120,7 @@ _cairo_xcb_surface_composite (cairo_operator_t op,
status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern,
&dst->base,
+ CAIRO_CONTENT_COLOR_ALPHA,
src_x, src_y,
mask_x, mask_y,
width, height,
@@ -1407,6 +1409,7 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op,
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_pattern_acquire_surface (pattern, &dst->base,
+ CAIRO_CONTENT_COLOR_ALPHA,
src_x, src_y, width, height,
(cairo_surface_t **) &src,
&attributes);
@@ -1555,38 +1558,34 @@ _cairo_xcb_surface_set_clip_region (void *abstract_surface,
xcb_render_change_picture (surface->dpy, surface->dst_picture,
XCB_RENDER_CP_CLIP_MASK, none);
} else {
- cairo_box_int_t *boxes;
cairo_status_t status;
xcb_rectangle_t *rects = NULL;
- int n_boxes, i;
+ int n_rects, i;
- n_boxes = 0;
- status = _cairo_region_get_boxes (region, &n_boxes, &boxes);
- if (status)
- return status;
+ n_rects = cairo_region_num_rectangles (region);
- if (n_boxes > 0) {
- rects = _cairo_malloc_ab (n_boxes, sizeof(xcb_rectangle_t));
- if (rects == NULL) {
- _cairo_region_boxes_fini (region, boxes);
+ if (n_rects > 0) {
+ rects = _cairo_malloc_ab (n_rects, sizeof(xcb_rectangle_t));
+ if (rects == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
} else {
rects = NULL;
}
- for (i = 0; i < n_boxes; i++) {
- rects[i].x = boxes[i].p1.x;
- rects[i].y = boxes[i].p1.y;
- rects[i].width = boxes[i].p2.x - boxes[i].p1.x;
- rects[i].height = boxes[i].p2.y - boxes[i].p1.y;
- }
-
- _cairo_region_boxes_fini (region, boxes);
+ for (i = 0; i < n_rects; i++) {
+ cairo_rectangle_int_t rect;
+ cairo_region_get_rectangle (region, i, &rect);
+
+ rects[i].x = rect.x;
+ rects[i].y = rect.y;
+ rects[i].width = rect.width;
+ rects[i].height = rect.height;
+ }
+
surface->have_clip_rects = TRUE;
surface->clip_rects = rects;
- surface->num_clip_rects = n_boxes;
+ surface->num_clip_rects = n_rects;
if (surface->gc)
_cairo_xcb_surface_set_gc_clip_rects (surface);
@@ -2503,6 +2502,7 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
if (src_pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
+ CAIRO_CONTENT_COLOR_ALPHA,
0, 0, 1, 1,
(cairo_surface_t **) &src,
&attributes);
@@ -2517,6 +2517,7 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
goto BAIL;
status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
+ CAIRO_CONTENT_COLOR_ALPHA,
glyph_extents.x, glyph_extents.y,
glyph_extents.width, glyph_extents.height,
(cairo_surface_t **) &src,
diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c
index e85174b7..af244abe 100644
--- a/src/cairo-xlib-display.c
+++ b/src/cairo-xlib-display.c
@@ -38,8 +38,6 @@
#include "cairo-xlib-private.h"
#include "cairo-xlib-xrender-private.h"
-#include <fontconfig/fontconfig.h>
-
#include <X11/Xlibint.h> /* For XESetCloseDisplay */
typedef int (*cairo_xlib_error_func_t) (Display *display,
diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c
index 3b1ae2e1..8f1e9497 100644
--- a/src/cairo-xlib-screen.c
+++ b/src/cairo-xlib-screen.c
@@ -112,7 +112,7 @@ get_integer_default (Display *dpy,
v = XGetDefault (dpy, "Xft", option);
if (v) {
-#if CAIRO_HAS_FT_FONT
+#if CAIRO_HAS_FC_FONT
if (FcNameConstant ((FcChar8 *) v, value))
return TRUE;
#endif
@@ -125,7 +125,15 @@ get_integer_default (Display *dpy,
return FALSE;
}
-/* Old versions of fontconfig didn't have these options */
+#ifndef FC_RGBA_UNKNOWN
+#define FC_RGBA_UNKNOWN 0
+#define FC_RGBA_RGB 1
+#define FC_RGBA_BGR 2
+#define FC_RGBA_VRGB 3
+#define FC_RGBA_VBGR 4
+#define FC_RGBA_NONE 5
+#endif
+
#ifndef FC_HINT_NONE
#define FC_HINT_NONE 0
#define FC_HINT_SLIGHT 1
@@ -133,17 +141,6 @@ get_integer_default (Display *dpy,
#define FC_HINT_FULL 3
#endif
-/* Fontconfig version older than 2.6 didn't have these options */
-#ifndef FC_LCD_FILTER
-#define FC_LCD_FILTER "lcdfilter"
-#endif
-/* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */
-#ifndef FC_LCD_NONE
-#define FC_LCD_NONE 0
-#define FC_LCD_DEFAULT 1
-#define FC_LCD_LIGHT 2
-#define FC_LCD_LEGACY 3
-#endif
static void
_cairo_xlib_init_screen_font_options (Display *dpy,
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index a18fc034..e4566914 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -208,7 +208,7 @@ _cairo_xlib_surface_create_similar (void *abstract_src,
Pixmap pix;
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
- return _cairo_surface_create_in_error (_cairo_error(CAIRO_STATUS_INVALID_SIZE));
+ return NULL;
_cairo_xlib_display_notify (src->display);
@@ -950,9 +950,10 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
ximage.blue_mask = surface->b_mask;
ximage.xoffset = 0;
- if (image_masks.red_mask == surface->r_mask &&
- image_masks.green_mask == surface->g_mask &&
- image_masks.blue_mask == surface->b_mask)
+ if ((image_masks.alpha_mask == surface->a_mask || surface->a_mask == 0) &&
+ (image_masks.red_mask == surface->r_mask || surface->r_mask == 0) &&
+ (image_masks.green_mask == surface->g_mask || surface->g_mask == 0) &&
+ (image_masks.blue_mask == surface->b_mask || surface->b_mask == 0))
{
int ret;
@@ -1016,8 +1017,8 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
goto BAIL;
}
- rowstride = cairo_image_surface_get_stride (&image->base) >> 2;
- row = (uint32_t *) cairo_image_surface_get_data (&image->base);
+ rowstride = image->stride >> 2;
+ row = (uint32_t *) image->data;
x0 = dst_x + surface->base.device_transform.x0;
y0 = dst_y + surface->base.device_transform.y0;
for (y = 0, y_off = y0 % ARRAY_LENGTH (dither_pattern);
@@ -1168,6 +1169,7 @@ _cairo_xlib_surface_same_screen (cairo_xlib_surface_t *dst,
static cairo_status_t
_cairo_xlib_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
+ cairo_content_t content,
int src_x,
int src_y,
int width,
@@ -1194,16 +1196,20 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface,
}
} else if (_cairo_surface_is_image (src)) {
cairo_image_surface_t *image_src = (cairo_image_surface_t *)src;
-
- if (! CAIRO_FORMAT_VALID (image_src->format))
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ cairo_format_t format;
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
- return _cairo_error (CAIRO_STATUS_INVALID_SIZE);
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ format = image_src->format;
+ if (format == CAIRO_FORMAT_INVALID ||
+ (_cairo_content_from_format (format) & ~content))
+ {
+ format = _cairo_format_from_content (image_src->base.content & content);
+ }
clone = (cairo_xlib_surface_t *)
_cairo_xlib_surface_create_similar_with_format (surface,
- image_src->format,
+ format,
width, height);
if (clone == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1506,14 +1512,15 @@ _surface_has_alpha (cairo_xlib_surface_t *surface)
*/
static cairo_bool_t
_operator_needs_alpha_composite (cairo_operator_t op,
- cairo_bool_t surface_has_alpha)
+ cairo_bool_t destination_has_alpha,
+ cairo_bool_t source_has_alpha)
{
if (op == CAIRO_OPERATOR_SOURCE ||
- (!surface_has_alpha &&
+ (! source_has_alpha &&
(op == CAIRO_OPERATOR_OVER ||
op == CAIRO_OPERATOR_ATOP ||
op == CAIRO_OPERATOR_IN)))
- return FALSE;
+ return destination_has_alpha;
return TRUE;
}
@@ -1622,7 +1629,9 @@ _recategorize_composite_operation (cairo_xlib_surface_t *dst,
return DO_UNSUPPORTED;
needs_alpha_composite =
- _operator_needs_alpha_composite (op, _surface_has_alpha (src));
+ _operator_needs_alpha_composite (op,
+ _surface_has_alpha (dst),
+ _surface_has_alpha (src));
if (! have_mask &&
is_integer_translation &&
@@ -1719,6 +1728,8 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
composite_operation_t operation;
int itx, ity;
cairo_bool_t is_integer_translation;
+ cairo_bool_t needs_alpha_composite;
+ cairo_content_t src_content;
_cairo_xlib_display_notify (dst->display);
@@ -1727,8 +1738,17 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
if (operation == DO_UNSUPPORTED)
return CAIRO_INT_STATUS_UNSUPPORTED;
+ needs_alpha_composite =
+ _operator_needs_alpha_composite (op,
+ _surface_has_alpha (dst),
+ ! _cairo_pattern_is_opaque (src_pattern));
+ src_content = CAIRO_CONTENT_COLOR_ALPHA;
+ if (! needs_alpha_composite)
+ src_content &= ~CAIRO_CONTENT_ALPHA;
+
status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern,
&dst->base,
+ src_content,
src_x, src_y,
mask_x, mask_y,
width, height,
@@ -1890,6 +1910,7 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface,
return status;
status = _cairo_pattern_acquire_surface (&solid.base, &surface->base,
+ CAIRO_CONTENT_COLOR_ALPHA,
0, 0,
ARRAY_LENGTH (dither_pattern[0]),
ARRAY_LENGTH (dither_pattern),
@@ -2140,6 +2161,7 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op,
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_pattern_acquire_surface (pattern, &dst->base,
+ CAIRO_CONTENT_COLOR_ALPHA,
src_x, src_y, width, height,
(cairo_surface_t **) &src,
&attributes);
@@ -2269,7 +2291,32 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op,
return status;
}
-COMPILE_TIME_ASSERT (sizeof (XRectangle) <= sizeof (cairo_box_int_t));
+static cairo_region_t *
+_surface_maybe_clip_region (cairo_xlib_surface_t *surface,
+ cairo_region_t *clip,
+ cairo_region_t *bounded)
+{
+ cairo_rectangle_int_t rect;
+
+ cairo_region_get_extents (clip, &rect);
+ if (rect.x >= 0 &&
+ rect.y >= 0 &&
+ rect.x + rect.width <= surface->width &&
+ rect.y + rect.height <= surface->height)
+ {
+ return clip;
+ }
+
+ rect.x = rect.y = 0;
+ rect.width = surface->width;
+ rect.height = surface->height;
+ _cairo_region_init_rectangle (bounded, &rect);
+
+ bounded->status = cairo_region_intersect (bounded, clip);
+
+ return bounded;
+}
+
static cairo_int_status_t
_cairo_xlib_surface_set_clip_region (void *abstract_surface,
cairo_region_t *region)
@@ -2289,68 +2336,50 @@ _cairo_xlib_surface_set_clip_region (void *abstract_surface,
surface->num_clip_rects = 0;
if (region != NULL) {
- cairo_box_int_t *boxes;
- cairo_status_t status;
XRectangle *rects = NULL;
- int n_boxes, i;
- cairo_rectangle_int_t rect;
- cairo_region_t bound, bounded;
-
- rect.x = rect.y = 0;
- rect.width = surface->width;
- rect.height = surface->height;
+ int n_rects, i;
+ cairo_region_t bounded;
/* Intersect the region with the bounds of the surface. This
* is necessary so we don't wrap around when we convert cairo's
* 32 bit region into 16 bit rectangles.
*/
- _cairo_region_init_rect (&bound, &rect);
- _cairo_region_init (&bounded);
- status = _cairo_region_intersect (&bounded, &bound, region);
- if (unlikely (status)) {
- _cairo_region_fini (&bound);
- _cairo_region_fini (&bounded);
- return status;
- }
+ region = _surface_maybe_clip_region (surface, region, &bounded);
+ if (unlikely (region->status))
+ return region->status;
- n_boxes = sizeof (surface->embedded_clip_rects) / sizeof (cairo_box_int_t);
- boxes = (cairo_box_int_t *) surface->embedded_clip_rects;
- status = _cairo_region_get_boxes (&bounded, &n_boxes, &boxes);
- if (unlikely (status)) {
- _cairo_region_fini (&bound);
- _cairo_region_fini (&bounded);
- return status;
- }
-
- if (n_boxes > ARRAY_LENGTH (surface->embedded_clip_rects)) {
- rects = _cairo_malloc_ab (n_boxes, sizeof (XRectangle));
+ n_rects = cairo_region_num_rectangles (region);
+ if (n_rects > ARRAY_LENGTH (surface->embedded_clip_rects)) {
+ rects = _cairo_malloc_ab (n_rects, sizeof (XRectangle));
if (unlikely (rects == NULL)) {
- _cairo_region_boxes_fini (&bounded, boxes);
- _cairo_region_fini (&bound);
- _cairo_region_fini (&bounded);
+ if (unlikely (region == &bounded))
+ _cairo_region_fini (&bounded);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
- } else
+ }
+ } else {
rects = surface->embedded_clip_rects;
+ }
+
+ for (i = 0; i < n_rects; i++) {
+ cairo_rectangle_int_t rect;
- for (i = 0; i < n_boxes; i++) {
- rects[i].x = boxes[i].p1.x;
- rects[i].y = boxes[i].p1.y;
- rects[i].width = boxes[i].p2.x - rects[i].x;
- rects[i].height = boxes[i].p2.y - rects[i].y;
+ cairo_region_get_rectangle (region, i, &rect);
+
+ rects[i].x = rect.x;
+ rects[i].y = rect.y;
+ rects[i].width = rect.width;
+ rects[i].height = rect.height;
}
- if (boxes != (cairo_box_int_t *) surface->embedded_clip_rects)
- _cairo_region_boxes_fini (&bounded, boxes);
- _cairo_region_fini (&bounded);
- _cairo_region_fini (&bound);
+ if (unlikely (region == &bounded))
+ _cairo_region_fini (&bounded);
surface->have_clip_rects = TRUE;
surface->clip_rects = rects;
- surface->num_clip_rects = n_boxes;
+ surface->num_clip_rects = n_rects;
/* Discard the trivial clip rectangle that covers the entire surface */
- if (n_boxes == 1 &&
+ if (n_rects == 1 &&
rects[0].x == 0 &&
rects[0].y == 0 &&
rects[0].width == surface->width &&
@@ -4062,6 +4091,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
if (src_pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
+ CAIRO_CONTENT_COLOR_ALPHA,
0, 0, 1, 1,
(cairo_surface_t **) &src,
&attributes);
@@ -4078,6 +4108,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
goto BAIL0;
status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
+ CAIRO_CONTENT_COLOR_ALPHA,
glyph_extents.x, glyph_extents.y,
glyph_extents.width, glyph_extents.height,
(cairo_surface_t **) &src,
diff --git a/src/cairo.c b/src/cairo.c
index 4cdf6853..ddc8d4a9 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -82,6 +82,7 @@ static const cairo_t _cairo_nil = {
cairo_status_t
_cairo_error (cairo_status_t status)
{
+ CAIRO_ENSURE_UNIQUE;
assert (_cairo_status_is_error (status));
return status;
@@ -648,10 +649,10 @@ _current_source_matches_solid (cairo_t *cr,
if (current->type != CAIRO_PATTERN_TYPE_SOLID)
return FALSE;
- _cairo_restrict_value (&red, 0.0, 1.0);
- _cairo_restrict_value (&green, 0.0, 1.0);
- _cairo_restrict_value (&blue, 0.0, 1.0);
- _cairo_restrict_value (&alpha, 0.0, 1.0);
+ red = _cairo_restrict_value (red, 0.0, 1.0);
+ green = _cairo_restrict_value (green, 0.0, 1.0);
+ blue = _cairo_restrict_value (blue, 0.0, 1.0);
+ alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
_cairo_color_init_rgba (&color, red, green, blue, alpha);
return _cairo_color_equal (&color,
@@ -855,7 +856,10 @@ cairo_get_source (cairo_t *cr)
* is less than @tolerance. The default value is 0.1. A larger
* value will give better performance, a smaller value, better
* appearance. (Reducing the value from the default value of 0.1
- * is unlikely to improve appearance significantly.)
+ * is unlikely to improve appearance significantly.) The accuracy of paths
+ * within Cairo is limited by the precision of its internal arithmetic, and
+ * the prescribed @tolerance is restricted to the smallest
+ * representable internal value.
**/
void
cairo_set_tolerance (cairo_t *cr, double tolerance)
@@ -865,7 +869,8 @@ cairo_set_tolerance (cairo_t *cr, double tolerance)
if (cr->status)
return;
- _cairo_restrict_value (&tolerance, CAIRO_TOLERANCE_MINIMUM, tolerance);
+ if (tolerance < CAIRO_TOLERANCE_MINIMUM)
+ tolerance = CAIRO_TOLERANCE_MINIMUM;
status = _cairo_gstate_set_tolerance (cr->gstate, tolerance);
if (unlikely (status))
@@ -959,7 +964,8 @@ cairo_set_line_width (cairo_t *cr, double width)
if (cr->status)
return;
- _cairo_restrict_value (&width, 0.0, width);
+ if (width < 0.)
+ width = 0.;
status = _cairo_gstate_set_line_width (cr->gstate, width);
if (unlikely (status))
diff --git a/src/cairo.h b/src/cairo.h
index e35c9ca8..4350bc1f 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -240,6 +240,11 @@ typedef struct _cairo_user_data_key {
* @CAIRO_STATUS_INVALID_SLANT: invalid value for an input #cairo_font_slant_t (Since 1.8)
* @CAIRO_STATUS_INVALID_WEIGHT: invalid value for an input #cairo_font_weight_t (Since 1.8)
* @CAIRO_STATUS_INVALID_SIZE: invalid value (typically too big) for a size (Since 1.10)
+ * @CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED: user-font method not implemented (Since 1.10)
+ * @CAIRO_STATUS_LAST_STATUS: this is a special value indicating the number of
+ * status values defined in this enumeration. When using this value, note
+ * that the version of cairo at run-time may have additional status values
+ * defined than the value of this symbol at compile-time. (Since 1.10)
*
* #cairo_status_t is used to indicate errors that can occur when
* using Cairo. In some cases it is returned directly by functions.
@@ -251,6 +256,7 @@ typedef struct _cairo_user_data_key {
**/
typedef enum _cairo_status {
CAIRO_STATUS_SUCCESS = 0,
+
CAIRO_STATUS_NO_MEMORY,
CAIRO_STATUS_INVALID_RESTORE,
CAIRO_STATUS_INVALID_POP_GROUP,
@@ -282,8 +288,10 @@ typedef enum _cairo_status {
CAIRO_STATUS_INVALID_CLUSTERS,
CAIRO_STATUS_INVALID_SLANT,
CAIRO_STATUS_INVALID_WEIGHT,
- CAIRO_STATUS_INVALID_SIZE
- /* after adding a new error: update CAIRO_STATUS_LAST_STATUS in cairoint.h. */
+ CAIRO_STATUS_INVALID_SIZE,
+ CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED,
+
+ CAIRO_STATUS_LAST_STATUS
} cairo_status_t;
/**
@@ -1447,8 +1455,7 @@ cairo_user_font_face_create (void);
* point and trying to use it for text operations in the callback will result
* in deadlock.
*
- * Returns: %CAIRO_STATUS_SUCCESS upon success, or
- * %CAIRO_STATUS_USER_FONT_ERROR or any other error status on error.
+ * Returns: %CAIRO_STATUS_SUCCESS upon success, or an error status on error.
*
* Since: 1.8
**/
@@ -1549,7 +1556,8 @@ typedef cairo_status_t (*cairo_user_scaled_font_render_glyph_func_t) (cairo_scal
* will free the allocated cluster array using cairo_text_cluster_free().
*
* The callback is optional. If @num_glyphs is negative upon
- * the callback returning, the unicode_to_glyph callback
+ * the callback returning or if the return value
+ * is %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED, the unicode_to_glyph callback
* is tried. See #cairo_user_scaled_font_unicode_to_glyph_func_t.
*
* Note: While cairo does not impose any limitation on glyph indices,
@@ -1560,8 +1568,9 @@ typedef cairo_status_t (*cairo_user_scaled_font_render_glyph_func_t) (cairo_scal
* are advised to use glyph 0 for such purposes and do not use that
* glyph value for other purposes.
*
- * Returns: %CAIRO_STATUS_SUCCESS upon success, or
- * %CAIRO_STATUS_USER_FONT_ERROR or any other error status on error.
+ * Returns: %CAIRO_STATUS_SUCCESS upon success,
+ * %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED if fallback options should be tried,
+ * or %CAIRO_STATUS_USER_FONT_ERROR or any other error status on error.
*
* Since: 1.8
**/
@@ -1594,8 +1603,9 @@ typedef cairo_status_t (*cairo_user_scaled_font_text_to_glyphs_func_t) (cairo_sc
* complex scripts can be implemented using this callback.
*
* The callback is optional, and only used if text_to_glyphs callback is not
- * set or fails to return glyphs. If this callback is not set, an identity
- * mapping from Unicode code-points to glyph indices is assumed.
+ * set or fails to return glyphs. If this callback is not set or if it returns
+ * %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED, an identity mapping from Unicode
+ * code-points to glyph indices is assumed.
*
* Note: While cairo does not impose any limitation on glyph indices,
* some applications may assume that a glyph index fits in a 16-bit
@@ -1605,8 +1615,9 @@ typedef cairo_status_t (*cairo_user_scaled_font_text_to_glyphs_func_t) (cairo_sc
* are advised to use glyph 0 for such purposes and do not use that
* glyph value for other purposes.
*
- * Returns: %CAIRO_STATUS_SUCCESS upon success, or
- * %CAIRO_STATUS_USER_FONT_ERROR or any other error status on error.
+ * Returns: %CAIRO_STATUS_SUCCESS upon success,
+ * %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED if fallback options should be tried,
+ * or %CAIRO_STATUS_USER_FONT_ERROR or any other error status on error.
*
* Since: 1.8
**/
@@ -1877,7 +1888,6 @@ cairo_surface_status (cairo_surface_t *surface);
* @CAIRO_SURFACE_TYPE_OS2: The surface is of type os2
* @CAIRO_SURFACE_TYPE_WIN32_PRINTING: The surface is a win32 printing surface
* @CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: The surface is of type quartz_image
- * @CAIRO_SURFACE_TYPE_SDL: The surface is of type SDL, since 1.10
* @CAIRO_SURFACE_TYPE_SCRIPT: The surface is of type script, since 1.10
* @CAIRO_SURFACE_TYPE_GL: The surface is of type OpenGL, since 1.10
*
@@ -1919,7 +1929,6 @@ typedef enum _cairo_surface_type {
CAIRO_SURFACE_TYPE_OS2,
CAIRO_SURFACE_TYPE_WIN32_PRINTING,
CAIRO_SURFACE_TYPE_QUARTZ_IMAGE,
- CAIRO_SURFACE_TYPE_SDL,
CAIRO_SURFACE_TYPE_SCRIPT,
CAIRO_SURFACE_TYPE_GL,
} cairo_surface_type_t;
@@ -2345,10 +2354,88 @@ cairo_public void
cairo_matrix_transform_point (const cairo_matrix_t *matrix,
double *x, double *y);
+/* Region functions */
+
+typedef struct _cairo_region cairo_region_t;
+
+typedef struct _cairo_rectangle_int {
+ int x, y;
+ int width, height;
+} cairo_rectangle_int_t;
+
+typedef enum _cairo_region_overlap {
+ CAIRO_REGION_OVERLAP_IN, /* completely inside region */
+ CAIRO_REGION_OVERLAP_OUT, /* completely outside region */
+ CAIRO_REGION_OVERLAP_PART /* partly inside region */
+} cairo_region_overlap_t;
+
+cairo_public cairo_region_t *
+cairo_region_create (void);
+
+cairo_public cairo_region_t *
+cairo_region_create_rectangle (const cairo_rectangle_int_t *rectangle);
+
+cairo_public cairo_region_t *
+cairo_region_copy (cairo_region_t *original);
+
+cairo_public void
+cairo_region_destroy (cairo_region_t *region);
+
+cairo_public cairo_status_t
+cairo_region_status (cairo_region_t *region);
+
+cairo_public void
+cairo_region_get_extents (cairo_region_t *region,
+ cairo_rectangle_int_t *extents);
+
+cairo_public int
+cairo_region_num_rectangles (cairo_region_t *region);
+
+cairo_public void
+cairo_region_get_rectangle (cairo_region_t *region,
+ int nth_rectangle,
+ cairo_rectangle_int_t *rectangle);
+
+cairo_public cairo_bool_t
+cairo_region_is_empty (cairo_region_t *region);
+
+cairo_public cairo_region_overlap_t
+cairo_region_contains_rectangle (cairo_region_t *region,
+ const cairo_rectangle_int_t *rectangle);
+
+cairo_public cairo_bool_t
+cairo_region_contains_point (cairo_region_t *region, int x, int y);
+
+cairo_public void
+cairo_region_translate (cairo_region_t *region, int dx, int dy);
+
+cairo_public cairo_status_t
+cairo_region_subtract (cairo_region_t *dst, cairo_region_t *other);
+
+cairo_public cairo_status_t
+cairo_region_subtract_rectangle (cairo_region_t *dst,
+ const cairo_rectangle_int_t *rectangle);
+
+cairo_public cairo_status_t
+cairo_region_intersect (cairo_region_t *dst, cairo_region_t *other);
+
+cairo_public cairo_status_t
+cairo_region_intersect_rectangle (cairo_region_t *dst,
+ const cairo_rectangle_int_t *rectangle);
+
+cairo_public cairo_status_t
+cairo_region_union (cairo_region_t *dst, cairo_region_t *other);
+
+cairo_public cairo_status_t
+cairo_region_union_rectangle (cairo_region_t *dst,
+ const cairo_rectangle_int_t *rectangle);
+
+
/* Functions to be used while debugging (not intended for use in production code) */
cairo_public void
cairo_debug_reset_static_data (void);
+
CAIRO_END_DECLS
#endif /* CAIRO_H */
diff --git a/src/cairoint.h b/src/cairoint.h
index 8115c81a..d694ae41 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -85,7 +85,7 @@
CAIRO_BEGIN_DECLS
-#ifdef _WIN32
+#if _WIN32 && !_WIN32_WCE /* Permissions on WinCE? No worries! */
cairo_private FILE *
_cairo_win32_tmpfile (void);
#define tmpfile() _cairo_win32_tmpfile()
@@ -120,16 +120,14 @@ _cairo_win32_tmpfile (void);
#undef ARRAY_LENGTH
#define ARRAY_LENGTH(__array) ((int) (sizeof (__array) / sizeof (__array[0])))
-
-/* This has to be updated whenever #cairo_status_t is extended. That's
- * a bit of a pain, but it should be easy to always catch as long as
- * one adds a new test case to test a trigger of the new status value.
- */
-#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_SIZE
+#undef STRINGIFY
+#undef STRINGIFY_ARG
+#define STRINGIFY(macro_or_string) STRINGIFY_ARG (macro_or_string)
+#define STRINGIFY_ARG(contents) #contents
#ifdef __GNUC__
#define cairo_container_of(ptr, type, member) ({ \
- const typeof(((type *) 0)->member) *mptr__ = (ptr); \
+ const __typeof__ (((type *) 0)->member) *mptr__ = (ptr); \
(type *) ((char *) mptr__ - offsetof (type, member)); \
})
#else
@@ -153,7 +151,7 @@ do { \
assert (NOT_REACHED); \
} while (0)
#define COMPILE_TIME_ASSERT1(condition, line) \
- typedef int compile_time_assertion_at_line_##line##_failed [(condition)?1:-1];
+ typedef int compile_time_assertion_at_line_##line##_failed [(condition)?1:-1]
#define COMPILE_TIME_ASSERT0(condition, line) COMPILE_TIME_ASSERT1(condition, line)
#define COMPILE_TIME_ASSERT(condition) COMPILE_TIME_ASSERT0(condition, __LINE__)
@@ -330,6 +328,17 @@ _cairo_user_data_array_set_data (cairo_user_data_array_t *array,
void *user_data,
cairo_destroy_func_t destroy);
+cairo_private cairo_status_t
+_cairo_user_data_array_copy (cairo_user_data_array_t *dst,
+ cairo_user_data_array_t *src);
+
+cairo_private void
+_cairo_user_data_array_foreach (cairo_user_data_array_t *array,
+ void (*func) (const void *key,
+ void *elt,
+ void *closure),
+ void *closure);
+
#define _CAIRO_HASH_INIT_VALUE 5381
cairo_private unsigned long
@@ -351,8 +360,7 @@ typedef struct _cairo_unscaled_font {
} cairo_unscaled_font_t;
typedef struct _cairo_scaled_glyph {
- unsigned long index;
- cairo_scaled_font_t *scaled_font; /* font the glyph lives in */
+ cairo_hash_entry_t hash_entry;
cairo_text_extents_t metrics; /* user-space metrics */
cairo_text_extents_t fs_metrics; /* font-space metrics */
@@ -367,8 +375,8 @@ typedef struct _cairo_scaled_glyph {
void *surface_private; /* for the surface backend */
} cairo_scaled_glyph_t;
-#define _cairo_scaled_glyph_index(g) ((g)->index)
-#define _cairo_scaled_glyph_set_index(g, i) ((g)->index = (i))
+#define _cairo_scaled_glyph_index(g) ((g)->hash_entry.hash)
+#define _cairo_scaled_glyph_set_index(g, i) ((g)->hash_entry.hash = (i))
#include "cairo-scaled-font-private.h"
@@ -482,7 +490,8 @@ struct _cairo_scaled_font_backend {
unsigned char *buffer,
unsigned long *length);
- /* returns -1 if the unicode character could not be found for the glyph */
+ /* ucs4 is set to -1 if the unicode character could not be found
+ * for the glyph */
cairo_warn cairo_int_status_t
(*index_to_ucs4)(void *scaled_font,
unsigned long index,
@@ -583,6 +592,7 @@ struct _cairo_surface_backend {
cairo_warn cairo_status_t
(*clone_similar) (void *surface,
cairo_surface_t *src,
+ cairo_content_t content,
int src_x,
int src_y,
int width,
@@ -1021,8 +1031,26 @@ typedef struct _cairo_stroke_face {
} cairo_stroke_face_t;
/* cairo.c */
-cairo_private void
-_cairo_restrict_value (double *value, double min, double max);
+
+static inline double
+_cairo_restrict_value (double value, double min, double max)
+{
+ if (value < min)
+ return min;
+ else if (value > max)
+ return max;
+ else
+ return value;
+}
+
+/* C99 round() rounds to the nearest integral value with halfway cases rounded
+ * away from 0. _cairo_round rounds halfway cases toward negative infinity.
+ * This matches the rounding behaviour of _cairo_lround. */
+static inline double
+_cairo_round (double r)
+{
+ return floor (r + .5);
+}
cairo_private int
_cairo_lround (double d);
@@ -1733,8 +1761,7 @@ _cairo_surface_create_in_error (cairo_status_t status);
cairo_private cairo_status_t
_cairo_surface_copy_mime_data (cairo_surface_t *dst,
- cairo_surface_t *src,
- const char *mime_type);
+ cairo_surface_t *src);
cairo_private cairo_status_t
_cairo_surface_set_error (cairo_surface_t *surface,
@@ -1938,6 +1965,7 @@ _cairo_surface_release_dest_image (cairo_surface_t *surface,
cairo_private cairo_status_t
_cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_surface_t *src,
+ cairo_content_t content,
int src_x,
int src_y,
int width,
@@ -2383,7 +2411,7 @@ _cairo_traps_extents (const cairo_traps_t *traps,
cairo_private cairo_int_status_t
_cairo_traps_extract_region (const cairo_traps_t *tr,
- cairo_region_t *region);
+ cairo_region_t **region);
cairo_private cairo_status_t
_cairo_traps_path (const cairo_traps_t *traps,
@@ -2457,6 +2485,7 @@ _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern);
cairo_private cairo_int_status_t
_cairo_pattern_acquire_surface (const cairo_pattern_t *pattern,
cairo_surface_t *dst,
+ cairo_content_t content,
int x,
int y,
unsigned int width,
@@ -2473,6 +2502,7 @@ cairo_private cairo_int_status_t
_cairo_pattern_acquire_surfaces (const cairo_pattern_t *src,
const cairo_pattern_t *mask,
cairo_surface_t *dst,
+ cairo_content_t src_content,
int src_x,
int src_y,
int mask_x,
@@ -2503,7 +2533,21 @@ _cairo_pattern_reset_static_data (void);
/* cairo-region.c */
-#include "cairo-region-private.h"
+struct _cairo_region {
+ cairo_status_t status;
+
+ pixman_region32_t rgn;
+};
+
+cairo_private void
+_cairo_region_init (cairo_region_t *region);
+
+cairo_private void
+_cairo_region_init_rectangle (cairo_region_t *region,
+ const cairo_rectangle_int_t *rectangle);
+
+cairo_private void
+_cairo_region_fini (cairo_region_t *region);
/* cairo-unicode.c */
@@ -2665,6 +2709,24 @@ slim_hidden_proto (cairo_user_font_face_set_unicode_to_glyph_func);
slim_hidden_proto (cairo_user_to_device);
slim_hidden_proto (cairo_user_to_device_distance);
slim_hidden_proto (cairo_version_string);
+slim_hidden_proto (cairo_region_create);
+slim_hidden_proto (cairo_region_create_rectangle);
+slim_hidden_proto (cairo_region_copy);
+slim_hidden_proto (cairo_region_destroy);
+slim_hidden_proto (cairo_region_status);
+slim_hidden_proto (cairo_region_get_extents);
+slim_hidden_proto (cairo_region_num_rectangles);
+slim_hidden_proto (cairo_region_get_rectangle);
+slim_hidden_proto (cairo_region_is_empty);
+slim_hidden_proto (cairo_region_contains_rectangle);
+slim_hidden_proto (cairo_region_contains_point);
+slim_hidden_proto (cairo_region_translate);
+slim_hidden_proto (cairo_region_subtract);
+slim_hidden_proto (cairo_region_subtract_rectangle);
+slim_hidden_proto (cairo_region_intersect);
+slim_hidden_proto (cairo_region_intersect_rectangle);
+slim_hidden_proto (cairo_region_union);
+slim_hidden_proto (cairo_region_union_rectangle);
#if CAIRO_HAS_PNG_FUNCTIONS
@@ -2680,4 +2742,15 @@ CAIRO_END_DECLS
#include "cairo-malloc-private.h"
#include "cairo-hash-private.h"
+#if HAVE_VALGRIND
+
+cairo_private void
+_cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface);
+
+#else
+
+#define _cairo_debug_check_image_surface_is_defined(X)
+
+#endif
+
#endif
diff --git a/src/test-fallback-surface.c b/src/test-fallback-surface.c
index 8acd91ee..2a7f1489 100644
--- a/src/test-fallback-surface.c
+++ b/src/test-fallback-surface.c
@@ -172,6 +172,7 @@ _test_fallback_surface_release_dest_image (void *abstract_surface,
static cairo_status_t
_test_fallback_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
+ cairo_content_t content,
int src_x,
int src_y,
int width,
diff --git a/src/test-fallback16-surface.c b/src/test-fallback16-surface.c
new file mode 100644
index 00000000..07c06105
--- /dev/null
+++ b/src/test-fallback16-surface.c
@@ -0,0 +1,236 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc
+ * Copyright © 2009 Chris Wilson
+ *
+ * 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 Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Carl Worth <cworth@cworth.org>
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ */
+
+/* This isn't a "real" surface, but just something to be used by the
+ * test suite to force use of a non-standard pixman image fallback - as
+ * may be exposed by xlib fallbacks with weird xservers, for example.
+ */
+
+#include "cairoint.h"
+
+#include "test-fallback16-surface.h"
+
+typedef struct _test_fallback16_surface {
+ cairo_surface_t base;
+
+ /* This is a cairo_image_surface to hold the actual contents. */
+ cairo_surface_t *backing;
+} test_fallback16_surface_t;
+
+static const cairo_surface_backend_t test_fallback16_surface_backend;
+
+slim_hidden_proto (_cairo_test_fallback16_surface_create);
+
+cairo_surface_t *
+_cairo_test_fallback16_surface_create (cairo_content_t content,
+ int width,
+ int height)
+{
+ test_fallback16_surface_t *surface;
+ cairo_surface_t *backing;
+ pixman_format_code_t format;
+
+ format = content & CAIRO_CONTENT_ALPHA ? PIXMAN_a1r5g5b5: PIXMAN_r5g6b5;
+
+ backing = _cairo_image_surface_create_with_pixman_format (NULL, format,
+ width, height,
+ -1);
+ if (cairo_surface_status (backing))
+ return backing;
+
+ surface = malloc (sizeof (test_fallback16_surface_t));
+ if (unlikely (surface == NULL)) {
+ cairo_surface_destroy (backing);
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+ }
+
+ _cairo_surface_init (&surface->base,
+ &test_fallback16_surface_backend,
+ content);
+
+ surface->backing = backing;
+
+ return &surface->base;
+}
+slim_hidden_def (_cairo_test_fallback16_surface_create);
+
+static cairo_surface_t *
+_test_fallback16_surface_create_similar (void *abstract_surface,
+ cairo_content_t content,
+ int width,
+ int height)
+{
+ assert (CAIRO_CONTENT_VALID (content));
+
+ return _cairo_test_fallback16_surface_create (content, width, height);
+}
+
+static cairo_status_t
+_test_fallback16_surface_finish (void *abstract_surface)
+{
+ test_fallback16_surface_t *surface = abstract_surface;
+
+ cairo_surface_destroy (surface->backing);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_test_fallback16_surface_acquire_source_image (void *abstract_surface,
+ cairo_image_surface_t **image_out,
+ void **image_extra)
+{
+ test_fallback16_surface_t *surface = abstract_surface;
+
+ return _cairo_surface_acquire_source_image (surface->backing,
+ image_out, image_extra);
+}
+
+static void
+_test_fallback16_surface_release_source_image (void *abstract_surface,
+ cairo_image_surface_t *image,
+ void *image_extra)
+{
+ test_fallback16_surface_t *surface = abstract_surface;
+
+ _cairo_surface_release_source_image (surface->backing,
+ image, image_extra);
+}
+
+static cairo_status_t
+_test_fallback16_surface_acquire_dest_image (void *abstract_surface,
+ cairo_rectangle_int_t *interest_rect,
+ cairo_image_surface_t **image_out,
+ cairo_rectangle_int_t *image_rect_out,
+ void **image_extra)
+{
+ test_fallback16_surface_t *surface = abstract_surface;
+
+ return _cairo_surface_acquire_dest_image (surface->backing,
+ interest_rect,
+ image_out,
+ image_rect_out,
+ image_extra);
+}
+
+static void
+_test_fallback16_surface_release_dest_image (void *abstract_surface,
+ cairo_rectangle_int_t *interest_rect,
+ cairo_image_surface_t *image,
+ cairo_rectangle_int_t *image_rect,
+ void *image_extra)
+{
+ test_fallback16_surface_t *surface = abstract_surface;
+
+ _cairo_surface_release_dest_image (surface->backing,
+ interest_rect,
+ image,
+ image_rect,
+ image_extra);
+}
+
+static cairo_status_t
+_test_fallback16_surface_clone_similar (void *abstract_surface,
+ cairo_surface_t *src,
+ cairo_content_t content,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
+ int *clone_offset_x,
+ int *clone_offset_y,
+ cairo_surface_t **clone_out)
+{
+ test_fallback16_surface_t *surface = abstract_surface;
+
+ if (src->backend == surface->base.backend) {
+ *clone_offset_x = 0;
+ *clone_offset_y = 0;
+ *clone_out = cairo_surface_reference (src);
+
+ return CAIRO_STATUS_SUCCESS;
+ } else {
+ return _cairo_surface_clone_similar (surface->backing, src,
+ content,
+ src_x, src_y,
+ width, height,
+ clone_offset_x, clone_offset_y,
+ clone_out);
+ }
+}
+
+static cairo_int_status_t
+_test_fallback16_surface_get_extents (void *abstract_surface,
+ cairo_rectangle_int_t *rectangle)
+{
+ test_fallback16_surface_t *surface = abstract_surface;
+
+ return _cairo_surface_get_extents (surface->backing, rectangle);
+}
+
+static const cairo_surface_backend_t test_fallback16_surface_backend = {
+ CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+ _test_fallback16_surface_create_similar,
+ _test_fallback16_surface_finish,
+ _test_fallback16_surface_acquire_source_image,
+ _test_fallback16_surface_release_source_image,
+ _test_fallback16_surface_acquire_dest_image,
+ _test_fallback16_surface_release_dest_image,
+ _test_fallback16_surface_clone_similar,
+ NULL, /* composite */
+ NULL, /* fill_rectangles */
+ NULL, /* composite_trapezoids */
+ NULL, /* create_span_renderer */
+ NULL, /* check_span_renderer */
+ NULL, /* copy_page */
+ NULL, /* show_page */
+ NULL, /* set_clip_region */
+ NULL, /* intersect_clip_path */
+ _test_fallback16_surface_get_extents,
+ NULL, /* old_show_glyphs */
+ NULL, /* get_font_options */
+ NULL, /* flush */
+ NULL, /* mark_dirty_rectangle */
+ NULL, /* scaled_font_fini */
+ NULL, /* scaled_glyph_fini */
+ NULL, /* paint */
+ NULL, /* mask */
+ NULL, /* stroke */
+ NULL, /* fill */
+ NULL, /* show_glyphs */
+ NULL /* snapshot */
+};
diff --git a/src/cairo-sdl.h b/src/test-fallback16-surface.h
index c5291a76..2c5b2ca7 100644
--- a/src/cairo-sdl.h
+++ b/src/test-fallback16-surface.h
@@ -1,6 +1,7 @@
-/* Cairo - a vector graphics library with display and print output
+/* cairo - a vector graphics library with display and print output
*
- * Copyright © 2008 Chris Wilson
+ * Copyright © 2005 Red Hat, Inc
+ * Copyright © 2009 Chris Wilson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -27,28 +28,25 @@
*
* The Original Code is the cairo graphics library.
*
- * The Initial Developer of the Original Code is Chris Wilson.
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Carl Worth <cworth@cworth.org>
+ * Chris Wilson <chris@chris-wilson.co.uk>
*/
-#ifndef CAIRO_SDL_H
-#define CAIRO_SDL_H
+#ifndef TEST_FALLBACK16_SURFACE_H
+#define TEST_FALLBACK16_SURFACE_H
#include "cairo.h"
-#if CAIRO_HAS_SDL_SURFACE
-
-#include <SDL.h>
-
CAIRO_BEGIN_DECLS
-cairo_public cairo_surface_t *
-cairo_sdl_surface_create (SDL_Surface *surface);
+cairo_surface_t *
+_cairo_test_fallback16_surface_create (cairo_content_t content,
+ int width,
+ int height);
CAIRO_END_DECLS
-#else /* CAIRO_HAS_SDL_SURFACE */
-# error Cairo was not compiled with support for the SDL backend
-#endif /* CAIRO_HAS_SDL_SURFACE */
-
-#endif /* CAIRO_SDL_H */
-
+#endif /* TEST_FALLBACK16_SURFACE_H */
diff --git a/test/Makefile.am b/test/Makefile.am
index 567e6848..bd5cf272 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,230 +1,24 @@
include $(top_srcdir)/build/Makefile.am.common
+include $(top_srcdir)/test/Makefile.sources
+
SUBDIRS=pdiff .
CLEANFILES += have-similar.*
-test_sources = \
- a1-image-sample.c \
- a1-mask.c \
- a1-traps-sample.c \
- a8-mask.c \
- alpha-similar.c \
- big-line.c \
- big-trap.c \
- bilevel-image.c \
- caps.c \
- caps-joins.c \
- caps-joins-alpha.c \
- caps-joins-curve.c \
- caps-sub-paths.c \
- clip-all.c \
- clip-empty.c \
- clip-fill-rule.c \
- clip-fill-rule-pixel-aligned.c \
- clip-nesting.c \
- clip-operator.c \
- clip-push-group.c \
- clip-twice.c \
- clip-zero.c \
- clipped-group.c \
- clipped-surface.c \
- close-path.c \
- composite-integer-translate-source.c \
- composite-integer-translate-over.c \
- composite-integer-translate-over-repeat.c \
- copy-path.c \
- create-for-stream.c \
- create-from-png.c \
- create-from-png-stream.c \
- culled-glyphs.c \
- dash-caps-joins.c \
- dash-curve.c \
- dash-no-dash.c \
- dash-offset-negative.c \
- dash-scale.c \
- dash-state.c \
- dash-zero-length.c \
- degenerate-arc.c \
- degenerate-dash.c \
- degenerate-path.c \
- degenerate-pen.c \
- device-offset.c \
- device-offset-fractional.c \
- device-offset-positive.c \
- device-offset-scale.c \
- extend-pad.c \
- extend-pad-border.c \
- extend-pad-similar.c \
- extend-reflect.c \
- extend-reflect-similar.c \
- extend-repeat.c \
- extend-repeat-similar.c \
- fill-alpha.c \
- fill-alpha-pattern.c \
- fill-and-stroke.c \
- fill-and-stroke-alpha.c \
- fill-and-stroke-alpha-add.c \
- fill-degenerate-sort-order.c \
- fill-image.c \
- fill-missed-stop.c \
- fill-rule.c \
- filter-bilinear-extents.c \
- filter-nearest-offset.c \
- filter-nearest-transformed.c \
- finer-grained-fallbacks.c \
- font-face-get-type.c \
- font-matrix-translation.c \
- font-options.c \
- glyph-cache-pressure.c \
- get-and-set.c \
- get-clip.c \
- get-group-target.c \
- get-path-extents.c \
- gradient-alpha.c \
- gradient-constant-alpha.c \
- gradient-zero-stops.c \
- group-paint.c \
- huge-linear.c \
- huge-radial.c \
- image-surface-source.c \
- infinite-join.c \
- in-fill-empty-trapezoid.c \
- in-fill-trapezoid.c \
- invalid-matrix.c \
- joins.c \
- large-clip.c \
- large-font.c \
- large-source.c \
- large-source-roi.c \
- leaky-dash.c \
- leaky-dashed-rectangle.c \
- leaky-dashed-stroke.c \
- leaky-polygon.c \
- line-width.c \
- line-width-scale.c \
- line-width-zero.c \
- linear-gradient.c \
- linear-gradient-reflect.c \
- long-dashed-lines.c \
- long-lines.c \
- mask.c \
- mask-alpha.c \
- mask-ctm.c \
- mask-surface-ctm.c \
- mask-transformed-image.c \
- mask-transformed-similar.c \
- meta-surface-pattern.c \
- mime-data.c \
- miter-precision.c \
- move-to-show-surface.c \
- new-sub-path.c \
- nil-surface.c \
- operator.c \
- operator-alpha.c \
- operator-clear.c \
- operator-source.c \
- over-above-source.c \
- over-around-source.c \
- over-below-source.c \
- over-between-source.c \
- paint.c \
- paint-repeat.c \
- paint-source-alpha.c \
- paint-with-alpha.c \
- path-precision.c \
- pattern-get-type.c \
- pattern-getters.c \
- pixman-rotate.c \
- png.c \
- push-group.c \
- radial-gradient.c \
- random-intersections.c \
- rectangle-rounding-error.c \
- rectilinear-fill.c \
- rectilinear-miter-limit.c \
- rectilinear-dash.c \
- rectilinear-stroke.c \
- reflected-stroke.c \
- rel-path.c \
- rgb24-ignore-alpha.c \
- rotate-image-surface-paint.c \
- scale-down-source-surface-paint.c \
- scale-offset-image.c \
- scale-offset-similar.c \
- scale-source-surface-paint.c \
- scaled-font-zero-matrix.c \
- stroke-ctm-caps.c \
- stroke-image.c \
- select-font-face.c \
- select-font-no-show-text.c \
- self-copy.c \
- self-copy-overlap.c \
- self-intersecting.c \
- set-source.c \
- show-glyphs-many.c \
- show-text-current-point.c \
- skew-extreme.c \
- smask.c \
- smask-fill.c \
- smask-image-mask.c \
- smask-mask.c \
- smask-paint.c \
- smask-stroke.c \
- smask-text.c \
- solid-pattern-cache-stress.c \
- source-clip.c \
- source-clip-scale.c \
- source-surface-scale-paint.c \
- spline-decomposition.c \
- surface-finish-twice.c \
- surface-pattern.c \
- surface-pattern-big-scale-down.c \
- surface-pattern-scale-down.c \
- surface-pattern-scale-up.c \
- text-antialias-gray.c \
- text-antialias-none.c \
- text-antialias-subpixel.c \
- text-cache-crash.c \
- text-glyph-range.c \
- text-pattern.c \
- text-rotate.c \
- text-transform.c \
- text-zero-len.c \
- toy-font-face.c \
- transforms.c \
- translate-show-surface.c \
- trap-clip.c \
- truetype-tables.c \
- twin.c \
- unantialiased-shapes.c \
- unbounded-operator.c \
- user-data.c \
- user-font.c \
- user-font-mask.c \
- user-font-proxy.c \
- user-font-rescale.c \
- zero-alpha.c
-
# Then we have a collection of tests that are only run if certain
# features are compiled into cairo
if HAVE_PTHREAD
-test_sources += pthread-show-text.c
+test_sources += $(pthread_test_sources)
endif
if CAIRO_HAS_FT_FONT
-test_sources += bitmap-font.c
-test_sources += ft-font-create-for-ft-face.c
-test_sources += ft-show-glyphs-positioning.c
-test_sources += ft-show-glyphs-table.c
-test_sources += ft-text-vertical-layout-type1.c
-test_sources += ft-text-vertical-layout-type3.c
-test_sources += ft-text-antialias-none.c
+test_sources += $(ft_font_test_sources)
endif
# Need to add quartz-surface-source
if CAIRO_HAS_QUARTZ_SURFACE
-test_sources += quartz-surface-source.c
+test_sources += $(quartz_surface_test_sources)
endif
if CAIRO_HAS_GL_EGL_SURFACE
@@ -238,49 +32,46 @@ glx_flowers_LDADD = $(top_builddir)/src/libcairo.la $(CAIRO_LDADD)
endif
if CAIRO_HAS_GLITZ_SURFACE
-test_sources += glitz-surface-source.c
+test_sources += $(glitz_surface_test_sources)
endif
if CAIRO_HAS_PDF_SURFACE
-test_sources += pdf-features.c
-test_sources += pdf-mime-data.c
-test_sources += pdf-surface-source.c
+test_sources += $(pdf_surface_test_sources)
endif
if CAIRO_HAS_PS_SURFACE
-test_sources += ps-features.c
-test_sources += ps-surface-source.c
+test_sources += $(ps_surface_test_sources)
endif
if CAIRO_HAS_SVG_SURFACE
-test_sources += svg-surface.c
-test_sources += svg-clip.c
-test_sources += svg-surface-source.c
+test_sources += $(svg_surface_test_sources)
+endif
+
+if CAIRO_HAS_TEST_SURFACES
+test_sources += $(test_fallback16_surface_test_sources)
endif
if CAIRO_HAS_XLIB_SURFACE
-test_sources += xlib-expose-event.c
-test_sources += xlib-surface.c
-test_sources += xlib-surface-source.c
+test_sources += $(xlib_surface_test_sources)
endif
if CAIRO_HAS_XLIB_XRENDER_SURFACE
-test_sources += get-xrender-format.c
+test_sources += $(xlib_xrender_surface_test_sources)
endif
if CAIRO_HAS_MULTI_PAGE_SURFACES
-test_sources += multi-page.c
+test_sources += $(multi_page_surface_test_sources)
endif
# Include fallback-resolution (once!) if we have any of the vector surfaces
if CAIRO_HAS_SVG_SURFACE
-test = fallback-resolution.c
+test = $(fallback_resolution_test_sources)
endif
if CAIRO_HAS_PDF_SURFACE
-test = fallback-resolution.c
+test = $(fallback_resolution_test_sources)
endif
if CAIRO_HAS_PS_SURFACE
-test = fallback-resolution.c
+test = $(fallback_resolution_test_sources)
endif
test_sources += $(test)
@@ -290,12 +81,8 @@ cairo-test-constructors.c: Makefile $(test_sources) make-cairo-test-constructors
@(cd $(srcdir) && ./make-cairo-test-constructors.pl $(test_sources)) > $@
cairo_test_suite_SOURCES = \
- buffer-diff.c \
- buffer-diff.h \
- cairo-test.c \
- cairo-test.h \
- cairo-test-private.h \
- cairo-test-runner.c \
+ $(cairo_test_suite_sources) \
+ $(cairo_test_suite_headers) \
$(test_sources)
if CAIRO_HAS_CONSTRUCTOR_ATTRIBUTE
else
@@ -318,10 +105,6 @@ if HAVE_PTHREAD
cairo_test_suite_LDADD += -lpthread
endif
-if CAIRO_HAS_SDL_SURFACE
-cairo_test_suite_LDADD += $(sdl_LIBS)
-endif
-
BUILT_SOURCES += cairo-test-constructors.c
noinst_SCRIPTS = make-cairo-test-constructors.pl
EXTRA_DIST += $(BUILT_SOURCES) $(noinst_SCRIPTS) COPYING
@@ -987,7 +770,6 @@ REFERENCE_IMAGES = \
trap-clip.ps2.argb32.ref.png \
trap-clip.ps2.rgb24.ref.png \
twin.ref.png \
- twin.pdf.ref.png \
twin.ps.ref.png \
twin.svg.ref.png \
unantialiased-shapes.ref.png \
diff --git a/test/Makefile.sources b/test/Makefile.sources
new file mode 100644
index 00000000..eeb9294e
--- /dev/null
+++ b/test/Makefile.sources
@@ -0,0 +1,254 @@
+test_sources = \
+ a1-image-sample.c \
+ a1-mask.c \
+ a1-traps-sample.c \
+ a8-mask.c \
+ alpha-similar.c \
+ big-line.c \
+ big-trap.c \
+ bilevel-image.c \
+ caps.c \
+ caps-joins.c \
+ caps-joins-alpha.c \
+ caps-joins-curve.c \
+ caps-sub-paths.c \
+ clip-all.c \
+ clip-empty.c \
+ clip-fill-rule.c \
+ clip-fill-rule-pixel-aligned.c \
+ clip-nesting.c \
+ clip-operator.c \
+ clip-push-group.c \
+ clip-twice.c \
+ clip-zero.c \
+ clipped-group.c \
+ clipped-surface.c \
+ close-path.c \
+ composite-integer-translate-source.c \
+ composite-integer-translate-over.c \
+ composite-integer-translate-over-repeat.c \
+ copy-path.c \
+ create-for-stream.c \
+ create-from-png.c \
+ create-from-png-stream.c \
+ culled-glyphs.c \
+ dash-caps-joins.c \
+ dash-curve.c \
+ dash-no-dash.c \
+ dash-offset-negative.c \
+ dash-scale.c \
+ dash-state.c \
+ dash-zero-length.c \
+ degenerate-arc.c \
+ degenerate-dash.c \
+ degenerate-path.c \
+ degenerate-pen.c \
+ device-offset.c \
+ device-offset-fractional.c \
+ device-offset-positive.c \
+ device-offset-scale.c \
+ extend-pad.c \
+ extend-pad-border.c \
+ extend-pad-similar.c \
+ extend-reflect.c \
+ extend-reflect-similar.c \
+ extend-repeat.c \
+ extend-repeat-similar.c \
+ fill-alpha.c \
+ fill-alpha-pattern.c \
+ fill-and-stroke.c \
+ fill-and-stroke-alpha.c \
+ fill-and-stroke-alpha-add.c \
+ fill-degenerate-sort-order.c \
+ fill-image.c \
+ fill-missed-stop.c \
+ fill-rule.c \
+ filter-bilinear-extents.c \
+ filter-nearest-offset.c \
+ filter-nearest-transformed.c \
+ finer-grained-fallbacks.c \
+ font-face-get-type.c \
+ font-matrix-translation.c \
+ font-options.c \
+ glyph-cache-pressure.c \
+ get-and-set.c \
+ get-clip.c \
+ get-group-target.c \
+ get-path-extents.c \
+ gradient-alpha.c \
+ gradient-constant-alpha.c \
+ gradient-zero-stops.c \
+ group-paint.c \
+ huge-linear.c \
+ huge-radial.c \
+ image-surface-source.c \
+ infinite-join.c \
+ in-fill-empty-trapezoid.c \
+ in-fill-trapezoid.c \
+ invalid-matrix.c \
+ joins.c \
+ large-clip.c \
+ large-font.c \
+ large-source.c \
+ large-source-roi.c \
+ leaky-dash.c \
+ leaky-dashed-rectangle.c \
+ leaky-dashed-stroke.c \
+ leaky-polygon.c \
+ line-width.c \
+ line-width-scale.c \
+ line-width-zero.c \
+ linear-gradient.c \
+ linear-gradient-reflect.c \
+ long-dashed-lines.c \
+ long-lines.c \
+ mask.c \
+ mask-alpha.c \
+ mask-ctm.c \
+ mask-surface-ctm.c \
+ mask-transformed-image.c \
+ mask-transformed-similar.c \
+ meta-surface-pattern.c \
+ mime-data.c \
+ miter-precision.c \
+ move-to-show-surface.c \
+ new-sub-path.c \
+ nil-surface.c \
+ operator.c \
+ operator-alpha.c \
+ operator-clear.c \
+ operator-source.c \
+ over-above-source.c \
+ over-around-source.c \
+ over-below-source.c \
+ over-between-source.c \
+ paint.c \
+ paint-repeat.c \
+ paint-source-alpha.c \
+ paint-with-alpha.c \
+ path-append.c \
+ path-precision.c \
+ pattern-get-type.c \
+ pattern-getters.c \
+ pixman-rotate.c \
+ png.c \
+ push-group.c \
+ radial-gradient.c \
+ random-intersections.c \
+ rectangle-rounding-error.c \
+ rectilinear-fill.c \
+ rectilinear-miter-limit.c \
+ rectilinear-dash.c \
+ rectilinear-stroke.c \
+ reflected-stroke.c \
+ rel-path.c \
+ rgb24-ignore-alpha.c \
+ rotate-image-surface-paint.c \
+ scale-down-source-surface-paint.c \
+ scale-offset-image.c \
+ scale-offset-similar.c \
+ scale-source-surface-paint.c \
+ scaled-font-zero-matrix.c \
+ stroke-ctm-caps.c \
+ stroke-image.c \
+ select-font-face.c \
+ select-font-no-show-text.c \
+ self-copy.c \
+ self-copy-overlap.c \
+ self-intersecting.c \
+ set-source.c \
+ show-glyphs-many.c \
+ show-text-current-point.c \
+ skew-extreme.c \
+ smask.c \
+ smask-fill.c \
+ smask-image-mask.c \
+ smask-mask.c \
+ smask-paint.c \
+ smask-stroke.c \
+ smask-text.c \
+ solid-pattern-cache-stress.c \
+ source-clip.c \
+ source-clip-scale.c \
+ source-surface-scale-paint.c \
+ spline-decomposition.c \
+ surface-finish-twice.c \
+ surface-pattern.c \
+ surface-pattern-big-scale-down.c \
+ surface-pattern-scale-down.c \
+ surface-pattern-scale-up.c \
+ text-antialias-gray.c \
+ text-antialias-none.c \
+ text-antialias-subpixel.c \
+ text-cache-crash.c \
+ text-glyph-range.c \
+ text-pattern.c \
+ text-rotate.c \
+ text-transform.c \
+ text-zero-len.c \
+ toy-font-face.c \
+ transforms.c \
+ translate-show-surface.c \
+ trap-clip.c \
+ twin.c \
+ unantialiased-shapes.c \
+ unbounded-operator.c \
+ user-data.c \
+ user-font.c \
+ user-font-mask.c \
+ user-font-proxy.c \
+ user-font-rescale.c \
+ zero-alpha.c
+
+pthread_test_sources = pthread-show-text.c
+
+ft_font_test_sources = \
+ bitmap-font.c \
+ ft-font-create-for-ft-face.c \
+ ft-show-glyphs-positioning.c \
+ ft-show-glyphs-table.c \
+ ft-text-vertical-layout-type1.c \
+ ft-text-vertical-layout-type3.c \
+ ft-text-antialias-none.c
+
+quartz_surface_test_sources = quartz-surface-source.c
+
+glitz_surface_test_sources = glitz-surface-source.c
+
+pdf_surface_test_sources = \
+ pdf-features.c \
+ pdf-mime-data.c \
+ pdf-surface-source.c
+
+ps_surface_test_sources = \
+ ps-features.c \
+ ps-surface-source.c
+
+svg_surface_test_sources = \
+ svg-surface.c \
+ svg-clip.c \
+ svg-surface-source.c
+
+test_fallback16_surface_test_sources = \
+ test-fallback16-surface-source.c
+
+xlib_surface_test_sources = \
+ xlib-expose-event.c \
+ xlib-surface.c \
+ xlib-surface-source.c
+
+xlib_xrender_surface_test_sources = get-xrender-format.c
+
+multi_page_surface_test_sources = multi-page.c
+
+fallback_resolution_test_sources = fallback-resolution.c
+
+cairo_test_suite_headers = \
+ buffer-diff.h \
+ cairo-test.h \
+ cairo-test-private.h
+
+cairo_test_suite_sources = \
+ buffer-diff.c \
+ cairo-test.c \
+ cairo-test-runner.c
diff --git a/test/Makefile.win32 b/test/Makefile.win32
index 003d96a2..f6a936ed 100644
--- a/test/Makefile.win32
+++ b/test/Makefile.win32
@@ -1,121 +1,49 @@
top_srcdir = ..
include $(top_srcdir)/build/Makefile.win32.common
+include $(top_srcdir)/test/Makefile.sources
CFLAGS += -I../src -I../boilerplate -I./pdiff
LDFLAGS += ./pdiff/pdiff.lib ../src/$(CFG)/cairo-static.lib $(PIXMAN_LIBS) ../boilerplate/$(CFG)/boiler.lib $(EXE_LDFLAGS)
-TESTS = \
-a8-mask \
-caps-joins \
-caps-joins-alpha \
-caps-sub-paths \
-clip-all \
-clip-fill-rule \
-clip-fill-rule-pixel-aligned \
-clip-nesting \
-clip-operator \
-clip-twice \
-composite-integer-translate-source \
-composite-integer-translate-over \
-composite-integer-translate-over-repeat \
-create-for-stream \
-create-from-png \
-create-from-png-stream \
-dash-caps-joins \
-dash-no-dash \
-dash-offset-negative \
-dash-scale \
-dash-zero-length \
-degenerate-path \
-device-offset \
-device-offset-positive \
-extend-pad \
-extend-reflect \
-fill-and-stroke \
-fill-and-stroke-alpha \
-fill-and-stroke-alpha-add \
-fill-rule \
-filter-nearest-offset \
-font-face-get-type \
-font-matrix-translation \
-glyph-cache-pressure \
-get-and-set \
-get-clip \
-get-group-target \
-get-path-extents \
-gradient-alpha \
-leaky-dash \
-leaky-polygon \
-line-width \
-line-width-scale \
-linear-gradient \
-mask \
-mask-ctm \
-mask-surface-ctm \
-move-to-show-surface \
-new-sub-path \
-nil-surface \
-operator-clear \
-operator-source \
-paint \
-paint-source-alpha \
-paint-with-alpha \
-pattern-get-type \
-pattern-getters \
-pixman-rotate \
-rectangle-rounding-error \
-scale-source-surface-paint \
-select-font-face \
-select-font-no-show-text \
-self-copy \
-self-intersecting \
-set-source \
-show-text-current-point \
-source-clip \
-source-surface-scale-paint \
-surface-finish-twice \
-surface-pattern \
-text-antialias-gray \
-text-antialias-none \
-text-antialias-subpixel \
-text-cache-crash \
-text-pattern \
-text-rotate \
-transforms \
-translate-show-surface \
-trap-clip \
-unantialiased-shapes \
-unbounded-operator \
-user-data \
-rel-path \
-push-group \
-zero-alpha \
-$(NULL)
TESTCORE_SOURCES = \
cairo-test.c \
buffer-diff.c \
$(NULL)
-TEST_EXE = $(patsubst %, $(CFG)/%.exe, $(TESTS))
-# TEST_EXE = $(addsuffix .exe,$(TESTS))
+all: cairo-test-suite.exe
-all: $(TEST_EXE)
+cairo-test-constructors.c: $(test_sources)
+ ./make-cairo-test-constructors.pl $(test_sources) > $@
-$(CFG)/%.exe: %.c ./pdiff/pdiff.lib
- @mkdir -p $(CFG)
- @$(CC) $(CFLAGS) -Fe"$@" $< $(TESTCORE_SOURCES) -link $(LDFLAGS)
+SOURCES = $(cairo_test_suite_sources) $(test_sources) cairo-test-constructors.c
+
+OBJECTS = $(patsubst %.c, $(CFG)/%-static.obj, $(SOURCES))
+
+cairo-test-suite.exe: $(OBJECTS) ./pdiff/pdiff.lib ../boilerplate/$(CFG)/boiler.lib
+ $(CC) $(OPT) $(MS_MDFLAGS) $(OBJECTS) -Fe"$@" -link $(LDFLAGS) $(CAIRO_LIBS) /NODEFAULTLIB:library
./pdiff/pdiff.lib:
(cd pdiff ; $(MAKE) -f Makefile.win32)
-test: $(TEST_EXE)
- @for exe in $(TEST_EXE) ; do \
- echo $$exe ; \
- ( ./$$exe || exit 0 ) ; \
- done
+../boilerplate/$(CFG)/boiler.lib:
+ (cd ../boilerplate ; $(MAKE) -f Makefile.win32)
+
+.PHONY: check test html
+
+check: cairo-test-suite.exe
+ ./cairo-test-suite.exe
+
+# define gen-html so that both 'test' and 'html' targets
+# can generate html while having different dependencies
+define gen-html
+@echo Creating index.html...
+@perl make-html.pl > index.html
+endef
+
+test: check
+ $(gen-html)
html:
- @echo Creating index.html...
- @perl make-html.pl > index.html
+ $(gen-html)
diff --git a/test/any2ppm.c b/test/any2ppm.c
index 7b3dabb8..13275814 100644
--- a/test/any2ppm.c
+++ b/test/any2ppm.c
@@ -77,7 +77,7 @@
#include <libspectre/spectre.h>
#endif
-#if HAVE_FCNTL_H && HAVE_SIGNAL_H && HAVE_SYS_STAT_H && HAVE_SYS_SOCKET_H && HAVE_SYS_POLL_H && HAVE_SYS_UN_H
+#if HAVE_UNISTD_H && HAVE_FCNTL_H && HAVE_SIGNAL_H && HAVE_SYS_STAT_H && HAVE_SYS_SOCKET_H && HAVE_SYS_POLL_H && HAVE_SYS_UN_H
#include <fcntl.h>
#include <signal.h>
#include <sys/stat.h>
@@ -89,7 +89,11 @@
#define SOCKET_PATH "./.any2ppm"
#define TIMEOUT 60000 /* 60 seconds */
+#if _BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500)
#define CAN_RUN_AS_DAEMON 1
+#else
+#define CAN_RUN_AS_DAEMON 0
+#endif
#endif
#define ARRAY_LENGTH(A) (sizeof (A) / sizeof (A[0]))
@@ -235,6 +239,7 @@ write_ppm (cairo_surface_t *surface, int fd)
static cairo_surface_t *
_create_image (void *closure,
+ cairo_content_t content,
double width, double height)
//csi_object_t *dictionary)
{
diff --git a/test/cairo-test-runner.c b/test/cairo-test-runner.c
index e604d0d9..3652a9b5 100644
--- a/test/cairo-test-runner.c
+++ b/test/cairo-test-runner.c
@@ -33,10 +33,6 @@
#undef CAIRO_VERSION_MICRO
#include "../cairo-version.h"
-#if CAIRO_HAS_SDL_SURFACE
-#include <SDL_main.h>
-#endif
-
#include <pixman.h> /* for version information */
/* Coregraphics doesn't seem to like being forked and reports:
@@ -54,6 +50,10 @@
#include <sys/wait.h>
#endif
+#ifdef _MSC_VER
+#include <crtdbg.h>
+#endif
+
typedef struct _cairo_test_list {
const cairo_test_t *test;
struct _cairo_test_list *next;
@@ -64,6 +64,7 @@ typedef struct _cairo_test_runner {
unsigned int num_device_offsets;
+ cairo_bool_t passed;
int num_passed;
int num_xpassed;
int num_skipped;
@@ -339,6 +340,8 @@ _runner_init (cairo_test_runner_t *runner)
{
cairo_test_init (&runner->base, "cairo-test-suite");
+ runner->passed = TRUE;
+
runner->xpasses_per_target = xcalloc (sizeof (cairo_test_list_t *),
runner->base.num_targets);
runner->fails_per_target = xcalloc (sizeof (cairo_test_list_t *),
@@ -449,6 +452,13 @@ _runner_print_results (cairo_test_runner_t *runner)
{
_runner_print_summary (runner);
_runner_print_details (runner);
+
+ if (! runner->passed) {
+ _log (&runner->base,
+"\n"
+"Note: These failures may be due to external factors.\n"
+"Please read test/README -- \"Getting the elusive zero failures\".\n");
+ }
}
static cairo_test_status_t
@@ -856,6 +866,7 @@ main (int argc, char **argv)
targets[len-2] = '\0';
_log (&runner.base, "\n%s: CRASH! (%s)\n", name, targets);
runner.num_crashed++;
+ runner.passed = FALSE;
} else if (failed) {
if (expectation == CAIRO_TEST_SUCCESS) {
len = 0;
@@ -878,6 +889,7 @@ main (int argc, char **argv)
targets[len-2] = '\0';
_log (&runner.base, "%s: FAIL (%s)\n", name, targets);
runner.num_failed++;
+ runner.passed = FALSE;
}
} else {
_log (&runner.base, "%s: XFAIL\n", name);
diff --git a/test/cairo-test.c b/test/cairo-test.c
index 264fed50..4e3d2fb3 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -131,7 +131,7 @@ _cairo_test_init (cairo_test_context_t *ctx,
{
char *log_name;
- MF (VALGRIND_DISABLE_FAULTS ());
+ MF (MEMFAULT_DISABLE_FAULTS ());
#if HAVE_FEENABLEEXCEPT
feenableexcept (FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
@@ -222,7 +222,7 @@ cairo_test_init_thread (cairo_test_context_t *ctx,
cairo_test_context_t *master,
int thread)
{
- MF (VALGRIND_DISABLE_FAULTS ());
+ MF (MEMFAULT_DISABLE_FAULTS ());
*ctx = *master;
ctx->thread = thread;
@@ -739,11 +739,17 @@ cairo_test_for_target (cairo_test_context_t *ctx,
#if HAVE_MEMFAULT
REPEAT:
- VALGRIND_CLEAR_FAULTS ();
- VALGRIND_RESET_LEAKS ();
+ MEMFAULT_CLEAR_FAULTS ();
+ MEMFAULT_RESET_LEAKS ();
ctx->last_fault_count = 0;
- last_fault_count = VALGRIND_COUNT_FAULTS ();
- VALGRIND_ENABLE_FAULTS ();
+ last_fault_count = MEMFAULT_COUNT_FAULTS ();
+
+ /* Pre-initialise fontconfig so that the configuration is loaded without
+ * malloc failures (our primary goal is to test cairo fault tolerance).
+ */
+ FcInit ();
+
+ MEMFAULT_ENABLE_FAULTS ();
#endif
have_output = FALSE;
have_result = FALSE;
@@ -766,7 +772,7 @@ REPEAT:
#if HAVE_MEMFAULT
if (ctx->malloc_failure &&
- VALGRIND_COUNT_FAULTS () - last_fault_count > 0 &&
+ MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 &&
cairo_surface_status (surface) == CAIRO_STATUS_NO_MEMORY)
{
goto REPEAT;
@@ -774,7 +780,7 @@ REPEAT:
#endif
if (cairo_surface_status (surface)) {
- MF (VALGRIND_PRINT_FAULTS ());
+ MF (MEMFAULT_PRINT_FAULTS ());
cairo_test_log (ctx, "Error: Created an error surface\n");
ret = CAIRO_TEST_FAILURE;
goto UNWIND_STRINGS;
@@ -782,7 +788,7 @@ REPEAT:
/* Check that we created a surface of the expected type. */
if (cairo_surface_get_type (surface) != target->expected_type) {
- MF (VALGRIND_PRINT_FAULTS ());
+ MF (MEMFAULT_PRINT_FAULTS ());
cairo_test_log (ctx, "Error: Created surface is of type %d (expected %d)\n",
cairo_surface_get_type (surface), target->expected_type);
ret = CAIRO_TEST_FAILURE;
@@ -795,7 +801,7 @@ REPEAT:
expected_content = cairo_boilerplate_content (target->content);
if (cairo_surface_get_content (surface) != expected_content) {
- MF (VALGRIND_PRINT_FAULTS ());
+ MF (MEMFAULT_PRINT_FAULTS ());
cairo_test_log (ctx, "Error: Created surface has content %d (expected %d)\n",
cairo_surface_get_content (surface), expected_content);
ret = CAIRO_TEST_FAILURE;
@@ -850,11 +856,11 @@ REPEAT:
}
#if HAVE_MEMFAULT
- VALGRIND_DISABLE_FAULTS ();
+ MEMFAULT_DISABLE_FAULTS ();
/* repeat test after malloc failure injection */
if (ctx->malloc_failure &&
- VALGRIND_COUNT_FAULTS () - last_fault_count > 0 &&
+ MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 &&
(status == CAIRO_TEST_NO_MEMORY ||
cairo_status (cr) == CAIRO_STATUS_NO_MEMORY ||
cairo_surface_status (surface) == CAIRO_STATUS_NO_MEMORY))
@@ -868,9 +874,9 @@ REPEAT:
#if HAVE_FCFINI
FcFini ();
#endif
- if (VALGRIND_COUNT_LEAKS () > 0) {
- VALGRIND_PRINT_FAULTS ();
- VALGRIND_PRINT_LEAKS ();
+ if (MEMFAULT_COUNT_LEAKS () > 0) {
+ MEMFAULT_PRINT_FAULTS ();
+ MEMFAULT_PRINT_LEAKS ();
}
}
@@ -893,11 +899,11 @@ REPEAT:
}
#if HAVE_MEMFAULT
- if (VALGRIND_COUNT_FAULTS () - last_fault_count > 0 &&
- VALGRIND_HAS_FAULTS ())
+ if (MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 &&
+ MEMFAULT_HAS_FAULTS ())
{
VALGRIND_PRINTF ("Unreported memfaults...");
- VALGRIND_PRINT_FAULTS ();
+ MEMFAULT_PRINT_FAULTS ();
}
#endif
@@ -910,7 +916,42 @@ REPEAT:
cairo_status_t diff_status;
if (target->finish_surface != NULL) {
+#if HAVE_MEMFAULT
+ /* We need to re-enable faults as most meta-surface processing
+ * is done during cairo_surface_finish().
+ */
+ MEMFAULT_CLEAR_FAULTS ();
+ last_fault_count = MEMFAULT_COUNT_FAULTS ();
+ MEMFAULT_ENABLE_FAULTS ();
+#endif
+
diff_status = target->finish_surface (surface);
+
+#if HAVE_MEMFAULT
+ MEMFAULT_DISABLE_FAULTS ();
+
+ if (ctx->malloc_failure &&
+ MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 &&
+ diff_status == CAIRO_STATUS_NO_MEMORY)
+ {
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+ if (target->cleanup)
+ target->cleanup (closure);
+ if (ctx->thread == 0) {
+ cairo_debug_reset_static_data ();
+#if HAVE_FCFINI
+ FcFini ();
+#endif
+ if (MEMFAULT_COUNT_LEAKS () > 0) {
+ MEMFAULT_PRINT_FAULTS ();
+ MEMFAULT_PRINT_LEAKS ();
+ }
+ }
+
+ goto REPEAT;
+ }
+#endif
if (diff_status) {
cairo_test_log (ctx, "Error: Failed to finish surface: %s\n",
cairo_status_to_string (diff_status));
@@ -1094,7 +1135,7 @@ UNWIND_CAIRO:
#if HAVE_MEMFAULT
if (ret == CAIRO_TEST_FAILURE && ctx->expectation != CAIRO_TEST_FAILURE)
- VALGRIND_PRINT_FAULTS ();
+ MEMFAULT_PRINT_FAULTS ();
#endif
cairo_destroy (cr);
UNWIND_SURFACE:
@@ -1111,13 +1152,13 @@ UNWIND_SURFACE:
FcFini ();
#endif
- if (VALGRIND_COUNT_LEAKS () > 0) {
+ if (MEMFAULT_COUNT_LEAKS () > 0) {
if (ret != CAIRO_TEST_FAILURE ||
ctx->expectation == CAIRO_TEST_FAILURE)
{
- VALGRIND_PRINT_FAULTS ();
+ MEMFAULT_PRINT_FAULTS ();
}
- VALGRIND_PRINT_LEAKS ();
+ MEMFAULT_PRINT_LEAKS ();
}
}
@@ -1193,7 +1234,7 @@ _cairo_test_context_run_for_target (cairo_test_context_t *ctx,
}
#if defined(HAVE_SIGNAL_H) && defined(HAVE_SETJMP_H)
- if (ctx->thread == 0) {
+ if (ctx->thread == 0 && ! RUNNING_ON_VALGRIND) {
void (* volatile old_segfault_handler)(int);
void (* volatile old_sigpipe_handler)(int);
void (* volatile old_sigabrt_handler)(int);
@@ -1607,7 +1648,7 @@ cairo_test_malloc_failure (const cairo_test_context_t *ctx,
int n_faults;
/* prevent infinite loops... */
- n_faults = VALGRIND_COUNT_FAULTS ();
+ n_faults = MEMFAULT_COUNT_FAULTS ();
if (n_faults == ctx->last_fault_count)
return FALSE;
diff --git a/test/cairo-test.h b/test/cairo-test.h
index 8e068f07..5a5be44e 100644
--- a/test/cairo-test.h
+++ b/test/cairo-test.h
@@ -56,12 +56,28 @@ typedef unsigned __int64 uint64_t;
#ifdef _MSC_VER
#define _USE_MATH_DEFINES
+
+#include <float.h>
+#define isnan(x) _isnan(x)
+
#endif
#include <math.h>
-/* remove this if you don't have IEEE754 floating point */
-#define HAVE_IEEE754
+static inline double
+cairo_test_NaN (void)
+{
+#ifdef _MSC_VER
+ /* MSVC strtod("NaN", NULL) returns 0.0 */
+ union {
+ uint32_t i[2];
+ double d;
+ } nan = {{0xffffffff, 0x7fffffff}};
+ return nan.d;
+#else
+ return strtod("NaN", NULL);
+#endif
+}
typedef enum cairo_test_status {
CAIRO_TEST_SUCCESS = 0,
diff --git a/test/create-from-png.c b/test/create-from-png.c
index d9d2e548..585fac2c 100644
--- a/test/create-from-png.c
+++ b/test/create-from-png.c
@@ -54,13 +54,19 @@ draw (cairo_t *cr, int width, int height)
surface = cairo_image_surface_create_from_png (filename);
if (cairo_surface_status (surface)) {
- cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
- filename,
- cairo_status_to_string (cairo_surface_status (surface)));
+ cairo_test_status_t result;
+
+ result = cairo_test_status_from_status (ctx,
+ cairo_surface_status (surface));
+ if (result == CAIRO_TEST_FAILURE) {
+ cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
+ filename,
+ cairo_status_to_string (cairo_surface_status (surface)));
+ }
+
free (filename);
- return CAIRO_TEST_FAILURE;
+ return result;
}
- free (filename);
cairo_set_source_surface (cr, surface, 0, 0);
cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
@@ -68,6 +74,7 @@ draw (cairo_t *cr, int width, int height)
cairo_surface_destroy (surface);
+ free (filename);
return CAIRO_TEST_SUCCESS;
}
@@ -81,27 +88,42 @@ preamble (cairo_test_context_t *ctx)
surface = cairo_image_surface_create_from_png ("___THIS_FILE_DOES_NOT_EXIST___");
if (cairo_surface_status (surface) != CAIRO_STATUS_FILE_NOT_FOUND) {
- cairo_test_log (ctx, "Error: expected \"file not found\", but got: %s\n",
- cairo_status_to_string (cairo_surface_status (surface)));
- result = CAIRO_TEST_FAILURE;
+ result = cairo_test_status_from_status (ctx,
+ cairo_surface_status (surface));
+ if (result == CAIRO_TEST_FAILURE) {
+ cairo_test_log (ctx, "Error: expected \"file not found\", but got: %s\n",
+ cairo_status_to_string (cairo_surface_status (surface)));
+ }
}
cairo_surface_destroy (surface);
+ if (result != CAIRO_TEST_SUCCESS)
+ return result;
surface = cairo_image_surface_create_from_png_stream (no_memory_error, NULL);
if (cairo_surface_status (surface) != CAIRO_STATUS_NO_MEMORY) {
- cairo_test_log (ctx, "Error: expected \"out of memory\", but got: %s\n",
- cairo_status_to_string (cairo_surface_status (surface)));
- result = CAIRO_TEST_FAILURE;
+ result = cairo_test_status_from_status (ctx,
+ cairo_surface_status (surface));
+ if (result == CAIRO_TEST_FAILURE) {
+ cairo_test_log (ctx, "Error: expected \"out of memory\", but got: %s\n",
+ cairo_status_to_string (cairo_surface_status (surface)));
+ }
}
cairo_surface_destroy (surface);
+ if (result != CAIRO_TEST_SUCCESS)
+ return result;
surface = cairo_image_surface_create_from_png_stream (read_error, NULL);
if (cairo_surface_status (surface) != CAIRO_STATUS_READ_ERROR) {
- cairo_test_log (ctx, "Error: expected \"read error\", but got: %s\n",
- cairo_status_to_string (cairo_surface_status (surface)));
- result = CAIRO_TEST_FAILURE;
+ result = cairo_test_status_from_status (ctx,
+ cairo_surface_status (surface));
+ if (result == CAIRO_TEST_FAILURE) {
+ cairo_test_log (ctx, "Error: expected \"read error\", but got: %s\n",
+ cairo_status_to_string (cairo_surface_status (surface)));
+ }
}
cairo_surface_destroy (surface);
+ if (result != CAIRO_TEST_SUCCESS)
+ return result;
/* cheekily test error propagation from the user write funcs as well ... */
xasprintf (&filename, "%s/%s", ctx->srcdir,
@@ -109,48 +131,63 @@ preamble (cairo_test_context_t *ctx)
surface = cairo_image_surface_create_from_png (filename);
if (cairo_surface_status (surface)) {
- cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
- filename,
- cairo_status_to_string (cairo_surface_status (surface)));
- result = CAIRO_TEST_FAILURE;
+ result = cairo_test_status_from_status (ctx,
+ cairo_surface_status (surface));
+ if (result == CAIRO_TEST_FAILURE) {
+ cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
+ filename,
+ cairo_status_to_string (cairo_surface_status (surface)));
+ }
} else {
status = cairo_surface_write_to_png_stream (surface,
(cairo_write_func_t) no_memory_error,
NULL);
if (status != CAIRO_STATUS_NO_MEMORY) {
- cairo_test_log (ctx, "Error: expected \"out of memory\", but got: %s\n",
- cairo_status_to_string (status));
- result = CAIRO_TEST_FAILURE;
+ result = cairo_test_status_from_status (ctx, status);
+ if (result == CAIRO_TEST_FAILURE) {
+ cairo_test_log (ctx, "Error: expected \"out of memory\", but got: %s\n",
+ cairo_status_to_string (status));
+ }
}
status = cairo_surface_write_to_png_stream (surface,
(cairo_write_func_t) read_error,
NULL);
if (status != CAIRO_STATUS_READ_ERROR) {
- cairo_test_log (ctx, "Error: expected \"read error\", but got: %s\n",
- cairo_status_to_string (status));
- result = CAIRO_TEST_FAILURE;
+ result = cairo_test_status_from_status (ctx, status);
+ if (result == CAIRO_TEST_FAILURE) {
+ cairo_test_log (ctx, "Error: expected \"read error\", but got: %s\n",
+ cairo_status_to_string (status));
+ }
}
/* and check that error has not propagated to the surface */
if (cairo_surface_status (surface)) {
- cairo_test_log (ctx, "Error: user write error propagated to surface: %s",
- cairo_status_to_string (cairo_surface_status (surface)));
- result = CAIRO_TEST_FAILURE;
+ result = cairo_test_status_from_status (ctx,
+ cairo_surface_status (surface));
+ if (result == CAIRO_TEST_FAILURE) {
+ cairo_test_log (ctx, "Error: user write error propagated to surface: %s",
+ cairo_status_to_string (cairo_surface_status (surface)));
+ }
}
}
cairo_surface_destroy (surface);
free (filename);
+ if (result != CAIRO_TEST_SUCCESS)
+ return result;
/* check that loading alpha/opaque PNGs generate the correct surfaces */
xasprintf (&filename, "%s/%s", ctx->srcdir,
"create-from-png.alpha.ref.png");
surface = cairo_image_surface_create_from_png (filename);
if (cairo_surface_status (surface)) {
- cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
- filename,
- cairo_status_to_string (cairo_surface_status (surface)));
- result = CAIRO_TEST_FAILURE;
+ result = cairo_test_status_from_status (ctx,
+ cairo_surface_status (surface));
+ if (result == CAIRO_TEST_FAILURE) {
+ cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
+ filename,
+ cairo_status_to_string (cairo_surface_status (surface)));
+ }
} else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32) {
cairo_test_log (ctx, "Error reading PNG image %s: did not create an ARGB32 image\n",
filename);
@@ -158,15 +195,20 @@ preamble (cairo_test_context_t *ctx)
}
free (filename);
cairo_surface_destroy (surface);
+ if (result != CAIRO_TEST_SUCCESS)
+ return result;
xasprintf (&filename, "%s/%s", ctx->srcdir,
"create-from-png.ref.png");
surface = cairo_image_surface_create_from_png (filename);
if (cairo_surface_status (surface)) {
- cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
- filename,
- cairo_status_to_string (cairo_surface_status (surface)));
- result = CAIRO_TEST_FAILURE;
+ result = cairo_test_status_from_status (ctx,
+ cairo_surface_status (surface));
+ if (result == CAIRO_TEST_FAILURE) {
+ cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
+ filename,
+ cairo_status_to_string (cairo_surface_status (surface)));
+ }
} else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_RGB24) {
cairo_test_log (ctx, "Error reading PNG image %s: did not create an RGB24 image\n",
filename);
@@ -174,16 +216,21 @@ preamble (cairo_test_context_t *ctx)
}
free (filename);
cairo_surface_destroy (surface);
+ if (result != CAIRO_TEST_SUCCESS)
+ return result;
/* check paletted PNGs */
xasprintf (&filename, "%s/%s", ctx->srcdir,
"create-from-png.indexed-alpha.ref.png");
surface = cairo_image_surface_create_from_png (filename);
if (cairo_surface_status (surface)) {
- cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
- filename,
- cairo_status_to_string (cairo_surface_status (surface)));
- result = CAIRO_TEST_FAILURE;
+ result = cairo_test_status_from_status (ctx,
+ cairo_surface_status (surface));
+ if (result == CAIRO_TEST_FAILURE) {
+ cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
+ filename,
+ cairo_status_to_string (cairo_surface_status (surface)));
+ }
} else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32) {
cairo_test_log (ctx, "Error reading PNG image %s: did not create an ARGB32 image\n",
filename);
@@ -191,15 +238,20 @@ preamble (cairo_test_context_t *ctx)
}
free (filename);
cairo_surface_destroy (surface);
+ if (result != CAIRO_TEST_SUCCESS)
+ return result;
xasprintf (&filename, "%s/%s", ctx->srcdir,
"create-from-png.indexed.ref.png");
surface = cairo_image_surface_create_from_png (filename);
if (cairo_surface_status (surface)) {
- cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
- filename,
- cairo_status_to_string (cairo_surface_status (surface)));
- result = CAIRO_TEST_FAILURE;
+ result = cairo_test_status_from_status (ctx,
+ cairo_surface_status (surface));
+ if (result == CAIRO_TEST_FAILURE) {
+ cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
+ filename,
+ cairo_status_to_string (cairo_surface_status (surface)));
+ }
} else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_RGB24) {
cairo_test_log (ctx, "Error reading PNG image %s: did not create an RGB24 image\n",
filename);
@@ -207,16 +259,21 @@ preamble (cairo_test_context_t *ctx)
}
free (filename);
cairo_surface_destroy (surface);
+ if (result != CAIRO_TEST_SUCCESS)
+ return result;
/* check grayscale PNGs */
xasprintf (&filename, "%s/%s", ctx->srcdir,
"create-from-png.gray-alpha.ref.png");
surface = cairo_image_surface_create_from_png (filename);
if (cairo_surface_status (surface)) {
- cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
- filename,
- cairo_status_to_string (cairo_surface_status (surface)));
- result = CAIRO_TEST_FAILURE;
+ result = cairo_test_status_from_status (ctx,
+ cairo_surface_status (surface));
+ if (result == CAIRO_TEST_FAILURE) {
+ cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
+ filename,
+ cairo_status_to_string (cairo_surface_status (surface)));
+ }
} else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32) {
cairo_test_log (ctx, "Error reading PNG image %s: did not create an ARGB32 image\n",
filename);
@@ -224,15 +281,20 @@ preamble (cairo_test_context_t *ctx)
}
free (filename);
cairo_surface_destroy (surface);
+ if (result != CAIRO_TEST_SUCCESS)
+ return result;
xasprintf (&filename, "%s/%s", ctx->srcdir,
"create-from-png.gray.ref.png");
surface = cairo_image_surface_create_from_png (filename);
if (cairo_surface_status (surface)) {
- cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
- filename,
- cairo_status_to_string (cairo_surface_status (surface)));
- result = CAIRO_TEST_FAILURE;
+ result = cairo_test_status_from_status (ctx,
+ cairo_surface_status (surface));
+ if (result == CAIRO_TEST_FAILURE) {
+ cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
+ filename,
+ cairo_status_to_string (cairo_surface_status (surface)));
+ }
} else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_RGB24) {
cairo_test_log (ctx, "Error reading PNG image %s: did not create an RGB24 image\n",
filename);
diff --git a/test/fallback-resolution.c b/test/fallback-resolution.c
index 7b1d313b..eab79959 100644
--- a/test/fallback-resolution.c
+++ b/test/fallback-resolution.c
@@ -216,6 +216,7 @@ check_result (cairo_test_context_t *ctx,
cairo_surface_destroy (test_image);
free (png_name);
free (diff_name);
+ free (ref_name);
return FALSE;
}
@@ -247,6 +248,7 @@ check_result (cairo_test_context_t *ctx,
cairo_surface_destroy (diff_image);
free (png_name);
free (diff_name);
+ free (ref_name);
return ret;
}
diff --git a/test/ft-font-create-for-ft-face.c b/test/ft-font-create-for-ft-face.c
index 702b846a..52c838dd 100644
--- a/test/ft-font-create-for-ft-face.c
+++ b/test/ft-font-create-for-ft-face.c
@@ -26,6 +26,84 @@
#include "cairo-test.h"
#include <cairo-ft.h>
+static void
+_stress_font_cache (FT_Face ft_face, cairo_t *cr, int lvl);
+
+static cairo_font_face_t *
+_load_font (FT_Face ft_face, int flags, cairo_t *cr, int lvl)
+{
+ cairo_font_face_t *font_face;
+ cairo_font_extents_t font_extents;
+
+ _stress_font_cache (ft_face, cr, lvl+1);
+
+ font_face = cairo_ft_font_face_create_for_ft_face (ft_face, flags);
+
+ cairo_set_font_face (cr, font_face);
+ cairo_font_extents (cr, &font_extents);
+
+ _stress_font_cache (ft_face, cr, lvl+1);
+
+ return font_face;
+}
+
+static void
+_stress_font_cache (FT_Face ft_face, cairo_t *cr, int lvl)
+{
+#define A _load_font (ft_face, 0, cr, lvl)
+#define B _load_font (ft_face, FT_LOAD_NO_BITMAP, cr, lvl)
+#define C _load_font (ft_face, FT_LOAD_NO_RECURSE, cr, lvl)
+#define D _load_font (ft_face, FT_LOAD_FORCE_AUTOHINT, cr, lvl)
+
+ cairo_font_face_t *font_face[4];
+
+ while (lvl++ < 5) {
+ font_face[0] = A; font_face[1] = A;
+ font_face[2] = A; font_face[3] = A;
+ cairo_font_face_destroy (font_face[0]);
+ cairo_font_face_destroy (font_face[1]);
+ cairo_font_face_destroy (font_face[2]);
+ cairo_font_face_destroy (font_face[3]);
+
+ font_face[0] = A; font_face[1] = B;
+ font_face[2] = C; font_face[3] = D;
+ cairo_font_face_destroy (font_face[0]);
+ cairo_font_face_destroy (font_face[1]);
+ cairo_font_face_destroy (font_face[2]);
+ cairo_font_face_destroy (font_face[3]);
+
+ font_face[0] = A; font_face[1] = B;
+ font_face[2] = C; font_face[3] = D;
+ cairo_font_face_destroy (font_face[3]);
+ cairo_font_face_destroy (font_face[2]);
+ cairo_font_face_destroy (font_face[1]);
+ cairo_font_face_destroy (font_face[0]);
+
+ font_face[0] = A;
+ font_face[1] = A;
+ cairo_font_face_destroy (font_face[0]);
+ font_face[2] = A;
+ cairo_font_face_destroy (font_face[1]);
+ font_face[3] = A;
+ cairo_font_face_destroy (font_face[2]);
+ cairo_font_face_destroy (font_face[3]);
+
+ font_face[0] = A;
+ font_face[1] = B;
+ cairo_font_face_destroy (font_face[0]);
+ font_face[2] = C;
+ cairo_font_face_destroy (font_face[1]);
+ font_face[3] = D;
+ cairo_font_face_destroy (font_face[2]);
+ cairo_font_face_destroy (font_face[3]);
+ }
+
+#undef A
+#undef B
+#undef C
+#undef D
+}
+
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
@@ -48,23 +126,31 @@ draw (cairo_t *cr, int width, int height)
pattern = FcPatternCreate ();
if (! pattern) {
cairo_test_log (ctx, "FcPatternCreate failed.\n");
- return CAIRO_TEST_FAILURE;
+ return cairo_test_status_from_status (ctx, CAIRO_STATUS_NO_MEMORY);
}
FcConfigSubstitute (NULL, pattern, FcMatchPattern);
FcDefaultSubstitute (pattern);
resolved = FcFontMatch (NULL, pattern, &result);
if (! resolved) {
+ FcPatternDestroy (pattern);
cairo_test_log (ctx, "FcFontMatch failed.\n");
- return CAIRO_TEST_FAILURE;
+ return cairo_test_status_from_status (ctx, CAIRO_STATUS_NO_MEMORY);
}
font_face = cairo_ft_font_face_create_for_pattern (resolved);
+ if (cairo_font_face_status (font_face)) {
+ FcPatternDestroy (resolved);
+ FcPatternDestroy (pattern);
+ return cairo_test_status_from_status (ctx, cairo_font_face_status (font_face));
+ }
if (cairo_font_face_get_type (font_face) != CAIRO_FONT_TYPE_FT) {
cairo_test_log (ctx, "Unexpected value from cairo_font_face_get_type: %d (expected %d)\n",
cairo_font_face_get_type (font_face), CAIRO_FONT_TYPE_FT);
cairo_font_face_destroy (font_face);
+ FcPatternDestroy (resolved);
+ FcPatternDestroy (pattern);
return CAIRO_TEST_FAILURE;
}
@@ -81,13 +167,16 @@ draw (cairo_t *cr, int width, int height)
&ctm,
font_options);
- ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
-
cairo_font_options_destroy (font_options);
cairo_font_face_destroy (font_face);
FcPatternDestroy (pattern);
FcPatternDestroy (resolved);
+ if (cairo_scaled_font_status (scaled_font)) {
+ return cairo_test_status_from_status (ctx,
+ cairo_scaled_font_status (scaled_font));
+ }
+
if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_FT) {
cairo_test_log (ctx, "Unexpected value from cairo_scaled_font_get_type: %d (expected %d)\n",
cairo_scaled_font_get_type (scaled_font), CAIRO_FONT_TYPE_FT);
@@ -95,7 +184,8 @@ draw (cairo_t *cr, int width, int height)
return CAIRO_TEST_FAILURE;
}
- if (!ft_face) {
+ ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
+ if (ft_face == NULL) {
cairo_test_log (ctx, "Failed to get an ft_face with cairo_ft_scaled_font_lock_face\n");
cairo_scaled_font_destroy (scaled_font);
return CAIRO_TEST_FAILURE;
@@ -107,13 +197,18 @@ draw (cairo_t *cr, int width, int height)
*
* Now, on to the simple thing we actually want to test.
*/
- font_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
+
+ cairo_save (cr);
+
+ /* First we want to test caching behaviour */
+ _stress_font_cache (ft_face, cr, 0);
/* Set the font_face and force cairo to actually use it for
* something. */
- cairo_save (cr);
+ font_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
cairo_set_font_face (cr, font_face);
cairo_font_extents (cr, &font_extents);
+
cairo_restore (cr);
/* Finally, even more cleanup */
diff --git a/test/get-clip.c b/test/get-clip.c
index e246671a..1a07f012 100644
--- a/test/get-clip.c
+++ b/test/get-clip.c
@@ -129,7 +129,6 @@ draw (cairo_t *cr, int width, int height)
case CAIRO_SURFACE_TYPE_WIN32:
case CAIRO_SURFACE_TYPE_BEOS:
case CAIRO_SURFACE_TYPE_DIRECTFB:
- case CAIRO_SURFACE_TYPE_SDL:
uses_clip_rects = TRUE;
break;
case CAIRO_SURFACE_TYPE_QUARTZ:
diff --git a/test/get-path-extents.c b/test/get-path-extents.c
index ce1bc7c6..337dad2d 100644
--- a/test/get-path-extents.c
+++ b/test/get-path-extents.c
@@ -57,6 +57,10 @@ check_extents (const cairo_test_context_t *ctx,
break;
}
+ /* ignore results after an error occurs */
+ if (cairo_status (cr))
+ return 1;
+
/* let empty rects match */
if ((ext_x1 == ext_x2 || ext_y1 == ext_y2) && (width == 0 || height == 0))
return 1;
@@ -70,10 +74,10 @@ check_extents (const cairo_test_context_t *ctx,
break;
case APPROX_EQUALS:
relation_string = "approx. equal";
- if (floor (ext_x1 + 0.5) == floor (x + 0.5) &&
- floor (ext_y1 + 0.5) == floor (y + 0.5) &&
- floor (ext_x2 + 0.5) == floor (x + width + 0.5) &&
- floor (ext_y2 + 0.5) == floor (y + height + 0.5))
+ if (fabs (ext_x1 - x) < 1. &&
+ fabs (ext_y1 - y) < 1. &&
+ fabs (ext_x2 - (x + width)) < 1. &&
+ fabs (ext_y2 - (y + height)) < 1.)
{
return 1;
}
@@ -106,6 +110,7 @@ draw (cairo_t *cr, int width, int height)
const char *phase;
const char string[] = "The quick brown fox jumps over the lazy dog.";
cairo_text_extents_t extents, scaled_font_extents;
+ cairo_status_t status;
int errors = 0;
surface = cairo_surface_create_similar (cairo_get_group_target (cr),
@@ -365,8 +370,12 @@ draw (cairo_t *cr, int width, int height)
cairo_new_path (cr2);
cairo_restore (cr2);
+ status = cairo_status (cr2);
cairo_destroy (cr2);
+ if (status)
+ return cairo_test_status_from_status (ctx, status);
+
return errors == 0 ? CAIRO_TEST_SUCCESS : CAIRO_TEST_FAILURE;
}
diff --git a/test/in-fill-trapezoid.c b/test/in-fill-trapezoid.c
index 57429687..b05f0002 100644
--- a/test/in-fill-trapezoid.c
+++ b/test/in-fill-trapezoid.c
@@ -43,24 +43,24 @@ draw (cairo_t *cr, int width, int height)
}
/* rectangular boundary tests */
- if (cairo_in_fill (cr, -10, -10)) {
- cairo_test_log (ctx, "Error: Found top-left vertex inside rectangle\n");
+ if (! cairo_in_fill (cr, -10, -10)) {
+ cairo_test_log (ctx, "Error: Failed to find top-left vertex inside rectangle\n");
ret = CAIRO_TEST_FAILURE;
}
- if (cairo_in_fill (cr, -10, 10)) {
- cairo_test_log (ctx, "Error: Found bottom-left vertex inside rectangle\n");
+ if (! cairo_in_fill (cr, -10, 10)) {
+ cairo_test_log (ctx, "Error: Failed to find bottom-left vertex inside rectangle\n");
ret = CAIRO_TEST_FAILURE;
}
if (! cairo_in_fill (cr, 10, -10)) {
cairo_test_log (ctx, "Error: Failed to find top-right vertex inside rectangle\n");
ret = CAIRO_TEST_FAILURE;
}
- if (cairo_in_fill (cr, 10, 10)) {
- cairo_test_log (ctx, "Error: Found bottom-right vertex inside rectangle\n");
+ if (! cairo_in_fill (cr, 10, 10)) {
+ cairo_test_log (ctx, "Error: Failed to find bottom-right vertex inside rectangle\n");
ret = CAIRO_TEST_FAILURE;
}
- if (cairo_in_fill (cr, -10, 0)) {
- cairo_test_log (ctx, "Error: Found left edge inside rectangle\n");
+ if (! cairo_in_fill (cr, -10, 0)) {
+ cairo_test_log (ctx, "Error: Failed to find left edge inside rectangle\n");
ret = CAIRO_TEST_FAILURE;
}
if (! cairo_in_fill (cr, 0, -10)) {
@@ -71,8 +71,8 @@ draw (cairo_t *cr, int width, int height)
cairo_test_log (ctx, "Error: Failed to find right edge inside rectangle\n");
ret = CAIRO_TEST_FAILURE;
}
- if (cairo_in_fill (cr, 0, 10)) {
- cairo_test_log (ctx, "Error: Found bottom edge inside rectangle\n");
+ if (! cairo_in_fill (cr, 0, 10)) {
+ cairo_test_log (ctx, "Error: Failed to find bottom edge inside rectangle\n");
ret = CAIRO_TEST_FAILURE;
}
@@ -89,7 +89,7 @@ draw (cairo_t *cr, int width, int height)
cairo_rectangle (cr, -10, -10, 20, 20);
cairo_rectangle (cr, -5, -5, 10, 10);
if (cairo_in_fill (cr, 0, 0)) {
- cairo_test_log (ctx, "Error: Found an unexpected point inside rectangular hole\n");
+ cairo_test_log (ctx, "Error: Found an unexpected point inside rectangular eo-hole\n");
ret = CAIRO_TEST_FAILURE;
}
@@ -98,7 +98,7 @@ draw (cairo_t *cr, int width, int height)
cairo_arc (cr, 0, 0, 10, 0, 2 * M_PI);
cairo_arc (cr, 0, 0, 5, 0, 2 * M_PI);
if (cairo_in_fill (cr, 0, 0)) {
- cairo_test_log (ctx, "Error: Found an unexpected point inside circular hole\n");
+ cairo_test_log (ctx, "Error: Found an unexpected point inside circular eo-hole\n");
ret = CAIRO_TEST_FAILURE;
}
@@ -136,7 +136,7 @@ draw (cairo_t *cr, int width, int height)
cairo_rectangle (cr, -10, -10, 20, 20);
cairo_rectangle (cr, 5, -5, -10, 10);
if (cairo_in_fill (cr, 0, 0)) {
- cairo_test_log (ctx, "Error: Found an unexpected point inside rectangular hole\n");
+ cairo_test_log (ctx, "Error: Found an unexpected point inside rectangular non-zero-hole\n");
ret = CAIRO_TEST_FAILURE;
}
@@ -145,7 +145,7 @@ draw (cairo_t *cr, int width, int height)
cairo_arc (cr, 0, 0, 10, 0, 2 * M_PI);
cairo_arc_negative (cr, 0, 0, 5, 0, -2 * M_PI);
if (cairo_in_fill (cr, 0, 0)) {
- cairo_test_log (ctx, "Error: Found an unexpected point inside circular hole\n");
+ cairo_test_log (ctx, "Error: Found an unexpected point inside circular non-zero-hole\n");
ret = CAIRO_TEST_FAILURE;
}
@@ -163,26 +163,26 @@ draw (cairo_t *cr, int width, int height)
cairo_arc (cr, 7.5, 0, 10, 0, 2 * M_PI);
cairo_arc_negative (cr, 7.5, 0, 5, 0, -2 * M_PI);
if (cairo_in_fill (cr, 7.5, 0)) {
- cairo_test_log (ctx, "Error: Found an unexpected point inside circular hole\n");
+ cairo_test_log (ctx, "Error: Found an unexpected point inside off-centre-x circular non-zero-hole\n");
ret = CAIRO_TEST_FAILURE;
}
cairo_new_path (cr);
cairo_arc (cr, 0, 7.5, 10, 0, 2 * M_PI);
cairo_arc_negative (cr, 0, 7.5, 5, 0, -2 * M_PI);
if (cairo_in_fill (cr, 0, 7.5)) {
- cairo_test_log (ctx, "Error: Found an unexpected point inside circular hole\n");
+ cairo_test_log (ctx, "Error: Found an unexpected point inside off-centre-y circular non-zero-hole\n");
ret = CAIRO_TEST_FAILURE;
}
cairo_new_path (cr);
cairo_arc (cr, 15, 0, 10, 0, 2 * M_PI);
if (! cairo_in_fill (cr, 15, 0)) {
- cairo_test_log (ctx, "Error: Failed to find point inside circle\n");
+ cairo_test_log (ctx, "Error: Failed to find point inside off-centre-x circle\n");
ret = CAIRO_TEST_FAILURE;
}
cairo_new_path (cr);
cairo_arc (cr, 0, 15, 10, 0, 2 * M_PI);
if (! cairo_in_fill (cr, 0, 15)) {
- cairo_test_log (ctx, "Error: Failed to find point inside circle\n");
+ cairo_test_log (ctx, "Error: Failed to find point inside off-centre-y circle\n");
ret = CAIRO_TEST_FAILURE;
}
@@ -209,12 +209,49 @@ draw (cairo_t *cr, int width, int height)
cairo_line_to (cr, 5, 5);
cairo_close_path (cr);
if (cairo_in_fill (cr, 0, 0) ||
- cairo_in_fill (cr, 10, 10) ||
+ cairo_in_fill (cr, 5, 0) ||
+ cairo_in_fill (cr, 15, 0) ||
cairo_in_fill (cr, 20, 0) ||
+ cairo_in_fill (cr, 0, 10) ||
+ cairo_in_fill (cr, 10, 10) ||
+ cairo_in_fill (cr, 20, 10) ||
cairo_in_fill (cr, 7, 2.5) ||
cairo_in_fill (cr, 13, 2.5))
{
- cairo_test_log (ctx, "Error: Found an unexpected point outside triangle\n");
+ cairo_test_log (ctx,
+ "Error: Found an unexpected point outside triangle\n"
+ "\t(0, 0) -> %s\n"
+ "\t(5, 0) -> %s\n"
+ "\t(15, 0) -> %s\n"
+ "\t(20, 0) -> %s\n"
+ "\t(0, 10) -> %s\n"
+ "\t(10, 10) -> %s\n"
+ "\t(20, 10) -> %s\n"
+ "\t(7, 2.5) -> %s\n"
+ "\t(13, 2.5) -> %s\n",
+ cairo_in_fill (cr, 0, 0) ? "inside" : "outside",
+ cairo_in_fill (cr, 5, 0) ? "inside" : "outside",
+ cairo_in_fill (cr, 15, 0) ? "inside" : "outside",
+ cairo_in_fill (cr, 20, 0) ? "inside" : "outside",
+ cairo_in_fill (cr, 0, 10) ? "inside" : "outside",
+ cairo_in_fill (cr, 10, 10) ? "inside" : "outside",
+ cairo_in_fill (cr, 20, 10) ? "inside" : "outside",
+ cairo_in_fill (cr, 7, 2.5) ? "inside" : "outside",
+ cairo_in_fill (cr, 13, 2.5) ? "inside" : "outside");
+ ret = CAIRO_TEST_FAILURE;
+ }
+ if (! cairo_in_fill (cr, 7.5, 2.5) ||
+ ! cairo_in_fill (cr, 12.5, 2.5) ||
+ ! cairo_in_fill (cr, 10, 5))
+ {
+ cairo_test_log (ctx,
+ "Error: Failed to find point on triangle edge\n"
+ "\t(7.5, 2.5) -> %s\n"
+ "\t(12.5, 2.5) -> %s\n"
+ "\t(10, 5) -> %s\n",
+ cairo_in_fill (cr, 7.5, 2.5) ? "inside" : "outside",
+ cairo_in_fill (cr, 12.5, 2.5) ? "inside" : "outside",
+ cairo_in_fill (cr, 10, 5) ? "inside" : "outside");
ret = CAIRO_TEST_FAILURE;
}
if (! cairo_in_fill (cr, 8, 2.5) ||
diff --git a/test/invalid-matrix.c b/test/invalid-matrix.c
index 62d3220b..4fbda614 100644
--- a/test/invalid-matrix.c
+++ b/test/invalid-matrix.c
@@ -29,8 +29,8 @@
#include "cairo-test.h"
-#if defined(HAVE_IEEE754) && !defined(INFINITY)
-#define INFINITY (0./1.)
+#if !defined(INFINITY) && defined(_MSC_VER)
+#define INFINITY HUGE_VAL
#endif
#if HAVE_FEDISABLEEXCEPT
@@ -74,7 +74,7 @@ if ((status) == CAIRO_STATUS_SUCCESS) { \
#endif
/* create a bogus matrix and check results of attempted inversion */
- bogus.x0 = bogus.xy = bogus.xx = strtod ("NaN", NULL);
+ bogus.x0 = bogus.xy = bogus.xx = cairo_test_NaN ();
bogus.y0 = bogus.yx = bogus.yy = bogus.xx;
status = cairo_matrix_invert (&bogus);
CHECK_STATUS (status, "cairo_matrix_invert(NaN)");
@@ -363,6 +363,10 @@ if ((status) == CAIRO_STATUS_SUCCESS) { \
CHECK_STATUS (status, "cairo_rotate(∞)");
cairo_destroy (cr2);
+#if HAVE_FECLEAREXCEPT
+ feclearexcept (FE_INVALID);
+#endif
+
return CAIRO_TEST_SUCCESS;
}
diff --git a/test/path-append.c b/test/path-append.c
new file mode 100644
index 00000000..bcd282db
--- /dev/null
+++ b/test/path-append.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright © 2009 Jeff Muizelaar
+ * Copyright © 2009 Chris Wilson
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS 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.
+ */
+
+#include <stdlib.h>
+#include "cairo-test.h"
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_matrix_t m;
+ int xoffset = 50;
+ int yoffset = 50;
+
+ cairo_surface_t *shadow;
+ cairo_t *shadow_cr;
+ cairo_path_t *path;
+
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+
+ cairo_translate (cr, 130, 130);
+ cairo_rotate (cr, .5);//2*M_PI*angle/360);
+ cairo_rectangle (cr, 0, 0, 50, 100);
+ cairo_get_matrix (cr, &m);
+
+ shadow = cairo_surface_create_similar (cairo_get_target (cr),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ 600 - xoffset,
+ 600 - yoffset);
+ cairo_surface_set_device_offset (shadow, xoffset, yoffset);
+ shadow_cr = cairo_create (shadow);
+ cairo_surface_destroy (shadow);
+
+ cairo_set_source_rgb (shadow_cr, 0, 1, 0);
+ cairo_set_matrix (shadow_cr, &m);
+
+ path = cairo_copy_path (cr);
+ cairo_new_path (shadow_cr);
+ cairo_append_path (shadow_cr, path);
+ cairo_fill (shadow_cr);
+ cairo_path_destroy (path);
+
+ cairo_identity_matrix (cr);
+ cairo_translate (cr, 10, 50);
+ cairo_set_source_surface (cr, cairo_get_target (shadow_cr), 0, 0);
+ cairo_paint (cr);
+ cairo_set_matrix (cr, &m);
+ cairo_set_source_rgb (cr, 1, 0, 0);
+ cairo_fill (cr);
+
+ cairo_destroy (shadow_cr);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+CAIRO_TEST (path_append,
+ "Test appending path to a context, in particular to exercise a regression in 005436",
+ "path", /* keywords */
+ NULL, /* requirements */
+ 600, 600,
+ NULL, draw)
diff --git a/test/path-append.ps.ref.png b/test/path-append.ps.ref.png
new file mode 100644
index 00000000..fd8026f7
--- /dev/null
+++ b/test/path-append.ps.ref.png
Binary files differ
diff --git a/test/path-append.ref.png b/test/path-append.ref.png
new file mode 100644
index 00000000..de9057c8
--- /dev/null
+++ b/test/path-append.ref.png
Binary files differ
diff --git a/test/path-append.test-fallback.ref.png b/test/path-append.test-fallback.ref.png
new file mode 100644
index 00000000..fa72ac06
--- /dev/null
+++ b/test/path-append.test-fallback.ref.png
Binary files differ
diff --git a/test/path-append.xlib-fallback.ref.png b/test/path-append.xlib-fallback.ref.png
new file mode 100644
index 00000000..08a33a26
--- /dev/null
+++ b/test/path-append.xlib-fallback.ref.png
Binary files differ
diff --git a/test/path-append.xlib.ref.png b/test/path-append.xlib.ref.png
new file mode 100644
index 00000000..fa72ac06
--- /dev/null
+++ b/test/path-append.xlib.ref.png
Binary files differ
diff --git a/test/path-precision.c b/test/path-precision.c
index 447b7a24..b5371021 100644
--- a/test/path-precision.c
+++ b/test/path-precision.c
@@ -33,20 +33,20 @@ static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
cairo_path_data_t path_data[] = {
- { .header = { CAIRO_PATH_MOVE_TO, 2 }, },
- { .point = { 95.000000, 40.000000 }, },
+ { { CAIRO_PATH_MOVE_TO, 2 }, },
+ { { 95.000000, 40.000000 }, },
- { .header = { CAIRO_PATH_LINE_TO, 2 }, },
- { .point = { 94.960533, 41.255810 }, },
+ { { CAIRO_PATH_LINE_TO, 2 }, },
+ { { 94.960533, 41.255810 }, },
- { .header = { CAIRO_PATH_LINE_TO, 2 }, },
- { .point = { 94.842293, 42.50666 }, },
+ { { CAIRO_PATH_LINE_TO, 2 }, },
+ { { 94.842293, 42.50666 }, },
- { .header = { CAIRO_PATH_LINE_TO, 2 }, },
- { .point = { 94.645744, 43.747627 }, },
+ { { CAIRO_PATH_LINE_TO, 2 }, },
+ { { 94.645744, 43.747627 }, },
- { .header = { CAIRO_PATH_LINE_TO, 2 }, },
- { .point = { 94.371666, 44.973797 }, },
+ { { CAIRO_PATH_LINE_TO, 2 }, },
+ { { 94.371666, 44.973797 }, },
};
const cairo_test_context_t *ctx = cairo_test_get_context (cr);
cairo_path_t path, *path_copy;
diff --git a/test/pattern-getters.c b/test/pattern-getters.c
index 0b9c86b1..657159c2 100644
--- a/test/pattern-getters.c
+++ b/test/pattern-getters.c
@@ -27,7 +27,12 @@
#include <stdlib.h>
#include "cairo-test.h"
-#define CHECK_SUCCESS do { if (status) return CAIRO_TEST_FAILURE; } while (0)
+#define CHECK_SUCCESS do { \
+ if (status) { \
+ cairo_pattern_destroy (pat); \
+ return cairo_test_status_from_status (ctx, status); \
+ } \
+} while (0)
static int
double_buf_equal (const cairo_test_context_t *ctx, double *a, double *b, int nc)
@@ -64,6 +69,7 @@ draw (cairo_t *cr, int width, int height)
!CAIRO_TEST_DOUBLE_EQUALS(a,0.5)) {
cairo_test_log (ctx, "Error: cairo_pattern_get_rgba returned unexepcted results: %g, %g, %g, %g\n",
r, g, b, a);
+ cairo_pattern_destroy (pat);
return CAIRO_TEST_FAILURE;
}
@@ -81,6 +87,7 @@ draw (cairo_t *cr, int width, int height)
if (surf != cairo_get_target (cr)) {
cairo_test_log (ctx, "Error: cairo_pattern_get_resurface returned wrong surface\n");
+ cairo_pattern_destroy (pat);
return CAIRO_TEST_FAILURE;
}
@@ -114,13 +121,18 @@ draw (cairo_t *cr, int width, int height)
!CAIRO_TEST_DOUBLE_EQUALS(y0,2.0) ||
!CAIRO_TEST_DOUBLE_EQUALS(x1,3.0) ||
!CAIRO_TEST_DOUBLE_EQUALS(y1,4.0))
+ {
+ cairo_pattern_destroy (pat);
return CAIRO_TEST_FAILURE;
+ }
status = cairo_pattern_get_color_stop_count (pat, &i);
CHECK_SUCCESS;
- if (i != 3)
+ if (i != 3) {
+ cairo_pattern_destroy (pat);
return CAIRO_TEST_FAILURE;
+ }
for (i = 0; i < 3; i++) {
status = cairo_pattern_get_color_stop_rgba (pat, i,
@@ -133,11 +145,17 @@ draw (cairo_t *cr, int width, int height)
}
status = cairo_pattern_get_color_stop_rgba (pat, 5, NULL, NULL, NULL, NULL, NULL);
- if (status != CAIRO_STATUS_INVALID_INDEX)
+ if (status != CAIRO_STATUS_INVALID_INDEX) {
+ cairo_pattern_destroy (pat);
return CAIRO_TEST_FAILURE;
+ }
- if (!double_buf_equal (ctx, new_buf, expected_values, sizeof(expected_values)/sizeof(double)) != 0)
+ if (!double_buf_equal (ctx, new_buf, expected_values,
+ sizeof(expected_values)/sizeof(double)) != 0)
+ {
+ cairo_pattern_destroy (pat);
return CAIRO_TEST_FAILURE;
+ }
cairo_pattern_destroy (pat);
}
@@ -157,7 +175,10 @@ draw (cairo_t *cr, int width, int height)
!CAIRO_TEST_DOUBLE_EQUALS(d,4.0) ||
!CAIRO_TEST_DOUBLE_EQUALS(e,5.0) ||
!CAIRO_TEST_DOUBLE_EQUALS(f,6.0))
+ {
+ cairo_pattern_destroy (pat);
return CAIRO_TEST_FAILURE;
+ }
cairo_pattern_destroy (pat);
}
diff --git a/test/pdiff/Makefile.win32 b/test/pdiff/Makefile.win32
index 5e6680dd..851d3af6 100644
--- a/test/pdiff/Makefile.win32
+++ b/test/pdiff/Makefile.win32
@@ -16,4 +16,4 @@ pdiff.lib: $(OBJECTS)
lib -NOLOGO -OUT:$@ $(OBJECTS)
%.obj: %.c
- @$(CC) $(CFLAGS) -c -Fo"$@" $<
+ @$(CC) $(CFLAGS) -DCAIRO_WIN32_STATIC_BUILD=1 -c -Fo"$@" $<
diff --git a/test/rel-path.c b/test/rel-path.c
index 15440013..d1ef2592 100644
--- a/test/rel-path.c
+++ b/test/rel-path.c
@@ -74,24 +74,37 @@ draw (cairo_t *cr, int width, int height)
{
const cairo_test_context_t *ctx = cairo_test_get_context (cr);
cairo_status_t status;
+ cairo_test_status_t result;
/* first test that a relative move without a current point fails... */
status = invalid_rel_move_to (cairo_get_target (cr));
if (status != CAIRO_STATUS_NO_CURRENT_POINT) {
+ result = cairo_test_status_from_status (ctx, status);
+ if (result == CAIRO_TEST_NO_MEMORY)
+ return result;
+
cairo_test_log (ctx, "Error: invalid cairo_rel_move_to() did not raise NO_CURRENT_POINT\n");
- return CAIRO_TEST_FAILURE;
+ return result;
}
status = invalid_rel_line_to (cairo_get_target (cr));
if (status != CAIRO_STATUS_NO_CURRENT_POINT) {
+ result = cairo_test_status_from_status (ctx, status);
+ if (result == CAIRO_TEST_NO_MEMORY)
+ return result;
+
cairo_test_log (ctx, "Error: invalid cairo_rel_line_to() did not raise NO_CURRENT_POINT\n");
- return CAIRO_TEST_FAILURE;
+ return result;
}
status = invalid_rel_curve_to (cairo_get_target (cr));
if (status != CAIRO_STATUS_NO_CURRENT_POINT) {
+ result = cairo_test_status_from_status (ctx, status);
+ if (result == CAIRO_TEST_NO_MEMORY)
+ return result;
+
cairo_test_log (ctx, "Error: invalid cairo_rel_curve_to() did not raise NO_CURRENT_POINT\n");
- return CAIRO_TEST_FAILURE;
+ return result;
}
cairo_set_source_rgb (cr, 1, 1, 1);
diff --git a/test/rotate-image-surface-paint.ref.png b/test/rotate-image-surface-paint.ref.png
index 5c98d7d8..bd30da6e 100644
--- a/test/rotate-image-surface-paint.ref.png
+++ b/test/rotate-image-surface-paint.ref.png
Binary files differ
diff --git a/test/show-glyphs-many.c b/test/show-glyphs-many.c
index 7276b076..dbfd6a1c 100644
--- a/test/show-glyphs-many.c
+++ b/test/show-glyphs-many.c
@@ -109,7 +109,7 @@ get_glyph (cairo_t *cr, const char *utf8, cairo_glyph_t *glyph)
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
- cairo_glyph_t glyphs[NUM_GLYPHS];
+ cairo_glyph_t *glyphs = xmalloc (NUM_GLYPHS * sizeof (cairo_glyph_t));
const char *characters[] = { /* try to exercise different widths of index */
"m", /* Latin letter m, index=0x50 */
"μ", /* Greek letter mu, index=0x349 */
@@ -130,7 +130,7 @@ draw (cairo_t *cr, int width, int height)
for (utf8 = characters; *utf8 != NULL; utf8++) {
status = get_glyph (cr, *utf8, &glyphs[0]);
if (status)
- return status;
+ goto BAIL;
if (glyphs[0].index) {
glyphs[0].x = 1.0;
@@ -145,19 +145,22 @@ draw (cairo_t *cr, int width, int height)
/* we can pack ~21k 1-byte glyphs into a single XRenderCompositeGlyphs8 */
status = get_glyph (cr, "m", &glyphs[0]);
if (status)
- return status;
+ goto BAIL;
for (i=1; i < 21500; i++)
glyphs[i] = glyphs[0];
/* so check expanding the current 1-byte request for 2-byte glyphs */
status = get_glyph (cr, "μ", &glyphs[i]);
if (status)
- return status;
+ goto BAIL;
for (j=i+1; j < NUM_GLYPHS; j++)
glyphs[j] = glyphs[i];
cairo_show_glyphs (cr, glyphs, NUM_GLYPHS);
- return CAIRO_TEST_SUCCESS;
+ BAIL:
+ free(glyphs);
+
+ return status;
}
CAIRO_TEST (show_glyphs_many,
diff --git a/test/solid-pattern-cache-stress.c b/test/solid-pattern-cache-stress.c
index ec183fde..285275e1 100644
--- a/test/solid-pattern-cache-stress.c
+++ b/test/solid-pattern-cache-stress.c
@@ -108,6 +108,9 @@ use_similar (cairo_t *cr,
{
cairo_t *cr2;
+ if (cairo_status (cr))
+ return;
+
cr2 = _cairo_create_similar (cr, 1, 1);
_draw (cr2, red, green, blue);
@@ -125,6 +128,9 @@ use_image (cairo_t *cr,
{
cairo_t *cr2;
+ if (cairo_status (cr))
+ return;
+
cr2 = _cairo_create_image (cr, format, 1, 1);
_draw (cr2, red, green, blue);
@@ -153,23 +159,36 @@ use_solid (cairo_t *cr,
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
- int loop;
- int i;
+ const cairo_test_context_t *ctx = cairo_test_get_context (cr);
+ cairo_status_t status;
+ const double colors[8][3] = {
+ { 1.0, 0.0, 0.0 }, /* red */
+ { 0.0, 1.0, 0.0 }, /* green */
+ { 1.0, 1.0, 0.0 }, /* yellow */
+ { 0.0, 0.0, 1.0 }, /* blue */
+ { 1.0, 0.0, 1.0 }, /* magenta */
+ { 0.0, 1.0, 1.0 }, /* cyan */
+ { 1.0, 1.0, 1.0 }, /* white */
+ { 0.0, 0.0, 0.0 }, /* black */
+ };
+ int i, j, loop;
for (loop = 0; loop < LOOPS; loop++) {
for (i = 0; i < LOOPS; i++) {
- use_solid (cr, 0.0, 0.0, 0.0); /* black */
- use_solid (cr, 1.0, 0.0, 0.0); /* red */
- use_solid (cr, 0.0, 1.0, 0.0); /* green */
- use_solid (cr, 1.0, 1.0, 0.0); /* yellow */
- use_solid (cr, 0.0, 0.0, 1.0); /* blue */
- use_solid (cr, 1.0, 0.0, 1.0); /* magenta */
- use_solid (cr, 0.0, 1.0, 1.0); /* cyan */
- use_solid (cr, 1.0, 1.0, 1.0); /* white */
+ for (j = 0; j < 8; j++) {
+ use_solid (cr, colors[j][0], colors[j][1], colors[j][2]);
+ status = cairo_status (cr);
+ if (status)
+ return cairo_test_status_from_status (ctx, status);
+ }
}
- for (i = 0; i < NRAND; i++)
+ for (i = 0; i < NRAND; i++) {
use_solid (cr, drand48 (), drand48 (), drand48 ());
+ status = cairo_status (cr);
+ if (status)
+ return cairo_test_status_from_status (ctx, status);
+ }
}
/* stress test only, so clear the surface before comparing */
diff --git a/test/surface-finish-twice.c b/test/surface-finish-twice.c
index 5154e99e..f63b5017 100644
--- a/test/surface-finish-twice.c
+++ b/test/surface-finish-twice.c
@@ -45,21 +45,26 @@
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
+ const cairo_test_context_t *ctx = cairo_test_get_context (cr);
cairo_surface_t *surface;
+ cairo_status_t status;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
cairo_surface_finish (surface);
- if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
- return CAIRO_TEST_FAILURE;
+ status = cairo_surface_status (surface);
+ if (status != CAIRO_STATUS_SUCCESS)
+ return cairo_test_status_from_status (ctx, status);
cairo_surface_finish (surface);
- if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
- return CAIRO_TEST_FAILURE;
+ status = cairo_surface_status (surface);
+ if (status != CAIRO_STATUS_SUCCESS)
+ return cairo_test_status_from_status (ctx, status);
cairo_surface_finish (surface);
- if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
- return CAIRO_TEST_FAILURE;
+ status = cairo_surface_status (surface);
+ if (status != CAIRO_STATUS_SUCCESS)
+ return cairo_test_status_from_status (ctx, status);
cairo_surface_destroy (surface);
diff --git a/test/surface-source.c b/test/surface-source.c
index 09069246..5d978f23 100644
--- a/test/surface-source.c
+++ b/test/surface-source.c
@@ -102,6 +102,7 @@ draw (cairo_t *cr, int width, int height)
(height - INTER_SIZE)/2);
cairo_destroy (cr2);
cairo_rectangle (cr, 15, 15, 60, 60);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_fill (cr);
/* destroy the surface last, as this triggers XCloseDisplay */
diff --git a/test/test-fallback16-surface-source.c b/test/test-fallback16-surface-source.c
new file mode 100644
index 00000000..7e9f920f
--- /dev/null
+++ b/test/test-fallback16-surface-source.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2009 Chris Wilson
+ *
+ * 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
+ * Chris Wilson not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Chris Wilson makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL CHRIS WILSON 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: Chris Wilson <chris@chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+#include <test-fallback16-surface.h>
+
+#include "surface-source.c"
+
+static cairo_surface_t *
+create_source_surface (int size)
+{
+ return _cairo_test_fallback16_surface_create (CAIRO_CONTENT_COLOR_ALPHA,
+ size, size);
+}
+
+CAIRO_TEST (test_fallback16_surface_source,
+ "Test using a 16-bit image (e.g. a low bit-depth XServer) surface as the source",
+ "source", /* keywords */
+ NULL, /* requirements */
+ SIZE, SIZE,
+ preamble, draw)
diff --git a/test/test-fallback16-surface-source.ref.png b/test/test-fallback16-surface-source.ref.png
new file mode 100644
index 00000000..3fa8bbe5
--- /dev/null
+++ b/test/test-fallback16-surface-source.ref.png
Binary files differ
diff --git a/test/toy-font-face.c b/test/toy-font-face.c
index e26a19ca..147c43b7 100644
--- a/test/toy-font-face.c
+++ b/test/toy-font-face.c
@@ -34,6 +34,17 @@
#include <assert.h>
#include <string.h>
+#if CAIRO_HAS_WIN32_FONT
+#define CAIRO_FONT_FAMILY_DEFAULT "Arial"
+#elif CAIRO_HAS_QUARTZ_FONT
+#define CAIRO_FONT_FAMILY_DEFAULT "Helvetica"
+#elif CAIRO_HAS_FT_FONT
+#define CAIRO_FONT_FAMILY_DEFAULT ""
+#else
+#define CAIRO_FONT_FAMILY_DEFAULT "@cairo:"
+#endif
+
+
static cairo_test_status_t
preamble (cairo_test_context_t *ctx)
{
@@ -79,7 +90,7 @@ preamble (cairo_test_context_t *ctx)
CAIRO_FONT_SLANT_OBLIQUE,
CAIRO_FONT_WEIGHT_BOLD);
assert (cairo_font_face_get_type (font_face) == CAIRO_FONT_TYPE_TOY);
- assert (0 == (strcmp) (cairo_toy_font_face_get_family (font_face), ""));
+ assert (0 == (strcmp) (cairo_toy_font_face_get_family (font_face), CAIRO_FONT_FAMILY_DEFAULT));
assert (cairo_toy_font_face_get_slant (font_face) == CAIRO_FONT_SLANT_NORMAL);
assert (cairo_toy_font_face_get_weight (font_face) == CAIRO_FONT_WEIGHT_NORMAL);
assert (cairo_font_face_status(font_face) == CAIRO_STATUS_NULL_POINTER);
@@ -89,7 +100,7 @@ preamble (cairo_test_context_t *ctx)
CAIRO_FONT_SLANT_OBLIQUE,
CAIRO_FONT_WEIGHT_BOLD);
assert (cairo_font_face_get_type (font_face) == CAIRO_FONT_TYPE_TOY);
- assert (0 == (strcmp) (cairo_toy_font_face_get_family (font_face), ""));
+ assert (0 == (strcmp) (cairo_toy_font_face_get_family (font_face), CAIRO_FONT_FAMILY_DEFAULT));
assert (cairo_toy_font_face_get_slant (font_face) == CAIRO_FONT_SLANT_NORMAL);
assert (cairo_toy_font_face_get_weight (font_face) == CAIRO_FONT_WEIGHT_NORMAL);
assert (cairo_font_face_status(font_face) == CAIRO_STATUS_INVALID_STRING);
@@ -99,7 +110,7 @@ preamble (cairo_test_context_t *ctx)
-1,
CAIRO_FONT_WEIGHT_BOLD);
assert (cairo_font_face_get_type (font_face) == CAIRO_FONT_TYPE_TOY);
- assert (0 == (strcmp) (cairo_toy_font_face_get_family (font_face), ""));
+ assert (0 == (strcmp) (cairo_toy_font_face_get_family (font_face), CAIRO_FONT_FAMILY_DEFAULT));
assert (cairo_toy_font_face_get_slant (font_face) == CAIRO_FONT_SLANT_NORMAL);
assert (cairo_toy_font_face_get_weight (font_face) == CAIRO_FONT_WEIGHT_NORMAL);
assert (cairo_font_face_status(font_face) == CAIRO_STATUS_INVALID_SLANT);
@@ -109,7 +120,7 @@ preamble (cairo_test_context_t *ctx)
CAIRO_FONT_SLANT_OBLIQUE,
-1);
assert (cairo_font_face_get_type (font_face) == CAIRO_FONT_TYPE_TOY);
- assert (0 == (strcmp) (cairo_toy_font_face_get_family (font_face), ""));
+ assert (0 == (strcmp) (cairo_toy_font_face_get_family (font_face), CAIRO_FONT_FAMILY_DEFAULT));
assert (cairo_toy_font_face_get_slant (font_face) == CAIRO_FONT_SLANT_NORMAL);
assert (cairo_toy_font_face_get_weight (font_face) == CAIRO_FONT_WEIGHT_NORMAL);
assert (cairo_font_face_status(font_face) == CAIRO_STATUS_INVALID_WEIGHT);
diff --git a/test/truetype-tables.c b/test/truetype-tables.c
deleted file mode 100644
index bab119f7..00000000
--- a/test/truetype-tables.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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: Behdad Esfahbod <behdad@behdad.org>
- */
-/*
- * Test that the structs we define for TrueType tables have the
- * correct size, ie. they are not padded.
- */
-
-#include "cairo-test.h"
-
-#include <cairo-truetype-subset-private.h>
-
-static cairo_test_status_t
-preamble (cairo_test_context_t *ctx)
-{
- cairo_test_status_t ret = CAIRO_TEST_SUCCESS;
-
-#define check(st, sz) \
- if (sizeof (st) != (sz)) { \
- cairo_test_log (ctx, "sizeof (%s): got %d, expected %d", #st, (int)sizeof (st), sz); \
- ret = CAIRO_TEST_FAILURE; \
- }
-#if CAIRO_HAS_FONT_SUBSET
- check (tt_head_t, 54);
- check (tt_hhea_t, 36);
- check (tt_maxp_t, 32);
- check (tt_name_record_t, 12);
- check (tt_name_t, 18);
- check (tt_name_t, 18);
- check (tt_composite_glyph_t, 18);
- check (tt_glyph_data_t, 28);
-#endif
-
- return ret;
-}
-
-CAIRO_TEST (truetype_tables,
- "Test that the size of TrueType table structs is correct",
- "ft, api", /* keywords */
- NULL, /* requirements */
- 0, 0,
- preamble, NULL)
diff --git a/test/twin.c b/test/twin.c
index b71d97eb..08865f07 100644
--- a/test/twin.c
+++ b/test/twin.c
@@ -41,6 +41,15 @@ draw (cairo_t *cr, int width, int height)
cairo_move_to (cr, 4, 14);
cairo_show_text (cr, "Is cairo's twin giza?");
+ cairo_move_to (cr, 4, 34);
+ cairo_text_path (cr, "Is cairo's twin giza?");
+ cairo_fill (cr);
+
+ cairo_move_to (cr, 4, 54);
+ cairo_text_path (cr, "Is cairo's twin giza?");
+ cairo_set_line_width (cr, 2/16.);
+ cairo_stroke (cr);
+
return CAIRO_TEST_SUCCESS;
}
@@ -48,5 +57,5 @@ CAIRO_TEST (twin,
"Tests the internal font",
"twin, font", /* keywords */
NULL, /* requirements */
- 140, 20,
+ 140, 60,
NULL, draw)
diff --git a/test/twin.ps.ref.png b/test/twin.ps.ref.png
index f9374e33..e75062ca 100644
--- a/test/twin.ps.ref.png
+++ b/test/twin.ps.ref.png
Binary files differ
diff --git a/test/twin.ref.png b/test/twin.ref.png
index 8bf098c1..3c46b02a 100644
--- a/test/twin.ref.png
+++ b/test/twin.ref.png
Binary files differ
diff --git a/test/twin.svg.ref.png b/test/twin.svg.ref.png
index 8b4617f0..b5d4a314 100644
--- a/test/twin.svg.ref.png
+++ b/test/twin.svg.ref.png
Binary files differ
diff --git a/test/user-font-mask.c b/test/user-font-mask.c
index 16bd59b7..6fd40c87 100644
--- a/test/user-font-mask.c
+++ b/test/user-font-mask.c
@@ -36,7 +36,12 @@
#define BORDER 10
#define TEXT_SIZE 64
#define WIDTH (TEXT_SIZE * 15 + 2*BORDER)
-#define HEIGHT ((TEXT_SIZE + 2*BORDER)*2)
+#ifndef ROTATED
+ #define HEIGHT ((TEXT_SIZE + 2*BORDER)*2)
+#else
+ #define HEIGHT WIDTH
+#endif
+#define END_GLYPH 0
#define TEXT "cairo"
/* Reverse the bits in a byte with 7 operations (no 64-bit):
@@ -112,6 +117,9 @@ test_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
metrics->x_advance = (glyphs[glyph].width + 1) / 8.0;
image = cairo_image_surface_create (CAIRO_FORMAT_A1, glyphs[glyph].width, 8);
+ if (cairo_surface_status (image))
+ return cairo_surface_status (image);
+
data = cairo_image_surface_get_data (image);
for (i = 0; i < 8; i++) {
byte = glyphs[glyph].data[i];
@@ -120,15 +128,17 @@ test_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
}
pattern = cairo_pattern_create_for_surface (image);
+ cairo_surface_destroy (image);
+
cairo_matrix_init_identity (&matrix);
cairo_matrix_scale (&matrix, 1.0/8.0, 1.0/8.0);
cairo_matrix_translate (&matrix, 0, -8);
cairo_matrix_invert (&matrix);
cairo_pattern_set_matrix (pattern, &matrix);
+
cairo_set_source (cr, pattern);
cairo_mask (cr, pattern);
cairo_pattern_destroy (pattern);
- cairo_surface_destroy (image);
return CAIRO_STATUS_SUCCESS;
}
@@ -238,9 +248,5 @@ CAIRO_TEST (user_font_mask,
"Tests a user-font using cairo_mask with bitmap images",
"user-font, mask", /* keywords */
NULL, /* requirements */
-#ifndef ROTATED
WIDTH, HEIGHT,
-#else
- WIDTH, WIDTH,
-#endif
NULL, draw)
diff --git a/test/user-font-proxy.c b/test/user-font-proxy.c
index 45974d3d..3470a121 100644
--- a/test/user-font-proxy.c
+++ b/test/user-font-proxy.c
@@ -35,7 +35,11 @@
#define BORDER 10
#define TEXT_SIZE 64
#define WIDTH (TEXT_SIZE * 12 + 2*BORDER)
-#define HEIGHT ((TEXT_SIZE + 2*BORDER)*2)
+#ifndef ROTATED
+ #define HEIGHT ((TEXT_SIZE + 2*BORDER)*2)
+#else
+ #define HEIGHT WIDTH
+#endif
#define TEXT "geez... cairo user-font"
static cairo_user_data_key_t fallback_font_key;
@@ -208,9 +212,5 @@ CAIRO_TEST (user_font_proxy,
"Tests a user-font using a native font in its render_glyph",
"font, user-font", /* keywords */
"cairo >= 1.7.4", /* requirements */
-#ifndef ROTATED
WIDTH, HEIGHT,
-#else
- WIDTH, WIDTH,
-#endif
NULL, draw)
diff --git a/test/user-font-rescale.c b/test/user-font-rescale.c
index 04d3f53c..ae56ef84 100644
--- a/test/user-font-rescale.c
+++ b/test/user-font-rescale.c
@@ -211,7 +211,7 @@ create_rescaled_font (cairo_font_face_t *substitute_font,
for (i = 0; i < r->glyph_count; i++) {
r->desired_width[i] = desired_width[i];
/* use NaN to specify unset */
- r->rescale_factor[i] = strtod ("NaN", NULL);
+ r->rescale_factor[i] = cairo_test_NaN ();
}
status = cairo_font_face_set_user_data (user_font_face,
diff --git a/test/user-font.c b/test/user-font.c
index 38e2b1d5..30bc74e3 100644
--- a/test/user-font.c
+++ b/test/user-font.c
@@ -35,7 +35,11 @@
#define BORDER 10
#define TEXT_SIZE 64
#define WIDTH (TEXT_SIZE * 15 + 2*BORDER)
-#define HEIGHT ((TEXT_SIZE + 2*BORDER)*2)
+#ifndef ROTATED
+ #define HEIGHT ((TEXT_SIZE + 2*BORDER)*2)
+#else
+ #define HEIGHT WIDTH
+#endif
#define TEXT "geez... cairo user-font"
#define END_GLYPH 0
@@ -259,9 +263,5 @@ CAIRO_TEST (user_font,
"Tests user font feature",
"font, user-font", /* keywords */
"cairo >= 1.7.4", /* requirements */
-#ifndef ROTATED
WIDTH, HEIGHT,
-#else
- WIDTH, WIDTH,
-#endif
NULL, draw)
diff --git a/util/cairo-script/cairo-script-file.c b/util/cairo-script/cairo-script-file.c
index fcdccf14..9a3ff70a 100644
--- a/util/cairo-script/cairo-script-file.c
+++ b/util/cairo-script/cairo-script-file.c
@@ -35,6 +35,7 @@
#include "cairo-script-private.h"
#include <stdio.h>
+#include <limits.h> /* INT_MAX */
#include <string.h>
#define CHUNK_SIZE 32768
@@ -996,7 +997,7 @@ _csi_file_as_string (csi_t *ctx,
char *newbytes;
int newlen;
- if (_csi_unlikely (allocated > INT32_MAX / 2))
+ if (_csi_unlikely (allocated > INT_MAX / 2))
return _csi_error (CAIRO_STATUS_NO_MEMORY);
newlen = allocated * 2;
diff --git a/util/cairo-script/cairo-script-hash.c b/util/cairo-script/cairo-script-hash.c
index 4fa9e492..67451117 100644
--- a/util/cairo-script/cairo-script-hash.c
+++ b/util/cairo-script/cairo-script-hash.c
@@ -279,7 +279,7 @@ _csi_hash_table_lookup (csi_hash_table_t *hash_table,
entry = &hash_table->entries[idx];
if (ENTRY_IS_LIVE (*entry)) {
- if (hash_table->keys_equal (key, *entry))
+ if ((*entry)->hash == key->hash && hash_table->keys_equal (key, *entry))
return *entry;
} else if (ENTRY_IS_FREE (*entry))
return NULL;
@@ -295,8 +295,11 @@ _csi_hash_table_lookup (csi_hash_table_t *hash_table,
entry = &hash_table->entries[idx];
if (ENTRY_IS_LIVE (*entry)) {
- if (hash_table->keys_equal (key, *entry))
+ if ((*entry)->hash == key->hash &&
+ hash_table->keys_equal (key, *entry))
+ {
return *entry;
+ }
} else if (ENTRY_IS_FREE (*entry))
return NULL;
} while (++i < table_size);
diff --git a/util/cairo-script/cairo-script-objects.c b/util/cairo-script/cairo-script-objects.c
index 552241f3..84398f18 100644
--- a/util/cairo-script/cairo-script-objects.c
+++ b/util/cairo-script/cairo-script-objects.c
@@ -34,6 +34,7 @@
#include "cairo-script-private.h"
+#include <limits.h> /* INT_MAX */
#include <string.h>
csi_status_t
@@ -193,9 +194,7 @@ csi_boolean_new (csi_t *ctx,
static cairo_bool_t
_dictionary_name_equal (const void *_a, const void *_b)
{
- const csi_dictionary_entry_t *a = _a;
- const csi_dictionary_entry_t *b = _b;
- return a->hash_entry.hash == b->hash_entry.hash;
+ return TRUE;
}
csi_status_t
@@ -523,7 +522,7 @@ csi_string_new (csi_t *ctx,
if (len < 0)
len = strlen (str);
- if (_csi_unlikely (len >= INT32_MAX))
+ if (_csi_unlikely (len >= INT_MAX))
return _csi_error (CSI_STATUS_NO_MEMORY);
if (ctx->free_string == NULL || ctx->free_string->len <= len) {
diff --git a/util/cairo-script/cairo-script-operators.c b/util/cairo-script/cairo-script-operators.c
index d2bdb4c8..0ed3dd3f 100644
--- a/util/cairo-script/cairo-script-operators.c
+++ b/util/cairo-script/cairo-script-operators.c
@@ -39,6 +39,7 @@
#include <stdio.h> /* snprintf */
#include <string.h>
#include <math.h>
+#include <limits.h> /* INT_MAX */
#include <assert.h>
typedef struct _csi_proxy {
@@ -2136,7 +2137,7 @@ _glyph_path (csi_t *ctx)
}
if (nglyphs > ARRAY_LENGTH (stack_glyphs)) {
- if (_csi_unlikely ((unsigned) nglyphs >= INT32_MAX / sizeof (cairo_glyph_t)))
+ if (_csi_unlikely ((unsigned) nglyphs >= INT_MAX / sizeof (cairo_glyph_t)))
return _csi_error (CSI_STATUS_NO_MEMORY);
glyphs = _csi_alloc (ctx, sizeof (cairo_glyph_t) * nglyphs);
if (_csi_unlikely (glyphs == NULL))
@@ -3898,7 +3899,7 @@ _set_dash (csi_t *ctx)
if (_csi_likely (array->stack.len < ARRAY_LENGTH (stack_dashes))) {
dashes = stack_dashes;
} else {
- if (_csi_unlikely ((unsigned) array->stack.len >= INT32_MAX / sizeof (double)))
+ if (_csi_unlikely ((unsigned) array->stack.len >= INT_MAX / sizeof (double)))
return _csi_error (CSI_STATUS_NO_MEMORY);
dashes = _csi_alloc (ctx, sizeof (double) * array->stack.len);
if (_csi_unlikely (dashes == NULL))
@@ -4734,7 +4735,7 @@ _show_glyphs (csi_t *ctx)
}
if (nglyphs > ARRAY_LENGTH (stack_glyphs)) {
- if (_csi_unlikely ((unsigned) nglyphs >= INT32_MAX / sizeof (cairo_glyph_t)))
+ if (_csi_unlikely ((unsigned) nglyphs >= INT_MAX / sizeof (cairo_glyph_t)))
return _csi_error (CSI_STATUS_NO_MEMORY);
glyphs = _csi_alloc (ctx, sizeof (cairo_glyph_t) * nglyphs);
if (_csi_unlikely (glyphs == NULL))
@@ -4880,7 +4881,7 @@ _show_text_glyphs (csi_t *ctx)
array = obj->datum.array;
nclusters = array->stack.len / 2;
if (nclusters > ARRAY_LENGTH (stack_clusters)) {
- if (_csi_unlikely ((unsigned) nclusters >= INT32_MAX / sizeof (cairo_text_cluster_t)))
+ if (_csi_unlikely ((unsigned) nclusters >= INT_MAX / sizeof (cairo_text_cluster_t)))
return _csi_error (CSI_STATUS_NO_MEMORY);
clusters = _csi_alloc (ctx, sizeof (cairo_text_cluster_t) * nclusters);
if (_csi_unlikely (clusters == NULL))
@@ -4898,7 +4899,7 @@ _show_text_glyphs (csi_t *ctx)
string = obj->datum.string;
nclusters = string->len / 2;
if (nclusters > ARRAY_LENGTH (stack_clusters)) {
- if (_csi_unlikely ((unsigned) nclusters >= INT32_MAX / sizeof (cairo_text_cluster_t)))
+ if (_csi_unlikely ((unsigned) nclusters >= INT_MAX / sizeof (cairo_text_cluster_t)))
return _csi_error (CSI_STATUS_NO_MEMORY);
clusters = _csi_alloc (ctx, sizeof (cairo_text_cluster_t) * nclusters);
if (_csi_unlikely (clusters == NULL))
@@ -4943,7 +4944,7 @@ _show_text_glyphs (csi_t *ctx)
return CSI_STATUS_SUCCESS;
if (nglyphs > ARRAY_LENGTH (stack_glyphs)) {
- if (_csi_unlikely ((unsigned) nglyphs >= INT32_MAX / sizeof (cairo_glyph_t)))
+ if (_csi_unlikely ((unsigned) nglyphs >= INT_MAX / sizeof (cairo_glyph_t)))
return _csi_error (CSI_STATUS_NO_MEMORY);
glyphs = _csi_alloc (ctx, sizeof (cairo_glyph_t) * nglyphs);
if (_csi_unlikely (glyphs == NULL)) {
@@ -5415,7 +5416,7 @@ _debug_print (csi_t *ctx)
fprintf (stderr, "name: %s\n", (char *) obj->datum.name);
break;
case CSI_OBJECT_TYPE_OPERATOR:
- fprintf (stderr, "operator: %p\n", obj->datum.op);
+ fprintf (stderr, "operator: %p\n", obj->datum.ptr);
break;
case CSI_OBJECT_TYPE_REAL:
fprintf (stderr, "real: %g\n", obj->datum.real);
diff --git a/util/cairo-script/cairo-script-private.h b/util/cairo-script/cairo-script-private.h
index f74cb49f..d2ebc0c8 100644
--- a/util/cairo-script/cairo-script-private.h
+++ b/util/cairo-script/cairo-script-private.h
@@ -247,7 +247,7 @@ typedef enum {
CSI_OBJECT_TYPE_FONT,
CSI_OBJECT_TYPE_PATTERN,
CSI_OBJECT_TYPE_SCALED_FONT,
- CSI_OBJECT_TYPE_SURFACE,
+ CSI_OBJECT_TYPE_SURFACE
} csi_object_type_t;
#define CSI_OBJECT_IS_ATOM(OBJ) (((OBJ)->type & CSI_OBJECT_TYPE_MASK) < 0x08)
@@ -256,7 +256,7 @@ typedef enum {
enum { /* attributes */
CSI_OBJECT_ATTR_EXECUTABLE = 1 << 6,
- CSI_OBJECT_ATTR_WRITABLE = 1 << 7,
+ CSI_OBJECT_ATTR_WRITABLE = 1 << 7
};
#define CSI_OBJECT_ATTR_MASK (CSI_OBJECT_ATTR_EXECUTABLE | \
CSI_OBJECT_ATTR_WRITABLE)
@@ -400,7 +400,7 @@ struct _csi_file {
STDIO,
BYTES,
PROCEDURE,
- FILTER,
+ FILTER
} type;
void *src;
void *data;
@@ -429,7 +429,7 @@ struct _csi_scanner {
COMMENT,
STRING,
HEX,
- BASE85,
+ BASE85
} state;
csi_buffer_t buffer;
diff --git a/util/cairo-script/cairo-script-scanner.c b/util/cairo-script/cairo-script-scanner.c
index c08e447d..22d1721e 100644
--- a/util/cairo-script/cairo-script-scanner.c
+++ b/util/cairo-script/cairo-script-scanner.c
@@ -34,9 +34,10 @@
#include "cairo-script-private.h"
+#include <limits.h> /* INT_MAX */
+#include <math.h> /* pow */
#include <stdio.h> /* EOF */
#include <string.h> /* memset */
-#include <math.h> /* pow */
/*
* whitespace:
@@ -88,7 +89,7 @@ _csi_buffer_grow (csi_t *ctx, csi_buffer_t *buffer)
if (_csi_unlikely (buffer->status))
return buffer->status;
- if (_csi_unlikely (buffer->size > INT32_MAX / 2))
+ if (_csi_unlikely (buffer->size > INT_MAX / 2))
return buffer->status = _csi_error (CSI_STATUS_NO_MEMORY);
offset = buffer->ptr - buffer->base;
diff --git a/util/cairo-script/cairo-script-stack.c b/util/cairo-script/cairo-script-stack.c
index d6c123b4..59d2c6a0 100644
--- a/util/cairo-script/cairo-script-stack.c
+++ b/util/cairo-script/cairo-script-stack.c
@@ -34,6 +34,7 @@
#include "cairo-script-private.h"
+#include <limits.h> /* INT_MAX */
#include <string.h>
csi_status_t
@@ -43,7 +44,7 @@ _csi_stack_init (csi_t *ctx, csi_stack_t *stack, csi_integer_t size)
stack->len = 0;
stack->size = size;
- /* assert ((unsigned) size < INT32_MAX / sizeof (csi_object_t)); */
+ /* assert ((unsigned) size < INT_MAX / sizeof (csi_object_t)); */
stack->objects = _csi_alloc (ctx, size * sizeof (csi_object_t));
if (_csi_unlikely (stack->objects == NULL))
status = _csi_error (CSI_STATUS_NO_MEMORY);
@@ -90,7 +91,7 @@ _csi_stack_roll (csi_t *ctx,
/* fall back to a copy */
if (n > ARRAY_LENGTH (stack_copy)) {
- if (_csi_unlikely ((unsigned) n > INT32_MAX / sizeof (csi_object_t)))
+ if (_csi_unlikely ((unsigned) n > INT_MAX / sizeof (csi_object_t)))
return _csi_error (CSI_STATUS_NO_MEMORY);
copy = _csi_alloc (ctx, n * sizeof (csi_object_t));
if (copy == NULL)
@@ -124,7 +125,7 @@ _csi_stack_grow (csi_t *ctx, csi_stack_t *stack, csi_integer_t cnt)
if (_csi_likely (cnt <= stack->size))
return CSI_STATUS_SUCCESS;
- if (_csi_unlikely ((unsigned) cnt >= INT32_MAX / sizeof (csi_object_t)))
+ if (_csi_unlikely ((unsigned) cnt >= INT_MAX / sizeof (csi_object_t)))
return _csi_error (CSI_STATUS_NO_MEMORY);
newsize = stack->size;
diff --git a/util/cairo-script/csi-replay.c b/util/cairo-script/csi-replay.c
index 8a1f3cd9..16b733cc 100644
--- a/util/cairo-script/csi-replay.c
+++ b/util/cairo-script/csi-replay.c
@@ -7,10 +7,8 @@
static const cairo_user_data_key_t _key;
-#if CAIRO_HAS_XLIB_XRENDER_SURFACE
+#if CAIRO_HAS_XLIB_SURFACE
#include <cairo-xlib.h>
-#include <cairo-xlib-xrender.h>
-
static Display *
_get_display (void)
{
@@ -29,16 +27,49 @@ _get_display (void)
}
static void
-_destroy_pixmap (void *closure)
+_destroy_window (void *closure)
{
- XFreePixmap (_get_display(), (Pixmap) closure);
+ XFlush (_get_display ());
+ XDestroyWindow (_get_display(), (Window) closure);
+}
+
+static cairo_surface_t *
+_xlib_surface_create (void *closure,
+ cairo_content_t content,
+ double width, double height)
+{
+ Display *dpy;
+ XSetWindowAttributes attr;
+ Visual *visual;
+ int depth;
+ Window w;
+ cairo_surface_t *surface;
+
+ dpy = _get_display ();
+
+ visual = DefaultVisual (dpy, DefaultScreen (dpy));
+ depth = DefaultDepth (dpy, DefaultScreen (dpy));
+ attr.override_redirect = True;
+ w = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0,
+ width <= 0 ? 1 : width,
+ height <= 0 ? 1 : height,
+ 0, depth,
+ InputOutput, visual, CWOverrideRedirect, &attr);
+ XMapWindow (dpy, w);
+
+ surface = cairo_xlib_surface_create (dpy, w, visual, width, height);
+ cairo_surface_set_user_data (surface, &_key, (void *) w, _destroy_window);
+
+ return surface;
}
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
+#include <cairo-xlib-xrender.h>
+
static void
-_destroy_window (void *closure)
+_destroy_pixmap (void *closure)
{
- XFlush (_get_display ());
- XDestroyWindow (_get_display(), (Window) closure);
+ XFreePixmap (_get_display(), (Pixmap) closure);
}
static cairo_surface_t *
@@ -47,66 +78,40 @@ _xrender_surface_create (void *closure,
double width, double height)
{
Display *dpy;
+ Pixmap pixmap;
XRenderPictFormat *xrender_format;
cairo_surface_t *surface;
dpy = _get_display ();
content = CAIRO_CONTENT_COLOR_ALPHA;
- if (1) {
- Pixmap pixmap;
-
- switch (content) {
- case CAIRO_CONTENT_COLOR_ALPHA:
- xrender_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
- break;
- case CAIRO_CONTENT_COLOR:
- xrender_format = XRenderFindStandardFormat (dpy, PictStandardRGB24);
- break;
- case CAIRO_CONTENT_ALPHA:
- default:
- xrender_format = XRenderFindStandardFormat (dpy, PictStandardA8);
- }
-
- pixmap = XCreatePixmap (dpy, DefaultRootWindow (dpy),
- width, height, xrender_format->depth);
-
- surface = cairo_xlib_surface_create_with_xrender_format (dpy, pixmap,
- DefaultScreenOfDisplay (dpy),
- xrender_format,
- width, height);
- cairo_surface_set_user_data (surface, &_key,
- (void *) pixmap, _destroy_pixmap);
- } else {
- XSetWindowAttributes attr;
- Visual *visual;
- Window w;
-
- visual = DefaultVisual (dpy, DefaultScreen (dpy));
- xrender_format = XRenderFindVisualFormat (dpy, visual);
- if (xrender_format == NULL) {
- fprintf (stderr, "X server does not have the Render extension.\n");
- exit (1);
- }
- attr.override_redirect = True;
- w = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0,
- width <= 0 ? 1 : width,
- height <= 0 ? 1 : height,
- 0, xrender_format->depth,
- InputOutput, visual, CWOverrideRedirect, &attr);
- XMapWindow (dpy, w);
-
- surface = cairo_xlib_surface_create_with_xrender_format (dpy, w,
- DefaultScreenOfDisplay (dpy),
- xrender_format,
- width, height);
- cairo_surface_set_user_data (surface, &_key, (void *) w, _destroy_window);
+ switch (content) {
+ case CAIRO_CONTENT_COLOR_ALPHA:
+ xrender_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
+ break;
+ case CAIRO_CONTENT_COLOR:
+ xrender_format = XRenderFindStandardFormat (dpy, PictStandardRGB24);
+ break;
+ case CAIRO_CONTENT_ALPHA:
+ default:
+ xrender_format = XRenderFindStandardFormat (dpy, PictStandardA8);
}
+ pixmap = XCreatePixmap (dpy, DefaultRootWindow (dpy),
+ width, height, xrender_format->depth);
+
+ surface = cairo_xlib_surface_create_with_xrender_format (dpy, pixmap,
+ DefaultScreenOfDisplay (dpy),
+ xrender_format,
+ width, height);
+ cairo_surface_set_user_data (surface, &_key,
+ (void *) pixmap, _destroy_pixmap);
+
return surface;
}
#endif
+#endif
#if CAIRO_HAS_GL_GLX_SURFACE
#include <cairo-gl.h>
@@ -213,6 +218,8 @@ main (int argc, char **argv)
cairo_script_interpreter_hooks_t hooks = {
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
.surface_create = _xrender_surface_create
+#elif CAIRO_HAS_XLIB_SURFACE
+ .surface_create = _xlib_surface_create
#elif CAIRO_PDF_SURFACE
.surface_create = _pdf_surface_create
#elif CAIRO_PS_SURFACE
@@ -235,6 +242,9 @@ main (int argc, char **argv)
#if CAIRO_HAS_GL_GLX_SURFACE
{ "--glx", _glx_surface_create },
#endif
+#if CAIRO_HAS_XLIB_SURFACE
+ { "--xlib", _xlib_surface_create },
+#endif
#if CAIRO_HAS_PDF_SURFACE
{ "--pdf", _pdf_surface_create },
#endif
diff --git a/util/cairo-trace/cairo-trace.in b/util/cairo-trace/cairo-trace.in
index 40c9d193..bf17217d 100644
--- a/util/cairo-trace/cairo-trace.in
+++ b/util/cairo-trace/cairo-trace.in
@@ -6,6 +6,7 @@ exec_prefix=@exec_prefix@
nofile=
flush=
nocallers=
+nomarkdirty=
usage() {
cat << EOF
@@ -14,10 +15,11 @@ cairo-trace will generate a log of all calls made by command to
cairo. This log will be stored in a file in the local directory
called command.pid.trace.
Whatever else happens is driven by its argument:
- --flush - Flush the output trace after every call.
- --no-file - Disable the creation of an output file. Outputs to the
- terminal instead.
- --no-callers - Do not lookup the caller address/symbol/line whilst tracing.
+ --flush - Flush the output trace after every call.
+ --no-file - Disable the creation of an output file. Outputs to the
+ terminal instead.
+ --no-callers - Do not lookup the caller address/symbol/line whilst tracing.
+ --no-mark-dirty - Do not record image data for cairo_mark_dirty()
Enviroment variables understood by cairo-trace:
CAIRO_TRACE_FLUSH - flush the output after every function call.
@@ -42,6 +44,10 @@ while test $skip -eq 1; do
skip=1
nocallers=1
;;
+ --no-mark-dirty)
+ skip=1
+ nomarkdirty=1
+ ;;
--version)
echo "cairo-trace, version @CAIRO_VERSION_MAJOR@.@CAIRO_VERSION_MINOR@.@CAIRO_VERSION_MICRO@."
exit
@@ -69,13 +75,18 @@ if test -n "$nocallers"; then
export CAIRO_TRACE_LINE_INFO
fi
+if test -n "$nomarkdirty"; then
+ CAIRO_TRACE_MARK_DIRTY=0
+ export CAIRO_TRACE_MARK_DIRTY
+fi
+
if test -n "$flush"; then
CAIRO_TRACE_FLUSH=1
export CAIRO_TRACE_FLUSH
fi
if test -z "$nofile"; then
- CAIRO_TRACE_OUTDIR=. "$@"
+ CAIRO_TRACE_OUTDIR=`pwd` "$@"
else
CAIRO_TRACE_FD=3 "$@" 3>&1 >/dev/null
fi
diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c
index 029a7200..4826e990 100644
--- a/util/cairo-trace/trace.c
+++ b/util/cairo-trace/trace.c
@@ -166,6 +166,7 @@ static FILE *logfile;
static bool _flush;
static bool _error;
static bool _line_info;
+static bool _mark_dirty;
static const cairo_user_data_key_t destroy_key;
#if __GNUC__ >= 3
@@ -692,12 +693,17 @@ _init_logfile (void)
if (env != NULL)
_line_info = atoi (env);
+ _mark_dirty = true;
+ env = getenv ("CAIRO_TRACE_MARK_DIRTY");
+ if (env != NULL)
+ _mark_dirty = atoi (env);
+
filename = getenv ("CAIRO_TRACE_FD");
if (filename != NULL) {
int fd = atoi (filename);
logfile = fdopen (fd, "w");
if (logfile == NULL) {
- fprintf (stderr, "Failed to open trace file descriptor '%s': %s",
+ fprintf (stderr, "Failed to open trace file descriptor '%s': %s\n",
filename, strerror (errno));
return false;
}
@@ -724,7 +730,7 @@ _init_logfile (void)
logfile = fopen (filename, "wb");
if (logfile == NULL) {
- fprintf (stderr, "Failed to open trace file '%s': %s",
+ fprintf (stderr, "Failed to open trace file '%s': %s\n",
filename, strerror (errno));
return false;
}
@@ -3115,9 +3121,12 @@ cairo_surface_mark_dirty (cairo_surface_t *surface)
{
_emit_line_info ();
if (surface != NULL && _write_lock ()) {
- _emit_surface (surface);
- _trace_printf ("%% mark-dirty\n");
- _emit_source_image (surface);
+ if (_mark_dirty) {
+ _emit_surface (surface);
+ _trace_printf ("%% mark-dirty\n");
+ _emit_source_image (surface);
+ } else
+ _trace_printf ("%% s%ld mark-dirty\n", _get_surface_id (surface));
_write_unlock ();
}
@@ -3130,10 +3139,14 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
{
_emit_line_info ();
if (surface != NULL && _write_lock ()) {
- _emit_surface (surface);
- _trace_printf ("%% %d %d %d %d mark-dirty-rectangle\n",
- x, y, width, height);
- _emit_source_image_rectangle (surface, x,y, width, height);
+ if (_mark_dirty) {
+ _emit_surface (surface);
+ _trace_printf ("%% %d %d %d %d mark-dirty-rectangle\n",
+ x, y, width, height);
+ _emit_source_image_rectangle (surface, x,y, width, height);
+ } else
+ _trace_printf ("%% s%ld %d %d %d %d mark-dirty-rectangle\n",
+ _get_surface_id (surface), x, y, width, height);
_write_unlock ();
}