diff options
author | Eric Anholt <eric@anholt.net> | 2009-06-02 00:37:19 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-06-02 00:56:39 -0700 |
commit | f59f44c140e5f60d336423e0585d2bb8a6c0ea01 (patch) | |
tree | b0e1369a4aedfb6ee288fd29264177e881021850 | |
parent | 2da78fd4666faa27d037ae3625ca83353a6e7629 (diff) | |
parent | 4232719af968ed05636fe34f2ffe2520dc02d737 (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
182 files changed, 4170 insertions, 2695 deletions
@@ -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 @@ -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, ®ion); - 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, - ®ion); + 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 (®ion); + 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, ®ion->rgn)) + if (! pixman_image_set_clip_region32 (surface->pixman_image, region? ®ion->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 (®ion->status, status); + + return _cairo_error (status); +} + void _cairo_region_init (cairo_region_t *region) { + region->status = CAIRO_STATUS_SUCCESS; pixman_region32_init (®ion->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 (®ion->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 (®ion->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 (®ion->rgn, pboxes, count)) - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + region->status = CAIRO_STATUS_SUCCESS; - if (pboxes != stack_pboxes) - free (pboxes); + pixman_region32_init (®ion->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 (®ion->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 (®ion->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 (©->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 (®ion->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 (®ion->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 (®ion->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 (®ion->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 (®ion->rgn); + pixman_box32_t *pextents; + + if (region->status) { + extents->x = extents->y = 0; + extents->width = extents->height = 0; + return; + } + + pextents = pixman_region32_extents (®ion->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 (®ion, + rectangle->x, rectangle->y, + rectangle->width, rectangle->height); + + if (! pixman_region32_subtract (&dst->rgn, &dst->rgn, ®ion)) + status = _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); + + pixman_region32_fini (®ion); + + 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 (®ion, + rectangle->x, rectangle->y, + rectangle->width, rectangle->height); + + if (! pixman_region32_intersect (&dst->rgn, &dst->rgn, ®ion)) + status = _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); + + pixman_region32_fini (®ion); + + 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 (®ion, + rectangle->x, rectangle->y, + rectangle->width, rectangle->height); + if (! pixman_region32_union (&dst->rgn, &dst->rgn, ®ion)) + status = _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); + + pixman_region32_fini (®ion); + + 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 (®ion->rgn); + if (region->status) + return TRUE; + + return ! pixman_region32_not_empty (®ion->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 (®ion->rgn, x, y); + if (region->status) + return; + + pixman_region32_translate (®ion->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 (®ion->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 (®ion->rgn, &pbox); + return pixman_region32_contains_point (®ion->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 Binary files differnew file mode 100644 index 00000000..fd8026f7 --- /dev/null +++ b/test/path-append.ps.ref.png diff --git a/test/path-append.ref.png b/test/path-append.ref.png Binary files differnew file mode 100644 index 00000000..de9057c8 --- /dev/null +++ b/test/path-append.ref.png diff --git a/test/path-append.test-fallback.ref.png b/test/path-append.test-fallback.ref.png Binary files differnew file mode 100644 index 00000000..fa72ac06 --- /dev/null +++ b/test/path-append.test-fallback.ref.png diff --git a/test/path-append.xlib-fallback.ref.png b/test/path-append.xlib-fallback.ref.png Binary files differnew file mode 100644 index 00000000..08a33a26 --- /dev/null +++ b/test/path-append.xlib-fallback.ref.png diff --git a/test/path-append.xlib.ref.png b/test/path-append.xlib.ref.png Binary files differnew file mode 100644 index 00000000..fa72ac06 --- /dev/null +++ b/test/path-append.xlib.ref.png 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 Binary files differindex 5c98d7d8..bd30da6e 100644 --- a/test/rotate-image-surface-paint.ref.png +++ b/test/rotate-image-surface-paint.ref.png 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 Binary files differnew file mode 100644 index 00000000..3fa8bbe5 --- /dev/null +++ b/test/test-fallback16-surface-source.ref.png 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 Binary files differindex f9374e33..e75062ca 100644 --- a/test/twin.ps.ref.png +++ b/test/twin.ps.ref.png diff --git a/test/twin.ref.png b/test/twin.ref.png Binary files differindex 8bf098c1..3c46b02a 100644 --- a/test/twin.ref.png +++ b/test/twin.ref.png diff --git a/test/twin.svg.ref.png b/test/twin.svg.ref.png Binary files differindex 8b4617f0..b5d4a314 100644 --- a/test/twin.svg.ref.png +++ b/test/twin.svg.ref.png 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 (); } |