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

This commit is contained in:
Carl Worth 2008-01-11 12:30:15 -08:00
commit bcf0c442b9
37 changed files with 2585 additions and 1953 deletions

1
.gitignore vendored
View file

@ -20,6 +20,7 @@ depcomp
install-sh
libtool
ltmain.sh
mkinstalldirs
missing
releases
stamp-h

View file

@ -222,6 +222,7 @@ static cairo_boilerplate_target_t targets[] =
{ "win32", CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR_ALPHA, 0,
_cairo_boilerplate_win32_create_surface,
cairo_surface_write_to_png },
#if CAIRO_CAN_TEST_WIN32_PRINTING_SURFACE
{ "win32-printing", CAIRO_SURFACE_TYPE_WIN32_PRINTING,
CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, 0,
_cairo_boilerplate_win32_printing_create_surface,
@ -234,6 +235,7 @@ static cairo_boilerplate_target_t targets[] =
_cairo_boilerplate_win32_printing_cleanup,
NULL, TRUE },
#endif
#endif
#if CAIRO_HAS_XCB_SURFACE
/* Acceleration architectures may make the results differ by a
* bit, so we set the error tolerance to 1. */

View file

@ -1,4 +1,4 @@
AC_PREREQ(2.54)
AC_PREREQ(2.58)
dnl cairo package version number, (as distinct from shared library version)
dnl For the minor number: odd => unstable series
@ -17,7 +17,9 @@ AC_CONFIG_HEADERS(config.h)
dnl automake 1.8 requires autoconf 2.58
dnl automake 1.7 requires autoconf 2.54
AM_INIT_AUTOMAKE([1.7])
dnl automake < 1.8 does not handle TESTS=some-test$(EXEXT) as used
dnl in test/Makefile.am and perf/Makefile.am
AM_INIT_AUTOMAKE([1.8])
dnl ===========================================================================
@ -87,7 +89,7 @@ AC_DEFUN([_CHECK_FUNCS_WITH_FLAGS],
dnl ===========================================================================
AC_CHECK_FUNCS(vasnprintf)
AC_CHECK_FUNCS(vasnprintf ctime_r drand48)
dnl ===========================================================================
dnl
@ -364,6 +366,20 @@ CAIRO_BACKEND_ENABLE(win32_font, Microsoft Windows font, win32-font, WIN32_FONT,
use_win32_font=$use_win32
])
test_win32_printing=no
if test "x$use_win32" = "xyes"; then
AC_CHECK_PROG(GS, gs, gs)
if test "$GS"; then
AC_DEFINE([CAIRO_CAN_TEST_WIN32_PRINTING_SURFACE], 1, [Define to 1 if the Win32 Printing backend can be tested (needs ghostscript)])
test_win32_printing="yes"
else
AC_MSG_WARN([Win32 Printing backend will not be tested since ghostscript is not available])
test_win32_printing="no (requires ghostscript)"
fi
fi
AM_CONDITIONAL(CAIRO_CAN_TEST_WIN32_PRINTING_SURFACE, test "x$test_win32_printing" = "xyes")
dnl ===========================================================================
CAIRO_BACKEND_ENABLE(os2, OS/2, os2, OS2_SURFACE, no, [
@ -498,7 +514,8 @@ FREETYPE_MIN_VERSION=9.7.3
CAIRO_BACKEND_ENABLE(ft, FreeType font, freetype, FT_FONT, auto, [
ft_REQUIRES="fontconfig"
PKG_CHECK_MODULES(FONTCONFIG, $ft_REQUIRES,
[_CHECK_FUNCS_WITH_FLAGS(FcFini, [$FONTCONFIG_CFLAGS], [$FONTCONFIG_LIBS])],
[_CHECK_FUNCS_WITH_FLAGS(FcFini, [$FONTCONFIG_CFLAGS], [$FONTCONFIG_LIBS],,
[AC_MSG_RESULT(no); use_ft="no (requires fontconfig)"])],
[AC_MSG_RESULT(no); use_ft="no (requires fontconfig)"])
if test "x$use_ft" = "xyes"; then
@ -609,9 +626,10 @@ test_pdf=no
if test "x$use_pdf" = "xyes"; then
poppler_DEPENDENCY="poppler-glib >= $POPPLER_VERSION_REQUIRED"
PKG_CHECK_MODULES(POPPLER, $poppler_DEPENDENCY pango gtk+-2.0,
[_CHECK_FUNCS_WITH_FLAGS(poppler_page_render_to_pixbuf, [$POPPLER_CFLAGS], [$POPPLER_LIBS],
[test_pdf=yes],
[AC_MSG_RESULT(no)
test_pdf="no (requires $poppler_DEPENDENCY)"])
[AC_MSG_RESULT(no); test_pdf="no (requires $poppler_DEPENDENCY)"])],
[AC_MSG_RESULT(no); test_pdf="no (requires $poppler_DEPENDENCY)"])
if test "x$test_pdf" = "xyes"; then
AC_DEFINE([CAIRO_CAN_TEST_PDF_SURFACE], 1, [Define to 1 if the PDF backend can be tested (need poppler and other dependencies for pdf2png)])
else
@ -638,9 +656,10 @@ test_svg=no
if test "x$use_svg" = "xyes"; then
librsvg_DEPENDENCY="librsvg-2.0 >= $LIBRSVG_VERSION_REQUIRED"
PKG_CHECK_MODULES(LIBRSVG, $librsvg_DEPENDENCY gdk-2.0,
[_CHECK_FUNCS_WITH_FLAGS(rsvg_pixbuf_from_file, [$LIBRSVG_CFLAGS], [$LIBRSVG_LIBS],
[test_svg=yes],
[AC_MSG_RESULT(no)
test_svg="no (requires $librsvg_DEPENDENCY)"])
[AC_MSG_RESULT(no); test_svg="no (requires $librsvg_DEPENDENCY)"])],
[AC_MSG_RESULT(no); test_svg="no (requires $librsvg_DEPENDENCY)"])
if test "x$test_svg" = "xyes"; then
AC_DEFINE([CAIRO_CAN_TEST_SVG_SURFACE], 1, [Define to 1 if the SVG backend can be tested])
else
@ -995,8 +1014,9 @@ AC_OUTPUT
dnl ===========================================================================
V="$CAIRO_VERSION_MAJOR.$CAIRO_VERSION_MINOR.$CAIRO_VERSION_MICRO"
echo ""
echo "cairo will be compiled with the following surface backends:"
echo "cairo (version $V) will be compiled with the following surface backends:"
echo " image: yes (always builtin)"
echo " Xlib: $use_xlib"
echo " Xlib Xrender: $use_xlib_xrender"
@ -1025,6 +1045,9 @@ echo " test surfaces: $use_test_surfaces"
echo " ps testing: $test_ps"
echo " pdf testing: $test_pdf"
echo " svg testing: $test_svg"
if test x"$use_win32" = "xyes"; then
echo " win32 printing testing: $test_win32_printing"
fi
echo ""
echo "using CFLAGS:"
echo $CAIRO_CFLAGS

View file

@ -77,14 +77,14 @@ CAIRO_PERF_ENVIRONMENT = CAIRO_PERF_ITERATIONS="$(ITERS)" CAIRO_TEST_TARGET="$(T
# Cap the maximum number of iterations during 'make check'
TESTS_ENVIRONMENT = CAIRO_TEST_TARGET="$(TARGETS)" CAIRO_PERF_ITERATIONS="10"
TESTS = cairo-perf
TESTS = cairo-perf$(EXEEXT)
perf: cairo-perf
$(CAIRO_PERF_ENVIRONMENT) ./cairo-perf
perf: cairo-perf$(EXEEXT)
$(CAIRO_PERF_ENVIRONMENT) ./cairo-perf$(EXEEXT)
html: index.html
index.html: cairo-perf
index.html: cairo-perf$(EXEEXT)
$(CAIRO_PERF_ENVIRONMENT) ./cairo-perf-diff -h HEAD > $@

View file

@ -22,6 +22,7 @@ endif
if CAIRO_HAS_PDF_SURFACE
libcairo_pdf_headers = cairo-pdf.h
libcairo_pdf_sources = cairo-pdf-surface.c cairo-pdf-surface-private.h \
cairo-pdf-operators.c cairo-pdf-operators-private.h \
cairo-deflate-stream.c
libcairo_font_subset_sources = $(font_subset_sources)
backend_pkgconfigs += cairo-pdf.pc
@ -292,7 +293,7 @@ cairo-features.h:
cd $(top_builddir) && ./config.status src/cairo-features.h
CLEANFILES = cairo.def
cairo.def: $(cairoinclude_HEADERS)
cairo.def: $(cairoinclude_HEADERS) $(nodist_cairoinclude_HEADERS)
@echo Generating $@
@(echo EXPORTS; \
(cd $(srcdir); cat $(cairo_headers) || echo 'cairo_ERROR ()' ) | \
@ -319,6 +320,15 @@ TESTS_ENVIRONMENT = srcdir="$(srcdir)" MAKE="$(MAKE)"
TESTS = check-def.sh check-plt.sh check-headers.sh check-cairoint.sh
EXTRA_DIST += $(TESTS)
check-def.sh check-plt.sh: .check-has-hidden-symbols
EXTRA_PROGRAMS = check-has-hidden-symbols
CLEANFILES += $(EXTRA_PROGRAMS) .check-has-hidden-symbols
check_has_hidden_symbols_CFLAGS = -I$(srcdir) $(CAIRO_CFLAGS)
.check-has-hidden-symbols: check-has-hidden-symbols$(EXEEXT)
@nm check-has-hidden-symbols$(EXEEXT) 2>/dev/null | grep cairo_has_hidden_symbols 2>/dev/null >/dev/null && echo 1 > $@ || echo 0 > $@
SPARSE = sparse
sparse:
@status=true; for f in $(libcairo_la_base_sources); do \

View file

@ -70,7 +70,7 @@ _cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *
cairo_surface_pattern_t *surface_pattern;
cairo_status_t status;
cairo_bool_t old_has_ctm;
cairo_matrix_t old_ctm;
cairo_matrix_t old_ctm, p2d;
assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
surface_pattern = (cairo_surface_pattern_t *) pattern;
@ -78,7 +78,12 @@ _cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *
old_ctm = surface->ctm;
old_has_ctm = surface->has_ctm;
cairo_matrix_multiply (&surface->ctm, &pattern->matrix, &surface->ctm);
p2d = pattern->matrix;
status = cairo_matrix_invert (&p2d);
/* _cairo_pattern_set_matrix guarantees invertibility */
assert (status == CAIRO_STATUS_SUCCESS);
cairo_matrix_multiply (&surface->ctm, &p2d, &surface->ctm);
surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
status = _cairo_meta_surface_replay_and_create_regions (surface_pattern->surface,
@ -114,9 +119,15 @@ _cairo_analysis_surface_add_operation (cairo_analysis_surface_t *surface,
&x1, &y1, &x2, &y2,
NULL);
rect->x = floor (x1);
rect->y = floor (x2);
rect->width = ceil (x2) - rect->x;
rect->height = ceil (y2) - rect->y;
rect->y = floor (y1);
x2 = ceil (x2) - rect->x;
y2 = ceil (y2) - rect->y;
if (x2 <= 0 || y2 <= 0)
return CAIRO_STATUS_SUCCESS;
rect->width = x2;
rect->height = y2;
}
bbox.p1.x = _cairo_fixed_from_int (rect->x);
@ -210,28 +221,24 @@ _cairo_analysis_surface_intersect_clip_path (void *abstract_surface,
cairo_analysis_surface_t *surface = abstract_surface;
double x1, y1, x2, y2;
cairo_rectangle_int_t extent;
cairo_status_t status;
if (path == NULL) {
surface->current_clip.x = 0;
surface->current_clip.y = 0;
surface->current_clip.width = surface->width;
surface->current_clip.width = surface->width;
surface->current_clip.height = surface->height;
status = CAIRO_STATUS_SUCCESS;
} else {
status = _cairo_path_fixed_bounds (path, &x1, &y1, &x2, &y2);
if (status)
return status;
_cairo_path_fixed_bounds (path, &x1, &y1, &x2, &y2);
extent.x = floor (x1);
extent.y = floor (y1);
extent.width = ceil (x2) - extent.x;
extent.width = ceil (x2) - extent.x;
extent.height = ceil (y2) - extent.y;
_cairo_rectangle_intersect (&surface->current_clip, &extent);
}
return status;
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@ -404,7 +411,7 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
tolerance,
&traps);
if (status) {
if (status || traps.num_traps == 0) {
_cairo_traps_fini (&traps);
return status;
}
@ -427,9 +434,9 @@ _cairo_analysis_surface_fill (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
cairo_antialias_t antialias)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status, backend_status;
@ -476,7 +483,7 @@ _cairo_analysis_surface_fill (void *abstract_surface,
tolerance,
&traps);
if (status) {
if (status || traps.num_traps == 0) {
_cairo_traps_fini (&traps);
return status;
}

View file

@ -70,12 +70,14 @@ CAIRO_BEGIN_DECLS
#endif
/* slim_internal.h */
#define CAIRO_HAS_HIDDEN_SYMBOLS 1
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) && !defined(__sun)
#define cairo_private_no_warn __attribute__((__visibility__("hidden")))
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
#define cairo_private_no_warn __hidden
#else /* not gcc >= 3.3 and not Sun Studio >= 8 */
#define cairo_private_no_warn
#undef CAIRO_HAS_HIDDEN_SYMBOLS
#endif
#ifndef WARN_UNUSED_RESULT

View file

@ -1495,6 +1495,7 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
font_matrix, ctm, options,
&cairo_ft_scaled_font_backend);
if (status) {
_cairo_unscaled_font_destroy (&unscaled->base);
free (scaled_font);
goto FAIL;
}
@ -1502,6 +1503,7 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
status = _cairo_ft_unscaled_font_set_scale (unscaled,
&scaled_font->base.scale);
if (status) {
_cairo_unscaled_font_destroy (&unscaled->base);
free (scaled_font);
goto FAIL;
}

View file

@ -1133,9 +1133,7 @@ _cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t *gstate,
{
cairo_box_t extents;
_cairo_traps_extents (traps, &extents);
if (extents.p1.x >= extents.p2.x || extents.p1.y >= extents.p2.y) {
if (traps->num_traps == 0) {
/* no traps, so we actually won't draw anything */
if (x1)
*x1 = 0.0;
@ -1146,6 +1144,8 @@ _cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t *gstate,
if (y2)
*y2 = 0.0;
} else {
_cairo_traps_extents (traps, &extents);
if (x1)
*x1 = _cairo_fixed_to_double (extents.p1.x);
if (y1)

View file

@ -38,8 +38,10 @@
#include "cairo-output-stream-private.h"
#include <stdio.h>
#include <locale.h>
#include <ctype.h>
#include <errno.h>
#ifdef _MSC_VER
#define snprintf _snprintf
@ -538,8 +540,14 @@ _cairo_output_stream_create_for_filename (const char *filename)
file = fopen (filename, "wb");
if (file == NULL) {
_cairo_error_throw (CAIRO_STATUS_WRITE_ERROR);
return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
switch (errno) {
case ENOMEM:
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
default:
_cairo_error_throw (CAIRO_STATUS_WRITE_ERROR);
return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
}
}
stream = malloc (sizeof *stream);

View file

@ -110,18 +110,22 @@ struct _cairo_paginated_surface_backend {
*
* 6. Replays a subset of the meta-surface operations to the target surface
*
* 7. Replays the remaining operations to an image surface, sets an
* 7. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_FALLBACK
*
* 8. Replays the remaining operations to an image surface, sets an
* appropriate clip on the target, then paints the resulting image
* surface to the target.
*
* So, the target will see drawing operations during two separate
* stages, (ANALYZE and RENDER). During the ANALYZE phase the target
* should not actually perform any rendering, (for example, if
* performing output to a file, no output should be generated during
* this stage). Instead the drawing functions simply need to return
* CAIRO_STATUS_SUCCESS or CAIRO_INT_STATUS_UNSUPPORTED to indicate
* whether rendering would be supported. And it should do this as
* quickly as possible.
* So, the target will see drawing operations during three separate
* stages, (ANALYZE, RENDER and FALLBACK). During the ANALYZE phase
* the target should not actually perform any rendering, (for example,
* if performing output to a file, no output should be generated
* during this stage). Instead the drawing functions simply need to
* return CAIRO_STATUS_SUCCESS or CAIRO_INT_STATUS_UNSUPPORTED to
* indicate whether rendering would be supported. And it should do
* this as quickly as possible. The FALLBACK phase allows the surface
* to distinguish fallback images from native rendering in case they
* need to be handled as a special case.
*
* NOTE: The paginated surface layer assumes that the target surface
* is "blank" by default at the beginning of each page, without any

View file

@ -161,7 +161,7 @@ _cairo_paginated_surface_finish (void *abstract_surface)
cairo_status_t status = CAIRO_STATUS_SUCCESS;
if (surface->page_is_blank == FALSE || surface->page_num == 1)
status = _cairo_paginated_surface_show_page (abstract_surface);
status = cairo_surface_show_page (abstract_surface);
if (status == CAIRO_STATUS_SUCCESS) {
cairo_surface_finish (surface->target);
@ -365,7 +365,9 @@ _paint_page (cairo_paginated_surface_t *surface)
cairo_box_int_t *boxes;
int num_boxes, i;
/* Reset clip region before drawing the fall back images */
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_FALLBACK);
/* Reset clip region before drawing the fall back images */
status = _cairo_surface_intersect_clip_path (surface->target,
NULL,
CAIRO_FILL_RULE_WINDING,

View file

@ -148,7 +148,7 @@ _cairo_path_bounder_close_path (void *closure)
}
/* XXX: Perhaps this should compute a PixRegion rather than 4 doubles */
cairo_status_t
void
_cairo_path_fixed_bounds (cairo_path_fixed_t *path,
double *x1, double *y1,
double *x2, double *y2)
@ -165,7 +165,9 @@ _cairo_path_fixed_bounds (cairo_path_fixed_t *path,
_cairo_path_bounder_curve_to,
_cairo_path_bounder_close_path,
&bounder);
if (status || ! bounder.has_point) {
assert (status == CAIRO_STATUS_SUCCESS);
if (! bounder.has_point) {
*x1 = *y1 = *x2 = *y2 = 0.;
} else {
*x1 = _cairo_fixed_to_double (bounder.min_x);
@ -175,6 +177,4 @@ _cairo_path_fixed_bounds (cairo_path_fixed_t *path,
}
_cairo_path_bounder_fini (&bounder);
return status;
}

View file

@ -91,8 +91,6 @@ _cairo_pattern_set_error (cairo_pattern_t *pattern,
static void
_cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
{
CAIRO_MUTEX_INITIALIZE ();
pattern->type = type;
CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
pattern->status = CAIRO_STATUS_SUCCESS;
@ -213,6 +211,42 @@ _cairo_pattern_fini (cairo_pattern_t *pattern)
}
}
cairo_status_t
_cairo_pattern_create_copy (cairo_pattern_t **pattern,
const cairo_pattern_t *other)
{
cairo_status_t status;
if (other->status)
return other->status;
switch (other->type) {
case CAIRO_PATTERN_TYPE_SOLID:
*pattern = malloc (sizeof (cairo_solid_pattern_t));
break;
case CAIRO_PATTERN_TYPE_SURFACE:
*pattern = malloc (sizeof (cairo_surface_pattern_t));
break;
case CAIRO_PATTERN_TYPE_LINEAR:
*pattern = malloc (sizeof (cairo_linear_pattern_t));
break;
case CAIRO_PATTERN_TYPE_RADIAL:
*pattern = malloc (sizeof (cairo_radial_pattern_t));
break;
}
if (*pattern == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = _cairo_pattern_init_copy (*pattern, other);
if (status) {
free (*pattern);
return status;
}
return CAIRO_STATUS_SUCCESS;
}
void
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
const cairo_color_t *color,
@ -339,6 +373,8 @@ _cairo_pattern_create_in_error (cairo_status_t status)
if (status == CAIRO_STATUS_NO_MEMORY)
return (cairo_pattern_t *)&_cairo_pattern_nil.base;
CAIRO_MUTEX_INITIALIZE ();
pattern = _cairo_pattern_create_solid (_cairo_stock_color (CAIRO_STOCK_BLACK),
CAIRO_CONTENT_COLOR);
if (pattern->status == CAIRO_STATUS_SUCCESS)
@ -379,6 +415,8 @@ cairo_pattern_create_rgb (double red, double green, double blue)
_cairo_color_init_rgb (&color, red, green, blue);
CAIRO_MUTEX_INITIALIZE ();
pattern = _cairo_pattern_create_solid (&color,
CAIRO_CONTENT_COLOR);
if (pattern->status)
@ -423,6 +461,8 @@ cairo_pattern_create_rgba (double red, double green, double blue,
_cairo_color_init_rgba (&color, red, green, blue, alpha);
CAIRO_MUTEX_INITIALIZE ();
pattern = _cairo_pattern_create_solid (&color,
CAIRO_CONTENT_COLOR_ALPHA);
if (pattern->status)
@ -464,6 +504,8 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface)
return (cairo_pattern_t *)&_cairo_pattern_nil.base;
}
CAIRO_MUTEX_INITIALIZE ();
_cairo_pattern_init_for_surface (pattern, surface);
return &pattern->base;
@ -507,6 +549,8 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
return (cairo_pattern_t *) &_cairo_pattern_nil.base;
}
CAIRO_MUTEX_INITIALIZE ();
_cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
return &pattern->base.base;
@ -552,6 +596,8 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0,
return (cairo_pattern_t *) &_cairo_pattern_nil.base;
}
CAIRO_MUTEX_INITIALIZE ();
_cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
return &pattern->base.base;

View file

@ -0,0 +1,107 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 Red Hat, Inc
* Copyright © 2006 Red Hat, Inc
* Copyright © 2007 Adrian Johnson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Kristian Høgsberg <krh@redhat.com>
* Carl Worth <cworth@cworth.org>
* Adrian Johnson <ajohnson@redneon.com>
*/
#ifndef CAIRO_PDF_OPERATORS_H
#define CAIRO_PDF_OPERATORS_H
#include "cairo-compiler-private.h"
#include "cairo-types-private.h"
typedef cairo_status_t
(*cairo_pdf_operators_use_font_subset_t) (unsigned int font_id,
unsigned int subset_id,
void *closure);
typedef struct _cairo_pdf_operators {
cairo_output_stream_t *stream;
cairo_matrix_t cairo_to_pdf;
cairo_scaled_font_subsets_t *font_subsets;
cairo_pdf_operators_use_font_subset_t use_font_subset;
void *use_font_subset_closure;
} cairo_pdf_operators_t;
cairo_private void
_cairo_pdf_operators_init (cairo_pdf_operators_t *pdf_operators,
cairo_output_stream_t *stream,
cairo_matrix_t cairo_to_pdf,
cairo_scaled_font_subsets_t *font_subsets);
cairo_private void
_cairo_pdf_operators_fini (cairo_pdf_operators_t *pdf_operators);
cairo_private void
_cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t *pdf_operators,
cairo_pdf_operators_use_font_subset_t use_font_subset,
void *closure);
cairo_private void
_cairo_pdf_operators_set_stream (cairo_pdf_operators_t *pdf_operators,
cairo_output_stream_t *stream);
cairo_private void
_cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators,
cairo_matrix_t cairo_to_pdf);
cairo_private cairo_int_status_t
_cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule);
cairo_private cairo_int_status_t
_cairo_pdf_operator_stroke (cairo_pdf_operators_t *pdf_operators,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse);
cairo_private cairo_int_status_t
_cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule);
cairo_private cairo_int_status_t
_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font);
#endif /* CAIRO_PDF_OPERATORS_H */

532
src/cairo-pdf-operators.c Normal file
View file

@ -0,0 +1,532 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 Red Hat, Inc
* Copyright © 2006 Red Hat, Inc
* Copyright © 2007 Adrian Johnson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Kristian Høgsberg <krh@redhat.com>
* Carl Worth <cworth@cworth.org>
* Adrian Johnson <ajohnson@redneon.com>
*/
#include "cairoint.h"
#include "cairo-pdf-operators-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-output-stream-private.h"
#include "cairo-scaled-font-subsets-private.h"
void
_cairo_pdf_operators_init (cairo_pdf_operators_t *pdf_operators,
cairo_output_stream_t *stream,
cairo_matrix_t cairo_to_pdf,
cairo_scaled_font_subsets_t *font_subsets)
{
pdf_operators->stream = stream;
pdf_operators->cairo_to_pdf = cairo_to_pdf;
pdf_operators->font_subsets = font_subsets;
pdf_operators->use_font_subset = NULL;
pdf_operators->use_font_subset_closure = NULL;
}
void
_cairo_pdf_operators_fini (cairo_pdf_operators_t *pdf_operators)
{
}
void
_cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t *pdf_operators,
cairo_pdf_operators_use_font_subset_t use_font_subset,
void *closure)
{
pdf_operators->use_font_subset = use_font_subset;
pdf_operators->use_font_subset_closure = closure;
}
void
_cairo_pdf_operators_set_stream (cairo_pdf_operators_t *pdf_operators,
cairo_output_stream_t *stream)
{
pdf_operators->stream = stream;
}
void
_cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators,
cairo_matrix_t cairo_to_pdf)
{
pdf_operators->cairo_to_pdf = cairo_to_pdf;
}
typedef struct _pdf_path_info {
cairo_output_stream_t *output;
cairo_matrix_t *cairo_to_pdf;
cairo_matrix_t *ctm_inverse;
} pdf_path_info_t;
static cairo_status_t
_cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
{
pdf_path_info_t *info = closure;
double x = _cairo_fixed_to_double (point->x);
double y = _cairo_fixed_to_double (point->y);
if (info->cairo_to_pdf)
cairo_matrix_transform_point (info->cairo_to_pdf, &x, &y);
if (info->ctm_inverse)
cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
_cairo_output_stream_printf (info->output,
"%f %f m ", x, y);
return _cairo_output_stream_get_status (info->output);
}
static cairo_status_t
_cairo_pdf_path_line_to (void *closure, cairo_point_t *point)
{
pdf_path_info_t *info = closure;
double x = _cairo_fixed_to_double (point->x);
double y = _cairo_fixed_to_double (point->y);
if (info->cairo_to_pdf)
cairo_matrix_transform_point (info->cairo_to_pdf, &x, &y);
if (info->ctm_inverse)
cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
_cairo_output_stream_printf (info->output,
"%f %f l ", x, y);
return _cairo_output_stream_get_status (info->output);
}
static cairo_status_t
_cairo_pdf_path_curve_to (void *closure,
cairo_point_t *b,
cairo_point_t *c,
cairo_point_t *d)
{
pdf_path_info_t *info = closure;
double bx = _cairo_fixed_to_double (b->x);
double by = _cairo_fixed_to_double (b->y);
double cx = _cairo_fixed_to_double (c->x);
double cy = _cairo_fixed_to_double (c->y);
double dx = _cairo_fixed_to_double (d->x);
double dy = _cairo_fixed_to_double (d->y);
if (info->cairo_to_pdf) {
cairo_matrix_transform_point (info->cairo_to_pdf, &bx, &by);
cairo_matrix_transform_point (info->cairo_to_pdf, &cx, &cy);
cairo_matrix_transform_point (info->cairo_to_pdf, &dx, &dy);
}
if (info->ctm_inverse) {
cairo_matrix_transform_point (info->ctm_inverse, &bx, &by);
cairo_matrix_transform_point (info->ctm_inverse, &cx, &cy);
cairo_matrix_transform_point (info->ctm_inverse, &dx, &dy);
}
_cairo_output_stream_printf (info->output,
"%f %f %f %f %f %f c ",
bx, by, cx, cy, dx, dy);
return _cairo_output_stream_get_status (info->output);
}
static cairo_status_t
_cairo_pdf_path_close_path (void *closure)
{
pdf_path_info_t *info = closure;
_cairo_output_stream_printf (info->output,
"h\r\n");
return _cairo_output_stream_get_status (info->output);
}
cairo_int_status_t
_cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule)
{
const char *pdf_operator;
if (! path->has_current_point) {
/* construct an empty path */
_cairo_output_stream_printf (pdf_operators->stream, "0 0 m ");
} else {
pdf_path_info_t info;
cairo_status_t status;
info.output = pdf_operators->stream;
info.cairo_to_pdf = &pdf_operators->cairo_to_pdf;
info.ctm_inverse = NULL;
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_pdf_path_move_to,
_cairo_pdf_path_line_to,
_cairo_pdf_path_curve_to,
_cairo_pdf_path_close_path,
&info);
if (status)
return status;
}
switch (fill_rule) {
case CAIRO_FILL_RULE_WINDING:
pdf_operator = "W";
break;
case CAIRO_FILL_RULE_EVEN_ODD:
pdf_operator = "W*";
break;
default:
ASSERT_NOT_REACHED;
}
_cairo_output_stream_printf (pdf_operators->stream,
"%s n\r\n",
pdf_operator);
return _cairo_output_stream_get_status (pdf_operators->stream);
}
static int
_cairo_pdf_line_cap (cairo_line_cap_t cap)
{
switch (cap) {
case CAIRO_LINE_CAP_BUTT:
return 0;
case CAIRO_LINE_CAP_ROUND:
return 1;
case CAIRO_LINE_CAP_SQUARE:
return 2;
default:
ASSERT_NOT_REACHED;
return 0;
}
}
static int
_cairo_pdf_line_join (cairo_line_join_t join)
{
switch (join) {
case CAIRO_LINE_JOIN_MITER:
return 0;
case CAIRO_LINE_JOIN_ROUND:
return 1;
case CAIRO_LINE_JOIN_BEVEL:
return 2;
default:
ASSERT_NOT_REACHED;
return 0;
}
}
static cairo_int_status_t
_cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
cairo_stroke_style_t *style)
{
_cairo_output_stream_printf (pdf_operators->stream,
"%f w\r\n",
style->line_width);
_cairo_output_stream_printf (pdf_operators->stream,
"%d J\r\n",
_cairo_pdf_line_cap (style->line_cap));
_cairo_output_stream_printf (pdf_operators->stream,
"%d j\r\n",
_cairo_pdf_line_join (style->line_join));
if (style->num_dashes) {
unsigned int d;
_cairo_output_stream_printf (pdf_operators->stream, "[");
for (d = 0; d < style->num_dashes; d++)
_cairo_output_stream_printf (pdf_operators->stream, " %f", style->dash[d]);
_cairo_output_stream_printf (pdf_operators->stream, "] %f d\r\n",
style->dash_offset);
} else {
_cairo_output_stream_printf (pdf_operators->stream, "[] 0.0 d\r\n");
}
_cairo_output_stream_printf (pdf_operators->stream,
"%f M ",
style->miter_limit);
return _cairo_output_stream_get_status (pdf_operators->stream);
}
cairo_int_status_t
_cairo_pdf_operator_stroke (cairo_pdf_operators_t *pdf_operators,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse)
{
pdf_path_info_t info;
cairo_status_t status;
cairo_matrix_t m;
status = _cairo_pdf_operators_emit_stroke_style (pdf_operators, style);
if (status)
return status;
info.output = pdf_operators->stream;
info.cairo_to_pdf = NULL;
info.ctm_inverse = ctm_inverse;
cairo_matrix_multiply (&m, ctm, &pdf_operators->cairo_to_pdf);
_cairo_output_stream_printf (pdf_operators->stream,
"q %f %f %f %f %f %f cm\r\n",
m.xx, m.yx, m.xy, m.yy,
m.x0, m.y0);
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_pdf_path_move_to,
_cairo_pdf_path_line_to,
_cairo_pdf_path_curve_to,
_cairo_pdf_path_close_path,
&info);
if (status)
return status;
_cairo_output_stream_printf (pdf_operators->stream, "S Q\r\n");
return _cairo_output_stream_get_status (pdf_operators->stream);
}
cairo_int_status_t
_cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule)
{
const char *pdf_operator;
cairo_status_t status;
pdf_path_info_t info;
info.output = pdf_operators->stream;
info.cairo_to_pdf = &pdf_operators->cairo_to_pdf;
info.ctm_inverse = NULL;
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_pdf_path_move_to,
_cairo_pdf_path_line_to,
_cairo_pdf_path_curve_to,
_cairo_pdf_path_close_path,
&info);
if (status)
return status;
switch (fill_rule) {
case CAIRO_FILL_RULE_WINDING:
pdf_operator = "f";
break;
case CAIRO_FILL_RULE_EVEN_ODD:
pdf_operator = "f*";
break;
default:
ASSERT_NOT_REACHED;
}
_cairo_output_stream_printf (pdf_operators->stream,
"%s\r\n",
pdf_operator);
return _cairo_output_stream_get_status (pdf_operators->stream);
}
#define GLYPH_POSITION_TOLERANCE 0.001
cairo_int_status_t
_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
unsigned int current_subset_id = (unsigned int)-1;
cairo_scaled_font_subsets_glyph_t subset_glyph;
cairo_bool_t diagonal, in_TJ;
cairo_status_t status;
double Tlm_x = 0, Tlm_y = 0;
double Tm_x = 0, y;
int i, hex_width;
for (i = 0; i < num_glyphs; i++)
cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &glyphs[i].x, &glyphs[i].y);
_cairo_output_stream_printf (pdf_operators->stream,
"BT\r\n");
if (scaled_font->scale.xy == 0.0 &&
scaled_font->scale.yx == 0.0)
diagonal = TRUE;
else
diagonal = FALSE;
in_TJ = FALSE;
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
scaled_font, glyphs[i].index,
&subset_glyph);
if (status)
return status;
if (subset_glyph.is_composite)
hex_width = 4;
else
hex_width = 2;
if (subset_glyph.is_scaled == FALSE) {
y = 0.0;
cairo_matrix_transform_distance (&scaled_font->scale,
&subset_glyph.x_advance,
&y);
}
if (subset_glyph.subset_id != current_subset_id) {
if (in_TJ) {
_cairo_output_stream_printf (pdf_operators->stream, ">] TJ\r\n");
in_TJ = FALSE;
}
_cairo_output_stream_printf (pdf_operators->stream,
"/f-%d-%d 1 Tf\r\n",
subset_glyph.font_id,
subset_glyph.subset_id);
if (pdf_operators->use_font_subset) {
status = pdf_operators->use_font_subset (subset_glyph.font_id,
subset_glyph.subset_id,
pdf_operators->use_font_subset_closure);
if (status)
return status;
}
}
if (subset_glyph.subset_id != current_subset_id || !diagonal) {
_cairo_output_stream_printf (pdf_operators->stream,
"%f %f %f %f %f %f Tm\r\n",
scaled_font->scale.xx,
-scaled_font->scale.yx,
-scaled_font->scale.xy,
scaled_font->scale.yy,
glyphs[i].x,
glyphs[i].y);
current_subset_id = subset_glyph.subset_id;
Tlm_x = glyphs[i].x;
Tlm_y = glyphs[i].y;
Tm_x = Tlm_x;
}
if (diagonal) {
if (i < num_glyphs - 1 &&
fabs((glyphs[i].y - glyphs[i+1].y)/scaled_font->scale.yy) < GLYPH_POSITION_TOLERANCE &&
fabs((glyphs[i].x - glyphs[i+1].x)/scaled_font->scale.xx) < 10)
{
if (!in_TJ) {
if (i != 0) {
_cairo_output_stream_printf (pdf_operators->stream,
"%f %f Td\r\n",
(glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
(glyphs[i].y - Tlm_y)/scaled_font->scale.yy);
Tlm_x = glyphs[i].x;
Tlm_y = glyphs[i].y;
Tm_x = Tlm_x;
}
_cairo_output_stream_printf (pdf_operators->stream,
"[<%0*x",
hex_width,
subset_glyph.subset_glyph_index);
Tm_x += subset_glyph.x_advance;
in_TJ = TRUE;
} else {
if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
double delta = glyphs[i].x - Tm_x;
_cairo_output_stream_printf (pdf_operators->stream,
"> %f <",
-1000.0*delta/scaled_font->scale.xx);
Tm_x += delta;
}
_cairo_output_stream_printf (pdf_operators->stream,
"%0*x",
hex_width,
subset_glyph.subset_glyph_index);
Tm_x += subset_glyph.x_advance;
}
}
else
{
if (in_TJ) {
if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
double delta = glyphs[i].x - Tm_x;
_cairo_output_stream_printf (pdf_operators->stream,
"> %f <",
-1000.0*delta/scaled_font->scale.xx);
Tm_x += delta;
}
_cairo_output_stream_printf (pdf_operators->stream,
"%0*x>] TJ\r\n",
hex_width,
subset_glyph.subset_glyph_index);
Tm_x += subset_glyph.x_advance;
in_TJ = FALSE;
} else {
if (i != 0) {
_cairo_output_stream_printf (pdf_operators->stream,
"%f %f Td ",
(glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
(glyphs[i].y - Tlm_y)/-scaled_font->scale.yy);
Tlm_x = glyphs[i].x;
Tlm_y = glyphs[i].y;
Tm_x = Tlm_x;
}
_cairo_output_stream_printf (pdf_operators->stream,
"<%0*x> Tj ",
hex_width,
subset_glyph.subset_glyph_index);
Tm_x += subset_glyph.x_advance;
}
}
} else {
_cairo_output_stream_printf (pdf_operators->stream,
"<%0*x> Tj\r\n",
hex_width,
subset_glyph.subset_glyph_index);
}
}
_cairo_output_stream_printf (pdf_operators->stream,
"ET\r\n");
return _cairo_output_stream_get_status (pdf_operators->stream);
}

View file

@ -1,8 +1,9 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 Red Hat, Inc
* Copyright © 2006 Red Hat, Inc
* Copyright © 2007 Adrian Johnson
* Copyright © 2007, 2008 Adrian Johnson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@ -44,6 +45,8 @@
#include "cairo-pdf.h"
#include "cairo-surface-private.h"
#include "cairo-pdf-operators-private.h"
#include "cairo-path-fixed-private.h"
typedef struct _cairo_pdf_resource {
unsigned int id;
@ -57,6 +60,37 @@ typedef struct _cairo_pdf_group_resources {
cairo_array_t fonts;
} cairo_pdf_group_resources_t;
typedef struct _cairo_pdf_pattern {
cairo_pattern_t *pattern;
cairo_pdf_resource_t pattern_res;
cairo_pdf_resource_t gstate_res;
} cairo_pdf_pattern_t;
typedef enum _cairo_pdf_operation {
PDF_PAINT,
PDF_MASK,
PDF_FILL,
PDF_STROKE,
PDF_SHOW_GLYPHS
} cairo_pdf_operation_t;
typedef struct _cairo_pdf_smask_group
{
cairo_pdf_resource_t group_res;
cairo_pdf_operation_t operation;
cairo_pattern_t *source;
cairo_pdf_resource_t source_res;
cairo_pattern_t *mask;
cairo_path_fixed_t path;
cairo_fill_rule_t fill_rule;
cairo_stroke_style_t *style;
cairo_matrix_t ctm;
cairo_matrix_t ctm_inverse;
cairo_glyph_t *glyphs;
int num_glyphs;
cairo_scaled_font_t *scaled_font;
} cairo_pdf_smask_group_t;
typedef struct _cairo_pdf_surface cairo_pdf_surface_t;
struct _cairo_pdf_surface {
@ -74,8 +108,9 @@ struct _cairo_pdf_surface {
cairo_array_t pages;
cairo_array_t rgb_linear_functions;
cairo_array_t alpha_linear_functions;
cairo_array_t patterns;
cairo_array_t smask_groups;
cairo_array_t knockout_group;
cairo_array_t content_group;
cairo_scaled_font_subsets_t *font_subsets;
cairo_array_t fonts;
@ -85,6 +120,11 @@ struct _cairo_pdf_surface {
cairo_bool_t compress_content;
cairo_pdf_resource_t content;
cairo_pdf_resource_t content_resources;
cairo_pdf_group_resources_t resources;
cairo_bool_t has_fallback_images;
struct {
cairo_bool_t active;
cairo_pdf_resource_t self;
@ -99,32 +139,11 @@ struct _cairo_pdf_surface {
cairo_output_stream_t *stream;
cairo_output_stream_t *mem_stream;
cairo_output_stream_t *old_output;
cairo_pdf_group_resources_t resources;
cairo_pdf_resource_t resource;
cairo_bool_t is_knockout;
cairo_pdf_resource_t first_object;
} group_stream;
struct {
cairo_bool_t active;
cairo_output_stream_t *stream;
cairo_output_stream_t *mem_stream;
cairo_output_stream_t *old_output;
cairo_pdf_group_resources_t resources;
} content_stream;
struct {
cairo_pattern_type_t type;
double red;
double green;
double blue;
double alpha;
cairo_pdf_resource_t smask;
cairo_pdf_resource_t pattern;
} emitted_pattern;
cairo_array_t *current_group;
cairo_pdf_group_resources_t *current_resources;
cairo_pdf_operators_t pdf_operators;
cairo_paginated_mode_t paginated_mode;
cairo_bool_t force_fallbacks;

File diff suppressed because it is too large Load diff

View file

@ -275,8 +275,14 @@ cairo_surface_write_to_png (cairo_surface_t *surface,
cairo_status_t status;
fp = fopen (filename, "wb");
if (fp == NULL)
return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
if (fp == NULL) {
switch (errno) {
case ENOMEM:
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
default:
return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
}
}
status = write_png (surface, stdio_write_func, fp);

View file

@ -78,6 +78,7 @@ typedef struct cairo_ps_surface {
cairo_array_t *dsc_comment_target;
cairo_ps_level_t ps_level;
cairo_ps_level_t ps_level_used;
cairo_surface_t *paginated_surface;
} cairo_ps_surface_t;

View file

@ -47,12 +47,18 @@
#include "cairo-meta-surface-private.h"
#include "cairo-output-stream-private.h"
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <zlib.h>
#include <errno.h>
#define DEBUG_PS 0
#ifndef HAVE_CTIME_R
#define ctime_r(T, BUF) ctime (T)
#endif
typedef enum _cairo_image_transparency {
CAIRO_IMAGE_IS_OPAQUE,
CAIRO_IMAGE_HAS_BILEVEL_ALPHA,
@ -318,18 +324,19 @@ _cairo_ps_surface_emit_path (cairo_ps_surface_t *surface,
static void
_cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
{
char ctime_buf[26];
time_t now;
char **comments;
int i, num_comments;
const char *level;
int level;
const char *eps_header = "";
now = time (NULL);
if (surface->ps_level == CAIRO_PS_LEVEL_2)
level = "2";
if (surface->ps_level_used == CAIRO_PS_LEVEL_2)
level = 2;
else
level = "3";
level = 3;
if (surface->eps)
eps_header = " EPSF-3.0";
@ -342,7 +349,7 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
"%%%%BoundingBox: %d %d %d %d\n",
eps_header,
cairo_version_string (),
ctime (&now),
ctime_r (&now, ctime_buf),
surface->num_pages,
surface->bbox_x1,
surface->bbox_y1,
@ -351,7 +358,7 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
_cairo_output_stream_printf (surface->final_stream,
"%%%%DocumentData: Clean7Bit\n"
"%%%%LanguageLevel: %s\n",
"%%%%LanguageLevel: %d\n",
level);
num_comments = _cairo_array_num_elements (&surface->dsc_header_comments);
@ -375,6 +382,14 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
"/dict_count countdictstack def\n"
"/op_count count 1 sub def\n"
"userdict begin\n");
} else {
_cairo_output_stream_printf (surface->final_stream,
"/languagelevel where{pop languagelevel}{1}ifelse %d lt{/Helvetica\n"
"findfont 12 scalefont setfont 50 500 moveto\n"
"(This print job requires a PostScript Language Level %d printer.)show\n"
"showpage quit}if\n",
level,
level);
}
_cairo_output_stream_printf (surface->final_stream,
@ -938,7 +953,14 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
surface->tmpfile = tmpfile ();
if (surface->tmpfile == NULL) {
status = _cairo_error (CAIRO_STATUS_TEMP_FILE_ERROR);
switch (errno) {
case ENOMEM:
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
break;
default:
status = _cairo_error (CAIRO_STATUS_TEMP_FILE_ERROR);
break;
}
goto CLEANUP_SURFACE;
}
@ -953,6 +975,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
surface->eps = FALSE;
surface->ps_level = CAIRO_PS_LEVEL_3;
surface->ps_level_used = CAIRO_PS_LEVEL_2;
surface->width = width;
surface->height = height;
surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
@ -1644,10 +1667,12 @@ _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t
break;
case CAIRO_IMAGE_HAS_BILEVEL_ALPHA:
if (surface->ps_level == CAIRO_PS_LEVEL_2)
if (surface->ps_level == CAIRO_PS_LEVEL_2) {
status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
else
} else {
surface->ps_level_used = CAIRO_PS_LEVEL_3;
status = CAIRO_STATUS_SUCCESS;
}
break;
case CAIRO_IMAGE_HAS_ALPHA:
@ -1710,6 +1735,7 @@ _gradient_pattern_supported (cairo_ps_surface_t *surface,
if (surface->ps_level == CAIRO_PS_LEVEL_2)
return FALSE;
surface->ps_level_used = CAIRO_PS_LEVEL_3;
extend = cairo_pattern_get_extend (pattern);
if (extend == CAIRO_EXTEND_REPEAT ||
@ -2607,6 +2633,9 @@ _cairo_ps_surface_emit_linear_pattern (cairo_ps_surface_t *surface,
cairo_status_t status;
cairo_matrix_t inverse = pattern->base.base.matrix;
if (pattern->base.n_stops == 0)
return CAIRO_INT_STATUS_NOTHING_TO_DO;
extend = cairo_pattern_get_extend (&pattern->base.base);
status = cairo_matrix_invert (&inverse);
@ -2662,6 +2691,9 @@ _cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t *surface,
cairo_status_t status;
cairo_matrix_t inverse = pattern->base.base.matrix;
if (pattern->base.n_stops == 0)
return CAIRO_INT_STATUS_NOTHING_TO_DO;
extend = cairo_pattern_get_extend (&pattern->base.base);
status = cairo_matrix_invert (&inverse);
@ -2859,6 +2891,9 @@ _cairo_ps_surface_paint (void *abstract_surface,
_cairo_rectangle_intersect (&extents, &pattern_extents);
status = _cairo_ps_surface_emit_pattern (surface, source, op);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
if (status)
return status;
@ -3002,6 +3037,9 @@ _cairo_ps_surface_stroke (void *abstract_surface,
}
status = _cairo_ps_surface_emit_pattern (surface, source, op);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
if (status) {
if (dash != style->dash)
free (dash);
@ -3082,6 +3120,9 @@ _cairo_ps_surface_fill (void *abstract_surface,
#endif
status = _cairo_ps_surface_emit_pattern (surface, source, op);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
if (status)
return status;
@ -3151,6 +3192,9 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
num_glyphs_unsigned = num_glyphs;
status = _cairo_ps_surface_emit_pattern (surface, source, op);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
if (status)
return status;

View file

@ -1051,7 +1051,7 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
image->height);
if (cairo_surface_status (snapshot)) {
_cairo_surface_release_source_image (surface,
image, &image_extra);
image, image_extra);
return snapshot;
}
@ -1069,7 +1069,7 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
_cairo_pattern_fini (&pattern.base);
_cairo_surface_release_source_image (surface,
image, &image_extra);
image, image_extra);
if (status) {
cairo_surface_destroy (snapshot);

View file

@ -86,7 +86,7 @@ DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error);
static cairo_status_t
_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
cairo_surface_t *destination,
cairo_pattern_t *pattern_out);
cairo_pattern_t **pattern_out);
/**
* _cairo_surface_set_error:
@ -1395,24 +1395,24 @@ _cairo_surface_paint (cairo_surface_t *surface,
cairo_pattern_t *source)
{
cairo_status_t status;
cairo_pattern_union_t dev_source;
cairo_pattern_t *dev_source;
assert (! surface->is_snapshot);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
if (status)
return _cairo_surface_set_error (surface, status);
if (surface->backend->paint) {
status = surface->backend->paint (surface, op, &dev_source.base);
status = surface->backend->paint (surface, op, dev_source);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
goto FINISH;
}
status = _cairo_surface_fallback_paint (surface, op, &dev_source.base);
status = _cairo_surface_fallback_paint (surface, op, dev_source);
FINISH:
_cairo_pattern_fini (&dev_source.base);
cairo_pattern_destroy (dev_source);
return _cairo_surface_set_error (surface, status);
}
@ -1424,31 +1424,31 @@ _cairo_surface_mask (cairo_surface_t *surface,
cairo_pattern_t *mask)
{
cairo_status_t status;
cairo_pattern_union_t dev_source;
cairo_pattern_union_t dev_mask;
cairo_pattern_t *dev_source;
cairo_pattern_t *dev_mask;
assert (! surface->is_snapshot);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
if (status)
goto FINISH;
status = _cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask.base);
status = _cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask);
if (status)
goto CLEANUP_SOURCE;
if (surface->backend->mask) {
status = surface->backend->mask (surface, op, &dev_source.base, &dev_mask.base);
status = surface->backend->mask (surface, op, dev_source, dev_mask);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
goto CLEANUP_MASK;
}
status = _cairo_surface_fallback_mask (surface, op, &dev_source.base, &dev_mask.base);
status = _cairo_surface_fallback_mask (surface, op, dev_source, dev_mask);
CLEANUP_MASK:
_cairo_pattern_fini (&dev_mask.base);
cairo_pattern_destroy (dev_mask);
CLEANUP_SOURCE:
_cairo_pattern_fini (&dev_source.base);
cairo_pattern_destroy (dev_source);
FINISH:
return _cairo_surface_set_error (surface, status);
@ -1473,29 +1473,29 @@ _cairo_surface_fill_stroke (cairo_surface_t *surface,
cairo_status_t status;
if (surface->backend->fill_stroke) {
cairo_pattern_union_t dev_stroke_source;
cairo_pattern_union_t dev_fill_source;
cairo_pattern_t *dev_stroke_source;
cairo_pattern_t *dev_fill_source;
cairo_matrix_t dev_ctm = *stroke_ctm;
cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse;
status = _cairo_surface_copy_pattern_for_destination (stroke_source, surface, &dev_stroke_source.base);
status = _cairo_surface_copy_pattern_for_destination (stroke_source, surface, &dev_stroke_source);
if (status)
return _cairo_surface_set_error (surface, status);
status = _cairo_surface_copy_pattern_for_destination (fill_source, surface, &dev_fill_source.base);
status = _cairo_surface_copy_pattern_for_destination (fill_source, surface, &dev_fill_source);
if (status) {
_cairo_pattern_fini (&dev_stroke_source.base);
cairo_pattern_destroy (dev_stroke_source);
return _cairo_surface_set_error (surface, status);
}
status = surface->backend->fill_stroke (surface, fill_op, &dev_fill_source.base,
status = surface->backend->fill_stroke (surface, fill_op, dev_fill_source,
fill_rule, fill_tolerance, fill_antialias,
path, stroke_op, &dev_stroke_source.base, stroke_style,
path, stroke_op, dev_stroke_source, stroke_style,
&dev_ctm, &dev_ctm_inverse, stroke_tolerance,
stroke_antialias);
_cairo_pattern_fini (&dev_stroke_source.base);
_cairo_pattern_fini (&dev_fill_source.base);
cairo_pattern_destroy (dev_stroke_source);
cairo_pattern_destroy (dev_fill_source);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return _cairo_surface_set_error (surface, status);
@ -1527,7 +1527,7 @@ _cairo_surface_stroke (cairo_surface_t *surface,
cairo_antialias_t antialias)
{
cairo_status_t status;
cairo_pattern_union_t dev_source;
cairo_pattern_t *dev_source;
cairo_path_fixed_t *dev_path = path;
cairo_path_fixed_t real_dev_path;
cairo_matrix_t dev_ctm = *ctm;
@ -1535,12 +1535,12 @@ _cairo_surface_stroke (cairo_surface_t *surface,
assert (! surface->is_snapshot);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
if (status)
return _cairo_surface_set_error (surface, status);
if (surface->backend->stroke) {
status = surface->backend->stroke (surface, op, &dev_source.base,
status = surface->backend->stroke (surface, op, dev_source,
path, stroke_style,
&dev_ctm, &dev_ctm_inverse,
tolerance, antialias);
@ -1549,7 +1549,7 @@ _cairo_surface_stroke (cairo_surface_t *surface,
goto FINISH;
}
status = _cairo_surface_fallback_stroke (surface, op, &dev_source.base,
status = _cairo_surface_fallback_stroke (surface, op, dev_source,
path, stroke_style,
&dev_ctm, &dev_ctm_inverse,
tolerance, antialias);
@ -1557,7 +1557,7 @@ _cairo_surface_stroke (cairo_surface_t *surface,
FINISH:
if (dev_path == &real_dev_path)
_cairo_path_fixed_fini (&real_dev_path);
_cairo_pattern_fini (&dev_source.base);
cairo_pattern_destroy (dev_source);
return _cairo_surface_set_error (surface, status);
}
@ -1572,16 +1572,16 @@ _cairo_surface_fill (cairo_surface_t *surface,
cairo_antialias_t antialias)
{
cairo_status_t status;
cairo_pattern_union_t dev_source;
cairo_pattern_t *dev_source;
assert (! surface->is_snapshot);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
if (status)
return _cairo_surface_set_error (surface, status);
if (surface->backend->fill) {
status = surface->backend->fill (surface, op, &dev_source.base,
status = surface->backend->fill (surface, op, dev_source,
path, fill_rule,
tolerance, antialias);
@ -1589,12 +1589,12 @@ _cairo_surface_fill (cairo_surface_t *surface,
goto FINISH;
}
status = _cairo_surface_fallback_fill (surface, op, &dev_source.base,
status = _cairo_surface_fallback_fill (surface, op, dev_source,
path, fill_rule,
tolerance, antialias);
FINISH:
_cairo_pattern_fini (&dev_source.base);
cairo_pattern_destroy (dev_source);
return _cairo_surface_set_error (surface, status);
}
@ -2045,7 +2045,7 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
{
cairo_status_t status;
cairo_scaled_font_t *dev_scaled_font = scaled_font;
cairo_pattern_union_t dev_source;
cairo_pattern_t *dev_source;
cairo_matrix_t font_matrix;
assert (! surface->is_snapshot);
@ -2055,7 +2055,7 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
status = _cairo_surface_copy_pattern_for_destination (source,
surface,
&dev_source.base);
&dev_source);
if (status)
return _cairo_surface_set_error (surface, status);
@ -2080,7 +2080,7 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
}
status = cairo_scaled_font_status (dev_scaled_font);
if (status) {
_cairo_pattern_fini (&dev_source.base);
cairo_pattern_destroy (dev_source);
return _cairo_surface_set_error (surface, status);
}
@ -2089,12 +2089,12 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
status = CAIRO_INT_STATUS_UNSUPPORTED;
if (surface->backend->show_glyphs)
status = surface->backend->show_glyphs (surface, op, &dev_source.base,
status = surface->backend->show_glyphs (surface, op, dev_source,
glyphs, num_glyphs,
dev_scaled_font);
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
status = _cairo_surface_fallback_show_glyphs (surface, op, &dev_source.base,
status = _cairo_surface_fallback_show_glyphs (surface, op, dev_source,
glyphs, num_glyphs,
dev_scaled_font);
@ -2103,7 +2103,7 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
if (dev_scaled_font != scaled_font)
cairo_scaled_font_destroy (dev_scaled_font);
_cairo_pattern_fini (&dev_source.base);
cairo_pattern_destroy (dev_source);
return _cairo_surface_set_error (surface, status);
}
@ -2370,11 +2370,11 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
static cairo_status_t
_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
cairo_surface_t *destination,
cairo_pattern_t *pattern_out)
cairo_pattern_t **pattern_out)
{
cairo_status_t status;
status = _cairo_pattern_init_copy (pattern_out, pattern);
status = _cairo_pattern_create_copy (pattern_out, pattern);
if (status)
return status;
@ -2387,7 +2387,7 @@ _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
* matrix should always be invertible. */
assert (status == CAIRO_STATUS_SUCCESS);
_cairo_pattern_transform (pattern_out, &device_to_surface);
_cairo_pattern_transform (*pattern_out, &device_to_surface);
}
return CAIRO_STATUS_SUCCESS;

View file

@ -568,7 +568,11 @@ _cairo_traps_contain (cairo_traps_t *traps, double x, double y)
void
_cairo_traps_extents (cairo_traps_t *traps, cairo_box_t *extents)
{
*extents = traps->extents;
if (traps->num_traps == 0) {
extents->p1.x = extents->p1.y = _cairo_fixed_from_int (0);
extents->p2.x = extents->p2.y = _cairo_fixed_from_int (0);
} else
*extents = traps->extents;
}
/**

View file

@ -147,18 +147,20 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
font->base.y_max = face->bbox.yMax;
font->base.ascent = face->ascender;
font->base.descent = face->descender;
font->base.base_font = strdup (face->family_name);
if (font->base.base_font == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
}
for (i = 0, j = 0; font->base.base_font[j]; j++) {
if (font->base.base_font[j] == ' ')
continue;
font->base.base_font[i++] = font->base.base_font[j];
if (face->family_name) {
font->base.base_font = strdup (face->family_name);
if (font->base.base_font == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
}
for (i = 0, j = 0; font->base.base_font[j]; j++) {
if (font->base.base_font[j] == ' ')
continue;
font->base.base_font[i++] = font->base.base_font[j];
}
font->base.base_font[i] = '\0';
}
font->base.base_font[i] = '\0';
font->glyphs = calloc (face->num_glyphs, sizeof font->glyphs[0]);
if (font->glyphs == NULL) {
@ -180,7 +182,8 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
return CAIRO_STATUS_SUCCESS;
fail3:
free (font->base.base_font);
if (font->base.base_font)
free (font->base.base_font);
fail2:
_cairo_unscaled_font_destroy (unscaled_font);
free (font);
@ -1158,7 +1161,8 @@ cairo_type1_font_subset_destroy (void *abstract_font)
_cairo_unscaled_font_destroy (font->base.unscaled_font);
free (font->base.base_font);
if (font->base.base_font)
free (font->base.base_font);
free (font->glyphs);
free (font);
}
@ -1175,6 +1179,7 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
unsigned long parent_glyph, length;
unsigned int i;
cairo_unscaled_font_t *unscaled_font;
char buf[30];
/* XXX: Need to fix this to work with a general cairo_unscaled_font_t. */
if (!_cairo_scaled_font_is_ft (scaled_font_subset->scaled_font))
@ -1198,7 +1203,13 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
if (status)
goto fail1;
type1_subset->base_font = strdup (font->base.base_font);
if (font->base.base_font) {
type1_subset->base_font = strdup (font->base.base_font);
} else {
snprintf(buf, sizeof (buf), "CairoFont-%u-%u",
scaled_font_subset->font_id, scaled_font_subset->subset_id);
type1_subset->base_font = strdup (buf);
}
if (type1_subset->base_font == NULL)
goto fail1;

View file

@ -41,6 +41,7 @@
/* This is the only header file not including cairoint.h. It only contains
* typedefs.*/
#include "cairo.h"
#include "cairo-fixed-private.h"
typedef struct _cairo_array cairo_array_t;
typedef struct _cairo_hash_table cairo_hash_table_t;
@ -123,7 +124,8 @@ struct _cairo_cache {
typedef enum _cairo_paginated_mode {
CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */
CAIRO_PAGINATED_MODE_RENDER /* render page contents */
CAIRO_PAGINATED_MODE_RENDER, /* render page contents */
CAIRO_PAGINATED_MODE_FALLBACK /* paint fallback images */
} cairo_paginated_mode_t;
/* Sure wish C had a real enum type so that this would be distinct
@ -148,4 +150,172 @@ typedef enum _cairo_internal_surface_type {
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
} cairo_internal_surface_type_t;
typedef struct _cairo_region cairo_region_t;
typedef struct _cairo_point {
cairo_fixed_t x;
cairo_fixed_t y;
} cairo_point_t;
typedef struct _cairo_slope
{
cairo_fixed_t dx;
cairo_fixed_t dy;
} cairo_slope_t, cairo_distance_t;
typedef struct _cairo_point_double {
double x;
double y;
} cairo_point_double_t;
typedef struct _cairo_distance_double {
double dx;
double dy;
} cairo_distance_double_t;
typedef struct _cairo_line {
cairo_point_t p1;
cairo_point_t p2;
} cairo_line_t, cairo_box_t;
typedef struct _cairo_trapezoid {
cairo_fixed_t top, bottom;
cairo_line_t left, right;
} cairo_trapezoid_t;
typedef struct _cairo_rectangle_int16 {
int16_t x, y;
uint16_t width, height;
} cairo_rectangle_int16_t, cairo_glyph_size_t;
typedef struct _cairo_rectangle_int32 {
int32_t x, y;
uint32_t width, height;
} cairo_rectangle_int32_t;
typedef struct _cairo_point_int16 {
int16_t x, y;
} cairo_point_int16_t;
typedef struct _cairo_point_int32 {
int16_t x, y;
} cairo_point_int32_t;
typedef struct _cairo_box_int16 {
cairo_point_int16_t p1;
cairo_point_int16_t p2;
} cairo_box_int16_t;
typedef struct _cairo_box_int32 {
cairo_point_int32_t p1;
cairo_point_int32_t p2;
} cairo_box_int32_t;
#if CAIRO_FIXED_BITS == 32 && CAIRO_FIXED_FRAC_BITS >= 16
typedef cairo_rectangle_int16_t cairo_rectangle_int_t;
typedef cairo_point_int16_t cairo_point_int_t;
typedef cairo_box_int16_t cairo_box_int_t;
#define CAIRO_RECT_INT_MIN INT16_MIN
#define CAIRO_RECT_INT_MAX INT16_MAX
#elif CAIRO_FIXED_BITS == 32
typedef cairo_rectangle_int32_t cairo_rectangle_int_t;
typedef cairo_point_int32_t cairo_point_int_t;
typedef cairo_box_int32_t cairo_box_int_t;
#define CAIRO_RECT_INT_MIN INT32_MIN
#define CAIRO_RECT_INT_MAX INT32_MAX
#else
#error Not sure how to pick a cairo_rectangle_int_t for your CAIRO_FIXED_BITS!
#endif
typedef enum _cairo_direction {
CAIRO_DIRECTION_FORWARD,
CAIRO_DIRECTION_REVERSE
} cairo_direction_t;
typedef struct _cairo_path_fixed cairo_path_fixed_t;
typedef enum _cairo_clip_mode {
CAIRO_CLIP_MODE_PATH,
CAIRO_CLIP_MODE_REGION,
CAIRO_CLIP_MODE_MASK
} cairo_clip_mode_t;
typedef struct _cairo_clip_path cairo_clip_path_t;
typedef struct _cairo_edge {
cairo_line_t edge;
int clockWise;
cairo_fixed_t current_x;
} cairo_edge_t;
typedef struct _cairo_polygon {
cairo_status_t status;
cairo_point_t first_point;
cairo_point_t current_point;
cairo_bool_t has_current_point;
int num_edges;
int edges_size;
cairo_edge_t *edges;
cairo_edge_t edges_embedded[8];
} cairo_polygon_t;
typedef struct _cairo_spline_knots {
cairo_point_t a, b, c, d;
} cairo_spline_knots_t;
typedef struct _cairo_spline {
cairo_spline_knots_t knots;
cairo_slope_t initial_slope;
cairo_slope_t final_slope;
int num_points;
int points_size;
cairo_point_t *points;
cairo_point_t points_embedded[8];
} cairo_spline_t;
typedef struct _cairo_pen_vertex {
cairo_point_t point;
cairo_slope_t slope_ccw;
cairo_slope_t slope_cw;
} cairo_pen_vertex_t;
typedef struct _cairo_pen {
double radius;
double tolerance;
cairo_pen_vertex_t *vertices;
int num_vertices;
} cairo_pen_t;
typedef struct _cairo_color cairo_color_t;
typedef struct _cairo_image_surface cairo_image_surface_t;
typedef struct _cairo_stroke_style {
double line_width;
cairo_line_cap_t line_cap;
cairo_line_join_t line_join;
double miter_limit;
double *dash;
unsigned int num_dashes;
double dash_offset;
} cairo_stroke_style_t;
typedef struct _cairo_format_masks {
int bpp;
unsigned long alpha_mask;
unsigned long red_mask;
unsigned long green_mask;
unsigned long blue_mask;
} cairo_format_masks_t;
typedef enum {
CAIRO_STOCK_WHITE,
CAIRO_STOCK_BLACK,
CAIRO_STOCK_TRANSPARENT
} cairo_stock_t;
#endif /* CAIRO_TYPES_PRIVATE_H */

View file

@ -33,6 +33,15 @@
* Contributor(s):
*/
#define WIN32_LEAN_AND_MEAN
/* We require Windows 2000 features such as GetGlyphIndices */
#if !defined(WINVER) || (WINVER < 0x0500)
# define WINVER 0x0500
#endif
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
# define _WIN32_WINNT 0x0500
#endif
#include "cairoint.h"
#include "cairo-win32-private.h"
@ -50,7 +59,7 @@
#define TT_PRIM_CSPLINE 3
#endif
#define OPENTYPE_CFF_TAG 0x20464643
#define CMAP_TAG 0x70616d63
const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend;
@ -99,10 +108,8 @@ typedef struct {
HFONT scaled_hfont;
HFONT unscaled_hfont;
cairo_bool_t is_truetype;
cairo_bool_t glyph_indexing;
cairo_bool_t is_bitmap;
cairo_bool_t is_type1;
cairo_bool_t delete_scaled_hfont;
} cairo_win32_scaled_font_t;
@ -570,6 +577,92 @@ _cairo_win32_scaled_font_fini (void *abstract_font)
DeleteObject (scaled_font->unscaled_hfont);
}
static cairo_int_status_t
_cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled_font,
double x,
double y,
const char *utf8,
cairo_glyph_t **glyphs,
int *num_glyphs)
{
uint16_t *utf16;
int n16;
int i;
WORD *glyph_indices = NULL;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
double x_pos, y_pos;
HDC hdc = NULL;
cairo_matrix_t mat;
status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16);
if (status)
return status;
glyph_indices = _cairo_malloc_ab (n16 + 1, sizeof (WORD));
if (!glyph_indices) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto FAIL1;
}
hdc = _get_global_font_dc ();
if (!hdc) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto FAIL2;
}
status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
if (status)
goto FAIL2;
if (GetGlyphIndicesW (hdc, utf16, n16, glyph_indices, 0) == GDI_ERROR) {
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_type1_text_to_glyphs:GetGlyphIndicesW");
goto FAIL2;
}
*num_glyphs = n16;
*glyphs = _cairo_malloc_ab (n16, sizeof (cairo_glyph_t));
if (!*glyphs) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto FAIL2;
}
x_pos = x;
y_pos = y;
mat = scaled_font->base.ctm;
cairo_matrix_invert (&mat);
for (i = 0; i < n16; i++) {
cairo_scaled_glyph_t *scaled_glyph;
(*glyphs)[i].index = glyph_indices[i];
(*glyphs)[i].x = x_pos;
(*glyphs)[i].y = y_pos;
status = _cairo_scaled_glyph_lookup (&scaled_font->base,
glyph_indices[i],
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
if (status) {
free (*glyphs);
goto FAIL2;
}
x = scaled_glyph->x_advance;
y = scaled_glyph->y_advance;
cairo_matrix_transform_distance (&mat, &x, &y);
x_pos += x;
y_pos += y;
}
cairo_win32_scaled_font_done_font (&scaled_font->base);
FAIL2:
free (glyph_indices);
FAIL1:
free (utf16);
return status;
}
static cairo_int_status_t
_cairo_win32_scaled_font_text_to_glyphs (void *abstract_font,
double x,
@ -590,6 +683,16 @@ _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font,
double x_incr, y_incr;
HDC hdc = NULL;
/* GetCharacterPlacement() returns utf16 instead of glyph indices
* for Type 1 fonts. Use GetGlyphIndices for Type 1 fonts. */
if (scaled_font->is_type1)
return _cairo_win32_scaled_font_type1_text_to_glyphs (scaled_font,
x,
y,
utf8,
glyphs,
num_glyphs);
/* Compute a vector in user space along the baseline of length one logical space unit */
x_incr = 1;
y_incr = 0;
@ -747,16 +850,27 @@ _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font)
}
if (metrics.tmPitchAndFamily & TMPF_VECTOR)
scaled_font->is_bitmap = FALSE;
else
scaled_font->is_bitmap = TRUE;
scaled_font->is_bitmap = !(metrics.tmPitchAndFamily & TMPF_VECTOR);
scaled_font->is_truetype = (metrics.tmPitchAndFamily & TMPF_TRUETYPE) != 0;
scaled_font->glyph_indexing = scaled_font->is_truetype ||
(GetFontData (hdc, OPENTYPE_CFF_TAG, 0, NULL, 0) != GDI_ERROR);
// XXX in what situations does this OPENTYPE_CFF thing not have the
// TMPF_TRUETYPE flag? GetFontData says it only works on Truetype fonts...
/* Need to determine if this is a Type 1 font for the special
* handling in _text_to_glyphs. Unlike TrueType or OpenType,
* Type1 fonts do not have a "cmap" table (or any other table).
* However GetFontData() will retrieve a Type1 font when
* requesting that GetFontData() retrieve data from the start of
* the file. This is to distinguish Type1 from stroke fonts such
* as "Script" and "Modern". The TMPF_TRUETYPE test is redundant
* but improves performance for the most common fonts.
*/
scaled_font->is_type1 = FALSE;
if (!(metrics.tmPitchAndFamily & TMPF_TRUETYPE) &&
(metrics.tmPitchAndFamily & TMPF_VECTOR))
{
if ((GetFontData (hdc, CMAP_TAG, 0, NULL, 0) == GDI_ERROR) &&
(GetFontData (hdc, 0, 0, NULL, 0) != GDI_ERROR))
{
scaled_font->is_type1 = TRUE;
}
}
_cairo_scaled_font_set_metrics (&scaled_font->base, &extents);
@ -777,7 +891,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f
if (!hdc)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
if (!scaled_font->is_truetype) {
if (scaled_font->is_bitmap) {
/* GetGlyphOutline will not work. Assume that the glyph does not extend outside the font box. */
cairo_font_extents_t font_extents;
INT width = 0;
@ -890,7 +1004,6 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font,
GLYPHMETRICS metrics;
cairo_status_t status;
int i;
UINT glyph_index_option;
if (!hdc)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@ -899,16 +1012,11 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font,
if (status)
return status;
if (scaled_font->glyph_indexing)
glyph_index_option = GGO_GLYPH_INDEX;
else
glyph_index_option = 0;
for (i = 0; i < num_glyphs; i++) {
int x = _cairo_lround (glyphs[i].x);
int y = _cairo_lround (glyphs[i].y);
GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | glyph_index_option,
GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | GGO_GLYPH_INDEX,
&metrics, 0, NULL, &matrix);
if (i == 0 || x1 > x + metrics.gmptGlyphOrigin.x)
@ -964,22 +1072,16 @@ _flush_glyphs (cairo_glyph_state_t *state)
int dx = 0;
WCHAR * elements;
int * dx_elements;
UINT glyph_index_option;
status = _cairo_array_append (&state->dx, &dx);
if (status)
return status;
if (state->scaled_font->glyph_indexing)
glyph_index_option = ETO_GLYPH_INDEX;
else
glyph_index_option = 0;
elements = _cairo_array_index (&state->glyphs, 0);
dx_elements = _cairo_array_index (&state->dx, 0);
if (!ExtTextOutW (state->hdc,
state->start_x, state->last_y,
glyph_index_option,
ETO_GLYPH_INDEX,
NULL,
elements,
state->glyphs.num_elements,
@ -1330,18 +1432,97 @@ _cairo_win32_scaled_font_load_truetype_table (void *abstract_font,
static cairo_int_status_t
_cairo_win32_scaled_font_map_glyphs_to_unicode (void *abstract_font,
cairo_scaled_font_subset_t *font_subset)
cairo_scaled_font_subset_t *font_subset)
{
cairo_win32_scaled_font_t *scaled_font = abstract_font;
unsigned int i;
GLYPHSET *glyph_set;
uint16_t *utf16 = NULL;
WORD *glyph_indices = NULL;
HDC hdc = NULL;
int res;
unsigned int i, j, k, count, num_glyphs;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
if (scaled_font->glyph_indexing)
return CAIRO_STATUS_SUCCESS; /* XXX ? */
hdc = _get_global_font_dc ();
if (!hdc)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
for (i = 0; i < font_subset->num_glyphs; i++)
font_subset->to_unicode[i] = font_subset->glyphs[i];
status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
res = GetFontUnicodeRanges(hdc, NULL);
if (res == 0) {
status = _cairo_win32_print_gdi_error (
"_cairo_win32_scaled_font_map_glyphs_to_unicode:GetFontUnicodeRanges");
goto fail1;
}
glyph_set = malloc (res);
if (glyph_set == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail1;
}
res = GetFontUnicodeRanges(hdc, glyph_set);
if (res == 0) {
status = _cairo_win32_print_gdi_error (
"_cairo_win32_scaled_font_map_glyphs_to_unicode:GetFontUnicodeRanges");
goto fail2;
}
count = font_subset->num_glyphs;
for (i = 0; i < glyph_set->cRanges && count > 0; i++) {
num_glyphs = glyph_set->ranges[i].cGlyphs;
utf16 = _cairo_malloc_ab (num_glyphs + 1, sizeof (uint16_t));
if (utf16 == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
}
glyph_indices = _cairo_malloc_ab (num_glyphs + 1, sizeof (WORD));
if (glyph_indices == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
}
for (j = 0; j < num_glyphs; j++)
utf16[j] = glyph_set->ranges[i].wcLow + j;
utf16[j] = 0;
if (GetGlyphIndicesW (hdc, utf16, num_glyphs, glyph_indices, 0) == GDI_ERROR) {
status = _cairo_win32_print_gdi_error (
"_cairo_win32_scaled_font_map_glyphs_to_unicode:GetGlyphIndicesW");
goto fail2;
}
for (j = 0; j < num_glyphs; j++) {
for (k = 0; k < font_subset->num_glyphs; k++) {
if (font_subset->glyphs[k] == glyph_indices[j]) {
font_subset->to_unicode[k] = utf16[j];
count--;
break;
}
}
}
free (glyph_indices);
glyph_indices = NULL;
free (utf16);
utf16= NULL;
}
fail2:
if (glyph_indices)
free (glyph_indices);
if (utf16)
free (utf16);
free (glyph_set);
fail1:
cairo_win32_scaled_font_done_font (&scaled_font->base);
return status;
}
static cairo_status_t
@ -1413,7 +1594,6 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
cairo_path_fixed_t *path;
cairo_matrix_t transform;
cairo_fixed_t x, y;
UINT glyph_index_option;
if (scaled_font->is_bitmap)
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -1437,13 +1617,8 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
if (status)
goto CLEANUP_PATH;
if (scaled_font->glyph_indexing)
glyph_index_option = GGO_GLYPH_INDEX;
else
glyph_index_option = 0;
bytesGlyph = GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
GGO_NATIVE | glyph_index_option,
GGO_NATIVE | GGO_GLYPH_INDEX,
&metrics, 0, NULL, &matrix);
if (bytesGlyph == GDI_ERROR) {
@ -1459,7 +1634,7 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
}
if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
GGO_NATIVE | glyph_index_option,
GGO_NATIVE | GGO_GLYPH_INDEX,
&metrics, bytesGlyph, buffer, &matrix) == GDI_ERROR) {
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
goto CLEANUP_BUFFER;

View file

@ -874,6 +874,7 @@ _cairo_win32_printing_surface_path_line_to (void *closure, cairo_point_t *point)
{
win32_path_info_t *path_info = closure;
path_info->surface->path_empty = FALSE;
if (path_info->surface->has_ctm) {
double x, y;
@ -899,6 +900,7 @@ _cairo_win32_printing_surface_path_curve_to (void *closure,
win32_path_info_t *path_info = closure;
POINT points[3];
path_info->surface->path_empty = FALSE;
if (path_info->surface->has_ctm) {
double x, y;
@ -1244,6 +1246,7 @@ _cairo_win32_printing_surface_fill (void *abstract_surface,
assert (_cairo_win32_printing_surface_operation_supported (surface, op, source));
surface->path_empty = TRUE;
BeginPath (surface->dc);
status = _cairo_win32_printing_surface_emit_path (surface, path);
EndPath (surface->dc);
@ -1266,7 +1269,7 @@ _cairo_win32_printing_surface_fill (void *abstract_surface,
FillPath (surface->dc);
_cairo_win32_printing_surface_done_solid_brush (surface);
} else {
} else if (surface->path_empty == FALSE) {
SaveDC (surface->dc);
SelectClipPath (surface->dc, RGN_AND);
status = _cairo_win32_printing_surface_paint_pattern (surface, source);
@ -1358,6 +1361,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
old_ctm = surface->ctm;
old_has_ctm = surface->has_ctm;
surface->has_ctm = TRUE;
surface->path_empty = TRUE;
BeginPath (surface->dc);
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_glyph_lookup (scaled_font,
@ -1373,9 +1377,19 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
EndPath (surface->dc);
surface->ctm = old_ctm;
surface->has_ctm = old_has_ctm;
if (status == CAIRO_STATUS_SUCCESS) {
SelectClipPath (surface->dc, RGN_AND);
status = _cairo_win32_printing_surface_paint_pattern (surface, source);
if (status == CAIRO_STATUS_SUCCESS && surface->path_empty == FALSE) {
if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
status = _cairo_win32_printing_surface_select_solid_brush (surface, source);
if (status)
return status;
SetPolyFillMode (surface->dc, WINDING);
FillPath (surface->dc);
_cairo_win32_printing_surface_done_solid_brush (surface);
} else {
SelectClipPath (surface->dc, RGN_AND);
status = _cairo_win32_printing_surface_paint_pattern (surface, source);
}
}
RestoreDC (surface->dc, -1);

View file

@ -83,6 +83,7 @@ typedef struct _cairo_win32_surface {
/* printing surface bits */
cairo_paginated_mode_t paginated_mode;
cairo_content_t content;
cairo_bool_t path_empty;
cairo_bool_t has_ctm;
cairo_matrix_t ctm;
int clip_saved_dc;

View file

@ -91,7 +91,7 @@ _cairo_win32_print_gdi_error (const char *context)
NULL,
last_error,
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
(LPSTR) &lpMsgBuf,
0, NULL)) {
fprintf (stderr, "%s: Unknown GDI error", context);
} else {
@ -745,7 +745,7 @@ _composite_alpha_blend (cairo_win32_surface_t *dst,
if (VER_PLATFORM_WIN32_WINDOWS != os.dwPlatformId ||
os.dwMajorVersion != 4 || os.dwMinorVersion != 10)
{
HMODULE msimg32_dll = LoadLibrary ("msimg32");
HMODULE msimg32_dll = LoadLibraryA ("msimg32");
if (msimg32_dll != NULL)
alpha_blend = (cairo_alpha_blend_func_t)GetProcAddress (msimg32_dll,

View file

@ -178,152 +178,8 @@ be32_to_cpu(uint32_t v)
#include "cairo-types-private.h"
#include "cairo-cache-private.h"
#include "cairo-fixed-private.h"
#include "cairo-reference-count-private.h"
typedef struct _cairo_region cairo_region_t;
typedef struct _cairo_point {
cairo_fixed_t x;
cairo_fixed_t y;
} cairo_point_t;
typedef struct _cairo_slope
{
cairo_fixed_t dx;
cairo_fixed_t dy;
} cairo_slope_t, cairo_distance_t;
typedef struct _cairo_point_double {
double x;
double y;
} cairo_point_double_t;
typedef struct _cairo_distance_double {
double dx;
double dy;
} cairo_distance_double_t;
typedef struct _cairo_line {
cairo_point_t p1;
cairo_point_t p2;
} cairo_line_t, cairo_box_t;
typedef struct _cairo_trapezoid {
cairo_fixed_t top, bottom;
cairo_line_t left, right;
} cairo_trapezoid_t;
typedef struct _cairo_rectangle_int16 {
int16_t x, y;
uint16_t width, height;
} cairo_rectangle_int16_t, cairo_glyph_size_t;
typedef struct _cairo_rectangle_int32 {
int32_t x, y;
uint32_t width, height;
} cairo_rectangle_int32_t;
typedef struct _cairo_point_int16 {
int16_t x, y;
} cairo_point_int16_t;
typedef struct _cairo_point_int32 {
int16_t x, y;
} cairo_point_int32_t;
typedef struct _cairo_box_int16 {
cairo_point_int16_t p1;
cairo_point_int16_t p2;
} cairo_box_int16_t;
typedef struct _cairo_box_int32 {
cairo_point_int32_t p1;
cairo_point_int32_t p2;
} cairo_box_int32_t;
#if CAIRO_FIXED_BITS == 32 && CAIRO_FIXED_FRAC_BITS >= 16
typedef cairo_rectangle_int16_t cairo_rectangle_int_t;
typedef cairo_point_int16_t cairo_point_int_t;
typedef cairo_box_int16_t cairo_box_int_t;
#define CAIRO_RECT_INT_MIN INT16_MIN
#define CAIRO_RECT_INT_MAX INT16_MAX
#elif CAIRO_FIXED_BITS == 32
typedef cairo_rectangle_int32_t cairo_rectangle_int_t;
typedef cairo_point_int32_t cairo_point_int_t;
typedef cairo_box_int32_t cairo_box_int_t;
#define CAIRO_RECT_INT_MIN INT32_MIN
#define CAIRO_RECT_INT_MAX INT32_MAX
#else
#error Not sure how to pick a cairo_rectangle_int_t for your CAIRO_FIXED_BITS!
#endif
typedef enum _cairo_direction {
CAIRO_DIRECTION_FORWARD,
CAIRO_DIRECTION_REVERSE
} cairo_direction_t;
typedef struct _cairo_path_fixed cairo_path_fixed_t;
typedef enum _cairo_clip_mode {
CAIRO_CLIP_MODE_PATH,
CAIRO_CLIP_MODE_REGION,
CAIRO_CLIP_MODE_MASK
} cairo_clip_mode_t;
typedef struct _cairo_clip_path cairo_clip_path_t;
typedef struct _cairo_edge {
cairo_line_t edge;
int clockWise;
cairo_fixed_t current_x;
} cairo_edge_t;
typedef struct _cairo_polygon {
cairo_status_t status;
cairo_point_t first_point;
cairo_point_t current_point;
cairo_bool_t has_current_point;
int num_edges;
int edges_size;
cairo_edge_t *edges;
cairo_edge_t edges_embedded[8];
} cairo_polygon_t;
typedef struct _cairo_spline_knots {
cairo_point_t a, b, c, d;
} cairo_spline_knots_t;
typedef struct _cairo_spline {
cairo_spline_knots_t knots;
cairo_slope_t initial_slope;
cairo_slope_t final_slope;
int num_points;
int points_size;
cairo_point_t *points;
cairo_point_t points_embedded[8];
} cairo_spline_t;
typedef struct _cairo_pen_vertex {
cairo_point_t point;
cairo_slope_t slope_ccw;
cairo_slope_t slope_cw;
} cairo_pen_vertex_t;
typedef struct _cairo_pen {
double radius;
double tolerance;
cairo_pen_vertex_t *vertices;
int num_vertices;
} cairo_pen_t;
typedef struct _cairo_color cairo_color_t;
typedef struct _cairo_image_surface cairo_image_surface_t;
cairo_private void
_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_int_t *rectangle);
@ -571,16 +427,6 @@ extern const cairo_private struct _cairo_scaled_font_backend cairo_atsui_scaled_
#endif
typedef struct _cairo_stroke_style {
double line_width;
cairo_line_cap_t line_cap;
cairo_line_join_t line_join;
double miter_limit;
double *dash;
unsigned int num_dashes;
double dash_offset;
} cairo_stroke_style_t;
struct _cairo_surface_backend {
cairo_surface_type_t type;
@ -841,14 +687,6 @@ struct _cairo_surface_backend {
cairo_antialias_t stroke_antialias);
};
typedef struct _cairo_format_masks {
int bpp;
unsigned long alpha_mask;
unsigned long red_mask;
unsigned long green_mask;
unsigned long blue_mask;
} cairo_format_masks_t;
#include "cairo-surface-private.h"
struct _cairo_image_surface {
@ -888,12 +726,6 @@ struct _cairo_color {
unsigned short alpha_short;
};
typedef enum {
CAIRO_STOCK_WHITE,
CAIRO_STOCK_BLACK,
CAIRO_STOCK_TRANSPARENT
} cairo_stock_t;
#define CAIRO_EXTEND_SURFACE_DEFAULT CAIRO_EXTEND_NONE
#define CAIRO_EXTEND_GRADIENT_DEFAULT CAIRO_EXTEND_PAD
#define CAIRO_FILTER_DEFAULT CAIRO_FILTER_BEST
@ -1015,6 +847,11 @@ typedef struct _cairo_traps {
#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_FT_FONT_FAMILY_DEFAULT
#define CAIRO_SCALED_FONT_BACKEND_DEFAULT &cairo_ft_scaled_font_backend
#else
/* Paranoia: this should have been caught by configure. */
#error No font backends are available.
#endif
#define CAIRO_GSTATE_OPERATOR_DEFAULT CAIRO_OPERATOR_OVER
@ -1521,7 +1358,7 @@ _cairo_path_fixed_interpret (cairo_path_fixed_t *path,
cairo_path_fixed_close_path_func_t *close_path,
void *closure);
cairo_private cairo_status_t
cairo_private void
_cairo_path_fixed_bounds (cairo_path_fixed_t *path,
double *x1, double *y1,
double *x2, double *y2);
@ -2222,6 +2059,10 @@ _cairo_slope_counter_clockwise (cairo_slope_t *a, cairo_slope_t *b);
/* cairo_pattern.c */
cairo_private cairo_status_t
_cairo_pattern_create_copy (cairo_pattern_t **pattern,
const cairo_pattern_t *other);
cairo_private cairo_status_t
_cairo_pattern_init_copy (cairo_pattern_t *pattern,
const cairo_pattern_t *other);

View file

@ -11,6 +11,12 @@ test -z "$srcdir" && srcdir=.
test -z "$MAKE" && MAKE=make
status=0
has_hidden_symbols=`cat .check-has-hidden-symbols`
if test "x$has_hidden_symbols" != "x1"; then
echo "Compiler doesn't support symbol visibility; skipping test"
exit 0
fi
get_cairo_syms='nm "$so" | grep " T " | cut -d" " -f3'
if [ "`uname -s`" = "Linux" ]; then
get_cairo_syms='objdump -t "$so" | sed -n "/.*g *F *\.\(opd\|text\).* \(.*cairo_.*\)$/s//\2/p"'

View file

@ -0,0 +1,12 @@
#include "cairoint.h"
#if CAIRO_HAS_HIDDEN_SYMBOLS
extern cairo_public int cairo_has_hidden_symbols;
int cairo_has_hidden_symbols;
#endif
int
main (void)
{
return 0;
}

View file

@ -2,13 +2,20 @@
LANG=C
status=0
if ! which readelf 2>/dev/null >/dev/null; then
echo "'readelf' not found; skipping test"
exit 0
fi
test -z "$srcdir" && srcdir=.
status=0
has_hidden_symbols=`cat .check-has-hidden-symbols`
if test "x$has_hidden_symbols" != "x1"; then
echo "Compiler doesn't support symbol visibility; skipping test"
exit 0
fi
for so in .libs/lib*.so; do
echo Checking "$so" for local PLT entries
readelf -W -r "$so" | grep 'JU\?MP_SLO' | grep 'cairo' && status=1

View file

@ -17,6 +17,16 @@
obj:/usr/lib/libz.so.1.2.3
fun:deflate
}
{
bugs in libpng/libz
Memcheck:Cond
obj:/usr/lib/libz.so.1.2.3.3
}
{
bugs in libpng/libz
Memcheck:Value8
obj:/usr/lib/libz.so.1.2.3.3
}
{
cairo's write_png triggers apparent bugs in libpng/libz
Memcheck:Cond
@ -209,7 +219,13 @@
Memcheck:Leak
fun:malloc
fun:_XrmInternalStringToQuark
fun:XrmPermStringToQuark
}
{
XrmInitialize is fairly obnoxious about leaving reachable memory around
Memcheck:Leak
fun:malloc
obj:/usr/lib/libX11.so.6.2.0
fun:_XrmInternalStringToQuark
fun:XrmInitialize
}
{
@ -218,8 +234,6 @@
fun:malloc
fun:permalloc
fun:_XrmInternalStringToQuark
fun:XrmPermStringToQuark
fun:XrmInitialize
}
{
XrmGetStringDatabase is fairly obnoxious about leaving reachable memory around

View file

@ -1,130 +1,130 @@
SUBDIRS=pdiff .
# Here are all the tests that are run unconditionally
TESTS = \
a8-mask \
big-trap \
caps-joins \
caps-joins-alpha \
caps-sub-paths \
clip-all \
clip-empty \
clip-fill-rule \
clip-fill-rule-pixel-aligned \
clip-nesting \
clip-operator \
clip-push-group \
clip-twice \
clip-zero \
close-path \
composite-integer-translate-source \
composite-integer-translate-over \
composite-integer-translate-over-repeat \
copy-path \
create-for-stream \
create-from-png \
create-from-png-stream \
dash-caps-joins \
dash-no-dash \
dash-offset-negative \
dash-scale \
dash-zero-length \
dash-state \
degenerate-path \
degenerate-pen \
device-offset \
device-offset-positive \
extend-pad \
fill-and-stroke \
fill-and-stroke-alpha \
fill-and-stroke-alpha-add \
fill-degenerate-sort-order \
fill-missed-stop \
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 \
gradient-zero-stops \
infinite-join \
in-fill-empty-trapezoid \
invalid-matrix \
leaky-dash \
leaky-polygon \
line-width \
line-width-scale \
line-width-zero \
linear-gradient \
linear-gradient-reflect \
long-lines \
mask \
mask-alpha \
mask-ctm \
mask-surface-ctm \
meta-surface-pattern \
miter-precision \
move-to-show-surface \
new-sub-path \
nil-surface \
operator-clear \
operator-source \
over-above-source \
over-around-source \
over-below-source \
over-between-source \
paint \
paint-repeat \
paint-source-alpha \
paint-with-alpha \
pattern-get-type \
pattern-getters \
pixman-rotate \
radial-gradient \
random-intersections \
rectangle-rounding-error \
rectilinear-stroke \
rgb24-ignore-alpha \
rotate-image-surface-paint \
scale-down-source-surface-paint \
scale-source-surface-paint \
select-font-face \
select-font-no-show-text \
self-copy \
self-intersecting \
set-source \
show-text-current-point \
skew-extreme \
solid-pattern-cache-stress \
source-clip \
source-clip-scale \
source-surface-scale-paint \
surface-finish-twice \
surface-pattern \
surface-pattern-big-scale-down \
surface-pattern-scale-down \
surface-pattern-scale-up \
text-antialias-gray \
text-antialias-none \
text-antialias-subpixel \
text-cache-crash \
text-pattern \
text-rotate \
text-zero-len \
transforms \
translate-show-surface \
trap-clip \
truetype-tables \
unantialiased-shapes \
unbounded-operator \
user-data \
rel-path \
push-group \
zero-alpha
TESTS = \
a8-mask$(EXEEXT) \
big-trap$(EXEEXT) \
caps-joins$(EXEEXT) \
caps-joins-alpha$(EXEEXT) \
caps-sub-paths$(EXEEXT) \
clip-all$(EXEEXT) \
clip-empty$(EXEEXT) \
clip-fill-rule$(EXEEXT) \
clip-fill-rule-pixel-aligned$(EXEEXT) \
clip-nesting$(EXEEXT) \
clip-operator$(EXEEXT) \
clip-push-group$(EXEEXT) \
clip-twice$(EXEEXT) \
clip-zero$(EXEEXT) \
close-path$(EXEEXT) \
composite-integer-translate-source$(EXEEXT) \
composite-integer-translate-over$(EXEEXT) \
composite-integer-translate-over-repeat$(EXEEXT) \
copy-path$(EXEEXT) \
create-for-stream$(EXEEXT) \
create-from-png$(EXEEXT) \
create-from-png-stream$(EXEEXT) \
dash-caps-joins$(EXEEXT) \
dash-no-dash$(EXEEXT) \
dash-offset-negative$(EXEEXT) \
dash-scale$(EXEEXT) \
dash-zero-length$(EXEEXT) \
dash-state$(EXEEXT) \
degenerate-path$(EXEEXT) \
degenerate-pen$(EXEEXT) \
device-offset$(EXEEXT) \
device-offset-positive$(EXEEXT) \
extend-pad$(EXEEXT) \
fill-and-stroke$(EXEEXT) \
fill-and-stroke-alpha$(EXEEXT) \
fill-and-stroke-alpha-add$(EXEEXT) \
fill-degenerate-sort-order$(EXEEXT) \
fill-missed-stop$(EXEEXT) \
fill-rule$(EXEEXT) \
filter-nearest-offset$(EXEEXT) \
font-face-get-type$(EXEEXT) \
font-matrix-translation$(EXEEXT) \
glyph-cache-pressure$(EXEEXT) \
get-and-set$(EXEEXT) \
get-clip$(EXEEXT) \
get-group-target$(EXEEXT) \
get-path-extents$(EXEEXT) \
gradient-alpha$(EXEEXT) \
gradient-zero-stops$(EXEEXT) \
infinite-join$(EXEEXT) \
in-fill-empty-trapezoid$(EXEEXT) \
invalid-matrix$(EXEEXT) \
leaky-dash$(EXEEXT) \
leaky-polygon$(EXEEXT) \
line-width$(EXEEXT) \
line-width-scale$(EXEEXT) \
line-width-zero$(EXEEXT) \
linear-gradient$(EXEEXT) \
linear-gradient-reflect$(EXEEXT) \
long-lines$(EXEEXT) \
mask$(EXEEXT) \
mask-alpha$(EXEEXT) \
mask-ctm$(EXEEXT) \
mask-surface-ctm$(EXEEXT) \
meta-surface-pattern$(EXEEXT) \
miter-precision$(EXEEXT) \
move-to-show-surface$(EXEEXT) \
new-sub-path$(EXEEXT) \
nil-surface$(EXEEXT) \
operator-clear$(EXEEXT) \
operator-source$(EXEEXT) \
over-above-source$(EXEEXT) \
over-around-source$(EXEEXT) \
over-below-source$(EXEEXT) \
over-between-source$(EXEEXT) \
paint$(EXEEXT) \
paint-repeat$(EXEEXT) \
paint-source-alpha$(EXEEXT) \
paint-with-alpha$(EXEEXT) \
pattern-get-type$(EXEEXT) \
pattern-getters$(EXEEXT) \
pixman-rotate$(EXEEXT) \
radial-gradient$(EXEEXT) \
random-intersections$(EXEEXT) \
rectangle-rounding-error$(EXEEXT) \
rectilinear-stroke$(EXEEXT) \
rgb24-ignore-alpha$(EXEEXT) \
rotate-image-surface-paint$(EXEEXT) \
scale-down-source-surface-paint$(EXEEXT) \
scale-source-surface-paint$(EXEEXT) \
select-font-face$(EXEEXT) \
select-font-no-show-text$(EXEEXT) \
self-copy$(EXEEXT) \
self-intersecting$(EXEEXT) \
set-source$(EXEEXT) \
show-text-current-point$(EXEEXT) \
skew-extreme$(EXEEXT) \
solid-pattern-cache-stress$(EXEEXT) \
source-clip$(EXEEXT) \
source-clip-scale$(EXEEXT) \
source-surface-scale-paint$(EXEEXT) \
surface-finish-twice$(EXEEXT) \
surface-pattern$(EXEEXT) \
surface-pattern-big-scale-down$(EXEEXT) \
surface-pattern-scale-down$(EXEEXT) \
surface-pattern-scale-up$(EXEEXT) \
text-antialias-gray$(EXEEXT) \
text-antialias-none$(EXEEXT) \
text-antialias-subpixel$(EXEEXT) \
text-cache-crash$(EXEEXT) \
text-pattern$(EXEEXT) \
text-rotate$(EXEEXT) \
text-zero-len$(EXEEXT) \
transforms$(EXEEXT) \
translate-show-surface$(EXEEXT) \
trap-clip$(EXEEXT) \
truetype-tables$(EXEEXT) \
unantialiased-shapes$(EXEEXT) \
unbounded-operator$(EXEEXT) \
user-data$(EXEEXT) \
rel-path$(EXEEXT) \
push-group$(EXEEXT) \
zero-alpha$(EXEEXT)
# XXX: Here are some existing tests that are currently disabled for
# one reason or another. They can still be built and run (manually)
@ -166,49 +166,50 @@ zero-alpha
# suite, (in spite of the XFAIL status of the test). So maybe
# that's just a bug in the test rig that should just consider
# the abort an XFAIL like any other.
DISABLED_TESTS = \
extend-reflect \
show-glyphs-many \
text-glyph-range
DISABLED_TESTS = \
extend-reflect$(EXEEXT) \
show-glyphs-many$(EXEEXT) \
text-glyph-range$(EXEEXT)
# Then we have a collection of tests that are only run if certain
# features are compiled into cairo
if HAVE_PTHREAD
TESTS += pthread-show-text
TESTS += pthread-show-text$(EXEEXT)
endif
if CAIRO_HAS_FT_FONT
TESTS += bitmap-font
TESTS += ft-font-create-for-ft-face
TESTS += ft-text-vertical-layout-type1
TESTS += ft-text-vertical-layout-type3
TESTS += ft-text-antialias-none
TESTS += bitmap-font$(EXEEXT)
TESTS += ft-font-create-for-ft-face$(EXEEXT)
TESTS += ft-text-vertical-layout-type1$(EXEEXT)
TESTS += ft-text-vertical-layout-type3$(EXEEXT)
TESTS += ft-text-antialias-none$(EXEEXT)
endif
if CAIRO_HAS_SVG_SURFACE
TESTS += svg-surface svg-clip
TESTS += svg-surface$(EXEEXT)
TESTS += svg-clip$(EXEEXT)
endif
if CAIRO_HAS_PDF_SURFACE
TESTS += pdf-features
TESTS += pdf-features$(EXEEXT)
endif
if CAIRO_HAS_PS_SURFACE
TESTS += ps-features
TESTS += ps-features$(EXEEXT)
endif
if CAIRO_HAS_XLIB_SURFACE
TESTS += xlib-surface
TESTS += xlib-surface$(EXEEXT)
endif
if CAIRO_HAS_MULTI_PAGE_SURFACES
TESTS += multi-page
TESTS += multi-page$(EXEEXT)
endif
if CAIRO_HAS_SVG_SURFACE
if CAIRO_HAS_PDF_SURFACE
if CAIRO_HAS_PS_SURFACE
TESTS += fallback-resolution
TESTS += fallback-resolution$(EXEEXT)
endif
endif
endif
@ -505,17 +506,17 @@ $(REFERENCE_IMAGES)
#
# Also, any test listed here should call cairo_test_expect_failure and
# provide an explanation for the expected failure.
XFAIL_TESTS = \
a8-mask \
big-trap \
extend-pad \
filter-nearest-offset \
long-lines \
self-intersecting \
surface-pattern \
surface-pattern-big-scale-down \
surface-pattern-scale-down \
surface-pattern-scale-up
XFAIL_TESTS = \
a8-mask$(EXEEXT) \
big-trap$(EXEEXT) \
extend-pad$(EXEEXT) \
filter-nearest-offset$(EXEEXT) \
long-lines$(EXEEXT) \
self-intersecting$(EXEEXT) \
surface-pattern$(EXEEXT) \
surface-pattern-big-scale-down$(EXEEXT) \
surface-pattern-scale-down$(EXEEXT) \
surface-pattern-scale-up$(EXEEXT)
# Any test that doesn't generate a log file goes here
NOLOG_TESTS = \
@ -597,7 +598,7 @@ EXTRA_PROGRAMS += $(TESTS) $(DISABLED_TESTS)
TARGETS = $(CAIRO_TEST_TARGET)
TARGETS_EXCLUDE = $(CAIRO_TEST_TARGET_EXCLUDE)
TESTS_ENVIRONMENT = CAIRO_XFAIL_TESTS="$(XFAIL_TESTS)" CAIRO_TEST_TARGET="$(TARGETS)" CAIRO_TEST_TARGET_EXCLUDE="$(TARGETS_EXCLUDE)"
TESTS_ENVIRONMENT = CAIRO_XFAIL_TESTS="$(XFAIL_TESTS:$(EXEEXT)=)" CAIRO_TEST_TARGET="$(TARGETS)" CAIRO_TEST_TARGET_EXCLUDE="$(TARGETS_EXCLUDE)"
EXTRA_VALGRIND_FLAGS = $(CAIRO_EXTRA_VALGRIND_FLAGS)
VALGRIND_FLAGS = \
@ -629,8 +630,8 @@ check-valgrind:
$(MAKE) $(AM_MAKEFLAGS) check TESTS_ENVIRONMENT='$(TESTS_ENVIRONMENT) $(top_builddir)/libtool --mode=execute valgrind $(VALGRIND_FLAGS)' 2>&1 | tee valgrind-log
# The following definitions both should work.
#FAILED_TESTS = `grep -l '\<FAIL\>' $(TESTS:=.log) 2>/dev/null | sed -e 's/[.]log$$//' | xargs echo`
FAILED_TESTS = `grep -l '\<FAIL\>' $(TESTS:=.log) 2>/dev/null | tr '\n' ' ' | sed -e 's/[.]log */ /g; s/^ //; s/ $$//'`
#FAILED_TESTS = `grep -l '\<FAIL\>' $(TESTS:$(EXEEXT)=.log) 2>/dev/null | sed -e 's/[.]log$$//' | xargs echo`
FAILED_TESTS = `grep -l '\<FAIL\>' $(TESTS:$(EXEEXT)=.log) 2>/dev/null | tr '\n' ' ' | sed -e 's/[.]log */ /g; s/^ //; s/ $$//'`
recheck = check TESTS="$(FAILED_TESTS)"
@ -655,7 +656,7 @@ retest:
# Make index.html with no dependency tracking.
html:
@echo Creating index.html
@perl $(srcdir)/make-html.pl $(TESTS:=.log) > index.html
@perl $(srcdir)/make-html.pl $(TESTS:$(EXEEXT)=.log) > index.html
# Make index.html with no dependency tracking, containing only the failed tests.
rehtml:
@ -669,7 +670,7 @@ NOLOG_TESTS_LOG = $(NOLOG_TESTS:=.log)
$(NOLOG_TESTS_LOG):
echo dummy > $@
index.html: $(srcdir)/make-html.pl $(TESTS:=.log)
index.html: $(srcdir)/make-html.pl $(TESTS:$(EXEEXT)=.log)
@echo Creating index.html
@perl $^ > $@

View file

@ -1,12 +1,12 @@
/*
* Copyright ? 2007 Chris Wilson.
* Copyright © 2007 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
* 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
@ -23,6 +23,10 @@
* Author: Chris Wilson <chris at chris-wilson.co.uk>
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "cairo-test.h"
static cairo_test_draw_function_t draw;
@ -39,6 +43,10 @@ cairo_test_t test = {
#define LOOPS 10
#define NRAND 100
#ifndef HAVE_DRAND48
#define drand48() (rand () / (double) RAND_MAX)
#endif
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{