зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
93c9a68ac1
Коммит
8cafeeb79e
|
@ -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
|
||||
|
|
3231
gfx/cairo/cairo/NEWS
3231
gfx/cairo/cairo/NEWS
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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);
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче