Bug 739096 - Update cairo to commit 277a1daec80cb6cf7bfb0e200cf78e7842cb2f82 (release 1.17.4 + post-release fixes on trunk) from https://gitlab.freedesktop.org/cairo/cairo/-/tree/master. r=jrmuizel

Differential Revision: https://phabricator.services.mozilla.com/D112558
This commit is contained in:
Jonathan Kew 2021-04-28 18:06:38 +00:00
Родитель 93c9a68ac1
Коммит 8cafeeb79e
369 изменённых файлов: 147260 добавлений и 46188 удалений

Просмотреть файл

@ -4,62 +4,75 @@ Shawn T. Amundson <amundson@gtk.org> Build fix
Olivier Andrieu <oliv__a@users.sourceforge.net> PNG backend
Peter Dennis Bartok <peter@novonyx.com> Bug fix for clipping
Dave Beckett <dajobe@debian.org> Build fixes, Debian packaging
Kai-Uwe Behrmann <ku.b@gmx.de> SVG bug fixes
Christian Biesinger <cbiesinger@web.de> BeOS backend
Billy Biggs <vektor@dumbterm.net> Pixman code merge. Optimization. Fixes for subtle rendering bugs.
Hans Breuer <hans@breuer.org> win32 bug fixes, build fixes, and improvements
Brian Cameron <brian.cameron@sun.com> Flag bug in Sun's X server
Carlos Garcia Campos <carlosgc@gnome.org> libspectre integration into the test-suite
Andrea Canciani <ranma42@gmail.com> Bugs, quartz backend improvements and type 6/7 patterns.
Damien Carbery <damien.carbery@sun.com> Build fixes
Andrew Chant <andrew.chant@utoronto.ca> Adding const where needed
Steve Chaplin <stevech1097@yahoo.com.au> Bug fixes for PNG reading
Tomasz Cholewo <cholewo@ieee-cis.org> Bug fixes
Manu Cornet <manu@manucornet.net> SVG build fix
Frederic Crozat <fcrozat@mandriva.com> Fix test suite for OPD platforms (IA64 or PPC64)
Julien Danjou <julien@danjou.info> XCB fixes
Radek Doulík <rodo@novell.com> Bug report and test case
John Ehresman <jpe@wingide.com> Build fixes for win32
John Ellson <ellson@research.att.com> First font/glyph extents functions
Michael Emmel <mike.emmel@gmail.com> DirectFB backend
Miklós Erdélyi <erdelyim@gmail.com> Fix typo leading to a crash
Behdad Esfahbod <behdad@behdad.org> Huge piles of bug fixes, improvements, and general maintenance
Gilles Espinasse <g.esp@free.fr> Font related fixes
Larry Ewing <lewing@novell.com> Test case for group-clip
Brian Ewins <Brian.Ewins@gmail.com> ATSUI maintenance (first success at making it really work)
Bertram Felgenhauer <int-e@gmx.de> Fixes for subtle arithmetic errors
Bdale Garbee <bdale@gag.com> Provided essential support for cairo achitecture sessions
Damian Frank <damian.frank@gmail.com> Build system improvements for win32
Bdale Garbee <bdale@gag.com> Provided essential support for cairo architecture sessions
Jens Granseuer <jensgr@gmx.net> Fixes to generate proper compiler flags
Laxmi Harikumar <laxmi.harikumar@digital.com> Build fix
J. Ali Harlow <ali@avrc.city.ac.uk> win32 backend updates
Bryce Harrington <bryce@osg.samsung.com> Test cases, bug/typo fixes
Mathias Hasselmann <mathias.hasselmann@gmx.de> Significant reduction of calls to malloc
Richard Henderson <rth@twiddle.net> "slim" macros for better shared libraries
James Henstridge <james@daa.com.au> Build fixes related to freetype
Graydon Hoare <graydon@redhat.com> Support for non-render X server, first real text support
Thomas Hunger <info@teh-web.de> Initial version of cairo_in_stroke/fill
Thomas Jaeger <ThJaeger@gmail.com> Extended repeat modes for X
Björn Lindqvist <bjourne@gmail.com> Performance test cases
Kristian Høgsberg <krh@redhat.com> PDF backend, PS backend with meta-surfaces
Amaury Jacquot <sxpert@esitcom.org> Documentation review, appplication testing
Amaury Jacquot <sxpert@esitcom.org> Documentation review, application testing
Adrian Johnson <ajohnson@redneon.com> PDF backend improvement
Michael Johnson <ahze@ahze.net> Bug fix for pre-C99 compilers
Jonathon Jongsma <jonathon.jongsma@gmail.com> Fix documentation typos
Øyvind Kolås <pippin@freedesktop.org> Bug fixes. Better default values.
Øyvind Kolås <pippin@freedesktop.org> OpenVG backend, Bug fixes. Better default values.
Martin Kretzschmar <martink@gnome.org> Arithmetic fix for 64-bit architectures
Mathieu Lacage <Mathieu.Lacage@sophia.inria.fr> several bug/typo fixes
Dominic Lachowicz <domlachowicz@gmail.com> PDF conformance fix, fix image surface to zero out contents
Alexander Larsson <alexl@redhat.com> Profiling and performance fixes.
Sylvestre Ledru <sylvestre@mozilla.com> Static analysis fixes.
Tor Lillqvist <tml@novell.com> win32 build fixes, build scripts
Jinghua Luo <sunmoon1997@gmail.com> Add bitmap glyph transformation, many freetype and glitz fixes
Luke-Jr <luke-jr@utopios.org> Build fix for cross-compiling
Kjartan Maraas <kmaraas@gnome.org> Several fixes for sparse, lots of debug help for multi-thread bugs
Nis Martensen <nis.martensen@web.de> Bug fix for sub paths
Jordi Mas <jordi@ximian.com> Bug fix for cairo_show_text
Nicholas Miell <nmiell@gmail.com> Fixes for linking bugs on AMD64
Eugeniy Meshcheryakov <eugen@debian.org> PS/PDF font subsetting improvements
Zakharov Mikhail <zmey20000@yahoo.com> Build fix for HP-UX
Christopher (Monty) Montgomery <xiphmont@gmail.com> Performnace fix (subimage_copy), multi-thread testing
Christopher (Monty) Montgomery <xiphmont@gmail.com> Performance fix (subimage_copy), multi-thread testing
Tim Mooney <enchanter@users.sourceforge.net> Fix test suite to compile with Solaris compiler
Jeff Muizelaar <jeff@infidigm.net> Patient, painful, pixman code merge. Many fixes for intricacies of dashing.
Yevgen Muntyan <muntyan@tamu.edu> win32 build fix
Ravi Nanjundappa <nravi.n@samsung.com> Static analysis fixes, test cases, skia backend update/fixes
Declan Naughton <piratepenguin@gmail.com> Fix documentation typos
Peter Nilsson <c99pnn@cs.umu.se> Glitz backend
Henning Noren <henning.noren.402@student.lu.se> Fix memory leak
Geoff Norton <gnorton@customerdna.com> Build fixes
Robert O'Callahan <rocallahan@novell.com> Const-correctness fixes, several new API functions for completeness (and to help mozilla)
Ian Osgood <iano@quirkster.com> XCB backend maintenance
Benjamin Otte <in7y118@public.uni-hamburg.de> Refinements to cairo/perf timing
Benjamin Otte <otte@gnome.org> Refinements to cairo/perf timing, OpenGL backend fixups, random fixes
Mike Owens <etc@filespanker.com> Bug fixes
Emmanuel Pacaud <emmanuel.pacaud@lapp.in2p3.fr> SVG backend
Keith Packard <keithp@keithp.com> Original concept, polygon tessellation, dashing, font metrics rewrite
@ -73,14 +86,17 @@ Calum Robinson <calumr@mac.com> Quartz backend
Pavel Roskin <proski@gnu.org> Several cleanups to eliminate warnings
Tim Rowley <tim.rowley@gmail.com> Quartz/ATSUI fixes, X server workarounds, win32 glyph path support, test case to expose gradient regression
Soeren Sandmann <sandmann@daimi.au.dk> Lots of MMX love for pixman compositing
Uli Schlachter <psychon@znc.in> Some more XCB fixes
Torsten Schönfeld <kaffeetisch@gmx.de> Build fixes
Jamey Sharp <jamey@minilop.net> Surface/font backend virtualization, XCB backend
Jason Dorje Short <jdorje@users.sf.net> Build fixes and bug fixes
Jeff Smith <whydoubt@yahoo.com> Fixes for intricacies of stroking code
Travis Spencer <tspencer@cs.pdx.edu> XCB backend fix
Bill Spitzak <spitzak@d2.com> Build fix to find Xrender.h without xrender.pc
Bill Spitzak <spitzak@d2.com> Build fix to find Xrender.h without xrender.pc, downscaling support
Zhe Su <james.su@gmail.com> Add support for fontconfig's embeddedbitmap option
Owen Taylor <otaylor@redhat.com> Font rewrite, documentation, win32 backend
Pierre Tardy <tardyp@gmail.com> EGL support and testing, OpenVG backend
Karl Tomlinson <karlt+@karlt.net> Optimisation and obscure bug fixes (mozilla)
Alp Toker <alp@atoker.com> Fix several code/comment typos
Malcolm Tredinnick <malcolm@commsecure.com.au> Documentation fixes
David Turner <david@freetype.org> Optimize gradient calculations
@ -89,7 +105,7 @@ Sasha Vasko <sasha@aftercode.net> Build fix to compile without xlib backend
Vladimir Vukicevic <vladimir@pobox.com> Quartz backend rewrite, win32/quartz maintenance
Jonathan Watt <jwatt@jwatt.org> win32 fixes
Peter Weilbacher <pmw@avila.aip.de> OS/2 backend
Dan Williams <dcbw@redhat.com> Implemnt MMX function to help OLPC
Dan Williams <dcbw@redhat.com> Implement MMX function to help OLPC
Chris Wilson <chris@chris-wilson.co.uk> Large-scale robustness improvements, (warn_unsed_result and malloc failure injection)
Carl Worth <cworth@isi.edu> Original library, support for paths, images
Richard D. Worth <richard@theworths.org> Build fixes for cygwin

Просмотреть файл

@ -1,6 +1,6 @@
Cairo is free software.
Every source file in the implementation of cairo is available to be
Every source file in the implementation[*] of cairo is available to be
redistributed and/or modified under the terms of either the GNU Lesser
General Public License (LGPL) version 2.1 or the Mozilla Public
License (MPL) version 1.1. Some files are available under more
@ -13,5 +13,21 @@ conditions of either license:
COPYING-LGPL-2.1
COPYING-MPL-1.1
Please see each file in the implementation for Copyright and licensing
information.
Please see each file in the implementation for copyright and licensing
information, (in the opening comment of each file).
[*] The implementation of cairo is contained entirely within the "src"
directory of the cairo source distribution. There are other components
of the cairo source distribution (such as the "test", "util", and "perf")
that are auxiliary to the library itself. None of the source code in these
directories contributes to a build of the cairo library itself, (libcairo.so
or cairo.dll or similar).
These auxiliary components are also free software, but may be under
different license terms than cairo itself. For example, most of the
test cases in the perf and test directories are made available under
an MIT license to simplify any use of this code for reference purposes
in using cairo itself. Other files might be available under the GNU
General Public License (GPL), for example. Again, please see the COPYING
file under each directory and the opening comment of each file for copyright
and licensing information.

Просмотреть файл

@ -3,7 +3,7 @@
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@ -490,7 +490,7 @@ notice is found.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
Also add information on how to contact you by electronic and paper mail.

Просмотреть файл

@ -66,34 +66,33 @@ More detailed build instructions
(NOTE: On Mac OS X, at least, use DYLD_LIBRARY_PATH in place
of LD_LIBRARY_PATH above.)
--enable-quartz
--enable-atsui
--enable-xcb
--enable-glitz
--enable-beos
--enable-os2
--enable-directfb
--enable-XYZ
--enable-XYZ=yes
--enable-XYZ=auto
--enable-XYZ=no
--disable-XYZ
Some of cairo's backends are marked as experimental and will
not be built by default. If you would like to build and
experiment with these backends, you will need to pass one of
the above options to the configure script. You may need to
have certain libraries installed first as discussed in the
dependencies section of the README file.
Cairo's various font and surface backends and other features can be
enabled or disabled at configure time. Features can be divided into
three categories based on their default state:
--disable-xlib
--disable-win32
--disable-png
--disable-freetype
--disable-ps
--disable-pdf
--disable-svg
* default=yes: These are the recommended features like PNG functions
and PS/PDF/SVG backends. It is highly recommended to not disable
these features but if that's really what one wants, they can be
disabled using --disable-XYZ.
Cairo's configure script detects the libraries needed to build
each stable backend, and when it finds them, enables each
backend. If you would like to override this detection and
disable a backend, (even when it would be possible to build
it), use one of the options above to disable the backend.
* default=auto: These are the "native" features, that is, they are
platform specific, like the Xlib surface backend. You probably
want one or two of these. They will be automatically enabled if
all their required facilities are available. Or you can use
--enable-XYZ or --disable-XYZ to make your desire clear, and then
cairo errs during configure if your intention cannot be followed.
* default=no: These are the "experimental" features, and hence by
default off. Use --enable-XYZ to enable them.
The list of all features and their default state can be seen in the
output of ./configure --help.
2) Compile the package:
@ -141,11 +140,11 @@ itself), then you're in the right place and should read on.
However, if you don't need such a bleeding-edge version of cairo, then
you might prefer to start by building the latest stable cairo release:
http://cairographics.org/releases
https://cairographics.org/releases
or perhaps the latest (unstable) development snapshot:
http://cairographics.org/snapshots
https://cairographics.org/snapshots
There you'll find nicely packaged tar files that include a configure
script so you can go back the the simpler instructions above.
@ -156,27 +155,25 @@ contributions to cairo. Since you're not using a packaged tar file,
you're going to need some additional tools beyond just a C compiler in
order to compile cairo. Specifically, you need the following utilities:
automake (1.8 or newer)
automake
autoconf
libtool
autoheader
aclocal
libtoolize
pkg-config [at least version 0.16]
gtk-doc (recommended)
Hopefully your platform of choice has packages readily available so
that you can easily install things with your system's package
management tool, (such as "apt-get install automake" on Debian or "yum
install automake" on Fedora, etc.). Note that Mac OS X ships with it's
own utility called libtool which is not what you want, (the one you do
want goes by the name of glibtool).
install automake" on Fedora, etc.). Note that Mac OS X ships with
glibtoolize instead of libtoolize.
Once you have all of those packages installed, the next step is to run
the autogen.sh script. That can be as simple as:
./autogen.sh
Or, if you're using Mac OS X, you'll have to let it know to use
glibtool by instead doing:
LIBTOOLIZE=glibtoolize ./autogen.sh
But before you run that command, note that the autogen.sh script
accepts all the same arguments as the configure script, (and in fact,
will generate the configure script and run it with the arguments you

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,13 +1,13 @@
Cairo - Multi-platform 2D graphics library
http://cairographics.org
https://cairographics.org
What is cairo
=============
Cairo is a 2D graphics library with support for multiple output
devices. Currently supported output targets include the X Window
System, win32, and image buffers, as well as PDF, PostScript, and SVG
file output. Experimental backends include OpenGL (through glitz),
Quartz, XCB, BeOS, OS/2, and DirectFB.
System (via both Xlib and XCB), quartz, win32, and image buffers,
as well as PDF, PostScript, and SVG file output. Experimental backends
include OpenGL, BeOS, OS/2, and DirectFB.
Cairo is designed to produce consistent output on all output media
while taking advantage of display hardware acceleration when available
@ -35,25 +35,25 @@ Where to get more information about cairo
=========================================
The primary source of information about cairo is:
http://cairographics.org/
https://cairographics.org/
The latest versions of cairo can always be found at:
http://cairographics.org/download
https://cairographics.org/download
Documentation on using cairo and frequently-asked questions:
http://cairographics.org/documentation
http://cairographics.org/FAQ
https://cairographics.org/documentation
https://cairographics.org/FAQ
Mailing lists for contacting cairo users and developers:
http://cairographics.org/lists
https://cairographics.org/lists
Roadmap and unscheduled things to do, (please feel free to help out):
http://cairographics.org/roadmap
http://cairographics.org/todo
https://cairographics.org/roadmap
https://cairographics.org/todo
Dependencies
============
@ -67,29 +67,31 @@ backends. Further, the supported backends can be divided into the
"platform" backends which depend on some underlying platform-specific
system, (such as the X Window System or some other window system).
As an example, for a standard Linux build, (with image, png, pdf,
PostScript, svg, and xlib surface backends, and the freetype font
backend), the following sample commands will install necessary
dependencies:
As an example, for a standard Linux build similar to what's shipped by
your distro, (with image, png, pdf, PostScript, svg, and xlib surface
backends, and the freetype font backend), the following sample commands
will install necessary dependencies:
Debian (and similar):
apt-get install libpng12-dev libz-dev libxrender-dev libfontconfig1-dev
apt-get build-dep cairo
Fedora (and similar):
yum install libpng-devel zlib-devel libXrender-devel fontconfig-devel
(Those commands intentionally don't install pixman from a distribution
package since if you're manually compiling cairo, then you likely want
to grab pixman from the same place at the same time and compile it as
well.)
Technically you probably don't need pixman from the distribution since
if you're manually compiling Cairo you probably want an updated pixman
as well. However, if you follow the default settings and install pixman
to /usr/local, your Cairo build should properly use it in preference to
the system pixman.
Supported, "standard" surface backends
------------------------------------
image backend (required)
------------------------
pixman >= 0.10.0 http://cairographics.org/releases
pixman >= 0.30.0 https://cairographics.org/releases
png support (can be left out if desired, but many
----------- applications expect it to be present)
@ -111,20 +113,24 @@ Supported, "platform" surface backends
-----------------------------------
xlib backend
------------
X11 http://freedesktop.org/Software/xlibs
X11 https://freedesktop.org/Software/xlibs
xlib-xrender backend
--------------------
Xrender >= 0.6 http://freedesktop.org/Software/xlibs
Xrender >= 0.6 https://freedesktop.org/Software/xlibs
quartz backend
--------------
MacOS X >= 10.4 with Xcode >= 2.4
MacOS X >= 10.4 with Xcode >= 2.5
win32 backend
-------------
Microsoft Windows 2000 or newer[*].
xcb backend
-----------
XCB https://xcb.freedesktop.org
Font backends (required to have at least one)
---------------------------------------------
freetype font backend
@ -163,14 +169,6 @@ Font backends (required to have at least one)
Experimental surface backends
-----------------------------
glitz
-------------
glitz >= 0.4.4 http://freedesktop.org/Software/glitz
xcb backend
-----------
XCB http://xcb.freedesktop.org
beos backend
------------
No dependencies in itself other than an installed BeOS system, but cairo
@ -183,10 +181,12 @@ Experimental surface backends
packages and developer dependencies are available at Netlabs:
ftp://ftp.netlabs.org/pub/cairo
Compiling
=========
See the INSTALL document for build instructions.
History
=======
Cairo was originally developed by Carl Worth <cworth@cworth.org> and

Просмотреть файл

@ -0,0 +1,66 @@
Building Cairo on Windows
=========================
There are two primary ways to build Cairo on Windows. You can use a
UNIX emulation based setup, such as Cygwin or MSYS, with the
conventional configure script shipped with Cairo releases. In this
configuration, you will build with GCC and (implicitly) libtool. In
the Cygwin case you end up with a DLL that depends on Cygwin and
should be used only from Cygwin applications. In the MSYS case you end
up with a "normal" Win32 DLL that can be used either from GCC- or
Microsoft Visual C++-compiled code. In theory, this technique is no
different than the ordinary build process for the Cairo library. In
practise there are lots of small details that can go wrong.
The second way is to use a GNU-compatible make, but build using
Microsoft's Visual C++ compiler to produce native libraries. This is
the setup this README.win32 is written for. Also the DLL produced this
way is usable either from GCC- or MSVC-compiled code.
Tools required
==============
You will need GNU make, version 3.80 or later. Earlier versions or
other modern make implementations may work, but are not guaranteed to.
You will also need Microsoft Visual C++. Version 7 has been most
heavily tested, but other versions are likely to work fine.
Libraries required
==================
Cairo requires a compatible version of the pixman library. Full build
instructions are beyond the scope of this document; however, using the
same tools, it should be possible to build pixman simply by entering
the pixman/src directory and typing:
make -f Makefile.win32 CFG=release
Depending on your feature set, you may also need zlib and libpng.
Building
========
There are a few files that you will need to edit. First, you must
determine which features will be built. Edit
build/Makefile.win32.features and set the features as desired. Note
that most features have external dependencies; specifically,
CAIRO_HAS_PNG_FUNCTIONS requires libpng to be present, and
CAIRO_HAS_PS_SURFACE and CAIRO_HAS_PDF_SURFACE both require zlib.
To ensure that the compiler can find all dependencies, you may need to
edit build/Makefile.win32.common. In particular, ensure that
PIXMAN_CFLAGS contains a -I parameter pointing to the location of
your pixman header files and that PIXMAN_LIBS points to the actual
location of your pixman-1.lib file. You may also need to edit the
various occurrences of CAIRO_LIBS to point to other libraries
correctly. Note also that if you wish to link statically with zlib,
you should replace zdll.lib with zlib.lib.
Finally, from the top Cairo directory, type:
make -f Makefile.win32 CFG=release
If this command succeeds, you will end up with src/release/cairo.dll.
To successfully use Cairo from your own programs, you will probably
want to move this file to some central location. You will also
probably want to copy the Cairo header files. These should be placed
in a cairo subdirectory (for instance, c:/code/common/include/cairo).
The exact set to copy depends on your features and is reported to you
at the end of the build.

Просмотреть файл

@ -0,0 +1,35 @@
SPARSE = sparse
sparse:
@echo Checking enabled sources with sparse checker
@status=true; for f in $(enabled_cairo_sources) $(enabled_cairo_cxx_sources); do \
echo $(SPARSE) $(PREPROCESS_ARGS) $(srcdir)/$$f; \
$(SPARSE) $(PREPROCESS_ARGS) $(srcdir)/$$f || status=false; \
done; $$status
SPLINT = splint -badflag
splint:
@echo Checking enabled sources with splint checker
@status=true; for f in $(enabled_cairo_sources) $(enabled_cairo_cxx_sources); do \
echo $(SPLINT) $(PREPROCESS_ARGS) $(srcdir)/$$f; \
$(SPLINT) $(PREPROCESS_ARGS) $(srcdir)/$$f || status=false; \
done; $$status
UNO = uno
uno:
@echo Checking enabled sources with uno checker
cd $(srcdir); $(UNO) $(PREPROCESS_ARGS) -DHAVE_CONFIG_H -U__GNUC__ $(enabled_cairo_sources)
headers-standalone: $(enabled_cairo_headers) $(enabled_cairo_private)
@echo Checking that enabled public/private headers can be compiled standalone
@status=true; for f in $(enabled_cairo_headers) $(enabled_cairo_private); do \
echo " CHECK $$f"; \
echo "#include \"$(srcdir)/$$f\"" > headers-standalone-tmp.c; \
echo "int main(int argc, char * argv[]) { return 0; }" >> headers-standalone-tmp.c; \
$(COMPILE) -o headers-standalone-tmp headers-standalone-tmp.c || status=false; \
$(RM) headers-standalone-tmp headers-standalone-tmp.c; \
done; $$status
@touch $@
CLEANFILES += headers-standalone
analysis: all headers-standalone sparse splint uno

Просмотреть файл

@ -0,0 +1,657 @@
# Generated by configure. Do not edit.
include $(top_srcdir)/src/Makefile.sources
supported_cairo_headers = $(cairo_headers)
unsupported_cairo_headers =
all_cairo_headers = $(cairo_headers)
all_cairo_private = $(cairo_private)
all_cairo_cxx_sources = $(cairo_cxx_sources)
all_cairo_sources = $(cairo_sources)
enabled_cairo_headers = $(cairo_headers)
enabled_cairo_private = $(cairo_private)
enabled_cairo_cxx_sources = $(cairo_cxx_sources)
enabled_cairo_sources = $(cairo_sources)
all_cairo_pkgconf = cairo.pc
enabled_cairo_pkgconf = cairo.pc
supported_cairo_headers += $(cairo_xlib_headers)
all_cairo_headers += $(cairo_xlib_headers)
all_cairo_private += $(cairo_xlib_private)
all_cairo_cxx_sources += $(cairo_xlib_cxx_sources)
all_cairo_sources += $(cairo_xlib_sources)
if CAIRO_HAS_XLIB_SURFACE
enabled_cairo_headers += $(cairo_xlib_headers)
enabled_cairo_private += $(cairo_xlib_private)
enabled_cairo_cxx_sources += $(cairo_xlib_cxx_sources)
enabled_cairo_sources += $(cairo_xlib_sources)
endif
all_cairo_pkgconf += cairo-xlib.pc
if CAIRO_HAS_XLIB_SURFACE
enabled_cairo_pkgconf += cairo-xlib.pc
endif
supported_cairo_headers += $(cairo_xlib_xrender_headers)
all_cairo_headers += $(cairo_xlib_xrender_headers)
all_cairo_private += $(cairo_xlib_xrender_private)
all_cairo_cxx_sources += $(cairo_xlib_xrender_cxx_sources)
all_cairo_sources += $(cairo_xlib_xrender_sources)
if CAIRO_HAS_XLIB_XRENDER_SURFACE
enabled_cairo_headers += $(cairo_xlib_xrender_headers)
enabled_cairo_private += $(cairo_xlib_xrender_private)
enabled_cairo_cxx_sources += $(cairo_xlib_xrender_cxx_sources)
enabled_cairo_sources += $(cairo_xlib_xrender_sources)
endif
all_cairo_pkgconf += cairo-xlib-xrender.pc
if CAIRO_HAS_XLIB_XRENDER_SURFACE
enabled_cairo_pkgconf += cairo-xlib-xrender.pc
endif
supported_cairo_headers += $(cairo_xcb_headers)
all_cairo_headers += $(cairo_xcb_headers)
all_cairo_private += $(cairo_xcb_private)
all_cairo_cxx_sources += $(cairo_xcb_cxx_sources)
all_cairo_sources += $(cairo_xcb_sources)
if CAIRO_HAS_XCB_SURFACE
enabled_cairo_headers += $(cairo_xcb_headers)
enabled_cairo_private += $(cairo_xcb_private)
enabled_cairo_cxx_sources += $(cairo_xcb_cxx_sources)
enabled_cairo_sources += $(cairo_xcb_sources)
endif
all_cairo_pkgconf += cairo-xcb.pc
if CAIRO_HAS_XCB_SURFACE
enabled_cairo_pkgconf += cairo-xcb.pc
endif
unsupported_cairo_headers += $(cairo_xlib_xcb_headers)
all_cairo_headers += $(cairo_xlib_xcb_headers)
all_cairo_private += $(cairo_xlib_xcb_private)
all_cairo_cxx_sources += $(cairo_xlib_xcb_cxx_sources)
all_cairo_sources += $(cairo_xlib_xcb_sources)
if CAIRO_HAS_XLIB_XCB_FUNCTIONS
enabled_cairo_headers += $(cairo_xlib_xcb_headers)
enabled_cairo_private += $(cairo_xlib_xcb_private)
enabled_cairo_cxx_sources += $(cairo_xlib_xcb_cxx_sources)
enabled_cairo_sources += $(cairo_xlib_xcb_sources)
endif
all_cairo_pkgconf += cairo-xlib-xcb.pc
if CAIRO_HAS_XLIB_XCB_FUNCTIONS
enabled_cairo_pkgconf += cairo-xlib-xcb.pc
endif
supported_cairo_headers += $(cairo_xcb_shm_headers)
all_cairo_headers += $(cairo_xcb_shm_headers)
all_cairo_private += $(cairo_xcb_shm_private)
all_cairo_cxx_sources += $(cairo_xcb_shm_cxx_sources)
all_cairo_sources += $(cairo_xcb_shm_sources)
if CAIRO_HAS_XCB_SHM_FUNCTIONS
enabled_cairo_headers += $(cairo_xcb_shm_headers)
enabled_cairo_private += $(cairo_xcb_shm_private)
enabled_cairo_cxx_sources += $(cairo_xcb_shm_cxx_sources)
enabled_cairo_sources += $(cairo_xcb_shm_sources)
endif
all_cairo_pkgconf += cairo-xcb-shm.pc
if CAIRO_HAS_XCB_SHM_FUNCTIONS
enabled_cairo_pkgconf += cairo-xcb-shm.pc
endif
unsupported_cairo_headers += $(cairo_qt_headers)
all_cairo_headers += $(cairo_qt_headers)
all_cairo_private += $(cairo_qt_private)
all_cairo_cxx_sources += $(cairo_qt_cxx_sources)
all_cairo_sources += $(cairo_qt_sources)
if CAIRO_HAS_QT_SURFACE
enabled_cairo_headers += $(cairo_qt_headers)
enabled_cairo_private += $(cairo_qt_private)
enabled_cairo_cxx_sources += $(cairo_qt_cxx_sources)
enabled_cairo_sources += $(cairo_qt_sources)
endif
all_cairo_pkgconf += cairo-qt.pc
if CAIRO_HAS_QT_SURFACE
enabled_cairo_pkgconf += cairo-qt.pc
endif
supported_cairo_headers += $(cairo_quartz_headers)
all_cairo_headers += $(cairo_quartz_headers)
all_cairo_private += $(cairo_quartz_private)
all_cairo_cxx_sources += $(cairo_quartz_cxx_sources)
all_cairo_sources += $(cairo_quartz_sources)
if CAIRO_HAS_QUARTZ_SURFACE
enabled_cairo_headers += $(cairo_quartz_headers)
enabled_cairo_private += $(cairo_quartz_private)
enabled_cairo_cxx_sources += $(cairo_quartz_cxx_sources)
enabled_cairo_sources += $(cairo_quartz_sources)
endif
all_cairo_pkgconf += cairo-quartz.pc
if CAIRO_HAS_QUARTZ_SURFACE
enabled_cairo_pkgconf += cairo-quartz.pc
endif
supported_cairo_headers += $(cairo_quartz_font_headers)
all_cairo_headers += $(cairo_quartz_font_headers)
all_cairo_private += $(cairo_quartz_font_private)
all_cairo_cxx_sources += $(cairo_quartz_font_cxx_sources)
all_cairo_sources += $(cairo_quartz_font_sources)
if CAIRO_HAS_QUARTZ_FONT
enabled_cairo_headers += $(cairo_quartz_font_headers)
enabled_cairo_private += $(cairo_quartz_font_private)
enabled_cairo_cxx_sources += $(cairo_quartz_font_cxx_sources)
enabled_cairo_sources += $(cairo_quartz_font_sources)
endif
all_cairo_pkgconf += cairo-quartz-font.pc
if CAIRO_HAS_QUARTZ_FONT
enabled_cairo_pkgconf += cairo-quartz-font.pc
endif
unsupported_cairo_headers += $(cairo_quartz_image_headers)
all_cairo_headers += $(cairo_quartz_image_headers)
all_cairo_private += $(cairo_quartz_image_private)
all_cairo_cxx_sources += $(cairo_quartz_image_cxx_sources)
all_cairo_sources += $(cairo_quartz_image_sources)
if CAIRO_HAS_QUARTZ_IMAGE_SURFACE
enabled_cairo_headers += $(cairo_quartz_image_headers)
enabled_cairo_private += $(cairo_quartz_image_private)
enabled_cairo_cxx_sources += $(cairo_quartz_image_cxx_sources)
enabled_cairo_sources += $(cairo_quartz_image_sources)
endif
all_cairo_pkgconf += cairo-quartz-image.pc
if CAIRO_HAS_QUARTZ_IMAGE_SURFACE
enabled_cairo_pkgconf += cairo-quartz-image.pc
endif
supported_cairo_headers += $(cairo_win32_headers)
all_cairo_headers += $(cairo_win32_headers)
all_cairo_private += $(cairo_win32_private)
all_cairo_cxx_sources += $(cairo_win32_cxx_sources)
all_cairo_sources += $(cairo_win32_sources)
if CAIRO_HAS_WIN32_SURFACE
enabled_cairo_headers += $(cairo_win32_headers)
enabled_cairo_private += $(cairo_win32_private)
enabled_cairo_cxx_sources += $(cairo_win32_cxx_sources)
enabled_cairo_sources += $(cairo_win32_sources)
endif
all_cairo_pkgconf += cairo-win32.pc
if CAIRO_HAS_WIN32_SURFACE
enabled_cairo_pkgconf += cairo-win32.pc
endif
supported_cairo_headers += $(cairo_win32_font_headers)
all_cairo_headers += $(cairo_win32_font_headers)
all_cairo_private += $(cairo_win32_font_private)
all_cairo_cxx_sources += $(cairo_win32_font_cxx_sources)
all_cairo_sources += $(cairo_win32_font_sources)
if CAIRO_HAS_WIN32_FONT
enabled_cairo_headers += $(cairo_win32_font_headers)
enabled_cairo_private += $(cairo_win32_font_private)
enabled_cairo_cxx_sources += $(cairo_win32_font_cxx_sources)
enabled_cairo_sources += $(cairo_win32_font_sources)
endif
all_cairo_pkgconf += cairo-win32-font.pc
if CAIRO_HAS_WIN32_FONT
enabled_cairo_pkgconf += cairo-win32-font.pc
endif
unsupported_cairo_headers += $(cairo_os2_headers)
all_cairo_headers += $(cairo_os2_headers)
all_cairo_private += $(cairo_os2_private)
all_cairo_cxx_sources += $(cairo_os2_cxx_sources)
all_cairo_sources += $(cairo_os2_sources)
if CAIRO_HAS_OS2_SURFACE
enabled_cairo_headers += $(cairo_os2_headers)
enabled_cairo_private += $(cairo_os2_private)
enabled_cairo_cxx_sources += $(cairo_os2_cxx_sources)
enabled_cairo_sources += $(cairo_os2_sources)
endif
all_cairo_pkgconf += cairo-os2.pc
if CAIRO_HAS_OS2_SURFACE
enabled_cairo_pkgconf += cairo-os2.pc
endif
unsupported_cairo_headers += $(cairo_beos_headers)
all_cairo_headers += $(cairo_beos_headers)
all_cairo_private += $(cairo_beos_private)
all_cairo_cxx_sources += $(cairo_beos_cxx_sources)
all_cairo_sources += $(cairo_beos_sources)
if CAIRO_HAS_BEOS_SURFACE
enabled_cairo_headers += $(cairo_beos_headers)
enabled_cairo_private += $(cairo_beos_private)
enabled_cairo_cxx_sources += $(cairo_beos_cxx_sources)
enabled_cairo_sources += $(cairo_beos_sources)
endif
all_cairo_pkgconf += cairo-beos.pc
if CAIRO_HAS_BEOS_SURFACE
enabled_cairo_pkgconf += cairo-beos.pc
endif
unsupported_cairo_headers += $(cairo_drm_headers)
all_cairo_headers += $(cairo_drm_headers)
all_cairo_private += $(cairo_drm_private)
all_cairo_cxx_sources += $(cairo_drm_cxx_sources)
all_cairo_sources += $(cairo_drm_sources)
if CAIRO_HAS_DRM_SURFACE
enabled_cairo_headers += $(cairo_drm_headers)
enabled_cairo_private += $(cairo_drm_private)
enabled_cairo_cxx_sources += $(cairo_drm_cxx_sources)
enabled_cairo_sources += $(cairo_drm_sources)
endif
all_cairo_pkgconf += cairo-drm.pc
if CAIRO_HAS_DRM_SURFACE
enabled_cairo_pkgconf += cairo-drm.pc
endif
unsupported_cairo_headers += $(cairo_gallium_headers)
all_cairo_headers += $(cairo_gallium_headers)
all_cairo_private += $(cairo_gallium_private)
all_cairo_cxx_sources += $(cairo_gallium_cxx_sources)
all_cairo_sources += $(cairo_gallium_sources)
if CAIRO_HAS_GALLIUM_SURFACE
enabled_cairo_headers += $(cairo_gallium_headers)
enabled_cairo_private += $(cairo_gallium_private)
enabled_cairo_cxx_sources += $(cairo_gallium_cxx_sources)
enabled_cairo_sources += $(cairo_gallium_sources)
endif
all_cairo_pkgconf += cairo-gallium.pc
if CAIRO_HAS_GALLIUM_SURFACE
enabled_cairo_pkgconf += cairo-gallium.pc
endif
supported_cairo_headers += $(cairo_png_headers)
all_cairo_headers += $(cairo_png_headers)
all_cairo_private += $(cairo_png_private)
all_cairo_cxx_sources += $(cairo_png_cxx_sources)
all_cairo_sources += $(cairo_png_sources)
if CAIRO_HAS_PNG_FUNCTIONS
enabled_cairo_headers += $(cairo_png_headers)
enabled_cairo_private += $(cairo_png_private)
enabled_cairo_cxx_sources += $(cairo_png_cxx_sources)
enabled_cairo_sources += $(cairo_png_sources)
endif
all_cairo_pkgconf += cairo-png.pc
if CAIRO_HAS_PNG_FUNCTIONS
enabled_cairo_pkgconf += cairo-png.pc
endif
unsupported_cairo_headers += $(cairo_gl_headers)
all_cairo_headers += $(cairo_gl_headers)
all_cairo_private += $(cairo_gl_private)
all_cairo_cxx_sources += $(cairo_gl_cxx_sources)
all_cairo_sources += $(cairo_gl_sources)
if CAIRO_HAS_GL_SURFACE
enabled_cairo_headers += $(cairo_gl_headers)
enabled_cairo_private += $(cairo_gl_private)
enabled_cairo_cxx_sources += $(cairo_gl_cxx_sources)
enabled_cairo_sources += $(cairo_gl_sources)
endif
all_cairo_pkgconf += cairo-gl.pc
if CAIRO_HAS_GL_SURFACE
enabled_cairo_pkgconf += cairo-gl.pc
endif
unsupported_cairo_headers += $(cairo_glesv2_headers)
all_cairo_headers += $(cairo_glesv2_headers)
all_cairo_private += $(cairo_glesv2_private)
all_cairo_cxx_sources += $(cairo_glesv2_cxx_sources)
all_cairo_sources += $(cairo_glesv2_sources)
if CAIRO_HAS_GLESV2_SURFACE
enabled_cairo_headers += $(cairo_glesv2_headers)
enabled_cairo_private += $(cairo_glesv2_private)
enabled_cairo_cxx_sources += $(cairo_glesv2_cxx_sources)
enabled_cairo_sources += $(cairo_glesv2_sources)
endif
all_cairo_pkgconf += cairo-glesv2.pc
if CAIRO_HAS_GLESV2_SURFACE
enabled_cairo_pkgconf += cairo-glesv2.pc
endif
unsupported_cairo_headers += $(cairo_glesv3_headers)
all_cairo_headers += $(cairo_glesv3_headers)
all_cairo_private += $(cairo_glesv3_private)
all_cairo_cxx_sources += $(cairo_glesv3_cxx_sources)
all_cairo_sources += $(cairo_glesv3_sources)
if CAIRO_HAS_GLESV3_SURFACE
enabled_cairo_headers += $(cairo_glesv3_headers)
enabled_cairo_private += $(cairo_glesv3_private)
enabled_cairo_cxx_sources += $(cairo_glesv3_cxx_sources)
enabled_cairo_sources += $(cairo_glesv3_sources)
endif
all_cairo_pkgconf += cairo-glesv3.pc
if CAIRO_HAS_GLESV3_SURFACE
enabled_cairo_pkgconf += cairo-glesv3.pc
endif
unsupported_cairo_headers += $(cairo_cogl_headers)
all_cairo_headers += $(cairo_cogl_headers)
all_cairo_private += $(cairo_cogl_private)
all_cairo_cxx_sources += $(cairo_cogl_cxx_sources)
all_cairo_sources += $(cairo_cogl_sources)
if CAIRO_HAS_COGL_SURFACE
enabled_cairo_headers += $(cairo_cogl_headers)
enabled_cairo_private += $(cairo_cogl_private)
enabled_cairo_cxx_sources += $(cairo_cogl_cxx_sources)
enabled_cairo_sources += $(cairo_cogl_sources)
endif
all_cairo_pkgconf += cairo-cogl.pc
if CAIRO_HAS_COGL_SURFACE
enabled_cairo_pkgconf += cairo-cogl.pc
endif
unsupported_cairo_headers += $(cairo_directfb_headers)
all_cairo_headers += $(cairo_directfb_headers)
all_cairo_private += $(cairo_directfb_private)
all_cairo_cxx_sources += $(cairo_directfb_cxx_sources)
all_cairo_sources += $(cairo_directfb_sources)
if CAIRO_HAS_DIRECTFB_SURFACE
enabled_cairo_headers += $(cairo_directfb_headers)
enabled_cairo_private += $(cairo_directfb_private)
enabled_cairo_cxx_sources += $(cairo_directfb_cxx_sources)
enabled_cairo_sources += $(cairo_directfb_sources)
endif
all_cairo_pkgconf += cairo-directfb.pc
if CAIRO_HAS_DIRECTFB_SURFACE
enabled_cairo_pkgconf += cairo-directfb.pc
endif
unsupported_cairo_headers += $(cairo_vg_headers)
all_cairo_headers += $(cairo_vg_headers)
all_cairo_private += $(cairo_vg_private)
all_cairo_cxx_sources += $(cairo_vg_cxx_sources)
all_cairo_sources += $(cairo_vg_sources)
if CAIRO_HAS_VG_SURFACE
enabled_cairo_headers += $(cairo_vg_headers)
enabled_cairo_private += $(cairo_vg_private)
enabled_cairo_cxx_sources += $(cairo_vg_cxx_sources)
enabled_cairo_sources += $(cairo_vg_sources)
endif
all_cairo_pkgconf += cairo-vg.pc
if CAIRO_HAS_VG_SURFACE
enabled_cairo_pkgconf += cairo-vg.pc
endif
supported_cairo_headers += $(cairo_egl_headers)
all_cairo_headers += $(cairo_egl_headers)
all_cairo_private += $(cairo_egl_private)
all_cairo_cxx_sources += $(cairo_egl_cxx_sources)
all_cairo_sources += $(cairo_egl_sources)
if CAIRO_HAS_EGL_FUNCTIONS
enabled_cairo_headers += $(cairo_egl_headers)
enabled_cairo_private += $(cairo_egl_private)
enabled_cairo_cxx_sources += $(cairo_egl_cxx_sources)
enabled_cairo_sources += $(cairo_egl_sources)
endif
all_cairo_pkgconf += cairo-egl.pc
if CAIRO_HAS_EGL_FUNCTIONS
enabled_cairo_pkgconf += cairo-egl.pc
endif
supported_cairo_headers += $(cairo_glx_headers)
all_cairo_headers += $(cairo_glx_headers)
all_cairo_private += $(cairo_glx_private)
all_cairo_cxx_sources += $(cairo_glx_cxx_sources)
all_cairo_sources += $(cairo_glx_sources)
if CAIRO_HAS_GLX_FUNCTIONS
enabled_cairo_headers += $(cairo_glx_headers)
enabled_cairo_private += $(cairo_glx_private)
enabled_cairo_cxx_sources += $(cairo_glx_cxx_sources)
enabled_cairo_sources += $(cairo_glx_sources)
endif
all_cairo_pkgconf += cairo-glx.pc
if CAIRO_HAS_GLX_FUNCTIONS
enabled_cairo_pkgconf += cairo-glx.pc
endif
supported_cairo_headers += $(cairo_wgl_headers)
all_cairo_headers += $(cairo_wgl_headers)
all_cairo_private += $(cairo_wgl_private)
all_cairo_cxx_sources += $(cairo_wgl_cxx_sources)
all_cairo_sources += $(cairo_wgl_sources)
if CAIRO_HAS_WGL_FUNCTIONS
enabled_cairo_headers += $(cairo_wgl_headers)
enabled_cairo_private += $(cairo_wgl_private)
enabled_cairo_cxx_sources += $(cairo_wgl_cxx_sources)
enabled_cairo_sources += $(cairo_wgl_sources)
endif
all_cairo_pkgconf += cairo-wgl.pc
if CAIRO_HAS_WGL_FUNCTIONS
enabled_cairo_pkgconf += cairo-wgl.pc
endif
supported_cairo_headers += $(cairo_script_headers)
all_cairo_headers += $(cairo_script_headers)
all_cairo_private += $(cairo_script_private)
all_cairo_cxx_sources += $(cairo_script_cxx_sources)
all_cairo_sources += $(cairo_script_sources)
if CAIRO_HAS_SCRIPT_SURFACE
enabled_cairo_headers += $(cairo_script_headers)
enabled_cairo_private += $(cairo_script_private)
enabled_cairo_cxx_sources += $(cairo_script_cxx_sources)
enabled_cairo_sources += $(cairo_script_sources)
endif
all_cairo_pkgconf += cairo-script.pc
if CAIRO_HAS_SCRIPT_SURFACE
enabled_cairo_pkgconf += cairo-script.pc
endif
supported_cairo_headers += $(cairo_ft_headers)
all_cairo_headers += $(cairo_ft_headers)
all_cairo_private += $(cairo_ft_private)
all_cairo_cxx_sources += $(cairo_ft_cxx_sources)
all_cairo_sources += $(cairo_ft_sources)
if CAIRO_HAS_FT_FONT
enabled_cairo_headers += $(cairo_ft_headers)
enabled_cairo_private += $(cairo_ft_private)
enabled_cairo_cxx_sources += $(cairo_ft_cxx_sources)
enabled_cairo_sources += $(cairo_ft_sources)
endif
all_cairo_pkgconf += cairo-ft.pc
if CAIRO_HAS_FT_FONT
enabled_cairo_pkgconf += cairo-ft.pc
endif
supported_cairo_headers += $(cairo_fc_headers)
all_cairo_headers += $(cairo_fc_headers)
all_cairo_private += $(cairo_fc_private)
all_cairo_cxx_sources += $(cairo_fc_cxx_sources)
all_cairo_sources += $(cairo_fc_sources)
if CAIRO_HAS_FC_FONT
enabled_cairo_headers += $(cairo_fc_headers)
enabled_cairo_private += $(cairo_fc_private)
enabled_cairo_cxx_sources += $(cairo_fc_cxx_sources)
enabled_cairo_sources += $(cairo_fc_sources)
endif
all_cairo_pkgconf += cairo-fc.pc
if CAIRO_HAS_FC_FONT
enabled_cairo_pkgconf += cairo-fc.pc
endif
supported_cairo_headers += $(cairo_ps_headers)
all_cairo_headers += $(cairo_ps_headers)
all_cairo_private += $(cairo_ps_private)
all_cairo_cxx_sources += $(cairo_ps_cxx_sources)
all_cairo_sources += $(cairo_ps_sources)
if CAIRO_HAS_PS_SURFACE
enabled_cairo_headers += $(cairo_ps_headers)
enabled_cairo_private += $(cairo_ps_private)
enabled_cairo_cxx_sources += $(cairo_ps_cxx_sources)
enabled_cairo_sources += $(cairo_ps_sources)
endif
all_cairo_pkgconf += cairo-ps.pc
if CAIRO_HAS_PS_SURFACE
enabled_cairo_pkgconf += cairo-ps.pc
endif
supported_cairo_headers += $(cairo_pdf_headers)
all_cairo_headers += $(cairo_pdf_headers)
all_cairo_private += $(cairo_pdf_private)
all_cairo_cxx_sources += $(cairo_pdf_cxx_sources)
all_cairo_sources += $(cairo_pdf_sources)
if CAIRO_HAS_PDF_SURFACE
enabled_cairo_headers += $(cairo_pdf_headers)
enabled_cairo_private += $(cairo_pdf_private)
enabled_cairo_cxx_sources += $(cairo_pdf_cxx_sources)
enabled_cairo_sources += $(cairo_pdf_sources)
endif
all_cairo_pkgconf += cairo-pdf.pc
if CAIRO_HAS_PDF_SURFACE
enabled_cairo_pkgconf += cairo-pdf.pc
endif
supported_cairo_headers += $(cairo_svg_headers)
all_cairo_headers += $(cairo_svg_headers)
all_cairo_private += $(cairo_svg_private)
all_cairo_cxx_sources += $(cairo_svg_cxx_sources)
all_cairo_sources += $(cairo_svg_sources)
if CAIRO_HAS_SVG_SURFACE
enabled_cairo_headers += $(cairo_svg_headers)
enabled_cairo_private += $(cairo_svg_private)
enabled_cairo_cxx_sources += $(cairo_svg_cxx_sources)
enabled_cairo_sources += $(cairo_svg_sources)
endif
all_cairo_pkgconf += cairo-svg.pc
if CAIRO_HAS_SVG_SURFACE
enabled_cairo_pkgconf += cairo-svg.pc
endif
all_cairo_private += $(cairo_test_surfaces_private) $(cairo_test_surfaces_headers)
all_cairo_cxx_sources += $(cairo_test_surfaces_cxx_sources)
all_cairo_sources += $(cairo_test_surfaces_sources)
if CAIRO_HAS_TEST_SURFACES
enabled_cairo_private += $(cairo_test_surfaces_private) $(cairo_test_surfaces_headers)
enabled_cairo_cxx_sources += $(cairo_test_surfaces_cxx_sources)
enabled_cairo_sources += $(cairo_test_surfaces_sources)
endif
supported_cairo_headers += $(cairo_image_headers)
all_cairo_headers += $(cairo_image_headers)
all_cairo_private += $(cairo_image_private)
all_cairo_cxx_sources += $(cairo_image_cxx_sources)
all_cairo_sources += $(cairo_image_sources)
enabled_cairo_headers += $(cairo_image_headers)
enabled_cairo_private += $(cairo_image_private)
enabled_cairo_cxx_sources += $(cairo_image_cxx_sources)
enabled_cairo_sources += $(cairo_image_sources)
supported_cairo_headers += $(cairo_mime_headers)
all_cairo_headers += $(cairo_mime_headers)
all_cairo_private += $(cairo_mime_private)
all_cairo_cxx_sources += $(cairo_mime_cxx_sources)
all_cairo_sources += $(cairo_mime_sources)
enabled_cairo_headers += $(cairo_mime_headers)
enabled_cairo_private += $(cairo_mime_private)
enabled_cairo_cxx_sources += $(cairo_mime_cxx_sources)
enabled_cairo_sources += $(cairo_mime_sources)
supported_cairo_headers += $(cairo_recording_headers)
all_cairo_headers += $(cairo_recording_headers)
all_cairo_private += $(cairo_recording_private)
all_cairo_cxx_sources += $(cairo_recording_cxx_sources)
all_cairo_sources += $(cairo_recording_sources)
enabled_cairo_headers += $(cairo_recording_headers)
enabled_cairo_private += $(cairo_recording_private)
enabled_cairo_cxx_sources += $(cairo_recording_cxx_sources)
enabled_cairo_sources += $(cairo_recording_sources)
supported_cairo_headers += $(cairo_observer_headers)
all_cairo_headers += $(cairo_observer_headers)
all_cairo_private += $(cairo_observer_private)
all_cairo_cxx_sources += $(cairo_observer_cxx_sources)
all_cairo_sources += $(cairo_observer_sources)
enabled_cairo_headers += $(cairo_observer_headers)
enabled_cairo_private += $(cairo_observer_private)
enabled_cairo_cxx_sources += $(cairo_observer_cxx_sources)
enabled_cairo_sources += $(cairo_observer_sources)
unsupported_cairo_headers += $(cairo_tee_headers)
all_cairo_headers += $(cairo_tee_headers)
all_cairo_private += $(cairo_tee_private)
all_cairo_cxx_sources += $(cairo_tee_cxx_sources)
all_cairo_sources += $(cairo_tee_sources)
if CAIRO_HAS_TEE_SURFACE
enabled_cairo_headers += $(cairo_tee_headers)
enabled_cairo_private += $(cairo_tee_private)
enabled_cairo_cxx_sources += $(cairo_tee_cxx_sources)
enabled_cairo_sources += $(cairo_tee_sources)
endif
all_cairo_pkgconf += cairo-tee.pc
if CAIRO_HAS_TEE_SURFACE
enabled_cairo_pkgconf += cairo-tee.pc
endif
unsupported_cairo_headers += $(cairo_xml_headers)
all_cairo_headers += $(cairo_xml_headers)
all_cairo_private += $(cairo_xml_private)
all_cairo_cxx_sources += $(cairo_xml_cxx_sources)
all_cairo_sources += $(cairo_xml_sources)
if CAIRO_HAS_XML_SURFACE
enabled_cairo_headers += $(cairo_xml_headers)
enabled_cairo_private += $(cairo_xml_private)
enabled_cairo_cxx_sources += $(cairo_xml_cxx_sources)
enabled_cairo_sources += $(cairo_xml_sources)
endif
all_cairo_pkgconf += cairo-xml.pc
if CAIRO_HAS_XML_SURFACE
enabled_cairo_pkgconf += cairo-xml.pc
endif
supported_cairo_headers += $(cairo_user_headers)
all_cairo_headers += $(cairo_user_headers)
all_cairo_private += $(cairo_user_private)
all_cairo_cxx_sources += $(cairo_user_cxx_sources)
all_cairo_sources += $(cairo_user_sources)
enabled_cairo_headers += $(cairo_user_headers)
enabled_cairo_private += $(cairo_user_private)
enabled_cairo_cxx_sources += $(cairo_user_cxx_sources)
enabled_cairo_sources += $(cairo_user_sources)
all_cairo_private += $(cairo_pthread_private) $(cairo_pthread_headers)
all_cairo_cxx_sources += $(cairo_pthread_cxx_sources)
all_cairo_sources += $(cairo_pthread_sources)
if CAIRO_HAS_PTHREAD
enabled_cairo_private += $(cairo_pthread_private) $(cairo_pthread_headers)
enabled_cairo_cxx_sources += $(cairo_pthread_cxx_sources)
enabled_cairo_sources += $(cairo_pthread_sources)
endif
supported_cairo_headers += $(cairo_gobject_headers)
all_cairo_headers += $(cairo_gobject_headers)
all_cairo_private += $(cairo_gobject_private)
all_cairo_cxx_sources += $(cairo_gobject_cxx_sources)
all_cairo_sources += $(cairo_gobject_sources)
if CAIRO_HAS_GOBJECT_FUNCTIONS
enabled_cairo_headers += $(cairo_gobject_headers)
enabled_cairo_private += $(cairo_gobject_private)
enabled_cairo_cxx_sources += $(cairo_gobject_cxx_sources)
enabled_cairo_sources += $(cairo_gobject_sources)
endif
all_cairo_pkgconf += cairo-gobject.pc
if CAIRO_HAS_GOBJECT_FUNCTIONS
enabled_cairo_pkgconf += cairo-gobject.pc
endif
all_cairo_private += $(cairo_trace_private) $(cairo_trace_headers)
all_cairo_cxx_sources += $(cairo_trace_cxx_sources)
all_cairo_sources += $(cairo_trace_sources)
if CAIRO_HAS_TRACE
enabled_cairo_private += $(cairo_trace_private) $(cairo_trace_headers)
enabled_cairo_cxx_sources += $(cairo_trace_cxx_sources)
enabled_cairo_sources += $(cairo_trace_sources)
endif
all_cairo_private += $(cairo_interpreter_private) $(cairo_interpreter_headers)
all_cairo_cxx_sources += $(cairo_interpreter_cxx_sources)
all_cairo_sources += $(cairo_interpreter_sources)
if CAIRO_HAS_INTERPRETER
enabled_cairo_private += $(cairo_interpreter_private) $(cairo_interpreter_headers)
enabled_cairo_cxx_sources += $(cairo_interpreter_cxx_sources)
enabled_cairo_sources += $(cairo_interpreter_sources)
endif
all_cairo_private += $(cairo_symbol_lookup_private) $(cairo_symbol_lookup_headers)
all_cairo_cxx_sources += $(cairo_symbol_lookup_cxx_sources)
all_cairo_sources += $(cairo_symbol_lookup_sources)
if CAIRO_HAS_SYMBOL_LOOKUP
enabled_cairo_private += $(cairo_symbol_lookup_private) $(cairo_symbol_lookup_headers)
enabled_cairo_cxx_sources += $(cairo_symbol_lookup_cxx_sources)
enabled_cairo_sources += $(cairo_symbol_lookup_sources)
endif

Просмотреть файл

@ -0,0 +1,117 @@
# Note: All source files are listed in Makefile.sources.
include $(top_srcdir)/build/Makefile.am.common
include $(srcdir)/Makefile.am.features
EXTRA_DIST += Makefile.win32 Makefile.win32.features
#MAINTAINERCLEANFILES += $(srcdir)/Makefile.win32.features
AM_CPPFLAGS = -I$(srcdir) $(CAIRO_CFLAGS)
AM_LDFLAGS = $(CAIRO_LDFLAGS)
if OS_WIN32
export_symbols = -export-symbols cairo.def
cairo_def_dependency = cairo.def
endif
$(top_builddir)/config.h: $(top_srcdir)/config.h.in
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) config.h
cairoincludedir = $(includedir)/cairo
cairoinclude_HEADERS = $(enabled_cairo_headers)
lib_LTLIBRARIES = libcairo.la
if BUILD_CXX
cairo_cxx_lib = libcairo_cxx.la
else
cairo_cxx_lib =
endif
noinst_LTLIBRARIES = $(cairo_cxx_lib)
libcairo_cxx_la_SOURCES = \
$(enabled_cairo_headers) \
$(enabled_cairo_private) \
$(enabled_cairo_cxx_sources) \
$(NULL)
libcairo_cxx_la_LDFLAGS = $(AM_LDFLAGS) $(export_symbols)
libcairo_cxx_la_LIBADD = $(CAIRO_LIBS)
libcairo_cxx_la_DEPENDENCIES = $(cairo_def_dependency)
libcairo_la_SOURCES = \
$(enabled_cairo_headers) \
$(enabled_cairo_private) \
$(enabled_cairo_sources) \
$(NULL)
libcairo_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(CAIRO_LIBTOOL_VERSION_INFO) -no-undefined $(export_symbols)
libcairo_la_LIBADD = $(CAIRO_LIBS) \
$(cairo_cxx_lib)
libcairo_la_DEPENDENCIES = $(cairo_def_dependency) $(cairo_cxx_lib)
# Special headers
nodist_cairoinclude_HEADERS = cairo-features.h
nodist_libcairo_la_SOURCES = cairo-features.h
BUILT_SOURCES += cairo-features.h cairo-supported-features.h
DISTCLEANFILES += cairo-features.h cairo-supported-features.h
cairo-features.h cairo-supported-features.h:
cd $(top_builddir) && ./config.status src/$@
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = $(enabled_cairo_pkgconf)
CLEANFILES += cairo.def
cairo.def: cairo-features.h $(enabled_cairo_headers)
@echo Generating $@
@(echo EXPORTS; \
(cd $(srcdir); cat $(enabled_cairo_headers) || echo 'cairo_ERROR ()' ) | \
$(EGREP) -v '^# *include' | \
( cat cairo-features.h - | $(CPP) -D__cplusplus - || echo 'cairo_ERROR ()' ) | \
$(EGREP) '^cairo_.* \(' | \
sed -e 's/[ ].*//' | \
sort; \
echo LIBRARY libcairo-$(CAIRO_VERSION_SONUM).dll; \
) >$@
@ ! grep -q cairo_ERROR $@ || ($(RM) $@; false)
TESTS_ENVIRONMENT = \
srcdir="$(srcdir)" \
MAKE="$(MAKE) $(AM_MAKEFLAGS)" \
all_cairo_files="$(all_cairo_files)" \
all_cairo_headers="$(all_cairo_headers)" \
all_cairo_private="$(all_cairo_private)" \
all_cairo_sources="$(all_cairo_sources)" \
enabled_cairo_headers="$(enabled_cairo_headers)" \
enabled_cairo_private="$(enabled_cairo_private)" \
enabled_cairo_sources="$(enabled_cairo_sources)" \
$(NULL)
TESTS_SH = \
check-def.sh \
check-doc-syntax.sh \
check-headers.sh \
check-plt.sh \
check-preprocessor-syntax.sh \
$(NULL)
TESTS += $(TESTS_SH)
if CROSS_COMPILING
else
TESTS += check-link$(EXEEXT)
endif
EXTRA_DIST += $(TESTS_SH) check-has-hidden-symbols.c check-doc-syntax.awk
check_PROGRAMS += check-link
check_link_LDADD = libcairo.la
check: headers-standalone
PREPROCESS_ARGS = $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS)
COMPILE_ARGS = $(PREPROCESS_ARGS) $(AM_CFLAGS) $(CFLAGS)
# The pre-processed result is used by check-{def,plt}.sh to determine whether
# cairo has been compiled with symbol hiding.
.c.i: $(cairoinclude_HEADERS) $(nodist_cairoinclude_HEADERS) cairoint.h $(top_builddir)/config.h
$(CPP) $(PREPROCESS_ARGS) $< -o $@
.c.s: $(cairoinclude_HEADERS) $(nodist_cairoinclude_HEADERS) cairoint.h $(top_builddir)/config.h
$(CC) $(COMPILE_ARGS) $< -S -o $@
include $(srcdir)/Makefile.am.analysis

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,461 @@
# Makefile.sources
#
# This file is the canonical location listing all the source files used
# to build the cairo library. Every source file is categorized as one of:
#
# * public header file
# * private header file (must end in -private.h except for cairoint.h)
# * source code file
#
# Every source file should be specified exactly once, grouped with the
# feature that uses the source file. If more than one feature use the
# file (like pdf_operators or font_subset files), the files should be
# appended to to the base cairo files, and the code inside them
# enabled/disabled using C preprocessor macros defined in cairoint.h.
# See how pdf_operators or font_subset are handled.
#
# The sources are picked up according to the configured features
# by the generated file Makefile.am.features or Makefile.win32.features.
#
# These are a few special source files. Those are not included in this
# file to not confuse build systems. Each build system must handle them
# separately. These files include:
#
# * cairo-features.h:
# This file is generated by configure and includes macros signifying
# which features are enabled. This file should be installed like
# other public headers, but should NOT be distributed in the cairo
# distribution.
#
# * cairo-supported-features.h:
# This file is generated by configure and includes macros signifying
# all supported features. This is used by gtk-doc to generate
# documentation for all those macros, enabled or not.
# This file is NOT used during the build of the library and should
# NOT be installed or distributed.
#
# Please follow the strict syntax of this file, including keeping file
# lists sorted.
#
cairo_headers = cairo.h cairo-version.h cairo-deprecated.h
cairo_private = \
cairoint.h \
cairo-analysis-surface-private.h \
cairo-arc-private.h \
cairo-array-private.h \
cairo-atomic-private.h \
cairo-backend-private.h \
cairo-box-inline.h \
cairo-boxes-private.h \
cairo-cache-private.h \
cairo-clip-inline.h \
cairo-clip-private.h \
cairo-combsort-inline.h \
cairo-compiler-private.h \
cairo-composite-rectangles-private.h \
cairo-compositor-private.h \
cairo-contour-inline.h \
cairo-contour-private.h \
cairo-damage-private.h \
cairo-default-context-private.h \
cairo-device-private.h \
cairo-error-inline.h \
cairo-error-private.h \
cairo-fixed-private.h \
cairo-fixed-type-private.h \
cairo-fontconfig-private.h \
cairo-freed-pool-private.h \
cairo-freelist-private.h \
cairo-freelist-type-private.h \
cairo-gstate-private.h \
cairo-hash-private.h \
cairo-image-info-private.h \
cairo-image-surface-inline.h \
cairo-image-surface-private.h \
cairo-line-inline.h \
cairo-line-private.h \
cairo-list-inline.h \
cairo-list-private.h \
cairo-malloc-private.h \
cairo-mempool-private.h \
cairo-mutex-impl-private.h \
cairo-mutex-list-private.h \
cairo-mutex-private.h \
cairo-mutex-type-private.h \
cairo-output-stream-private.h \
cairo-paginated-private.h \
cairo-paginated-surface-private.h \
cairo-path-fixed-private.h \
cairo-path-private.h \
cairo-pattern-inline.h \
cairo-pattern-private.h \
cairo-pixman-private.h \
cairo-private.h \
cairo-recording-surface-inline.h \
cairo-recording-surface-private.h \
cairo-reference-count-private.h \
cairo-region-private.h \
cairo-rtree-private.h \
cairo-scaled-font-private.h \
cairo-slope-private.h \
cairo-spans-compositor-private.h \
cairo-spans-private.h \
cairo-stroke-dash-private.h \
cairo-surface-backend-private.h \
cairo-surface-clipper-private.h \
cairo-surface-fallback-private.h \
cairo-surface-inline.h \
cairo-surface-observer-inline.h \
cairo-surface-observer-private.h \
cairo-surface-offset-private.h \
cairo-surface-private.h \
cairo-surface-snapshot-inline.h \
cairo-surface-snapshot-private.h \
cairo-surface-subsurface-inline.h \
cairo-surface-subsurface-private.h \
cairo-surface-wrapper-private.h \
cairo-time-private.h \
cairo-traps-private.h \
cairo-tristrip-private.h \
cairo-types-private.h \
cairo-user-font-private.h \
cairo-wideint-private.h \
cairo-wideint-type-private.h \
$(NULL)
cairo_sources = \
cairo-analysis-surface.c \
cairo-arc.c \
cairo-array.c \
cairo-atomic.c \
cairo-base64-stream.c \
cairo-base85-stream.c \
cairo-bentley-ottmann-rectangular.c \
cairo-bentley-ottmann-rectilinear.c \
cairo-bentley-ottmann.c \
cairo-botor-scan-converter.c \
cairo-boxes-intersect.c \
cairo-boxes.c \
cairo-cache.c \
cairo-clip-boxes.c \
cairo-clip-polygon.c \
cairo-clip-region.c \
cairo-clip-surface.c \
cairo-clip-tor-scan-converter.c \
cairo-clip.c \
cairo-color.c \
cairo-composite-rectangles.c \
cairo-compositor.c \
cairo-contour.c \
cairo-damage.c \
cairo-debug.c \
cairo-default-context.c \
cairo-device.c \
cairo-error.c \
cairo-fallback-compositor.c \
cairo-fixed.c \
cairo-font-face-twin-data.c \
cairo-font-face-twin.c \
cairo-font-face.c \
cairo-font-options.c \
cairo-freed-pool.c \
cairo-freelist.c \
cairo-gstate.c \
cairo-hash.c \
cairo-hull.c \
cairo-image-compositor.c \
cairo-image-info.c \
cairo-image-source.c \
cairo-image-surface.c \
cairo-line.c \
cairo-lzw.c \
cairo-mask-compositor.c \
cairo-matrix.c \
cairo-mempool.c \
cairo-mesh-pattern-rasterizer.c \
cairo-misc.c \
cairo-mono-scan-converter.c \
cairo-mutex.c \
cairo-no-compositor.c \
cairo-observer.c \
cairo-output-stream.c \
cairo-paginated-surface.c \
cairo-path-bounds.c \
cairo-path-fill.c \
cairo-path-fixed.c \
cairo-path-in-fill.c \
cairo-path-stroke-boxes.c \
cairo-path-stroke-polygon.c \
cairo-path-stroke-traps.c \
cairo-path-stroke-tristrip.c \
cairo-path-stroke.c \
cairo-path.c \
cairo-pattern.c \
cairo-pen.c \
cairo-polygon-intersect.c \
cairo-polygon-reduce.c \
cairo-polygon.c \
cairo-raster-source-pattern.c \
cairo-recording-surface.c \
cairo-rectangle.c \
cairo-rectangular-scan-converter.c \
cairo-region.c \
cairo-rtree.c \
cairo-scaled-font.c \
cairo-shape-mask-compositor.c \
cairo-slope.c \
cairo-spans-compositor.c \
cairo-spans.c \
cairo-spline.c \
cairo-stroke-dash.c \
cairo-stroke-style.c \
cairo-surface-clipper.c \
cairo-surface-fallback.c \
cairo-surface-observer.c \
cairo-surface-offset.c \
cairo-surface-snapshot.c \
cairo-surface-subsurface.c \
cairo-surface-wrapper.c \
cairo-surface.c \
cairo-time.c \
cairo-tor-scan-converter.c \
cairo-tor22-scan-converter.c \
cairo-toy-font-face.c \
cairo-traps-compositor.c \
cairo-traps.c \
cairo-tristrip.c \
cairo-unicode.c \
cairo-user-font.c \
cairo-version.c \
cairo-wideint.c \
cairo.c \
$(NULL)
_cairo_font_subset_private = \
cairo-scaled-font-subsets-private.h \
cairo-truetype-subset-private.h \
cairo-type1-private.h \
cairo-type3-glyph-surface-private.h \
$(NULL)
_cairo_font_subset_sources = \
cairo-cff-subset.c \
cairo-scaled-font-subsets.c \
cairo-truetype-subset.c \
cairo-type1-fallback.c \
cairo-type1-glyph-names.c \
cairo-type1-subset.c \
cairo-type3-glyph-surface.c \
$(NULL)
cairo_private += $(_cairo_font_subset_private)
cairo_sources += $(_cairo_font_subset_sources)
cairo_egl_sources =
cairo_glx_sources =
cairo_wgl_sources =
_cairo_pdf_operators_private = \
cairo-pdf-operators-private.h \
cairo-pdf-shading-private.h \
cairo-tag-attributes-private.h \
$(NULL)
_cairo_pdf_operators_sources = \
cairo-pdf-operators.c \
cairo-pdf-shading.c \
cairo-tag-attributes.c \
$(NULL)
cairo_private += $(_cairo_pdf_operators_private)
cairo_sources += $(_cairo_pdf_operators_sources)
cairo_png_sources = cairo-png.c
cairo_ps_headers = cairo-ps.h
cairo_ps_private = cairo-ps-surface-private.h
cairo_ps_sources = cairo-ps-surface.c
_cairo_deflate_stream_sources = cairo-deflate-stream.c
cairo_sources += $(_cairo_deflate_stream_sources)
cairo_pdf_headers = cairo-pdf.h
cairo_pdf_private = cairo-pdf-surface-private.h cairo-tag-stack-private.h
cairo_pdf_sources = cairo-pdf-surface.c cairo-pdf-interchange.c cairo-tag-stack.c
cairo_svg_headers = cairo-svg.h
cairo_svg_private = cairo-svg-surface-private.h
cairo_svg_sources = cairo-svg-surface.c
cairo_ft_headers = cairo-ft.h
cairo_ft_private = cairo-ft-private.h
cairo_ft_sources = cairo-ft-font.c
# These are private, even though they look like public headers
cairo_test_surfaces_private = \
test-compositor-surface.h \
test-compositor-surface-private.h \
test-null-compositor-surface.h \
test-paginated-surface.h \
$(NULL)
cairo_test_surfaces_sources = \
test-compositor-surface.c \
test-null-compositor-surface.c \
test-base-compositor-surface.c \
test-paginated-surface.c \
$(NULL)
cairo_xlib_headers = cairo-xlib.h
cairo_xlib_private = \
cairo-xlib-private.h \
cairo-xlib-surface-private.h \
cairo-xlib-xrender-private.h \
$(NULL)
cairo_xlib_sources = \
cairo-xlib-display.c \
cairo-xlib-core-compositor.c \
cairo-xlib-fallback-compositor.c \
cairo-xlib-render-compositor.c \
cairo-xlib-screen.c \
cairo-xlib-source.c \
cairo-xlib-surface.c \
cairo-xlib-surface-shm.c \
cairo-xlib-visual.c \
cairo-xlib-xcb-surface.c \
$(NULL)
cairo_xlib_xrender_headers = cairo-xlib-xrender.h
cairo_xcb_headers = cairo-xcb.h
cairo_xcb_private = cairo-xcb-private.h
cairo_xcb_sources = \
cairo-xcb-connection.c \
cairo-xcb-connection-core.c \
cairo-xcb-connection-render.c \
cairo-xcb-connection-shm.c \
cairo-xcb-screen.c \
cairo-xcb-shm.c \
cairo-xcb-surface.c \
cairo-xcb-surface-core.c \
cairo-xcb-surface-render.c \
cairo-xcb-resources.c \
$(NULL)
cairo_qt_headers = cairo-qt.h
cairo_qt_cxx_sources = cairo-qt-surface.cpp
cairo_quartz_headers = cairo-quartz.h
cairo_quartz_private = cairo-quartz-private.h
cairo_quartz_sources = cairo-quartz-surface.c
cairo_quartz_image_headers = cairo-quartz-image.h
cairo_quartz_image_sources = cairo-quartz-image-surface.c
cairo_quartz_font_sources = cairo-quartz-font.c
cairo_win32_headers = cairo-win32.h
cairo_win32_private = win32/cairo-win32-private.h
cairo_win32_sources = \
win32/cairo-win32-debug.c \
win32/cairo-win32-device.c \
win32/cairo-win32-gdi-compositor.c \
win32/cairo-win32-system.c \
win32/cairo-win32-surface.c \
win32/cairo-win32-display-surface.c \
win32/cairo-win32-printing-surface.c \
$(NULL)
cairo_win32_font_sources = \
win32/cairo-win32-font.c \
$(NULL)
cairo_os2_headers = cairo-os2.h
cairo_os2_private = cairo-os2-private.h
cairo_os2_sources = cairo-os2-surface.c
# automake is stupid enough to always use c++ linker if we enable the
# following lines, even if beos surface is not enabled. Disable it for now.
cairo_beos_headers = cairo-beos.h
cairo_beos_cxx_sources = cairo-beos-surface.cpp
cairo_gl_headers = cairo-gl.h
cairo_gl_private = cairo-gl-private.h \
cairo-gl-dispatch-private.h \
cairo-gl-ext-def-private.h \
cairo-gl-gradient-private.h
cairo_gl_sources = cairo-gl-composite.c \
cairo-gl-device.c \
cairo-gl-dispatch.c \
cairo-gl-glyphs.c \
cairo-gl-gradient.c \
cairo-gl-info.c \
cairo-gl-msaa-compositor.c \
cairo-gl-operand.c \
cairo-gl-shaders.c \
cairo-gl-source.c \
cairo-gl-spans-compositor.c \
cairo-gl-surface.c \
cairo-gl-traps-compositor.c
cairo_glesv2_headers = $(cairo_gl_headers)
cairo_glesv2_private = $(cairo_gl_private)
cairo_glesv2_sources = $(cairo_gl_sources)
cairo_glesv3_headers = $(cairo_gl_headers)
cairo_glesv3_private = $(cairo_gl_private)
cairo_glesv3_sources = $(cairo_gl_sources)
cairo_egl_sources += cairo-egl-context.c
cairo_glx_sources += cairo-glx-context.c
cairo_wgl_sources += cairo-wgl-context.c
cairo_directfb_headers = cairo-directfb.h
cairo_directfb_sources = cairo-directfb-surface.c
cairo_drm_headers = cairo-drm.h
cairo_drm_private = drm/cairo-drm-private.h \
drm/cairo-drm-intel-private.h \
drm/cairo-drm-intel-brw-defines.h \
drm/cairo-drm-intel-brw-structs.h \
drm/cairo-drm-intel-brw-eu.h \
drm/cairo-drm-intel-command-private.h \
drm/cairo-drm-intel-ioctl-private.h \
drm/cairo-drm-i915-private.h \
drm/cairo-drm-i965-private.h \
drm/cairo-drm-radeon-private.h
cairo_drm_sources = drm/cairo-drm.c \
drm/cairo-drm-bo.c \
drm/cairo-drm-surface.c \
drm/cairo-drm-intel.c \
drm/cairo-drm-intel-debug.c \
drm/cairo-drm-intel-surface.c \
drm/cairo-drm-i915-surface.c \
drm/cairo-drm-i915-glyphs.c \
drm/cairo-drm-i915-shader.c \
drm/cairo-drm-i915-spans.c \
drm/cairo-drm-i965-surface.c \
drm/cairo-drm-i965-glyphs.c \
drm/cairo-drm-i965-shader.c \
drm/cairo-drm-i965-spans.c \
drm/cairo-drm-intel-brw-eu.c \
drm/cairo-drm-intel-brw-eu-emit.c \
drm/cairo-drm-intel-brw-eu-util.c \
drm/cairo-drm-radeon.c \
drm/cairo-drm-radeon-surface.c
cairo_gallium_sources = drm/cairo-drm-gallium-surface.c
cairo_script_headers = cairo-script.h
cairo_script_private = cairo-script-private.h
cairo_script_sources = cairo-script-surface.c
cairo_tee_headers = cairo-tee.h
cairo_tee_private = cairo-tee-surface-private.h
cairo_tee_sources = cairo-tee-surface.c
cairo_xml_headers = cairo-xml.h
cairo_xml_sources = cairo-xml-surface.c
cairo_vg_headers = cairo-vg.h
cairo_vg_sources = cairo-vg-surface.c
cairo_cogl_headers = cairo-cogl.h
cairo_cogl_private = cairo-cogl-private.h \
cairo-cogl-gradient-private.h
cairo_cogl_sources = cairo-cogl-surface.c \
cairo-cogl-gradient.c

Просмотреть файл

@ -0,0 +1,28 @@
top_srcdir = ..
include $(top_srcdir)/build/Makefile.win32.common
include Makefile.win32.features
SOURCES = $(enabled_cairo_sources)
STATIC_SOURCES = cairo-system.c
OBJECTS = $(patsubst %.c, $(CFG)/%.obj, $(SOURCES))
OBJECTS_STATIC = $(patsubst %cairo-system.obj, %cairo-system-static.obj, $(OBJECTS))
static: inform $(CFG)/cairo-static.lib
dynamic: inform $(CFG)/cairo.dll
$(CFG)/cairo.dll: $(OBJECTS)
@$(LD) $(CAIRO_LDFLAGS) -DLL -OUT:$@ $(CAIRO_LIBS) $(PIXMAN_LIBS) $(OBJECTS)
$(CFG)/cairo-static.lib: $(OBJECTS_STATIC)
@$(AR) $(CAIRO_ARFLAGS) -OUT:$@ $(PIXMAN_LIBS) $(OBJECTS_STATIC)
all: inform $(CFG)/cairo.dll $(CFG)/cairo-static.lib
@echo "Built successfully!"
@echo "You should copy the following files to a proper place now:"
@echo ""
@echo " src/cairo-features.h"
@for x in $(enabled_cairo_headers); do echo " src/$$x"; done
@echo " src/$(CFG)/cairo.dll"
@echo " src/$(CFG)/cairo-static.lib"

Просмотреть файл

@ -0,0 +1,661 @@
# Generated by configure. Do not edit.
ifeq ($(top_srcdir),)
include Makefile.sources
else
include $(top_srcdir)/src/Makefile.sources
endif
supported_cairo_headers = $(cairo_headers)
unsupported_cairo_headers =
all_cairo_headers = $(cairo_headers)
all_cairo_private = $(cairo_private)
all_cairo_cxx_sources = $(cairo_cxx_sources)
all_cairo_sources = $(cairo_sources)
enabled_cairo_headers = $(cairo_headers)
enabled_cairo_private = $(cairo_private)
enabled_cairo_cxx_sources = $(cairo_cxx_sources)
enabled_cairo_sources = $(cairo_sources)
all_cairo_pkgconf = cairo.pc
enabled_cairo_pkgconf = cairo.pc
supported_cairo_headers += $(cairo_xlib_headers)
all_cairo_headers += $(cairo_xlib_headers)
all_cairo_private += $(cairo_xlib_private)
all_cairo_cxx_sources += $(cairo_xlib_cxx_sources)
all_cairo_sources += $(cairo_xlib_sources)
ifeq ($(CAIRO_HAS_XLIB_SURFACE),1)
enabled_cairo_headers += $(cairo_xlib_headers)
enabled_cairo_private += $(cairo_xlib_private)
enabled_cairo_cxx_sources += $(cairo_xlib_cxx_sources)
enabled_cairo_sources += $(cairo_xlib_sources)
endif
all_cairo_pkgconf += cairo-xlib.pc
ifeq ($(CAIRO_HAS_XLIB_SURFACE),1)
enabled_cairo_pkgconf += cairo-xlib.pc
endif
supported_cairo_headers += $(cairo_xlib_xrender_headers)
all_cairo_headers += $(cairo_xlib_xrender_headers)
all_cairo_private += $(cairo_xlib_xrender_private)
all_cairo_cxx_sources += $(cairo_xlib_xrender_cxx_sources)
all_cairo_sources += $(cairo_xlib_xrender_sources)
ifeq ($(CAIRO_HAS_XLIB_XRENDER_SURFACE),1)
enabled_cairo_headers += $(cairo_xlib_xrender_headers)
enabled_cairo_private += $(cairo_xlib_xrender_private)
enabled_cairo_cxx_sources += $(cairo_xlib_xrender_cxx_sources)
enabled_cairo_sources += $(cairo_xlib_xrender_sources)
endif
all_cairo_pkgconf += cairo-xlib-xrender.pc
ifeq ($(CAIRO_HAS_XLIB_XRENDER_SURFACE),1)
enabled_cairo_pkgconf += cairo-xlib-xrender.pc
endif
supported_cairo_headers += $(cairo_xcb_headers)
all_cairo_headers += $(cairo_xcb_headers)
all_cairo_private += $(cairo_xcb_private)
all_cairo_cxx_sources += $(cairo_xcb_cxx_sources)
all_cairo_sources += $(cairo_xcb_sources)
ifeq ($(CAIRO_HAS_XCB_SURFACE),1)
enabled_cairo_headers += $(cairo_xcb_headers)
enabled_cairo_private += $(cairo_xcb_private)
enabled_cairo_cxx_sources += $(cairo_xcb_cxx_sources)
enabled_cairo_sources += $(cairo_xcb_sources)
endif
all_cairo_pkgconf += cairo-xcb.pc
ifeq ($(CAIRO_HAS_XCB_SURFACE),1)
enabled_cairo_pkgconf += cairo-xcb.pc
endif
unsupported_cairo_headers += $(cairo_xlib_xcb_headers)
all_cairo_headers += $(cairo_xlib_xcb_headers)
all_cairo_private += $(cairo_xlib_xcb_private)
all_cairo_cxx_sources += $(cairo_xlib_xcb_cxx_sources)
all_cairo_sources += $(cairo_xlib_xcb_sources)
ifeq ($(CAIRO_HAS_XLIB_XCB_FUNCTIONS),1)
enabled_cairo_headers += $(cairo_xlib_xcb_headers)
enabled_cairo_private += $(cairo_xlib_xcb_private)
enabled_cairo_cxx_sources += $(cairo_xlib_xcb_cxx_sources)
enabled_cairo_sources += $(cairo_xlib_xcb_sources)
endif
all_cairo_pkgconf += cairo-xlib-xcb.pc
ifeq ($(CAIRO_HAS_XLIB_XCB_FUNCTIONS),1)
enabled_cairo_pkgconf += cairo-xlib-xcb.pc
endif
supported_cairo_headers += $(cairo_xcb_shm_headers)
all_cairo_headers += $(cairo_xcb_shm_headers)
all_cairo_private += $(cairo_xcb_shm_private)
all_cairo_cxx_sources += $(cairo_xcb_shm_cxx_sources)
all_cairo_sources += $(cairo_xcb_shm_sources)
ifeq ($(CAIRO_HAS_XCB_SHM_FUNCTIONS),1)
enabled_cairo_headers += $(cairo_xcb_shm_headers)
enabled_cairo_private += $(cairo_xcb_shm_private)
enabled_cairo_cxx_sources += $(cairo_xcb_shm_cxx_sources)
enabled_cairo_sources += $(cairo_xcb_shm_sources)
endif
all_cairo_pkgconf += cairo-xcb-shm.pc
ifeq ($(CAIRO_HAS_XCB_SHM_FUNCTIONS),1)
enabled_cairo_pkgconf += cairo-xcb-shm.pc
endif
unsupported_cairo_headers += $(cairo_qt_headers)
all_cairo_headers += $(cairo_qt_headers)
all_cairo_private += $(cairo_qt_private)
all_cairo_cxx_sources += $(cairo_qt_cxx_sources)
all_cairo_sources += $(cairo_qt_sources)
ifeq ($(CAIRO_HAS_QT_SURFACE),1)
enabled_cairo_headers += $(cairo_qt_headers)
enabled_cairo_private += $(cairo_qt_private)
enabled_cairo_cxx_sources += $(cairo_qt_cxx_sources)
enabled_cairo_sources += $(cairo_qt_sources)
endif
all_cairo_pkgconf += cairo-qt.pc
ifeq ($(CAIRO_HAS_QT_SURFACE),1)
enabled_cairo_pkgconf += cairo-qt.pc
endif
supported_cairo_headers += $(cairo_quartz_headers)
all_cairo_headers += $(cairo_quartz_headers)
all_cairo_private += $(cairo_quartz_private)
all_cairo_cxx_sources += $(cairo_quartz_cxx_sources)
all_cairo_sources += $(cairo_quartz_sources)
ifeq ($(CAIRO_HAS_QUARTZ_SURFACE),1)
enabled_cairo_headers += $(cairo_quartz_headers)
enabled_cairo_private += $(cairo_quartz_private)
enabled_cairo_cxx_sources += $(cairo_quartz_cxx_sources)
enabled_cairo_sources += $(cairo_quartz_sources)
endif
all_cairo_pkgconf += cairo-quartz.pc
ifeq ($(CAIRO_HAS_QUARTZ_SURFACE),1)
enabled_cairo_pkgconf += cairo-quartz.pc
endif
supported_cairo_headers += $(cairo_quartz_font_headers)
all_cairo_headers += $(cairo_quartz_font_headers)
all_cairo_private += $(cairo_quartz_font_private)
all_cairo_cxx_sources += $(cairo_quartz_font_cxx_sources)
all_cairo_sources += $(cairo_quartz_font_sources)
ifeq ($(CAIRO_HAS_QUARTZ_FONT),1)
enabled_cairo_headers += $(cairo_quartz_font_headers)
enabled_cairo_private += $(cairo_quartz_font_private)
enabled_cairo_cxx_sources += $(cairo_quartz_font_cxx_sources)
enabled_cairo_sources += $(cairo_quartz_font_sources)
endif
all_cairo_pkgconf += cairo-quartz-font.pc
ifeq ($(CAIRO_HAS_QUARTZ_FONT),1)
enabled_cairo_pkgconf += cairo-quartz-font.pc
endif
unsupported_cairo_headers += $(cairo_quartz_image_headers)
all_cairo_headers += $(cairo_quartz_image_headers)
all_cairo_private += $(cairo_quartz_image_private)
all_cairo_cxx_sources += $(cairo_quartz_image_cxx_sources)
all_cairo_sources += $(cairo_quartz_image_sources)
ifeq ($(CAIRO_HAS_QUARTZ_IMAGE_SURFACE),1)
enabled_cairo_headers += $(cairo_quartz_image_headers)
enabled_cairo_private += $(cairo_quartz_image_private)
enabled_cairo_cxx_sources += $(cairo_quartz_image_cxx_sources)
enabled_cairo_sources += $(cairo_quartz_image_sources)
endif
all_cairo_pkgconf += cairo-quartz-image.pc
ifeq ($(CAIRO_HAS_QUARTZ_IMAGE_SURFACE),1)
enabled_cairo_pkgconf += cairo-quartz-image.pc
endif
supported_cairo_headers += $(cairo_win32_headers)
all_cairo_headers += $(cairo_win32_headers)
all_cairo_private += $(cairo_win32_private)
all_cairo_cxx_sources += $(cairo_win32_cxx_sources)
all_cairo_sources += $(cairo_win32_sources)
ifeq ($(CAIRO_HAS_WIN32_SURFACE),1)
enabled_cairo_headers += $(cairo_win32_headers)
enabled_cairo_private += $(cairo_win32_private)
enabled_cairo_cxx_sources += $(cairo_win32_cxx_sources)
enabled_cairo_sources += $(cairo_win32_sources)
endif
all_cairo_pkgconf += cairo-win32.pc
ifeq ($(CAIRO_HAS_WIN32_SURFACE),1)
enabled_cairo_pkgconf += cairo-win32.pc
endif
supported_cairo_headers += $(cairo_win32_font_headers)
all_cairo_headers += $(cairo_win32_font_headers)
all_cairo_private += $(cairo_win32_font_private)
all_cairo_cxx_sources += $(cairo_win32_font_cxx_sources)
all_cairo_sources += $(cairo_win32_font_sources)
ifeq ($(CAIRO_HAS_WIN32_FONT),1)
enabled_cairo_headers += $(cairo_win32_font_headers)
enabled_cairo_private += $(cairo_win32_font_private)
enabled_cairo_cxx_sources += $(cairo_win32_font_cxx_sources)
enabled_cairo_sources += $(cairo_win32_font_sources)
endif
all_cairo_pkgconf += cairo-win32-font.pc
ifeq ($(CAIRO_HAS_WIN32_FONT),1)
enabled_cairo_pkgconf += cairo-win32-font.pc
endif
unsupported_cairo_headers += $(cairo_os2_headers)
all_cairo_headers += $(cairo_os2_headers)
all_cairo_private += $(cairo_os2_private)
all_cairo_cxx_sources += $(cairo_os2_cxx_sources)
all_cairo_sources += $(cairo_os2_sources)
ifeq ($(CAIRO_HAS_OS2_SURFACE),1)
enabled_cairo_headers += $(cairo_os2_headers)
enabled_cairo_private += $(cairo_os2_private)
enabled_cairo_cxx_sources += $(cairo_os2_cxx_sources)
enabled_cairo_sources += $(cairo_os2_sources)
endif
all_cairo_pkgconf += cairo-os2.pc
ifeq ($(CAIRO_HAS_OS2_SURFACE),1)
enabled_cairo_pkgconf += cairo-os2.pc
endif
unsupported_cairo_headers += $(cairo_beos_headers)
all_cairo_headers += $(cairo_beos_headers)
all_cairo_private += $(cairo_beos_private)
all_cairo_cxx_sources += $(cairo_beos_cxx_sources)
all_cairo_sources += $(cairo_beos_sources)
ifeq ($(CAIRO_HAS_BEOS_SURFACE),1)
enabled_cairo_headers += $(cairo_beos_headers)
enabled_cairo_private += $(cairo_beos_private)
enabled_cairo_cxx_sources += $(cairo_beos_cxx_sources)
enabled_cairo_sources += $(cairo_beos_sources)
endif
all_cairo_pkgconf += cairo-beos.pc
ifeq ($(CAIRO_HAS_BEOS_SURFACE),1)
enabled_cairo_pkgconf += cairo-beos.pc
endif
unsupported_cairo_headers += $(cairo_drm_headers)
all_cairo_headers += $(cairo_drm_headers)
all_cairo_private += $(cairo_drm_private)
all_cairo_cxx_sources += $(cairo_drm_cxx_sources)
all_cairo_sources += $(cairo_drm_sources)
ifeq ($(CAIRO_HAS_DRM_SURFACE),1)
enabled_cairo_headers += $(cairo_drm_headers)
enabled_cairo_private += $(cairo_drm_private)
enabled_cairo_cxx_sources += $(cairo_drm_cxx_sources)
enabled_cairo_sources += $(cairo_drm_sources)
endif
all_cairo_pkgconf += cairo-drm.pc
ifeq ($(CAIRO_HAS_DRM_SURFACE),1)
enabled_cairo_pkgconf += cairo-drm.pc
endif
unsupported_cairo_headers += $(cairo_gallium_headers)
all_cairo_headers += $(cairo_gallium_headers)
all_cairo_private += $(cairo_gallium_private)
all_cairo_cxx_sources += $(cairo_gallium_cxx_sources)
all_cairo_sources += $(cairo_gallium_sources)
ifeq ($(CAIRO_HAS_GALLIUM_SURFACE),1)
enabled_cairo_headers += $(cairo_gallium_headers)
enabled_cairo_private += $(cairo_gallium_private)
enabled_cairo_cxx_sources += $(cairo_gallium_cxx_sources)
enabled_cairo_sources += $(cairo_gallium_sources)
endif
all_cairo_pkgconf += cairo-gallium.pc
ifeq ($(CAIRO_HAS_GALLIUM_SURFACE),1)
enabled_cairo_pkgconf += cairo-gallium.pc
endif
supported_cairo_headers += $(cairo_png_headers)
all_cairo_headers += $(cairo_png_headers)
all_cairo_private += $(cairo_png_private)
all_cairo_cxx_sources += $(cairo_png_cxx_sources)
all_cairo_sources += $(cairo_png_sources)
ifeq ($(CAIRO_HAS_PNG_FUNCTIONS),1)
enabled_cairo_headers += $(cairo_png_headers)
enabled_cairo_private += $(cairo_png_private)
enabled_cairo_cxx_sources += $(cairo_png_cxx_sources)
enabled_cairo_sources += $(cairo_png_sources)
endif
all_cairo_pkgconf += cairo-png.pc
ifeq ($(CAIRO_HAS_PNG_FUNCTIONS),1)
enabled_cairo_pkgconf += cairo-png.pc
endif
unsupported_cairo_headers += $(cairo_gl_headers)
all_cairo_headers += $(cairo_gl_headers)
all_cairo_private += $(cairo_gl_private)
all_cairo_cxx_sources += $(cairo_gl_cxx_sources)
all_cairo_sources += $(cairo_gl_sources)
ifeq ($(CAIRO_HAS_GL_SURFACE),1)
enabled_cairo_headers += $(cairo_gl_headers)
enabled_cairo_private += $(cairo_gl_private)
enabled_cairo_cxx_sources += $(cairo_gl_cxx_sources)
enabled_cairo_sources += $(cairo_gl_sources)
endif
all_cairo_pkgconf += cairo-gl.pc
ifeq ($(CAIRO_HAS_GL_SURFACE),1)
enabled_cairo_pkgconf += cairo-gl.pc
endif
unsupported_cairo_headers += $(cairo_glesv2_headers)
all_cairo_headers += $(cairo_glesv2_headers)
all_cairo_private += $(cairo_glesv2_private)
all_cairo_cxx_sources += $(cairo_glesv2_cxx_sources)
all_cairo_sources += $(cairo_glesv2_sources)
ifeq ($(CAIRO_HAS_GLESV2_SURFACE),1)
enabled_cairo_headers += $(cairo_glesv2_headers)
enabled_cairo_private += $(cairo_glesv2_private)
enabled_cairo_cxx_sources += $(cairo_glesv2_cxx_sources)
enabled_cairo_sources += $(cairo_glesv2_sources)
endif
all_cairo_pkgconf += cairo-glesv2.pc
ifeq ($(CAIRO_HAS_GLESV2_SURFACE),1)
enabled_cairo_pkgconf += cairo-glesv2.pc
endif
unsupported_cairo_headers += $(cairo_glesv3_headers)
all_cairo_headers += $(cairo_glesv3_headers)
all_cairo_private += $(cairo_glesv3_private)
all_cairo_cxx_sources += $(cairo_glesv3_cxx_sources)
all_cairo_sources += $(cairo_glesv3_sources)
ifeq ($(CAIRO_HAS_GLESV3_SURFACE),1)
enabled_cairo_headers += $(cairo_glesv3_headers)
enabled_cairo_private += $(cairo_glesv3_private)
enabled_cairo_cxx_sources += $(cairo_glesv3_cxx_sources)
enabled_cairo_sources += $(cairo_glesv3_sources)
endif
all_cairo_pkgconf += cairo-glesv3.pc
ifeq ($(CAIRO_HAS_GLESV3_SURFACE),1)
enabled_cairo_pkgconf += cairo-glesv3.pc
endif
unsupported_cairo_headers += $(cairo_cogl_headers)
all_cairo_headers += $(cairo_cogl_headers)
all_cairo_private += $(cairo_cogl_private)
all_cairo_cxx_sources += $(cairo_cogl_cxx_sources)
all_cairo_sources += $(cairo_cogl_sources)
ifeq ($(CAIRO_HAS_COGL_SURFACE),1)
enabled_cairo_headers += $(cairo_cogl_headers)
enabled_cairo_private += $(cairo_cogl_private)
enabled_cairo_cxx_sources += $(cairo_cogl_cxx_sources)
enabled_cairo_sources += $(cairo_cogl_sources)
endif
all_cairo_pkgconf += cairo-cogl.pc
ifeq ($(CAIRO_HAS_COGL_SURFACE),1)
enabled_cairo_pkgconf += cairo-cogl.pc
endif
unsupported_cairo_headers += $(cairo_directfb_headers)
all_cairo_headers += $(cairo_directfb_headers)
all_cairo_private += $(cairo_directfb_private)
all_cairo_cxx_sources += $(cairo_directfb_cxx_sources)
all_cairo_sources += $(cairo_directfb_sources)
ifeq ($(CAIRO_HAS_DIRECTFB_SURFACE),1)
enabled_cairo_headers += $(cairo_directfb_headers)
enabled_cairo_private += $(cairo_directfb_private)
enabled_cairo_cxx_sources += $(cairo_directfb_cxx_sources)
enabled_cairo_sources += $(cairo_directfb_sources)
endif
all_cairo_pkgconf += cairo-directfb.pc
ifeq ($(CAIRO_HAS_DIRECTFB_SURFACE),1)
enabled_cairo_pkgconf += cairo-directfb.pc
endif
unsupported_cairo_headers += $(cairo_vg_headers)
all_cairo_headers += $(cairo_vg_headers)
all_cairo_private += $(cairo_vg_private)
all_cairo_cxx_sources += $(cairo_vg_cxx_sources)
all_cairo_sources += $(cairo_vg_sources)
ifeq ($(CAIRO_HAS_VG_SURFACE),1)
enabled_cairo_headers += $(cairo_vg_headers)
enabled_cairo_private += $(cairo_vg_private)
enabled_cairo_cxx_sources += $(cairo_vg_cxx_sources)
enabled_cairo_sources += $(cairo_vg_sources)
endif
all_cairo_pkgconf += cairo-vg.pc
ifeq ($(CAIRO_HAS_VG_SURFACE),1)
enabled_cairo_pkgconf += cairo-vg.pc
endif
supported_cairo_headers += $(cairo_egl_headers)
all_cairo_headers += $(cairo_egl_headers)
all_cairo_private += $(cairo_egl_private)
all_cairo_cxx_sources += $(cairo_egl_cxx_sources)
all_cairo_sources += $(cairo_egl_sources)
ifeq ($(CAIRO_HAS_EGL_FUNCTIONS),1)
enabled_cairo_headers += $(cairo_egl_headers)
enabled_cairo_private += $(cairo_egl_private)
enabled_cairo_cxx_sources += $(cairo_egl_cxx_sources)
enabled_cairo_sources += $(cairo_egl_sources)
endif
all_cairo_pkgconf += cairo-egl.pc
ifeq ($(CAIRO_HAS_EGL_FUNCTIONS),1)
enabled_cairo_pkgconf += cairo-egl.pc
endif
supported_cairo_headers += $(cairo_glx_headers)
all_cairo_headers += $(cairo_glx_headers)
all_cairo_private += $(cairo_glx_private)
all_cairo_cxx_sources += $(cairo_glx_cxx_sources)
all_cairo_sources += $(cairo_glx_sources)
ifeq ($(CAIRO_HAS_GLX_FUNCTIONS),1)
enabled_cairo_headers += $(cairo_glx_headers)
enabled_cairo_private += $(cairo_glx_private)
enabled_cairo_cxx_sources += $(cairo_glx_cxx_sources)
enabled_cairo_sources += $(cairo_glx_sources)
endif
all_cairo_pkgconf += cairo-glx.pc
ifeq ($(CAIRO_HAS_GLX_FUNCTIONS),1)
enabled_cairo_pkgconf += cairo-glx.pc
endif
supported_cairo_headers += $(cairo_wgl_headers)
all_cairo_headers += $(cairo_wgl_headers)
all_cairo_private += $(cairo_wgl_private)
all_cairo_cxx_sources += $(cairo_wgl_cxx_sources)
all_cairo_sources += $(cairo_wgl_sources)
ifeq ($(CAIRO_HAS_WGL_FUNCTIONS),1)
enabled_cairo_headers += $(cairo_wgl_headers)
enabled_cairo_private += $(cairo_wgl_private)
enabled_cairo_cxx_sources += $(cairo_wgl_cxx_sources)
enabled_cairo_sources += $(cairo_wgl_sources)
endif
all_cairo_pkgconf += cairo-wgl.pc
ifeq ($(CAIRO_HAS_WGL_FUNCTIONS),1)
enabled_cairo_pkgconf += cairo-wgl.pc
endif
supported_cairo_headers += $(cairo_script_headers)
all_cairo_headers += $(cairo_script_headers)
all_cairo_private += $(cairo_script_private)
all_cairo_cxx_sources += $(cairo_script_cxx_sources)
all_cairo_sources += $(cairo_script_sources)
ifeq ($(CAIRO_HAS_SCRIPT_SURFACE),1)
enabled_cairo_headers += $(cairo_script_headers)
enabled_cairo_private += $(cairo_script_private)
enabled_cairo_cxx_sources += $(cairo_script_cxx_sources)
enabled_cairo_sources += $(cairo_script_sources)
endif
all_cairo_pkgconf += cairo-script.pc
ifeq ($(CAIRO_HAS_SCRIPT_SURFACE),1)
enabled_cairo_pkgconf += cairo-script.pc
endif
supported_cairo_headers += $(cairo_ft_headers)
all_cairo_headers += $(cairo_ft_headers)
all_cairo_private += $(cairo_ft_private)
all_cairo_cxx_sources += $(cairo_ft_cxx_sources)
all_cairo_sources += $(cairo_ft_sources)
ifeq ($(CAIRO_HAS_FT_FONT),1)
enabled_cairo_headers += $(cairo_ft_headers)
enabled_cairo_private += $(cairo_ft_private)
enabled_cairo_cxx_sources += $(cairo_ft_cxx_sources)
enabled_cairo_sources += $(cairo_ft_sources)
endif
all_cairo_pkgconf += cairo-ft.pc
ifeq ($(CAIRO_HAS_FT_FONT),1)
enabled_cairo_pkgconf += cairo-ft.pc
endif
supported_cairo_headers += $(cairo_fc_headers)
all_cairo_headers += $(cairo_fc_headers)
all_cairo_private += $(cairo_fc_private)
all_cairo_cxx_sources += $(cairo_fc_cxx_sources)
all_cairo_sources += $(cairo_fc_sources)
ifeq ($(CAIRO_HAS_FC_FONT),1)
enabled_cairo_headers += $(cairo_fc_headers)
enabled_cairo_private += $(cairo_fc_private)
enabled_cairo_cxx_sources += $(cairo_fc_cxx_sources)
enabled_cairo_sources += $(cairo_fc_sources)
endif
all_cairo_pkgconf += cairo-fc.pc
ifeq ($(CAIRO_HAS_FC_FONT),1)
enabled_cairo_pkgconf += cairo-fc.pc
endif
supported_cairo_headers += $(cairo_ps_headers)
all_cairo_headers += $(cairo_ps_headers)
all_cairo_private += $(cairo_ps_private)
all_cairo_cxx_sources += $(cairo_ps_cxx_sources)
all_cairo_sources += $(cairo_ps_sources)
ifeq ($(CAIRO_HAS_PS_SURFACE),1)
enabled_cairo_headers += $(cairo_ps_headers)
enabled_cairo_private += $(cairo_ps_private)
enabled_cairo_cxx_sources += $(cairo_ps_cxx_sources)
enabled_cairo_sources += $(cairo_ps_sources)
endif
all_cairo_pkgconf += cairo-ps.pc
ifeq ($(CAIRO_HAS_PS_SURFACE),1)
enabled_cairo_pkgconf += cairo-ps.pc
endif
supported_cairo_headers += $(cairo_pdf_headers)
all_cairo_headers += $(cairo_pdf_headers)
all_cairo_private += $(cairo_pdf_private)
all_cairo_cxx_sources += $(cairo_pdf_cxx_sources)
all_cairo_sources += $(cairo_pdf_sources)
ifeq ($(CAIRO_HAS_PDF_SURFACE),1)
enabled_cairo_headers += $(cairo_pdf_headers)
enabled_cairo_private += $(cairo_pdf_private)
enabled_cairo_cxx_sources += $(cairo_pdf_cxx_sources)
enabled_cairo_sources += $(cairo_pdf_sources)
endif
all_cairo_pkgconf += cairo-pdf.pc
ifeq ($(CAIRO_HAS_PDF_SURFACE),1)
enabled_cairo_pkgconf += cairo-pdf.pc
endif
supported_cairo_headers += $(cairo_svg_headers)
all_cairo_headers += $(cairo_svg_headers)
all_cairo_private += $(cairo_svg_private)
all_cairo_cxx_sources += $(cairo_svg_cxx_sources)
all_cairo_sources += $(cairo_svg_sources)
ifeq ($(CAIRO_HAS_SVG_SURFACE),1)
enabled_cairo_headers += $(cairo_svg_headers)
enabled_cairo_private += $(cairo_svg_private)
enabled_cairo_cxx_sources += $(cairo_svg_cxx_sources)
enabled_cairo_sources += $(cairo_svg_sources)
endif
all_cairo_pkgconf += cairo-svg.pc
ifeq ($(CAIRO_HAS_SVG_SURFACE),1)
enabled_cairo_pkgconf += cairo-svg.pc
endif
all_cairo_private += $(cairo_test_surfaces_private) $(cairo_test_surfaces_headers)
all_cairo_cxx_sources += $(cairo_test_surfaces_cxx_sources)
all_cairo_sources += $(cairo_test_surfaces_sources)
ifeq ($(CAIRO_HAS_TEST_SURFACES),1)
enabled_cairo_private += $(cairo_test_surfaces_private) $(cairo_test_surfaces_headers)
enabled_cairo_cxx_sources += $(cairo_test_surfaces_cxx_sources)
enabled_cairo_sources += $(cairo_test_surfaces_sources)
endif
supported_cairo_headers += $(cairo_image_headers)
all_cairo_headers += $(cairo_image_headers)
all_cairo_private += $(cairo_image_private)
all_cairo_cxx_sources += $(cairo_image_cxx_sources)
all_cairo_sources += $(cairo_image_sources)
enabled_cairo_headers += $(cairo_image_headers)
enabled_cairo_private += $(cairo_image_private)
enabled_cairo_cxx_sources += $(cairo_image_cxx_sources)
enabled_cairo_sources += $(cairo_image_sources)
supported_cairo_headers += $(cairo_mime_headers)
all_cairo_headers += $(cairo_mime_headers)
all_cairo_private += $(cairo_mime_private)
all_cairo_cxx_sources += $(cairo_mime_cxx_sources)
all_cairo_sources += $(cairo_mime_sources)
enabled_cairo_headers += $(cairo_mime_headers)
enabled_cairo_private += $(cairo_mime_private)
enabled_cairo_cxx_sources += $(cairo_mime_cxx_sources)
enabled_cairo_sources += $(cairo_mime_sources)
supported_cairo_headers += $(cairo_recording_headers)
all_cairo_headers += $(cairo_recording_headers)
all_cairo_private += $(cairo_recording_private)
all_cairo_cxx_sources += $(cairo_recording_cxx_sources)
all_cairo_sources += $(cairo_recording_sources)
enabled_cairo_headers += $(cairo_recording_headers)
enabled_cairo_private += $(cairo_recording_private)
enabled_cairo_cxx_sources += $(cairo_recording_cxx_sources)
enabled_cairo_sources += $(cairo_recording_sources)
supported_cairo_headers += $(cairo_observer_headers)
all_cairo_headers += $(cairo_observer_headers)
all_cairo_private += $(cairo_observer_private)
all_cairo_cxx_sources += $(cairo_observer_cxx_sources)
all_cairo_sources += $(cairo_observer_sources)
enabled_cairo_headers += $(cairo_observer_headers)
enabled_cairo_private += $(cairo_observer_private)
enabled_cairo_cxx_sources += $(cairo_observer_cxx_sources)
enabled_cairo_sources += $(cairo_observer_sources)
unsupported_cairo_headers += $(cairo_tee_headers)
all_cairo_headers += $(cairo_tee_headers)
all_cairo_private += $(cairo_tee_private)
all_cairo_cxx_sources += $(cairo_tee_cxx_sources)
all_cairo_sources += $(cairo_tee_sources)
ifeq ($(CAIRO_HAS_TEE_SURFACE),1)
enabled_cairo_headers += $(cairo_tee_headers)
enabled_cairo_private += $(cairo_tee_private)
enabled_cairo_cxx_sources += $(cairo_tee_cxx_sources)
enabled_cairo_sources += $(cairo_tee_sources)
endif
all_cairo_pkgconf += cairo-tee.pc
ifeq ($(CAIRO_HAS_TEE_SURFACE),1)
enabled_cairo_pkgconf += cairo-tee.pc
endif
unsupported_cairo_headers += $(cairo_xml_headers)
all_cairo_headers += $(cairo_xml_headers)
all_cairo_private += $(cairo_xml_private)
all_cairo_cxx_sources += $(cairo_xml_cxx_sources)
all_cairo_sources += $(cairo_xml_sources)
ifeq ($(CAIRO_HAS_XML_SURFACE),1)
enabled_cairo_headers += $(cairo_xml_headers)
enabled_cairo_private += $(cairo_xml_private)
enabled_cairo_cxx_sources += $(cairo_xml_cxx_sources)
enabled_cairo_sources += $(cairo_xml_sources)
endif
all_cairo_pkgconf += cairo-xml.pc
ifeq ($(CAIRO_HAS_XML_SURFACE),1)
enabled_cairo_pkgconf += cairo-xml.pc
endif
supported_cairo_headers += $(cairo_user_headers)
all_cairo_headers += $(cairo_user_headers)
all_cairo_private += $(cairo_user_private)
all_cairo_cxx_sources += $(cairo_user_cxx_sources)
all_cairo_sources += $(cairo_user_sources)
enabled_cairo_headers += $(cairo_user_headers)
enabled_cairo_private += $(cairo_user_private)
enabled_cairo_cxx_sources += $(cairo_user_cxx_sources)
enabled_cairo_sources += $(cairo_user_sources)
all_cairo_private += $(cairo_pthread_private) $(cairo_pthread_headers)
all_cairo_cxx_sources += $(cairo_pthread_cxx_sources)
all_cairo_sources += $(cairo_pthread_sources)
ifeq ($(CAIRO_HAS_PTHREAD),1)
enabled_cairo_private += $(cairo_pthread_private) $(cairo_pthread_headers)
enabled_cairo_cxx_sources += $(cairo_pthread_cxx_sources)
enabled_cairo_sources += $(cairo_pthread_sources)
endif
supported_cairo_headers += $(cairo_gobject_headers)
all_cairo_headers += $(cairo_gobject_headers)
all_cairo_private += $(cairo_gobject_private)
all_cairo_cxx_sources += $(cairo_gobject_cxx_sources)
all_cairo_sources += $(cairo_gobject_sources)
ifeq ($(CAIRO_HAS_GOBJECT_FUNCTIONS),1)
enabled_cairo_headers += $(cairo_gobject_headers)
enabled_cairo_private += $(cairo_gobject_private)
enabled_cairo_cxx_sources += $(cairo_gobject_cxx_sources)
enabled_cairo_sources += $(cairo_gobject_sources)
endif
all_cairo_pkgconf += cairo-gobject.pc
ifeq ($(CAIRO_HAS_GOBJECT_FUNCTIONS),1)
enabled_cairo_pkgconf += cairo-gobject.pc
endif
all_cairo_private += $(cairo_trace_private) $(cairo_trace_headers)
all_cairo_cxx_sources += $(cairo_trace_cxx_sources)
all_cairo_sources += $(cairo_trace_sources)
ifeq ($(CAIRO_HAS_TRACE),1)
enabled_cairo_private += $(cairo_trace_private) $(cairo_trace_headers)
enabled_cairo_cxx_sources += $(cairo_trace_cxx_sources)
enabled_cairo_sources += $(cairo_trace_sources)
endif
all_cairo_private += $(cairo_interpreter_private) $(cairo_interpreter_headers)
all_cairo_cxx_sources += $(cairo_interpreter_cxx_sources)
all_cairo_sources += $(cairo_interpreter_sources)
ifeq ($(CAIRO_HAS_INTERPRETER),1)
enabled_cairo_private += $(cairo_interpreter_private) $(cairo_interpreter_headers)
enabled_cairo_cxx_sources += $(cairo_interpreter_cxx_sources)
enabled_cairo_sources += $(cairo_interpreter_sources)
endif
all_cairo_private += $(cairo_symbol_lookup_private) $(cairo_symbol_lookup_headers)
all_cairo_cxx_sources += $(cairo_symbol_lookup_cxx_sources)
all_cairo_sources += $(cairo_symbol_lookup_sources)
ifeq ($(CAIRO_HAS_SYMBOL_LOOKUP),1)
enabled_cairo_private += $(cairo_symbol_lookup_private) $(cairo_symbol_lookup_headers)
enabled_cairo_cxx_sources += $(cairo_symbol_lookup_cxx_sources)
enabled_cairo_sources += $(cairo_symbol_lookup_sources)
endif

Просмотреть файл

@ -0,0 +1,69 @@
Cairo Library Source Code
=========================
This directory contains the source code of the cairo library.
Source Code Listing
-------------------
The canonical list of source files is the file Makefile.sources. See that
file for how it works.
New Backends
------------
The rule of the thumb for adding new backends is to see how other
backends are integrated. Pick one of the simpler, unsupported, backends
and search the entire tree for it, and go from there.
To add new backends you need to basically:
* Modify $(top_srcdir)/configure.in to add checks for your backend.
* Modify Makefile.sources to add source files for your backend,
* Modify $(top_srcdir)/boilerplate/ to add boilerplate code for
testing your new backend.
New API
-------
After adding new API, run "make check" in this directory and fix any
reported issues. Also add new API to the right location in
$(top_srcdir)/doc/public/cairo-sections.txt and run "make check"
in $(top_builddir)/doc/public to make sure that any newly added
documentation is correctly hooked up.
Do not forget to add tests for the new API. See next section.
Tests
-----
There are some tests in this directory that check the source code and
the build for various issues. The tests are very quick to run, and
particularly should be run after any documentation or API changes. It
does not hurt to run them after any source modification either. Run
them simply by calling:
make check
There are also extensive regression tests in $(top_srcdir)/test. It is
a good idea to run that test suite for any changes made to the source
code. Moreover, for any new feature, API, or bug fix, new tests should
be added to the regression test suite to test the new code.
Bibliography
------------
A detailed list of academic publications used in cairo code is available
in the file $(top_srcdir)/BIBLIOGRAPHY. Feel free to update as you
implement more papers.
For more technical publications (eg. Adobe technical reports) just
point them out in a comment in the header of the file implementing them.

Просмотреть файл

@ -37,8 +37,6 @@
#include "cairoint.h"
CAIRO_BEGIN_DECLS
cairo_private cairo_surface_t *
_cairo_analysis_surface_create (cairo_surface_t *target);
@ -70,6 +68,7 @@ cairo_private cairo_int_status_t
_cairo_analysis_surface_merge_status (cairo_int_status_t status_a,
cairo_int_status_t status_b);
CAIRO_END_DECLS
cairo_private cairo_surface_t *
_cairo_null_surface_create (cairo_content_t content);
#endif /* CAIRO_ANALYSIS_SURFACE_H */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -38,6 +38,8 @@
#include "cairoint.h"
CAIRO_BEGIN_DECLS
cairo_private void
_cairo_arc_path (cairo_t *cr,
double xc,
@ -54,4 +56,6 @@ _cairo_arc_path_negative (cairo_t *cr,
double angle1,
double angle2);
CAIRO_END_DECLS
#endif /* CAIRO_ARC_PRIVATE_H */

Просмотреть файл

@ -38,6 +38,8 @@
#include "cairo-arc-private.h"
#define MAX_FULL_CIRCLES 65536
/* Spline deviation from the circle in radius would be given by:
error = sqrt (x**2 + y**2) - 1
@ -131,13 +133,13 @@ _arc_segments_needed (double angle,
for some value of h.
"Approximation of circular arcs by cubic poynomials", Michael
"Approximation of circular arcs by cubic polynomials", Michael
Goldapp, Computer Aided Geometric Design 8 (1991) 227-238, provides
various values of h along with error analysis for each.
From that paper, a very practical value of h is:
h = 4/3 * tan(angle/4)
h = 4/3 * R * tan(angle/4)
This value does not give the spline with minimal error, but it does
provide a very good approximation, (6th-order convergence), and the
@ -184,8 +186,13 @@ _cairo_arc_in_direction (cairo_t *cr,
if (cairo_status (cr))
return;
while (angle_max - angle_min > 4 * M_PI)
angle_max -= 2 * M_PI;
assert (angle_max >= angle_min);
if (angle_max - angle_min > 2 * M_PI * MAX_FULL_CIRCLES) {
angle_max = fmod (angle_max - angle_min, 2 * M_PI);
angle_min = fmod (angle_min, 2 * M_PI);
angle_max += angle_min + 2 * M_PI * MAX_FULL_CIRCLES;
}
/* Recurse if drawing arc larger than pi */
if (angle_max - angle_min > M_PI) {
@ -210,32 +217,45 @@ _cairo_arc_in_direction (cairo_t *cr,
} else if (angle_max != angle_min) {
cairo_matrix_t ctm;
int i, segments;
double angle, angle_step;
double step;
cairo_get_matrix (cr, &ctm);
segments = _arc_segments_needed (angle_max - angle_min,
radius, &ctm,
cairo_get_tolerance (cr));
angle_step = (angle_max - angle_min) / (double) segments;
step = (angle_max - angle_min) / segments;
segments -= 1;
if (dir == CAIRO_DIRECTION_FORWARD) {
angle = angle_min;
} else {
angle = angle_max;
angle_step = - angle_step;
if (dir == CAIRO_DIRECTION_REVERSE) {
double t;
t = angle_min;
angle_min = angle_max;
angle_max = t;
step = -step;
}
for (i = 0; i < segments; i++, angle += angle_step) {
_cairo_arc_segment (cr, xc, yc,
radius,
angle,
angle + angle_step);
cairo_line_to (cr,
xc + radius * cos (angle_min),
yc + radius * sin (angle_min));
for (i = 0; i < segments; i++, angle_min += step) {
_cairo_arc_segment (cr, xc, yc, radius,
angle_min, angle_min + step);
}
_cairo_arc_segment (cr, xc, yc, radius,
angle_min, angle_max);
} else {
cairo_line_to (cr,
xc + radius * cos (angle_min),
yc + radius * sin (angle_min));
}
}
/**
* _cairo_arc_path
* _cairo_arc_path:
* @cr: a cairo context
* @xc: X position of the center of the arc
* @yc: Y position of the center of the arc

Просмотреть файл

@ -0,0 +1,90 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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>
*/
#ifndef CAIRO_ARRAY_PRIVATE_H
#define CAIRO_ARRAY_PRIVATE_H
#include "cairo-compiler-private.h"
#include "cairo-types-private.h"
CAIRO_BEGIN_DECLS
/* cairo-array.c structures and functions */
cairo_private void
_cairo_array_init (cairo_array_t *array, unsigned int element_size);
cairo_private void
_cairo_array_fini (cairo_array_t *array);
cairo_private cairo_status_t
_cairo_array_grow_by (cairo_array_t *array, unsigned int additional);
cairo_private void
_cairo_array_truncate (cairo_array_t *array, unsigned int num_elements);
cairo_private cairo_status_t
_cairo_array_append (cairo_array_t *array, const void *element);
cairo_private cairo_status_t
_cairo_array_append_multiple (cairo_array_t *array,
const void *elements,
unsigned int num_elements);
cairo_private cairo_status_t
_cairo_array_allocate (cairo_array_t *array,
unsigned int num_elements,
void **elements);
cairo_private void *
_cairo_array_index (cairo_array_t *array, unsigned int index);
cairo_private const void *
_cairo_array_index_const (const cairo_array_t *array, unsigned int index);
cairo_private void
_cairo_array_copy_element (const cairo_array_t *array, unsigned int index, void *dst);
cairo_private unsigned int
_cairo_array_num_elements (const cairo_array_t *array);
cairo_private unsigned int
_cairo_array_size (const cairo_array_t *array);
CAIRO_END_DECLS
#endif /* CAIRO_ARRAY_PRIVATE_H */

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 Red Hat, Inc
@ -36,6 +37,7 @@
*/
#include "cairoint.h"
#include "cairo-array-private.h"
#include "cairo-error-private.h"
/**
@ -53,39 +55,12 @@
* called to free resources allocated during use of the array.
**/
void
_cairo_array_init (cairo_array_t *array, int element_size)
_cairo_array_init (cairo_array_t *array, unsigned int element_size)
{
array->size = 0;
array->num_elements = 0;
array->element_size = element_size;
array->elements = NULL;
array->is_snapshot = FALSE;
}
/**
* _cairo_array_init_snapshot:
* @array: A #cairo_array_t to be initialized as a snapshot
* @other: The #cairo_array_t from which to create the snapshot
*
* Initialize @array as an immutable copy of @other. It is an error to
* call an array-modifying function (other than _cairo_array_fini) on
* @array after calling this function.
**/
void
_cairo_array_init_snapshot (cairo_array_t *array,
const cairo_array_t *other)
{
array->size = other->size;
array->num_elements = other->num_elements;
array->element_size = other->element_size;
array->elements = other->elements;
array->is_snapshot = TRUE;
if (array->num_elements != 0 && *array->elements == NULL)
abort();
}
/**
@ -99,18 +74,7 @@ _cairo_array_init_snapshot (cairo_array_t *array,
void
_cairo_array_fini (cairo_array_t *array)
{
if (array->is_snapshot)
return;
if (array->num_elements != 0 && *array->elements == NULL)
abort();
if (array->elements) {
free (* array->elements);
free (array->elements);
array->elements = NULL;
array->num_elements = 0;
}
free (array->elements);
}
/**
@ -129,8 +93,6 @@ _cairo_array_grow_by (cairo_array_t *array, unsigned int additional)
unsigned int required_size = array->num_elements + additional;
unsigned int new_size;
assert (! array->is_snapshot);
/* check for integer overflow */
if (required_size > INT_MAX || required_size < array->num_elements)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@ -149,16 +111,8 @@ _cairo_array_grow_by (cairo_array_t *array, unsigned int additional)
while (new_size < required_size)
new_size = new_size * 2;
if (array->elements == NULL) {
array->elements = malloc (sizeof (char *));
if (unlikely (array->elements == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
*array->elements = NULL;
}
array->size = new_size;
new_elements = _cairo_realloc_ab (*array->elements,
new_elements = _cairo_realloc_ab (array->elements,
array->size, array->element_size);
if (unlikely (new_elements == NULL)) {
@ -166,10 +120,7 @@ _cairo_array_grow_by (cairo_array_t *array, unsigned int additional)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
*array->elements = new_elements;
if (array->num_elements != 0 && *array->elements == NULL)
abort();
array->elements = new_elements;
return CAIRO_STATUS_SUCCESS;
}
@ -185,13 +136,8 @@ _cairo_array_grow_by (cairo_array_t *array, unsigned int additional)
void
_cairo_array_truncate (cairo_array_t *array, unsigned int num_elements)
{
assert (! array->is_snapshot);
if (num_elements < array->num_elements)
array->num_elements = num_elements;
if (array->num_elements != 0 && *array->elements == NULL)
abort();
}
/**
@ -222,7 +168,7 @@ _cairo_array_index (cairo_array_t *array, unsigned int index)
/* We allow an index of 0 for the no-elements case.
* This makes for cleaner calling code which will often look like:
*
* elements = _cairo_array_index (array, num_elements);
* elements = _cairo_array_index (array, 0);
* for (i=0; i < num_elements; i++) {
* ... use elements[i] here ...
* }
@ -235,10 +181,51 @@ _cairo_array_index (cairo_array_t *array, unsigned int index)
assert (index < array->num_elements);
if (array->num_elements != 0 && *array->elements == NULL)
abort();
return array->elements + index * array->element_size;
}
return (void *) &(*array->elements)[index * array->element_size];
/**
* _cairo_array_index_const:
* @array: a #cairo_array_t
* Returns: A pointer to the object stored at @index.
*
* If the resulting value is assigned to a pointer to an object of the same
* element_size as initially passed to _cairo_array_init() then that
* pointer may be used for further direct indexing with []. For
* example:
*
* <informalexample><programlisting>
* cairo_array_t array;
* const double *values;
*
* _cairo_array_init (&array, sizeof(double));
* ... calls to _cairo_array_append() here ...
*
* values = _cairo_array_index_const (&array, 0);
* for (i = 0; i < _cairo_array_num_elements (&array); i++)
* ... read values[i] here ...
* </programlisting></informalexample>
**/
const void *
_cairo_array_index_const (const cairo_array_t *array, unsigned int index)
{
/* We allow an index of 0 for the no-elements case.
* This makes for cleaner calling code which will often look like:
*
* elements = _cairo_array_index_const (array, 0);
* for (i=0; i < num_elements; i++) {
* ... read elements[i] here ...
* }
*
* which in the num_elements==0 case gets the NULL pointer here,
* but never dereferences it.
*/
if (index == 0 && array->num_elements == 0)
return NULL;
assert (index < array->num_elements);
return array->elements + index * array->element_size;
}
/**
@ -249,9 +236,11 @@ _cairo_array_index (cairo_array_t *array, unsigned int index)
* location pointed to by @dst.
**/
void
_cairo_array_copy_element (cairo_array_t *array, int index, void *dst)
_cairo_array_copy_element (const cairo_array_t *array,
unsigned int index,
void *dst)
{
memcpy (dst, _cairo_array_index (array, index), array->element_size);
memcpy (dst, _cairo_array_index_const (array, index), array->element_size);
}
/**
@ -273,8 +262,6 @@ cairo_status_t
_cairo_array_append (cairo_array_t *array,
const void *element)
{
assert (! array->is_snapshot);
return _cairo_array_append_multiple (array, element, 1);
}
@ -293,22 +280,17 @@ _cairo_array_append (cairo_array_t *array,
cairo_status_t
_cairo_array_append_multiple (cairo_array_t *array,
const void *elements,
int num_elements)
unsigned int num_elements)
{
cairo_status_t status;
void *dest;
assert (! array->is_snapshot);
status = _cairo_array_allocate (array, num_elements, &dest);
if (unlikely (status))
return status;
memcpy (dest, elements, num_elements * array->element_size);
if (array->num_elements != 0 && *array->elements == NULL)
abort();
return CAIRO_STATUS_SUCCESS;
}
@ -318,7 +300,7 @@ _cairo_array_append_multiple (cairo_array_t *array,
*
* Allocate space at the end of the array for @num_elements additional
* elements, providing the address of the new memory chunk in
* @elements. This memory will be unitialized, but will be accounted
* @elements. This memory will be uninitialized, but will be accounted
* for in the return value of _cairo_array_num_elements().
*
* Return value: %CAIRO_STATUS_SUCCESS if successful or
@ -332,21 +314,16 @@ _cairo_array_allocate (cairo_array_t *array,
{
cairo_status_t status;
assert (! array->is_snapshot);
status = _cairo_array_grow_by (array, num_elements);
if (unlikely (status))
return status;
assert (array->num_elements + num_elements <= array->size);
*elements = &(*array->elements)[array->num_elements * array->element_size];
*elements = array->elements + array->num_elements * array->element_size;
array->num_elements += num_elements;
if (array->num_elements != 0 && *array->elements == NULL)
abort();
return CAIRO_STATUS_SUCCESS;
}
@ -357,8 +334,8 @@ _cairo_array_allocate (cairo_array_t *array,
*
* This space was left intentionally blank, but gtk-doc filled it.
**/
int
_cairo_array_num_elements (cairo_array_t *array)
unsigned int
_cairo_array_num_elements (const cairo_array_t *array)
{
return array->num_elements;
}
@ -371,8 +348,8 @@ _cairo_array_num_elements (cairo_array_t *array)
*
* This space was left intentionally blank, but gtk-doc filled it.
**/
int
_cairo_array_size (cairo_array_t *array)
unsigned int
_cairo_array_size (const cairo_array_t *array)
{
return array->size;
}
@ -404,24 +381,18 @@ _cairo_user_data_array_fini (cairo_user_data_array_t *array)
{
unsigned int num_slots;
if (array->num_elements != 0 && *array->elements == NULL)
abort();
num_slots = array->num_elements;
if (num_slots) {
cairo_user_data_slot_t *slots;
slots = _cairo_array_index (array, 0);
do {
if (slots->user_data != NULL && slots->destroy != NULL)
slots->destroy (slots->user_data);
slots++;
} while (--num_slots);
while (num_slots--) {
cairo_user_data_slot_t *s = &slots[num_slots];
if (s->user_data != NULL && s->destroy != NULL)
s->destroy (s->user_data);
}
}
if (array->num_elements != 0 && *array->elements == NULL)
abort();
_cairo_array_fini (array);
}
@ -448,9 +419,6 @@ _cairo_user_data_array_get_data (cairo_user_data_array_t *array,
if (array == NULL)
return NULL;
if (array->num_elements != 0 && *array->elements == NULL)
abort();
num_slots = array->num_elements;
slots = _cairo_array_index (array, 0);
for (i = 0; i < num_slots; i++) {
@ -512,14 +480,14 @@ _cairo_user_data_array_set_data (cairo_user_data_array_t *array,
}
}
if (array->num_elements != 0 && *array->elements == NULL)
abort();
if (slot) {
*slot = new_slot;
return CAIRO_STATUS_SUCCESS;
}
if (user_data == NULL)
return CAIRO_STATUS_SUCCESS;
status = _cairo_array_append (array, &new_slot);
if (unlikely (status))
return status;
@ -529,7 +497,7 @@ _cairo_user_data_array_set_data (cairo_user_data_array_t *array,
cairo_status_t
_cairo_user_data_array_copy (cairo_user_data_array_t *dst,
cairo_user_data_array_t *src)
const cairo_user_data_array_t *src)
{
/* discard any existing user-data */
if (dst->num_elements != 0) {
@ -537,11 +505,13 @@ _cairo_user_data_array_copy (cairo_user_data_array_t *dst,
_cairo_user_data_array_init (dst);
}
/* don't call _cairo_array_append_multiple if there's nothing to do,
* as it assumes at least 1 element is to be appended */
if (src->num_elements == 0)
return CAIRO_STATUS_SUCCESS;
return CAIRO_STATUS_SUCCESS;
return _cairo_array_append_multiple (dst,
_cairo_array_index (src, 0),
_cairo_array_index_const (src, 0),
src->num_elements);
}

Просмотреть файл

@ -45,9 +45,7 @@
#include "config.h"
#endif
#if HAVE_WIN32_ATOMIC_PRIMITIVES
#include <Windows.h>
#endif
#include <assert.h>
/* The autoconf on OpenBSD 4.5 produces the malformed constant name
* SIZEOF_VOID__ rather than SIZEOF_VOID_P. Work around that here. */
@ -159,37 +157,12 @@ _cairo_atomic_ptr_cmpxchg_return_old_impl(void **x, void *oldv, void *newv)
#endif
#if HAVE_WIN32_ATOMIC_PRIMITIVES
#define HAS_ATOMIC_OPS 1
typedef volatile long cairo_atomic_int_t;
# define _cairo_atomic_int_get(x) ((int)*x)
# define _cairo_atomic_int_get_relaxed(x) ((int)*(x))
# define _cairo_atomic_int_set_relaxed(x, val) (*(x) = (val))
# define _cairo_atomic_ptr_get(x) ((void*)*x)
# define _cairo_atomic_int_inc(x) ((void) InterlockedIncrement(x))
# define _cairo_atomic_int_dec(x) ((void) InterlockedDecrement(x))
# define _cairo_atomic_int_dec_and_test(x) (InterlockedDecrement(x) == 0)
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) (InterlockedCompareExchange(x, newv, oldv) == oldv)
# define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) InterlockedCompareExchange(x, newv, oldv)
typedef volatile void* cairo_atomic_intptr_t;
#define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) (InterlockedCompareExchangePointer(x, newv, oldv) == oldv)
#define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) (InterlockedCompareExchangePointer(x, newv, oldv))
#endif
#if HAVE_INTEL_ATOMIC_PRIMITIVES
#if HAVE_GCC_LEGACY_ATOMICS
#define HAS_ATOMIC_OPS 1
typedef int cairo_atomic_int_t;
#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
static cairo_always_inline cairo_atomic_int_t
_cairo_atomic_int_get (cairo_atomic_int_t *x)
{
@ -215,14 +188,9 @@ _cairo_atomic_ptr_get (void **x)
__sync_synchronize ();
return *x;
}
#else
# define _cairo_atomic_int_get(x) (*x)
# define _cairo_atomic_int_get_relaxed(x) (*(x))
# define _cairo_atomic_int_set_relaxed(x, val) (*(x) = (val))
# define _cairo_atomic_ptr_get(x) (*x)
#endif
# define _cairo_atomic_int_inc(x) ((void) __sync_fetch_and_add(x, 1))
# define _cairo_atomic_int_dec(x) ((void) __sync_fetch_and_add(x, -1))
# define _cairo_atomic_int_dec_and_test(x) (__sync_fetch_and_add(x, -1) == 1)
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_bool_compare_and_swap (x, oldv, newv)
# define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
@ -257,6 +225,7 @@ typedef AO_t cairo_atomic_int_t;
# define _cairo_atomic_int_set_relaxed(x, val) (AO_store_full ((x), (val)))
# define _cairo_atomic_int_inc(x) ((void) AO_fetch_and_add1_full(x))
# define _cairo_atomic_int_dec(x) ((void) AO_fetch_and_sub1_full(x))
# define _cairo_atomic_int_dec_and_test(x) (AO_fetch_and_sub1_full(x) == 1)
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) AO_compare_and_swap_full(x, oldv, newv)
@ -284,10 +253,11 @@ typedef unsigned long long cairo_atomic_intptr_t;
typedef int32_t cairo_atomic_int_t;
# define _cairo_atomic_int_get(x) (OSMemoryBarrier(), *(x))
# define _cairo_atomic_int_get_relaxed(x) (*(x))
# define _cairo_atomic_int_set_relaxed(x, val) (*(x) = (val))
# define _cairo_atomic_int_get_relaxed(x) *(x)
# define _cairo_atomic_int_set_relaxed(x, val) *(x) = (val)
# define _cairo_atomic_int_inc(x) ((void) OSAtomicIncrement32Barrier (x))
# define _cairo_atomic_int_dec(x) ((void) OSAtomicDecrement32Barrier (x))
# define _cairo_atomic_int_dec_and_test(x) (OSAtomicDecrement32Barrier (x) == 0)
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) OSAtomicCompareAndSwap32Barrier(oldv, newv, x)
@ -326,6 +296,8 @@ typedef cairo_atomic_intptr_t cairo_atomic_int_t;
cairo_private void
_cairo_atomic_int_inc (cairo_atomic_int_t *x);
#define _cairo_atomic_int_dec(x) _cairo_atomic_int_dec_and_test(x)
cairo_private cairo_bool_t
_cairo_atomic_int_dec_and_test (cairo_atomic_int_t *x);
@ -348,8 +320,8 @@ _cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, cairo_atomic_int_t val);
# define _cairo_atomic_ptr_get(x) (void *) _cairo_atomic_int_get((cairo_atomic_int_t *) x)
#else
# define _cairo_atomic_int_get(x) (*x)
# define _cairo_atomic_int_get_relaxed(x) (*(x))
# define _cairo_atomic_int_set_relaxed(x, val) (*(x) = (val))
# define _cairo_atomic_int_get_relaxed(x) (*x)
# define _cairo_atomic_int_set_relaxed(x, val) (*x) = (val)
# define _cairo_atomic_ptr_get(x) (*x)
#endif
@ -408,12 +380,45 @@ _cairo_atomic_ptr_cmpxchg_return_old_fallback(void **x, void *oldv, void *newv)
_cairo_atomic_int_cmpxchg((cairo_atomic_int_t *)x, oldv, newv)
#define _cairo_status_set_error(status, err) do { \
int ret__; \
assert (err < CAIRO_STATUS_LAST_STATUS); \
/* hide compiler warnings about cairo_status_t != int (gcc treats its as \
* an unsigned integer instead, and about ignoring the return value. */ \
int ret__ = _cairo_atomic_int_cmpxchg ((cairo_atomic_int_t *) status, CAIRO_STATUS_SUCCESS, err); \
ret__ = _cairo_atomic_int_cmpxchg ((cairo_atomic_int_t *) status, CAIRO_STATUS_SUCCESS, err); \
(void) ret__; \
} while (0)
typedef cairo_atomic_int_t cairo_atomic_once_t;
#define CAIRO_ATOMIC_ONCE_UNINITIALIZED (0)
#define CAIRO_ATOMIC_ONCE_INITIALIZING (1)
#define CAIRO_ATOMIC_ONCE_INITIALIZED (2)
#define CAIRO_ATOMIC_ONCE_INIT CAIRO_ATOMIC_ONCE_UNINITIALIZED
static cairo_always_inline cairo_bool_t
_cairo_atomic_init_once_enter(cairo_atomic_once_t *once)
{
if (likely(_cairo_atomic_int_get(once) == CAIRO_ATOMIC_ONCE_INITIALIZED))
return 0;
if (_cairo_atomic_int_cmpxchg(once,
CAIRO_ATOMIC_ONCE_UNINITIALIZED,
CAIRO_ATOMIC_ONCE_INITIALIZING))
return 1;
while (_cairo_atomic_int_get(once) != CAIRO_ATOMIC_ONCE_INITIALIZED) {}
return 0;
}
static cairo_always_inline void
_cairo_atomic_init_once_leave(cairo_atomic_once_t *once)
{
if (unlikely(!_cairo_atomic_int_cmpxchg(once,
CAIRO_ATOMIC_ONCE_INITIALIZING,
CAIRO_ATOMIC_ONCE_INITIALIZED)))
assert (0 && "incorrect use of _cairo_atomic_init_once API (once != CAIRO_ATOMIC_ONCE_INITIALIZING)");
}
CAIRO_END_DECLS
#endif

Просмотреть файл

@ -0,0 +1,204 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2010 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Intel Corporation
*
* Contributor(s):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#ifndef CAIRO_BACKEND_PRIVATE_H
#define CAIRO_BACKEND_PRIVATE_H
#include "cairo-types-private.h"
#include "cairo-private.h"
typedef enum _cairo_backend_type {
CAIRO_TYPE_DEFAULT,
CAIRO_TYPE_SKIA,
} cairo_backend_type_t;
struct _cairo_backend {
cairo_backend_type_t type;
void (*destroy) (void *cr);
cairo_surface_t *(*get_original_target) (void *cr);
cairo_surface_t *(*get_current_target) (void *cr);
cairo_status_t (*save) (void *cr);
cairo_status_t (*restore) (void *cr);
cairo_status_t (*push_group) (void *cr, cairo_content_t content);
cairo_pattern_t *(*pop_group) (void *cr);
cairo_status_t (*set_source_rgba) (void *cr, double red, double green, double blue, double alpha);
cairo_status_t (*set_source_surface) (void *cr, cairo_surface_t *surface, double x, double y);
cairo_status_t (*set_source) (void *cr, cairo_pattern_t *source);
cairo_pattern_t *(*get_source) (void *cr);
cairo_status_t (*set_antialias) (void *cr, cairo_antialias_t antialias);
cairo_status_t (*set_dash) (void *cr, const double *dashes, int num_dashes, double offset);
cairo_status_t (*set_fill_rule) (void *cr, cairo_fill_rule_t fill_rule);
cairo_status_t (*set_line_cap) (void *cr, cairo_line_cap_t line_cap);
cairo_status_t (*set_line_join) (void *cr, cairo_line_join_t line_join);
cairo_status_t (*set_line_width) (void *cr, double line_width);
cairo_status_t (*set_miter_limit) (void *cr, double limit);
cairo_status_t (*set_opacity) (void *cr, double opacity);
cairo_status_t (*set_operator) (void *cr, cairo_operator_t op);
cairo_status_t (*set_tolerance) (void *cr, double tolerance);
cairo_antialias_t (*get_antialias) (void *cr);
void (*get_dash) (void *cr, double *dashes, int *num_dashes, double *offset);
cairo_fill_rule_t (*get_fill_rule) (void *cr);
cairo_line_cap_t (*get_line_cap) (void *cr);
cairo_line_join_t (*get_line_join) (void *cr);
double (*get_line_width) (void *cr);
double (*get_miter_limit) (void *cr);
double (*get_opacity) (void *cr);
cairo_operator_t (*get_operator) (void *cr);
double (*get_tolerance) (void *cr);
cairo_status_t (*translate) (void *cr, double tx, double ty);
cairo_status_t (*scale) (void *cr, double sx, double sy);
cairo_status_t (*rotate) (void *cr, double theta);
cairo_status_t (*transform) (void *cr, const cairo_matrix_t *matrix);
cairo_status_t (*set_matrix) (void *cr, const cairo_matrix_t *matrix);
cairo_status_t (*set_identity_matrix) (void *cr);
void (*get_matrix) (void *cr, cairo_matrix_t *matrix);
void (*user_to_device) (void *cr, double *x, double *y);
void (*user_to_device_distance) (void *cr, double *x, double *y);
void (*device_to_user) (void *cr, double *x, double *y);
void (*device_to_user_distance) (void *cr, double *x, double *y);
void (*user_to_backend) (void *cr, double *x, double *y);
void (*user_to_backend_distance) (void *cr, double *x, double *y);
void (*backend_to_user) (void *cr, double *x, double *y);
void (*backend_to_user_distance) (void *cr, double *x, double *y);
cairo_status_t (*new_path) (void *cr);
cairo_status_t (*new_sub_path) (void *cr);
cairo_status_t (*move_to) (void *cr, double x, double y);
cairo_status_t (*rel_move_to) (void *cr, double dx, double dy);
cairo_status_t (*line_to) (void *cr, double x, double y);
cairo_status_t (*rel_line_to) (void *cr, double dx, double dy);
cairo_status_t (*curve_to) (void *cr, double x1, double y1, double x2, double y2, double x3, double y3);
cairo_status_t (*rel_curve_to) (void *cr, double dx1, double dy1, double dx2, double dy2, double dx3, double dy3);
cairo_status_t (*arc_to) (void *cr, double x1, double y1, double x2, double y2, double radius);
cairo_status_t (*rel_arc_to) (void *cr, double dx1, double dy1, double dx2, double dy2, double radius);
cairo_status_t (*close_path) (void *cr);
cairo_status_t (*arc) (void *cr, double xc, double yc, double radius, double angle1, double angle2, cairo_bool_t forward);
cairo_status_t (*rectangle) (void *cr, double x, double y, double width, double height);
void (*path_extents) (void *cr, double *x1, double *y1, double *x2, double *y2);
cairo_bool_t (*has_current_point) (void *cr);
cairo_bool_t (*get_current_point) (void *cr, double *x, double *y);
cairo_path_t *(*copy_path) (void *cr);
cairo_path_t *(*copy_path_flat) (void *cr);
cairo_status_t (*append_path) (void *cr, const cairo_path_t *path);
cairo_status_t (*stroke_to_path) (void *cr);
cairo_status_t (*clip) (void *cr);
cairo_status_t (*clip_preserve) (void *cr);
cairo_status_t (*in_clip) (void *cr, double x, double y, cairo_bool_t *inside);
cairo_status_t (*clip_extents) (void *cr, double *x1, double *y1, double *x2, double *y2);
cairo_status_t (*reset_clip) (void *cr);
cairo_rectangle_list_t *(*clip_copy_rectangle_list) (void *cr);
cairo_status_t (*paint) (void *cr);
cairo_status_t (*paint_with_alpha) (void *cr, double opacity);
cairo_status_t (*mask) (void *cr, cairo_pattern_t *pattern);
cairo_status_t (*stroke) (void *cr);
cairo_status_t (*stroke_preserve) (void *cr);
cairo_status_t (*in_stroke) (void *cr, double x, double y, cairo_bool_t *inside);
cairo_status_t (*stroke_extents) (void *cr, double *x1, double *y1, double *x2, double *y2);
cairo_status_t (*fill) (void *cr);
cairo_status_t (*fill_preserve) (void *cr);
cairo_status_t (*in_fill) (void *cr, double x, double y, cairo_bool_t *inside);
cairo_status_t (*fill_extents) (void *cr, double *x1, double *y1, double *x2, double *y2);
cairo_status_t (*set_font_face) (void *cr, cairo_font_face_t *font_face);
cairo_font_face_t *(*get_font_face) (void *cr);
cairo_status_t (*set_font_size) (void *cr, double size);
cairo_status_t (*set_font_matrix) (void *cr, const cairo_matrix_t *matrix);
void (*get_font_matrix) (void *cr, cairo_matrix_t *matrix);
cairo_status_t (*set_font_options) (void *cr, const cairo_font_options_t *options);
void (*get_font_options) (void *cr, cairo_font_options_t *options);
cairo_status_t (*set_scaled_font) (void *cr, cairo_scaled_font_t *scaled_font);
cairo_scaled_font_t *(*get_scaled_font) (void *cr);
cairo_status_t (*font_extents) (void *cr, cairo_font_extents_t *extents);
cairo_status_t (*glyphs) (void *cr,
const cairo_glyph_t *glyphs, int num_glyphs,
cairo_glyph_text_info_t *info);
cairo_status_t (*glyph_path) (void *cr,
const cairo_glyph_t *glyphs, int num_glyphs);
cairo_status_t (*glyph_extents) (void *cr,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents);
cairo_status_t (*copy_page) (void *cr);
cairo_status_t (*show_page) (void *cr);
cairo_status_t (*tag_begin) (void *cr, const char *tag_name, const char *attributes);
cairo_status_t (*tag_end) (void *cr, const char *tag_name);
};
static inline void
_cairo_backend_to_user (cairo_t *cr, double *x, double *y)
{
cr->backend->backend_to_user (cr, x, y);
}
static inline void
_cairo_backend_to_user_distance (cairo_t *cr, double *x, double *y)
{
cr->backend->backend_to_user_distance (cr, x, y);
}
static inline void
_cairo_user_to_backend (cairo_t *cr, double *x, double *y)
{
cr->backend->user_to_backend (cr, x, y);
}
static inline void
_cairo_user_to_backend_distance (cairo_t *cr, double *x, double *y)
{
cr->backend->user_to_backend_distance (cr, x, y);
}
#endif /* CAIRO_BACKEND_PRIVATE_H */

Просмотреть файл

@ -85,6 +85,7 @@ _cairo_base64_stream_write (cairo_output_stream_t *base,
switch (stream->trailing) {
case 2:
dst[2] = '=';
/* fall through */
case 1:
dst[3] = '=';
default:
@ -125,7 +126,7 @@ _cairo_base64_stream_create (cairo_output_stream_t *output)
if (output->status)
return _cairo_output_stream_create_in_error (output->status);
stream = malloc (sizeof (cairo_base64_stream_t));
stream = _cairo_malloc (sizeof (cairo_base64_stream_t));
if (unlikely (stream == NULL)) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_output_stream_t *) &_cairo_output_stream_nil;

Просмотреть файл

@ -53,7 +53,7 @@ _expand_four_tuple_to_five (unsigned char four_tuple[4],
uint32_t value;
int digit, i;
value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3];
value = (uint32_t)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++) {
@ -114,7 +114,7 @@ _cairo_base85_stream_create (cairo_output_stream_t *output)
if (output->status)
return _cairo_output_stream_create_in_error (output->status);
stream = malloc (sizeof (cairo_base85_stream_t));
stream = _cairo_malloc (sizeof (cairo_base85_stream_t));
if (unlikely (stream == NULL)) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_output_stream_t *) &_cairo_output_stream_nil;

Просмотреть файл

@ -40,8 +40,9 @@
#include "cairo-boxes-private.h"
#include "cairo-error-private.h"
#include "cairo-combsort-private.h"
#include "cairo-combsort-inline.h"
#include "cairo-list-private.h"
#include "cairo-traps-private.h"
#include <setjmp.h>
@ -69,23 +70,20 @@ struct _rectangle {
/* left and right children are index * 2 and (index * 2) +1 respectively */
#define PQ_LEFT_CHILD_INDEX(i) ((i) << 1)
typedef struct _pqueue {
int size, max_size;
rectangle_t **elements;
rectangle_t *elements_embedded[1024];
} pqueue_t;
typedef struct _sweep_line {
rectangle_t **rectangles;
pqueue_t pq;
edge_t head, tail;
edge_t *insert_left, *insert_right;
rectangle_t **stop;
edge_t head, tail, *insert, *cursor;
int32_t current_y;
int32_t last_y;
int stop_size;
int32_t insert_x;
cairo_fill_rule_t fill_rule;
cairo_bool_t do_traps;
void *container;
jmp_buf unwind;
} sweep_line_t;
@ -138,64 +136,14 @@ rectangle_compare_stop (const rectangle_t *a,
return a->bottom - b->bottom;
}
static inline void
pqueue_init (pqueue_t *pq)
{
pq->max_size = ARRAY_LENGTH (pq->elements_embedded);
pq->size = 0;
pq->elements = pq->elements_embedded;
pq->elements[PQ_FIRST_ENTRY] = NULL;
}
static inline void
pqueue_fini (pqueue_t *pq)
{
if (pq->elements != pq->elements_embedded)
free (pq->elements);
}
static cairo_bool_t
pqueue_grow (pqueue_t *pq)
{
rectangle_t **new_elements;
pq->max_size *= 2;
if (pq->elements == pq->elements_embedded) {
new_elements = _cairo_malloc_ab (pq->max_size,
sizeof (rectangle_t *));
if (unlikely (new_elements == NULL))
return FALSE;
memcpy (new_elements, pq->elements_embedded,
sizeof (pq->elements_embedded));
} else {
new_elements = _cairo_realloc_ab (pq->elements,
pq->max_size,
sizeof (rectangle_t *));
if (unlikely (new_elements == NULL))
return FALSE;
}
pq->elements = new_elements;
return TRUE;
}
static inline void
pqueue_push (sweep_line_t *sweep, rectangle_t *rectangle)
{
rectangle_t **elements;
int i, parent;
if (unlikely (sweep->pq.size + 1 == sweep->pq.max_size)) {
if (unlikely (! pqueue_grow (&sweep->pq))) {
longjmp (sweep->unwind,
_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
}
elements = sweep->pq.elements;
for (i = ++sweep->pq.size;
elements = sweep->stop;
for (i = ++sweep->stop_size;
i != PQ_FIRST_ENTRY &&
rectangle_compare_stop (rectangle,
elements[parent = PQ_PARENT_INDEX (i)]) < 0;
@ -208,23 +156,23 @@ pqueue_push (sweep_line_t *sweep, rectangle_t *rectangle)
}
static inline void
pqueue_pop (pqueue_t *pq)
rectangle_pop_stop (sweep_line_t *sweep)
{
rectangle_t **elements = pq->elements;
rectangle_t **elements = sweep->stop;
rectangle_t *tail;
int child, i;
tail = elements[pq->size--];
if (pq->size == 0) {
tail = elements[sweep->stop_size--];
if (sweep->stop_size == 0) {
elements[PQ_FIRST_ENTRY] = NULL;
return;
}
for (i = PQ_FIRST_ENTRY;
(child = PQ_LEFT_CHILD_INDEX (i)) <= pq->size;
(child = PQ_LEFT_CHILD_INDEX (i)) <= sweep->stop_size;
i = child)
{
if (child != pq->size &&
if (child != sweep->stop_size &&
rectangle_compare_stop (elements[child+1],
elements[child]) < 0)
{
@ -248,7 +196,7 @@ rectangle_pop_start (sweep_line_t *sweep_line)
static inline rectangle_t *
rectangle_peek_stop (sweep_line_t *sweep_line)
{
return sweep_line->pq.elements[PQ_FIRST_ENTRY];
return sweep_line->stop[PQ_FIRST_ENTRY];
}
CAIRO_COMBSORT_DECLARE (_rectangle_sort,
@ -259,57 +207,48 @@ static void
sweep_line_init (sweep_line_t *sweep_line,
rectangle_t **rectangles,
int num_rectangles,
cairo_fill_rule_t fill_rule)
cairo_fill_rule_t fill_rule,
cairo_bool_t do_traps,
void *container)
{
_rectangle_sort (rectangles, num_rectangles);
rectangles[-2] = NULL;
rectangles[-1] = NULL;
rectangles[num_rectangles] = NULL;
sweep_line->rectangles = rectangles;
sweep_line->stop = rectangles - 2;
sweep_line->stop_size = 0;
sweep_line->insert = NULL;
sweep_line->insert_x = INT_MAX;
sweep_line->cursor = &sweep_line->tail;
sweep_line->head.dir = 0;
sweep_line->head.x = INT32_MIN;
sweep_line->head.right = NULL;
sweep_line->head.dir = 0;
sweep_line->head.next = &sweep_line->tail;
/* we need to initialize prev so that we can check
* if this edge is the left most and make sure
* we always insert to the right of it, even if
* our x coordinate matches */
sweep_line->head.prev = NULL;
sweep_line->tail.x = INT32_MAX;
sweep_line->tail.right = NULL;
sweep_line->tail.dir = 0;
sweep_line->head.next = &sweep_line->tail;
sweep_line->tail.prev = &sweep_line->head;
sweep_line->tail.next = NULL;
sweep_line->insert_left = &sweep_line->tail;
sweep_line->insert_right = &sweep_line->tail;
sweep_line->tail.right = NULL;
sweep_line->tail.x = INT32_MAX;
sweep_line->tail.dir = 0;
sweep_line->current_y = INT32_MIN;
sweep_line->last_y = INT32_MIN;
sweep_line->fill_rule = fill_rule;
pqueue_init (&sweep_line->pq);
sweep_line->container = container;
sweep_line->do_traps = do_traps;
}
static void
sweep_line_fini (sweep_line_t *sweep_line)
{
pqueue_fini (&sweep_line->pq);
}
static void
edge_end_box (sweep_line_t *sweep_line,
edge_t *left,
int32_t bot,
cairo_bool_t do_traps,
void *container)
edge_end_box (sweep_line_t *sweep_line, edge_t *left, int32_t bot)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
/* Only emit (trivial) non-degenerate trapezoids with positive height. */
if (likely (left->top < bot)) {
if (do_traps) {
if (sweep_line->do_traps) {
cairo_line_t _left = {
{ left->x, left->top },
{ left->x, bot },
@ -317,8 +256,8 @@ edge_end_box (sweep_line_t *sweep_line,
{ left->right->x, left->top },
{ left->right->x, bot },
};
_cairo_traps_add_trap (container, left->top, bot, &_left, &_right);
status = _cairo_traps_status ((cairo_traps_t *) container);
_cairo_traps_add_trap (sweep_line->container, left->top, bot, &_left, &_right);
status = _cairo_traps_status ((cairo_traps_t *) sweep_line->container);
} else {
cairo_box_t box;
@ -327,7 +266,9 @@ edge_end_box (sweep_line_t *sweep_line,
box.p2.x = left->right->x;
box.p2.y = bot;
status = _cairo_boxes_add (container, &box);
status = _cairo_boxes_add (sweep_line->container,
CAIRO_ANTIALIAS_DEFAULT,
&box);
}
}
if (unlikely (status))
@ -345,34 +286,169 @@ static inline void
edge_start_or_continue_box (sweep_line_t *sweep_line,
edge_t *left,
edge_t *right,
int top,
cairo_bool_t do_traps,
void *container)
int top)
{
if (left->right == right)
return;
if (left->right != NULL) {
if (right != NULL && left->right->x == right->x) {
if (left->right->x == right->x) {
/* continuation on right, so just swap edges */
left->right = right;
return;
}
edge_end_box (sweep_line,
left, top, do_traps, container);
edge_end_box (sweep_line, left, top);
}
if (right != NULL && left->x != right->x) {
if (left->x != right->x) {
left->top = top;
left->right = right;
}
}
/*
* Merge two sorted edge lists.
* Input:
* - head_a: The head of the first list.
* - head_b: The head of the second list; head_b cannot be NULL.
* Output:
* Returns the head of the merged list.
*
* Implementation notes:
* To make it fast (in particular, to reduce to an insertion sort whenever
* one of the two input lists only has a single element) we iterate through
* a list until its head becomes greater than the head of the other list,
* then we switch their roles. As soon as one of the two lists is empty, we
* just attach the other one to the current list and exit.
* Writes to memory are only needed to "switch" lists (as it also requires
* attaching to the output list the list which we will be iterating next) and
* to attach the last non-empty list.
*/
static edge_t *
merge_sorted_edges (edge_t *head_a, edge_t *head_b)
{
edge_t *head, *prev;
int32_t x;
prev = head_a->prev;
if (head_a->x <= head_b->x) {
head = head_a;
} else {
head_b->prev = prev;
head = head_b;
goto start_with_b;
}
do {
x = head_b->x;
while (head_a != NULL && head_a->x <= x) {
prev = head_a;
head_a = head_a->next;
}
head_b->prev = prev;
prev->next = head_b;
if (head_a == NULL)
return head;
start_with_b:
x = head_a->x;
while (head_b != NULL && head_b->x <= x) {
prev = head_b;
head_b = head_b->next;
}
head_a->prev = prev;
prev->next = head_a;
if (head_b == NULL)
return head;
} while (1);
}
/*
* Sort (part of) a list.
* Input:
* - list: The list to be sorted; list cannot be NULL.
* - limit: Recursion limit.
* Output:
* - head_out: The head of the sorted list containing the first 2^(level+1) elements of the
* input list; if the input list has fewer elements, head_out be a sorted list
* containing all the elements of the input list.
* Returns the head of the list of unprocessed elements (NULL if the sorted list contains
* all the elements of the input list).
*
* Implementation notes:
* Special case single element list, unroll/inline the sorting of the first two elements.
* Some tail recursion is used since we iterate on the bottom-up solution of the problem
* (we start with a small sorted list and keep merging other lists of the same size to it).
*/
static edge_t *
sort_edges (edge_t *list,
unsigned int level,
edge_t **head_out)
{
edge_t *head_other, *remaining;
unsigned int i;
head_other = list->next;
if (head_other == NULL) {
*head_out = list;
return NULL;
}
remaining = head_other->next;
if (list->x <= head_other->x) {
*head_out = list;
head_other->next = NULL;
} else {
*head_out = head_other;
head_other->prev = list->prev;
head_other->next = list;
list->prev = head_other;
list->next = NULL;
}
for (i = 0; i < level && remaining; i++) {
remaining = sort_edges (remaining, i, &head_other);
*head_out = merge_sorted_edges (*head_out, head_other);
}
return remaining;
}
static edge_t *
merge_unsorted_edges (edge_t *head, edge_t *unsorted)
{
sort_edges (unsorted, UINT_MAX, &unsorted);
return merge_sorted_edges (head, unsorted);
}
static void
active_edges_insert (sweep_line_t *sweep)
{
edge_t *prev;
int x;
x = sweep->insert_x;
prev = sweep->cursor;
if (prev->x > x) {
do {
prev = prev->prev;
} while (prev->x > x);
} else {
while (prev->next->x < x)
prev = prev->next;
}
prev->next = merge_unsorted_edges (prev->next, sweep->insert);
sweep->cursor = sweep->insert;
sweep->insert = NULL;
sweep->insert_x = INT_MAX;
}
static inline void
active_edges_to_traps (sweep_line_t *sweep,
cairo_bool_t do_traps,
void *container)
active_edges_to_traps (sweep_line_t *sweep)
{
int top = sweep->current_y;
edge_t *pos;
@ -380,6 +456,9 @@ active_edges_to_traps (sweep_line_t *sweep,
if (sweep->last_y == sweep->current_y)
return;
if (sweep->insert)
active_edges_insert (sweep);
pos = sweep->head.next;
if (pos == &sweep->tail)
return;
@ -395,51 +474,42 @@ active_edges_to_traps (sweep_line_t *sweep,
right = left->next;
/* Check if there is a co-linear edge with an existing trap */
if (left->right == NULL) {
while (unlikely (right->x == left->x)) {
winding += right->dir;
if (right->right != NULL) {
/* continuation on left */
left->top = right->top;
left->right = right->right;
right->right = NULL;
winding -= right->dir;
break;
}
right = right->next;
}
if (winding == 0) {
pos = right;
continue;
while (right->x == left->x) {
if (right->right != NULL) {
assert (left->right == NULL);
/* continuation on left */
left->top = right->top;
left->right = right->right;
right->right = NULL;
}
winding += right->dir;
right = right->next;
}
/* Greedily search for the closing edge, so that we generate the
* maximal span width with the minimal number of trapezoids.
*/
if (winding == 0) {
if (left->right != NULL)
edge_end_box (sweep, left, top);
pos = right;
continue;
}
do {
/* End all subsumed traps */
if (unlikely (right->right != NULL)) {
edge_end_box (sweep,
right, top, do_traps, container);
}
if (unlikely (right->right != NULL))
edge_end_box (sweep, right, top);
/* Greedily search for the closing edge, so that we generate
* the * maximal span width with the minimal number of
* boxes.
*/
winding += right->dir;
if (winding == 0) {
/* skip co-linear edges */
if (likely (right->x != right->next->x))
break;
}
if (winding == 0 && right->x != right->next->x)
break;
right = right->next;
} while (TRUE);
edge_start_or_continue_box (sweep,
left, right, top,
do_traps, container);
edge_start_or_continue_box (sweep, left, right, top);
pos = right->next;
} while (pos != &sweep->tail);
@ -450,23 +520,17 @@ active_edges_to_traps (sweep_line_t *sweep,
do {
/* End all subsumed traps */
if (unlikely (right->right != NULL)) {
edge_end_box (sweep,
right, top, do_traps, container);
}
if (unlikely (right->right != NULL))
edge_end_box (sweep, right, top);
if (++count & 1) {
/* skip co-linear edges */
if (likely (right->x != right->next->x))
break;
}
if (++count & 1 && right->x != right->next->x)
break;
right = right->next;
} while (TRUE);
edge_start_or_continue_box (sweep,
pos, right, top,
do_traps, container);
edge_start_or_continue_box (sweep, pos, right, top);
pos = right->next;
} while (pos != &sweep->tail);
@ -476,38 +540,26 @@ active_edges_to_traps (sweep_line_t *sweep,
}
static inline void
sweep_line_delete_edge (sweep_line_t *sweep_line,
edge_t *edge,
cairo_bool_t do_traps,
void *container)
sweep_line_delete_edge (sweep_line_t *sweep, edge_t *edge)
{
if (edge->right != NULL) {
edge_t *next = edge->next;
if (next->x == edge->x) {
next->top = edge->top;
next->right = edge->right;
} else {
edge_end_box (sweep_line,
edge,
sweep_line->current_y,
do_traps, container);
}
} else
edge_end_box (sweep, edge, sweep->current_y);
}
if (sweep_line->insert_left == edge)
sweep_line->insert_left = edge->next;
if (sweep_line->insert_right == edge)
sweep_line->insert_right = edge->next;
if (sweep->cursor == edge)
sweep->cursor = edge->prev;
edge->prev->next = edge->next;
edge->next->prev = edge->prev;
}
static inline cairo_bool_t
sweep_line_delete (sweep_line_t *sweep,
rectangle_t *rectangle,
cairo_bool_t do_traps,
void *container)
sweep_line_delete (sweep_line_t *sweep, rectangle_t *rectangle)
{
cairo_bool_t update;
@ -518,82 +570,27 @@ sweep_line_delete (sweep_line_t *sweep,
update = rectangle->left.next != &rectangle->right;
}
sweep_line_delete_edge (sweep,
&rectangle->left,
do_traps, container);
sweep_line_delete_edge (sweep, &rectangle->left);
sweep_line_delete_edge (sweep, &rectangle->right);
sweep_line_delete_edge (sweep,
&rectangle->right,
do_traps, container);
pqueue_pop (&sweep->pq);
rectangle_pop_stop (sweep);
return update;
}
static inline void
insert_edge (edge_t *edge, edge_t *pos)
sweep_line_insert (sweep_line_t *sweep, rectangle_t *rectangle)
{
if (pos->x != edge->x) {
if (pos->x > edge->x) {
do {
UNROLL3({
if (pos->prev->x <= edge->x)
break;
pos = pos->prev;
})
} while (TRUE);
} else {
do {
UNROLL3({
pos = pos->next;
if (pos->x >= edge->x)
break;
})
} while (TRUE);
}
}
if (pos->prev) {
pos->prev->next = edge;
edge->prev = pos->prev;
edge->next = pos;
pos->prev = edge;
} else {
/* we have edge that shares an x coordinate with the left most sentinal.
* instead of inserting before pos and ruining our sentinal we insert after pos. */
pos->next->prev = edge;
edge->next = pos->next;
edge->prev = pos;
pos->next = edge;
}
}
static inline cairo_bool_t
sweep_line_insert (sweep_line_t *sweep,
rectangle_t *rectangle)
{
edge_t *pos;
/* right edge */
pos = sweep->insert_right;
insert_edge (&rectangle->right, pos);
sweep->insert_right = &rectangle->right;
/* left edge */
pos = sweep->insert_left;
if (pos->x > sweep->insert_right->x)
pos = sweep->insert_right->prev;
insert_edge (&rectangle->left, pos);
sweep->insert_left = &rectangle->left;
if (sweep->insert)
sweep->insert->prev = &rectangle->right;
rectangle->right.next = sweep->insert;
rectangle->right.prev = &rectangle->left;
rectangle->left.next = &rectangle->right;
rectangle->left.prev = NULL;
sweep->insert = &rectangle->left;
if (rectangle->left.x < sweep->insert_x)
sweep->insert_x = rectangle->left.x;
pqueue_push (sweep, rectangle);
if (sweep->fill_rule == CAIRO_FILL_RULE_WINDING &&
rectangle->left.prev->dir == rectangle->left.dir)
{
return rectangle->left.next != &rectangle->right;
}
return TRUE;
}
static cairo_status_t
@ -606,11 +603,16 @@ _cairo_bentley_ottmann_tessellate_rectangular (rectangle_t **rectangles,
sweep_line_t sweep_line;
rectangle_t *rectangle;
cairo_status_t status;
cairo_bool_t update = FALSE;
cairo_bool_t update;
sweep_line_init (&sweep_line, rectangles, num_rectangles, fill_rule);
sweep_line_init (&sweep_line,
rectangles, num_rectangles,
fill_rule,
do_traps, container);
if ((status = setjmp (sweep_line.unwind)))
goto unwind;
return status;
update = FALSE;
rectangle = rectangle_pop_start (&sweep_line);
do {
@ -621,46 +623,45 @@ _cairo_bentley_ottmann_tessellate_rectangular (rectangle_t **rectangles,
while (stop != NULL && stop->bottom < rectangle->top) {
if (stop->bottom != sweep_line.current_y) {
if (update) {
active_edges_to_traps (&sweep_line,
do_traps, container);
active_edges_to_traps (&sweep_line);
update = FALSE;
}
sweep_line.current_y = stop->bottom;
}
update |= sweep_line_delete (&sweep_line, stop, do_traps, container);
update |= sweep_line_delete (&sweep_line, stop);
stop = rectangle_peek_stop (&sweep_line);
}
if (update) {
active_edges_to_traps (&sweep_line, do_traps, container);
active_edges_to_traps (&sweep_line);
update = FALSE;
}
sweep_line.current_y = rectangle->top;
}
update |= sweep_line_insert (&sweep_line, rectangle);
} while ((rectangle = rectangle_pop_start (&sweep_line)) != NULL);
do {
sweep_line_insert (&sweep_line, rectangle);
} while ((rectangle = rectangle_pop_start (&sweep_line)) != NULL &&
sweep_line.current_y == rectangle->top);
update = TRUE;
} while (rectangle);
while ((rectangle = rectangle_peek_stop (&sweep_line)) != NULL) {
if (rectangle->bottom != sweep_line.current_y) {
if (update) {
active_edges_to_traps (&sweep_line, do_traps, container);
active_edges_to_traps (&sweep_line);
update = FALSE;
}
sweep_line.current_y = rectangle->bottom;
}
update |= sweep_line_delete (&sweep_line, rectangle, do_traps, container);
update |= sweep_line_delete (&sweep_line, rectangle);
}
unwind:
sweep_line_fini (&sweep_line);
return status;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
@ -668,13 +669,12 @@ _cairo_bentley_ottmann_tessellate_rectangular_traps (cairo_traps_t *traps,
cairo_fill_rule_t fill_rule)
{
rectangle_t stack_rectangles[CAIRO_STACK_ARRAY_LENGTH (rectangle_t)];
rectangle_t *rectangles;
rectangle_t *stack_rectangles_ptrs[ARRAY_LENGTH (stack_rectangles) + 1];
rectangle_t **rectangles_ptrs;
rectangle_t *stack_rectangles_ptrs[ARRAY_LENGTH (stack_rectangles) + 3];
rectangle_t *rectangles, **rectangles_ptrs;
cairo_status_t status;
int i;
assert (traps->is_rectangular);
assert (traps->is_rectangular);
if (unlikely (traps->num_traps <= 1)) {
if (traps->num_traps == 1) {
@ -683,9 +683,9 @@ _cairo_bentley_ottmann_tessellate_rectangular_traps (cairo_traps_t *traps,
cairo_line_t tmp = trap->left;
trap->left = trap->right;
trap->right = tmp;
}
}
}
return CAIRO_STATUS_SUCCESS;
return CAIRO_STATUS_SUCCESS;
}
dump_traps (traps, "bo-rects-traps-in.txt");
@ -694,9 +694,9 @@ _cairo_bentley_ottmann_tessellate_rectangular_traps (cairo_traps_t *traps,
rectangles_ptrs = stack_rectangles_ptrs;
if (traps->num_traps > ARRAY_LENGTH (stack_rectangles)) {
rectangles = _cairo_malloc_ab_plus_c (traps->num_traps,
sizeof (rectangle_t) +
sizeof (rectangle_t *),
sizeof (rectangle_t *));
sizeof (rectangle_t) +
sizeof (rectangle_t *),
3*sizeof (rectangle_t *));
if (unlikely (rectangles == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@ -724,11 +724,13 @@ _cairo_bentley_ottmann_tessellate_rectangular_traps (cairo_traps_t *traps,
rectangles[i].top = traps->traps[i].top;
rectangles[i].bottom = traps->traps[i].bottom;
rectangles_ptrs[i] = &rectangles[i];
rectangles_ptrs[i+2] = &rectangles[i];
}
/* XXX incremental sort */
_rectangle_sort (rectangles_ptrs+2, i);
_cairo_traps_clear (traps);
status = _cairo_bentley_ottmann_tessellate_rectangular (rectangles_ptrs, i,
status = _cairo_bentley_ottmann_tessellate_rectangular (rectangles_ptrs+2, i,
fill_rule,
TRUE, traps);
traps->is_rectilinear = TRUE;
@ -748,12 +750,13 @@ _cairo_bentley_ottmann_tessellate_boxes (const cairo_boxes_t *in,
cairo_boxes_t *out)
{
rectangle_t stack_rectangles[CAIRO_STACK_ARRAY_LENGTH (rectangle_t)];
rectangle_t *rectangles;
rectangle_t *stack_rectangles_ptrs[ARRAY_LENGTH (stack_rectangles) + 1];
rectangle_t **rectangles_ptrs;
rectangle_t *stack_rectangles_ptrs[ARRAY_LENGTH (stack_rectangles) + 3];
rectangle_t *rectangles, **rectangles_ptrs;
rectangle_t *stack_rectangles_chain[CAIRO_STACK_ARRAY_LENGTH (rectangle_t *) ];
rectangle_t **rectangles_chain = NULL;
const struct _cairo_boxes_chunk *chunk;
cairo_status_t status;
int i, j;
int i, j, y_min, y_max;
if (unlikely (in->num_boxes == 0)) {
_cairo_boxes_clear (out);
@ -779,21 +782,48 @@ _cairo_bentley_ottmann_tessellate_boxes (const cairo_boxes_t *in,
}
_cairo_boxes_clear (out);
status = _cairo_boxes_add (out, &box);
status = _cairo_boxes_add (out, CAIRO_ANTIALIAS_DEFAULT, &box);
assert (status == CAIRO_STATUS_SUCCESS);
}
return CAIRO_STATUS_SUCCESS;
}
y_min = INT_MAX; y_max = INT_MIN;
for (chunk = &in->chunks; chunk != NULL; chunk = chunk->next) {
const cairo_box_t *box = chunk->base;
for (i = 0; i < chunk->count; i++) {
if (box[i].p1.y < y_min)
y_min = box[i].p1.y;
if (box[i].p1.y > y_max)
y_max = box[i].p1.y;
}
}
y_min = _cairo_fixed_integer_floor (y_min);
y_max = _cairo_fixed_integer_floor (y_max) + 1;
y_max -= y_min;
if (y_max < in->num_boxes) {
rectangles_chain = stack_rectangles_chain;
if (y_max > ARRAY_LENGTH (stack_rectangles_chain)) {
rectangles_chain = _cairo_malloc_ab (y_max, sizeof (rectangle_t *));
if (unlikely (rectangles_chain == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
memset (rectangles_chain, 0, y_max * sizeof (rectangle_t*));
}
rectangles = stack_rectangles;
rectangles_ptrs = stack_rectangles_ptrs;
if (in->num_boxes > ARRAY_LENGTH (stack_rectangles)) {
rectangles = _cairo_malloc_ab_plus_c (in->num_boxes,
sizeof (rectangle_t) +
sizeof (rectangle_t *),
sizeof (rectangle_t *));
if (unlikely (rectangles == NULL))
sizeof (rectangle_t) +
sizeof (rectangle_t *),
3*sizeof (rectangle_t *));
if (unlikely (rectangles == NULL)) {
if (rectangles_chain != stack_rectangles_chain)
free (rectangles_chain);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
rectangles_ptrs = (rectangle_t **) (rectangles + in->num_boxes);
}
@ -802,6 +832,8 @@ _cairo_bentley_ottmann_tessellate_boxes (const cairo_boxes_t *in,
for (chunk = &in->chunks; chunk != NULL; chunk = chunk->next) {
const cairo_box_t *box = chunk->base;
for (i = 0; i < chunk->count; i++) {
int h;
if (box[i].p1.x < box[i].p2.x) {
rectangles[j].left.x = box[i].p1.x;
rectangles[j].left.dir = 1;
@ -822,13 +854,38 @@ _cairo_bentley_ottmann_tessellate_boxes (const cairo_boxes_t *in,
rectangles[j].top = box[i].p1.y;
rectangles[j].bottom = box[i].p2.y;
rectangles_ptrs[j] = &rectangles[j];
if (rectangles_chain) {
h = _cairo_fixed_integer_floor (box[i].p1.y) - y_min;
rectangles[j].left.next = (edge_t *)rectangles_chain[h];
rectangles_chain[h] = &rectangles[j];
} else {
rectangles_ptrs[j+2] = &rectangles[j];
}
j++;
}
}
if (rectangles_chain) {
j = 2;
for (y_min = 0; y_min < y_max; y_min++) {
rectangle_t *r;
int start = j;
for (r = rectangles_chain[y_min]; r; r = (rectangle_t *)r->left.next)
rectangles_ptrs[j++] = r;
if (j > start + 1)
_rectangle_sort (rectangles_ptrs + start, j - start);
}
if (rectangles_chain != stack_rectangles_chain)
free (rectangles_chain);
j -= 2;
} else {
_rectangle_sort (rectangles_ptrs + 2, j);
}
_cairo_boxes_clear (out);
status = _cairo_bentley_ottmann_tessellate_rectangular (rectangles_ptrs, j,
status = _cairo_bentley_ottmann_tessellate_rectangular (rectangles_ptrs+2, j,
fill_rule,
FALSE, out);
if (rectangles != stack_rectangles)

Просмотреть файл

@ -39,8 +39,9 @@
#include "cairoint.h"
#include "cairo-boxes-private.h"
#include "cairo-combsort-private.h"
#include "cairo-combsort-inline.h"
#include "cairo-error-private.h"
#include "cairo-traps-private.h"
typedef struct _cairo_bo_edge cairo_bo_edge_t;
typedef struct _cairo_bo_trap cairo_bo_trap_t;
@ -237,7 +238,7 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
box.p1.y = trap->top;
box.p2.x = trap->right->edge.line.p1.x;
box.p2.y = bot;
status = _cairo_boxes_add (container, &box);
status = _cairo_boxes_add (container, CAIRO_ANTIALIAS_DEFAULT, &box);
}
}
@ -436,74 +437,6 @@ _cairo_bentley_ottmann_tessellate_rectilinear (cairo_bo_event_t **start_events
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_bentley_ottmann_tessellate_rectilinear_polygon (cairo_traps_t *traps,
const cairo_polygon_t *polygon,
cairo_fill_rule_t fill_rule)
{
cairo_status_t status;
cairo_bo_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_event_t)];
cairo_bo_event_t *events;
cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
cairo_bo_event_t **event_ptrs;
cairo_bo_edge_t stack_edges[ARRAY_LENGTH (stack_events)];
cairo_bo_edge_t *edges;
int num_events;
int i, j;
if (unlikely (polygon->num_edges == 0))
return CAIRO_STATUS_SUCCESS;
num_events = 2 * polygon->num_edges;
events = stack_events;
event_ptrs = stack_event_ptrs;
edges = stack_edges;
if (num_events > ARRAY_LENGTH (stack_events)) {
events = _cairo_malloc_ab_plus_c (num_events,
sizeof (cairo_bo_event_t) +
sizeof (cairo_bo_edge_t) +
sizeof (cairo_bo_event_t *),
sizeof (cairo_bo_event_t *));
if (unlikely (events == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
event_ptrs = (cairo_bo_event_t **) (events + num_events);
edges = (cairo_bo_edge_t *) (event_ptrs + num_events + 1);
}
for (i = j = 0; i < polygon->num_edges; i++) {
edges[i].edge = polygon->edges[i];
edges[i].deferred_trap.right = NULL;
edges[i].prev = NULL;
edges[i].next = NULL;
event_ptrs[j] = &events[j];
events[j].type = CAIRO_BO_EVENT_TYPE_START;
events[j].point.y = polygon->edges[i].top;
events[j].point.x = polygon->edges[i].line.p1.x;
events[j].edge = &edges[i];
j++;
event_ptrs[j] = &events[j];
events[j].type = CAIRO_BO_EVENT_TYPE_STOP;
events[j].point.y = polygon->edges[i].bottom;
events[j].point.x = polygon->edges[i].line.p1.x;
events[j].edge = &edges[i];
j++;
}
status = _cairo_bentley_ottmann_tessellate_rectilinear (event_ptrs, j,
fill_rule,
TRUE, traps);
if (events != stack_events)
free (events);
traps->is_rectilinear = TRUE;
return status;
}
cairo_status_t
_cairo_bentley_ottmann_tessellate_rectilinear_polygon_to_boxes (const cairo_polygon_t *polygon,
cairo_fill_rule_t fill_rule,

Просмотреть файл

@ -38,9 +38,11 @@
/* Provide definitions for standalone compilation */
#include "cairoint.h"
#include "cairo-combsort-inline.h"
#include "cairo-error-private.h"
#include "cairo-freelist-private.h"
#include "cairo-combsort-private.h"
#include "cairo-line-inline.h"
#include "cairo-traps-private.h"
#define DEBUG_PRINT_STATE 0
#define DEBUG_EVENTS 0
@ -71,6 +73,7 @@ struct _cairo_bo_edge {
cairo_edge_t edge;
cairo_bo_edge_t *prev;
cairo_bo_edge_t *next;
cairo_bo_edge_t *colinear;
cairo_bo_trap_t deferred_trap;
};
@ -305,156 +308,6 @@ _slope_compare (const cairo_bo_edge_t *a,
}
}
/*
* We need to compare the x-coordinates of a pair of lines for a particular y,
* without loss of precision.
*
* The x-coordinate along an edge for a given y is:
* X = A_x + (Y - A_y) * A_dx / A_dy
*
* So the inequality we wish to test is:
* A_x + (Y - A_y) * A_dx / A_dy B_x + (Y - B_y) * B_dx / B_dy,
* where is our inequality operator.
*
* By construction, we know that A_dy and B_dy (and (Y - A_y), (Y - B_y)) are
* all positive, so we can rearrange it thus without causing a sign change:
* A_dy * B_dy * (A_x - B_x) (Y - B_y) * B_dx * A_dy
* - (Y - A_y) * A_dx * B_dy
*
* Given the assumption that all the deltas fit within 32 bits, we can compute
* this comparison directly using 128 bit arithmetic. For certain, but common,
* input we can reduce this down to a single 32 bit compare by inspecting the
* deltas.
*
* (And put the burden of the work on developing fast 128 bit ops, which are
* required throughout the tessellator.)
*
* See the similar discussion for _slope_compare().
*/
static int
edges_compare_x_for_y_general (const cairo_bo_edge_t *a,
const cairo_bo_edge_t *b,
int32_t y)
{
/* XXX: We're assuming here that dx and dy will still fit in 32
* bits. That's not true in general as there could be overflow. We
* should prevent that before the tessellation algorithm
* begins.
*/
int32_t dx;
int32_t adx, ady;
int32_t bdx, bdy;
enum {
HAVE_NONE = 0x0,
HAVE_DX = 0x1,
HAVE_ADX = 0x2,
HAVE_DX_ADX = HAVE_DX | HAVE_ADX,
HAVE_BDX = 0x4,
HAVE_DX_BDX = HAVE_DX | HAVE_BDX,
HAVE_ADX_BDX = HAVE_ADX | HAVE_BDX,
HAVE_ALL = HAVE_DX | HAVE_ADX | HAVE_BDX
} have_dx_adx_bdx = HAVE_ALL;
/* don't bother solving for abscissa if the edges' bounding boxes
* can be used to order them. */
{
int32_t amin, amax;
int32_t bmin, bmax;
if (a->edge.line.p1.x < a->edge.line.p2.x) {
amin = a->edge.line.p1.x;
amax = a->edge.line.p2.x;
} else {
amin = a->edge.line.p2.x;
amax = a->edge.line.p1.x;
}
if (b->edge.line.p1.x < b->edge.line.p2.x) {
bmin = b->edge.line.p1.x;
bmax = b->edge.line.p2.x;
} else {
bmin = b->edge.line.p2.x;
bmax = b->edge.line.p1.x;
}
if (amax < bmin) return -1;
if (amin > bmax) return +1;
}
ady = a->edge.line.p2.y - a->edge.line.p1.y;
adx = a->edge.line.p2.x - a->edge.line.p1.x;
if (adx == 0)
have_dx_adx_bdx &= ~HAVE_ADX;
bdy = b->edge.line.p2.y - b->edge.line.p1.y;
bdx = b->edge.line.p2.x - b->edge.line.p1.x;
if (bdx == 0)
have_dx_adx_bdx &= ~HAVE_BDX;
dx = a->edge.line.p1.x - b->edge.line.p1.x;
if (dx == 0)
have_dx_adx_bdx &= ~HAVE_DX;
#define L _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy), dx)
#define A _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx, bdy), y - a->edge.line.p1.y)
#define B _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx, ady), y - b->edge.line.p1.y)
switch (have_dx_adx_bdx) {
default:
case HAVE_NONE:
return 0;
case HAVE_DX:
/* A_dy * B_dy * (A_x - B_x) ∘ 0 */
return dx; /* ady * bdy is positive definite */
case HAVE_ADX:
/* 0 ∘ - (Y - A_y) * A_dx * B_dy */
return adx; /* bdy * (y - a->top.y) is positive definite */
case HAVE_BDX:
/* 0 ∘ (Y - B_y) * B_dx * A_dy */
return -bdx; /* ady * (y - b->top.y) is positive definite */
case HAVE_ADX_BDX:
/* 0 ∘ (Y - B_y) * B_dx * A_dy - (Y - A_y) * A_dx * B_dy */
if ((adx ^ bdx) < 0) {
return adx;
} else if (a->edge.line.p1.y == b->edge.line.p1.y) { /* common origin */
cairo_int64_t adx_bdy, bdx_ady;
/* ∴ A_dx * B_dy ∘ B_dx * A_dy */
adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
return _cairo_int64_cmp (adx_bdy, bdx_ady);
} else
return _cairo_int128_cmp (A, B);
case HAVE_DX_ADX:
/* A_dy * (A_x - B_x) ∘ - (Y - A_y) * A_dx */
if ((-adx ^ dx) < 0) {
return dx;
} else {
cairo_int64_t ady_dx, dy_adx;
ady_dx = _cairo_int32x32_64_mul (ady, dx);
dy_adx = _cairo_int32x32_64_mul (a->edge.line.p1.y - y, adx);
return _cairo_int64_cmp (ady_dx, dy_adx);
}
case HAVE_DX_BDX:
/* B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx */
if ((bdx ^ dx) < 0) {
return dx;
} else {
cairo_int64_t bdy_dx, dy_bdx;
bdy_dx = _cairo_int32x32_64_mul (bdy, dx);
dy_bdx = _cairo_int32x32_64_mul (y - b->edge.line.p1.y, bdx);
return _cairo_int64_cmp (bdy_dx, dy_bdx);
}
case HAVE_ALL:
/* XXX try comparing (a->edge.line.p2.x - b->edge.line.p2.x) et al */
return _cairo_int128_cmp (L, _cairo_int128_sub (B, A));
}
#undef B
#undef A
#undef L
}
/*
* We need to compare the x-coordinate of a line for a particular y wrt to a
@ -508,81 +361,19 @@ edge_compare_for_y_against_x (const cairo_bo_edge_t *a,
return _cairo_int64_cmp (L, R);
}
static int
edges_compare_x_for_y (const cairo_bo_edge_t *a,
const cairo_bo_edge_t *b,
int32_t y)
{
/* If the sweep-line is currently on an end-point of a line,
* then we know its precise x value (and considering that we often need to
* compare events at end-points, this happens frequently enough to warrant
* special casing).
*/
enum {
HAVE_NEITHER = 0x0,
HAVE_AX = 0x1,
HAVE_BX = 0x2,
HAVE_BOTH = HAVE_AX | HAVE_BX
} have_ax_bx = HAVE_BOTH;
int32_t ax, bx;
if (y == a->edge.line.p1.y)
ax = a->edge.line.p1.x;
else if (y == a->edge.line.p2.y)
ax = a->edge.line.p2.x;
else
have_ax_bx &= ~HAVE_AX;
if (y == b->edge.line.p1.y)
bx = b->edge.line.p1.x;
else if (y == b->edge.line.p2.y)
bx = b->edge.line.p2.x;
else
have_ax_bx &= ~HAVE_BX;
switch (have_ax_bx) {
default:
case HAVE_NEITHER:
return edges_compare_x_for_y_general (a, b, y);
case HAVE_AX:
return -edge_compare_for_y_against_x (b, y, ax);
case HAVE_BX:
return edge_compare_for_y_against_x (a, y, bx);
case HAVE_BOTH:
return ax - bx;
}
}
static inline int
_line_equal (const cairo_line_t *a, const cairo_line_t *b)
{
return a->p1.x == b->p1.x && a->p1.y == b->p1.y &&
a->p2.x == b->p2.x && a->p2.y == b->p2.y;
}
static int
_cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t *sweep_line,
_cairo_bo_sweep_line_compare_edges (const cairo_bo_sweep_line_t *sweep_line,
const cairo_bo_edge_t *a,
const cairo_bo_edge_t *b)
{
int cmp;
/* compare the edges if not identical */
if (! _line_equal (&a->edge.line, &b->edge.line)) {
cmp = edges_compare_x_for_y (a, b, sweep_line->current_y);
if (cmp)
cmp = _cairo_lines_compare_at_y (&a->edge.line,
&b->edge.line,
sweep_line->current_y);
if (cmp)
return cmp;
/* The two edges intersect exactly at y, so fall back on slope
* comparison. We know that this compare_edges function will be
* called only when starting a new edge, (not when stopping an
* edge), so we don't have to worry about conditionally inverting
* the sense of _slope_compare. */
cmp = _slope_compare (a, b);
if (cmp)
return cmp;
}
/* We've got two collinear edges now. */
return b->edge.bottom - a->edge.bottom;
}
@ -1040,9 +831,6 @@ _cairo_bo_event_queue_init (cairo_bo_event_queue_t *event_queue,
cairo_bo_event_t **start_events,
int num_events)
{
_cairo_bo_event_queue_sort (start_events, num_events);
start_events[num_events] = NULL;
event_queue->start_events = start_events;
_cairo_freepool_init (&event_queue->pool,
@ -1080,7 +868,11 @@ _cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_
{
cairo_bo_point32_t intersection;
if (_line_equal (&left->edge.line, &right->edge.line))
if (MAX (left->edge.line.p1.x, left->edge.line.p2.x) <=
MIN (right->edge.line.p1.x, right->edge.line.p2.x))
return CAIRO_STATUS_SUCCESS;
if (cairo_lines_equal (&left->edge.line, &right->edge.line))
return CAIRO_STATUS_SUCCESS;
/* The names "left" and "right" here are correct descriptions of
@ -1109,7 +901,7 @@ _cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line)
sweep_line->current_edge = NULL;
}
static cairo_status_t
static void
_cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t *sweep_line,
cairo_bo_edge_t *edge)
{
@ -1162,11 +954,10 @@ _cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t *sweep_line,
}
} else {
sweep_line->head = edge;
edge->next = NULL;
}
sweep_line->current_edge = edge;
return CAIRO_STATUS_SUCCESS;
}
static void
@ -1300,33 +1091,61 @@ event_log (const char *fmt, ...)
}
#endif
static inline cairo_bool_t
edges_colinear (const cairo_bo_edge_t *a, const cairo_bo_edge_t *b)
{
if (_line_equal (&a->edge.line, &b->edge.line))
return TRUE;
#define HAS_COLINEAR(a, b) ((cairo_bo_edge_t *)(((uintptr_t)(a))&~1) == (b))
#define IS_COLINEAR(e) (((uintptr_t)(e))&1)
#define MARK_COLINEAR(e, v) ((cairo_bo_edge_t *)(((uintptr_t)(e))|(v)))
if (_slope_compare (a, b))
static inline cairo_bool_t
edges_colinear (cairo_bo_edge_t *a, const cairo_bo_edge_t *b)
{
unsigned p;
if (HAS_COLINEAR(a->colinear, b))
return IS_COLINEAR(a->colinear);
if (HAS_COLINEAR(b->colinear, a)) {
p = IS_COLINEAR(b->colinear);
a->colinear = MARK_COLINEAR(b, p);
return p;
}
p = 0;
p |= (a->edge.line.p1.x == b->edge.line.p1.x) << 0;
p |= (a->edge.line.p1.y == b->edge.line.p1.y) << 1;
p |= (a->edge.line.p2.x == b->edge.line.p2.x) << 3;
p |= (a->edge.line.p2.y == b->edge.line.p2.y) << 4;
if (p == ((1 << 0) | (1 << 1) | (1 << 3) | (1 << 4))) {
a->colinear = MARK_COLINEAR(b, 1);
return TRUE;
}
if (_slope_compare (a, b)) {
a->colinear = MARK_COLINEAR(b, 0);
return FALSE;
}
/* The choice of y is not truly arbitrary since we must guarantee that it
* is greater than the start of either line.
*/
if (a->edge.line.p1.y == b->edge.line.p1.y) {
return a->edge.line.p1.x == b->edge.line.p1.x;
if (p != 0) {
/* colinear if either end-point are coincident */
p = (((p >> 1) & p) & 5) != 0;
} else if (a->edge.line.p1.y < b->edge.line.p1.y) {
return edge_compare_for_y_against_x (b,
a->edge.line.p1.y,
a->edge.line.p1.x) == 0;
p = edge_compare_for_y_against_x (b,
a->edge.line.p1.y,
a->edge.line.p1.x) == 0;
} else {
return edge_compare_for_y_against_x (a,
b->edge.line.p1.y,
b->edge.line.p1.x) == 0;
p = edge_compare_for_y_against_x (a,
b->edge.line.p1.y,
b->edge.line.p1.x) == 0;
}
a->colinear = MARK_COLINEAR(b, p);
return p;
}
/* Adds the trapezoid, if any, of the left edge to the #cairo_traps_t */
static cairo_status_t
static void
_cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
int32_t bot,
cairo_traps_t *traps)
@ -1358,8 +1177,6 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
}
trap->right = NULL;
return _cairo_traps_status (traps);
}
@ -1368,31 +1185,28 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
* then either add it to the traps in `traps', if the trapezoid's
* right edge differs from `edge->next', or do nothing if the new
* trapezoid would be a continuation of the existing one. */
static inline cairo_status_t
static inline void
_cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t *left,
cairo_bo_edge_t *right,
int top,
cairo_traps_t *traps)
{
cairo_status_t status;
if (left->deferred_trap.right == right)
return CAIRO_STATUS_SUCCESS;
return;
assert (right);
if (left->deferred_trap.right != NULL) {
if (right != NULL && edges_colinear (left->deferred_trap.right, right))
if (edges_colinear (left->deferred_trap.right, right))
{
/* continuation on right, so just swap edges */
left->deferred_trap.right = right;
return CAIRO_STATUS_SUCCESS;
return;
}
status = _cairo_bo_edge_end_trap (left, top, traps);
if (unlikely (status))
return status;
_cairo_bo_edge_end_trap (left, top, traps);
}
if (right != NULL && ! edges_colinear (left, right)) {
if (! edges_colinear (left, right)) {
left->deferred_trap.top = top;
left->deferred_trap.right = right;
@ -1403,134 +1217,66 @@ _cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t *left,
top);
#endif
}
return CAIRO_STATUS_SUCCESS;
}
static inline cairo_status_t
_active_edges_to_traps (cairo_bo_edge_t *left,
int32_t top,
cairo_fill_rule_t fill_rule,
cairo_traps_t *traps)
static inline void
_active_edges_to_traps (cairo_bo_edge_t *pos,
int32_t top,
unsigned mask,
cairo_traps_t *traps)
{
cairo_bo_edge_t *right;
cairo_status_t status;
cairo_bo_edge_t *left;
int in_out;
#if DEBUG_PRINT_STATE
printf ("Processing active edges for %x\n", top);
#endif
if (fill_rule == CAIRO_FILL_RULE_WINDING) {
while (left != NULL) {
int in_out;
/* Greedily search for the closing edge, so that we generate the
* maximal span width with the minimal number of trapezoids.
in_out = 0;
left = pos;
while (pos != NULL) {
if (pos != left && pos->deferred_trap.right) {
/* XXX It shouldn't be possible to here with 2 deferred traps
* on colinear edges... See bug-bo-rictoz.
*/
in_out = left->edge.dir;
/* Check if there is a co-linear edge with an existing trap */
right = left->next;
if (left->deferred_trap.right == NULL) {
while (right != NULL && right->deferred_trap.right == NULL)
right = right->next;
if (right != NULL && edges_colinear (left, right)) {
/* continuation on left */
left->deferred_trap = right->deferred_trap;
right->deferred_trap.right = NULL;
}
if (left->deferred_trap.right == NULL &&
edges_colinear (left, pos))
{
/* continuation on left */
left->deferred_trap = pos->deferred_trap;
pos->deferred_trap.right = NULL;
}
/* End all subsumed traps */
right = left->next;
while (right != NULL) {
if (right->deferred_trap.right != NULL) {
status = _cairo_bo_edge_end_trap (right, top, traps);
if (unlikely (status))
return status;
}
in_out += right->edge.dir;
if (in_out == 0) {
cairo_bo_edge_t *next;
cairo_bool_t skip = FALSE;
/* skip co-linear edges */
next = right->next;
if (next != NULL)
skip = edges_colinear (right, next);
if (! skip)
break;
}
right = right->next;
else
{
_cairo_bo_edge_end_trap (pos, top, traps);
}
status = _cairo_bo_edge_start_or_continue_trap (left, right,
top, traps);
if (unlikely (status))
return status;
left = right;
if (left != NULL)
left = left->next;
}
} else {
while (left != NULL) {
int in_out = 0;
right = left->next;
while (right != NULL) {
if (right->deferred_trap.right != NULL) {
status = _cairo_bo_edge_end_trap (right, top, traps);
if (unlikely (status))
return status;
}
if ((in_out++ & 1) == 0) {
cairo_bo_edge_t *next;
cairo_bool_t skip = FALSE;
/* skip co-linear edges */
next = right->next;
if (next != NULL)
skip = edges_colinear (right, next);
if (! skip)
break;
}
right = right->next;
in_out += pos->edge.dir;
if ((in_out & mask) == 0) {
/* skip co-linear edges */
if (pos->next == NULL || ! edges_colinear (pos, pos->next)) {
_cairo_bo_edge_start_or_continue_trap (left, pos, top, traps);
left = pos->next;
}
status = _cairo_bo_edge_start_or_continue_trap (left, right,
top, traps);
if (unlikely (status))
return status;
left = right;
if (left != NULL)
left = left->next;
}
pos = pos->next;
}
return CAIRO_STATUS_SUCCESS;
}
/* Execute a single pass of the Bentley-Ottmann algorithm on edges,
* generating trapezoids according to the fill_rule and appending them
* to traps. */
static cairo_status_t
_cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t **start_events,
int num_events,
cairo_fill_rule_t fill_rule,
unsigned fill_rule,
cairo_traps_t *traps,
int *num_intersections)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS; /* silence compiler */
cairo_status_t status;
int intersection_count = 0;
cairo_bo_event_queue_t event_queue;
cairo_bo_sweep_line_t sweep_line;
@ -1538,6 +1284,12 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t **start_events,
cairo_bo_edge_t *left, *right;
cairo_bo_edge_t *e1, *e2;
/* convert the fill_rule into a winding mask */
if (fill_rule == CAIRO_FILL_RULE_WINDING)
fill_rule = (unsigned) -1;
else
fill_rule = 1;
#if DEBUG_EVENTS
{
int i;
@ -1565,20 +1317,16 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t **start_events,
if (event->point.y != sweep_line.current_y) {
for (e1 = sweep_line.stopped; e1; e1 = e1->next) {
if (e1->deferred_trap.right != NULL) {
status = _cairo_bo_edge_end_trap (e1,
e1->edge.bottom,
traps);
if (unlikely (status))
goto unwind;
_cairo_bo_edge_end_trap (e1,
e1->edge.bottom,
traps);
}
}
sweep_line.stopped = NULL;
status = _active_edges_to_traps (sweep_line.head,
sweep_line.current_y,
fill_rule, traps);
if (unlikely (status))
goto unwind;
_active_edges_to_traps (sweep_line.head,
sweep_line.current_y,
fill_rule, traps);
sweep_line.current_y = event->point.y;
}
@ -1596,9 +1344,7 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t **start_events,
case CAIRO_BO_EVENT_TYPE_START:
e1 = &((cairo_bo_start_event_t *) event)->edge;
status = _cairo_bo_sweep_line_insert (&sweep_line, e1);
if (unlikely (status))
goto unwind;
_cairo_bo_sweep_line_insert (&sweep_line, e1);
status = _cairo_bo_event_queue_insert_stop (&event_queue, e1);
if (unlikely (status))
@ -1701,11 +1447,10 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t **start_events,
*num_intersections = intersection_count;
for (e1 = sweep_line.stopped; e1; e1 = e1->next) {
if (e1->deferred_trap.right != NULL) {
status = _cairo_bo_edge_end_trap (e1, e1->edge.bottom, traps);
if (unlikely (status))
break;
_cairo_bo_edge_end_trap (e1, e1->edge.bottom, traps);
}
}
status = traps->status;
unwind:
_cairo_bo_event_queue_fini (&event_queue);
@ -1722,18 +1467,33 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
cairo_fill_rule_t fill_rule)
{
int intersections;
cairo_status_t status;
cairo_bo_start_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_start_event_t)];
cairo_bo_start_event_t *events;
cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
cairo_bo_event_t **event_ptrs;
int num_events;
int i;
cairo_bo_start_event_t *stack_event_y[64];
cairo_bo_start_event_t **event_y = NULL;
int i, num_events, y, ymin, ymax;
cairo_status_t status;
num_events = polygon->num_edges;
if (unlikely (0 == num_events))
return CAIRO_STATUS_SUCCESS;
if (polygon->num_limits) {
ymin = _cairo_fixed_integer_floor (polygon->limit.p1.y);
ymax = _cairo_fixed_integer_ceil (polygon->limit.p2.y) - ymin;
if (ymax > 64) {
event_y = _cairo_malloc_ab(sizeof (cairo_bo_event_t*), ymax);
if (unlikely (event_y == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
} else {
event_y = stack_event_y;
}
memset (event_y, 0, ymax * sizeof(cairo_bo_event_t *));
}
events = stack_events;
event_ptrs = stack_event_ptrs;
if (num_events > ARRAY_LENGTH (stack_events)) {
@ -1741,15 +1501,16 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
sizeof (cairo_bo_start_event_t) +
sizeof (cairo_bo_event_t *),
sizeof (cairo_bo_event_t *));
if (unlikely (events == NULL))
if (unlikely (events == NULL)) {
if (event_y != stack_event_y)
free (event_y);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
event_ptrs = (cairo_bo_event_t **) (events + num_events);
}
for (i = 0; i < num_events; i++) {
event_ptrs[i] = (cairo_bo_event_t *) &events[i];
events[i].type = CAIRO_BO_EVENT_TYPE_START;
events[i].point.y = polygon->edges[i].top;
events[i].point.x =
@ -1760,8 +1521,31 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
events[i].edge.deferred_trap.right = NULL;
events[i].edge.prev = NULL;
events[i].edge.next = NULL;
events[i].edge.colinear = NULL;
if (event_y) {
y = _cairo_fixed_integer_floor (events[i].point.y) - ymin;
events[i].edge.next = (cairo_bo_edge_t *) event_y[y];
event_y[y] = (cairo_bo_start_event_t *) &events[i];
} else
event_ptrs[i] = (cairo_bo_event_t *) &events[i];
}
if (event_y) {
for (y = i = 0; y < ymax && i < num_events; y++) {
cairo_bo_start_event_t *e;
int j = i;
for (e = event_y[y]; e; e = (cairo_bo_start_event_t *)e->edge.next)
event_ptrs[i++] = (cairo_bo_event_t *) e;
if (i > j + 1)
_cairo_bo_event_queue_sort (event_ptrs+j, i-j);
}
if (event_y != stack_event_y)
free (event_y);
} else
_cairo_bo_event_queue_sort (event_ptrs, i);
event_ptrs[i] = NULL;
#if DEBUG_TRAPS
dump_edges (events, num_events, "bo-polygon-edges.txt");
#endif
@ -1770,8 +1554,7 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
* passes of the Bentley-Ottmann algorithm. It would merely
* require storing the results of each pass into a temporary
* cairo_traps_t. */
status = _cairo_bentley_ottmann_tessellate_bo_edges (event_ptrs,
num_events,
status = _cairo_bentley_ottmann_tessellate_bo_edges (event_ptrs, num_events,
fill_rule, traps,
&intersections);
#if DEBUG_TRAPS
@ -1799,8 +1582,7 @@ _cairo_bentley_ottmann_tessellate_traps (cairo_traps_t *traps,
dump_traps (traps, "bo-traps-in.txt");
#endif
_cairo_polygon_init (&polygon);
_cairo_polygon_limit (&polygon, traps->limits, traps->num_limits);
_cairo_polygon_init (&polygon, traps->limits, traps->num_limits);
for (i = 0; i < traps->num_traps; i++) {
status = _cairo_polygon_add_line (&polygon,

Просмотреть файл

@ -1,4 +1,4 @@
/* vim:set ts=8 sw=2 noet cin: */
/* vim:set ts=8 sw=4 noet cin: */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Christian Biesinger <cbiesinger@web.de>
@ -13,7 +13,7 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -40,6 +40,9 @@
#include "cairo-beos.h"
#include "cairo-error-private.h"
#include "cairo-image-surface-inline.h"
#include <new>
#include <Bitmap.h>
@ -51,11 +54,23 @@
#include <Window.h>
#include <Locker.h>
/**
* SECTION:beos-surface
* @Title: BeOS Surfaces
* @Short_Description: BeOS surface support
* @See_Also: #cairo_surface_t
*
* The BeOS surface is used to render cairo graphics to BeOS views
* and bitmaps.
**/
#define CAIRO_INT_STATUS_SUCCESS (cairo_int_status_t)(CAIRO_STATUS_SUCCESS)
struct cairo_beos_surface_t {
cairo_surface_t base;
cairo_region_t *clip_region;
BView* view;
/*
@ -70,7 +85,6 @@ struct cairo_beos_surface_t {
BBitmap* bitmap;
// If true, surface and view should be deleted when this surface is
// destroyed
bool owns_bitmap_view;
@ -101,27 +115,28 @@ _cairo_beos_surface_create_internal (BView* view,
BBitmap* bmp,
bool owns_bitmap_view = false);
static BRect
_cairo_rect_to_brect (const cairo_rectangle_int16_t* rect)
static inline BRect
_cairo_rectangle_to_brect (const cairo_rectangle_int_t* rect)
{
// A BRect is one pixel wider than you'd think
return BRect(rect->x, rect->y, rect->x + rect->width - 1,
rect->y + rect->height - 1);
return BRect (rect->x, rect->y,
rect->x + rect->width - 1,
rect->y + rect->height - 1);
}
static cairo_rectangle_int16_t
_brect_to_cairo_rect (const BRect& rect)
static inline cairo_rectangle_int_t
_brect_to_cairo_rectangle (const BRect &rect)
{
cairo_rectangle_int16_t retval;
retval.x = int(rect.left + 0.5);
retval.y = int(rect.top + 0.5);
retval.width = rect.IntegerWidth() + 1;
retval.height = rect.IntegerHeight() + 1;
cairo_rectangle_int_t retval;
retval.x = floor (rect.left);
retval.y = floor (rect.top);
retval.width = ceil (rect.right) - retval.x + 1;
retval.height = ceil (rect.bottom) - rectval.y + 1;
return retval;
}
static rgb_color
_cairo_color_to_be_color (const cairo_color_t* color)
static inline rgb_color
_cairo_color_to_be_color (const cairo_color_t *color)
{
// This factor ensures a uniform distribution of numbers
const float factor = 256 - 1e-5;
@ -199,32 +214,8 @@ _cairo_beos_view_to_bitmap (BView* view,
return ERROR;
}
inline unsigned char
unpremultiply (unsigned char color,
unsigned char alpha)
{
if (alpha == 0)
return 0;
// plus alpha/2 to round instead of truncate
return (color * 255 + alpha / 2) / alpha;
}
inline unsigned char
premultiply (unsigned char color,
unsigned char alpha)
{
// + 127 to round, instead of truncate
return (color * alpha + 127) / 255;
}
/**
* unpremultiply_rgba:
*
* Takes an input in ABGR premultiplied image data and unmultiplies it.
* The result is stored in retdata.
**/
static void
unpremultiply_rgba (unsigned char* data,
unpremultiply_bgra (unsigned char* data,
int width,
int height,
int stride,
@ -235,52 +226,108 @@ unpremultiply_rgba (unsigned char* data,
in < end;
in += stride, out += stride)
{
for (int i = 0; i < width; ++i) {
// XXX for a big-endian platform this'd have to change
int idx = 4 * i;
unsigned char alpha = in[idx + 3];
out[idx + 0] = unpremultiply(in[idx + 0], alpha); // B
out[idx + 1] = unpremultiply(in[idx + 1], alpha); // G
out[idx + 2] = unpremultiply(in[idx + 2], alpha); // R
out[idx + 3] = in[idx + 3]; // Alpha
for (int i = 0; i < width; i ++) {
uint8_t *b = &out[4*i];
uint32_t pixel;
uint8_t alpha;
memcpy (&pixel, &data[4*i], sizeof (uint32_t));
alpha = pixel & 0xff;
if (alpha == 0) {
b[0] = b[1] = b[2] = b[3] = 0;
} else {
b[0] = (((pixel >> 24) & 0xff) * 255 + alpha / 2) / alpha;
b[1] = (((pixel >> 16) & 0xff) * 255 + alpha / 2) / alpha;
b[2] = (((pixel >> 8) & 0xff) * 255 + alpha / 2) / alpha;
b[3] = alpha;
}
}
}
}
/**
* premultiply_rgba:
*
* Takes an input in ABGR non-premultiplied image data and premultiplies it.
* The returned data must be freed with free().
**/
static inline int
multiply_alpha (int alpha, int color)
{
int temp = (alpha * color) + 0x80;
return ((temp + (temp >> 8)) >> 8);
}
static unsigned char*
premultiply_rgba (unsigned char* data,
premultiply_bgra (unsigned char* data,
int width,
int height,
int stride)
{
unsigned char* retdata = reinterpret_cast<unsigned char*>(_cairo_malloc_ab(height, stride));
uint8_t * retdata = reinterpret_cast<unsigned char*>(_cairo_malloc_ab(height, stride));
if (!retdata)
return NULL;
unsigned char* end = data + stride * height;
for (unsigned char* in = data, *out = retdata;
uint8_t * end = data + stride * height;
for (uint8_t * in = data, *out = retdata;
in < end;
in += stride, out += stride)
{
for (int i = 0; i < width; ++i) {
// XXX for a big-endian platform this'd have to change
int idx = 4 * i;
unsigned char alpha = in[idx + 3];
out[idx + 0] = premultiply(in[idx + 0], alpha); // B
out[idx + 1] = premultiply(in[idx + 1], alpha); // G
out[idx + 2] = premultiply(in[idx + 2], alpha); // R
out[idx + 3] = in[idx + 3]; // Alpha
for (int i = 0; i < width; i ++) {
uint8_t *base = &in[4*i];
uint8_t alpha = base[3];
uint32_t p;
if (alpha == 0) {
p = 0;
} else {
uint8_t blue = base[0];
uint8_t green = base[1];
uint8_t red = base[2];
if (alpha != 0xff) {
blue = multiply_alpha (alpha, blue);
green = multiply_alpha (alpha, green);
red = multiply_alpha (alpha, red);
}
p = (alpha << 0) | (red << 8) | (green << 16) | ((uint32_t)blue << 24);
}
memcpy (&out[4*i], &p, sizeof (uint32_t));
}
}
return retdata;
}
static cairo_int_status_t
_cairo_beos_surface_set_clip_region (cairo_beos_surface_t *surface,
cairo_region_t *region)
{
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
abstract_surface);
AutoLockView locker(surface->view);
assert (locker);
if (region == surface->clip_region)
return CAIRO_INT_STATUS_SUCCESS;
cairo_region_destroy (surface->clip_region);
surface->clip_region = cairo_region_reference (region);
if (region == NULL) {
// No clipping
surface->view->ConstrainClippingRegion(NULL);
return CAIRO_INT_STATUS_SUCCESS;
}
int count = cairo_region_num_rectangles (region);
BRegion bregion;
for (int i = 0; i < count; ++i) {
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect);
// Have to subtract one, because for pixman, the second coordinate
// lies outside the rectangle.
bregion.Include (_cairo_rectangle_to_brect (&rect));
}
surface->view->ConstrainClippingRegion(&bregion);
return CAIRO_INT_STATUS_SUCCESS;
}
/**
* _cairo_beos_bitmap_to_surface:
*
@ -309,8 +356,8 @@ _cairo_beos_bitmap_to_surface (BBitmap* bitmap)
return imgsurf;
}
cairo_format_t cformat = format == B_RGB32 ? CAIRO_FORMAT_RGB24
: CAIRO_FORMAT_ARGB32;
cairo_format_t cformat = format == B_RGB32 ?
CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32;
BRect bounds(bitmap->Bounds());
unsigned char* bits = reinterpret_cast<unsigned char*>(bitmap->Bits());
@ -318,8 +365,8 @@ _cairo_beos_bitmap_to_surface (BBitmap* bitmap)
int height = bounds.IntegerHeight() + 1;
unsigned char* premultiplied;
if (cformat == CAIRO_FORMAT_ARGB32) {
premultiplied = premultiply_rgba(bits, width, height,
bitmap->BytesPerRow());
premultiplied = premultiply_bgra (bits, width, height,
bitmap->BytesPerRow());
} else {
premultiplied = reinterpret_cast<unsigned char*>(
_cairo_malloc_ab(bitmap->BytesPerRow(), height));
@ -327,7 +374,7 @@ _cairo_beos_bitmap_to_surface (BBitmap* bitmap)
memcpy(premultiplied, bits, bitmap->BytesPerRow() * height);
}
if (!premultiplied)
return NULL;
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
cairo_image_surface_t* surf = reinterpret_cast<cairo_image_surface_t*>
(cairo_image_surface_create_for_data(premultiplied,
@ -355,11 +402,11 @@ _cairo_image_surface_to_bitmap (cairo_image_surface_t* surface)
switch (surface->format) {
case CAIRO_FORMAT_ARGB32: {
BBitmap* data = new BBitmap(size, B_RGBA32);
unpremultiply_rgba(surface->data,
surface->width,
surface->height,
surface->stride,
reinterpret_cast<unsigned char*>(data->Bits()));
unpremultiply_bgra (surface->data,
surface->width,
surface->height,
surface->stride,
reinterpret_cast<unsigned char*>(data->Bits()));
return data;
}
case CAIRO_FORMAT_RGB24: {
@ -384,44 +431,44 @@ _cairo_op_to_be_op (cairo_operator_t cairo_op,
drawing_mode* beos_op)
{
switch (cairo_op) {
case CAIRO_OPERATOR_SOURCE:
*beos_op = B_OP_COPY;
return true;
case CAIRO_OPERATOR_OVER:
*beos_op = B_OP_ALPHA;
return true;
case CAIRO_OPERATOR_SOURCE:
*beos_op = B_OP_COPY;
return true;
case CAIRO_OPERATOR_OVER:
*beos_op = B_OP_ALPHA;
return true;
case CAIRO_OPERATOR_ADD:
// Does not actually work
case CAIRO_OPERATOR_ADD:
// Does not actually work
// XXX This is a fundamental compositing operator, it has to work!
#if 1
return false;
return false;
#else
*beos_op = B_OP_ADD;
return true;
*beos_op = B_OP_ADD;
return true;
#endif
case CAIRO_OPERATOR_CLEAR:
// Does not map to B_OP_ERASE - it replaces the dest with the low
// color, instead of transparency; could be done by setting low
// color appropriately.
case CAIRO_OPERATOR_CLEAR:
// Does not map to B_OP_ERASE - it replaces the dest with the low
// color, instead of transparency; could be done by setting low
// color appropriately.
case CAIRO_OPERATOR_IN:
case CAIRO_OPERATOR_OUT:
case CAIRO_OPERATOR_ATOP:
case CAIRO_OPERATOR_IN:
case CAIRO_OPERATOR_OUT:
case CAIRO_OPERATOR_ATOP:
case CAIRO_OPERATOR_DEST:
case CAIRO_OPERATOR_DEST_OVER:
case CAIRO_OPERATOR_DEST_IN:
case CAIRO_OPERATOR_DEST_OUT:
case CAIRO_OPERATOR_DEST_ATOP:
case CAIRO_OPERATOR_DEST:
case CAIRO_OPERATOR_DEST_OVER:
case CAIRO_OPERATOR_DEST_IN:
case CAIRO_OPERATOR_DEST_OUT:
case CAIRO_OPERATOR_DEST_ATOP:
case CAIRO_OPERATOR_XOR:
case CAIRO_OPERATOR_SATURATE:
case CAIRO_OPERATOR_XOR:
case CAIRO_OPERATOR_SATURATE:
default:
return false;
};
default:
return false;
}
}
static cairo_surface_t *
@ -430,8 +477,6 @@ _cairo_beos_surface_create_similar (void *abstract_surface,
int width,
int height)
{
fprintf(stderr, "Creating similar\n");
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
abstract_surface);
@ -444,9 +489,7 @@ _cairo_beos_surface_create_similar (void *abstract_surface,
BBitmap* bmp;
switch (content) {
case CAIRO_CONTENT_ALPHA:
// Can't support this natively
return _cairo_image_surface_create_with_content(content, width,
height);
return NULL;
case CAIRO_CONTENT_COLOR_ALPHA:
bmp = new BBitmap(rect, B_RGBA32, true);
break;
@ -470,10 +513,9 @@ _cairo_beos_surface_create_similar (void *abstract_surface,
}
break;
default:
assert(0);
ASSERT_NOT_REACHED;
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);
@ -495,6 +537,8 @@ _cairo_beos_surface_finish (void *abstract_surface)
surface->bitmap = NULL;
}
cairo_region_destroy (surface->clip_region);
return CAIRO_STATUS_SUCCESS;
}
@ -503,7 +547,6 @@ _cairo_beos_surface_acquire_source_image (void *abstract_surfa
cairo_image_surface_t **image_out,
void **image_extra)
{
fprintf(stderr, "Getting source image\n");
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
abstract_surface);
AutoLockView locker(surface->view);
@ -514,9 +557,9 @@ _cairo_beos_surface_acquire_source_image (void *abstract_surfa
surface->view->Sync();
if (surface->bitmap) {
*image_out = _cairo_beos_bitmap_to_surface(surface->bitmap);
if (!*image_out)
return CAIRO_STATUS_NO_MEMORY;
*image_out = _cairo_beos_bitmap_to_surface (surface->bitmap);
if (unlikely ((*image_out)->base.status))
return (*image_out)->base.status;
*image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
@ -526,10 +569,10 @@ _cairo_beos_surface_acquire_source_image (void *abstract_surfa
if (_cairo_beos_view_to_bitmap(surface->view, &bmp) != OK)
return CAIRO_STATUS_NO_MEMORY; /// XXX incorrect if the error was NOT_VISIBLE
*image_out = _cairo_beos_bitmap_to_surface(bmp);
if (!*image_out) {
*image_out = _cairo_beos_bitmap_to_surface (bmp);
if (unlikely ((*image_out)->base.status)) {
delete bmp;
return CAIRO_STATUS_NO_MEMORY;
return (*image_out)->base.status;
}
*image_extra = bmp;
@ -543,17 +586,17 @@ _cairo_beos_surface_release_source_image (void *abstract_surfac
{
cairo_surface_destroy (&image->base);
BBitmap* bmp = static_cast<BBitmap*>(image_extra);
delete bmp;
if (image_extra != NULL) {
BBitmap* bmp = static_cast<BBitmap*>(image_extra);
delete bmp;
}
}
static cairo_status_t
_cairo_beos_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int16_t *image_rect,
cairo_rectangle_int_t *image_rect,
void **image_extra)
{
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
@ -563,14 +606,14 @@ _cairo_beos_surface_acquire_dest_image (void *abstract_surface,
if (!locker) {
*image_out = NULL;
*image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
return (cairo_status_t) CAIRO_INT_STATUS_NOTHING_TO_DO;
}
if (surface->bitmap) {
surface->view->Sync();
*image_out = _cairo_beos_bitmap_to_surface(surface->bitmap);
if (!*image_out)
return CAIRO_STATUS_NO_MEMORY;
if (unlikely ((*image_out)->base.status))
return (*image_out)->base.status;
image_rect->x = 0;
image_rect->y = 0;
@ -581,7 +624,7 @@ _cairo_beos_surface_acquire_dest_image (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
BRect b_interest_rect(_cairo_rect_to_brect(interest_rect));
BRect b_interest_rect (_cairo_rectangle_to_brect (interest_rect));
BRect rect;
BBitmap* bitmap;
@ -595,18 +638,11 @@ _cairo_beos_surface_acquire_dest_image (void *abstract_surface,
if (status == ERROR)
return CAIRO_STATUS_NO_MEMORY;
*image_rect = _brect_to_cairo_rect(rect);
#if 0
fprintf(stderr, "Requested: (cairo rects) (%ix%i) dim (%u, %u) returning (%ix%i) dim (%u, %u)\n",
interest_rect->x, interest_rect->y, interest_rect->width, interest_rect->height,
image_rect->x, image_rect->y, image_rect->width, image_rect->height);
#endif
*image_rect = _brect_to_cairo_rectangle(rect);
*image_out = _cairo_beos_bitmap_to_surface(bitmap);
delete bitmap;
if (!*image_out)
return CAIRO_STATUS_NO_MEMORY;
if (unlikely ((*image_out)->base.status))
return (*image_out)->base.status;
*image_extra = NULL;
@ -616,13 +652,11 @@ _cairo_beos_surface_acquire_dest_image (void *abstract_surface,
static void
_cairo_beos_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_int16_t *intersect_rect,
cairo_rectangle_int_t *intersect_rect,
cairo_image_surface_t *image,
cairo_rectangle_int16_t *image_rect,
cairo_rectangle_int_t *image_rect,
void *image_extra)
{
fprintf(stderr, "Fallback drawing\n");
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
abstract_surface);
@ -634,9 +668,9 @@ _cairo_beos_surface_release_dest_image (void *abstract_surface,
surface->view->PushState();
surface->view->SetDrawingMode(B_OP_COPY);
BRect rect(_cairo_rect_to_brect(image_rect));
surface->view->DrawBitmap(bitmap_to_draw, rect);
surface->view->DrawBitmap (bitmap_to_draw,
_cairo_rectangle_to_brect (image_rect));
surface->view->PopState();
@ -649,17 +683,19 @@ _cairo_beos_surface_composite (cairo_operator_t op,
cairo_pattern_t *src,
cairo_pattern_t *mask,
void *dst,
int src_x,
int src_x,
int src_y,
int mask_x,
int mask_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height)
unsigned int height,
cairo_region_t *clip_region)
{
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
dst);
cairo_int_status_t status;
AutoLockView locker(surface->view);
if (!locker)
return CAIRO_INT_STATUS_SUCCESS;
@ -684,6 +720,10 @@ _cairo_beos_surface_composite (cairo_operator_t op,
if (!_cairo_matrix_is_integer_translation(&src->matrix, &itx, &ity))
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_beos_surface_set_clip_region (surface, clip_region);
if (unlikely (status))
return status;
BRect srcRect(src_x + itx,
src_y + ity,
src_x + itx + width - 1,
@ -731,8 +771,6 @@ _cairo_beos_surface_composite (cairo_operator_t op,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
fprintf(stderr, "Composite\n");
// Draw it on screen.
surface->view->PushState();
@ -767,24 +805,17 @@ _cairo_beos_surface_composite (cairo_operator_t op,
}
static void
_cairo_beos_surface_fill_rectangle (cairo_beos_surface_t *surface,
cairo_rectangle_int16_t *rect)
{
BRect brect(_cairo_rect_to_brect(rect));
surface->view->FillRect(brect);
}
static cairo_int_status_t
_cairo_beos_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_int16_t *rects,
int num_rects)
cairo_rectangle_int_t *rects,
int num_rects,
cairo_region_t *clip_region)
{
fprintf(stderr, "Drawing %i rectangles\n", num_rects);
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
abstract_surface);
cairo_int_status_t status;
if (num_rects <= 0)
return CAIRO_INT_STATUS_SUCCESS;
@ -797,6 +828,10 @@ _cairo_beos_surface_fill_rectangles (void *abstract_surface,
if (!_cairo_op_to_be_op(op, &mode))
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_beos_surface_set_clip_region (surface, clip_region);
if (unlikely (status))
return status;
rgb_color be_color = _cairo_color_to_be_color(color);
if (mode == B_OP_ALPHA && be_color.alpha == 0xFF)
@ -808,9 +843,9 @@ _cairo_beos_surface_fill_rectangles (void *abstract_surface,
if (mode == B_OP_COPY && be_color.alpha != 0xFF &&
(!surface->bitmap || surface->bitmap->ColorSpace() != B_RGBA32))
{
be_color.red = premultiply(be_color.red, be_color.alpha);
be_color.green = premultiply(be_color.green, be_color.alpha);
be_color.blue = premultiply(be_color.blue, be_color.alpha);
be_color.red = color->red_short >> 8;
be_color.green = color->green_short >> 8;
be_color.blue = color->blue_short >> 8;
}
surface->view->PushState();
@ -822,65 +857,26 @@ _cairo_beos_surface_fill_rectangles (void *abstract_surface,
else
surface->view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
for (int i = 0; i < num_rects; ++i) {
_cairo_beos_surface_fill_rectangle(surface, &rects[i]);
}
for (int i = 0; i < num_rects; ++i)
surface->view->FillRect (_cairo_rectangle_to_brect (&rects[i]));
surface->view->PopState();
return CAIRO_INT_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_beos_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region)
{
fprintf(stderr, "Setting clip region\n");
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
abstract_surface);
AutoLockView locker(surface->view);
if (!locker)
return CAIRO_INT_STATUS_SUCCESS;
if (region == NULL) {
// No clipping
surface->view->ConstrainClippingRegion(NULL);
return CAIRO_INT_STATUS_SUCCESS;
}
int count = pixman_region_num_rects(region);
pixman_box16_t* rects = pixman_region_rects(region);
BRegion bregion;
for (int i = 0; i < count; ++i) {
// Have to substract one, because for pixman, the second coordinate
// lies outside the rectangle.
bregion.Include(BRect(rects[i].x1, rects[i].y1, rects[i].x2 - 1, rects[i].y2 - 1));
}
surface->view->ConstrainClippingRegion(&bregion);
return CAIRO_INT_STATUS_SUCCESS;
}
static cairo_int_status_t
static cairo_bool_t
_cairo_beos_surface_get_extents (void *abstract_surface,
cairo_rectangle_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
abstract_surface);
AutoLockView locker(surface->view);
if (!locker)
return CAIRO_INT_STATUS_UNSUPPORTED;
return FALSE;
BRect size = surface->view->Bounds();
*rectangle = _brect_to_cairo_rect(size);
// Make sure to have our upperleft edge as (0,0)
rectangle->x = 0;
rectangle->y = 0;
return CAIRO_INT_STATUS_SUCCESS;
*rectangle = _brect_to_cairo_rectangle (surface->view->Bounds());
return TRUE;
}
static const struct _cairo_surface_backend cairo_beos_surface_backend = {
@ -899,8 +895,6 @@ static const struct _cairo_surface_backend cairo_beos_surface_backend = {
NULL, /* check_span_renderer */
NULL, /* copy_page */
NULL, /* show_page */
_cairo_beos_surface_set_clip_region,
NULL, /* intersect_clip_path */
_cairo_beos_surface_get_extents,
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
@ -932,13 +926,18 @@ _cairo_beos_surface_create_internal (BView* view,
cairo_content_t content = CAIRO_CONTENT_COLOR;
if (bmp && (bmp->ColorSpace() == B_RGBA32 || bmp->ColorSpace() == B_RGBA15))
content = CAIRO_CONTENT_COLOR_ALPHA;
_cairo_surface_init(&surface->base, &cairo_beos_surface_backend, content);
_cairo_surface_init (&surface->base,
&cairo_beos_surface_backend,
NULL, /* device */
content);
surface->view = view;
surface->bitmap = bmp;
surface->owns_bitmap_view = owns_bitmap_view;
return (cairo_surface_t *) surface;
surface->clip_region = NULL;
return &surface->base;
}
/**
@ -949,6 +948,8 @@ _cairo_beos_surface_create_internal (BView* view,
* The caller must ensure that the view does not get deleted before the surface.
* If the view is attached to a bitmap rather than an on-screen window, use
* cairo_beos_surface_create_for_bitmap() instead of this function.
*
* Since: TBD
**/
cairo_surface_t *
cairo_beos_surface_create (BView* view)
@ -972,6 +973,8 @@ cairo_beos_surface_create (BView* view)
*
* For now, only views that draw to the entire area of bmp are supported.
* The view must already be attached to the bitmap.
*
* Since: TBD
**/
cairo_surface_t *
cairo_beos_surface_create_for_bitmap (BView* view,

Просмотреть файл

@ -43,9 +43,9 @@
#include "cairoint.h"
#include "cairo-error-private.h"
#include "cairo-list-private.h"
#include "cairo-list-inline.h"
#include "cairo-freelist-private.h"
#include "cairo-combsort-private.h"
#include "cairo-combsort-inline.h"
#include <setjmp.h>
@ -456,7 +456,7 @@ edges_compare_x_for_y (const cairo_edge_t *a,
HAVE_BX = 0x2,
HAVE_BOTH = HAVE_AX | HAVE_BX
} have_ax_bx = HAVE_BOTH;
int32_t ax, bx;
int32_t ax = 0, bx = 0;
/* XXX given we have x and dx? */
@ -1072,7 +1072,7 @@ coverage_reset (struct coverage *cells)
coverage_rewind (cells);
}
inline static struct cell *
static struct cell *
coverage_alloc (sweep_line_t *sweep_line,
struct cell *tail,
int x)
@ -1397,6 +1397,7 @@ render_rows (cairo_botor_scan_converter_t *self,
if (x > prev_x) {
spans[num_spans].x = prev_x;
spans[num_spans].inverse = 0;
spans[num_spans].coverage = AREA_TO_ALPHA (cover);
++num_spans;
}
@ -1413,12 +1414,14 @@ render_rows (cairo_botor_scan_converter_t *self,
if (prev_x <= self->xmax) {
spans[num_spans].x = prev_x;
spans[num_spans].inverse = 0;
spans[num_spans].coverage = AREA_TO_ALPHA (cover);
++num_spans;
}
if (cover && prev_x < self->xmax) {
spans[num_spans].x = self->xmax;
spans[num_spans].inverse = 1;
spans[num_spans].coverage = 0;
++num_spans;
}
@ -2125,6 +2128,7 @@ botor_add_edge (cairo_botor_scan_converter_t *self,
return CAIRO_STATUS_SUCCESS;
}
#if 0
static cairo_status_t
_cairo_botor_scan_converter_add_edge (void *converter,
const cairo_point_t *p1,
@ -2143,9 +2147,10 @@ _cairo_botor_scan_converter_add_edge (void *converter,
return botor_add_edge (self, &edge);
}
#endif
static cairo_status_t
_cairo_botor_scan_converter_add_polygon (void *converter,
cairo_status_t
_cairo_botor_scan_converter_add_polygon (cairo_botor_scan_converter_t *converter,
const cairo_polygon_t *polygon)
{
cairo_botor_scan_converter_t *self = converter;
@ -2179,8 +2184,6 @@ _cairo_botor_scan_converter_init (cairo_botor_scan_converter_t *self,
cairo_fill_rule_t fill_rule)
{
self->base.destroy = _cairo_botor_scan_converter_destroy;
self->base.add_edge = _cairo_botor_scan_converter_add_edge;
self->base.add_polygon = _cairo_botor_scan_converter_add_polygon;
self->base.generate = _cairo_botor_scan_converter_generate;
self->extents = *extents;

Просмотреть файл

@ -0,0 +1,131 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2010 Andrea Canciani
*
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.
*
* Contributor(s):
* Andrea Canciani <ranma42@gmail.com>
*/
#ifndef CAIRO_BOX_H
#define CAIRO_BOX_H
#include "cairo-types-private.h"
#include "cairo-compiler-private.h"
#include "cairo-fixed-private.h"
static inline void
_cairo_box_set (cairo_box_t *box,
const cairo_point_t *p1,
const cairo_point_t *p2)
{
box->p1 = *p1;
box->p2 = *p2;
}
static inline void
_cairo_box_from_integers (cairo_box_t *box, int x, int y, int w, int h)
{
box->p1.x = _cairo_fixed_from_int (x);
box->p1.y = _cairo_fixed_from_int (y);
box->p2.x = _cairo_fixed_from_int (x + w);
box->p2.y = _cairo_fixed_from_int (y + h);
}
static inline void
_cairo_box_from_rectangle_int (cairo_box_t *box,
const cairo_rectangle_int_t *rect)
{
box->p1.x = _cairo_fixed_from_int (rect->x);
box->p1.y = _cairo_fixed_from_int (rect->y);
box->p2.x = _cairo_fixed_from_int (rect->x + rect->width);
box->p2.y = _cairo_fixed_from_int (rect->y + rect->height);
}
/* assumes box->p1 is top-left, p2 bottom-right */
static inline void
_cairo_box_add_point (cairo_box_t *box,
const cairo_point_t *point)
{
if (point->x < box->p1.x)
box->p1.x = point->x;
else if (point->x > box->p2.x)
box->p2.x = point->x;
if (point->y < box->p1.y)
box->p1.y = point->y;
else if (point->y > box->p2.y)
box->p2.y = point->y;
}
static inline void
_cairo_box_add_box (cairo_box_t *box,
const cairo_box_t *add)
{
if (add->p1.x < box->p1.x)
box->p1.x = add->p1.x;
if (add->p2.x > box->p2.x)
box->p2.x = add->p2.x;
if (add->p1.y < box->p1.y)
box->p1.y = add->p1.y;
if (add->p2.y > box->p2.y)
box->p2.y = add->p2.y;
}
/* assumes box->p1 is top-left, p2 bottom-right */
static inline cairo_bool_t
_cairo_box_contains_point (const cairo_box_t *box,
const cairo_point_t *point)
{
return box->p1.x <= point->x && point->x <= box->p2.x &&
box->p1.y <= point->y && point->y <= box->p2.y;
}
static inline cairo_bool_t
_cairo_box_is_pixel_aligned (const cairo_box_t *box)
{
#if CAIRO_FIXED_FRAC_BITS <= 8 && 0
return ((cairo_fixed_unsigned_t)(box->p1.x & CAIRO_FIXED_FRAC_MASK) << 24 |
(box->p1.y & CAIRO_FIXED_FRAC_MASK) << 16 |
(box->p2.x & CAIRO_FIXED_FRAC_MASK) << 8 |
(box->p2.y & CAIRO_FIXED_FRAC_MASK) << 0) == 0;
#else /* GCC on i7 prefers this variant (bizarrely according to the profiler) */
cairo_fixed_t f;
f = 0;
f |= box->p1.x & CAIRO_FIXED_FRAC_MASK;
f |= box->p1.y & CAIRO_FIXED_FRAC_MASK;
f |= box->p2.x & CAIRO_FIXED_FRAC_MASK;
f |= box->p2.y & CAIRO_FIXED_FRAC_MASK;
return f == 0;
#endif
}
#endif /* CAIRO_BOX_H */

Просмотреть файл

@ -0,0 +1,690 @@
/*
* Copyright © 2004 Carl Worth
* Copyright © 2006 Red Hat, Inc.
* Copyright © 2009 Chris Wilson
* Copyright © 2011 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Carl Worth
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
* Chris Wilson <chris@chris-wilson.co.uk>
*/
/* Provide definitions for standalone compilation */
#include "cairoint.h"
#include "cairo-boxes-private.h"
#include "cairo-error-private.h"
#include "cairo-combsort-inline.h"
#include "cairo-list-private.h"
#include <setjmp.h>
typedef struct _rectangle rectangle_t;
typedef struct _edge edge_t;
struct _edge {
edge_t *next, *prev;
edge_t *right;
cairo_fixed_t x, top;
int a_or_b;
int dir;
};
struct _rectangle {
edge_t left, right;
int32_t top, bottom;
};
#define UNROLL3(x) x x x
/* the parent is always given by index/2 */
#define PQ_PARENT_INDEX(i) ((i) >> 1)
#define PQ_FIRST_ENTRY 1
/* left and right children are index * 2 and (index * 2) +1 respectively */
#define PQ_LEFT_CHILD_INDEX(i) ((i) << 1)
typedef struct _pqueue {
int size, max_size;
rectangle_t **elements;
rectangle_t *elements_embedded[1024];
} pqueue_t;
typedef struct _sweep_line {
rectangle_t **rectangles;
pqueue_t pq;
edge_t head, tail;
edge_t *insert_left, *insert_right;
int32_t current_y;
int32_t last_y;
jmp_buf unwind;
} sweep_line_t;
#define DEBUG_TRAPS 0
#if DEBUG_TRAPS
static void
dump_traps (cairo_traps_t *traps, const char *filename)
{
FILE *file;
int n;
if (getenv ("CAIRO_DEBUG_TRAPS") == NULL)
return;
file = fopen (filename, "a");
if (file != NULL) {
for (n = 0; n < traps->num_traps; n++) {
fprintf (file, "%d %d L:(%d, %d), (%d, %d) R:(%d, %d), (%d, %d)\n",
traps->traps[n].top,
traps->traps[n].bottom,
traps->traps[n].left.p1.x,
traps->traps[n].left.p1.y,
traps->traps[n].left.p2.x,
traps->traps[n].left.p2.y,
traps->traps[n].right.p1.x,
traps->traps[n].right.p1.y,
traps->traps[n].right.p2.x,
traps->traps[n].right.p2.y);
}
fprintf (file, "\n");
fclose (file);
}
}
#else
#define dump_traps(traps, filename)
#endif
static inline int
rectangle_compare_start (const rectangle_t *a,
const rectangle_t *b)
{
return a->top - b->top;
}
static inline int
rectangle_compare_stop (const rectangle_t *a,
const rectangle_t *b)
{
return a->bottom - b->bottom;
}
static inline void
pqueue_init (pqueue_t *pq)
{
pq->max_size = ARRAY_LENGTH (pq->elements_embedded);
pq->size = 0;
pq->elements = pq->elements_embedded;
pq->elements[PQ_FIRST_ENTRY] = NULL;
}
static inline void
pqueue_fini (pqueue_t *pq)
{
if (pq->elements != pq->elements_embedded)
free (pq->elements);
}
static cairo_bool_t
pqueue_grow (pqueue_t *pq)
{
rectangle_t **new_elements;
pq->max_size *= 2;
if (pq->elements == pq->elements_embedded) {
new_elements = _cairo_malloc_ab (pq->max_size,
sizeof (rectangle_t *));
if (unlikely (new_elements == NULL))
return FALSE;
memcpy (new_elements, pq->elements_embedded,
sizeof (pq->elements_embedded));
} else {
new_elements = _cairo_realloc_ab (pq->elements,
pq->max_size,
sizeof (rectangle_t *));
if (unlikely (new_elements == NULL))
return FALSE;
}
pq->elements = new_elements;
return TRUE;
}
static inline void
pqueue_push (sweep_line_t *sweep, rectangle_t *rectangle)
{
rectangle_t **elements;
int i, parent;
if (unlikely (sweep->pq.size + 1 == sweep->pq.max_size)) {
if (unlikely (! pqueue_grow (&sweep->pq))) {
longjmp (sweep->unwind,
_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
}
elements = sweep->pq.elements;
for (i = ++sweep->pq.size;
i != PQ_FIRST_ENTRY &&
rectangle_compare_stop (rectangle,
elements[parent = PQ_PARENT_INDEX (i)]) < 0;
i = parent)
{
elements[i] = elements[parent];
}
elements[i] = rectangle;
}
static inline void
pqueue_pop (pqueue_t *pq)
{
rectangle_t **elements = pq->elements;
rectangle_t *tail;
int child, i;
tail = elements[pq->size--];
if (pq->size == 0) {
elements[PQ_FIRST_ENTRY] = NULL;
return;
}
for (i = PQ_FIRST_ENTRY;
(child = PQ_LEFT_CHILD_INDEX (i)) <= pq->size;
i = child)
{
if (child != pq->size &&
rectangle_compare_stop (elements[child+1],
elements[child]) < 0)
{
child++;
}
if (rectangle_compare_stop (elements[child], tail) >= 0)
break;
elements[i] = elements[child];
}
elements[i] = tail;
}
static inline rectangle_t *
rectangle_pop_start (sweep_line_t *sweep_line)
{
return *sweep_line->rectangles++;
}
static inline rectangle_t *
rectangle_peek_stop (sweep_line_t *sweep_line)
{
return sweep_line->pq.elements[PQ_FIRST_ENTRY];
}
CAIRO_COMBSORT_DECLARE (_rectangle_sort,
rectangle_t *,
rectangle_compare_start)
static void
sweep_line_init (sweep_line_t *sweep_line,
rectangle_t **rectangles,
int num_rectangles)
{
_rectangle_sort (rectangles, num_rectangles);
rectangles[num_rectangles] = NULL;
sweep_line->rectangles = rectangles;
sweep_line->head.x = INT32_MIN;
sweep_line->head.right = NULL;
sweep_line->head.dir = 0;
sweep_line->head.next = &sweep_line->tail;
sweep_line->tail.x = INT32_MAX;
sweep_line->tail.right = NULL;
sweep_line->tail.dir = 0;
sweep_line->tail.prev = &sweep_line->head;
sweep_line->insert_left = &sweep_line->tail;
sweep_line->insert_right = &sweep_line->tail;
sweep_line->current_y = INT32_MIN;
sweep_line->last_y = INT32_MIN;
pqueue_init (&sweep_line->pq);
}
static void
sweep_line_fini (sweep_line_t *sweep_line)
{
pqueue_fini (&sweep_line->pq);
}
static void
end_box (sweep_line_t *sweep_line, edge_t *left, int32_t bot, cairo_boxes_t *out)
{
if (likely (left->top < bot)) {
cairo_status_t status;
cairo_box_t box;
box.p1.x = left->x;
box.p1.y = left->top;
box.p2.x = left->right->x;
box.p2.y = bot;
status = _cairo_boxes_add (out, CAIRO_ANTIALIAS_DEFAULT, &box);
if (unlikely (status))
longjmp (sweep_line->unwind, status);
}
left->right = NULL;
}
/* Start a new trapezoid at the given top y coordinate, whose edges
* are `edge' and `edge->next'. If `edge' already has a trapezoid,
* then either add it to the traps in `traps', if the trapezoid's
* right edge differs from `edge->next', or do nothing if the new
* trapezoid would be a continuation of the existing one. */
static inline void
start_or_continue_box (sweep_line_t *sweep_line,
edge_t *left,
edge_t *right,
int top,
cairo_boxes_t *out)
{
if (left->right == right)
return;
if (left->right != NULL) {
if (right != NULL && left->right->x == right->x) {
/* continuation on right, so just swap edges */
left->right = right;
return;
}
end_box (sweep_line, left, top, out);
}
if (right != NULL && left->x != right->x) {
left->top = top;
left->right = right;
}
}
static inline int is_zero(const int *winding)
{
return winding[0] == 0 || winding[1] == 0;
}
static inline void
active_edges (sweep_line_t *sweep, cairo_boxes_t *out)
{
int top = sweep->current_y;
int winding[2] = { 0 };
edge_t *pos;
if (sweep->last_y == sweep->current_y)
return;
pos = sweep->head.next;
if (pos == &sweep->tail)
return;
do {
edge_t *left, *right;
left = pos;
do {
winding[left->a_or_b] += left->dir;
if (!is_zero (winding))
break;
if (left->next == &sweep->tail)
goto out;
if (unlikely (left->right != NULL))
end_box (sweep, left, top, out);
left = left->next;
} while (1);
right = left->next;
do {
if (unlikely (right->right != NULL))
end_box (sweep, right, top, out);
winding[right->a_or_b] += right->dir;
if (is_zero (winding)) {
/* skip co-linear edges */
if (likely (right->x != right->next->x))
break;
}
right = right->next;
} while (TRUE);
start_or_continue_box (sweep, left, right, top, out);
pos = right->next;
} while (pos != &sweep->tail);
out:
sweep->last_y = sweep->current_y;
}
static inline void
sweep_line_delete_edge (sweep_line_t *sweep_line, edge_t *edge, cairo_boxes_t *out)
{
if (edge->right != NULL) {
edge_t *next = edge->next;
if (next->x == edge->x) {
next->top = edge->top;
next->right = edge->right;
} else {
end_box (sweep_line, edge, sweep_line->current_y, out);
}
}
if (sweep_line->insert_left == edge)
sweep_line->insert_left = edge->next;
if (sweep_line->insert_right == edge)
sweep_line->insert_right = edge->next;
edge->prev->next = edge->next;
edge->next->prev = edge->prev;
}
static inline void
sweep_line_delete (sweep_line_t *sweep,
rectangle_t *rectangle,
cairo_boxes_t *out)
{
sweep_line_delete_edge (sweep, &rectangle->left, out);
sweep_line_delete_edge (sweep, &rectangle->right, out);
pqueue_pop (&sweep->pq);
}
static inline void
insert_edge (edge_t *edge, edge_t *pos)
{
if (pos->x != edge->x) {
if (pos->x > edge->x) {
do {
UNROLL3({
if (pos->prev->x <= edge->x)
break;
pos = pos->prev;
})
} while (TRUE);
} else {
do {
UNROLL3({
pos = pos->next;
if (pos->x >= edge->x)
break;
})
} while (TRUE);
}
}
pos->prev->next = edge;
edge->prev = pos->prev;
edge->next = pos;
pos->prev = edge;
}
static inline void
sweep_line_insert (sweep_line_t *sweep, rectangle_t *rectangle)
{
edge_t *pos;
/* right edge */
pos = sweep->insert_right;
insert_edge (&rectangle->right, pos);
sweep->insert_right = &rectangle->right;
/* left edge */
pos = sweep->insert_left;
if (pos->x > sweep->insert_right->x)
pos = sweep->insert_right->prev;
insert_edge (&rectangle->left, pos);
sweep->insert_left = &rectangle->left;
pqueue_push (sweep, rectangle);
}
static cairo_status_t
intersect (rectangle_t **rectangles, int num_rectangles, cairo_boxes_t *out)
{
sweep_line_t sweep_line;
rectangle_t *rectangle;
cairo_status_t status;
sweep_line_init (&sweep_line, rectangles, num_rectangles);
if ((status = setjmp (sweep_line.unwind)))
goto unwind;
rectangle = rectangle_pop_start (&sweep_line);
do {
if (rectangle->top != sweep_line.current_y) {
rectangle_t *stop;
stop = rectangle_peek_stop (&sweep_line);
while (stop != NULL && stop->bottom < rectangle->top) {
if (stop->bottom != sweep_line.current_y) {
active_edges (&sweep_line, out);
sweep_line.current_y = stop->bottom;
}
sweep_line_delete (&sweep_line, stop, out);
stop = rectangle_peek_stop (&sweep_line);
}
active_edges (&sweep_line, out);
sweep_line.current_y = rectangle->top;
}
sweep_line_insert (&sweep_line, rectangle);
} while ((rectangle = rectangle_pop_start (&sweep_line)) != NULL);
while ((rectangle = rectangle_peek_stop (&sweep_line)) != NULL) {
if (rectangle->bottom != sweep_line.current_y) {
active_edges (&sweep_line, out);
sweep_line.current_y = rectangle->bottom;
}
sweep_line_delete (&sweep_line, rectangle, out);
}
unwind:
sweep_line_fini (&sweep_line);
return status;
}
static cairo_status_t
_cairo_boxes_intersect_with_box (const cairo_boxes_t *boxes,
const cairo_box_t *box,
cairo_boxes_t *out)
{
cairo_status_t status;
int i, j;
if (out == boxes) { /* inplace update */
struct _cairo_boxes_chunk *chunk;
out->num_boxes = 0;
for (chunk = &out->chunks; chunk != NULL; chunk = chunk->next) {
for (i = j = 0; i < chunk->count; i++) {
cairo_box_t *b = &chunk->base[i];
b->p1.x = MAX (b->p1.x, box->p1.x);
b->p1.y = MAX (b->p1.y, box->p1.y);
b->p2.x = MIN (b->p2.x, box->p2.x);
b->p2.y = MIN (b->p2.y, box->p2.y);
if (b->p1.x < b->p2.x && b->p1.y < b->p2.y) {
if (i != j)
chunk->base[j] = *b;
j++;
}
}
/* XXX unlink empty chains? */
chunk->count = j;
out->num_boxes += j;
}
} else {
const struct _cairo_boxes_chunk *chunk;
_cairo_boxes_clear (out);
_cairo_boxes_limit (out, box, 1);
for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
for (i = 0; i < chunk->count; i++) {
status = _cairo_boxes_add (out,
CAIRO_ANTIALIAS_DEFAULT,
&chunk->base[i]);
if (unlikely (status))
return status;
}
}
}
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_boxes_intersect (const cairo_boxes_t *a,
const cairo_boxes_t *b,
cairo_boxes_t *out)
{
rectangle_t stack_rectangles[CAIRO_STACK_ARRAY_LENGTH (rectangle_t)];
rectangle_t *rectangles;
rectangle_t *stack_rectangles_ptrs[ARRAY_LENGTH (stack_rectangles) + 1];
rectangle_t **rectangles_ptrs;
const struct _cairo_boxes_chunk *chunk;
cairo_status_t status;
int i, j, count;
if (unlikely (a->num_boxes == 0 || b->num_boxes == 0)) {
_cairo_boxes_clear (out);
return CAIRO_STATUS_SUCCESS;
}
if (a->num_boxes == 1) {
cairo_box_t box = a->chunks.base[0];
return _cairo_boxes_intersect_with_box (b, &box, out);
}
if (b->num_boxes == 1) {
cairo_box_t box = b->chunks.base[0];
return _cairo_boxes_intersect_with_box (a, &box, out);
}
rectangles = stack_rectangles;
rectangles_ptrs = stack_rectangles_ptrs;
count = a->num_boxes + b->num_boxes;
if (count > ARRAY_LENGTH (stack_rectangles)) {
rectangles = _cairo_malloc_ab_plus_c (count,
sizeof (rectangle_t) +
sizeof (rectangle_t *),
sizeof (rectangle_t *));
if (unlikely (rectangles == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
rectangles_ptrs = (rectangle_t **) (rectangles + count);
}
j = 0;
for (chunk = &a->chunks; chunk != NULL; chunk = chunk->next) {
const cairo_box_t *box = chunk->base;
for (i = 0; i < chunk->count; i++) {
if (box[i].p1.x < box[i].p2.x) {
rectangles[j].left.x = box[i].p1.x;
rectangles[j].left.dir = 1;
rectangles[j].right.x = box[i].p2.x;
rectangles[j].right.dir = -1;
} else {
rectangles[j].right.x = box[i].p1.x;
rectangles[j].right.dir = 1;
rectangles[j].left.x = box[i].p2.x;
rectangles[j].left.dir = -1;
}
rectangles[j].left.a_or_b = 0;
rectangles[j].left.right = NULL;
rectangles[j].right.a_or_b = 0;
rectangles[j].right.right = NULL;
rectangles[j].top = box[i].p1.y;
rectangles[j].bottom = box[i].p2.y;
rectangles_ptrs[j] = &rectangles[j];
j++;
}
}
for (chunk = &b->chunks; chunk != NULL; chunk = chunk->next) {
const cairo_box_t *box = chunk->base;
for (i = 0; i < chunk->count; i++) {
if (box[i].p1.x < box[i].p2.x) {
rectangles[j].left.x = box[i].p1.x;
rectangles[j].left.dir = 1;
rectangles[j].right.x = box[i].p2.x;
rectangles[j].right.dir = -1;
} else {
rectangles[j].right.x = box[i].p1.x;
rectangles[j].right.dir = 1;
rectangles[j].left.x = box[i].p2.x;
rectangles[j].left.dir = -1;
}
rectangles[j].left.a_or_b = 1;
rectangles[j].left.right = NULL;
rectangles[j].right.a_or_b = 1;
rectangles[j].right.right = NULL;
rectangles[j].top = box[i].p1.y;
rectangles[j].bottom = box[i].p2.y;
rectangles_ptrs[j] = &rectangles[j];
j++;
}
}
assert (j == count);
_cairo_boxes_clear (out);
status = intersect (rectangles_ptrs, j, out);
if (rectangles != stack_rectangles)
free (rectangles);
return status;
}

Просмотреть файл

@ -37,13 +37,19 @@
#include "cairo-types-private.h"
#include "cairo-compiler-private.h"
#include <stdio.h>
#include <stdlib.h>
struct _cairo_boxes_t {
cairo_status_t status;
cairo_box_t limit;
const cairo_box_t *limits;
int num_limits;
int num_boxes;
unsigned int is_pixel_aligned : 1;
unsigned int is_pixel_aligned;
struct _cairo_boxes_chunk {
struct _cairo_boxes_chunk *next;
@ -57,11 +63,19 @@ struct _cairo_boxes_t {
cairo_private void
_cairo_boxes_init (cairo_boxes_t *boxes);
cairo_private void
_cairo_boxes_init_with_clip (cairo_boxes_t *boxes,
cairo_clip_t *clip);
cairo_private void
_cairo_boxes_init_for_array (cairo_boxes_t *boxes,
cairo_box_t *array,
int num_boxes);
cairo_private void
_cairo_boxes_init_from_rectangle (cairo_boxes_t *boxes,
int x, int y, int w, int h);
cairo_private void
_cairo_boxes_limit (cairo_boxes_t *boxes,
const cairo_box_t *limits,
@ -69,16 +83,40 @@ _cairo_boxes_limit (cairo_boxes_t *boxes,
cairo_private cairo_status_t
_cairo_boxes_add (cairo_boxes_t *boxes,
cairo_antialias_t antialias,
const cairo_box_t *box);
cairo_private void
_cairo_boxes_extents (const cairo_boxes_t *boxes,
cairo_rectangle_int_t *extents);
cairo_box_t *box);
cairo_private cairo_box_t *
_cairo_boxes_to_array (const cairo_boxes_t *boxes,
int *num_boxes);
cairo_private cairo_status_t
_cairo_boxes_intersect (const cairo_boxes_t *a,
const cairo_boxes_t *b,
cairo_boxes_t *out);
cairo_private void
_cairo_boxes_clear (cairo_boxes_t *boxes);
cairo_private_no_warn cairo_bool_t
_cairo_boxes_for_each_box (cairo_boxes_t *boxes,
cairo_bool_t (*func) (cairo_box_t *box, void *data),
void *data);
cairo_private cairo_status_t
_cairo_rasterise_polygon_to_boxes (cairo_polygon_t *polygon,
cairo_fill_rule_t fill_rule,
cairo_boxes_t *boxes);
cairo_private void
_cairo_boxes_fini (cairo_boxes_t *boxes);
cairo_private void
_cairo_debug_print_boxes (FILE *stream,
const cairo_boxes_t *boxes);
#endif /* CAIRO_BOXES_H */

Просмотреть файл

@ -33,6 +33,7 @@
#include "cairoint.h"
#include "cairo-box-inline.h"
#include "cairo-boxes-private.h"
#include "cairo-error-private.h"
@ -52,6 +53,25 @@ _cairo_boxes_init (cairo_boxes_t *boxes)
boxes->is_pixel_aligned = TRUE;
}
void
_cairo_boxes_init_from_rectangle (cairo_boxes_t *boxes,
int x, int y, int w, int h)
{
_cairo_boxes_init (boxes);
_cairo_box_from_integers (&boxes->chunks.base[0], x, y, w, h);
boxes->num_boxes = 1;
}
void
_cairo_boxes_init_with_clip (cairo_boxes_t *boxes,
cairo_clip_t *clip)
{
_cairo_boxes_init (boxes);
if (clip)
_cairo_boxes_limit (boxes, clip->boxes, clip->num_boxes);
}
void
_cairo_boxes_init_for_array (cairo_boxes_t *boxes,
cairo_box_t *array,
@ -82,6 +102,17 @@ _cairo_boxes_init_for_array (cairo_boxes_t *boxes,
boxes->is_pixel_aligned = n == num_boxes;
}
/** _cairo_boxes_limit:
*
* Computes the minimum bounding box of the given list of boxes and assign
* it to the given boxes set. It also assigns that list as the list of
* limiting boxes in the box set.
*
* @param boxes the box set to be filled (return buffer)
* @param limits array of the limiting boxes to compute the bounding
* box from
* @param num_limits length of the limits array
*/
void
_cairo_boxes_limit (cairo_boxes_t *boxes,
const cairo_box_t *limits,
@ -145,19 +176,25 @@ _cairo_boxes_add_internal (cairo_boxes_t *boxes,
chunk->base[chunk->count++] = *box;
boxes->num_boxes++;
if (boxes->is_pixel_aligned) {
boxes->is_pixel_aligned =
_cairo_fixed_is_integer (box->p1.x) &&
_cairo_fixed_is_integer (box->p1.y) &&
_cairo_fixed_is_integer (box->p2.x) &&
_cairo_fixed_is_integer (box->p2.y);
}
if (boxes->is_pixel_aligned)
boxes->is_pixel_aligned = _cairo_box_is_pixel_aligned (box);
}
cairo_status_t
_cairo_boxes_add (cairo_boxes_t *boxes,
cairo_antialias_t antialias,
const cairo_box_t *box)
{
cairo_box_t b;
if (antialias == CAIRO_ANTIALIAS_NONE) {
b.p1.x = _cairo_fixed_round_down (box->p1.x);
b.p1.y = _cairo_fixed_round_down (box->p1.y);
b.p2.x = _cairo_fixed_round_down (box->p2.x);
b.p2.y = _cairo_fixed_round_down (box->p2.y);
box = &b;
}
if (box->p1.y == box->p2.y)
return CAIRO_STATUS_SUCCESS;
@ -239,35 +276,44 @@ _cairo_boxes_add (cairo_boxes_t *boxes,
return boxes->status;
}
/** _cairo_boxes_extents:
*
* Computes the minimum bounding box of the given box set and stores
* it in the given box.
*
* @param boxes The box set whose minimum bounding is computed.
* @param box Return buffer for the computed result.
*/
void
_cairo_boxes_extents (const cairo_boxes_t *boxes,
cairo_rectangle_int_t *extents)
cairo_box_t *box)
{
const struct _cairo_boxes_chunk *chunk;
cairo_box_t box;
cairo_box_t b;
int i;
box.p1.y = box.p1.x = INT_MAX;
box.p2.y = box.p2.x = INT_MIN;
for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
const cairo_box_t *b = chunk->base;
for (i = 0; i < chunk->count; i++) {
if (b[i].p1.x < box.p1.x)
box.p1.x = b[i].p1.x;
if (b[i].p1.y < box.p1.y)
box.p1.y = b[i].p1.y;
if (b[i].p2.x > box.p2.x)
box.p2.x = b[i].p2.x;
if (b[i].p2.y > box.p2.y)
box.p2.y = b[i].p2.y;
}
if (boxes->num_boxes == 0) {
box->p1.x = box->p1.y = box->p2.x = box->p2.y = 0;
return;
}
_cairo_box_round_to_rectangle (&box, extents);
b = boxes->chunks.base[0];
for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
for (i = 0; i < chunk->count; i++) {
if (chunk->base[i].p1.x < b.p1.x)
b.p1.x = chunk->base[i].p1.x;
if (chunk->base[i].p1.y < b.p1.y)
b.p1.y = chunk->base[i].p1.y;
if (chunk->base[i].p2.x > b.p2.x)
b.p2.x = chunk->base[i].p2.x;
if (chunk->base[i].p2.y > b.p2.y)
b.p2.y = chunk->base[i].p2.y;
}
}
*box = b;
}
void
@ -283,11 +329,48 @@ _cairo_boxes_clear (cairo_boxes_t *boxes)
boxes->tail = &boxes->chunks;
boxes->chunks.next = 0;
boxes->chunks.count = 0;
boxes->chunks.base = boxes->boxes_embedded;
boxes->chunks.size = ARRAY_LENGTH (boxes->boxes_embedded);
boxes->num_boxes = 0;
boxes->is_pixel_aligned = TRUE;
}
/** _cairo_boxes_to_array:
*
* Linearize a box set of possibly multiple chunks into one big chunk
* and returns an array of boxes
*
* @param boxes The box set to be converted.
* @param num_boxes Return buffer for the number of boxes (array count).
* @return Pointer to the newly allocated array of boxes
* (the number o elements is given in num_boxes).
*/
cairo_box_t *
_cairo_boxes_to_array (const cairo_boxes_t *boxes,
int *num_boxes)
{
const struct _cairo_boxes_chunk *chunk;
cairo_box_t *box;
int i, j;
*num_boxes = boxes->num_boxes;
box = _cairo_malloc_ab (boxes->num_boxes, sizeof (cairo_box_t));
if (box == NULL) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
j = 0;
for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
for (i = 0; i < chunk->count; i++)
box[j++] = chunk->base[i];
}
return box;
}
void
_cairo_boxes_fini (cairo_boxes_t *boxes)
{
@ -298,3 +381,106 @@ _cairo_boxes_fini (cairo_boxes_t *boxes)
free (chunk);
}
}
cairo_bool_t
_cairo_boxes_for_each_box (cairo_boxes_t *boxes,
cairo_bool_t (*func) (cairo_box_t *box, void *data),
void *data)
{
struct _cairo_boxes_chunk *chunk;
int i;
for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
for (i = 0; i < chunk->count; i++)
if (! func (&chunk->base[i], data))
return FALSE;
}
return TRUE;
}
struct cairo_box_renderer {
cairo_span_renderer_t base;
cairo_boxes_t *boxes;
};
static cairo_status_t
span_to_boxes (void *abstract_renderer, int y, int h,
const cairo_half_open_span_t *spans, unsigned num_spans)
{
struct cairo_box_renderer *r = abstract_renderer;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_box_t box;
if (num_spans == 0)
return CAIRO_STATUS_SUCCESS;
box.p1.y = _cairo_fixed_from_int (y);
box.p2.y = _cairo_fixed_from_int (y + h);
do {
if (spans[0].coverage) {
box.p1.x = _cairo_fixed_from_int(spans[0].x);
box.p2.x = _cairo_fixed_from_int(spans[1].x);
status = _cairo_boxes_add (r->boxes, CAIRO_ANTIALIAS_DEFAULT, &box);
}
spans++;
} while (--num_spans > 1 && status == CAIRO_STATUS_SUCCESS);
return status;
}
cairo_status_t
_cairo_rasterise_polygon_to_boxes (cairo_polygon_t *polygon,
cairo_fill_rule_t fill_rule,
cairo_boxes_t *boxes)
{
struct cairo_box_renderer renderer;
cairo_scan_converter_t *converter;
cairo_int_status_t status;
cairo_rectangle_int_t r;
TRACE ((stderr, "%s: fill_rule=%d\n", __FUNCTION__, fill_rule));
_cairo_box_round_to_rectangle (&polygon->extents, &r);
converter = _cairo_mono_scan_converter_create (r.x, r.y,
r.x + r.width,
r.y + r.height,
fill_rule);
status = _cairo_mono_scan_converter_add_polygon (converter, polygon);
if (unlikely (status))
goto cleanup_converter;
renderer.boxes = boxes;
renderer.base.render_rows = span_to_boxes;
status = converter->generate (converter, &renderer.base);
cleanup_converter:
converter->destroy (converter);
return status;
}
void
_cairo_debug_print_boxes (FILE *stream, const cairo_boxes_t *boxes)
{
const struct _cairo_boxes_chunk *chunk;
cairo_box_t extents;
int i;
_cairo_boxes_extents (boxes, &extents);
fprintf (stream, "boxes x %d: (%f, %f) x (%f, %f)\n",
boxes->num_boxes,
_cairo_fixed_to_double (extents.p1.x),
_cairo_fixed_to_double (extents.p1.y),
_cairo_fixed_to_double (extents.p2.x),
_cairo_fixed_to_double (extents.p2.y));
for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
for (i = 0; i < chunk->count; i++) {
fprintf (stderr, " box[%d]: (%f, %f), (%f, %f)\n", i,
_cairo_fixed_to_double (chunk->base[i].p1.x),
_cairo_fixed_to_double (chunk->base[i].p1.y),
_cairo_fixed_to_double (chunk->base[i].p2.x),
_cairo_fixed_to_double (chunk->base[i].p2.y));
}
}
}

Просмотреть файл

@ -43,7 +43,7 @@
#include "cairo-types-private.h"
/**
* cairo_cache_entry_t:
* _cairo_cache_entry:
*
* A #cairo_cache_entry_t contains both a key and a value for
* #cairo_cache_t. User-derived types for #cairo_cache_entry_t must
@ -84,7 +84,7 @@
* not be initialized if so desired.
**/
typedef struct _cairo_cache_entry {
uintptr_t hash;
unsigned long hash;
unsigned long size;
} cairo_cache_entry_t;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,609 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* Copyright © 2005 Red Hat, Inc.
* Copyright © 2009 Chris Wilson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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>
* Kristian Høgsberg <krh@redhat.com>
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-box-inline.h"
#include "cairo-clip-inline.h"
#include "cairo-clip-private.h"
#include "cairo-error-private.h"
#include "cairo-freed-pool-private.h"
#include "cairo-gstate-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-pattern-private.h"
#include "cairo-composite-rectangles-private.h"
#include "cairo-region-private.h"
static inline int
pot (int v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
static cairo_bool_t
_cairo_clip_contains_rectangle_box (const cairo_clip_t *clip,
const cairo_rectangle_int_t *rect,
const cairo_box_t *box)
{
int i;
/* clip == NULL means no clip, so the clip contains everything */
if (clip == NULL)
return TRUE;
if (_cairo_clip_is_all_clipped (clip))
return FALSE;
/* If we have a non-trivial path, just say no */
if (clip->path)
return FALSE;
if (! _cairo_rectangle_contains_rectangle (&clip->extents, rect))
return FALSE;
if (clip->num_boxes == 0)
return TRUE;
/* Check for a clip-box that wholly contains the rectangle */
for (i = 0; i < clip->num_boxes; i++) {
if (box->p1.x >= clip->boxes[i].p1.x &&
box->p1.y >= clip->boxes[i].p1.y &&
box->p2.x <= clip->boxes[i].p2.x &&
box->p2.y <= clip->boxes[i].p2.y)
{
return TRUE;
}
}
return FALSE;
}
cairo_bool_t
_cairo_clip_contains_box (const cairo_clip_t *clip,
const cairo_box_t *box)
{
cairo_rectangle_int_t rect;
_cairo_box_round_to_rectangle (box, &rect);
return _cairo_clip_contains_rectangle_box(clip, &rect, box);
}
cairo_bool_t
_cairo_clip_contains_rectangle (const cairo_clip_t *clip,
const cairo_rectangle_int_t *rect)
{
cairo_box_t box;
_cairo_box_from_rectangle_int (&box, rect);
return _cairo_clip_contains_rectangle_box (clip, rect, &box);
}
cairo_clip_t *
_cairo_clip_intersect_rectilinear_path (cairo_clip_t *clip,
const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
cairo_antialias_t antialias)
{
cairo_status_t status;
cairo_boxes_t boxes;
_cairo_boxes_init (&boxes);
status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
fill_rule,
antialias,
&boxes);
if (likely (status == CAIRO_STATUS_SUCCESS && boxes.num_boxes))
clip = _cairo_clip_intersect_boxes (clip, &boxes);
else
clip = _cairo_clip_set_all_clipped (clip);
_cairo_boxes_fini (&boxes);
return clip;
}
static cairo_clip_t *
_cairo_clip_intersect_rectangle_box (cairo_clip_t *clip,
const cairo_rectangle_int_t *r,
const cairo_box_t *box)
{
cairo_box_t extents_box;
cairo_bool_t changed = FALSE;
int i, j;
if (clip == NULL) {
clip = _cairo_clip_create ();
if (clip == NULL)
return _cairo_clip_set_all_clipped (clip);
}
if (clip->num_boxes == 0) {
clip->boxes = &clip->embedded_box;
clip->boxes[0] = *box;
clip->num_boxes = 1;
if (clip->path == NULL) {
clip->extents = *r;
} else {
if (! _cairo_rectangle_intersect (&clip->extents, r))
return _cairo_clip_set_all_clipped (clip);
}
if (clip->path == NULL)
clip->is_region = _cairo_box_is_pixel_aligned (box);
return clip;
}
/* Does the new box wholly subsume the clip? Perform a cheap check
* for the common condition of a single clip rectangle.
*/
if (clip->num_boxes == 1 &&
clip->boxes[0].p1.x >= box->p1.x &&
clip->boxes[0].p1.y >= box->p1.y &&
clip->boxes[0].p2.x <= box->p2.x &&
clip->boxes[0].p2.y <= box->p2.y)
{
return clip;
}
for (i = j = 0; i < clip->num_boxes; i++) {
cairo_box_t *b = &clip->boxes[j];
if (j != i)
*b = clip->boxes[i];
if (box->p1.x > b->p1.x)
b->p1.x = box->p1.x, changed = TRUE;
if (box->p2.x < b->p2.x)
b->p2.x = box->p2.x, changed = TRUE;
if (box->p1.y > b->p1.y)
b->p1.y = box->p1.y, changed = TRUE;
if (box->p2.y < b->p2.y)
b->p2.y = box->p2.y, changed = TRUE;
j += b->p2.x > b->p1.x && b->p2.y > b->p1.y;
}
clip->num_boxes = j;
if (clip->num_boxes == 0)
return _cairo_clip_set_all_clipped (clip);
if (! changed)
return clip;
extents_box = clip->boxes[0];
for (i = 1; i < clip->num_boxes; i++) {
if (clip->boxes[i].p1.x < extents_box.p1.x)
extents_box.p1.x = clip->boxes[i].p1.x;
if (clip->boxes[i].p1.y < extents_box.p1.y)
extents_box.p1.y = clip->boxes[i].p1.y;
if (clip->boxes[i].p2.x > extents_box.p2.x)
extents_box.p2.x = clip->boxes[i].p2.x;
if (clip->boxes[i].p2.y > extents_box.p2.y)
extents_box.p2.y = clip->boxes[i].p2.y;
}
if (clip->path == NULL) {
_cairo_box_round_to_rectangle (&extents_box, &clip->extents);
} else {
cairo_rectangle_int_t extents_rect;
_cairo_box_round_to_rectangle (&extents_box, &extents_rect);
if (! _cairo_rectangle_intersect (&clip->extents, &extents_rect))
return _cairo_clip_set_all_clipped (clip);
}
if (clip->region) {
cairo_region_destroy (clip->region);
clip->region = NULL;
}
clip->is_region = FALSE;
return clip;
}
cairo_clip_t *
_cairo_clip_intersect_box (cairo_clip_t *clip,
const cairo_box_t *box)
{
cairo_rectangle_int_t r;
if (_cairo_clip_is_all_clipped (clip))
return clip;
_cairo_box_round_to_rectangle (box, &r);
if (r.width == 0 || r.height == 0)
return _cairo_clip_set_all_clipped (clip);
return _cairo_clip_intersect_rectangle_box (clip, &r, box);
}
/* Copy a box set to a clip
*
* @param boxes The box set to copy from.
* @param clip The clip to copy to (return buffer).
* @returns Zero if the allocation failed (the clip will be set to
* all-clipped), otherwise non-zero.
*/
static cairo_bool_t
_cairo_boxes_copy_to_clip (const cairo_boxes_t *boxes, cairo_clip_t *clip)
{
/* XXX cow-boxes? */
if (boxes->num_boxes == 1) {
clip->boxes = &clip->embedded_box;
clip->boxes[0] = boxes->chunks.base[0];
clip->num_boxes = 1;
return TRUE;
}
clip->boxes = _cairo_boxes_to_array (boxes, &clip->num_boxes);
if (unlikely (clip->boxes == NULL))
{
_cairo_clip_set_all_clipped (clip);
return FALSE;
}
return TRUE;
}
cairo_clip_t *
_cairo_clip_intersect_boxes (cairo_clip_t *clip,
const cairo_boxes_t *boxes)
{
cairo_boxes_t clip_boxes;
cairo_box_t limits;
cairo_rectangle_int_t extents;
if (_cairo_clip_is_all_clipped (clip))
return clip;
if (boxes->num_boxes == 0)
return _cairo_clip_set_all_clipped (clip);
if (boxes->num_boxes == 1)
return _cairo_clip_intersect_box (clip, boxes->chunks.base);
if (clip == NULL)
clip = _cairo_clip_create ();
if (clip->num_boxes) {
_cairo_boxes_init_for_array (&clip_boxes, clip->boxes, clip->num_boxes);
if (unlikely (_cairo_boxes_intersect (&clip_boxes, boxes, &clip_boxes))) {
clip = _cairo_clip_set_all_clipped (clip);
goto out;
}
if (clip->boxes != &clip->embedded_box)
free (clip->boxes);
clip->boxes = NULL;
boxes = &clip_boxes;
}
if (boxes->num_boxes == 0) {
clip = _cairo_clip_set_all_clipped (clip);
goto out;
}
_cairo_boxes_copy_to_clip (boxes, clip);
_cairo_boxes_extents (boxes, &limits);
_cairo_box_round_to_rectangle (&limits, &extents);
if (clip->path == NULL) {
clip->extents = extents;
} else if (! _cairo_rectangle_intersect (&clip->extents, &extents)) {
clip = _cairo_clip_set_all_clipped (clip);
goto out;
}
if (clip->region) {
cairo_region_destroy (clip->region);
clip->region = NULL;
}
clip->is_region = FALSE;
out:
if (boxes == &clip_boxes)
_cairo_boxes_fini (&clip_boxes);
return clip;
}
cairo_clip_t *
_cairo_clip_intersect_rectangle (cairo_clip_t *clip,
const cairo_rectangle_int_t *r)
{
cairo_box_t box;
if (_cairo_clip_is_all_clipped (clip))
return clip;
if (r->width == 0 || r->height == 0)
return _cairo_clip_set_all_clipped (clip);
_cairo_box_from_rectangle_int (&box, r);
return _cairo_clip_intersect_rectangle_box (clip, r, &box);
}
struct reduce {
cairo_clip_t *clip;
cairo_box_t limit;
cairo_box_t extents;
cairo_bool_t inside;
cairo_point_t current_point;
cairo_point_t last_move_to;
};
static void
_add_clipped_edge (struct reduce *r,
const cairo_point_t *p1,
const cairo_point_t *p2,
int y1, int y2)
{
cairo_fixed_t x;
x = _cairo_edge_compute_intersection_x_for_y (p1, p2, y1);
if (x < r->extents.p1.x)
r->extents.p1.x = x;
x = _cairo_edge_compute_intersection_x_for_y (p1, p2, y2);
if (x > r->extents.p2.x)
r->extents.p2.x = x;
if (y1 < r->extents.p1.y)
r->extents.p1.y = y1;
if (y2 > r->extents.p2.y)
r->extents.p2.y = y2;
r->inside = TRUE;
}
static void
_add_edge (struct reduce *r,
const cairo_point_t *p1,
const cairo_point_t *p2)
{
int top, bottom;
int top_y, bot_y;
int n;
if (p1->y < p2->y) {
top = p1->y;
bottom = p2->y;
} else {
top = p2->y;
bottom = p1->y;
}
if (bottom < r->limit.p1.y || top > r->limit.p2.y)
return;
if (p1->x > p2->x) {
const cairo_point_t *t = p1;
p1 = p2;
p2 = t;
}
if (p2->x <= r->limit.p1.x || p1->x >= r->limit.p2.x)
return;
for (n = 0; n < r->clip->num_boxes; n++) {
const cairo_box_t *limits = &r->clip->boxes[n];
if (bottom < limits->p1.y || top > limits->p2.y)
continue;
if (p2->x <= limits->p1.x || p1->x >= limits->p2.x)
continue;
if (p1->x >= limits->p1.x && p2->x <= limits->p1.x) {
top_y = top;
bot_y = bottom;
} else {
int p1_y, p2_y;
p1_y = _cairo_edge_compute_intersection_y_for_x (p1, p2,
limits->p1.x);
p2_y = _cairo_edge_compute_intersection_y_for_x (p1, p2,
limits->p2.x);
if (p1_y < p2_y) {
top_y = p1_y;
bot_y = p2_y;
} else {
top_y = p2_y;
bot_y = p1_y;
}
if (top_y < top)
top_y = top;
if (bot_y > bottom)
bot_y = bottom;
}
if (top_y < limits->p1.y)
top_y = limits->p1.y;
if (bot_y > limits->p2.y)
bot_y = limits->p2.y;
if (bot_y > top_y)
_add_clipped_edge (r, p1, p2, top_y, bot_y);
}
}
static cairo_status_t
_reduce_line_to (void *closure,
const cairo_point_t *point)
{
struct reduce *r = closure;
_add_edge (r, &r->current_point, point);
r->current_point = *point;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_reduce_close (void *closure)
{
struct reduce *r = closure;
return _reduce_line_to (r, &r->last_move_to);
}
static cairo_status_t
_reduce_move_to (void *closure,
const cairo_point_t *point)
{
struct reduce *r = closure;
cairo_status_t status;
/* close current subpath */
status = _reduce_close (closure);
/* make sure that the closure represents a degenerate path */
r->current_point = *point;
r->last_move_to = *point;
return status;
}
static cairo_clip_t *
_cairo_clip_reduce_to_boxes (cairo_clip_t *clip)
{
struct reduce r;
cairo_clip_path_t *clip_path;
cairo_status_t status;
return clip;
if (clip->path == NULL)
return clip;
r.clip = clip;
r.extents.p1.x = r.extents.p1.y = INT_MAX;
r.extents.p2.x = r.extents.p2.y = INT_MIN;
r.inside = FALSE;
r.limit.p1.x = _cairo_fixed_from_int (clip->extents.x);
r.limit.p1.y = _cairo_fixed_from_int (clip->extents.y);
r.limit.p2.x = _cairo_fixed_from_int (clip->extents.x + clip->extents.width);
r.limit.p2.y = _cairo_fixed_from_int (clip->extents.y + clip->extents.height);
clip_path = clip->path;
do {
r.current_point.x = 0;
r.current_point.y = 0;
r.last_move_to = r.current_point;
status = _cairo_path_fixed_interpret_flat (&clip_path->path,
_reduce_move_to,
_reduce_line_to,
_reduce_close,
&r,
clip_path->tolerance);
assert (status == CAIRO_STATUS_SUCCESS);
_reduce_close (&r);
} while ((clip_path = clip_path->prev));
if (! r.inside) {
_cairo_clip_path_destroy (clip->path);
clip->path = NULL;
}
return _cairo_clip_intersect_box (clip, &r.extents);
}
cairo_clip_t *
_cairo_clip_reduce_to_rectangle (const cairo_clip_t *clip,
const cairo_rectangle_int_t *r)
{
cairo_clip_t *copy;
if (_cairo_clip_is_all_clipped (clip))
return (cairo_clip_t *) clip;
if (_cairo_clip_contains_rectangle (clip, r))
return _cairo_clip_intersect_rectangle (NULL, r);
copy = _cairo_clip_copy_intersect_rectangle (clip, r);
if (_cairo_clip_is_all_clipped (copy))
return copy;
return _cairo_clip_reduce_to_boxes (copy);
}
cairo_clip_t *
_cairo_clip_reduce_for_composite (const cairo_clip_t *clip,
cairo_composite_rectangles_t *extents)
{
const cairo_rectangle_int_t *r;
r = extents->is_bounded ? &extents->bounded : &extents->unbounded;
return _cairo_clip_reduce_to_rectangle (clip, r);
}
cairo_clip_t *
_cairo_clip_from_boxes (const cairo_boxes_t *boxes)
{
cairo_box_t extents;
cairo_clip_t *clip = _cairo_clip_create ();
if (clip == NULL)
return _cairo_clip_set_all_clipped (clip);
if (unlikely (! _cairo_boxes_copy_to_clip (boxes, clip)))
return clip;
_cairo_boxes_extents (boxes, &extents);
_cairo_box_round_to_rectangle (&extents, &clip->extents);
return clip;
}

Просмотреть файл

@ -0,0 +1,96 @@
/* cairo - a vector graphics library with display and print output
*
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Kristian Høgsberg <krh@redhat.com>
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#ifndef CAIRO_CLIP_INLINE_H
#define CAIRO_CLIP_INLINE_H
#include "cairo-clip-private.h"
static inline cairo_bool_t _cairo_clip_is_all_clipped(const cairo_clip_t *clip)
{
return clip == &__cairo_clip_all;
}
static inline cairo_clip_t *
_cairo_clip_set_all_clipped (cairo_clip_t *clip)
{
_cairo_clip_destroy (clip);
return (cairo_clip_t *) &__cairo_clip_all;
}
static inline cairo_clip_t *
_cairo_clip_copy_intersect_rectangle (const cairo_clip_t *clip,
const cairo_rectangle_int_t *r)
{
return _cairo_clip_intersect_rectangle (_cairo_clip_copy (clip), r);
}
static inline cairo_clip_t *
_cairo_clip_copy_intersect_clip (const cairo_clip_t *clip,
const cairo_clip_t *other)
{
return _cairo_clip_intersect_clip (_cairo_clip_copy (clip), other);
}
static inline void
_cairo_clip_steal_boxes (cairo_clip_t *clip, cairo_boxes_t *boxes)
{
cairo_box_t *array = clip->boxes;
if (array == &clip->embedded_box) {
assert (clip->num_boxes == 1);
boxes->boxes_embedded[0] = clip->embedded_box;
array = &boxes->boxes_embedded[0];
}
_cairo_boxes_init_for_array (boxes, array, clip->num_boxes);
clip->boxes = NULL;
clip->num_boxes = 0;
}
static inline void
_cairo_clip_unsteal_boxes (cairo_clip_t *clip, cairo_boxes_t *boxes)
{
if (boxes->chunks.base == &boxes->boxes_embedded[0]) {
assert(boxes->num_boxes == 1);
clip->embedded_box = *boxes->chunks.base;
clip->boxes = &clip->embedded_box;
} else {
clip->boxes = boxes->chunks.base;
}
clip->num_boxes = boxes->num_boxes;
}
#endif /* CAIRO_CLIP_INLINE_H */

Просмотреть файл

@ -0,0 +1,156 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2011 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-clip-inline.h"
#include "cairo-clip-private.h"
#include "cairo-error-private.h"
#include "cairo-freed-pool-private.h"
#include "cairo-gstate-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-pattern-private.h"
#include "cairo-composite-rectangles-private.h"
#include "cairo-region-private.h"
static cairo_bool_t
can_convert_to_polygon (const cairo_clip_t *clip)
{
cairo_clip_path_t *clip_path = clip->path;
cairo_antialias_t antialias = clip_path->antialias;
while ((clip_path = clip_path->prev) != NULL) {
if (clip_path->antialias != antialias)
return FALSE;
}
return TRUE;
}
cairo_int_status_t
_cairo_clip_get_polygon (const cairo_clip_t *clip,
cairo_polygon_t *polygon,
cairo_fill_rule_t *fill_rule,
cairo_antialias_t *antialias)
{
cairo_status_t status;
cairo_clip_path_t *clip_path;
if (_cairo_clip_is_all_clipped (clip)) {
_cairo_polygon_init (polygon, NULL, 0);
return CAIRO_INT_STATUS_SUCCESS;
}
/* If there is no clip, we need an infinite polygon */
assert (clip && (clip->path || clip->num_boxes));
if (clip->path == NULL) {
*fill_rule = CAIRO_FILL_RULE_WINDING;
*antialias = CAIRO_ANTIALIAS_DEFAULT;
return _cairo_polygon_init_box_array (polygon,
clip->boxes,
clip->num_boxes);
}
/* check that residual is all of the same type/tolerance */
if (! can_convert_to_polygon (clip))
return CAIRO_INT_STATUS_UNSUPPORTED;
if (clip->num_boxes < 2)
_cairo_polygon_init_with_clip (polygon, clip);
else
_cairo_polygon_init_with_clip (polygon, NULL);
clip_path = clip->path;
*fill_rule = clip_path->fill_rule;
*antialias = clip_path->antialias;
status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
clip_path->tolerance,
polygon);
if (unlikely (status))
goto err;
if (clip->num_boxes > 1) {
status = _cairo_polygon_intersect_with_boxes (polygon, fill_rule,
clip->boxes, clip->num_boxes);
if (unlikely (status))
goto err;
}
polygon->limits = NULL;
polygon->num_limits = 0;
while ((clip_path = clip_path->prev) != NULL) {
cairo_polygon_t next;
_cairo_polygon_init (&next, NULL, 0);
status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
clip_path->tolerance,
&next);
if (likely (status == CAIRO_STATUS_SUCCESS))
status = _cairo_polygon_intersect (polygon, *fill_rule,
&next, clip_path->fill_rule);
_cairo_polygon_fini (&next);
if (unlikely (status))
goto err;
*fill_rule = CAIRO_FILL_RULE_WINDING;
}
return CAIRO_STATUS_SUCCESS;
err:
_cairo_polygon_fini (polygon);
return status;
}
cairo_bool_t
_cairo_clip_is_polygon (const cairo_clip_t *clip)
{
if (_cairo_clip_is_all_clipped (clip))
return TRUE;
/* If there is no clip, we need an infinite polygon */
if (clip == NULL)
return FALSE;
if (clip->path == NULL)
return TRUE;
/* check that residual is all of the same type/tolerance */
return can_convert_to_polygon (clip);
}

Просмотреть файл

@ -31,24 +31,23 @@
*
* Contributor(s):
* Kristian Høgsberg <krh@redhat.com>
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#ifndef CAIRO_CLIP_PRIVATE_H
#define CAIRO_CLIP_PRIVATE_H
#include "cairo-types-private.h"
#include "cairo-boxes-private.h"
#include "cairo-error-private.h"
#include "cairo-compiler-private.h"
#include "cairo-error-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-reference-count-private.h"
extern const cairo_private cairo_rectangle_list_t _cairo_rectangles_nil;
enum {
CAIRO_CLIP_PATH_HAS_REGION = 0x1,
CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED = 0x2,
CAIRO_CLIP_PATH_IS_BOX = 0x4
};
struct _cairo_clip_path {
cairo_reference_count_t ref_count;
cairo_path_fixed_t path;
@ -56,96 +55,144 @@ struct _cairo_clip_path {
double tolerance;
cairo_antialias_t antialias;
cairo_clip_path_t *prev;
cairo_rectangle_int_t extents;
/* partial caches */
unsigned int flags;
cairo_region_t *region;
cairo_surface_t *surface;
};
struct _cairo_clip {
/* can be used as a cairo_hash_entry_t for live clips */
cairo_rectangle_int_t extents;
cairo_clip_path_t *path;
cairo_bool_t all_clipped;
cairo_box_t *boxes;
int num_boxes;
cairo_region_t *region;
cairo_bool_t is_region;
cairo_box_t embedded_box;
};
cairo_private void
_cairo_clip_init (cairo_clip_t *clip);
cairo_private cairo_clip_t *
_cairo_clip_create (void);
cairo_private_no_warn cairo_clip_t *
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other);
cairo_private cairo_status_t
_cairo_clip_init_copy_transformed (cairo_clip_t *clip,
cairo_clip_t *other,
const cairo_matrix_t *matrix);
cairo_private cairo_clip_path_t *
_cairo_clip_path_reference (cairo_clip_path_t *clip_path);
cairo_private void
_cairo_clip_reset (cairo_clip_t *clip);
_cairo_clip_path_destroy (cairo_clip_path_t *clip_path);
cairo_private void
_cairo_clip_destroy (cairo_clip_t *clip);
cairo_private extern const cairo_clip_t __cairo_clip_all;
cairo_private cairo_clip_t *
_cairo_clip_copy (const cairo_clip_t *clip);
cairo_private cairo_clip_t *
_cairo_clip_copy_region (const cairo_clip_t *clip);
cairo_private cairo_clip_t *
_cairo_clip_copy_path (const cairo_clip_t *clip);
cairo_private cairo_clip_t *
_cairo_clip_translate (cairo_clip_t *clip, int tx, int ty);
cairo_private cairo_clip_t *
_cairo_clip_transform (cairo_clip_t *clip, const cairo_matrix_t *m);
cairo_private cairo_clip_t *
_cairo_clip_copy_with_translation (const cairo_clip_t *clip, int tx, int ty);
cairo_private cairo_bool_t
_cairo_clip_equal (const cairo_clip_t *clip_a,
const cairo_clip_t *clip_b);
#define _cairo_clip_fini(clip) _cairo_clip_reset (clip)
cairo_private cairo_clip_t *
_cairo_clip_intersect_rectangle (cairo_clip_t *clip,
const cairo_rectangle_int_t *rectangle);
cairo_private cairo_status_t
_cairo_clip_rectangle (cairo_clip_t *clip,
const cairo_rectangle_int_t *rectangle);
cairo_private cairo_clip_t *
_cairo_clip_intersect_clip (cairo_clip_t *clip,
const cairo_clip_t *other);
cairo_private cairo_status_t
_cairo_clip_clip (cairo_clip_t *clip,
const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias);
cairo_private cairo_clip_t *
_cairo_clip_intersect_box (cairo_clip_t *clip,
const cairo_box_t *box);
cairo_private cairo_status_t
_cairo_clip_apply_clip (cairo_clip_t *clip,
const cairo_clip_t *other);
cairo_private cairo_clip_t *
_cairo_clip_intersect_boxes (cairo_clip_t *clip,
const cairo_boxes_t *boxes);
cairo_private cairo_clip_t *
_cairo_clip_intersect_rectilinear_path (cairo_clip_t *clip,
const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
cairo_antialias_t antialias);
cairo_private cairo_clip_t *
_cairo_clip_intersect_path (cairo_clip_t *clip,
const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias);
cairo_private const cairo_rectangle_int_t *
_cairo_clip_get_extents (const cairo_clip_t *clip);
cairo_private cairo_surface_t *
_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *dst, int *tx, int *ty);
_cairo_clip_get_surface (const cairo_clip_t *clip, cairo_surface_t *dst, int *tx, int *ty);
cairo_private cairo_surface_t *
_cairo_clip_get_image (const cairo_clip_t *clip,
cairo_surface_t *target,
const cairo_rectangle_int_t *extents);
cairo_private cairo_status_t
_cairo_clip_combine_with_surface (cairo_clip_t *clip,
_cairo_clip_combine_with_surface (const cairo_clip_t *clip,
cairo_surface_t *dst,
int dst_x, int dst_y);
cairo_private cairo_int_status_t
_cairo_clip_get_region (cairo_clip_t *clip,
cairo_region_t **region);
cairo_private cairo_clip_t *
_cairo_clip_from_boxes (const cairo_boxes_t *boxes);
cairo_private cairo_int_status_t
_cairo_clip_get_boxes (cairo_clip_t *clip,
cairo_box_t **boxes,
int *count);
cairo_private cairo_status_t
_cairo_clip_to_boxes (cairo_clip_t **clip,
cairo_composite_rectangles_t *extents,
cairo_box_t **boxes,
int *num_boxes);
cairo_private cairo_region_t *
_cairo_clip_get_region (const cairo_clip_t *clip);
cairo_private cairo_bool_t
_cairo_clip_contains_rectangle (cairo_clip_t *clip,
_cairo_clip_is_region (const cairo_clip_t *clip);
cairo_private cairo_clip_t *
_cairo_clip_reduce_to_rectangle (const cairo_clip_t *clip,
const cairo_rectangle_int_t *r);
cairo_private cairo_clip_t *
_cairo_clip_reduce_for_composite (const cairo_clip_t *clip,
cairo_composite_rectangles_t *extents);
cairo_private cairo_bool_t
_cairo_clip_contains_rectangle (const cairo_clip_t *clip,
const cairo_rectangle_int_t *rect);
cairo_private cairo_bool_t
_cairo_clip_contains_extents (cairo_clip_t *clip,
const cairo_composite_rectangles_t *extents);
_cairo_clip_contains_box (const cairo_clip_t *clip,
const cairo_box_t *box);
cairo_private void
_cairo_clip_drop_cache (cairo_clip_t *clip);
cairo_private cairo_bool_t
_cairo_clip_contains_extents (const cairo_clip_t *clip,
const cairo_composite_rectangles_t *extents);
cairo_private cairo_rectangle_list_t*
_cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate);
cairo_private cairo_rectangle_list_t *
_cairo_rectangle_list_create_in_error (cairo_status_t status);
cairo_private cairo_bool_t
_cairo_clip_is_polygon (const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_clip_get_polygon (const cairo_clip_t *clip,
cairo_polygon_t *polygon,
cairo_fill_rule_t *fill_rule,
cairo_antialias_t *antialias);
#endif /* CAIRO_CLIP_PRIVATE_H */

Просмотреть файл

@ -0,0 +1,123 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* Copyright © 2005 Red Hat, Inc.
* Copyright © 2009 Chris Wilson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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>
* Kristian Høgsberg <krh@redhat.com>
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-clip-private.h"
#include "cairo-error-private.h"
#include "cairo-freed-pool-private.h"
#include "cairo-gstate-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-pattern-private.h"
#include "cairo-composite-rectangles-private.h"
#include "cairo-region-private.h"
static void
_cairo_clip_extract_region (cairo_clip_t *clip)
{
cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
cairo_rectangle_int_t *r = stack_rects;
cairo_bool_t is_region;
int i;
if (clip->num_boxes == 0)
return;
if (clip->num_boxes > ARRAY_LENGTH (stack_rects)) {
r = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_rectangle_int_t));
if (r == NULL){
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return;
}
}
is_region = clip->path == NULL;
for (i = 0; i < clip->num_boxes; i++) {
cairo_box_t *b = &clip->boxes[i];
if (is_region)
is_region =
_cairo_fixed_is_integer (b->p1.x | b->p1.y | b->p2.x | b->p2.y);
r[i].x = _cairo_fixed_integer_floor (b->p1.x);
r[i].y = _cairo_fixed_integer_floor (b->p1.y);
r[i].width = _cairo_fixed_integer_ceil (b->p2.x) - r[i].x;
r[i].height = _cairo_fixed_integer_ceil (b->p2.y) - r[i].y;
}
clip->is_region = is_region;
clip->region = cairo_region_create_rectangles (r, i);
if (r != stack_rects)
free (r);
}
cairo_region_t *
_cairo_clip_get_region (const cairo_clip_t *clip)
{
if (clip == NULL)
return NULL;
if (clip->region == NULL)
_cairo_clip_extract_region ((cairo_clip_t *) clip);
return clip->region;
}
cairo_bool_t
_cairo_clip_is_region (const cairo_clip_t *clip)
{
if (clip == NULL)
return TRUE;
if (clip->is_region)
return TRUE;
/* XXX Geometric reduction? */
if (clip->path)
return FALSE;
if (clip->num_boxes == 0)
return TRUE;
if (clip->region == NULL)
_cairo_clip_extract_region ((cairo_clip_t *) clip);
return clip->is_region;
}

Просмотреть файл

@ -0,0 +1,240 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* Copyright © 2005 Red Hat, Inc.
* Copyright © 2009 Chris Wilson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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>
* Kristian Høgsberg <krh@redhat.com>
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-clip-private.h"
#include "cairo-error-private.h"
#include "cairo-freed-pool-private.h"
#include "cairo-gstate-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-pattern-private.h"
#include "cairo-composite-rectangles-private.h"
#include "cairo-region-private.h"
cairo_status_t
_cairo_clip_combine_with_surface (const cairo_clip_t *clip,
cairo_surface_t *dst,
int dst_x, int dst_y)
{
cairo_clip_path_t *copy_path;
cairo_clip_path_t *clip_path;
cairo_clip_t *copy;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
copy = _cairo_clip_copy_with_translation (clip, -dst_x, -dst_y);
copy_path = copy->path;
copy->path = NULL;
if (copy->boxes) {
status = _cairo_surface_paint (dst,
CAIRO_OPERATOR_IN,
&_cairo_pattern_white.base,
copy);
}
clip = NULL;
if (_cairo_clip_is_region (copy))
clip = copy;
clip_path = copy_path;
while (status == CAIRO_STATUS_SUCCESS && clip_path) {
status = _cairo_surface_fill (dst,
CAIRO_OPERATOR_IN,
&_cairo_pattern_white.base,
&clip_path->path,
clip_path->fill_rule,
clip_path->tolerance,
clip_path->antialias,
clip);
clip_path = clip_path->prev;
}
copy->path = copy_path;
_cairo_clip_destroy (copy);
return status;
}
static cairo_status_t
_cairo_path_fixed_add_box (cairo_path_fixed_t *path,
const cairo_box_t *box,
cairo_fixed_t fx,
cairo_fixed_t fy)
{
cairo_status_t status;
status = _cairo_path_fixed_move_to (path, box->p1.x + fx, box->p1.y + fy);
if (unlikely (status))
return status;
status = _cairo_path_fixed_line_to (path, box->p2.x + fx, box->p1.y + fy);
if (unlikely (status))
return status;
status = _cairo_path_fixed_line_to (path, box->p2.x + fx, box->p2.y + fy);
if (unlikely (status))
return status;
status = _cairo_path_fixed_line_to (path, box->p1.x + fx, box->p2.y + fy);
if (unlikely (status))
return status;
return _cairo_path_fixed_close_path (path);
}
cairo_surface_t *
_cairo_clip_get_surface (const cairo_clip_t *clip,
cairo_surface_t *target,
int *tx, int *ty)
{
cairo_surface_t *surface;
cairo_status_t status;
cairo_clip_t *copy, *region;
cairo_clip_path_t *copy_path, *clip_path;
if (clip->num_boxes) {
cairo_path_fixed_t path;
int i;
surface = _cairo_surface_create_scratch (target,
CAIRO_CONTENT_ALPHA,
clip->extents.width,
clip->extents.height,
CAIRO_COLOR_TRANSPARENT);
if (unlikely (surface->status))
return surface;
_cairo_path_fixed_init (&path);
status = CAIRO_STATUS_SUCCESS;
for (i = 0; status == CAIRO_STATUS_SUCCESS && i < clip->num_boxes; i++) {
status = _cairo_path_fixed_add_box (&path, &clip->boxes[i],
-_cairo_fixed_from_int (clip->extents.x),
-_cairo_fixed_from_int (clip->extents.y));
}
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_surface_fill (surface,
CAIRO_OPERATOR_ADD,
&_cairo_pattern_white.base,
&path,
CAIRO_FILL_RULE_WINDING,
1.,
CAIRO_ANTIALIAS_DEFAULT,
NULL);
_cairo_path_fixed_fini (&path);
if (unlikely (status)) {
cairo_surface_destroy (surface);
return _cairo_surface_create_in_error (status);
}
} else {
surface = _cairo_surface_create_scratch (target,
CAIRO_CONTENT_ALPHA,
clip->extents.width,
clip->extents.height,
CAIRO_COLOR_WHITE);
if (unlikely (surface->status))
return surface;
}
copy = _cairo_clip_copy_with_translation (clip,
-clip->extents.x,
-clip->extents.y);
copy_path = copy->path;
copy->path = NULL;
region = copy;
if (! _cairo_clip_is_region (copy))
region = _cairo_clip_copy_region (copy);
status = CAIRO_STATUS_SUCCESS;
clip_path = copy_path;
while (status == CAIRO_STATUS_SUCCESS && clip_path) {
status = _cairo_surface_fill (surface,
CAIRO_OPERATOR_IN,
&_cairo_pattern_white.base,
&clip_path->path,
clip_path->fill_rule,
clip_path->tolerance,
clip_path->antialias,
region);
clip_path = clip_path->prev;
}
copy->path = copy_path;
_cairo_clip_destroy (copy);
if (region != copy)
_cairo_clip_destroy (region);
if (unlikely (status)) {
cairo_surface_destroy (surface);
return _cairo_surface_create_in_error (status);
}
*tx = clip->extents.x;
*ty = clip->extents.y;
return surface;
}
cairo_surface_t *
_cairo_clip_get_image (const cairo_clip_t *clip,
cairo_surface_t *target,
const cairo_rectangle_int_t *extents)
{
cairo_surface_t *surface;
cairo_status_t status;
surface = cairo_surface_create_similar_image (target,
CAIRO_FORMAT_A8,
extents->width,
extents->height);
if (unlikely (surface->status))
return surface;
status = _cairo_surface_paint (surface, CAIRO_OPERATOR_SOURCE,
&_cairo_pattern_white.base, NULL);
if (likely (status == CAIRO_STATUS_SUCCESS))
status = _cairo_clip_combine_with_surface (clip, surface,
extents->x, extents->y);
if (unlikely (status)) {
cairo_surface_destroy (surface);
surface = _cairo_surface_create_in_error (status);
}
return surface;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,90 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2011 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.og/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.
*
* Contributor(s):
* Robert Bragg <robert@linux.intel.com>
*/
#ifndef CAIRO_COGL_GRADIENT_PRIVATE_H
#define CAIRO_COGL_GRADIENT_PRIVATE_H
#include "cairoint.h"
#include "cairo-pattern-private.h"
#include <cogl/cogl2-experimental.h>
#define CAIRO_COGL_LINEAR_GRADIENT_CACHE_SIZE (1024 * 1024)
typedef enum _cairo_cogl_gradient_compatibility {
CAIRO_COGL_GRADIENT_CAN_EXTEND_PAD = 1<<0,
CAIRO_COGL_GRADIENT_CAN_EXTEND_REPEAT = 1<<1,
CAIRO_COGL_GRADIENT_CAN_EXTEND_REFLECT = 1<<2,
CAIRO_COGL_GRADIENT_CAN_EXTEND_NONE = 1<<3
} cairo_cogl_gradient_compatibility_t;
#define CAIRO_COGL_GRADIENT_CAN_EXTEND_ALL (CAIRO_COGL_GRADIENT_CAN_EXTEND_PAD |\
CAIRO_COGL_GRADIENT_CAN_EXTEND_REPEAT|\
CAIRO_COGL_GRADIENT_CAN_EXTEND_REFLECT|\
CAIRO_COGL_GRADIENT_CAN_EXTEND_NONE)
typedef struct _cairo_cogl_linear_texture_entry {
cairo_cogl_gradient_compatibility_t compatibility;
CoglTexture *texture;
float translate_x;
float scale_x;
} cairo_cogl_linear_texture_entry_t;
typedef struct _cairo_cogl_linear_gradient {
cairo_cache_entry_t cache_entry;
cairo_reference_count_t ref_count;
GList *textures;
int n_stops;
const cairo_gradient_stop_t *stops;
cairo_gradient_stop_t stops_embedded[1];
} cairo_cogl_linear_gradient_t;
cairo_int_status_t
_cairo_cogl_get_linear_gradient (cairo_cogl_device_t *context,
cairo_extend_t extend_mode,
int n_stops,
const cairo_gradient_stop_t *stops,
const cairo_bool_t need_mirrored_gradient,
cairo_cogl_linear_gradient_t **gradient_out);
cairo_cogl_linear_texture_entry_t *
_cairo_cogl_linear_gradient_texture_for_extend (cairo_cogl_linear_gradient_t *gradient,
cairo_extend_t extend_mode);
cairo_cogl_linear_gradient_t *
_cairo_cogl_linear_gradient_reference (cairo_cogl_linear_gradient_t *gradient);
void
_cairo_cogl_linear_gradient_destroy (cairo_cogl_linear_gradient_t *gradient);
cairo_bool_t
_cairo_cogl_linear_gradient_equal (const void *key_a, const void *key_b);
#endif /* CAIRO_COGL_GRADIENT_PRIVATE_H */

Просмотреть файл

@ -0,0 +1,678 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2011 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.og/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.
*
* Contributor(s):
* Robert Bragg <robert@linux.intel.com>
*/
//#include "cairoint.h"
#include "cairo-cogl-private.h"
#include "cairo-cogl-gradient-private.h"
#include "cairo-image-surface-private.h"
#include <cogl/cogl2-experimental.h>
#include <glib.h>
//#define DUMP_GRADIENTS_TO_PNG
static unsigned long
_cairo_cogl_linear_gradient_hash (unsigned int n_stops,
const cairo_gradient_stop_t *stops)
{
return _cairo_hash_bytes (n_stops, stops,
sizeof (cairo_gradient_stop_t) * n_stops);
}
static cairo_cogl_linear_gradient_t *
_cairo_cogl_linear_gradient_lookup (cairo_cogl_device_t *ctx,
unsigned long hash,
unsigned int n_stops,
const cairo_gradient_stop_t *stops)
{
cairo_cogl_linear_gradient_t lookup;
lookup.cache_entry.hash = hash,
lookup.n_stops = n_stops;
lookup.stops = stops;
return _cairo_cache_lookup (&ctx->linear_cache, &lookup.cache_entry);
}
cairo_bool_t
_cairo_cogl_linear_gradient_equal (const void *key_a, const void *key_b)
{
const cairo_cogl_linear_gradient_t *a = key_a;
const cairo_cogl_linear_gradient_t *b = key_b;
if (a->n_stops != b->n_stops)
return FALSE;
return memcmp (a->stops, b->stops, a->n_stops * sizeof (cairo_gradient_stop_t)) == 0;
}
cairo_cogl_linear_gradient_t *
_cairo_cogl_linear_gradient_reference (cairo_cogl_linear_gradient_t *gradient)
{
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&gradient->ref_count));
_cairo_reference_count_inc (&gradient->ref_count);
return gradient;
}
void
_cairo_cogl_linear_gradient_destroy (cairo_cogl_linear_gradient_t *gradient)
{
GList *l;
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&gradient->ref_count));
if (! _cairo_reference_count_dec_and_test (&gradient->ref_count))
return;
for (l = gradient->textures; l; l = l->next) {
cairo_cogl_linear_texture_entry_t *entry = l->data;
cogl_object_unref (entry->texture);
free (entry);
}
g_list_free (gradient->textures);
free (gradient);
}
static int
_cairo_cogl_util_next_p2 (int a)
{
int rval = 1;
while (rval < a)
rval <<= 1;
return rval;
}
static float
get_max_color_component_range (const cairo_color_stop_t *color0,
const cairo_color_stop_t *color1)
{
float range;
float max = 0;
range = fabs (color0->red - color1->red);
max = MAX (range, max);
range = fabs (color0->green - color1->green);
max = MAX (range, max);
range = fabs (color0->blue - color1->blue);
max = MAX (range, max);
range = fabs (color0->alpha - color1->alpha);
max = MAX (range, max);
return max;
}
static int
_cairo_cogl_linear_gradient_width_for_stops (cairo_extend_t extend,
unsigned int n_stops,
const cairo_gradient_stop_t *stops)
{
unsigned int n;
float max_texels_per_unit_offset = 0;
float total_offset_range;
/* Find the stop pair demanding the most precision because we are
* interpolating the largest color-component range.
*
* From that we can define the relative sizes of all the other
* stop pairs within our texture and thus the overall size.
*
* To determine the maximum number of texels for a given gap we
* look at the range of colors we are expected to interpolate (so
* long as the stop offsets are not degenerate) and we simply
* assume we want one texel for each unique color value possible
* for a one byte-per-component representation.
* XXX: maybe this is overkill and just allowing 128 levels
* instead of 256 would be enough and then we'd rely on the
* bilinear filtering to give the full range.
*
* XXX: potentially we could try and map offsets to pixels to come
* up with a more precise mapping, but we are aiming to cache
* the gradients so we can't make assumptions about how it will be
* scaled in the future.
*/
for (n = 1; n < n_stops; n++) {
float color_range;
float offset_range;
float texels;
float texels_per_unit_offset;
/* note: degenerate stops don't need to be represented in the
* texture but we want to be sure that solid gaps get at least
* one texel and all other gaps get at least 2 texels.
*/
if (stops[n].offset == stops[n-1].offset)
continue;
color_range = get_max_color_component_range (&stops[n].color, &stops[n-1].color);
if (color_range == 0)
texels = 1;
else
texels = MAX (2, 256.0f * color_range);
/* So how many texels would we need to map over the full [0,1]
* gradient range so this gap would have enough texels? ... */
offset_range = stops[n].offset - stops[n - 1].offset;
texels_per_unit_offset = texels / offset_range;
if (texels_per_unit_offset > max_texels_per_unit_offset)
max_texels_per_unit_offset = texels_per_unit_offset;
}
total_offset_range = fabs (stops[n_stops - 1].offset - stops[0].offset);
return max_texels_per_unit_offset * total_offset_range;
}
/* Aim to create gradient textures without an alpha component so we can avoid
* needing to use blending... */
static CoglTextureComponents
_cairo_cogl_linear_gradient_components_for_stops (cairo_extend_t extend,
unsigned int n_stops,
const cairo_gradient_stop_t *stops)
{
unsigned int n;
/* We have to add extra transparent texels to the end of the gradient to
* handle CAIRO_EXTEND_NONE... */
if (extend == CAIRO_EXTEND_NONE)
return COGL_TEXTURE_COMPONENTS_RGBA;
for (n = 1; n < n_stops; n++) {
if (stops[n].color.alpha != 1.0)
return COGL_TEXTURE_COMPONENTS_RGBA;
}
return COGL_TEXTURE_COMPONENTS_RGBA;
}
static cairo_cogl_gradient_compatibility_t
_cairo_cogl_compatibility_from_extend_mode (cairo_extend_t extend_mode)
{
switch (extend_mode)
{
case CAIRO_EXTEND_NONE:
return CAIRO_COGL_GRADIENT_CAN_EXTEND_NONE;
case CAIRO_EXTEND_PAD:
return CAIRO_COGL_GRADIENT_CAN_EXTEND_PAD;
case CAIRO_EXTEND_REPEAT:
return CAIRO_COGL_GRADIENT_CAN_EXTEND_REPEAT;
case CAIRO_EXTEND_REFLECT:
return CAIRO_COGL_GRADIENT_CAN_EXTEND_REFLECT;
}
assert (0); /* not reached */
return CAIRO_EXTEND_NONE;
}
cairo_cogl_linear_texture_entry_t *
_cairo_cogl_linear_gradient_texture_for_extend (cairo_cogl_linear_gradient_t *gradient,
cairo_extend_t extend_mode)
{
GList *l;
cairo_cogl_gradient_compatibility_t compatibility =
_cairo_cogl_compatibility_from_extend_mode (extend_mode);
for (l = gradient->textures; l; l = l->next) {
cairo_cogl_linear_texture_entry_t *entry = l->data;
if (entry->compatibility & compatibility)
return entry;
}
return NULL;
}
static void
color_stop_lerp (const cairo_color_stop_t *c0,
const cairo_color_stop_t *c1,
float factor,
cairo_color_stop_t *dest)
{
/* NB: we always ignore the short members in this file so we don't need to
* worry about initializing them here. */
dest->red = c0->red * (1.0f-factor) + c1->red * factor;
dest->green = c0->green * (1.0f-factor) + c1->green * factor;
dest->blue = c0->blue * (1.0f-factor) + c1->blue * factor;
dest->alpha = c0->alpha * (1.0f-factor) + c1->alpha * factor;
}
static size_t
_cairo_cogl_linear_gradient_size (cairo_cogl_linear_gradient_t *gradient)
{
GList *l;
size_t size = 0;
for (l = gradient->textures; l; l = l->next) {
cairo_cogl_linear_texture_entry_t *entry = l->data;
size += cogl_texture_get_width (entry->texture) * 4;
}
return size;
}
static void
emit_stop (CoglVertexP2C4 **position,
float left,
float right,
const cairo_color_stop_t *left_color,
const cairo_color_stop_t *right_color)
{
CoglVertexP2C4 *p = *position;
guint8 lr = left_color->red * 255;
guint8 lg = left_color->green * 255;
guint8 lb = left_color->blue * 255;
guint8 la = left_color->alpha * 255;
guint8 rr = right_color->red * 255;
guint8 rg = right_color->green * 255;
guint8 rb = right_color->blue * 255;
guint8 ra = right_color->alpha * 255;
p[0].x = left;
p[0].y = 0;
p[0].r = lr; p[0].g = lg; p[0].b = lb; p[0].a = la;
p[1].x = left;
p[1].y = 1;
p[1].r = lr; p[1].g = lg; p[1].b = lb; p[1].a = la;
p[2].x = right;
p[2].y = 1;
p[2].r = rr; p[2].g = rg; p[2].b = rb; p[2].a = ra;
p[3].x = left;
p[3].y = 0;
p[3].r = lr; p[3].g = lg; p[3].b = lb; p[3].a = la;
p[4].x = right;
p[4].y = 1;
p[4].r = rr; p[4].g = rg; p[4].b = rb; p[4].a = ra;
p[5].x = right;
p[5].y = 0;
p[5].r = rr; p[5].g = rg; p[5].b = rb; p[5].a = ra;
*position = &p[6];
}
#ifdef DUMP_GRADIENTS_TO_PNG
static void
dump_gradient_to_png (CoglTexture *texture)
{
cairo_image_surface_t *image = (cairo_image_surface_t *)
cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
cogl_texture_get_width (texture),
cogl_texture_get_height (texture));
CoglPixelFormat format;
static int gradient_id = 0;
char *gradient_name;
if (image->base.status)
return;
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
#else
format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
#endif
cogl_texture_get_data (texture,
format,
0,
image->data);
gradient_name = g_strdup_printf ("./gradient%d.png", gradient_id++);
g_print ("writing gradient: %s\n", gradient_name);
cairo_surface_write_to_png ((cairo_surface_t *)image, gradient_name);
g_free (gradient_name);
}
#endif
cairo_int_status_t
_cairo_cogl_get_linear_gradient (cairo_cogl_device_t *device,
cairo_extend_t extend_mode,
int n_stops,
const cairo_gradient_stop_t *stops,
const cairo_bool_t need_mirrored_gradient,
cairo_cogl_linear_gradient_t **gradient_out)
{
unsigned long hash;
cairo_cogl_linear_gradient_t *gradient;
cairo_cogl_linear_texture_entry_t *entry;
cairo_gradient_stop_t *internal_stops;
int stop_offset;
int n_internal_stops;
int n;
cairo_cogl_gradient_compatibility_t compatibilities;
int width;
int tex_width;
int left_padding = 0;
cairo_color_stop_t left_padding_color;
int right_padding = 0;
cairo_color_stop_t right_padding_color;
CoglTextureComponents components;
CoglTexture2D *tex;
int un_padded_width;
CoglFramebuffer *offscreen = NULL;
cairo_int_status_t status;
int n_quads;
int n_vertices;
float prev;
float right;
CoglVertexP2C4 *vertices;
CoglVertexP2C4 *p;
CoglPrimitive *prim;
CoglPipeline *pipeline;
hash = _cairo_cogl_linear_gradient_hash (n_stops, stops);
gradient = _cairo_cogl_linear_gradient_lookup (device, hash, n_stops, stops);
if (gradient) {
cairo_cogl_linear_texture_entry_t *entry =
_cairo_cogl_linear_gradient_texture_for_extend (gradient, extend_mode);
if (entry) {
*gradient_out = _cairo_cogl_linear_gradient_reference (gradient);
return CAIRO_INT_STATUS_SUCCESS;
}
}
if (!gradient) {
gradient = _cairo_malloc (sizeof (cairo_cogl_linear_gradient_t) +
sizeof (cairo_gradient_stop_t) * (n_stops - 1));
if (!gradient)
return CAIRO_INT_STATUS_NO_MEMORY;
CAIRO_REFERENCE_COUNT_INIT (&gradient->ref_count, 1);
/* NB: we update the cache_entry size at the end before
* [re]adding it to the cache. */
gradient->cache_entry.hash = hash;
gradient->textures = NULL;
gradient->n_stops = n_stops;
gradient->stops = gradient->stops_embedded;
memcpy (gradient->stops_embedded, stops, sizeof (cairo_gradient_stop_t) * n_stops);
} else {
_cairo_cogl_linear_gradient_reference (gradient);
}
entry = _cairo_malloc (sizeof (cairo_cogl_linear_texture_entry_t));
if (unlikely (!entry)) {
status = CAIRO_INT_STATUS_NO_MEMORY;
goto BAIL;
}
compatibilities = _cairo_cogl_compatibility_from_extend_mode (extend_mode);
n_internal_stops = n_stops;
stop_offset = 0;
/* We really need stops covering the full [0,1] range for repeat/reflect
* if we want to use sampler REPEAT/MIRROR wrap modes so we may need
* to add some extra stops... */
if (extend_mode == CAIRO_EXTEND_REPEAT || extend_mode == CAIRO_EXTEND_REFLECT)
{
/* If we don't need any extra stops then actually the texture
* will be shareable for repeat and reflect... */
compatibilities = (CAIRO_COGL_GRADIENT_CAN_EXTEND_REPEAT |
CAIRO_COGL_GRADIENT_CAN_EXTEND_REFLECT);
if (stops[0].offset != 0) {
n_internal_stops++;
stop_offset++;
}
if (stops[n_stops - 1].offset != 1)
n_internal_stops++;
}
internal_stops = alloca (n_internal_stops * sizeof (cairo_gradient_stop_t));
memcpy (&internal_stops[stop_offset], stops, sizeof (cairo_gradient_stop_t) * n_stops);
/* cairo_color_stop_t values are all unpremultiplied but we need to
* interpolate premultiplied colors so we premultiply all the double
* components now. (skipping any extra stops added for repeat/reflect)
*
* Another thing to note is that by premultiplying the colors
* early we'll also reduce the range of colors to interpolate
* which can result in smaller gradient textures.
*/
for (n = stop_offset; n < n_stops; n++) {
cairo_color_stop_t *color = &internal_stops[n].color;
color->red *= color->alpha;
color->green *= color->alpha;
color->blue *= color->alpha;
}
if (n_internal_stops != n_stops)
{
if (extend_mode == CAIRO_EXTEND_REPEAT) {
compatibilities &= ~CAIRO_COGL_GRADIENT_CAN_EXTEND_REFLECT;
if (stops[0].offset != 0) {
/* what's the wrap-around distance between the user's end-stops? */
double dx = (1.0 - stops[n_stops - 1].offset) + stops[0].offset;
internal_stops[0].offset = 0;
color_stop_lerp (&stops[0].color,
&stops[n_stops - 1].color,
stops[0].offset / dx,
&internal_stops[0].color);
}
if (stops[n_stops - 1].offset != 1) {
internal_stops[n_internal_stops - 1].offset = 1;
internal_stops[n_internal_stops - 1].color = internal_stops[0].color;
}
} else if (extend_mode == CAIRO_EXTEND_REFLECT) {
compatibilities &= ~CAIRO_COGL_GRADIENT_CAN_EXTEND_REPEAT;
if (stops[0].offset != 0) {
internal_stops[0].offset = 0;
internal_stops[0].color = stops[n_stops - 1].color;
}
if (stops[n_stops - 1].offset != 1) {
internal_stops[n_internal_stops - 1].offset = 1;
internal_stops[n_internal_stops - 1].color = stops[0].color;
}
}
}
stops = internal_stops;
n_stops = n_internal_stops;
width = _cairo_cogl_linear_gradient_width_for_stops (extend_mode, n_stops, stops);
if (extend_mode == CAIRO_EXTEND_PAD) {
/* Here we need to guarantee that the edge texels of our
* texture correspond to the desired padding color so we
* can use CLAMP_TO_EDGE.
*
* For short stop-gaps and especially for degenerate stops
* it's possible that without special consideration the
* user's end stop colors would not be present in our final
* texture.
*
* To handle this we forcibly add two extra padding texels
* at the edges which extend beyond the [0,1] range of the
* gradient itself and we will later report a translate and
* scale transform to compensate for this.
*/
/* XXX: If we consider generating a mipmap for our 1d texture
* at some point then we also need to consider how much
* padding to add to be sure lower mipmap levels still have
* the desired edge color (as opposed to a linear blend with
* other colors of the gradient).
*/
left_padding = 1;
left_padding_color = stops[0].color;
right_padding = 1;
right_padding_color = stops[n_stops - 1].color;
} else if (extend_mode == CAIRO_EXTEND_NONE) {
/* We handle EXTEND_NONE by adding two extra, transparent, texels at
* the ends of the texture and use CLAMP_TO_EDGE.
*
* We add a scale and translate transform so to account for our texels
* extending beyond the [0,1] range. */
left_padding = 1;
left_padding_color.red = 0;
left_padding_color.green = 0;
left_padding_color.blue = 0;
left_padding_color.alpha = 0;
right_padding = 1;
right_padding_color = left_padding_color;
}
/* If we still have stops that don't cover the full [0,1] range
* then we need to define a texture-coordinate scale + translate
* transform to account for that... */
if (stops[n_stops - 1].offset - stops[0].offset < 1) {
float range = stops[n_stops - 1].offset - stops[0].offset;
entry->scale_x = 1.0 / range;
entry->translate_x = -(stops[0].offset * entry->scale_x);
}
width += left_padding + right_padding;
width = _cairo_cogl_util_next_p2 (width);
width = MIN (4096, width); /* lets not go too stupidly big! */
if (!device->has_npots)
width = pow (2, ceil (log2 (width)));
if (need_mirrored_gradient)
tex_width = width * 2;
else
tex_width = width;
components = _cairo_cogl_linear_gradient_components_for_stops (extend_mode, n_stops, stops);
do {
tex = cogl_texture_2d_new_with_size (device->cogl_context,
tex_width, 1);
} while (tex == NULL && width >> 1 && tex_width >> 1);
if (unlikely (!tex)) {
status = CAIRO_INT_STATUS_NO_MEMORY;
goto BAIL;
}
cogl_texture_set_components (tex, components);
entry->texture = tex;
entry->compatibility = compatibilities;
un_padded_width = width - left_padding - right_padding;
/* XXX: only when we know the final texture width can we calculate the
* scale and translate factors needed to account for padding... */
if (un_padded_width != width)
entry->scale_x *= (float)un_padded_width / (float)width;
if (left_padding)
entry->translate_x += (entry->scale_x / (float)un_padded_width) * (float)left_padding;
offscreen = cogl_offscreen_new_with_texture (tex);
cogl_framebuffer_orthographic (offscreen, 0, 0,
tex_width, 1,
-1, 100);
cogl_framebuffer_clear4f (offscreen,
COGL_BUFFER_BIT_COLOR,
0, 0, 0, 0);
n_quads = n_stops - 1 + !!left_padding + !!right_padding;
n_vertices = 6 * n_quads;
vertices = _cairo_malloc_ab (n_vertices, sizeof (CoglVertexP2C4));
if (unlikely (!vertices)) {
status = CAIRO_INT_STATUS_NO_MEMORY;
goto BAIL;
}
p = vertices;
if (left_padding)
emit_stop (&p, 0, left_padding, &left_padding_color, &left_padding_color);
prev = (float)left_padding;
for (n = 1; n < n_stops; n++) {
right = (float)left_padding + (float)un_padded_width * stops[n].offset;
emit_stop (&p, prev, right, &stops[n-1].color, &stops[n].color);
prev = right;
}
if (right_padding)
emit_stop (&p, prev, width, &right_padding_color, &right_padding_color);
prim = cogl_primitive_new_p2c4 (device->cogl_context,
COGL_VERTICES_MODE_TRIANGLES,
n_vertices,
vertices);
free (vertices);
pipeline = cogl_pipeline_new (device->cogl_context);
cogl_primitive_draw (prim, offscreen, pipeline);
if (need_mirrored_gradient) {
/* In order to use a reflected gradient on hardware that
* doesn't have a mirrored repeating texture wrap mode, we
* render two reflected images to a double-length linear
* texture and reflect that */
CoglMatrix transform;
cogl_matrix_init_identity (&transform);
cogl_matrix_translate (&transform, tex_width, 0.0f, 0.0f);
cogl_matrix_scale (&transform, -1.0f, 1.0f, 1.0f);
cogl_framebuffer_transform (offscreen, &transform);
cogl_primitive_draw (prim, offscreen, pipeline);
}
cogl_object_unref (prim);
cogl_object_unref (pipeline);
cogl_object_unref (offscreen);
offscreen = NULL;
gradient->textures = g_list_prepend (gradient->textures, entry);
gradient->cache_entry.size = _cairo_cogl_linear_gradient_size (gradient);
#ifdef DUMP_GRADIENTS_TO_PNG
dump_gradient_to_png (tex);
#endif
#warning "FIXME:"
/* XXX: it seems the documentation of _cairo_cache_insert isn't true - it
* doesn't handle re-adding the same entry gracefully - the cache will
* just keep on growing and then it will start randomly evicting things
* pointlessly */
/* we ignore errors here and just return an uncached gradient */
if (likely (! _cairo_cache_insert (&device->linear_cache, &gradient->cache_entry)))
_cairo_cogl_linear_gradient_reference (gradient);
*gradient_out = gradient;
return CAIRO_INT_STATUS_SUCCESS;
BAIL:
free (entry);
if (gradient)
_cairo_cogl_linear_gradient_destroy (gradient);
if (offscreen)
cogl_object_unref (offscreen);
return status;
}

Просмотреть файл

@ -0,0 +1,164 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2011 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.og/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.
*
* Contributor(s):
* Robert Bragg <robert@linux.intel.com>
*/
#ifndef CAIRO_COGL_PRIVATE_H
#define CAIRO_COGL_PRIVATE_H
#include "cairo-device-private.h"
#include "cairo-cache-private.h"
#include "cairo-backend-private.h"
#include "cairo-default-context-private.h"
#include "cairo-surface-private.h"
#include "cairo-freelist-private.h"
#include <cogl/cogl2-experimental.h>
typedef enum _cairo_cogl_template_type {
/* solid source */
CAIRO_COGL_TEMPLATE_TYPE_SOLID,
/* solid source with solid mask */
CAIRO_COGL_TEMPLATE_TYPE_SOLID_MASK_SOLID,
/* solid source with texture mask */
CAIRO_COGL_TEMPLATE_TYPE_TEXTURE_MASK_SOLID,
/* texture source */
CAIRO_COGL_TEMPLATE_TYPE_TEXTURE,
/* texture source with solid mask */
CAIRO_COGL_TEMPLATE_TYPE_SOLID_MASK_TEXTURE,
/* texture source with texture mask */
CAIRO_COGL_TEMPLATE_TYPE_TEXTURE_MASK_TEXTURE,
/* texture source with source alpha ignored */
CAIRO_COGL_TEMPLATE_TYPE_TEXTURE_IGNORE_ALPHA,
/* texture source with solid mask with source alpha ignored */
CAIRO_COGL_TEMPLATE_TYPE_SOLID_MASK_TEXTURE_IGNORE_ALPHA,
/* texture source with texture mask with source alpha ignored */
CAIRO_COGL_TEMPLATE_TYPE_TEXTURE_MASK_TEXTURE_IGNORE_ALPHA,
CAIRO_COGL_TEMPLATE_TYPE_COUNT
} cairo_cogl_template_type;
typedef struct _cairo_cogl_device {
cairo_device_t base;
CoglContext *cogl_context;
cairo_bool_t has_npots;
cairo_bool_t has_mirrored_repeat;
CoglAttributeBuffer *buffer_stack;
size_t buffer_stack_size;
size_t buffer_stack_offset;
guint8 *buffer_stack_pointer;
/* This is a limited set of templates because we don't support the
* full range of operators that cairo has. The CAIRO_OPERATOR_ADD
* is the operator enum with the highest value that we support so
* we cap the size of the array by that.
*
* For each operator, we have a template for when we have a solid
* source and a non-solid source. For each of those, we also have
* additional templates for when we have a solid mask or a
* non-solid mask, for a total of six templates per operator.
*
* The templates are set to null at device creation time and only
* actually created on their first use.
*/
CoglPipeline *template_pipelines[CAIRO_OPERATOR_ADD + 1][CAIRO_COGL_TEMPLATE_TYPE_COUNT];
/* Caches 1d linear gradient textures */
cairo_cache_t linear_cache;
cairo_cache_t path_fill_prim_cache;
cairo_cache_t path_stroke_prim_cache;
cairo_freelist_t path_fill_meta_freelist;
cairo_freelist_t path_stroke_meta_freelist;
} cairo_cogl_device_t;
typedef struct _cairo_cogl_clip_primitives {
cairo_t *clip;
CoglPrimitive **primitives;
} cairo_cogl_clip_primitives_t;
typedef struct _cairo_cogl_surface {
cairo_surface_t base;
/* We currently have 3 basic kinds of Cogl surfaces:
* 1) A light surface simply wrapping a CoglTexture
* 2) A CoglOffscreen framebuffer that implicitly also wraps a CoglTexture
* 3) A CoglOnscreen framebuffer which could potentially be mapped to
* a CoglTexture (e.g. via tfp on X11) but we don't currently do
* that.
*/
CoglTexture *texture;
CoglFramebuffer *framebuffer;
int width;
int height;
/* Is this a snapshot used for mirrored repeating on hardware which
* doesn't have it, consisting of four reflected images? */
cairo_bool_t is_mirrored_snapshot;
GQueue *journal;
cairo_clip_t *last_clip;
/* A small fifo of recently used cairo_clip_ts paired with CoglPrimitives
* that can be used to mask the stencil buffer. */
GList *clips_fifo;
int n_clip_updates_per_frame;
/* Since the surface backend drawing operator functions don't get
* passed the current cairo_t context we don't have a good way
* to get our user-coordinates path into our surface_fill function.
*
* For now we use our _cairo_cogl_context_fill() wrapper to set this
* side band data on the surface...
*/
cairo_path_fixed_t *user_path;
cairo_matrix_t ctm;
cairo_matrix_t ctm_inverse;
cairo_bool_t path_is_rectangle;
double path_rectangle_x;
double path_rectangle_y;
double path_rectangle_width;
double path_rectangle_height;
} cairo_cogl_surface_t;
cairo_status_t
_cairo_cogl_path_fixed_rectangle (cairo_path_fixed_t *path,
cairo_fixed_t x,
cairo_fixed_t y,
cairo_fixed_t width,
cairo_fixed_t height);
#endif /* CAIRO_COGL_PRIVATE_H */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,86 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2011 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
*
* Contributor(s):
* Robert Bragg <robert@linux.intel.com>
*/
#ifndef CAIRO_COGL_H
#define CAIRO_COGL_H
#include "cairo.h"
#if CAIRO_HAS_COGL_SURFACE
#include <cogl/cogl2-experimental.h>
CAIRO_BEGIN_DECLS
cairo_public cairo_device_t *
cairo_cogl_device_create (CoglContext *context);
cairo_public cairo_surface_t *
cairo_cogl_onscreen_surface_create (cairo_device_t *device,
cairo_content_t content,
int width, int height);
cairo_public cairo_surface_t *
cairo_cogl_offscreen_surface_create (cairo_device_t *device,
cairo_content_t content,
int width, int height);
cairo_public cairo_surface_t *
cairo_cogl_surface_create_for_fb (cairo_device_t *device,
CoglFramebuffer *framebuffer,
cairo_content_t content);
cairo_public CoglFramebuffer *
cairo_cogl_surface_get_framebuffer (cairo_surface_t *surface);
/* If NPOT textures are not supported, the contents of interests may
* only be in the lowest-coordinate corner of the texture obtained from
* this function */
cairo_public CoglTexture *
cairo_cogl_surface_get_texture (cairo_surface_t *surface);
cairo_public cairo_status_t
cairo_cogl_surface_end_frame (cairo_surface_t *surface);
cairo_public cairo_status_t
cairo_cogl_surface_synchronize (cairo_surface_t *surface);
CAIRO_END_DECLS
#else /* CAIRO_HAS_COGL_SURFACE*/
# error Cairo was not compiled with support for the Cogl backend
#endif /* CAIRO_HAS_COGL_SURFACE*/
#endif /* CAIRO_COGL_H */

Просмотреть файл

@ -77,32 +77,14 @@ _cairo_stock_color (cairo_stock_t stock)
}
}
void
_cairo_color_init (cairo_color_t *color)
{
*color = cairo_color_white;
}
void
_cairo_color_init_rgb (cairo_color_t *color,
double red, double green, double blue)
{
_cairo_color_init_rgba (color, red, green, blue, 1.0);
}
/* Convert a double in [0.0, 1.0] to an integer in [0, 65535]
* The conversion is designed to divide the input range into 65536
* equally-sized regions. This is achieved by multiplying by 65536 and
* then special-casing the result of an input value of 1.0 so that it
* maps to 65535 instead of 65536.
* The conversion is designed to choose the integer i such that
* i / 65535.0 is as close as possible to the input value.
*/
uint16_t
_cairo_color_double_to_short (double d)
{
uint32_t i;
i = (uint32_t) (d * 65536);
i -= (i >> 16);
return i;
return d * 65535.0 + 0.5;
}
static void

Просмотреть файл

@ -69,3 +69,26 @@ NAME (TYPE *base, unsigned int nmemb) \
} \
} while (swapped); \
}
#define CAIRO_COMBSORT_DECLARE_WITH_DATA(NAME, TYPE, CMP) \
static void \
NAME (TYPE *base, unsigned int nmemb, void *data) \
{ \
unsigned int gap = nmemb; \
unsigned int i, j; \
int swapped; \
do { \
gap = _cairo_combsort_newgap (gap); \
swapped = gap > 1; \
for (i = 0; i < nmemb-gap ; i++) { \
j = i + gap; \
if (CMP (base[i], base[j], data) > 0 ) { \
TYPE tmp; \
tmp = base[i]; \
base[i] = base[j]; \
base[j] = tmp; \
swapped = 1; \
} \
} \
} while (swapped); \
}

Просмотреть файл

@ -69,7 +69,7 @@
* call sites. The macro works by renaming `f' to an internal name
* in the symbol table and hiding that. As far as cairo internal
* calls are concerned they're calling a library internal function
* and thus don't need to bounce via the PLT.
* and thus don't need to bounce via the procedure linkage table (PLT).
*
* slim_hidden_def(f)
*
@ -114,7 +114,9 @@
/* slim_internal.h */
#define CAIRO_HAS_HIDDEN_SYMBOLS 1
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) && !defined(__sun)
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && \
(defined(__ELF__) || defined(__APPLE__)) && \
!defined(__sun)
#define cairo_private_no_warn __attribute__((__visibility__("hidden")))
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
#define cairo_private_no_warn __hidden
@ -181,70 +183,37 @@
#endif
#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
#define _CAIRO_BOOLEAN_EXPR(expr) \
__extension__ ({ \
int _cairo_boolean_var_; \
if (expr) \
_cairo_boolean_var_ = 1; \
else \
_cairo_boolean_var_ = 0; \
_cairo_boolean_var_; \
})
#define likely(expr) (__builtin_expect (_CAIRO_BOOLEAN_EXPR(expr), 1))
#define unlikely(expr) (__builtin_expect (_CAIRO_BOOLEAN_EXPR(expr), 0))
#define likely(expr) (__builtin_expect (!!(expr), 1))
#define unlikely(expr) (__builtin_expect (!!(expr), 0))
#else
#define likely(expr) (expr)
#define unlikely(expr) (expr)
#endif
/*
* clang-cl supports __attribute__, but MSVC doesn't, so we need to make sure
* we do this if not GNUC but also if not clang either.
*/
#if !defined(__GNUC__) && !defined(__clang__)
#ifndef __GNUC__
#undef __attribute__
#define __attribute__(x)
#endif
#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
#define snprintf _snprintf
#define popen _popen
#define pclose _pclose
#define access _access
#define fdopen _fdopen
#define hypot _hypot
#define pclose _pclose
#define popen _popen
#define strdup _strdup
#define unlink _unlink
#if _MSC_VER < 1900
#define vsnprintf _vsnprintf
#define snprintf _snprintf
#endif
#endif
#ifdef _MSC_VER
#define HAVE_WIN32_ATOMIC_PRIMITIVES 1
#ifndef __cplusplus
#undef inline
#define inline __inline
#endif
/* there are currently linkage problems that arise when trying to include intrin.h in c++:
* D:\sdks\v7.0\include\winnt.h(3674) : error C2733: second C linkage of overloaded function '_interlockedbittestandset' not allowed
* so avoid defining ffs in c++ code for now */
#ifndef __cplusplus
/* Add a definition of ffs */
#include <intrin.h>
#pragma intrinsic(_BitScanForward)
static __forceinline int
ffs (int x)
{
unsigned long i;
if (_BitScanForward(&i, x) != 0)
return i + 1;
return 0;
}
#endif
#elif defined(__WIN32__) && defined(__GNUC__)
#define ffs(x) __builtin_ffs(x)
#endif
#if defined(_MSC_VER) && defined(_M_IX86)

Просмотреть файл

@ -38,6 +38,8 @@
#define CAIRO_COMPOSITE_RECTANGLES_PRIVATE_H
#include "cairo-types-private.h"
#include "cairo-error-private.h"
#include "cairo-pattern-private.h"
CAIRO_BEGIN_DECLS
@ -51,55 +53,107 @@ CAIRO_BEGIN_DECLS
*
*/
struct _cairo_composite_rectangles {
cairo_surface_t *surface;
cairo_operator_t op;
cairo_rectangle_int_t source;
cairo_rectangle_int_t mask;
cairo_rectangle_int_t bounded; /* dst */
cairo_rectangle_int_t unbounded; /* clip */
cairo_rectangle_int_t destination;
cairo_rectangle_int_t bounded; /* source? IN mask? IN unbounded */
cairo_rectangle_int_t unbounded; /* destination IN clip */
uint32_t is_bounded;
cairo_rectangle_int_t source_sample_area;
cairo_rectangle_int_t mask_sample_area;
cairo_pattern_union_t source_pattern;
cairo_pattern_union_t mask_pattern;
const cairo_pattern_t *original_source_pattern;
const cairo_pattern_t *original_mask_pattern;
cairo_clip_t *clip; /* clip will be reduced to the minimal container */
};
cairo_private cairo_int_status_t
_cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_clip_t *clip);
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
cairo_clip_t *clip);
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_path_fixed_t *path,
const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
cairo_clip_t *clip);
const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_init_for_fill (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_clip_t *clip);
const cairo_path_fixed_t *path,
const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_init_for_boxes (cairo_composite_rectangles_t *extents,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_boxes_t *boxes,
const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_init_for_polygon (cairo_composite_rectangles_t *extents,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_polygon_t *polygon,
const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_clip_t *clip,
const cairo_clip_t *clip,
cairo_bool_t *overlap);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_intersect_source_extents (cairo_composite_rectangles_t *extents,
const cairo_box_t *box);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_intersect_mask_extents (cairo_composite_rectangles_t *extents,
const cairo_box_t *box);
cairo_private cairo_bool_t
_cairo_composite_rectangles_can_reduce_clip (cairo_composite_rectangles_t *composite,
cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_add_to_damage (cairo_composite_rectangles_t *composite,
cairo_boxes_t *damage);
cairo_private void
_cairo_composite_rectangles_fini (cairo_composite_rectangles_t *extents);
CAIRO_END_DECLS
#endif /* CAIRO_COMPOSITE_RECTANGLES_PRIVATE_H */

Просмотреть файл

@ -35,153 +35,412 @@
#include "cairoint.h"
#include "cairo-clip-inline.h"
#include "cairo-error-private.h"
#include "cairo-composite-rectangles-private.h"
#include "cairo-pattern-private.h"
/* A collection of routines to facilitate writing compositors. */
void _cairo_composite_rectangles_fini (cairo_composite_rectangles_t *extents)
{
_cairo_clip_destroy (extents->clip);
}
static void
_cairo_composite_reduce_pattern (const cairo_pattern_t *src,
cairo_pattern_union_t *dst)
{
int tx, ty;
_cairo_pattern_init_static_copy (&dst->base, src);
if (dst->base.type == CAIRO_PATTERN_TYPE_SOLID)
return;
dst->base.filter = _cairo_pattern_analyze_filter (&dst->base);
tx = ty = 0;
if (_cairo_matrix_is_pixman_translation (&dst->base.matrix,
dst->base.filter,
&tx, &ty))
{
dst->base.matrix.x0 = tx;
dst->base.matrix.y0 = ty;
}
}
static inline cairo_bool_t
_cairo_composite_rectangles_init (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_clip_t *clip)
const cairo_clip_t *clip)
{
extents->unbounded = *surface_extents;
if (_cairo_clip_is_all_clipped (clip))
return FALSE;
if (clip != NULL) {
const cairo_rectangle_int_t *clip_extents;
extents->surface = surface;
extents->op = op;
clip_extents = _cairo_clip_get_extents (clip);
if (clip_extents == NULL)
return FALSE;
_cairo_surface_get_extents (surface, &extents->destination);
extents->clip = NULL;
if (! _cairo_rectangle_intersect (&extents->unbounded, clip_extents))
return FALSE;
}
extents->unbounded = extents->destination;
if (clip && ! _cairo_rectangle_intersect (&extents->unbounded,
_cairo_clip_get_extents (clip)))
return FALSE;
extents->bounded = extents->unbounded;
extents->is_bounded = _cairo_operator_bounded_by_either (op);
_cairo_pattern_get_extents (source, &extents->source);
extents->original_source_pattern = source;
_cairo_composite_reduce_pattern (source, &extents->source_pattern);
_cairo_pattern_get_extents (&extents->source_pattern.base,
&extents->source,
surface->is_vector);
if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_SOURCE) {
if (! _cairo_rectangle_intersect (&extents->bounded, &extents->source))
return FALSE;
}
extents->original_mask_pattern = NULL;
extents->mask_pattern.base.type = CAIRO_PATTERN_TYPE_SOLID;
extents->mask_pattern.solid.color.alpha = 1.; /* XXX full initialisation? */
extents->mask_pattern.solid.color.alpha_short = 0xffff;
return TRUE;
}
cairo_int_status_t
_cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_clip_t *clip)
const cairo_clip_t *clip)
{
if (! _cairo_composite_rectangles_init (extents,
surface_extents,
op, source, clip))
surface, op, source, clip))
{
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
extents->mask = extents->bounded;
extents->mask = extents->destination;
extents->clip = _cairo_clip_reduce_for_composite (clip, extents);
if (_cairo_clip_is_all_clipped (extents->clip))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
if (! _cairo_rectangle_intersect (&extents->unbounded,
_cairo_clip_get_extents (extents->clip)))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
if (extents->source_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID)
_cairo_pattern_sampled_area (&extents->source_pattern.base,
&extents->bounded,
&extents->source_sample_area);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents)
_cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents,
const cairo_clip_t *clip)
{
cairo_bool_t ret;
ret = _cairo_rectangle_intersect (&extents->bounded, &extents->mask);
if (! ret && extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
if ((!_cairo_rectangle_intersect (&extents->bounded, &extents->mask)) &&
(extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
if (extents->is_bounded == (CAIRO_OPERATOR_BOUND_BY_MASK | CAIRO_OPERATOR_BOUND_BY_SOURCE)) {
extents->unbounded = extents->bounded;
} else if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK) {
if (!_cairo_rectangle_intersect (&extents->unbounded, &extents->mask))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
extents->clip = _cairo_clip_reduce_for_composite (clip, extents);
if (_cairo_clip_is_all_clipped (extents->clip))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
if (! _cairo_rectangle_intersect (&extents->unbounded,
_cairo_clip_get_extents (extents->clip)))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
if (! _cairo_rectangle_intersect (&extents->bounded,
_cairo_clip_get_extents (extents->clip)) &&
extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
{
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
if (extents->source_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID)
_cairo_pattern_sampled_area (&extents->source_pattern.base,
&extents->bounded,
&extents->source_sample_area);
if (extents->mask_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID) {
_cairo_pattern_sampled_area (&extents->mask_pattern.base,
&extents->bounded,
&extents->mask_sample_area);
if (extents->mask_sample_area.width == 0 ||
extents->mask_sample_area.height == 0) {
_cairo_composite_rectangles_fini (extents);
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
}
return CAIRO_STATUS_SUCCESS;
}
cairo_int_status_t
_cairo_composite_rectangles_intersect_source_extents (cairo_composite_rectangles_t *extents,
const cairo_box_t *box)
{
cairo_rectangle_int_t rect;
cairo_clip_t *clip;
_cairo_box_round_to_rectangle (box, &rect);
if (rect.x == extents->source.x &&
rect.y == extents->source.y &&
rect.width == extents->source.width &&
rect.height == extents->source.height)
{
return CAIRO_INT_STATUS_SUCCESS;
}
_cairo_rectangle_intersect (&extents->source, &rect);
rect = extents->bounded;
if (! _cairo_rectangle_intersect (&extents->bounded, &extents->source) &&
extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_SOURCE)
return CAIRO_INT_STATUS_NOTHING_TO_DO;
if (rect.width == extents->bounded.width &&
rect.height == extents->bounded.height)
return CAIRO_INT_STATUS_SUCCESS;
if (extents->is_bounded == (CAIRO_OPERATOR_BOUND_BY_MASK | CAIRO_OPERATOR_BOUND_BY_SOURCE)) {
extents->unbounded = extents->bounded;
} else if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK) {
if (!_cairo_rectangle_intersect (&extents->unbounded, &extents->mask))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
clip = extents->clip;
extents->clip = _cairo_clip_reduce_for_composite (clip, extents);
if (clip != extents->clip)
_cairo_clip_destroy (clip);
if (_cairo_clip_is_all_clipped (extents->clip))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
if (! _cairo_rectangle_intersect (&extents->unbounded,
_cairo_clip_get_extents (extents->clip)))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
if (extents->source_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID)
_cairo_pattern_sampled_area (&extents->source_pattern.base,
&extents->bounded,
&extents->source_sample_area);
if (extents->mask_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID) {
_cairo_pattern_sampled_area (&extents->mask_pattern.base,
&extents->bounded,
&extents->mask_sample_area);
if (extents->mask_sample_area.width == 0 ||
extents->mask_sample_area.height == 0)
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
return CAIRO_INT_STATUS_SUCCESS;
}
cairo_int_status_t
_cairo_composite_rectangles_intersect_mask_extents (cairo_composite_rectangles_t *extents,
const cairo_box_t *box)
{
cairo_rectangle_int_t mask;
cairo_clip_t *clip;
_cairo_box_round_to_rectangle (box, &mask);
if (mask.x == extents->mask.x &&
mask.y == extents->mask.y &&
mask.width == extents->mask.width &&
mask.height == extents->mask.height)
{
return CAIRO_INT_STATUS_SUCCESS;
}
_cairo_rectangle_intersect (&extents->mask, &mask);
mask = extents->bounded;
if (! _cairo_rectangle_intersect (&extents->bounded, &extents->mask) &&
extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
return CAIRO_INT_STATUS_NOTHING_TO_DO;
if (mask.width == extents->bounded.width &&
mask.height == extents->bounded.height)
return CAIRO_INT_STATUS_SUCCESS;
if (extents->is_bounded == (CAIRO_OPERATOR_BOUND_BY_MASK | CAIRO_OPERATOR_BOUND_BY_SOURCE)) {
extents->unbounded = extents->bounded;
} else if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK) {
if (!_cairo_rectangle_intersect (&extents->unbounded, &extents->mask))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
clip = extents->clip;
extents->clip = _cairo_clip_reduce_for_composite (clip, extents);
if (clip != extents->clip)
_cairo_clip_destroy (clip);
if (_cairo_clip_is_all_clipped (extents->clip))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
if (! _cairo_rectangle_intersect (&extents->unbounded,
_cairo_clip_get_extents (extents->clip)))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
if (extents->source_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID)
_cairo_pattern_sampled_area (&extents->source_pattern.base,
&extents->bounded,
&extents->source_sample_area);
if (extents->mask_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID) {
_cairo_pattern_sampled_area (&extents->mask_pattern.base,
&extents->bounded,
&extents->mask_sample_area);
if (extents->mask_sample_area.width == 0 ||
extents->mask_sample_area.height == 0)
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
return CAIRO_INT_STATUS_SUCCESS;
}
cairo_int_status_t
_cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
cairo_clip_t *clip)
const cairo_clip_t *clip)
{
if (! _cairo_composite_rectangles_init (extents,
surface_extents,
op, source, clip))
surface, op, source, clip))
{
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
_cairo_pattern_get_extents (mask, &extents->mask);
extents->original_mask_pattern = mask;
_cairo_composite_reduce_pattern (mask, &extents->mask_pattern);
_cairo_pattern_get_extents (&extents->mask_pattern.base, &extents->mask, surface->is_vector);
return _cairo_composite_rectangles_intersect (extents);
return _cairo_composite_rectangles_intersect (extents, clip);
}
cairo_int_status_t
_cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_path_fixed_t *path,
const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
cairo_clip_t *clip)
const cairo_clip_t *clip)
{
if (! _cairo_composite_rectangles_init (extents,
surface_extents,
op, source, clip))
surface, op, source, clip))
{
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
_cairo_path_fixed_approximate_stroke_extents (path, style, ctm, &extents->mask);
_cairo_path_fixed_approximate_stroke_extents (path, style, ctm, surface->is_vector, &extents->mask);
return _cairo_composite_rectangles_intersect (extents);
return _cairo_composite_rectangles_intersect (extents, clip);
}
cairo_int_status_t
_cairo_composite_rectangles_init_for_fill (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_clip_t *clip)
const cairo_path_fixed_t *path,
const cairo_clip_t *clip)
{
if (! _cairo_composite_rectangles_init (extents,
surface_extents,
op, source, clip))
surface, op, source, clip))
{
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
_cairo_path_fixed_approximate_fill_extents (path, &extents->mask);
return _cairo_composite_rectangles_intersect (extents);
return _cairo_composite_rectangles_intersect (extents, clip);
}
cairo_int_status_t
_cairo_composite_rectangles_init_for_polygon (cairo_composite_rectangles_t *extents,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_polygon_t *polygon,
const cairo_clip_t *clip)
{
if (! _cairo_composite_rectangles_init (extents,
surface, op, source, clip))
{
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
_cairo_box_round_to_rectangle (&polygon->extents, &extents->mask);
return _cairo_composite_rectangles_intersect (extents, clip);
}
cairo_int_status_t
_cairo_composite_rectangles_init_for_boxes (cairo_composite_rectangles_t *extents,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_boxes_t *boxes,
const cairo_clip_t *clip)
{
cairo_box_t box;
if (! _cairo_composite_rectangles_init (extents,
surface, op, source, clip))
{
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
_cairo_boxes_extents (boxes, &box);
_cairo_box_round_to_rectangle (&box, &extents->mask);
return _cairo_composite_rectangles_intersect (extents, clip);
}
cairo_int_status_t
_cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *extents,
const cairo_rectangle_int_t *surface_extents,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_clip_t *clip,
const cairo_clip_t *clip,
cairo_bool_t *overlap)
{
cairo_status_t status;
if (! _cairo_composite_rectangles_init (extents,
surface_extents,
op, source, clip))
{
if (! _cairo_composite_rectangles_init (extents, surface, op, source, clip))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
/* Computing the exact bbox and the overlap is expensive.
* First perform a cheap test to see if the glyphs are all clipped out.
*/
if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK &&
_cairo_scaled_font_glyph_approximate_extents (scaled_font,
glyphs, num_glyphs,
&extents->mask))
{
if (! _cairo_rectangle_intersect (&extents->bounded, &extents->mask))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
@ -191,5 +450,50 @@ _cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *exten
if (unlikely (status))
return status;
return _cairo_composite_rectangles_intersect (extents);
if (overlap && *overlap &&
scaled_font->options.antialias == CAIRO_ANTIALIAS_NONE &&
_cairo_pattern_is_opaque_solid (&extents->source_pattern.base))
{
*overlap = FALSE;
}
return _cairo_composite_rectangles_intersect (extents, clip);
}
cairo_bool_t
_cairo_composite_rectangles_can_reduce_clip (cairo_composite_rectangles_t *composite,
cairo_clip_t *clip)
{
cairo_rectangle_int_t extents;
cairo_box_t box;
if (clip == NULL)
return TRUE;
extents = composite->destination;
if (composite->is_bounded & CAIRO_OPERATOR_BOUND_BY_SOURCE)
_cairo_rectangle_intersect (&extents, &composite->source);
if (composite->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
_cairo_rectangle_intersect (&extents, &composite->mask);
_cairo_box_from_rectangle (&box, &extents);
return _cairo_clip_contains_box (clip, &box);
}
cairo_int_status_t
_cairo_composite_rectangles_add_to_damage (cairo_composite_rectangles_t *composite,
cairo_boxes_t *damage)
{
cairo_int_status_t status;
int n;
for (n = 0; n < composite->clip->num_boxes; n++) {
status = _cairo_boxes_add (damage,
CAIRO_ANTIALIAS_NONE,
&composite->clip->boxes[n]);
if (unlikely (status))
return status;
}
return CAIRO_INT_STATUS_SUCCESS;
}

Просмотреть файл

@ -0,0 +1,365 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2011 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#ifndef CAIRO_COMPOSITOR_PRIVATE_H
#define CAIRO_COMPOSITOR_PRIVATE_H
#include "cairo-composite-rectangles-private.h"
CAIRO_BEGIN_DECLS
typedef struct {
cairo_scaled_font_t *font;
cairo_glyph_t *glyphs;
int num_glyphs;
cairo_bool_t use_mask;
cairo_rectangle_int_t extents;
} cairo_composite_glyphs_info_t;
struct cairo_compositor {
const cairo_compositor_t *delegate;
cairo_warn cairo_int_status_t
(*paint) (const cairo_compositor_t *compositor,
cairo_composite_rectangles_t *extents);
cairo_warn cairo_int_status_t
(*mask) (const cairo_compositor_t *compositor,
cairo_composite_rectangles_t *extents);
cairo_warn cairo_int_status_t
(*stroke) (const cairo_compositor_t *compositor,
cairo_composite_rectangles_t *extents,
const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias);
cairo_warn cairo_int_status_t
(*fill) (const cairo_compositor_t *compositor,
cairo_composite_rectangles_t *extents,
const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias);
cairo_warn cairo_int_status_t
(*glyphs) (const cairo_compositor_t *compositor,
cairo_composite_rectangles_t *extents,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_bool_t overlap);
};
struct cairo_mask_compositor {
cairo_compositor_t base;
cairo_int_status_t (*acquire) (void *surface);
cairo_int_status_t (*release) (void *surface);
cairo_int_status_t (*set_clip_region) (void *surface,
cairo_region_t *clip_region);
cairo_surface_t * (*pattern_to_surface) (cairo_surface_t *dst,
const cairo_pattern_t *pattern,
cairo_bool_t is_mask,
const cairo_rectangle_int_t *extents,
const cairo_rectangle_int_t *sample,
int *src_x, int *src_y);
cairo_int_status_t (*draw_image_boxes) (void *surface,
cairo_image_surface_t *image,
cairo_boxes_t *boxes,
int dx, int dy);
cairo_int_status_t (*copy_boxes) (void *surface,
cairo_surface_t *src,
cairo_boxes_t *boxes,
const cairo_rectangle_int_t *extents,
int dx, int dy);
cairo_int_status_t
(*fill_rectangles) (void *surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_int_t *rectangles,
int num_rects);
cairo_int_status_t
(*fill_boxes) (void *surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_boxes_t *boxes);
cairo_int_status_t
(*check_composite) (const cairo_composite_rectangles_t *extents);
cairo_int_status_t
(*composite) (void *dst,
cairo_operator_t op,
cairo_surface_t *src,
cairo_surface_t *mask,
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_int_status_t
(*composite_boxes) (void *surface,
cairo_operator_t op,
cairo_surface_t *source,
cairo_surface_t *mask,
int src_x,
int src_y,
int mask_x,
int mask_y,
int dst_x,
int dst_y,
cairo_boxes_t *boxes,
const cairo_rectangle_int_t *extents);
cairo_int_status_t
(*check_composite_glyphs) (const cairo_composite_rectangles_t *extents,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int *num_glyphs);
cairo_int_status_t
(*composite_glyphs) (void *surface,
cairo_operator_t op,
cairo_surface_t *src,
int src_x,
int src_y,
int dst_x,
int dst_y,
cairo_composite_glyphs_info_t *info);
};
struct cairo_traps_compositor {
cairo_compositor_t base;
cairo_int_status_t
(*acquire) (void *surface);
cairo_int_status_t
(*release) (void *surface);
cairo_int_status_t
(*set_clip_region) (void *surface,
cairo_region_t *clip_region);
cairo_surface_t *
(*pattern_to_surface) (cairo_surface_t *dst,
const cairo_pattern_t *pattern,
cairo_bool_t is_mask,
const cairo_rectangle_int_t *extents,
const cairo_rectangle_int_t *sample,
int *src_x, int *src_y);
cairo_int_status_t (*draw_image_boxes) (void *surface,
cairo_image_surface_t *image,
cairo_boxes_t *boxes,
int dx, int dy);
cairo_int_status_t (*copy_boxes) (void *surface,
cairo_surface_t *src,
cairo_boxes_t *boxes,
const cairo_rectangle_int_t *extents,
int dx, int dy);
cairo_int_status_t
(*fill_boxes) (void *surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_boxes_t *boxes);
cairo_int_status_t
(*check_composite) (const cairo_composite_rectangles_t *extents);
cairo_int_status_t
(*composite) (void *dst,
cairo_operator_t op,
cairo_surface_t *src,
cairo_surface_t *mask,
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_int_status_t
(*lerp) (void *_dst,
cairo_surface_t *abstract_src,
cairo_surface_t *abstract_mask,
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_int_status_t
(*composite_boxes) (void *surface,
cairo_operator_t op,
cairo_surface_t *source,
cairo_surface_t *mask,
int src_x,
int src_y,
int mask_x,
int mask_y,
int dst_x,
int dst_y,
cairo_boxes_t *boxes,
const cairo_rectangle_int_t *extents);
cairo_int_status_t
(*composite_traps) (void *dst,
cairo_operator_t op,
cairo_surface_t *source,
int src_x,
int src_y,
int dst_x,
int dst_y,
const cairo_rectangle_int_t *extents,
cairo_antialias_t antialias,
cairo_traps_t *traps);
cairo_int_status_t
(*composite_tristrip) (void *dst,
cairo_operator_t op,
cairo_surface_t *source,
int src_x,
int src_y,
int dst_x,
int dst_y,
const cairo_rectangle_int_t *extents,
cairo_antialias_t antialias,
cairo_tristrip_t *tristrip);
cairo_int_status_t
(*check_composite_glyphs) (const cairo_composite_rectangles_t *extents,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int *num_glyphs);
cairo_int_status_t
(*composite_glyphs) (void *surface,
cairo_operator_t op,
cairo_surface_t *src,
int src_x,
int src_y,
int dst_x,
int dst_y,
cairo_composite_glyphs_info_t *info);
};
cairo_private extern const cairo_compositor_t __cairo_no_compositor;
cairo_private extern const cairo_compositor_t _cairo_fallback_compositor;
cairo_private void
_cairo_mask_compositor_init (cairo_mask_compositor_t *compositor,
const cairo_compositor_t *delegate);
cairo_private void
_cairo_shape_mask_compositor_init (cairo_compositor_t *compositor,
const cairo_compositor_t *delegate);
cairo_private void
_cairo_traps_compositor_init (cairo_traps_compositor_t *compositor,
const cairo_compositor_t *delegate);
cairo_private cairo_int_status_t
_cairo_compositor_paint (const cairo_compositor_t *compositor,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_compositor_mask (const cairo_compositor_t *compositor,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_compositor_stroke (const cairo_compositor_t *compositor,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_compositor_fill (const cairo_compositor_t *compositor,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_compositor_glyphs (const cairo_compositor_t *compositor,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
const cairo_clip_t *clip);
CAIRO_END_DECLS
#endif /* CAIRO_COMPOSITOR_PRIVATE_H */

Просмотреть файл

@ -0,0 +1,268 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2011 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-compositor-private.h"
#include "cairo-damage-private.h"
#include "cairo-error-private.h"
cairo_int_status_t
_cairo_compositor_paint (const cairo_compositor_t *compositor,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_clip_t *clip)
{
cairo_composite_rectangles_t extents;
cairo_int_status_t status;
TRACE ((stderr, "%s\n", __FUNCTION__));
status = _cairo_composite_rectangles_init_for_paint (&extents, surface,
op, source,
clip);
if (unlikely (status))
return status;
do {
while (compositor->paint == NULL)
compositor = compositor->delegate;
status = compositor->paint (compositor, &extents);
compositor = compositor->delegate;
} while (status == CAIRO_INT_STATUS_UNSUPPORTED);
if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
__FUNCTION__,
extents.unbounded.x, extents.unbounded.y,
extents.unbounded.width, extents.unbounded.height));
surface->damage = _cairo_damage_add_rectangle (surface->damage,
&extents.unbounded);
}
_cairo_composite_rectangles_fini (&extents);
return status;
}
cairo_int_status_t
_cairo_compositor_mask (const cairo_compositor_t *compositor,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
const cairo_clip_t *clip)
{
cairo_composite_rectangles_t extents;
cairo_int_status_t status;
TRACE ((stderr, "%s\n", __FUNCTION__));
status = _cairo_composite_rectangles_init_for_mask (&extents, surface,
op, source, mask,
clip);
if (unlikely (status))
return status;
do {
while (compositor->mask == NULL)
compositor = compositor->delegate;
status = compositor->mask (compositor, &extents);
compositor = compositor->delegate;
} while (status == CAIRO_INT_STATUS_UNSUPPORTED);
if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
__FUNCTION__,
extents.unbounded.x, extents.unbounded.y,
extents.unbounded.width, extents.unbounded.height));
surface->damage = _cairo_damage_add_rectangle (surface->damage,
&extents.unbounded);
}
_cairo_composite_rectangles_fini (&extents);
return status;
}
cairo_int_status_t
_cairo_compositor_stroke (const cairo_compositor_t *compositor,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
const cairo_clip_t *clip)
{
cairo_composite_rectangles_t extents;
cairo_int_status_t status;
TRACE ((stderr, "%s\n", __FUNCTION__));
if (_cairo_pen_vertices_needed (tolerance, style->line_width/2, ctm) <= 1)
return CAIRO_INT_STATUS_NOTHING_TO_DO;
status = _cairo_composite_rectangles_init_for_stroke (&extents, surface,
op, source,
path, style, ctm,
clip);
if (unlikely (status))
return status;
do {
while (compositor->stroke == NULL)
compositor = compositor->delegate;
status = compositor->stroke (compositor, &extents,
path, style, ctm, ctm_inverse,
tolerance, antialias);
compositor = compositor->delegate;
} while (status == CAIRO_INT_STATUS_UNSUPPORTED);
if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
__FUNCTION__,
extents.unbounded.x, extents.unbounded.y,
extents.unbounded.width, extents.unbounded.height));
surface->damage = _cairo_damage_add_rectangle (surface->damage,
&extents.unbounded);
}
_cairo_composite_rectangles_fini (&extents);
return status;
}
cairo_int_status_t
_cairo_compositor_fill (const cairo_compositor_t *compositor,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
const cairo_clip_t *clip)
{
cairo_composite_rectangles_t extents;
cairo_int_status_t status;
TRACE ((stderr, "%s\n", __FUNCTION__));
status = _cairo_composite_rectangles_init_for_fill (&extents, surface,
op, source, path,
clip);
if (unlikely (status))
return status;
do {
while (compositor->fill == NULL)
compositor = compositor->delegate;
status = compositor->fill (compositor, &extents,
path, fill_rule, tolerance, antialias);
compositor = compositor->delegate;
} while (status == CAIRO_INT_STATUS_UNSUPPORTED);
if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
__FUNCTION__,
extents.unbounded.x, extents.unbounded.y,
extents.unbounded.width, extents.unbounded.height));
surface->damage = _cairo_damage_add_rectangle (surface->damage,
&extents.unbounded);
}
_cairo_composite_rectangles_fini (&extents);
return status;
}
cairo_int_status_t
_cairo_compositor_glyphs (const cairo_compositor_t *compositor,
cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
const cairo_clip_t *clip)
{
cairo_composite_rectangles_t extents;
cairo_bool_t overlap;
cairo_int_status_t status;
TRACE ((stderr, "%s\n", __FUNCTION__));
status = _cairo_composite_rectangles_init_for_glyphs (&extents, surface,
op, source,
scaled_font,
glyphs, num_glyphs,
clip, &overlap);
if (unlikely (status))
return status;
do {
while (compositor->glyphs == NULL)
compositor = compositor->delegate;
status = compositor->glyphs (compositor, &extents,
scaled_font, glyphs, num_glyphs, overlap);
compositor = compositor->delegate;
} while (status == CAIRO_INT_STATUS_UNSUPPORTED);
if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
__FUNCTION__,
extents.unbounded.x, extents.unbounded.y,
extents.unbounded.width, extents.unbounded.height));
surface->damage = _cairo_damage_add_rectangle (surface->damage,
&extents.unbounded);
}
_cairo_composite_rectangles_fini (&extents);
return status;
}

Просмотреть файл

@ -0,0 +1,80 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2011 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Intel Corporation
*
* Contributor(s):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#ifndef CAIRO_CONTOUR_INLINE_H
#define CAIRO_CONTOUR_INLINE_H
#include "cairo-contour-private.h"
CAIRO_BEGIN_DECLS
static inline cairo_int_status_t
_cairo_contour_add_point (cairo_contour_t *contour,
const cairo_point_t *point)
{
struct _cairo_contour_chain *tail = contour->tail;
if (unlikely (tail->num_points == tail->size_points))
return __cairo_contour_add_point (contour, point);
tail->points[tail->num_points++] = *point;
return CAIRO_INT_STATUS_SUCCESS;
}
static inline cairo_point_t *
_cairo_contour_first_point (cairo_contour_t *c)
{
return &c->chain.points[0];
}
static inline cairo_point_t *
_cairo_contour_last_point (cairo_contour_t *c)
{
return &c->tail->points[c->tail->num_points-1];
}
static inline void
_cairo_contour_remove_last_point (cairo_contour_t *contour)
{
if (contour->chain.num_points == 0)
return;
if (--contour->tail->num_points == 0)
__cairo_contour_remove_last_chain (contour);
}
CAIRO_END_DECLS
#endif /* CAIRO_CONTOUR_INLINE_H */

Просмотреть файл

@ -0,0 +1,124 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2011 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Intel Corporation
*
* Contributor(s):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#ifndef CAIRO_CONTOUR_PRIVATE_H
#define CAIRO_CONTOUR_PRIVATE_H
#include "cairo-types-private.h"
#include "cairo-compiler-private.h"
#include "cairo-error-private.h"
#include "cairo-list-private.h"
#include <stdio.h>
CAIRO_BEGIN_DECLS
/* A contour is simply a closed chain of points that divide the infinite plane
* into inside and outside. Each contour is a simple polygon, that is it
* contains no holes or self-intersections, but maybe either concave or convex.
*/
struct _cairo_contour_chain {
cairo_point_t *points;
int num_points, size_points;
struct _cairo_contour_chain *next;
};
struct _cairo_contour_iter {
cairo_point_t *point;
cairo_contour_chain_t *chain;
};
struct _cairo_contour {
cairo_list_t next;
int direction;
cairo_contour_chain_t chain, *tail;
cairo_point_t embedded_points[64];
};
/* Initial definition of a shape is a set of contours (some representing holes) */
struct _cairo_shape {
cairo_list_t contours;
};
typedef struct _cairo_shape cairo_shape_t;
#if 0
cairo_private cairo_status_t
_cairo_shape_init_from_polygon (cairo_shape_t *shape,
const cairo_polygon_t *polygon);
cairo_private cairo_status_t
_cairo_shape_reduce (cairo_shape_t *shape, double tolerance);
#endif
cairo_private void
_cairo_contour_init (cairo_contour_t *contour,
int direction);
cairo_private cairo_int_status_t
__cairo_contour_add_point (cairo_contour_t *contour,
const cairo_point_t *point);
cairo_private void
_cairo_contour_simplify (cairo_contour_t *contour, double tolerance);
cairo_private void
_cairo_contour_reverse (cairo_contour_t *contour);
cairo_private cairo_int_status_t
_cairo_contour_add (cairo_contour_t *dst,
const cairo_contour_t *src);
cairo_private cairo_int_status_t
_cairo_contour_add_reversed (cairo_contour_t *dst,
const cairo_contour_t *src);
cairo_private void
__cairo_contour_remove_last_chain (cairo_contour_t *contour);
cairo_private void
_cairo_contour_reset (cairo_contour_t *contour);
cairo_private void
_cairo_contour_fini (cairo_contour_t *contour);
cairo_private void
_cairo_debug_print_contour (FILE *file, cairo_contour_t *contour);
CAIRO_END_DECLS
#endif /* CAIRO_CONTOUR_PRIVATE_H */

Просмотреть файл

@ -0,0 +1,453 @@
/*
* Copyright © 2004 Carl Worth
* Copyright © 2006 Red Hat, Inc.
* Copyright © 2008 Chris Wilson
* Copyright © 2011 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Carl Worth
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-error-private.h"
#include "cairo-freelist-private.h"
#include "cairo-combsort-inline.h"
#include "cairo-contour-inline.h"
#include "cairo-contour-private.h"
void
_cairo_contour_init (cairo_contour_t *contour,
int direction)
{
contour->direction = direction;
contour->chain.points = contour->embedded_points;
contour->chain.next = NULL;
contour->chain.num_points = 0;
contour->chain.size_points = ARRAY_LENGTH (contour->embedded_points);
contour->tail = &contour->chain;
}
cairo_int_status_t
__cairo_contour_add_point (cairo_contour_t *contour,
const cairo_point_t *point)
{
cairo_contour_chain_t *tail = contour->tail;
cairo_contour_chain_t *next;
assert (tail->next == NULL);
next = _cairo_malloc_ab_plus_c (tail->size_points*2,
sizeof (cairo_point_t),
sizeof (cairo_contour_chain_t));
if (unlikely (next == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
next->size_points = tail->size_points*2;
next->num_points = 1;
next->points = (cairo_point_t *)(next+1);
next->next = NULL;
tail->next = next;
contour->tail = next;
next->points[0] = *point;
return CAIRO_INT_STATUS_SUCCESS;
}
static void
first_inc (cairo_contour_t *contour,
cairo_point_t **p,
cairo_contour_chain_t **chain)
{
if (*p == (*chain)->points + (*chain)->num_points) {
assert ((*chain)->next);
*chain = (*chain)->next;
*p = &(*chain)->points[0];
} else
++*p;
}
static void
last_dec (cairo_contour_t *contour,
cairo_point_t **p,
cairo_contour_chain_t **chain)
{
if (*p == (*chain)->points) {
cairo_contour_chain_t *prev;
assert (*chain != &contour->chain);
for (prev = &contour->chain; prev->next != *chain; prev = prev->next)
;
*chain = prev;
*p = &(*chain)->points[(*chain)->num_points-1];
} else
--*p;
}
void
_cairo_contour_reverse (cairo_contour_t *contour)
{
cairo_contour_chain_t *first_chain, *last_chain;
cairo_point_t *first, *last;
contour->direction = -contour->direction;
if (contour->chain.num_points <= 1)
return;
first_chain = &contour->chain;
last_chain = contour->tail;
first = &first_chain->points[0];
last = &last_chain->points[last_chain->num_points-1];
while (first != last) {
cairo_point_t p;
p = *first;
*first = *last;
*last = p;
first_inc (contour, &first, &first_chain);
last_dec (contour, &last, &last_chain);
}
}
cairo_int_status_t
_cairo_contour_add (cairo_contour_t *dst,
const cairo_contour_t *src)
{
const cairo_contour_chain_t *chain;
cairo_int_status_t status;
int i;
for (chain = &src->chain; chain; chain = chain->next) {
for (i = 0; i < chain->num_points; i++) {
status = _cairo_contour_add_point (dst, &chain->points[i]);
if (unlikely (status))
return status;
}
}
return CAIRO_INT_STATUS_SUCCESS;
}
static inline cairo_bool_t
iter_next (cairo_contour_iter_t *iter)
{
if (iter->point == &iter->chain->points[iter->chain->size_points-1]) {
iter->chain = iter->chain->next;
if (iter->chain == NULL)
return FALSE;
iter->point = &iter->chain->points[0];
return TRUE;
} else {
iter->point++;
return TRUE;
}
}
static cairo_bool_t
iter_equal (const cairo_contour_iter_t *i1,
const cairo_contour_iter_t *i2)
{
return i1->chain == i2->chain && i1->point == i2->point;
}
static void
iter_init (cairo_contour_iter_t *iter, cairo_contour_t *contour)
{
iter->chain = &contour->chain;
iter->point = &contour->chain.points[0];
}
static void
iter_init_last (cairo_contour_iter_t *iter, cairo_contour_t *contour)
{
iter->chain = contour->tail;
iter->point = &contour->tail->points[contour->tail->num_points-1];
}
static const cairo_contour_chain_t *prev_const_chain(const cairo_contour_t *contour,
const cairo_contour_chain_t *chain)
{
const cairo_contour_chain_t *prev;
if (chain == &contour->chain)
return NULL;
for (prev = &contour->chain; prev->next != chain; prev = prev->next)
;
return prev;
}
cairo_int_status_t
_cairo_contour_add_reversed (cairo_contour_t *dst,
const cairo_contour_t *src)
{
const cairo_contour_chain_t *last;
cairo_int_status_t status;
int i;
if (src->chain.num_points == 0)
return CAIRO_INT_STATUS_SUCCESS;
for (last = src->tail; last; last = prev_const_chain (src, last)) {
for (i = last->num_points-1; i >= 0; i--) {
status = _cairo_contour_add_point (dst, &last->points[i]);
if (unlikely (status))
return status;
}
}
return CAIRO_INT_STATUS_SUCCESS;
}
static cairo_uint64_t
point_distance_sq (const cairo_point_t *p1,
const cairo_point_t *p2)
{
int32_t dx = p1->x - p2->x;
int32_t dy = p1->y - p2->y;
return _cairo_int32x32_64_mul (dx, dx) + _cairo_int32x32_64_mul (dy, dy);
}
#define DELETED(p) ((p)->x == INT_MIN && (p)->y == INT_MAX)
#define MARK_DELETED(p) ((p)->x = INT_MIN, (p)->y = INT_MAX)
static cairo_bool_t
_cairo_contour_simplify_chain (cairo_contour_t *contour, const double tolerance,
const cairo_contour_iter_t *first,
const cairo_contour_iter_t *last)
{
cairo_contour_iter_t iter, furthest;
uint64_t max_error;
int x0, y0;
int nx, ny;
int count;
iter = *first;
iter_next (&iter);
if (iter_equal (&iter, last))
return FALSE;
x0 = first->point->x;
y0 = first->point->y;
nx = last->point->y - y0;
ny = x0 - last->point->x;
count = 0;
max_error = 0;
do {
cairo_point_t *p = iter.point;
if (! DELETED(p)) {
uint64_t d = (uint64_t)nx * (x0 - p->x) + (uint64_t)ny * (y0 - p->y);
if (d * d > max_error) {
max_error = d * d;
furthest = iter;
}
count++;
}
iter_next (&iter);
} while (! iter_equal (&iter, last));
if (count == 0)
return FALSE;
if (max_error > tolerance * ((uint64_t)nx * nx + (uint64_t)ny * ny)) {
cairo_bool_t simplified;
simplified = FALSE;
simplified |= _cairo_contour_simplify_chain (contour, tolerance,
first, &furthest);
simplified |= _cairo_contour_simplify_chain (contour, tolerance,
&furthest, last);
return simplified;
} else {
iter = *first;
iter_next (&iter);
do {
MARK_DELETED (iter.point);
iter_next (&iter);
} while (! iter_equal (&iter, last));
return TRUE;
}
}
void
_cairo_contour_simplify (cairo_contour_t *contour, double tolerance)
{
cairo_contour_chain_t *chain;
cairo_point_t *last = NULL;
cairo_contour_iter_t iter, furthest;
cairo_bool_t simplified;
uint64_t max = 0;
int i;
if (contour->chain.num_points <= 2)
return;
tolerance = tolerance * CAIRO_FIXED_ONE;
tolerance *= tolerance;
/* stage 1: vertex reduction */
for (chain = &contour->chain; chain; chain = chain->next) {
for (i = 0; i < chain->num_points; i++) {
if (last == NULL ||
point_distance_sq (last, &chain->points[i]) > tolerance) {
last = &chain->points[i];
} else {
MARK_DELETED (&chain->points[i]);
}
}
}
/* stage2: polygon simplification using Douglas-Peucker */
do {
last = &contour->chain.points[0];
iter_init (&furthest, contour);
max = 0;
for (chain = &contour->chain; chain; chain = chain->next) {
for (i = 0; i < chain->num_points; i++) {
uint64_t d;
if (DELETED (&chain->points[i]))
continue;
d = point_distance_sq (last, &chain->points[i]);
if (d > max) {
furthest.chain = chain;
furthest.point = &chain->points[i];
max = d;
}
}
}
assert (max);
simplified = FALSE;
iter_init (&iter, contour);
simplified |= _cairo_contour_simplify_chain (contour, tolerance,
&iter, &furthest);
iter_init_last (&iter, contour);
if (! iter_equal (&furthest, &iter))
simplified |= _cairo_contour_simplify_chain (contour, tolerance,
&furthest, &iter);
} while (simplified);
iter_init (&iter, contour);
for (chain = &contour->chain; chain; chain = chain->next) {
int num_points = chain->num_points;
chain->num_points = 0;
for (i = 0; i < num_points; i++) {
if (! DELETED(&chain->points[i])) {
if (iter.point != &chain->points[i])
*iter.point = chain->points[i];
iter.chain->num_points++;
iter_next (&iter);
}
}
}
if (iter.chain) {
cairo_contour_chain_t *next;
for (chain = iter.chain->next; chain; chain = next) {
next = chain->next;
free (chain);
}
iter.chain->next = NULL;
contour->tail = iter.chain;
}
}
void
_cairo_contour_reset (cairo_contour_t *contour)
{
_cairo_contour_fini (contour);
_cairo_contour_init (contour, contour->direction);
}
void
_cairo_contour_fini (cairo_contour_t *contour)
{
cairo_contour_chain_t *chain, *next;
for (chain = contour->chain.next; chain; chain = next) {
next = chain->next;
free (chain);
}
}
void
_cairo_debug_print_contour (FILE *file, cairo_contour_t *contour)
{
cairo_contour_chain_t *chain;
int num_points, size_points;
int i;
num_points = 0;
size_points = 0;
for (chain = &contour->chain; chain; chain = chain->next) {
num_points += chain->num_points;
size_points += chain->size_points;
}
fprintf (file, "contour: direction=%d, num_points=%d / %d\n",
contour->direction, num_points, size_points);
num_points = 0;
for (chain = &contour->chain; chain; chain = chain->next) {
for (i = 0; i < chain->num_points; i++) {
fprintf (file, " [%d] = (%f, %f)\n",
num_points++,
_cairo_fixed_to_double (chain->points[i].x),
_cairo_fixed_to_double (chain->points[i].y));
}
}
}
void
__cairo_contour_remove_last_chain (cairo_contour_t *contour)
{
cairo_contour_chain_t *chain;
if (contour->tail == &contour->chain)
return;
for (chain = &contour->chain; chain->next != contour->tail; chain = chain->next)
;
free (contour->tail);
contour->tail = chain;
chain->next = NULL;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,85 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2012 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Chris Wilson
*
* Contributor(s):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#ifndef CAIRO_DAMAGE_PRIVATE_H
#define CAIRO_DAMAGE_PRIVATE_H
#include "cairo-types-private.h"
#include <pixman.h>
CAIRO_BEGIN_DECLS
struct _cairo_damage {
cairo_status_t status;
cairo_region_t *region;
int dirty, remain;
struct _cairo_damage_chunk {
struct _cairo_damage_chunk *next;
cairo_box_t *base;
int count;
int size;
} chunks, *tail;
cairo_box_t boxes[32];
};
cairo_private cairo_damage_t *
_cairo_damage_create (void);
cairo_private cairo_damage_t *
_cairo_damage_create_in_error (cairo_status_t status);
cairo_private cairo_damage_t *
_cairo_damage_add_box (cairo_damage_t *damage,
const cairo_box_t *box);
cairo_private cairo_damage_t *
_cairo_damage_add_rectangle (cairo_damage_t *damage,
const cairo_rectangle_int_t *rect);
cairo_private cairo_damage_t *
_cairo_damage_add_region (cairo_damage_t *damage,
const cairo_region_t *region);
cairo_private cairo_damage_t *
_cairo_damage_reduce (cairo_damage_t *damage);
cairo_private void
_cairo_damage_destroy (cairo_damage_t *damage);
CAIRO_END_DECLS
#endif /* CAIRO_DAMAGE_PRIVATE_H */

Просмотреть файл

@ -0,0 +1,241 @@
/*
* Copyright © 2012 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Chris Wilson
*
* Contributor(s):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-damage-private.h"
#include "cairo-region-private.h"
static const cairo_damage_t __cairo_damage__nil = { CAIRO_STATUS_NO_MEMORY };
cairo_damage_t *
_cairo_damage_create_in_error (cairo_status_t status)
{
_cairo_error_throw (status);
return (cairo_damage_t *) &__cairo_damage__nil;
}
cairo_damage_t *
_cairo_damage_create (void)
{
cairo_damage_t *damage;
damage = _cairo_malloc (sizeof (*damage));
if (unlikely (damage == NULL)) {
_cairo_error_throw(CAIRO_STATUS_NO_MEMORY);
return (cairo_damage_t *) &__cairo_damage__nil;
}
damage->status = CAIRO_STATUS_SUCCESS;
damage->region = NULL;
damage->dirty = 0;
damage->tail = &damage->chunks;
damage->chunks.base = damage->boxes;
damage->chunks.size = ARRAY_LENGTH(damage->boxes);
damage->chunks.count = 0;
damage->chunks.next = NULL;
damage->remain = damage->chunks.size;
return damage;
}
void
_cairo_damage_destroy (cairo_damage_t *damage)
{
struct _cairo_damage_chunk *chunk, *next;
if (damage == (cairo_damage_t *) &__cairo_damage__nil)
return;
for (chunk = damage->chunks.next; chunk != NULL; chunk = next) {
next = chunk->next;
free (chunk);
}
cairo_region_destroy (damage->region);
free (damage);
}
static cairo_damage_t *
_cairo_damage_add_boxes(cairo_damage_t *damage,
const cairo_box_t *boxes,
int count)
{
struct _cairo_damage_chunk *chunk;
int n, size;
TRACE ((stderr, "%s x%d\n", __FUNCTION__, count));
if (damage == NULL)
damage = _cairo_damage_create ();
if (damage->status)
return damage;
damage->dirty += count;
n = count;
if (n > damage->remain)
n = damage->remain;
memcpy (damage->tail->base + damage->tail->count, boxes,
n * sizeof (cairo_box_t));
count -= n;
damage->tail->count += n;
damage->remain -= n;
if (count == 0)
return damage;
size = 2 * damage->tail->size;
if (size < count)
size = (count + 64) & ~63;
chunk = _cairo_malloc (sizeof (*chunk) + sizeof (cairo_box_t) * size);
if (unlikely (chunk == NULL)) {
_cairo_damage_destroy (damage);
return (cairo_damage_t *) &__cairo_damage__nil;
}
chunk->next = NULL;
chunk->base = (cairo_box_t *) (chunk + 1);
chunk->size = size;
chunk->count = count;
damage->tail->next = chunk;
damage->tail = chunk;
memcpy (damage->tail->base, boxes + n,
count * sizeof (cairo_box_t));
damage->remain = size - count;
return damage;
}
cairo_damage_t *
_cairo_damage_add_box(cairo_damage_t *damage,
const cairo_box_t *box)
{
TRACE ((stderr, "%s: (%d, %d),(%d, %d)\n", __FUNCTION__,
box->p1.x, box->p1.y, box->p2.x, box->p2.y));
return _cairo_damage_add_boxes(damage, box, 1);
}
cairo_damage_t *
_cairo_damage_add_rectangle(cairo_damage_t *damage,
const cairo_rectangle_int_t *r)
{
cairo_box_t box;
TRACE ((stderr, "%s: (%d, %d)x(%d, %d)\n", __FUNCTION__,
r->x, r->y, r->width, r->height));
box.p1.x = r->x;
box.p1.y = r->y;
box.p2.x = r->x + r->width;
box.p2.y = r->y + r->height;
return _cairo_damage_add_boxes(damage, &box, 1);
}
cairo_damage_t *
_cairo_damage_add_region (cairo_damage_t *damage,
const cairo_region_t *region)
{
cairo_box_t *boxes;
int nbox;
TRACE ((stderr, "%s\n", __FUNCTION__));
boxes = _cairo_region_get_boxes (region, &nbox);
return _cairo_damage_add_boxes(damage, boxes, nbox);
}
cairo_damage_t *
_cairo_damage_reduce (cairo_damage_t *damage)
{
cairo_box_t *free_boxes = NULL;
cairo_box_t *boxes, *b;
struct _cairo_damage_chunk *chunk, *last;
TRACE ((stderr, "%s: dirty=%d\n", __FUNCTION__,
damage ? damage->dirty : -1));
if (damage == NULL || damage->status || !damage->dirty)
return damage;
if (damage->region) {
cairo_region_t *region;
region = damage->region;
damage->region = NULL;
damage = _cairo_damage_add_region (damage, region);
cairo_region_destroy (region);
if (unlikely (damage->status))
return damage;
}
boxes = damage->tail->base;
if (damage->dirty > damage->tail->size) {
boxes = free_boxes = _cairo_malloc (damage->dirty * sizeof (cairo_box_t));
if (unlikely (boxes == NULL)) {
_cairo_damage_destroy (damage);
return (cairo_damage_t *) &__cairo_damage__nil;
}
b = boxes;
last = NULL;
} else {
b = boxes + damage->tail->count;
last = damage->tail;
}
for (chunk = &damage->chunks; chunk != last; chunk = chunk->next) {
memcpy (b, chunk->base, chunk->count * sizeof (cairo_box_t));
b += chunk->count;
}
damage->region = _cairo_region_create_from_boxes (boxes, damage->dirty);
free (free_boxes);
if (unlikely (damage->region->status)) {
_cairo_damage_destroy (damage);
return (cairo_damage_t *) &__cairo_damage__nil;
}
damage->dirty = 0;
return damage;
}

Просмотреть файл

@ -34,6 +34,7 @@
*/
#include "cairoint.h"
#include "cairo-image-surface-private.h"
/**
* cairo_debug_reset_static_data:
@ -55,6 +56,8 @@
* functions have been called as necessary). If there are active cairo
* objects, this call is likely to cause a crash, (eg. an assertion
* failure due to a hash table being destroyed when non-empty).
*
* Since: 1.0
**/
void
cairo_debug_reset_static_data (void)
@ -83,11 +86,13 @@ cairo_debug_reset_static_data (void)
_cairo_image_reset_static_data ();
_cairo_image_compositor_reset_static_data ();
#if CAIRO_HAS_DRM_SURFACE
_cairo_drm_device_reset_static_data ();
#endif
_cairo_reset_static_data ();
_cairo_default_context_reset_static_data ();
CAIRO_MUTEX_FINALIZE ();
}
@ -118,9 +123,16 @@ _cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface)
width = image->width*2;
break;
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_ARGB32:
width = image->width*4;
break;
case CAIRO_FORMAT_RGB96F:
width = image->width*12;
break;
case CAIRO_FORMAT_RGBA128F:
width = image->width*16;
break;
case CAIRO_FORMAT_INVALID:
default:
/* XXX compute width from pixman bpp */
@ -229,18 +241,19 @@ _print_close (void *closure)
}
void
_cairo_debug_print_path (FILE *stream, cairo_path_fixed_t *path)
_cairo_debug_print_path (FILE *stream, const cairo_path_fixed_t *path)
{
cairo_status_t status;
cairo_box_t box;
printf ("path: extents=(%f, %f), (%f, %f)\n",
fprintf (stream,
"path: extents=(%f, %f), (%f, %f)\n",
_cairo_fixed_to_double (path->extents.p1.x),
_cairo_fixed_to_double (path->extents.p1.y),
_cairo_fixed_to_double (path->extents.p2.x),
_cairo_fixed_to_double (path->extents.p2.y));
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_print_move_to,
_print_line_to,
_print_curve_to,
@ -248,5 +261,65 @@ _cairo_debug_print_path (FILE *stream, cairo_path_fixed_t *path)
stream);
assert (status == CAIRO_STATUS_SUCCESS);
printf ("\n");
if (_cairo_path_fixed_is_box (path, &box)) {
fprintf (stream, "[box (%d, %d), (%d, %d)]",
box.p1.x, box.p1.y, box.p2.x, box.p2.y);
}
fprintf (stream, "\n");
}
void
_cairo_debug_print_polygon (FILE *stream, cairo_polygon_t *polygon)
{
int n;
fprintf (stream,
"polygon: extents=(%f, %f), (%f, %f)\n",
_cairo_fixed_to_double (polygon->extents.p1.x),
_cairo_fixed_to_double (polygon->extents.p1.y),
_cairo_fixed_to_double (polygon->extents.p2.x),
_cairo_fixed_to_double (polygon->extents.p2.y));
if (polygon->num_limits) {
fprintf (stream,
" : limit=(%f, %f), (%f, %f) x %d\n",
_cairo_fixed_to_double (polygon->limit.p1.x),
_cairo_fixed_to_double (polygon->limit.p1.y),
_cairo_fixed_to_double (polygon->limit.p2.x),
_cairo_fixed_to_double (polygon->limit.p2.y),
polygon->num_limits);
}
for (n = 0; n < polygon->num_edges; n++) {
cairo_edge_t *edge = &polygon->edges[n];
fprintf (stream,
" [%d] = [(%f, %f), (%f, %f)], top=%f, bottom=%f, dir=%d\n",
n,
_cairo_fixed_to_double (edge->line.p1.x),
_cairo_fixed_to_double (edge->line.p1.y),
_cairo_fixed_to_double (edge->line.p2.x),
_cairo_fixed_to_double (edge->line.p2.y),
_cairo_fixed_to_double (edge->top),
_cairo_fixed_to_double (edge->bottom),
edge->dir);
}
}
void
_cairo_debug_print_matrix (FILE *file, const cairo_matrix_t *matrix)
{
fprintf (file, "[%g %g %g %g %g %g]\n",
matrix->xx, matrix->yx,
matrix->xy, matrix->yy,
matrix->x0, matrix->y0);
}
void
_cairo_debug_print_rect (FILE *file, const cairo_rectangle_int_t *rect)
{
fprintf (file, "x: %d y: %d width: %d height: %d\n",
rect->x, rect->y,
rect->width, rect->height);
}

Просмотреть файл

@ -0,0 +1,68 @@
/* cairo - a vector graphics library with display and print output
*
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl D. Worth <cworth@redhat.com>
*/
#ifndef CAIRO_DEFAULT_CONTEXT_PRIVATE_H
#define CAIRO_DEFAULT_CONTEXT_PRIVATE_H
#include "cairo-private.h"
#include "cairo-gstate-private.h"
#include "cairo-path-fixed-private.h"
CAIRO_BEGIN_DECLS
typedef struct _cairo_default_context cairo_default_context_t;
struct _cairo_default_context {
cairo_t base;
cairo_gstate_t *gstate;
cairo_gstate_t gstate_tail[2];
cairo_gstate_t *gstate_freelist;
cairo_path_fixed_t path[1];
};
cairo_private cairo_t *
_cairo_default_context_create (void *target);
cairo_private cairo_status_t
_cairo_default_context_init (cairo_default_context_t *cr, void *target);
cairo_private void
_cairo_default_context_fini (cairo_default_context_t *cr);
CAIRO_END_DECLS
#endif /* CAIRO_DEFAULT_CONTEXT_PRIVATE_H */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -35,6 +35,9 @@
*/
#include "cairoint.h"
#if CAIRO_HAS_DEFLATE_STREAM
#include "cairo-error-private.h"
#include "cairo-output-stream-private.h"
#include <zlib.h>
@ -121,7 +124,7 @@ _cairo_deflate_stream_create (cairo_output_stream_t *output)
if (output->status)
return _cairo_output_stream_create_in_error (output->status);
stream = malloc (sizeof (cairo_deflate_stream_t));
stream = _cairo_malloc (sizeof (cairo_deflate_stream_t));
if (unlikely (stream == NULL)) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
@ -149,3 +152,5 @@ _cairo_deflate_stream_create (cairo_output_stream_t *output)
return &stream->base;
}
#endif /* CAIRO_HAS_DEFLATE_STREAM */

Просмотреть файл

@ -92,7 +92,7 @@
* interactions with existing surface API of the device functions for
* surfaces of that type.
* </para></note>
*/
**/
static const cairo_device_t _nil_device = {
CAIRO_REFERENCE_COUNT_INVALID,
@ -156,6 +156,13 @@ _cairo_device_create_in_error (cairo_status_t status)
case CAIRO_STATUS_INVALID_WEIGHT:
case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
case CAIRO_STATUS_INVALID_CONTENT:
case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION:
case CAIRO_STATUS_DEVICE_FINISHED:
case CAIRO_STATUS_JBIG2_GLOBAL_MISSING:
case CAIRO_STATUS_PNG_ERROR:
case CAIRO_STATUS_FREETYPE_ERROR:
case CAIRO_STATUS_WIN32_GDI_ERROR:
case CAIRO_STATUS_TAG_ERROR:
default:
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_device_t *) &_nil_device;
@ -187,8 +194,8 @@ _cairo_device_init (cairo_device_t *device,
* @device from being destroyed until a matching call to
* cairo_device_destroy() is made.
*
* The number of references to a #cairo_device_t can be get using
* cairo_device_get_reference_count().
* Use cairo_device_get_reference_count() to get the number of references
* to a #cairo_device_t.
*
* Return value: the referenced #cairo_device_t.
*
@ -254,6 +261,9 @@ cairo_device_flush (cairo_device_t *device)
if (device == NULL || device->status)
return;
if (device->finished)
return;
if (device->backend->flush != NULL) {
status = device->backend->flush (device);
if (unlikely (status))
@ -295,10 +305,14 @@ cairo_device_finish (cairo_device_t *device)
cairo_device_flush (device);
device->finished = TRUE;
if (device->backend->finish != NULL)
device->backend->finish (device);
/* We only finish the device after the backend's callback returns because
* the device might still be needed during the callback
* (e.g. for cairo_device_acquire ()).
*/
device->finished = TRUE;
}
slim_hidden_def (cairo_device_finish);
@ -360,7 +374,7 @@ cairo_device_get_type (cairo_device_t *device)
if (device == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
{
return (cairo_device_type_t) -1;
return CAIRO_DEVICE_TYPE_INVALID;
}
return device->backend->type;
@ -406,7 +420,7 @@ cairo_device_acquire (cairo_device_t *device)
return device->status;
if (unlikely (device->finished))
return _cairo_device_set_error (device, CAIRO_STATUS_SURFACE_FINISHED); /* XXX */
return _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_FINISHED);
CAIRO_MUTEX_LOCK (device->mutex);
if (device->mutex_depth++ == 0) {
@ -448,11 +462,9 @@ cairo_status_t
_cairo_device_set_error (cairo_device_t *device,
cairo_status_t status)
{
if (status == CAIRO_STATUS_SUCCESS || status >= CAIRO_INT_STATUS_UNSUPPORTED)
return status;
if (status == CAIRO_STATUS_SUCCESS)
return CAIRO_STATUS_SUCCESS;
/* Don't overwrite an existing error. This preserves the first
* error, which is the most significant. */
_cairo_status_set_error (&device->status, status);
return _cairo_error (status);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,181 +0,0 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Eric Anholt
* Copyright © 2009 Chris Wilson
* 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 the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl Worth <cworth@cworth.org>
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-gl-private.h"
#include <i915_drm.h> /* XXX dummy surface for glewInit() */
#include <sys/ioctl.h>
typedef struct _cairo_eagle_context {
cairo_gl_context_t base;
EGLDisplay display;
EGLContext context;
} cairo_eagle_context_t;
typedef struct _cairo_eagle_surface {
cairo_gl_surface_t base;
EGLSurface eagle;
} cairo_eagle_surface_t;
static void
_eagle_make_current (void *abstract_ctx,
cairo_gl_surface_t *abstract_surface)
{
cairo_eagle_context_t *ctx = abstract_ctx;
cairo_eagle_surface_t *surface = (cairo_eagle_surface_t *) abstract_surface;
eagleMakeCurrent (ctx->display, surface->eagle, surface->eagle, ctx->context);
}
static void
_eagle_swap_buffers (void *abstract_ctx,
cairo_gl_surface_t *abstract_surface)
{
cairo_eagle_context_t *ctx = abstract_ctx;
cairo_eagle_surface_t *surface = (cairo_eagle_surface_t *) abstract_surface;
eagleSwapBuffers (ctx->display, surface->eagle);
}
static void
_eagle_destroy (void *abstract_ctx)
{
}
static cairo_bool_t
_eagle_init (EGLDisplay display, EGLContext context)
{
const EGLint config_attribs[] = {
EGL_CONFIG_CAVEAT, EGL_NONE,
EGL_NONE
};
const EGLint surface_attribs[] = {
EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
EGL_NONE
};
EGLConfig config;
EGLSurface dummy;
struct drm_i915_gem_create create;
struct drm_gem_flink flink;
int fd;
GLenum err;
if (! eagleChooseConfig (display, config_attribs, &config, 1, NULL)) {
fprintf (stderr, "Unable to choose config\n");
return FALSE;
}
/* XXX */
fd = eagleGetDisplayFD (display);
create.size = 4096;
if (ioctl (fd, DRM_IOCTL_I915_GEM_CREATE, &create) != 0) {
fprintf (stderr, "gem create failed: %m\n");
return FALSE;
}
flink.handle = create.handle;
if (ioctl (fd, DRM_IOCTL_GEM_FLINK, &flink) != 0) {
fprintf (stderr, "gem flink failed: %m\n");
return FALSE;
}
dummy = eagleCreateSurfaceForName (display, config, flink.name,
1, 1, 4, surface_attribs);
if (dummy == NULL) {
fprintf (stderr, "Failed to create dummy surface\n");
return FALSE;
}
eagleMakeCurrent (display, dummy, dummy, context);
}
cairo_gl_context_t *
cairo_eagle_context_create (EGLDisplay display, EGLContext context)
{
cairo_eagle_context_t *ctx;
cairo_status_t status;
if (! _eagle_init (display, context)) {
return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY);
}
ctx = calloc (1, sizeof (cairo_eagle_context_t));
if (ctx == NULL)
return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY);
ctx->display = display;
ctx->context = context;
ctx->base.make_current = _eagle_make_current;
ctx->base.swap_buffers = _eagle_swap_buffers;
ctx->base.destroy = _eagle_destroy;
status = _cairo_gl_context_init (&ctx->base);
if (status) {
free (ctx);
return _cairo_gl_context_create_in_error (status);
}
return &ctx->base;
}
cairo_surface_t *
cairo_gl_surface_create_for_eagle (cairo_gl_context_t *ctx,
EGLSurface eagle,
int width,
int height)
{
cairo_eagle_surface_t *surface;
if (ctx->status)
return _cairo_surface_create_in_error (ctx->status);
surface = calloc (1, sizeof (cairo_eagle_surface_t));
if (unlikely (surface == NULL))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
_cairo_gl_surface_init (ctx, &surface->base,
CAIRO_CONTENT_COLOR_ALPHA, width, height);
surface->eagle = eagle;
return &surface->base.base;
}

Просмотреть файл

@ -0,0 +1,317 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Eric Anholt
* Copyright © 2009 Chris Wilson
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl Worth <cworth@cworth.org>
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-gl-private.h"
#include "cairo-error-private.h"
typedef struct _cairo_egl_context {
cairo_gl_context_t base;
EGLDisplay display;
EGLContext context;
EGLSurface dummy_surface;
EGLContext previous_context;
EGLSurface previous_surface;
} cairo_egl_context_t;
typedef struct _cairo_egl_surface {
cairo_gl_surface_t base;
EGLSurface egl;
} cairo_egl_surface_t;
static cairo_bool_t
_context_acquisition_changed_egl_state (cairo_egl_context_t *ctx,
EGLSurface current_surface)
{
return ctx->previous_context != ctx->context ||
ctx->previous_surface != current_surface;
}
static EGLSurface
_egl_get_current_surface (cairo_egl_context_t *ctx)
{
if (ctx->base.current_target == NULL ||
_cairo_gl_surface_is_texture (ctx->base.current_target)) {
return ctx->dummy_surface;
}
return ((cairo_egl_surface_t *) ctx->base.current_target)->egl;
}
static void
_egl_query_current_state (cairo_egl_context_t *ctx)
{
ctx->previous_surface = eglGetCurrentSurface (EGL_DRAW);
ctx->previous_context = eglGetCurrentContext ();
/* If any of the values were none, assume they are all none. Not all
drivers seem well behaved when it comes to using these values across
multiple threads. */
if (ctx->previous_surface == EGL_NO_SURFACE ||
ctx->previous_context == EGL_NO_CONTEXT) {
ctx->previous_surface = EGL_NO_SURFACE;
ctx->previous_context = EGL_NO_CONTEXT;
}
}
static void
_egl_acquire (void *abstract_ctx)
{
cairo_egl_context_t *ctx = abstract_ctx;
EGLSurface current_surface = _egl_get_current_surface (ctx);
_egl_query_current_state (ctx);
if (!_context_acquisition_changed_egl_state (ctx, current_surface))
return;
eglMakeCurrent (ctx->display,
current_surface, current_surface, ctx->context);
}
static void
_egl_release (void *abstract_ctx)
{
cairo_egl_context_t *ctx = abstract_ctx;
if (!ctx->base.thread_aware ||
!_context_acquisition_changed_egl_state (ctx,
_egl_get_current_surface (ctx))) {
return;
}
eglMakeCurrent (ctx->display,
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
static void
_egl_make_current (void *abstract_ctx,
cairo_gl_surface_t *abstract_surface)
{
cairo_egl_context_t *ctx = abstract_ctx;
cairo_egl_surface_t *surface = (cairo_egl_surface_t *) abstract_surface;
eglMakeCurrent(ctx->display, surface->egl, surface->egl, ctx->context);
}
static void
_egl_swap_buffers (void *abstract_ctx,
cairo_gl_surface_t *abstract_surface)
{
cairo_egl_context_t *ctx = abstract_ctx;
cairo_egl_surface_t *surface = (cairo_egl_surface_t *) abstract_surface;
eglSwapBuffers (ctx->display, surface->egl);
}
static void
_egl_destroy (void *abstract_ctx)
{
cairo_egl_context_t *ctx = abstract_ctx;
eglMakeCurrent (ctx->display,
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (ctx->dummy_surface != EGL_NO_SURFACE)
eglDestroySurface (ctx->display, ctx->dummy_surface);
}
static cairo_bool_t
_egl_make_current_surfaceless(cairo_egl_context_t *ctx)
{
const char *extensions;
extensions = eglQueryString(ctx->display, EGL_EXTENSIONS);
if (strstr(extensions, "EGL_KHR_surfaceless_context") == NULL &&
strstr(extensions, "EGL_KHR_surfaceless_opengl") == NULL)
return FALSE;
if (!eglMakeCurrent(ctx->display,
EGL_NO_SURFACE, EGL_NO_SURFACE, ctx->context))
return FALSE;
return TRUE;
}
cairo_device_t *
cairo_egl_device_create (EGLDisplay dpy, EGLContext egl)
{
cairo_egl_context_t *ctx;
cairo_status_t status;
int attribs[] = {
EGL_WIDTH, 1,
EGL_HEIGHT, 1,
EGL_NONE,
};
EGLConfig config;
EGLint numConfigs;
ctx = calloc (1, sizeof (cairo_egl_context_t));
if (unlikely (ctx == NULL))
return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY);
ctx->display = dpy;
ctx->context = egl;
ctx->base.acquire = _egl_acquire;
ctx->base.release = _egl_release;
ctx->base.make_current = _egl_make_current;
ctx->base.swap_buffers = _egl_swap_buffers;
ctx->base.destroy = _egl_destroy;
/* We are about the change the current state of EGL, so we should
* query the pre-existing surface now instead of later. */
_egl_query_current_state (ctx);
if (!_egl_make_current_surfaceless (ctx)) {
/* Fall back to dummy surface, meh. */
EGLint config_attribs[] = {
EGL_CONFIG_ID, 0,
EGL_NONE
};
/*
* In order to be able to make an egl context current when using a
* pbuffer surface, that surface must have been created with a config
* that is compatible with the context config. For Mesa, this means
* that the configs must be the same.
*/
eglQueryContext (dpy, egl, EGL_CONFIG_ID, &config_attribs[1]);
eglChooseConfig (dpy, config_attribs, &config, 1, &numConfigs);
ctx->dummy_surface = eglCreatePbufferSurface (dpy, config, attribs);
if (ctx->dummy_surface == NULL) {
free (ctx);
return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY);
}
if (!eglMakeCurrent (dpy, ctx->dummy_surface, ctx->dummy_surface, egl)) {
free (ctx);
return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY);
}
}
status = _cairo_gl_dispatch_init (&ctx->base.dispatch, eglGetProcAddress);
if (unlikely (status)) {
free (ctx);
return _cairo_gl_context_create_in_error (status);
}
status = _cairo_gl_context_init (&ctx->base);
if (unlikely (status)) {
if (ctx->dummy_surface != EGL_NO_SURFACE)
eglDestroySurface (dpy, ctx->dummy_surface);
free (ctx);
return _cairo_gl_context_create_in_error (status);
}
/* Tune the default VBO size to reduce overhead on embedded devices.
* This smaller size means that flushing needs to be done more often,
* but it is less demanding of scarce memory on embedded devices.
*/
ctx->base.vbo_size = 16*1024;
eglMakeCurrent (dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
return &ctx->base.base;
}
cairo_surface_t *
cairo_gl_surface_create_for_egl (cairo_device_t *device,
EGLSurface egl,
int width,
int height)
{
cairo_egl_surface_t *surface;
if (unlikely (device->status))
return _cairo_surface_create_in_error (device->status);
if (device->backend->type != CAIRO_DEVICE_TYPE_GL)
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
if (width <= 0 || height <= 0)
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
surface = calloc (1, sizeof (cairo_egl_surface_t));
if (unlikely (surface == NULL))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
_cairo_gl_surface_init (device, &surface->base,
CAIRO_CONTENT_COLOR_ALPHA, width, height);
surface->egl = egl;
return &surface->base.base;
}
static cairo_bool_t is_egl_device (cairo_device_t *device)
{
return (device->backend != NULL &&
device->backend->type == CAIRO_DEVICE_TYPE_GL);
}
static cairo_egl_context_t *to_egl_context (cairo_device_t *device)
{
return (cairo_egl_context_t *) device;
}
EGLDisplay
cairo_egl_device_get_display (cairo_device_t *device)
{
if (! is_egl_device (device)) {
_cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
return EGL_NO_DISPLAY;
}
return to_egl_context (device)->display;
}
cairo_public EGLContext
cairo_egl_device_get_context (cairo_device_t *device)
{
if (! is_egl_device (device)) {
_cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
return EGL_NO_CONTEXT;
}
return to_egl_context (device)->context;
}

Просмотреть файл

@ -1,6 +1,7 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* 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
@ -12,7 +13,7 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
@ -34,24 +35,18 @@
* Carl D. Worth <cworth@cworth.org>
*/
#ifndef CAIRO_GLITZ_H
#define CAIRO_GLITZ_H
#ifndef _CAIRO_ERROR_INLINE_H_
#define _CAIRO_ERROR_INLINE_H_
#include "cairo.h"
#if CAIRO_HAS_GLITZ_SURFACE
#include <glitz.h>
#include "cairo-error-private.h"
CAIRO_BEGIN_DECLS
cairo_public cairo_surface_t *
cairo_glitz_surface_create (glitz_surface_t *surface);
static inline cairo_status_t
_cairo_public_status (cairo_int_status_t status)
{
assert (status <= CAIRO_INT_STATUS_LAST_STATUS);
return (cairo_status_t) status;
}
CAIRO_END_DECLS
#else /* CAIRO_HAS_GLITZ_SURFACE */
# error Cairo was not compiled with support for the glitz backend
#endif /* CAIRO_HAS_GLITZ_SURFACE */
#endif /* CAIRO_GLITZ_H */
#endif /* _CAIRO_ERROR_INLINE_H_ */

Просмотреть файл

@ -40,11 +40,82 @@
#include "cairo.h"
#include "cairo-compiler-private.h"
#include "cairo-types-private.h"
#include <assert.h>
CAIRO_BEGIN_DECLS
/* _cairo_int_status: internal status
*
* Sure wish C had a real enum type so that this would be distinct
* from #cairo_status_t. Oh well, without that, I'll use this bogus 100
* offset. We want to keep it fit in int8_t as the compiler may choose
* that for #cairo_status_t
*/
enum _cairo_int_status {
CAIRO_INT_STATUS_SUCCESS = 0,
CAIRO_INT_STATUS_NO_MEMORY,
CAIRO_INT_STATUS_INVALID_RESTORE,
CAIRO_INT_STATUS_INVALID_POP_GROUP,
CAIRO_INT_STATUS_NO_CURRENT_POINT,
CAIRO_INT_STATUS_INVALID_MATRIX,
CAIRO_INT_STATUS_INVALID_STATUS,
CAIRO_INT_STATUS_NULL_POINTER,
CAIRO_INT_STATUS_INVALID_STRING,
CAIRO_INT_STATUS_INVALID_PATH_DATA,
CAIRO_INT_STATUS_READ_ERROR,
CAIRO_INT_STATUS_WRITE_ERROR,
CAIRO_INT_STATUS_SURFACE_FINISHED,
CAIRO_INT_STATUS_SURFACE_TYPE_MISMATCH,
CAIRO_INT_STATUS_PATTERN_TYPE_MISMATCH,
CAIRO_INT_STATUS_INVALID_CONTENT,
CAIRO_INT_STATUS_INVALID_FORMAT,
CAIRO_INT_STATUS_INVALID_VISUAL,
CAIRO_INT_STATUS_FILE_NOT_FOUND,
CAIRO_INT_STATUS_INVALID_DASH,
CAIRO_INT_STATUS_INVALID_DSC_COMMENT,
CAIRO_INT_STATUS_INVALID_INDEX,
CAIRO_INT_STATUS_CLIP_NOT_REPRESENTABLE,
CAIRO_INT_STATUS_TEMP_FILE_ERROR,
CAIRO_INT_STATUS_INVALID_STRIDE,
CAIRO_INT_STATUS_FONT_TYPE_MISMATCH,
CAIRO_INT_STATUS_USER_FONT_IMMUTABLE,
CAIRO_INT_STATUS_USER_FONT_ERROR,
CAIRO_INT_STATUS_NEGATIVE_COUNT,
CAIRO_INT_STATUS_INVALID_CLUSTERS,
CAIRO_INT_STATUS_INVALID_SLANT,
CAIRO_INT_STATUS_INVALID_WEIGHT,
CAIRO_INT_STATUS_INVALID_SIZE,
CAIRO_INT_STATUS_USER_FONT_NOT_IMPLEMENTED,
CAIRO_INT_STATUS_DEVICE_TYPE_MISMATCH,
CAIRO_INT_STATUS_DEVICE_ERROR,
CAIRO_INT_STATUS_INVALID_MESH_CONSTRUCTION,
CAIRO_INT_STATUS_DEVICE_FINISHED,
CAIRO_INT_STATUS_JBIG2_GLOBAL_MISSING,
CAIRO_INT_STATUS_PNG_ERROR,
CAIRO_INT_STATUS_FREETYPE_ERROR,
CAIRO_INT_STATUS_WIN32_GDI_ERROR,
CAIRO_INT_STATUS_TAG_ERROR,
CAIRO_INT_STATUS_LAST_STATUS,
CAIRO_INT_STATUS_UNSUPPORTED = 100,
CAIRO_INT_STATUS_DEGENERATE,
CAIRO_INT_STATUS_NOTHING_TO_DO,
CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY,
CAIRO_INT_STATUS_IMAGE_FALLBACK,
CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN,
};
typedef enum _cairo_int_status cairo_int_status_t;
#define _cairo_status_is_error(status) \
(status != CAIRO_STATUS_SUCCESS && status <= CAIRO_STATUS_LAST_STATUS)
(status != CAIRO_STATUS_SUCCESS && status < CAIRO_STATUS_LAST_STATUS)
#define _cairo_int_status_is_error(status) \
(status != CAIRO_INT_STATUS_SUCCESS && status < CAIRO_INT_STATUS_LAST_STATUS)
cairo_private cairo_status_t
_cairo_error (cairo_status_t status);

Просмотреть файл

@ -0,0 +1,73 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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"
#include "cairo-private.h"
#include "cairo-compiler-private.h"
#include "cairo-error-private.h"
#include <assert.h>
/**
* _cairo_error:
* @status: a status value indicating an error, (eg. not
* %CAIRO_STATUS_SUCCESS)
*
* Checks that status is an error status, but does nothing else.
*
* All assignments of an error status to any user-visible object
* within the cairo application should result in a call to
* _cairo_error().
*
* The purpose of this function is to allow the user to set a
* breakpoint in _cairo_error() to generate a stack trace for when the
* user causes cairo to detect an error.
*
* Return value: the error status.
**/
cairo_status_t
_cairo_error (cairo_status_t status)
{
CAIRO_ENSURE_UNIQUE;
assert (_cairo_status_is_error (status));
return status;
}
COMPILE_TIME_ASSERT ((int)CAIRO_INT_STATUS_LAST_STATUS == (int)CAIRO_STATUS_LAST_STATUS);

Просмотреть файл

@ -0,0 +1,185 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* Copyright © 2005 Red Hat, Inc.
* Copyright © 2011 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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>
* Joonas Pihlaja <jpihlaja@cc.helsinki.fi>
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-compositor-private.h"
#include "cairo-image-surface-private.h"
#include "cairo-surface-offset-private.h"
/* high-level compositor interface */
static cairo_int_status_t
_cairo_fallback_compositor_paint (const cairo_compositor_t *_compositor,
cairo_composite_rectangles_t *extents)
{
cairo_image_surface_t *image;
cairo_int_status_t status;
TRACE ((stderr, "%s\n", __FUNCTION__));
image = _cairo_surface_map_to_image (extents->surface, &extents->unbounded);
status = _cairo_surface_offset_paint (&image->base,
extents->unbounded.x,
extents->unbounded.y,
extents->op,
&extents->source_pattern.base,
extents->clip);
return _cairo_surface_unmap_image (extents->surface, image);
}
static cairo_int_status_t
_cairo_fallback_compositor_mask (const cairo_compositor_t *_compositor,
cairo_composite_rectangles_t *extents)
{
cairo_image_surface_t *image;
cairo_int_status_t status;
TRACE ((stderr, "%s\n", __FUNCTION__));
image = _cairo_surface_map_to_image (extents->surface, &extents->unbounded);
status = _cairo_surface_offset_mask (&image->base,
extents->unbounded.x,
extents->unbounded.y,
extents->op,
&extents->source_pattern.base,
&extents->mask_pattern.base,
extents->clip);
return _cairo_surface_unmap_image (extents->surface, image);
}
static cairo_int_status_t
_cairo_fallback_compositor_stroke (const cairo_compositor_t *_compositor,
cairo_composite_rectangles_t *extents,
const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias)
{
cairo_image_surface_t *image;
cairo_int_status_t status;
TRACE ((stderr, "%s\n", __FUNCTION__));
image = _cairo_surface_map_to_image (extents->surface, &extents->unbounded);
status = _cairo_surface_offset_stroke (&image->base,
extents->unbounded.x,
extents->unbounded.y,
extents->op,
&extents->source_pattern.base,
path, style,
ctm, ctm_inverse,
tolerance,
antialias,
extents->clip);
return _cairo_surface_unmap_image (extents->surface, image);
}
static cairo_int_status_t
_cairo_fallback_compositor_fill (const cairo_compositor_t *_compositor,
cairo_composite_rectangles_t *extents,
const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
{
cairo_image_surface_t *image;
cairo_int_status_t status;
TRACE ((stderr, "%s\n", __FUNCTION__));
image = _cairo_surface_map_to_image (extents->surface, &extents->unbounded);
status = _cairo_surface_offset_fill (&image->base,
extents->unbounded.x,
extents->unbounded.y,
extents->op,
&extents->source_pattern.base,
path,
fill_rule, tolerance, antialias,
extents->clip);
return _cairo_surface_unmap_image (extents->surface, image);
}
static cairo_int_status_t
_cairo_fallback_compositor_glyphs (const cairo_compositor_t *_compositor,
cairo_composite_rectangles_t *extents,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_bool_t overlap)
{
cairo_image_surface_t *image;
cairo_int_status_t status;
TRACE ((stderr, "%s\n", __FUNCTION__));
image = _cairo_surface_map_to_image (extents->surface, &extents->unbounded);
status = _cairo_surface_offset_glyphs (&image->base,
extents->unbounded.x,
extents->unbounded.y,
extents->op,
&extents->source_pattern.base,
scaled_font, glyphs, num_glyphs,
extents->clip);
return _cairo_surface_unmap_image (extents->surface, image);
}
const cairo_compositor_t _cairo_fallback_compositor = {
&__cairo_no_compositor,
_cairo_fallback_compositor_paint,
_cairo_fallback_compositor_mask,
_cairo_fallback_compositor_stroke,
_cairo_fallback_compositor_fill,
_cairo_fallback_compositor_glyphs,
};

Просмотреть файл

@ -0,0 +1,7 @@
Name: @FEATURE_PC@
Description: @FEATURE_NAME@ for cairo graphics library
Version: @VERSION@
Requires: @FEATURE_BASE@ @FEATURE_REQUIRES@
Libs: @FEATURE_NONPKGCONFIG_LIBS@ @FEATURE_NONPKGCONFIG_EXTRA_LIBS@
Cflags: -I${pc_top_builddir}/${pcfiledir}/@srcdir@/src @FEATURE_NONPKGCONFIG_CFLAGS@

Просмотреть файл

@ -1,16 +0,0 @@
/* Generated by configure. Do not edit. */
#ifndef CAIRO_FEATURES_H
#define CAIRO_FEATURES_H
#define HAVE_WINDOWS_H 1
#define CAIRO_HAS_WIN32_SURFACE 1
#define CAIRO_HAS_WIN32_FONT 1
#define CAIRO_HAS_PNG_FUNCTIONS 1
#define CAIRO_HAS_PS_SURFACE 1
#define CAIRO_HAS_PDF_SURFACE 1
#define CAIRO_HAS_SVG_SURFACE 1
#define CAIRO_HAS_IMAGE_SURFACE 1
#define CAIRO_HAS_USER_FONT 1
#endif

Просмотреть файл

@ -0,0 +1,12 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: @FEATURE_PC@
Description: @FEATURE_NAME@ for cairo graphics library
Version: @VERSION@
Requires: @FEATURE_BASE@ @FEATURE_REQUIRES@
Libs: @FEATURE_NONPKGCONFIG_LIBS@ @FEATURE_NONPKGCONFIG_EXTRA_LIBS@
Cflags: -I${includedir}/cairo @FEATURE_NONPKGCONFIG_CFLAGS@

Просмотреть файл

@ -40,26 +40,28 @@
#include "cairo-fixed-type-private.h"
#include "cairo-wideint-private.h"
#include "cairoint.h"
/* Implementation */
#if (CAIRO_FIXED_BITS != 32)
# error CAIRO_FIXED_BITS must be 32, and the type must be a 32-bit type.
# error To remove this limitation, you will have to fix the tesselator.
# error To remove this limitation, you will have to fix the tessellator.
#endif
#define CAIRO_FIXED_ONE ((cairo_fixed_t)(1 << CAIRO_FIXED_FRAC_BITS))
#define CAIRO_FIXED_ONE_DOUBLE ((double)(1 << CAIRO_FIXED_FRAC_BITS))
#define CAIRO_FIXED_ONE_FLOAT ((float)(1 << CAIRO_FIXED_FRAC_BITS))
#define CAIRO_FIXED_EPSILON ((cairo_fixed_t)(1))
#define CAIRO_FIXED_ERROR_DOUBLE (1. / (2 * CAIRO_FIXED_ONE_DOUBLE))
#define CAIRO_FIXED_FRAC_MASK ((cairo_fixed_t)(((cairo_fixed_unsigned_t)(-1)) >> (CAIRO_FIXED_BITS - CAIRO_FIXED_FRAC_BITS)))
#define CAIRO_FIXED_WHOLE_MASK (~CAIRO_FIXED_FRAC_MASK)
static inline cairo_fixed_t
_cairo_fixed_from_int (int i)
{
return (cairo_fixed_t)((cairo_fixed_unsigned_t)i << CAIRO_FIXED_FRAC_BITS);
return i << CAIRO_FIXED_FRAC_BITS;
}
/* This is the "magic number" approach to converting a double into fixed
@ -152,12 +154,6 @@ _cairo_fixed_to_double (cairo_fixed_t f)
return ((double) f) / CAIRO_FIXED_ONE_DOUBLE;
}
static inline float
_cairo_fixed_to_float (cairo_fixed_t f)
{
return ((float) f) / CAIRO_FIXED_ONE_FLOAT;
}
static inline int
_cairo_fixed_is_integer (cairo_fixed_t f)
{
@ -170,6 +166,12 @@ _cairo_fixed_floor (cairo_fixed_t f)
return f & ~CAIRO_FIXED_FRAC_MASK;
}
static inline cairo_fixed_t
_cairo_fixed_ceil (cairo_fixed_t f)
{
return _cairo_fixed_floor (f + CAIRO_FIXED_FRAC_MASK);
}
static inline cairo_fixed_t
_cairo_fixed_round (cairo_fixed_t f)
{
@ -221,7 +223,7 @@ _cairo_fixed_integer_ceil (cairo_fixed_t f)
if (f > 0)
return ((f - 1)>>CAIRO_FIXED_FRAC_BITS) + 1;
else
return - (-f >> CAIRO_FIXED_FRAC_BITS);
return - ((cairo_fixed_t)(-(cairo_fixed_unsigned_t)f) >> CAIRO_FIXED_FRAC_BITS);
}
/* A bunch of explicit 16.16 operators; we need these
@ -310,7 +312,7 @@ _cairo_fixed_mul_div_floor (cairo_fixed_t a, cairo_fixed_t b, cairo_fixed_t c)
return _cairo_int64_32_div (_cairo_int32x32_64_mul (a, b), c);
}
/* compute y from x so that (x,y), p1, and p2 are collinear */
static inline cairo_fixed_t
_cairo_edge_compute_intersection_y_for_x (const cairo_point_t *p1,
const cairo_point_t *p2,
@ -331,6 +333,7 @@ _cairo_edge_compute_intersection_y_for_x (const cairo_point_t *p1,
return y;
}
/* compute x from y so that (x,y), p1, and p2 are collinear */
static inline cairo_fixed_t
_cairo_edge_compute_intersection_x_for_y (const cairo_point_t *p1,
const cairo_point_t *p2,
@ -351,6 +354,40 @@ _cairo_edge_compute_intersection_x_for_y (const cairo_point_t *p1,
return x;
}
/* Intersect two segments based on the algorithm described at
* http://paulbourke.net/geometry/pointlineplane/. This implementation
* uses floating point math. */
static inline cairo_bool_t
_slow_segment_intersection (const cairo_point_t *seg1_p1,
const cairo_point_t *seg1_p2,
const cairo_point_t *seg2_p1,
const cairo_point_t *seg2_p2,
cairo_point_t *intersection)
{
double denominator, u_a, u_b;
double seg1_dx, seg1_dy, seg2_dx, seg2_dy, seg_start_dx, seg_start_dy;
seg1_dx = _cairo_fixed_to_double (seg1_p2->x - seg1_p1->x);
seg1_dy = _cairo_fixed_to_double (seg1_p2->y - seg1_p1->y);
seg2_dx = _cairo_fixed_to_double (seg2_p2->x - seg2_p1->x);
seg2_dy = _cairo_fixed_to_double (seg2_p2->y - seg2_p1->y);
denominator = (seg2_dy * seg1_dx) - (seg2_dx * seg1_dy);
if (denominator == 0)
return FALSE;
seg_start_dx = _cairo_fixed_to_double (seg1_p1->x - seg2_p1->x);
seg_start_dy = _cairo_fixed_to_double (seg1_p1->y - seg2_p1->y);
u_a = ((seg2_dx * seg_start_dy) - (seg2_dy * seg_start_dx)) / denominator;
u_b = ((seg1_dx * seg_start_dy) - (seg1_dy * seg_start_dx)) / denominator;
if (u_a <= 0 || u_a >= 1 || u_b <= 0 || u_b >= 1)
return FALSE;
intersection->x = seg1_p1->x + _cairo_fixed_from_double ((u_a * seg1_dx));
intersection->y = seg1_p1->y + _cairo_fixed_from_double ((u_a * seg1_dy));
return TRUE;
}
#else
# error Please define multiplication and other operands for your fixed-point type size
#endif

Просмотреть файл

@ -50,7 +50,7 @@ typedef cairo_int128_t cairo_fixed_64_64_t;
typedef cairo_int128_t cairo_fixed_96_32_t;
/* Eventually, we should allow changing this, but I think
* there are some assumptions in the tesselator about the
* there are some assumptions in the tessellator about the
* size of a fixed type. For now, it must be 32.
*/
#define CAIRO_FIXED_BITS 32

Просмотреть файл

@ -283,16 +283,14 @@ face_props_parse (twin_face_properties_t *props,
parse_field (props, start, end - start);
}
static cairo_status_t
twin_font_face_create_properties (cairo_font_face_t *twin_face,
twin_face_properties_t **props_out)
static twin_face_properties_t *
twin_font_face_create_properties (cairo_font_face_t *twin_face)
{
twin_face_properties_t *props;
cairo_status_t status;
props = malloc (sizeof (twin_face_properties_t));
props = _cairo_malloc (sizeof (twin_face_properties_t));
if (unlikely (props == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return NULL;
props->stretch = TWIN_STRETCH_NORMAL;
props->slant = CAIRO_FONT_SLANT_NORMAL;
@ -300,30 +298,25 @@ twin_font_face_create_properties (cairo_font_face_t *twin_face,
props->monospace = FALSE;
props->smallcaps = FALSE;
status = cairo_font_face_set_user_data (twin_face,
if (unlikely (cairo_font_face_set_user_data (twin_face,
&twin_properties_key,
props, free);
if (unlikely (status)) {
props, free))) {
free (props);
return status;
return NULL;
}
if (props_out)
*props_out = props;
return CAIRO_STATUS_SUCCESS;
return props;
}
static cairo_status_t
twin_font_face_set_properties_from_toy (cairo_font_face_t *twin_face,
cairo_toy_font_face_t *toy_face)
{
cairo_status_t status;
twin_face_properties_t *props;
status = twin_font_face_create_properties (twin_face, &props);
if (unlikely (status))
return status;
props = twin_font_face_create_properties (twin_face);
if (unlikely (props == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
props->slant = toy_face->slant;
props->weight = toy_face->weight == CAIRO_FONT_WEIGHT_NORMAL ?
@ -419,7 +412,7 @@ twin_scaled_font_compute_properties (cairo_scaled_font_t *scaled_font,
cairo_status_t status;
twin_scaled_properties_t *props;
props = malloc (sizeof (twin_scaled_properties_t));
props = _cairo_malloc (sizeof (twin_scaled_properties_t));
if (unlikely (props == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@ -729,11 +722,9 @@ cairo_font_face_t *
_cairo_font_face_twin_create_fallback (void)
{
cairo_font_face_t *twin_font_face;
cairo_status_t status;
twin_font_face = _cairo_font_face_twin_create_internal ();
status = twin_font_face_create_properties (twin_font_face, NULL);
if (status) {
if (! twin_font_face_create_properties (twin_font_face)) {
cairo_font_face_destroy (twin_font_face);
return (cairo_font_face_t *) &_cairo_font_face_nil;
}

Просмотреть файл

@ -49,14 +49,14 @@
*
* #cairo_font_face_t represents a particular font at a particular weight,
* slant, and other characteristic but no size, transformation, or size.
*
*
* Font faces are created using <firstterm>font-backend</firstterm>-specific
* constructors, typically of the form
* cairo_<emphasis>backend</emphasis>_font_face_create(), or implicitly
* using the <firstterm>toy</firstterm> text API by way of
* <function>cairo_<emphasis>backend</emphasis>_font_face_create(<!-- -->)</function>,
* or implicitly using the <firstterm>toy</firstterm> text API by way of
* cairo_select_font_face(). The resulting face can be accessed using
* cairo_get_font_face().
*/
**/
/* #cairo_font_face_t */
@ -67,6 +67,13 @@ const cairo_font_face_t _cairo_font_face_nil = {
{ 0, 0, 0, NULL }, /* user_data */
NULL
};
const cairo_font_face_t _cairo_font_face_nil_file_not_found = {
{ 0 }, /* hash_entry */
CAIRO_STATUS_FILE_NOT_FOUND, /* status */
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
{ 0, 0, 0, NULL }, /* user_data */
NULL
};
cairo_status_t
_cairo_font_face_set_error (cairo_font_face_t *font_face,
@ -104,16 +111,18 @@ _cairo_font_face_init (cairo_font_face_t *font_face,
* @font_face from being destroyed until a matching call to
* cairo_font_face_destroy() is made.
*
* The number of references to a #cairo_font_face_t can be get using
* cairo_font_face_get_reference_count().
* Use cairo_font_face_get_reference_count() to get the number of
* references to a #cairo_font_face_t.
*
* Return value: the referenced #cairo_font_face_t.
*
* Since: 1.0
**/
cairo_font_face_t *
cairo_font_face_reference (cairo_font_face_t *font_face)
{
if (font_face == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
return font_face;
/* We would normally assert that we have a reference here but we
@ -126,6 +135,28 @@ cairo_font_face_reference (cairo_font_face_t *font_face)
}
slim_hidden_def (cairo_font_face_reference);
static inline cairo_bool_t
__put(cairo_reference_count_t *v)
{
int c, old;
c = CAIRO_REFERENCE_COUNT_GET_VALUE(v);
while (c != 1 && (old = _cairo_atomic_int_cmpxchg_return_old(&v->ref_count, c, c - 1)) != c)
c = old;
return c != 1;
}
cairo_bool_t
_cairo_font_face_destroy (void *abstract_face)
{
#if 0 /* Nothing needs to be done, we can just drop the last reference */
cairo_font_face_t *font_face = abstract_face;
return _cairo_reference_count_dec_and_test (&font_face->ref_count);
#endif
return TRUE;
}
/**
* cairo_font_face_destroy:
* @font_face: a #cairo_font_face_t
@ -133,37 +164,30 @@ slim_hidden_def (cairo_font_face_reference);
* Decreases the reference count on @font_face by one. If the result
* is zero, then @font_face and all associated resources are freed.
* See cairo_font_face_reference().
*
* Since: 1.0
**/
void
cairo_font_face_destroy (cairo_font_face_t *font_face)
{
if (font_face == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
return;
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->ref_count));
if (! _cairo_reference_count_dec_and_test (&font_face->ref_count))
return;
if (font_face->backend->destroy)
font_face->backend->destroy (font_face);
/* We allow resurrection to deal with some memory management for the
* FreeType backend where cairo_ft_font_face_t and cairo_ft_unscaled_font_t
* need to effectively mutually reference each other
*/
if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->ref_count))
if (__put (&font_face->ref_count))
return;
if (font_face->backend->lock)
font_face->backend->lock (font_face);
if (! font_face->backend->destroy (font_face))
return;
_cairo_user_data_array_fini (&font_face->user_data);
if (font_face->backend->unlock)
font_face->backend->unlock (font_face);
free (font_face);
}
slim_hidden_def (cairo_font_face_destroy);
@ -203,7 +227,7 @@ unsigned int
cairo_font_face_get_reference_count (cairo_font_face_t *font_face)
{
if (font_face == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
return 0;
return CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->ref_count);
@ -218,6 +242,8 @@ cairo_font_face_get_reference_count (cairo_font_face_t *font_face)
*
* Return value: %CAIRO_STATUS_SUCCESS or another error such as
* %CAIRO_STATUS_NO_MEMORY.
*
* Since: 1.0
**/
cairo_status_t
cairo_font_face_status (cairo_font_face_t *font_face)
@ -236,19 +262,15 @@ cairo_font_face_status (cairo_font_face_t *font_face)
* function returns %NULL.
*
* Return value: the user data previously attached or %NULL.
*
* Since: 1.0
**/
void *
cairo_font_face_get_user_data (cairo_font_face_t *font_face,
const cairo_user_data_key_t *key)
{
void *result;
if (font_face->backend->lock)
font_face->backend->lock (font_face);
result = _cairo_user_data_array_get_data (&font_face->user_data,
key);
if (font_face->backend->unlock)
font_face->backend->unlock (font_face);
return result;
return _cairo_user_data_array_get_data (&font_face->user_data,
key);
}
slim_hidden_def (cairo_font_face_get_user_data);
@ -267,6 +289,8 @@ slim_hidden_def (cairo_font_face_get_user_data);
*
* Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
* slot could not be allocated for the user data.
*
* Since: 1.0
**/
cairo_status_t
cairo_font_face_set_user_data (cairo_font_face_t *font_face,
@ -277,14 +301,8 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face,
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
return font_face->status;
cairo_status_t status;
if (font_face->backend->lock)
font_face->backend->lock (font_face);
status = _cairo_user_data_array_set_data (&font_face->user_data,
key, user_data, destroy);
if (font_face->backend->unlock)
font_face->backend->unlock (font_face);
return status;
return _cairo_user_data_array_set_data (&font_face->user_data,
key, user_data, destroy);
}
slim_hidden_def (cairo_font_face_set_user_data);
@ -317,10 +335,11 @@ _cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled_font->ref_count));
if (! _cairo_reference_count_dec_and_test (&unscaled_font->ref_count))
if (__put (&unscaled_font->ref_count))
return;
unscaled_font->backend->destroy (unscaled_font);
if (! unscaled_font->backend->destroy (unscaled_font))
return;
free (unscaled_font);
}

Просмотреть файл

@ -47,7 +47,7 @@
* time the font options implied by a surface are just right and do not
* need any changes, but for pixel-based targets tweaking font options
* may result in superior output on a particular display.
*/
**/
static const cairo_font_options_t _cairo_font_options_nil = {
CAIRO_ANTIALIAS_DEFAULT,
@ -55,7 +55,8 @@ static const cairo_font_options_t _cairo_font_options_nil = {
CAIRO_LCD_FILTER_DEFAULT,
CAIRO_HINT_STYLE_DEFAULT,
CAIRO_HINT_METRICS_DEFAULT,
CAIRO_ROUND_GLYPH_POS_DEFAULT
CAIRO_ROUND_GLYPH_POS_DEFAULT,
NULL
};
/**
@ -73,6 +74,7 @@ _cairo_font_options_init_default (cairo_font_options_t *options)
options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
options->round_glyph_positions = CAIRO_ROUND_GLYPH_POS_DEFAULT;
options->variations = NULL;
}
void
@ -85,6 +87,7 @@ _cairo_font_options_init_copy (cairo_font_options_t *options,
options->hint_style = other->hint_style;
options->hint_metrics = other->hint_metrics;
options->round_glyph_positions = other->round_glyph_positions;
options->variations = other->variations ? strdup (other->variations) : NULL;
}
/**
@ -98,13 +101,15 @@ _cairo_font_options_init_copy (cairo_font_options_t *options,
* valid pointer; if memory cannot be allocated, then a special
* error object is returned where all operations on the object do nothing.
* You can check for this with cairo_font_options_status().
*
* Since: 1.0
**/
cairo_font_options_t *
cairo_font_options_create (void)
{
cairo_font_options_t *options;
options = malloc (sizeof (cairo_font_options_t));
options = _cairo_malloc (sizeof (cairo_font_options_t));
if (!options) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_options_t *) &_cairo_font_options_nil;
@ -127,6 +132,8 @@ cairo_font_options_create (void)
* valid pointer; if memory cannot be allocated, then a special
* error object is returned where all operations on the object do nothing.
* You can check for this with cairo_font_options_status().
*
* Since: 1.0
**/
cairo_font_options_t *
cairo_font_options_copy (const cairo_font_options_t *original)
@ -136,7 +143,7 @@ cairo_font_options_copy (const cairo_font_options_t *original)
if (cairo_font_options_status ((cairo_font_options_t *) original))
return (cairo_font_options_t *) &_cairo_font_options_nil;
options = malloc (sizeof (cairo_font_options_t));
options = _cairo_malloc (sizeof (cairo_font_options_t));
if (!options) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_options_t *) &_cairo_font_options_nil;
@ -147,12 +154,20 @@ cairo_font_options_copy (const cairo_font_options_t *original)
return options;
}
void
_cairo_font_options_fini (cairo_font_options_t *options)
{
free (options->variations);
}
/**
* cairo_font_options_destroy:
* @options: a #cairo_font_options_t
*
* Destroys a #cairo_font_options_t object created with
* cairo_font_options_create() or cairo_font_options_copy().
*
* Since: 1.0
**/
void
cairo_font_options_destroy (cairo_font_options_t *options)
@ -160,6 +175,7 @@ cairo_font_options_destroy (cairo_font_options_t *options)
if (cairo_font_options_status (options))
return;
_cairo_font_options_fini (options);
free (options);
}
@ -171,6 +187,8 @@ cairo_font_options_destroy (cairo_font_options_t *options)
* font options object
*
* Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
*
* Since: 1.0
**/
cairo_status_t
cairo_font_options_status (cairo_font_options_t *options)
@ -192,7 +210,9 @@ slim_hidden_def (cairo_font_options_status);
* Merges non-default options from @other into @options, replacing
* existing values. This operation can be thought of as somewhat
* similar to compositing @other onto @options with the operation
* of %CAIRO_OPERATION_OVER.
* of %CAIRO_OPERATOR_OVER.
*
* Since: 1.0
**/
void
cairo_font_options_merge (cairo_font_options_t *options,
@ -216,6 +236,24 @@ cairo_font_options_merge (cairo_font_options_t *options,
options->hint_metrics = other->hint_metrics;
if (other->round_glyph_positions != CAIRO_ROUND_GLYPH_POS_DEFAULT)
options->round_glyph_positions = other->round_glyph_positions;
if (other->variations) {
if (options->variations) {
char *p;
/* 'merge' variations by concatenating - later entries win */
p = malloc (strlen (other->variations) + strlen (options->variations) + 2);
p[0] = 0;
strcat (p, options->variations);
strcat (p, ",");
strcat (p, other->variations);
free (options->variations);
options->variations = p;
}
else {
options->variations = strdup (other->variations);
}
}
}
slim_hidden_def (cairo_font_options_merge);
@ -229,6 +267,8 @@ slim_hidden_def (cairo_font_options_merge);
* Return value: %TRUE if all fields of the two font options objects match.
* Note that this function will return %FALSE if either object is in
* error.
*
* Since: 1.0
**/
cairo_bool_t
cairo_font_options_equal (const cairo_font_options_t *options,
@ -247,7 +287,10 @@ cairo_font_options_equal (const cairo_font_options_t *options,
options->lcd_filter == other->lcd_filter &&
options->hint_style == other->hint_style &&
options->hint_metrics == other->hint_metrics &&
options->round_glyph_positions == other->round_glyph_positions);
options->round_glyph_positions == other->round_glyph_positions &&
((options->variations == NULL && other->variations == NULL) ||
(options->variations != NULL && other->variations != NULL &&
strcmp (options->variations, other->variations) == 0)));
}
slim_hidden_def (cairo_font_options_equal);
@ -262,18 +305,25 @@ slim_hidden_def (cairo_font_options_equal);
* Return value: the hash value for the font options object.
* The return value can be cast to a 32-bit type if a
* 32-bit hash value is needed.
*
* Since: 1.0
**/
unsigned long
cairo_font_options_hash (const cairo_font_options_t *options)
{
unsigned long hash = 0;
if (cairo_font_options_status ((cairo_font_options_t *) options))
options = &_cairo_font_options_nil; /* force default values */
if (options->variations)
hash = _cairo_string_hash (options->variations, strlen (options->variations));
return ((options->antialias) |
(options->subpixel_order << 4) |
(options->lcd_filter << 8) |
(options->hint_style << 12) |
(options->hint_metrics << 16));
(options->hint_metrics << 16)) ^ hash;
}
slim_hidden_def (cairo_font_options_hash);
@ -284,6 +334,8 @@ slim_hidden_def (cairo_font_options_hash);
*
* Sets the antialiasing mode for the font options object. This
* specifies the type of antialiasing to do when rendering text.
*
* Since: 1.0
**/
void
cairo_font_options_set_antialias (cairo_font_options_t *options,
@ -303,6 +355,8 @@ slim_hidden_def (cairo_font_options_set_antialias);
* Gets the antialiasing mode for the font options object.
*
* Return value: the antialiasing mode
*
* Since: 1.0
**/
cairo_antialias_t
cairo_font_options_get_antialias (const cairo_font_options_t *options)
@ -323,6 +377,8 @@ cairo_font_options_get_antialias (const cairo_font_options_t *options)
* the display device when rendering with an antialiasing mode of
* %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for
* #cairo_subpixel_order_t for full details.
*
* Since: 1.0
**/
void
cairo_font_options_set_subpixel_order (cairo_font_options_t *options,
@ -343,6 +399,8 @@ slim_hidden_def (cairo_font_options_set_subpixel_order);
* See the documentation for #cairo_subpixel_order_t for full details.
*
* Return value: the subpixel order for the font options object
*
* Since: 1.0
**/
cairo_subpixel_order_t
cairo_font_options_get_subpixel_order (const cairo_font_options_t *options)
@ -362,11 +420,9 @@ cairo_font_options_get_subpixel_order (const cairo_font_options_t *options)
* specifies how pixels are filtered when rendered with an antialiasing
* mode of %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for
* #cairo_lcd_filter_t for full details.
*
* Since: 1.8
**/
void
cairo_font_options_set_lcd_filter (cairo_font_options_t *options,
_cairo_font_options_set_lcd_filter (cairo_font_options_t *options,
cairo_lcd_filter_t lcd_filter)
{
if (cairo_font_options_status (options))
@ -374,7 +430,6 @@ cairo_font_options_set_lcd_filter (cairo_font_options_t *options,
options->lcd_filter = lcd_filter;
}
slim_hidden_def (cairo_font_options_set_lcd_filter);
/**
* _cairo_font_options_get_lcd_filter:
@ -384,8 +439,6 @@ slim_hidden_def (cairo_font_options_set_lcd_filter);
* See the documentation for #cairo_lcd_filter_t for full details.
*
* Return value: the LCD filter for the font options object
*
* Since: 1.8
**/
cairo_lcd_filter_t
_cairo_font_options_get_lcd_filter (const cairo_font_options_t *options)
@ -403,8 +456,6 @@ _cairo_font_options_get_lcd_filter (const cairo_font_options_t *options)
*
* Sets the rounding options for the font options object. If rounding is set, a
* glyph's position will be rounded to integer values.
*
* Since: 1.12
**/
void
_cairo_font_options_set_round_glyph_positions (cairo_font_options_t *options,
@ -423,8 +474,6 @@ _cairo_font_options_set_round_glyph_positions (cairo_font_options_t *options,
* Gets the glyph position rounding option for the font options object.
*
* Return value: The round glyph posistions flag for the font options object.
*
* Since: 1.12
**/
cairo_round_glyph_positions_t
_cairo_font_options_get_round_glyph_positions (const cairo_font_options_t *options)
@ -444,6 +493,8 @@ _cairo_font_options_get_round_glyph_positions (const cairo_font_options_t *optio
* This controls whether to fit font outlines to the pixel grid,
* and if so, whether to optimize for fidelity or contrast.
* See the documentation for #cairo_hint_style_t for full details.
*
* Since: 1.0
**/
void
cairo_font_options_set_hint_style (cairo_font_options_t *options,
@ -464,6 +515,8 @@ slim_hidden_def (cairo_font_options_set_hint_style);
* See the documentation for #cairo_hint_style_t for full details.
*
* Return value: the hint style for the font options object
*
* Since: 1.0
**/
cairo_hint_style_t
cairo_font_options_get_hint_style (const cairo_font_options_t *options)
@ -483,6 +536,8 @@ cairo_font_options_get_hint_style (const cairo_font_options_t *options)
* controls whether metrics are quantized to integer values in
* device units.
* See the documentation for #cairo_hint_metrics_t for full details.
*
* Since: 1.0
**/
void
cairo_font_options_set_hint_metrics (cairo_font_options_t *options,
@ -503,6 +558,8 @@ slim_hidden_def (cairo_font_options_set_hint_metrics);
* See the documentation for #cairo_hint_metrics_t for full details.
*
* Return value: the metrics hinting mode for the font options object
*
* Since: 1.0
**/
cairo_hint_metrics_t
cairo_font_options_get_hint_metrics (const cairo_font_options_t *options)
@ -512,3 +569,54 @@ cairo_font_options_get_hint_metrics (const cairo_font_options_t *options)
return options->hint_metrics;
}
/**
* cairo_font_options_set_variations:
* @options: a #cairo_font_options_t
* @variations: the new font variations, or %NULL
*
* Sets the OpenType font variations for the font options object.
* Font variations are specified as a string with a format that
* is similar to the CSS font-variation-settings. The string contains
* a comma-separated list of axis assignments, which each assignment
* consists of a 4-character axis name and a value, separated by
* whitespace and optional equals sign.
*
* Examples:
*
* wght=200,wdth=140.5
*
* wght 200 , wdth 140.5
*
* Since: 1.16
**/
void
cairo_font_options_set_variations (cairo_font_options_t *options,
const char *variations)
{
char *tmp = variations ? strdup (variations) : NULL;
free (options->variations);
options->variations = tmp;
}
/**
* cairo_font_options_get_variations:
* @options: a #cairo_font_options_t
*
* Gets the OpenType font variations for the font options object.
* See cairo_font_options_set_variations() for details about the
* string format.
*
* Return value: the font variations for the font options object. The
* returned string belongs to the @options and must not be modified.
* It is valid until either the font options object is destroyed or
* the font variations in this object is modified with
* cairo_font_options_set_variations().
*
* Since: 1.16
**/
const char *
cairo_font_options_get_variations (cairo_font_options_t *options)
{
return options->variations;
}

Просмотреть файл

@ -40,11 +40,15 @@
#include "cairoint.h"
#include "cairo-atomic-private.h"
#if HAS_ATOMIC_OPS
CAIRO_BEGIN_DECLS
#define DISABLE_FREED_POOLS 0
#if HAS_ATOMIC_OPS && ! DISABLE_FREED_POOLS
/* Keep a stash of recently freed clip_paths, since we need to
* reallocate them frequently.
*/
#define MAX_FREED_POOL_SIZE 4
#define MAX_FREED_POOL_SIZE 16
typedef struct {
void *pool[MAX_FREED_POOL_SIZE];
cairo_atomic_int_t top;
@ -118,6 +122,10 @@ _freed_pool_reset (freed_pool_t *pool);
#else
/* A warning about an unused freed-pool in a build without atomics
* enabled usually indicates a missing _freed_pool_reset() in the
* static reset function */
typedef int freed_pool_t;
#define _freed_pool_get(pool) NULL
@ -126,4 +134,6 @@ typedef int freed_pool_t;
#endif
CAIRO_END_DECLS
#endif /* CAIRO_FREED_POOL_PRIVATE_H */

Просмотреть файл

@ -111,7 +111,7 @@ _cairo_freepool_alloc (cairo_freepool_t *freepool)
cairo_freelist_node_t *node;
node = freepool->first_free_node;
if (unlikely (node == NULL))
if (node == NULL)
return _cairo_freepool_alloc_from_pool (freepool);
VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next)));
@ -133,7 +133,7 @@ _cairo_freepool_free (cairo_freepool_t *freepool, void *ptr)
node->next = freepool->first_free_node;
freepool->first_free_node = node;
VG (VALGRIND_MAKE_MEM_NOACCESS (node, freepool->nodesize));
VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freepool->nodesize));
}
#endif /* CAIRO_FREELIST_H */

Просмотреть файл

@ -61,7 +61,7 @@ _cairo_freelist_alloc (cairo_freelist_t *freelist)
return node;
}
return malloc (freelist->nodesize);
return _cairo_malloc (freelist->nodesize);
}
void *
@ -80,7 +80,7 @@ _cairo_freelist_free (cairo_freelist_t *freelist, void *voidnode)
if (node) {
node->next = freelist->first_free_node;
freelist->first_free_node = node;
VG (VALGRIND_MAKE_MEM_NOACCESS (node, freelist->nodesize));
VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freelist->nodesize));
}
}
@ -97,7 +97,7 @@ _cairo_freepool_init (cairo_freepool_t *freepool, unsigned nodesize)
freepool->embedded_pool.rem = sizeof (freepool->embedded_data);
freepool->embedded_pool.data = freepool->embedded_data;
VG (VALGRIND_MAKE_MEM_NOACCESS (freepool->embedded_data, sizeof (freepool->embedded_data)));
VG (VALGRIND_MAKE_MEM_UNDEFINED (freepool->embedded_data, sizeof (freepool->embedded_data)));
}
void
@ -119,7 +119,7 @@ _cairo_freepool_fini (cairo_freepool_t *freepool)
pool = next;
}
VG (VALGRIND_MAKE_MEM_NOACCESS (freepool, sizeof (freepool)));
VG (VALGRIND_MAKE_MEM_UNDEFINED (freepool, sizeof (freepool)));
}
void *
@ -139,7 +139,7 @@ _cairo_freepool_alloc_from_new_pool (cairo_freepool_t *freepool)
else
poolsize = (128 * freepool->nodesize + 8191) & -8192;
pool = malloc (sizeof (cairo_freelist_pool_t) + poolsize);
pool = _cairo_malloc (sizeof (cairo_freelist_pool_t) + poolsize);
if (unlikely (pool == NULL))
return pool;
@ -152,7 +152,7 @@ _cairo_freepool_alloc_from_new_pool (cairo_freepool_t *freepool)
pool->rem = poolsize - freepool->nodesize;
pool->data = (uint8_t *) (pool + 1) + freepool->nodesize;
VG (VALGRIND_MAKE_MEM_NOACCESS (pool->data, pool->rem));
VG (VALGRIND_MAKE_MEM_UNDEFINED (pool->data, pool->rem));
return pool + 1;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -37,8 +37,8 @@
#ifndef CAIRO_FT_PRIVATE_H
#define CAIRO_FT_PRIVATE_H
#include "cairo-ft.h"
#include "cairoint.h"
#include "cairo-ft.h"
#if CAIRO_HAS_FT_FONT
@ -52,18 +52,6 @@ _cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font);
/* These functions are needed by the PDF backend, which needs to keep track of the
* the different fonts-on-disk used by a document, so it can embed them
*/
cairo_private cairo_unscaled_font_t *
_cairo_ft_scaled_font_get_unscaled_font (cairo_scaled_font_t *scaled_font);
cairo_private FT_Face
_cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled);
cairo_private void
_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled);
cairo_private cairo_bool_t
_cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font);
cairo_private unsigned int
_cairo_ft_scaled_font_get_load_flags (cairo_scaled_font_t *scaled_font);

Просмотреть файл

@ -52,16 +52,45 @@
CAIRO_BEGIN_DECLS
cairo_public cairo_font_face_t *
cairo_ft_font_face_create_for_ft_face (FT_Face face,
int load_flags);
/**
* cairo_ft_synthesize_t:
* @CAIRO_FT_SYNTHESIZE_BOLD: Embolden the glyphs (redraw with a pixel offset)
* @CAIRO_FT_SYNTHESIZE_OBLIQUE: Slant the glyph outline by 12 degrees to the
* right.
*
* A set of synthesis options to control how FreeType renders the glyphs
* for a particular font face.
*
* Individual synthesis features of a #cairo_ft_font_face_t can be set
* using cairo_ft_font_face_set_synthesize(), or disabled using
* cairo_ft_font_face_unset_synthesize(). The currently enabled set of
* synthesis options can be queried with cairo_ft_font_face_get_synthesize().
*
* Note: that when synthesizing glyphs, the font metrics returned will only
* be estimates.
*
* Since: 1.12
**/
typedef enum {
CAIRO_FT_SYNTHESIZE_BOLD = 1 << 0,
CAIRO_FT_SYNTHESIZE_OBLIQUE = 1 << 1
} cairo_ft_synthesize_t;
cairo_public cairo_font_face_t *
cairo_ft_font_face_create_for_ft_face (FT_Face face,
int load_flags,
unsigned int synth_flags,
void *face_context);
cairo_public void
cairo_ft_font_face_set_synthesize (cairo_font_face_t *font_face,
unsigned int synth_flags);
cairo_public void
cairo_ft_font_face_unset_synthesize (cairo_font_face_t *font_face,
unsigned int synth_flags);
cairo_public unsigned int
cairo_ft_font_face_get_synthesize (cairo_font_face_t *font_face);
cairo_public FT_Face
cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *scaled_font);
@ -72,7 +101,7 @@ cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *scaled_font);
#if CAIRO_HAS_FC_FONT
cairo_public cairo_font_face_t *
cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
cairo_public void
cairo_ft_font_options_substitute (const cairo_font_options_t *options,

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,851 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Eric Anholt
* Copyright © 2009 Chris Wilson
* Copyright © 2005,2010 Red Hat, Inc
* Copyright © 2010 Linaro Limited
*
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Benjamin Otte <otte@gnome.org>
* Carl Worth <cworth@cworth.org>
* Chris Wilson <chris@chris-wilson.co.uk>
* Eric Anholt <eric@anholt.net>
* Alexandros Frantzis <alexandros.frantzis@linaro.org>
*/
#include "cairoint.h"
#include "cairo-error-private.h"
#include "cairo-gl-private.h"
#define MAX_MSAA_SAMPLES 4
static void
_gl_lock (void *device)
{
cairo_gl_context_t *ctx = (cairo_gl_context_t *) device;
ctx->acquire (ctx);
}
static void
_gl_unlock (void *device)
{
cairo_gl_context_t *ctx = (cairo_gl_context_t *) device;
ctx->release (ctx);
}
static cairo_status_t
_gl_flush (void *device)
{
cairo_gl_context_t *ctx;
cairo_status_t status;
status = _cairo_gl_context_acquire (device, &ctx);
if (unlikely (status))
return status;
_cairo_gl_composite_flush (ctx);
_cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_SOURCE);
_cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_MASK);
if (ctx->clip_region) {
cairo_region_destroy (ctx->clip_region);
ctx->clip_region = NULL;
}
ctx->current_target = NULL;
ctx->current_operator = -1;
ctx->vertex_size = 0;
ctx->pre_shader = NULL;
_cairo_gl_set_shader (ctx, NULL);
ctx->dispatch.BindBuffer (GL_ARRAY_BUFFER, 0);
glDisable (GL_SCISSOR_TEST);
glDisable (GL_BLEND);
return _cairo_gl_context_release (ctx, status);
}
static void
_gl_finish (void *device)
{
cairo_gl_context_t *ctx = device;
int n;
_gl_lock (device);
_cairo_cache_fini (&ctx->gradients);
_cairo_gl_context_fini_shaders (ctx);
for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++)
_cairo_gl_glyph_cache_fini (ctx, &ctx->glyph_cache[n]);
_gl_unlock (device);
}
static void
_gl_destroy (void *device)
{
cairo_gl_context_t *ctx = device;
ctx->acquire (ctx);
while (! cairo_list_is_empty (&ctx->fonts)) {
cairo_gl_font_t *font;
font = cairo_list_first_entry (&ctx->fonts,
cairo_gl_font_t,
link);
cairo_list_del (&font->base.link);
cairo_list_del (&font->link);
free (font);
}
_cairo_array_fini (&ctx->tristrip_indices);
cairo_region_destroy (ctx->clip_region);
_cairo_clip_destroy (ctx->clip);
free (ctx->vb);
ctx->destroy (ctx);
free (ctx);
}
static const cairo_device_backend_t _cairo_gl_device_backend = {
CAIRO_DEVICE_TYPE_GL,
_gl_lock,
_gl_unlock,
_gl_flush, /* flush */
_gl_finish,
_gl_destroy,
};
static cairo_bool_t
_cairo_gl_msaa_compositor_enabled (void)
{
const char *env = getenv ("CAIRO_GL_COMPOSITOR");
return env && strcmp(env, "msaa") == 0;
}
static cairo_bool_t
test_can_read_bgra (cairo_gl_flavor_t gl_flavor)
{
/* Desktop GL always supports BGRA formats. */
if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
return TRUE;
assert (gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
gl_flavor == CAIRO_GL_FLAVOR_ES2);
/* For OpenGL ES we have to look for the specific extension and BGRA only
* matches cairo's integer packed bytes on little-endian machines. */
if (!_cairo_is_little_endian())
return FALSE;
return _cairo_gl_has_extension ("EXT_read_format_bgra");
}
cairo_status_t
_cairo_gl_context_init (cairo_gl_context_t *ctx)
{
cairo_status_t status;
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
int gl_version = _cairo_gl_get_version ();
cairo_gl_flavor_t gl_flavor = _cairo_gl_get_flavor ();
int n;
cairo_bool_t is_desktop = gl_flavor == CAIRO_GL_FLAVOR_DESKTOP;
cairo_bool_t is_gles = (gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
gl_flavor == CAIRO_GL_FLAVOR_ES2);
_cairo_device_init (&ctx->base, &_cairo_gl_device_backend);
/* XXX The choice of compositor should be made automatically at runtime.
* However, it is useful to force one particular compositor whilst
* testing.
*/
if (_cairo_gl_msaa_compositor_enabled ())
ctx->compositor = _cairo_gl_msaa_compositor_get ();
else
ctx->compositor = _cairo_gl_span_compositor_get ();
ctx->thread_aware = TRUE;
memset (ctx->glyph_cache, 0, sizeof (ctx->glyph_cache));
cairo_list_init (&ctx->fonts);
/* Support only GL version >= 1.3 */
if (gl_version < CAIRO_GL_VERSION_ENCODE (1, 3))
return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
/* Check for required extensions */
if (is_desktop) {
if (_cairo_gl_has_extension ("GL_ARB_texture_non_power_of_two")) {
ctx->tex_target = GL_TEXTURE_2D;
ctx->has_npot_repeat = TRUE;
} else if (_cairo_gl_has_extension ("GL_ARB_texture_rectangle")) {
ctx->tex_target = GL_TEXTURE_RECTANGLE;
ctx->has_npot_repeat = FALSE;
} else
return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
} else {
ctx->tex_target = GL_TEXTURE_2D;
if (_cairo_gl_has_extension ("GL_OES_texture_npot") ||
_cairo_gl_has_extension ("GL_IMG_texture_npot"))
ctx->has_npot_repeat = TRUE;
else
ctx->has_npot_repeat = FALSE;
}
if (is_desktop && gl_version < CAIRO_GL_VERSION_ENCODE (2, 1) &&
! _cairo_gl_has_extension ("GL_ARB_pixel_buffer_object"))
return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
if (is_gles && ! _cairo_gl_has_extension ("GL_EXT_texture_format_BGRA8888"))
return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
ctx->has_map_buffer =
is_desktop || (is_gles && _cairo_gl_has_extension ("GL_OES_mapbuffer"));
ctx->can_read_bgra = test_can_read_bgra (gl_flavor);
ctx->has_mesa_pack_invert =
_cairo_gl_has_extension ("GL_MESA_pack_invert");
ctx->has_packed_depth_stencil =
(is_desktop && _cairo_gl_has_extension ("GL_EXT_packed_depth_stencil")) ||
(is_gles && _cairo_gl_has_extension ("GL_OES_packed_depth_stencil"));
ctx->num_samples = 1;
#if CAIRO_HAS_GL_SURFACE
if (is_desktop && ctx->has_packed_depth_stencil &&
(gl_version >= CAIRO_GL_VERSION_ENCODE (3, 0) ||
_cairo_gl_has_extension ("GL_ARB_framebuffer_object") ||
(_cairo_gl_has_extension ("GL_EXT_framebuffer_blit") &&
_cairo_gl_has_extension ("GL_EXT_framebuffer_multisample")))) {
glGetIntegerv(GL_MAX_SAMPLES_EXT, &ctx->num_samples);
}
#endif
#if CAIRO_HAS_GLESV3_SURFACE
if (is_gles && ctx->has_packed_depth_stencil) {
glGetIntegerv(GL_MAX_SAMPLES, &ctx->num_samples);
}
#elif CAIRO_HAS_GLESV2_SURFACE && defined(GL_MAX_SAMPLES_EXT)
if (is_gles && ctx->has_packed_depth_stencil &&
_cairo_gl_has_extension ("GL_EXT_multisampled_render_to_texture")) {
glGetIntegerv(GL_MAX_SAMPLES_EXT, &ctx->num_samples);
}
if (is_gles && ctx->has_packed_depth_stencil &&
_cairo_gl_has_extension ("GL_IMG_multisampled_render_to_texture")) {
glGetIntegerv(GL_MAX_SAMPLES_IMG, &ctx->num_samples);
}
#endif
/* we always use renderbuffer for rendering in glesv3 */
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
ctx->supports_msaa = TRUE;
else
ctx->supports_msaa = ctx->num_samples > 1;
if (ctx->num_samples > MAX_MSAA_SAMPLES)
ctx->num_samples = MAX_MSAA_SAMPLES;
ctx->current_operator = -1;
ctx->gl_flavor = gl_flavor;
status = _cairo_gl_context_init_shaders (ctx);
if (unlikely (status))
return status;
status = _cairo_cache_init (&ctx->gradients,
_cairo_gl_gradient_equal,
NULL,
(cairo_destroy_func_t) _cairo_gl_gradient_destroy,
CAIRO_GL_GRADIENT_CACHE_SIZE);
if (unlikely (status))
return status;
ctx->vbo_size = _cairo_gl_get_vbo_size();
ctx->vb = _cairo_malloc (ctx->vbo_size);
if (unlikely (ctx->vb == NULL)) {
_cairo_cache_fini (&ctx->gradients);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
ctx->primitive_type = CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES;
_cairo_array_init (&ctx->tristrip_indices, sizeof (unsigned short));
/* PBO for any sort of texture upload */
dispatch->GenBuffers (1, &ctx->texture_load_pbo);
ctx->max_framebuffer_size = 0;
glGetIntegerv (GL_MAX_RENDERBUFFER_SIZE, &ctx->max_framebuffer_size);
ctx->max_texture_size = 0;
glGetIntegerv (GL_MAX_TEXTURE_SIZE, &ctx->max_texture_size);
ctx->max_textures = 0;
glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &ctx->max_textures);
for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++)
_cairo_gl_glyph_cache_init (&ctx->glyph_cache[n]);
return CAIRO_STATUS_SUCCESS;
}
void
_cairo_gl_context_activate (cairo_gl_context_t *ctx,
cairo_gl_tex_t tex_unit)
{
if (ctx->max_textures <= (GLint) tex_unit) {
if (tex_unit < 2) {
_cairo_gl_composite_flush (ctx);
_cairo_gl_context_destroy_operand (ctx, ctx->max_textures - 1);
}
glActiveTexture (ctx->max_textures - 1);
} else {
glActiveTexture (GL_TEXTURE0 + tex_unit);
}
}
static GLenum
_get_depth_stencil_format (cairo_gl_context_t *ctx)
{
/* This is necessary to properly handle the situation where both
OpenGL and OpenGLES are active and returning a sane default. */
#if CAIRO_HAS_GL_SURFACE
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
return GL_DEPTH_STENCIL;
#endif
#if CAIRO_HAS_GLESV2_SURFACE && !CAIRO_HAS_GLESV3_SURFACE
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
return GL_DEPTH24_STENCIL8_OES;
#endif
#if CAIRO_HAS_GL_SURFACE
return GL_DEPTH_STENCIL;
#elif CAIRO_HAS_GLESV3_SURFACE
return GL_DEPTH24_STENCIL8;
#elif CAIRO_HAS_GLESV2_SURFACE
return GL_DEPTH24_STENCIL8_OES;
#endif
}
#if CAIRO_HAS_GLESV2_SURFACE
static void
_cairo_gl_ensure_msaa_gles_framebuffer (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface)
{
if (surface->msaa_active)
return;
ctx->dispatch.FramebufferTexture2DMultisample(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
ctx->tex_target,
surface->tex,
0,
ctx->num_samples);
/* From now on MSAA will always be active on this surface. */
surface->msaa_active = TRUE;
}
#endif
void
_cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface)
{
GLenum status;
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
if (likely (surface->fb))
return;
/* Create a framebuffer object wrapping the texture so that we can render
* to it.
*/
dispatch->GenFramebuffers (1, &surface->fb);
dispatch->BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
/* Unlike for desktop GL we only maintain one multisampling framebuffer
for OpenGLES since the EXT_multisampled_render_to_texture extension
does not require an explicit multisample resolution. */
#if CAIRO_HAS_GLESV2_SURFACE
if (surface->supports_msaa && _cairo_gl_msaa_compositor_enabled () &&
ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) {
_cairo_gl_ensure_msaa_gles_framebuffer (ctx, surface);
} else
#endif
dispatch->FramebufferTexture2D (GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
ctx->tex_target,
surface->tex,
0);
#if CAIRO_HAS_GL_SURFACE
glDrawBuffer (GL_COLOR_ATTACHMENT0);
glReadBuffer (GL_COLOR_ATTACHMENT0);
#endif
status = dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
const char *str;
switch (status) {
//case GL_FRAMEBUFFER_UNDEFINED: str= "undefined"; break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: str= "incomplete attachment"; break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: str= "incomplete/missing attachment"; break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: str= "incomplete draw buffer"; break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: str= "incomplete read buffer"; break;
case GL_FRAMEBUFFER_UNSUPPORTED: str= "unsupported"; break;
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: str= "incomplete multiple"; break;
default: str = "unknown error"; break;
}
fprintf (stderr,
"destination is framebuffer incomplete: %s [%#x]\n",
str, status);
}
}
#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
static void
_cairo_gl_ensure_multisampling (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface)
{
assert (surface->supports_msaa);
assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3);
if (surface->msaa_fb)
return;
/* We maintain a separate framebuffer for multisampling operations.
This allows us to do a fast paint to the non-multisampling framebuffer
when mulitsampling is disabled. */
ctx->dispatch.GenFramebuffers (1, &surface->msaa_fb);
ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb);
ctx->dispatch.GenRenderbuffers (1, &surface->msaa_rb);
ctx->dispatch.BindRenderbuffer (GL_RENDERBUFFER, surface->msaa_rb);
/* FIXME: For now we assume that textures passed from the outside have GL_RGBA
format, but eventually we need to expose a way for the API consumer to pass
this information. */
ctx->dispatch.RenderbufferStorageMultisample (GL_RENDERBUFFER,
ctx->num_samples,
#if CAIRO_HAS_GLESV3_SURFACE
GL_RGBA8,
#else
GL_RGBA,
#endif
surface->width,
surface->height);
ctx->dispatch.FramebufferRenderbuffer (GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER,
surface->msaa_rb);
/* Cairo surfaces start out initialized to transparent (black) */
glDisable (GL_SCISSOR_TEST);
glClearColor (0, 0, 0, 0);
glClear (GL_COLOR_BUFFER_BIT);
/* for glesv3 with multisample renderbuffer, we always render to
this renderbuffer */
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
surface->msaa_active = TRUE;
}
#endif
static cairo_bool_t
_cairo_gl_ensure_msaa_depth_stencil_buffer (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
if (surface->msaa_depth_stencil)
return TRUE;
_cairo_gl_ensure_framebuffer (ctx, surface);
#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
_cairo_gl_ensure_multisampling (ctx, surface);
#endif
dispatch->GenRenderbuffers (1, &surface->msaa_depth_stencil);
dispatch->BindRenderbuffer (GL_RENDERBUFFER,
surface->msaa_depth_stencil);
dispatch->RenderbufferStorageMultisample (GL_RENDERBUFFER,
ctx->num_samples,
_get_depth_stencil_format (ctx),
surface->width,
surface->height);
#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) {
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER,
GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER,
surface->msaa_depth_stencil);
}
#endif
#if CAIRO_HAS_GLESV2_SURFACE
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) {
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER,
surface->msaa_depth_stencil);
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER,
GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER,
surface->msaa_depth_stencil);
}
#endif
if (dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
dispatch->DeleteRenderbuffers (1, &surface->msaa_depth_stencil);
surface->msaa_depth_stencil = 0;
return FALSE;
}
return TRUE;
}
static cairo_bool_t
_cairo_gl_ensure_depth_stencil_buffer (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
if (surface->depth_stencil)
return TRUE;
_cairo_gl_ensure_framebuffer (ctx, surface);
dispatch->GenRenderbuffers (1, &surface->depth_stencil);
dispatch->BindRenderbuffer (GL_RENDERBUFFER, surface->depth_stencil);
dispatch->RenderbufferStorage (GL_RENDERBUFFER,
_get_depth_stencil_format (ctx),
surface->width, surface->height);
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, surface->depth_stencil);
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, surface->depth_stencil);
if (dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
dispatch->DeleteRenderbuffers (1, &surface->depth_stencil);
surface->depth_stencil = 0;
return FALSE;
}
return TRUE;
}
cairo_bool_t
_cairo_gl_ensure_stencil (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface)
{
if (! _cairo_gl_surface_is_texture (surface))
return TRUE; /* best guess for now, will check later */
if (! ctx->has_packed_depth_stencil)
return FALSE;
if (surface->msaa_active)
return _cairo_gl_ensure_msaa_depth_stencil_buffer (ctx, surface);
else
return _cairo_gl_ensure_depth_stencil_buffer (ctx, surface);
}
/*
* Stores a parallel projection transformation in matrix 'm',
* using column-major order.
*
* This is equivalent to:
*
* glLoadIdentity()
* gluOrtho2D()
*
* The calculation for the ortho transformation was taken from the
* mesa source code.
*/
static void
_gl_identity_ortho (GLfloat *m,
GLfloat left, GLfloat right,
GLfloat bottom, GLfloat top)
{
#define M(row,col) m[col*4+row]
M(0,0) = 2.f / (right - left);
M(0,1) = 0.f;
M(0,2) = 0.f;
M(0,3) = -(right + left) / (right - left);
M(1,0) = 0.f;
M(1,1) = 2.f / (top - bottom);
M(1,2) = 0.f;
M(1,3) = -(top + bottom) / (top - bottom);
M(2,0) = 0.f;
M(2,1) = 0.f;
M(2,2) = -1.f;
M(2,3) = 0.f;
M(3,0) = 0.f;
M(3,1) = 0.f;
M(3,2) = 0.f;
M(3,3) = 1.f;
#undef M
}
#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
static void
bind_multisample_framebuffer (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface)
{
cairo_bool_t stencil_test_enabled;
cairo_bool_t scissor_test_enabled;
assert (surface->supports_msaa);
assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3);
_cairo_gl_ensure_framebuffer (ctx, surface);
_cairo_gl_ensure_multisampling (ctx, surface);
if (surface->msaa_active) {
#if CAIRO_HAS_GL_SURFACE
glEnable (GL_MULTISAMPLE);
#endif
ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb);
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
surface->content_in_texture = FALSE;
return;
}
_cairo_gl_composite_flush (ctx);
stencil_test_enabled = glIsEnabled (GL_STENCIL_TEST);
scissor_test_enabled = glIsEnabled (GL_SCISSOR_TEST);
glDisable (GL_STENCIL_TEST);
glDisable (GL_SCISSOR_TEST);
#if CAIRO_HAS_GL_SURFACE
glEnable (GL_MULTISAMPLE);
#endif
/* The last time we drew to the surface, we were not using multisampling,
so we need to blit from the non-multisampling framebuffer into the
multisampling framebuffer. */
ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER, surface->msaa_fb);
ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER, surface->fb);
ctx->dispatch.BlitFramebuffer (0, 0, surface->width, surface->height,
0, 0, surface->width, surface->height,
GL_COLOR_BUFFER_BIT
#if CAIRO_HAS_GL_SURFACE
| GL_STENCIL_BUFFER_BIT
#endif
,
GL_NEAREST);
ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb);
if (stencil_test_enabled)
glEnable (GL_STENCIL_TEST);
if (scissor_test_enabled)
glEnable (GL_SCISSOR_TEST);
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
surface->content_in_texture = FALSE;
}
#endif
#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
static void
bind_singlesample_framebuffer (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface)
{
cairo_bool_t stencil_test_enabled;
cairo_bool_t scissor_test_enabled;
assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3);
_cairo_gl_ensure_framebuffer (ctx, surface);
if (! surface->msaa_active) {
#if CAIRO_HAS_GL_SURFACE
glDisable (GL_MULTISAMPLE);
#endif
ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
return;
}
_cairo_gl_composite_flush (ctx);
stencil_test_enabled = glIsEnabled (GL_STENCIL_TEST);
scissor_test_enabled = glIsEnabled (GL_SCISSOR_TEST);
glDisable (GL_STENCIL_TEST);
glDisable (GL_SCISSOR_TEST);
#if CAIRO_HAS_GL_SURFACE
glDisable (GL_MULTISAMPLE);
#endif
/* The last time we drew to the surface, we were using multisampling,
so we need to blit from the multisampling framebuffer into the
non-multisampling framebuffer. */
ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER, surface->fb);
ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER, surface->msaa_fb);
ctx->dispatch.BlitFramebuffer (0, 0, surface->width, surface->height,
0, 0, surface->width, surface->height,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
if (stencil_test_enabled)
glEnable (GL_STENCIL_TEST);
if (scissor_test_enabled)
glEnable (GL_SCISSOR_TEST);
}
#endif
void
_cairo_gl_context_bind_framebuffer (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface,
cairo_bool_t multisampling)
{
if (_cairo_gl_surface_is_texture (surface)) {
/* OpenGL ES surfaces only have either a multisample framebuffer or a
* singlesample framebuffer, so we cannot switch back and forth. */
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) {
_cairo_gl_ensure_framebuffer (ctx, surface);
ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
return;
}
#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
if (multisampling)
bind_multisample_framebuffer (ctx, surface);
else
bind_singlesample_framebuffer (ctx, surface);
#endif
} else {
ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, 0);
#if CAIRO_HAS_GL_SURFACE
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) {
if (multisampling)
glEnable (GL_MULTISAMPLE);
else
glDisable (GL_MULTISAMPLE);
}
#endif
}
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
surface->msaa_active = multisampling;
}
void
_cairo_gl_context_set_destination (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface,
cairo_bool_t multisampling)
{
cairo_bool_t changing_surface, changing_sampling;
/* The decision whether or not to use multisampling happens when
* we create an OpenGL ES surface, so we can never switch modes. */
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2)
multisampling = surface->msaa_active;
/* For GLESV3, we always use renderbuffer for drawing */
else if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
multisampling = TRUE;
changing_surface = ctx->current_target != surface || surface->needs_update;
changing_sampling = (surface->msaa_active != multisampling ||
surface->content_in_texture);
if (! changing_surface && ! changing_sampling)
return;
if (! changing_surface) {
_cairo_gl_composite_flush (ctx);
_cairo_gl_context_bind_framebuffer (ctx, surface, multisampling);
return;
}
_cairo_gl_composite_flush (ctx);
ctx->current_target = surface;
surface->needs_update = FALSE;
if (! _cairo_gl_surface_is_texture (surface)) {
ctx->make_current (ctx, surface);
}
_cairo_gl_context_bind_framebuffer (ctx, surface, multisampling);
if (! _cairo_gl_surface_is_texture (surface)) {
#if CAIRO_HAS_GL_SURFACE
glDrawBuffer (GL_BACK_LEFT);
glReadBuffer (GL_BACK_LEFT);
#endif
}
glDisable (GL_DITHER);
glViewport (0, 0, surface->width, surface->height);
if (_cairo_gl_surface_is_texture (surface))
_gl_identity_ortho (ctx->modelviewprojection_matrix,
0, surface->width, 0, surface->height);
else
_gl_identity_ortho (ctx->modelviewprojection_matrix,
0, surface->width, surface->height, 0);
}
void
cairo_gl_device_set_thread_aware (cairo_device_t *device,
cairo_bool_t thread_aware)
{
if (device->backend->type != CAIRO_DEVICE_TYPE_GL) {
_cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
return;
}
((cairo_gl_context_t *) device)->thread_aware = thread_aware;
}

Просмотреть файл

@ -0,0 +1,129 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2010 Linaro Limited
*
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.
*
* Contributor(s):
* Alexandros Frantzis <alexandros.frantzis@linaro.org>
*/
#ifndef CAIRO_GL_DISPATCH_PRIVATE_H
#define CAIRO_GL_DISPATCH_PRIVATE_H
#include "cairo-gl-private.h"
#include <stddef.h>
typedef enum _cairo_gl_dispatch_name {
CAIRO_GL_DISPATCH_NAME_CORE,
CAIRO_GL_DISPATCH_NAME_EXT,
CAIRO_GL_DISPATCH_NAME_ES,
CAIRO_GL_DISPATCH_NAME_COUNT
} cairo_gl_dispatch_name_t;
typedef struct _cairo_gl_dispatch_entry {
const char *name[CAIRO_GL_DISPATCH_NAME_COUNT];
size_t offset;
} cairo_gl_dispatch_entry_t;
#define DISPATCH_ENTRY_ARB(name) { { "gl"#name, "gl"#name"ARB", "gl"#name }, \
offsetof(cairo_gl_dispatch_t, name) }
#define DISPATCH_ENTRY_EXT(name) { { "gl"#name, "gl"#name"EXT", "gl"#name }, \
offsetof(cairo_gl_dispatch_t, name) }
#define DISPATCH_ENTRY_ARB_OES(name) { { "gl"#name, "gl"#name"ARB", "gl"#name"OES" }, \
offsetof(cairo_gl_dispatch_t, name) }
#define DISPATCH_ENTRY_EXT_IMG(name) { { "gl"#name, "gl"#name"EXT", "gl"#name"IMG" }, \
offsetof(cairo_gl_dispatch_t, name) }
#define DISPATCH_ENTRY_CUSTOM(name, name2) { { "gl"#name, "gl"#name2, "gl"#name }, \
offsetof(cairo_gl_dispatch_t, name)}
#define DISPATCH_ENTRY_LAST { { NULL, NULL, NULL }, 0 }
cairo_private cairo_gl_dispatch_entry_t dispatch_buffers_entries[] = {
DISPATCH_ENTRY_ARB (GenBuffers),
DISPATCH_ENTRY_ARB (BindBuffer),
DISPATCH_ENTRY_ARB (BufferData),
DISPATCH_ENTRY_ARB_OES (MapBuffer),
DISPATCH_ENTRY_ARB_OES (UnmapBuffer),
DISPATCH_ENTRY_LAST
};
cairo_private cairo_gl_dispatch_entry_t dispatch_shaders_entries[] = {
/* Shaders */
DISPATCH_ENTRY_CUSTOM (CreateShader, CreateShaderObjectARB),
DISPATCH_ENTRY_ARB (ShaderSource),
DISPATCH_ENTRY_ARB (CompileShader),
DISPATCH_ENTRY_CUSTOM (GetShaderiv, GetObjectParameterivARB),
DISPATCH_ENTRY_CUSTOM (GetShaderInfoLog, GetInfoLogARB),
DISPATCH_ENTRY_CUSTOM (DeleteShader, DeleteObjectARB),
/* Programs */
DISPATCH_ENTRY_CUSTOM (CreateProgram, CreateProgramObjectARB),
DISPATCH_ENTRY_CUSTOM (AttachShader, AttachObjectARB),
DISPATCH_ENTRY_CUSTOM (DeleteProgram, DeleteObjectARB),
DISPATCH_ENTRY_ARB (LinkProgram),
DISPATCH_ENTRY_CUSTOM (UseProgram, UseProgramObjectARB),
DISPATCH_ENTRY_CUSTOM (GetProgramiv, GetObjectParameterivARB),
DISPATCH_ENTRY_CUSTOM (GetProgramInfoLog, GetInfoLogARB),
/* Uniforms */
DISPATCH_ENTRY_ARB (GetUniformLocation),
DISPATCH_ENTRY_ARB (Uniform1f),
DISPATCH_ENTRY_ARB (Uniform2f),
DISPATCH_ENTRY_ARB (Uniform3f),
DISPATCH_ENTRY_ARB (Uniform4f),
DISPATCH_ENTRY_ARB (UniformMatrix3fv),
DISPATCH_ENTRY_ARB (UniformMatrix4fv),
DISPATCH_ENTRY_ARB (Uniform1i),
/* Attributes */
DISPATCH_ENTRY_ARB (BindAttribLocation),
DISPATCH_ENTRY_ARB (VertexAttribPointer),
DISPATCH_ENTRY_ARB (EnableVertexAttribArray),
DISPATCH_ENTRY_ARB (DisableVertexAttribArray),
DISPATCH_ENTRY_LAST
};
cairo_private cairo_gl_dispatch_entry_t dispatch_fbo_entries[] = {
DISPATCH_ENTRY_EXT (GenFramebuffers),
DISPATCH_ENTRY_EXT (BindFramebuffer),
DISPATCH_ENTRY_EXT (FramebufferTexture2D),
DISPATCH_ENTRY_EXT (CheckFramebufferStatus),
DISPATCH_ENTRY_EXT (DeleteFramebuffers),
DISPATCH_ENTRY_EXT (GenRenderbuffers),
DISPATCH_ENTRY_EXT (BindRenderbuffer),
DISPATCH_ENTRY_EXT (RenderbufferStorage),
DISPATCH_ENTRY_EXT (FramebufferRenderbuffer),
DISPATCH_ENTRY_EXT (DeleteRenderbuffers),
DISPATCH_ENTRY_EXT (BlitFramebuffer),
DISPATCH_ENTRY_LAST
};
cairo_private cairo_gl_dispatch_entry_t dispatch_multisampling_entries[] = {
DISPATCH_ENTRY_EXT_IMG (RenderbufferStorageMultisample),
DISPATCH_ENTRY_EXT_IMG (FramebufferTexture2DMultisample),
DISPATCH_ENTRY_LAST
};
#endif /* CAIRO_GL_DISPATCH_PRIVATE_H */

Просмотреть файл

@ -0,0 +1,273 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2010 Linaro Limited
*
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.
*
* Contributor(s):
* Alexandros Frantzis <alexandros.frantzis@linaro.org>
*/
#include "cairoint.h"
#include "cairo-gl-private.h"
#include "cairo-gl-dispatch-private.h"
#if CAIRO_HAS_DLSYM
#include <dlfcn.h>
#endif
#if CAIRO_HAS_DLSYM
static void *
_cairo_gl_dispatch_open_lib (void)
{
return dlopen (NULL, RTLD_LAZY);
}
static void
_cairo_gl_dispatch_close_lib (void *handle)
{
dlclose (handle);
}
static cairo_gl_generic_func_t
_cairo_gl_dispatch_get_proc_addr (void *handle, const char *name)
{
return (cairo_gl_generic_func_t) dlsym (handle, name);
}
#else
static void *
_cairo_gl_dispatch_open_lib (void)
{
return NULL;
}
static void
_cairo_gl_dispatch_close_lib (void *handle)
{
return;
}
static cairo_gl_generic_func_t
_cairo_gl_dispatch_get_proc_addr (void *handle, const char *name)
{
return NULL;
}
#endif /* CAIRO_HAS_DLSYM */
static void
_cairo_gl_dispatch_init_entries (cairo_gl_dispatch_t *dispatch,
cairo_gl_get_proc_addr_func_t get_proc_addr,
cairo_gl_dispatch_entry_t *entries,
cairo_gl_dispatch_name_t dispatch_name)
{
cairo_gl_dispatch_entry_t *entry = entries;
void *handle = _cairo_gl_dispatch_open_lib ();
while (entry->name[CAIRO_GL_DISPATCH_NAME_CORE] != NULL) {
void *dispatch_ptr = &((char *) dispatch)[entry->offset];
const char *name = entry->name[dispatch_name];
/*
* In strictly conforming EGL implementations, eglGetProcAddress() can
* be used only to get extension functions, but some of the functions
* we want belong to core GL(ES). If the *GetProcAddress function
* provided by the context fails, try to get the address of the wanted
* GL function using standard system facilities (eg dlsym() in *nix
* systems).
*/
cairo_gl_generic_func_t func = get_proc_addr (name);
if (func == NULL)
func = _cairo_gl_dispatch_get_proc_addr (handle, name);
*((cairo_gl_generic_func_t *) dispatch_ptr) = func;
++entry;
}
_cairo_gl_dispatch_close_lib (handle);
}
static cairo_status_t
_cairo_gl_dispatch_init_buffers (cairo_gl_dispatch_t *dispatch,
cairo_gl_get_proc_addr_func_t get_proc_addr,
int gl_version, cairo_gl_flavor_t gl_flavor)
{
cairo_gl_dispatch_name_t dispatch_name;
if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
{
if (gl_version >= CAIRO_GL_VERSION_ENCODE (1, 5))
dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE;
else if (_cairo_gl_has_extension ("GL_ARB_vertex_buffer_object"))
dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT;
else
return CAIRO_STATUS_DEVICE_ERROR;
}
else if (gl_flavor == CAIRO_GL_FLAVOR_ES3)
{
dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE;
}
else if (gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0))
{
dispatch_name = CAIRO_GL_DISPATCH_NAME_ES;
}
else
{
return CAIRO_STATUS_DEVICE_ERROR;
}
_cairo_gl_dispatch_init_entries (dispatch, get_proc_addr,
dispatch_buffers_entries, dispatch_name);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_gl_dispatch_init_shaders (cairo_gl_dispatch_t *dispatch,
cairo_gl_get_proc_addr_func_t get_proc_addr,
int gl_version, cairo_gl_flavor_t gl_flavor)
{
cairo_gl_dispatch_name_t dispatch_name;
if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
{
if (gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0))
dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE;
else if (_cairo_gl_has_extension ("GL_ARB_shader_objects"))
dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT;
else
return CAIRO_STATUS_DEVICE_ERROR;
}
else if (gl_flavor == CAIRO_GL_FLAVOR_ES3)
{
dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE;
}
else if (gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0))
{
dispatch_name = CAIRO_GL_DISPATCH_NAME_ES;
}
else
{
return CAIRO_STATUS_DEVICE_ERROR;
}
_cairo_gl_dispatch_init_entries (dispatch, get_proc_addr,
dispatch_shaders_entries, dispatch_name);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_gl_dispatch_init_fbo (cairo_gl_dispatch_t *dispatch,
cairo_gl_get_proc_addr_func_t get_proc_addr,
int gl_version, cairo_gl_flavor_t gl_flavor)
{
cairo_gl_dispatch_name_t dispatch_name;
if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
{
if (gl_version >= CAIRO_GL_VERSION_ENCODE (3, 0) ||
_cairo_gl_has_extension ("GL_ARB_framebuffer_object"))
dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE;
else if (_cairo_gl_has_extension ("GL_EXT_framebuffer_object"))
dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT;
else
return CAIRO_STATUS_DEVICE_ERROR;
}
else if (gl_flavor == CAIRO_GL_FLAVOR_ES3)
{
dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE;
}
else if (gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0))
{
dispatch_name = CAIRO_GL_DISPATCH_NAME_ES;
}
else
{
return CAIRO_STATUS_DEVICE_ERROR;
}
_cairo_gl_dispatch_init_entries (dispatch, get_proc_addr,
dispatch_fbo_entries, dispatch_name);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_gl_dispatch_init_multisampling (cairo_gl_dispatch_t *dispatch,
cairo_gl_get_proc_addr_func_t get_proc_addr,
int gl_version,
cairo_gl_flavor_t gl_flavor)
{
/* For the multisampling table, there are two GLES versions of the
* extension, so we put one in the EXT slot and one in the real ES slot.*/
cairo_gl_dispatch_name_t dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE;
if (gl_flavor == CAIRO_GL_FLAVOR_ES2) {
if (_cairo_gl_has_extension ("GL_EXT_multisampled_render_to_texture"))
dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT;
else if (_cairo_gl_has_extension ("GL_IMG_multisampled_render_to_texture"))
dispatch_name = CAIRO_GL_DISPATCH_NAME_ES;
}
_cairo_gl_dispatch_init_entries (dispatch, get_proc_addr,
dispatch_multisampling_entries,
dispatch_name);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_gl_dispatch_init (cairo_gl_dispatch_t *dispatch,
cairo_gl_get_proc_addr_func_t get_proc_addr)
{
cairo_status_t status;
int gl_version;
cairo_gl_flavor_t gl_flavor;
gl_version = _cairo_gl_get_version ();
gl_flavor = _cairo_gl_get_flavor ();
status = _cairo_gl_dispatch_init_buffers (dispatch, get_proc_addr,
gl_version, gl_flavor);
if (status != CAIRO_STATUS_SUCCESS)
return status;
status = _cairo_gl_dispatch_init_shaders (dispatch, get_proc_addr,
gl_version, gl_flavor);
if (status != CAIRO_STATUS_SUCCESS)
return status;
status = _cairo_gl_dispatch_init_fbo (dispatch, get_proc_addr,
gl_version, gl_flavor);
if (status != CAIRO_STATUS_SUCCESS)
return status;
status = _cairo_gl_dispatch_init_multisampling (dispatch, get_proc_addr,
gl_version, gl_flavor);
if (status != CAIRO_STATUS_SUCCESS)
return status;
return CAIRO_STATUS_SUCCESS;
}

Просмотреть файл

@ -0,0 +1,143 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2010 Linaro Limited
*
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.
*
* Contributor(s):
* Alexandros Frantzis <alexandros.frantzis@linaro.org>
*/
#ifndef CAIRO_GL_EXT_DEF_PRIVATE_H
#define CAIRO_GL_EXT_DEF_PRIVATE_H
#ifndef GL_TEXTURE_RECTANGLE
#define GL_TEXTURE_RECTANGLE 0x84F5
#endif
#ifndef GL_ARRAY_BUFFER
#define GL_ARRAY_BUFFER 0x8892
#endif
#ifndef GL_STREAM_DRAW
#define GL_STREAM_DRAW 0x88E0
#endif
#ifndef GL_WRITE_ONLY
#define GL_WRITE_ONLY 0x88B9
#endif
#ifndef GL_PIXEL_UNPACK_BUFFER
#define GL_PIXEL_UNPACK_BUFFER 0x88EC
#endif
#ifndef GL_FRAMEBUFFER
#define GL_FRAMEBUFFER 0x8D40
#endif
#ifndef GL_COLOR_ATTACHMENT0
#define GL_COLOR_ATTACHMENT0 0x8CE0
#endif
#ifndef GL_FRAMEBUFFER_COMPLETE
#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
#endif
#ifndef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
#endif
#ifndef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
#endif
#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
#endif
#ifndef GL_FRAMEBUFFER_INCOMPLETE_FORMATS
#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS 0x8CDA
#endif
#ifndef GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER
#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
#endif
#ifndef GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER
#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
#endif
#ifndef GL_FRAMEBUFFER_UNSUPPORTED
#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
#endif
#ifndef GL_PACK_INVERT_MESA
#define GL_PACK_INVERT_MESA 0x8758
#endif
#ifndef GL_CLAMP_TO_BORDER
#define GL_CLAMP_TO_BORDER 0x812D
#endif
#ifndef GL_BGR
#define GL_BGR 0x80E0
#endif
#ifndef GL_BGRA
#define GL_BGRA 0x80E1
#endif
#ifndef GL_RGBA8
#define GL_RGBA8 0x8058
#endif
#ifndef GL_UNSIGNED_INT_8_8_8_8
#define GL_UNSIGNED_INT_8_8_8_8 0x8035
#endif
#ifndef GL_UNSIGNED_SHORT_5_6_5_REV
#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
#endif
#ifndef GL_UNSIGNED_SHORT_1_5_5_5_REV
#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
#endif
#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
#endif
#ifndef GL_PACK_ROW_LENGTH
#define GL_PACK_ROW_LENGTH 0x0D02
#endif
#ifndef GL_UNPACK_ROW_LENGTH
#define GL_UNPACK_ROW_LENGTH 0x0CF2
#endif
#ifndef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
#endif
#endif /* CAIRO_GL_EXT_DEF_PRIVATE_H */

Просмотреть файл

@ -40,7 +40,10 @@
#include "cairo-gl-private.h"
#include "cairo-compositor-private.h"
#include "cairo-composite-rectangles-private.h"
#include "cairo-error-private.h"
#include "cairo-image-surface-private.h"
#include "cairo-rtree-private.h"
#define GLYPH_CACHE_WIDTH 1024
@ -48,22 +51,61 @@
#define GLYPH_CACHE_MIN_SIZE 4
#define GLYPH_CACHE_MAX_SIZE 128
typedef struct _cairo_gl_glyph_private {
typedef struct _cairo_gl_glyph {
cairo_rtree_node_t node;
cairo_scaled_glyph_private_t base;
cairo_scaled_glyph_t *glyph;
cairo_gl_glyph_cache_t *cache;
struct { float x, y; } p1, p2;
} cairo_gl_glyph_private_t;
} cairo_gl_glyph_t;
static cairo_status_t
static void
_cairo_gl_node_destroy (cairo_rtree_node_t *node)
{
cairo_gl_glyph_t *priv = cairo_container_of (node, cairo_gl_glyph_t, node);
cairo_scaled_glyph_t *glyph;
glyph = priv->glyph;
if (glyph == NULL)
return;
if (glyph->dev_private_key == priv->cache) {
glyph->dev_private = NULL;
glyph->dev_private_key = NULL;
}
cairo_list_del (&priv->base.link);
priv->glyph = NULL;
}
static void
_cairo_gl_glyph_fini (cairo_scaled_glyph_private_t *glyph_private,
cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_font_t *scaled_font)
{
cairo_gl_glyph_t *priv = cairo_container_of (glyph_private,
cairo_gl_glyph_t,
base);
assert (priv->glyph);
_cairo_gl_node_destroy (&priv->node);
/* XXX thread-safety? Probably ok due to the frozen scaled-font. */
if (! priv->node.pinned)
_cairo_rtree_node_remove (&priv->cache->rtree, &priv->node);
assert (priv->glyph == NULL);
}
static cairo_int_status_t
_cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
cairo_gl_glyph_cache_t *cache,
cairo_scaled_glyph_t *scaled_glyph)
{
cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
cairo_gl_surface_t *cache_surface;
cairo_gl_glyph_private_t *glyph_private;
cairo_gl_glyph_t *glyph_private;
cairo_rtree_node_t *node = NULL;
cairo_status_t status;
cairo_int_status_t status;
int width, height;
width = glyph_surface->width;
@ -78,32 +120,34 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
/* search for an unlocked slot */
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
status = _cairo_rtree_evict_random (&cache->rtree,
width, height, &node);
if (status == CAIRO_STATUS_SUCCESS) {
width, height, &node);
if (status == CAIRO_INT_STATUS_SUCCESS) {
status = _cairo_rtree_node_insert (&cache->rtree,
node, width, height, &node);
node, width, height, &node);
}
}
if (status)
return status;
cache_surface = (cairo_gl_surface_t *) cache->pattern.surface;
/* XXX: Make sure we use the mask texture. This should work automagically somehow */
glActiveTexture (GL_TEXTURE1);
status = _cairo_gl_surface_draw_image (cache_surface,
glyph_surface,
0, 0,
glyph_surface->width, glyph_surface->height,
node->x, node->y);
status = _cairo_gl_surface_draw_image (cache->surface, glyph_surface,
0, 0,
glyph_surface->width, glyph_surface->height,
node->x, node->y, FALSE);
if (unlikely (status))
return status;
scaled_glyph->surface_private = node;
node->owner = &scaled_glyph->surface_private;
glyph_private = (cairo_gl_glyph_private_t *) node;
glyph_private = (cairo_gl_glyph_t *) node;
glyph_private->cache = cache;
glyph_private->glyph = scaled_glyph;
_cairo_scaled_glyph_attach_private (scaled_glyph,
&glyph_private->base,
cache,
_cairo_gl_glyph_fini);
scaled_glyph->dev_private = glyph_private;
scaled_glyph->dev_private_key = cache;
/* compute tex coords */
glyph_private->p1.x = node->x;
@ -111,177 +155,119 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
glyph_private->p2.x = node->x + glyph_surface->width;
glyph_private->p2.y = node->y + glyph_surface->height;
if (! _cairo_gl_device_requires_power_of_two_textures (&ctx->base)) {
glyph_private->p1.x /= cache_surface->width;
glyph_private->p1.y /= cache_surface->height;
glyph_private->p2.x /= cache_surface->width;
glyph_private->p2.y /= cache_surface->height;
glyph_private->p1.x /= GLYPH_CACHE_WIDTH;
glyph_private->p2.x /= GLYPH_CACHE_WIDTH;
glyph_private->p1.y /= GLYPH_CACHE_HEIGHT;
glyph_private->p2.y /= GLYPH_CACHE_HEIGHT;
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_gl_glyph_private_t *
static cairo_gl_glyph_t *
_cairo_gl_glyph_cache_lock (cairo_gl_glyph_cache_t *cache,
cairo_scaled_glyph_t *scaled_glyph)
{
return _cairo_rtree_pin (&cache->rtree, scaled_glyph->surface_private);
return _cairo_rtree_pin (&cache->rtree, scaled_glyph->dev_private);
}
static cairo_status_t
cairo_gl_context_get_glyph_cache (cairo_gl_context_t *ctx,
cairo_format_t format,
cairo_gl_glyph_cache_t **cache_out)
cairo_gl_glyph_cache_t **cache_out)
{
cairo_gl_glyph_cache_t *cache;
cairo_content_t content;
switch (format) {
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_RGB16_565:
case CAIRO_FORMAT_ARGB32:
case CAIRO_FORMAT_RGB24:
cache = &ctx->glyph_cache[0];
content = CAIRO_CONTENT_COLOR_ALPHA;
content = CAIRO_CONTENT_COLOR_ALPHA;
break;
case CAIRO_FORMAT_A8:
case CAIRO_FORMAT_A1:
cache = &ctx->glyph_cache[1];
content = CAIRO_CONTENT_ALPHA;
content = CAIRO_CONTENT_ALPHA;
break;
default:
case CAIRO_FORMAT_INVALID:
ASSERT_NOT_REACHED;
return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
}
if (unlikely (cache->pattern.surface == NULL)) {
cairo_surface_t *surface;
surface = cairo_gl_surface_create (&ctx->base,
content,
GLYPH_CACHE_WIDTH,
GLYPH_CACHE_HEIGHT);
if (unlikely (surface->status)) {
cairo_status_t status = surface->status;
cairo_surface_destroy (surface);
return status;
}
_cairo_surface_release_device_reference (surface);
_cairo_pattern_init_for_surface (&cache->pattern, surface);
cairo_surface_destroy (surface);
cache->pattern.base.has_component_alpha = (content == CAIRO_CONTENT_COLOR_ALPHA);
if (unlikely (cache->surface == NULL)) {
cairo_surface_t *surface;
surface = _cairo_gl_surface_create_scratch_for_caching (ctx,
content,
GLYPH_CACHE_WIDTH,
GLYPH_CACHE_HEIGHT);
if (unlikely (surface->status))
return surface->status;
_cairo_surface_release_device_reference (surface);
cache->surface = (cairo_gl_surface_t *)surface;
cache->surface->operand.texture.attributes.has_component_alpha =
content == CAIRO_CONTENT_COLOR_ALPHA;
}
*cache_out = cache;
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_gl_glyph_cache_unlock (cairo_gl_glyph_cache_t *cache)
{
_cairo_rtree_unpin (&cache->rtree);
}
static cairo_bool_t
_cairo_gl_surface_owns_font (cairo_gl_surface_t *surface,
cairo_scaled_font_t *scaled_font)
{
cairo_device_t *font_private;
font_private = scaled_font->surface_private;
if ((scaled_font->surface_backend != NULL &&
scaled_font->surface_backend != &_cairo_gl_surface_backend) ||
(font_private != NULL && font_private != surface->base.device))
{
return FALSE;
}
return TRUE;
}
void
_cairo_gl_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
{
cairo_list_del (&scaled_font->link);
}
void
_cairo_gl_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_font_t *scaled_font)
{
cairo_gl_glyph_private_t *glyph_private;
glyph_private = scaled_glyph->surface_private;
if (glyph_private != NULL) {
glyph_private->node.owner = NULL;
if (! glyph_private->node.pinned) {
/* XXX thread-safety? Probably ok due to the frozen scaled-font. */
_cairo_rtree_node_remove (&glyph_private->cache->rtree,
&glyph_private->node);
}
}
}
static cairo_status_t
_render_glyphs (cairo_gl_surface_t *dst,
int dst_x, int dst_y,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
const cairo_rectangle_int_t *glyph_extents,
cairo_scaled_font_t *scaled_font,
cairo_bool_t *has_component_alpha,
cairo_region_t *clip_region,
int *remaining_glyphs)
render_glyphs (cairo_gl_surface_t *dst,
int dst_x, int dst_y,
cairo_operator_t op,
cairo_surface_t *source,
cairo_composite_glyphs_info_t *info,
cairo_bool_t *has_component_alpha,
cairo_clip_t *clip)
{
cairo_format_t last_format = CAIRO_FORMAT_INVALID;
cairo_gl_glyph_cache_t *cache = NULL;
cairo_gl_context_t *ctx;
cairo_gl_emit_glyph_t emit = NULL;
cairo_gl_composite_t setup;
cairo_status_t status;
cairo_int_status_t status;
int i = 0;
TRACE ((stderr, "%s (%d, %d)x(%d, %d)\n", __FUNCTION__,
info->extents.x, info->extents.y,
info->extents.width, info->extents.height));
*has_component_alpha = FALSE;
status = _cairo_gl_context_acquire (dst->base.device, &ctx);
if (unlikely (status))
return status;
_cairo_scaled_font_freeze_cache (scaled_font);
status = _cairo_gl_composite_init (&setup, op, dst,
TRUE, glyph_extents);
status = _cairo_gl_composite_init (&setup, op, dst, TRUE);
if (unlikely (status))
goto FINISH;
if (! _cairo_gl_surface_owns_font (dst, scaled_font)) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto FINISH;
if (source == NULL) {
_cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_WHITE);
} else {
_cairo_gl_composite_set_source_operand (&setup,
source_to_operand (source));
}
status = _cairo_gl_composite_set_source (&setup, source,
glyph_extents->x, glyph_extents->y,
dst_x, dst_y,
glyph_extents->width,
glyph_extents->height);
if (unlikely (status))
goto FINISH;
_cairo_gl_composite_set_clip (&setup, clip);
if (scaled_font->surface_private == NULL) {
scaled_font->surface_private = ctx;
scaled_font->surface_backend = &_cairo_gl_surface_backend;
cairo_list_add (&scaled_font->link, &ctx->fonts);
}
_cairo_gl_composite_set_clip_region (&setup, clip_region);
for (i = 0; i < num_glyphs; i++) {
for (i = 0; i < info->num_glyphs; i++) {
cairo_scaled_glyph_t *scaled_glyph;
cairo_gl_glyph_private_t *glyph;
cairo_gl_glyph_t *glyph;
double x_offset, y_offset;
double x1, x2, y1, y2;
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
status = _cairo_scaled_glyph_lookup (info->font,
info->glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyph);
if (unlikely (status))
@ -292,133 +278,135 @@ _render_glyphs (cairo_gl_surface_t *dst,
{
continue;
}
if (scaled_glyph->surface->width > GLYPH_CACHE_MAX_SIZE ||
scaled_glyph->surface->height > GLYPH_CACHE_MAX_SIZE)
{
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto FINISH;
}
if (scaled_glyph->surface->format != last_format) {
status = cairo_gl_context_get_glyph_cache (ctx,
scaled_glyph->surface->format,
&cache);
if (unlikely (status))
goto FINISH;
&cache);
if (unlikely (status))
goto FINISH;
last_format = scaled_glyph->surface->format;
status = _cairo_gl_composite_set_mask (&setup,
&cache->pattern.base,
0, 0, 0, 0, 0, 0);
if (unlikely (status))
goto FINISH;
_cairo_gl_composite_set_mask_operand (&setup, &cache->surface->operand);
*has_component_alpha |= cache->surface->operand.texture.attributes.has_component_alpha;
*has_component_alpha |= cache->pattern.base.has_component_alpha;
/* XXX: _cairo_gl_composite_begin() acquires the context a
* second time. Need to refactor this loop so this doesn't happen.
*/
status = _cairo_gl_composite_begin (&setup, &ctx);
status = _cairo_gl_context_release (ctx, status);
/* XXX Shoot me. */
status = _cairo_gl_composite_begin (&setup, &ctx);
status = _cairo_gl_context_release (ctx, status);
if (unlikely (status))
goto FINISH;
emit = _cairo_gl_context_choose_emit_glyph (ctx);
}
if (scaled_glyph->surface_private == NULL) {
status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph);
if (scaled_glyph->dev_private_key != cache) {
cairo_scaled_glyph_private_t *priv;
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
/* Cache is full, so flush existing prims and try again. */
_cairo_gl_composite_flush (ctx);
_cairo_gl_glyph_cache_unlock (cache);
priv = _cairo_scaled_glyph_find_private (scaled_glyph, cache);
if (priv) {
scaled_glyph->dev_private_key = cache;
scaled_glyph->dev_private = cairo_container_of (priv,
cairo_gl_glyph_t,
base);
} else {
status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph);
}
if (unlikely (_cairo_status_is_error (status)))
goto FINISH;
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
/* Cache is full, so flush existing prims and try again. */
_cairo_gl_composite_flush (ctx);
_cairo_gl_glyph_cache_unlock (cache);
status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph);
}
if (unlikely (_cairo_int_status_is_error (status)))
goto FINISH;
}
}
x_offset = scaled_glyph->surface->base.device_transform.x0;
y_offset = scaled_glyph->surface->base.device_transform.y0;
x1 = _cairo_lround (glyphs[i].x - x_offset);
y1 = _cairo_lround (glyphs[i].y - y_offset);
x1 = _cairo_lround (info->glyphs[i].x - x_offset - dst_x);
y1 = _cairo_lround (info->glyphs[i].y - y_offset - dst_y);
x2 = x1 + scaled_glyph->surface->width;
y2 = y1 + scaled_glyph->surface->height;
glyph = _cairo_gl_glyph_cache_lock (cache, scaled_glyph);
_cairo_gl_composite_emit_glyph (ctx,
x1, y1, x2, y2,
glyph->p1.x, glyph->p1.y,
glyph->p2.x, glyph->p2.y);
assert (emit);
emit (ctx,
x1, y1, x2, y2,
glyph->p1.x, glyph->p1.y,
glyph->p2.x, glyph->p2.y);
}
status = CAIRO_STATUS_SUCCESS;
FINISH:
_cairo_scaled_font_thaw_cache (scaled_font);
status = _cairo_gl_context_release (ctx, status);
_cairo_gl_composite_fini (&setup);
*remaining_glyphs = num_glyphs - i;
return status;
}
static cairo_int_status_t
_cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t *dst,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
const cairo_rectangle_int_t *glyph_extents,
cairo_scaled_font_t *scaled_font,
cairo_clip_t *clip,
int *remaining_glyphs)
render_glyphs_via_mask (cairo_gl_surface_t *dst,
int dst_x, int dst_y,
cairo_operator_t op,
cairo_surface_t *source,
cairo_composite_glyphs_info_t *info,
cairo_clip_t *clip)
{
cairo_surface_t *mask;
cairo_status_t status;
cairo_bool_t has_component_alpha;
int i;
TRACE ((stderr, "%s\n", __FUNCTION__));
/* XXX: For non-CA, this should be CAIRO_CONTENT_ALPHA to save memory */
mask = cairo_gl_surface_create (dst->base.device,
CAIRO_CONTENT_COLOR_ALPHA,
glyph_extents->width,
glyph_extents->height);
CAIRO_CONTENT_COLOR_ALPHA,
info->extents.width,
info->extents.height);
if (unlikely (mask->status))
return mask->status;
return mask->status;
for (i = 0; i < num_glyphs; i++) {
glyphs[i].x -= glyph_extents->x;
glyphs[i].y -= glyph_extents->y;
}
status = _render_glyphs ((cairo_gl_surface_t *) mask, 0, 0,
CAIRO_OPERATOR_ADD,
&_cairo_pattern_white.base,
glyphs, num_glyphs, glyph_extents,
scaled_font, &has_component_alpha,
NULL, remaining_glyphs);
status = render_glyphs ((cairo_gl_surface_t *) mask,
info->extents.x, info->extents.y,
CAIRO_OPERATOR_ADD, NULL,
info, &has_component_alpha, NULL);
if (likely (status == CAIRO_STATUS_SUCCESS)) {
cairo_surface_pattern_t mask_pattern;
cairo_surface_pattern_t source_pattern;
cairo_rectangle_int_t clip_extents;
mask->is_clear = FALSE;
mask->is_clear = FALSE;
_cairo_pattern_init_for_surface (&mask_pattern, mask);
mask_pattern.base.has_component_alpha = has_component_alpha;
mask_pattern.base.filter = CAIRO_FILTER_NEAREST;
mask_pattern.base.extend = CAIRO_EXTEND_NONE;
cairo_matrix_init_translate (&mask_pattern.base.matrix,
-glyph_extents->x, -glyph_extents->y);
dst_x-info->extents.x, dst_y-info->extents.y);
_cairo_pattern_init_for_surface (&source_pattern, source);
cairo_matrix_init_translate (&source_pattern.base.matrix,
dst_x-info->extents.x, dst_y-info->extents.y);
clip = _cairo_clip_copy (clip);
clip_extents.x = info->extents.x - dst_x;
clip_extents.y = info->extents.y - dst_y;
clip_extents.width = info->extents.width;
clip_extents.height = info->extents.height;
clip = _cairo_clip_intersect_rectangle (clip, &clip_extents);
status = _cairo_surface_mask (&dst->base, op,
source, &mask_pattern.base, clip);
&source_pattern.base,
&mask_pattern.base,
clip);
_cairo_clip_destroy (clip);
_cairo_pattern_fini (&mask_pattern.base);
} else {
for (i = 0; i < num_glyphs; i++) {
glyphs[i].x += glyph_extents->x;
glyphs[i].y += glyph_extents->y;
}
*remaining_glyphs = num_glyphs;
_cairo_pattern_fini (&source_pattern.base);
}
cairo_surface_destroy (mask);
@ -427,158 +415,72 @@ _cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t *dst,
}
cairo_int_status_t
_cairo_gl_surface_show_glyphs (void *abstract_dst,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
cairo_clip_t *clip,
int *remaining_glyphs)
_cairo_gl_check_composite_glyphs (const cairo_composite_rectangles_t *extents,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int *num_glyphs)
{
cairo_gl_surface_t *dst = abstract_dst;
cairo_rectangle_int_t surface_extents;
cairo_rectangle_int_t extents;
cairo_region_t *clip_region = NULL;
cairo_bool_t overlap, use_mask = FALSE;
cairo_bool_t has_component_alpha;
cairo_status_t status;
int i;
if (! _cairo_gl_operator_is_supported (op))
if (! _cairo_gl_operator_is_supported (extents->op))
return UNSUPPORTED ("unsupported operator");
if (! _cairo_operator_bounded_by_mask (op))
use_mask |= TRUE;
/* XXX use individual masks for large glyphs? */
if (ceil (scaled_font->max_scale) >= GLYPH_CACHE_MAX_SIZE)
return UNSUPPORTED ("glyphs too large");
/* If any of the glyphs are component alpha, we have to go through a mask,
* since only _cairo_gl_surface_composite() currently supports component
* alpha.
return CAIRO_STATUS_SUCCESS;
}
cairo_int_status_t
_cairo_gl_composite_glyphs_with_clip (void *_dst,
cairo_operator_t op,
cairo_surface_t *_src,
int src_x,
int src_y,
int dst_x,
int dst_y,
cairo_composite_glyphs_info_t *info,
cairo_clip_t *clip)
{
cairo_gl_surface_t *dst = _dst;
cairo_bool_t has_component_alpha;
TRACE ((stderr, "%s\n", __FUNCTION__));
/* If any of the glyphs require component alpha, we have to go through
* a mask, since only _cairo_gl_surface_composite() currently supports
* component alpha.
*/
if (!use_mask && op != CAIRO_OPERATOR_OVER) {
for (i = 0; i < num_glyphs; i++) {
cairo_scaled_glyph_t *scaled_glyph;
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyph);
if (!_cairo_status_is_error (status) &&
scaled_glyph->surface->format == CAIRO_FORMAT_ARGB32)
{
use_mask = TRUE;
break;
}
}
if (!dst->base.is_clear && ! info->use_mask && op != CAIRO_OPERATOR_OVER &&
(info->font->options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ||
info->font->options.antialias == CAIRO_ANTIALIAS_BEST))
{
info->use_mask = TRUE;
}
/* For CLEAR, cairo's rendering equation (quoting Owen's description in:
* http://lists.cairographics.org/archives/cairo/2005-August/004992.html)
* is:
* mask IN clip ? src OP dest : dest
* or more simply:
* mask IN CLIP ? 0 : dest
*
* where the ternary operator A ? B : C is (A * B) + ((1 - A) * C).
*
* The model we use in _cairo_gl_set_operator() is Render's:
* src IN mask IN clip OP dest
* which would boil down to:
* 0 (bounded by the extents of the drawing).
*
* However, we can do a Render operation using an opaque source
* and DEST_OUT to produce:
* 1 IN mask IN clip DEST_OUT dest
* which is
* mask IN clip ? 0 : dest
*/
if (op == CAIRO_OPERATOR_CLEAR) {
source = &_cairo_pattern_white.base;
op = CAIRO_OPERATOR_DEST_OUT;
if (info->use_mask) {
return render_glyphs_via_mask (dst, dst_x, dst_y,
op, _src, info, clip);
} else {
return render_glyphs (dst, dst_x, dst_y,
op, _src, info,
&has_component_alpha,
clip);
}
/* For SOURCE, cairo's rendering equation is:
* (mask IN clip) ? src OP dest : dest
* or more simply:
* (mask IN clip) ? src : dest.
*
* If we just used the Render equation, we would get:
* (src IN mask IN clip) OP dest
* or:
* (src IN mask IN clip) bounded by extents of the drawing.
*
* The trick is that for GL blending, we only get our 4 source values
* into the blender, and since we need all 4 components of source, we
* can't also get the mask IN clip into the blender. But if we did
* two passes we could make it work:
* dest = (mask IN clip) DEST_OUT dest
* dest = src IN mask IN clip ADD dest
*
* But for now, composite via an intermediate mask.
*/
if (op == CAIRO_OPERATOR_SOURCE)
use_mask |= TRUE;
}
/* XXX we don't need ownership of the font as we use a global
* glyph cache -- but we do need scaled_glyph eviction notification. :-(
*/
if (! _cairo_gl_surface_owns_font (dst, scaled_font))
return UNSUPPORTED ("do not control font");
/* If the glyphs overlap, we need to build an intermediate mask rather
* then perform the compositing directly.
*/
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
glyphs, num_glyphs,
&extents,
&overlap);
if (unlikely (status))
return status;
use_mask |= overlap;
if (clip != NULL) {
status = _cairo_clip_get_region (clip, &clip_region);
/* the empty clip should never be propagated this far */
assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
if (unlikely (_cairo_status_is_error (status)))
return status;
use_mask |= status == CAIRO_INT_STATUS_UNSUPPORTED;
if (! _cairo_rectangle_intersect (&extents,
_cairo_clip_get_extents (clip)))
goto EMPTY;
}
surface_extents.x = surface_extents.y = 0;
surface_extents.width = dst->width;
surface_extents.height = dst->height;
if (! _cairo_rectangle_intersect (&extents, &surface_extents))
goto EMPTY;
if (use_mask) {
return _cairo_gl_surface_show_glyphs_via_mask (dst, op,
source,
glyphs, num_glyphs,
&extents,
scaled_font,
clip,
remaining_glyphs);
}
return _render_glyphs (dst, extents.x, extents.y,
op, source,
glyphs, num_glyphs, &extents,
scaled_font, &has_component_alpha,
clip_region, remaining_glyphs);
EMPTY:
*remaining_glyphs = 0;
if (! _cairo_operator_bounded_by_mask (op))
return _cairo_surface_paint (&dst->base, op, source, clip);
else
return CAIRO_STATUS_SUCCESS;
cairo_int_status_t
_cairo_gl_composite_glyphs (void *_dst,
cairo_operator_t op,
cairo_surface_t *_src,
int src_x,
int src_y,
int dst_x,
int dst_y,
cairo_composite_glyphs_info_t *info)
{
return _cairo_gl_composite_glyphs_with_clip (_dst, op, _src, src_x, src_y,
dst_x, dst_y, info, NULL);
}
void
@ -588,7 +490,8 @@ _cairo_gl_glyph_cache_init (cairo_gl_glyph_cache_t *cache)
GLYPH_CACHE_WIDTH,
GLYPH_CACHE_HEIGHT,
GLYPH_CACHE_MIN_SIZE,
sizeof (cairo_gl_glyph_private_t));
sizeof (cairo_gl_glyph_t),
_cairo_gl_node_destroy);
}
void
@ -596,10 +499,5 @@ _cairo_gl_glyph_cache_fini (cairo_gl_context_t *ctx,
cairo_gl_glyph_cache_t *cache)
{
_cairo_rtree_fini (&cache->rtree);
if (cache->pattern.surface) {
_cairo_pattern_fini (&cache->pattern.base);
cache->pattern.surface = NULL;
}
cairo_surface_destroy (&cache->surface->base);
}

Просмотреть файл

@ -0,0 +1,96 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Eric Anholt
* Copyright © 2009 Chris Wilson
* Copyright © 2005,2010 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Benjamin Otte <otte@gnome.org>
* Carl Worth <cworth@cworth.org>
* Chris Wilson <chris@chris-wilson.co.uk>
* Eric Anholt <eric@anholt.net>
*/
#ifndef CAIRO_GL_GRADIENT_PRIVATE_H
#define CAIRO_GL_GRADIENT_PRIVATE_H
#define GL_GLEXT_PROTOTYPES
#include "cairo-cache-private.h"
#include "cairo-device-private.h"
#include "cairo-reference-count-private.h"
#include "cairo-pattern-private.h"
#include "cairo-types-private.h"
#include "cairo-gl.h"
#if CAIRO_HAS_GLESV3_SURFACE
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#elif CAIRO_HAS_GLESV2_SURFACE
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#elif CAIRO_HAS_GL_SURFACE
#include <GL/gl.h>
#include <GL/glext.h>
#endif
#define CAIRO_GL_GRADIENT_CACHE_SIZE 4096
/* XXX: Declare in a better place */
typedef struct _cairo_gl_context cairo_gl_context_t;
typedef struct _cairo_gl_gradient {
cairo_cache_entry_t cache_entry;
cairo_reference_count_t ref_count;
cairo_device_t *device; /* NB: we don't hold a reference */
GLuint tex;
unsigned int n_stops;
const cairo_gradient_stop_t *stops;
cairo_gradient_stop_t stops_embedded[1];
} cairo_gl_gradient_t;
cairo_private cairo_int_status_t
_cairo_gl_gradient_create (cairo_gl_context_t *ctx,
unsigned int n_stops,
const cairo_gradient_stop_t *stops,
cairo_gl_gradient_t **gradient_out);
cairo_private_no_warn cairo_gl_gradient_t *
_cairo_gl_gradient_reference (cairo_gl_gradient_t *gradient);
cairo_private void
_cairo_gl_gradient_destroy (cairo_gl_gradient_t *gradient);
cairo_private cairo_bool_t
_cairo_gl_gradient_equal (const void *key_a, const void *key_b);
#endif /* CAIRO_GL_GRADIENT_PRIVATE_H */

Просмотреть файл

@ -0,0 +1,339 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Eric Anholt
* Copyright © 2009 Chris Wilson
* Copyright © 2005,2010 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Benjamin Otte <otte@gnome.org>
* Carl Worth <cworth@cworth.org>
* Chris Wilson <chris@chris-wilson.co.uk>
* Eric Anholt <eric@anholt.net>
*/
#include "cairoint.h"
#include <stdint.h>
#include "cairo-error-private.h"
#include "cairo-gl-gradient-private.h"
#include "cairo-gl-private.h"
static int
_cairo_gl_gradient_sample_width (unsigned int n_stops,
const cairo_gradient_stop_t *stops)
{
unsigned int n;
int width;
width = 8;
for (n = 1; n < n_stops; n++) {
double dx = stops[n].offset - stops[n-1].offset;
double delta, max;
int ramp;
if (dx == 0)
return 1024; /* we need to emulate an infinitely sharp step */
max = fabs (stops[n].color.red - stops[n-1].color.red);
delta = fabs (stops[n].color.green - stops[n-1].color.green);
if (delta > max)
max = delta;
delta = fabs (stops[n].color.blue - stops[n-1].color.blue);
if (delta > max)
max = delta;
delta = fabs (stops[n].color.alpha - stops[n-1].color.alpha);
if (delta > max)
max = delta;
ramp = 128 * max / dx;
if (ramp > width)
width = ramp;
}
return (width + 7) & -8;
}
static uint8_t premultiply(double c, double a)
{
int v = c * a * 256;
return v - (v >> 8);
}
static uint32_t color_stop_to_pixel(const cairo_gradient_stop_t *stop)
{
uint8_t a, r, g, b;
a = stop->color.alpha_short >> 8;
r = premultiply(stop->color.red, stop->color.alpha);
g = premultiply(stop->color.green, stop->color.alpha);
b = premultiply(stop->color.blue, stop->color.alpha);
if (_cairo_is_little_endian ())
return (uint32_t)a << 24 | r << 16 | g << 8 | b << 0;
else
return a << 0 | r << 8 | g << 16 | (uint32_t)b << 24;
}
static cairo_status_t
_cairo_gl_gradient_render (const cairo_gl_context_t *ctx,
unsigned int n_stops,
const cairo_gradient_stop_t *stops,
void *bytes,
int width)
{
pixman_image_t *gradient, *image;
pixman_gradient_stop_t pixman_stops_stack[32];
pixman_gradient_stop_t *pixman_stops;
pixman_point_fixed_t p1, p2;
unsigned int i;
pixman_format_code_t gradient_pixman_format;
/*
* Ensure that the order of the gradient's components in memory is BGRA.
* This is done so that the gradient's pixel data is always suitable for
* texture upload using format=GL_BGRA and type=GL_UNSIGNED_BYTE.
*/
if (_cairo_is_little_endian ())
gradient_pixman_format = PIXMAN_a8r8g8b8;
else
gradient_pixman_format = PIXMAN_b8g8r8a8;
pixman_stops = pixman_stops_stack;
if (unlikely (n_stops > ARRAY_LENGTH (pixman_stops_stack))) {
pixman_stops = _cairo_malloc_ab (n_stops,
sizeof (pixman_gradient_stop_t));
if (unlikely (pixman_stops == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
for (i = 0; i < n_stops; i++) {
pixman_stops[i].x = _cairo_fixed_16_16_from_double (stops[i].offset);
pixman_stops[i].color.red = stops[i].color.red_short;
pixman_stops[i].color.green = stops[i].color.green_short;
pixman_stops[i].color.blue = stops[i].color.blue_short;
pixman_stops[i].color.alpha = stops[i].color.alpha_short;
}
p1.x = _cairo_fixed_16_16_from_double (0.5);
p1.y = 0;
p2.x = _cairo_fixed_16_16_from_double (width - 0.5);
p2.y = 0;
gradient = pixman_image_create_linear_gradient (&p1, &p2,
pixman_stops,
n_stops);
if (pixman_stops != pixman_stops_stack)
free (pixman_stops);
if (unlikely (gradient == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
pixman_image_set_filter (gradient, PIXMAN_FILTER_BILINEAR, NULL, 0);
pixman_image_set_repeat (gradient, PIXMAN_REPEAT_PAD);
image = pixman_image_create_bits (gradient_pixman_format, width, 1,
bytes, sizeof(uint32_t)*width);
if (unlikely (image == NULL)) {
pixman_image_unref (gradient);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
pixman_image_composite32 (PIXMAN_OP_SRC,
gradient, NULL, image,
0, 0,
0, 0,
0, 0,
width, 1);
pixman_image_unref (gradient);
pixman_image_unref (image);
/* We need to fudge pixel 0 to hold the left-most color stop and not
* the neareset stop to the zeroth pixel centre in order to correctly
* populate the border color. For completeness, do both edges.
*/
((uint32_t*)bytes)[0] = color_stop_to_pixel(&stops[0]);
((uint32_t*)bytes)[width-1] = color_stop_to_pixel(&stops[n_stops-1]);
return CAIRO_STATUS_SUCCESS;
}
static unsigned long
_cairo_gl_gradient_hash (unsigned int n_stops,
const cairo_gradient_stop_t *stops)
{
return _cairo_hash_bytes (n_stops,
stops,
sizeof (cairo_gradient_stop_t) * n_stops);
}
static cairo_gl_gradient_t *
_cairo_gl_gradient_lookup (cairo_gl_context_t *ctx,
unsigned long hash,
unsigned int n_stops,
const cairo_gradient_stop_t *stops)
{
cairo_gl_gradient_t lookup;
lookup.cache_entry.hash = hash,
lookup.n_stops = n_stops;
lookup.stops = stops;
return _cairo_cache_lookup (&ctx->gradients, &lookup.cache_entry);
}
cairo_bool_t
_cairo_gl_gradient_equal (const void *key_a, const void *key_b)
{
const cairo_gl_gradient_t *a = key_a;
const cairo_gl_gradient_t *b = key_b;
if (a->n_stops != b->n_stops)
return FALSE;
return memcmp (a->stops, b->stops, a->n_stops * sizeof (cairo_gradient_stop_t)) == 0;
}
cairo_int_status_t
_cairo_gl_gradient_create (cairo_gl_context_t *ctx,
unsigned int n_stops,
const cairo_gradient_stop_t *stops,
cairo_gl_gradient_t **gradient_out)
{
unsigned long hash;
cairo_gl_gradient_t *gradient;
cairo_status_t status;
int tex_width;
GLint internal_format;
void *data;
if ((unsigned int) ctx->max_texture_size / 2 <= n_stops)
return CAIRO_INT_STATUS_UNSUPPORTED;
hash = _cairo_gl_gradient_hash (n_stops, stops);
gradient = _cairo_gl_gradient_lookup (ctx, hash, n_stops, stops);
if (gradient) {
*gradient_out = _cairo_gl_gradient_reference (gradient);
return CAIRO_STATUS_SUCCESS;
}
gradient = _cairo_malloc (sizeof (cairo_gl_gradient_t) + sizeof (cairo_gradient_stop_t) * (n_stops - 1));
if (gradient == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
tex_width = _cairo_gl_gradient_sample_width (n_stops, stops);
if (tex_width > ctx->max_texture_size)
tex_width = ctx->max_texture_size;
CAIRO_REFERENCE_COUNT_INIT (&gradient->ref_count, 2);
gradient->cache_entry.hash = hash;
gradient->cache_entry.size = tex_width;
gradient->device = &ctx->base;
gradient->n_stops = n_stops;
gradient->stops = gradient->stops_embedded;
memcpy (gradient->stops_embedded, stops, n_stops * sizeof (cairo_gradient_stop_t));
glGenTextures (1, &gradient->tex);
_cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP);
glBindTexture (ctx->tex_target, gradient->tex);
data = _cairo_malloc_ab (tex_width, sizeof (uint32_t));
if (unlikely (data == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto cleanup_gradient;
}
status = _cairo_gl_gradient_render (ctx, n_stops, stops, data, tex_width);
if (unlikely (status))
goto cleanup_data;
/*
* In OpenGL ES 2.0 no format conversion is allowed i.e. 'internalFormat'
* must match 'format' in glTexImage2D.
*/
if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES3 ||
_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES2)
internal_format = GL_BGRA;
else
internal_format = GL_RGBA;
glTexImage2D (ctx->tex_target, 0, internal_format, tex_width, 1, 0,
GL_BGRA, GL_UNSIGNED_BYTE, data);
free (data);
/* we ignore errors here and just return an uncached gradient */
if (unlikely (_cairo_cache_insert (&ctx->gradients, &gradient->cache_entry)))
CAIRO_REFERENCE_COUNT_INIT (&gradient->ref_count, 1);
*gradient_out = gradient;
return CAIRO_STATUS_SUCCESS;
cleanup_data:
free (data);
cleanup_gradient:
free (gradient);
return status;
}
cairo_gl_gradient_t *
_cairo_gl_gradient_reference (cairo_gl_gradient_t *gradient)
{
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&gradient->ref_count));
_cairo_reference_count_inc (&gradient->ref_count);
return gradient;
}
void
_cairo_gl_gradient_destroy (cairo_gl_gradient_t *gradient)
{
cairo_gl_context_t *ctx;
cairo_status_t ignore;
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&gradient->ref_count));
if (! _cairo_reference_count_dec_and_test (&gradient->ref_count))
return;
if (_cairo_gl_context_acquire (gradient->device, &ctx) == CAIRO_STATUS_SUCCESS) {
/* The gradient my still be active in the last operation, so flush */
_cairo_gl_composite_flush (ctx);
glDeleteTextures (1, &gradient->tex);
ignore = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS);
}
free (gradient);
}

Просмотреть файл

@ -0,0 +1,145 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2010 Linaro Limited
*
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.
*
* Contributor(s):
* Alexandros Frantzis <alexandros.frantzis@linaro.org>
* Heiko Lewin <heiko.lewin@gmx.de>
*/
#include "cairoint.h"
#include "cairo-gl-private.h"
#include <errno.h>
int
_cairo_gl_get_version (void)
{
int major, minor;
const char *version = (const char *) glGetString (GL_VERSION);
const char *dot = version == NULL ? NULL : strchr (version, '.');
const char *major_start = dot;
/* Sanity check */
if (dot == NULL || dot == version || *(dot + 1) == '\0') {
major = 0;
minor = 0;
} else {
/* Find the start of the major version in the string */
while (major_start > version && *major_start != ' ')
--major_start;
major = strtol (major_start, NULL, 10);
minor = strtol (dot + 1, NULL, 10);
}
return CAIRO_GL_VERSION_ENCODE (major, minor);
}
cairo_gl_flavor_t
_cairo_gl_degrade_flavor_by_build_features (cairo_gl_flavor_t flavor) {
switch(flavor) {
case CAIRO_GL_FLAVOR_DESKTOP:
#if CAIRO_HAS_GL_SURFACE
return CAIRO_GL_FLAVOR_DESKTOP;
#else
return CAIRO_GL_FLAVOR_NONE;
#endif
case CAIRO_GL_FLAVOR_ES3:
#if CAIRO_HAS_GLESV3_SURFACE
return CAIRO_GL_FLAVOR_ES3;
#else
/* intentional fall through: degrade to GLESv2 if GLESv3-surfaces are not available */
#endif
case CAIRO_GL_FLAVOR_ES2:
#if CAIRO_HAS_GLESV2_SURFACE
return CAIRO_GL_FLAVOR_ES2;
#else
/* intentional fall through: no OpenGL in first place or no surfaces for it's version */
#endif
default:
return CAIRO_GL_FLAVOR_NONE;
}
}
cairo_gl_flavor_t
_cairo_gl_get_flavor (void)
{
const char *version = (const char *) glGetString (GL_VERSION);
cairo_gl_flavor_t flavor;
if (version == NULL) {
flavor = CAIRO_GL_FLAVOR_NONE;
} else if (strstr (version, "OpenGL ES 3") != NULL) {
flavor = CAIRO_GL_FLAVOR_ES3;
} else if (strstr (version, "OpenGL ES 2") != NULL) {
flavor = CAIRO_GL_FLAVOR_ES2;
} else {
flavor = CAIRO_GL_FLAVOR_DESKTOP;
}
return _cairo_gl_degrade_flavor_by_build_features(flavor);
}
unsigned long
_cairo_gl_get_vbo_size (void)
{
unsigned long vbo_size;
const char *env = getenv ("CAIRO_GL_VBO_SIZE");
if (env == NULL) {
vbo_size = CAIRO_GL_VBO_SIZE_DEFAULT;
} else {
errno = 0;
vbo_size = strtol (env, NULL, 10);
assert (errno == 0);
assert (vbo_size > 0);
}
return vbo_size;
}
cairo_bool_t
_cairo_gl_has_extension (const char *ext)
{
const char *extensions = (const char *) glGetString (GL_EXTENSIONS);
size_t len = strlen (ext);
const char *ext_ptr = extensions;
if (unlikely (ext_ptr == NULL))
return 0;
while ((ext_ptr = strstr (ext_ptr, ext)) != NULL) {
if (ext_ptr[len] == ' ' || ext_ptr[len] == '\0')
break;
ext_ptr += len;
}
return (ext_ptr != NULL);
}

Просмотреть файл

@ -0,0 +1,956 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* Copyright © 2005 Red Hat, Inc.
* Copyright © 2011 Intel Corporation
* Copyright © 2011 Samsung Electronics
*
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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):
* Henry Song <hsong@sisa.samsung.com>
* Martin Robinson <mrobinson@igalia.com>
*/
#include "cairoint.h"
#include "cairo-clip-inline.h"
#include "cairo-composite-rectangles-private.h"
#include "cairo-compositor-private.h"
#include "cairo-gl-private.h"
#include "cairo-path-private.h"
#include "cairo-traps-private.h"
static cairo_bool_t
can_use_msaa_compositor (cairo_gl_surface_t *surface,
cairo_antialias_t antialias);
static void
query_surface_capabilities (cairo_gl_surface_t *surface);
struct _tristrip_composite_info {
cairo_gl_composite_t setup;
cairo_gl_context_t *ctx;
};
static cairo_int_status_t
_draw_trap (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
cairo_trapezoid_t *trap)
{
cairo_point_t quad[4];
quad[0].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1,
&trap->left.p2,
trap->top);
quad[0].y = trap->top;
quad[1].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1,
&trap->left.p2,
trap->bottom);
quad[1].y = trap->bottom;
quad[2].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1,
&trap->right.p2,
trap->bottom);
quad[2].y = trap->bottom;
quad[3].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1,
&trap->right.p2,
trap->top);
quad[3].y = trap->top;
return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
}
static cairo_int_status_t
_draw_traps (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
cairo_traps_t *traps)
{
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
int i;
for (i = 0; i < traps->num_traps; i++) {
cairo_trapezoid_t *trap = traps->traps + i;
if (unlikely ((status = _draw_trap (ctx, setup, trap))))
return status;
}
return status;
}
static cairo_int_status_t
_draw_int_rect (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
cairo_rectangle_int_t *rect)
{
cairo_box_t box;
cairo_point_t quad[4];
_cairo_box_from_rectangle (&box, rect);
quad[0].x = box.p1.x;
quad[0].y = box.p1.y;
quad[1].x = box.p1.x;
quad[1].y = box.p2.y;
quad[2].x = box.p2.x;
quad[2].y = box.p2.y;
quad[3].x = box.p2.x;
quad[3].y = box.p1.y;
return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
}
static cairo_int_status_t
_draw_triangle_fan (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
const cairo_point_t *midpt,
const cairo_point_t *points,
int npoints)
{
int i;
/* Our strategy here is to not even try to build a triangle fan, but to
draw each triangle as if it was an unconnected member of a triangle strip. */
for (i = 1; i < npoints; i++) {
cairo_int_status_t status;
cairo_point_t triangle[3];
triangle[0] = *midpt;
triangle[1] = points[i - 1];
triangle[2] = points[i];
status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
if (unlikely (status))
return status;
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_clip_to_traps (cairo_clip_t *clip,
cairo_traps_t *traps)
{
cairo_int_status_t status;
cairo_polygon_t polygon;
cairo_antialias_t antialias;
cairo_fill_rule_t fill_rule;
_cairo_traps_init (traps);
if (clip->num_boxes == 1 && clip->path == NULL) {
cairo_boxes_t boxes;
_cairo_boxes_init_for_array (&boxes, clip->boxes, clip->num_boxes);
return _cairo_traps_init_boxes (traps, &boxes);
}
status = _cairo_clip_get_polygon (clip, &polygon, &fill_rule, &antialias);
if (unlikely (status))
return status;
/* We ignore the antialias mode of the clip here, since the user requested
* unantialiased rendering of their path and we expect that this stencil
* based rendering of the clip to be a reasonable approximation to
* the intersection between that clip and the path.
*
* In other words, what the user expects when they try to perform
* a geometric intersection between an unantialiased polygon and an
* antialiased polygon is open to interpretation. And we choose the fast
* option.
*/
_cairo_traps_init (traps);
status = _cairo_bentley_ottmann_tessellate_polygon (traps,
&polygon,
fill_rule);
_cairo_polygon_fini (&polygon);
return status;
}
cairo_int_status_t
_cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
cairo_clip_t *clip)
{
cairo_int_status_t status;
cairo_traps_t traps;
status = _clip_to_traps (clip, &traps);
if (unlikely (status))
return status;
status = _draw_traps (ctx, setup, &traps);
_cairo_traps_fini (&traps);
return status;
}
static cairo_bool_t
_should_use_unbounded_surface (cairo_composite_rectangles_t *composite)
{
cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
cairo_rectangle_int_t *source = &composite->source;
if (composite->is_bounded)
return FALSE;
/* This isn't just an optimization. It also detects when painting is used
to paint back the unbounded surface, preventing infinite recursion. */
return ! (source->x <= 0 && source->y <= 0 &&
source->height + source->y >= dst->height &&
source->width + source->x >= dst->width);
}
static cairo_surface_t*
_prepare_unbounded_surface (cairo_gl_surface_t *dst)
{
cairo_surface_t* surface = cairo_gl_surface_create (dst->base.device,
dst->base.content,
dst->width,
dst->height);
if (surface == NULL)
return NULL;
if (unlikely (surface->status)) {
cairo_surface_destroy (surface);
return NULL;
}
return surface;
}
static cairo_int_status_t
_paint_back_unbounded_surface (const cairo_compositor_t *compositor,
cairo_composite_rectangles_t *composite,
cairo_surface_t *surface)
{
cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
cairo_int_status_t status;
cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
if (unlikely (pattern->status)) {
status = pattern->status;
goto finish;
}
status = _cairo_compositor_paint (compositor, &dst->base,
composite->op, pattern,
composite->clip);
finish:
cairo_pattern_destroy (pattern);
cairo_surface_destroy (surface);
return status;
}
static cairo_bool_t
can_use_msaa_compositor (cairo_gl_surface_t *surface,
cairo_antialias_t antialias)
{
cairo_gl_flavor_t gl_flavor = ((cairo_gl_context_t *) surface->base.device)->gl_flavor;
query_surface_capabilities (surface);
if (! surface->supports_stencil)
return FALSE;
/* Multisampling OpenGL ES surfaces only maintain one multisampling
framebuffer and thus must use the spans compositor to do non-antialiased
rendering. */
if ((gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
gl_flavor == CAIRO_GL_FLAVOR_ES2)
&& surface->supports_msaa
&& surface->num_samples > 1
&& antialias == CAIRO_ANTIALIAS_NONE)
return FALSE;
/* The MSAA compositor has a single-sample mode, so we can
support non-antialiased rendering. */
if (antialias == CAIRO_ANTIALIAS_NONE)
return TRUE;
if (antialias == CAIRO_ANTIALIAS_FAST || antialias == CAIRO_ANTIALIAS_DEFAULT)
return surface->supports_msaa;
return FALSE;
}
static void
_cairo_gl_msaa_compositor_set_clip (cairo_composite_rectangles_t *composite,
cairo_gl_composite_t *setup)
{
if (_cairo_composite_rectangles_can_reduce_clip (composite, composite->clip))
return;
_cairo_gl_composite_set_clip (setup, composite->clip);
}
/* Masking with the SOURCE operator requires two passes. In the first
* pass we use the mask as the source to get:
* result = (1 - ma) * dst
* In the second pass we use the add operator to achieve:
* result = (src * ma) + dst
* Combined this produces:
* result = (src * ma) + (1 - ma) * dst
*/
static cairo_int_status_t
_cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compositor,
cairo_composite_rectangles_t *composite)
{
cairo_gl_composite_t setup;
cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
cairo_gl_context_t *ctx = NULL;
cairo_int_status_t status;
cairo_clip_t *clip = composite->clip;
cairo_traps_t traps;
/* If we have a non-rectangular clip, we can avoid using the stencil buffer
* for clipping and just draw the clip polygon. */
if (clip) {
status = _clip_to_traps (clip, &traps);
if (unlikely (status)) {
_cairo_traps_fini (&traps);
return status;
}
}
status = _cairo_gl_composite_init (&setup,
CAIRO_OPERATOR_DEST_OUT,
dst,
FALSE /* assume_component_alpha */);
if (unlikely (status))
return status;
status = _cairo_gl_composite_set_source (&setup,
&composite->mask_pattern.base,
&composite->mask_sample_area,
&composite->bounded,
FALSE);
if (unlikely (status))
goto finish;
_cairo_gl_composite_set_multisample (&setup);
status = _cairo_gl_composite_begin (&setup, &ctx);
if (unlikely (status))
goto finish;
if (! clip)
status = _draw_int_rect (ctx, &setup, &composite->bounded);
else
status = _draw_traps (ctx, &setup, &traps);
if (unlikely (status))
goto finish;
/* Now draw the second pass. */
status = _cairo_gl_composite_set_operator (&setup, CAIRO_OPERATOR_ADD,
FALSE /* assume_component_alpha */);
if (unlikely (status))
goto finish;
status = _cairo_gl_composite_set_source (&setup,
&composite->source_pattern.base,
&composite->source_sample_area,
&composite->bounded,
FALSE);
if (unlikely (status))
goto finish;
status = _cairo_gl_composite_set_mask (&setup,
&composite->mask_pattern.base,
&composite->source_sample_area,
&composite->bounded,
FALSE);
if (unlikely (status))
goto finish;
_cairo_gl_context_set_destination (ctx, dst, setup.multisample);
status = _cairo_gl_set_operands_and_operator (&setup, ctx);
if (unlikely (status))
goto finish;
if (! clip)
status = _draw_int_rect (ctx, &setup, &composite->bounded);
else
status = _draw_traps (ctx, &setup, &traps);
finish:
_cairo_gl_composite_fini (&setup);
if (ctx)
status = _cairo_gl_context_release (ctx, status);
if (clip)
_cairo_traps_fini (&traps);
return status;
}
static cairo_int_status_t
_cairo_gl_msaa_compositor_mask (const cairo_compositor_t *compositor,
cairo_composite_rectangles_t *composite)
{
cairo_gl_composite_t setup;
cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
cairo_gl_context_t *ctx = NULL;
cairo_int_status_t status;
cairo_operator_t op = composite->op;
cairo_clip_t *clip = composite->clip;
if (! can_use_msaa_compositor (dst, CAIRO_ANTIALIAS_DEFAULT))
return CAIRO_INT_STATUS_UNSUPPORTED;
if (composite->op == CAIRO_OPERATOR_CLEAR &&
composite->original_mask_pattern != NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
/* GL compositing operators cannot properly represent a mask operation
using the SOURCE compositing operator in one pass. This only matters if
there actually is a mask (there isn't in a paint operation) and if the
mask isn't totally opaque. */
if (op == CAIRO_OPERATOR_SOURCE &&
composite->original_mask_pattern != NULL &&
! _cairo_pattern_is_opaque (&composite->mask_pattern.base,
&composite->mask_sample_area)) {
if (! _cairo_pattern_is_opaque (&composite->source_pattern.base,
&composite->source_sample_area)) {
return _cairo_gl_msaa_compositor_mask_source_operator (compositor, composite);
}
/* If the source is opaque the operation reduces to OVER. */
op = CAIRO_OPERATOR_OVER;
}
if (_should_use_unbounded_surface (composite)) {
cairo_surface_t* surface = _prepare_unbounded_surface (dst);
if (unlikely (surface == NULL))
return CAIRO_INT_STATUS_UNSUPPORTED;
/* This may be a paint operation. */
if (composite->original_mask_pattern == NULL) {
status = _cairo_compositor_paint (compositor, surface,
CAIRO_OPERATOR_SOURCE,
&composite->source_pattern.base,
NULL);
} else {
status = _cairo_compositor_mask (compositor, surface,
CAIRO_OPERATOR_SOURCE,
&composite->source_pattern.base,
&composite->mask_pattern.base,
NULL);
}
if (unlikely (status)) {
cairo_surface_destroy (surface);
return status;
}
return _paint_back_unbounded_surface (compositor, composite, surface);
}
status = _cairo_gl_composite_init (&setup,
op,
dst,
FALSE /* assume_component_alpha */);
if (unlikely (status))
return status;
status = _cairo_gl_composite_set_source (&setup,
&composite->source_pattern.base,
&composite->source_sample_area,
&composite->bounded,
FALSE);
if (unlikely (status))
goto finish;
if (composite->original_mask_pattern != NULL) {
status = _cairo_gl_composite_set_mask (&setup,
&composite->mask_pattern.base,
&composite->mask_sample_area,
&composite->bounded,
FALSE);
}
if (unlikely (status))
goto finish;
/* We always use multisampling here, because we do not yet have the smarts
to calculate when the clip or the source requires it. */
_cairo_gl_composite_set_multisample (&setup);
status = _cairo_gl_composite_begin (&setup, &ctx);
if (unlikely (status))
goto finish;
if (! clip)
status = _draw_int_rect (ctx, &setup, &composite->bounded);
else
status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, clip);
finish:
_cairo_gl_composite_fini (&setup);
if (ctx)
status = _cairo_gl_context_release (ctx, status);
return status;
}
static cairo_int_status_t
_cairo_gl_msaa_compositor_paint (const cairo_compositor_t *compositor,
cairo_composite_rectangles_t *composite)
{
return _cairo_gl_msaa_compositor_mask (compositor, composite);
}
static cairo_status_t
_stroke_shaper_add_triangle (void *closure,
const cairo_point_t triangle[3])
{
struct _tristrip_composite_info *info = closure;
return _cairo_gl_composite_emit_triangle_as_tristrip (info->ctx,
&info->setup,
triangle);
}
static cairo_status_t
_stroke_shaper_add_triangle_fan (void *closure,
const cairo_point_t *midpoint,
const cairo_point_t *points,
int npoints)
{
struct _tristrip_composite_info *info = closure;
return _draw_triangle_fan (info->ctx, &info->setup,
midpoint, points, npoints);
}
static cairo_status_t
_stroke_shaper_add_quad (void *closure,
const cairo_point_t quad[4])
{
struct _tristrip_composite_info *info = closure;
return _cairo_gl_composite_emit_quad_as_tristrip (info->ctx, &info->setup,
quad);
}
static cairo_int_status_t
_prevent_overlapping_strokes (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
cairo_composite_rectangles_t *composite,
const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm)
{
cairo_rectangle_int_t stroke_extents;
if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
return CAIRO_INT_STATUS_UNSUPPORTED;
if (_cairo_pattern_is_opaque (&composite->source_pattern.base,
&composite->source_sample_area))
return CAIRO_INT_STATUS_SUCCESS;
if (glIsEnabled (GL_STENCIL_TEST) == FALSE) {
cairo_bool_t scissor_was_enabled;
/* In case we have pending operations we have to flush before
adding the stencil buffer. */
_cairo_gl_composite_flush (ctx);
/* Enable the stencil buffer, even if we are not using it for clipping,
so we can use it below to prevent overlapping shapes. We initialize
it all to one here which represents infinite clip. */
glDepthMask (GL_TRUE);
glEnable (GL_STENCIL_TEST);
/* We scissor here so that we don't have to clear the entire stencil
* buffer. If the scissor test is already enabled, it was enabled
* for clipping. In that case, instead of calculating an intersection,
* we just reuse it, and risk clearing too much. */
scissor_was_enabled = glIsEnabled (GL_SCISSOR_TEST);
if (! scissor_was_enabled) {
_cairo_path_fixed_approximate_stroke_extents (path, style, ctm,
FALSE, /* is_vector */
&stroke_extents);
_cairo_gl_scissor_to_rectangle (setup->dst, &stroke_extents);
}
glClearStencil (1);
glClear (GL_STENCIL_BUFFER_BIT);
if (! scissor_was_enabled)
glDisable (GL_SCISSOR_TEST);
glStencilFunc (GL_EQUAL, 1, 1);
}
/* This means that once we draw to a particular pixel nothing else can
be drawn there until the stencil buffer is reset or the stencil test
is disabled. */
glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO);
_cairo_clip_destroy (setup->dst->clip_on_stencil_buffer);
setup->dst->clip_on_stencil_buffer = NULL;
return CAIRO_INT_STATUS_SUCCESS;
}
static void
query_surface_capabilities (cairo_gl_surface_t *surface)
{
GLint samples, stencil_bits;
cairo_gl_context_t *ctx;
cairo_int_status_t status;
/* Texture surfaces are create in such a way that they always
have stencil and multisample bits if possible, so we don't
need to query their capabilities lazily. */
if (_cairo_gl_surface_is_texture (surface))
return;
if (surface->stencil_and_msaa_caps_initialized)
return;
surface->stencil_and_msaa_caps_initialized = TRUE;
surface->supports_stencil = FALSE;
surface->supports_msaa = FALSE;
status = _cairo_gl_context_acquire (surface->base.device, &ctx);
if (unlikely (status))
return;
_cairo_gl_context_set_destination (ctx, surface, FALSE);
glGetIntegerv(GL_SAMPLES, &samples);
glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
surface->supports_stencil = stencil_bits > 0;
surface->supports_msaa = samples > 1;
surface->num_samples = samples;
status = _cairo_gl_context_release (ctx, status);
}
static cairo_int_status_t
_cairo_gl_msaa_compositor_stroke (const cairo_compositor_t *compositor,
cairo_composite_rectangles_t *composite,
const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias)
{
cairo_int_status_t status;
cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
struct _tristrip_composite_info info;
if (! can_use_msaa_compositor (dst, antialias))
return CAIRO_INT_STATUS_UNSUPPORTED;
if (composite->is_bounded == FALSE) {
cairo_surface_t* surface = _prepare_unbounded_surface (dst);
if (unlikely (surface == NULL))
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_compositor_stroke (compositor, surface,
CAIRO_OPERATOR_SOURCE,
&composite->source_pattern.base,
path, style, ctm, ctm_inverse,
tolerance, antialias, NULL);
if (unlikely (status)) {
cairo_surface_destroy (surface);
return status;
}
return _paint_back_unbounded_surface (compositor, composite, surface);
}
status = _cairo_gl_composite_init (&info.setup,
composite->op,
dst,
FALSE /* assume_component_alpha */);
if (unlikely (status))
return status;
info.ctx = NULL;
status = _cairo_gl_composite_set_source (&info.setup,
&composite->source_pattern.base,
&composite->source_sample_area,
&composite->bounded,
FALSE);
if (unlikely (status))
goto finish;
_cairo_gl_msaa_compositor_set_clip (composite, &info.setup);
if (antialias != CAIRO_ANTIALIAS_NONE)
_cairo_gl_composite_set_multisample (&info.setup);
status = _cairo_gl_composite_begin (&info.setup, &info.ctx);
if (unlikely (status))
goto finish;
status = _prevent_overlapping_strokes (info.ctx, &info.setup,
composite, path, style, ctm);
if (unlikely (status))
goto finish;
status = _cairo_path_fixed_stroke_to_shaper ((cairo_path_fixed_t *) path,
style,
ctm,
ctm_inverse,
tolerance,
_stroke_shaper_add_triangle,
_stroke_shaper_add_triangle_fan,
_stroke_shaper_add_quad,
&info);
if (unlikely (status))
goto finish;
finish:
_cairo_gl_composite_fini (&info.setup);
if (info.ctx)
status = _cairo_gl_context_release (info.ctx, status);
return status;
}
static cairo_int_status_t
_draw_simple_quad_path (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
const cairo_path_fixed_t *path)
{
cairo_point_t triangle[3];
cairo_int_status_t status;
const cairo_point_t *points;
points = cairo_path_head (path)->points;
triangle[0] = points[0];
triangle[1] = points[1];
triangle[2] = points[2];
status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
if (status)
return status;
triangle[0] = points[2];
triangle[1] = points[3];
triangle[2] = points[0];
return _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
}
static cairo_int_status_t
_cairo_gl_msaa_compositor_fill (const cairo_compositor_t *compositor,
cairo_composite_rectangles_t *composite,
const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
{
cairo_gl_composite_t setup;
cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
cairo_gl_context_t *ctx = NULL;
cairo_int_status_t status;
cairo_traps_t traps;
cairo_bool_t draw_path_with_traps;
if (! can_use_msaa_compositor (dst, antialias))
return CAIRO_INT_STATUS_UNSUPPORTED;
if (composite->is_bounded == FALSE) {
cairo_surface_t* surface = _prepare_unbounded_surface (dst);
if (unlikely (surface == NULL))
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_compositor_fill (compositor, surface,
CAIRO_OPERATOR_SOURCE,
&composite->source_pattern.base,
path, fill_rule, tolerance,
antialias, NULL);
if (unlikely (status)) {
cairo_surface_destroy (surface);
return status;
}
return _paint_back_unbounded_surface (compositor, composite, surface);
}
draw_path_with_traps = ! _cairo_path_fixed_is_simple_quad (path);
if (draw_path_with_traps) {
_cairo_traps_init (&traps);
status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps);
if (unlikely (status))
goto cleanup_traps;
}
status = _cairo_gl_composite_init (&setup,
composite->op,
dst,
FALSE /* assume_component_alpha */);
if (unlikely (status))
goto cleanup_traps;
status = _cairo_gl_composite_set_source (&setup,
&composite->source_pattern.base,
&composite->source_sample_area,
&composite->bounded,
FALSE);
if (unlikely (status))
goto cleanup_setup;
_cairo_gl_msaa_compositor_set_clip (composite, &setup);
if (antialias != CAIRO_ANTIALIAS_NONE)
_cairo_gl_composite_set_multisample (&setup);
status = _cairo_gl_composite_begin (&setup, &ctx);
if (unlikely (status))
goto cleanup_setup;
if (! draw_path_with_traps)
status = _draw_simple_quad_path (ctx, &setup, path);
else
status = _draw_traps (ctx, &setup, &traps);
if (unlikely (status))
goto cleanup_setup;
cleanup_setup:
_cairo_gl_composite_fini (&setup);
if (ctx)
status = _cairo_gl_context_release (ctx, status);
cleanup_traps:
if (draw_path_with_traps)
_cairo_traps_fini (&traps);
return status;
}
static cairo_int_status_t
_cairo_gl_msaa_compositor_glyphs (const cairo_compositor_t *compositor,
cairo_composite_rectangles_t *composite,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_bool_t overlap)
{
cairo_int_status_t status;
cairo_surface_t *src = NULL;
int src_x, src_y;
cairo_composite_glyphs_info_t info;
cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
query_surface_capabilities (dst);
if (! dst->supports_stencil)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (composite->op == CAIRO_OPERATOR_CLEAR)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (composite->is_bounded == FALSE) {
cairo_surface_t* surface = _prepare_unbounded_surface (dst);
if (unlikely (surface == NULL))
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_compositor_glyphs (compositor, surface,
CAIRO_OPERATOR_SOURCE,
&composite->source_pattern.base,
glyphs, num_glyphs,
scaled_font, composite->clip);
if (unlikely (status)) {
cairo_surface_destroy (surface);
return status;
}
return _paint_back_unbounded_surface (compositor, composite, surface);
}
src = _cairo_gl_pattern_to_source (&dst->base,
&composite->source_pattern.base,
FALSE,
&composite->bounded,
&composite->source_sample_area,
&src_x, &src_y);
if (unlikely (src->status)) {
status = src->status;
goto finish;
}
status = _cairo_gl_check_composite_glyphs (composite,
scaled_font, glyphs,
&num_glyphs);
if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
goto finish;
info.font = scaled_font;
info.glyphs = glyphs;
info.num_glyphs = num_glyphs;
info.use_mask = overlap || ! composite->is_bounded ||
composite->op == CAIRO_OPERATOR_SOURCE;
info.extents = composite->bounded;
_cairo_scaled_font_freeze_cache (scaled_font);
status = _cairo_gl_composite_glyphs_with_clip (dst, composite->op,
src, src_x, src_y,
0, 0, &info,
composite->clip);
_cairo_scaled_font_thaw_cache (scaled_font);
finish:
if (src)
cairo_surface_destroy (src);
return status;
}
static void
_cairo_gl_msaa_compositor_init (cairo_compositor_t *compositor,
const cairo_compositor_t *delegate)
{
compositor->delegate = delegate;
compositor->paint = _cairo_gl_msaa_compositor_paint;
compositor->mask = _cairo_gl_msaa_compositor_mask;
compositor->fill = _cairo_gl_msaa_compositor_fill;
compositor->stroke = _cairo_gl_msaa_compositor_stroke;
compositor->glyphs = _cairo_gl_msaa_compositor_glyphs;
}
const cairo_compositor_t *
_cairo_gl_msaa_compositor_get (void)
{
static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT;
static cairo_compositor_t compositor;
if (_cairo_atomic_init_once_enter(&once)) {
_cairo_gl_msaa_compositor_init (&compositor,
_cairo_gl_span_compositor_get ());
_cairo_atomic_init_once_leave(&once);
}
return &compositor;
}

Просмотреть файл

@ -0,0 +1,793 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Eric Anholt
* Copyright © 2009 Chris Wilson
* Copyright © 2005,2010 Red Hat, Inc
* Copyright © 2011 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Benjamin Otte <otte@gnome.org>
* Carl Worth <cworth@cworth.org>
* Chris Wilson <chris@chris-wilson.co.uk>
* Eric Anholt <eric@anholt.net>
*/
#include "cairoint.h"
#include "cairo-gl-private.h"
#include "cairo-composite-rectangles-private.h"
#include "cairo-compositor-private.h"
#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-image-surface-private.h"
#include "cairo-surface-backend-private.h"
#include "cairo-surface-offset-private.h"
#include "cairo-surface-subsurface-inline.h"
static cairo_int_status_t
_cairo_gl_create_gradient_texture (cairo_gl_surface_t *dst,
const cairo_gradient_pattern_t *pattern,
cairo_gl_gradient_t **gradient)
{
cairo_gl_context_t *ctx;
cairo_status_t status;
status = _cairo_gl_context_acquire (dst->base.device, &ctx);
if (unlikely (status))
return status;
status = _cairo_gl_gradient_create (ctx, pattern->n_stops, pattern->stops, gradient);
return _cairo_gl_context_release (ctx, status);
}
static cairo_status_t
_cairo_gl_subsurface_clone_operand_init (cairo_gl_operand_t *operand,
const cairo_pattern_t *_src,
cairo_gl_surface_t *dst,
const cairo_rectangle_int_t *sample,
const cairo_rectangle_int_t *extents,
cairo_bool_t use_texgen)
{
const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
cairo_surface_pattern_t local_pattern;
cairo_surface_subsurface_t *sub;
cairo_gl_surface_t *surface;
cairo_gl_context_t *ctx;
cairo_surface_attributes_t *attributes;
cairo_status_t status;
sub = (cairo_surface_subsurface_t *) src->surface;
if (sub->snapshot &&
sub->snapshot->type == CAIRO_SURFACE_TYPE_GL &&
sub->snapshot->device == dst->base.device)
{
surface = (cairo_gl_surface_t *)
cairo_surface_reference (sub->snapshot);
}
else
{
status = _cairo_gl_context_acquire (dst->base.device, &ctx);
if (unlikely (status))
return status;
/* XXX Trim surface to the sample area within the subsurface? */
surface = (cairo_gl_surface_t *)
_cairo_gl_surface_create_scratch (ctx,
sub->target->content,
sub->extents.width,
sub->extents.height);
if (surface->base.status)
return _cairo_gl_context_release (ctx, surface->base.status);
_cairo_pattern_init_for_surface (&local_pattern, sub->target);
cairo_matrix_init_translate (&local_pattern.base.matrix,
sub->extents.x, sub->extents.y);
local_pattern.base.filter = CAIRO_FILTER_NEAREST;
status = _cairo_surface_paint (&surface->base,
CAIRO_OPERATOR_SOURCE,
&local_pattern.base,
NULL);
_cairo_pattern_fini (&local_pattern.base);
status = _cairo_gl_context_release (ctx, status);
if (unlikely (status)) {
cairo_surface_destroy (&surface->base);
return status;
}
_cairo_surface_subsurface_set_snapshot (&sub->base, &surface->base);
}
status = _cairo_gl_surface_resolve_multisampling (surface);
if (unlikely (status))
return status;
attributes = &operand->texture.attributes;
operand->type = CAIRO_GL_OPERAND_TEXTURE;
operand->texture.surface = surface;
operand->texture.owns_surface = surface;
operand->texture.tex = surface->tex;
if (_cairo_gl_device_requires_power_of_two_textures (dst->base.device)) {
attributes->matrix = src->base.matrix;
} else {
cairo_matrix_t m;
cairo_matrix_init_scale (&m,
1.0 / surface->width,
1.0 / surface->height);
cairo_matrix_multiply (&attributes->matrix, &src->base.matrix, &m);
}
attributes->extend = src->base.extend;
attributes->filter = src->base.filter;
attributes->has_component_alpha = src->base.has_component_alpha;
operand->texture.texgen = use_texgen;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand,
const cairo_pattern_t *_src,
cairo_gl_surface_t *dst,
const cairo_rectangle_int_t *sample,
const cairo_rectangle_int_t *extents,
cairo_bool_t use_texgen)
{
const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
cairo_surface_subsurface_t *sub;
cairo_gl_surface_t *surface;
cairo_surface_attributes_t *attributes;
cairo_int_status_t status;
sub = (cairo_surface_subsurface_t *) src->surface;
if (sample->x < 0 || sample->y < 0 ||
sample->x + sample->width > sub->extents.width ||
sample->y + sample->height > sub->extents.height)
{
return _cairo_gl_subsurface_clone_operand_init (operand, _src,
dst, sample, extents,
use_texgen);
}
surface = (cairo_gl_surface_t *) sub->target;
if (surface->base.device && surface->base.device != dst->base.device)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (! _cairo_gl_surface_is_texture (surface))
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_gl_surface_resolve_multisampling (surface);
if (unlikely (status))
return status;
/* Translate the matrix from
* (unnormalized src -> unnormalized src) to
* (unnormalized dst -> unnormalized src)
*/
_cairo_gl_operand_copy(operand, &surface->operand);
attributes = &operand->texture.attributes;
attributes->matrix = src->base.matrix;
attributes->matrix.x0 += sub->extents.x;
attributes->matrix.y0 += sub->extents.y;
cairo_matrix_multiply (&attributes->matrix,
&attributes->matrix,
&surface->operand.texture.attributes.matrix);
attributes->extend = src->base.extend;
attributes->filter = src->base.filter;
attributes->has_component_alpha = src->base.has_component_alpha;
operand->texture.texgen = use_texgen;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
const cairo_pattern_t *_src,
cairo_gl_surface_t *dst,
const cairo_rectangle_int_t *sample,
const cairo_rectangle_int_t *extents,
cairo_bool_t use_texgen)
{
const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
cairo_gl_surface_t *surface;
cairo_surface_attributes_t *attributes;
cairo_int_status_t status;
surface = (cairo_gl_surface_t *) src->surface;
if (surface->base.type != CAIRO_SURFACE_TYPE_GL)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (surface->base.backend->type != CAIRO_SURFACE_TYPE_GL) {
if (_cairo_surface_is_subsurface (&surface->base))
return _cairo_gl_subsurface_operand_init (operand, _src, dst,
sample, extents,
use_texgen);
return CAIRO_INT_STATUS_UNSUPPORTED;
}
if (surface->base.device && surface->base.device != dst->base.device)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (surface->base.device && ! _cairo_gl_surface_is_texture (surface))
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_gl_surface_resolve_multisampling (surface);
if (unlikely (status))
return status;
_cairo_gl_operand_copy(operand, &surface->operand);
attributes = &operand->texture.attributes;
cairo_matrix_multiply (&attributes->matrix,
&src->base.matrix,
&attributes->matrix);
attributes->extend = src->base.extend;
attributes->filter = src->base.filter;
attributes->has_component_alpha = src->base.has_component_alpha;
operand->texture.texgen = use_texgen;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
const cairo_pattern_t *_src,
cairo_gl_surface_t *dst,
const cairo_rectangle_int_t *extents)
{
cairo_status_t status;
cairo_gl_surface_t *surface;
cairo_gl_context_t *ctx;
cairo_image_surface_t *image;
cairo_bool_t src_is_gl_surface = FALSE;
cairo_rectangle_int_t map_extents;
if (_src->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_t* src_surface = ((cairo_surface_pattern_t *) _src)->surface;
src_is_gl_surface = src_surface->type == CAIRO_SURFACE_TYPE_GL;
}
status = _cairo_gl_context_acquire (dst->base.device, &ctx);
if (unlikely (status))
return status;
surface = (cairo_gl_surface_t *)
_cairo_gl_surface_create_scratch (ctx,
CAIRO_CONTENT_COLOR_ALPHA,
extents->width, extents->height);
map_extents = *extents;
map_extents.x = map_extents.y = 0;
image = _cairo_surface_map_to_image (&surface->base, &map_extents);
/* If the pattern is a GL surface, it belongs to some other GL context,
so we need to release this device while we paint it to the image. */
if (src_is_gl_surface) {
status = _cairo_gl_context_release (ctx, status);
if (unlikely (status)) {
_cairo_surface_unmap_image (&surface->base, image);
goto fail;
}
}
status = _cairo_surface_offset_paint (&image->base, extents->x, extents->y,
CAIRO_OPERATOR_SOURCE, _src, NULL);
if (src_is_gl_surface) {
status = _cairo_gl_context_acquire (dst->base.device, &ctx);
if (unlikely (status)) {
_cairo_surface_unmap_image (&surface->base, image);
goto fail;
}
}
status = _cairo_surface_unmap_image (&surface->base, image);
status = _cairo_gl_context_release (ctx, status);
if (unlikely (status))
goto fail;
*operand = surface->operand;
operand->texture.owns_surface = surface;
operand->texture.attributes.matrix.x0 -= extents->x * operand->texture.attributes.matrix.xx;
operand->texture.attributes.matrix.y0 -= extents->y * operand->texture.attributes.matrix.yy;
return CAIRO_STATUS_SUCCESS;
fail:
cairo_surface_destroy (&surface->base);
return status;
}
void
_cairo_gl_solid_operand_init (cairo_gl_operand_t *operand,
const cairo_color_t *color)
{
operand->type = CAIRO_GL_OPERAND_CONSTANT;
operand->constant.color[0] = color->red * color->alpha;
operand->constant.color[1] = color->green * color->alpha;
operand->constant.color[2] = color->blue * color->alpha;
operand->constant.color[3] = color->alpha;
}
void
_cairo_gl_operand_translate (cairo_gl_operand_t *operand,
double tx, double ty)
{
switch (operand->type) {
case CAIRO_GL_OPERAND_TEXTURE:
operand->texture.attributes.matrix.x0 -= tx * operand->texture.attributes.matrix.xx;
operand->texture.attributes.matrix.y0 -= ty * operand->texture.attributes.matrix.yy;
break;
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
operand->gradient.m.x0 -= tx * operand->gradient.m.xx;
operand->gradient.m.y0 -= ty * operand->gradient.m.yy;
break;
case CAIRO_GL_OPERAND_NONE:
case CAIRO_GL_OPERAND_CONSTANT:
case CAIRO_GL_OPERAND_COUNT:
default:
break;
}
}
static cairo_status_t
_cairo_gl_gradient_operand_init (cairo_gl_operand_t *operand,
const cairo_pattern_t *pattern,
cairo_gl_surface_t *dst,
cairo_bool_t use_texgen)
{
const cairo_gradient_pattern_t *gradient = (const cairo_gradient_pattern_t *)pattern;
cairo_status_t status;
assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
if (! _cairo_gl_device_has_glsl (dst->base.device))
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_gl_create_gradient_texture (dst,
gradient,
&operand->gradient.gradient);
if (unlikely (status))
return status;
if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
double x0, y0, dx, dy, sf, offset;
dx = linear->pd2.x - linear->pd1.x;
dy = linear->pd2.y - linear->pd1.y;
sf = 1.0 / (dx * dx + dy * dy);
dx *= sf;
dy *= sf;
x0 = linear->pd1.x;
y0 = linear->pd1.y;
offset = dx * x0 + dy * y0;
operand->type = CAIRO_GL_OPERAND_LINEAR_GRADIENT;
cairo_matrix_init (&operand->gradient.m, dx, 0, dy, 1, -offset, 0);
if (! _cairo_matrix_is_identity (&pattern->matrix)) {
cairo_matrix_multiply (&operand->gradient.m,
&pattern->matrix,
&operand->gradient.m);
}
} else {
cairo_matrix_t m;
cairo_circle_double_t circles[2];
double x0, y0, r0, dx, dy, dr;
/*
* Some fragment shader implementations use half-floats to
* represent numbers, so the maximum number they can represent
* is about 2^14. Some intermediate computations used in the
* radial gradient shaders can produce results of up to 2*k^4.
* Setting k=8 makes the maximum result about 8192 (assuming
* that the extreme circles are not much smaller than the
* destination image).
*/
_cairo_gradient_pattern_fit_to_range (gradient, 8.,
&operand->gradient.m, circles);
x0 = circles[0].center.x;
y0 = circles[0].center.y;
r0 = circles[0].radius;
dx = circles[1].center.x - x0;
dy = circles[1].center.y - y0;
dr = circles[1].radius - r0;
operand->gradient.a = dx * dx + dy * dy - dr * dr;
operand->gradient.radius_0 = r0;
operand->gradient.circle_d.center.x = dx;
operand->gradient.circle_d.center.y = dy;
operand->gradient.circle_d.radius = dr;
if (operand->gradient.a == 0)
operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0;
else if (pattern->extend == CAIRO_EXTEND_NONE)
operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE;
else
operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT;
cairo_matrix_init_translate (&m, -x0, -y0);
cairo_matrix_multiply (&operand->gradient.m,
&operand->gradient.m,
&m);
}
operand->gradient.extend = pattern->extend;
operand->gradient.texgen = use_texgen;
return CAIRO_STATUS_SUCCESS;
}
void
_cairo_gl_operand_copy (cairo_gl_operand_t *dst,
const cairo_gl_operand_t *src)
{
*dst = *src;
switch (dst->type) {
case CAIRO_GL_OPERAND_CONSTANT:
break;
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
_cairo_gl_gradient_reference (dst->gradient.gradient);
break;
case CAIRO_GL_OPERAND_TEXTURE:
cairo_surface_reference (&dst->texture.owns_surface->base);
break;
default:
case CAIRO_GL_OPERAND_COUNT:
ASSERT_NOT_REACHED;
case CAIRO_GL_OPERAND_NONE:
break;
}
}
void
_cairo_gl_operand_destroy (cairo_gl_operand_t *operand)
{
switch (operand->type) {
case CAIRO_GL_OPERAND_CONSTANT:
break;
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
_cairo_gl_gradient_destroy (operand->gradient.gradient);
break;
case CAIRO_GL_OPERAND_TEXTURE:
cairo_surface_destroy (&operand->texture.owns_surface->base);
break;
default:
case CAIRO_GL_OPERAND_COUNT:
ASSERT_NOT_REACHED;
case CAIRO_GL_OPERAND_NONE:
break;
}
operand->type = CAIRO_GL_OPERAND_NONE;
}
cairo_int_status_t
_cairo_gl_operand_init (cairo_gl_operand_t *operand,
const cairo_pattern_t *pattern,
cairo_gl_surface_t *dst,
const cairo_rectangle_int_t *sample,
const cairo_rectangle_int_t *extents,
cairo_bool_t use_texgen)
{
cairo_int_status_t status;
TRACE ((stderr, "%s: type=%d\n", __FUNCTION__, pattern->type));
switch (pattern->type) {
case CAIRO_PATTERN_TYPE_SOLID:
_cairo_gl_solid_operand_init (operand,
&((cairo_solid_pattern_t *) pattern)->color);
return CAIRO_STATUS_SUCCESS;
case CAIRO_PATTERN_TYPE_SURFACE:
status = _cairo_gl_surface_operand_init (operand, pattern, dst,
sample, extents, use_texgen);
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
break;
return status;
case CAIRO_PATTERN_TYPE_LINEAR:
case CAIRO_PATTERN_TYPE_RADIAL:
status = _cairo_gl_gradient_operand_init (operand, pattern, dst,
use_texgen);
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
break;
return status;
default:
case CAIRO_PATTERN_TYPE_MESH:
case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
break;
}
return _cairo_gl_pattern_texture_setup (operand, pattern, dst, extents);
}
cairo_filter_t
_cairo_gl_operand_get_filter (cairo_gl_operand_t *operand)
{
cairo_filter_t filter;
switch ((int) operand->type) {
case CAIRO_GL_OPERAND_TEXTURE:
filter = operand->texture.attributes.filter;
break;
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
filter = CAIRO_FILTER_BILINEAR;
break;
default:
filter = CAIRO_FILTER_DEFAULT;
break;
}
return filter;
}
GLint
_cairo_gl_operand_get_gl_filter (cairo_gl_operand_t *operand)
{
cairo_filter_t filter = _cairo_gl_operand_get_filter (operand);
return filter != CAIRO_FILTER_FAST && filter != CAIRO_FILTER_NEAREST ?
GL_LINEAR :
GL_NEAREST;
}
cairo_extend_t
_cairo_gl_operand_get_extend (cairo_gl_operand_t *operand)
{
cairo_extend_t extend;
switch ((int) operand->type) {
case CAIRO_GL_OPERAND_TEXTURE:
extend = operand->texture.attributes.extend;
break;
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
extend = operand->gradient.extend;
break;
default:
extend = CAIRO_EXTEND_NONE;
break;
}
return extend;
}
void
_cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
cairo_gl_operand_t *operand,
cairo_gl_tex_t tex_unit)
{
const cairo_matrix_t *texgen = NULL;
switch (operand->type) {
default:
case CAIRO_GL_OPERAND_COUNT:
ASSERT_NOT_REACHED;
case CAIRO_GL_OPERAND_NONE:
return;
case CAIRO_GL_OPERAND_CONSTANT:
_cairo_gl_shader_bind_vec4 (ctx,
ctx->current_shader->constant_location[tex_unit],
operand->constant.color[0],
operand->constant.color[1],
operand->constant.color[2],
operand->constant.color[3]);
return;
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
_cairo_gl_shader_bind_float (ctx,
ctx->current_shader->a_location[tex_unit],
operand->gradient.a);
/* fall through */
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
_cairo_gl_shader_bind_vec3 (ctx,
ctx->current_shader->circle_d_location[tex_unit],
operand->gradient.circle_d.center.x,
operand->gradient.circle_d.center.y,
operand->gradient.circle_d.radius);
_cairo_gl_shader_bind_float (ctx,
ctx->current_shader->radius_0_location[tex_unit],
operand->gradient.radius_0);
/* fall through */
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
case CAIRO_GL_OPERAND_TEXTURE:
/*
* For GLES2 we use shaders to implement GL_CLAMP_TO_BORDER (used
* with CAIRO_EXTEND_NONE). When bilinear filtering is enabled,
* these shaders need the texture dimensions for their calculations.
*/
if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) &&
_cairo_gl_operand_get_extend (operand) == CAIRO_EXTEND_NONE &&
_cairo_gl_operand_get_gl_filter (operand) == GL_LINEAR)
{
float width, height;
if (operand->type == CAIRO_GL_OPERAND_TEXTURE) {
width = operand->texture.surface->width;
height = operand->texture.surface->height;
}
else {
width = operand->gradient.gradient->cache_entry.size,
height = 1;
}
_cairo_gl_shader_bind_vec2 (ctx,
ctx->current_shader->texdims_location[tex_unit],
width, height);
}
break;
}
if (operand->type == CAIRO_GL_OPERAND_TEXTURE) {
if (operand->texture.texgen)
texgen = &operand->texture.attributes.matrix;
} else {
if (operand->gradient.texgen)
texgen = &operand->gradient.m;
}
if (texgen) {
_cairo_gl_shader_bind_matrix(ctx,
ctx->current_shader->texgen_location[tex_unit],
texgen);
}
}
cairo_bool_t
_cairo_gl_operand_needs_setup (cairo_gl_operand_t *dest,
cairo_gl_operand_t *source,
unsigned int vertex_offset)
{
if (dest->type != source->type)
return TRUE;
if (dest->vertex_offset != vertex_offset)
return TRUE;
switch (source->type) {
case CAIRO_GL_OPERAND_NONE:
return FALSE;
case CAIRO_GL_OPERAND_CONSTANT:
return dest->constant.color[0] != source->constant.color[0] ||
dest->constant.color[1] != source->constant.color[1] ||
dest->constant.color[2] != source->constant.color[2] ||
dest->constant.color[3] != source->constant.color[3];
case CAIRO_GL_OPERAND_TEXTURE:
return dest->texture.surface != source->texture.surface ||
dest->texture.attributes.extend != source->texture.attributes.extend ||
dest->texture.attributes.filter != source->texture.attributes.filter ||
dest->texture.attributes.has_component_alpha != source->texture.attributes.has_component_alpha;
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
/* XXX: improve this */
return TRUE;
default:
case CAIRO_GL_OPERAND_COUNT:
ASSERT_NOT_REACHED;
break;
}
return TRUE;
}
unsigned int
_cairo_gl_operand_get_vertex_size (const cairo_gl_operand_t *operand)
{
switch (operand->type) {
default:
case CAIRO_GL_OPERAND_COUNT:
ASSERT_NOT_REACHED;
case CAIRO_GL_OPERAND_NONE:
case CAIRO_GL_OPERAND_CONSTANT:
return 0;
case CAIRO_GL_OPERAND_TEXTURE:
return operand->texture.texgen ? 0 : 2 * sizeof (GLfloat);
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
return operand->gradient.texgen ? 0 : 2 * sizeof (GLfloat);
}
}
void
_cairo_gl_operand_emit (cairo_gl_operand_t *operand,
GLfloat ** vb,
GLfloat x,
GLfloat y)
{
switch (operand->type) {
default:
case CAIRO_GL_OPERAND_COUNT:
ASSERT_NOT_REACHED;
case CAIRO_GL_OPERAND_NONE:
case CAIRO_GL_OPERAND_CONSTANT:
break;
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
if (! operand->gradient.texgen) {
double s = x;
double t = y;
cairo_matrix_transform_point (&operand->gradient.m, &s, &t);
*(*vb)++ = s;
*(*vb)++ = t;
}
break;
case CAIRO_GL_OPERAND_TEXTURE:
if (! operand->texture.texgen) {
cairo_surface_attributes_t *src_attributes = &operand->texture.attributes;
double s = x;
double t = y;
cairo_matrix_transform_point (&src_attributes->matrix, &s, &t);
*(*vb)++ = s;
*(*vb)++ = t;
}
break;
}
}

Просмотреть файл

@ -3,6 +3,7 @@
* Copyright © 2009 Eric Anholt
* Copyright © 2009 Chris Wilson
* Copyright © 2005,2010 Red Hat, Inc
* Copyright © 2011 Linaro Limited
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@ -37,28 +38,40 @@
* Chris Wilson <chris@chris-wilson.co.uk>
* Eric Anholt <eric@anholt.net>
* T. Zachary Laine <whatwasthataddress@gmail.com>
* Alexandros Frantzis <alexandros.frantzis@linaro.org>
*/
#ifndef CAIRO_GL_PRIVATE_H
#define CAIRO_GL_PRIVATE_H
#define GL_GLEXT_PROTOTYPES
#include "cairoint.h"
#include "cairo-gl.h"
#include "cairo-gl-gradient-private.h"
#include "cairo-device-private.h"
#include "cairo-error-private.h"
#include "cairo-rtree-private.h"
#include "cairo-scaled-font-private.h"
#include "cairo-spans-compositor-private.h"
#include "cairo-array-private.h"
#include <assert.h>
#include <GL/glew.h>
#include "cairo-gl.h"
#if CAIRO_HAS_GLESV3_SURFACE
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#elif CAIRO_HAS_GLESV2_SURFACE
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#elif CAIRO_HAS_GL_SURFACE
#include <GL/gl.h>
#define GL_GLEXT_PROTOTYPES
#include <GL/glext.h>
#endif
#include "cairo-gl-ext-def-private.h"
#define DEBUG_GL 0
@ -73,27 +86,119 @@
#define UNSUPPORTED(reason) CAIRO_INT_STATUS_UNSUPPORTED
#endif
#define CAIRO_GL_VERSION_ENCODE(major, minor) ( \
((major) * 256) \
+ ((minor) * 1))
/* maximal number of shaders we keep in the cache.
* Random number that is hopefully big enough to not cause many cache evictions. */
#define CAIRO_GL_MAX_SHADERS_PER_CONTEXT 64
/* VBO size that we allocate, smaller size means we gotta flush more often */
#define CAIRO_GL_VBO_SIZE 16384
/* VBO size that we allocate, smaller size means we gotta flush more often,
* but larger means hogging more memory and can cause trouble for drivers
* (especially on embedded devices). Use the CAIRO_GL_VBO_SIZE environment
* variable to set this to a different size. */
#define CAIRO_GL_VBO_SIZE_DEFAULT (1024*1024)
typedef struct _cairo_gl_surface {
typedef struct _cairo_gl_surface cairo_gl_surface_t;
/* GL flavor is the type of GL supported by the underlying platform. */
typedef enum cairo_gl_flavor {
CAIRO_GL_FLAVOR_NONE = 0,
CAIRO_GL_FLAVOR_DESKTOP = 1,
CAIRO_GL_FLAVOR_ES2 = 2,
CAIRO_GL_FLAVOR_ES3 = 3
} cairo_gl_flavor_t;
/* Indices for vertex attributes used by BindAttribLocation, etc. */
enum {
CAIRO_GL_VERTEX_ATTRIB_INDEX = 0,
CAIRO_GL_COLOR_ATTRIB_INDEX = 1,
CAIRO_GL_TEXCOORD0_ATTRIB_INDEX = 2,
CAIRO_GL_TEXCOORD1_ATTRIB_INDEX = CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + 1
};
typedef enum cairo_gl_operand_type {
CAIRO_GL_OPERAND_NONE,
CAIRO_GL_OPERAND_CONSTANT,
CAIRO_GL_OPERAND_TEXTURE,
CAIRO_GL_OPERAND_LINEAR_GRADIENT,
CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0,
CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE,
CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT,
CAIRO_GL_OPERAND_COUNT
} cairo_gl_operand_type_t;
/* This union structure describes a potential source or mask operand to the
* compositing equation.
*/
typedef struct cairo_gl_operand {
cairo_gl_operand_type_t type;
union {
struct {
GLuint tex;
cairo_gl_surface_t *surface;
cairo_gl_surface_t *owns_surface;
cairo_surface_attributes_t attributes;
int texgen;
} texture;
struct {
GLfloat color[4];
} constant;
struct {
cairo_gl_gradient_t *gradient;
cairo_matrix_t m;
cairo_circle_double_t circle_d;
double radius_0, a;
cairo_extend_t extend;
int texgen;
} gradient;
};
unsigned int vertex_offset;
} cairo_gl_operand_t;
typedef struct cairo_gl_source {
cairo_surface_t base;
cairo_gl_operand_t operand;
} cairo_gl_source_t;
struct _cairo_gl_surface {
cairo_surface_t base;
cairo_gl_operand_t operand;
int width, height;
GLuint tex; /* GL texture object containing our data. */
GLuint fb; /* GL framebuffer object wrapping our data. */
GLuint depth; /* GL framebuffer object holding depth */
GLuint depth_stencil; /* GL renderbuffer object for holding stencil buffer clip. */
#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
GLuint msaa_rb; /* The ARB MSAA path uses a renderbuffer. */
GLuint msaa_fb;
#endif
GLuint msaa_depth_stencil;
cairo_bool_t stencil_and_msaa_caps_initialized;
cairo_bool_t supports_stencil; /* Stencil support for for non-texture surfaces. */
cairo_bool_t supports_msaa;
GLint num_samples;
cairo_bool_t msaa_active; /* Whether the multisampling
framebuffer is active or not. */
cairo_bool_t content_in_texture; /* whether we just uploaded image
to texture, used for certain
gles2 extensions and glesv3 */
cairo_clip_t *clip_on_stencil_buffer;
int owns_tex;
} cairo_gl_surface_t;
cairo_bool_t needs_update;
cairo_region_t *clip_region;
};
typedef struct cairo_gl_glyph_cache {
cairo_rtree_t rtree;
cairo_surface_pattern_t pattern;
cairo_gl_surface_t *surface;
} cairo_gl_glyph_cache_t;
typedef enum cairo_gl_tex {
@ -102,22 +207,16 @@ typedef enum cairo_gl_tex {
CAIRO_GL_TEX_TEMP = 2
} cairo_gl_tex_t;
typedef enum cairo_gl_operand_type {
CAIRO_GL_OPERAND_NONE,
CAIRO_GL_OPERAND_CONSTANT,
CAIRO_GL_OPERAND_TEXTURE,
CAIRO_GL_OPERAND_LINEAR_GRADIENT,
CAIRO_GL_OPERAND_RADIAL_GRADIENT,
CAIRO_GL_OPERAND_SPANS,
CAIRO_GL_OPERAND_COUNT
} cairo_gl_operand_type_t;
typedef struct cairo_gl_shader_impl cairo_gl_shader_impl_t;
typedef struct cairo_gl_shader {
GLuint fragment_shader;
GLuint program;
GLint mvp_location;
GLint constant_location[2];
GLint a_location[2];
GLint circle_d_location[2];
GLint radius_0_location[2];
GLint texdims_location[2];
GLint texgen_location[2];
} cairo_gl_shader_t;
typedef enum cairo_gl_shader_in {
@ -131,60 +230,130 @@ typedef enum cairo_gl_shader_in {
typedef enum cairo_gl_var_type {
CAIRO_GL_VAR_NONE,
CAIRO_GL_VAR_TEXCOORDS,
CAIRO_GL_VAR_COVERAGE
CAIRO_GL_VAR_TEXGEN,
} cairo_gl_var_type_t;
#define cairo_gl_var_type_hash(src,mask,dest) ((mask) << 2 | (src << 1) | (dest))
#define CAIRO_GL_VAR_TYPE_MAX ((CAIRO_GL_VAR_COVERAGE << 2) | (CAIRO_GL_VAR_TEXCOORDS << 1) | CAIRO_GL_VAR_TEXCOORDS)
typedef enum cairo_gl_primitive_type {
CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES,
CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS
} cairo_gl_primitive_type_t;
/* This union structure describes a potential source or mask operand to the
* compositing equation.
*/
typedef struct cairo_gl_operand {
cairo_gl_operand_type_t type;
union {
struct {
GLuint tex;
cairo_gl_surface_t *surface;
cairo_surface_attributes_t attributes;
} texture;
struct {
GLfloat color[4];
} constant;
struct {
cairo_gl_gradient_t *gradient;
cairo_matrix_t m;
float segment_x;
float segment_y;
cairo_extend_t extend;
} linear;
struct {
cairo_gl_gradient_t *gradient;
cairo_matrix_t m;
float circle_1_x;
float circle_1_y;
float radius_0;
float radius_1;
cairo_extend_t extend;
} radial;
};
unsigned int vertex_offset;
} cairo_gl_operand_t;
typedef void (*cairo_gl_emit_rect_t) (cairo_gl_context_t *ctx,
GLfloat x1, GLfloat y1,
GLfloat x2, GLfloat y2);
typedef void (*cairo_gl_emit_span_t) (cairo_gl_context_t *ctx,
GLfloat x1, GLfloat y1,
GLfloat x2, GLfloat y2,
uint8_t alpha);
typedef void (*cairo_gl_emit_glyph_t) (cairo_gl_context_t *ctx,
GLfloat x1, GLfloat y1,
GLfloat x2, GLfloat y2,
GLfloat glyph_x1, GLfloat glyph_y1,
GLfloat glyph_x2, GLfloat glyph_y2);
#define cairo_gl_var_type_hash(src,mask,spans,dest) ((spans) << 5) | ((mask) << 3 | (src << 1) | (dest))
#define CAIRO_GL_VAR_TYPE_MAX (1 << 6)
typedef void (*cairo_gl_generic_func_t)(void);
typedef cairo_gl_generic_func_t (*cairo_gl_get_proc_addr_func_t)(const char *procname);
typedef struct _cairo_gl_dispatch {
/* Buffers */
void (*GenBuffers) (GLsizei n, GLuint *buffers);
void (*BindBuffer) (GLenum target, GLuint buffer);
void (*BufferData) (GLenum target, GLsizeiptr size,
const GLvoid* data, GLenum usage);
GLvoid *(*MapBuffer) (GLenum target, GLenum access);
GLboolean (*UnmapBuffer) (GLenum target);
/* Shaders */
GLuint (*CreateShader) (GLenum type);
void (*ShaderSource) (GLuint shader, GLsizei count,
const GLchar** string, const GLint* length);
void (*CompileShader) (GLuint shader);
void (*GetShaderiv) (GLuint shader, GLenum pname, GLint *params);
void (*GetShaderInfoLog) (GLuint shader, GLsizei bufSize,
GLsizei *length, GLchar *infoLog);
void (*DeleteShader) (GLuint shader);
/* Programs */
GLuint (*CreateProgram) (void);
void (*AttachShader) (GLuint program, GLuint shader);
void (*DeleteProgram) (GLuint program);
void (*LinkProgram) (GLuint program);
void (*UseProgram) (GLuint program);
void (*GetProgramiv) (GLuint program, GLenum pname, GLint *params);
void (*GetProgramInfoLog) (GLuint program, GLsizei bufSize,
GLsizei *length, GLchar *infoLog);
/* Uniforms */
GLint (*GetUniformLocation) (GLuint program, const GLchar* name);
void (*Uniform1f) (GLint location, GLfloat x);
void (*Uniform2f) (GLint location, GLfloat x, GLfloat y);
void (*Uniform3f) (GLint location, GLfloat x, GLfloat y, GLfloat z);
void (*Uniform4f) (GLint location, GLfloat x, GLfloat y, GLfloat z,
GLfloat w);
void (*UniformMatrix3fv) (GLint location, GLsizei count,
GLboolean transpose, const GLfloat *value);
void (*UniformMatrix4fv) (GLint location, GLsizei count,
GLboolean transpose, const GLfloat *value);
void (*Uniform1i) (GLint location, GLint x);
/* Attributes */
void (*BindAttribLocation) (GLuint program, GLuint index,
const GLchar *name);
void (*VertexAttribPointer) (GLuint index, GLint size, GLenum type,
GLboolean normalized, GLsizei stride,
const GLvoid *pointer);
void (*EnableVertexAttribArray) (GLuint index);
void (*DisableVertexAttribArray) (GLuint index);
/* Framebuffer objects */
void (*GenFramebuffers) (GLsizei n, GLuint* framebuffers);
void (*BindFramebuffer) (GLenum target, GLuint framebuffer);
void (*FramebufferTexture2D) (GLenum target, GLenum attachment,
GLenum textarget, GLuint texture,
GLint level);
GLenum (*CheckFramebufferStatus) (GLenum target);
void (*DeleteFramebuffers) (GLsizei n, const GLuint* framebuffers);
void (*GenRenderbuffers) (GLsizei n, GLuint *renderbuffers);
void (*BindRenderbuffer) (GLenum target, GLuint renderbuffer);
void (*RenderbufferStorage) (GLenum target, GLenum internal_format,
GLsizei width, GLsizei height);
void (*FramebufferRenderbuffer) (GLenum target, GLenum attachment,
GLenum renderbuffer_ttarget, GLuint renderbuffer);
void (*DeleteRenderbuffers) (GLsizei n, GLuint *renderbuffers);
void (*BlitFramebuffer) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
void (*RenderbufferStorageMultisample) (GLenum target, GLsizei samples,
GLenum internalformat,
GLsizei width, GLsizei height);
void (*FramebufferTexture2DMultisample) (GLenum target, GLenum attachment,
GLenum textarget, GLuint texture,
GLint level, GLsizei samples);
} cairo_gl_dispatch_t;
struct _cairo_gl_context {
cairo_device_t base;
GLuint dummy_tex;
const cairo_compositor_t *compositor;
GLuint texture_load_pbo;
GLuint vbo;
GLint max_framebuffer_size;
GLint max_texture_size;
GLint max_textures;
GLenum tex_target;
const cairo_gl_shader_impl_t *shader_impl;
GLint num_samples;
cairo_bool_t supports_msaa;
char *vb;
GLuint vertex_shaders[CAIRO_GL_VAR_TYPE_MAX + 1];
cairo_bool_t has_shader_support;
GLuint vertex_shaders[CAIRO_GL_VAR_TYPE_MAX];
cairo_gl_shader_t fill_rectangles_shader;
cairo_cache_t shaders;
@ -199,11 +368,27 @@ struct _cairo_gl_context {
cairo_gl_shader_t *current_shader;
cairo_gl_operand_t operands[2];
cairo_bool_t spans;
char *vb;
unsigned int vbo_size;
unsigned int vb_offset;
unsigned int vertex_size;
cairo_region_t *clip_region;
cairo_clip_t *clip;
cairo_gl_primitive_type_t primitive_type;
cairo_array_t tristrip_indices;
cairo_bool_t has_mesa_pack_invert;
cairo_gl_dispatch_t dispatch;
GLfloat modelviewprojection_matrix[16];
cairo_gl_flavor_t gl_flavor;
cairo_bool_t has_map_buffer;
cairo_bool_t has_packed_depth_stencil;
cairo_bool_t has_npot_repeat;
cairo_bool_t can_read_bgra;
cairo_bool_t thread_aware;
void (*acquire) (void *ctx);
void (*release) (void *ctx);
@ -220,9 +405,17 @@ typedef struct _cairo_gl_composite {
cairo_gl_operand_t src;
cairo_gl_operand_t mask;
cairo_bool_t spans;
cairo_clip_t *clip;
cairo_bool_t multisample;
} cairo_gl_composite_t;
cairo_private extern const cairo_surface_backend_t _cairo_gl_surface_backend;
typedef struct _cairo_gl_font {
cairo_scaled_font_private_t base;
cairo_device_t *device;
cairo_list_t link;
} cairo_gl_font_t;
static cairo_always_inline GLenum
_cairo_gl_get_error (void)
@ -261,18 +454,22 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
cairo_image_surface_t *src,
int src_x, int src_y,
int width, int height,
int dst_x, int dst_y);
int dst_x, int dst_y,
cairo_bool_t force_flush);
cairo_private cairo_int_status_t
_cairo_gl_surface_resolve_multisampling (cairo_gl_surface_t *surface);
static cairo_always_inline cairo_bool_t
_cairo_gl_device_has_glsl (cairo_device_t *device)
{
return ((cairo_gl_context_t *) device)->shader_impl != NULL;
return ((cairo_gl_context_t *) device)->has_shader_support;
}
static cairo_always_inline cairo_bool_t
_cairo_gl_device_requires_power_of_two_textures (cairo_device_t *device)
{
return ((cairo_gl_context_t *) device)->tex_target == GL_TEXTURE_RECTANGLE_EXT;
return ((cairo_gl_context_t *) device)->tex_target == GL_TEXTURE_RECTANGLE;
}
static cairo_always_inline cairo_status_t cairo_warn
@ -312,7 +509,28 @@ _cairo_gl_context_release (cairo_gl_context_t *ctx, cairo_status_t status)
}
cairo_private void
_cairo_gl_context_set_destination (cairo_gl_context_t *ctx, cairo_gl_surface_t *surface);
_cairo_gl_context_set_destination (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface,
cairo_bool_t multisampling);
cairo_private void
_cairo_gl_context_bind_framebuffer (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface,
cairo_bool_t multisampling);
cairo_private cairo_gl_emit_rect_t
_cairo_gl_context_choose_emit_rect (cairo_gl_context_t *ctx);
cairo_private void
_cairo_gl_context_emit_rect (cairo_gl_context_t *ctx,
GLfloat x1, GLfloat y1,
GLfloat x2, GLfloat y2);
cairo_private cairo_gl_emit_span_t
_cairo_gl_context_choose_emit_span (cairo_gl_context_t *ctx);
cairo_private cairo_gl_emit_glyph_t
_cairo_gl_context_choose_emit_glyph (cairo_gl_context_t *ctx);
cairo_private void
_cairo_gl_context_activate (cairo_gl_context_t *ctx,
@ -321,78 +539,95 @@ _cairo_gl_context_activate (cairo_gl_context_t *ctx,
cairo_private cairo_bool_t
_cairo_gl_operator_is_supported (cairo_operator_t op);
cairo_private cairo_bool_t
_cairo_gl_ensure_stencil (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface);
cairo_private cairo_status_t
_cairo_gl_composite_init (cairo_gl_composite_t *setup,
cairo_operator_t op,
cairo_gl_surface_t *dst,
cairo_bool_t has_component_alpha,
const cairo_rectangle_int_t *rect);
cairo_bool_t has_component_alpha);
cairo_private void
_cairo_gl_composite_fini (cairo_gl_composite_t *setup);
cairo_private cairo_status_t
_cairo_gl_composite_set_operator (cairo_gl_composite_t *setup,
cairo_operator_t op,
cairo_bool_t assume_component_alpha);
cairo_private void
_cairo_gl_composite_set_clip_region (cairo_gl_composite_t *setup,
cairo_region_t *clip_region);
cairo_private void
_cairo_gl_composite_set_clip(cairo_gl_composite_t *setup,
cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_gl_composite_set_source (cairo_gl_composite_t *setup,
const cairo_pattern_t *pattern,
int src_x, int src_y,
int dst_x, int dst_y,
int width, int height);
const cairo_pattern_t *pattern,
const cairo_rectangle_int_t *sample,
const cairo_rectangle_int_t *extents,
cairo_bool_t use_texgen);
cairo_private void
_cairo_gl_composite_set_solid_source (cairo_gl_composite_t *setup,
const cairo_color_t *color);
cairo_private void
_cairo_gl_composite_set_source_operand (cairo_gl_composite_t *setup,
const cairo_gl_operand_t *source);
cairo_private cairo_int_status_t
_cairo_gl_composite_set_mask (cairo_gl_composite_t *setup,
const cairo_pattern_t *pattern,
int src_x, int src_y,
int dst_x, int dst_y,
int width, int height);
const cairo_rectangle_int_t *sample,
const cairo_rectangle_int_t *extents,
cairo_bool_t use_texgen);
cairo_private void
_cairo_gl_composite_set_mask_spans (cairo_gl_composite_t *setup);
_cairo_gl_composite_set_mask_operand (cairo_gl_composite_t *setup,
const cairo_gl_operand_t *mask);
cairo_private void
_cairo_gl_composite_set_spans (cairo_gl_composite_t *setup);
cairo_private void
_cairo_gl_composite_set_multisample (cairo_gl_composite_t *setup);
cairo_private cairo_status_t
_cairo_gl_composite_begin (cairo_gl_composite_t *setup,
cairo_gl_context_t **ctx);
cairo_private void
_cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx,
GLfloat x1,
GLfloat y1,
GLfloat x2,
GLfloat y2,
uint8_t alpha);
cairo_private void
_cairo_gl_composite_emit_glyph (cairo_gl_context_t *ctx,
GLfloat x1,
GLfloat y1,
GLfloat x2,
GLfloat y2,
GLfloat glyph_x1,
GLfloat glyph_y1,
GLfloat glyph_x2,
GLfloat glyph_y2);
cairo_private cairo_status_t
_cairo_gl_set_operands_and_operator (cairo_gl_composite_t *setup,
cairo_gl_context_t *ctx);
cairo_private void
_cairo_gl_composite_flush (cairo_gl_context_t *ctx);
cairo_private cairo_int_status_t
_cairo_gl_composite_emit_quad_as_tristrip (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
const cairo_point_t quad[4]);
cairo_private cairo_int_status_t
_cairo_gl_composite_emit_triangle_as_tristrip (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
const cairo_point_t triangle[3]);
cairo_private void
_cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx,
cairo_gl_tex_t tex_unit);
cairo_private cairo_bool_t
_cairo_gl_get_image_format_and_type (pixman_format_code_t pixman_format,
_cairo_gl_get_image_format_and_type (cairo_gl_flavor_t flavor,
pixman_format_code_t pixman_format,
GLenum *internal_format, GLenum *format,
GLenum *type, cairo_bool_t *has_alpha);
cairo_private void
_cairo_gl_surface_scaled_font_fini ( cairo_scaled_font_t *scaled_font);
cairo_private void
_cairo_gl_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_font_t *scaled_font);
GLenum *type, cairo_bool_t *has_alpha,
cairo_bool_t *needs_swap);
cairo_private void
_cairo_gl_glyph_cache_init (cairo_gl_glyph_cache_t *cache);
@ -408,18 +643,9 @@ _cairo_gl_surface_show_glyphs (void *abstract_dst,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
cairo_clip_t *clip,
const cairo_clip_t *clip,
int *remaining_glyphs);
static inline int
_cairo_gl_y_flip (cairo_gl_surface_t *surface, int y)
{
if (surface->fb)
return y;
else
return (surface->height - 1) - y;
}
cairo_private cairo_status_t
_cairo_gl_context_init_shaders (cairo_gl_context_t *ctx);
@ -429,48 +655,49 @@ _cairo_gl_context_fini_shaders (cairo_gl_context_t *ctx);
static cairo_always_inline cairo_bool_t
_cairo_gl_context_is_flushed (cairo_gl_context_t *ctx)
{
return ctx->vb == NULL;
return ctx->vb_offset == 0;
}
cairo_private cairo_status_t
_cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx,
cairo_gl_operand_type_t source,
cairo_gl_operand_type_t mask,
cairo_gl_operand_t *source,
cairo_gl_operand_t *mask,
cairo_bool_t use_coverage,
cairo_gl_shader_in_t in,
cairo_gl_shader_t **shader);
cairo_private void
_cairo_gl_shader_bind_float (cairo_gl_context_t *ctx,
const char *name,
GLint location,
float value);
cairo_private void
_cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx,
const char *name,
GLint location,
float value0, float value1);
cairo_private void
_cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx,
const char *name,
GLint location,
float value0,
float value1,
float value2);
cairo_private void
_cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx,
const char *name,
GLint location,
float value0, float value1,
float value2, float value3);
cairo_private void
_cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx,
const char *name,
cairo_matrix_t* m);
GLint location,
const cairo_matrix_t* m);
cairo_private void
_cairo_gl_shader_bind_texture (cairo_gl_context_t *ctx,
const char *name,
GLuint tex_unit);
_cairo_gl_shader_bind_matrix4f (cairo_gl_context_t *ctx,
GLint location,
GLfloat* gl_m);
cairo_private void
_cairo_gl_set_shader (cairo_gl_context_t *ctx,
@ -479,6 +706,159 @@ _cairo_gl_set_shader (cairo_gl_context_t *ctx,
cairo_private void
_cairo_gl_shader_fini (cairo_gl_context_t *ctx, cairo_gl_shader_t *shader);
cairo_private int
_cairo_gl_get_version (void);
cairo_private cairo_gl_flavor_t
_cairo_gl_get_flavor (void);
cairo_private unsigned long
_cairo_gl_get_vbo_size (void);
cairo_private cairo_bool_t
_cairo_gl_has_extension (const char *ext);
cairo_private cairo_status_t
_cairo_gl_dispatch_init(cairo_gl_dispatch_t *dispatch,
cairo_gl_get_proc_addr_func_t get_proc_addr);
cairo_private cairo_int_status_t
_cairo_gl_operand_init (cairo_gl_operand_t *operand,
const cairo_pattern_t *pattern,
cairo_gl_surface_t *dst,
const cairo_rectangle_int_t *sample,
const cairo_rectangle_int_t *extents,
cairo_bool_t use_texgen);
cairo_private void
_cairo_gl_solid_operand_init (cairo_gl_operand_t *operand,
const cairo_color_t *color);
cairo_private cairo_filter_t
_cairo_gl_operand_get_filter (cairo_gl_operand_t *operand);
cairo_private GLint
_cairo_gl_operand_get_gl_filter (cairo_gl_operand_t *operand);
cairo_private cairo_extend_t
_cairo_gl_operand_get_extend (cairo_gl_operand_t *operand);
cairo_private unsigned int
_cairo_gl_operand_get_vertex_size (const cairo_gl_operand_t *operand);
cairo_private cairo_bool_t
_cairo_gl_operand_needs_setup (cairo_gl_operand_t *dest,
cairo_gl_operand_t *source,
unsigned int vertex_offset);
cairo_private void
_cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
cairo_gl_operand_t *operand,
cairo_gl_tex_t tex_unit);
cairo_private void
_cairo_gl_operand_emit (cairo_gl_operand_t *operand,
GLfloat ** vb,
GLfloat x,
GLfloat y);
cairo_private void
_cairo_gl_operand_copy (cairo_gl_operand_t *dst,
const cairo_gl_operand_t *src);
cairo_private void
_cairo_gl_operand_translate (cairo_gl_operand_t *operand,
double tx, double ty);
cairo_private void
_cairo_gl_operand_destroy (cairo_gl_operand_t *operand);
cairo_private const cairo_compositor_t *
_cairo_gl_msaa_compositor_get (void);
cairo_private const cairo_compositor_t *
_cairo_gl_span_compositor_get (void);
cairo_private const cairo_compositor_t *
_cairo_gl_traps_compositor_get (void);
cairo_private cairo_int_status_t
_cairo_gl_check_composite_glyphs (const cairo_composite_rectangles_t *extents,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int *num_glyphs);
cairo_private cairo_int_status_t
_cairo_gl_composite_glyphs (void *_dst,
cairo_operator_t op,
cairo_surface_t *_src,
int src_x,
int src_y,
int dst_x,
int dst_y,
cairo_composite_glyphs_info_t *info);
cairo_private cairo_int_status_t
_cairo_gl_composite_glyphs_with_clip (void *_dst,
cairo_operator_t op,
cairo_surface_t *_src,
int src_x,
int src_y,
int dst_x,
int dst_y,
cairo_composite_glyphs_info_t *info,
cairo_clip_t *clip);
cairo_private void
_cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface);
cairo_private cairo_surface_t *
_cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx,
cairo_content_t content,
int width,
int height);
cairo_private cairo_surface_t *
_cairo_gl_surface_create_scratch_for_caching (cairo_gl_context_t *ctx,
cairo_content_t content,
int width,
int height);
cairo_private cairo_surface_t *
_cairo_gl_pattern_to_source (cairo_surface_t *dst,
const cairo_pattern_t *pattern,
cairo_bool_t is_mask,
const cairo_rectangle_int_t *extents,
const cairo_rectangle_int_t *sample,
int *src_x, int *src_y);
cairo_private cairo_int_status_t
_cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
cairo_clip_t *clip);
cairo_private cairo_surface_t *
_cairo_gl_white_source (void);
cairo_private void
_cairo_gl_scissor_to_rectangle (cairo_gl_surface_t *surface,
const cairo_rectangle_int_t *r);
static inline cairo_gl_operand_t *
source_to_operand (cairo_surface_t *surface)
{
cairo_gl_source_t *source = (cairo_gl_source_t *)surface;
return source ? &source->operand : NULL;
}
static inline void
_cairo_gl_glyph_cache_unlock (cairo_gl_glyph_cache_t *cache)
{
_cairo_rtree_unpin (&cache->rtree);
}
slim_hidden_proto (cairo_gl_surface_create);
slim_hidden_proto (cairo_gl_surface_create_for_texture);

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше