Merge branch 'cairo' into new-sub-path
Conflicts: src/cairo-path-stroke.c src/cairo-pdf-surface.c src/cairo-ps-surface.c
1
.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
|||
ChangeLog
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
|
|
|
|||
1
AUTHORS
|
|
@ -14,6 +14,7 @@ John Ehresman <jpe@wingide.com> Build fixes for win32
|
|||
John Ellson <ellson@research.att.com> First font/glyph extents functions
|
||||
Behdad Esfahbod <behdad@behdad.org> Release script improvements, bug fixes.
|
||||
Bertram Felgenhauer <int-e@gmx.de> Fixes for subtle arithmetic errors
|
||||
Bdale Garbee <bdale@gag.com> Provided essential support for cairo achitecture sessions
|
||||
J. Ali Harlow <ali@avrc.city.ac.uk> win32 backend updates
|
||||
Richard Henderson <rth@twiddle.net> "slim" macros for better shared libraries
|
||||
James Henstridge <james@daa.com.au> Build fixes related to freetype
|
||||
|
|
|
|||
2
INSTALL
|
|
@ -16,7 +16,7 @@ This final step may require temporary root access (eg. with sudo) if
|
|||
you don't have write permission to the directory in which cairo will
|
||||
be installed.
|
||||
|
||||
NOTE: If you are working with source from CVS rather than from a tar
|
||||
NOTE: If you are working with source from git/cvs rather than from a tar
|
||||
file, then you should use ./autogen.sh in place of ./configure
|
||||
anywhere it is mentioned in these instructions.
|
||||
|
||||
|
|
|
|||
47
Makefile.am
|
|
@ -11,6 +11,21 @@ EXTRA_DIST = \
|
|||
COPYING-LGPL-2.1 \
|
||||
COPYING-MPL-1.1 \
|
||||
cairo.pc.in
|
||||
MAINTAINERCLEANFILES = \
|
||||
$(srcdir)/INSTALL \
|
||||
$(srcdir)/aclocal.m4 \
|
||||
$(srcdir)/autoscan.log \
|
||||
$(srcdir)/compile \
|
||||
$(srcdir)/config.guess \
|
||||
$(srcdir)/config.h.in \
|
||||
$(srcdir)/config.sub \
|
||||
$(srcdir)/configure.scan \
|
||||
$(srcdir)/depcomp \
|
||||
$(srcdir)/install-sh \
|
||||
$(srcdir)/ltmain.sh \
|
||||
$(srcdir)/missing \
|
||||
$(srcdir)/mkinstalldirs \
|
||||
`find "$(srcdir)" -type f -name Makefile.in -print`
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = cairo.pc
|
||||
|
|
@ -20,6 +35,30 @@ check-valgrind: all
|
|||
|
||||
DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc
|
||||
|
||||
# Creating ChangeLog from git log:
|
||||
|
||||
MAINTAINERCLEANFILES += ChangeLog
|
||||
|
||||
EXTRA_DIST += ChangeLog
|
||||
|
||||
ChangeLog: $(srcdir)/ChangeLog
|
||||
|
||||
$(srcdir)/ChangeLog:
|
||||
@if test -d "$(srcdir)/.git"; then \
|
||||
(cd "$(srcdir)" && \
|
||||
./missing --run git-log) | fmt --split-only > $@.tmp \
|
||||
&& mv -f $@.tmp $@ \
|
||||
|| ($(RM) $@.tmp; \
|
||||
echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \
|
||||
(test -f $@ || echo git-log is required to generate this file >> $@)); \
|
||||
else \
|
||||
test -f $@ || \
|
||||
(echo A git checkout and git-log is required to generate ChangeLog >&2 && \
|
||||
echo A git checkout and git-log is required to generate this file >> $@); \
|
||||
fi
|
||||
|
||||
.PHONY: ChangeLog $(srcdir)/ChangeLog
|
||||
|
||||
# Some custom targets to make it easier to release things.
|
||||
# Use either:
|
||||
# make release-check
|
||||
|
|
@ -82,7 +121,7 @@ release-verify-newer:
|
|||
@echo -n "Checking that no $(VERSION) release already exists..."
|
||||
@ssh $(RELEASE_UPLOAD_HOST) test ! -e $(RELEASE_UPLOAD_DIR)/$(tar_file) \
|
||||
|| (echo "Ouch." && echo "Found: $(RELEASE_UPLOAD_HOST):$(RELEASE_UPLOAD_DIR)/$(tar_file)" \
|
||||
&& echo "Are you sure you have an updated CVS checkout?" \
|
||||
&& echo "Are you sure you have an updated checkout?" \
|
||||
&& echo "This should never happen." \
|
||||
&& false)
|
||||
@echo "Good."
|
||||
|
|
@ -104,9 +143,9 @@ release-upload: release-check $(tar_file) $(sha1_file) $(gpg_file)
|
|||
scp $(tar_file) $(sha1_file) $(gpg_file) $(RELEASE_UPLOAD_HOST):$(RELEASE_UPLOAD_DIR)
|
||||
mv $(tar_file) $(sha1_file) $(gpg_file) releases
|
||||
ssh $(RELEASE_UPLOAD_HOST) "rm -f $(RELEASE_UPLOAD_DIR)/LATEST-$(PACKAGE)-[0-9]* && ln -s $(tar_file) $(RELEASE_UPLOAD_DIR)/LATEST-$(PACKAGE)-$(VERSION)"
|
||||
$(CVS) tag RELEASE_$(CAIRO_VERSION_MAJOR)_$(CAIRO_VERSION_MINOR)_$(CAIRO_VERSION_MICRO)
|
||||
git tag -s $(CAIRO_VERSION_MAJOR).$(CAIRO_VERSION_MINOR).$(CAIRO_VERSION_MICRO)
|
||||
|
||||
release-publish: release-upload releases/$(sha1_file)
|
||||
release-publish-message: releases/$(sha1_file)
|
||||
@echo ""
|
||||
@echo "Please send an announcement to $(RELEASE_ANNOUNCE_LIST)"
|
||||
@echo "including the following:"
|
||||
|
|
@ -133,6 +172,8 @@ release-publish: release-upload releases/$(sha1_file)
|
|||
@echo "Last but not least, do not forget to bump up the micro"
|
||||
@echo "version component to the next (odd) number and commit."
|
||||
|
||||
release-publish: release-upload release-publish-message
|
||||
|
||||
# XXX: Depending on all here is rather overkill. We don't really need
|
||||
# the library built in order to create the documentation.
|
||||
docs-publish: all
|
||||
|
|
|
|||
26
RELEASING
|
|
@ -1,12 +1,7 @@
|
|||
Here are the steps to follow to create a new cairo release:
|
||||
|
||||
1) Ensure that there are no local, uncommitted modifications. The best
|
||||
thing to do here may be to begin with a fresh checkout from CVS:
|
||||
|
||||
cvs -d cairographics.org:/cvs/cairo co cairo
|
||||
|
||||
But it's probably good enough if "cvs -q update -Ad" generates no
|
||||
output.
|
||||
1) Ensure that there are no local, uncommitted modifications.
|
||||
It's probably good enough if "git diff" doesn't output anything.
|
||||
|
||||
2) Verify that the code passes "make distcheck"
|
||||
|
||||
|
|
@ -32,7 +27,10 @@ Here are the steps to follow to create a new cairo release:
|
|||
previous release tag:
|
||||
|
||||
find src/ -name '*.h' -not -name '*-private.h' -not -name 'cairoint.h' | \
|
||||
xargs cvs diff -r RELEASE_X_Y_Z
|
||||
xargs git diff X.Y.Z --
|
||||
|
||||
Note that for older releases made under CVS, the tag name is
|
||||
RELEASE_X_Y_Z instead.
|
||||
|
||||
4) Increment cairo_version_{minor|micro} and LT_{CURRENT|VERSION|AGE}
|
||||
in configure.in:
|
||||
|
|
@ -55,9 +53,8 @@ Here are the steps to follow to create a new cairo release:
|
|||
|
||||
5) Commit the changes to NEWS and configure.in
|
||||
|
||||
Don't forget to fill out the ChangeLog just like with any
|
||||
other commit. It's especially important to mention the new
|
||||
version number in the ChangeLog.
|
||||
It's especially important to mention the new version number in your
|
||||
commit log.
|
||||
|
||||
6) Run "make release-publish" which will perform the following steps
|
||||
for you:
|
||||
|
|
@ -71,8 +68,13 @@ Here are the steps to follow to create a new cairo release:
|
|||
* scp the three files to appear on http://cairographics.org/releases
|
||||
* Place local copies of the three files in the releases directory
|
||||
* Create a LATEST-package-version file (after deleting any old one)
|
||||
* Tag the entire source tree with a tag of the form RELEASE_X_Y_Z
|
||||
* Tag the entire source tree with a tag of the form X.Y.Z, and sign
|
||||
the tag with your GPG key (asks for your GPG password, and you
|
||||
may need to set GIT_COMMITTER_NAME and GIT_COMMITTER_EMAIL to match
|
||||
your public-key's setting or this fails.)
|
||||
* Provide some text for the release announcement (see below).
|
||||
If for some reason you lost this message, "make release-publish-message"
|
||||
prints it for you.
|
||||
|
||||
7) Increment cairo_version_micro to the next larger (odd) number in
|
||||
configure, and commit.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ PACKAGE=cairo
|
|||
LIBTOOLIZE=${LIBTOOLIZE-libtoolize}
|
||||
LIBTOOLIZE_FLAGS="--copy --force"
|
||||
AUTOHEADER=${AUTOHEADER-autoheader}
|
||||
AUTOMAKE_FLAGS="--add-missing"
|
||||
AUTOMAKE_FLAGS="--add-missing --foreign"
|
||||
AUTOCONF=${AUTOCONF-autoconf}
|
||||
|
||||
# automake 1.8 requires autoconf 2.58
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
AC_PREREQ(2.54)
|
||||
|
||||
# cairo package version number, (as distinct from shared library version)
|
||||
# An odd micro number indicates in-progress development, (eg. from CVS)
|
||||
# An odd micro number indicates in-progress development, (eg. from git/cvs)
|
||||
# An even micro number indicates a released version.
|
||||
m4_define(cairo_version_major, 1)
|
||||
m4_define(cairo_version_minor, 1)
|
||||
|
|
@ -810,6 +810,6 @@ if test x"$use_beos" = "xyes" ; then
|
|||
echo "$WARNING_MESSAGE" | sed 's/@BACKEND@/BeOS/'
|
||||
fi
|
||||
|
||||
if test x"$use_directfb" == "xyes" ; then
|
||||
if test x"$use_directfb" = "xyes" ; then
|
||||
echo "$WARNING_MESSAGE" | sed 's/@BACKEND@/DirectFB/'
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
<xi:include href="xml/cairo-ps.xml"/>
|
||||
<xi:include href="xml/cairo-win32.xml"/>
|
||||
<xi:include href="xml/cairo-beos.xml"/>
|
||||
<xi:include href="xml/cairo-svg.xml"/>
|
||||
<!-- Experimental Quartz and XCB backends removed
|
||||
from the public doc for now.
|
||||
<xi:include href="xml/cairo-quartz.xml"/>
|
||||
|
|
|
|||
|
|
@ -108,6 +108,14 @@ cairo_xlib_surface_set_drawable
|
|||
cairo_xlib_surface_create_with_xrender_format
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>cairo-svg</FILE>
|
||||
<TITLE>SVG Surfaces</TITLE>
|
||||
cairo_svg_surface_create
|
||||
cairo_svg_surface_create_for_stream
|
||||
cairo_svg_surface_set_dpi
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>cairo-surface</FILE>
|
||||
<TITLE>cairo_surface_t</TITLE>
|
||||
|
|
|
|||
52
doc/public/tmpl/cairo-svg.sgml
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
<!-- ##### SECTION Title ##### -->
|
||||
SVG Surfaces
|
||||
|
||||
<!-- ##### SECTION Short_Description ##### -->
|
||||
Rendering SVG documents
|
||||
|
||||
<!-- ##### SECTION Long_Description ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
<!-- ##### SECTION See_Also ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
<!-- ##### SECTION Stability_Level ##### -->
|
||||
|
||||
|
||||
<!-- ##### FUNCTION cairo_svg_surface_create ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@filename:
|
||||
@width_in_points:
|
||||
@height_in_points:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION cairo_svg_surface_create_for_stream ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@write_func:
|
||||
@closure:
|
||||
@width_in_points:
|
||||
@height_in_points:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION cairo_svg_surface_set_dpi ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@surface:
|
||||
@x_dpi:
|
||||
@y_dpi:
|
||||
|
||||
|
||||
|
|
@ -33,10 +33,18 @@
|
|||
|
||||
#include "pixregionint.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
// #define PIXMAN_CONVOLUTION
|
||||
// #define PIXMAN_INDEXED_FORMATS
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
/* #define PIXMAN_CONVOLUTION */
|
||||
/* #define PIXMAN_INDEXED_FORMATS */
|
||||
|
||||
static Bool
|
||||
PictureTransformPoint3d (pixman_transform_t *transform,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
* $Id: fbedge.c,v 1.3 2005-08-02 01:01:24 vektor Exp $
|
||||
*
|
||||
* Copyright © 2004 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
* $Id: fbedgeimp.h,v 1.2 2005-01-21 18:38:42 cworth Exp $
|
||||
*
|
||||
* Copyright © 2004 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
* $Id: fbpict.c,v 1.8 2006-01-21 17:39:11 biesi Exp $
|
||||
*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
|
|
@ -1151,7 +1149,7 @@ fbCompositeTrans_0888xnx0888(pixman_operator_t op,
|
|||
setupPackedReader(ws,wt,isrc,wsrc,workingSource);
|
||||
|
||||
/* get to word aligned */
|
||||
switch(!(long)dst&3)
|
||||
switch(~(long)dst&3)
|
||||
{
|
||||
case 1:
|
||||
readPackedSource(rs);
|
||||
|
|
@ -1227,7 +1225,7 @@ fbCompositeTrans_0888xnx0888(pixman_operator_t op,
|
|||
srcLine += srcStride;
|
||||
w = width*3;
|
||||
/* get to word aligned */
|
||||
switch(!(long)src&3)
|
||||
switch(~(long)src&3)
|
||||
{
|
||||
case 1:
|
||||
rd=alphamaskCombine24(*src++, *dst)>>8;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
* $Id: fbpict.h,v 1.2 2005-09-12 12:55:11 otaylor Exp $
|
||||
*
|
||||
* Copyright © 2000 Keith Packard
|
||||
* 2005 Lars Knoll & Zack Rusin, Trolltech
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
* $Id: icpixels.c,v 1.9 2005-06-25 03:13:19 jrmuizel Exp $
|
||||
*
|
||||
* Copyright © 1998 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
|
|
@ -72,6 +70,7 @@ FbPixelsCreate (int width, int height, int depth)
|
|||
return NULL;
|
||||
|
||||
buf = (pixman_bits_t *) ((char *)pixels + base + adjust);
|
||||
memset (buf, 0, height * stride);
|
||||
|
||||
FbPixelsInit (pixels, buf, width, height, depth, bpp, stride);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
* $Id: ictrap.c,v 1.27 2005-08-28 02:32:57 vektor Exp $
|
||||
*
|
||||
* Copyright © 2002 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@ typedef pixman_triangle_t xTriangle;
|
|||
#define FB_SHIFT IC_SHIFT
|
||||
#define FB_MASK IC_MASK
|
||||
#define FB_ALLONES IC_ALLONES
|
||||
#define FbMaskBits IcMaskBits
|
||||
*/
|
||||
//#define FbMaskBits IcMaskBits
|
||||
|
||||
/* XXX: We changed some function and field names which makes for some
|
||||
* ugly hacks... */
|
||||
|
|
|
|||
|
|
@ -54,8 +54,6 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|||
SOFTWARE.
|
||||
|
||||
******************************************************************/
|
||||
/* $Id: pixman.h,v 1.25 2006-01-05 00:26:10 cworth Exp $ */
|
||||
|
||||
/* libic.h */
|
||||
|
||||
/*
|
||||
|
|
@ -83,7 +81,7 @@ SOFTWARE.
|
|||
|
||||
#if defined (__SVR4) && defined (__sun)
|
||||
# include <sys/int_types.h>
|
||||
#elif defined (__OpenBSD__) || defined (_AIX)
|
||||
#elif defined (__OpenBSD__) || defined (_AIX) || defined (__osf__)
|
||||
# include <inttypes.h>
|
||||
#elif defined (_MSC_VER)
|
||||
typedef __int8 int8_t;
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ SOFTWARE.
|
|||
#endif
|
||||
|
||||
#undef assert
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG_PIXREGION
|
||||
#define assert(expr) {if (!(expr)) \
|
||||
FatalError("Assertion failed file %s, line %d: expr\n", \
|
||||
__FILE__, __LINE__); }
|
||||
|
|
@ -208,7 +208,7 @@ if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \
|
|||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG_PIXREGION
|
||||
int
|
||||
pixman_region16_print(rgn)
|
||||
pixman_region16_t * rgn;
|
||||
|
|
@ -302,7 +302,7 @@ pixman_region16_valid(reg)
|
|||
}
|
||||
}
|
||||
|
||||
#endif /* DEBUG */
|
||||
#endif /* DEBUG_PIXREGION */
|
||||
|
||||
|
||||
/* Create a new empty region */
|
||||
|
|
|
|||
|
|
@ -44,8 +44,6 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|||
SOFTWARE.
|
||||
|
||||
******************************************************************/
|
||||
/* $Id: pixregionint.h,v 1.7 2004-04-16 15:32:53 cworth Exp $ */
|
||||
|
||||
#ifndef _PIXREGIONINT_H_
|
||||
#define _PIXREGIONINT_H_
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
* $Id: renderedge.c,v 1.2 2005-01-21 18:26:28 cworth Exp $
|
||||
*
|
||||
* Copyright © 2004 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
* $Id: renderedge.h,v 1.3 2005-02-21 21:29:22 cworth Exp $
|
||||
*
|
||||
* Copyright © 2004 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
|
|
|
|||
|
|
@ -56,6 +56,11 @@ libcairo_beos_sources =
|
|||
if CAIRO_HAS_BEOS_SURFACE
|
||||
libcairo_beos_headers = cairo-beos.h
|
||||
libcairo_beos_sources += cairo-beos-surface.cpp
|
||||
|
||||
noinst_LTLIBRARIES = libcairo_beos.la
|
||||
libcairo_beos_la_SOURCES = $(libcairo_beos_sources)
|
||||
# BeOS system headers trigger this warning
|
||||
libcairo_beos_la_CXXFLAGS = -Wno-multichar
|
||||
endif
|
||||
|
||||
if CAIRO_HAS_GLITZ_SURFACE
|
||||
|
|
@ -129,6 +134,7 @@ libcairo_la_SOURCES = \
|
|||
cairo-arc.c \
|
||||
cairo-arc-private.h \
|
||||
cairo-array.c \
|
||||
cairo-base85-stream.c \
|
||||
cairo-cache.c \
|
||||
cairo-cache-private.h \
|
||||
cairo-clip.c \
|
||||
|
|
@ -145,7 +151,9 @@ libcairo_la_SOURCES = \
|
|||
cairo-hash-private.h \
|
||||
cairo-hull.c \
|
||||
cairo-image-surface.c \
|
||||
cairo-lzw.c \
|
||||
cairo-matrix.c \
|
||||
cairo-operator.c \
|
||||
cairo-path.c \
|
||||
cairo-path-bounds.c \
|
||||
cairo-path-data.c \
|
||||
|
|
@ -173,6 +181,8 @@ libcairo_la_SOURCES = \
|
|||
cairo-meta-surface-private.h \
|
||||
cairo-paginated-surface.c \
|
||||
cairo-paginated-surface-private.h \
|
||||
cairo-analysis-surface.c \
|
||||
cairo-analysis-surface-private.h \
|
||||
$(libcairo_atsui_sources) \
|
||||
$(libcairo_ft_sources) \
|
||||
$(libcairo_ps_sources) \
|
||||
|
|
@ -187,19 +197,16 @@ libcairo_la_SOURCES = \
|
|||
$(libcairo_glitz_sources) \
|
||||
$(libcairo_win32_sources) \
|
||||
$(libcairo_beos_sources) \
|
||||
$(libcairo_directfb_sources) \
|
||||
$(libcairo_directfb_sources) \
|
||||
cairoint.h
|
||||
|
||||
libcairo_la_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined $(export_symbols)
|
||||
# this -Wno-multichar line is really just for the beos surface, because the
|
||||
# system headers trigger this warning.
|
||||
libcairo_la_CXXFLAGS = -Wno-multichar
|
||||
|
||||
INCLUDES = -I$(srcdir) -I$(top_srcdir)/pixman/src $(CAIRO_CFLAGS)
|
||||
|
||||
libcairo_la_LIBADD = $(top_builddir)/pixman/src/libpixman.la $(CAIRO_LIBS)
|
||||
libcairo_la_LIBADD = $(top_builddir)/pixman/src/libpixman.la $(CAIRO_LIBS) $(noinst_LTLIBRARIES)
|
||||
|
||||
libcairo_la_DEPENDENCIES = $(cairo_def_dependency) $(top_builddir)/pixman/src/libpixman.la
|
||||
libcairo_la_DEPENDENCIES = $(cairo_def_dependency) $(top_builddir)/pixman/src/libpixman.la $(noinst_LTLIBRARIES)
|
||||
|
||||
EXTRA_DIST = \
|
||||
cairo.def
|
||||
|
|
|
|||
55
src/cairo-analysis-surface-private.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/* $Id: $
|
||||
*
|
||||
* Copyright © 2005 Keith Packard
|
||||
*
|
||||
* 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 Keith Packard
|
||||
*
|
||||
* Contributor(s):
|
||||
* Keith Packard <keithp@keithp.com>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_ANALYSIS_SURFACE_H
|
||||
#define CAIRO_ANALYSIS_SURFACE_H
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_analysis_surface_create (cairo_surface_t *target,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
cairo_private pixman_region16_t *
|
||||
_cairo_analysis_surface_get_supported (cairo_surface_t *surface);
|
||||
|
||||
cairo_private pixman_region16_t *
|
||||
_cairo_analysis_surface_get_unsupported (cairo_surface_t *unsupported);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_analysis_surface_has_unsupported (cairo_surface_t *unsupported);
|
||||
|
||||
#endif /* CAIRO_ANALYSIS_SURFACE_H */
|
||||
256
src/cairo-analysis-surface.c
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* Copyright © 2006 Keith Packard
|
||||
*
|
||||
* 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 Keith Packard
|
||||
*
|
||||
* Contributor(s):
|
||||
* Keith Packard <keithp@keithp.com>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-analysis-surface-private.h"
|
||||
#include "cairo-paginated-surface-private.h"
|
||||
|
||||
typedef struct {
|
||||
cairo_surface_t base;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
cairo_surface_t *target;
|
||||
|
||||
cairo_bool_t fallback;
|
||||
} cairo_analysis_surface_t;
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_analysis_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_t *rectangle)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
|
||||
return _cairo_surface_get_extents (surface->target, rectangle);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_analysis_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
if (!surface->target->backend->paint)
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
else
|
||||
status = (*surface->target->backend->paint) (surface->target, op,
|
||||
source);
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
surface->fallback = TRUE;
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_analysis_surface_mask (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
cairo_pattern_t *mask)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
if (!surface->target->backend->mask)
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
else
|
||||
status = (*surface->target->backend->mask) (surface->target, op,
|
||||
source, mask);
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
surface->fallback = TRUE;
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_analysis_surface_stroke (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
if (!surface->target->backend->stroke)
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
else
|
||||
status = (*surface->target->backend->stroke) (surface->target, op,
|
||||
source, path, style,
|
||||
ctm, ctm_inverse,
|
||||
tolerance, antialias);
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
surface->fallback = TRUE;
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_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,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
if (!surface->target->backend->fill)
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
else
|
||||
status = (*surface->target->backend->fill) (surface->target, op,
|
||||
source, path, fill_rule,
|
||||
tolerance, antialias);
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
surface->fallback = TRUE;
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_analysis_surface_show_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
if (!surface->target->backend->show_glyphs)
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
else
|
||||
status = (*surface->target->backend->show_glyphs) (surface->target, op,
|
||||
source,
|
||||
glyphs, num_glyphs,
|
||||
scaled_font);
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
surface->fallback = TRUE;
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_analysis_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
|
||||
NULL, /* create_similar */
|
||||
NULL, /* finish_surface */
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
NULL, /* acquire_dest_image */
|
||||
NULL, /* release_dest_image */
|
||||
NULL, /* clone_similar */
|
||||
NULL, /* composite */
|
||||
NULL, /* fill_rectangles */
|
||||
NULL, /* composite_trapezoids */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
NULL, /* set_clip_region */
|
||||
NULL, /* clip_path */
|
||||
_cairo_analysis_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
NULL, /* flush */
|
||||
NULL, /* mark_dirty_rectangle */
|
||||
NULL, /* scaled_font_fini */
|
||||
NULL, /* scaled_glyph_fini */
|
||||
_cairo_analysis_surface_paint,
|
||||
_cairo_analysis_surface_mask,
|
||||
_cairo_analysis_surface_stroke,
|
||||
_cairo_analysis_surface_fill,
|
||||
_cairo_analysis_surface_show_glyphs,
|
||||
NULL, /* snapshot */
|
||||
};
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_analysis_surface_create (cairo_surface_t *target,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_analysis_surface_t *surface;
|
||||
|
||||
surface = malloc (sizeof (cairo_analysis_surface_t));
|
||||
if (surface == NULL)
|
||||
goto FAIL;
|
||||
|
||||
_cairo_surface_init (&surface->base, &cairo_analysis_surface_backend);
|
||||
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
|
||||
surface->target = target;
|
||||
surface->fallback = FALSE;
|
||||
|
||||
return &surface->base;
|
||||
FAIL:
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cairo_private pixman_region16_t *
|
||||
_cairo_analysis_surface_get_supported (cairo_surface_t *abstract_surface)
|
||||
{
|
||||
/* XXX */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cairo_private pixman_region16_t *
|
||||
_cairo_analysis_surface_get_unsupported (cairo_surface_t *abstract_surface)
|
||||
{
|
||||
/* XXX */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_analysis_surface_has_unsupported (cairo_surface_t *abstract_surface)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface;
|
||||
|
||||
return surface->fallback;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -40,6 +40,16 @@
|
|||
#include "cairo.h"
|
||||
#include "cairo-quartz-private.h"
|
||||
|
||||
/*
|
||||
* FixedToFloat/FloatToFixed are 10.3+ SDK items - include definitions
|
||||
* here so we can use older SDKs.
|
||||
*/
|
||||
#ifndef FixedToFloat
|
||||
#define fixed1 ((Fixed) 0x00010000L)
|
||||
#define FixedToFloat(a) ((float)(a) / fixed1)
|
||||
#define FloatToFixed(a) ((Fixed)((float)(a) * fixed1))
|
||||
#endif
|
||||
|
||||
typedef struct _cairo_atsui_font_face cairo_atsui_font_face_t;
|
||||
typedef struct _cairo_atsui_font cairo_atsui_font_t;
|
||||
|
||||
|
|
@ -94,6 +104,7 @@ _cairo_atsui_font_face_scaled_font_create (void *abstract_face,
|
|||
}
|
||||
|
||||
static const cairo_font_face_backend_t _cairo_atsui_font_face_backend = {
|
||||
CAIRO_FONT_TYPE_ATSUI,
|
||||
_cairo_atsui_font_face_destroy,
|
||||
_cairo_atsui_font_face_scaled_font_create
|
||||
};
|
||||
|
|
@ -132,7 +143,7 @@ CreateSizedCopyOfStyle(ATSUStyle inStyle, const cairo_matrix_t *scale)
|
|||
ATSUStyle style;
|
||||
OSStatus err;
|
||||
|
||||
// Set the style's size
|
||||
/* Set the style's size */
|
||||
CGAffineTransform theTransform =
|
||||
CGAffineTransformMakeWithCairoFontScale(scale);
|
||||
Fixed theSize =
|
||||
|
|
@ -174,7 +185,7 @@ _cairo_atsui_font_set_metrics (cairo_atsui_font_t *font)
|
|||
extents.height = metrics.capHeight;
|
||||
extents.max_x_advance = metrics.maxAdvanceWidth;
|
||||
|
||||
// The FT backend doesn't handle max_y_advance either, so we'll ignore it for now.
|
||||
/* The FT backend doesn't handle max_y_advance either, so we'll ignore it for now. */
|
||||
extents.max_y_advance = 0.0;
|
||||
|
||||
_cairo_scaled_font_set_metrics (&font->base, &extents);
|
||||
|
|
@ -275,7 +286,7 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
|
|||
kFontNoLanguageCode, &fontID);
|
||||
|
||||
if (err != noErr) {
|
||||
// couldn't get the font - remap css names and try again
|
||||
/* couldn't get the font - remap css names and try again */
|
||||
|
||||
if (!strcmp(family, "serif"))
|
||||
family = "Times";
|
||||
|
|
@ -287,7 +298,7 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
|
|||
family = "Gadget";
|
||||
else if (!strcmp(family, "monospace"))
|
||||
family = "Courier";
|
||||
else // anything else - return error instead?
|
||||
else /* anything else - return error instead? */
|
||||
family = "Courier";
|
||||
|
||||
err = ATSUFindFontFromName(family, strlen(family),
|
||||
|
|
@ -504,7 +515,7 @@ _cairo_atsui_font_text_to_glyphs (void *abstract_font,
|
|||
|
||||
err = ATSUSetTextPointerLocation(textLayout, utf16, 0, n16, n16);
|
||||
|
||||
// Set the style for all of the text
|
||||
/* Set the style for all of the text */
|
||||
err = ATSUSetRunStyle(textLayout,
|
||||
font->style, kATSUFromTextBeginning, kATSUToTextEnd);
|
||||
|
||||
|
|
@ -552,117 +563,140 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
|
|||
int num_glyphs)
|
||||
{
|
||||
cairo_atsui_font_t *font = abstract_font;
|
||||
CGContextRef myBitmapContext;
|
||||
CGColorSpaceRef colorSpace;
|
||||
CGContextRef myBitmapContext = 0, drawingContext;
|
||||
CGColorSpaceRef colorSpace = 0;;
|
||||
cairo_image_surface_t *destImageSurface;
|
||||
int i;
|
||||
void *extra = NULL;
|
||||
cairo_bool_t can_draw_directly;
|
||||
cairo_rectangle_t rect;
|
||||
|
||||
cairo_rectangle_t rect = {dest_x, dest_y, width, height};
|
||||
_cairo_surface_acquire_dest_image(generic_surface,
|
||||
&rect,
|
||||
&destImageSurface,
|
||||
&rect,
|
||||
&extra);
|
||||
/* Check if we can draw directly to the destination surface */
|
||||
can_draw_directly = _cairo_surface_is_quartz (generic_surface) &&
|
||||
_cairo_pattern_is_opaque_solid (pattern) &&
|
||||
op == CAIRO_OPERATOR_OVER;
|
||||
|
||||
// Create a CGBitmapContext for the dest surface for drawing into
|
||||
colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
if (!can_draw_directly) {
|
||||
rect.x = dest_x;
|
||||
rect.y = dest_y;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
|
||||
myBitmapContext = CGBitmapContextCreate(destImageSurface->data,
|
||||
destImageSurface->width,
|
||||
destImageSurface->height,
|
||||
destImageSurface->depth / 4,
|
||||
destImageSurface->stride,
|
||||
colorSpace,
|
||||
kCGImageAlphaPremultipliedFirst);
|
||||
CGContextTranslateCTM(myBitmapContext, 0, destImageSurface->height);
|
||||
CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f);
|
||||
_cairo_surface_acquire_dest_image(generic_surface,
|
||||
&rect,
|
||||
&destImageSurface,
|
||||
&rect,
|
||||
&extra);
|
||||
|
||||
/* Create a CGBitmapContext for the dest surface for drawing into */
|
||||
colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
|
||||
myBitmapContext = CGBitmapContextCreate(destImageSurface->data,
|
||||
destImageSurface->width,
|
||||
destImageSurface->height,
|
||||
destImageSurface->depth / 4,
|
||||
destImageSurface->stride,
|
||||
colorSpace,
|
||||
kCGImageAlphaPremultipliedFirst);
|
||||
CGContextTranslateCTM(myBitmapContext, 0, destImageSurface->height);
|
||||
CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f);
|
||||
|
||||
drawingContext = myBitmapContext;
|
||||
} else {
|
||||
drawingContext = ((cairo_quartz_surface_t *)generic_surface)->context;
|
||||
CGContextSaveGState (drawingContext);
|
||||
}
|
||||
|
||||
ATSFontRef atsFont = FMGetATSFontRefFromFont(font->fontID);
|
||||
CGFontRef cgFont = CGFontCreateWithPlatformFont(&atsFont);
|
||||
|
||||
CGContextSetFont(myBitmapContext, cgFont);
|
||||
CGContextSetFont(drawingContext, cgFont);
|
||||
|
||||
CGAffineTransform textTransform =
|
||||
CGAffineTransformMakeWithCairoFontScale(&font->base.scale);
|
||||
|
||||
textTransform = CGAffineTransformScale(textTransform, 1.0f, -1.0f);
|
||||
|
||||
CGContextSetFontSize(myBitmapContext, 1.0);
|
||||
CGContextSetTextMatrix(myBitmapContext, textTransform);
|
||||
CGContextSetFontSize(drawingContext, 1.0);
|
||||
CGContextSetTextMatrix(drawingContext, textTransform);
|
||||
|
||||
if (pattern->type == CAIRO_PATTERN_SOLID &&
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID &&
|
||||
_cairo_pattern_is_opaque_solid(pattern))
|
||||
{
|
||||
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern;
|
||||
CGContextSetRGBFillColor(myBitmapContext,
|
||||
CGContextSetRGBFillColor(drawingContext,
|
||||
solid->color.red,
|
||||
solid->color.green,
|
||||
solid->color.blue, 1.0f);
|
||||
} else {
|
||||
CGContextSetRGBFillColor(myBitmapContext, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||
CGContextSetRGBFillColor(drawingContext, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
if (_cairo_surface_is_quartz (generic_surface)) {
|
||||
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface;
|
||||
if (surface->clip_region) {
|
||||
pixman_box16_t *boxes = pixman_region_rects (surface->clip_region);
|
||||
int num_boxes = pixman_region_num_rects (surface->clip_region);
|
||||
CGRect stack_rects[10];
|
||||
CGRect *rects;
|
||||
int i;
|
||||
|
||||
if (num_boxes > 10)
|
||||
rects = malloc (sizeof (CGRect) * num_boxes);
|
||||
else
|
||||
rects = stack_rects;
|
||||
|
||||
for (i = 0; i < num_boxes; i++) {
|
||||
rects[i].origin.x = boxes[i].x1;
|
||||
rects[i].origin.y = boxes[i].y1;
|
||||
rects[i].size.width = boxes[i].x2 - boxes[i].x1;
|
||||
rects[i].size.height = boxes[i].y2 - boxes[i].y1;
|
||||
}
|
||||
|
||||
CGContextClipToRects (myBitmapContext, rects, num_boxes);
|
||||
|
||||
if (rects != stack_rects)
|
||||
free(rects);
|
||||
}
|
||||
} else {
|
||||
/* XXX: Need to get the text clipped */
|
||||
if (_cairo_surface_is_quartz (generic_surface)) {
|
||||
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface;
|
||||
if (surface->clip_region) {
|
||||
pixman_box16_t *boxes = pixman_region_rects (surface->clip_region);
|
||||
int num_boxes = pixman_region_num_rects (surface->clip_region);
|
||||
CGRect stack_rects[10];
|
||||
CGRect *rects;
|
||||
int i;
|
||||
|
||||
if (num_boxes > 10)
|
||||
rects = malloc (sizeof (CGRect) * num_boxes);
|
||||
else
|
||||
rects = stack_rects;
|
||||
|
||||
for (i = 0; i < num_boxes; i++) {
|
||||
rects[i].origin.x = boxes[i].x1;
|
||||
rects[i].origin.y = boxes[i].y1;
|
||||
rects[i].size.width = boxes[i].x2 - boxes[i].x1;
|
||||
rects[i].size.height = boxes[i].y2 - boxes[i].y1;
|
||||
}
|
||||
|
||||
CGContextClipToRects (drawingContext, rects, num_boxes);
|
||||
|
||||
if (rects != stack_rects)
|
||||
free(rects);
|
||||
}
|
||||
} else {
|
||||
/* XXX: Need to get the text clipped */
|
||||
}
|
||||
|
||||
// TODO - bold and italic text
|
||||
//
|
||||
// We could draw the text using ATSUI and get bold, italics
|
||||
// etc. for free, but ATSUI does a lot of text layout work
|
||||
// that we don't really need...
|
||||
/* TODO - bold and italic text
|
||||
*
|
||||
* We could draw the text using ATSUI and get bold, italics
|
||||
* etc. for free, but ATSUI does a lot of text layout work
|
||||
* that we don't really need...
|
||||
*/
|
||||
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
CGGlyph theGlyph = glyphs[i].index;
|
||||
|
||||
CGContextShowGlyphsAtPoint(myBitmapContext,
|
||||
CGContextShowGlyphsAtPoint(drawingContext,
|
||||
glyphs[i].x,
|
||||
glyphs[i].y,
|
||||
&theGlyph, 1);
|
||||
}
|
||||
|
||||
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
CGContextRelease(myBitmapContext);
|
||||
|
||||
_cairo_surface_release_dest_image(generic_surface,
|
||||
&rect,
|
||||
destImageSurface,
|
||||
&rect,
|
||||
extra);
|
||||
if (!can_draw_directly) {
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
CGContextRelease(myBitmapContext);
|
||||
|
||||
_cairo_surface_release_dest_image(generic_surface,
|
||||
&rect,
|
||||
destImageSurface,
|
||||
&rect,
|
||||
extra);
|
||||
} else {
|
||||
CGContextRestoreGState (drawingContext);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = {
|
||||
CAIRO_FONT_TYPE_ATSUI,
|
||||
_cairo_atsui_font_create_toy,
|
||||
_cairo_atsui_font_fini,
|
||||
_cairo_atsui_font_scaled_glyph_init,
|
||||
|
|
|
|||
130
src/cairo-base85-stream.c
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/* cairo_output_stream.c: Output stream abstraction
|
||||
*
|
||||
* Copyright © 2005 Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* 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 cairo_output_stream.c as distributed with the
|
||||
* cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*
|
||||
* Author(s):
|
||||
* Kristian Høgsberg <krh@redhat.com>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
typedef struct _cairo_base85_stream {
|
||||
cairo_output_stream_t *output;
|
||||
unsigned char four_tuple[4];
|
||||
int pending;
|
||||
} cairo_base85_stream_t;
|
||||
|
||||
static void
|
||||
_expand_four_tuple_to_five (unsigned char four_tuple[4],
|
||||
unsigned char five_tuple[5],
|
||||
cairo_bool_t *all_zero)
|
||||
{
|
||||
uint32_t value;
|
||||
int digit, i;
|
||||
|
||||
value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3];
|
||||
if (all_zero)
|
||||
*all_zero = TRUE;
|
||||
for (i = 0; i < 5; i++) {
|
||||
digit = value % 85;
|
||||
if (digit != 0 && all_zero)
|
||||
*all_zero = FALSE;
|
||||
five_tuple[4-i] = digit + 33;
|
||||
value = value / 85;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_base85_stream_write (void *closure,
|
||||
const unsigned char *data,
|
||||
unsigned int length)
|
||||
{
|
||||
cairo_base85_stream_t *stream = closure;
|
||||
const unsigned char *ptr = data;
|
||||
unsigned char five_tuple[5];
|
||||
cairo_bool_t is_zero;
|
||||
|
||||
while (length) {
|
||||
stream->four_tuple[stream->pending++] = *ptr++;
|
||||
length--;
|
||||
if (stream->pending == 4) {
|
||||
_expand_four_tuple_to_five (stream->four_tuple, five_tuple, &is_zero);
|
||||
if (is_zero)
|
||||
_cairo_output_stream_write (stream->output, "z", 1);
|
||||
else
|
||||
_cairo_output_stream_write (stream->output, five_tuple, 5);
|
||||
stream->pending = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return _cairo_output_stream_get_status (stream->output);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_base85_stream_close (void *closure)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_base85_stream_t *stream = closure;
|
||||
unsigned char five_tuple[5];
|
||||
|
||||
if (stream->pending) {
|
||||
memset (stream->four_tuple + stream->pending, 0, 4 - stream->pending);
|
||||
_expand_four_tuple_to_five (stream->four_tuple, five_tuple, NULL);
|
||||
_cairo_output_stream_write (stream->output, five_tuple, stream->pending + 1);
|
||||
}
|
||||
|
||||
/* Mark end of base85 data */
|
||||
_cairo_output_stream_printf (stream->output, "~>");
|
||||
|
||||
status = _cairo_output_stream_get_status (stream->output);
|
||||
|
||||
free (stream);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_output_stream_t *
|
||||
_cairo_base85_stream_create (cairo_output_stream_t *output)
|
||||
{
|
||||
cairo_base85_stream_t *stream;
|
||||
|
||||
stream = malloc (sizeof (cairo_base85_stream_t));
|
||||
if (stream == NULL)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil;
|
||||
|
||||
stream->output = output;
|
||||
stream->pending = 0;
|
||||
|
||||
return _cairo_output_stream_create (_cairo_base85_stream_write,
|
||||
_cairo_base85_stream_close,
|
||||
stream);
|
||||
}
|
||||
|
||||
|
|
@ -70,6 +70,9 @@ struct cairo_beos_surface_t {
|
|||
BBitmap* bitmap;
|
||||
|
||||
|
||||
// If true, surface and view should be deleted when this surface is
|
||||
// destroyed
|
||||
bool owns_bitmap_view;
|
||||
};
|
||||
|
||||
class AutoLockView {
|
||||
|
|
@ -92,6 +95,11 @@ class AutoLockView {
|
|||
bool mOK;
|
||||
};
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_beos_surface_create_internal (BView* view,
|
||||
BBitmap* bmp,
|
||||
bool owns_bitmap_view = false);
|
||||
|
||||
static BRect
|
||||
_cairo_rect_to_brect (const cairo_rectangle_t* rect)
|
||||
{
|
||||
|
|
@ -359,6 +367,7 @@ _cairo_image_surface_to_bitmap (cairo_image_surface_t* surface)
|
|||
return data;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -414,10 +423,76 @@ _cairo_op_to_be_op (cairo_operator_t cairo_op,
|
|||
};
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_beos_surface_create_similar (void *abstract_surface,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
fprintf(stderr, "Creating similar\n");
|
||||
|
||||
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
|
||||
abstract_surface);
|
||||
|
||||
if (width <= 0)
|
||||
width = 1;
|
||||
if (height <= 0)
|
||||
height = 1;
|
||||
|
||||
BRect rect(0.0, 0.0, width - 1, height - 1);
|
||||
BBitmap* bmp;
|
||||
switch (content) {
|
||||
case CAIRO_CONTENT_ALPHA:
|
||||
// Can't support this natively
|
||||
return _cairo_image_surface_create_with_content(content, width,
|
||||
height);
|
||||
case CAIRO_CONTENT_COLOR_ALPHA:
|
||||
bmp = new BBitmap(rect, B_RGBA32, true);
|
||||
break;
|
||||
case CAIRO_CONTENT_COLOR:
|
||||
// Match the color depth
|
||||
if (surface->bitmap) {
|
||||
color_space space = surface->bitmap->ColorSpace();
|
||||
// No alpha was requested -> make sure not to return
|
||||
// a surface with alpha
|
||||
if (space == B_RGBA32)
|
||||
space = B_RGB32;
|
||||
if (space == B_RGBA15)
|
||||
space = B_RGB15;
|
||||
bmp = new BBitmap(rect, space, true);
|
||||
} else {
|
||||
BScreen scr(surface->view->Window());
|
||||
color_space space = B_RGB32;
|
||||
if (scr.IsValid())
|
||||
space = scr.ColorSpace();
|
||||
bmp = new BBitmap(rect, space, true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return NULL;
|
||||
|
||||
};
|
||||
BView* view = new BView(rect, "Cairo bitmap view", B_FOLLOW_ALL_SIDES, 0);
|
||||
bmp->AddChild(view);
|
||||
return _cairo_beos_surface_create_internal(view, bmp, true);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_beos_surface_finish (void *abstract_surface)
|
||||
{
|
||||
// Nothing to do
|
||||
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
|
||||
abstract_surface);
|
||||
if (surface->owns_bitmap_view) {
|
||||
if (surface->bitmap)
|
||||
surface->bitmap->RemoveChild(surface->view);
|
||||
|
||||
delete surface->view;
|
||||
delete surface->bitmap;
|
||||
|
||||
surface->view = NULL;
|
||||
surface->bitmap = NULL;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -549,13 +624,12 @@ _cairo_beos_surface_release_dest_image (void *abstract_surface,
|
|||
|
||||
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
|
||||
abstract_surface);
|
||||
|
||||
AutoLockView locker(surface->view);
|
||||
if (!locker)
|
||||
return;
|
||||
|
||||
|
||||
BBitmap* bitmap_to_draw = _cairo_image_surface_to_bitmap(image);
|
||||
|
||||
surface->view->PushState();
|
||||
|
||||
surface->view->SetDrawingMode(B_OP_COPY);
|
||||
|
|
@ -570,18 +644,18 @@ _cairo_beos_surface_release_dest_image (void *abstract_surface,
|
|||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_beos_composite (cairo_operator_t op,
|
||||
cairo_pattern_t *src,
|
||||
cairo_pattern_t *mask,
|
||||
void *dst,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int mask_x,
|
||||
int mask_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height)
|
||||
_cairo_beos_surface_composite (cairo_operator_t op,
|
||||
cairo_pattern_t *src,
|
||||
cairo_pattern_t *mask,
|
||||
void *dst,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int mask_x,
|
||||
int mask_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height)
|
||||
{
|
||||
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
|
||||
dst);
|
||||
|
|
@ -598,7 +672,7 @@ _cairo_beos_composite (cairo_operator_t op,
|
|||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
// XXX should eventually support the others
|
||||
if (src->type != CAIRO_PATTERN_SURFACE ||
|
||||
if (src->type != CAIRO_PATTERN_TYPE_SURFACE ||
|
||||
src->extend != CAIRO_EXTEND_NONE)
|
||||
{
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
|
@ -617,63 +691,95 @@ _cairo_beos_composite (cairo_operator_t op,
|
|||
|
||||
cairo_surface_t* src_surface = reinterpret_cast<cairo_surface_pattern_t*>(src)->
|
||||
surface;
|
||||
if (_cairo_surface_is_image(src_surface)) {
|
||||
fprintf(stderr, "Composite\n");
|
||||
|
||||
// Draw it on screen.
|
||||
// Get a bitmap
|
||||
BBitmap* bmp = NULL;
|
||||
bool free_bmp = false;
|
||||
if (_cairo_surface_is_image(src_surface)) {
|
||||
cairo_image_surface_t* img_surface =
|
||||
reinterpret_cast<cairo_image_surface_t*>(src_surface);
|
||||
|
||||
BBitmap* bmp = _cairo_image_surface_to_bitmap(img_surface);
|
||||
surface->view->PushState();
|
||||
|
||||
// If our image rect is only a subrect of the desired size, and we
|
||||
// aren't using B_OP_ALPHA, then we need to fill the rect first.
|
||||
if (mode == B_OP_COPY && !bmp->Bounds().Contains(srcRect)) {
|
||||
rgb_color black = { 0, 0, 0, 0 };
|
||||
|
||||
surface->view->SetDrawingMode(mode);
|
||||
surface->view->SetHighColor(black);
|
||||
surface->view->FillRect(dstRect);
|
||||
}
|
||||
|
||||
if (mode == B_OP_ALPHA && img_surface->format != CAIRO_FORMAT_ARGB32) {
|
||||
mode = B_OP_COPY;
|
||||
|
||||
}
|
||||
surface->view->SetDrawingMode(mode);
|
||||
|
||||
if (surface->bitmap && surface->bitmap->ColorSpace() == B_RGBA32)
|
||||
surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
|
||||
else
|
||||
surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
|
||||
|
||||
surface->view->DrawBitmap(bmp, srcRect, dstRect);
|
||||
|
||||
surface->view->PopState();
|
||||
delete bmp;
|
||||
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
bmp = _cairo_image_surface_to_bitmap(img_surface);
|
||||
free_bmp = true;
|
||||
} else if (src_surface->backend == surface->base.backend) {
|
||||
cairo_beos_surface_t *beos_surface =
|
||||
reinterpret_cast<cairo_beos_surface_t*>(src_surface);
|
||||
if (beos_surface->bitmap) {
|
||||
AutoLockView locker(beos_surface->view);
|
||||
if (locker)
|
||||
beos_surface->view->Sync();
|
||||
bmp = beos_surface->bitmap;
|
||||
} else {
|
||||
_cairo_beos_view_to_bitmap(surface->view, &bmp);
|
||||
free_bmp = true;
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (!bmp)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
// So, BeOS seems to screw up painting an opaque bitmap onto a
|
||||
// translucent one (it makes them partly transparent). Just return
|
||||
// unsupported.
|
||||
if (bmp->ColorSpace() == B_RGB32 && surface->bitmap &&
|
||||
surface->bitmap->ColorSpace() == B_RGBA32 &&
|
||||
(mode == B_OP_COPY || mode == B_OP_ALPHA))
|
||||
{
|
||||
if (free_bmp)
|
||||
delete bmp;
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Composite\n");
|
||||
|
||||
// Draw it on screen.
|
||||
surface->view->PushState();
|
||||
|
||||
// If our image rect is only a subrect of the desired size, and we
|
||||
// aren't using B_OP_ALPHA, then we need to fill the rect first.
|
||||
if (mode == B_OP_COPY && !bmp->Bounds().Contains(srcRect)) {
|
||||
rgb_color black = { 0, 0, 0, 0 };
|
||||
|
||||
surface->view->SetDrawingMode(mode);
|
||||
surface->view->SetHighColor(black);
|
||||
surface->view->FillRect(dstRect);
|
||||
}
|
||||
|
||||
if (mode == B_OP_ALPHA && bmp->ColorSpace() == B_RGB32) {
|
||||
mode = B_OP_COPY;
|
||||
}
|
||||
surface->view->SetDrawingMode(mode);
|
||||
|
||||
if (surface->bitmap && surface->bitmap->ColorSpace() == B_RGBA32)
|
||||
surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
|
||||
else
|
||||
surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
|
||||
|
||||
surface->view->DrawBitmap(bmp, srcRect, dstRect);
|
||||
|
||||
surface->view->PopState();
|
||||
|
||||
if (free_bmp)
|
||||
delete bmp;
|
||||
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_cairo_beos_fill_rectangle (cairo_beos_surface_t *surface,
|
||||
cairo_rectangle_t *rect)
|
||||
_cairo_beos_surface_fill_rectangle (cairo_beos_surface_t *surface,
|
||||
cairo_rectangle_t *rect)
|
||||
{
|
||||
BRect brect(_cairo_rect_to_brect(rect));
|
||||
surface->view->FillRect(brect);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_beos_fill_rectangles (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_color_t *color,
|
||||
cairo_rectangle_t *rects,
|
||||
int num_rects)
|
||||
_cairo_beos_surface_fill_rectangles (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_color_t *color,
|
||||
cairo_rectangle_t *rects,
|
||||
int num_rects)
|
||||
{
|
||||
fprintf(stderr, "Drawing %i rectangles\n", num_rects);
|
||||
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
|
||||
|
|
@ -716,7 +822,7 @@ _cairo_beos_fill_rectangles (void *abstract_surface,
|
|||
surface->view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
|
||||
|
||||
for (int i = 0; i < num_rects; ++i) {
|
||||
_cairo_beos_fill_rectangle(surface, &rects[i]);
|
||||
_cairo_beos_surface_fill_rectangle(surface, &rects[i]);
|
||||
}
|
||||
|
||||
surface->view->PopState();
|
||||
|
|
@ -777,15 +883,16 @@ _cairo_beos_surface_get_extents (void *abstract_surface,
|
|||
}
|
||||
|
||||
static const struct _cairo_surface_backend cairo_beos_surface_backend = {
|
||||
NULL, /* create_similar */
|
||||
CAIRO_SURFACE_TYPE_BEOS,
|
||||
_cairo_beos_surface_create_similar,
|
||||
_cairo_beos_surface_finish,
|
||||
_cairo_beos_surface_acquire_source_image,
|
||||
_cairo_beos_surface_release_source_image,
|
||||
_cairo_beos_surface_acquire_dest_image,
|
||||
_cairo_beos_surface_release_dest_image,
|
||||
NULL, /* clone_similar */
|
||||
_cairo_beos_composite, /* composite */
|
||||
_cairo_beos_fill_rectangles,
|
||||
_cairo_beos_surface_composite, /* composite */
|
||||
_cairo_beos_surface_fill_rectangles,
|
||||
NULL, /* composite_trapezoids */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
|
|
@ -806,6 +913,28 @@ static const struct _cairo_surface_backend cairo_beos_surface_backend = {
|
|||
NULL /* show_glyphs */
|
||||
};
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_beos_surface_create_internal (BView* view,
|
||||
BBitmap* bmp,
|
||||
bool owns_bitmap_view)
|
||||
{
|
||||
// Must use malloc, because cairo code will use free() on the surface
|
||||
cairo_beos_surface_t *surface = static_cast<cairo_beos_surface_t*>(
|
||||
malloc(sizeof(cairo_beos_surface_t)));
|
||||
if (surface == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return const_cast<cairo_surface_t*>(&_cairo_surface_nil);
|
||||
}
|
||||
|
||||
_cairo_surface_init(&surface->base, &cairo_beos_surface_backend);
|
||||
|
||||
surface->view = view;
|
||||
surface->bitmap = bmp;
|
||||
surface->owns_bitmap_view = owns_bitmap_view;
|
||||
|
||||
return (cairo_surface_t *) surface;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_beos_surface_create:
|
||||
* @view: The view to draw on
|
||||
|
|
@ -842,20 +971,7 @@ cairo_surface_t *
|
|||
cairo_beos_surface_create_for_bitmap (BView* view,
|
||||
BBitmap* bmp)
|
||||
{
|
||||
// Must use malloc, because cairo code will use free() on the surface
|
||||
cairo_beos_surface_t *surface = static_cast<cairo_beos_surface_t*>(
|
||||
malloc(sizeof(cairo_beos_surface_t)));
|
||||
if (surface == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return const_cast<cairo_surface_t*>(&_cairo_surface_nil);
|
||||
}
|
||||
|
||||
_cairo_surface_init(&surface->base, &cairo_beos_surface_backend);
|
||||
|
||||
surface->view = view;
|
||||
surface->bitmap = bmp;
|
||||
|
||||
return (cairo_surface_t *) surface;
|
||||
return _cairo_beos_surface_create_internal(view, bmp);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ typedef struct _cairo_cache_entry {
|
|||
} cairo_cache_entry_t;
|
||||
|
||||
typedef cairo_bool_t
|
||||
(*cairo_cache_keys_equal_func_t) (void *key_a, void *key_b);
|
||||
(*cairo_cache_keys_equal_func_t) (const void *key_a, const void *key_b);
|
||||
|
||||
typedef void
|
||||
(*cairo_cache_callback_func_t) (void *entry,
|
||||
|
|
|
|||
|
|
@ -248,8 +248,10 @@ _cairo_clip_intersect_path (cairo_clip_t *clip,
|
|||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
status = _cairo_path_fixed_init_copy (&clip_path->path, path);
|
||||
if (status)
|
||||
if (status) {
|
||||
free (clip_path);
|
||||
return status;
|
||||
}
|
||||
|
||||
clip_path->ref_count = 1;
|
||||
clip_path->fill_rule = fill_rule;
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ static inline int cairo_to_directfb_format(cairo_format_t format ) {
|
|||
return DSPF_A1;
|
||||
default:
|
||||
{
|
||||
//assert(0);
|
||||
/*assert(0);*/
|
||||
return DSPF_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
|
@ -483,9 +483,9 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
|
|||
if( _dfb_set_operator(op,surface->buffer) == DFB_UNSUPPORTED )
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (src_pattern->type == CAIRO_PATTERN_SOLID ) {
|
||||
if (src_pattern->type == CAIRO_PATTERN_TYPE_SOLID ) {
|
||||
|
||||
} else if (src_pattern->type != CAIRO_PATTERN_SURFACE ||
|
||||
} else if (src_pattern->type != CAIRO_PATTERN_TYPE_SURFACE ||
|
||||
src_pattern->extend != CAIRO_EXTEND_NONE) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
|
@ -494,7 +494,7 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
|
|||
/* FIXME: When we fully support RENDER style 4-channel
|
||||
* masks we need to check r/g/b != 1.0.
|
||||
*/
|
||||
if (mask_pattern->type != CAIRO_PATTERN_SOLID)
|
||||
if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
alpha = ((cairo_solid_pattern_t *)mask_pattern)->color.alpha_short >> 8;
|
||||
|
|
@ -662,6 +662,7 @@ _cairo_directfb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
|
|||
|
||||
|
||||
static const cairo_surface_backend_t cairo_directfb_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_DIRECTFB,
|
||||
_cairo_directfb_surface_create_similar,
|
||||
_cairo_directfb_surface_finish,
|
||||
_cairo_directfb_surface_acquire_source_image,
|
||||
|
|
|
|||
|
|
@ -130,6 +130,18 @@ cairo_font_face_destroy (cairo_font_face_t *font_face)
|
|||
free (font_face);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_font_face_get_type:
|
||||
* @font_face: a #cairo_font_face_t
|
||||
*
|
||||
* Return value: The type of @font_face. See #cairo_font_type_t.
|
||||
**/
|
||||
cairo_font_type_t
|
||||
cairo_font_face_get_type (cairo_font_face_t *font_face)
|
||||
{
|
||||
return font_face->backend->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_font_face_status:
|
||||
* @font_face: a #cairo_font_face_t
|
||||
|
|
@ -198,8 +210,8 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face,
|
|||
static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
|
||||
|
||||
static int
|
||||
_cairo_toy_font_face_keys_equal (void *key_a,
|
||||
void *key_b);
|
||||
_cairo_toy_font_face_keys_equal (const void *key_a,
|
||||
const void *key_b);
|
||||
|
||||
/* We maintain a hash table from family/weight/slant =>
|
||||
* cairo_font_face_t for cairo_toy_font_t. The primary purpose of
|
||||
|
|
@ -300,11 +312,11 @@ _cairo_toy_font_face_fini (cairo_toy_font_face_t *font_face)
|
|||
}
|
||||
|
||||
static int
|
||||
_cairo_toy_font_face_keys_equal (void *key_a,
|
||||
void *key_b)
|
||||
_cairo_toy_font_face_keys_equal (const void *key_a,
|
||||
const void *key_b)
|
||||
{
|
||||
cairo_toy_font_face_t *face_a = key_a;
|
||||
cairo_toy_font_face_t *face_b = key_b;
|
||||
const cairo_toy_font_face_t *face_a = key_a;
|
||||
const cairo_toy_font_face_t *face_b = key_b;
|
||||
|
||||
return (strcmp (face_a->family, face_b->family) == 0 &&
|
||||
face_a->slant == face_b->slant &&
|
||||
|
|
@ -409,6 +421,7 @@ _cairo_toy_font_face_scaled_font_create (void *abstract_font_face
|
|||
}
|
||||
|
||||
static const cairo_font_face_backend_t _cairo_toy_font_face_backend = {
|
||||
CAIRO_FONT_TYPE_TOY,
|
||||
_cairo_toy_font_face_destroy,
|
||||
_cairo_toy_font_face_scaled_font_create
|
||||
};
|
||||
|
|
|
|||
|
|
@ -103,8 +103,8 @@ struct _cairo_ft_unscaled_font {
|
|||
};
|
||||
|
||||
static int
|
||||
_cairo_ft_unscaled_font_keys_equal (void *key_a,
|
||||
void *key_b);
|
||||
_cairo_ft_unscaled_font_keys_equal (const void *key_a,
|
||||
const void *key_b);
|
||||
|
||||
static void
|
||||
_cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled);
|
||||
|
|
@ -365,11 +365,11 @@ _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled)
|
|||
}
|
||||
|
||||
static int
|
||||
_cairo_ft_unscaled_font_keys_equal (void *key_a,
|
||||
void *key_b)
|
||||
_cairo_ft_unscaled_font_keys_equal (const void *key_a,
|
||||
const void *key_b)
|
||||
{
|
||||
cairo_ft_unscaled_font_t *unscaled_a = key_a;
|
||||
cairo_ft_unscaled_font_t *unscaled_b = key_b;
|
||||
const cairo_ft_unscaled_font_t *unscaled_a = key_a;
|
||||
const cairo_ft_unscaled_font_t *unscaled_b = key_b;
|
||||
|
||||
return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0 &&
|
||||
unscaled_a->id == unscaled_b->id);
|
||||
|
|
@ -1901,6 +1901,7 @@ _cairo_ft_show_glyphs (void *abstract_font,
|
|||
}
|
||||
|
||||
const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
|
||||
CAIRO_FONT_TYPE_FT,
|
||||
_cairo_ft_scaled_font_create_toy,
|
||||
_cairo_ft_scaled_font_fini,
|
||||
_cairo_ft_scaled_glyph_init,
|
||||
|
|
@ -2004,6 +2005,7 @@ _cairo_ft_font_face_scaled_font_create (void *abstract_face,
|
|||
}
|
||||
|
||||
static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
|
||||
CAIRO_FONT_TYPE_FT,
|
||||
_cairo_ft_font_face_destroy,
|
||||
_cairo_ft_font_face_scaled_font_create
|
||||
};
|
||||
|
|
|
|||
|
|
@ -551,8 +551,8 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
|
|||
attr->acquired = FALSE;
|
||||
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_LINEAR:
|
||||
case CAIRO_PATTERN_RADIAL: {
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
case CAIRO_PATTERN_TYPE_RADIAL: {
|
||||
cairo_gradient_pattern_t *gradient =
|
||||
(cairo_gradient_pattern_t *) pattern;
|
||||
char *data;
|
||||
|
|
@ -587,7 +587,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
|
|||
if (!CAIRO_GLITZ_FEATURE_OK (dst->surface, FRAGMENT_PROGRAM))
|
||||
break;
|
||||
|
||||
if (pattern->type == CAIRO_PATTERN_RADIAL)
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
|
||||
n_base_params = 6;
|
||||
else
|
||||
n_base_params = 4;
|
||||
|
|
@ -639,7 +639,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
|
|||
|
||||
glitz_buffer_destroy (buffer);
|
||||
|
||||
if (pattern->type == CAIRO_PATTERN_LINEAR)
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR)
|
||||
{
|
||||
cairo_linear_pattern_t *grad = (cairo_linear_pattern_t *) pattern;
|
||||
|
||||
|
|
@ -776,8 +776,8 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src,
|
|||
* information in mask, so this will need to change when we
|
||||
* support RENDER-style 4-channel masks. */
|
||||
|
||||
if (src->type == CAIRO_PATTERN_SOLID &&
|
||||
mask->type == CAIRO_PATTERN_SOLID)
|
||||
if (src->type == CAIRO_PATTERN_TYPE_SOLID &&
|
||||
mask->type == CAIRO_PATTERN_TYPE_SOLID)
|
||||
{
|
||||
cairo_color_t combined;
|
||||
cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src;
|
||||
|
|
@ -1018,7 +1018,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
|
|||
if (_glitz_ensure_target (dst->surface))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (pattern->type == CAIRO_PATTERN_SURFACE)
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
|
||||
{
|
||||
_cairo_pattern_init_copy (&tmp_src_pattern.base, pattern);
|
||||
|
||||
|
|
@ -2121,6 +2121,7 @@ _cairo_glitz_surface_flush (void *abstract_surface)
|
|||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_glitz_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_GLITZ,
|
||||
_cairo_glitz_surface_create_similar,
|
||||
_cairo_glitz_surface_finish,
|
||||
_cairo_glitz_surface_acquire_source_image,
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ typedef struct _cairo_hash_entry {
|
|||
} cairo_hash_entry_t;
|
||||
|
||||
typedef cairo_bool_t
|
||||
(*cairo_hash_keys_equal_func_t) (void *key_a, void *key_b);
|
||||
(*cairo_hash_keys_equal_func_t) (const void *key_a, const void *key_b);
|
||||
|
||||
typedef cairo_bool_t
|
||||
(*cairo_hash_predicate_func_t) (void *entry);
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ struct _cairo_hash_table {
|
|||
cairo_hash_entry_t **entries;
|
||||
|
||||
unsigned long live_entries;
|
||||
unsigned long iterating; /* Iterating, no insert, no resize */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -163,6 +164,7 @@ _cairo_hash_table_create (cairo_hash_keys_equal_func_t keys_equal)
|
|||
}
|
||||
|
||||
hash_table->live_entries = 0;
|
||||
hash_table->iterating = 0;
|
||||
|
||||
return hash_table;
|
||||
}
|
||||
|
|
@ -179,6 +181,10 @@ _cairo_hash_table_create (cairo_hash_keys_equal_func_t keys_equal)
|
|||
* and this function will halt. The rationale for this behavior is to
|
||||
* avoid memory leaks and to avoid needless complication of the API
|
||||
* with destroy notifiy callbacks.
|
||||
*
|
||||
* WARNING: The hash_table must have no running iterators in it when
|
||||
* _cairo_hash_table_destroy is called. It is a fatal error otherwise,
|
||||
* and this function will halt.
|
||||
**/
|
||||
void
|
||||
_cairo_hash_table_destroy (cairo_hash_table_t *hash_table)
|
||||
|
|
@ -188,6 +194,8 @@ _cairo_hash_table_destroy (cairo_hash_table_t *hash_table)
|
|||
|
||||
/* The hash table must be empty. Otherwise, halt. */
|
||||
assert (hash_table->live_entries == 0);
|
||||
/* No iterators can be running. Otherwise, halt. */
|
||||
assert (hash_table->iterating == 0);
|
||||
|
||||
free (hash_table->entries);
|
||||
hash_table->entries = NULL;
|
||||
|
|
@ -440,6 +448,9 @@ _cairo_hash_table_random_entry (cairo_hash_table_t *hash_table,
|
|||
* WARNING: It is a fatal error if an entry exists in the hash table
|
||||
* with a matching key, (this function will halt).
|
||||
*
|
||||
* WARNING: It is a fatal error to insert an element while
|
||||
* an iterator is running
|
||||
*
|
||||
* Instead of using insert to replace an entry, consider just editing
|
||||
* the entry obtained with _cairo_hash_table_lookup. Or if absolutely
|
||||
* necessary, use _cairo_hash_table_remove first.
|
||||
|
|
@ -454,6 +465,9 @@ _cairo_hash_table_insert (cairo_hash_table_t *hash_table,
|
|||
cairo_status_t status;
|
||||
cairo_hash_entry_t **entry;
|
||||
|
||||
/* Insert is illegal while an iterator is running. */
|
||||
assert (hash_table->iterating == 0);
|
||||
|
||||
entry = _cairo_hash_table_lookup_internal (hash_table,
|
||||
key_and_value, FALSE);
|
||||
|
||||
|
|
@ -498,11 +512,16 @@ _cairo_hash_table_remove (cairo_hash_table_t *hash_table,
|
|||
*entry = DEAD_ENTRY;
|
||||
hash_table->live_entries--;
|
||||
|
||||
/* This call _can_ fail, but only in failing to allocate new
|
||||
* memory to shrink the hash table. It does leave the table in a
|
||||
* consistent state, and we've already succeeded in removing the
|
||||
* entry, so we don't examine the failure status of this call. */
|
||||
_cairo_hash_table_resize (hash_table);
|
||||
/* Check for table resize. Don't do this when iterating as this will
|
||||
* reorder elements of the table and cause the iteration to potentially
|
||||
* skip some elements. */
|
||||
if (hash_table->iterating == 0) {
|
||||
/* This call _can_ fail, but only in failing to allocate new
|
||||
* memory to shrink the hash table. It does leave the table in a
|
||||
* consistent state, and we've already succeeded in removing the
|
||||
* entry, so we don't examine the failure status of this call. */
|
||||
_cairo_hash_table_resize (hash_table);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -513,6 +532,12 @@ _cairo_hash_table_remove (cairo_hash_table_t *hash_table,
|
|||
*
|
||||
* Call @hash_callback for each live entry in the hash table, in a
|
||||
* non-specified order.
|
||||
*
|
||||
* Entries in @hash_table may be removed by code executed from @hash_callback.
|
||||
*
|
||||
* Entries may not be inserted to @hash_table, nor may @hash_table
|
||||
* be destroyed by code executed from @hash_callback. The relevant
|
||||
* functions will halt in these cases.
|
||||
**/
|
||||
void
|
||||
_cairo_hash_table_foreach (cairo_hash_table_t *hash_table,
|
||||
|
|
@ -525,9 +550,17 @@ _cairo_hash_table_foreach (cairo_hash_table_t *hash_table,
|
|||
if (hash_table == NULL)
|
||||
return;
|
||||
|
||||
/* Mark the table for iteration */
|
||||
++hash_table->iterating;
|
||||
for (i = 0; i < hash_table->arrangement->size; i++) {
|
||||
entry = hash_table->entries[i];
|
||||
if (ENTRY_IS_LIVE(entry))
|
||||
hash_callback (entry, closure);
|
||||
}
|
||||
/* If some elements were deleted during the iteration,
|
||||
* the table may need resizing. Just do this every time
|
||||
* as the check is inexpensive.
|
||||
*/
|
||||
if (--hash_table->iterating == 0)
|
||||
_cairo_hash_table_resize (hash_table);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,9 +188,10 @@ _create_pixman_format (cairo_format_t format)
|
|||
* @height: height of the surface, in pixels
|
||||
*
|
||||
* Creates an image surface of the specified format and
|
||||
* dimensions. The initial contents of the surface is undefined; you
|
||||
* must explicitly initialize the surface contents, using, for
|
||||
* example, cairo_paint().
|
||||
* dimensions. Initially the surface contents are all
|
||||
* 0. (Specifically, within each pixel, each color or alpha channel
|
||||
* belonging to format will be 0. The contents of bits within a pixel,
|
||||
* but not belonging to the given format are undefined).
|
||||
*
|
||||
* Return value: a pointer to the newly created surface. The caller
|
||||
* owns the surface and should call cairo_surface_destroy when done
|
||||
|
|
@ -861,7 +862,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
|
|||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
cairo_int_status_t
|
||||
_cairo_image_surface_set_clip_region (void *abstract_surface,
|
||||
pixman_region16_t *region)
|
||||
{
|
||||
|
|
@ -903,6 +904,7 @@ _cairo_surface_is_image (const cairo_surface_t *surface)
|
|||
}
|
||||
|
||||
const cairo_surface_backend_t cairo_image_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
_cairo_image_surface_create_similar,
|
||||
_cairo_image_surface_finish,
|
||||
_cairo_image_surface_acquire_source_image,
|
||||
|
|
|
|||
400
src/cairo-lzw.c
Normal file
|
|
@ -0,0 +1,400 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2006 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* 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):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
typedef struct _lzw_buf {
|
||||
cairo_status_t status;
|
||||
|
||||
unsigned char *data;
|
||||
int data_size;
|
||||
int num_data;
|
||||
uint32_t pending;
|
||||
int pending_bits;
|
||||
} lzw_buf_t;
|
||||
|
||||
/* An lzw_buf_t is a simple, growable chunk of memory for holding
|
||||
* variable-size objects of up to 16 bits each.
|
||||
*
|
||||
* Initialize an lzw_buf_t to the given size in bytes.
|
||||
*
|
||||
* To store objects into the lzw_buf_t, call _lzw_buf_store_bits and
|
||||
* when finished, call _lzw_buf_store_pending, (which flushes out the
|
||||
* last few bits that hadn't yet made a complete byte yet).
|
||||
*
|
||||
* Instead of returning failure from any functions, lzw_buf_t provides
|
||||
* a status value that the caller can query, (and should query at
|
||||
* least once when done with the object). The status value will be
|
||||
* either CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY;
|
||||
*/
|
||||
static void
|
||||
_lzw_buf_init (lzw_buf_t *buf, int size)
|
||||
{
|
||||
if (size == 0)
|
||||
size = 16;
|
||||
|
||||
buf->status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
buf->data = malloc (size);
|
||||
if (buf->data == NULL) {
|
||||
buf->data_size = 0;
|
||||
buf->status = CAIRO_STATUS_NO_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
buf->data_size = size;
|
||||
buf->num_data = 0;
|
||||
buf->pending = 0;
|
||||
buf->pending_bits = 0;
|
||||
}
|
||||
|
||||
/* Increase the buffer size by doubling.
|
||||
*
|
||||
* Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY
|
||||
*/
|
||||
static cairo_status_t
|
||||
_lzw_buf_grow (lzw_buf_t *buf)
|
||||
{
|
||||
int new_size = buf->data_size * 2;
|
||||
unsigned char *new_data;
|
||||
|
||||
if (buf->status)
|
||||
return buf->status;
|
||||
|
||||
new_data = realloc (buf->data, new_size);
|
||||
if (new_data == NULL) {
|
||||
free (buf->data);
|
||||
buf->data_size = 0;
|
||||
buf->status = CAIRO_STATUS_NO_MEMORY;
|
||||
return buf->status;
|
||||
}
|
||||
|
||||
buf->data = new_data;
|
||||
buf->data_size = new_size;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Store the lowest num_bits bits of values into buf.
|
||||
*
|
||||
* NOTE: The bits of value above size_in_bits must be 0, (so don't lie
|
||||
* about the size).
|
||||
*
|
||||
* See also _lzw_buf_store_pending which must be called after the last
|
||||
* call to _lzw_buf_store_bits.
|
||||
*
|
||||
* Sets buf->status to either CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY.
|
||||
*/
|
||||
static void
|
||||
_lzw_buf_store_bits (lzw_buf_t *buf, uint16_t value, int num_bits)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
assert (value <= (1 << num_bits) - 1);
|
||||
|
||||
if (buf->status)
|
||||
return;
|
||||
|
||||
buf->pending = (buf->pending << num_bits) | value;
|
||||
buf->pending_bits += num_bits;
|
||||
|
||||
while (buf->pending_bits >= 8) {
|
||||
if (buf->num_data >= buf->data_size) {
|
||||
status = _lzw_buf_grow (buf);
|
||||
if (status)
|
||||
return;
|
||||
}
|
||||
buf->data[buf->num_data++] = buf->pending >> (buf->pending_bits - 8);
|
||||
buf->pending_bits -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* Store the last remaining pending bits into the buffer.
|
||||
*
|
||||
* NOTE: This function must be called after the last call to
|
||||
* _lzw_buf_store_bits.
|
||||
*
|
||||
* Sets buf->status to either CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY.
|
||||
*/
|
||||
static void
|
||||
_lzw_buf_store_pending (lzw_buf_t *buf)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (buf->status)
|
||||
return;
|
||||
|
||||
if (buf->pending_bits == 0)
|
||||
return;
|
||||
|
||||
assert (buf->pending_bits < 8);
|
||||
|
||||
if (buf->num_data >= buf->data_size) {
|
||||
status = _lzw_buf_grow (buf);
|
||||
if (status)
|
||||
return;
|
||||
}
|
||||
|
||||
buf->data[buf->num_data++] = buf->pending << (8 - buf->pending_bits);
|
||||
buf->pending_bits = 0;
|
||||
}
|
||||
|
||||
/* LZW defines a few magic code values */
|
||||
#define LZW_CODE_CLEAR_TABLE 256
|
||||
#define LZW_CODE_EOD 257
|
||||
#define LZW_CODE_FIRST 258
|
||||
|
||||
/* We pack three separate values into a symbol as follows:
|
||||
*
|
||||
* 12 bits (31 down to 20): CODE: code value used to represent this symbol
|
||||
* 12 bits (19 down to 8): PREV: previous code value in chain
|
||||
* 8 bits ( 7 down to 0): NEXT: next byte value in chain
|
||||
*/
|
||||
typedef uint32_t lzw_symbol_t;
|
||||
|
||||
#define LZW_SYMBOL_SET(sym, prev, next) ((sym) = ((prev) << 8)|(next))
|
||||
#define LZW_SYMBOL_SET_CODE(sym, code, prev, next) ((sym) = ((code << 20)|(prev) << 8)|(next))
|
||||
#define LZW_SYMBOL_GET_CODE(sym) (((sym) >> 20))
|
||||
#define LZW_SYMBOL_GET_PREV(sym) (((sym) >> 8) & 0x7ff)
|
||||
#define LZW_SYMBOL_GET_BYTE(sym) (((sym) >> 0) & 0x0ff)
|
||||
|
||||
/* The PREV+NEXT fields can be seen as the key used to fetch values
|
||||
* from the hash table, while the code is the value fetched.
|
||||
*/
|
||||
#define LZW_SYMBOL_KEY_MASK 0x000fffff
|
||||
|
||||
/* Since code values are only stored starting with 258 we can safely
|
||||
* use a zero value to represent free slots in the hash table. */
|
||||
#define LZW_SYMBOL_FREE 0x00000000
|
||||
|
||||
/* These really aren't very free for modifying. First, the PostScript
|
||||
* specification sets the 9-12 bit range. Second, the encoding of
|
||||
* lzw_symbol_t above also relies on 2 of LZW_BITS_MAX plus one byte
|
||||
* fitting within 32 bits.
|
||||
*
|
||||
* But other than that, the LZW compression scheme could function with
|
||||
* more bits per code.
|
||||
*/
|
||||
#define LZW_BITS_MIN 9
|
||||
#define LZW_BITS_MAX 12
|
||||
#define LZW_BITS_BOUNDARY(bits) ((1<<(bits))-1)
|
||||
#define LZW_MAX_SYMBOLS (1<<LZW_BITS_MAX)
|
||||
|
||||
#define LZW_SYMBOL_TABLE_SIZE 9013
|
||||
#define LZW_SYMBOL_MOD1 LZW_SYMBOL_TABLE_SIZE
|
||||
#define LZW_SYMBOL_MOD2 9011
|
||||
|
||||
typedef struct _lzw_symbol_table {
|
||||
lzw_symbol_t table[LZW_SYMBOL_TABLE_SIZE];
|
||||
} lzw_symbol_table_t;
|
||||
|
||||
/* Initialize the hash table to entirely empty */
|
||||
static void
|
||||
_lzw_symbol_table_init (lzw_symbol_table_t *table)
|
||||
{
|
||||
memset (table->table, 0, LZW_SYMBOL_TABLE_SIZE * sizeof (lzw_symbol_t));
|
||||
}
|
||||
|
||||
/* Lookup a symbol in the symbol table. The PREV and NEXT fields of
|
||||
* symbol form the key for the lookup.
|
||||
*
|
||||
* If succesful, then this function returns TRUE and slot_ret will be
|
||||
* left pointing at the result that will have the CODE field of
|
||||
* interest.
|
||||
*
|
||||
* If the lookup fails, then this function returns FALSE and slot_ret
|
||||
* will be pointing at the location in the table to which a new CODE
|
||||
* value should be stored along with PREV and NEXT.
|
||||
*/
|
||||
static cairo_bool_t
|
||||
_lzw_symbol_table_lookup (lzw_symbol_table_t *table,
|
||||
lzw_symbol_t symbol,
|
||||
lzw_symbol_t **slot_ret)
|
||||
{
|
||||
/* The algorithm here is identical to that in cairo-hash.c. We
|
||||
* copy it here to allow for a rather more efficient
|
||||
* implementation due to several circumstances that do not apply
|
||||
* to the more general case:
|
||||
*
|
||||
* 1) We have a known bound on the total number of symbols, so we
|
||||
* have a fixed-size table without any copying when growing
|
||||
*
|
||||
* 2) We never delete any entries, so we don't need to
|
||||
* support/check for DEAD entries during lookup.
|
||||
*
|
||||
* 3) The object fits in 32 bits so we store each object in its
|
||||
* entirety within the table rather than storing objects
|
||||
* externally and putting pointers in the table, (which here
|
||||
* would just double the storage requirements and have negative
|
||||
* impacts on memory locality).
|
||||
*/
|
||||
int i, idx, step, hash = symbol & LZW_SYMBOL_KEY_MASK;
|
||||
lzw_symbol_t candidate;
|
||||
|
||||
idx = hash % LZW_SYMBOL_MOD1;
|
||||
step = 0;
|
||||
|
||||
*slot_ret = NULL;
|
||||
for (i = 0; i < LZW_SYMBOL_TABLE_SIZE; i++)
|
||||
{
|
||||
candidate = table->table[idx];
|
||||
if (candidate == LZW_SYMBOL_FREE)
|
||||
{
|
||||
*slot_ret = &table->table[idx];
|
||||
return FALSE;
|
||||
}
|
||||
else /* candidate is LIVE */
|
||||
{
|
||||
if ((candidate & LZW_SYMBOL_KEY_MASK) ==
|
||||
(symbol & LZW_SYMBOL_KEY_MASK))
|
||||
{
|
||||
*slot_ret = &table->table[idx];
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (step == 0) {
|
||||
step = hash % LZW_SYMBOL_MOD2;
|
||||
if (step == 0)
|
||||
step = 1;
|
||||
}
|
||||
|
||||
idx += step;
|
||||
if (idx >= LZW_SYMBOL_TABLE_SIZE)
|
||||
idx -= LZW_SYMBOL_TABLE_SIZE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Compress a bytestream using the LZW algorithm.
|
||||
*
|
||||
* This is an original implementation based on reading the
|
||||
* specification of the LZWDecode filter in the PostScript Language
|
||||
* Reference. The free parameters in the LZW algorithm are set to the
|
||||
* values mandated by PostScript, (symbols encoded with widths from 9
|
||||
* to 12 bits).
|
||||
*
|
||||
* This function returns a pointer to a newly allocated buffer holding
|
||||
* the compressed data, or NULL if an out-of-memory situation
|
||||
* occurs.
|
||||
*
|
||||
* Notice that any one of the _lzw_buf functions called here could
|
||||
* trigger an out-of-memory condition. But lzw_buf_t uses cairo's
|
||||
* shutdown-on-error idiom, so it's safe to continue to call into
|
||||
* lzw_buf without having to check for errors, (until a final check at
|
||||
* the end).
|
||||
*/
|
||||
cairo_public unsigned char *
|
||||
_cairo_lzw_compress (unsigned char *data, unsigned long *size_in_out)
|
||||
{
|
||||
int bytes_remaining = *size_in_out;
|
||||
lzw_buf_t buf;
|
||||
lzw_symbol_table_t table;
|
||||
lzw_symbol_t symbol, *slot;
|
||||
int code_next = LZW_CODE_FIRST;
|
||||
int code_bits = LZW_BITS_MIN;
|
||||
int prev, next;
|
||||
|
||||
if (*size_in_out == 0)
|
||||
return NULL;
|
||||
|
||||
_lzw_buf_init (&buf, *size_in_out);
|
||||
|
||||
_lzw_symbol_table_init (&table);
|
||||
|
||||
/* The LZW header is a clear table code. */
|
||||
_lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits);
|
||||
|
||||
while (1) {
|
||||
|
||||
/* Find the longest existing code in the symbol table that
|
||||
* matches the current input, if any. */
|
||||
prev = *data++;
|
||||
bytes_remaining--;
|
||||
if (bytes_remaining) {
|
||||
do
|
||||
{
|
||||
next = *data++;
|
||||
bytes_remaining--;
|
||||
LZW_SYMBOL_SET (symbol, prev, next);
|
||||
if (_lzw_symbol_table_lookup (&table, symbol, &slot))
|
||||
prev = LZW_SYMBOL_GET_CODE (*slot);
|
||||
} while (bytes_remaining && *slot != LZW_SYMBOL_FREE);
|
||||
if (*slot == LZW_SYMBOL_FREE) {
|
||||
data--;
|
||||
bytes_remaining++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the code into the output. This is either a byte read
|
||||
* directly from the input, or a code from the last successful
|
||||
* lookup. */
|
||||
_lzw_buf_store_bits (&buf, prev, code_bits);
|
||||
|
||||
if (bytes_remaining == 0)
|
||||
break;
|
||||
|
||||
LZW_SYMBOL_SET_CODE (*slot, code_next++, prev, next);
|
||||
|
||||
if (code_next > LZW_BITS_BOUNDARY(code_bits))
|
||||
{
|
||||
code_bits++;
|
||||
if (code_bits > LZW_BITS_MAX) {
|
||||
_lzw_symbol_table_init (&table);
|
||||
_lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits - 1);
|
||||
code_bits = LZW_BITS_MIN;
|
||||
code_next = LZW_CODE_FIRST;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The LZW footer is an end-of-data code. */
|
||||
_lzw_buf_store_bits (&buf, LZW_CODE_EOD, code_bits);
|
||||
|
||||
_lzw_buf_store_pending (&buf);
|
||||
|
||||
/* See if we ever ran out of memory while writing to buf. */
|
||||
if (buf.status == CAIRO_STATUS_NO_MEMORY) {
|
||||
*size_in_out = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert (buf.status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
*size_in_out = buf.num_data;
|
||||
return buf.data;
|
||||
}
|
||||
|
|
@ -53,7 +53,7 @@ typedef enum {
|
|||
* fallbacks should never get triggered). So the plan is to
|
||||
* eliminate as many of these as possible. */
|
||||
|
||||
CAIRO_COMMAND_INTERSECT_CLIP_PATH,
|
||||
CAIRO_COMMAND_INTERSECT_CLIP_PATH
|
||||
|
||||
} cairo_command_type_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ _init_pattern_with_snapshot (cairo_pattern_t *pattern,
|
|||
{
|
||||
_cairo_pattern_init_copy (pattern, other);
|
||||
|
||||
if (pattern->type == CAIRO_PATTERN_SURFACE) {
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
cairo_surface_pattern_t *surface_pattern =
|
||||
(cairo_surface_pattern_t *) pattern;
|
||||
cairo_surface_t *surface = surface_pattern->surface;
|
||||
|
|
@ -557,6 +557,7 @@ _cairo_surface_is_meta (const cairo_surface_t *surface)
|
|||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_meta_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_META,
|
||||
_cairo_meta_surface_create_similar,
|
||||
_cairo_meta_surface_finish,
|
||||
_cairo_meta_surface_acquire_source_image,
|
||||
|
|
|
|||
119
src/cairo-operator.c
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2006 Keith Packard
|
||||
* Copyright © 2006 Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* 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):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
* Keith Packard <keithp@keithp.com>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
/* The analysis here assumes destination alpha semantics (that is
|
||||
* CAIRO_CONTENT_COLOR_ALPHA). More things can be considered opaque
|
||||
* otherwise (CAIRO_CONTENT_COLOR) so we'll probably want to add a
|
||||
* cairo_content_t parameter to this function
|
||||
*
|
||||
* We also need a definition of what "opaque" means. Is it, "does not
|
||||
* requiring 'knowing' the original contents of destination, nor does
|
||||
* it set the destination alpha to anything but 1.0" ?
|
||||
*/
|
||||
cairo_bool_t
|
||||
_cairo_operator_always_opaque (cairo_operator_t op)
|
||||
{
|
||||
switch (op) {
|
||||
case CAIRO_OPERATOR_CLEAR:
|
||||
return FALSE;
|
||||
|
||||
case CAIRO_OPERATOR_SOURCE:
|
||||
return FALSE;
|
||||
|
||||
case CAIRO_OPERATOR_OVER:
|
||||
case CAIRO_OPERATOR_IN:
|
||||
case CAIRO_OPERATOR_OUT:
|
||||
case CAIRO_OPERATOR_ATOP:
|
||||
return FALSE;
|
||||
|
||||
case CAIRO_OPERATOR_DEST:
|
||||
return TRUE;
|
||||
|
||||
case CAIRO_OPERATOR_DEST_OVER:
|
||||
case CAIRO_OPERATOR_DEST_IN:
|
||||
case CAIRO_OPERATOR_DEST_OUT:
|
||||
case CAIRO_OPERATOR_DEST_ATOP:
|
||||
return FALSE;
|
||||
|
||||
case CAIRO_OPERATOR_XOR:
|
||||
case CAIRO_OPERATOR_ADD:
|
||||
case CAIRO_OPERATOR_SATURATE:
|
||||
return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* As above, we'll probably want to add a cairo_content_t parameter to
|
||||
* this function
|
||||
*
|
||||
* We also need a definition of what "translucent" means.
|
||||
*/
|
||||
cairo_bool_t
|
||||
_cairo_operator_always_translucent (cairo_operator_t op)
|
||||
{
|
||||
switch (op) {
|
||||
case CAIRO_OPERATOR_CLEAR:
|
||||
return TRUE;
|
||||
|
||||
case CAIRO_OPERATOR_SOURCE:
|
||||
return FALSE;
|
||||
|
||||
case CAIRO_OPERATOR_OVER:
|
||||
case CAIRO_OPERATOR_IN:
|
||||
case CAIRO_OPERATOR_OUT:
|
||||
case CAIRO_OPERATOR_ATOP:
|
||||
return FALSE;
|
||||
|
||||
case CAIRO_OPERATOR_DEST:
|
||||
return FALSE;
|
||||
|
||||
case CAIRO_OPERATOR_DEST_OVER:
|
||||
case CAIRO_OPERATOR_DEST_IN:
|
||||
case CAIRO_OPERATOR_DEST_OUT:
|
||||
case CAIRO_OPERATOR_DEST_ATOP:
|
||||
return FALSE;
|
||||
|
||||
case CAIRO_OPERATOR_XOR:
|
||||
case CAIRO_OPERATOR_ADD:
|
||||
case CAIRO_OPERATOR_SATURATE:
|
||||
return TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -44,54 +44,92 @@
|
|||
#endif /* _MSC_VER */
|
||||
|
||||
struct _cairo_output_stream {
|
||||
cairo_write_func_t write_data;
|
||||
cairo_write_func_t write_func;
|
||||
cairo_close_func_t close_func;
|
||||
void *closure;
|
||||
cairo_bool_t owns_closure_is_file;
|
||||
unsigned long position;
|
||||
cairo_status_t status;
|
||||
cairo_bool_t closed;
|
||||
};
|
||||
|
||||
const cairo_output_stream_t cairo_output_stream_nil = {
|
||||
NULL, /* write_func */
|
||||
NULL, /* close_func */
|
||||
NULL, /* closure */
|
||||
0, /* position */
|
||||
CAIRO_STATUS_NO_MEMORY,
|
||||
FALSE /* closed */
|
||||
};
|
||||
|
||||
static const cairo_output_stream_t cairo_output_stream_nil_write_error = {
|
||||
NULL, /* write_func */
|
||||
NULL, /* close_func */
|
||||
NULL, /* closure */
|
||||
0, /* position */
|
||||
CAIRO_STATUS_WRITE_ERROR,
|
||||
FALSE /* closed */
|
||||
};
|
||||
|
||||
cairo_output_stream_t *
|
||||
_cairo_output_stream_create (cairo_write_func_t write_data,
|
||||
_cairo_output_stream_create (cairo_write_func_t write_func,
|
||||
cairo_close_func_t close_func,
|
||||
void *closure)
|
||||
{
|
||||
cairo_output_stream_t *stream;
|
||||
|
||||
stream = malloc (sizeof (cairo_output_stream_t));
|
||||
if (stream == NULL)
|
||||
return NULL;
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil;
|
||||
|
||||
stream->write_data = write_data;
|
||||
stream->write_func = write_func;
|
||||
stream->close_func = close_func;
|
||||
stream->closure = closure;
|
||||
stream->owns_closure_is_file = FALSE;
|
||||
stream->position = 0;
|
||||
stream->status = CAIRO_STATUS_SUCCESS;
|
||||
stream->closed = FALSE;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_output_stream_close (cairo_output_stream_t *stream)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (stream->closed)
|
||||
return;
|
||||
|
||||
if (stream->close_func) {
|
||||
status = stream->close_func (stream->closure);
|
||||
if (status)
|
||||
stream->status = status;
|
||||
}
|
||||
|
||||
stream->closed = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_output_stream_destroy (cairo_output_stream_t *stream)
|
||||
{
|
||||
if (stream->owns_closure_is_file) {
|
||||
FILE *file = stream->closure;
|
||||
fflush (file);
|
||||
fclose (file);
|
||||
}
|
||||
if (stream == NULL)
|
||||
return;
|
||||
|
||||
_cairo_output_stream_close (stream);
|
||||
free (stream);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_output_stream_write (cairo_output_stream_t *stream,
|
||||
const void *data, size_t length)
|
||||
{
|
||||
if (length == 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return;
|
||||
|
||||
stream->status = stream->write_data (stream->closure, data, length);
|
||||
if (stream->status)
|
||||
return;
|
||||
|
||||
stream->status = stream->write_func (stream->closure, data, length);
|
||||
stream->position += length;
|
||||
|
||||
return stream->status;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -103,6 +141,9 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
|
|||
char buffer[2];
|
||||
int i, column;
|
||||
|
||||
if (stream->status)
|
||||
return;
|
||||
|
||||
for (i = 0, column = 0; i < length; i++, column++) {
|
||||
if (column == 38) {
|
||||
_cairo_output_stream_write (stream, "\n", 1);
|
||||
|
|
@ -175,8 +216,7 @@ enum {
|
|||
* formatting. This functionality is only for internal use and we
|
||||
* only implement the formats we actually use.
|
||||
*/
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_output_stream_vprintf (cairo_output_stream_t *stream,
|
||||
const char *fmt, va_list ap)
|
||||
{
|
||||
|
|
@ -185,6 +225,9 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
|
|||
const char *f;
|
||||
int length_modifier;
|
||||
|
||||
if (stream->status)
|
||||
return;
|
||||
|
||||
f = fmt;
|
||||
p = buffer;
|
||||
while (*f != '\0') {
|
||||
|
|
@ -247,24 +290,19 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
|
|||
}
|
||||
|
||||
_cairo_output_stream_write (stream, buffer, p - buffer);
|
||||
|
||||
return stream->status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_output_stream_printf (cairo_output_stream_t *stream,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
cairo_status_t status;
|
||||
|
||||
va_start (ap, fmt);
|
||||
|
||||
status = _cairo_output_stream_vprintf (stream, fmt, ap);
|
||||
_cairo_output_stream_vprintf (stream, fmt, ap);
|
||||
|
||||
va_end (ap);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
long
|
||||
|
|
@ -286,28 +324,57 @@ _cairo_output_stream_get_status (cairo_output_stream_t *stream)
|
|||
static cairo_status_t
|
||||
stdio_write (void *closure, const unsigned char *data, unsigned int length)
|
||||
{
|
||||
FILE *fp = closure;
|
||||
FILE *file = closure;
|
||||
|
||||
if (fwrite (data, 1, length, fp) == length)
|
||||
if (fwrite (data, 1, length, file) != length)
|
||||
return CAIRO_STATUS_WRITE_ERROR;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
stdio_flush (void *closure)
|
||||
{
|
||||
FILE *file = closure;
|
||||
|
||||
fflush (file);
|
||||
|
||||
if (ferror (file))
|
||||
return CAIRO_STATUS_WRITE_ERROR;
|
||||
else
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_WRITE_ERROR;
|
||||
static cairo_status_t
|
||||
stdio_close (void *closure)
|
||||
{
|
||||
cairo_status_t status;
|
||||
FILE *file = closure;
|
||||
|
||||
status = stdio_flush (closure);
|
||||
|
||||
fclose (file);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_output_stream_t *
|
||||
_cairo_output_stream_create_for_file (const char *filename)
|
||||
_cairo_output_stream_create_for_file (FILE *file)
|
||||
{
|
||||
FILE *fp;
|
||||
cairo_output_stream_t *stream;
|
||||
if (file == NULL)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil_write_error;
|
||||
|
||||
fp = fopen (filename, "wb");
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
|
||||
stream = _cairo_output_stream_create (stdio_write, fp);
|
||||
if (stream == NULL)
|
||||
fclose (fp);
|
||||
stream->owns_closure_is_file = TRUE;
|
||||
|
||||
return stream;
|
||||
return _cairo_output_stream_create (stdio_write, stdio_flush, file);
|
||||
}
|
||||
|
||||
cairo_output_stream_t *
|
||||
_cairo_output_stream_create_for_filename (const char *filename)
|
||||
{
|
||||
FILE *file;
|
||||
|
||||
file = fopen (filename, "wb");
|
||||
if (file == NULL)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil_write_error;
|
||||
|
||||
return _cairo_output_stream_create (stdio_write, stdio_close, file);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,11 +38,99 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
typedef enum {
|
||||
CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */
|
||||
CAIRO_PAGINATED_MODE_RENDER /* render page contents */
|
||||
} cairo_paginated_mode_t;
|
||||
|
||||
typedef struct _cairo_paginated_surface_backend {
|
||||
/* Optional. Will be called once for each page.
|
||||
*
|
||||
* NOTE: With respect to the order of drawing operations as seen
|
||||
* by the target, this call will occur before any drawing
|
||||
* operations for the relevant page. However, with respect to the
|
||||
* function calls as made by the user, this call will be *after*
|
||||
* any drawing operations for the page, (that is, it will occur
|
||||
* during the user's call to cairo_show_page or cairo_copy_page).
|
||||
*/
|
||||
cairo_int_status_t
|
||||
(*start_page) (void *surface);
|
||||
|
||||
/* Required. Will be called twice for each page, once with an
|
||||
* argument of CAIRO_PAGINATED_MODE_ANALYZE and once with
|
||||
* CAIRO_PAGINATED_MODE_RENDER. See more details in the
|
||||
* documentation for _cairo_paginated_surface_create below.
|
||||
*/
|
||||
void
|
||||
(*set_paginated_mode) (void *surface,
|
||||
cairo_paginated_mode_t mode);
|
||||
} cairo_paginated_surface_backend_t;
|
||||
|
||||
/* A cairo_paginated_surface provides a very convenient wrapper that
|
||||
* is well-suited for doing the analysis common to most surfaces that
|
||||
* have paginated output, (that is, things directed at printers, or
|
||||
* for saving content in files such as PostScript or PDF files).
|
||||
*
|
||||
* To use the paginated surface, you'll first need to create your
|
||||
* 'real' surface using _cairo_surface_init and the standard
|
||||
* cairo_surface_backend_t. Then you also call
|
||||
* _cairo_paginated_surface_create which takes its own, much simpler,
|
||||
* cairo_paginated_surface_backend. You are free to return the result
|
||||
* of _cairo_paginated_surface_create from your public
|
||||
* cairo_<foo>_surface_create. The paginated backend will be careful
|
||||
* to not let the user see that they really got a "wrapped"
|
||||
* surface. See test-paginated-surface.c for a fairly minimal example
|
||||
* of a paginated-using surface. That should be a reasonable example
|
||||
* to follow.
|
||||
*
|
||||
* What the paginated surface does is first save all drawing
|
||||
* operations for a page into a meta-surface. Then when the user calls
|
||||
* cairo_show_page, the paginated surface performs the following
|
||||
* sequence of operations (using the backend functions passed to
|
||||
* cairo_paginated_surface_create):
|
||||
*
|
||||
* 1. Calls start_page (if non NULL). At this point, it is appropriate
|
||||
* for the target to emit any page-specific header information into
|
||||
* its output.
|
||||
*
|
||||
* 2. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_ANALYZE
|
||||
*
|
||||
* 3. Replays the meta-surface to the target surface, (with an
|
||||
* analysis surface inserted between which watches the return value
|
||||
* from each operation). This analysis stage is used to decide which
|
||||
* operations will require fallbacks.
|
||||
*
|
||||
* 4. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_RENDER
|
||||
*
|
||||
* 5. Replays a subset of the meta-surface operations to the target surface
|
||||
*
|
||||
* 6. 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.
|
||||
*
|
||||
* NOTE: The paginated surface layer assumes that the target surface
|
||||
* is "blank" by default at the beginning of each page, without any
|
||||
* need for an explicit erasea operation, (as opposed to an image
|
||||
* surface, for example, which might have uninitialized content
|
||||
* originally). As such, it optimizes away CLEAR operations that
|
||||
* happen at the beginning of each page---the target surface will not
|
||||
* even see these operations.
|
||||
*/
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_paginated_surface_create (cairo_surface_t *target,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height);
|
||||
_cairo_paginated_surface_create (cairo_surface_t *target,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height,
|
||||
const cairo_paginated_surface_backend_t *backend);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_paginated_surface_get_target (cairo_surface_t *surface);
|
||||
|
|
|
|||
|
|
@ -31,47 +31,27 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
* Keith Packard <keithp@keithp.com>
|
||||
*/
|
||||
|
||||
/* The paginated surface layer exists to provide as much code sharing
|
||||
* as possible for the various paginated surface backends in cairo
|
||||
* (PostScript, PDF, etc.).
|
||||
*
|
||||
* The concept is that a surface which uses a paginated surface merely
|
||||
* needs to implement backend operations which it can accurately
|
||||
* provide, (and return CAIRO_INT_STATUS_UNSUPPORTED or leave backend
|
||||
* function pointers NULL otherwise). The paginated surface is the
|
||||
* responsible for collecting operations that aren't supported,
|
||||
* replaying them against the image surface, and then supplying the
|
||||
* resulting images to the target surface.
|
||||
*
|
||||
* When created, a paginated surface accepts the target surface to
|
||||
* which the final drawing will eventually be performed. The paginated
|
||||
* surface then uses cairo_meta_surface_t to record all drawing
|
||||
* operations up until each show_page operation.
|
||||
*
|
||||
* At the time of show_page, the paginated surface replays the meta
|
||||
* surface against the target surface and maintains regions of the
|
||||
* result that will come from the nativ surface and regions that will
|
||||
* need to come from image fallbacks. It then replays the necessary
|
||||
* portions against image surface and provides those results to the
|
||||
* target surface through existing interfaces.
|
||||
*
|
||||
* This way the target surface is never even aware of any distinction
|
||||
* between native drawing operations vs. results that are supplied by
|
||||
* image fallbacks. Instead the surface need only implement as much of
|
||||
* the surface backend interface as it can do correctly, and let the
|
||||
* paginated surface take care of all the messy details.
|
||||
* (PostScript, PDF, etc.). See cairo-paginated-surface-private.h for
|
||||
* more details on how it works and how to use it.
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-paginated-surface-private.h"
|
||||
#include "cairo-meta-surface-private.h"
|
||||
#include "cairo-analysis-surface-private.h"
|
||||
|
||||
typedef struct _cairo_paginated_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
/* The target surface to hold the final result. */
|
||||
cairo_surface_t *target;
|
||||
|
||||
cairo_content_t content;
|
||||
|
||||
/* XXX: These shouldn't actually exist. We inherit this ugliness
|
||||
|
|
@ -82,14 +62,16 @@ typedef struct _cairo_paginated_surface {
|
|||
int width;
|
||||
int height;
|
||||
|
||||
/* The target surface to hold the final result. */
|
||||
cairo_surface_t *target;
|
||||
/* Paginated-surface specific functions for the target */
|
||||
const cairo_paginated_surface_backend_t *backend;
|
||||
|
||||
/* A cairo_meta_surface to record all operations. To be replayed
|
||||
* against target, and also against image surface as necessary for
|
||||
* fallbacks. */
|
||||
cairo_surface_t *meta;
|
||||
|
||||
cairo_bool_t page_is_blank;
|
||||
|
||||
} cairo_paginated_surface_t;
|
||||
|
||||
const cairo_private cairo_surface_backend_t cairo_paginated_surface_backend;
|
||||
|
|
@ -97,11 +79,30 @@ const cairo_private cairo_surface_backend_t cairo_paginated_surface_backend;
|
|||
static cairo_int_status_t
|
||||
_cairo_paginated_surface_show_page (void *abstract_surface);
|
||||
|
||||
/* XXX: This would seem the natural thing to do here. But currently,
|
||||
* PDF and PS surfaces do not yet work as source surfaces. So instead,
|
||||
* we don't implement create_similar for the paginate_surface which
|
||||
* means that any create_similar() call on a paginated_surfacae will
|
||||
* result in a new image surface. */
|
||||
#if 0
|
||||
static cairo_surface_t *
|
||||
_cairo_paginated_surface_create_similar (void *abstract_surface,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
return cairo_surface_create_similar (surface->target, content,
|
||||
width, height);
|
||||
}
|
||||
#endif
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_paginated_surface_create (cairo_surface_t *target,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height)
|
||||
_cairo_paginated_surface_create (cairo_surface_t *target,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height,
|
||||
const cairo_paginated_surface_backend_t *backend)
|
||||
{
|
||||
cairo_paginated_surface_t *surface;
|
||||
|
||||
|
|
@ -111,16 +112,24 @@ _cairo_paginated_surface_create (cairo_surface_t *target,
|
|||
|
||||
_cairo_surface_init (&surface->base, &cairo_paginated_surface_backend);
|
||||
|
||||
/* Override surface->base.type with target's type so we don't leak
|
||||
* evidence of the paginated wrapper out to the user. */
|
||||
surface->base.type = cairo_surface_get_type (target);
|
||||
|
||||
surface->target = target;
|
||||
|
||||
surface->content = content;
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
|
||||
surface->target = target;
|
||||
surface->backend = backend;
|
||||
|
||||
surface->meta = _cairo_meta_surface_create (content, width, height);
|
||||
if (cairo_surface_status (surface->meta))
|
||||
goto FAIL_CLEANUP_SURFACE;
|
||||
|
||||
surface->page_is_blank = TRUE;
|
||||
|
||||
return &surface->base;
|
||||
|
||||
FAIL_CLEANUP_SURFACE:
|
||||
|
|
@ -191,32 +200,70 @@ _cairo_paginated_surface_release_source_image (void *abstract_surface,
|
|||
cairo_surface_destroy (&image->base);
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_int_status_t
|
||||
_paint_page (cairo_paginated_surface_t *surface)
|
||||
{
|
||||
cairo_surface_t *analysis;
|
||||
cairo_surface_t *image;
|
||||
cairo_pattern_t *pattern;
|
||||
cairo_status_t status;
|
||||
|
||||
image = _cairo_image_surface_create_with_content (surface->content,
|
||||
surface->width,
|
||||
surface->height);
|
||||
analysis = _cairo_analysis_surface_create (surface->target,
|
||||
surface->width, surface->height);
|
||||
|
||||
_cairo_meta_surface_replay (surface->meta, image);
|
||||
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE);
|
||||
_cairo_meta_surface_replay (surface->meta, analysis);
|
||||
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER);
|
||||
|
||||
pattern = cairo_pattern_create_for_surface (image);
|
||||
if (analysis->status) {
|
||||
status = analysis->status;
|
||||
cairo_surface_destroy (analysis);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (_cairo_analysis_surface_has_unsupported (analysis))
|
||||
{
|
||||
image = _cairo_image_surface_create_with_content (surface->content,
|
||||
surface->width,
|
||||
surface->height);
|
||||
|
||||
_cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);
|
||||
_cairo_meta_surface_replay (surface->meta, image);
|
||||
|
||||
cairo_pattern_destroy (pattern);
|
||||
pattern = cairo_pattern_create_for_surface (image);
|
||||
|
||||
cairo_surface_destroy (image);
|
||||
_cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);
|
||||
|
||||
cairo_pattern_destroy (pattern);
|
||||
|
||||
cairo_surface_destroy (image);
|
||||
}
|
||||
else
|
||||
{
|
||||
_cairo_meta_surface_replay (surface->meta, surface->target);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_start_page (cairo_paginated_surface_t *surface)
|
||||
{
|
||||
if (! surface->backend->start_page)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return (surface->backend->start_page) (surface->target);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_paginated_surface_copy_page (void *abstract_surface)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
status = _start_page (surface);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_paint_page (surface);
|
||||
|
||||
/* XXX: It might make sense to add some suport here for calling
|
||||
|
|
@ -235,8 +282,13 @@ _cairo_paginated_surface_copy_page (void *abstract_surface)
|
|||
static cairo_int_status_t
|
||||
_cairo_paginated_surface_show_page (void *abstract_surface)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
status = _start_page (surface);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_paint_page (surface);
|
||||
|
||||
_cairo_surface_show_page (surface->target);
|
||||
|
|
@ -248,6 +300,8 @@ _cairo_paginated_surface_show_page (void *abstract_surface)
|
|||
if (cairo_surface_status (surface->meta))
|
||||
return cairo_surface_status (surface->meta);
|
||||
|
||||
surface->page_is_blank = TRUE;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -281,6 +335,12 @@ _cairo_paginated_surface_paint (void *abstract_surface,
|
|||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
/* Optimize away erasing of nothing. */
|
||||
if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
surface->page_is_blank = FALSE;
|
||||
|
||||
return _cairo_surface_paint (surface->meta, op, source);
|
||||
}
|
||||
|
||||
|
|
@ -308,6 +368,12 @@ _cairo_paginated_surface_stroke (void *abstract_surface,
|
|||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
/* Optimize away erasing of nothing. */
|
||||
if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
surface->page_is_blank = FALSE;
|
||||
|
||||
return _cairo_surface_stroke (surface->meta, op, source,
|
||||
path, style,
|
||||
ctm, ctm_inverse,
|
||||
|
|
@ -325,6 +391,12 @@ _cairo_paginated_surface_fill (void *abstract_surface,
|
|||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
/* Optimize away erasing of nothing. */
|
||||
if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
surface->page_is_blank = FALSE;
|
||||
|
||||
return _cairo_surface_fill (surface->meta, op, source,
|
||||
path, fill_rule,
|
||||
tolerance, antialias);
|
||||
|
|
@ -340,6 +412,12 @@ _cairo_paginated_surface_show_glyphs (void *abstract_surface,
|
|||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
/* Optimize away erasing of nothing. */
|
||||
if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
surface->page_is_blank = FALSE;
|
||||
|
||||
return _cairo_surface_show_glyphs (surface->meta, op, source,
|
||||
glyphs, num_glyphs,
|
||||
scaled_font);
|
||||
|
|
@ -381,7 +459,8 @@ _cairo_paginated_surface_snapshot (void *abstract_other)
|
|||
}
|
||||
|
||||
const cairo_surface_backend_t cairo_paginated_surface_backend = {
|
||||
NULL, /* create_similar */
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
|
||||
NULL, /* create_similar --- see note for _cairo_paginated_surface_create_similar */
|
||||
_cairo_paginated_surface_finish,
|
||||
_cairo_paginated_surface_acquire_source_image,
|
||||
_cairo_paginated_surface_release_source_image,
|
||||
|
|
|
|||
|
|
@ -115,7 +115,11 @@ _cairo_stroker_start_dash (cairo_stroker_t *stroker)
|
|||
int i = 0;
|
||||
|
||||
offset = stroker->style->dash_offset;
|
||||
while (offset >= stroker->style->dash[i]) {
|
||||
|
||||
/* We stop searching for a starting point as soon as the
|
||||
offset reaches zero. Otherwise when an initial dash
|
||||
segment shrinks to zero it will be skipped over. */
|
||||
while (offset > 0.0 && offset >= stroker->style->dash[i]) {
|
||||
offset -= stroker->style->dash[i];
|
||||
on = 1-on;
|
||||
if (++i == stroker->style->num_dashes)
|
||||
|
|
@ -546,11 +550,18 @@ _compute_face (cairo_point_t *point, cairo_slope_t *slope, cairo_stroker_t *stro
|
|||
|
||||
static cairo_status_t
|
||||
_cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_point_t *p2,
|
||||
cairo_stroke_face_t *start, cairo_stroke_face_t *end)
|
||||
cairo_slope_t *slope, cairo_stroke_face_t *start,
|
||||
cairo_stroke_face_t *end)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_polygon_t polygon;
|
||||
cairo_slope_t slope;
|
||||
|
||||
_compute_face (p1, slope, stroker, start);
|
||||
|
||||
/* XXX: This could be optimized slightly by not calling
|
||||
_compute_face again but rather translating the relevant
|
||||
fields from start. */
|
||||
_compute_face (p2, slope, stroker, end);
|
||||
|
||||
if (p1->x == p2->x && p1->y == p2->y) {
|
||||
/* XXX: Need to rethink how this case should be handled, (both
|
||||
|
|
@ -559,14 +570,6 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_cairo_slope_init (&slope, p1, p2);
|
||||
_compute_face (p1, &slope, stroker, start);
|
||||
|
||||
/* XXX: This could be optimized slightly by not calling
|
||||
_compute_face again but rather translating the relevant
|
||||
fields from start. */
|
||||
_compute_face (p2, &slope, stroker, end);
|
||||
|
||||
/* XXX: I should really check the return value of the
|
||||
move_to/line_to functions here to catch out of memory
|
||||
conditions. But since that would be ugly, I'd prefer to add a
|
||||
|
|
@ -612,6 +615,16 @@ _cairo_stroker_move_to (void *closure, cairo_point_t *point)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_stroker_move_to_dashed (void *closure, cairo_point_t *point)
|
||||
{
|
||||
/* reset the dash pattern for new sub paths */
|
||||
cairo_stroker_t *stroker = closure;
|
||||
_cairo_stroker_start_dash (stroker);
|
||||
|
||||
return _cairo_stroker_move_to (closure, point);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_stroker_line_to (void *closure, cairo_point_t *point)
|
||||
{
|
||||
|
|
@ -620,6 +633,7 @@ _cairo_stroker_line_to (void *closure, cairo_point_t *point)
|
|||
cairo_stroke_face_t start, end;
|
||||
cairo_point_t *p1 = &stroker->current_point;
|
||||
cairo_point_t *p2 = point;
|
||||
cairo_slope_t slope;
|
||||
|
||||
if (p1->x == p2->x && p1->y == p2->y) {
|
||||
/* XXX: Need to rethink how this case should be handled, (both
|
||||
|
|
@ -628,8 +642,10 @@ _cairo_stroker_line_to (void *closure, cairo_point_t *point)
|
|||
as possible. */
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_cairo_slope_init (&slope, p1, p2);
|
||||
|
||||
status = _cairo_stroker_add_sub_edge (stroker, p1, p2, &start, &end);
|
||||
status = _cairo_stroker_add_sub_edge (stroker, p1, p2, &slope, &start, &end);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
|
@ -667,6 +683,17 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
|
|||
cairo_stroke_face_t sub_start, sub_end;
|
||||
cairo_point_t *p1 = &stroker->current_point;
|
||||
cairo_point_t *p2 = point;
|
||||
cairo_slope_t slope;
|
||||
|
||||
if (p1->x == p2->x && p1->y == p2->y) {
|
||||
/* XXX: Need to rethink how this case should be handled, (both
|
||||
here and in cairo_stroker_add_sub_edge and in _compute_face). The
|
||||
key behavior is that degenerate paths should draw as much
|
||||
as possible. */
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_cairo_slope_init (&slope, p1, p2);
|
||||
|
||||
dx = _cairo_fixed_to_double (p2->x - p1->x);
|
||||
dy = _cairo_fixed_to_double (p2->y - p1->y);
|
||||
|
|
@ -692,7 +719,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
|
|||
* XXX simplify this case analysis
|
||||
*/
|
||||
if (stroker->dash_on) {
|
||||
status = _cairo_stroker_add_sub_edge (stroker, &fd1, &fd2, &sub_start, &sub_end);
|
||||
status = _cairo_stroker_add_sub_edge (stroker, &fd1, &fd2, &slope, &sub_start, &sub_end);
|
||||
if (status)
|
||||
return status;
|
||||
if (!first) {
|
||||
|
|
@ -942,7 +969,7 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
|
|||
if (stroker.style->dash)
|
||||
status = _cairo_path_fixed_interpret (path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_stroker_move_to,
|
||||
_cairo_stroker_move_to_dashed,
|
||||
_cairo_stroker_line_to_dashed,
|
||||
_cairo_stroker_curve_to_dashed,
|
||||
_cairo_stroker_close_path,
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#include "cairoint.h"
|
||||
|
||||
const cairo_solid_pattern_t cairo_pattern_nil = {
|
||||
{ CAIRO_PATTERN_SOLID, /* type */
|
||||
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
|
||||
(unsigned int)-1, /* ref_count */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
|
|
@ -39,7 +39,7 @@ const cairo_solid_pattern_t cairo_pattern_nil = {
|
|||
};
|
||||
|
||||
static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = {
|
||||
{ CAIRO_PATTERN_SOLID, /* type */
|
||||
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
|
||||
(unsigned int)-1, /* ref_count */
|
||||
CAIRO_STATUS_NULL_POINTER,/* status */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
|
|
@ -48,7 +48,7 @@ static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = {
|
|||
};
|
||||
|
||||
static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = {
|
||||
{ CAIRO_PATTERN_SOLID, /* type */
|
||||
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
|
||||
(unsigned int)-1, /* ref_count */
|
||||
CAIRO_STATUS_FILE_NOT_FOUND, /* status */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
|
|
@ -57,7 +57,7 @@ static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = {
|
|||
};
|
||||
|
||||
static const cairo_solid_pattern_t cairo_pattern_nil_read_error = {
|
||||
{ CAIRO_PATTERN_SOLID, /* type */
|
||||
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
|
||||
(unsigned int)-1, /* ref_count */
|
||||
CAIRO_STATUS_READ_ERROR, /* status */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
|
|
@ -117,7 +117,7 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
|
|||
pattern->ref_count = 1;
|
||||
pattern->status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (type == CAIRO_PATTERN_SURFACE)
|
||||
if (type == CAIRO_PATTERN_TYPE_SURFACE)
|
||||
pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
|
||||
else
|
||||
pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT;
|
||||
|
|
@ -131,7 +131,7 @@ static void
|
|||
_cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
|
||||
const cairo_gradient_pattern_t *other)
|
||||
{
|
||||
if (other->base.type == CAIRO_PATTERN_LINEAR)
|
||||
if (other->base.type == CAIRO_PATTERN_TYPE_LINEAR)
|
||||
{
|
||||
cairo_linear_pattern_t *dst = (cairo_linear_pattern_t *) pattern;
|
||||
cairo_linear_pattern_t *src = (cairo_linear_pattern_t *) other;
|
||||
|
|
@ -170,21 +170,21 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern,
|
|||
}
|
||||
|
||||
switch (other->type) {
|
||||
case CAIRO_PATTERN_SOLID: {
|
||||
case CAIRO_PATTERN_TYPE_SOLID: {
|
||||
cairo_solid_pattern_t *dst = (cairo_solid_pattern_t *) pattern;
|
||||
cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) other;
|
||||
|
||||
*dst = *src;
|
||||
} break;
|
||||
case CAIRO_PATTERN_SURFACE: {
|
||||
case CAIRO_PATTERN_TYPE_SURFACE: {
|
||||
cairo_surface_pattern_t *dst = (cairo_surface_pattern_t *) pattern;
|
||||
cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) other;
|
||||
|
||||
*dst = *src;
|
||||
cairo_surface_reference (dst->surface);
|
||||
} break;
|
||||
case CAIRO_PATTERN_LINEAR:
|
||||
case CAIRO_PATTERN_RADIAL: {
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
case CAIRO_PATTERN_TYPE_RADIAL: {
|
||||
cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern;
|
||||
cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other;
|
||||
|
||||
|
|
@ -199,16 +199,16 @@ void
|
|||
_cairo_pattern_fini (cairo_pattern_t *pattern)
|
||||
{
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_SOLID:
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
break;
|
||||
case CAIRO_PATTERN_SURFACE: {
|
||||
case CAIRO_PATTERN_TYPE_SURFACE: {
|
||||
cairo_surface_pattern_t *surface_pattern =
|
||||
(cairo_surface_pattern_t *) pattern;
|
||||
|
||||
cairo_surface_destroy (surface_pattern->surface);
|
||||
} break;
|
||||
case CAIRO_PATTERN_LINEAR:
|
||||
case CAIRO_PATTERN_RADIAL: {
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
case CAIRO_PATTERN_TYPE_RADIAL: {
|
||||
cairo_gradient_pattern_t *gradient =
|
||||
(cairo_gradient_pattern_t *) pattern;
|
||||
|
||||
|
|
@ -222,7 +222,7 @@ void
|
|||
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
|
||||
const cairo_color_t *color)
|
||||
{
|
||||
_cairo_pattern_init (&pattern->base, CAIRO_PATTERN_SOLID);
|
||||
_cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
|
||||
pattern->color = *color;
|
||||
}
|
||||
|
||||
|
|
@ -232,12 +232,12 @@ _cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern,
|
|||
{
|
||||
if (surface->status) {
|
||||
/* Force to solid to simplify the pattern_fini process. */
|
||||
pattern->base.type = CAIRO_PATTERN_SOLID;
|
||||
pattern->base.type = CAIRO_PATTERN_TYPE_SOLID;
|
||||
_cairo_pattern_set_error (&pattern->base, surface->status);
|
||||
return;
|
||||
}
|
||||
|
||||
_cairo_pattern_init (&pattern->base, CAIRO_PATTERN_SURFACE);
|
||||
_cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SURFACE);
|
||||
|
||||
pattern->surface = cairo_surface_reference (surface);
|
||||
}
|
||||
|
|
@ -256,7 +256,7 @@ void
|
|||
_cairo_pattern_init_linear (cairo_linear_pattern_t *pattern,
|
||||
double x0, double y0, double x1, double y1)
|
||||
{
|
||||
_cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_LINEAR);
|
||||
_cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_LINEAR);
|
||||
|
||||
pattern->gradient.p1.x = _cairo_fixed_from_double (x0);
|
||||
pattern->gradient.p1.y = _cairo_fixed_from_double (y0);
|
||||
|
|
@ -269,7 +269,7 @@ _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
|
|||
double cx0, double cy0, double radius0,
|
||||
double cx1, double cy1, double radius1)
|
||||
{
|
||||
_cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_RADIAL);
|
||||
_cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL);
|
||||
|
||||
pattern->gradient.inner.x = _cairo_fixed_from_double (cx0);
|
||||
pattern->gradient.inner.y = _cairo_fixed_from_double (cy0);
|
||||
|
|
@ -524,6 +524,18 @@ cairo_pattern_reference (cairo_pattern_t *pattern)
|
|||
return pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_pattern_get_type:
|
||||
* @pattern: a #cairo_pattern_t
|
||||
*
|
||||
* Return value: The type of @pattern. See #cairo_pattern_type_t.
|
||||
**/
|
||||
cairo_pattern_type_t
|
||||
cairo_pattern_get_type (cairo_pattern_t *pattern)
|
||||
{
|
||||
return pattern->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_pattern_status:
|
||||
* @pattern: a #cairo_pattern_t
|
||||
|
|
@ -641,8 +653,8 @@ cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
|
|||
if (pattern->status)
|
||||
return;
|
||||
|
||||
if (pattern->type != CAIRO_PATTERN_LINEAR &&
|
||||
pattern->type != CAIRO_PATTERN_RADIAL)
|
||||
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
|
||||
pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
|
||||
{
|
||||
_cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
|
||||
return;
|
||||
|
|
@ -689,8 +701,8 @@ cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
|
|||
if (pattern->status)
|
||||
return;
|
||||
|
||||
if (pattern->type != CAIRO_PATTERN_LINEAR &&
|
||||
pattern->type != CAIRO_PATTERN_RADIAL)
|
||||
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
|
||||
pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
|
||||
{
|
||||
_cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
|
||||
return;
|
||||
|
|
@ -894,7 +906,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
|
|||
cairo_status_t status;
|
||||
cairo_bool_t repeat = FALSE;
|
||||
|
||||
if (pattern->base.type == CAIRO_PATTERN_LINEAR)
|
||||
if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR)
|
||||
{
|
||||
cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern;
|
||||
|
||||
|
|
@ -936,7 +948,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (pattern->base.type == CAIRO_PATTERN_LINEAR) {
|
||||
if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
|
||||
cairo_bool_t is_horizontal;
|
||||
cairo_bool_t is_vertical;
|
||||
|
||||
|
|
@ -1038,7 +1050,6 @@ _cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t *pattern,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* _cairo_pattern_is_opaque_solid
|
||||
*
|
||||
|
|
@ -1051,11 +1062,11 @@ _cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t *pattern,
|
|||
* Return value: %TRUE if the pattern is an opaque, solid color.
|
||||
**/
|
||||
cairo_bool_t
|
||||
_cairo_pattern_is_opaque_solid (cairo_pattern_t *pattern)
|
||||
_cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern)
|
||||
{
|
||||
cairo_solid_pattern_t *solid;
|
||||
|
||||
if (pattern->type != CAIRO_PATTERN_SOLID)
|
||||
if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
|
||||
return FALSE;
|
||||
|
||||
solid = (cairo_solid_pattern_t *) pattern;
|
||||
|
|
@ -1063,6 +1074,47 @@ _cairo_pattern_is_opaque_solid (cairo_pattern_t *pattern)
|
|||
return CAIRO_ALPHA_IS_OPAQUE (solid->color.alpha);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_gradient_is_opaque (const cairo_gradient_pattern_t *gradient)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < gradient->n_stops; i++)
|
||||
if (! CAIRO_ALPHA_IS_OPAQUE (gradient->stops[i].color.alpha))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_pattern_is_opaque
|
||||
*
|
||||
* Convenience function to determine whether a pattern is an opaque
|
||||
* pattern (of any type). The same caveats that apply to
|
||||
* _cairo_pattern_is_opaque_solid apply here as well.
|
||||
*
|
||||
* Return value: %TRUE if the pattern is a opaque.
|
||||
**/
|
||||
cairo_bool_t
|
||||
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern)
|
||||
{
|
||||
const cairo_pattern_union_t *pattern;
|
||||
|
||||
pattern = (cairo_pattern_union_t *) abstract_pattern;
|
||||
switch (pattern->base.type) {
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
return _cairo_pattern_is_opaque_solid (abstract_pattern);
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
return _cairo_surface_is_opaque (pattern->surface.surface);
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
return _gradient_is_opaque (&pattern->gradient.base);
|
||||
}
|
||||
|
||||
ASSERT_NOT_REACHED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
||||
cairo_surface_t *dst,
|
||||
|
|
@ -1151,7 +1203,7 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
|
|||
}
|
||||
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_SOLID: {
|
||||
case CAIRO_PATTERN_TYPE_SOLID: {
|
||||
cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) pattern;
|
||||
|
||||
status = _cairo_pattern_acquire_surface_for_solid (src, dst,
|
||||
|
|
@ -1159,8 +1211,8 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
|
|||
surface_out,
|
||||
attributes);
|
||||
} break;
|
||||
case CAIRO_PATTERN_LINEAR:
|
||||
case CAIRO_PATTERN_RADIAL: {
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
case CAIRO_PATTERN_TYPE_RADIAL: {
|
||||
cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) pattern;
|
||||
|
||||
/* fast path for gradients with less than 2 color stops */
|
||||
|
|
@ -1203,7 +1255,7 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
|
|||
attributes);
|
||||
}
|
||||
} break;
|
||||
case CAIRO_PATTERN_SURFACE: {
|
||||
case CAIRO_PATTERN_TYPE_SURFACE: {
|
||||
cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) pattern;
|
||||
|
||||
status = _cairo_pattern_acquire_surface_for_surface (src, dst,
|
||||
|
|
@ -1235,7 +1287,7 @@ _cairo_pattern_release_surface (cairo_pattern_t *pattern,
|
|||
{
|
||||
cairo_surface_pattern_t *surface_pattern;
|
||||
|
||||
assert (pattern->type == CAIRO_PATTERN_SURFACE);
|
||||
assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
|
||||
surface_pattern = (cairo_surface_pattern_t *) pattern;
|
||||
|
||||
_cairo_surface_release_source_image (surface_pattern->surface,
|
||||
|
|
@ -1277,8 +1329,8 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t *src,
|
|||
/* XXX: This optimization assumes that there is no color
|
||||
* information in mask, so this will need to change when we
|
||||
* support RENDER-style 4-channel masks. */
|
||||
if (src->type == CAIRO_PATTERN_SOLID &&
|
||||
mask && mask->type == CAIRO_PATTERN_SOLID)
|
||||
if (src->type == CAIRO_PATTERN_TYPE_SOLID &&
|
||||
mask && mask->type == CAIRO_PATTERN_TYPE_SOLID)
|
||||
{
|
||||
cairo_color_t combined;
|
||||
cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src;
|
||||
|
|
@ -1346,7 +1398,7 @@ _cairo_pattern_get_extents (cairo_pattern_t *pattern,
|
|||
cairo_rectangle_t *extents)
|
||||
{
|
||||
if (pattern->extend == CAIRO_EXTEND_NONE &&
|
||||
pattern->type == CAIRO_PATTERN_SURFACE)
|
||||
pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_rectangle_t surface_extents;
|
||||
|
|
|
|||
|
|
@ -140,6 +140,8 @@ struct cairo_pdf_surface {
|
|||
cairo_array_t alphas;
|
||||
cairo_array_t fonts;
|
||||
cairo_bool_t has_clip;
|
||||
|
||||
cairo_paginated_mode_t paginated_mode;
|
||||
};
|
||||
|
||||
#define DEFAULT_DPI 300
|
||||
|
|
@ -186,6 +188,7 @@ static void
|
|||
_cairo_pdf_surface_ensure_stream (cairo_pdf_surface_t *surface);
|
||||
|
||||
static const cairo_surface_backend_t cairo_pdf_surface_backend;
|
||||
static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend;
|
||||
|
||||
static unsigned int
|
||||
_cairo_pdf_document_new_object (cairo_pdf_document_t *document)
|
||||
|
|
@ -306,7 +309,8 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
|||
|
||||
return _cairo_paginated_surface_create (target,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
width, height);
|
||||
width, height,
|
||||
&cairo_pdf_surface_paginated_backend);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -333,11 +337,13 @@ cairo_pdf_surface_create_for_stream (cairo_write_func_t write,
|
|||
double width_in_points,
|
||||
double height_in_points)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_output_stream_t *stream;
|
||||
|
||||
stream = _cairo_output_stream_create (write, closure);
|
||||
if (stream == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
stream = _cairo_output_stream_create (write, NULL, closure);
|
||||
status = _cairo_output_stream_get_status (stream);
|
||||
if (status) {
|
||||
_cairo_error (status);
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
|
|
@ -368,11 +374,13 @@ cairo_pdf_surface_create (const char *filename,
|
|||
double width_in_points,
|
||||
double height_in_points)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_output_stream_t *stream;
|
||||
|
||||
stream = _cairo_output_stream_create_for_file (filename);
|
||||
if (stream == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
stream = _cairo_output_stream_create_for_filename (filename);
|
||||
status = _cairo_output_stream_get_status (stream);
|
||||
if (status) {
|
||||
_cairo_error (status);
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
|
|
@ -388,7 +396,7 @@ _cairo_surface_is_pdf (cairo_surface_t *surface)
|
|||
}
|
||||
|
||||
/**
|
||||
* cairo__surface_set_dpi:
|
||||
* cairo_pdf_surface_set_dpi:
|
||||
* @surface: a postscript cairo_surface_t
|
||||
* @x_dpi: horizontal dpi
|
||||
* @y_dpi: vertical dpi
|
||||
|
|
@ -451,6 +459,8 @@ _cairo_pdf_surface_create_for_document (cairo_pdf_document_t *document,
|
|||
_cairo_array_init (&surface->fonts, sizeof (cairo_pdf_resource_t));
|
||||
surface->has_clip = FALSE;
|
||||
|
||||
surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
|
||||
|
||||
return &surface->base;
|
||||
}
|
||||
|
||||
|
|
@ -654,8 +664,10 @@ emit_image_rgb_data (cairo_pdf_document_t *document,
|
|||
opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
|
||||
image->width,
|
||||
image->height);
|
||||
if (opaque->status)
|
||||
if (opaque->status) {
|
||||
free (rgb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
|
||||
|
||||
|
|
@ -841,7 +853,7 @@ _cairo_pdf_surface_composite (cairo_operator_t op,
|
|||
if (mask_pattern)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (src_pattern->type != CAIRO_PATTERN_SURFACE)
|
||||
if (src_pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (src->surface->backend == &cairo_pdf_surface_backend)
|
||||
|
|
@ -1237,16 +1249,16 @@ static cairo_status_t
|
|||
emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern)
|
||||
{
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_SOLID:
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
return emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
|
||||
|
||||
case CAIRO_PATTERN_SURFACE:
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
return emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
|
||||
|
||||
case CAIRO_PATTERN_LINEAR:
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
return emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
|
||||
|
||||
case CAIRO_PATTERN_RADIAL:
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
return emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
|
||||
}
|
||||
|
||||
|
|
@ -1320,55 +1332,6 @@ _cairo_pdf_path_close_path (void *closure)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_surface_fill (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *pattern,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
cairo_pdf_document_t *document = surface->document;
|
||||
const char *pdf_operator;
|
||||
cairo_status_t status;
|
||||
|
||||
status = emit_pattern (surface, pattern);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* After the above switch the current stream should belong to this
|
||||
* surface, so no need to _cairo_pdf_surface_ensure_stream() */
|
||||
assert (document->current_stream != NULL &&
|
||||
document->current_stream == surface->current_stream);
|
||||
|
||||
status = _cairo_path_fixed_interpret (path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_pdf_path_move_to,
|
||||
_cairo_pdf_path_line_to,
|
||||
_cairo_pdf_path_curve_to,
|
||||
_cairo_pdf_path_close_path,
|
||||
document->output_stream);
|
||||
|
||||
switch (fill_rule) {
|
||||
case CAIRO_FILL_RULE_WINDING:
|
||||
pdf_operator = "f";
|
||||
break;
|
||||
case CAIRO_FILL_RULE_EVEN_ODD:
|
||||
pdf_operator = "f*";
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (document->output_stream,
|
||||
"%s\r\n",
|
||||
pdf_operator);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_surface_composite_trapezoids (cairo_operator_t op,
|
||||
cairo_pattern_t *pattern,
|
||||
|
|
@ -1632,38 +1595,6 @@ _cairo_pdf_surface_get_font_options (void *abstract_surface,
|
|||
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_pdf_surface_backend = {
|
||||
_cairo_pdf_surface_create_similar,
|
||||
_cairo_pdf_surface_finish,
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
NULL, /* acquire_dest_image */
|
||||
NULL, /* release_dest_image */
|
||||
NULL, /* clone_similar */
|
||||
_cairo_pdf_surface_composite,
|
||||
_cairo_pdf_surface_fill_rectangles,
|
||||
_cairo_pdf_surface_composite_trapezoids,
|
||||
_cairo_pdf_surface_copy_page,
|
||||
_cairo_pdf_surface_show_page,
|
||||
NULL, /* set_clip_region */
|
||||
_cairo_pdf_surface_intersect_clip_path,
|
||||
_cairo_pdf_surface_get_extents,
|
||||
_cairo_pdf_surface_old_show_glyphs,
|
||||
_cairo_pdf_surface_get_font_options,
|
||||
NULL, /* flush */
|
||||
NULL, /* mark_dirty_rectangle */
|
||||
NULL, /* scaled_font_fini */
|
||||
NULL, /* scaled_glyph_fini */
|
||||
|
||||
/* Here are the drawing functions */
|
||||
|
||||
NULL, /* paint */
|
||||
NULL, /* mask */
|
||||
NULL, /* stroke */
|
||||
_cairo_pdf_surface_fill,
|
||||
NULL /* show_glyphs */
|
||||
};
|
||||
|
||||
static cairo_pdf_document_t *
|
||||
_cairo_pdf_document_create (cairo_output_stream_t *output_stream,
|
||||
double width,
|
||||
|
|
@ -2086,3 +2017,229 @@ _cairo_pdf_document_add_page (cairo_pdf_document_t *document,
|
|||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_surface_pattern_supported (const cairo_surface_pattern_t *pattern)
|
||||
{
|
||||
if (pattern->surface->backend->acquire_source_image != NULL)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_pattern_supported (const cairo_pattern_t *pattern)
|
||||
{
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
|
||||
return TRUE;
|
||||
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
|
||||
return _surface_pattern_supported ((const cairo_surface_pattern_t *) pattern);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_operation_supported (cairo_pdf_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern)
|
||||
{
|
||||
if (! _pattern_supported (pattern))
|
||||
return FALSE;
|
||||
|
||||
if (_cairo_operator_always_opaque (op))
|
||||
return TRUE;
|
||||
|
||||
if (_cairo_operator_always_translucent (op))
|
||||
return FALSE;
|
||||
|
||||
return _cairo_pattern_is_opaque (pattern);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_analyze_operation (cairo_pdf_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern)
|
||||
{
|
||||
if (_operation_supported (surface, op, pattern))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
else
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
/* One would think that since we analyzed this away as unsupported
|
||||
* that it would never be called after analyzing. But in fact,
|
||||
* paint is called to paint the actual fallback surface. So we
|
||||
* must not ASSERT_NOT_REACHED as we do for the other drawing
|
||||
* operations. */
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_surface_mask (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
cairo_pattern_t *mask)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
ASSERT_NOT_REACHED;
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_surface_stroke (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
ASSERT_NOT_REACHED;
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_surface_fill (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
cairo_pdf_document_t *document = surface->document;
|
||||
const char *pdf_operator;
|
||||
cairo_status_t status;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _analyze_operation (surface, op, source);
|
||||
|
||||
assert (_operation_supported (surface, op, source));
|
||||
|
||||
status = emit_pattern (surface, source);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* After emitting the pattern the current stream should belong to
|
||||
* this surface, so no need to _cairo_pdf_surface_ensure_stream()
|
||||
*/
|
||||
assert (document->current_stream != NULL &&
|
||||
document->current_stream == surface->current_stream);
|
||||
|
||||
status = _cairo_path_fixed_interpret (path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_pdf_path_move_to,
|
||||
_cairo_pdf_path_line_to,
|
||||
_cairo_pdf_path_curve_to,
|
||||
_cairo_pdf_path_close_path,
|
||||
document->output_stream);
|
||||
|
||||
switch (fill_rule) {
|
||||
case CAIRO_FILL_RULE_WINDING:
|
||||
pdf_operator = "f";
|
||||
break;
|
||||
case CAIRO_FILL_RULE_EVEN_ODD:
|
||||
pdf_operator = "f*";
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (document->output_stream,
|
||||
"%s\r\n",
|
||||
pdf_operator);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_surface_show_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
ASSERT_NOT_REACHED;
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
|
||||
cairo_paginated_mode_t paginated_mode)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
|
||||
surface->paginated_mode = paginated_mode;
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_pdf_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_PDF,
|
||||
_cairo_pdf_surface_create_similar,
|
||||
_cairo_pdf_surface_finish,
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
NULL, /* acquire_dest_image */
|
||||
NULL, /* release_dest_image */
|
||||
NULL, /* clone_similar */
|
||||
_cairo_pdf_surface_composite,
|
||||
_cairo_pdf_surface_fill_rectangles,
|
||||
_cairo_pdf_surface_composite_trapezoids,
|
||||
_cairo_pdf_surface_copy_page,
|
||||
_cairo_pdf_surface_show_page,
|
||||
NULL, /* set_clip_region */
|
||||
_cairo_pdf_surface_intersect_clip_path,
|
||||
_cairo_pdf_surface_get_extents,
|
||||
_cairo_pdf_surface_old_show_glyphs,
|
||||
_cairo_pdf_surface_get_font_options,
|
||||
NULL, /* flush */
|
||||
NULL, /* mark_dirty_rectangle */
|
||||
NULL, /* scaled_font_fini */
|
||||
NULL, /* scaled_glyph_fini */
|
||||
|
||||
/* Here are the drawing functions */
|
||||
|
||||
_cairo_pdf_surface_paint,
|
||||
_cairo_pdf_surface_mask,
|
||||
_cairo_pdf_surface_stroke,
|
||||
_cairo_pdf_surface_fill,
|
||||
_cairo_pdf_surface_show_glyphs,
|
||||
NULL, /* snapshot */
|
||||
};
|
||||
|
||||
static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = {
|
||||
NULL, /* start_page */
|
||||
_cairo_pdf_surface_set_paginated_mode
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,15 +44,11 @@ typedef struct cairo_quartz_surface {
|
|||
|
||||
CGContextRef context;
|
||||
|
||||
cairo_bool_t flipped;
|
||||
cairo_bool_t y_grows_down;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
cairo_rectangle_t extents;
|
||||
|
||||
cairo_image_surface_t *image;
|
||||
pixman_region16_t *clip_region;
|
||||
|
||||
CGImageRef cgImage;
|
||||
pixman_region16_t *clip_region;
|
||||
} cairo_quartz_surface_t;
|
||||
|
||||
cairo_bool_t
|
||||
|
|
|
|||
|
|
@ -37,27 +37,13 @@
|
|||
#include "cairo-private.h"
|
||||
#include "cairo-quartz-private.h"
|
||||
|
||||
static void
|
||||
ImageDataReleaseFunc(void *info, const void *data, size_t size)
|
||||
{
|
||||
if (data != NULL) {
|
||||
free((void *) data);
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_quartz_surface_finish(void *abstract_surface)
|
||||
{
|
||||
cairo_quartz_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->image)
|
||||
cairo_surface_destroy(&surface->image->base);
|
||||
|
||||
if (surface->cgImage)
|
||||
CGImageRelease(surface->cgImage);
|
||||
|
||||
if (surface->clip_region)
|
||||
pixman_region_destroy (surface->clip_region);
|
||||
if (surface->clip_region)
|
||||
pixman_region_destroy (surface->clip_region);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -67,63 +53,13 @@ _cairo_quartz_surface_acquire_source_image(void *abstract_surface,
|
|||
cairo_image_surface_t **image_out,
|
||||
void **image_extra)
|
||||
{
|
||||
cairo_quartz_surface_t *surface = abstract_surface;
|
||||
CGColorSpaceRef colorSpace;
|
||||
void *imageData;
|
||||
UInt32 imageDataSize, rowBytes;
|
||||
CGDataProviderRef dataProvider;
|
||||
cairo_quartz_surface_t *surface = abstract_surface;
|
||||
|
||||
// We keep a cached (cairo_image_surface_t *) in the cairo_quartz_surface_t
|
||||
// struct. If the window is ever drawn to without going through Cairo, then
|
||||
// we would need to refetch the pixel data from the window into the cached
|
||||
// image surface.
|
||||
if (surface->image) {
|
||||
cairo_surface_reference(&surface->image->base);
|
||||
if (CGBitmapContextGetBitmapInfo (surface->context) != 0) {
|
||||
/* XXX: We can create an image out of the bitmap here */
|
||||
}
|
||||
|
||||
*image_out = surface->image;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
|
||||
|
||||
rowBytes = surface->width * 4;
|
||||
imageDataSize = rowBytes * surface->height;
|
||||
imageData = malloc(imageDataSize);
|
||||
|
||||
dataProvider =
|
||||
CGDataProviderCreateWithData(NULL, imageData, imageDataSize,
|
||||
ImageDataReleaseFunc);
|
||||
|
||||
surface->cgImage = CGImageCreate(surface->width,
|
||||
surface->height,
|
||||
8,
|
||||
32,
|
||||
rowBytes,
|
||||
colorSpace,
|
||||
kCGImageAlphaPremultipliedFirst,
|
||||
dataProvider,
|
||||
NULL,
|
||||
false, kCGRenderingIntentDefault);
|
||||
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
CGDataProviderRelease(dataProvider);
|
||||
|
||||
surface->image = (cairo_image_surface_t *)
|
||||
cairo_image_surface_create_for_data(imageData,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
surface->width,
|
||||
surface->height, rowBytes);
|
||||
if (surface->image->base.status) {
|
||||
if (surface->cgImage)
|
||||
CGImageRelease(surface->cgImage);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
*image_out = surface->image;
|
||||
*image_extra = NULL;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
@ -135,19 +71,79 @@ _cairo_quartz_surface_acquire_dest_image(void *abstract_surface,
|
|||
void **image_extra)
|
||||
{
|
||||
cairo_quartz_surface_t *surface = abstract_surface;
|
||||
cairo_surface_t *image_surface;
|
||||
unsigned char *data;
|
||||
int x1, y1, x2, y2;
|
||||
|
||||
image_rect->x = 0;
|
||||
image_rect->y = 0;
|
||||
image_rect->width = surface->image->width;
|
||||
image_rect->height = surface->image->height;
|
||||
x1 = surface->extents.x;
|
||||
x2 = surface->extents.x + surface->extents.width;
|
||||
y1 = surface->extents.y;
|
||||
y2 = surface->extents.y + surface->extents.height;
|
||||
|
||||
*image_out = surface->image;
|
||||
if (image_extra)
|
||||
if (interest_rect->x > x1)
|
||||
x1 = interest_rect->x;
|
||||
if (interest_rect->y > y1)
|
||||
y1 = interest_rect->y;
|
||||
if (interest_rect->x + interest_rect->width < x2)
|
||||
x2 = interest_rect->x + interest_rect->width;
|
||||
if (interest_rect->y + interest_rect->height < y2)
|
||||
y2 = interest_rect->y + interest_rect->height;
|
||||
|
||||
if (x1 >= x2 || y1 >= y2) {
|
||||
*image_out = NULL;
|
||||
*image_extra = NULL;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
image_rect->x = x1;
|
||||
image_rect->y = y1;
|
||||
image_rect->width = x2 - x1;
|
||||
image_rect->height = y2 - y1;
|
||||
|
||||
data = calloc (image_rect->width * image_rect->height * 4, 1);
|
||||
image_surface = cairo_image_surface_create_for_data (data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
image_rect->width,
|
||||
image_rect->height,
|
||||
image_rect->width * 4);
|
||||
|
||||
*image_out = (cairo_image_surface_t *)image_surface;
|
||||
*image_extra = data;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static CGImageRef
|
||||
create_image_from_surface (cairo_image_surface_t *image_surface, void *data)
|
||||
{
|
||||
CGImageRef image;
|
||||
CGColorSpaceRef color_space;
|
||||
CGDataProviderRef data_provider;
|
||||
int width, height;
|
||||
|
||||
width = cairo_image_surface_get_width ((cairo_surface_t *)image_surface);
|
||||
height = cairo_image_surface_get_height ((cairo_surface_t *)image_surface);
|
||||
|
||||
color_space = CGColorSpaceCreateDeviceRGB();
|
||||
data_provider = CGDataProviderCreateWithData (NULL, data,
|
||||
width * height * 4, NULL);
|
||||
image = CGImageCreate (width, height,
|
||||
8, 32,
|
||||
width * 4,
|
||||
color_space,
|
||||
kCGImageAlphaPremultipliedFirst,
|
||||
data_provider,
|
||||
NULL,
|
||||
FALSE, kCGRenderingIntentDefault);
|
||||
|
||||
CGColorSpaceRelease (color_space);
|
||||
CGDataProviderRelease (data_provider);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_quartz_surface_release_dest_image(void *abstract_surface,
|
||||
|
|
@ -158,25 +154,28 @@ _cairo_quartz_surface_release_dest_image(void *abstract_surface,
|
|||
void *image_extra)
|
||||
{
|
||||
cairo_quartz_surface_t *surface = abstract_surface;
|
||||
CGImageRef image_ref;
|
||||
CGRect rect;
|
||||
|
||||
image_ref = create_image_from_surface (image, image_extra);
|
||||
|
||||
if (surface->image == image) {
|
||||
CGRect rect;
|
||||
rect = CGRectMake (image_rect->x, image_rect->y, image_rect->width, image_rect->height);
|
||||
|
||||
rect = CGRectMake(0, 0, surface->width, surface->height);
|
||||
|
||||
if (surface->flipped) {
|
||||
CGContextSaveGState (surface->context);
|
||||
CGContextTranslateCTM (surface->context, 0, surface->height);
|
||||
CGContextScaleCTM (surface->context, 1, -1);
|
||||
}
|
||||
|
||||
CGContextDrawImage(surface->context, rect, surface->cgImage);
|
||||
|
||||
if (surface->flipped)
|
||||
CGContextRestoreGState (surface->context);
|
||||
|
||||
memset(surface->image->data, 0, surface->width * surface->height * 4);
|
||||
if (surface->y_grows_down) {
|
||||
CGContextSaveGState (surface->context);
|
||||
CGContextTranslateCTM (surface->context, 0, image_rect->height + 2 * image_rect->y);
|
||||
CGContextScaleCTM (surface->context, 1, -1);
|
||||
}
|
||||
|
||||
CGContextDrawImage(surface->context, rect, image_ref);
|
||||
CFRelease (image_ref);
|
||||
|
||||
if (surface->y_grows_down) {
|
||||
CGContextRestoreGState (surface->context);
|
||||
}
|
||||
|
||||
cairo_surface_destroy ((cairo_surface_t *)image);
|
||||
free (image_extra);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -184,21 +183,17 @@ _cairo_quartz_surface_set_clip_region(void *abstract_surface,
|
|||
pixman_region16_t * region)
|
||||
{
|
||||
cairo_quartz_surface_t *surface = abstract_surface;
|
||||
unsigned int serial;
|
||||
|
||||
serial = _cairo_surface_allocate_clip_serial (&surface->image->base);
|
||||
if (surface->clip_region)
|
||||
pixman_region_destroy (surface->clip_region);
|
||||
|
||||
if (region) {
|
||||
surface->clip_region = pixman_region_create ();
|
||||
pixman_region_copy (surface->clip_region, region);
|
||||
} else
|
||||
surface->clip_region = NULL;
|
||||
|
||||
if (surface->clip_region)
|
||||
pixman_region_destroy (surface->clip_region);
|
||||
|
||||
if (region) {
|
||||
surface->clip_region = pixman_region_create ();
|
||||
pixman_region_copy (surface->clip_region, region);
|
||||
} else
|
||||
surface->clip_region = NULL;
|
||||
|
||||
return _cairo_surface_set_clip_region(&surface->image->base,
|
||||
region, serial);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -207,15 +202,13 @@ _cairo_quartz_surface_get_extents (void *abstract_surface,
|
|||
{
|
||||
cairo_quartz_surface_t *surface = abstract_surface;
|
||||
|
||||
rectangle->x = 0;
|
||||
rectangle->y = 0;
|
||||
rectangle->width = surface->width;
|
||||
rectangle->height = surface->height;
|
||||
*rectangle = surface->extents;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_QUARTZ,
|
||||
NULL, /* create_similar */
|
||||
_cairo_quartz_surface_finish,
|
||||
_cairo_quartz_surface_acquire_source_image,
|
||||
|
|
@ -236,10 +229,12 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
|
|||
|
||||
|
||||
cairo_surface_t *cairo_quartz_surface_create(CGContextRef context,
|
||||
cairo_bool_t flipped,
|
||||
int width, int height)
|
||||
int width,
|
||||
int height,
|
||||
cairo_bool_t y_grows_down)
|
||||
{
|
||||
cairo_quartz_surface_t *surface;
|
||||
CGRect clip_box;
|
||||
|
||||
surface = malloc(sizeof(cairo_quartz_surface_t));
|
||||
if (surface == NULL) {
|
||||
|
|
@ -250,16 +245,14 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context,
|
|||
_cairo_surface_init(&surface->base, &cairo_quartz_surface_backend);
|
||||
|
||||
surface->context = context;
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
surface->image = NULL;
|
||||
surface->cgImage = NULL;
|
||||
surface->clip_region = NULL;
|
||||
surface->flipped = flipped;
|
||||
surface->clip_region = NULL;
|
||||
surface->y_grows_down = y_grows_down;
|
||||
|
||||
// Set up the image surface which Cairo draws into and we blit to & from.
|
||||
void *foo;
|
||||
_cairo_quartz_surface_acquire_source_image(surface, &surface->image, &foo);
|
||||
clip_box = CGContextGetClipBoundingBox (context);
|
||||
surface->extents.x = clip_box.origin.x;
|
||||
surface->extents.y = clip_box.origin.y;
|
||||
surface->extents.width = clip_box.size.width;
|
||||
surface->extents.height = clip_box.size.height;
|
||||
|
||||
return (cairo_surface_t *) surface;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,9 +47,9 @@ CAIRO_BEGIN_DECLS
|
|||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_quartz_surface_create (CGContextRef context,
|
||||
cairo_bool_t flipped,
|
||||
int width,
|
||||
int height);
|
||||
int height,
|
||||
cairo_bool_t y_grows_down);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
|
|
|
|||
|
|
@ -39,10 +39,10 @@
|
|||
#include "cairoint.h"
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_scaled_glyph_keys_equal (void *abstract_key_a, void *abstract_key_b)
|
||||
_cairo_scaled_glyph_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
|
||||
{
|
||||
cairo_scaled_glyph_t *key_a = abstract_key_a;
|
||||
cairo_scaled_glyph_t *key_b = abstract_key_b;
|
||||
const cairo_scaled_glyph_t *key_a = abstract_key_a;
|
||||
const cairo_scaled_glyph_t *key_b = abstract_key_b;
|
||||
|
||||
return (_cairo_scaled_glyph_index (key_a) ==
|
||||
_cairo_scaled_glyph_index (key_b));
|
||||
|
|
@ -118,6 +118,18 @@ _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
|
|||
_cairo_error (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_scaled_font_get_type:
|
||||
* @scaled_font: a #cairo_scaled_font_t
|
||||
*
|
||||
* Return value: The type of @scaled_font. See #cairo_font_type_t.
|
||||
**/
|
||||
cairo_font_type_t
|
||||
cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
return scaled_font->backend->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_scaled_font_status:
|
||||
* @scaled_font: a #cairo_scaled_font_t
|
||||
|
|
@ -168,7 +180,7 @@ static cairo_scaled_font_map_t *cairo_scaled_font_map = NULL;
|
|||
CAIRO_MUTEX_DECLARE (cairo_scaled_font_map_mutex);
|
||||
|
||||
static int
|
||||
_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b);
|
||||
_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b);
|
||||
|
||||
static cairo_scaled_font_map_t *
|
||||
_cairo_scaled_font_map_lock (void)
|
||||
|
|
@ -286,10 +298,10 @@ _cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font,
|
|||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b)
|
||||
_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
|
||||
{
|
||||
cairo_scaled_font_t *key_a = abstract_key_a;
|
||||
cairo_scaled_font_t *key_b = abstract_key_b;
|
||||
const cairo_scaled_font_t *key_a = abstract_key_a;
|
||||
const cairo_scaled_font_t *key_b = abstract_key_b;
|
||||
|
||||
return (key_a->font_face == key_b->font_face &&
|
||||
memcmp ((unsigned char *)(&key_a->font_matrix.xx),
|
||||
|
|
@ -1008,7 +1020,7 @@ _scaled_glyph_path_close_path (void *abstract_closure)
|
|||
|
||||
cairo_status_t
|
||||
_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_path_fixed_t *path)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -451,6 +451,10 @@ _composite_trap_region (cairo_clip_t *clip,
|
|||
extents->x, extents->y,
|
||||
extents->width, extents->height);
|
||||
|
||||
/* Restore the original clip if we modified it temporarily. */
|
||||
if (num_rects >1)
|
||||
_cairo_surface_set_clip (dst, clip);
|
||||
|
||||
if (clip_surface)
|
||||
_cairo_pattern_fini (&mask.base);
|
||||
|
||||
|
|
@ -549,6 +553,9 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
|
|||
return status;
|
||||
|
||||
clear_region = _cairo_region_create_from_rectangle (&extents);
|
||||
if (clear_region == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
status = _cairo_clip_intersect_to_region (clip, clear_region);
|
||||
if (status)
|
||||
return status;
|
||||
|
|
@ -576,7 +583,7 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
|
|||
{
|
||||
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
|
||||
|
||||
if ((src->type == CAIRO_PATTERN_SOLID || op == CAIRO_OPERATOR_CLEAR) &&
|
||||
if ((src->type == CAIRO_PATTERN_TYPE_SOLID || op == CAIRO_OPERATOR_CLEAR) &&
|
||||
!clip_surface)
|
||||
{
|
||||
const cairo_color_t *color;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
const cairo_surface_t _cairo_surface_nil = {
|
||||
&cairo_image_surface_backend, /* backend */
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
-1, /* ref_count */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
FALSE, /* finished */
|
||||
|
|
@ -59,6 +60,7 @@ const cairo_surface_t _cairo_surface_nil = {
|
|||
|
||||
const cairo_surface_t _cairo_surface_nil_file_not_found = {
|
||||
&cairo_image_surface_backend, /* backend */
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
-1, /* ref_count */
|
||||
CAIRO_STATUS_FILE_NOT_FOUND, /* status */
|
||||
FALSE, /* finished */
|
||||
|
|
@ -75,6 +77,7 @@ const cairo_surface_t _cairo_surface_nil_file_not_found = {
|
|||
|
||||
const cairo_surface_t _cairo_surface_nil_read_error = {
|
||||
&cairo_image_surface_backend, /* backend */
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
-1, /* ref_count */
|
||||
CAIRO_STATUS_READ_ERROR, /* status */
|
||||
FALSE, /* finished */
|
||||
|
|
@ -118,6 +121,22 @@ _cairo_surface_set_error (cairo_surface_t *surface,
|
|||
_cairo_error (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_surface_get_type:
|
||||
* @surface: a #cairo_surface_t
|
||||
*
|
||||
* Return value: The type of @surface. See #cairo_surface_type_t.
|
||||
**/
|
||||
cairo_surface_type_t
|
||||
cairo_surface_get_type (cairo_surface_t *surface)
|
||||
{
|
||||
/* We don't use surface->backend->type here so that some of the
|
||||
* special "wrapper" surfaces such as cairo_paginated_surface_t
|
||||
* can override surface->type with the type of the "child"
|
||||
* surface. */
|
||||
return surface->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_surface_status:
|
||||
* @surface: a #cairo_surface_t
|
||||
|
|
@ -141,6 +160,8 @@ _cairo_surface_init (cairo_surface_t *surface,
|
|||
const cairo_surface_backend_t *backend)
|
||||
{
|
||||
surface->backend = backend;
|
||||
|
||||
surface->type = backend->type;
|
||||
|
||||
surface->ref_count = 1;
|
||||
surface->status = CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -186,7 +207,8 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other,
|
|||
*
|
||||
* Create a new surface that is as compatible as possible with an
|
||||
* existing surface. The new surface will use the same backend as
|
||||
* @other unless that is not possible for some reason.
|
||||
* @other unless that is not possible for some reason. The type of the
|
||||
* returned surface may be examined with cairo_surface_get_type().
|
||||
*
|
||||
* Return value: a pointer to the newly allocated surface. The caller
|
||||
* owns the surface and should call cairo_surface_destroy when done
|
||||
|
|
@ -502,6 +524,10 @@ cairo_surface_mark_dirty (cairo_surface_t *surface)
|
|||
* Like cairo_surface_mark_dirty(), but drawing has been done only to
|
||||
* the specified rectangle, so that cairo can retain cached contents
|
||||
* for other parts of the surface.
|
||||
*
|
||||
* Any cached clip set on the surface will be reset by this function,
|
||||
* to make sure that future cairo calls have the clip set that they
|
||||
* expect.
|
||||
*/
|
||||
void
|
||||
cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
|
||||
|
|
@ -520,6 +546,13 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Always reset the clip here, to avoid having external calls to
|
||||
* clip manipulation functions of the underlying device clip result
|
||||
* in a desync between the cairo clip and the backend clip, due to
|
||||
* the clip caching.
|
||||
*/
|
||||
surface->current_clip_serial = -1;
|
||||
|
||||
if (surface->backend->mark_dirty_rectangle) {
|
||||
cairo_status_t status;
|
||||
|
||||
|
|
@ -1329,6 +1362,12 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
|
|||
if (!surface)
|
||||
return CAIRO_STATUS_NULL_POINTER;
|
||||
|
||||
if (surface->status)
|
||||
return surface->status;
|
||||
|
||||
if (surface->finished)
|
||||
return CAIRO_STATUS_SURFACE_FINISHED;
|
||||
|
||||
if (clip) {
|
||||
serial = clip->serial;
|
||||
if (serial == 0)
|
||||
|
|
@ -1336,7 +1375,7 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
|
|||
}
|
||||
|
||||
surface->clip = clip;
|
||||
|
||||
|
||||
if (serial == _cairo_surface_get_current_clip_serial (surface))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
|
@ -1654,3 +1693,39 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
|
|||
return _cairo_surface_composite_fixup_unbounded_internal (dst, src_rectangle, mask_rectangle,
|
||||
dst_x, dst_y, width, height);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_format_is_opaque (cairo_format_t format)
|
||||
{
|
||||
switch (format) {
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
return FALSE;
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
return TRUE;
|
||||
case CAIRO_FORMAT_A8:
|
||||
return FALSE;
|
||||
case CAIRO_FORMAT_A1:
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* XXX: This function is funny in a couple of ways. First it seems to
|
||||
* be computing something like "not translucent" rather than "opaque"
|
||||
* since it returns TRUE for an A1 image surface. Second, it just
|
||||
* gives up on anything other than an image surface.
|
||||
*
|
||||
* I imagine something that might be more useful here (or in addition)
|
||||
* would be cairo_surface_get_content.
|
||||
*/
|
||||
cairo_bool_t
|
||||
_cairo_surface_is_opaque (const cairo_surface_t *surface)
|
||||
{
|
||||
if (_cairo_surface_is_image (surface)) {
|
||||
const cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
|
||||
|
||||
return _format_is_opaque (image_surface->format);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,11 +75,15 @@ struct cairo_svg_document {
|
|||
unsigned int filter_id;
|
||||
unsigned int clip_id;
|
||||
unsigned int mask_id;
|
||||
|
||||
cairo_bool_t alpha_filter;
|
||||
};
|
||||
|
||||
struct cairo_svg_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
cairo_content_t content;
|
||||
|
||||
unsigned int id;
|
||||
|
||||
double width;
|
||||
|
|
@ -88,8 +92,12 @@ struct cairo_svg_surface {
|
|||
cairo_svg_document_t *document;
|
||||
|
||||
xmlNodePtr xml_node;
|
||||
xmlNodePtr xml_root_node;
|
||||
|
||||
unsigned int clip_level;
|
||||
|
||||
cairo_bool_t modified;
|
||||
unsigned int previous_id;
|
||||
};
|
||||
|
||||
static cairo_svg_document_t *
|
||||
|
|
@ -108,8 +116,9 @@ _cairo_svg_document_reference (cairo_svg_document_t *document);
|
|||
|
||||
static cairo_surface_t *
|
||||
_cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
|
||||
double width,
|
||||
double height);
|
||||
cairo_content_t content,
|
||||
double width,
|
||||
double height);
|
||||
|
||||
static const cairo_surface_backend_t cairo_svg_surface_backend;
|
||||
|
||||
|
|
@ -125,7 +134,8 @@ _cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
|||
if (document == NULL)
|
||||
return NULL;
|
||||
|
||||
surface = _cairo_svg_surface_create_for_document (document, width, height);
|
||||
surface = _cairo_svg_surface_create_for_document (document, CAIRO_CONTENT_COLOR_ALPHA,
|
||||
width, height);
|
||||
|
||||
document->owner = surface;
|
||||
_cairo_svg_document_destroy (document);
|
||||
|
|
@ -133,35 +143,90 @@ _cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
|||
return surface;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_svg_surface_create_for_stream:
|
||||
* @write: a #cairo_write_func_t to accept the output data
|
||||
* @closure: the closure argument for @write
|
||||
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
|
||||
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
|
||||
*
|
||||
* Creates a SVG surface of the specified size in points to be written
|
||||
* incrementally to the stream represented by @write and @closure.
|
||||
*
|
||||
* Return value: a pointer to the newly created surface. The caller
|
||||
* owns the surface and should call cairo_surface_destroy when done
|
||||
* with it.
|
||||
*
|
||||
* This function always returns a valid pointer, but it will return a
|
||||
* pointer to a "nil" surface if an error such as out of memory
|
||||
* occurs. You can use cairo_surface_status() to check for this.
|
||||
*/
|
||||
cairo_surface_t *
|
||||
cairo_svg_surface_create_for_stream (cairo_write_func_t write,
|
||||
void *closure,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_output_stream_t *stream;
|
||||
|
||||
stream = _cairo_output_stream_create (write, closure);
|
||||
if (stream == NULL)
|
||||
return NULL;
|
||||
stream = _cairo_output_stream_create (write, NULL, closure);
|
||||
status = _cairo_output_stream_get_status (stream);
|
||||
if (status) {
|
||||
_cairo_error (status);
|
||||
return (cairo_surface_t *) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
return _cairo_svg_surface_create_for_stream_internal (stream, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_svg_surface_create:
|
||||
* @filename: a filename for the SVG output (must be writable)
|
||||
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
|
||||
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
|
||||
*
|
||||
* Creates a SVG surface of the specified size in points to be written
|
||||
* to @filename.
|
||||
*
|
||||
* Return value: a pointer to the newly created surface. The caller
|
||||
* owns the surface and should call cairo_surface_destroy when done
|
||||
* with it.
|
||||
*
|
||||
* This function always returns a valid pointer, but it will return a
|
||||
* pointer to a "nil" surface if an error such as out of memory
|
||||
* occurs. You can use cairo_surface_status() to check for this.
|
||||
**/
|
||||
cairo_surface_t *
|
||||
cairo_svg_surface_create (const char *filename,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_output_stream_t *stream;
|
||||
|
||||
stream = _cairo_output_stream_create_for_file (filename);
|
||||
if (stream == NULL)
|
||||
return NULL;
|
||||
stream = _cairo_output_stream_create_for_filename (filename);
|
||||
status = _cairo_output_stream_get_status (stream);
|
||||
if (status) {
|
||||
_cairo_error (status);
|
||||
return (cairo_surface_t *) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
return _cairo_svg_surface_create_for_stream_internal (stream, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_svg_surface_set_dpi:
|
||||
* @surface: a svg cairo_surface_t
|
||||
* @x_dpi: horizontal dpi
|
||||
* @y_dpi: vertical dpi
|
||||
*
|
||||
* Set the horizontal and vertical resolution for image fallbacks.
|
||||
* When the svg backend needs to fall back to image overlays, it will
|
||||
* use this resolution. These DPI values are not used for any other
|
||||
* purpose, (in particular, they do not have any bearing on the size
|
||||
* passed to cairo_svg_surface_create() nor on the CTM).
|
||||
**/
|
||||
void
|
||||
cairo_svg_surface_set_dpi (cairo_surface_t *surface,
|
||||
double x_dpi,
|
||||
|
|
@ -175,11 +240,12 @@ cairo_svg_surface_set_dpi (cairo_surface_t *surface,
|
|||
|
||||
static cairo_surface_t *
|
||||
_cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
|
||||
double width,
|
||||
double height)
|
||||
cairo_content_t content,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
cairo_svg_surface_t *surface;
|
||||
xmlNodePtr clip, clip_rect;
|
||||
xmlNodePtr clip, rect;
|
||||
int clip_id;
|
||||
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
|
||||
|
||||
|
|
@ -203,22 +269,33 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
|
|||
clip = xmlNewChild (document->xml_node_defs, NULL, CC2XML ("clipPath"), NULL);
|
||||
snprintf (buffer, sizeof buffer, "clip%d", clip_id);
|
||||
xmlSetProp (clip, CC2XML ("id"), C2XML (buffer));
|
||||
clip_rect = xmlNewChild (clip, NULL, CC2XML ("rect"), NULL);
|
||||
rect = xmlNewChild (clip, NULL, CC2XML ("rect"), NULL);
|
||||
_cairo_dtostr (buffer, sizeof buffer, width);
|
||||
xmlSetProp (clip_rect, CC2XML ("width"), C2XML (buffer));
|
||||
xmlSetProp (rect, CC2XML ("width"), C2XML (buffer));
|
||||
_cairo_dtostr (buffer, sizeof buffer, height);
|
||||
xmlSetProp (clip_rect, CC2XML ("height"), C2XML (buffer));
|
||||
xmlSetProp (rect, CC2XML ("height"), C2XML (buffer));
|
||||
|
||||
surface->xml_node = xmlNewChild (surface->id == 0 ?
|
||||
document->xml_node_main :
|
||||
document->xml_node_defs,
|
||||
NULL, CC2XML ("g"), NULL);
|
||||
surface->xml_node = xmlNewNode (NULL, CC2XML ("g"));
|
||||
surface->xml_root_node = surface->xml_node;
|
||||
|
||||
snprintf (buffer, sizeof buffer, "surface%d", surface->id);
|
||||
xmlSetProp (surface->xml_node, CC2XML ("id"), C2XML (buffer));
|
||||
snprintf (buffer, sizeof buffer, "url(#clip%d)", clip_id);
|
||||
xmlSetProp (surface->xml_node, CC2XML ("clip-path"), C2XML (buffer));
|
||||
|
||||
|
||||
if (content == CAIRO_CONTENT_COLOR) {
|
||||
rect = xmlNewChild (surface->xml_node, NULL, CC2XML ("rect"), NULL);
|
||||
_cairo_dtostr (buffer, sizeof buffer, width);
|
||||
xmlSetProp (rect, CC2XML ("width"), C2XML (buffer));
|
||||
_cairo_dtostr (buffer, sizeof buffer, height);
|
||||
xmlSetProp (rect, CC2XML ("height"), C2XML (buffer));
|
||||
xmlSetProp (rect, CC2XML ("style"), CC2XML ("opacity:1; stroke:none; fill:rgb(0,0,0);"));
|
||||
}
|
||||
|
||||
surface->modified = TRUE;
|
||||
surface->previous_id = surface->id;
|
||||
surface->content = content;
|
||||
|
||||
return &surface->base;
|
||||
}
|
||||
|
||||
|
|
@ -231,7 +308,7 @@ _cairo_svg_surface_create_similar (void *abstract_src,
|
|||
cairo_svg_surface_t *template = abstract_src;
|
||||
|
||||
return _cairo_svg_surface_create_for_document (template->document,
|
||||
width, height);
|
||||
content, width, height);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
@ -240,17 +317,45 @@ _cairo_svg_surface_finish (void *abstract_surface)
|
|||
cairo_status_t status;
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
cairo_svg_document_t *document = surface->document;
|
||||
|
||||
|
||||
if (document->owner == &surface->base)
|
||||
if (document->owner == &surface->base) {
|
||||
xmlAddChild (document->xml_node_main, xmlCopyNode (surface->xml_root_node, 1));
|
||||
status = _cairo_svg_document_finish (document);
|
||||
else
|
||||
} else
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_svg_document_destroy (document);
|
||||
|
||||
xmlFreeNode (surface->xml_root_node);
|
||||
surface->xml_node = NULL;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
emit_alpha_filter (cairo_svg_document_t *document)
|
||||
{
|
||||
if (!document->alpha_filter) {
|
||||
xmlNodePtr node;
|
||||
xmlNodePtr child;
|
||||
|
||||
node = xmlNewChild (document->xml_node_defs, NULL,
|
||||
CC2XML ("filter"), NULL);
|
||||
xmlSetProp (node, CC2XML ("id"), CC2XML ("alpha"));
|
||||
xmlSetProp (node, CC2XML ("filterUnits"), CC2XML ("objectBoundingBox"));
|
||||
xmlSetProp (node, CC2XML ("x"), CC2XML ("0%"));
|
||||
xmlSetProp (node, CC2XML ("y"), CC2XML ("0%"));
|
||||
xmlSetProp (node, CC2XML ("width"), CC2XML ("100%"));
|
||||
xmlSetProp (node, CC2XML ("height"), CC2XML ("100%"));
|
||||
child = xmlNewChild (node, NULL, CC2XML ("feColorMatrix"), NULL);
|
||||
xmlSetProp (child, CC2XML("type"), CC2XML ("matrix"));
|
||||
xmlSetProp (child, CC2XML("in"), CC2XML ("SourceGraphic"));
|
||||
xmlSetProp (child, CC2XML("values"), CC2XML ("0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"));
|
||||
document->alpha_filter = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
emit_transform (xmlNodePtr node,
|
||||
char const *attribute_str,
|
||||
|
|
@ -263,22 +368,22 @@ emit_transform (xmlNodePtr node,
|
|||
xmlBufferCat (matrix_buffer, CC2XML ("matrix("));
|
||||
_cairo_dtostr (buffer, sizeof buffer, matrix->xx);
|
||||
xmlBufferCat (matrix_buffer, C2XML (buffer));
|
||||
xmlBufferCat (matrix_buffer, ",");
|
||||
xmlBufferCat (matrix_buffer, CC2XML (","));
|
||||
_cairo_dtostr (buffer, sizeof buffer, matrix->yx);
|
||||
xmlBufferCat (matrix_buffer, C2XML (buffer));
|
||||
xmlBufferCat (matrix_buffer, ",");
|
||||
xmlBufferCat (matrix_buffer, CC2XML (","));
|
||||
_cairo_dtostr (buffer, sizeof buffer, matrix->xy);
|
||||
xmlBufferCat (matrix_buffer, C2XML (buffer));
|
||||
xmlBufferCat (matrix_buffer, ",");
|
||||
xmlBufferCat (matrix_buffer, CC2XML (","));
|
||||
_cairo_dtostr (buffer, sizeof buffer, matrix->yy);
|
||||
xmlBufferCat (matrix_buffer, C2XML (buffer));
|
||||
xmlBufferCat (matrix_buffer, ",");
|
||||
xmlBufferCat (matrix_buffer, CC2XML (","));
|
||||
_cairo_dtostr (buffer, sizeof buffer, matrix->x0);
|
||||
xmlBufferCat (matrix_buffer, C2XML (buffer));
|
||||
xmlBufferCat (matrix_buffer, ",");
|
||||
xmlBufferCat (matrix_buffer, CC2XML(","));
|
||||
_cairo_dtostr (buffer, sizeof buffer, matrix->y0);
|
||||
xmlBufferCat (matrix_buffer, C2XML (buffer));
|
||||
xmlBufferCat (matrix_buffer, ")");
|
||||
xmlBufferCat (matrix_buffer, CC2XML (")"));
|
||||
xmlSetProp (node, CC2XML (attribute_str), C2XML (xmlBufferContent (matrix_buffer)));
|
||||
xmlBufferFree (matrix_buffer);
|
||||
}
|
||||
|
|
@ -288,11 +393,10 @@ typedef struct {
|
|||
unsigned int in_mem;
|
||||
unsigned char src[3];
|
||||
unsigned char dst[5];
|
||||
unsigned int count;
|
||||
unsigned int trailing;
|
||||
} base64_write_closure_t;
|
||||
|
||||
static unsigned char const *base64_table =
|
||||
static char const *base64_table =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
static cairo_status_t
|
||||
|
|
@ -322,11 +426,6 @@ base64_write_func (void *closure,
|
|||
data++;
|
||||
length--;
|
||||
}
|
||||
info->count++;
|
||||
if (info->count >= 18) {
|
||||
info->count = 0;
|
||||
xmlBufferCat (info->buffer, "\r\n");
|
||||
}
|
||||
dst[0] = base64_table[src[0] >> 2];
|
||||
dst[1] = base64_table[(src[0] & 0x03) << 4 | src[1] >> 4];
|
||||
dst[2] = base64_table[(src[1] & 0x0f) << 2 | src[2] >> 6];
|
||||
|
|
@ -366,7 +465,6 @@ _cairo_surface_base64_encode (cairo_surface_t *surface,
|
|||
|
||||
info.buffer = xmlBufferCreate();
|
||||
info.in_mem = 0;
|
||||
info.count = 0;
|
||||
info.trailing = 0;
|
||||
memset (info.dst, '\x0', 5);
|
||||
*buffer = info.buffer;
|
||||
|
|
@ -450,16 +548,22 @@ emit_composite_svg_pattern (xmlNodePtr node,
|
|||
cairo_bool_t is_pattern)
|
||||
{
|
||||
cairo_svg_surface_t *surface = (cairo_svg_surface_t *) pattern->surface;
|
||||
cairo_svg_document_t *document = surface->document;
|
||||
cairo_matrix_t p2u;
|
||||
xmlNodePtr child;
|
||||
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
|
||||
|
||||
/* FIXME: self copy is not supported yet */
|
||||
if (surface->id == 0)
|
||||
return NULL;
|
||||
if (surface->modified) {
|
||||
if (surface->content == CAIRO_CONTENT_ALPHA)
|
||||
emit_alpha_filter (document);
|
||||
child = xmlAddChild (document->xml_node_defs, xmlCopyNode (surface->xml_root_node, 1));
|
||||
if (surface->content == CAIRO_CONTENT_ALPHA)
|
||||
xmlSetProp (child, CC2XML ("filter"), CC2XML("url(#alpha)"));
|
||||
}
|
||||
|
||||
child = xmlNewChild (node, NULL, CC2XML("use"), NULL);
|
||||
snprintf (buffer, sizeof buffer, "#surface%d", surface->id);
|
||||
snprintf (buffer, sizeof buffer, "#surface%d",
|
||||
surface->modified ? surface->id : surface->previous_id);
|
||||
xmlSetProp (child, CC2XML ("xlink:href"), C2XML (buffer));
|
||||
|
||||
if (!is_pattern) {
|
||||
|
|
@ -473,6 +577,14 @@ emit_composite_svg_pattern (xmlNodePtr node,
|
|||
if (height != NULL)
|
||||
*height = surface->height;
|
||||
|
||||
if (surface->modified) {
|
||||
surface->modified = FALSE;
|
||||
surface->previous_id = surface->id;
|
||||
surface->id = document->surface_id++;
|
||||
snprintf (buffer, sizeof buffer, "surface%d", surface->id);
|
||||
xmlSetProp (surface->xml_root_node, CC2XML ("id"), C2XML (buffer));
|
||||
}
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
|
|
@ -762,19 +874,19 @@ emit_pattern (cairo_svg_surface_t *surface, cairo_pattern_t *pattern,
|
|||
xmlBufferPtr style, int is_stroke)
|
||||
{
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_SOLID:
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern, style, is_stroke);
|
||||
break;
|
||||
|
||||
case CAIRO_PATTERN_SURFACE:
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, style, is_stroke);
|
||||
break;
|
||||
|
||||
case CAIRO_PATTERN_LINEAR:
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, style, is_stroke);
|
||||
break;
|
||||
|
||||
case CAIRO_PATTERN_RADIAL:
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, style, is_stroke);
|
||||
break;
|
||||
}
|
||||
|
|
@ -887,9 +999,9 @@ _cairo_svg_surface_fill (void *abstract_surface,
|
|||
|
||||
style = xmlBufferCreate ();
|
||||
emit_pattern (surface, source, style, 0);
|
||||
xmlBufferCat (style, " stroke: none;");
|
||||
xmlBufferCat (style, " fill-rule: ");
|
||||
xmlBufferCat (style, fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? "evenodd;" : "nonzero;");
|
||||
xmlBufferCat (style, CC2XML (" stroke: none;"));
|
||||
xmlBufferCat (style, CC2XML (" fill-rule: "));
|
||||
xmlBufferCat (style, fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? CC2XML("evenodd;") : CC2XML ("nonzero;"));
|
||||
|
||||
status = _cairo_path_fixed_interpret (path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
|
|
@ -907,6 +1019,7 @@ _cairo_svg_surface_fill (void *abstract_surface,
|
|||
xmlBufferFree (info.path);
|
||||
xmlBufferFree (style);
|
||||
|
||||
surface->modified = TRUE;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -939,14 +1052,15 @@ emit_paint (xmlNodePtr node,
|
|||
xmlBufferPtr style;
|
||||
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
|
||||
|
||||
if (source->type == CAIRO_PATTERN_SURFACE)
|
||||
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
|
||||
source->extend == CAIRO_EXTEND_NONE)
|
||||
return emit_composite_pattern (node,
|
||||
(cairo_surface_pattern_t *) source,
|
||||
NULL, NULL, FALSE);
|
||||
|
||||
style = xmlBufferCreate ();
|
||||
emit_pattern (surface, source, style, 0);
|
||||
xmlBufferCat (style, " stroke: none;");
|
||||
xmlBufferCat (style, CC2XML (" stroke: none;"));
|
||||
|
||||
child = xmlNewChild (node, NULL, CC2XML ("rect"), NULL);
|
||||
xmlSetProp (child, CC2XML ("x"), CC2XML ("0"));
|
||||
|
|
@ -970,7 +1084,40 @@ _cairo_svg_surface_paint (void *abstract_surface,
|
|||
{
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
|
||||
/* Emulation of clear and source operators, when no clipping region
|
||||
* is defined. We just delete existing content of surface root node,
|
||||
* and exit early if operator is clear. */
|
||||
if (surface->clip_level == 0 &&
|
||||
(op == CAIRO_OPERATOR_CLEAR ||
|
||||
op == CAIRO_OPERATOR_SOURCE)) {
|
||||
xmlNodePtr child = surface->xml_root_node->children;
|
||||
|
||||
while (child != NULL) {
|
||||
xmlUnlinkNode (child);
|
||||
xmlFreeNode (child);
|
||||
child = surface->xml_root_node->children;
|
||||
}
|
||||
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
if (surface->content == CAIRO_CONTENT_COLOR) {
|
||||
xmlNodePtr rect;
|
||||
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
|
||||
|
||||
rect = xmlNewChild (surface->xml_node, NULL, CC2XML ("rect"), NULL);
|
||||
_cairo_dtostr (buffer, sizeof buffer, surface->width);
|
||||
xmlSetProp (rect, CC2XML ("width"), C2XML (buffer));
|
||||
_cairo_dtostr (buffer, sizeof buffer, surface->height);
|
||||
xmlSetProp (rect, CC2XML ("height"), C2XML (buffer));
|
||||
xmlSetProp (rect, CC2XML ("style"), CC2XML ("opacity:1; stroke:none; fill:rgb(0,0,0);"));
|
||||
}
|
||||
surface->modified = TRUE;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
emit_paint (surface->xml_node, surface, op, source);
|
||||
|
||||
surface->modified = TRUE;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -985,10 +1132,16 @@ _cairo_svg_surface_mask (void *abstract_surface,
|
|||
xmlNodePtr child, mask_node;
|
||||
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
|
||||
|
||||
mask_node = xmlNewChild (document->xml_node_defs, NULL, CC2XML ("mask"), NULL);
|
||||
emit_alpha_filter (document);
|
||||
|
||||
mask_node = xmlNewNode (NULL, CC2XML ("mask"));
|
||||
snprintf (buffer, sizeof buffer, "mask%d", document->mask_id);
|
||||
xmlSetProp (mask_node, CC2XML ("id"), C2XML (buffer));
|
||||
emit_paint (mask_node, surface, op, mask);
|
||||
child = xmlNewChild (mask_node, NULL, CC2XML ("g"), NULL);
|
||||
xmlSetProp (child, CC2XML ("filter"), CC2XML ("url(#alpha)"));
|
||||
emit_paint (child, surface, op, mask);
|
||||
|
||||
xmlAddChild (document->xml_node_defs, mask_node);
|
||||
|
||||
child = emit_paint (surface->xml_node, surface, op, source);
|
||||
|
||||
|
|
@ -999,6 +1152,7 @@ _cairo_svg_surface_mask (void *abstract_surface,
|
|||
|
||||
document->mask_id++;
|
||||
|
||||
surface->modified = TRUE;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -1064,21 +1218,21 @@ _cairo_svg_surface_stroke (void *abstract_dst,
|
|||
xmlBufferCat (style, CC2XML (" stroke-dasharray: "));
|
||||
for (i = 0; i < stroke_style->num_dashes; i++) {
|
||||
if (i != 0)
|
||||
xmlBufferCat (style, ",");
|
||||
xmlBufferCat (style, CC2XML (","));
|
||||
/* FIXME: Is is really what we want ? */
|
||||
rx = ry = stroke_style->dash[i];
|
||||
cairo_matrix_transform_distance (ctm, &rx, &ry);
|
||||
_cairo_dtostr (buffer, sizeof buffer, sqrt ((rx * rx + ry * ry) / 2.0));
|
||||
xmlBufferCat (style, C2XML (buffer));
|
||||
}
|
||||
xmlBufferCat (style, ";");
|
||||
xmlBufferCat (style, CC2XML (";"));
|
||||
if (stroke_style->dash_offset != 0.0) {
|
||||
xmlBufferCat (style, CC2XML (" stroke-dashoffset: "));
|
||||
rx = ry = stroke_style->dash_offset;
|
||||
cairo_matrix_transform_distance (ctm, &rx, &ry);
|
||||
_cairo_dtostr (buffer, sizeof buffer, sqrt ((rx * rx + ry * ry) / 2.0));
|
||||
xmlBufferCat (style, C2XML (buffer));
|
||||
xmlBufferCat (style, ";");
|
||||
xmlBufferCat (style, CC2XML (";"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1103,6 +1257,7 @@ _cairo_svg_surface_stroke (void *abstract_dst,
|
|||
xmlBufferFree (info.path);
|
||||
xmlBufferFree (style);
|
||||
|
||||
surface->modified = TRUE;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -1114,6 +1269,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
|
|||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
cairo_path_fixed_t path;
|
||||
cairo_status_t status;
|
||||
|
||||
|
|
@ -1137,6 +1293,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
|
|||
|
||||
_cairo_path_fixed_fini (&path);
|
||||
|
||||
surface->modified = TRUE;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -1155,10 +1312,8 @@ _cairo_svg_surface_intersect_clip_path (void *dst,
|
|||
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
|
||||
|
||||
if (path == NULL) {
|
||||
while (surface->clip_level > 0) {
|
||||
surface->xml_node = surface->xml_node->parent;
|
||||
surface->clip_level--;
|
||||
}
|
||||
surface->xml_node = surface->xml_root_node;
|
||||
surface->clip_level = 0;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -1208,6 +1363,7 @@ _cairo_svg_surface_get_font_options (void *abstract_surface,
|
|||
|
||||
|
||||
static const cairo_surface_backend_t cairo_svg_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_SVG,
|
||||
_cairo_svg_surface_create_similar,
|
||||
_cairo_svg_surface_finish,
|
||||
NULL, /* acquire_source_image */
|
||||
|
|
@ -1284,6 +1440,8 @@ _cairo_svg_document_create (cairo_output_stream_t *output_stream,
|
|||
xmlSetProp (node, CC2XML ("xmlns:xlink"), CC2XML ("http://www.w3.org/1999/xlink"));
|
||||
xmlSetProp (node, CC2XML ("version"), CC2XML ("1.2"));
|
||||
|
||||
document->alpha_filter = FALSE;
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
|
|
@ -1305,21 +1463,39 @@ _cairo_svg_document_destroy (cairo_svg_document_t *document)
|
|||
free (document);
|
||||
}
|
||||
|
||||
static int
|
||||
_cairo_svg_document_write (cairo_output_stream_t *output_stream,
|
||||
const char * buffer,
|
||||
int len)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_output_stream_write (output_stream, buffer, len);
|
||||
status = _cairo_output_stream_get_status (output_stream);
|
||||
if (status) {
|
||||
_cairo_error (status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_svg_document_finish (cairo_svg_document_t *document)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_output_stream_t *output = document->output_stream;
|
||||
xmlChar *xml_buffer;
|
||||
int xml_buffer_size;
|
||||
xmlOutputBufferPtr xml_output_buffer;
|
||||
|
||||
if (document->finished)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
/* FIXME: Dumping xml tree in memory is silly. */
|
||||
xmlDocDumpFormatMemoryEnc (document->xml_doc, &xml_buffer, &xml_buffer_size, "UTF-8", 1);
|
||||
_cairo_output_stream_write (document->output_stream, xml_buffer, xml_buffer_size);
|
||||
xmlFree(xml_buffer);
|
||||
xml_output_buffer = xmlOutputBufferCreateIO ((xmlOutputWriteCallback) _cairo_svg_document_write,
|
||||
(xmlOutputCloseCallback) NULL,
|
||||
(void *) document->output_stream,
|
||||
NULL);
|
||||
xmlSaveFormatFileTo (xml_output_buffer, document->xml_doc, "UTF-8", 1);
|
||||
|
||||
xmlFreeDoc (document->xml_doc);
|
||||
|
||||
status = _cairo_output_stream_get_status (output);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
/*
|
||||
* $Id: cairo-wideint.c,v 1.6 2005-07-30 19:57:54 keithp Exp $
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2004 Keith Packard
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
/*
|
||||
* $Id: cairo-wideint.h,v 1.12 2005-08-05 14:48:19 cworth Exp $
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2004 Keith Packard
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1159,7 +1159,7 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font,
|
|||
cairo_surface_pattern_t mask;
|
||||
RECT r;
|
||||
|
||||
tmp_surface = (cairo_win32_surface_t *)_cairo_win32_surface_create_dib (CAIRO_FORMAT_ARGB32, width, height);
|
||||
tmp_surface = (cairo_win32_surface_t *)cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, width, height);
|
||||
if (tmp_surface->base.status)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
|
|
@ -1355,6 +1355,7 @@ CLEANUP_FONT:
|
|||
}
|
||||
|
||||
const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend = {
|
||||
CAIRO_FONT_TYPE_WIN32,
|
||||
_cairo_win32_scaled_font_create_toy,
|
||||
_cairo_win32_scaled_font_fini,
|
||||
_cairo_win32_scaled_font_glyph_init,
|
||||
|
|
@ -1398,6 +1399,7 @@ _cairo_win32_font_face_scaled_font_create (void *abstract_face,
|
|||
}
|
||||
|
||||
static const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
|
||||
CAIRO_FONT_TYPE_WIN32,
|
||||
_cairo_win32_font_face_destroy,
|
||||
_cairo_win32_font_face_scaled_font_create
|
||||
};
|
||||
|
|
|
|||
|
|
@ -62,19 +62,14 @@ typedef struct _cairo_win32_surface {
|
|||
|
||||
cairo_rectangle_t clip_rect;
|
||||
|
||||
int set_clip;
|
||||
HRGN saved_clip;
|
||||
|
||||
cairo_rectangle_t extents;
|
||||
} cairo_win32_surface_t;
|
||||
|
||||
cairo_status_t
|
||||
_cairo_win32_print_gdi_error (const char *context);
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_win32_surface_create_dib (cairo_format_t format,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_surface_is_win32 (cairo_surface_t *surface);
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Owen Taylor <otaylor@redhat.com>
|
||||
* Stuart Parmenter <stuart@mozilla.com>
|
||||
* Vladimir Vukicevic <vladimir@pobox.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -274,9 +276,14 @@ _cairo_win32_surface_create_for_dc (HDC original_dc,
|
|||
surface->clip_rect.width = width;
|
||||
surface->clip_rect.height = height;
|
||||
|
||||
surface->set_clip = 0;
|
||||
surface->saved_clip = NULL;
|
||||
|
||||
surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
|
||||
if (GetClipRgn (surface->dc, surface->saved_clip) == 0) {
|
||||
DeleteObject(surface->saved_clip);
|
||||
surface->saved_clip = NULL;
|
||||
}
|
||||
|
||||
surface->extents = surface->clip_rect;
|
||||
|
||||
_cairo_surface_init (&surface->base, &cairo_win32_surface_backend);
|
||||
|
||||
return (cairo_surface_t *)surface;
|
||||
|
|
@ -311,27 +318,6 @@ _cairo_win32_surface_create_similar (void *abstract_src,
|
|||
return _cairo_win32_surface_create_for_dc (src->dc, format, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_win32_surface_create_dib:
|
||||
* @format: format of pixels in the surface to create
|
||||
* @width: width of the surface, in pixels
|
||||
* @height: height of the surface, in pixels
|
||||
*
|
||||
* Creates a device-independent-bitmap surface not associated with
|
||||
* any particular existing surface or device context. The created
|
||||
* bitmap will be unititialized.
|
||||
*
|
||||
* Return value: the newly created surface, or %NULL if it couldn't
|
||||
* be created (probably because of lack of memory)
|
||||
**/
|
||||
cairo_surface_t *
|
||||
_cairo_win32_surface_create_dib (cairo_format_t format,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
return _cairo_win32_surface_create_for_dc (NULL, format, width, height);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_surface_finish (void *abstract_surface)
|
||||
{
|
||||
|
|
@ -340,9 +326,8 @@ _cairo_win32_surface_finish (void *abstract_surface)
|
|||
if (surface->image)
|
||||
cairo_surface_destroy (surface->image);
|
||||
|
||||
if (surface->saved_clip) {
|
||||
if (surface->saved_clip)
|
||||
DeleteObject (surface->saved_clip);
|
||||
}
|
||||
|
||||
/* If we created the Bitmap and DC, destroy them */
|
||||
if (surface->bitmap) {
|
||||
|
|
@ -379,8 +364,18 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface,
|
|||
width, height,
|
||||
surface->dc,
|
||||
x, y,
|
||||
SRCCOPY))
|
||||
goto FAIL;
|
||||
SRCCOPY)) {
|
||||
/* If we fail to BitBlt here, most likely the source is a printer.
|
||||
* You can't reliably get bits from a printer DC, so just fill in
|
||||
* the surface as white (common case for printing).
|
||||
*/
|
||||
|
||||
RECT r;
|
||||
r.left = r.top = 0;
|
||||
r.right = width;
|
||||
r.bottom = height;
|
||||
FillRect(local->dc, &r, (HBRUSH)GetStockObject(WHITE_BRUSH));
|
||||
}
|
||||
|
||||
*local_out = local;
|
||||
|
||||
|
|
@ -403,7 +398,7 @@ _cairo_win32_surface_acquire_source_image (void *abstract_sur
|
|||
cairo_win32_surface_t *surface = abstract_surface;
|
||||
cairo_win32_surface_t *local = NULL;
|
||||
cairo_status_t status;
|
||||
|
||||
|
||||
if (surface->image) {
|
||||
*image_out = (cairo_image_surface_t *)surface->image;
|
||||
*image_extra = NULL;
|
||||
|
|
@ -446,7 +441,7 @@ _cairo_win32_surface_acquire_dest_image (void *abstract_surfa
|
|||
cairo_status_t status;
|
||||
RECT clip_box;
|
||||
int x1, y1, x2, y2;
|
||||
|
||||
|
||||
if (surface->image) {
|
||||
image_rect->x = 0;
|
||||
image_rect->y = 0;
|
||||
|
|
@ -461,12 +456,12 @@ _cairo_win32_surface_acquire_dest_image (void *abstract_surfa
|
|||
|
||||
if (GetClipBox (surface->dc, &clip_box) == ERROR)
|
||||
return _cairo_win32_print_gdi_error ("_cairo_win3_surface_acquire_dest_image");
|
||||
|
||||
|
||||
x1 = clip_box.left;
|
||||
x2 = clip_box.right;
|
||||
y1 = clip_box.top;
|
||||
y2 = clip_box.bottom;
|
||||
|
||||
|
||||
if (interest_rect->x > x1)
|
||||
x1 = interest_rect->x;
|
||||
if (interest_rect->y > y1)
|
||||
|
|
@ -595,6 +590,8 @@ _composite_alpha_blend (cairo_win32_surface_t *dst,
|
|||
|
||||
if (alpha_blend == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (GetDeviceCaps(dst->dc, SHADEBLENDCAPS) == SB_NONE)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
blend_function.BlendOp = AC_SRC_OVER;
|
||||
blend_function.BlendFlags = 0;
|
||||
|
|
@ -634,7 +631,7 @@ _cairo_win32_surface_composite (cairo_operator_t op,
|
|||
int integer_transform;
|
||||
int itx, ity;
|
||||
|
||||
if (pattern->type != CAIRO_PATTERN_SURFACE ||
|
||||
if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE ||
|
||||
pattern->extend != CAIRO_EXTEND_NONE)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
|
|
@ -642,7 +639,7 @@ _cairo_win32_surface_composite (cairo_operator_t op,
|
|||
/* FIXME: When we fully support RENDER style 4-channel
|
||||
* masks we need to check r/g/b != 1.0.
|
||||
*/
|
||||
if (mask_pattern->type != CAIRO_PATTERN_SOLID)
|
||||
if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
alpha = ((cairo_solid_pattern_t *)mask_pattern)->color.alpha_short >> 8;
|
||||
|
|
@ -660,6 +657,33 @@ _cairo_win32_surface_composite (cairo_operator_t op,
|
|||
if (!integer_transform)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
/* Fix up src coordinates; the src coords and size must be within the
|
||||
* bounds of the source surface.
|
||||
* XXX the region not covered should be appropriately rendered!
|
||||
* - for OVER/SOURCE with RGB24 source -> opaque black
|
||||
* - for SOURCE with ARGB32 source -> 100% transparent black
|
||||
*/
|
||||
src_x += itx;
|
||||
src_y += ity;
|
||||
|
||||
if (src_x < 0) {
|
||||
width += src_x;
|
||||
dst_x -= src_x;
|
||||
src_x = 0;
|
||||
}
|
||||
|
||||
if (src_y < 0) {
|
||||
height += src_y;
|
||||
dst_y -= src_y;
|
||||
src_y = 0;
|
||||
}
|
||||
|
||||
if (src_x + width > src->extents.width)
|
||||
width = src->extents.width - src_x;
|
||||
|
||||
if (src_y + height > src->extents.height)
|
||||
height = src->extents.height - src_y;
|
||||
|
||||
if (alpha == 255 &&
|
||||
src->format == dst->format &&
|
||||
(op == CAIRO_OPERATOR_SOURCE ||
|
||||
|
|
@ -669,7 +693,7 @@ _cairo_win32_surface_composite (cairo_operator_t op,
|
|||
dst_x, dst_y,
|
||||
width, height,
|
||||
src->dc,
|
||||
src_x + itx, src_y + ity,
|
||||
src_x, src_y,
|
||||
SRCCOPY))
|
||||
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite");
|
||||
|
||||
|
|
@ -681,7 +705,7 @@ _cairo_win32_surface_composite (cairo_operator_t op,
|
|||
op == CAIRO_OPERATOR_OVER) {
|
||||
|
||||
return _composite_alpha_blend (dst, src, alpha,
|
||||
src_x + itx, src_y + ity,
|
||||
src_x, src_y,
|
||||
dst_x, dst_y, width, height);
|
||||
}
|
||||
|
||||
|
|
@ -855,19 +879,9 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
|
|||
|
||||
if (region == NULL) {
|
||||
/* Clear any clip set by cairo, return to the original */
|
||||
|
||||
if (surface->set_clip) {
|
||||
if (SelectClipRgn (surface->dc, surface->saved_clip) == ERROR)
|
||||
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region");
|
||||
if (SelectClipRgn (surface->dc, surface->saved_clip) == ERROR)
|
||||
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region (reset)");
|
||||
|
||||
if (surface->saved_clip) {
|
||||
DeleteObject (surface->saved_clip);
|
||||
surface->saved_clip = NULL;
|
||||
}
|
||||
|
||||
surface->set_clip = 0;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
} else {
|
||||
|
|
@ -910,36 +924,16 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
|
|||
if (!gdi_region)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
if (surface->set_clip) {
|
||||
/* Combine the new region with the original clip */
|
||||
|
||||
if (surface->saved_clip) {
|
||||
if (CombineRgn (gdi_region, gdi_region, surface->saved_clip, RGN_AND) == ERROR)
|
||||
goto FAIL;
|
||||
}
|
||||
/* Combine the new region with the original clip */
|
||||
|
||||
if (SelectClipRgn (surface->dc, gdi_region) == ERROR)
|
||||
if (surface->saved_clip) {
|
||||
if (CombineRgn (gdi_region, gdi_region, surface->saved_clip, RGN_AND) == ERROR)
|
||||
goto FAIL;
|
||||
|
||||
} else {
|
||||
/* Save the the current region */
|
||||
|
||||
surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
|
||||
if (!surface->saved_clip) {
|
||||
goto FAIL; }
|
||||
|
||||
/* This function has no error return! */
|
||||
if (GetClipRgn (surface->dc, surface->saved_clip) == 0) { /* No clip */
|
||||
DeleteObject (surface->saved_clip);
|
||||
surface->saved_clip = NULL;
|
||||
}
|
||||
|
||||
if (ExtSelectClipRgn (surface->dc, gdi_region, RGN_AND) == ERROR)
|
||||
goto FAIL;
|
||||
|
||||
surface->set_clip = 1;
|
||||
}
|
||||
|
||||
if (SelectClipRgn (surface->dc, gdi_region) == ERROR)
|
||||
goto FAIL;
|
||||
|
||||
DeleteObject (gdi_region);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
|
@ -955,15 +949,8 @@ _cairo_win32_surface_get_extents (void *abstract_surface,
|
|||
cairo_rectangle_t *rectangle)
|
||||
{
|
||||
cairo_win32_surface_t *surface = abstract_surface;
|
||||
RECT clip_box;
|
||||
|
||||
if (GetClipBox (surface->dc, &clip_box) == ERROR)
|
||||
return _cairo_win32_print_gdi_error ("_cairo_win3_surface_acquire_dest_image");
|
||||
|
||||
rectangle->x = clip_box.left;
|
||||
rectangle->y = clip_box.top;
|
||||
rectangle->width = clip_box.right - clip_box.left;
|
||||
rectangle->height = clip_box.bottom - clip_box.top;
|
||||
*rectangle = surface->extents;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -974,11 +961,25 @@ _cairo_win32_surface_flush (void *abstract_surface)
|
|||
return _cairo_surface_reset_clip (abstract_surface);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_win32_surface_create:
|
||||
* @hdc: the DC to create a surface for
|
||||
*
|
||||
* Creates a cairo surface that targets the given DC. The DC will be
|
||||
* queried for its initial clip extents, and this will be used as the
|
||||
* size of the cairo surface. Also, if the DC is a raster DC, it will
|
||||
* be queried for its pixel format and the cairo surface format will
|
||||
* be set appropriately.
|
||||
*
|
||||
* Return value: the newly created surface
|
||||
**/
|
||||
cairo_surface_t *
|
||||
cairo_win32_surface_create (HDC hdc)
|
||||
{
|
||||
cairo_win32_surface_t *surface;
|
||||
RECT rect;
|
||||
int depth;
|
||||
cairo_format_t format;
|
||||
|
||||
/* Try to figure out the drawing bounds for the Device context
|
||||
*/
|
||||
|
|
@ -988,7 +989,28 @@ cairo_win32_surface_create (HDC hdc)
|
|||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
|
||||
if (GetDeviceCaps(hdc, TECHNOLOGY) == DT_RASDISPLAY) {
|
||||
depth = GetDeviceCaps(hdc, BITSPIXEL);
|
||||
if (depth == 32)
|
||||
format = CAIRO_FORMAT_ARGB32;
|
||||
else if (depth == 24)
|
||||
format = CAIRO_FORMAT_RGB24;
|
||||
else if (depth == 16)
|
||||
format = CAIRO_FORMAT_RGB24;
|
||||
else if (depth == 8)
|
||||
format = CAIRO_FORMAT_A8;
|
||||
else if (depth == 1)
|
||||
format = CAIRO_FORMAT_A1;
|
||||
else {
|
||||
_cairo_win32_print_gdi_error("cairo_win32_surface_create(bad BITSPIXEL)");
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return &_cairo_surface_nil;
|
||||
}
|
||||
} else {
|
||||
format = CAIRO_FORMAT_RGB24;
|
||||
}
|
||||
|
||||
surface = malloc (sizeof (cairo_win32_surface_t));
|
||||
if (surface == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
|
@ -996,7 +1018,7 @@ cairo_win32_surface_create (HDC hdc)
|
|||
}
|
||||
|
||||
surface->image = NULL;
|
||||
surface->format = CAIRO_FORMAT_RGB24;
|
||||
surface->format = format;
|
||||
|
||||
surface->dc = hdc;
|
||||
surface->bitmap = NULL;
|
||||
|
|
@ -1007,14 +1029,47 @@ cairo_win32_surface_create (HDC hdc)
|
|||
surface->clip_rect.width = rect.right - rect.left;
|
||||
surface->clip_rect.height = rect.bottom - rect.top;
|
||||
|
||||
surface->set_clip = 0;
|
||||
surface->saved_clip = NULL;
|
||||
if (surface->clip_rect.width == 0 ||
|
||||
surface->clip_rect.height == 0)
|
||||
{
|
||||
surface->saved_clip = NULL;
|
||||
} else {
|
||||
surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
|
||||
if (GetClipRgn (hdc, surface->saved_clip) == 0) {
|
||||
DeleteObject(surface->saved_clip);
|
||||
surface->saved_clip = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
surface->extents = surface->clip_rect;
|
||||
|
||||
_cairo_surface_init (&surface->base, &cairo_win32_surface_backend);
|
||||
|
||||
return (cairo_surface_t *)surface;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_win32_surface_create_with_dib:
|
||||
* @format: format of pixels in the surface to create
|
||||
* @width: width of the surface, in pixels
|
||||
* @height: height of the surface, in pixels
|
||||
*
|
||||
* Creates a device-independent-bitmap surface not associated with
|
||||
* any particular existing surface or device context. The created
|
||||
* bitmap will be unititialized.
|
||||
*
|
||||
* Return value: the newly created surface
|
||||
*
|
||||
**/
|
||||
cairo_surface_t *
|
||||
cairo_win32_surface_create_with_dib (cairo_format_t format,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
return _cairo_win32_surface_create_for_dc (NULL, format, width, height);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* _cairo_surface_is_win32:
|
||||
* @surface: a #cairo_surface_t
|
||||
|
|
@ -1029,7 +1084,33 @@ _cairo_surface_is_win32 (cairo_surface_t *surface)
|
|||
return surface->backend == &cairo_win32_surface_backend;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_win32_surface_get_dc
|
||||
* @surface: a #cairo_surface_t
|
||||
*
|
||||
* Returns the HDC associated with this surface, or NULL if none.
|
||||
* Also returns NULL if the surface is not a win32 surface.
|
||||
*
|
||||
* Return value: HDC or NULL if no HDC available.
|
||||
**/
|
||||
HDC
|
||||
cairo_win32_surface_get_dc (cairo_surface_t *surface)
|
||||
{
|
||||
cairo_win32_surface_t *winsurf;
|
||||
|
||||
if (surface == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!_cairo_surface_is_win32(surface))
|
||||
return NULL;
|
||||
|
||||
winsurf = (cairo_win32_surface_t *) surface;
|
||||
|
||||
return winsurf->dc;
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_win32_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_WIN32,
|
||||
_cairo_win32_surface_create_similar,
|
||||
_cairo_win32_surface_finish,
|
||||
_cairo_win32_surface_acquire_source_image,
|
||||
|
|
|
|||
|
|
@ -47,6 +47,14 @@ CAIRO_BEGIN_DECLS
|
|||
cairo_public cairo_surface_t *
|
||||
cairo_win32_surface_create (HDC hdc);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_win32_surface_create_with_dib (cairo_format_t format,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
cairo_public HDC
|
||||
cairo_win32_surface_get_dc (cairo_surface_t *surface);
|
||||
|
||||
cairo_public cairo_font_face_t *
|
||||
cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont);
|
||||
|
||||
|
|
|
|||
|
|
@ -1025,6 +1025,7 @@ _cairo_xcb_surface_get_extents (void *abstract_surface,
|
|||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_xcb_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_XCB,
|
||||
_cairo_xcb_surface_create_similar,
|
||||
_cairo_xcb_surface_finish,
|
||||
_cairo_xcb_surface_acquire_source_image,
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "cairo-xlib-test.h"
|
||||
#include "cairo-xlib-private.h"
|
||||
#include <X11/extensions/Xrender.h>
|
||||
#include <X11/extensions/renderproto.h>
|
||||
|
||||
/* Xlib doesn't define a typedef, so define one ourselves */
|
||||
typedef int (*cairo_xlib_error_func_t) (Display *display,
|
||||
|
|
@ -1047,7 +1048,7 @@ _categorize_composite_operation (cairo_xlib_surface_t *dst,
|
|||
if (!dst->buggy_repeat)
|
||||
return DO_RENDER;
|
||||
|
||||
if (src_pattern->type == CAIRO_PATTERN_SURFACE)
|
||||
if (src_pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
|
||||
{
|
||||
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *)src_pattern;
|
||||
|
||||
|
|
@ -1675,6 +1676,7 @@ _cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
|
|||
cairo_scaled_font_t *scaled_font);
|
||||
|
||||
static const cairo_surface_backend_t cairo_xlib_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_XLIB,
|
||||
_cairo_xlib_surface_create_similar,
|
||||
_cairo_xlib_surface_finish,
|
||||
_cairo_xlib_surface_acquire_source_image,
|
||||
|
|
@ -2403,6 +2405,8 @@ _cairo_xlib_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
cairo_int_status_t status;
|
||||
cairo_xlib_surface_t *self = abstract_surface;
|
||||
cairo_xlib_surface_t *src;
|
||||
const cairo_glyph_t *glyphs_chunk;
|
||||
int glyphs_remaining, chunk_size, max_chunk_size;
|
||||
composite_operation_t operation;
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_xlib_surface_font_private_t *font_private;
|
||||
|
|
@ -2457,23 +2461,41 @@ _cairo_xlib_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
}
|
||||
|
||||
_cairo_xlib_surface_ensure_dst_picture (self);
|
||||
/* Call the appropriate sub-function. */
|
||||
|
||||
max_chunk_size = XMaxRequestSize (self->dpy);
|
||||
if (max_index < 256)
|
||||
status = _cairo_xlib_surface_old_show_glyphs8 (scaled_font, op, src, self,
|
||||
source_x + attributes.x_offset - dest_x,
|
||||
source_y + attributes.y_offset - dest_y,
|
||||
glyphs, num_glyphs);
|
||||
max_chunk_size -= sz_xRenderCompositeGlyphs8Req;
|
||||
else if (max_index < 65536)
|
||||
status = _cairo_xlib_surface_old_show_glyphs16 (scaled_font, op, src, self,
|
||||
source_x + attributes.x_offset - dest_x,
|
||||
source_y + attributes.y_offset - dest_y,
|
||||
glyphs, num_glyphs);
|
||||
else
|
||||
status = _cairo_xlib_surface_old_show_glyphs32 (scaled_font, op, src, self,
|
||||
source_x + attributes.x_offset - dest_x,
|
||||
source_y + attributes.y_offset - dest_y,
|
||||
glyphs, num_glyphs);
|
||||
max_chunk_size -= sz_xRenderCompositeGlyphs16Req;
|
||||
else
|
||||
max_chunk_size -= sz_xRenderCompositeGlyphs32Req;
|
||||
max_chunk_size /= sz_xGlyphElt;
|
||||
|
||||
for (glyphs_remaining = num_glyphs, glyphs_chunk = glyphs;
|
||||
glyphs_remaining;
|
||||
glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size)
|
||||
{
|
||||
chunk_size = MIN (glyphs_remaining, max_chunk_size);
|
||||
|
||||
/* Call the appropriate sub-function. */
|
||||
if (max_index < 256)
|
||||
status = _cairo_xlib_surface_old_show_glyphs8 (scaled_font, op, src, self,
|
||||
source_x + attributes.x_offset - dest_x,
|
||||
source_y + attributes.y_offset - dest_y,
|
||||
glyphs_chunk, chunk_size);
|
||||
else if (max_index < 65536)
|
||||
status = _cairo_xlib_surface_old_show_glyphs16 (scaled_font, op, src, self,
|
||||
source_x + attributes.x_offset - dest_x,
|
||||
source_y + attributes.y_offset - dest_y,
|
||||
glyphs_chunk, chunk_size);
|
||||
else
|
||||
status = _cairo_xlib_surface_old_show_glyphs32 (scaled_font, op, src, self,
|
||||
source_x + attributes.x_offset - dest_x,
|
||||
source_y + attributes.y_offset - dest_y,
|
||||
glyphs_chunk, chunk_size);
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS && !_cairo_operator_bounded_by_mask (op)) {
|
||||
cairo_rectangle_t extents;
|
||||
|
|
|
|||
49
src/cairo.c
|
|
@ -220,6 +220,9 @@ cairo_create (cairo_surface_t *target)
|
|||
cairo_t *
|
||||
cairo_reference (cairo_t *cr)
|
||||
{
|
||||
if (cr == NULL)
|
||||
return NULL;
|
||||
|
||||
if (cr->ref_count == (unsigned int)-1)
|
||||
return cr;
|
||||
|
||||
|
|
@ -241,6 +244,9 @@ cairo_reference (cairo_t *cr)
|
|||
void
|
||||
cairo_destroy (cairo_t *cr)
|
||||
{
|
||||
if (cr == NULL)
|
||||
return;
|
||||
|
||||
if (cr->ref_count == (unsigned int)-1)
|
||||
return;
|
||||
|
||||
|
|
@ -2026,6 +2032,46 @@ cairo_get_font_options (cairo_t *cr,
|
|||
_cairo_gstate_get_font_options (cr->gstate, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_set_scaled_font:
|
||||
* @cr: a #cairo_t
|
||||
* @scaled_font: a #cairo_scaled_font_t
|
||||
*
|
||||
* Replaces the current font face, font matrix, and font options in
|
||||
* the #cairo_t with those of the #cairo_scaled_font_t. Except for
|
||||
* some translation, the current CTM of the #cairo_t should be the
|
||||
* same as that of the #cairo_scaled_font_t, which can be accessed
|
||||
* using cairo_scaled_font_get_ctm().
|
||||
**/
|
||||
void
|
||||
cairo_set_scaled_font (cairo_t *cr,
|
||||
const cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
if (cr->status)
|
||||
return;
|
||||
|
||||
cr->status = scaled_font->status;
|
||||
if (cr->status)
|
||||
goto BAIL;
|
||||
|
||||
cr->status = _cairo_gstate_set_font_face (cr->gstate, scaled_font->font_face);
|
||||
if (cr->status)
|
||||
goto BAIL;
|
||||
|
||||
cr->status = _cairo_gstate_set_font_matrix (cr->gstate, &scaled_font->font_matrix);
|
||||
if (cr->status)
|
||||
goto BAIL;
|
||||
|
||||
cr->status = _cairo_gstate_set_font_options (cr->gstate, &scaled_font->options);
|
||||
if (cr->status)
|
||||
goto BAIL;
|
||||
|
||||
return;
|
||||
|
||||
BAIL:
|
||||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_text_extents:
|
||||
* @cr: a #cairo_t
|
||||
|
|
@ -2203,6 +2249,9 @@ cairo_show_glyphs (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs)
|
|||
if (cr->status)
|
||||
return;
|
||||
|
||||
if (num_glyphs == 0)
|
||||
return;
|
||||
|
||||
cr->status = _cairo_gstate_show_glyphs (cr->gstate, glyphs, num_glyphs);
|
||||
if (cr->status)
|
||||
_cairo_set_error (cr, cr->status);
|
||||
|
|
|
|||
139
src/cairo.h
|
|
@ -855,6 +855,10 @@ cairo_public void
|
|||
cairo_get_font_options (cairo_t *cr,
|
||||
cairo_font_options_t *options);
|
||||
|
||||
cairo_public void
|
||||
cairo_set_scaled_font (cairo_t *cr,
|
||||
const cairo_scaled_font_t *scaled_font);
|
||||
|
||||
cairo_public void
|
||||
cairo_show_text (cairo_t *cr, const char *utf8);
|
||||
|
||||
|
|
@ -899,6 +903,47 @@ cairo_font_face_destroy (cairo_font_face_t *font_face);
|
|||
cairo_public cairo_status_t
|
||||
cairo_font_face_status (cairo_font_face_t *font_face);
|
||||
|
||||
/**
|
||||
* cairo_font_type_t
|
||||
* @CAIRO_SCALED_FONT_TYPE_FT: The font is of type ft
|
||||
* @CAIRO_SCALED_FONT_TYPE_WIN32: The font is of type win32
|
||||
* @CAIRO_SCALED_FONT_TYPE_ATSUI: The font is of type atsui
|
||||
*
|
||||
* @cairo_font_type_t is used to describe the type of a given font
|
||||
* face or scaled font. The font types are also known as "font
|
||||
* backends" within cairo.
|
||||
*
|
||||
* The type of a font face is determined by the function used to
|
||||
* create it, which will generally be of the form
|
||||
* cairo_<type>_font_face_create. The font face type can be queried
|
||||
* with cairo_font_face_get_type()
|
||||
*
|
||||
* The various cairo_font_face functions can be used with a font face
|
||||
* of any type.
|
||||
*
|
||||
* The type of a scaled font is determined by the type of the font
|
||||
* face passed to cairo_scaled_font_create. The scaled font type can
|
||||
* be queried with cairo_scaled_font_get_type()
|
||||
*
|
||||
* The various cairo_scaled_font functions can be used with scaled
|
||||
* fonts of any type, but some font backends also provide
|
||||
* type-specific functions that must only be called with a scaled font
|
||||
* of the appropriate type. These functions have names that begin with
|
||||
* cairo_<type>_scaled_font such as cairo_ft_scaled_font_lock_face.
|
||||
*
|
||||
* The behavior of calling a type-specific function with a scaled font
|
||||
* of the wrong type is undefined.
|
||||
*/
|
||||
typedef enum _cairo_font_type {
|
||||
CAIRO_FONT_TYPE_TOY,
|
||||
CAIRO_FONT_TYPE_FT,
|
||||
CAIRO_FONT_TYPE_WIN32,
|
||||
CAIRO_FONT_TYPE_ATSUI
|
||||
} cairo_font_type_t;
|
||||
|
||||
cairo_public cairo_font_type_t
|
||||
cairo_font_face_get_type (cairo_font_face_t *font_face);
|
||||
|
||||
cairo_public void *
|
||||
cairo_font_face_get_user_data (cairo_font_face_t *font_face,
|
||||
const cairo_user_data_key_t *key);
|
||||
|
|
@ -926,6 +971,9 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font);
|
|||
cairo_public cairo_status_t
|
||||
cairo_scaled_font_status (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
cairo_public cairo_font_type_t
|
||||
cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
cairo_public void
|
||||
cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font,
|
||||
cairo_font_extents_t *extents);
|
||||
|
|
@ -1150,14 +1198,64 @@ cairo_surface_create_similar (cairo_surface_t *other,
|
|||
cairo_public cairo_surface_t *
|
||||
cairo_surface_reference (cairo_surface_t *surface);
|
||||
|
||||
cairo_public void
|
||||
cairo_surface_finish (cairo_surface_t *surface);
|
||||
|
||||
cairo_public void
|
||||
cairo_surface_destroy (cairo_surface_t *surface);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_surface_status (cairo_surface_t *surface);
|
||||
|
||||
cairo_public void
|
||||
cairo_surface_finish (cairo_surface_t *surface);
|
||||
/**
|
||||
* cairo_surface_type_t
|
||||
* @CAIRO_SURFACE_TYPE_IMAGE: The surface is of type image
|
||||
* @CAIRO_SURFACE_TYPE_PDF: The surface is of type pdf
|
||||
* @CAIRO_SURFACE_TYPE_PS: The surface is of type ps
|
||||
* @CAIRO_SURFACE_TYPE_XLIB: The surface is of type xlib
|
||||
* @CAIRO_SURFACE_TYPE_XCB: The surface is of type xcb
|
||||
* @CAIRO_SURFACE_TYPE_GLITZ: The surface is of type glitz
|
||||
* @CAIRO_SURFACE_TYPE_QUARTZ: The surface is of type quartz
|
||||
* @CAIRO_SURFACE_TYPE_WIN32: The surface is of type win32
|
||||
* @CAIRO_SURFACE_TYPE_BEOS: The surface is of type beos
|
||||
* @CAIRO_SURFACE_TYPE_DIRECTFB: The surface is of type directfb
|
||||
* @CAIRO_SURFACE_TYPE_SVG: The surface is of type svg
|
||||
*
|
||||
* @cairo_surface_type_t is used to describe the type of a given
|
||||
* surface. The surface types are also known as "backends" or "surface
|
||||
* backends" within cairo.
|
||||
*
|
||||
* The type of a surface is determined by the function used to create
|
||||
* it, which will generally be of the form cairo_<type>_surface_create,
|
||||
* (though see cairo_surface_create_similar as well).
|
||||
*
|
||||
* The surface type can be queried with cairo_surface_get_type()
|
||||
*
|
||||
* The various cairo_surface functions can be used with surfaces of
|
||||
* any type, but some backends also provide type-specific functions
|
||||
* that must only be called with a surface of the appropriate
|
||||
* type. These functions have names that begin with
|
||||
* cairo_<type>_surface such as cairo_image_surface_get_width().
|
||||
*
|
||||
* The behavior of calling a type-specific function with a surface of
|
||||
* the wrong type is undefined.
|
||||
*/
|
||||
typedef enum _cairo_surface_type {
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_SURFACE_TYPE_PDF,
|
||||
CAIRO_SURFACE_TYPE_PS,
|
||||
CAIRO_SURFACE_TYPE_XLIB,
|
||||
CAIRO_SURFACE_TYPE_XCB,
|
||||
CAIRO_SURFACE_TYPE_GLITZ,
|
||||
CAIRO_SURFACE_TYPE_QUARTZ,
|
||||
CAIRO_SURFACE_TYPE_WIN32,
|
||||
CAIRO_SURFACE_TYPE_BEOS,
|
||||
CAIRO_SURFACE_TYPE_DIRECTFB,
|
||||
CAIRO_SURFACE_TYPE_SVG
|
||||
} cairo_surface_type_t;
|
||||
|
||||
cairo_public cairo_surface_type_t
|
||||
cairo_surface_get_type (cairo_surface_t *surface);
|
||||
|
||||
#if CAIRO_HAS_PNG_FUNCTIONS
|
||||
|
||||
|
|
@ -1293,6 +1391,43 @@ cairo_pattern_destroy (cairo_pattern_t *pattern);
|
|||
cairo_public cairo_status_t
|
||||
cairo_pattern_status (cairo_pattern_t *pattern);
|
||||
|
||||
/**
|
||||
* cairo_pattern_type_t
|
||||
|
||||
* @CAIRO_PATTERN_TYPE_SOLID: The pattern is a solid (uniform)
|
||||
* color. It may be opaque or translucent.
|
||||
* @CAIRO_PATTERN_TYPE_SURFACE: The pattern is a based on a surface (an image).
|
||||
* @CAIRO_PATTERN_TYPE_LINEAR: The pattern is a linear gradient.
|
||||
* @CAIRO_PATTERN_TYPE_RADIAL: The pattern is a radial gradient.
|
||||
*
|
||||
* @cairo_pattern_type_t us used to describe the type of a given pattern.
|
||||
*
|
||||
* The type of a pattern is determined by the function used to create
|
||||
* it. The cairo_pattern_create_rgb() and cairo_pattern_create_rgba()
|
||||
* functions create SOLID patterns. The remaining
|
||||
* cairo_pattern_create functions map to pattern types in obvious
|
||||
* ways.
|
||||
*
|
||||
* The pattern type can be queried with cairo_pattern_get_type()
|
||||
*
|
||||
* Most cairo_pattern functions can be called with a pattern of any
|
||||
* type, (though trying to change the extend or filter for a solid
|
||||
* pattern will have no effect). A notable exception is
|
||||
* cairo_pattern_add_color_stop_rgb() and
|
||||
* cairo_pattern_add_color_stop_rgba() which must only be called with
|
||||
* gradient patterns (either LINEAR or RADIAL). Otherwise the pattern
|
||||
* will be shutdown and put into an error state.
|
||||
*/
|
||||
typedef enum _cairo_pattern_type {
|
||||
CAIRO_PATTERN_TYPE_SOLID,
|
||||
CAIRO_PATTERN_TYPE_SURFACE,
|
||||
CAIRO_PATTERN_TYPE_LINEAR,
|
||||
CAIRO_PATTERN_TYPE_RADIAL
|
||||
} cairo_pattern_type_t;
|
||||
|
||||
cairo_public cairo_pattern_type_t
|
||||
cairo_pattern_get_type (cairo_pattern_t *pattern);
|
||||
|
||||
cairo_public void
|
||||
cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
|
||||
double offset,
|
||||
|
|
|
|||
119
src/cairoint.h
|
|
@ -184,6 +184,10 @@ cairo_private void _cairo_beos_unlock(void*);
|
|||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#define ASSERT_NOT_REACHED \
|
||||
do { \
|
||||
static const int NOT_REACHED = 0; \
|
||||
|
|
@ -256,6 +260,15 @@ typedef enum cairo_int_status {
|
|||
CAIRO_INT_STATUS_CACHE_EMPTY
|
||||
} cairo_int_status_t;
|
||||
|
||||
typedef enum cairo_internal_surface_type {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
|
||||
} cairo_internal_surface_type_t;
|
||||
|
||||
typedef enum cairo_direction {
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
CAIRO_DIRECTION_REVERSE
|
||||
|
|
@ -464,6 +477,7 @@ struct _cairo_scaled_font {
|
|||
};
|
||||
|
||||
struct _cairo_font_face {
|
||||
/* hash_entry must be first */
|
||||
cairo_hash_entry_t hash_entry;
|
||||
cairo_status_t status;
|
||||
int ref_count;
|
||||
|
|
@ -508,6 +522,8 @@ typedef enum _cairo_scaled_glyph_info {
|
|||
} cairo_scaled_glyph_info_t;
|
||||
|
||||
struct _cairo_scaled_font_backend {
|
||||
cairo_font_type_t type;
|
||||
|
||||
cairo_status_t
|
||||
(*create_toy) (cairo_toy_font_face_t *toy_face,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
|
|
@ -555,6 +571,8 @@ struct _cairo_scaled_font_backend {
|
|||
};
|
||||
|
||||
struct _cairo_font_face_backend {
|
||||
cairo_font_type_t type;
|
||||
|
||||
/* The destroy() function is allowed to resurrect the font face
|
||||
* by re-referencing. This is needed for the FreeType backend.
|
||||
*/
|
||||
|
|
@ -599,6 +617,8 @@ typedef struct _cairo_stroke_style {
|
|||
} cairo_stroke_style_t;
|
||||
|
||||
struct _cairo_surface_backend {
|
||||
cairo_surface_type_t type;
|
||||
|
||||
cairo_surface_t *
|
||||
(*create_similar) (void *surface,
|
||||
cairo_content_t content,
|
||||
|
|
@ -829,6 +849,11 @@ typedef struct _cairo_format_masks {
|
|||
struct _cairo_surface {
|
||||
const cairo_surface_backend_t *backend;
|
||||
|
||||
/* We allow surfaces to override the backend->type by shoving something
|
||||
* else into surface->type. This is for "wrapper" surfaces that want to
|
||||
* hide their internal type from the user-level API. */
|
||||
cairo_surface_type_t type;
|
||||
|
||||
unsigned int ref_count;
|
||||
cairo_status_t status;
|
||||
cairo_bool_t finished;
|
||||
|
|
@ -909,13 +934,6 @@ typedef enum {
|
|||
#define CAIRO_EXTEND_GRADIENT_DEFAULT CAIRO_EXTEND_PAD
|
||||
#define CAIRO_FILTER_DEFAULT CAIRO_FILTER_BEST
|
||||
|
||||
typedef enum {
|
||||
CAIRO_PATTERN_SOLID,
|
||||
CAIRO_PATTERN_SURFACE,
|
||||
CAIRO_PATTERN_LINEAR,
|
||||
CAIRO_PATTERN_RADIAL
|
||||
} cairo_pattern_type_t;
|
||||
|
||||
struct _cairo_pattern {
|
||||
cairo_pattern_type_t type;
|
||||
unsigned int ref_count;
|
||||
|
|
@ -1372,6 +1390,13 @@ _cairo_font_options_init_copy (cairo_font_options_t *options,
|
|||
cairo_private cairo_status_t
|
||||
_cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices);
|
||||
|
||||
/* cairo_operator.c */
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_operator_always_opaque (cairo_operator_t op);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_operator_always_translucent (cairo_operator_t op);
|
||||
|
||||
/* cairo_path.c */
|
||||
cairo_private void
|
||||
_cairo_path_fixed_init (cairo_path_fixed_t *path);
|
||||
|
|
@ -1536,7 +1561,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_path_fixed_t *path);
|
||||
|
||||
|
|
@ -1804,6 +1829,9 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
|
|||
unsigned int width,
|
||||
unsigned int height);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_surface_is_opaque (const cairo_surface_t *surface);
|
||||
|
||||
/* cairo_image_surface.c */
|
||||
|
||||
#define CAIRO_FORMAT_VALID(format) ((format) >= CAIRO_FORMAT_ARGB32 && \
|
||||
|
|
@ -1847,6 +1875,19 @@ _cairo_image_surface_create_for_data_with_content (unsigned char *data,
|
|||
cairo_private void
|
||||
_cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface);
|
||||
|
||||
/* XXX: It's a nasty kludge that this appears here. Backend functions
|
||||
* like this should really be static. But we're doing this to work
|
||||
* around some general defects in the backend clipping interfaces,
|
||||
* (see some notes in test-paginated-surface.c).
|
||||
*
|
||||
* I want to fix the real defects, but it's "hard" as they touch many
|
||||
* backends, so doing that will require synchronizing several backend
|
||||
* maintainers.
|
||||
*/
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_image_surface_set_clip_region (void *abstract_surface,
|
||||
pixman_region16_t *region);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_surface_is_image (const cairo_surface_t *surface);
|
||||
|
||||
|
|
@ -2040,7 +2081,10 @@ _cairo_pattern_transform (cairo_pattern_t *pattern,
|
|||
const cairo_matrix_t *ctm_inverse);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_pattern_is_opaque_solid (cairo_pattern_t *pattern);
|
||||
_cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern);
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
|
||||
|
|
@ -2110,14 +2154,37 @@ _cairo_utf8_to_utf16 (const unsigned char *str,
|
|||
|
||||
typedef struct _cairo_output_stream cairo_output_stream_t;
|
||||
|
||||
extern const cairo_private cairo_output_stream_t cairo_output_stream_nil;
|
||||
|
||||
/* We already have the following declared in cairo.h:
|
||||
|
||||
typedef cairo_status_t (*cairo_write_func_t) (void *closure,
|
||||
const unsigned char *data,
|
||||
unsigned int length);
|
||||
*/
|
||||
typedef cairo_status_t (*cairo_close_func_t) (void *closure);
|
||||
|
||||
|
||||
/* This function never returns NULL. If an error occurs (NO_MEMORY)
|
||||
* while trying to create the output stream this function returns a
|
||||
* valid pointer to a nil output stream.
|
||||
*
|
||||
* Note that even with a nil surface, the close_func callback will be
|
||||
* called by a call to _cairo_output_stream_close or
|
||||
* _cairo_output_stream_destroy.
|
||||
*/
|
||||
cairo_private cairo_output_stream_t *
|
||||
_cairo_output_stream_create (cairo_write_func_t write_func,
|
||||
cairo_close_func_t close_func,
|
||||
void *closure);
|
||||
|
||||
cairo_private void
|
||||
_cairo_output_stream_close (cairo_output_stream_t *stream);
|
||||
|
||||
cairo_private void
|
||||
_cairo_output_stream_destroy (cairo_output_stream_t *stream);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
cairo_private void
|
||||
_cairo_output_stream_write (cairo_output_stream_t *stream,
|
||||
const void *data, size_t length);
|
||||
|
||||
|
|
@ -2126,11 +2193,14 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
|
|||
const char *data,
|
||||
size_t length);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
cairo_private unsigned char *
|
||||
_cairo_lzw_compress (unsigned char *data, unsigned long *data_size_in_out);
|
||||
|
||||
cairo_private void
|
||||
_cairo_output_stream_vprintf (cairo_output_stream_t *stream,
|
||||
const char *fmt, va_list ap);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
cairo_private void
|
||||
_cairo_output_stream_printf (cairo_output_stream_t *stream,
|
||||
const char *fmt, ...) CAIRO_PRINTF_FORMAT(2, 3);
|
||||
|
||||
|
|
@ -2140,8 +2210,30 @@ _cairo_output_stream_get_position (cairo_output_stream_t *status);
|
|||
cairo_private cairo_status_t
|
||||
_cairo_output_stream_get_status (cairo_output_stream_t *stream);
|
||||
|
||||
/* This function never returns NULL. If an error occurs (NO_MEMORY or
|
||||
* WRITE_ERROR) while trying to create the output stream this function
|
||||
* returns a valid pointer to a nil output stream.
|
||||
*
|
||||
* NOTE: Even if a nil surface is returned, the caller should still
|
||||
* call _cairo_output_stream_destroy (or _cairo_output_stream_close at
|
||||
* least) in order to ensure that everything is properly cleaned up.
|
||||
*/
|
||||
cairo_private cairo_output_stream_t *
|
||||
_cairo_output_stream_create_for_file (const char *filename);
|
||||
_cairo_output_stream_create_for_filename (const char *filename);
|
||||
|
||||
/* This function never returns NULL. If an error occurs (NO_MEMORY or
|
||||
* WRITE_ERROR) while trying to create the output stream this function
|
||||
* returns a valid pointer to a nil output stream.
|
||||
*
|
||||
* The caller still "owns" file and is responsible for calling fclose
|
||||
* on it when finished. The stream will not do this itself.
|
||||
*/
|
||||
cairo_private cairo_output_stream_t *
|
||||
_cairo_output_stream_create_for_file (FILE *file);
|
||||
|
||||
/* cairo_base85_stream.c */
|
||||
cairo_output_stream_t *
|
||||
_cairo_base85_stream_create (cairo_output_stream_t *output);
|
||||
|
||||
cairo_private void
|
||||
_cairo_error (cairo_status_t status);
|
||||
|
|
@ -2150,7 +2242,6 @@ cairo_private int
|
|||
_cairo_dtostr (char *buffer, size_t size, double d);
|
||||
|
||||
/* Avoid unnecessary PLT entries. */
|
||||
|
||||
slim_hidden_proto(cairo_get_current_point)
|
||||
slim_hidden_proto(cairo_fill_preserve)
|
||||
slim_hidden_proto(cairo_clip_preserve)
|
||||
|
|
|
|||
|
|
@ -175,6 +175,7 @@ _test_fallback_surface_get_extents (void *abstract_surface,
|
|||
}
|
||||
|
||||
const cairo_surface_backend_t test_fallback_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
|
||||
_test_fallback_surface_create_similar,
|
||||
_test_fallback_surface_finish,
|
||||
_test_fallback_surface_acquire_source_image,
|
||||
|
|
|
|||
|
|
@ -296,6 +296,7 @@ _test_meta_surface_snapshot (void *abstract_other)
|
|||
}
|
||||
|
||||
const cairo_surface_backend_t test_meta_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
|
||||
NULL, /* create_similar */
|
||||
_test_meta_surface_finish,
|
||||
_test_meta_surface_acquire_source_image,
|
||||
|
|
|
|||
|
|
@ -51,6 +51,15 @@
|
|||
|
||||
#include "cairo-paginated-surface-private.h"
|
||||
|
||||
typedef struct _test_paginated_surface {
|
||||
cairo_surface_t base;
|
||||
cairo_surface_t *target;
|
||||
cairo_paginated_mode_t paginated_mode;
|
||||
} test_paginated_surface_t;
|
||||
|
||||
static const cairo_surface_backend_t test_paginated_surface_backend;
|
||||
static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend;
|
||||
|
||||
cairo_surface_t *
|
||||
_test_paginated_surface_create_for_data (unsigned char *data,
|
||||
cairo_content_t content,
|
||||
|
|
@ -58,11 +67,218 @@ _test_paginated_surface_create_for_data (unsigned char *data,
|
|||
int height,
|
||||
int stride)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_surface_t *target;
|
||||
test_paginated_surface_t *surface;
|
||||
|
||||
target = _cairo_image_surface_create_for_data_with_content (data, content,
|
||||
target = _cairo_image_surface_create_for_data_with_content (data, content,
|
||||
width, height,
|
||||
stride);
|
||||
status = cairo_surface_status (target);
|
||||
if (status) {
|
||||
_cairo_error (status);
|
||||
return (cairo_surface_t *) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
return _cairo_paginated_surface_create (target, content, width, height);
|
||||
surface = malloc (sizeof (test_paginated_surface_t));
|
||||
if (surface == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_surface_t *) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
_cairo_surface_init (&surface->base, &test_paginated_surface_backend);
|
||||
|
||||
surface->target = target;
|
||||
|
||||
return _cairo_paginated_surface_create (&surface->base, content, width, height,
|
||||
&test_paginated_surface_paginated_backend);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_test_paginated_surface_set_clip_region (void *abstract_surface,
|
||||
pixman_region16_t *region)
|
||||
{
|
||||
test_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
/* XXX: The whole surface backend clipping interface is a giant
|
||||
* disaster right now. In particular, its uncleanness shows up
|
||||
* when trying to implement one surface that wraps another one (as
|
||||
* we are doing here).
|
||||
*
|
||||
* Here are two of the problems that show up:
|
||||
*
|
||||
* 1. The most critical piece of information in all this stuff,
|
||||
* the "clip" isn't getting passed to the backend
|
||||
* functions. Instead the generic surface layer is caching that as
|
||||
* surface->clip. This is a problem for surfaces like this one
|
||||
* that do wrapping. Our base surface will have the clip set, but
|
||||
* our target's surface will not.
|
||||
*
|
||||
* 2. We're here in our backend's set_clip_region function, and we
|
||||
* want to call into our target surface's set_clip_region.
|
||||
* Generally, we would do this by calling an equivalent
|
||||
* _cairo_surface function, but _cairo_surface_set_clip_region
|
||||
* does not have the same signature/semantics, (it has the
|
||||
* clip_serial stuff as well).
|
||||
*
|
||||
* We kludge around each of these by manually copying the clip
|
||||
* object from our base surface into the target's base surface
|
||||
* (yuck!) and by reaching directly into the image surface's
|
||||
* set_clip_region instead of calling into the generic
|
||||
* _cairo_surface_set_clip_region (double yuck!).
|
||||
*/
|
||||
|
||||
surface->target->clip = surface->base.clip;
|
||||
|
||||
return _cairo_image_surface_set_clip_region (surface->target, region);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_test_paginated_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_t *rectangle)
|
||||
{
|
||||
test_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
return _cairo_surface_get_extents (surface->target, rectangle);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_test_paginated_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source)
|
||||
{
|
||||
test_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return _cairo_surface_paint (surface->target, op, source);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_test_paginated_surface_mask (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
cairo_pattern_t *mask)
|
||||
{
|
||||
test_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return _cairo_surface_mask (surface->target, op, source, mask);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_test_paginated_surface_stroke (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
test_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return _cairo_surface_stroke (surface->target, op, source,
|
||||
path, style,
|
||||
ctm, ctm_inverse,
|
||||
tolerance, antialias);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_test_paginated_surface_fill (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
test_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return _cairo_surface_fill (surface->target, op, source,
|
||||
path, fill_rule,
|
||||
tolerance, antialias);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_test_paginated_surface_show_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
test_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return _cairo_surface_show_glyphs (surface->target, op, source,
|
||||
glyphs, num_glyphs, scaled_font);
|
||||
}
|
||||
|
||||
static void
|
||||
_test_paginated_surface_set_paginated_mode (void *abstract_surface,
|
||||
cairo_paginated_mode_t mode)
|
||||
{
|
||||
test_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
surface->paginated_mode = mode;
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t test_paginated_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
|
||||
|
||||
/* Since we are a paginated user, we get to regard most of the
|
||||
* surface backend interface as historical cruft and ignore it. */
|
||||
|
||||
NULL, /* create_similar */
|
||||
NULL, /* finish */
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
NULL, /* acquire_dest_image */
|
||||
NULL, /* release_dest_image */
|
||||
NULL, /* clone_similar */
|
||||
NULL, /* composite */
|
||||
NULL, /* fill_rectangles */
|
||||
NULL, /* composite_trapezoids */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
_test_paginated_surface_set_clip_region,
|
||||
NULL, /* intersect_clip_path */
|
||||
_test_paginated_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
NULL, /* flush */
|
||||
NULL, /* mark_dirty_rectangle */
|
||||
NULL, /* scaled_font_fini */
|
||||
NULL, /* scaled_glyph_fini */
|
||||
|
||||
/* Here is the more "modern" section of the surface backend
|
||||
* interface which is mostly just drawing functions */
|
||||
|
||||
_test_paginated_surface_paint,
|
||||
_test_paginated_surface_mask,
|
||||
_test_paginated_surface_stroke,
|
||||
_test_paginated_surface_fill,
|
||||
_test_paginated_surface_show_glyphs,
|
||||
NULL /* snapshot */
|
||||
};
|
||||
|
||||
static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend = {
|
||||
NULL, /* start_page */
|
||||
_test_paginated_surface_set_paginated_mode
|
||||
};
|
||||
|
|
|
|||
4
test/.gitignore
vendored
|
|
@ -19,11 +19,13 @@ create-from-png
|
|||
create-from-png-stream
|
||||
dash-caps-joins
|
||||
dash-offset-negative
|
||||
dash-zero-length
|
||||
extend-reflect
|
||||
fill-and-stroke
|
||||
fill-rule
|
||||
filter-nearest-offset
|
||||
ft-font-create-for-ft-face
|
||||
font-face-get-type
|
||||
get-and-set
|
||||
gradient-alpha
|
||||
imagediff
|
||||
|
|
@ -44,6 +46,7 @@ operator-source
|
|||
paint
|
||||
paint-with-alpha
|
||||
path-data
|
||||
pattern-get-type
|
||||
pdf2png
|
||||
png-flatten
|
||||
svg2png
|
||||
|
|
@ -60,6 +63,7 @@ select-font-no-show-text
|
|||
self-copy
|
||||
self-intersecting
|
||||
set-source
|
||||
show-glyphs-many
|
||||
show-text-current-point
|
||||
source-clip
|
||||
source-surface-scale-paint
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# All test cases go here
|
||||
# Here are all the tests that are run unconditionally
|
||||
TESTS = \
|
||||
a8-mask \
|
||||
caps-joins \
|
||||
|
|
@ -16,10 +16,12 @@ create-from-png \
|
|||
create-from-png-stream \
|
||||
dash-caps-joins \
|
||||
dash-offset-negative \
|
||||
dash-zero-length \
|
||||
extend-reflect \
|
||||
fill-and-stroke \
|
||||
fill-rule \
|
||||
filter-nearest-offset \
|
||||
font-face-get-type \
|
||||
get-and-set \
|
||||
gradient-alpha \
|
||||
leaky-polygon \
|
||||
|
|
@ -36,6 +38,7 @@ operator-source \
|
|||
paint \
|
||||
paint-with-alpha \
|
||||
path-data \
|
||||
pattern-get-type \
|
||||
pixman-rotate \
|
||||
rectangle-rounding-error \
|
||||
scale-source-surface-paint \
|
||||
|
|
@ -62,6 +65,8 @@ unbounded-operator \
|
|||
user-data \
|
||||
rel-path
|
||||
|
||||
# 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
|
||||
endif
|
||||
|
|
@ -82,6 +87,23 @@ if CAIRO_HAS_MULTI_PAGE_SURFACES
|
|||
TESTS += multi-page
|
||||
endif
|
||||
|
||||
# XXX: Here are some existing tests that are currently disabled for
|
||||
# one reason or another.
|
||||
#
|
||||
# show-glyphs-many - this stress test was exercising a particular bug
|
||||
# in the xlib surface code (exceeding the X11 protocol request
|
||||
# limit) when rendering several thousand glyphs at once. The
|
||||
# original xlib-surface bug is fixed now, but the test continues
|
||||
# to stress some other aspects of the test suite. For example,
|
||||
# when doing text as paths, the resuilting PostScript file is one
|
||||
# giant path that ghostscript has a particularly hard time
|
||||
# with. I'm disabling this test for now, since I don't care about
|
||||
# that performance problem in ghostscript. (But, there is a
|
||||
# similar performance problem when using cairo to rasterize the
|
||||
# equivalen giant path---from an SBG files say---so this might be
|
||||
# a useful kind of test to bring back again for performance (not
|
||||
# correctness) testing.
|
||||
|
||||
# All tests which have a reference image go here.
|
||||
# I really don't like having to repeat this list. Anyone know a good
|
||||
# way to avoid it? Can I use a wildcard here?
|
||||
|
|
@ -120,6 +142,8 @@ dash-caps-joins-rgb24-ref.png \
|
|||
dash-offset-negative-ref.png \
|
||||
dash-offset-negative-rgb24-ref.png \
|
||||
dash-offset-negative-ps-rgb24-ref.png \
|
||||
dash-zero-length-ref.png \
|
||||
dash-zero-length-rgb24-ref.png \
|
||||
extend-reflect-ref.png \
|
||||
extend-reflect-rgb24-ref.png \
|
||||
fill-and-stroke-ref.png \
|
||||
|
|
@ -299,9 +323,11 @@ create_from_png_LDADD = $(LDADDS)
|
|||
create_from_png_stream_LDADD = $(LDADDS)
|
||||
dash_caps_joins_LDADD = $(LDADDS)
|
||||
dash_offset_negative_LDADD = $(LDADDS)
|
||||
dash_zero_length_LDADD = $(LDADDS)
|
||||
extend_reflect_LDADD = $(LDADDS)
|
||||
fill_and_stroke_LDADD = $(LDADDS)
|
||||
fill_rule_LDADD = $(LDADDS)
|
||||
font_face_get_type_LDADD = $(LDADDS)
|
||||
filter_nearest_offset_LDADD = $(LDADDS)
|
||||
ft_font_create_for_ft_face_LDADD = $(LDADDS)
|
||||
get_and_set_LDADD = $(LDADDS)
|
||||
|
|
@ -321,6 +347,7 @@ operator_source_LDADD = $(LDADDS)
|
|||
paint_LDADD = $(LDADDS)
|
||||
paint_with_alpha_LDADD = $(LDADDS)
|
||||
path_data_LDADD = $(LDADDS)
|
||||
pattern_get_type_LDADD = $(LDADDS)
|
||||
svg_surface_LDADD = $(LDADDS)
|
||||
svg_clip_LDADD = $(LDADDS)
|
||||
pixman_rotate_LDADD = $(LDADDS)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,21 @@
|
|||
#include "write-png.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* This is copied from cairoint.h. That makes it painful to keep in
|
||||
* sync, but the slim stuff makes cairoint.h "hard" to include when
|
||||
* not actually building the cairo library itself. Fortunately, since
|
||||
* we're checking all these values, we do have a safeguard for keeping
|
||||
* them in sync.
|
||||
*/
|
||||
typedef enum cairo_internal_surface_type {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
|
||||
} cairo_internal_surface_type_t;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define vsnprintf _vsnprintf
|
||||
#define access _access
|
||||
|
|
@ -163,11 +178,12 @@ typedef void
|
|||
typedef struct _cairo_test_target
|
||||
{
|
||||
const char *name;
|
||||
cairo_surface_type_t expected_type;
|
||||
cairo_content_t content;
|
||||
cairo_test_create_target_surface_t create_target_surface;
|
||||
cairo_test_write_to_png_t write_to_png;
|
||||
cairo_test_cleanup_target_t cleanup_target;
|
||||
void *closure;
|
||||
void *closure;
|
||||
} cairo_test_target_t;
|
||||
|
||||
static char *
|
||||
|
|
@ -1282,12 +1298,21 @@ cleanup_pdf (void *closure)
|
|||
#if CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE
|
||||
#include "cairo-svg.h"
|
||||
|
||||
static const char *svg_ignored_tests[] = {
|
||||
"operator-source",
|
||||
"operator-clear",
|
||||
"clip-operator",
|
||||
"unbounded-operator",
|
||||
NULL
|
||||
};
|
||||
|
||||
cairo_user_data_key_t svg_closure_key;
|
||||
|
||||
typedef struct _svg_target_closure
|
||||
{
|
||||
char *filename;
|
||||
int width, height;
|
||||
cairo_surface_t *target;
|
||||
} svg_target_closure_t;
|
||||
|
||||
static cairo_surface_t *
|
||||
|
|
@ -1297,22 +1322,41 @@ create_svg_surface (cairo_test_t *test,
|
|||
{
|
||||
int width = test->width;
|
||||
int height = test->height;
|
||||
int i;
|
||||
svg_target_closure_t *ptc;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
for (i = 0; svg_ignored_tests[i] != NULL; i++)
|
||||
if (strcmp (test->name, svg_ignored_tests[i]) == 0)
|
||||
return NULL;
|
||||
|
||||
*closure = ptc = xmalloc (sizeof (svg_target_closure_t));
|
||||
|
||||
ptc->width = width;
|
||||
ptc->height = height;
|
||||
|
||||
xasprintf (&ptc->filename, "%s-%s%s", test->name, "svg-argb32-out", ".svg");
|
||||
xasprintf (&ptc->filename, "%s-svg-%s-out.svg",
|
||||
test->name, _cairo_test_content_name (content));
|
||||
|
||||
surface = cairo_svg_surface_create (ptc->filename, width, height);
|
||||
if (cairo_surface_status (surface)) {
|
||||
free (ptc->filename);
|
||||
free (ptc);
|
||||
return NULL;
|
||||
}
|
||||
cairo_svg_surface_set_dpi (surface, 72., 72.);
|
||||
|
||||
if (content == CAIRO_CONTENT_COLOR) {
|
||||
ptc->target = surface;
|
||||
surface = cairo_surface_create_similar (ptc->target,
|
||||
CAIRO_CONTENT_COLOR,
|
||||
width, height);
|
||||
} else {
|
||||
ptc->target = NULL;
|
||||
}
|
||||
|
||||
cairo_surface_set_user_data (surface, &svg_closure_key, ptc, NULL);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
|
|
@ -1322,15 +1366,26 @@ svg_surface_write_to_png (cairo_surface_t *surface, const char *filename)
|
|||
svg_target_closure_t *ptc = cairo_surface_get_user_data (surface, &svg_closure_key);
|
||||
char command[4096];
|
||||
|
||||
cairo_surface_finish (surface);
|
||||
if (ptc->target) {
|
||||
cairo_t *cr;
|
||||
cr = cairo_create (ptc->target);
|
||||
cairo_set_source_surface (cr, surface, 0, 0);
|
||||
cairo_paint (cr);
|
||||
cairo_show_page (cr);
|
||||
cairo_destroy (cr);
|
||||
|
||||
cairo_surface_finish (surface);
|
||||
surface = ptc->target;
|
||||
}
|
||||
|
||||
cairo_surface_finish (surface);
|
||||
sprintf (command, "./svg2png %s %s",
|
||||
ptc->filename, filename);
|
||||
|
||||
if (system (command) != 0)
|
||||
return CAIRO_STATUS_WRITE_ERROR;
|
||||
|
||||
return CAIRO_STATUS_WRITE_ERROR;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1387,13 +1442,19 @@ cairo_test_for_target (cairo_test_t *test,
|
|||
goto UNWIND_STRINGS;
|
||||
}
|
||||
|
||||
if (cairo_surface_get_type (surface) != target->expected_type) {
|
||||
cairo_test_log ("Error: Created surface is of type %d (expected %d)\n",
|
||||
cairo_surface_get_type (surface), target->expected_type);
|
||||
ret = CAIRO_TEST_FAILURE;
|
||||
goto UNWIND_SURFACE;
|
||||
}
|
||||
|
||||
cr = cairo_create (surface);
|
||||
|
||||
/* Clear to transparent (or black) depending on whether the target
|
||||
* surface supports alpha. */
|
||||
cairo_save (cr);
|
||||
cairo_set_source_rgba (cr, 0, 0, 0, 0);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
|
||||
cairo_paint (cr);
|
||||
cairo_restore (cr);
|
||||
|
||||
|
|
@ -1418,6 +1479,7 @@ cairo_test_for_target (cairo_test_t *test,
|
|||
/* Skip image check for tests with no image (width,height == 0,0) */
|
||||
if (test->width != 0 && test->height != 0) {
|
||||
int pixels_changed;
|
||||
xunlink (png_name);
|
||||
(target->write_to_png) (surface, png_name);
|
||||
if (target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
|
||||
pixels_changed = image_diff_flattened (png_name, ref_name, diff_name);
|
||||
|
|
@ -1436,6 +1498,7 @@ cairo_test_for_target (cairo_test_t *test,
|
|||
|
||||
UNWIND_CAIRO:
|
||||
cairo_destroy (cr);
|
||||
UNWIND_SURFACE:
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
cairo_debug_reset_static_data ();
|
||||
|
|
@ -1461,102 +1524,134 @@ cairo_test_expecting (cairo_test_t *test, cairo_test_draw_function_t draw,
|
|||
cairo_test_target_t **targets_to_test;
|
||||
cairo_test_target_t targets[] =
|
||||
{
|
||||
{ "image", CAIRO_CONTENT_COLOR_ALPHA,
|
||||
{ "image", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR_ALPHA,
|
||||
create_image_surface, cairo_surface_write_to_png, NULL},
|
||||
{ "image", CAIRO_CONTENT_COLOR,
|
||||
{ "image", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR,
|
||||
create_image_surface, cairo_surface_write_to_png, NULL},
|
||||
#ifdef CAIRO_HAS_TEST_SURFACES
|
||||
{ "test-fallback", CAIRO_CONTENT_COLOR_ALPHA,
|
||||
{ "test-fallback", CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
create_test_fallback_surface, cairo_surface_write_to_png, NULL },
|
||||
{ "test-fallback", CAIRO_CONTENT_COLOR,
|
||||
{ "test-fallback", CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
|
||||
CAIRO_CONTENT_COLOR,
|
||||
create_test_fallback_surface, cairo_surface_write_to_png, NULL },
|
||||
{ "test-meta", CAIRO_CONTENT_COLOR_ALPHA,
|
||||
{ "test-meta", CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
create_test_meta_surface, cairo_surface_write_to_png, NULL },
|
||||
{ "test-meta", CAIRO_CONTENT_COLOR,
|
||||
{ "test-meta", CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
|
||||
CAIRO_CONTENT_COLOR,
|
||||
create_test_meta_surface, cairo_surface_write_to_png, NULL },
|
||||
{ "test-paginated", CAIRO_CONTENT_COLOR_ALPHA,
|
||||
{ "test-paginated", CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
create_test_paginated_surface,
|
||||
test_paginated_write_to_png,
|
||||
cleanup_test_paginated },
|
||||
{ "test-paginated", CAIRO_CONTENT_COLOR,
|
||||
{ "test-paginated", CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
|
||||
CAIRO_CONTENT_COLOR,
|
||||
create_test_paginated_surface,
|
||||
test_paginated_write_to_png,
|
||||
cleanup_test_paginated },
|
||||
#endif
|
||||
#ifdef CAIRO_HAS_GLITZ_SURFACE
|
||||
#if CAIRO_CAN_TEST_GLITZ_GLX_SURFACE
|
||||
{ "glitz-glx", CAIRO_CONTENT_COLOR_ALPHA,
|
||||
{ "glitz-glx", CAIRO_SURFACE_TYPE_GLITZ,CAIRO_CONTENT_COLOR_ALPHA,
|
||||
create_cairo_glitz_glx_surface, cairo_surface_write_to_png,
|
||||
cleanup_cairo_glitz_glx },
|
||||
{ "glitz-glx", CAIRO_CONTENT_COLOR,
|
||||
{ "glitz-glx", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR,
|
||||
create_cairo_glitz_glx_surface, cairo_surface_write_to_png,
|
||||
cleanup_cairo_glitz_glx },
|
||||
#endif
|
||||
#if CAIRO_CAN_TEST_GLITZ_AGL_SURFACE
|
||||
{ "glitz-agl", CAIRO_CONTENT_COLOR_ALPHA,
|
||||
{ "glitz-agl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA,
|
||||
create_cairo_glitz_agl_surface, cairo_surface_write_to_png,
|
||||
cleanup_cairo_glitz_agl },
|
||||
{ "glitz-agl", CAIRO_CONTENT_COLOR,
|
||||
{ "glitz-agl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR,
|
||||
create_cairo_glitz_agl_surface, cairo_surface_write_to_png,
|
||||
cleanup_cairo_glitz_agl },
|
||||
#endif
|
||||
#if CAIRO_CAN_TEST_GLITZ_WGL_SURFACE
|
||||
{ "glitz-wgl", CAIRO_CONTENT_COLOR_ALPHA,
|
||||
{ "glitz-wgl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA,
|
||||
create_cairo_glitz_wgl_surface, cairo_surface_write_to_png,
|
||||
cleanup_cairo_glitz_wgl },
|
||||
{ "glitz-wgl", CAIRO_CONTENT_COLOR,
|
||||
{ "glitz-wgl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR,
|
||||
create_cairo_glitz_wgl_surface, cairo_surface_write_to_png,
|
||||
cleanup_cairo_glitz_wgl },
|
||||
#endif
|
||||
#endif /* CAIRO_HAS_GLITZ_SURFACE */
|
||||
#if 0 && CAIRO_HAS_QUARTZ_SURFACE
|
||||
{ "quartz", CAIRO_CONTENT_COLOR,
|
||||
{ "quartz", CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_CONTENT_COLOR,
|
||||
create_quartz_surface, cairo_surface_write_to_png,
|
||||
cleanup_quartz },
|
||||
#endif
|
||||
#if CAIRO_HAS_WIN32_SURFACE
|
||||
{ "win32", CAIRO_CONTENT_COLOR,
|
||||
{ "win32", CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR,
|
||||
create_win32_surface, cairo_surface_write_to_png, cleanup_win32 },
|
||||
#endif
|
||||
#if CAIRO_HAS_XCB_SURFACE
|
||||
{ "xcb", CAIRO_CONTENT_COLOR_ALPHA,
|
||||
{ "xcb", CAIRO_SURFACE_TYPE_XCB, CAIRO_CONTENT_COLOR_ALPHA,
|
||||
create_xcb_surface, cairo_surface_write_to_png, cleanup_xcb},
|
||||
#endif
|
||||
#if CAIRO_HAS_XLIB_SURFACE
|
||||
{ "xlib", CAIRO_CONTENT_COLOR_ALPHA,
|
||||
{ "xlib", CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR_ALPHA,
|
||||
create_xlib_surface, cairo_surface_write_to_png, cleanup_xlib},
|
||||
{ "xlib", CAIRO_CONTENT_COLOR,
|
||||
{ "xlib", CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR,
|
||||
create_xlib_surface, cairo_surface_write_to_png, cleanup_xlib},
|
||||
#endif
|
||||
#if CAIRO_HAS_PS_SURFACE
|
||||
{ "ps", CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED,
|
||||
{ "ps", CAIRO_SURFACE_TYPE_PS,
|
||||
CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED,
|
||||
create_ps_surface, ps_surface_write_to_png, cleanup_ps },
|
||||
{ "ps", CAIRO_CONTENT_COLOR,
|
||||
|
||||
/* XXX: We expect type image here only due to a limitation in
|
||||
* the current PS/meta-surface code. A PS surface is
|
||||
* "naturally" COLOR_ALPHA, so the COLOR-only variant goes
|
||||
* through create_similar in create_ps_surface which results
|
||||
* in the similar surface being used as a source. We do not yet
|
||||
* have source support for PS/meta-surfaces, so the
|
||||
* create_similar path for all paginated surfaces currently
|
||||
* returns an image surface.*/
|
||||
{ "ps", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR,
|
||||
create_ps_surface, ps_surface_write_to_png, cleanup_ps },
|
||||
#endif
|
||||
#if CAIRO_HAS_PDF_SURFACE && CAIRO_CAN_TEST_PDF_SURFACE
|
||||
{ "pdf", CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED,
|
||||
{ "pdf", CAIRO_SURFACE_TYPE_PDF,
|
||||
CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED,
|
||||
create_pdf_surface, pdf_surface_write_to_png, cleanup_pdf },
|
||||
{ "pdf", CAIRO_CONTENT_COLOR,
|
||||
|
||||
/* XXX: We expect type image here only due to a limitation in
|
||||
* the current PDF/meta-surface code. A PDF surface is
|
||||
* "naturally" COLOR_ALPHA, so the COLOR-only variant goes
|
||||
* through create_similar in create_pdf_surface which results
|
||||
* in the similar surface being used as a source. We do not yet
|
||||
* have source support for PDF/meta-surfaces, so the
|
||||
* create_similar path for all paginated surfaces currently
|
||||
* returns an image surface.*/
|
||||
{ "pdf", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR,
|
||||
create_pdf_surface, pdf_surface_write_to_png, cleanup_pdf },
|
||||
#endif
|
||||
#if CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE
|
||||
{ "svg", CAIRO_CONTENT_COLOR_ALPHA,
|
||||
{ "svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA,
|
||||
create_svg_surface, svg_surface_write_to_png, cleanup_svg },
|
||||
|
||||
/* A SVG surface is COLOR_APLHA by default, and currently a create
|
||||
* similar with content != COLOR_ALPHA will return a nil surface.
|
||||
* So don't test COLOR for now. */
|
||||
{ "svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR,
|
||||
create_svg_surface, svg_surface_write_to_png, cleanup_svg },
|
||||
#endif
|
||||
#if CAIRO_HAS_BEOS_SURFACE
|
||||
{ "beos", CAIRO_CONTENT_COLOR,
|
||||
{ "beos", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR,
|
||||
create_beos_surface, cairo_surface_write_to_png, cleanup_beos},
|
||||
{ "beos_bitmap", CAIRO_CONTENT_COLOR,
|
||||
{ "beos_bitmap", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR,
|
||||
create_beos_bitmap_surface, cairo_surface_write_to_png, cleanup_beos_bitmap},
|
||||
{ "beos_bitmap", CAIRO_CONTENT_COLOR_ALPHA,
|
||||
{ "beos_bitmap", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR_ALPHA,
|
||||
create_beos_bitmap_surface, cairo_surface_write_to_png, cleanup_beos_bitmap},
|
||||
#endif
|
||||
|
||||
#if CAIRO_HAS_DIRECTFB_SURFACE
|
||||
{ "directfb", CAIRO_CONTENT_COLOR,
|
||||
{ "directfb", CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR,
|
||||
create_directfb_surface, cairo_surface_write_to_png, cleanup_directfb},
|
||||
{ "directfb_bitmap", CAIRO_CONTENT_COLOR_ALPHA,
|
||||
{ "directfb_bitmap", CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR_ALPHA,
|
||||
create_directfb_bitmap_surface, cairo_surface_write_to_png,cleanup_directfb},
|
||||
#endif
|
||||
};
|
||||
|
|
|
|||
BIN
test/caps-joins-ps-argb32-ref.png
Normal file
|
After Width: | Height: | Size: 995 B |
BIN
test/caps-sub-paths-ps-argb32-ref.png
Normal file
|
After Width: | Height: | Size: 170 B |
BIN
test/clip-fill-rule-ps-argb32-ref.png
Normal file
|
After Width: | Height: | Size: 280 B |
BIN
test/clip-nesting-ps-argb32-ref.png
Normal file
|
After Width: | Height: | Size: 488 B |
BIN
test/clip-twice-ps-argb32-ref.png
Normal file
|
After Width: | Height: | Size: 460 B |
BIN
test/dash-caps-joins-ps-argb32-ref.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.4 KiB |
BIN
test/dash-offset-negative-ps-argb32-ref.png
Normal file
|
After Width: | Height: | Size: 170 B |
BIN
test/dash-zero-length-ps-argb32-ref.png
Normal file
|
After Width: | Height: | Size: 214 B |
BIN
test/dash-zero-length-ref.png
Normal file
|
After Width: | Height: | Size: 235 B |
BIN
test/dash-zero-length-rgb24-ref.png
Normal file
|
After Width: | Height: | Size: 222 B |
88
test/dash-zero-length.c
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright © 2006 Jeff Muizelaar
|
||||
*
|
||||
* 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
|
||||
* Jeff Muizelaar. not be used in advertising or publicity pertaining to
|
||||
* distribution of the software without specific, written prior
|
||||
* permission. Jeff Muizelaar. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* JEFF MUIZELAAR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL JEFF MUIZELAAR BE LIABLE FOR ANY SPECIAL,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: Jeff Muizelaar <jeff@infidigm.net>
|
||||
*/
|
||||
|
||||
#include "cairo-test.h"
|
||||
|
||||
#define IMAGE_WIDTH 19
|
||||
#define IMAGE_HEIGHT 25
|
||||
|
||||
/* A test of the two extremes of dashing: a solid line
|
||||
* and an invisible one. Also test that capping works
|
||||
* on invisible lines.
|
||||
*/
|
||||
|
||||
cairo_test_t test = {
|
||||
"dash-zero-length",
|
||||
"Tests cairo_set_dash with zero length",
|
||||
IMAGE_WIDTH, IMAGE_HEIGHT
|
||||
};
|
||||
|
||||
static cairo_test_status_t
|
||||
draw (cairo_t *cr, int width, int height)
|
||||
{
|
||||
double solid_line[] = { 4, 0 };
|
||||
double invisible_line[] = { 0, 4 };
|
||||
double dotted_line[] = { 0, 6 };
|
||||
double rounded_line[] = { 2, 6 };
|
||||
|
||||
cairo_set_source_rgb (cr, 1, 0, 0);
|
||||
cairo_set_line_width (cr, 2);
|
||||
|
||||
/* draw a solid line */
|
||||
cairo_set_dash (cr, solid_line, 2, 0);
|
||||
cairo_move_to (cr, 1, 2);
|
||||
cairo_line_to (cr, 18, 2);
|
||||
cairo_stroke (cr);
|
||||
|
||||
/* draw an invisible line */
|
||||
cairo_set_dash (cr, invisible_line, 2, 0);
|
||||
cairo_move_to (cr, 1, 8);
|
||||
cairo_line_to (cr, 18, 8);
|
||||
cairo_stroke (cr);
|
||||
|
||||
/* draw a dotted line */
|
||||
cairo_set_line_width (cr, 5);
|
||||
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
|
||||
cairo_set_dash (cr, dotted_line, 2, 0);
|
||||
cairo_move_to (cr, 5, 13);
|
||||
cairo_line_to (cr, 18, 13);
|
||||
cairo_stroke (cr);
|
||||
|
||||
/* draw a rounded line */
|
||||
cairo_set_line_width (cr, 5);
|
||||
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
|
||||
cairo_set_dash (cr, rounded_line, 2, 2);
|
||||
cairo_move_to (cr, 5, 20);
|
||||
cairo_line_to (cr, 18, 20);
|
||||
cairo_stroke (cr);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
return cairo_test (&test, draw);
|
||||
}
|
||||
BIN
test/fill-and-stroke-ps-argb32-ref.png
Normal file
|
After Width: | Height: | Size: 243 B |
BIN
test/fill-rule-ps-argb32-ref.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
64
test/font-face-get-type.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright © 2006 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation, and that the name of
|
||||
* Red Hat, Inc. not be used in advertising or publicity pertaining to
|
||||
* distribution of the software without specific, written prior
|
||||
* permission. Red Hat, Inc. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include "cairo-test.h"
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
cairo_font_face_t *font_face;
|
||||
|
||||
cairo_test_init ("font-face-get-type");
|
||||
|
||||
cairo_test_log ("Creating cairo context and obtaining a font face\n");
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
|
||||
cr = cairo_create (surface);
|
||||
|
||||
cairo_select_font_face (cr, "Bitstream Vera Sans",
|
||||
CAIRO_FONT_SLANT_NORMAL,
|
||||
CAIRO_FONT_WEIGHT_NORMAL);
|
||||
|
||||
font_face = cairo_get_font_face (cr);
|
||||
|
||||
cairo_test_log ("Testing return value of cairo_font_face_get_type\n");
|
||||
|
||||
if (cairo_font_face_get_type (font_face) != CAIRO_FONT_TYPE_TOY) {
|
||||
cairo_test_log ("Unexpected value %d from cairo_font_face_get_type (expected %d)\n",
|
||||
cairo_font_face_get_type (font_face), CAIRO_FONT_TYPE_TOY);
|
||||
return CAIRO_TEST_FAILURE;
|
||||
}
|
||||
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -64,6 +64,13 @@ draw (cairo_t *cr, int width, int height)
|
|||
|
||||
font_face = cairo_ft_font_face_create_for_pattern (resolved);
|
||||
|
||||
if (cairo_font_face_get_type (font_face) != CAIRO_FONT_TYPE_FT) {
|
||||
cairo_test_log ("Unexpected value from cairo_font_face_get_type: %d (expected %d)\n",
|
||||
cairo_font_face_get_type (font_face), CAIRO_FONT_TYPE_FT);
|
||||
cairo_font_face_destroy (font_face);
|
||||
return CAIRO_TEST_FAILURE;
|
||||
}
|
||||
|
||||
cairo_matrix_init_identity (&font_matrix);
|
||||
|
||||
cairo_get_matrix (cr, &ctm);
|
||||
|
|
@ -82,6 +89,13 @@ draw (cairo_t *cr, int width, int height)
|
|||
FcPatternDestroy (pattern);
|
||||
FcPatternDestroy (resolved);
|
||||
|
||||
if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_FT) {
|
||||
cairo_test_log ("Unexpected value from cairo_scaled_font_get_type: %d (expected %d)\n",
|
||||
cairo_scaled_font_get_type (scaled_font), CAIRO_FONT_TYPE_FT);
|
||||
cairo_scaled_font_destroy (scaled_font);
|
||||
return CAIRO_TEST_FAILURE;
|
||||
}
|
||||
|
||||
if (!ft_face) {
|
||||
cairo_test_log ("Failed to get an ft_face with cairo_ft_scaled_font_lock_face\n");
|
||||
cairo_scaled_font_destroy (scaled_font);
|
||||
|
|
|
|||
BIN
test/leaky-polygon-ps-argb32-ref.png
Normal file
|
After Width: | Height: | Size: 233 B |
BIN
test/line-width-ps-argb32-ref.png
Normal file
|
After Width: | Height: | Size: 201 B |
|
|
@ -213,12 +213,10 @@ draw (cairo_t *cr, int width, int height)
|
|||
int x = i * (WIDTH + PAD) + PAD;
|
||||
int y = (ARRAY_SIZE (mask_funcs) * k + j) * (HEIGHT + PAD) + PAD;
|
||||
|
||||
/* Clear area we are going to be drawing onto */
|
||||
/* Clear intermediate surface we are going to be drawing onto */
|
||||
cairo_save (cr2);
|
||||
cairo_set_source_rgba (cr2, 0, 0, 0, 0); /* transparent */
|
||||
cairo_set_operator (cr2, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_rectangle (cr2, x, y, WIDTH, HEIGHT);
|
||||
cairo_fill (cr2);
|
||||
cairo_set_operator (cr2, CAIRO_OPERATOR_CLEAR);
|
||||
cairo_paint (cr2);
|
||||
cairo_restore (cr2);
|
||||
|
||||
/* draw */
|
||||
|
|
|
|||
BIN
test/path-data-ps-argb32-ref.png
Normal file
|
After Width: | Height: | Size: 322 B |
74
test/pattern-get-type.c
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright © 2006 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation, and that the name of
|
||||
* Red Hat, Inc. not be used in advertising or publicity pertaining to
|
||||
* distribution of the software without specific, written prior
|
||||
* permission. Red Hat, Inc. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include "cairo-test.h"
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_pattern_t *solid_rgb, *solid_rgba, *surface_pattern, *linear, *radial;
|
||||
|
||||
cairo_test_init ("pattern-get-type");
|
||||
|
||||
cairo_test_log ("Creating patterns of all types\n");
|
||||
|
||||
solid_rgb = cairo_pattern_create_rgb (0.0, 0.1, 0.2);
|
||||
solid_rgba = cairo_pattern_create_rgba (0.3, 0.4, 0.5, 0.6);
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
1, 1);
|
||||
surface_pattern = cairo_pattern_create_for_surface (surface);
|
||||
linear = cairo_pattern_create_linear (0.0, 0.0, 10.0, 10.0);
|
||||
radial = cairo_pattern_create_radial (10.0, 10.0, 0.1,
|
||||
10.0, 10.0, 1.0);
|
||||
|
||||
cairo_test_log ("Verifying return values of cairo_pattern_get_type\n");
|
||||
|
||||
if (cairo_pattern_get_type (solid_rgb) != CAIRO_PATTERN_TYPE_SOLID)
|
||||
return CAIRO_TEST_FAILURE;
|
||||
|
||||
if (cairo_pattern_get_type (solid_rgba) != CAIRO_PATTERN_TYPE_SOLID)
|
||||
return CAIRO_TEST_FAILURE;
|
||||
|
||||
if (cairo_pattern_get_type (surface_pattern) != CAIRO_PATTERN_TYPE_SURFACE)
|
||||
return CAIRO_TEST_FAILURE;
|
||||
|
||||
if (cairo_pattern_get_type (linear) != CAIRO_PATTERN_TYPE_LINEAR)
|
||||
return CAIRO_TEST_FAILURE;
|
||||
|
||||
if (cairo_pattern_get_type (radial) != CAIRO_PATTERN_TYPE_RADIAL)
|
||||
return CAIRO_TEST_FAILURE;
|
||||
|
||||
cairo_test_log ("Cleaning up\n");
|
||||
|
||||
cairo_pattern_destroy (solid_rgb);
|
||||
cairo_pattern_destroy (solid_rgba);
|
||||
cairo_pattern_destroy (surface_pattern);
|
||||
cairo_surface_destroy (surface);
|
||||
cairo_pattern_destroy (linear);
|
||||
cairo_pattern_destroy (radial);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
}
|
||||
BIN
test/rectangle-rounding-error-ps-argb32-ref.png
Normal file
|
After Width: | Height: | Size: 258 B |
BIN
test/show-glyphs-many-ref.png
Normal file
|
After Width: | Height: | Size: 118 B |
BIN
test/show-glyphs-many-rgb24-ref.png
Normal file
|
After Width: | Height: | Size: 115 B |
127
test/show-glyphs-many.c
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Copyright © 2006 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation, and that the name of
|
||||
* Red Hat, Inc. not be used in advertising or publicity pertaining to
|
||||
* distribution of the software without specific, written prior
|
||||
* permission. Red Hat, Inc. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include "cairo-test.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Bug history
|
||||
*
|
||||
* 2006-01-07 Jon Hellan <hellan@acm.org>
|
||||
*
|
||||
* Jon opened the following bug report:
|
||||
*
|
||||
* _XError from XRenderCompositeText8
|
||||
* https://bugs.freedesktop.org/show_bug.cgi?id=5528
|
||||
*
|
||||
* 2006-03-02 Carl Worth <cworth@cworth.org>
|
||||
*
|
||||
* I wrote this test case to demonstrate the bug.
|
||||
*
|
||||
* Approach:
|
||||
*
|
||||
* Draw 65535 glyphs white-on-white all on top of each other.
|
||||
*
|
||||
* Rationale:
|
||||
*
|
||||
* The number 65535 comes from the original bug report.
|
||||
*
|
||||
* I would use cairo_show_text with a long string of 'x's say,
|
||||
* but then the surface would need to be enormous to contain
|
||||
* them. A smaller surface could be used, but I fear that at some
|
||||
* point the off-surface glyph drawing would be optimized away
|
||||
* and not exercise the bug.
|
||||
*
|
||||
* So, to keep the surface size under control, I use
|
||||
* cairo_show_glyphs which allows me to place the glyphs all on
|
||||
* top of each other. But, since cairo doesn't provide any
|
||||
* character-to-glyphs mapping, I can't get a reliable glyph
|
||||
* index (for character 'x' for example). So I just "guess" a
|
||||
* glyph index and use white-on-white drawing to ignore the
|
||||
* result. (I don't care what's drawn---I just want to ensure
|
||||
* that things don't crash.)
|
||||
*
|
||||
* Status: I replicated bug. The largest value of NUM_GLYPHS for
|
||||
* which I saw success is 21842.
|
||||
*/
|
||||
|
||||
#define TEXT_SIZE 12
|
||||
#define NUM_GLYPHS 65535
|
||||
|
||||
/* This is the index into the font for what glyph we'll draw. Since we
|
||||
* don't guarantee we'll get any particular font, we can't relibably
|
||||
* get any particular glyph. But we don't care what we draw anyway,
|
||||
* (see discussion of white-on-white drawing above). For what it's
|
||||
* worth, this appears to be giving me 'M' with Bitstream Vera
|
||||
* Sans Mono. */
|
||||
#define GLYPH_INDEX 48
|
||||
|
||||
cairo_test_t test = {
|
||||
"show-glyphs-many",
|
||||
"Test that cairo_show_glyps works when handed 'many' glyphs",
|
||||
9, 11
|
||||
};
|
||||
|
||||
static cairo_test_status_t
|
||||
draw (cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_glyph_t glyphs[NUM_GLYPHS];
|
||||
cairo_font_options_t *font_options;
|
||||
int i;
|
||||
|
||||
/* Initialize our giant array of glyphs. */
|
||||
for (i=0; i < NUM_GLYPHS; i++) {
|
||||
glyphs[i].index = GLYPH_INDEX;
|
||||
glyphs[i].x = 1.0;
|
||||
glyphs[i].y = height - 1;
|
||||
}
|
||||
|
||||
/* Paint white background. */
|
||||
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_select_font_face (cr, "Bitstream Vera Sans Mono",
|
||||
CAIRO_FONT_SLANT_NORMAL,
|
||||
CAIRO_FONT_WEIGHT_NORMAL);
|
||||
cairo_set_font_size (cr, TEXT_SIZE);
|
||||
|
||||
font_options = cairo_font_options_create ();
|
||||
|
||||
cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
|
||||
cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_GRAY);
|
||||
|
||||
cairo_set_font_options (cr, font_options);
|
||||
cairo_font_options_destroy (font_options);
|
||||
|
||||
cairo_show_glyphs (cr, glyphs, NUM_GLYPHS);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
return cairo_test (&test, draw);
|
||||
}
|
||||
BIN
test/show-text-current-point-ps-argb32-ref.png
Normal file
|
After Width: | Height: | Size: 638 B |