pax_global_header00006660000000000000000000000064132376242170014521gustar00rootroot0000000000000052 comment=c74dc1e3589bd8a197582836c7db2ab400a988bb pycairo-1.16.2/000077500000000000000000000000001323762421700132565ustar00rootroot00000000000000pycairo-1.16.2/.appveyor.yml000066400000000000000000000024001323762421700157200ustar00rootroot00000000000000environment: matrix: - MSYS2_ARCH: x86_64 MSYSTEM: MINGW64 PYTHON: python2 - MSYS2_ARCH: i686 MSYSTEM: MINGW32 PYTHON: python2 - MSYS2_ARCH: x86_64 MSYSTEM: MINGW64 PYTHON: python3 - MSYS2_ARCH: i686 MSYSTEM: MINGW32 PYTHON: python3 - MSVC_PLATFORM: x86 PYTHON_ROOT: Python27 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - MSVC_PLATFORM: x86 PYTHON_ROOT: Python34 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - MSVC_PLATFORM: x86 PYTHON_ROOT: Python35 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - MSVC_PLATFORM: x64 PYTHON_ROOT: Python35-x64 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - MSVC_PLATFORM: x86 PYTHON_ROOT: Python36 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - MSVC_PLATFORM: x64 PYTHON_ROOT: Python36-x64 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 build_script: - IF DEFINED MSYSTEM set PATH=C:\msys64\%MSYSTEM%\bin;C:\msys64\usr\bin;%PATH% - IF DEFINED MSYSTEM set CHERE_INVOKING=yes - IF DEFINED MSYSTEM bash -lc "bash -x .appveyor/msys2-pre.sh" - IF DEFINED MSYSTEM bash -lc "bash -x .appveyor/msys2.sh" - IF DEFINED MSVC_PLATFORM ".appveyor/msvc.bat" deploy: off pycairo-1.16.2/.appveyor/000077500000000000000000000000001323762421700152015ustar00rootroot00000000000000pycairo-1.16.2/.appveyor/msvc.bat000066400000000000000000000015621323762421700166450ustar00rootroot00000000000000set CAIRO_VER=1.15.6 appveyor DownloadFile https://github.com/preshing/cairo-windows/releases/download/%CAIRO_VER%/cairo-windows-%CAIRO_VER%.zip 7z x cairo-windows-%CAIRO_VER%.zip ::~ set MSVC_PLATFORM=x86 ::~ set PYTHON_ROOT=Python27 ::~ set PATH= ::~ set LIBPATH= set CAIRO_ROOT=%CD%\cairo-windows-%CAIRO_VER% set INCLUDE=%CAIRO_ROOT%\include set LIB=%CAIRO_ROOT%\lib\%MSVC_PLATFORM% set PYTHON=C:\%PYTHON_ROOT%\python.exe ::~ call "%LOCALAPPDATA%\Programs\Common\Microsoft\Visual C++ for Python\9.0\vcvarsall.bat" %MSVC_PLATFORM% ::~ SET DISTUTILS_USE_SDK=1 ::~ SET MSSdk=1 %PYTHON% -m pip install --upgrade setuptools %PYTHON% -m pip install --upgrade pytest hypothesis coverage codecov copy cairo-windows-%CAIRO_VER%\lib\%MSVC_PLATFORM%\cairo.dll cairo set CL=/WX %PYTHON% -m coverage run --branch setup.py test %PYTHON% -m coverage xml %PYTHON% -m codecov -f coverage.xml pycairo-1.16.2/.appveyor/msys2-pre.sh000066400000000000000000000001551323762421700173770ustar00rootroot00000000000000#!/bin/bash set -e sed -i 's/^CheckSpace/#CheckSpace/g' /etc/pacman.conf pacman --noconfirm --ask 20 -Suy pycairo-1.16.2/.appveyor/msys2.sh000066400000000000000000000013111323762421700166060ustar00rootroot00000000000000set -e export MSYS2_FC_CACHE_SKIP=1 pacman --noconfirm -Suy pacman --noconfirm -S --needed mingw-w64-$MSYS2_ARCH-cairo \ mingw-w64-$MSYS2_ARCH-$PYTHON mingw-w64-$MSYS2_ARCH-$PYTHON-pip $PYTHON -m pip install pytest coverage codecov hypothesis export CFLAGS="-std=c90 -Wall -Wno-long-long -Werror -coverage" $PYTHON -m coverage run --branch setup.py test $PYTHON -m codecov $PYTHON setup.py sdist $PYTHON setup.py install --root="$(pwd)"/_root_abs $PYTHON -m pip install dist/* # Also test with older cairo curl -O "http://repo.msys2.org/mingw/$MSYS2_ARCH/mingw-w64-$MSYS2_ARCH-cairo-1.14.4-1-any.pkg.tar.xz" pacman --noconfirm -U "mingw-w64-$MSYS2_ARCH-cairo-1.14.4-1-any.pkg.tar.xz" $PYTHON setup.py test pycairo-1.16.2/.codecov.yml000066400000000000000000000001331323762421700154760ustar00rootroot00000000000000comment: false coverage: status: project: false patch: false changes: false pycairo-1.16.2/.gitignore000066400000000000000000000010171323762421700152450ustar00rootroot00000000000000# top-level .gitignore *~ .*.sw? .deps .libs .lock* .perf .waf* *.la *.lo *.orig *.rej *.pyc *.pyo *.so .cache MANIFEST dist .hypothesis *.pyd *.dll # image files *.pdf *.png *.ps *.svg *-uninstalled.pc aclocal.m4 autom4te.cache autoscan.log build build_directory config.cache config.guess config.h config.h.in config.log config.lt config.status config.sub configure configure.scan depcomp doltcompile doltlibtool install-sh libtool ltmain.sh Makefile.in missing py-compile pycairo.pc releases stamp-h stamp-h1 stamp-h.in pycairo-1.16.2/.travis.yml000066400000000000000000000064751323762421700154030ustar00rootroot00000000000000matrix: include: - os: linux dist: trusty language: python python: "2.7" env: PYCAIRO_WARN=1 CFLAGS="-Werror -coverage" - os: linux dist: trusty language: python python: "3.3" env: PYCAIRO_WARN=1 CFLAGS="-Werror -coverage" - os: linux dist: trusty language: python python: "3.4" env: PYCAIRO_WARN=1 CFLAGS="-Werror -coverage" - os: linux dist: trusty language: python python: "3.5" env: PYCAIRO_WARN=1 CFLAGS="-Werror -coverage" - os: linux dist: trusty language: python python: "3.6" env: PYCAIRO_WARN=1 CFLAGS="-Werror -coverage" - os: linux dist: trusty language: python python: "pypy2.7-5.10.0" env: PYCAIRO_WARN=1 CFLAGS="-Werror -coverage" - os: linux dist: trusty language: python python: "pypy3.5-5.10.1" env: PYCAIRO_WARN=1 CFLAGS="-coverage" - os: osx osx_image: xcode7.3 language: generic env: PYVER="3" PYCAIRO_WARN=1 CFLAGS="-Werror -coverage" - os: osx osx_image: xcode7.3 language: generic env: PYVER="2" PYCAIRO_WARN=1 CFLAGS="-Werror -coverage" install: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then travis_retry sudo apt-get update -q; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then travis_retry sudo apt-get install -y libcairo2-dev; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install pkg-config || brew upgrade pkg-config || true; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install cairo || brew upgrade cairo || true; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ "$PYVER" == "2" ]]; then brew install python || brew upgrade python || true; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ "$PYVER" == "2" ]]; then python2 -m pip install virtualenv; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ "$PYVER" == "2" ]]; then virtualenv ../venv -p python2; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ "$PYVER" == "3" ]]; then brew install python3 || brew upgrade python3 || true; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ "$PYVER" == "3" ]]; then python3 -m pip install virtualenv; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ "$PYVER" == "3" ]]; then virtualenv ../venv -p python3; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then source ../venv/bin/activate; fi - python -m pip install --upgrade setuptools - python -m pip install --upgrade pytest flake8 sphinx sphinx_rtd_theme coverage codecov hypothesis - if [[ "$TRAVIS_PYTHON_VERSION" != "3.3" ]] && [[ "${TRAVIS_PYTHON_VERSION:0:4}" != "pypy" ]]; then python -m pip install --upgrade pygame; fi script: - python -m coverage run --branch setup.py test - python -m codecov - python -m flake8 . - python setup.py sdist - python setup.py bdist - python setup.py install --root=_root - python setup.py install --root="$(pwd)"/_root_abs - python setup.py install --user - PYCAIRO_SETUPTOOLS=1 python setup.py bdist_egg - PYCAIRO_SETUPTOOLS=1 python setup.py bdist_wheel - PYCAIRO_SETUPTOOLS=1 python setup.py install --root=_root_setup - if [[ "${TRAVIS_PYTHON_VERSION:0:4}" != "pypy" ]] ; then python -m pip install .; fi - if [[ "$TRAVIS_PYTHON_VERSION" != "3.3" ]]; then python -m sphinx -W -a -E -b html -n docs docs/_build; fi pycairo-1.16.2/COPYING000066400000000000000000000011551323762421700143130ustar00rootroot00000000000000PyCairo is free software. Every source file in the implementation of PyCairo 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 liberal terms, but we believe that in all cases, each file may be used under either the LGPL or the MPL. See the following files in this directory for the precise terms and conditions of either license: COPYING-LGPL-2.1 COPYING-MPL-1.1 Please see each file in the implementation for Copyright and licensing information. pycairo-1.16.2/COPYING-LGPL-2.1000066400000000000000000000636401323762421700153540ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 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 Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! pycairo-1.16.2/COPYING-MPL-1.1000066400000000000000000000622331323762421700152420ustar00rootroot00000000000000 MOZILLA PUBLIC LICENSE Version 1.1 --------------- 1. Definitions. 1.0.1. "Commercial Use" means distribution or otherwise making the Covered Code available to a third party. 1.1. "Contributor" means each entity that creates or contributes to the creation of Modifications. 1.2. "Contributor Version" means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor. 1.3. "Covered Code" means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof. 1.4. "Electronic Distribution Mechanism" means a mechanism generally accepted in the software development community for the electronic transfer of data. 1.5. "Executable" means Covered Code in any form other than Source Code. 1.6. "Initial Developer" means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. 1.7. "Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. 1.8. "License" means this document. 1.8.1. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein. 1.9. "Modifications" means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is: A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. B. Any new file that contains any part of the Original Code or previous Modifications. 1.10. "Original Code" means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License. 1.10.1. "Patent Claims" means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor. 1.11. "Source Code" means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an Executable, or source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge. 1.12. "You" (or "Your") means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You" includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. Source Code License. 2.1. The Initial Developer Grant. The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, and/or as part of a Larger Work; and (b) under Patents Claims infringed by the making, using or selling of Original Code, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Code (or portions thereof). (c) the licenses granted in this Section 2.1(a) and (b) are effective on the date Initial Developer first distributes Original Code under the terms of this License. (d) Notwithstanding Section 2.1(b) above, no patent license is granted: 1) for code that You delete from the Original Code; 2) separate from the Original Code; or 3) for infringements caused by: i) the modification of the Original Code or ii) the combination of the Original Code with other software or devices. 2.2. Contributor Grant. Subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license (a) under intellectual property rights (other than patent or trademark) Licensable by Contributor, to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code and/or as part of a Larger Work; and (b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: 1) Modifications made by that Contributor (or portions thereof); and 2) the combination of Modifications made by that Contributor with its Contributor Version (or portions of such combination). (c) the licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first makes Commercial Use of the Covered Code. (d) Notwithstanding Section 2.2(b) above, no patent license is granted: 1) for any code that Contributor has deleted from the Contributor Version; 2) separate from the Contributor Version; 3) for infringements caused by: i) third party modifications of Contributor Version or ii) the combination of Modifications made by that Contributor with other software (except as part of the Contributor Version) or other devices; or 4) under Patent Claims infringed by Covered Code in the absence of Modifications made by that Contributor. 3. Distribution Obligations. 3.1. Application of License. The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5. 3.2. Availability of Source Code. Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party. 3.3. Description of Modifications. You must cause all Covered Code to which You contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code. 3.4. Intellectual Property Matters (a) Third Party Claims. If Contributor has knowledge that a license under a third party's intellectual property rights is required to exercise the rights granted by such Contributor under Sections 2.1 or 2.2, Contributor must include a text file with the Source Code distribution titled "LEGAL" which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If Contributor obtains such knowledge after the Modification is made available as described in Section 3.2, Contributor shall promptly modify the LEGAL file in all copies Contributor makes available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained. (b) Contributor APIs. If Contributor's Modifications include an application programming interface and Contributor has knowledge of patent licenses which are reasonably necessary to implement that API, Contributor must also include this information in the LEGAL file. (c) Representations. Contributor represents that, except as disclosed pursuant to Section 3.4(a) above, Contributor believes that Contributor's Modifications are Contributor's original creation(s) and/or Contributor has sufficient rights to grant the rights conveyed by this License. 3.5. Required Notices. You must duplicate the notice in Exhibit A in each file of the Source Code. If it is not possible to put such notice in a particular Source Code file due to its structure, then You must include such notice in a location (such as a relevant directory) where a user would be likely to look for such a notice. If You created one or more Modification(s) You may add your name as a Contributor to the notice described in Exhibit A. You must also duplicate this License in any documentation for the Source Code where You describe recipients' rights or ownership rights relating to Covered Code. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. 3.6. Distribution of Executable Versions. You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code or ownership rights under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. 3.7. Larger Works. You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code. 4. Inability to Comply Due to Statute or Regulation. If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Application of this License. This License applies to code to which the Initial Developer has attached the notice in Exhibit A and to related Covered Code. 6. Versions of the License. 6.1. New Versions. Netscape Communications Corporation ("Netscape") may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. 6.2. Effect of New Versions. Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License. 6.3. Derivative Works. If You create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), You must (a) rename Your license so that the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", "MPL", "NPL" or any confusingly similar phrase do not appear in your license (except to note that your license differs from this License) and (b) otherwise make it clear that Your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.) 7. DISCLAIMER OF WARRANTY. COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 8. TERMINATION. 8.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. 8.2. If You initiate litigation by asserting a patent infringement claim (excluding declatory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You file such action is referred to as "Participant") alleging that: (a) such Participant's Contributor Version directly or indirectly infringes any patent, then any and all rights granted by such Participant to You under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively, unless if within 60 days after receipt of notice You either: (i) agree in writing to pay Participant a mutually agreeable reasonable royalty for Your past and future use of Modifications made by such Participant, or (ii) withdraw Your litigation claim with respect to the Contributor Version against such Participant. If within 60 days of notice, a reasonable royalty and payment arrangement are not mutually agreed upon in writing by the parties or the litigation claim is not withdrawn, the rights granted by Participant to You under Sections 2.1 and/or 2.2 automatically terminate at the expiration of the 60 day notice period specified above. (b) any software, hardware, or device, other than such Participant's Contributor Version, directly or indirectly infringes any patent, then any rights granted to You by such Participant under Sections 2.1(b) and 2.2(b) are revoked effective as of the date You first made, used, sold, distributed, or had made, Modifications made by that Participant. 8.3. If You assert a patent infringement claim against Participant alleging that such Participant's Contributor Version directly or indirectly infringes any patent where such claim is resolved (such as by license or settlement) prior to the initiation of patent infringement litigation, then the reasonable value of the licenses granted by such Participant under Sections 2.1 or 2.2 shall be taken into account in determining the amount or value of any payment or license. 8.4. In the event of termination under Sections 8.1 or 8.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or any distributor hereunder prior to termination shall survive termination. 9. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. 10. U.S. GOVERNMENT END USERS. The Covered Code is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein. 11. MISCELLANEOUS. This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in the United States of America, any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys' fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. 12. RESPONSIBILITY FOR CLAIMS. As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability. 13. MULTIPLE-LICENSED CODE. Initial Developer may designate portions of the Covered Code as "Multiple-Licensed". "Multiple-Licensed" means that the Initial Developer permits you to utilize portions of the Covered Code under Your choice of the NPL or the alternative licenses, if any, specified by the Initial Developer in the file described in Exhibit A. EXHIBIT A -Mozilla Public License. ``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/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is ______________________________________. The Initial Developer of the Original Code is ________________________. Portions created by ______________________ are Copyright (C) ______ _______________________. All Rights Reserved. Contributor(s): ______________________________________. Alternatively, the contents of this file may be used under the terms of the _____ license (the "[___] License"), in which case the provisions of [______] License are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of the [____] License and not to allow others to use your version of this file under the MPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the [___] License. If you do not delete the provisions above, a recipient may use your version of this file under either the MPL or the [___] License." [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should use the text of this Exhibit A rather than the text found in the Original Code Source Code for Your Modifications.] pycairo-1.16.2/MANIFEST.in000066400000000000000000000003751323762421700150210ustar00rootroot00000000000000include COPYING* include NEWS include README.rst include MANIFEST.in include setup.cfg recursive-include docs *.py Makefile *.rst *.css *.svg prune docs/_build recursive-include tests *.py README recursive-include examples *.py README include cairo/*.h pycairo-1.16.2/NEWS000066400000000000000000000601351323762421700137620ustar00rootroot00000000000000Since version 1.11.0 Pycairo uses `Semantic Versioning `__ i.e. the newest version is the latest stable one. .. _v1.16.2: 1.16.2 - 2018-02-10 ------------------- * setup.py: Some fixes for Debian pybuild quirks. :bug:`98` .. _v1.16.1: 1.16.1 - 2018-02-06 ------------------- * setup.py: correctly install pkgconfig into /usr/lib* again. To make JHBuild on Fedora work the following patch is needed: https://bugzilla.gnome.org/show_bug.cgi?id=793216 .. _v1.16.0: 1.16.0 - 2018-02-05 ------------------- * Add a :func:`get_include` function which returns the compiler include path needed for interfacing with the Pycairo C API :bug:`92` * Note for packagers: The default header installation path has changed, but a compat header is installed to the old location to prevent breakage in case anyone has hardcoded the old path instead of using pkg-config. Just in case anyone is wondering why there are two header files now. .. _v1.15.6: 1.15.6 - 2018-01-30 ------------------- * Experimental PyPy and PyPy3 support :bug:`90` .. _v1.15.5: 1.15.5 - 2018-01-29 ------------------- * Support Unicode paths under Windows with cairo 1.15.10+ :pr:`87` * Don't include the pkg-config file when building a wheel :bug:`83` .. _v1.15.4: 1.15.4 - 2017-11-08 ------------------- Fixes: * Fix some enum conversation errors with (unused) large and negative values. :pr:`81` Tests: * Fix a rare test error :pr:`80` (:user:`Sergei Trofimovich `) .. _v1.15.3: 1.15.3 - 2017-09-17 ------------------- Fixes: * setup.py: Install pkgconfig file into /usr/share/pkgconfig to work around JHBuild on Fedora not picking it up. * Fix tests on big endian machines. :bug:`75` * Support building with MSVC :pr:`72` (:user:`Chun-wei Fan `) Tests: * Test MSVC builds on appveyor .. _v1.15.2: 1.15.2 - 2017-09-03 ------------------- Fixes: * setup.py: Install pkgconfig file to the same library prefix that Python uses. (/usr/lib64 instead of /usr/lib under Fedora for example) :bug:`70` :pr:`71` (:user:`Sander Sweers `) .. _v1.15.1: 1.15.1 - 2017-08-19 ------------------- Fixes: * Improved support for Python filesystem paths including :class:`os.PathLike`. See :class:`pathlike` for details. * Various minor fixes Changes: * Expose :class:`cairo.Path` Tests: * Improved test coverage from ~70% to ~90% .. _v1.15.0: 1.15.0 - 2017-07-24 ------------------- New Features: * Add :meth:`Surface.map_to_image` and :meth:`Surface.unmap_image` :bug:`51` * Add :class:`RasterSourcePattern` :bug:`48` * Add :class:`Glyph` :bug:`53` * Add :class:`Rectangle` :bug:`54` * Add :class:`TextCluster` :bug:`61` * Add :meth:`ScaledFont.text_to_glyphs` and :meth:`ScaledFont.glyph_extents` * Add :meth:`Context.show_text_glyphs` * Add :class:`TextExtents` :bug:`62` Changes: * Pycairo instances wrapping the same underlying cairo object now hash and compare equally e.g. ``context.get_target() == context.get_target()`` * Functions which returned a cairo error with :attr:`Status.NO_MEMORY` no longer raise :exc:`python3:MemoryError`, but a subclass of :exc:`Error` and :exc:`python3:MemoryError`. Similarly errors with :attr:`Status.READ_ERROR` and :attr:`Status.WRITE_ERROR` no longer raise :exc:`python3:IOError`, but a subclass of :exc:`Error` and :exc:`python3:IOError`. :bug:`55` * Some functions which previously returned a tuple now return a tuple subclass like :class:`Rectangle`, :class:`Glyph`, :class:`TextCluster` and :class:`TextExtents` .. _v1.14.1: 1.14.1 - 2017-07-24 ------------------- Fixes: * Fix a crash with :meth:`Surface.get_device` :bug:`57` .. _v1.14.0: 1.14.0 - 2017-07-12 ------------------- General: * Requires at least cairo 1.13.1 (The snapshop in Ubuntu 14.04) Tests: * Optional `Hypothesis `__ tests. New Features: * Add :meth:`Surface.set_device_scale` and :meth:`Surface.get_device_scale`. :pr:`44` (:user:`Sander Sweers `) * Add :class:`Device` :pr:`45` * Add :meth:`Surface.get_device` :pr:`45` * Add :class:`ScriptDevice` and :class:`ScriptMode` :pr:`46` * Add :class:`ScriptSurface` :bug:`17` * Add :attr:`Status.JBIG2_GLOBAL_MISSING` * Add :meth:`Format.stride_for_width` * Add :class:`TextClusterFlags` and :class:`SurfaceObserverMode` * Add :meth:`Gradient.get_color_stops_rgba` * Add :class:`TeeSurface` * Add :class:`MeshPattern` .. _v1.13.4: 1.13.4 - 2017-07-12 ------------------- Fixes: * Fix a rare crash with :meth:`get_data() ` under Python 3 (1.13.3 regression). .. _v1.13.3: 1.13.3 - 2017-06-01 ------------------- Fixes: * Fix ImageSurface leaking in case :meth:`get_data() ` is used under Python 3. :bug:`41` Documentation: * Add Pillow to ImageSurface example. :pr:`40` (:user:`Stuart Axon `) * Describe Freetype-py intergration. :bug:`25` :pr:`43` (:user:`Hin-Tak Leung `) .. _v1.13.2: 1.13.2 - 2017-05-21 ------------------- Fixes: * Fix pip failing to install pycairo in some cases. :bug:`39` Testing: * Added continuous testing for Windows using MSYS2 and appveyor. :bug:`19` .. _v1.13.1: 1.13.1 - 2017-05-07 ------------------- Fixes: * setup.py install: Fix generated pkg-config file if ``--home`` or ``--user`` is specified. :bug:`34` * Fix a build error on macOS Sierra. :pr:`36` (:user:`Nicolas P. Rougier `) * examples: Fix snippet examples when .pyc files are present. :bug:`35` Documentation: * Add Pyglet integration example. :pr:`33` (:user:`Stuart Axon `) .. _v1.13.0: 1.13.0 - 2017-05-03 ------------------- New Features: * The buffer returned by :meth:`ImageSurface.get_data` under Python 2 now implements the character buffer interface to make it work with pygame.image.frombuffer(). :pr:`29` * All C enum types now have their own corresponding Python enum type: :class:`Antialias`, :class:`Content`, :class:`Extend`, :class:`FillRule`, :class:`Filter`, :class:`FontSlant`, :class:`FontWeight`, :class:`Format`, :class:`HintMetrics`, :class:`HintStyle`, :class:`LineCap`, :class:`LineJoin`, :class:`Operator`, :class:`PDFVersion`, :class:`PSLevel`, :class:`PathDataType`, :class:`RegionOverlap`, :class:`SVGVersion`, :class:`Status`, :class:`SubpixelOrder`. :bug:`26` All relevant constants are now an alias to attributes of those types e.g. :data:`ANTIALIAS_DEFAULT` is the same as :attr:`Antialias.DEFAULT`. All functions returning enum values now return instances of the new types e.g. :meth:`Context.get_antialias` returns a :class:`Antialias`. :attr:`Error.status` is now a :class:`Status`. * All included examples now work with Python 2 & 3 * All included examples using GTK+ have been ported to GTK+ 3/PyGObject 3 Fixes: * Fix the signature of the :class:`ImageSurface` buffer interface for Python 2 (int -> Py_ssize_t) * setup.py: Ensure "-fno-strict-aliasing" is used with Python 2. Testing: * Added travis-ci tests for flake8 and sphinx. :pr:`30`, :pr:`32` * The test suite now has optional tests for numpy and pygame integration. .. _v1.12.0: 1.12.0 - 2017-04-18 ------------------- General: * Require cairo 1.12.0 * Use C90 and enforce it on travis-ci. :bug:`5`, :fdobug:`22940` Constants: * Add various new cairo.OPERATOR_*, cairo.ANTIALIAS_* and cairo.FORMAT_* constants. :bug:`1` * Add :data:`HAS_MIME_SURFACE` and cairo.MIME_TYPE_*. :bug:`7`, :fdobug:`58771` * Add cairo.PDF_VERSION_*. :pr:`16` * Add cairo.SVG_VERSION_* :exc:`Error`: * Add a :data:`Error.status` attribute exposing cairo.STATUS_* * Add :exc:`CairoError` alias for :exc:`Error` for cairocffi compatibility :class:`Matrix`: * Expose matrix components as read/write properties. e.g. :data:`Matrix.xx` * Fix type checking of the multiplication operator under Python 3. :bug:`8`, :fdobug:`89162` (Lawrence D'Oliveiro) :class:`Surface`: * Add :meth:`Surface.set_mime_data`. :bug:`7`, :fdobug:`58771` * Add :meth:`Surface.get_mime_data`. :bug:`7`, :fdobug:`58771` * Add :meth:`Surface.supports_mime_type`. :bug:`7`, :fdobug:`58771` * Add :meth:`Surface.create_for_rectangle`. :pr:`13` * Add :meth:`Surface.create_similar_image`. :pr:`15` * Add :meth:`Surface.has_show_text_glyphs` * Fix crash when the surface wrapper gets deallocated before the surface object. :bug:`11` :class:`Context`: * Add :meth:`Context.in_clip`. :pr:`14` :class:`PDFSurface`: * Add :meth:`PDFSurface.restrict_to_version`. :pr:`16` * Add :meth:`PDFSurface.get_versions`. :pr:`16` * Add :meth:`PDFSurface.version_to_string`. :pr:`16` :class:`SVGSurface`: * Add :meth:`SVGSurface.restrict_to_version` * Add :meth:`SVGSurface.get_versions` * Add :meth:`SVGSurface.version_to_string` :class:`XCBSurface`: * Add :meth:`XCBSurface.set_size` :class:`PSSurface`: * Add :meth:`PSSurface.get_levels` * Add :meth:`PSSurface.level_to_string` :class:`Pattern`: * Add :meth:`Pattern.set_filter` * Add :meth:`Pattern.get_filter` :class:`RecordingSurface`: * Add :meth:`RecordingSurface.get_extents` :class:`FontOptions`: * Implement ``__eq__`` and ``__ne__`` * Add :meth:`FontOptions.copy` * Add :meth:`FontOptions.hash` * Add :meth:`FontOptions.equal` * Add :meth:`FontOptions.merge` :class:`ScaledFont`: * Add :meth:`ScaledFont.get_ctm` * Add :meth:`ScaledFont.get_font_matrix` * Add :meth:`ScaledFont.get_font_options` .. _v1.11.1: 1.11.1 - 2017-04-12 ------------------- This release fixes an ABI breakage. I missed that the original pycairo master had already broken ABI compared to 1.10.0. .. _v1.11.0: 1.11.0 - 2017-04-09 ------------------- This version is based on the Python 2 version of pycairo 1.10.0 and is API/ABI compatible with both py2cairo 1.10.0 and py3cairo 1.10.0. General Changes: * Requires cairo 1.10.2+ * Switch to semantic versioning * Switch build system to distutils/setup.py (xpyb integration can be enabled with passing ``--enable-xpyb`` to setup.py build) * Moved to GitHub: https://github.com/pygobject/pycairo New Features: * Python 3 support (API/ABI compatible with py3cairo 1.10.0) including support for :exc:`cairo.Error`, :meth:`cairo.ImageSurface.get_data` and :meth:`cairo.ImageSurface.create_for_data`, which were missing in py3cairo. * :class:`cairo.RecordingSurface` (:fdobug:`36854`, `Torsten Landschoff `__) * :class:`cairo.Region`, :class:`cairo.RectangleInt` and cairo.REGION_OVERLAP_* (:fdobug:`44336`, `Bug Fly `__) Bug Fixes: * Fix crash when read()/write() methods of file objects passed to pycairo raise exceptions. * Fix possible value truncation of handles passed to Win32Surface and Win32PrintingSurface on 64bit Windows. :fdobug:`57493` 1.10.0 - 2011-05-01 ------------------- General Changes: py2cairo 1.10.0 requires cairo 1.10.0 (or later). New Constants: cairo.FORMAT_RGB16_565 Bug Fixes: * context.get_source().get_surface() fails :fdobug:`33013` * Add support for './waf configure --libdir=XXX' :fdobug:`30230` Documentation Changes: * Upgrade to using Sphinx 1.0.7. * Include html documentation in the pycairo archive file. Build Changes: * Update waf to 1.6.3 * Remove setup.py Other Changes: * Improve/simplify unicode filename support. * Improve/simplify unicode text support. 1.8.10 - 2010-05-20 ------------------- General Changes: Pycairo 1.8.10 requires cairo 1.8.10 (or later). New Classes/Types: * Win32PrintingSurface * XCBSurface - add XCB support using xpyb Bug Fixes: * Fix for libtool 2.2 (:fdobug:`27974`). * Mingw32 and pypy fixes (:fdobug:`25203`). Other Changes: Tests updated. The Win32PrintingSurface and XCBSurface changes mean that pycairo 1.8.10 is not binary compatible with pycairo 1.8.8. So modules that use the pycairo C API (like pygtk) will need to be recompiled to use pycairo 1.8.10. 1.8.8 - 2009-08-26 ------------------ General Changes: * Pycairo 1.8.8 requires cairo 1.8.8 (or later). * Move from CVS to git. * Add support for the waf build tool. Updated Methods: * The PDF/PS/SVGSurface constructors now accept None as a filename. 1.8.6 - 2009-06-25 ------------------ General Changes: Pycairo 1.8.6 requires cairo 1.8.6 (or later) Bug Fixes: * ImageSurface.create_from_png _read_func fix * ToyFontFace type fix * :fdobug:`19221`: restore cairo.Matrix '*' operator to the way it originally worked. Other Changes: Documentation completed. 1.8.4 - 2009-03-19 ------------------ General Changes: Pycairo 1.8.4 requires cairo 1.8.4 (or later) and Python 2.6 Bug Fixes: * 20674: Add get/set_extend for Gradient Patterns New Classes: cairo.ToyFontFace New Methods: | Pattern.get_extend | Pattern.set_extend | ToyFontFace.get_family | ToyFontFace.get_slant | ToyFontFace.get_weight Deleted Methods: | SurfacePattern.get_extend | SurfacePattern.set_extend Other Changes: Threading for surfaces with stream functions has been reenabled. Documentation updates. 1.8.2 - 2009-01-15 ------------------ Pycairo 1.8.0 resulted in crashes for some applications using threads. So upgrading to 1.8.2 is recommended for threaded applications. Bug Fixes: * :fdobug:`19287`: Threading support results in crashes in cairo.ImageSurface New Methods: Context.set_scaled_font API Changes: Matrix multiplication:: old code: matrix3 = matrix1 * matrix2 new equivalent code: matrix3 = matrix1.multiply(matrix2) matrix3 = matrix1 * matrix2 is now equivalent to matrix3 = matrix2.multiply(matrix1) which is consistent with standard matrix multiplication. 1.8.0 - 2008-12-15 ------------------ General Changes: Pycairo 1.8.0 requires cairo 1.8.0 (or later). Add documentation (available separately) Bug Fixes: * :fdobug:`18101`: Add support for threading * :fdobug:`18947`: cairo.SurfacePattern should INCREF the used surface New Methods: | ScaledFont.get_scale_matrix | Surface.mark_dirty_rectangle | Surface.set_fallback_resolution New Constants: | cairo.EXTEND_PAD | cairo.HAS_IMAGE_SURFACE | cairo.HAS_USER_FONT API Changes: * Surface.mark_dirty: no longer accepts keyword arguments with default values. * PycairoPattern_FromPattern (C API): has a new 'base' argument - to fix :fdobug:`18947`. Other Changes: Allow unknown cairo Pattern/Surface types to use the pycairo base Pattern/Surface type. 1.6.4 - 2008-08-18 ------------------ General changes: Pycairo 1.6.4 requires cairo 1.6.4 (or later). requires Python 2.5 (or later). Bug fixes: :fdobug:`16112`: Fix win32 'python setup.py ...' build -- use double quotes New Methods: | Context.has_current_point | Context.path_extents | ImageSurface.format_stride_for_width | PSSurface.get_eps | PSSurface.set_eps | PSSurface.ps_level_to_string | PSSurface.restrict_to_level | Surface.copy_page | Surface.show_page New Constants: cairo.PS_LEVEL_2, cairo.PS_LEVEL_3 Other changes: test/pygame-test1.py, test/pygame-test2.py : pygame tests examples/cairo_snippets/snippets/ellipse.py : Update so line-width is a constant width in device-space not user-space 1.4.12 - 2007-12-13 ------------------- General changes: Pycairo 1.4.12 requires cairo 1.4.12 (or later). requires Python 2.4 (or later). Bug fixes: * :fdobug:`10006`: update autogen.sh to support automake >= 1.10 * :fdobug:`13460`: use python-config to get python includes Other changes: * allow cairo.Context to be subclassed * create a 'doc' subdirectory and start a FAQ file 1.4.0 - 2007-03-14 ------------------ General changes: Pycairo 1.4.0 requires cairo 1.4.0 (or later). New methods: | Context.clip_extents | Context.copy_clip_rectangles | Context.get_dash | Context.get_dash_count | Context.get_scaled_font | Context.glyph_extents | Context.glyph_path | Context.show_glyphs | LinearGradient.get_linear_points | RadialGradient.get_radial_circles | SolidPattern.get_rgba | SurfacePattern.get_surface Deleted methods: ImageSurface.create_for_array Remove Numeric Python support, since Numeric has been made obsolete by numpy, and numpy data can be read using ImageSurface.create_for_data. Other changes: the module cairo.gtk has been removed (pygtk 2.7.0 onwards has cairo support built in). 1.2.6 - 2006-11-27 ------------------ * Pycairo 1.2.6 requires cairo 1.2.6 (or later). * mingw32 compiler fixes (Cedric Gustin) * setup.py improvements (Cedric Gustin) * ImageSurface.get_data() new method added ImageSurface.get_data_as_rgba() method removed 1.2.2 - 2006-08-21 ------------------ * Pycairo requires cairo 1.2.2 (or later). * setup.py has been updated to allow installation by executing $ python setup.py install * examples/cairo_snippets/snippets/gradient_mask.py A new example to demonstrate pattern masks. * The cairo.svg module has been removed because: 1) Cairo does not include SVG parsing, so this module does not belong in pycairo. 2) libsvg-cairo (the underlying C library) is unmaintained. 1.2.0 - 2006-07-03 ------------------ General changes: Pycairo has been updated to work with cairo 1.2.0. New methods: | Surface.set_fallback_resolution | Surface_get_content | ImageSurface_get_format | Image_surface_get_stride Deleted methods: PDFSurface.set_dpi, PSSurface.set_dpi, SVGSurface.set_dpi - replaced by Surface.set_fallback_resolution Other changes: cairo.FORMAT_RGB16_565 added 1.1.6 - 2006-05-29 ------------------ General changes: Pycairo has been updated to work with cairo 1.1.6. New objects: SVGSurface New methods: | Context.get_group_target | Context.new_sub_path | Context.pop_group | Context.pop_group_to_source | Context.push_group | Context.push_group_with_content | FontOptions.get_antialias | FontOptions.get_hint_metrics | FontOptions.get_hint_style | FontOptions.get_subpixel_order | FontOptions.set_antialias | FontOptions.set_hint_metrics | FontOptions.set_hint_style | FontOptions.set_subpixel_order | PDFSurface.set_size | PSSurface.dsc_begin_page_setup | PSSurface.dsc_begin_setup | PSSurface.dsc_comment | PSSurface.set_size | ScaledFont.get_font_face | ScaledFont.text_extents | Surface.get_device_offset | XlibSurface.get_depth Updated methods: PDFSurface()/PSSurface() - can now write to file-like objects (like StringIO). surface.write_to_png() and ImageSurface.create_from_png() can now write to file-like objects (like StringIO). select_font_face, show_text, text_extents and text_path now accept unicode objects. Other changes: misc bug fixes. New examples: | examples/cairo_snippets/snippets_svg.py | examples/cairo_snippets/snippets/ellipse.py | examples/cairo_snippets/snippets/group.py | examples/svg/svgconvert.py 1.0.2 - 2005-10-11 ------------------ General changes: Pycairo has been updated to work with cairo 1.0.2. New cairo functions supported: cairo.ImageSurface.create_for_data() Updated functions: ctx.set_source_rgba (r, g, b, a=1.0) now supports a default alpha argument Other changes: cairo.Matrix now supports the Python sequence protocol, so you can do: xx, yx, xy, yy, x0, y0 = matrix 1.0.0 - 2005-08-31 ------------------ General changes: Pycairo has been updated to work with cairo 1.0.0. New cairo functions supported: | cairo.cairo_version() | cairo.cairo_version_string() | PSSurface.set_dpi() Patterns are now implemented in a class hierarchy, the new constructors are: | cairo.SolidPattern (r, g, b, a=1.0) | cairo.SurfacePattern (surface) | cairo.LinearGradient (x0, y0, x1, y1) | cairo.RadialGradient (cx0, cy0, radius0, cx1, cy1, radius1) Updated functions: Surface.write_to_png() now accepts a file object as well as a filename Updated examples: The gtk examples now work with pygtk >= 2.7.0 without requiring the cairo.gtk module Bug Fixes: fix "initializer element is not constant" compiler warnings 0.9.0 - 2005-08-10 ------------------ General changes: Pycairo has been updated to work with cairo 0.9.0. New cairo functions supported: | cairo_get_antialias | cairo_set_antialias | cairo_surface_mark_dirty_rectangle | cairo_surface_flush Bug Fixes: * double buffering now works with the cairo.gtk module 0.6.0 - 2005-08-01 ------------------ This version has many changes which update Pycairo to the new cairo API. The change list is not duplicated here, instead see the cairo/NEWS file for full details of all these API changes. Pycairo method names that were different from the underlying cairo function names have been changed to make Pycairo more closely follow cairo and so enable the cairo documentation to be used for writing Pycairo programs. NOTES has been updated to list the differences between the C API and the Pycairo API. Context.copy_path() has been implemented, it returns a Path instance which supports the iterator protocol. Python 2.3 is now required. New examples: examples/warpedtext.py: shows usage of the Path iterator examples/cairo_snippets/: shows many of the 'cairo-demo/cairo_snippets' examples examples/gtk/png_view.py: example using cairo.ImageSurface.create_from_png() General changes: Pycairo has been updated to work with cairo 0.6.0, including using cairo's new error handling scheme. New features: cairo.CONTENT_COLOR, cairo.ALPHA, cairo.COLOR_ALPHA have been added for working with surfaces. A new class cairo.FontOptions has been added. cairo.ImageSurface.create_from_png() now accepts a filename string or a file object New wrapper functions have been added for cairo_get_font_options, cairo_set_font_options and cairo_surface_get_font_options. 0.5.1 - 2005-06-22 ------------------ New features: * new class cairo.Win32Surface (Niki Spahiev) * cairo.HAS_WIN32_SURFACE, cairo.HAS_PS_SURFACE etc are defined to give access to the values from cairo-features.h Fixes: * fix cairo_mask, cairo_mask_surface and cairo_stroke_preserve wrappers * compile properly against GTK+ 2.7 (Gustavo Carneiro) * other small fixes, including fixes for gcc 4.0 warnings 0.4.0 - 2005-03-10 ------------------ New cairo bindings: | cairo_font_extents Bindings removed: | cairo_font_set_transform | cairo_font_current_transform New examples: gtk/hangman.py Other: Changed version numbering to correspond directly with the Cairo version Pycairo was developed to work with. So, for example, Pycairo version 0.4.0 represents the Pycairo version that has been developed and tested with Cairo 0.4.0. 0.1.4 - 2005-01-14 ------------------ The Pycairo license has changed so that it is now dual-licensed under the LGPL and the MPL, the same as Cairo itself. For details see the COPYING file as well as COPYING-LGPL-2.1 and COPYING-MPL-1.1. New cairo bindings: | cairo_pdf_surface_create | cairo_set_target_pdf New libsvg-cairo bindings: | svg_cairo_parse | svg_cairo_parse_buffer | svg_cairo_render | svg_cairo_get_size Other: * Added --without-pygtk configure option. * Renamed the Pycairo API _new() functions to _wrap() to allow _new() to * be used for python __new__ functions. * New examples: svg2png.py and svgview.py. 0.1.3 - 2004-11-24 ------------------ After the recent server compromise we discarded all unsigned snapshots. That left us without a pycairo snapshot. Additionally, there were no tags in the source repository so I couldn't recreate the 0.1.2 snapshot, so here's a new 0.1.3 snapshot. I apologize if I botched the version number or left something significant out of this announcement---I'm not the one who will usually be doing pycairo maintenance. New bindings: | current_path | current_path_flat | current_font_extents Changes: fill_extents,stroke_extents: Remove unnecessary args and change from a method to an attribute. Other: Added two new examples: context-subclass.py and warpedtext.py pycairo-1.16.2/README.rst000066400000000000000000000045641323762421700147560ustar00rootroot00000000000000.. image:: https://cdn.rawgit.com/pygobject/pycairo/master/docs/images/pycairo.svg :align: center :width: 370px | Pycairo is a Python module providing bindings for the `cairo graphics library `__. It depends on **cairo >= 1.13.1** and works with **Python 2.7+** as well as **Python 3.3+**. Pycairo, including this documentation, is licensed under the **LGPLv2.1** as well as the **MPLv1.1**. The Pycairo bindings are designed to match the cairo C API as closely as possible, and to deviate only in cases which are clearly better implemented in a more ‘Pythonic’ way. Features of the Pycairo bindings: * Provides an object oriented interface to cairo. * Queries the error status of objects and translates them to exceptions. * Provides a C API that can be used by other Python extensions. ---- .. image:: https://cdn.rawgit.com/pygobject/pycairo/master/docs/images/example.svg :align: right :width: 200px .. code:: python import cairo surface = cairo.SVGSurface("example.svg", 200, 200) context = cairo.Context(surface) x, y, x1, y1 = 0.1, 0.5, 0.4, 0.9 x2, y2, x3, y3 = 0.6, 0.1, 0.9, 0.5 context.scale(200, 200) context.set_line_width(0.04) context.move_to(x, y) context.curve_to(x1, y1, x2, y2, x3, y3) context.stroke() context.set_source_rgba(1, 0.2, 0.2, 0.6) context.set_line_width(0.02) context.move_to(x, y) context.line_to(x1, y1) context.move_to(x2, y2) context.line_to(x3, y3) context.stroke() surface.finish() ---- If Pycairo is not what you need, have a look at `cairocffi `__, which is an API compatible package using `cffi `__ or `Qahirah `__, which is using `ctypes `__ and provides a more "pythonic" API with less focus on matching the cairo C API. For more information visit https://pycairo.readthedocs.io .. image:: https://travis-ci.org/pygobject/pycairo.svg?branch=master :target: https://travis-ci.org/pygobject/pycairo .. image:: https://ci.appveyor.com/api/projects/status/9hurdbb19lg2i9xm/branch/master?svg=true :target: https://ci.appveyor.com/project/lazka/pycairo/branch/master .. image:: https://codecov.io/gh/pygobject/pycairo/branch/master/graph/badge.svg :target: https://codecov.io/gh/pygobject/pycairo pycairo-1.16.2/cairo/000077500000000000000000000000001323762421700143535ustar00rootroot00000000000000pycairo-1.16.2/cairo/__init__.py000077500000000000000000000012241323762421700164660ustar00rootroot00000000000000from ._cairo import * # noqa: F401,F403 def get_include(): """Returns a path to the directory containing the C header files""" import os def is_ok(path): return os.path.exists(path) and os.path.isdir(path) package_path = os.path.dirname(os.path.realpath(__file__)) install_path = os.path.join(package_path, "include") # in case we are installed if is_ok(install_path): return install_path # in case we are running from source if is_ok(package_path): return package_path # in case we are in an .egg import pkg_resources return pkg_resources.resource_filename(__name__, "include") pycairo-1.16.2/cairo/bufferproxy.c000066400000000000000000000074531323762421700171030ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2017 Christoph Reiter * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "private.h" #if PY_MAJOR_VERSION >= 3 typedef struct { PyObject_HEAD PyObject *exporter; void *buf; Py_ssize_t len; int readonly; } Pycairo_BufferProxy; static PyTypeObject Pycairo_BufferProxyType = { PyVarObject_HEAD_INIT(NULL, 0) "cairo._BufferProxy", sizeof(Pycairo_BufferProxy), }; static int buffer_proxy_getbuffer(PyObject *exporter, Py_buffer *view, int flags) { Pycairo_BufferProxy *self = (Pycairo_BufferProxy *)exporter; return PyBuffer_FillInfo (view, exporter, self->buf, self->len, self->readonly, flags); } static PyBufferProcs Pycairo_BufferProxy_as_buffer = { (getbufferproc)buffer_proxy_getbuffer, (releasebufferproc)0, }; PyObject * buffer_proxy_create_view(PyObject *exporter, void *buf, Py_ssize_t len, int readonly) { PyObject *memoryview; PyObject *obj; Pycairo_BufferProxy *self; obj = (PyObject *)PyObject_GC_New(Pycairo_BufferProxy, &Pycairo_BufferProxyType); if (obj == NULL) return NULL; self = (Pycairo_BufferProxy *)obj; Py_INCREF(exporter); self->exporter = exporter; self->buf = buf; self->len = len; self->readonly = readonly; PyObject_GC_Track(obj); memoryview = PyMemoryView_FromObject (obj); Py_DECREF(obj); return memoryview; } static int buffer_proxy_traverse(PyObject* obj, visitproc visit, void *arg) { Pycairo_BufferProxy *self = (Pycairo_BufferProxy *)obj; Py_VISIT(self->exporter); return 0; } static int buffer_proxy_clear(PyObject *obj) { Pycairo_BufferProxy *self = (Pycairo_BufferProxy *)obj; Py_CLEAR(self->exporter); return 0; } static void buffer_proxy_dealloc(PyObject* obj) { Pycairo_BufferProxy *self = (Pycairo_BufferProxy *)obj; PyObject_GC_UnTrack(obj); self->buf = NULL; self->len = 0; self->readonly = 0; buffer_proxy_clear(obj); Py_TYPE(obj)->tp_free(obj); } #endif int init_buffer_proxy (void) { #if PY_MAJOR_VERSION >= 3 Pycairo_BufferProxyType.tp_as_buffer = &Pycairo_BufferProxy_as_buffer; Pycairo_BufferProxyType.tp_dealloc = &buffer_proxy_dealloc; Pycairo_BufferProxyType.tp_traverse = &buffer_proxy_traverse; Pycairo_BufferProxyType.tp_clear = &buffer_proxy_clear; Pycairo_BufferProxyType.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC; if (PyType_Ready(&Pycairo_BufferProxyType) < 0) return -1; #endif return 0; } pycairo-1.16.2/cairo/cairomodule.c000066400000000000000000000376061323762421700170360ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2003 James Henstridge * Copyright © 2004-2011 Steven Chaplin * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "private.h" /* for XCB api */ #if defined(CAIRO_HAS_XCB_SURFACE) && defined(HAVE_XPYB) xpyb_CAPI_t *xpyb_CAPI; PyObject *xpybVISUALTYPE_type; #endif /* C API. Clients get at this via Pycairo_IMPORT or import_cairo(), defined in pycairo.h. */ static Pycairo_CAPI_t CAPI = { &PycairoContext_Type, PycairoContext_FromContext, &PycairoFontFace_Type, &PycairoToyFontFace_Type, PycairoFontFace_FromFontFace, &PycairoFontOptions_Type, PycairoFontOptions_FromFontOptions, &PycairoMatrix_Type, PycairoMatrix_FromMatrix, &PycairoPath_Type, PycairoPath_FromPath, &PycairoPattern_Type, &PycairoSolidPattern_Type, &PycairoSurfacePattern_Type, &PycairoGradient_Type, &PycairoLinearGradient_Type, &PycairoRadialGradient_Type, PycairoPattern_FromPattern, &PycairoScaledFont_Type, PycairoScaledFont_FromScaledFont, &PycairoSurface_Type, #ifdef CAIRO_HAS_IMAGE_SURFACE &PycairoImageSurface_Type, #else 0, #endif #ifdef CAIRO_HAS_PDF_SURFACE &PycairoPDFSurface_Type, #else 0, #endif #ifdef CAIRO_HAS_PS_SURFACE &PycairoPSSurface_Type, #else 0, #endif #ifdef CAIRO_HAS_SVG_SURFACE &PycairoSVGSurface_Type, #else 0, #endif #ifdef CAIRO_HAS_WIN32_SURFACE &PycairoWin32Surface_Type, &PycairoWin32PrintingSurface_Type, #else 0, 0, #endif #ifdef CAIRO_HAS_XCB_SURFACE &PycairoXCBSurface_Type, #else 0, #endif #ifdef CAIRO_HAS_XLIB_SURFACE &PycairoXlibSurface_Type, #else 0, #endif PycairoSurface_FromSurface, Pycairo_Check_Status, &PycairoRectangleInt_Type, PycairoRectangleInt_FromRectangleInt, &PycairoRegion_Type, PycairoRegion_FromRegion, #ifdef CAIRO_HAS_RECORDING_SURFACE &PycairoRecordingSurface_Type, #else 0, #endif }; static PyObject * pycairo_cairo_version (PyObject *self) { return PYCAIRO_PyLong_FromLong (cairo_version()); } static PyObject * pycairo_cairo_version_string (PyObject *self) { return PYCAIRO_PyUnicode_FromString (cairo_version_string()); } static PyMethodDef cairo_functions[] = { {"cairo_version", (PyCFunction)pycairo_cairo_version, METH_NOARGS}, {"cairo_version_string", (PyCFunction)pycairo_cairo_version_string, METH_NOARGS}, {NULL, NULL, 0, NULL}, }; #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef cairomoduledef = { PyModuleDef_HEAD_INIT, "cairo", NULL, 0, cairo_functions, 0, 0, 0, 0, }; #endif PYCAIRO_MOD_INIT(_cairo) { PyObject *m, *capi; if (PyType_Ready(&PycairoContext_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoFontFace_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoToyFontFace_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoFontOptions_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoMatrix_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoPath_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; PycairoPathiter_Type.tp_iter=&PyObject_SelfIter; if (PyType_Ready(&PycairoPathiter_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoPattern_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoSolidPattern_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoSurfacePattern_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoGradient_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoLinearGradient_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoRadialGradient_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoMeshPattern_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoRasterSourcePattern_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoRectangleInt_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoDevice_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; PycairoGlyph_Type.tp_base = &PyTuple_Type; if (PyType_Ready(&PycairoGlyph_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; PycairoRectangle_Type.tp_base = &PyTuple_Type; if (PyType_Ready(&PycairoRectangle_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; PycairoTextCluster_Type.tp_base = &PyTuple_Type; if (PyType_Ready(&PycairoTextCluster_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; PycairoTextExtents_Type.tp_base = &PyTuple_Type; if (PyType_Ready(&PycairoTextExtents_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; #ifdef CAIRO_HAS_SCRIPT_SURFACE if (PyType_Ready(&PycairoScriptDevice_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoScriptSurface_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; #endif if (PyType_Ready(&PycairoRegion_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoScaledFont_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoSurface_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; #ifdef CAIRO_HAS_IMAGE_SURFACE if (PyType_Ready(&PycairoImageSurface_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoMappedImageSurface_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; #endif #ifdef CAIRO_HAS_PDF_SURFACE if (PyType_Ready(&PycairoPDFSurface_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; #endif #ifdef CAIRO_HAS_PS_SURFACE if (PyType_Ready(&PycairoPSSurface_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; #endif #ifdef CAIRO_HAS_RECORDING_SURFACE if (PyType_Ready(&PycairoRecordingSurface_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; #endif #ifdef CAIRO_HAS_SVG_SURFACE if (PyType_Ready(&PycairoSVGSurface_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; #endif #ifdef CAIRO_HAS_WIN32_SURFACE if (PyType_Ready(&PycairoWin32Surface_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; if (PyType_Ready(&PycairoWin32PrintingSurface_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; #endif #ifdef CAIRO_HAS_XCB_SURFACE if (PyType_Ready(&PycairoXCBSurface_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; #endif #ifdef CAIRO_HAS_XLIB_SURFACE if (PyType_Ready(&PycairoXlibSurface_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; #endif #ifdef CAIRO_HAS_TEE_SURFACE if (PyType_Ready(&PycairoTeeSurface_Type) < 0) return PYCAIRO_MOD_ERROR_VAL; #endif #if PY_MAJOR_VERSION < 3 m = Py_InitModule("cairo._cairo", cairo_functions); #else m = PyModule_Create(&cairomoduledef); #endif if (m == NULL) return PYCAIRO_MOD_ERROR_VAL; if(init_error(m) < 0) return PYCAIRO_MOD_ERROR_VAL; if(init_buffer_proxy() < 0) return PYCAIRO_MOD_ERROR_VAL; if(init_enums(m) < 0) return PYCAIRO_MOD_ERROR_VAL; PyModule_AddStringConstant(m, "version", PYCAIRO_STRINGIFY(PYCAIRO_VERSION_MAJOR) "." PYCAIRO_STRINGIFY(PYCAIRO_VERSION_MINOR) "." PYCAIRO_STRINGIFY(PYCAIRO_VERSION_MICRO)); PyModule_AddObject(m, "version_info", Py_BuildValue("(iii)", PYCAIRO_VERSION_MAJOR, PYCAIRO_VERSION_MINOR, PYCAIRO_VERSION_MICRO )); Py_INCREF(&PycairoContext_Type); PyModule_AddObject(m, "Context", (PyObject *)&PycairoContext_Type); Py_INCREF(&PycairoFontFace_Type); PyModule_AddObject(m, "FontFace",(PyObject *)&PycairoFontFace_Type); Py_INCREF(&PycairoToyFontFace_Type); PyModule_AddObject(m, "ToyFontFace",(PyObject *)&PycairoToyFontFace_Type); Py_INCREF(&PycairoFontOptions_Type); PyModule_AddObject(m, "FontOptions",(PyObject *)&PycairoFontOptions_Type); Py_INCREF(&PycairoMatrix_Type); PyModule_AddObject(m, "Matrix", (PyObject *)&PycairoMatrix_Type); Py_INCREF(&PycairoPath_Type); /* Don't add Path object since it is not accessed directly as 'cairo.Path' * PyModule_AddObject(m, "Path", (PyObject *)&PycairoPath_Type); */ Py_INCREF(&PycairoPattern_Type); PyModule_AddObject(m, "Pattern", (PyObject *)&PycairoPattern_Type); Py_INCREF(&PycairoSolidPattern_Type); PyModule_AddObject(m, "SolidPattern", (PyObject *)&PycairoSolidPattern_Type); Py_INCREF(&PycairoSurfacePattern_Type); PyModule_AddObject(m, "SurfacePattern", (PyObject *)&PycairoSurfacePattern_Type); Py_INCREF(&PycairoGradient_Type); PyModule_AddObject(m, "Gradient", (PyObject *)&PycairoGradient_Type); Py_INCREF(&PycairoLinearGradient_Type); PyModule_AddObject(m, "LinearGradient", (PyObject *)&PycairoLinearGradient_Type); Py_INCREF(&PycairoRadialGradient_Type); PyModule_AddObject(m, "RadialGradient", (PyObject *)&PycairoRadialGradient_Type); Py_INCREF(&PycairoRadialGradient_Type); PyModule_AddObject(m, "MeshPattern", (PyObject *)&PycairoMeshPattern_Type); Py_INCREF(&PycairoRasterSourcePattern_Type); PyModule_AddObject(m, "RasterSourcePattern", (PyObject *)&PycairoRasterSourcePattern_Type); Py_INCREF(&PycairoRectangleInt_Type); PyModule_AddObject(m, "RectangleInt", (PyObject *)&PycairoRectangleInt_Type); Py_INCREF(&PycairoRegion_Type); PyModule_AddObject(m, "Region", (PyObject *)&PycairoRegion_Type); Py_INCREF(&PycairoScaledFont_Type); PyModule_AddObject(m, "ScaledFont", (PyObject *)&PycairoScaledFont_Type); Py_INCREF(&PycairoSurface_Type); PyModule_AddObject(m, "Surface", (PyObject *)&PycairoSurface_Type); Py_INCREF(&PycairoDevice_Type); PyModule_AddObject(m, "Device", (PyObject *)&PycairoDevice_Type); Py_INCREF(&PycairoGlyph_Type); PyModule_AddObject(m, "Glyph", (PyObject *)&PycairoGlyph_Type); Py_INCREF(&PycairoRectangle_Type); PyModule_AddObject(m, "Rectangle", (PyObject *)&PycairoRectangle_Type); Py_INCREF(&PycairoTextCluster_Type); PyModule_AddObject(m, "TextCluster", (PyObject *)&PycairoTextCluster_Type); Py_INCREF(&PycairoTextExtents_Type); PyModule_AddObject(m, "TextExtents", (PyObject *)&PycairoTextExtents_Type); Py_INCREF(&PycairoPath_Type); PyModule_AddObject(m, "Path", (PyObject *)&PycairoPath_Type); #ifdef CAIRO_HAS_SCRIPT_SURFACE Py_INCREF(&PycairoScriptDevice_Type); PyModule_AddObject(m, "ScriptDevice", (PyObject *)&PycairoScriptDevice_Type); Py_INCREF(&PycairoScriptSurface_Type); PyModule_AddObject(m, "ScriptSurface", (PyObject *)&PycairoScriptSurface_Type); #endif #ifdef CAIRO_HAS_IMAGE_SURFACE Py_INCREF(&PycairoImageSurface_Type); PyModule_AddObject(m, "ImageSurface", (PyObject *)&PycairoImageSurface_Type); #endif #ifdef CAIRO_HAS_PDF_SURFACE Py_INCREF(&PycairoPDFSurface_Type); PyModule_AddObject(m, "PDFSurface", (PyObject *)&PycairoPDFSurface_Type); #endif #ifdef CAIRO_HAS_PS_SURFACE Py_INCREF(&PycairoPSSurface_Type); PyModule_AddObject(m, "PSSurface", (PyObject *)&PycairoPSSurface_Type); #endif #ifdef CAIRO_HAS_RECORDING_SURFACE Py_INCREF(&PycairoRecordingSurface_Type); PyModule_AddObject(m, "RecordingSurface", (PyObject *)&PycairoRecordingSurface_Type); #endif #ifdef CAIRO_HAS_SVG_SURFACE Py_INCREF(&PycairoSVGSurface_Type); PyModule_AddObject(m, "SVGSurface", (PyObject *)&PycairoSVGSurface_Type); #endif #ifdef CAIRO_HAS_WIN32_SURFACE Py_INCREF(&PycairoWin32Surface_Type); PyModule_AddObject(m, "Win32Surface", (PyObject *)&PycairoWin32Surface_Type); Py_INCREF(&PycairoWin32PrintingSurface_Type); PyModule_AddObject(m, "Win32PrintingSurface", (PyObject *)&PycairoWin32PrintingSurface_Type); #endif #ifdef CAIRO_HAS_XCB_SURFACE Py_INCREF(&PycairoXCBSurface_Type); PyModule_AddObject(m, "XCBSurface", (PyObject *)&PycairoXCBSurface_Type); #endif #ifdef CAIRO_HAS_XLIB_SURFACE Py_INCREF(&PycairoXlibSurface_Type); PyModule_AddObject(m, "XlibSurface", (PyObject *)&PycairoXlibSurface_Type); #endif #ifdef CAIRO_HAS_TEE_SURFACE Py_INCREF(&PycairoTeeSurface_Type); PyModule_AddObject(m, "TeeSurface", (PyObject *)&PycairoTeeSurface_Type); #endif /* constants */ #ifdef CAIRO_HAS_ATSUI_FONT PyModule_AddIntConstant(m, "HAS_ATSUI_FONT", 1); #else PyModule_AddIntConstant(m, "HAS_ATSUI_FONT", 0); #endif #ifdef CAIRO_HAS_FT_FONT PyModule_AddIntConstant(m, "HAS_FT_FONT", 1); #else PyModule_AddIntConstant(m, "HAS_FT_FONT", 0); #endif #ifdef CAIRO_HAS_GLITZ_SURFACE PyModule_AddIntConstant(m, "HAS_GLITZ_SURFACE", 1); #else PyModule_AddIntConstant(m, "HAS_GLITZ_SURFACE", 0); #endif #ifdef CAIRO_HAS_IMAGE_SURFACE PyModule_AddIntConstant(m, "HAS_IMAGE_SURFACE", 1); #else PyModule_AddIntConstant(m, "HAS_IMAGE_SURFACE", 0); #endif #ifdef CAIRO_HAS_PDF_SURFACE PyModule_AddIntConstant(m, "HAS_PDF_SURFACE", 1); #else PyModule_AddIntConstant(m, "HAS_PDF_SURFACE", 0); #endif #ifdef CAIRO_HAS_PNG_FUNCTIONS PyModule_AddIntConstant(m, "HAS_PNG_FUNCTIONS", 1); #else PyModule_AddIntConstant(m, "HAS_PNG_FUNCTIONS", 0); #endif #ifdef CAIRO_HAS_PS_SURFACE PyModule_AddIntConstant(m, "HAS_PS_SURFACE", 1); #else PyModule_AddIntConstant(m, "HAS_PS_SURFACE", 0); #endif #ifdef CAIRO_HAS_RECORDING_SURFACE PyModule_AddIntConstant(m, "HAS_RECORDING_SURFACE", 1); #else PyModule_AddIntConstant(m, "HAS_RECORDING_SURFACE", 0); #endif #ifdef CAIRO_HAS_SVG_SURFACE PyModule_AddIntConstant(m, "HAS_SVG_SURFACE", 1); #else PyModule_AddIntConstant(m, "HAS_SVG_SURFACE", 0); #endif #ifdef CAIRO_HAS_USER_FONT PyModule_AddIntConstant(m, "HAS_USER_FONT", 1); #else PyModule_AddIntConstant(m, "HAS_USER_FONT", 0); #endif #ifdef CAIRO_HAS_QUARTZ_SURFACE PyModule_AddIntConstant(m, "HAS_QUARTZ_SURFACE", 1); #else PyModule_AddIntConstant(m, "HAS_QUARTZ_SURFACE", 0); #endif #ifdef CAIRO_HAS_WIN32_FONT PyModule_AddIntConstant(m, "HAS_WIN32_FONT", 1); #else PyModule_AddIntConstant(m, "HAS_WIN32_FONT", 0); #endif #ifdef CAIRO_HAS_WIN32_SURFACE PyModule_AddIntConstant(m, "HAS_WIN32_SURFACE", 1); #else PyModule_AddIntConstant(m, "HAS_WIN32_SURFACE", 0); #endif #ifdef CAIRO_HAS_XCB_SURFACE PyModule_AddIntConstant(m, "HAS_XCB_SURFACE", 1); #else PyModule_AddIntConstant(m, "HAS_XCB_SURFACE", 0); #endif #ifdef CAIRO_HAS_XLIB_SURFACE PyModule_AddIntConstant(m, "HAS_XLIB_SURFACE", 1); #else PyModule_AddIntConstant(m, "HAS_XLIB_SURFACE", 0); #endif #ifdef CAIRO_HAS_MIME_SURFACE PyModule_AddIntConstant(m, "HAS_MIME_SURFACE", 1); #else PyModule_AddIntConstant(m, "HAS_MIME_SURFACE", 0); #endif #ifdef CAIRO_HAS_SCRIPT_SURFACE PyModule_AddIntConstant(m, "HAS_SCRIPT_SURFACE", 1); #else PyModule_AddIntConstant(m, "HAS_SCRIPT_SURFACE", 0); #endif #ifdef CAIRO_HAS_TEE_SURFACE PyModule_AddIntConstant(m, "HAS_TEE_SURFACE", 1); #else PyModule_AddIntConstant(m, "HAS_TEE_SURFACE", 0); #endif #define STRCONSTANT(x) PyModule_AddStringConstant(m, #x, CAIRO_##x) STRCONSTANT(MIME_TYPE_JP2); STRCONSTANT(MIME_TYPE_JPEG); STRCONSTANT(MIME_TYPE_PNG); STRCONSTANT(MIME_TYPE_URI); STRCONSTANT(MIME_TYPE_UNIQUE_ID); #undef STRCONSTANT #if PY_MAJOR_VERSION >= 3 /* Create a Capsule containing the CAPI pointer */ capi = PyCapsule_New((void *)(&CAPI), "cairo.CAPI", 0); #else capi = PyCObject_FromVoidPtr(&CAPI, NULL); #endif if (capi != NULL) { PyModule_AddObject(m, "CAPI", capi); } return PYCAIRO_MOD_SUCCESS_VAL(m); } pycairo-1.16.2/cairo/compat.h000066400000000000000000000064531323762421700160170ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2017 Christoph Reiter * * 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. */ #ifndef __PYCAIRO_COMPAT_H__ #define __PYCAIRO_COMPAT_H__ #ifndef PyVarObject_HEAD_INIT #define PyVarObject_HEAD_INIT(type, size) \ PyObject_HEAD_INIT(type) size, #endif #if PY_MAJOR_VERSION < 3 #define PYCAIRO_MOD_ERROR_VAL #define PYCAIRO_MOD_SUCCESS_VAL(val) #define PYCAIRO_MOD_INIT(name) void init##name(void) #define PYCAIRO_PyUnicode_FromString PyString_FromString #define PYCAIRO_PyUnicode_Format PyString_Format #define PYCAIRO_PyUnicode_Join _PyString_Join #define PYCAIRO_PyUnicode_InternFromString PyString_InternFromString #define PYCAIRO_PyUnicode_Astring PyString_AsString #define PYCAIRO_PyUnicode_FromFormat PyString_FromFormat #define PYCAIRO_PyNumber_Long PyNumber_Int #define PYCAIRO_PyBytes_AsStringAndSize PyString_AsStringAndSize #define PYCAIRO_PyLong_Type PyInt_Type #define PYCAIRO_PyLongObject PyIntObject #define PYCAIRO_PyLong_FromLong PyInt_FromLong #define PYCAIRO_PyLong_AsLong PyInt_AsLong #define PYCAIRO_ENC_TEXT_FORMAT "et" #define PYCAIRO_DATA_FORMAT "s" #define PYCAIRO_Py_hash_t long #else #define PYCAIRO_MOD_ERROR_VAL NULL #define PYCAIRO_MOD_SUCCESS_VAL(val) val #define PYCAIRO_MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void) #define PYCAIRO_PyUnicode_FromString PyUnicode_FromString #define PYCAIRO_PyUnicode_Format PyUnicode_Format #define PYCAIRO_PyUnicode_Join PyUnicode_Join #define PYCAIRO_PyUnicode_InternFromString PyUnicode_InternFromString #define PYCAIRO_PyUnicode_Astring _PyUnicode_AsString #define PYCAIRO_PyUnicode_FromFormat PyUnicode_FromFormat #define PYCAIRO_PyNumber_Long PyNumber_Long #define PYCAIRO_PyBytes_AsStringAndSize PyBytes_AsStringAndSize #define PYCAIRO_PyLong_Type PyLong_Type #define PYCAIRO_PyLongObject PyLongObject #define PYCAIRO_PyLong_FromLong PyLong_FromLong #define PYCAIRO_PyLong_AsLong PyLong_AsLong #define PYCAIRO_ENC_TEXT_FORMAT "es" #define PYCAIRO_DATA_FORMAT "y" #define PYCAIRO_Py_hash_t Py_hash_t #endif #define PYCAIRO_Py_hash_t_FromVoidPtr(p) ((PYCAIRO_Py_hash_t)(Py_ssize_t)(p)) #endif /* __PYCAIRO_COMPAT_H__ */ pycairo-1.16.2/cairo/context.c000066400000000000000000001275671323762421700162250ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2003 James Henstridge, Steven Chaplin * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "private.h" PyObject * PycairoContext_FromContext(cairo_t *ctx, PyTypeObject *type, PyObject *base) { PyObject *o; assert (ctx != NULL); if (Pycairo_Check_Status (cairo_status (ctx))) { cairo_destroy (ctx); return NULL; } o = PycairoContext_Type.tp_alloc (type, 0); if (o) { ((PycairoContext *)o)->ctx = ctx; Py_XINCREF(base); ((PycairoContext *)o)->base = base; } else { cairo_destroy (ctx); } return o; } static void pycairo_dealloc(PycairoContext *o) { if (o->ctx) { cairo_destroy(o->ctx); o->ctx = NULL; } Py_CLEAR(o->base); Py_TYPE(o)->tp_free(o); } static PyObject * pycairo_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { PycairoSurface *s; if (!PyArg_ParseTuple(args, "O!:Context.__new__", &PycairoSurface_Type, &s)) return NULL; return PycairoContext_FromContext (cairo_create (s->surface), type, NULL); } static PyObject * pycairo_append_path (PycairoContext *o, PyObject *args) { PycairoPath *p; if (!PyArg_ParseTuple(args, "O!:Context.append_path", &PycairoPath_Type, &p)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_append_path (o->ctx, p->path); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_arc (PycairoContext *o, PyObject *args) { double xc, yc, radius, angle1, angle2; if (!PyArg_ParseTuple (args, "ddddd:Context.arc", &xc, &yc, &radius, &angle1, &angle2)) return NULL; cairo_arc (o->ctx, xc, yc, radius, angle1, angle2); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_arc_negative (PycairoContext *o, PyObject *args) { double xc, yc, radius, angle1, angle2; if (!PyArg_ParseTuple (args, "ddddd:Context.arc_negative", &xc, &yc, &radius, &angle1, &angle2)) return NULL; cairo_arc_negative (o->ctx, xc, yc, radius, angle1, angle2); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_clip (PycairoContext *o) { Py_BEGIN_ALLOW_THREADS; cairo_clip (o->ctx); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_clip_extents (PycairoContext *o) { double x1, y1, x2, y2; cairo_clip_extents (o->ctx, &x1, &y1, &x2, &y2); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); return Py_BuildValue("(dddd)", x1, y1, x2, y2); } static PyObject * pycairo_clip_preserve (PycairoContext *o) { Py_BEGIN_ALLOW_THREADS; cairo_clip_preserve (o->ctx); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_in_clip (PycairoContext *o, PyObject *args) { double x, y; cairo_bool_t result; if (!PyArg_ParseTuple (args, "dd:Context.in_clip", &x, &y)) return NULL; Py_BEGIN_ALLOW_THREADS; result = cairo_in_clip (o->ctx, x, y); Py_END_ALLOW_THREADS; return PyBool_FromLong(result); } static PyObject * pycairo_close_path (PycairoContext *o) { Py_BEGIN_ALLOW_THREADS; cairo_close_path (o->ctx); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_copy_clip_rectangle_list (PycairoContext *o) { int i; PyObject *rv = NULL; PyObject *rect = NULL; cairo_rectangle_t *r; cairo_rectangle_list_t *rlist = cairo_copy_clip_rectangle_list (o->ctx); if (rlist->status != CAIRO_STATUS_SUCCESS) { Pycairo_Check_Status (rlist->status); goto exit; } rv = PyList_New(rlist->num_rectangles); if (rv == NULL) goto exit; for (i = 0, r = rlist->rectangles; i < rlist->num_rectangles; i++, r++) { PyObject *py_rect = Py_BuildValue("(dddd)", r->x, r->y, r->width, r->height); if (py_rect == NULL) { Py_CLEAR(rv); goto exit; } rect = PyObject_Call((PyObject *)&PycairoRectangle_Type, py_rect, NULL); Py_DECREF (py_rect); if (rect == NULL) { Py_CLEAR(rv); goto exit; } PyList_SET_ITEM (rv, i, rect); } exit: cairo_rectangle_list_destroy(rlist); return rv; } static PyObject * pycairo_copy_page (PycairoContext *o) { Py_BEGIN_ALLOW_THREADS; cairo_copy_page (o->ctx); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_copy_path (PycairoContext *o) { cairo_path_t *cp; Py_BEGIN_ALLOW_THREADS; cp = cairo_copy_path (o->ctx); Py_END_ALLOW_THREADS; return PycairoPath_FromPath (cp); } static PyObject * pycairo_copy_path_flat (PycairoContext *o) { cairo_path_t *cp; Py_BEGIN_ALLOW_THREADS; cp = cairo_copy_path_flat (o->ctx); Py_END_ALLOW_THREADS; return PycairoPath_FromPath (cp); } static PyObject * pycairo_curve_to (PycairoContext *o, PyObject *args) { double x1, y1, x2, y2, x3, y3; if (!PyArg_ParseTuple (args, "dddddd:Context.curve_to", &x1, &y1, &x2, &y2, &x3, &y3)) return NULL; cairo_curve_to (o->ctx, x1, y1, x2, y2, x3, y3); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_device_to_user(PycairoContext *o, PyObject *args) { double x, y; if (!PyArg_ParseTuple(args, "dd:Context.device_to_user", &x, &y)) return NULL; cairo_device_to_user(o->ctx, &x, &y); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); return Py_BuildValue("(dd)", x, y); } static PyObject * pycairo_device_to_user_distance (PycairoContext *o, PyObject *args) { double dx, dy; if (!PyArg_ParseTuple (args, "dd:Context.device_to_user_distance", &dx, &dy)) return NULL; cairo_device_to_user_distance (o->ctx, &dx, &dy); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); return Py_BuildValue("(dd)", dx, dy); } static PyObject * pycairo_fill (PycairoContext *o) { Py_BEGIN_ALLOW_THREADS; cairo_fill (o->ctx); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_fill_extents (PycairoContext *o) { double x1, y1, x2, y2; cairo_fill_extents (o->ctx, &x1, &y1, &x2, &y2); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); return Py_BuildValue("(dddd)", x1, y1, x2, y2); } static PyObject * pycairo_fill_preserve (PycairoContext *o) { Py_BEGIN_ALLOW_THREADS; cairo_fill_preserve (o->ctx); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_font_extents (PycairoContext *o) { cairo_font_extents_t e; cairo_font_extents (o->ctx, &e); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); return Py_BuildValue("(ddddd)", e.ascent, e.descent, e.height, e.max_x_advance, e.max_y_advance); } static PyObject * pycairo_get_antialias (PycairoContext *o) { RETURN_INT_ENUM (Antialias, cairo_get_antialias (o->ctx)); } static PyObject * pycairo_get_current_point (PycairoContext *o) { double x, y; cairo_get_current_point (o->ctx, &x, &y); return Py_BuildValue("(dd)", x, y); } static PyObject * pycairo_get_dash (PycairoContext *o) { double *dashes = NULL, offset; int count, i; PyObject *py_dashes = NULL, *rv = NULL; count = cairo_get_dash_count (o->ctx); if (count < 0) { PyErr_SetString (PyExc_RuntimeError, "invalid dash return"); return NULL; } dashes = PyMem_Malloc ((unsigned int)count * sizeof(double)); if (dashes == NULL) return PyErr_NoMemory(); cairo_get_dash (o->ctx, dashes, &offset); py_dashes = PyTuple_New(count); if (py_dashes == NULL) goto exit; for (i = 0; i < count; i++) { PyObject *dash = PyFloat_FromDouble(dashes[i]); if (dash == NULL) goto exit; PyTuple_SET_ITEM (py_dashes, i, dash); } rv = Py_BuildValue("(Od)", py_dashes, offset); exit: PyMem_Free (dashes); Py_XDECREF(py_dashes); return rv; } static PyObject * pycairo_get_dash_count (PycairoContext *o) { return PYCAIRO_PyLong_FromLong (cairo_get_dash_count (o->ctx)); } static PyObject * pycairo_get_fill_rule (PycairoContext *o) { RETURN_INT_ENUM(FillRule, cairo_get_fill_rule (o->ctx)); } static PyObject * pycairo_get_font_face (PycairoContext *o) { return PycairoFontFace_FromFontFace ( cairo_font_face_reference (cairo_get_font_face (o->ctx))); } static PyObject * pycairo_get_font_matrix (PycairoContext *o) { cairo_matrix_t matrix; cairo_get_font_matrix (o->ctx, &matrix); return PycairoMatrix_FromMatrix (&matrix); } static PyObject * pycairo_get_font_options (PycairoContext *o) { cairo_font_options_t *options = cairo_font_options_create(); cairo_get_font_options (o->ctx, options); /* there is no reference fn */ return PycairoFontOptions_FromFontOptions (options); } static PyObject * pycairo_get_group_target (PycairoContext *o) { cairo_surface_t *surface = cairo_get_group_target (o->ctx); return PycairoSurface_FromSurface (cairo_surface_reference (surface), NULL); } static PyObject * pycairo_get_line_cap (PycairoContext *o) { RETURN_INT_ENUM(LineCap, cairo_get_line_cap (o->ctx)); } static PyObject * pycairo_get_line_join (PycairoContext *o) { RETURN_INT_ENUM(LineJoin, cairo_get_line_join (o->ctx)); } static PyObject * pycairo_get_line_width (PycairoContext *o) { return PyFloat_FromDouble(cairo_get_line_width (o->ctx)); } static PyObject * pycairo_get_matrix (PycairoContext *o) { cairo_matrix_t matrix; cairo_get_matrix (o->ctx, &matrix); return PycairoMatrix_FromMatrix (&matrix); } static PyObject * pycairo_get_miter_limit (PycairoContext *o) { return PyFloat_FromDouble (cairo_get_miter_limit (o->ctx)); } static PyObject * pycairo_get_operator (PycairoContext *o) { RETURN_INT_ENUM(Operator, cairo_get_operator (o->ctx)); } static PyObject * pycairo_get_scaled_font (PycairoContext *o) { return PycairoScaledFont_FromScaledFont ( cairo_scaled_font_reference (cairo_get_scaled_font (o->ctx))); } static PyObject * pycairo_get_source (PycairoContext *o) { return PycairoPattern_FromPattern ( cairo_pattern_reference (cairo_get_source (o->ctx)), NULL); } static PyObject * pycairo_get_target (PycairoContext *o) { return PycairoSurface_FromSurface ( cairo_surface_reference (cairo_get_target (o->ctx)), NULL); } static PyObject * pycairo_get_tolerance (PycairoContext *o) { return PyFloat_FromDouble (cairo_get_tolerance (o->ctx)); } static PyObject * pycairo_glyph_extents (PycairoContext *o, PyObject *args) { int num_glyphs = -1; cairo_glyph_t *glyphs; cairo_text_extents_t extents; PyObject *py_object, *ext_args, *res; if (!PyArg_ParseTuple (args, "O|i:Context.glyph_extents", &py_object, &num_glyphs)) return NULL; glyphs = _PycairoGlyphs_AsGlyphs (py_object, &num_glyphs); if (glyphs == NULL) return NULL; cairo_glyph_extents (o->ctx, glyphs, num_glyphs, &extents); PyMem_Free (glyphs); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); ext_args = Py_BuildValue ("(dddddd)", extents.x_bearing, extents.y_bearing, extents.width, extents.height, extents.x_advance, extents.y_advance); res = PyObject_Call ((PyObject *)&PycairoTextExtents_Type, ext_args, NULL); Py_DECREF (ext_args); return res; } static PyObject * pycairo_glyph_path (PycairoContext *o, PyObject *args) { int num_glyphs = -1; cairo_glyph_t *glyphs; PyObject *py_object; if (!PyArg_ParseTuple (args, "O|i:Context.glyph_path", &py_object, &num_glyphs)) return NULL; glyphs = _PycairoGlyphs_AsGlyphs (py_object, &num_glyphs); if (glyphs == NULL) return NULL; cairo_glyph_path (o->ctx, glyphs, num_glyphs); PyMem_Free (glyphs); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_has_current_point (PycairoContext *o) { PyObject *b = cairo_has_current_point (o->ctx) ? Py_True : Py_False; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_INCREF(b); return b; } static PyObject * pycairo_identity_matrix (PycairoContext *o) { cairo_identity_matrix (o->ctx); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_in_fill (PycairoContext *o, PyObject *args) { double x, y; PyObject *result; if (!PyArg_ParseTuple (args, "dd:Context.in_fill", &x, &y)) return NULL; result = cairo_in_fill (o->ctx, x, y) ? Py_True : Py_False; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_INCREF(result); return result; } static PyObject * pycairo_in_stroke (PycairoContext *o, PyObject *args) { double x, y; PyObject *result; if (!PyArg_ParseTuple (args, "dd:Context.in_stroke", &x, &y)) return NULL; result = cairo_in_stroke (o->ctx, x, y) ? Py_True : Py_False; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_INCREF(result); return result; } static PyObject * pycairo_line_to (PycairoContext *o, PyObject *args) { double x, y; if (!PyArg_ParseTuple (args, "dd:Context.line_to", &x, &y)) return NULL; cairo_line_to (o->ctx, x, y); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_mask (PycairoContext *o, PyObject *args) { PycairoPattern *p; if (!PyArg_ParseTuple(args, "O!:Context.mask", &PycairoPattern_Type, &p)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_mask (o->ctx, p->pattern); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_mask_surface (PycairoContext *o, PyObject *args) { PycairoSurface *s; double surface_x = 0.0, surface_y = 0.0; if (!PyArg_ParseTuple (args, "O!|dd:Context.mask_surface", &PycairoSurface_Type, &s, &surface_x, &surface_y)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_mask_surface (o->ctx, s->surface, surface_x, surface_y); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_move_to (PycairoContext *o, PyObject *args) { double x, y; if (!PyArg_ParseTuple (args, "dd:Context.move_to", &x, &y)) return NULL; cairo_move_to (o->ctx, x, y); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_new_path (PycairoContext *o) { cairo_new_path (o->ctx); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_new_sub_path (PycairoContext *o) { cairo_new_sub_path (o->ctx); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_paint (PycairoContext *o) { Py_BEGIN_ALLOW_THREADS; cairo_paint (o->ctx); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_paint_with_alpha (PycairoContext *o, PyObject *args) { double alpha; if (!PyArg_ParseTuple (args, "d:Context.paint_with_alpha", &alpha)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_paint_with_alpha (o->ctx, alpha); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_path_extents (PycairoContext *o) { double x1, y1, x2, y2; cairo_path_extents (o->ctx, &x1, &y1, &x2, &y2); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); return Py_BuildValue("(dddd)", x1, y1, x2, y2); } static PyObject * pycairo_pop_group (PycairoContext *o) { return PycairoPattern_FromPattern (cairo_pop_group (o->ctx), NULL); } static PyObject * pycairo_pop_group_to_source (PycairoContext *o) { cairo_pop_group_to_source (o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_push_group (PycairoContext *o) { cairo_push_group (o->ctx); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_push_group_with_content (PycairoContext *o, PyObject *args) { cairo_content_t content; int content_arg; if (!PyArg_ParseTuple (args, "i:Context.push_group_with_content", &content_arg)) return NULL; content = (cairo_content_t)content_arg; cairo_push_group_with_content (o->ctx, content); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_rectangle (PycairoContext *o, PyObject *args) { double x, y, width, height; if (!PyArg_ParseTuple (args, "dddd:Context.rectangle", &x, &y, &width, &height)) return NULL; cairo_rectangle (o->ctx, x, y, width, height); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_rel_curve_to (PycairoContext *o, PyObject *args) { double dx1, dy1, dx2, dy2, dx3, dy3; if (!PyArg_ParseTuple (args, "dddddd:Context.rel_curve_to", &dx1, &dy1, &dx2, &dy2, &dx3, &dy3)) return NULL; cairo_rel_curve_to (o->ctx, dx1, dy1, dx2, dy2, dx3, dy3); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_rel_line_to (PycairoContext *o, PyObject *args) { double dx, dy; if (!PyArg_ParseTuple (args, "dd:Context.rel_line_to", &dx, &dy)) return NULL; cairo_rel_line_to (o->ctx, dx, dy); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_rel_move_to (PycairoContext *o, PyObject *args) { double dx, dy; if (!PyArg_ParseTuple (args, "dd:Context.rel_move_to", &dx, &dy)) return NULL; cairo_rel_move_to (o->ctx, dx, dy); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_reset_clip (PycairoContext *o) { cairo_reset_clip (o->ctx); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_restore (PycairoContext *o) { cairo_restore (o->ctx); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_rotate (PycairoContext *o, PyObject *args) { double angle; if (!PyArg_ParseTuple(args, "d:Context.rotate", &angle)) return NULL; cairo_rotate (o->ctx, angle); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_save (PycairoContext *o) { cairo_save (o->ctx); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_scale (PycairoContext *o, PyObject *args) { double sx, sy; if (!PyArg_ParseTuple (args, "dd:Context.scale", &sx, &sy)) return NULL; cairo_scale (o->ctx, sx, sy); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_select_font_face (PycairoContext *o, PyObject *args) { const char *utf8; cairo_font_slant_t slant; cairo_font_weight_t weight; int slant_arg = CAIRO_FONT_SLANT_NORMAL; int weight_arg = CAIRO_FONT_WEIGHT_NORMAL; if (!PyArg_ParseTuple (args, PYCAIRO_ENC_TEXT_FORMAT "|ii:Context.select_font_face", "utf-8", &utf8, &slant_arg, &weight_arg)) return NULL; slant = (cairo_font_slant_t)slant_arg; weight = (cairo_font_weight_t)weight_arg; cairo_select_font_face (o->ctx, utf8, slant, weight); PyMem_Free((void *)utf8); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_antialias (PycairoContext *o, PyObject *args) { cairo_antialias_t antialias; int antialias_arg = CAIRO_ANTIALIAS_DEFAULT; if (!PyArg_ParseTuple (args, "|i:Context.set_antialias", &antialias_arg)) return NULL; antialias = (cairo_antialias_t)antialias_arg; cairo_set_antialias (o->ctx, antialias); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_dash (PycairoContext *o, PyObject *args) { double *dashes, offset = 0; Py_ssize_t num_dashes, i; PyObject *py_dashes; if (!PyArg_ParseTuple (args, "O|d:Context.set_dash", &py_dashes, &offset)) return NULL; py_dashes = PySequence_Fast (py_dashes, "first argument must be a sequence"); if (py_dashes == NULL) return NULL; num_dashes = PySequence_Fast_GET_SIZE(py_dashes); if (num_dashes > INT_MAX) { Py_DECREF (py_dashes); PyErr_SetString (PyExc_ValueError, "dash sequence too large"); return NULL; } dashes = PyMem_Malloc ((unsigned int)num_dashes * sizeof(double)); if (dashes == NULL) { Py_DECREF(py_dashes); return PyErr_NoMemory(); } for (i = 0; i < num_dashes; i++) { dashes[i] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(py_dashes, i)); if (PyErr_Occurred()) { PyMem_Free (dashes); Py_DECREF(py_dashes); return NULL; } } cairo_set_dash (o->ctx, dashes, (int)num_dashes, offset); PyMem_Free (dashes); Py_DECREF(py_dashes); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_fill_rule (PycairoContext *o, PyObject *args) { cairo_fill_rule_t fill_rule; int fill_rule_arg; if (!PyArg_ParseTuple (args, "i:Context.set_fill_rule", &fill_rule_arg)) return NULL; fill_rule = (cairo_fill_rule_t)fill_rule_arg; cairo_set_fill_rule (o->ctx, fill_rule); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_font_face (PycairoContext *o, PyObject *obj) { if (PyObject_TypeCheck(obj, &PycairoFontFace_Type)) cairo_set_font_face (o->ctx, ((PycairoFontFace *)obj)->font_face); else if (obj == Py_None) cairo_set_font_face (o->ctx, NULL); else { PyErr_SetString(PyExc_TypeError, "Context.set_font_face() argument must be " "cairo.FontFace or None"); return NULL; } RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_font_matrix (PycairoContext *o, PyObject *args) { PycairoMatrix *matrix; if (!PyArg_ParseTuple (args, "O!:Context.set_font_matrix", &PycairoMatrix_Type, &matrix)) return NULL; cairo_set_font_matrix (o->ctx, &matrix->matrix); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_font_options (PycairoContext *o, PyObject *args) { PycairoFontOptions *options; if (!PyArg_ParseTuple (args, "O!:Context.set_font_options", &PycairoFontOptions_Type, &options)) return NULL; cairo_set_font_options (o->ctx, options->font_options); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_font_size (PycairoContext *o, PyObject *args) { double size; if (!PyArg_ParseTuple (args, "d:Context.set_font_size", &size)) return NULL; cairo_set_font_size (o->ctx, size); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_line_cap (PycairoContext *o, PyObject *args) { cairo_line_cap_t line_cap; int line_cap_arg; if (!PyArg_ParseTuple (args, "i:Context.set_line_cap", &line_cap_arg)) return NULL; line_cap = (cairo_line_cap_t)line_cap_arg; cairo_set_line_cap (o->ctx, line_cap); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_line_join (PycairoContext *o, PyObject *args) { cairo_line_join_t line_join; int line_join_arg; if (!PyArg_ParseTuple (args, "i:Context.set_line_join", &line_join_arg)) return NULL; line_join = (cairo_line_join_t)line_join_arg; cairo_set_line_join (o->ctx, line_join); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_line_width (PycairoContext *o, PyObject *args) { double width; if (!PyArg_ParseTuple (args, "d:Context.set_line_width", &width)) return NULL; cairo_set_line_width (o->ctx, width); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_matrix (PycairoContext *o, PyObject *args) { PycairoMatrix *matrix; if (!PyArg_ParseTuple (args, "O!:Context.set_matrix", &PycairoMatrix_Type, &matrix)) return NULL; cairo_set_matrix (o->ctx, &matrix->matrix); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_miter_limit (PycairoContext *o, PyObject *args) { double limit; if (!PyArg_ParseTuple (args, "d:Context.set_miter_limit", &limit)) return NULL; cairo_set_miter_limit (o->ctx, limit); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_operator(PycairoContext *o, PyObject *args) { cairo_operator_t operator; int operator_arg; if (!PyArg_ParseTuple (args, "i:Context.set_operator", &operator_arg)) return NULL; operator = (cairo_operator_t)operator_arg; cairo_set_operator(o->ctx, operator); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_scaled_font(PycairoContext *o, PyObject *args) { PycairoScaledFont *f; if (!PyArg_ParseTuple (args, "O!:Context.set_scaled_font", &PycairoScaledFont_Type, &f)) return NULL; cairo_set_scaled_font(o->ctx, f->scaled_font); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_source (PycairoContext *o, PyObject *args) { PycairoPattern *p; if (!PyArg_ParseTuple (args, "O!:Context.set_source", &PycairoPattern_Type, &p)) return NULL; cairo_set_source (o->ctx, p->pattern); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_source_rgb (PycairoContext *o, PyObject *args) { double red, green, blue; if (!PyArg_ParseTuple (args, "ddd:Context.set_source_rgb", &red, &green, &blue)) return NULL; cairo_set_source_rgb (o->ctx, red, green, blue); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_source_rgba (PycairoContext *o, PyObject *args) { double red, green, blue; double alpha = 1.0; if (!PyArg_ParseTuple (args, "ddd|d:Context.set_source_rgba", &red, &green, &blue, &alpha)) return NULL; cairo_set_source_rgba (o->ctx, red, green, blue, alpha); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_source_surface (PycairoContext *o, PyObject *args) { PycairoSurface *surface; double x = 0.0, y = 0.0; if (!PyArg_ParseTuple (args, "O!|dd:Context.set_source_surface", &PycairoSurface_Type, &surface, &x, &y)) return NULL; cairo_set_source_surface (o->ctx, surface->surface, x, y); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_set_tolerance (PycairoContext *o, PyObject *args) { double tolerance; if (!PyArg_ParseTuple (args, "d:Context.set_tolerance", &tolerance)) return NULL; cairo_set_tolerance (o->ctx, tolerance); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_show_glyphs (PycairoContext *o, PyObject *args) { int num_glyphs = -1; cairo_glyph_t *glyphs; PyObject *py_object; if (!PyArg_ParseTuple (args, "O|i:Context.show_glyphs", &py_object, &num_glyphs)) return NULL; glyphs = _PycairoGlyphs_AsGlyphs (py_object, &num_glyphs); if (glyphs == NULL) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_show_glyphs (o->ctx, glyphs, num_glyphs); Py_END_ALLOW_THREADS; PyMem_Free (glyphs); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_show_page (PycairoContext *o) { Py_BEGIN_ALLOW_THREADS; cairo_show_page (o->ctx); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_show_text (PycairoContext *o, PyObject *args) { const char *utf8; if (!PyArg_ParseTuple (args, PYCAIRO_ENC_TEXT_FORMAT ":Context.show_text", "utf-8", &utf8)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_show_text (o->ctx, utf8); Py_END_ALLOW_THREADS; PyMem_Free((void *)utf8); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_stroke (PycairoContext *o) { Py_BEGIN_ALLOW_THREADS; cairo_stroke (o->ctx); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_stroke_extents (PycairoContext *o) { double x1, y1, x2, y2; cairo_stroke_extents (o->ctx, &x1, &y1, &x2, &y2); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); return Py_BuildValue("(dddd)", x1, y1, x2, y2); } static PyObject * pycairo_stroke_preserve (PycairoContext *o) { Py_BEGIN_ALLOW_THREADS; cairo_stroke_preserve (o->ctx); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_text_extents (PycairoContext *o, PyObject *args) { cairo_text_extents_t extents; const char *utf8; PyObject *ext_args, *res; if (!PyArg_ParseTuple (args, PYCAIRO_ENC_TEXT_FORMAT ":Context.text_extents", "utf-8", &utf8)) return NULL; cairo_text_extents (o->ctx, utf8, &extents); PyMem_Free((void *)utf8); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); ext_args = Py_BuildValue ("(dddddd)", extents.x_bearing, extents.y_bearing, extents.width, extents.height, extents.x_advance, extents.y_advance); res = PyObject_Call ((PyObject *)&PycairoTextExtents_Type, ext_args, NULL); Py_DECREF (ext_args); return res; } static PyObject * pycairo_text_path (PycairoContext *o, PyObject *args) { const char *utf8; if (!PyArg_ParseTuple (args, PYCAIRO_ENC_TEXT_FORMAT ":Context.text_path", "utf-8", &utf8)) return NULL; cairo_text_path (o->ctx, utf8); PyMem_Free((void *)utf8); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_transform (PycairoContext *o, PyObject *args) { PycairoMatrix *matrix; if (!PyArg_ParseTuple (args, "O!:Context.transform", &PycairoMatrix_Type, &matrix)) return NULL; cairo_transform (o->ctx, &matrix->matrix); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_translate (PycairoContext *o, PyObject *args) { double tx, ty; if (!PyArg_ParseTuple (args, "dd:Context.translate", &tx, &ty)) return NULL; cairo_translate (o->ctx, tx, ty); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_user_to_device (PycairoContext *o, PyObject *args) { double x, y; if (!PyArg_ParseTuple (args, "dd:Context.user_to_device", &x, &y)) return NULL; cairo_user_to_device (o->ctx, &x, &y); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); return Py_BuildValue("(dd)", x, y); } static PyObject * pycairo_user_to_device_distance (PycairoContext *o, PyObject *args) { double dx, dy; if (!PyArg_ParseTuple (args, "dd:Context.user_to_device_distance", &dx, &dy)) return NULL; cairo_user_to_device_distance (o->ctx, &dx, &dy); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); return Py_BuildValue("(dd)", dx, dy); } static PyObject * pycairo_show_text_glyphs (PycairoContext *o, PyObject *args) { const char *utf8 = NULL; PyObject *glyphs_arg, *glyphs_seq = NULL; PyObject *clusters_arg, *clusters_seq = NULL; cairo_text_cluster_flags_t cluster_flags; int cluster_flags_arg; PyObject *py_item; cairo_glyph_t *glyphs = NULL; cairo_text_cluster_t *clusters = NULL; Py_ssize_t i, clusters_size, glyphs_size; if (!PyArg_ParseTuple (args, PYCAIRO_ENC_TEXT_FORMAT "OOi:Context.show_text_glyphs", "utf-8", &utf8, &glyphs_arg, &clusters_arg, &cluster_flags_arg)) return NULL; cluster_flags = (cairo_text_cluster_flags_t)cluster_flags_arg; glyphs_seq = PySequence_Fast (glyphs_arg, "glyphs must be a sequence"); if (glyphs_seq == NULL) goto error; glyphs_size = PySequence_Fast_GET_SIZE (glyphs_seq); if (glyphs_size > INT_MAX) { PyErr_SetString (PyExc_ValueError, "glyph sequence too large"); goto error; } glyphs = cairo_glyph_allocate ((int)glyphs_size); if (glyphs_size && glyphs == NULL) { PyErr_NoMemory(); goto error; } for (i=0; i < glyphs_size; i++) { py_item = PySequence_Fast_GET_ITEM (glyphs_seq, i); if (py_item == 0 || _PyGlyph_AsGlyph (py_item, &(glyphs[i])) != 0) goto error; } Py_CLEAR (glyphs_seq); clusters_seq = PySequence_Fast (clusters_arg, "clusters must be a sequence"); if (clusters_seq == NULL) goto error; clusters_size = PySequence_Fast_GET_SIZE (clusters_seq); if (clusters_size > INT_MAX) { PyErr_SetString (PyExc_ValueError, "clusters sequence too large"); goto error; } clusters = cairo_text_cluster_allocate ((int)clusters_size); if (clusters_size && clusters == NULL) { PyErr_NoMemory(); goto error; } for (i=0; i < clusters_size; i++) { py_item = PySequence_Fast_GET_ITEM (clusters_seq, i); if (py_item == NULL || _PyTextCluster_AsTextCluster (py_item, &(clusters[i])) != 0) goto error; } Py_CLEAR (clusters_seq); Py_BEGIN_ALLOW_THREADS; cairo_show_text_glyphs ( o->ctx, utf8, -1, glyphs, (int)glyphs_size, clusters, (int)clusters_size, cluster_flags); Py_END_ALLOW_THREADS; PyMem_Free ((void *)utf8); utf8 = NULL; cairo_glyph_free (glyphs); cairo_text_cluster_free (clusters); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR (o->ctx); Py_RETURN_NONE; error: PyMem_Free ((void *)utf8); cairo_glyph_free (glyphs); cairo_text_cluster_free (clusters); Py_XDECREF (glyphs_seq); Py_XDECREF (clusters_seq); return NULL; } static PyMethodDef pycairo_methods[] = { /* methods never exposed in a language binding: * cairo_destroy() * cairo_reference() * cairo_rectangle_list_destroy() * * cairo_status() * cairo_status_string() * - not needed since Pycairo calls Pycairo_Check_Status() to check * for errors and raise exceptions */ {"append_path", (PyCFunction)pycairo_append_path, METH_VARARGS}, {"arc", (PyCFunction)pycairo_arc, METH_VARARGS}, {"arc_negative", (PyCFunction)pycairo_arc_negative, METH_VARARGS}, {"clip", (PyCFunction)pycairo_clip, METH_NOARGS}, {"clip_extents", (PyCFunction)pycairo_clip_extents, METH_NOARGS}, {"clip_preserve", (PyCFunction)pycairo_clip_preserve, METH_NOARGS}, {"close_path", (PyCFunction)pycairo_close_path, METH_NOARGS}, {"copy_clip_rectangle_list", (PyCFunction)pycairo_copy_clip_rectangle_list, METH_NOARGS}, {"copy_page", (PyCFunction)pycairo_copy_page, METH_NOARGS}, {"copy_path", (PyCFunction)pycairo_copy_path, METH_NOARGS}, {"copy_path_flat", (PyCFunction)pycairo_copy_path_flat, METH_NOARGS}, {"curve_to", (PyCFunction)pycairo_curve_to, METH_VARARGS}, {"device_to_user", (PyCFunction)pycairo_device_to_user, METH_VARARGS}, {"device_to_user_distance", (PyCFunction)pycairo_device_to_user_distance, METH_VARARGS}, {"fill", (PyCFunction)pycairo_fill, METH_NOARGS}, {"fill_extents", (PyCFunction)pycairo_fill_extents, METH_NOARGS}, {"fill_preserve", (PyCFunction)pycairo_fill_preserve, METH_NOARGS}, {"font_extents", (PyCFunction)pycairo_font_extents, METH_NOARGS}, {"get_antialias", (PyCFunction)pycairo_get_antialias, METH_NOARGS}, {"get_current_point",(PyCFunction)pycairo_get_current_point,METH_NOARGS}, {"get_dash", (PyCFunction)pycairo_get_dash, METH_NOARGS}, {"get_dash_count", (PyCFunction)pycairo_get_dash_count, METH_NOARGS}, {"get_fill_rule", (PyCFunction)pycairo_get_fill_rule, METH_NOARGS}, {"get_font_face", (PyCFunction)pycairo_get_font_face, METH_NOARGS}, {"get_font_matrix", (PyCFunction)pycairo_get_font_matrix, METH_NOARGS}, {"get_font_options",(PyCFunction)pycairo_get_font_options, METH_NOARGS}, {"get_group_target",(PyCFunction)pycairo_get_group_target, METH_NOARGS}, {"get_line_cap", (PyCFunction)pycairo_get_line_cap, METH_NOARGS}, {"get_line_join", (PyCFunction)pycairo_get_line_join, METH_NOARGS}, {"get_line_width", (PyCFunction)pycairo_get_line_width, METH_NOARGS}, {"get_matrix", (PyCFunction)pycairo_get_matrix, METH_NOARGS}, {"get_miter_limit", (PyCFunction)pycairo_get_miter_limit, METH_NOARGS}, {"get_operator", (PyCFunction)pycairo_get_operator, METH_NOARGS}, {"get_scaled_font", (PyCFunction)pycairo_get_scaled_font, METH_NOARGS}, {"get_source", (PyCFunction)pycairo_get_source, METH_NOARGS}, {"get_target", (PyCFunction)pycairo_get_target, METH_NOARGS}, {"get_tolerance", (PyCFunction)pycairo_get_tolerance, METH_NOARGS}, {"glyph_extents", (PyCFunction)pycairo_glyph_extents, METH_VARARGS}, {"glyph_path", (PyCFunction)pycairo_glyph_path, METH_VARARGS}, {"has_current_point",(PyCFunction)pycairo_has_current_point, METH_NOARGS}, {"identity_matrix", (PyCFunction)pycairo_identity_matrix, METH_NOARGS}, {"in_clip", (PyCFunction)pycairo_in_clip, METH_VARARGS}, {"in_fill", (PyCFunction)pycairo_in_fill, METH_VARARGS}, {"in_stroke", (PyCFunction)pycairo_in_stroke, METH_VARARGS}, {"line_to", (PyCFunction)pycairo_line_to, METH_VARARGS}, {"mask", (PyCFunction)pycairo_mask, METH_VARARGS}, {"mask_surface", (PyCFunction)pycairo_mask_surface, METH_VARARGS}, {"move_to", (PyCFunction)pycairo_move_to, METH_VARARGS}, {"new_path", (PyCFunction)pycairo_new_path, METH_NOARGS}, {"new_sub_path", (PyCFunction)pycairo_new_sub_path, METH_NOARGS}, {"paint", (PyCFunction)pycairo_paint, METH_NOARGS}, {"paint_with_alpha",(PyCFunction)pycairo_paint_with_alpha, METH_VARARGS}, {"path_extents", (PyCFunction)pycairo_path_extents, METH_NOARGS}, {"pop_group", (PyCFunction)pycairo_pop_group, METH_NOARGS}, {"pop_group_to_source", (PyCFunction)pycairo_pop_group_to_source, METH_NOARGS}, {"push_group", (PyCFunction)pycairo_push_group, METH_NOARGS}, {"push_group_with_content", (PyCFunction)pycairo_push_group_with_content, METH_VARARGS}, {"rectangle", (PyCFunction)pycairo_rectangle, METH_VARARGS}, {"rel_curve_to", (PyCFunction)pycairo_rel_curve_to, METH_VARARGS}, {"rel_line_to", (PyCFunction)pycairo_rel_line_to, METH_VARARGS}, {"rel_move_to", (PyCFunction)pycairo_rel_move_to, METH_VARARGS}, {"reset_clip", (PyCFunction)pycairo_reset_clip, METH_NOARGS}, {"restore", (PyCFunction)pycairo_restore, METH_NOARGS}, {"rotate", (PyCFunction)pycairo_rotate, METH_VARARGS}, {"save", (PyCFunction)pycairo_save, METH_NOARGS}, {"scale", (PyCFunction)pycairo_scale, METH_VARARGS}, {"select_font_face",(PyCFunction)pycairo_select_font_face, METH_VARARGS}, {"set_antialias", (PyCFunction)pycairo_set_antialias, METH_VARARGS}, {"set_dash", (PyCFunction)pycairo_set_dash, METH_VARARGS}, {"set_fill_rule", (PyCFunction)pycairo_set_fill_rule, METH_VARARGS}, {"set_font_face", (PyCFunction)pycairo_set_font_face, METH_O}, {"set_font_matrix", (PyCFunction)pycairo_set_font_matrix, METH_VARARGS}, {"set_font_options",(PyCFunction)pycairo_set_font_options, METH_VARARGS}, {"set_font_size", (PyCFunction)pycairo_set_font_size, METH_VARARGS}, {"set_line_cap", (PyCFunction)pycairo_set_line_cap, METH_VARARGS}, {"set_line_join", (PyCFunction)pycairo_set_line_join, METH_VARARGS}, {"set_line_width", (PyCFunction)pycairo_set_line_width, METH_VARARGS}, {"set_matrix", (PyCFunction)pycairo_set_matrix, METH_VARARGS}, {"set_miter_limit", (PyCFunction)pycairo_set_miter_limit, METH_VARARGS}, {"set_operator", (PyCFunction)pycairo_set_operator, METH_VARARGS}, {"set_scaled_font", (PyCFunction)pycairo_set_scaled_font, METH_VARARGS}, {"set_source", (PyCFunction)pycairo_set_source, METH_VARARGS}, {"set_source_rgb", (PyCFunction)pycairo_set_source_rgb, METH_VARARGS}, {"set_source_rgba", (PyCFunction)pycairo_set_source_rgba, METH_VARARGS}, {"set_source_surface",(PyCFunction)pycairo_set_source_surface, METH_VARARGS}, {"set_tolerance", (PyCFunction)pycairo_set_tolerance, METH_VARARGS}, {"show_glyphs", (PyCFunction)pycairo_show_glyphs, METH_VARARGS}, {"show_page", (PyCFunction)pycairo_show_page, METH_NOARGS}, {"show_text", (PyCFunction)pycairo_show_text, METH_VARARGS}, {"stroke", (PyCFunction)pycairo_stroke, METH_NOARGS}, {"stroke_extents", (PyCFunction)pycairo_stroke_extents, METH_NOARGS}, {"stroke_preserve", (PyCFunction)pycairo_stroke_preserve, METH_NOARGS}, {"text_extents", (PyCFunction)pycairo_text_extents, METH_VARARGS}, {"text_path", (PyCFunction)pycairo_text_path, METH_VARARGS}, {"transform", (PyCFunction)pycairo_transform, METH_VARARGS}, {"translate", (PyCFunction)pycairo_translate, METH_VARARGS}, {"user_to_device", (PyCFunction)pycairo_user_to_device, METH_VARARGS}, {"user_to_device_distance",(PyCFunction)pycairo_user_to_device_distance, METH_VARARGS}, {"show_text_glyphs",(PyCFunction)pycairo_show_text_glyphs, METH_VARARGS}, {NULL, NULL, 0, NULL}, }; static PyObject* pycairo_richcompare (PyObject *self, PyObject *other, int op) { if (Py_TYPE(self) == Py_TYPE(other)) return Pycairo_richcompare ( ((PycairoContext *)self)->ctx, ((PycairoContext *)other)->ctx, op); else { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } } static PYCAIRO_Py_hash_t pycairo_hash (PyObject *self) { return PYCAIRO_Py_hash_t_FromVoidPtr (((PycairoContext *)self)->ctx); } PyTypeObject PycairoContext_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.Context", /* tp_name */ sizeof(PycairoContext), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)pycairo_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ pycairo_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,/* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ pycairo_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ pycairo_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)pycairo_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; pycairo-1.16.2/cairo/device.c000066400000000000000000000316211323762421700157610ustar00rootroot00000000000000/* Pycairo - Python bindings for cairo * * Copyright © 2017 Christoph Reiter * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "private.h" static void device_dealloc(PycairoDevice *obj) { if (obj->device) { cairo_device_destroy(obj->device); obj->device = NULL; } Py_TYPE(obj)->tp_free(obj); } static PyObject * device_finish (PycairoDevice *obj) { cairo_device_finish (obj->device); RETURN_NULL_IF_CAIRO_DEVICE_ERROR(obj->device); Py_RETURN_NONE; } static PyObject * device_flush (PycairoDevice *obj) { cairo_device_flush (obj->device); RETURN_NULL_IF_CAIRO_DEVICE_ERROR(obj->device); Py_RETURN_NONE; } static PyObject * device_acquire (PycairoDevice *obj) { cairo_status_t status; Py_BEGIN_ALLOW_THREADS; status = cairo_device_acquire (obj->device); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_ERROR (status); Py_RETURN_NONE; } static PyObject * device_release (PycairoDevice *obj) { cairo_device_release (obj->device); Py_RETURN_NONE; } static PyMethodDef device_methods[] = { {"finish", (PyCFunction)device_finish, METH_NOARGS}, {"flush", (PyCFunction)device_flush, METH_NOARGS}, {"acquire", (PyCFunction)device_acquire, METH_NOARGS}, {"release", (PyCFunction)device_release, METH_NOARGS}, {NULL, NULL, 0, NULL}, }; static PyObject * device_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { PyErr_SetString(PyExc_TypeError, "The Device type cannot be instantiated"); return NULL; } static PyObject* device_richcompare (PyObject *self, PyObject *other, int op) { if (Py_TYPE(self) == Py_TYPE(other)) return Pycairo_richcompare ( ((PycairoDevice *)self)->device, ((PycairoDevice *)other)->device, op); else { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } } static PYCAIRO_Py_hash_t device_hash (PyObject *self) { return PYCAIRO_Py_hash_t_FromVoidPtr (((PycairoDevice *)self)->device); } PyTypeObject PycairoDevice_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.Device", /* tp_name */ sizeof(PycairoDevice), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)device_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ device_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ device_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ device_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)device_new, /* tp_new */ }; #ifdef CAIRO_HAS_SCRIPT_SURFACE #include static const cairo_user_data_key_t device_base_object_key; static void _decref_destroy_func(void *user_data) { PyGILState_STATE gstate = PyGILState_Ensure(); Py_DECREF(user_data); PyGILState_Release(gstate); } static PyObject * _device_create_with_object(cairo_device_t *device, PyObject *base) { PyObject *pydevice; cairo_status_t status; pydevice = PycairoDevice_FromDevice(device); if (pydevice == NULL) return NULL; if (base != NULL) { status = cairo_device_set_user_data( device, &device_base_object_key, base, _decref_destroy_func); if (status != CAIRO_STATUS_SUCCESS) Py_DECREF(pydevice); RETURN_NULL_IF_CAIRO_ERROR(status); Py_INCREF(base); } return pydevice; } static cairo_status_t _write_func (void *closure, const unsigned char *data, unsigned int length) { PyGILState_STATE gstate = PyGILState_Ensure(); PyObject *res = PyObject_CallMethod ( (PyObject *)closure, "write", "(" PYCAIRO_DATA_FORMAT "#)", data, (Py_ssize_t)length); if (res == NULL) { PyErr_Clear(); /* an exception has occurred, it will be picked up later by * Pycairo_Check_Status() */ PyGILState_Release(gstate); return CAIRO_STATUS_WRITE_ERROR; } Py_DECREF(res); PyGILState_Release(gstate); return CAIRO_STATUS_SUCCESS; } static PyObject * script_device_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { char *name = NULL; PyObject *file; cairo_device_t *device; if (!PyArg_ParseTuple (args, "O:ScriptDevice.__new__", &file)) return NULL; if (Pycairo_is_fspath (file)) { if (!PyArg_ParseTuple (args, "O&:ScriptDevice.__new__", Pycairo_fspath_converter, &name)) return NULL; Py_BEGIN_ALLOW_THREADS; device = cairo_script_create (name); Py_END_ALLOW_THREADS; PyMem_Free (name); return PycairoDevice_FromDevice (device); } else { if (PyArg_ParseTuple (args, "O&:ScriptDevice.__new__", Pycairo_writer_converter, &file)) { Py_BEGIN_ALLOW_THREADS; device = cairo_script_create_for_stream (_write_func, file); Py_END_ALLOW_THREADS; return _device_create_with_object (device, file); } else { PyErr_Clear (); PyErr_SetString (PyExc_TypeError, "ScriptDevice takes one argument which must be " "a filename, file object, or a file-like object " "which has a \"write\" method (like StringIO)"); return NULL; } } } static PyObject * script_device_get_mode (PycairoDevice *obj) { RETURN_INT_ENUM (ScriptMode, cairo_script_get_mode (obj->device)); } static PyObject * script_device_set_mode (PycairoDevice *obj, PyObject *args) { cairo_script_mode_t mode; int mode_arg; if (!PyArg_ParseTuple (args, "i:ScriptDevice.set_mode", &mode_arg)) return NULL; mode = (cairo_script_mode_t)mode_arg; Py_BEGIN_ALLOW_THREADS; cairo_script_set_mode (obj->device, mode); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_DEVICE_ERROR (obj->device); Py_RETURN_NONE; } static PyObject * script_device_write_comment (PycairoDevice *obj, PyObject *args) { const char *comment; if (!PyArg_ParseTuple(args, "s:ScriptDevice.write_comment", &comment)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_script_write_comment (obj->device, comment, -1); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_DEVICE_ERROR(obj->device); Py_RETURN_NONE; } #ifdef CAIRO_HAS_RECORDING_SURFACE static PyObject * script_device_from_recording_surface (PycairoDevice *obj, PyObject *args) { PyObject *pysurface; cairo_status_t status; if (!PyArg_ParseTuple(args, "O!:ScriptDevice.from_recording_surface", &PycairoRecordingSurface_Type, &pysurface)) return NULL; Py_BEGIN_ALLOW_THREADS; status = cairo_script_from_recording_surface (obj->device, ((PycairoRecordingSurface*)pysurface)->surface); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_ERROR(status); Py_RETURN_NONE; } #endif static PyMethodDef script_device_methods[] = { {"get_mode", (PyCFunction)script_device_get_mode, METH_NOARGS}, {"set_mode", (PyCFunction)script_device_set_mode, METH_VARARGS}, {"write_comment", (PyCFunction)script_device_write_comment, METH_VARARGS}, #ifdef CAIRO_HAS_RECORDING_SURFACE {"from_recording_surface", (PyCFunction)script_device_from_recording_surface, METH_VARARGS}, #endif {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoScriptDevice_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.ScriptDevice", /* tp_name */ sizeof(PycairoScriptDevice), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ script_device_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoDevice_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)script_device_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; #endif PyObject * PycairoDevice_FromDevice (cairo_device_t *device) { PyObject *obj; PyTypeObject *type; assert (device != NULL); if (Pycairo_Check_Status (cairo_device_status (device))) { cairo_device_destroy (device); return NULL; } switch (cairo_device_get_type (device)) { #ifdef CAIRO_HAS_SCRIPT_SURFACE case CAIRO_DEVICE_TYPE_SCRIPT: type = &PycairoScriptDevice_Type; break; #endif default: type = &PycairoDevice_Type; break; } obj = type->tp_alloc (type, 0); if (obj) { ((PycairoDevice *)obj)->device = device; } else { cairo_device_destroy (device); } return obj; } pycairo-1.16.2/cairo/enums.c000066400000000000000000000336721323762421700156610ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2017 Christoph Reiter * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "private.h" /* For the CAIRO_SVG_VERSION_* defines */ #ifdef CAIRO_HAS_SVG_SURFACE # include #endif /* For the CAIRO_PDF_VERSION_* defines */ #ifdef CAIRO_HAS_PDF_SURFACE # include #endif /* For the CAIRO_PS_LEVEL_* defines */ #ifdef CAIRO_HAS_PS_SURFACE # include #endif /* For the CAIRO_SCRIPT_* defines */ #ifdef CAIRO_HAS_SCRIPT_SURFACE # include #endif typedef struct { PYCAIRO_PyLongObject base; } Pycairo_IntEnumObject; static PyObject * int_enum_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *dummy; if (!PyArg_ParseTuple (args, "O", &dummy)) return NULL; return PYCAIRO_PyLong_Type.tp_new(type, args, kwds); } PyObject * int_enum_create(PyTypeObject *type, long value) { PyObject *args, *result; args = Py_BuildValue("(l)", value); if (args == NULL) return NULL; result = int_enum_new(type, args, NULL); Py_DECREF(args); return result; } static const char *map_name = "__map"; static PyObject* enum_type_register_constant(PyTypeObject *type, const char* name, long value) { PyObject *value_map; PyObject *int_obj, *name_obj, *en; /* Get/Create the int->name mapping */ value_map = PyDict_GetItemString(type->tp_dict, map_name); if (value_map == NULL) { value_map = PyDict_New(); PyDict_SetItemString(type->tp_dict, map_name, value_map); Py_DECREF(value_map); } /* Add int->name pair to the mapping */ int_obj = PYCAIRO_PyLong_FromLong(value); name_obj = PYCAIRO_PyUnicode_FromString (name); if (PyDict_SetItem(value_map, int_obj, name_obj) < 0) { Py_DECREF(int_obj); Py_DECREF(name_obj); return NULL; } Py_DECREF(int_obj); Py_DECREF(name_obj); /* Create a new enum instance of the right type and add to the class */ en = int_enum_create(type, value); if (en == NULL || PyDict_SetItemString(type->tp_dict, name, en) < 0) return NULL; return en; } /* If returns NULL no error is set */ static PyObject * int_enum_get_name(PyObject *obj) { PyObject *value_map, *name_obj; value_map = PyDict_GetItemString(Py_TYPE(obj)->tp_dict, map_name); if(value_map == NULL) return NULL; name_obj = PyDict_GetItem(value_map, obj); if(name_obj == NULL) return NULL; return PYCAIRO_PyUnicode_FromFormat("%s.%s", Py_TYPE(obj)->tp_name, PYCAIRO_PyUnicode_Astring(name_obj)); } static PyObject * int_enum_repr(PyObject *obj) { PyObject *name_obj; name_obj = int_enum_get_name(obj); if(name_obj == NULL) return PYCAIRO_PyLong_Type.tp_repr(obj); return name_obj; } static PyObject * int_enum_reduce(PyObject *self) { PyObject *num = PYCAIRO_PyNumber_Long (self); if (num == NULL) return NULL; return Py_BuildValue ("(O, (N))", &PYCAIRO_PyLong_Type, num); } static PyMethodDef int_enum_methods[] = { {"__reduce__", (PyCFunction)int_enum_reduce, METH_NOARGS}, {NULL, NULL, 0}, }; PyTypeObject Pycairo_IntEnum_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo._IntEnum", sizeof(Pycairo_IntEnumObject), }; #define DEFINE_ENUM(n) \ PyTypeObject Pycairo_##n##_Type = { \ PyVarObject_HEAD_INIT(NULL, 0) \ "cairo." #n, \ sizeof(Pycairo_IntEnumObject), \ }; DEFINE_ENUM(Antialias) DEFINE_ENUM(Content) DEFINE_ENUM(Extend) DEFINE_ENUM(FillRule) DEFINE_ENUM(Filter) DEFINE_ENUM(FontSlant) DEFINE_ENUM(FontWeight) DEFINE_ENUM(Format) DEFINE_ENUM(HintMetrics) DEFINE_ENUM(HintStyle) DEFINE_ENUM(LineCap) DEFINE_ENUM(LineJoin) DEFINE_ENUM(Operator) DEFINE_ENUM(PathDataType) DEFINE_ENUM(RegionOverlap) DEFINE_ENUM(Status) DEFINE_ENUM(SubpixelOrder) DEFINE_ENUM(TextClusterFlags) DEFINE_ENUM(SurfaceObserverMode) #ifdef CAIRO_HAS_SVG_SURFACE DEFINE_ENUM(SVGVersion) #endif #ifdef CAIRO_HAS_PDF_SURFACE DEFINE_ENUM(PDFVersion) #endif #ifdef CAIRO_HAS_PS_SURFACE DEFINE_ENUM(PSLevel) #endif #ifdef CAIRO_HAS_SCRIPT_SURFACE DEFINE_ENUM(ScriptMode) #endif #undef DEFINE_ENUM static int init_enum_type (PyObject *module, const char *name, PyTypeObject *type) { type->tp_base = &Pycairo_IntEnum_Type; type->tp_flags = Py_TPFLAGS_DEFAULT; if (PyType_Ready(type) < 0) return -1; Py_INCREF(type); if (PyModule_AddObject(module, name, (PyObject *)type) < 0) return -1; return 0; } static PyObject * format_stride_for_width (PyObject *self, PyObject *args) { cairo_format_t format; long value; int width; if (!PyArg_ParseTuple(args, "i:stride_for_width", &width)) return NULL; value = PyLong_AsLong (self); if (PyErr_Occurred()) return NULL; if (value > INT_MAX || value < INT_MIN) { PyErr_SetString (PyExc_ValueError, "format value out of range"); return NULL; } format = (cairo_format_t)value; return PYCAIRO_PyLong_FromLong ( cairo_format_stride_for_width (format, width)); } static PyMethodDef format_methods[] = { {"stride_for_width", (PyCFunction)format_stride_for_width, METH_VARARGS}, {NULL, NULL, 0, NULL}, }; int init_enums (PyObject *module) { PyObject *ev; Pycairo_IntEnum_Type.tp_repr = (reprfunc)int_enum_repr; Pycairo_IntEnum_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; Pycairo_IntEnum_Type.tp_methods = int_enum_methods; Pycairo_IntEnum_Type.tp_base = &PYCAIRO_PyLong_Type; Pycairo_IntEnum_Type.tp_new = (newfunc)int_enum_new; if (PyType_Ready(&Pycairo_IntEnum_Type) < 0) return -1; #define ENUM(t) \ if (init_enum_type(module, #t, &Pycairo_##t##_Type) < 0) \ return -1; #define CONSTANT(t, a, b) \ ev = enum_type_register_constant(&Pycairo_##t##_Type, #b, CAIRO_##a##_##b); \ if (ev == NULL || PyModule_AddObject(module, #a "_" #b, ev) < 0) \ return -1; ENUM(Antialias); CONSTANT(Antialias, ANTIALIAS, DEFAULT); CONSTANT(Antialias, ANTIALIAS, NONE); CONSTANT(Antialias, ANTIALIAS, GRAY); CONSTANT(Antialias, ANTIALIAS, SUBPIXEL); CONSTANT(Antialias, ANTIALIAS, FAST); CONSTANT(Antialias, ANTIALIAS, GOOD); CONSTANT(Antialias, ANTIALIAS, BEST); ENUM(Content); CONSTANT(Content, CONTENT, COLOR); CONSTANT(Content, CONTENT, ALPHA); CONSTANT(Content, CONTENT, COLOR_ALPHA); ENUM(Extend); CONSTANT(Extend, EXTEND, NONE); CONSTANT(Extend, EXTEND, REPEAT); CONSTANT(Extend, EXTEND, REFLECT); CONSTANT(Extend, EXTEND, PAD); ENUM(FillRule); CONSTANT(FillRule, FILL_RULE, WINDING); CONSTANT(FillRule, FILL_RULE, EVEN_ODD); ENUM(Filter); CONSTANT(Filter, FILTER, FAST); CONSTANT(Filter, FILTER, GOOD); CONSTANT(Filter, FILTER, BEST); CONSTANT(Filter, FILTER, NEAREST); CONSTANT(Filter, FILTER, BILINEAR); CONSTANT(Filter, FILTER, GAUSSIAN); ENUM(FontWeight) CONSTANT(FontWeight, FONT_WEIGHT, NORMAL); CONSTANT(FontWeight, FONT_WEIGHT, BOLD); ENUM(FontSlant); CONSTANT(FontSlant, FONT_SLANT, NORMAL); CONSTANT(FontSlant, FONT_SLANT, ITALIC); CONSTANT(FontSlant, FONT_SLANT, OBLIQUE); Pycairo_Format_Type.tp_methods = format_methods; ENUM(Format); CONSTANT(Format, FORMAT, INVALID); CONSTANT(Format, FORMAT, ARGB32); CONSTANT(Format, FORMAT, RGB24); CONSTANT(Format, FORMAT, A8); CONSTANT(Format, FORMAT, A1); CONSTANT(Format, FORMAT, RGB16_565); CONSTANT(Format, FORMAT, RGB30); ENUM(HintMetrics); CONSTANT(HintMetrics, HINT_METRICS, DEFAULT); CONSTANT(HintMetrics, HINT_METRICS, OFF); CONSTANT(HintMetrics, HINT_METRICS, ON); ENUM(HintStyle); CONSTANT(HintStyle, HINT_STYLE, DEFAULT); CONSTANT(HintStyle, HINT_STYLE, NONE); CONSTANT(HintStyle, HINT_STYLE, SLIGHT); CONSTANT(HintStyle, HINT_STYLE, MEDIUM); CONSTANT(HintStyle, HINT_STYLE, FULL); ENUM(LineCap); CONSTANT(LineCap, LINE_CAP, BUTT); CONSTANT(LineCap, LINE_CAP, ROUND); CONSTANT(LineCap, LINE_CAP, SQUARE); ENUM(LineJoin); CONSTANT(LineJoin, LINE_JOIN, MITER); CONSTANT(LineJoin, LINE_JOIN, ROUND); CONSTANT(LineJoin, LINE_JOIN, BEVEL); ENUM(Operator); CONSTANT(Operator, OPERATOR, CLEAR); CONSTANT(Operator, OPERATOR, SOURCE); CONSTANT(Operator, OPERATOR, OVER); CONSTANT(Operator, OPERATOR, IN); CONSTANT(Operator, OPERATOR, OUT); CONSTANT(Operator, OPERATOR, ATOP); CONSTANT(Operator, OPERATOR, DEST); CONSTANT(Operator, OPERATOR, DEST_OVER); CONSTANT(Operator, OPERATOR, DEST_IN); CONSTANT(Operator, OPERATOR, DEST_OUT); CONSTANT(Operator, OPERATOR, DEST_ATOP); CONSTANT(Operator, OPERATOR, XOR); CONSTANT(Operator, OPERATOR, ADD); CONSTANT(Operator, OPERATOR, SATURATE); CONSTANT(Operator, OPERATOR, MULTIPLY); CONSTANT(Operator, OPERATOR, SCREEN); CONSTANT(Operator, OPERATOR, OVERLAY); CONSTANT(Operator, OPERATOR, DARKEN); CONSTANT(Operator, OPERATOR, LIGHTEN); CONSTANT(Operator, OPERATOR, COLOR_DODGE); CONSTANT(Operator, OPERATOR, COLOR_BURN); CONSTANT(Operator, OPERATOR, HARD_LIGHT); CONSTANT(Operator, OPERATOR, SOFT_LIGHT); CONSTANT(Operator, OPERATOR, DIFFERENCE); CONSTANT(Operator, OPERATOR, EXCLUSION); CONSTANT(Operator, OPERATOR, HSL_HUE); CONSTANT(Operator, OPERATOR, HSL_SATURATION); CONSTANT(Operator, OPERATOR, HSL_COLOR); CONSTANT(Operator, OPERATOR, HSL_LUMINOSITY); ENUM(Status); CONSTANT(Status, STATUS, SUCCESS); CONSTANT(Status, STATUS, NO_MEMORY); CONSTANT(Status, STATUS, INVALID_RESTORE); CONSTANT(Status, STATUS, INVALID_POP_GROUP); CONSTANT(Status, STATUS, NO_CURRENT_POINT); CONSTANT(Status, STATUS, INVALID_MATRIX); CONSTANT(Status, STATUS, INVALID_STATUS); CONSTANT(Status, STATUS, NULL_POINTER); CONSTANT(Status, STATUS, INVALID_STRING); CONSTANT(Status, STATUS, INVALID_PATH_DATA); CONSTANT(Status, STATUS, READ_ERROR); CONSTANT(Status, STATUS, WRITE_ERROR); CONSTANT(Status, STATUS, SURFACE_FINISHED); CONSTANT(Status, STATUS, SURFACE_TYPE_MISMATCH); CONSTANT(Status, STATUS, PATTERN_TYPE_MISMATCH); CONSTANT(Status, STATUS, INVALID_CONTENT); CONSTANT(Status, STATUS, INVALID_FORMAT); CONSTANT(Status, STATUS, INVALID_VISUAL); CONSTANT(Status, STATUS, FILE_NOT_FOUND); CONSTANT(Status, STATUS, INVALID_DASH); CONSTANT(Status, STATUS, INVALID_DSC_COMMENT); CONSTANT(Status, STATUS, INVALID_INDEX); CONSTANT(Status, STATUS, CLIP_NOT_REPRESENTABLE); CONSTANT(Status, STATUS, TEMP_FILE_ERROR); CONSTANT(Status, STATUS, INVALID_STRIDE); CONSTANT(Status, STATUS, FONT_TYPE_MISMATCH); CONSTANT(Status, STATUS, USER_FONT_IMMUTABLE); CONSTANT(Status, STATUS, USER_FONT_ERROR); CONSTANT(Status, STATUS, NEGATIVE_COUNT); CONSTANT(Status, STATUS, INVALID_CLUSTERS); CONSTANT(Status, STATUS, INVALID_SLANT); CONSTANT(Status, STATUS, INVALID_WEIGHT); CONSTANT(Status, STATUS, INVALID_SIZE); CONSTANT(Status, STATUS, USER_FONT_NOT_IMPLEMENTED); CONSTANT(Status, STATUS, DEVICE_TYPE_MISMATCH); CONSTANT(Status, STATUS, DEVICE_ERROR); CONSTANT(Status, STATUS, INVALID_MESH_CONSTRUCTION); CONSTANT(Status, STATUS, DEVICE_FINISHED); CONSTANT(Status, STATUS, JBIG2_GLOBAL_MISSING); CONSTANT(Status, STATUS, LAST_STATUS); ENUM(PathDataType); CONSTANT(PathDataType, PATH, MOVE_TO); CONSTANT(PathDataType, PATH, LINE_TO); CONSTANT(PathDataType, PATH, CURVE_TO); CONSTANT(PathDataType, PATH, CLOSE_PATH); ENUM(RegionOverlap); CONSTANT(RegionOverlap, REGION_OVERLAP, IN); CONSTANT(RegionOverlap, REGION_OVERLAP, OUT); CONSTANT(RegionOverlap, REGION_OVERLAP, PART); ENUM(SubpixelOrder); CONSTANT(SubpixelOrder, SUBPIXEL_ORDER, DEFAULT); CONSTANT(SubpixelOrder, SUBPIXEL_ORDER, RGB); CONSTANT(SubpixelOrder, SUBPIXEL_ORDER, BGR); CONSTANT(SubpixelOrder, SUBPIXEL_ORDER, VRGB); CONSTANT(SubpixelOrder, SUBPIXEL_ORDER, VBGR); ENUM(TextClusterFlags); CONSTANT(TextClusterFlags, TEXT_CLUSTER_FLAG, BACKWARD); ENUM(SurfaceObserverMode); CONSTANT(SurfaceObserverMode, SURFACE_OBSERVER, NORMAL); CONSTANT(SurfaceObserverMode, SURFACE_OBSERVER, RECORD_OPERATIONS); #ifdef CAIRO_HAS_SVG_SURFACE ENUM(SVGVersion); CONSTANT(SVGVersion, SVG, VERSION_1_1); CONSTANT(SVGVersion, SVG, VERSION_1_2); #endif #ifdef CAIRO_HAS_PDF_SURFACE ENUM(PDFVersion); CONSTANT(PDFVersion, PDF, VERSION_1_4); CONSTANT(PDFVersion, PDF, VERSION_1_5); #endif #ifdef CAIRO_HAS_PS_SURFACE ENUM(PSLevel); CONSTANT(PSLevel, PS, LEVEL_2); CONSTANT(PSLevel, PS, LEVEL_3); #endif #ifdef CAIRO_HAS_SCRIPT_SURFACE ENUM(ScriptMode); CONSTANT(ScriptMode, SCRIPT_MODE, ASCII); CONSTANT(ScriptMode, SCRIPT_MODE, BINARY); #endif #undef ENUM #undef CONSTANT return 0; } pycairo-1.16.2/cairo/error.c000066400000000000000000000213401323762421700156500ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2017 Christoph Reiter * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "private.h" static PyTypeObject PycairoError_Type; static PyObject *error_get_type_combined ( PyObject *error, PyObject *other, char *name); /* Like cairo_status_to_string(), but translates some C function names to * Python function names. */ static const char* status_to_string(cairo_status_t status) { if (status == CAIRO_STATUS_INVALID_RESTORE) return "Context.restore() without matching Context.save()"; else if (status == CAIRO_STATUS_INVALID_POP_GROUP) return "Context.pop_group() without matching Context.push_group()"; else return cairo_status_to_string(status); } /* Sets an exception based on a cairo_status_t */ static void set_error (PyObject *error_type, cairo_status_t status) { PyObject *args, *v; args = Py_BuildValue("(sO)", status_to_string(status), CREATE_INT_ENUM(Status, status)); v = PyObject_Call(error_type, args, NULL); Py_DECREF(args); if (v != NULL) { PyErr_SetObject((PyObject *)Py_TYPE(v), v); Py_DECREF(v); } } int Pycairo_Check_Status (cairo_status_t status) { PyObject *module, *error, *suberror; if (PyErr_Occurred() != NULL) return 1; if (status == CAIRO_STATUS_SUCCESS) return 0; module = PyImport_ImportModule ("cairo"); if (module == NULL) return 1; error = PyObject_GetAttrString (module, "Error"); Py_DECREF (module); if (error == NULL) return 1; switch (status) { case CAIRO_STATUS_NO_MEMORY: suberror = error_get_type_combined ( error, PyExc_MemoryError, "cairo.MemoryError"); set_error (suberror, status); Py_DECREF (suberror); break; case CAIRO_STATUS_READ_ERROR: case CAIRO_STATUS_WRITE_ERROR: suberror = error_get_type_combined ( error, PyExc_IOError, "cairo.IOError"); set_error (suberror, status); Py_DECREF (suberror); break; default: set_error (error, status); } Py_DECREF (error); return 1; } typedef struct { PyBaseExceptionObject base; } PycairoErrorObject; static PyObject * error_get_args(PycairoErrorObject *self) { PyObject *args; args = PyObject_GetAttrString((PyObject *)self, "args"); if (args == NULL) return NULL; if (!PyTuple_Check(args)) { PyErr_SetString(PyExc_TypeError, ".args not a tuple"); Py_DECREF(args); return NULL; } return args; } static int error_init(PycairoErrorObject *self, PyObject *args, PyObject *kwds) { PyObject *status_obj, *error_args; if (PycairoError_Type.tp_base->tp_init((PyObject *)self, args, kwds) < 0) return -1; error_args = error_get_args(self); if (error_args == NULL) return -1; if(PyTuple_GET_SIZE(error_args) >= 2) { status_obj = PyTuple_GET_ITEM(error_args, 1); } else { status_obj = Py_None; } Py_DECREF(error_args); if (PyObject_SetAttrString ((PyObject *)self, "__status", status_obj) < 0) return -1; return 0; } static PyObject * error_get_status(PycairoErrorObject *self, void *closure) { return PyObject_GetAttrString ((PyObject *)self, "__status"); } static int error_set_status(PycairoErrorObject *self, PyObject *value, void *closure) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete attribute"); return -1; } if (PyObject_SetAttrString ((PyObject *)self, "__status", value) < 0) return -1; return 0; } static PyGetSetDef error_getset[] = { {"status", (getter)error_get_status, (setter)error_set_status,}, {NULL,}, }; static PyObject * error_str(PycairoErrorObject *self) { PyObject *result, *error_args; error_args = error_get_args(self); if (error_args == NULL) return NULL; /* Default to printing just the message */ if (PyTuple_GET_SIZE(error_args) >= 1) { result = PyObject_Str(PyTuple_GET_ITEM(error_args, 0)); } else { result = PycairoError_Type.tp_base->tp_str((PyObject*)self); } Py_DECREF(error_args); return result; } static PyObject * error_check_status (PyTypeObject *type, PyObject *args) { cairo_status_t status; int status_arg; if (!PyArg_ParseTuple (args, "i:Error._check_status", &status_arg)) return NULL; status = (cairo_status_t)status_arg; if (Pycairo_Check_Status (status)) return NULL; Py_RETURN_NONE; } static PyMethodDef error_methods[] = { {"_check_status", (PyCFunction)error_check_status, METH_VARARGS | METH_CLASS}, {NULL, NULL, 0, NULL}, }; static PyTypeObject PycairoError_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.Error", /* tp_name */ sizeof(PycairoErrorObject),/* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ (reprfunc)error_str, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ error_methods, /* tp_methods */ 0, /* tp_members */ error_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)error_init, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ }; int init_error (PyObject *module) { PyObject *error; PycairoError_Type.tp_base = (PyTypeObject*)PyExc_Exception; if (PyType_Ready(&PycairoError_Type) < 0) return -1; error = (PyObject*)&PycairoError_Type; Py_INCREF(error); if (PyModule_AddObject(module, "Error", error) < 0) { Py_DECREF (error); return -1; } Py_INCREF(error); if (PyModule_AddObject(module, "CairoError", error) < 0) { Py_DECREF (error); return -1; } return 0; } static PyObject * error_get_type_combined (PyObject *error, PyObject *other, char* name) { PyObject *class_dict, *new_type_args; PyObject *new_type; class_dict = PyDict_New (); if (class_dict == NULL) return NULL; new_type_args = Py_BuildValue ("s(OO)O", name, error, other, class_dict); Py_DECREF (class_dict); if (new_type_args == NULL) return NULL; new_type = PyType_Type.tp_new (&PyType_Type, new_type_args, NULL); return new_type; } pycairo-1.16.2/cairo/font.c000066400000000000000000000712141323762421700154720ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2003 James Henstridge, Steven Chaplin * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "private.h" /* class cairo.FontFace --------------------------------------------------- */ PyObject * PycairoFontFace_FromFontFace (cairo_font_face_t *font_face) { PyTypeObject *type = NULL; PyObject *o; assert (font_face != NULL); if (Pycairo_Check_Status (cairo_font_face_status (font_face))) { cairo_font_face_destroy (font_face); return NULL; } switch (cairo_font_face_get_type (font_face)) { case CAIRO_FONT_TYPE_TOY: type = &PycairoToyFontFace_Type; break; default: type = &PycairoFontFace_Type; break; } o = type->tp_alloc (type, 0); if (o == NULL) cairo_font_face_destroy (font_face); else ((PycairoFontFace *)o)->font_face = font_face; return o; } static void font_face_dealloc (PycairoFontFace *o) { if (o->font_face) { cairo_font_face_destroy (o->font_face); o->font_face = NULL; } Py_TYPE(o)->tp_free(o); } static PyObject * font_face_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { PyErr_SetString (PyExc_TypeError, "The FontFace type cannot be " "instantiated directly, use Context.get_font_face()"); return NULL; } /* static PyMethodDef font_face_methods[] = { * methods never exposed in a language binding: * cairo_font_face_destroy() * cairo_font_face_get_user_data() * cairo_font_face_get_type() * cairo_font_face_reference() * cairo_font_face_set_user_data(), {NULL, NULL, 0, NULL}, }; */ static PyObject* font_face_richcompare (PyObject *self, PyObject *other, int op) { if (Py_TYPE(self) == Py_TYPE(other)) return Pycairo_richcompare ( ((PycairoFontFace *)self)->font_face, ((PycairoFontFace *)other)->font_face, op); else { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } } static PYCAIRO_Py_hash_t font_face_hash (PyObject *self) { return PYCAIRO_Py_hash_t_FromVoidPtr (((PycairoFontFace *)self)->font_face); } PyTypeObject PycairoFontFace_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.FontFace", /* tp_name */ sizeof(PycairoFontFace), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)font_face_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ font_face_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ font_face_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)font_face_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; /* class cairo.ToyFontFace ------------------------------------------------- */ static PyObject * toy_font_face_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { const char *utf8; PyObject *o; cairo_font_slant_t slant; cairo_font_weight_t weight; int slant_arg = CAIRO_FONT_SLANT_NORMAL; int weight_arg = CAIRO_FONT_WEIGHT_NORMAL; if (!PyArg_ParseTuple (args, PYCAIRO_ENC_TEXT_FORMAT "|ii:ToyFontFace.__new__", "utf-8", &utf8, &slant_arg, &weight_arg)) return NULL; slant = (cairo_font_slant_t)slant_arg; weight = (cairo_font_weight_t)weight_arg; o = PycairoFontFace_FromFontFace ( cairo_toy_font_face_create (utf8, slant, weight)); PyMem_Free((void *)utf8); return o; } static PyObject * toy_font_get_family (PycairoToyFontFace *o) { return PYCAIRO_PyUnicode_FromString (cairo_toy_font_face_get_family (o->font_face)); } static PyObject * toy_font_get_slant (PycairoToyFontFace *o) { RETURN_INT_ENUM (FontSlant, cairo_toy_font_face_get_slant (o->font_face)); } static PyObject * toy_font_get_weight (PycairoToyFontFace *o) { RETURN_INT_ENUM (FontWeight, cairo_toy_font_face_get_weight (o->font_face)); } static PyMethodDef toy_font_face_methods[] = { {"get_family", (PyCFunction)toy_font_get_family, METH_NOARGS}, {"get_slant", (PyCFunction)toy_font_get_slant, METH_NOARGS}, {"get_weight", (PyCFunction)toy_font_get_weight, METH_NOARGS}, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoToyFontFace_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.ToyFontFace", /* tp_name */ sizeof(PycairoToyFontFace), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ toy_font_face_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoFontFace_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)toy_font_face_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; /* class cairo.ScaledFont ------------------------------------------------- */ PyObject * PycairoScaledFont_FromScaledFont (cairo_scaled_font_t *scaled_font) { PyObject *o; assert (scaled_font != NULL); if (Pycairo_Check_Status (cairo_scaled_font_status (scaled_font))) { cairo_scaled_font_destroy (scaled_font); return NULL; } o = PycairoScaledFont_Type.tp_alloc (&PycairoScaledFont_Type, 0); if (o == NULL) cairo_scaled_font_destroy (scaled_font); else ((PycairoScaledFont *)o)->scaled_font = scaled_font; return o; } static void scaled_font_dealloc(PycairoScaledFont *o) { if (o->scaled_font) { cairo_scaled_font_destroy (o->scaled_font); o->scaled_font = NULL; } Py_TYPE(o)->tp_free(o); } static PyObject * scaled_font_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { PycairoFontFace *ff; PycairoFontOptions *fo; PycairoMatrix *mx1, *mx2; if (!PyArg_ParseTuple(args, "O!O!O!O!:ScaledFont.__new__", &PycairoFontFace_Type, &ff, &PycairoMatrix_Type, &mx1, &PycairoMatrix_Type, &mx2, &PycairoFontOptions_Type, &fo)) return NULL; return PycairoScaledFont_FromScaledFont ( cairo_scaled_font_create (ff->font_face, &mx1->matrix, &mx2->matrix, fo->font_options)); } static PyObject * scaled_font_extents (PycairoScaledFont *o) { cairo_font_extents_t e; cairo_scaled_font_extents (o->scaled_font, &e); RETURN_NULL_IF_CAIRO_SCALED_FONT_ERROR(o->scaled_font); return Py_BuildValue ("(ddddd)", e.ascent, e.descent, e.height, e.max_x_advance, e.max_y_advance); } static PyObject * scaled_font_get_font_face (PycairoScaledFont *o) { return PycairoFontFace_FromFontFace ( cairo_font_face_reference ( cairo_scaled_font_get_font_face (o->scaled_font))); } static PyObject * scaled_font_get_scale_matrix (PycairoScaledFont *o) { cairo_matrix_t matrix; cairo_scaled_font_get_scale_matrix (o->scaled_font, &matrix); return PycairoMatrix_FromMatrix (&matrix); } static PyObject * scaled_font_text_extents (PycairoScaledFont *o, PyObject *args) { cairo_text_extents_t extents; const char *utf8; PyObject *ext_args, *res; if (!PyArg_ParseTuple (args, PYCAIRO_ENC_TEXT_FORMAT ":ScaledFont.text_extents", "utf-8", &utf8)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_scaled_font_text_extents (o->scaled_font, utf8, &extents); Py_END_ALLOW_THREADS; PyMem_Free ((void *)utf8); RETURN_NULL_IF_CAIRO_SCALED_FONT_ERROR (o->scaled_font); ext_args = Py_BuildValue ("(dddddd)", extents.x_bearing, extents.y_bearing, extents.width, extents.height, extents.x_advance, extents.y_advance); res = PyObject_Call ((PyObject *)&PycairoTextExtents_Type, ext_args, NULL); Py_DECREF (ext_args); return res; } static PyObject * scaled_font_get_ctm (PycairoScaledFont *o) { cairo_matrix_t matrix; Py_BEGIN_ALLOW_THREADS; cairo_scaled_font_get_ctm (o->scaled_font, &matrix); Py_END_ALLOW_THREADS; return PycairoMatrix_FromMatrix (&matrix); } static PyObject * scaled_font_get_font_matrix (PycairoScaledFont *o) { cairo_matrix_t matrix; Py_BEGIN_ALLOW_THREADS; cairo_scaled_font_get_font_matrix (o->scaled_font, &matrix); Py_END_ALLOW_THREADS; return PycairoMatrix_FromMatrix (&matrix); } static PyObject * scaled_font_get_font_options (PycairoScaledFont *o) { cairo_font_options_t *options = cairo_font_options_create(); Py_BEGIN_ALLOW_THREADS; cairo_scaled_font_get_font_options (o->scaled_font, options); Py_END_ALLOW_THREADS; return PycairoFontOptions_FromFontOptions (options); } static PyObject * scaled_font_text_to_glyphs (PycairoScaledFont *o, PyObject *args) { const char *utf8; double x, y; int with_clusters = 1; cairo_status_t status; cairo_glyph_t *glyphs = NULL; int num_glyphs; cairo_text_cluster_t *clusters = NULL; int num_clusters; cairo_text_cluster_flags_t cluster_flags; int i; PyObject *glyph_list = NULL; PyObject *cluster_list = NULL; PyObject *flags = NULL; PyObject *pyglyph, *glyph_args; PyObject *pycluster, *cluster_args; if (!PyArg_ParseTuple (args, "dd" PYCAIRO_ENC_TEXT_FORMAT "|i:ScaledFont.text_to_glyphs", &x, &y, "utf-8", &utf8, &with_clusters)) return NULL; Py_BEGIN_ALLOW_THREADS; status = cairo_scaled_font_text_to_glyphs ( o->scaled_font, x, y, utf8, -1, &glyphs, &num_glyphs, (with_clusters) ? &clusters : NULL, (with_clusters) ? &num_clusters : NULL, (with_clusters) ? &cluster_flags : NULL); Py_END_ALLOW_THREADS; PyMem_Free ((void *)utf8); RETURN_NULL_IF_CAIRO_ERROR (status); glyph_list = PyList_New (num_glyphs); if (glyph_list == NULL) goto error; for(i=0; i < num_glyphs; i++) { cairo_glyph_t *glyph = &glyphs[i]; glyph_args = Py_BuildValue( "(kdd)", glyph->index, glyph->x, glyph->y); if (glyph_args == NULL) goto error; pyglyph = PyObject_Call( (PyObject *)&PycairoGlyph_Type, glyph_args, NULL); if (pyglyph == NULL) { Py_DECREF (glyph_args); goto error; } PyList_SET_ITEM (glyph_list, i, pyglyph); } cairo_glyph_free (glyphs); glyphs = NULL; if (with_clusters) { cluster_list = PyList_New (num_clusters); if (cluster_list == NULL) goto error; for(i=0; i < num_clusters; i++) { cairo_text_cluster_t *cluster = &clusters[i]; cluster_args = Py_BuildValue( "(ii)", cluster->num_bytes, cluster->num_glyphs); if (cluster_args == NULL) goto error; pycluster = PyObject_Call( (PyObject *)&PycairoTextCluster_Type, cluster_args, NULL); if (pycluster == NULL) { Py_DECREF (cluster_args); goto error; } PyList_SET_ITEM (cluster_list, i, pycluster); } cairo_text_cluster_free (clusters); clusters = NULL; flags = CREATE_INT_ENUM (TextClusterFlags, cluster_flags); if (flags == NULL) goto error; return Py_BuildValue ("(NNN)", glyph_list, cluster_list, flags); } else { return glyph_list; } error: cairo_glyph_free (glyphs); cairo_text_cluster_free (clusters); Py_XDECREF (glyph_list); Py_XDECREF (cluster_list); Py_XDECREF (flags); return NULL; } static PyObject * scaled_font_glyph_extents (PycairoScaledFont *o, PyObject *args) { int num_glyphs = -1; cairo_glyph_t *glyphs; cairo_text_extents_t extents; PyObject *py_object, *ext_args, *res; if (!PyArg_ParseTuple (args, "O|i:ScaledFont.glyph_extents", &py_object, &num_glyphs)) return NULL; glyphs = _PycairoGlyphs_AsGlyphs (py_object, &num_glyphs); if (glyphs == NULL) return NULL; Py_BEGIN_ALLOW_THREADS cairo_scaled_font_glyph_extents ( o->scaled_font, glyphs, num_glyphs, &extents); Py_END_ALLOW_THREADS; PyMem_Free (glyphs); RETURN_NULL_IF_CAIRO_SCALED_FONT_ERROR (o->scaled_font); ext_args = Py_BuildValue ("(dddddd)", extents.x_bearing, extents.y_bearing, extents.width, extents.height, extents.x_advance, extents.y_advance); res = PyObject_Call ((PyObject *)&PycairoTextExtents_Type, ext_args, NULL); Py_DECREF (ext_args); return res; } static PyMethodDef scaled_font_methods[] = { /* methods never exposed in a language binding: * cairo_scaled_font_destroy() * cairo_scaled_font_get_type() * cairo_scaled_font_reference() */ {"extents", (PyCFunction)scaled_font_extents, METH_NOARGS}, {"get_font_face", (PyCFunction)scaled_font_get_font_face, METH_NOARGS}, {"get_ctm", (PyCFunction)scaled_font_get_ctm, METH_NOARGS}, {"get_font_matrix", (PyCFunction)scaled_font_get_font_matrix, METH_NOARGS}, {"get_font_options", (PyCFunction)scaled_font_get_font_options, METH_NOARGS}, {"get_scale_matrix", (PyCFunction)scaled_font_get_scale_matrix, METH_VARARGS}, {"text_extents", (PyCFunction)scaled_font_text_extents, METH_VARARGS}, {"text_to_glyphs", (PyCFunction)scaled_font_text_to_glyphs, METH_VARARGS}, {"glyph_extents", (PyCFunction)scaled_font_glyph_extents, METH_VARARGS}, {NULL, NULL, 0, NULL}, }; static PyObject* scaled_font_richcompare (PyObject *self, PyObject *other, int op) { if (Py_TYPE(self) == Py_TYPE(other)) return Pycairo_richcompare ( ((PycairoScaledFont *)self)->scaled_font, ((PycairoScaledFont *)other)->scaled_font, op); else { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } } static PYCAIRO_Py_hash_t scaled_font_hash (PyObject *self) { return PYCAIRO_Py_hash_t_FromVoidPtr ( ((PycairoScaledFont *)self)->scaled_font); } PyTypeObject PycairoScaledFont_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.ScaledFont", /* tp_name */ sizeof(PycairoScaledFont), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)scaled_font_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ scaled_font_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ scaled_font_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ scaled_font_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)scaled_font_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; /* class cairo.FontOptions ------------------------------------------------ */ PyObject * PycairoFontOptions_FromFontOptions (cairo_font_options_t *font_options) { PyObject *o; assert (font_options != NULL); if (Pycairo_Check_Status (cairo_font_options_status (font_options))) { cairo_font_options_destroy (font_options); return NULL; } o = PycairoFontOptions_Type.tp_alloc (&PycairoFontOptions_Type, 0); if (o == NULL) cairo_font_options_destroy (font_options); else ((PycairoFontOptions *)o)->font_options = font_options; return o; } static void font_options_dealloc(PycairoFontOptions *o) { if (o->font_options) { cairo_font_options_destroy (o->font_options); o->font_options = NULL; } Py_TYPE(o)->tp_free(o); } static PyObject * font_options_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { if (!PyArg_ParseTuple (args, ":FontOptions.__new__")) return NULL; return PycairoFontOptions_FromFontOptions (cairo_font_options_create()); } static PyObject * font_options_get_antialias (PycairoFontOptions *o) { RETURN_INT_ENUM (Antialias, cairo_font_options_get_antialias (o->font_options)); } static PyObject * font_options_get_hint_metrics (PycairoFontOptions *o) { RETURN_INT_ENUM (HintMetrics, cairo_font_options_get_hint_metrics (o->font_options)); } static PyObject * font_options_get_hint_style (PycairoFontOptions *o) { RETURN_INT_ENUM (HintStyle, cairo_font_options_get_hint_style (o->font_options)); } static PyObject * font_options_get_subpixel_order (PycairoFontOptions *o) { RETURN_INT_ENUM (SubpixelOrder, cairo_font_options_get_subpixel_order (o->font_options)); } static PyObject * font_options_set_antialias (PycairoFontOptions *o, PyObject *args) { cairo_antialias_t antialias; int antialias_arg = CAIRO_ANTIALIAS_DEFAULT; if (!PyArg_ParseTuple (args, "|i:FontOptions.set_antialias", &antialias_arg)) return NULL; antialias = (cairo_antialias_t)antialias_arg; cairo_font_options_set_antialias (o->font_options, antialias); RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options); Py_RETURN_NONE; } static PyObject * font_options_set_hint_metrics (PycairoFontOptions *o, PyObject *args) { cairo_hint_metrics_t hint_metrics; int hint_metrics_arg = CAIRO_HINT_METRICS_DEFAULT; if (!PyArg_ParseTuple (args, "|i:FontOptions.set_hint_metrics", &hint_metrics_arg)) return NULL; hint_metrics = (cairo_hint_metrics_t)hint_metrics_arg; cairo_font_options_set_hint_metrics (o->font_options, hint_metrics); RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options); Py_RETURN_NONE; } static PyObject * font_options_set_hint_style (PycairoFontOptions *o, PyObject *args) { cairo_hint_style_t hint_style; int hint_style_arg = CAIRO_HINT_STYLE_DEFAULT; if (!PyArg_ParseTuple (args, "|i:FontOptions.set_hint_style", &hint_style_arg)) return NULL; hint_style = (cairo_hint_style_t)hint_style_arg; cairo_font_options_set_hint_style (o->font_options, hint_style); RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options); Py_RETURN_NONE; } static PyObject * font_options_set_subpixel_order (PycairoFontOptions *o, PyObject *args) { cairo_subpixel_order_t subpixel_order; int subpixel_order_arg = CAIRO_SUBPIXEL_ORDER_DEFAULT; if (!PyArg_ParseTuple (args, "|i:FontOptions.set_subpixel_order", &subpixel_order_arg)) return NULL; subpixel_order = (cairo_subpixel_order_t)subpixel_order_arg; cairo_font_options_set_subpixel_order (o->font_options, subpixel_order); RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options); Py_RETURN_NONE; } static PyObject * font_options_copy (PycairoFontOptions *o) { cairo_font_options_t *new; Py_BEGIN_ALLOW_THREADS; new = cairo_font_options_copy (o->font_options); Py_END_ALLOW_THREADS; return PycairoFontOptions_FromFontOptions (new); } static PyObject * font_options_hash (PycairoFontOptions *o) { unsigned long hash; Py_BEGIN_ALLOW_THREADS; hash = cairo_font_options_hash (o->font_options); Py_END_ALLOW_THREADS; return PyLong_FromUnsignedLong (hash); } static PyObject * font_options_equal (PycairoFontOptions *o, PyObject *args) { PycairoFontOptions *other; cairo_bool_t result; if (!PyArg_ParseTuple(args, "O!:FontOptions.equal", &PycairoFontOptions_Type, &other)) return NULL; Py_BEGIN_ALLOW_THREADS; result = cairo_font_options_equal (o->font_options, other->font_options); Py_END_ALLOW_THREADS; return PyBool_FromLong(result); } static PyObject * font_options_merge (PycairoFontOptions *o, PyObject *args) { PycairoFontOptions *other; if (!PyArg_ParseTuple(args, "O!:FontOptions.merge", &PycairoFontOptions_Type, &other)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_font_options_merge (o->font_options, other->font_options); Py_END_ALLOW_THREADS; Py_RETURN_NONE; } static PyMethodDef font_options_methods[] = { /* methods never exposed in a language binding: * cairo_font_options_destroy() * cairo_font_options_reference() */ {"get_antialias", (PyCFunction)font_options_get_antialias, METH_NOARGS}, {"get_hint_metrics", (PyCFunction)font_options_get_hint_metrics, METH_NOARGS}, {"get_hint_style", (PyCFunction)font_options_get_hint_style, METH_NOARGS}, {"get_subpixel_order",(PyCFunction)font_options_get_subpixel_order, METH_NOARGS}, {"set_antialias", (PyCFunction)font_options_set_antialias, METH_VARARGS}, {"set_hint_metrics", (PyCFunction)font_options_set_hint_metrics, METH_VARARGS}, {"set_hint_style", (PyCFunction)font_options_set_hint_style, METH_VARARGS}, {"set_subpixel_order",(PyCFunction)font_options_set_subpixel_order, METH_VARARGS}, {"copy", (PyCFunction)font_options_copy, METH_NOARGS}, {"hash", (PyCFunction)font_options_hash, METH_NOARGS}, {"equal", (PyCFunction)font_options_equal, METH_VARARGS}, {"merge", (PyCFunction)font_options_merge, METH_VARARGS}, {NULL, NULL, 0, NULL}, }; static PyObject * font_options_tp_richcompare (PyObject *a, PyObject *b, int op) { PycairoFontOptions *other; cairo_bool_t is_equal; if (!PyObject_TypeCheck (b, &PycairoFontOptions_Type) || (op != Py_EQ && op != Py_NE)) { Py_INCREF (Py_NotImplemented); return Py_NotImplemented; } other = (PycairoFontOptions *)b; Py_BEGIN_ALLOW_THREADS; is_equal = cairo_font_options_equal (((PycairoFontOptions *)a)->font_options, other->font_options); Py_END_ALLOW_THREADS; if (is_equal == (op == Py_EQ)) Py_RETURN_TRUE; else Py_RETURN_FALSE; } PyTypeObject PycairoFontOptions_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.FontOptions", /* tp_name */ sizeof(PycairoFontOptions), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)font_options_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)PyObject_HashNotImplemented,/* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ font_options_tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ font_options_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)font_options_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; pycairo-1.16.2/cairo/glyph.c000066400000000000000000000165101323762421700156450ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2017 Christoph Reiter * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "private.h" /* read a Python sequence of (i,x,y) sequences * return cairo_glyph_t * * num_glyphs * must call PyMem_Free(glyphs) when finished using the glyphs */ cairo_glyph_t * _PycairoGlyphs_AsGlyphs (PyObject *py_object, int *num_glyphs) { Py_ssize_t length, i; cairo_glyph_t *glyphs = NULL, *glyph; PyObject *py_glyphs, *py_seq = NULL; py_glyphs = PySequence_Fast (py_object, "glyphs must be a sequence"); if (py_glyphs == NULL) return NULL; length = PySequence_Fast_GET_SIZE (py_glyphs); if (length > INT_MAX) { Py_DECREF (py_glyphs); PyErr_SetString (PyExc_ValueError, "sequence too large"); return NULL; } if (*num_glyphs < 0 || *num_glyphs > length) *num_glyphs = (int)length; glyphs = PyMem_Malloc ((unsigned int)*num_glyphs * sizeof(cairo_glyph_t)); if (glyphs == NULL) { PyErr_NoMemory(); goto error; } for (i = 0, glyph = glyphs; i < *num_glyphs; i++, glyph++) { long index; PyObject *py_item = PySequence_Fast_GET_ITEM (py_glyphs, i); py_seq = PySequence_Fast (py_item, "glyph items must be a sequence"); if (py_seq == NULL) goto error; if (PySequence_Fast_GET_SIZE (py_seq) != 3) { PyErr_SetString (PyExc_ValueError, "each glyph item must be an (i,x,y) sequence"); goto error; } index = PYCAIRO_PyLong_AsLong (PySequence_Fast_GET_ITEM (py_seq, 0)); if (PyErr_Occurred ()) goto error; glyph->index = (unsigned long)index; glyph->x = PyFloat_AsDouble (PySequence_Fast_GET_ITEM (py_seq, 1)); glyph->y = PyFloat_AsDouble (PySequence_Fast_GET_ITEM (py_seq, 2)); if (PyErr_Occurred()) goto error; Py_DECREF (py_seq); } Py_DECREF (py_glyphs); return glyphs; error: Py_DECREF (py_glyphs); Py_XDECREF (py_seq); PyMem_Free (glyphs); return NULL; } /* 0 on success */ int _PyGlyph_AsGlyph (PyObject *pyobj, cairo_glyph_t *glyph) { long index; if (!PyObject_TypeCheck (pyobj, &PycairoGlyph_Type)) { PyErr_SetString (PyExc_TypeError, "item must be of type cairo.Glyph"); return -1; } index = PYCAIRO_PyLong_AsLong (PySequence_Fast_GET_ITEM (pyobj, 0)); if (PyErr_Occurred ()) return -1; if (index < 0) { PyErr_SetString (PyExc_ValueError, "negative index"); return -1; } glyph->index = (unsigned long) index; glyph->x = PyFloat_AsDouble (PySequence_Fast_GET_ITEM (pyobj, 1)); glyph->y = PyFloat_AsDouble (PySequence_Fast_GET_ITEM (pyobj, 2)); return 0; } static char *KWDS[] = {"index", "x", "y", NULL}; static PyObject * glyph_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { double x, y; unsigned long index; PyObject *pyindex, *tuple_args, *result; if (!PyArg_ParseTupleAndKeywords (args, kwds, "Odd:Glyph.__new__", KWDS, &pyindex, &x, &y)) return NULL; if (_conv_pyobject_to_ulong (pyindex, &index) < 0) return NULL; tuple_args = Py_BuildValue ("((kdd))", index, x, y); if (tuple_args == NULL) return NULL; result = PyTuple_Type.tp_new (type, tuple_args, NULL); Py_DECREF (tuple_args); return result; } static PyObject* glyph_repr(PyObject *self) { PyObject *format, *result; format = PYCAIRO_PyUnicode_FromString ( "cairo.Glyph(index=%r, x=%r, y=%r)"); if (format == NULL) return NULL; result = PYCAIRO_PyUnicode_Format (format, self); Py_DECREF (format); return result; } static PyObject* glyph_getattro (PyObject *self, PyObject *name) { return Pycairo_tuple_getattro (self, KWDS, name); } PyTypeObject PycairoGlyph_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.Glyph", /* tp_name */ sizeof(PycairGlyph), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)glyph_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ glyph_getattro, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)glyph_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; pycairo-1.16.2/cairo/matrix.c000066400000000000000000000301751323762421700160310ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2003 James Henstridge, Steven Chaplin * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "structmember.h" #include "private.h" PyObject * PycairoMatrix_FromMatrix (const cairo_matrix_t *matrix) { PyObject *o; assert (matrix != NULL); o = PycairoMatrix_Type.tp_alloc (&PycairoMatrix_Type, 0); if (o != NULL) ((PycairoMatrix *)o)->matrix = *matrix; /* copy struct */ return o; } static void matrix_dealloc (PycairoMatrix *o) { Py_TYPE(o)->tp_free(o); } static PyObject * matrix_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { cairo_matrix_t mx; static char *kwlist[] = { "xx", "yx", "xy", "yy", "x0", "y0", NULL }; double xx = 1.0, yx = 0.0, xy = 0.0, yy = 1.0, x0 = 0.0, y0 = 0.0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|dddddd:Matrix.__init__", kwlist, &xx, &yx, &xy, &yy, &x0, &y0)) return NULL; cairo_matrix_init (&mx, xx, yx, xy, yy, x0, y0); return PycairoMatrix_FromMatrix (&mx); } static PyObject * matrix_init_rotate (PyTypeObject *type, PyObject *args) { cairo_matrix_t matrix; double radians; if (!PyArg_ParseTuple(args, "d:Matrix.init_rotate", &radians)) return NULL; cairo_matrix_init_rotate (&matrix, radians); return PycairoMatrix_FromMatrix (&matrix); } static PyObject * matrix_invert (PycairoMatrix *o) { if (Pycairo_Check_Status (cairo_matrix_invert (&o->matrix))) return NULL; Py_RETURN_NONE; } /* cairo_matrix_multiply */ static PyObject * matrix_multiply (PycairoMatrix *o, PyObject *args) { PycairoMatrix *mx2; cairo_matrix_t result; if (!PyArg_ParseTuple(args, "O!:Matrix.multiply", &PycairoMatrix_Type, &mx2)) return NULL; cairo_matrix_multiply (&result, &o->matrix, &mx2->matrix); return PycairoMatrix_FromMatrix (&result); } /* standard matrix multiply, for use by '*' operator */ static PyObject * matrix_operator_multiply (PycairoMatrix *o, PycairoMatrix *o2) { cairo_matrix_t result; if (PyObject_IsInstance((PyObject *)o2, (PyObject *)&PycairoMatrix_Type) <= 0) { PyErr_SetString(PyExc_TypeError, "matrix can only multiply another matrix"); return NULL; } cairo_matrix_multiply (&result, &o->matrix, &o2->matrix); return PycairoMatrix_FromMatrix (&result); } static PyObject * matrix_repr (PycairoMatrix *o) { char buf[256]; PyOS_snprintf(buf, sizeof(buf), "cairo.Matrix(%g, %g, %g, %g, %g, %g)", o->matrix.xx, o->matrix.yx, o->matrix.xy, o->matrix.yy, o->matrix.x0, o->matrix.y0); return PYCAIRO_PyUnicode_FromString(buf); } static PyObject * matrix_richcmp (PycairoMatrix *m1, PycairoMatrix *m2, int op) { int equal; PyObject *ret; cairo_matrix_t *mx1 = &m1->matrix; cairo_matrix_t *mx2 = &m2->matrix; if (op != Py_EQ && op != Py_NE) { PyErr_SetString(PyExc_TypeError, "Only support testing for == or !="); return NULL; } if (!PyObject_TypeCheck(m2, &PycairoMatrix_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } equal = mx1->xx == mx2->xx && mx1->yx == mx2->yx && mx1->xy == mx2->xy && mx1->yy == mx2->yy && mx1->x0 == mx2->x0 && mx1->y0 == mx2->y0; if (op == Py_EQ) ret = equal ? Py_True : Py_False; else ret = equal ? Py_False : Py_True; Py_INCREF(ret); return ret; } static PyObject * matrix_rotate (PycairoMatrix *o, PyObject *args) { double radians; if (!PyArg_ParseTuple(args, "d:Matrix.rotate", &radians)) return NULL; cairo_matrix_rotate (&o->matrix, radians); Py_RETURN_NONE; } static PyObject * matrix_scale (PycairoMatrix *o, PyObject *args) { double sx, sy; if (!PyArg_ParseTuple(args, "dd:Matrix.scale", &sx, &sy)) return NULL; cairo_matrix_scale (&o->matrix, sx, sy); Py_RETURN_NONE; } static PyObject * matrix_transform_distance (PycairoMatrix *o, PyObject *args) { double dx, dy; if (!PyArg_ParseTuple(args, "dd:Matrix.transform_distance", &dx, &dy)) return NULL; cairo_matrix_transform_distance (&o->matrix, &dx, &dy); return Py_BuildValue("(dd)", dx, dy); } static PyObject * matrix_transform_point (PycairoMatrix *o, PyObject *args) { double x, y; if (!PyArg_ParseTuple(args, "dd:Matrix.transform_point", &x, &y)) return NULL; cairo_matrix_transform_point (&o->matrix, &x, &y); return Py_BuildValue("(dd)", x, y); } static PyObject * matrix_translate (PycairoMatrix *o, PyObject *args) { double tx, ty; if (!PyArg_ParseTuple(args, "dd:Matrix.translate", &tx, &ty)) return NULL; cairo_matrix_translate (&o->matrix, tx, ty); Py_RETURN_NONE; } static PyObject * matrix_item (PycairoMatrix *o, Py_ssize_t i) { switch (i) { case 0: return Py_BuildValue("d", o->matrix.xx); case 1: return Py_BuildValue("d", o->matrix.yx); case 2: return Py_BuildValue("d", o->matrix.xy); case 3: return Py_BuildValue("d", o->matrix.yy); case 4: return Py_BuildValue("d", o->matrix.x0); case 5: return Py_BuildValue("d", o->matrix.y0); default: PyErr_SetString(PyExc_IndexError, "Matrix index out of range"); return NULL; } } static PyNumberMethods matrix_as_number = { (binaryfunc)0, /*nb_add*/ (binaryfunc)0, /*nb_subtract*/ (binaryfunc)matrix_operator_multiply, /*nb_multiply*/ #if PY_MAJOR_VERSION < 3 (binaryfunc)0, /*nb_divide*/ #endif (binaryfunc)0, /*nb_remainder*/ (binaryfunc)0, /*nb_divmod*/ (ternaryfunc)0, /*nb_power*/ (unaryfunc)0, /*nb_negative*/ (unaryfunc)0, /*nb_positive*/ (unaryfunc)0, /*nb_absolute*/ (inquiry)0, /*py2:nb_nonzero/py3:nb_bool*/ (unaryfunc)0, /*nb_invert*/ (binaryfunc)0, /*nb_lshift*/ (binaryfunc)0, /*nb_rshift*/ (binaryfunc)0, /*nb_and*/ (binaryfunc)0, /*nb_xor*/ (binaryfunc)0, /*nb_or*/ #if PY_MAJOR_VERSION < 3 (coercion)0, /*nb_coerce*/ #endif (unaryfunc)0, /*nb_int*/ 0, /*py2:nb_long/py3:nb_reserved*/ (unaryfunc)0, /*nb_float*/ #if PY_MAJOR_VERSION < 3 (unaryfunc)0, /*nb_oct*/ (unaryfunc)0, /*nb_hex*/ #endif 0, /*nb_inplace_add*/ 0, /*nb_inplace_subtract*/ 0, /*nb_inplace_multiply*/ #if PY_MAJOR_VERSION < 3 0, /*nb_inplace_divide*/ #endif 0, /*nb_inplace_remainder*/ 0, /*nb_inplace_power*/ 0, /*nb_inplace_lshift*/ 0, /*nb_inplace_rshift*/ 0, /*nb_inplace_and*/ 0, /*nb_inplace_xor*/ 0, /*nb_inplace_or*/ (binaryfunc)0, /* nb_floor_divide */ 0, /* nb_true_divide */ 0, /* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ (unaryfunc)0, /* nb_index */ }; static PySequenceMethods matrix_as_sequence = { 0, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ (ssizeargfunc)matrix_item, /* sq_item */ 0, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ 0, /* sq_contains */ }; static PyMethodDef matrix_methods[] = { /* Do not need to wrap all cairo_matrix_init_*() functions * C API Matrix constructors Python equivalents * cairo_matrix_init() cairo.Matrix(xx,yx,xy,yy,x0,y0) * cairo_matrix_init_rotate() cairo.Matrix.init_rotate(radians) * cairo_matrix_init_identity() cairo.Matrix() * cairo_matrix_init_translate() cairo.Matrix(x0=x0,y0=y0) * cairo_matrix_init_scale() cairo.Matrix(xx=xx,yy=yy) */ {"init_rotate", (PyCFunction)matrix_init_rotate, METH_VARARGS | METH_CLASS }, {"invert", (PyCFunction)matrix_invert, METH_NOARGS }, {"multiply", (PyCFunction)matrix_multiply, METH_VARARGS }, {"rotate", (PyCFunction)matrix_rotate, METH_VARARGS }, {"scale", (PyCFunction)matrix_scale, METH_VARARGS }, {"transform_distance",(PyCFunction)matrix_transform_distance, METH_VARARGS }, {"transform_point", (PyCFunction)matrix_transform_point, METH_VARARGS }, {"translate", (PyCFunction)matrix_translate, METH_VARARGS }, {NULL, NULL, 0, NULL}, }; static PyMemberDef matrix_tp_members[] = { {"xx", T_DOUBLE, sizeof(PyObject) + sizeof(double) * 0, 0, "xx component of the affine transformation"}, {"yx", T_DOUBLE, sizeof(PyObject) + sizeof(double) * 1, 0, "yx component of the affine transformation"}, {"xy", T_DOUBLE, sizeof(PyObject) + sizeof(double) * 2, 0, "xy component of the affine transformation"}, {"yy", T_DOUBLE, sizeof(PyObject) + sizeof(double) * 3, 0, "yy component of the affine transformation"}, {"x0", T_DOUBLE, sizeof(PyObject) + sizeof(double) * 4, 0, "X translation component of the affine transformation"}, {"y0", T_DOUBLE, sizeof(PyObject) + sizeof(double) * 5, 0, "Y translation component of the affine transformation"}, {NULL} }; PyTypeObject PycairoMatrix_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.Matrix", /* tp_name */ sizeof(PycairoMatrix), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)matrix_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)matrix_repr, /* tp_repr */ &matrix_as_number, /* tp_as_number */ &matrix_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ #if PY_MAJOR_VERSION < 3 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ #else Py_TPFLAGS_DEFAULT, /* tp_flags */ #endif NULL, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)matrix_richcmp, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ matrix_methods, /* tp_methods */ matrix_tp_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)matrix_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; pycairo-1.16.2/cairo/misc.c000066400000000000000000000212611323762421700154540ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2017 Christoph Reiter * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "private.h" /* Returns 1 if the object has the correct file type for a filesystem path. * Parsing it with Pycairo_fspath_converter() might still fail. */ int Pycairo_is_fspath (PyObject *obj) { #if PY_MAJOR_VERSION < 3 return (PyString_Check (obj) || PyUnicode_Check (obj)); #elif PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 6 PyObject *real = PyOS_FSPath (obj); if (real == NULL) { PyErr_Clear (); return 0; } else { Py_DECREF (real); return 1; } #else return (PyBytes_Check (obj) || PyUnicode_Check (obj)); #endif } /* Converts a Python object to a cairo path. The result needs to be freed with * PyMem_Free(). */ int Pycairo_fspath_converter (PyObject *obj, char** result) { char *internal, *buf; PyObject *bytes; #if defined(MS_WINDOWS) && PY_MAJOR_VERSION < 3 PyObject *uni, *other; if (PyString_Check (obj)) { uni = PyString_AsDecodedObject ( obj, Py_FileSystemDefaultEncoding, "strict"); if (uni == NULL) return 0; } else if (PyUnicode_Check (obj)) { uni = obj; Py_INCREF (uni); } else { PyErr_SetString (PyExc_TypeError, "paths must be str/unicode"); return 0; } if (cairo_version() >= CAIRO_VERSION_ENCODE(1, 15, 10)) { bytes = PyUnicode_AsEncodedString (uni, "utf-8", "strict"); Py_DECREF (uni); if (bytes == NULL) { return 0; } if (PyString_AsStringAndSize (bytes, &internal, NULL) == -1) { Py_DECREF (bytes); return 0; } } else { bytes = PyUnicode_AsMBCSString (uni); if (bytes == NULL) { Py_DECREF (uni); return 0; } if (PyString_AsStringAndSize (bytes, &internal, NULL) == -1) { Py_DECREF (uni); Py_DECREF (bytes); return 0; } /* PyUnicode_AsMBCSString doesn't do error handling, so we have to * decode and compare again */ other = PyUnicode_DecodeMBCS ( internal, PyString_Size (bytes), "strict"); if (other == NULL) { Py_DECREF (uni); Py_DECREF (bytes); return 0; } if (PyUnicode_Compare (uni, other) != 0) { Py_DECREF (uni); Py_DECREF (bytes); Py_DECREF (other); PyErr_SetString ( PyExc_ValueError, "only ANSI paths supported on Windows"); return 0; } Py_DECREF (other); Py_DECREF (uni); } #elif defined(MS_WINDOWS) && PY_MAJOR_VERSION >= 3 PyObject *uni; if (PyUnicode_FSDecoder (obj, &uni) == 0) return 0; if (cairo_version() >= CAIRO_VERSION_ENCODE(1, 15, 10)) { bytes = PyUnicode_AsEncodedString (uni, "utf-8", "strict"); } else { bytes = PyUnicode_AsMBCSString (uni); } Py_DECREF (uni); if (bytes == NULL) return 0; if (PyBytes_AsStringAndSize (bytes, &internal, NULL) == -1) { Py_DECREF (bytes); return 0; } #elif !defined(MS_WINDOWS) && PY_MAJOR_VERSION < 3 if (PyUnicode_Check (obj)) { bytes = PyUnicode_AsEncodedString ( obj, Py_FileSystemDefaultEncoding, "strict"); if (bytes == 0) return 0; } else if (PyString_Check (obj)) { bytes = obj; Py_INCREF (bytes); } else { PyErr_SetString (PyExc_TypeError, "paths must be str/unicode"); return 0; } if (PyString_AsStringAndSize (bytes, &internal, NULL) == -1) { Py_DECREF (bytes); return 0; } #elif !defined(MS_WINDOWS) && PY_MAJOR_VERSION >= 3 if (PyUnicode_FSConverter (obj, &bytes) == 0) return 0; if (PyBytes_AsStringAndSize (bytes, &internal, NULL) == -1) { Py_DECREF (bytes); return 0; } #else #error "unsupported" #endif buf = PyMem_Malloc (strlen (internal) + 1); if (buf == NULL) { Py_DECREF (bytes); PyErr_NoMemory (); return 0; } strcpy (buf, internal); Py_DECREF (bytes); *result = buf; return 1; } /* Verifies that the object has a callable write() method. * Gives a borrowed reference. */ int Pycairo_writer_converter (PyObject *obj, PyObject** file) { PyObject *attr; attr = PyObject_GetAttrString (obj, "write"); if (attr == NULL) return 0; if (!PyCallable_Check (attr)) { Py_DECREF (attr); PyErr_SetString ( PyExc_TypeError, "'write' attribute not callable"); return 0; } Py_DECREF (attr); *file = obj; return 1; } int Pycairo_reader_converter (PyObject *obj, PyObject** file) { PyObject *attr; attr = PyObject_GetAttrString (obj, "read"); if (attr == NULL) return 0; if (!PyCallable_Check (attr)) { Py_DECREF (attr); PyErr_SetString ( PyExc_TypeError, "'read' attribute not callable"); return 0; } Py_DECREF (attr); *file = obj; return 1; } int Pycairo_fspath_none_converter (PyObject *obj, char** result) { if (obj == Py_None) { *result = NULL; return 1; } return Pycairo_fspath_converter (obj, result); } PyObject* Pycairo_tuple_getattro (PyObject *self, char **kwds, PyObject *name) { PyObject *value, *item; int res; Py_ssize_t i; for (i = 0; kwds[i] != NULL; i++) { value = PYCAIRO_PyUnicode_FromString (kwds[i]); res = PyObject_RichCompareBool (name, value, Py_EQ); Py_DECREF (value); if (res == -1) { return NULL; } else if (res == 1) { item = PyTuple_GetItem (self, i); if (item == NULL) return NULL; Py_INCREF (item); return item; } } return PyTuple_Type.tp_getattro (self, name); } PyObject* Pycairo_richcompare (void* a, void *b, int op) { PyObject *res; switch (op) { case Py_EQ: res = (a == b) ? Py_True : Py_False; break; case Py_NE: res = (a != b) ? Py_True : Py_False; break; case Py_LT: res = (a < b) ? Py_True : Py_False; break; case Py_LE: res = (a <= b) ? Py_True : Py_False; break; case Py_GT: res = (a > b) ? Py_True : Py_False; break; case Py_GE: res = (a >= b) ? Py_True : Py_False; break; default: res = Py_NotImplemented; break; } Py_INCREF (res); return res; } /* NULL on error */ static PyObject * _conv_pyobject_to_pylong (PyObject *pyobj) { #if PY_MAJOR_VERSION < 3 if (PyInt_Check (pyobj)) { return PyNumber_Long (pyobj); } else if (!PyLong_Check (pyobj)) { PyErr_SetString (PyExc_TypeError, "not of type int or long"); return NULL; } Py_INCREF (pyobj); return pyobj; #else if (!PyLong_Check (pyobj)) { PyErr_SetString (PyExc_TypeError, "not of type int"); return NULL; } Py_INCREF (pyobj); return pyobj; #endif } /* -1 on error */ int _conv_pyobject_to_ulong (PyObject *pyobj, unsigned long *result) { unsigned long temp; PyObject *pylong; pylong = _conv_pyobject_to_pylong (pyobj); if (pylong == NULL) return -1; temp = PyLong_AsUnsignedLong (pylong); if (PyErr_Occurred ()) return -1; *result = temp; return 0; } pycairo-1.16.2/cairo/path.c000066400000000000000000000223211323762421700154530ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2005 Steve Chaplin * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "private.h" /* PycairoPath iterator object * modelled on Python-2.4/Objects/rangeobject.c and tupleobject.c */ PyObject * PycairoPath_FromPath (cairo_path_t *path) { PyObject *o; assert (path != NULL); if (Pycairo_Check_Status (path->status)) { cairo_path_destroy (path); return NULL; } o = PycairoPath_Type.tp_alloc (&PycairoPath_Type, 0); if (o) ((PycairoPath *)o)->path = path; else cairo_path_destroy (path); return o; } static void path_dealloc(PycairoPath *p) { if (p->path) { cairo_path_destroy(p->path); p->path = NULL; } Py_TYPE(p)->tp_free(p); } static PyObject * path_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { return type->tp_alloc(type, 0); /* initializes memory to zeros */ } static int path_init(PycairoPath *p, PyObject *args, PyObject *kwds) { PyErr_SetString(PyExc_TypeError, "The Path type cannot be instantiated, " "use Context.copy_path()"); return -1; } static PyObject * path_str(PycairoPath *p) { PyObject *s, *pieces = NULL, *result = NULL; cairo_path_t *path = p->path; cairo_path_data_t *data; int i, ret; char buf[80]; pieces = PyList_New(0); if (pieces == NULL) goto Done; /* loop reading elements */ for (i=0; i < path->num_data; i += path->data[i].header.length) { data = &path->data[i]; switch (data->header.type) { case CAIRO_PATH_MOVE_TO: PyOS_snprintf(buf, sizeof(buf), "move_to %f %f", data[1].point.x, data[1].point.y); s = PYCAIRO_PyUnicode_FromString(buf); if (!s) goto Done; ret = PyList_Append(pieces, s); Py_DECREF(s); if (ret < 0) goto Done; break; case CAIRO_PATH_LINE_TO: PyOS_snprintf(buf, sizeof(buf), "line_to %f %f", data[1].point.x, data[1].point.y); s = PYCAIRO_PyUnicode_FromString(buf); if (!s) goto Done; ret = PyList_Append(pieces, s); Py_DECREF(s); if (ret < 0) goto Done; break; case CAIRO_PATH_CURVE_TO: PyOS_snprintf(buf, sizeof(buf), "curve_to %f %f %f %f %f %f", data[1].point.x, data[1].point.y, data[2].point.x, data[2].point.y, data[3].point.x, data[3].point.y); s = PYCAIRO_PyUnicode_FromString(buf); if (!s) goto Done; ret = PyList_Append(pieces, s); Py_DECREF(s); if (ret < 0) goto Done; break; case CAIRO_PATH_CLOSE_PATH: s = PYCAIRO_PyUnicode_FromString("close path"); if (!s) goto Done; ret = PyList_Append(pieces, s); Py_DECREF(s); if (ret < 0) goto Done; break; default: PyErr_SetString(PyExc_RuntimeError, "unknown CAIRO_PATH type"); goto Done; break; } } /* result = "\n".join(pieces) */ s = PYCAIRO_PyUnicode_FromString("\n"); if (s == NULL) goto Done; result = PYCAIRO_PyUnicode_Join(s, pieces); Py_DECREF(s); Done: Py_XDECREF(pieces); return result; } static PyObject * path_iter(PyObject *seq); /* forward declaration */ static PyObject* path_richcompare (PyObject *self, PyObject *other, int op) { if (Py_TYPE(self) == Py_TYPE(other)) return Pycairo_richcompare ( ((PycairoPath *)self)->path, ((PycairoPath *)other)->path, op); else { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } } static PYCAIRO_Py_hash_t path_hash (PyObject *self) { return PYCAIRO_Py_hash_t_FromVoidPtr (((PycairoPath *)self)->path); } PyTypeObject PycairoPath_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.Path", /* tp_name */ sizeof(PycairoPath), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)path_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ path_hash, /* tp_hash */ 0, /* tp_call */ (reprfunc)path_str, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ path_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)path_iter, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)path_init, /* tp_init */ 0, /* tp_alloc */ (newfunc)path_new, /* tp_new */ }; /*********************** PycairoPath Iterator **************************/ typedef struct { PyObject_HEAD int index; /* position within PycairoPath */ PycairoPath *pypath; /* Set to NULL when iterator is exhausted */ } PycairoPathiter; PyTypeObject PycairoPathiter_Type; static void pathiter_dealloc(PycairoPathiter *it) { Py_XDECREF(it->pypath); PyObject_Del(it); } static PyObject * path_iter(PyObject *pypath) { PycairoPathiter *it; if (!PyObject_TypeCheck (pypath, &PycairoPath_Type)) { PyErr_BadInternalCall(); return NULL; } it = PyObject_New(PycairoPathiter, &PycairoPathiter_Type); if (it == NULL) return NULL; it->index = 0; Py_INCREF(pypath); it->pypath = (PycairoPath *)pypath; return (PyObject *) it; } static PyObject * pathiter_next(PycairoPathiter *it) { PycairoPath *pypath; cairo_path_t *path; assert(it != NULL); pypath = it->pypath; if (pypath == NULL) return NULL; assert (PyObject_TypeCheck (pypath, &PycairoPath_Type)); path = pypath->path; /* return the next path element, advance index */ if (it->index < path->num_data) { cairo_path_data_t *data = &path->data[it->index]; int type = data->header.type; it->index += data[0].header.length; switch (type) { case CAIRO_PATH_MOVE_TO: case CAIRO_PATH_LINE_TO: return Py_BuildValue("(i(dd))", type, data[1].point.x, data[1].point.y); case CAIRO_PATH_CURVE_TO: return Py_BuildValue("(i(dddddd))", type, data[1].point.x, data[1].point.y, data[2].point.x, data[2].point.y, data[3].point.x, data[3].point.y); case CAIRO_PATH_CLOSE_PATH: return Py_BuildValue("i()", type); default: PyErr_SetString(PyExc_RuntimeError, "unknown CAIRO_PATH type"); return NULL; } } /* iterator has no remaining items */ Py_DECREF(pypath); it->pypath = NULL; return NULL; } PyTypeObject PycairoPathiter_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.Pathiter", /* tp_name */ sizeof(PycairoPathiter), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)pathiter_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* PyObject_SelfIter, */ /* tp_iter */ (iternextfunc)pathiter_next, /* tp_iternext */ 0, /* tp_methods */ }; pycairo-1.16.2/cairo/pattern.c000066400000000000000000001242011323762421700161740ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2004-2006 Steve Chaplin * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "private.h" /* Class Pattern ---------------------------------------------------------- */ PyObject * PycairoPattern_FromPattern (cairo_pattern_t *pattern, PyObject *base) { PyTypeObject *type = NULL; PyObject *o; assert (pattern != NULL); if (Pycairo_Check_Status (cairo_pattern_status (pattern))) { cairo_pattern_destroy (pattern); return NULL; } switch (cairo_pattern_get_type (pattern)) { case CAIRO_PATTERN_TYPE_SOLID: type = &PycairoSolidPattern_Type; break; case CAIRO_PATTERN_TYPE_SURFACE: type = &PycairoSurfacePattern_Type; break; case CAIRO_PATTERN_TYPE_LINEAR: type = &PycairoLinearGradient_Type; break; case CAIRO_PATTERN_TYPE_RADIAL: type = &PycairoRadialGradient_Type; break; case CAIRO_PATTERN_TYPE_MESH: type = &PycairoMeshPattern_Type; break; case CAIRO_PATTERN_TYPE_RASTER_SOURCE: type = &PycairoRasterSourcePattern_Type; break; default: type = &PycairoPattern_Type; break; } o = type->tp_alloc(type, 0); if (o == NULL) { cairo_pattern_destroy (pattern); } else { ((PycairoPattern *)o)->pattern = pattern; Py_XINCREF(base); ((PycairoPattern *)o)->base = base; } return o; } static void pattern_dealloc (PycairoPattern *o) { if (o->pattern) { cairo_pattern_destroy (o->pattern); o->pattern = NULL; } Py_CLEAR(o->base); Py_TYPE(o)->tp_free(o); } static PyObject * pattern_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { PyErr_SetString(PyExc_TypeError, "The Pattern type cannot be instantiated"); return NULL; } static PyObject * pattern_get_extend (PycairoPattern *o) { RETURN_INT_ENUM (Extend, cairo_pattern_get_extend (o->pattern)); } static PyObject * pattern_get_matrix (PycairoPattern *o) { cairo_matrix_t matrix; cairo_pattern_get_matrix (o->pattern, &matrix); return PycairoMatrix_FromMatrix (&matrix); } static PyObject * pattern_set_extend (PycairoPattern *o, PyObject *args) { cairo_extend_t extend; int extend_arg; if (!PyArg_ParseTuple (args, "i:Pattern.set_extend", &extend_arg)) return NULL; extend = (cairo_extend_t)extend_arg; cairo_pattern_set_extend (o->pattern, extend); Py_RETURN_NONE; } static PyObject * pattern_set_matrix (PycairoPattern *o, PyObject *args) { PycairoMatrix *m; if (!PyArg_ParseTuple (args, "O!:Pattern.set_matrix", &PycairoMatrix_Type, &m)) return NULL; cairo_pattern_set_matrix (o->pattern, &m->matrix); Py_RETURN_NONE; } static PyObject * pattern_get_filter (PycairoPattern *o) { cairo_filter_t filter; Py_BEGIN_ALLOW_THREADS; filter = cairo_pattern_get_filter (o->pattern); Py_END_ALLOW_THREADS; RETURN_INT_ENUM (Filter, filter); } static PyObject * pattern_set_filter (PycairoPattern *o, PyObject *args) { cairo_filter_t filter; int filter_arg; if (!PyArg_ParseTuple (args, "i:Pattern.set_filter", &filter_arg)) return NULL; filter = (cairo_filter_t)filter_arg; Py_BEGIN_ALLOW_THREADS; cairo_pattern_set_filter (o->pattern, filter); Py_END_ALLOW_THREADS; Py_RETURN_NONE; } static PyMethodDef pattern_methods[] = { /* methods never exposed in a language binding: * cairo_pattern_destroy() * cairo_pattern_get_type() * cairo_pattern_reference() * * cairo_pattern_status() * - not needed since Pycairo handles status checking */ {"get_extend", (PyCFunction)pattern_get_extend, METH_NOARGS }, {"get_matrix", (PyCFunction)pattern_get_matrix, METH_NOARGS }, {"set_extend", (PyCFunction)pattern_set_extend, METH_VARARGS }, {"set_matrix", (PyCFunction)pattern_set_matrix, METH_VARARGS }, {"get_filter", (PyCFunction)pattern_get_filter, METH_NOARGS }, {"set_filter", (PyCFunction)pattern_set_filter, METH_VARARGS }, {NULL, NULL, 0, NULL}, }; static PyObject* pattern_richcompare (PyObject *self, PyObject *other, int op) { if (Py_TYPE(self) == Py_TYPE(other)) return Pycairo_richcompare ( ((PycairoPattern *)self)->pattern, ((PycairoPattern *)other)->pattern, op); else { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } } static PYCAIRO_Py_hash_t pattern_hash (PyObject *self) { return PYCAIRO_Py_hash_t_FromVoidPtr (((PycairoPattern *)self)->pattern); } PyTypeObject PycairoPattern_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.Pattern", /* tp_name */ sizeof(PycairoPattern), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)pattern_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ pattern_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,/* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ pattern_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ pattern_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)pattern_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; /* Class SolidPattern ----------------------------------------------------- */ static PyObject * solid_pattern_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { double r, g, b, a = 1.0; if (!PyArg_ParseTuple (args, "ddd|d:SolidPattern.__new__", &r, &g, &b, &a)) return NULL; return PycairoPattern_FromPattern (cairo_pattern_create_rgba (r, g, b, a), NULL); } static PyObject * solid_pattern_get_rgba (PycairoSolidPattern *o) { double red, green, blue, alpha; cairo_pattern_get_rgba (o->pattern, &red, &green, &blue, &alpha); return Py_BuildValue("(dddd)", red, green, blue, alpha); } static PyMethodDef solid_pattern_methods[] = { {"get_rgba", (PyCFunction)solid_pattern_get_rgba, METH_NOARGS }, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoSolidPattern_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.SolidPattern", /* tp_name */ sizeof(PycairoSolidPattern), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ solid_pattern_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoPattern_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)solid_pattern_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; /* Class SurfacePattern --------------------------------------------------- */ static PyObject * surface_pattern_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { PycairoSurface *s; if (!PyArg_ParseTuple (args, "O!:SurfacePattern.__new__", &PycairoSurface_Type, &s)) return NULL; return PycairoPattern_FromPattern ( cairo_pattern_create_for_surface (s->surface), NULL); } static PyObject * surface_pattern_get_surface (PycairoSurfacePattern *o) { cairo_surface_t *surface; RETURN_NULL_IF_CAIRO_ERROR(cairo_pattern_get_surface (o->pattern, &surface)); return PycairoSurface_FromSurface(cairo_surface_reference (surface), NULL); } static PyMethodDef surface_pattern_methods[] = { {"get_surface", (PyCFunction)surface_pattern_get_surface, METH_NOARGS }, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoSurfacePattern_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.SurfacePattern", /* tp_name */ sizeof(PycairoSurfacePattern), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ surface_pattern_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoPattern_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)surface_pattern_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; /* Class Gradient --------------------------------------------------------- */ static PyObject * gradient_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { PyErr_SetString(PyExc_TypeError, "The Gradient type cannot be instantiated"); return NULL; } static PyObject * gradient_add_color_stop_rgb (PycairoGradient *o, PyObject *args) { double offset, red, green, blue; if (!PyArg_ParseTuple(args, "dddd:Gradient.add_color_stop_rgb", &offset, &red, &green, &blue)) return NULL; cairo_pattern_add_color_stop_rgb (o->pattern, offset, red, green, blue); RETURN_NULL_IF_CAIRO_PATTERN_ERROR(o->pattern); Py_RETURN_NONE; } static PyObject * gradient_add_color_stop_rgba (PycairoGradient *o, PyObject *args) { double offset, red, green, blue, alpha; if (!PyArg_ParseTuple(args, "ddddd:Gradient.add_color_stop_rgba", &offset, &red, &green, &blue, &alpha)) return NULL; cairo_pattern_add_color_stop_rgba (o->pattern, offset, red, green, blue, alpha); RETURN_NULL_IF_CAIRO_PATTERN_ERROR(o->pattern); Py_RETURN_NONE; } static PyObject * gradient_get_color_stops_rgba (PycairoGradient *obj) { cairo_status_t status; double offset, red, green, blue, alpha; int count; PyObject *list, *tuple; int result, i; status = cairo_pattern_get_color_stop_count (obj->pattern, &count); RETURN_NULL_IF_CAIRO_ERROR (status); list = PyList_New (0); if (list == NULL) return NULL; for (i = 0; i < count; i++) { status = cairo_pattern_get_color_stop_rgba ( obj->pattern, i, &offset, &red, &green, &blue, &alpha); if (status != CAIRO_STATUS_SUCCESS) goto error; tuple = Py_BuildValue("(ddddd)", offset, red, green, blue, alpha); if (tuple == NULL) goto error; result = PyList_Append (list, tuple); Py_DECREF (tuple); if (result == -1) goto error; } return list; error: Py_DECREF (list); if (status != CAIRO_STATUS_SUCCESS) Pycairo_Check_Status (status); return NULL; } static PyMethodDef gradient_methods[] = { {"add_color_stop_rgb",(PyCFunction)gradient_add_color_stop_rgb, METH_VARARGS }, {"add_color_stop_rgba",(PyCFunction)gradient_add_color_stop_rgba, METH_VARARGS }, {"get_color_stops_rgba",(PyCFunction)gradient_get_color_stops_rgba, METH_NOARGS }, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoGradient_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.Gradient", /* tp_name */ sizeof(PycairoGradient), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,/* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ gradient_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoPattern_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)gradient_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; /* Class LinearGradient --------------------------------------------------- */ static PyObject * linear_gradient_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { double x0, y0, x1, y1; if (!PyArg_ParseTuple(args, "dddd:LinearGradient.__new__", &x0, &y0, &x1, &y1)) return NULL; return PycairoPattern_FromPattern ( cairo_pattern_create_linear (x0, y0, x1, y1), NULL); } static PyObject * linear_gradient_get_linear_points (PycairoLinearGradient *o) { double x0, y0, x1, y1; cairo_pattern_get_linear_points (o->pattern, &x0, &y0, &x1, &y1); return Py_BuildValue("(dddd)", x0, y0, x1, y1); } static PyMethodDef linear_gradient_methods[] = { {"get_linear_points", (PyCFunction)linear_gradient_get_linear_points, METH_NOARGS }, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoLinearGradient_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.LinearGradient", /* tp_name */ sizeof(PycairoLinearGradient), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ linear_gradient_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoGradient_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)linear_gradient_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; /* Class RadialGradient --------------------------------------------------- */ static PyObject * radial_gradient_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { double cx0, cy0, radius0, cx1, cy1, radius1; if (!PyArg_ParseTuple(args, "dddddd:RadialGradient.__new__", &cx0, &cy0, &radius0, &cx1, &cy1, &radius1)) return NULL; return PycairoPattern_FromPattern ( cairo_pattern_create_radial (cx0, cy0, radius0, cx1, cy1, radius1), NULL); } static PyObject * radial_gradient_get_radial_circles (PycairoRadialGradient *o) { double x0, y0, r0, x1, y1, r1; cairo_pattern_get_radial_circles (o->pattern, &x0, &y0, &r0, &x1, &y1, &r1); return Py_BuildValue("(dddddd)", x0, y0, r0, x1, y1, r1); } static PyMethodDef radial_gradient_methods[] = { {"get_radial_circles", (PyCFunction)radial_gradient_get_radial_circles, METH_NOARGS }, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoRadialGradient_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.RadialGradient", /* tp_name */ sizeof(PycairoRadialGradient), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ radial_gradient_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoGradient_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)radial_gradient_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; static PyObject * mesh_pattern_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { if (!PyArg_ParseTuple (args, ":Mesh.__new__")) return NULL; return PycairoPattern_FromPattern (cairo_pattern_create_mesh (), NULL); } static PyObject * mesh_pattern_begin_patch (PycairoMeshPattern *obj) { Py_BEGIN_ALLOW_THREADS; cairo_mesh_pattern_begin_patch (obj->pattern); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_PATTERN_ERROR (obj->pattern); Py_RETURN_NONE; } static PyObject * mesh_pattern_end_patch (PycairoMeshPattern *obj) { Py_BEGIN_ALLOW_THREADS; cairo_mesh_pattern_end_patch (obj->pattern); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_PATTERN_ERROR (obj->pattern); Py_RETURN_NONE; } static PyObject * mesh_pattern_curve_to (PycairoMeshPattern *obj, PyObject *args) { double x1, y1, x2, y2, x3, y3; if (!PyArg_ParseTuple(args, "dddddd:MeshPattern.curve_to", &x1, &y1, &x2, &y2, &x3, &y3)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_mesh_pattern_curve_to (obj->pattern, x1, y1, x2, y2, x3, y3); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_PATTERN_ERROR (obj->pattern); Py_RETURN_NONE; } static PyObject * mesh_pattern_get_control_point (PycairoMeshPattern *obj, PyObject *args) { double x, y; unsigned int patch_num, point_num; cairo_status_t status; if (!PyArg_ParseTuple(args, "II:MeshPattern.get_control_point", &patch_num, &point_num)) return NULL; Py_BEGIN_ALLOW_THREADS; status = cairo_mesh_pattern_get_control_point ( obj->pattern, patch_num, point_num, &x, &y); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_ERROR (status); return Py_BuildValue("(dd)", x, y); } static PyObject * mesh_pattern_get_corner_color_rgba (PycairoMeshPattern *obj, PyObject *args) { double red, green, blue, alpha; unsigned int patch_num, corner_num; cairo_status_t status; if (!PyArg_ParseTuple(args, "II:MeshPattern.get_corner_color_rgba", &patch_num, &corner_num)) return NULL; Py_BEGIN_ALLOW_THREADS; status = cairo_mesh_pattern_get_corner_color_rgba ( obj->pattern, patch_num, corner_num, &red, &green, &blue, &alpha); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_ERROR (status); return Py_BuildValue("(dddd)", red, green, blue, alpha); } static PyObject * mesh_pattern_get_patch_count (PycairoMeshPattern *obj) { unsigned int count; cairo_status_t status; Py_BEGIN_ALLOW_THREADS; status = cairo_mesh_pattern_get_patch_count (obj->pattern, &count); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_ERROR (status); return PYCAIRO_PyLong_FromLong ((long)count); } static PyObject * mesh_pattern_get_path (PycairoMeshPattern *obj, PyObject *args) { unsigned int patch_num; cairo_path_t *path; if (!PyArg_ParseTuple(args, "I:MeshPattern.get_path", &patch_num)) return NULL; Py_BEGIN_ALLOW_THREADS; path = cairo_mesh_pattern_get_path (obj->pattern, patch_num); Py_END_ALLOW_THREADS; return PycairoPath_FromPath (path); } static PyObject * mesh_pattern_line_to (PycairoMeshPattern *obj, PyObject *args) { double x, y; if (!PyArg_ParseTuple(args, "dd:MeshPattern.line_to", &x, &y)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_mesh_pattern_line_to (obj->pattern, x, y); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_PATTERN_ERROR (obj->pattern); Py_RETURN_NONE; } static PyObject * mesh_pattern_move_to (PycairoMeshPattern *obj, PyObject *args) { double x, y; if (!PyArg_ParseTuple(args, "dd:MeshPattern.move_to", &x, &y)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_mesh_pattern_move_to (obj->pattern, x, y); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_PATTERN_ERROR (obj->pattern); Py_RETURN_NONE; } static PyObject * mesh_pattern_set_control_point (PycairoMeshPattern *obj, PyObject *args) { double x, y; unsigned int point_num; if (!PyArg_ParseTuple(args, "Idd:MeshPattern.set_control_point", &point_num, &x, &y)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_mesh_pattern_set_control_point (obj->pattern, point_num, x, y); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_PATTERN_ERROR (obj->pattern); Py_RETURN_NONE; } static PyObject * mesh_pattern_set_corner_color_rgb (PycairoMeshPattern *obj, PyObject *args) { double red, green, blue; unsigned int corner_num; if (!PyArg_ParseTuple(args, "Iddd:MeshPattern.set_corner_color_rgb", &corner_num, &red, &green, &blue)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_mesh_pattern_set_corner_color_rgb ( obj->pattern, corner_num, red, green, blue); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_PATTERN_ERROR (obj->pattern); Py_RETURN_NONE; } static PyObject * mesh_pattern_set_corner_color_rgba (PycairoMeshPattern *obj, PyObject *args) { double red, green, blue, alpha; unsigned int corner_num; if (!PyArg_ParseTuple(args, "Idddd:MeshPattern.set_corner_color_rgba", &corner_num, &red, &green, &blue, &alpha)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_mesh_pattern_set_corner_color_rgba ( obj->pattern, corner_num, red, green, blue, alpha); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_PATTERN_ERROR (obj->pattern); Py_RETURN_NONE; } static PyMethodDef mesh_pattern_methods[] = { {"begin_patch", (PyCFunction)mesh_pattern_begin_patch, METH_NOARGS}, {"end_patch", (PyCFunction)mesh_pattern_end_patch, METH_NOARGS}, {"curve_to", (PyCFunction)mesh_pattern_curve_to, METH_VARARGS}, {"get_control_point", (PyCFunction)mesh_pattern_get_control_point, METH_VARARGS}, {"get_corner_color_rgba", (PyCFunction)mesh_pattern_get_corner_color_rgba, METH_VARARGS}, {"get_patch_count", (PyCFunction)mesh_pattern_get_patch_count, METH_NOARGS}, {"get_path", (PyCFunction)mesh_pattern_get_path, METH_VARARGS}, {"line_to", (PyCFunction)mesh_pattern_line_to, METH_VARARGS}, {"move_to", (PyCFunction)mesh_pattern_move_to, METH_VARARGS}, {"set_control_point", (PyCFunction)mesh_pattern_set_control_point, METH_VARARGS}, {"set_corner_color_rgb", (PyCFunction)mesh_pattern_set_corner_color_rgb, METH_VARARGS}, {"set_corner_color_rgba", (PyCFunction)mesh_pattern_set_corner_color_rgba, METH_VARARGS}, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoMeshPattern_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.MeshPattern", /* tp_name */ sizeof(PycairoMeshPattern), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ mesh_pattern_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoPattern_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)mesh_pattern_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; static PyObject * raster_source_pattern_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { cairo_content_t content; int width, height, content_arg; if (!PyArg_ParseTuple (args, "iii:RasterSourcePattern.__new__", &content_arg, &width, &height)) return NULL; content = (cairo_content_t)content_arg; return PycairoPattern_FromPattern ( cairo_pattern_create_raster_source (NULL, content, width, height), NULL); } static const cairo_user_data_key_t raster_source_acquire_key; static const cairo_user_data_key_t raster_source_release_key; static void _decref_destroy_func (void *user_data) { PyGILState_STATE gstate = PyGILState_Ensure (); Py_DECREF (user_data); PyGILState_Release (gstate); } static void _raster_source_release_func (cairo_pattern_t *pattern, void *callback_data, cairo_surface_t *surface) { void *user_data; PyObject *pysurface, *result; PyGILState_STATE gstate; pattern = (cairo_pattern_t *)callback_data; user_data = cairo_pattern_get_user_data ( pattern, &raster_source_release_key); /* in case there is a acquire callback but no release one, this gets called * anyway so we can free the surface */ if (user_data == NULL) { cairo_surface_destroy (surface); return; } gstate = PyGILState_Ensure (); pysurface = PycairoSurface_FromSurface ( cairo_surface_reference (surface), NULL); if (pysurface == NULL) goto error; result = PyObject_CallFunction ((PyObject *)user_data, "(O)", pysurface); if (result == NULL) goto error; if (result != Py_None) { Py_DECREF (result); PyErr_SetString (PyExc_TypeError, "Return value of release callback needs to be None"); result = NULL; goto error; } Py_DECREF (pysurface); PyGILState_Release (gstate); cairo_surface_destroy (surface); return; error: if (PyErr_Occurred ()) { PyErr_Print (); PyErr_Clear (); } Py_XDECREF (pysurface); PyGILState_Release (gstate); cairo_surface_destroy (surface); return; } static cairo_surface_t* _raster_source_acquire_func (cairo_pattern_t *pattern, void *callback_data, cairo_surface_t *target, const cairo_rectangle_int_t *extents) { void *user_data; PyGILState_STATE gstate; PyObject *result; PyObject *pysurface = NULL, *pyrect = NULL; cairo_surface_t *result_surface; /* https://bugs.freedesktop.org/show_bug.cgi?id=101866 * If something changes the callback data, we are screwed, but not much * we can do to detect that.. */ pattern = (cairo_pattern_t *)callback_data; gstate = PyGILState_Ensure (); user_data = cairo_pattern_get_user_data ( pattern, &raster_source_acquire_key); if (user_data == NULL) goto error; pysurface = PycairoSurface_FromSurface ( cairo_surface_reference (target), NULL); if (pysurface == NULL) goto error; pyrect = PycairoRectangleInt_FromRectangleInt (extents); if (pyrect == NULL) goto error; result = PyObject_CallFunction ( (PyObject *)user_data, "(OO)", pysurface, pyrect); if (result != NULL) { if (!PyObject_TypeCheck (result, &PycairoSurface_Type)) { Py_DECREF (result); PyErr_SetString (PyExc_TypeError, "Return value of acquire callback needs to be of type Surface"); result = NULL; } } if (result == NULL) goto error; Py_DECREF (pysurface); Py_DECREF (pyrect); result_surface = ((PycairoSurface *)result)->surface; cairo_surface_reference (result_surface); Py_DECREF (result); PyGILState_Release (gstate); return result_surface; error: if (PyErr_Occurred ()) { PyErr_Print (); PyErr_Clear (); } Py_XDECREF (pysurface); Py_XDECREF (pyrect); PyGILState_Release (gstate); return NULL; } static PyObject * raster_source_pattern_set_acquire (PycairoRasterSourcePattern *obj, PyObject *args) { PyObject *acquire_callable, *release_callable; cairo_status_t status; cairo_pattern_t *pattern; void *callback_data; cairo_raster_source_acquire_func_t acquire_func; cairo_raster_source_release_func_t release_func; void *acquire_user_data, *release_user_data; if (!PyArg_ParseTuple (args, "OO:RasterSourcePattern.set_acquire", &acquire_callable, &release_callable)) return NULL; pattern = obj->pattern; callback_data = cairo_raster_source_pattern_get_callback_data (pattern); if (callback_data != NULL && callback_data != pattern) { PyErr_SetString (PyExc_RuntimeError, "Callback is set, but not through Pycairo. Replacing not supported."); return NULL; } if (!PyCallable_Check (acquire_callable) && acquire_callable != Py_None) { PyErr_SetString ( PyExc_TypeError, "argument needs to be a callable or None"); return NULL; } if (!PyCallable_Check (release_callable) && release_callable != Py_None) { PyErr_SetString ( PyExc_TypeError, "argument needs to be a callable or None"); return NULL; } if (acquire_callable == Py_None) { acquire_func = NULL; acquire_user_data = NULL; } else { acquire_func = _raster_source_acquire_func; acquire_user_data = acquire_callable; } if (release_callable == Py_None) { release_func = NULL; release_user_data = NULL; } else { release_func = _raster_source_release_func; release_user_data = release_callable; } /* in case acquire is set we have to clean up anyway */ if (acquire_func != NULL && release_func == NULL) { release_func = _raster_source_release_func; } status = cairo_pattern_set_user_data ( pattern, &raster_source_acquire_key, acquire_user_data, (acquire_user_data) ? _decref_destroy_func : NULL); RETURN_NULL_IF_CAIRO_ERROR (status); if (acquire_user_data != NULL) Py_INCREF (acquire_user_data); status = cairo_pattern_set_user_data ( pattern, &raster_source_release_key, release_user_data, (release_user_data) ? _decref_destroy_func : NULL); if (status != CAIRO_STATUS_SUCCESS) { cairo_pattern_set_user_data ( pattern, &raster_source_acquire_key, NULL, NULL); RETURN_NULL_IF_CAIRO_ERROR (status); } if (release_user_data != NULL) Py_INCREF (release_user_data); cairo_raster_source_pattern_set_callback_data (pattern, pattern); Py_BEGIN_ALLOW_THREADS; cairo_raster_source_pattern_set_acquire ( pattern, acquire_func, release_func); Py_END_ALLOW_THREADS; Py_RETURN_NONE; } static PyObject * raster_source_pattern_get_acquire (PycairoRasterSourcePattern *obj) { cairo_pattern_t *pattern; void *user_data; PyObject *acquire_callable, *release_callable; pattern = obj->pattern; user_data = cairo_pattern_get_user_data ( pattern, &raster_source_acquire_key); if (user_data == NULL) { acquire_callable = Py_None; } else { acquire_callable = user_data; } user_data = cairo_pattern_get_user_data ( pattern, &raster_source_release_key); if (user_data == NULL) { release_callable = Py_None; } else { release_callable = user_data; } return Py_BuildValue ("(OO)", acquire_callable, release_callable); } static PyMethodDef raster_source_pattern_methods[] = { {"set_acquire", (PyCFunction)raster_source_pattern_set_acquire, METH_VARARGS}, {"get_acquire", (PyCFunction)raster_source_pattern_get_acquire, METH_NOARGS}, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoRasterSourcePattern_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.RasterSourcePattern", /* tp_name */ sizeof(PycairoRasterSourcePattern), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ raster_source_pattern_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoPattern_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)raster_source_pattern_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; pycairo-1.16.2/cairo/private.h000066400000000000000000000231511323762421700162000ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2003 James Henstridge * Copyright © 2004-2011 Steven Chaplin * * 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. */ #ifndef _PYCAIRO_PRIVATE_H_ #define _PYCAIRO_PRIVATE_H_ #ifdef _PYCAIRO_H_ # error "don't include pycairo.h and pycairo-private.h together" #endif #define _INSIDE_PYCAIRO_ #include #include "pycairo.h" #include "compat.h" #define PYCAIRO_STRINGIFY(s) PYCAIRO_STRINGIFY_ARG(s) #define PYCAIRO_STRINGIFY_ARG(s) #s int init_error(PyObject *module); int Pycairo_fspath_converter (PyObject *obj, char** result); int Pycairo_fspath_none_converter (PyObject *obj, char** result); int Pycairo_writer_converter (PyObject *obj, PyObject** file); int Pycairo_reader_converter (PyObject *obj, PyObject** file); int Pycairo_is_fspath (PyObject *obj); cairo_glyph_t * _PycairoGlyphs_AsGlyphs (PyObject *py_object, int *num_glyphs); int _PyGlyph_AsGlyph (PyObject *pyobj, cairo_glyph_t *glyph); int _PyTextCluster_AsTextCluster (PyObject *pyobj, cairo_text_cluster_t *cluster); int _conv_pyobject_to_ulong (PyObject *pyobj, unsigned long *result); PyObject* Pycairo_richcompare (void* a, void *b, int op); PyObject* Pycairo_tuple_getattro (PyObject *self, char **kwds, PyObject *name); extern PyTypeObject PycairoContext_Type; PyObject *PycairoContext_FromContext (cairo_t *ctx, PyTypeObject *type, PyObject *base); extern PyTypeObject PycairoFontFace_Type; extern PyTypeObject PycairoToyFontFace_Type; PyObject *PycairoFontFace_FromFontFace (cairo_font_face_t *font_face); extern PyTypeObject PycairoFontOptions_Type; PyObject *PycairoFontOptions_FromFontOptions ( cairo_font_options_t *font_options); extern PyTypeObject PycairoMatrix_Type; PyObject *PycairoMatrix_FromMatrix (const cairo_matrix_t *matrix); extern PyTypeObject PycairoPath_Type; PyObject *PycairoPath_FromPath (cairo_path_t *path); extern PyTypeObject PycairoPathiter_Type; extern PyTypeObject PycairoPattern_Type; extern PyTypeObject PycairoSolidPattern_Type; extern PyTypeObject PycairoSurfacePattern_Type; extern PyTypeObject PycairoGradient_Type; extern PyTypeObject PycairoLinearGradient_Type; extern PyTypeObject PycairoRadialGradient_Type; PyObject *PycairoPattern_FromPattern (cairo_pattern_t *pattern, PyObject *base); typedef PycairoPattern PycairoMeshPattern; extern PyTypeObject PycairoMeshPattern_Type; typedef PycairoPattern PycairoRasterSourcePattern; extern PyTypeObject PycairoRasterSourcePattern_Type; extern PyTypeObject PycairoRectangleInt_Type; PyObject *PycairoRectangleInt_FromRectangleInt ( const cairo_rectangle_int_t *rectangle_int); extern PyTypeObject PycairoRegion_Type; PyObject *PycairoRegion_FromRegion (cairo_region_t *region); extern PyTypeObject PycairoDevice_Type; PyObject *PycairoDevice_FromDevice (cairo_device_t *device); extern PyTypeObject PycairoScriptDevice_Type; extern PyTypeObject PycairoScaledFont_Type; PyObject *PycairoScaledFont_FromScaledFont (cairo_scaled_font_t *scaled_font); extern PyTypeObject PycairoSurface_Type; extern PyTypeObject PycairoImageSurface_Type; extern PyTypeObject PycairoMappedImageSurface_Type; extern PyTypeObject PycairoGlyph_Type; typedef PyTupleObject PycairGlyph; extern PyTypeObject PycairoRectangle_Type; typedef PyTupleObject PycairRectangle; extern PyTypeObject PycairoTextCluster_Type; typedef PyTupleObject PycairTextCluster; extern PyTypeObject PycairoTextExtents_Type; typedef PyTupleObject PycairoTextExtents; typedef struct { PyObject_HEAD cairo_device_t *device; } PycairoDevice; #ifdef CAIRO_HAS_SCRIPT_SURFACE typedef PycairoDevice PycairoScriptDevice; extern PyTypeObject PycairoScriptSurface_Type; #endif #ifdef CAIRO_HAS_PDF_SURFACE extern PyTypeObject PycairoPDFSurface_Type; #endif #ifdef CAIRO_HAS_PS_SURFACE extern PyTypeObject PycairoPSSurface_Type; #endif #ifdef CAIRO_HAS_RECORDING_SURFACE extern PyTypeObject PycairoRecordingSurface_Type; #endif #ifdef CAIRO_HAS_SVG_SURFACE extern PyTypeObject PycairoSVGSurface_Type; #endif #ifdef CAIRO_HAS_WIN32_SURFACE extern PyTypeObject PycairoWin32Surface_Type; extern PyTypeObject PycairoWin32PrintingSurface_Type; #endif #ifdef CAIRO_HAS_XCB_SURFACE extern PyTypeObject PycairoXCBSurface_Type; #ifdef HAVE_XPYB # include extern xpyb_CAPI_t *xpyb_CAPI; extern PyObject *xpybVISUALTYPE_type; #endif #endif #ifdef CAIRO_HAS_XLIB_SURFACE extern PyTypeObject PycairoXlibSurface_Type; #endif #ifdef CAIRO_HAS_TEE_SURFACE typedef PycairoSurface PycairoTeeSurface; extern PyTypeObject PycairoTeeSurface_Type; #endif PyObject *PycairoSurface_FromSurface (cairo_surface_t *surface, PyObject *base); int Pycairo_Check_Status (cairo_status_t status); /* error checking macros */ #define RETURN_NULL_IF_CAIRO_ERROR(status) \ do { \ if (status != CAIRO_STATUS_SUCCESS) { \ Pycairo_Check_Status (status); \ return NULL; \ } \ } while (0) #define RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(ctx) \ do { \ cairo_status_t status = cairo_status (ctx); \ if (status != CAIRO_STATUS_SUCCESS) { \ Pycairo_Check_Status (status); \ return NULL; \ } \ } while (0) #define RETURN_NULL_IF_CAIRO_PATTERN_ERROR(pattern) \ do { \ cairo_status_t status = cairo_pattern_status (pattern); \ if (status != CAIRO_STATUS_SUCCESS) { \ Pycairo_Check_Status (status); \ return NULL; \ } \ } while (0) #define RETURN_NULL_IF_CAIRO_REGION_ERROR(region) \ do { \ cairo_status_t status = cairo_region_status (region); \ if (status != CAIRO_STATUS_SUCCESS) { \ Pycairo_Check_Status (status); \ return NULL; \ } \ } while (0) #define RETURN_NULL_IF_CAIRO_SURFACE_ERROR(surface) \ do { \ cairo_status_t status = cairo_surface_status (surface); \ if (status != CAIRO_STATUS_SUCCESS) { \ Pycairo_Check_Status (status); \ return NULL; \ } \ } while (0) #define RETURN_NULL_IF_CAIRO_DEVICE_ERROR(device) \ do { \ cairo_status_t status = cairo_device_status (device); \ if (status != CAIRO_STATUS_SUCCESS) { \ Pycairo_Check_Status (status); \ return NULL; \ } \ } while (0) #define RETURN_NULL_IF_CAIRO_SCALED_FONT_ERROR(sc_font) \ do { \ cairo_status_t status = cairo_scaled_font_status (sc_font); \ if (status != CAIRO_STATUS_SUCCESS) { \ Pycairo_Check_Status (status); \ return NULL; \ } \ } while (0) #define RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(fo) \ do { \ cairo_status_t status = cairo_font_options_status (fo); \ if (status != CAIRO_STATUS_SUCCESS) { \ Pycairo_Check_Status (status); \ return NULL; \ } \ } while (0) PyObject *error_get_type(void); int init_buffer_proxy(void); PyObject *buffer_proxy_create_view(PyObject *exporter, void *buf, Py_ssize_t len, int readonly); /* int enums */ int init_enums(PyObject *module); PyObject *int_enum_create(PyTypeObject *type, long value); #define DECL_ENUM(name) extern PyTypeObject Pycairo_##name##_Type; /* A defined variant of (int)(unsigned int)(u). The cast from unsigned to * signed gives the reverse result of a signed to unsigned cast. */ #define _ENSURE_INT(u) ( \ ((unsigned int)(u) > INT_MAX) ? \ -(int)(UINT_MAX - (unsigned int)(u)) - 1 : (int)(unsigned int)(u) \ ) #define CREATE_INT_ENUM(type_name, value) \ (int_enum_create(&Pycairo_##type_name##_Type, _ENSURE_INT(value))) #define RETURN_INT_ENUM(type_name, value) \ return CREATE_INT_ENUM(type_name, value); DECL_ENUM(Antialias) DECL_ENUM(Content) DECL_ENUM(Extend) DECL_ENUM(FillRule) DECL_ENUM(Filter) DECL_ENUM(FontSlant) DECL_ENUM(FontWeight) DECL_ENUM(Format) DECL_ENUM(HintMetrics) DECL_ENUM(HintStyle) DECL_ENUM(LineCap) DECL_ENUM(LineJoin) DECL_ENUM(Operator) DECL_ENUM(PathDataType) DECL_ENUM(RegionOverlap) DECL_ENUM(Status) DECL_ENUM(SubpixelOrder) DECL_ENUM(TextClusterFlags) DECL_ENUM(SurfaceObserverMode) #ifdef CAIRO_HAS_SVG_SURFACE DECL_ENUM(SVGVersion) #endif #ifdef CAIRO_HAS_PDF_SURFACE DECL_ENUM(PDFVersion) #endif #ifdef CAIRO_HAS_PS_SURFACE DECL_ENUM(PSLevel) #endif #ifdef CAIRO_HAS_SCRIPT_SURFACE DECL_ENUM(ScriptMode) #endif #endif /* _PYCAIRO_PRIVATE_H_ */ pycairo-1.16.2/cairo/pycairo.h000066400000000000000000000215701323762421700161770ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2003 James Henstridge * Copyright © 2004-2011 Steven Chaplin * * 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. */ #ifndef _PYCAIRO_H_ #define _PYCAIRO_H_ #include #include typedef struct { PyObject_HEAD cairo_t *ctx; PyObject *base; /* base object used to create context, or NULL */ } PycairoContext; typedef struct { PyObject_HEAD cairo_font_face_t *font_face; } PycairoFontFace; #define PycairoToyFontFace PycairoFontFace typedef struct { PyObject_HEAD cairo_font_options_t *font_options; } PycairoFontOptions; typedef struct { PyObject_HEAD cairo_matrix_t matrix; } PycairoMatrix; typedef struct { PyObject_HEAD cairo_path_t *path; } PycairoPath; typedef struct { PyObject_HEAD cairo_pattern_t *pattern; PyObject *base; /* base object used to create pattern, or NULL */ } PycairoPattern; typedef struct { PyObject_HEAD cairo_rectangle_int_t rectangle_int; } PycairoRectangleInt; typedef struct { PyObject_HEAD cairo_region_t *region; } PycairoRegion; #define PycairoSolidPattern PycairoPattern #define PycairoSurfacePattern PycairoPattern #define PycairoGradient PycairoPattern #define PycairoLinearGradient PycairoPattern #define PycairoRadialGradient PycairoPattern typedef struct { PyObject_HEAD cairo_scaled_font_t *scaled_font; } PycairoScaledFont; typedef struct { PyObject_HEAD cairo_surface_t *surface; PyObject *base; /* base object used to create surface, or NULL */ } PycairoSurface; #define PycairoImageSurface PycairoSurface #define PycairoPDFSurface PycairoSurface #define PycairoPSSurface PycairoSurface #define PycairoRecordingSurface PycairoSurface #define PycairoSVGSurface PycairoSurface #define PycairoWin32Surface PycairoSurface #define PycairoWin32PrintingSurface PycairoSurface #define PycairoXCBSurface PycairoSurface #define PycairoXlibSurface PycairoSurface /* get C object out of the Python wrapper */ #define PycairoContext_GET(obj) (((PycairoContext *)(obj))->ctx) /* Define structure for C API. */ typedef struct { /* (type object, constructor) pairs */ PyTypeObject *Context_Type; PyObject *(*Context_FromContext)(cairo_t *ctx, PyTypeObject *type, PyObject *base); PyTypeObject *FontFace_Type; PyTypeObject *ToyFontFace_Type; PyObject *(*FontFace_FromFontFace)(cairo_font_face_t *font_face); PyTypeObject *FontOptions_Type; PyObject *(*FontOptions_FromFontOptions)( cairo_font_options_t *font_options); PyTypeObject *Matrix_Type; PyObject *(*Matrix_FromMatrix)(const cairo_matrix_t *matrix); PyTypeObject *Path_Type; PyObject *(*Path_FromPath)(cairo_path_t *path); PyTypeObject *Pattern_Type; PyTypeObject *SolidPattern_Type; PyTypeObject *SurfacePattern_Type; PyTypeObject *Gradient_Type; PyTypeObject *LinearGradient_Type; PyTypeObject *RadialGradient_Type; PyObject *(*Pattern_FromPattern)(cairo_pattern_t *pattern, PyObject *base); PyTypeObject *ScaledFont_Type; PyObject *(*ScaledFont_FromScaledFont)(cairo_scaled_font_t *scaled_font); PyTypeObject *Surface_Type; PyTypeObject *ImageSurface_Type; PyTypeObject *PDFSurface_Type; PyTypeObject *PSSurface_Type; PyTypeObject *SVGSurface_Type; PyTypeObject *Win32Surface_Type; PyTypeObject *Win32PrintingSurface_Type; PyTypeObject *XCBSurface_Type; PyTypeObject *XlibSurface_Type; PyObject *(*Surface_FromSurface)(cairo_surface_t *surface, PyObject *base); /* misc functions */ int (*Check_Status)(cairo_status_t status); PyTypeObject *RectangleInt_Type; PyObject *(*RectangleInt_FromRectangleInt)( const cairo_rectangle_int_t *rectangle_int); PyTypeObject *Region_Type; PyObject *(*Region_FromRegion)(cairo_region_t *region); PyTypeObject *RecordingSurface_Type; } Pycairo_CAPI_t; #ifndef _INSIDE_PYCAIRO_ /* Macros for accessing the C API */ #define PycairoContext_Type *(Pycairo_CAPI->Context_Type) #define PycairoContext_FromContext (Pycairo_CAPI->Context_FromContext) #define PycairoFontFace_Type *(Pycairo_CAPI->FontFace_Type) #define PycairoToyFontFace_Type *(Pycairo_CAPI->ToyFontFace_Type) #define PycairoFontFace_FromFontFace (Pycairo_CAPI->FontFace_FromFontFace) #define PycairoFontOptions_Type *(Pycairo_CAPI->FontOptions_Type) #define PycairoFontOptions_FromFontOptions \ (Pycairo_CAPI->FontOptions_FromFontOptions) #define PycairoMatrix_Type *(Pycairo_CAPI->Matrix_Type) #define PycairoMatrix_FromMatrix (Pycairo_CAPI->Matrix_FromMatrix) #define PycairoPath_Type *(Pycairo_CAPI->Path_Type) #define PycairoPath_FromPath (Pycairo_CAPI->Path_FromPath) #define PycairoPattern_Type *(Pycairo_CAPI->Pattern_Type) #define PycairoSolidPattern_Type *(Pycairo_CAPI->SolidPattern_Type) #define PycairoSurfacePattern_Type *(Pycairo_CAPI->SurfacePattern_Type) #define PycairoGradient_Type *(Pycairo_CAPI->Gradient_Type) #define PycairoLinearGradient_Type *(Pycairo_CAPI->LinearGradient_Type) #define PycairoRadialGradient_Type *(Pycairo_CAPI->RadialGradient_Type) #define PycairoPattern_FromPattern (Pycairo_CAPI->Pattern_FromPattern) #define PycairoRectangleInt_Type *(Pycairo_CAPI->RectangleInt_Type) #define PycairoRectangleInt_FromRectangleInt \ (Pycairo_CAPI->RectangleInt_FromRectangleInt) #define PycairoRegion_Type *(Pycairo_CAPI->Region_Type) #define PycairoRegion_FromRegion (Pycairo_CAPI->Region_FromRegion) #define PycairoScaledFont_Type *(Pycairo_CAPI->ScaledFont_Type) #define PycairoScaledFont_FromScaledFont \ (Pycairo_CAPI->ScaledFont_FromScaledFont) #define PycairoSurface_Type *(Pycairo_CAPI->Surface_Type) #define PycairoImageSurface_Type *(Pycairo_CAPI->ImageSurface_Type) #ifdef CAIRO_HAS_PDF_SURFACE #define PycairoPDFSurface_Type *(Pycairo_CAPI->PDFSurface_Type) #endif #ifdef CAIRO_HAS_PS_SURFACE #define PycairoPSSurface_Type *(Pycairo_CAPI->PSSurface_Type) #endif #ifdef CAIRO_HAS_RECORDING_SURFACE #define PycairoRecordingSurface_Type \ *(Pycairo_CAPI->RecordingSurface_Type) #endif #ifdef CAIRO_HAS_SVG_SURFACE #define PycairoSVGSurface_Type *(Pycairo_CAPI->SVGSurface_Type) #endif #ifdef CAIRO_HAS_WIN32_SURFACE #define PycairoWin32Surface_Type *(Pycairo_CAPI->Win32Surface_Type) #define PycairoWin32PrintingSurface_Type \ *(Pycairo_CAPI->Win32PrintingSurface_Type) #endif #ifdef CAIRO_HAS_XCB_SURFACE #define PycairoXCBSurface_Type *(Pycairo_CAPI->XCBSurface_Type) #endif #ifdef CAIRO_HAS_XLIB_SURFACE #define PycairoXlibSurface_Type *(Pycairo_CAPI->XlibSurface_Type) #endif #define PycairoSurface_FromSurface (Pycairo_CAPI->Surface_FromSurface) #define Pycairo_Check_Status (Pycairo_CAPI->Check_Status) #if PY_MAJOR_VERSION < 3 /* To access the Pycairo C API, edit the client module file to: * 1) Add the following line to define a global variable for the C API * static Pycairo_CAPI_t *Pycairo_CAPI; * 2) Add 'Pycairo_IMPORT;' to the init function */ #define Pycairo_IMPORT \ Pycairo_CAPI = (Pycairo_CAPI_t*) PyCObject_Import("cairo", "CAPI") #else /* To access the Pycairo C API, the client module should call 'import_cairo()' * from the init function, and check the return value, < 0 means the * import failed. */ static Pycairo_CAPI_t *Pycairo_CAPI; /* Return -1 on error, 0 on success. * PyCapsule_Import will set an exception if there's an error. */ static int import_cairo(void) { Pycairo_CAPI = (Pycairo_CAPI_t*) PyCapsule_Import("cairo.CAPI", 0); return (Pycairo_CAPI != 0) ? 0 : -1; } #endif #endif /* ifndef _INSIDE_PYCAIRO_ */ #endif /* ifndef _PYCAIRO_H_ */ pycairo-1.16.2/cairo/rectangle.c000066400000000000000000000112501323762421700164620ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2017 Christoph Reiter * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "private.h" static char *KWDS[] = {"x", "y", "width", "height", NULL}; static PyObject * rectangle_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { double x, y, width, height; PyObject *tuple_args, *result; if (!PyArg_ParseTupleAndKeywords (args, kwds, "dddd:Rectangle.__new__", KWDS, &x, &y, &width, &height)) return NULL; tuple_args = Py_BuildValue ("((dddd))", x, y, width, height); if (tuple_args == NULL) return NULL; result = PyTuple_Type.tp_new (type, tuple_args, NULL); Py_DECREF (tuple_args); return result; } static PyObject* rectangle_repr(PyObject *self) { PyObject *format, *result; format = PYCAIRO_PyUnicode_FromString ( "cairo.Rectangle(x=%r, y=%r, width=%r, height=%r)"); if (format == NULL) return NULL; result = PYCAIRO_PyUnicode_Format (format, self); Py_DECREF (format); return result; } static PyObject* rectangle_getattro (PyObject *self, PyObject *name) { return Pycairo_tuple_getattro (self, KWDS, name); } PyTypeObject PycairoRectangle_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.Rectangle", /* tp_name */ sizeof(PycairRectangle), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)rectangle_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ rectangle_getattro, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)rectangle_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; pycairo-1.16.2/cairo/region.c000066400000000000000000000454321323762421700160120ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2005,2010 Steve Chaplin * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "structmember.h" #include "private.h" PyObject * PycairoRectangleInt_FromRectangleInt (const cairo_rectangle_int_t *rectangle_int) { PyObject *o; assert (rectangle_int != NULL); o = PycairoRectangleInt_Type.tp_alloc (&PycairoRectangleInt_Type, 0); if (o) ((PycairoRectangleInt *)o)->rectangle_int = *rectangle_int; return o; } static void rectangle_int_dealloc(PycairoRectangleInt *o) { Py_TYPE(o)->tp_free(o); } static PyObject * rectangle_int_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { static char *kwlist[] = { "x", "y", "width", "height", NULL }; int x, y, w, h; cairo_rectangle_int_t rect; x = y = w = h = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iiii:RectangleInt.__new__", kwlist, &x, &y, &w, &h)) return NULL; rect.x = x; rect.y = y; rect.width = w; rect.height = h; return PycairoRectangleInt_FromRectangleInt(&rect); } static PyObject * rectangle_int_repr(PycairoRectangleInt *rect_o) { PyObject *s; cairo_rectangle_int_t *rect = &(rect_o->rectangle_int); char buf[80]; PyOS_snprintf(buf, sizeof(buf), "cairo.RectangleInt(x=%d, y=%d, width=%d, height=%d)", rect->x, rect->y, rect->width, rect->height); s = PYCAIRO_PyUnicode_FromString(buf); return s; } static PyObject * rectangle_int_richcompare(PycairoRectangleInt *self, PycairoRectangleInt *other, int op) { int res = 0; PyObject *b; if (op != Py_EQ && op != Py_NE) { PyErr_SetString(PyExc_TypeError, "Only support testing for == or !="); return NULL; } if (!PyObject_TypeCheck((PyObject*)other, &PycairoRectangleInt_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } else if ( self->rectangle_int.x == other->rectangle_int.x && self->rectangle_int.y == other->rectangle_int.y && self->rectangle_int.width == other->rectangle_int.width && self->rectangle_int.height == other->rectangle_int.height ) res = 1; res = op == Py_NE ? !res : res; b = res ? Py_True : Py_False; Py_INCREF(b); return b; } static PyMemberDef RectangleInt_members[] = { {"x", T_INT, sizeof(PyObject), 0, "X coordinate of the left side of the rectangle"}, {"y", T_INT, sizeof(PyObject)+sizeof(int), 0, "Y coordinate of the the top side of the rectangle"}, {"width", T_INT, sizeof(PyObject)+sizeof(int)*2, 0, "width of the rectangle"}, {"height", T_INT, sizeof(PyObject)+sizeof(int)*3, 0, "height of the rectangle"}, {NULL} }; PyTypeObject PycairoRectangleInt_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.RectangleInt", /* tp_name */ sizeof(PycairoRectangleInt), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)rectangle_int_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)rectangle_int_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)PyObject_HashNotImplemented,/* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)rectangle_int_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ RectangleInt_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)rectangle_int_new, /* tp_new */ }; PyObject * PycairoRegion_FromRegion (cairo_region_t *region) { PyObject *o; assert (region != NULL); if (Pycairo_Check_Status (cairo_region_status(region))) { cairo_region_destroy (region); return NULL; } o = PycairoRegion_Type.tp_alloc (&PycairoRegion_Type, 0); if (o) ((PycairoRegion *)o)->region = region; else cairo_region_destroy (region); return o; } static void region_dealloc(PycairoRegion *o) { if (o->region) { cairo_region_destroy(o->region); o->region = NULL; } Py_TYPE(o)->tp_free(o); } static PyObject * region_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *s = NULL; PycairoRectangleInt *rect_obj = NULL; cairo_region_t *region = NULL; cairo_rectangle_int_t *rect = NULL; if (PyArg_ParseTuple(args, "|O!:Region.__new__", &PycairoRectangleInt_Type, &rect_obj)) { if (rect_obj != NULL) { region = cairo_region_create_rectangle(&(rect_obj->rectangle_int)); } } else if (!PyArg_ParseTuple(args, "|O:Region.__new__", &s)) { PyErr_SetString(PyExc_TypeError, "argument must be a RectangleInt or a sequence of RectangleInt."); return NULL; } PyErr_Clear(); /* Clear possible err in the 1st arg parser. */ /* list of rectangle_int or no args */ if (s != NULL) { Py_ssize_t i, rect_size; PyObject *seq = NULL; seq = PySequence_Fast (s, "argument must be a RectangleInt or a sequence of RectangleInt."); if (seq == NULL) { return NULL; } rect_size = PySequence_Fast_GET_SIZE(seq); if (rect_size > INT_MAX) { Py_DECREF (seq); PyErr_SetString (PyExc_ValueError, "sequence too large"); return NULL; } rect = PyMem_Malloc ((unsigned int)rect_size * sizeof(cairo_rectangle_int_t)); if (rect == NULL) { Py_DECREF(seq); return PyErr_NoMemory(); } for(i=0; irectangle_int; } region = cairo_region_create_rectangles(rect, (int)rect_size); Py_DECREF(seq); PyMem_Free(rect); } if (region == NULL) { region = cairo_region_create(); } RETURN_NULL_IF_CAIRO_REGION_ERROR(region); return PycairoRegion_FromRegion(region); } static PyObject * region_copy (PycairoRegion *o) { cairo_region_t *res; Py_BEGIN_ALLOW_THREADS; res = cairo_region_copy (o->region); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_REGION_ERROR(res); return PycairoRegion_FromRegion(res); } static PyObject * region_get_extents (PycairoRegion *o) { cairo_rectangle_int_t rect; Py_BEGIN_ALLOW_THREADS; cairo_region_get_extents(o->region, &rect); Py_END_ALLOW_THREADS; return PycairoRectangleInt_FromRectangleInt(&rect); } static PyObject * region_num_rectangles (PycairoRegion *o) { int res; Py_BEGIN_ALLOW_THREADS; res = cairo_region_num_rectangles(o->region); Py_END_ALLOW_THREADS; return PYCAIRO_PyLong_FromLong(res); } static PyObject * region_get_rectangle (PycairoRegion *o, PyObject *args) { cairo_rectangle_int_t rect; int i; int total; if (!PyArg_ParseTuple (args, "i:Region.get_rectangle", &i)) return NULL; total = cairo_region_num_rectangles(o->region); if (i >= total || i < 0) { if ( i < 0) PyErr_SetString(PyExc_ValueError, "index must be a positive number"); else PyErr_SetString(PyExc_ValueError, "index is to big for the region"); return NULL; } Py_BEGIN_ALLOW_THREADS; cairo_region_get_rectangle(o->region, i, &rect); Py_END_ALLOW_THREADS; return PycairoRectangleInt_FromRectangleInt(&rect); } static PyObject * region_is_empty (PycairoRegion *o) { cairo_bool_t res; PyObject *b; Py_BEGIN_ALLOW_THREADS; res = cairo_region_is_empty(o->region); Py_END_ALLOW_THREADS; b = res ? Py_True : Py_False; Py_INCREF(b); return b; } static PyObject * region_contains_point (PycairoRegion *o, PyObject *args) { int x, y; cairo_bool_t res; PyObject *b; if (!PyArg_ParseTuple (args, "ii:Region.contains_point", &x, &y)) return NULL; Py_BEGIN_ALLOW_THREADS; res = cairo_region_contains_point(o->region, x, y); Py_END_ALLOW_THREADS; b = res ? Py_True : Py_False; Py_INCREF(b); return b; } static PyObject * region_contains_rectangle (PycairoRegion *o, PyObject *args) { cairo_region_overlap_t res; PycairoRectangleInt *rect_int; if (!PyArg_ParseTuple (args, "O!:Region.contains_rectangle", &PycairoRectangleInt_Type, &rect_int)) return NULL; Py_BEGIN_ALLOW_THREADS; res = cairo_region_contains_rectangle(o->region, &(rect_int->rectangle_int)); Py_END_ALLOW_THREADS; RETURN_INT_ENUM(RegionOverlap, res); } static PyObject * region_equal (PycairoRegion *o, PyObject *args) { cairo_bool_t res; PyObject *b; PycairoRegion *region_obj; if (!PyArg_ParseTuple (args, "O!:Region.equal", &PycairoRegion_Type, ®ion_obj)) return NULL; Py_BEGIN_ALLOW_THREADS; res = cairo_region_equal (o->region, region_obj->region); Py_END_ALLOW_THREADS; b = res ? Py_True : Py_False; Py_INCREF(b); return b; } static PyObject * region_richcompare(PycairoRegion *self, PycairoRegion *other, int op) { int res = 0; PyObject *b; if (op != Py_EQ && op != Py_NE) { PyErr_SetString(PyExc_TypeError, "Only support testing for == or !="); return NULL; } if (!PyObject_TypeCheck((PyObject*)other, &PycairoRegion_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } else { res = cairo_region_equal (self->region, other->region); } res = op == Py_NE ? !res : res; b = res ? Py_True : Py_False; Py_INCREF(b); return b; } static PyObject * region_translate (PycairoRegion *o, PyObject *args) { int x, y; if (!PyArg_ParseTuple (args, "ii:Region.translate", &x, &y)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_region_translate (o->region, x, y); Py_END_ALLOW_THREADS; Py_RETURN_NONE; } static PyObject * region_intersect (PycairoRegion *o, PyObject *args) { cairo_status_t res; PyObject *other; if (!PyArg_ParseTuple (args, "O:Region.intersect", &other)) return NULL; if (PyObject_TypeCheck(other, &PycairoRegion_Type)) { Py_BEGIN_ALLOW_THREADS; res = cairo_region_intersect(o->region, ((PycairoRegion *)other)->region); Py_END_ALLOW_THREADS; } else if (PyObject_TypeCheck(other, &PycairoRectangleInt_Type)) { Py_BEGIN_ALLOW_THREADS; res = cairo_region_intersect_rectangle(o->region, &(((PycairoRectangleInt *)other)->rectangle_int)); Py_END_ALLOW_THREADS; } else { PyErr_SetString(PyExc_TypeError, "argument must be a Region or a RectangleInt."); return NULL; } RETURN_NULL_IF_CAIRO_ERROR(res); Py_RETURN_NONE; } static PyObject * region_subtract (PycairoRegion *o, PyObject *args) { cairo_status_t res; PyObject *other; if (!PyArg_ParseTuple (args, "O:Region.subtract", &other)) return NULL; if (PyObject_TypeCheck(other, &PycairoRegion_Type)) { Py_BEGIN_ALLOW_THREADS; res = cairo_region_subtract(o->region, ((PycairoRegion *)other)->region); Py_END_ALLOW_THREADS; } else if (PyObject_TypeCheck(other, &PycairoRectangleInt_Type)) { Py_BEGIN_ALLOW_THREADS; res = cairo_region_subtract_rectangle(o->region, &(((PycairoRectangleInt *)other)->rectangle_int)); Py_END_ALLOW_THREADS; } else { PyErr_SetString(PyExc_TypeError, "argument must be a Region or a RectangleInt."); return NULL; } RETURN_NULL_IF_CAIRO_ERROR(res); Py_RETURN_NONE; } static PyObject * region_union (PycairoRegion *o, PyObject *args) { cairo_status_t res; PyObject *other; if (!PyArg_ParseTuple (args, "O:Region.union", &other)) return NULL; if (PyObject_TypeCheck(other, &PycairoRegion_Type)) { Py_BEGIN_ALLOW_THREADS; res = cairo_region_union(o->region, ((PycairoRegion *)other)->region); Py_END_ALLOW_THREADS; } else if (PyObject_TypeCheck(other, &PycairoRectangleInt_Type)) { Py_BEGIN_ALLOW_THREADS; res = cairo_region_union_rectangle(o->region, &(((PycairoRectangleInt *)other)->rectangle_int)); Py_END_ALLOW_THREADS; } else { PyErr_SetString(PyExc_TypeError, "argument must be a Region or a RectangleInt."); return NULL; } RETURN_NULL_IF_CAIRO_ERROR(res); Py_RETURN_NONE; } static PyObject * region_xor (PycairoRegion *o, PyObject *args) { cairo_status_t res; PyObject *other; if (!PyArg_ParseTuple (args, "O:Region.xorg", &other)) return NULL; if (PyObject_TypeCheck(other, &PycairoRegion_Type)) { Py_BEGIN_ALLOW_THREADS; res = cairo_region_xor(o->region, ((PycairoRegion *)other)->region); Py_END_ALLOW_THREADS; } else if (PyObject_TypeCheck(other, &PycairoRectangleInt_Type)) { Py_BEGIN_ALLOW_THREADS; res = cairo_region_xor_rectangle(o->region, &(((PycairoRectangleInt *)other)->rectangle_int)); Py_END_ALLOW_THREADS; } else { PyErr_SetString(PyExc_TypeError, "argument must be a Region or a RectangleInt."); return NULL; } RETURN_NULL_IF_CAIRO_ERROR(res); Py_RETURN_NONE; } static PyMethodDef region_methods[] = { /* methods never exposed in a language binding: * cairo_region_destroy() * cairo_region_get_type() * cairo_region_reference() * * cairo_region_status() * - not needed since Pycairo handles status checking * * _(intersect/subtract/union/xor)_rectangle are merged with the region * ones. */ {"copy", (PyCFunction)region_copy, METH_NOARGS }, {"get_extents", (PyCFunction)region_get_extents, METH_NOARGS }, {"num_rectangles", (PyCFunction)region_num_rectangles, METH_NOARGS }, {"get_rectangle", (PyCFunction)region_get_rectangle, METH_VARARGS }, {"is_empty", (PyCFunction)region_is_empty, METH_NOARGS }, {"contains_point", (PyCFunction)region_contains_point, METH_VARARGS }, {"contains_rectangle", (PyCFunction)region_contains_rectangle, METH_VARARGS }, {"equal", (PyCFunction)region_equal, METH_VARARGS }, {"translate", (PyCFunction)region_translate, METH_VARARGS }, {"intersect", (PyCFunction)region_intersect, METH_VARARGS }, {"subtract", (PyCFunction)region_subtract, METH_VARARGS }, {"union", (PyCFunction)region_union, METH_VARARGS }, {"xor", (PyCFunction)region_xor, METH_VARARGS }, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoRegion_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.Region", /* tp_name */ sizeof(PycairoRegion), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)region_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)PyObject_HashNotImplemented,/* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)region_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ region_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)region_new, /* tp_new */ }; pycairo-1.16.2/cairo/surface.c000066400000000000000000002455541323762421700161660ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2003 James Henstridge * Copyright © 2004-2011 Steven Chaplin * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "private.h" /* Class Surface ---------------------------------------------------------- */ PyObject * PycairoSurface_FromSurface (cairo_surface_t *surface, PyObject *base) { PyTypeObject *type = NULL; PyObject *o; assert (surface != NULL); if (Pycairo_Check_Status (cairo_surface_status (surface))) { cairo_surface_destroy (surface); return NULL; } switch (cairo_surface_get_type (surface)) { #ifdef CAIRO_HAS_IMAGE_SURFACE case CAIRO_SURFACE_TYPE_IMAGE: type = &PycairoImageSurface_Type; break; #endif #ifdef CAIRO_HAS_PDF_SURFACE case CAIRO_SURFACE_TYPE_PDF: type = &PycairoPDFSurface_Type; break; #endif #ifdef CAIRO_HAS_PS_SURFACE case CAIRO_SURFACE_TYPE_PS: type = &PycairoPSSurface_Type; break; #endif #ifdef CAIRO_HAS_RECORDING_SURFACE case CAIRO_SURFACE_TYPE_RECORDING: type = &PycairoRecordingSurface_Type; break; #endif #ifdef CAIRO_HAS_SVG_SURFACE case CAIRO_SURFACE_TYPE_SVG: type = &PycairoSVGSurface_Type; break; #endif #ifdef CAIRO_HAS_WIN32_SURFACE case CAIRO_SURFACE_TYPE_WIN32: type = &PycairoWin32Surface_Type; break; case CAIRO_SURFACE_TYPE_WIN32_PRINTING: type = &PycairoWin32PrintingSurface_Type; break; #endif #ifdef CAIRO_HAS_XCB_SURFACE case CAIRO_SURFACE_TYPE_XCB: type = &PycairoXCBSurface_Type; break; #endif #ifdef CAIRO_HAS_XLIB_SURFACE case CAIRO_SURFACE_TYPE_XLIB: type = &PycairoXlibSurface_Type; break; #endif #ifdef CAIRO_HAS_SCRIPT_SURFACE case CAIRO_SURFACE_TYPE_SCRIPT: type = &PycairoScriptSurface_Type; break; #endif #ifdef CAIRO_HAS_TEE_SURFACE case CAIRO_SURFACE_TYPE_TEE: type = &PycairoTeeSurface_Type; break; #endif default: type = &PycairoSurface_Type; break; } o = type->tp_alloc (type, 0); if (o == NULL) { cairo_surface_destroy (surface); } else { ((PycairoSurface *)o)->surface = surface; Py_XINCREF(base); ((PycairoSurface *)o)->base = base; } return o; } /* for use with * cairo_surface_write_to_png_stream() * cairo_pdf/ps/svg_surface_create_for_stream() */ static cairo_status_t _write_func (void *closure, const unsigned char *data, unsigned int length) { PyGILState_STATE gstate = PyGILState_Ensure(); PyObject *res = PyObject_CallMethod ((PyObject *)closure, "write", "(" PYCAIRO_DATA_FORMAT "#)", data, (Py_ssize_t)length); if (res == NULL) { PyErr_Clear(); /* an exception has occurred, it will be picked up later by * Pycairo_Check_Status() */ PyGILState_Release(gstate); return CAIRO_STATUS_WRITE_ERROR; } Py_DECREF(res); PyGILState_Release(gstate); return CAIRO_STATUS_SUCCESS; } static const cairo_user_data_key_t surface_base_object_key; static const cairo_user_data_key_t surface_is_mapped_image; static void surface_dealloc (PycairoSurface *o) { if (o->surface) { if (cairo_surface_get_user_data ( o->surface, &surface_is_mapped_image) == NULL) { cairo_surface_destroy(o->surface); } o->surface = NULL; } Py_CLEAR(o->base); Py_TYPE(o)->tp_free(o); } static void _decref_destroy_func(void *user_data) { PyGILState_STATE gstate = PyGILState_Ensure(); Py_DECREF(user_data); PyGILState_Release(gstate); } /* Like PycairoSurface_FromSurface, but keeps the base object alive as long * as cairo_surface_t exists and not as long as the wrapper exists. */ static PyObject * _surface_create_with_object(cairo_surface_t *surface, PyObject *base) { PyObject *pysurface; cairo_status_t status; pysurface = PycairoSurface_FromSurface(surface, NULL); if (pysurface == NULL) return NULL; if (base != NULL) { status = cairo_surface_set_user_data( surface, &surface_base_object_key, base, _decref_destroy_func); if (status != CAIRO_STATUS_SUCCESS) Py_DECREF(pysurface); RETURN_NULL_IF_CAIRO_ERROR(status); Py_INCREF(base); } return pysurface; } static PyObject * surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { PyErr_SetString(PyExc_TypeError, "The Surface type cannot be instantiated"); return NULL; } static PyObject * surface_copy_page (PycairoSurface *o) { Py_BEGIN_ALLOW_THREADS; cairo_surface_copy_page (o->surface); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); Py_RETURN_NONE; } static PyObject * surface_create_similar (PycairoSurface *o, PyObject *args) { cairo_content_t content; int width, height, content_arg; if (!PyArg_ParseTuple (args, "iii:Surface.create_similar", &content_arg, &width, &height)) return NULL; content = (cairo_content_t)content_arg; return PycairoSurface_FromSurface ( cairo_surface_create_similar (o->surface, content, width, height), NULL); } static PyObject * surface_finish (PycairoSurface *o) { cairo_surface_finish (o->surface); Py_CLEAR(o->base); RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); Py_RETURN_NONE; } static PyObject * surface_flush (PycairoSurface *o) { Py_BEGIN_ALLOW_THREADS; cairo_surface_flush (o->surface); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); Py_RETURN_NONE; } static PyObject * surface_get_content (PycairoSurface *o) { RETURN_INT_ENUM (Content, cairo_surface_get_content (o->surface)); } static PyObject * surface_get_device_offset (PycairoSurface *o) { double x_offset, y_offset; cairo_surface_get_device_offset (o->surface, &x_offset, &y_offset); return Py_BuildValue("(dd)", x_offset, y_offset); } static PyObject * surface_get_device_scale (PycairoSurface *o) { double x_scale, y_scale; cairo_surface_get_device_scale (o->surface, &x_scale, &y_scale); return Py_BuildValue("(dd)", x_scale, y_scale); } static PyObject * surface_get_fallback_resolution (PycairoSurface *o) { double x_ppi, y_ppi; cairo_surface_get_fallback_resolution (o->surface, &x_ppi, &y_ppi); return Py_BuildValue("(dd)", x_ppi, y_ppi); } static PyObject * surface_get_font_options (PycairoSurface *o) { cairo_font_options_t *options = cairo_font_options_create(); cairo_surface_get_font_options (o->surface, options); /* there is no reference fn */ return PycairoFontOptions_FromFontOptions (options); } static PyObject * surface_get_device (PycairoSurface *o) { cairo_device_t *device = cairo_surface_get_device (o->surface); if (device == NULL) Py_RETURN_NONE; return PycairoDevice_FromDevice (cairo_device_reference (device)); } static PyObject * surface_mark_dirty (PycairoSurface *o) { cairo_surface_mark_dirty (o->surface); RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); Py_RETURN_NONE; } static PyObject * surface_mark_dirty_rectangle (PycairoSurface *o, PyObject *args) { int x, y, width, height; if (!PyArg_ParseTuple(args, "iiii:Surface.mark_dirty_rectangle", &x, &y, &width, &height)) return NULL; cairo_surface_mark_dirty_rectangle (o->surface, x, y, width, height); RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); Py_RETURN_NONE; } static PyObject * surface_set_device_offset (PycairoSurface *o, PyObject *args) { double x_offset, y_offset; if (!PyArg_ParseTuple (args, "dd:Surface.set_device_offset", &x_offset, &y_offset)) return NULL; cairo_surface_set_device_offset (o->surface, x_offset, y_offset); Py_RETURN_NONE; } static PyObject * surface_set_device_scale (PycairoSurface *o, PyObject *args) { double x_scale, y_scale; cairo_matrix_t transform; if (!PyArg_ParseTuple (args, "dd:Surface.set_device_scale", &x_scale, &y_scale)) return NULL; /* cairo asserts the following without reporting an error back. * Since we don't want things to crash in Python replicate the logic here. */ cairo_matrix_init_scale (&transform, x_scale, y_scale); RETURN_NULL_IF_CAIRO_ERROR (cairo_matrix_invert (&transform)); cairo_surface_set_device_scale (o->surface, x_scale, y_scale); Py_RETURN_NONE; } static PyObject * surface_set_fallback_resolution (PycairoSurface *o, PyObject *args) { double x_ppi, y_ppi; if (!PyArg_ParseTuple(args, "dd:Surface.set_fallback_resolution", &x_ppi, &y_ppi)) return NULL; cairo_surface_set_fallback_resolution (o->surface, x_ppi, y_ppi); Py_RETURN_NONE; } static PyObject * surface_create_for_rectangle (PycairoSurface *o, PyObject *args) { double x, y, width, height; cairo_surface_t *new; if (!PyArg_ParseTuple(args, "dddd:Surface.create_for_rectangle", &x, &y, &width, &height)) return NULL; Py_BEGIN_ALLOW_THREADS; new = cairo_surface_create_for_rectangle(o->surface, x, y, width, height); Py_END_ALLOW_THREADS; return PycairoSurface_FromSurface(new, NULL); } static PyObject * surface_show_page (PycairoSurface *o) { Py_BEGIN_ALLOW_THREADS; cairo_surface_show_page (o->surface); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); Py_RETURN_NONE; } static PyObject * surface_create_similar_image (PycairoSurface *o, PyObject *args) { cairo_format_t format; int width, height, format_arg; cairo_surface_t *new; if (!PyArg_ParseTuple (args, "iii:Surface.create_similar_image", &format_arg, &width, &height)) return NULL; format = (cairo_format_t)format_arg; Py_BEGIN_ALLOW_THREADS; new = cairo_surface_create_similar_image (o->surface, format, width, height); Py_END_ALLOW_THREADS; return PycairoSurface_FromSurface (new, NULL); } #ifdef CAIRO_HAS_PNG_FUNCTIONS static PyObject * surface_write_to_png (PycairoSurface *o, PyObject *args) { cairo_status_t status; char *name = NULL; PyObject *file; if (!PyArg_ParseTuple (args, "O:Surface.write_to_png", &file)) return NULL; if (Pycairo_is_fspath (file)) { if (!PyArg_ParseTuple (args, "O&:Surface.write_to_png", Pycairo_fspath_converter, &name)) return NULL; Py_BEGIN_ALLOW_THREADS; status = cairo_surface_write_to_png (o->surface, name); Py_END_ALLOW_THREADS; PyMem_Free (name); } else { if (PyArg_ParseTuple (args, "O&:Surface.write_to_png", Pycairo_writer_converter, &file)) { Py_BEGIN_ALLOW_THREADS; status = cairo_surface_write_to_png_stream (o->surface, _write_func, file); Py_END_ALLOW_THREADS; } else { PyErr_Clear (); PyErr_SetString (PyExc_TypeError, "Surface.write_to_png takes one argument which must be " "a filename, file object, or a file-like object " "which has a \"write\" method (like StringIO)"); return NULL; } } RETURN_NULL_IF_CAIRO_ERROR (status); Py_RETURN_NONE; } #endif /* CAIRO_HAS_PNG_FUNCTIONS */ static void _destroy_mime_user_data_func (PyObject *user_data) { PyGILState_STATE gstate = PyGILState_Ensure(); Py_DECREF(user_data); PyGILState_Release(gstate); } static void _destroy_mime_data_func (PyObject *user_data) { cairo_surface_t *surface; PyObject *mime_intern; PyGILState_STATE gstate = PyGILState_Ensure(); /* Remove the user data holding the source object */ surface = PyCapsule_GetPointer(PyTuple_GET_ITEM(user_data, 0), NULL); mime_intern = PyTuple_GET_ITEM(user_data, 2); cairo_surface_set_user_data( surface, (cairo_user_data_key_t *)mime_intern, NULL, NULL); /* Destroy the user data */ _destroy_mime_user_data_func(user_data); PyGILState_Release(gstate); } static PyObject * surface_set_mime_data (PycairoSurface *o, PyObject *args) { PyObject *obj, *user_data, *mime_intern, *capsule; const unsigned char *buffer; const char *mime_type; Py_ssize_t buffer_len; int res; cairo_status_t status; if (!PyArg_ParseTuple(args, "sO:Surface.set_mime_data", &mime_type, &obj)) return NULL; if (obj == Py_None) { status = cairo_surface_set_mime_data ( o->surface, mime_type, NULL, 0, NULL, NULL); RETURN_NULL_IF_CAIRO_ERROR(status); Py_RETURN_NONE; } res = PyObject_AsReadBuffer (obj, (const void **)&buffer, &buffer_len); if (res == -1) return NULL; /* We use the interned mime type string as user data key and store the * passed in object with it. This allows us to return the same object in * surface_get_mime_data(). */ mime_intern = PYCAIRO_PyUnicode_InternFromString(mime_type); capsule = PyCapsule_New(o->surface, NULL, NULL); user_data = Py_BuildValue("(NOO)", capsule, obj, mime_intern); if (user_data == NULL) return NULL; status = cairo_surface_set_user_data( o->surface, (cairo_user_data_key_t *)mime_intern, user_data, (cairo_destroy_func_t)_destroy_mime_user_data_func); if (status != CAIRO_STATUS_SUCCESS) Py_DECREF(user_data); RETURN_NULL_IF_CAIRO_ERROR(status); status = cairo_surface_set_mime_data ( o->surface, mime_type, buffer, (unsigned long)buffer_len, (cairo_destroy_func_t)_destroy_mime_data_func, user_data); if (status != CAIRO_STATUS_SUCCESS) { cairo_surface_set_user_data( o->surface, (cairo_user_data_key_t *)mime_intern, NULL, NULL); } RETURN_NULL_IF_CAIRO_ERROR(status); Py_INCREF(user_data); Py_RETURN_NONE; } static PyObject * surface_get_mime_data (PycairoSurface *o, PyObject *args) { PyObject *user_data, *obj, *mime_intern; const char *mime_type; const unsigned char *buffer; unsigned long buffer_len; if (!PyArg_ParseTuple(args, "s:Surface.get_mime_data", &mime_type)) return NULL; cairo_surface_get_mime_data (o->surface, mime_type, &buffer, &buffer_len); if (buffer == NULL) { Py_RETURN_NONE; } mime_intern = PYCAIRO_PyUnicode_InternFromString(mime_type); user_data = cairo_surface_get_user_data( o->surface, (cairo_user_data_key_t *)mime_intern); if (user_data == NULL) { /* In case the mime data wasn't set through the Python API just copy it */ return Py_BuildValue(PYCAIRO_DATA_FORMAT "#", buffer, buffer_len); } else { obj = PyTuple_GET_ITEM(user_data, 1); Py_INCREF(obj); return obj; } } static PyObject * surface_supports_mime_type (PycairoSurface *self, PyObject *args) { const char *mime_type; if (!PyArg_ParseTuple(args, "s:Surface.supports_mime_type", &mime_type)) return NULL; return PyBool_FromLong( cairo_surface_supports_mime_type(self->surface, mime_type)); } static PyObject * surface_has_show_text_glyphs (PycairoSurface *o) { cairo_bool_t result; Py_BEGIN_ALLOW_THREADS; result = cairo_surface_has_show_text_glyphs (o->surface); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_SURFACE_ERROR (o->surface); return PyBool_FromLong (result); } #ifdef CAIRO_HAS_IMAGE_SURFACE static PyObject * surface_map_to_image (PycairoSurface *self, PyObject *args) { PyObject *pyextents, *pymapped; cairo_rectangle_int_t *extents; cairo_surface_t *mapped_surface; if (!PyArg_ParseTuple(args, "O:Surface.map_to_image", &pyextents)) return NULL; if (PyObject_TypeCheck (pyextents, &PycairoRectangleInt_Type)) { extents = &(((PycairoRectangleInt *)pyextents)->rectangle_int); } else { if (pyextents == Py_None) { extents = NULL; } else { PyErr_SetString (PyExc_TypeError, "argument must be a RectangleInt or None."); return NULL; } } Py_BEGIN_ALLOW_THREADS; mapped_surface = cairo_surface_map_to_image (self->surface, extents); Py_END_ALLOW_THREADS; if (Pycairo_Check_Status (cairo_surface_status (mapped_surface))) { cairo_surface_destroy (mapped_surface); return NULL; } /* So we can skip the destroy() call in the base tp_dealloc */ cairo_surface_set_user_data ( mapped_surface, &surface_is_mapped_image, (void*)1, NULL); pymapped = PycairoMappedImageSurface_Type.tp_alloc ( &PycairoMappedImageSurface_Type, 0); if (pymapped == NULL) { Py_BEGIN_ALLOW_THREADS; cairo_surface_unmap_image (self->surface, mapped_surface); Py_END_ALLOW_THREADS; return NULL; } ((PycairoSurface *)pymapped)->surface = mapped_surface; Py_XINCREF (self); ((PycairoSurface *)pymapped)->base = (PyObject *)self; return pymapped; } static PyObject * surface_unmap_image (PycairoSurface *self, PyObject *args) { PycairoSurface *pymapped; cairo_surface_t *base_surface, *fake_surface; if (!PyArg_ParseTuple(args, "O!:Surface.unmap_image", &PycairoMappedImageSurface_Type, &pymapped)) return NULL; if (cairo_surface_get_user_data (pymapped->surface, &surface_is_mapped_image) == NULL) { PyErr_SetString (PyExc_RuntimeError, "MappedImageSurface was already unmapped"); return NULL; } base_surface = ((PycairoSurface *)(pymapped->base))->surface; if (base_surface != self->surface) { PyErr_SetString (PyExc_ValueError, "ImageSurface isn't mapped from this surface"); return NULL; } Py_BEGIN_ALLOW_THREADS; cairo_surface_unmap_image (self->surface, pymapped->surface); Py_END_ALLOW_THREADS; /* Replace the mapped image surface with a fake one and finish it so * that any operation on it fails. */ fake_surface = cairo_image_surface_create (CAIRO_FORMAT_INVALID, 0, 0); cairo_surface_finish (fake_surface); pymapped->surface = fake_surface; /* We no longer need the base surface */ Py_CLEAR(pymapped->base); Py_RETURN_NONE; } #endif /* CAIRO_HAS_IMAGE_SURFACE */ static PyMethodDef surface_methods[] = { /* methods never exposed in a language binding: * cairo_surface_destroy() * cairo_surface_get_type() * cairo_surface_get_user_data() * cairo_surface_reference() * cairo_surface_set_user_data() */ {"copy_page", (PyCFunction)surface_copy_page, METH_NOARGS}, {"create_similar", (PyCFunction)surface_create_similar, METH_VARARGS}, {"create_similar_image", (PyCFunction)surface_create_similar_image, METH_VARARGS}, {"finish", (PyCFunction)surface_finish, METH_NOARGS}, {"flush", (PyCFunction)surface_flush, METH_NOARGS}, {"get_content", (PyCFunction)surface_get_content, METH_NOARGS}, {"get_device_offset",(PyCFunction)surface_get_device_offset,METH_NOARGS}, {"get_device_scale", (PyCFunction)surface_get_device_scale, METH_NOARGS}, {"get_fallback_resolution",(PyCFunction)surface_get_fallback_resolution, METH_NOARGS}, {"get_font_options",(PyCFunction)surface_get_font_options, METH_NOARGS}, {"get_device", (PyCFunction)surface_get_device, METH_NOARGS}, {"mark_dirty", (PyCFunction)surface_mark_dirty, METH_NOARGS}, {"mark_dirty_rectangle", (PyCFunction)surface_mark_dirty_rectangle, METH_VARARGS}, {"set_device_offset",(PyCFunction)surface_set_device_offset,METH_VARARGS}, {"set_device_scale", (PyCFunction)surface_set_device_scale, METH_VARARGS}, {"set_fallback_resolution",(PyCFunction)surface_set_fallback_resolution, METH_VARARGS}, {"show_page", (PyCFunction)surface_show_page, METH_NOARGS}, #ifdef CAIRO_HAS_PNG_FUNCTIONS {"write_to_png", (PyCFunction)surface_write_to_png, METH_VARARGS}, #endif {"set_mime_data", (PyCFunction)surface_set_mime_data, METH_VARARGS}, {"get_mime_data", (PyCFunction)surface_get_mime_data, METH_VARARGS}, {"supports_mime_type", (PyCFunction)surface_supports_mime_type, METH_VARARGS}, {"create_for_rectangle",(PyCFunction)surface_create_for_rectangle, METH_VARARGS}, {"has_show_text_glyphs", (PyCFunction)surface_has_show_text_glyphs, METH_NOARGS}, #ifdef CAIRO_HAS_IMAGE_SURFACE {"map_to_image", (PyCFunction)surface_map_to_image, METH_VARARGS}, {"unmap_image", (PyCFunction)surface_unmap_image, METH_VARARGS}, #endif {NULL, NULL, 0, NULL}, }; static PyObject* surface_richcompare (PyObject *self, PyObject *other, int op) { if (Py_TYPE(self) == Py_TYPE(other)) return Pycairo_richcompare ( ((PycairoSurface *)self)->surface, ((PycairoSurface *)other)->surface, op); else { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } } static PYCAIRO_Py_hash_t surface_hash (PyObject *self) { return PYCAIRO_Py_hash_t_FromVoidPtr (((PycairoSurface *)self)->surface); } PyTypeObject PycairoSurface_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.Surface", /* tp_name */ sizeof(PycairoSurface), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)surface_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ surface_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,/* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ surface_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ surface_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)surface_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; /* Class ImageSurface(Surface) -------------------------------------------- */ #ifdef CAIRO_HAS_IMAGE_SURFACE static PyObject * image_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { cairo_format_t format; int width, height, format_arg; if (!PyArg_ParseTuple (args, "iii:ImageSurface.__new__", &format_arg, &width, &height)) return NULL; format = (cairo_format_t)format_arg; return PycairoSurface_FromSurface ( cairo_image_surface_create (format, width, height), NULL); } /* METH_CLASS */ static PyObject * image_surface_create_for_data (PyTypeObject *type, PyObject *args) { cairo_surface_t *surface; cairo_format_t format; unsigned char *buffer; int width, height, stride = -1, res, format_arg; Py_ssize_t buffer_len; PyObject *obj; if (!PyArg_ParseTuple (args, "Oiii|i:ImageSurface.create_for_data", &obj, &format_arg, &width, &height, &stride)) return NULL; format = (cairo_format_t)format_arg; res = PyObject_AsWriteBuffer (obj, (void **)&buffer, &buffer_len); if (res == -1) return NULL; if (width <= 0) { PyErr_SetString(PyExc_ValueError, "width must be positive"); return NULL; } if (height <= 0) { PyErr_SetString(PyExc_ValueError, "height must be positive"); return NULL; } /* if stride is missing, calculate it from width */ if (stride < 0) { stride = cairo_format_stride_for_width (format, width); if (stride == -1){ PyErr_SetString(PyExc_ValueError, "format is invalid or the width too large"); return NULL; } } if (height * stride > buffer_len) { PyErr_SetString(PyExc_TypeError, "buffer is not long enough"); return NULL; } Py_BEGIN_ALLOW_THREADS; surface = cairo_image_surface_create_for_data (buffer, format, width, height, stride); Py_END_ALLOW_THREADS; return _surface_create_with_object(surface, obj); } #ifdef CAIRO_HAS_PNG_FUNCTIONS static cairo_status_t _read_func (void *closure, unsigned char *data, unsigned int length) { char *buffer; int ret; Py_ssize_t str_length; cairo_status_t status = CAIRO_STATUS_READ_ERROR; PyGILState_STATE gstate = PyGILState_Ensure(); PyObject *pystr = PyObject_CallMethod ((PyObject *)closure, "read", "(i)", length); if (pystr == NULL) { PyErr_Clear(); /* an exception has occurred, it will be picked up later by * Pycairo_Check_Status() */ goto end; } ret = PYCAIRO_PyBytes_AsStringAndSize(pystr, &buffer, &str_length); if (ret == -1 || str_length < (Py_ssize_t)length) { PyErr_Clear(); goto end; } /* don't use strncpy() since png data may contain NUL bytes */ memcpy (data, buffer, (size_t)str_length); status = CAIRO_STATUS_SUCCESS; end: Py_XDECREF(pystr); PyGILState_Release(gstate); return status; } /* METH_CLASS */ static PyObject * image_surface_create_from_png (PyTypeObject *type, PyObject *args) { cairo_surface_t *image_surface; PyObject *file; char *name; if (!PyArg_ParseTuple (args, "O:ImageSurface.create_from_png", &file)) return NULL; if (Pycairo_is_fspath (file)) { if (!PyArg_ParseTuple(args, "O&:ImageSurface.create_from_png", Pycairo_fspath_converter, &name)) return NULL; Py_BEGIN_ALLOW_THREADS; image_surface = cairo_image_surface_create_from_png (name); Py_END_ALLOW_THREADS; PyMem_Free(name); return PycairoSurface_FromSurface (image_surface, NULL); } else { if (PyArg_ParseTuple (args, "O&:ImageSurface.create_from_png", Pycairo_reader_converter, &file)) { Py_BEGIN_ALLOW_THREADS; image_surface = cairo_image_surface_create_from_png_stream ( _read_func, file); Py_END_ALLOW_THREADS; return PycairoSurface_FromSurface (image_surface, NULL); } else { PyErr_SetString(PyExc_TypeError, "ImageSurface.create_from_png argument must be a " "filename (str), file object, or an object that has a " "\"read\" method (like StringIO)"); return NULL; } } } #endif /* CAIRO_HAS_PNG_FUNCTIONS */ /* METH_STATIC */ static PyObject * image_surface_format_stride_for_width (PyObject *self, PyObject *args) { cairo_format_t format; int width, format_arg; if (!PyArg_ParseTuple (args, "ii:format_stride_for_width", &format_arg, &width)) return NULL; format = (cairo_format_t)format_arg; return PYCAIRO_PyLong_FromLong (cairo_format_stride_for_width (format, width)); } static PyObject * image_surface_get_data (PycairoImageSurface *o) { #if PY_MAJOR_VERSION >= 3 cairo_surface_t *surface; int height, stride; unsigned char * buffer; surface = o->surface; buffer = cairo_image_surface_get_data (surface); if (buffer == NULL) { Py_RETURN_NONE; } height = cairo_image_surface_get_height (surface); stride = cairo_image_surface_get_stride (surface); return buffer_proxy_create_view((PyObject *)o, buffer, height * stride, 0); #else return PyBuffer_FromReadWriteObject((PyObject *)o, 0, Py_END_OF_BUFFER); #endif } static PyObject * image_surface_get_format (PycairoImageSurface *o) { RETURN_INT_ENUM (Format, cairo_image_surface_get_format (o->surface)); } static PyObject * image_surface_get_height (PycairoImageSurface *o) { return PYCAIRO_PyLong_FromLong (cairo_image_surface_get_height (o->surface)); } static PyObject * image_surface_get_stride (PycairoImageSurface *o) { return PYCAIRO_PyLong_FromLong (cairo_image_surface_get_stride (o->surface)); } static PyObject * image_surface_get_width (PycairoImageSurface *o) { return PYCAIRO_PyLong_FromLong (cairo_image_surface_get_width (o->surface)); } #if PY_MAJOR_VERSION < 3 /* Buffer interface functions, used by ImageSurface.get_data() */ static Py_ssize_t image_surface_buffer_getreadbuf (PycairoImageSurface *o, Py_ssize_t segment, const void **ptr) { cairo_surface_t *surface = o->surface; int height, stride; if (segment != 0) { PyErr_SetString(PyExc_SystemError, "accessing non-existent ImageSurface segment"); return -1; } height = cairo_image_surface_get_height (surface); stride = cairo_image_surface_get_stride (surface); *ptr = (void *) cairo_image_surface_get_data (surface); return height * stride; } static Py_ssize_t image_surface_buffer_getwritebuf (PycairoImageSurface *o, Py_ssize_t segment, const void **ptr) { cairo_surface_t *surface = o->surface; int height, stride; if (segment != 0) { PyErr_SetString(PyExc_SystemError, "accessing non-existent ImageSurface segment"); return -1; } height = cairo_image_surface_get_height (surface); stride = cairo_image_surface_get_stride (surface); *ptr = (void *) cairo_image_surface_get_data (surface); return height * stride; } static Py_ssize_t image_surface_buffer_getsegcount (PycairoImageSurface *o, Py_ssize_t *lenp) { if (lenp) { /* report the sum of the sizes (in bytes) of all segments */ cairo_surface_t *surface = o->surface; int height = cairo_image_surface_get_height (surface); int stride = cairo_image_surface_get_stride (surface); *lenp = height * stride; } return 1; /* surface data is all in one segment */ } static Py_ssize_t image_surface_buffer_getcharbuffer (PycairoImageSurface *o, Py_ssize_t segment, char **ptrptr) { Py_ssize_t segment_size; if (segment != 0) { PyErr_SetString(PyExc_SystemError, "accessing non-existent ImageSurface segment"); return -1; } image_surface_buffer_getsegcount (o, &segment_size); return segment_size; } /* See Python C API Manual 10.7 */ static PyBufferProcs image_surface_as_buffer = { (readbufferproc) image_surface_buffer_getreadbuf, (writebufferproc)image_surface_buffer_getwritebuf, (segcountproc) image_surface_buffer_getsegcount, (charbufferproc) image_surface_buffer_getcharbuffer, }; #endif static PyMethodDef image_surface_methods[] = { {"create_for_data",(PyCFunction)image_surface_create_for_data, METH_VARARGS | METH_CLASS}, #ifdef CAIRO_HAS_PNG_FUNCTIONS {"create_from_png", (PyCFunction)image_surface_create_from_png, METH_VARARGS | METH_CLASS}, #endif {"format_stride_for_width", (PyCFunction)image_surface_format_stride_for_width, METH_VARARGS | METH_STATIC}, {"get_data", (PyCFunction)image_surface_get_data, METH_NOARGS}, {"get_format", (PyCFunction)image_surface_get_format, METH_NOARGS}, {"get_height", (PyCFunction)image_surface_get_height, METH_NOARGS}, {"get_stride", (PyCFunction)image_surface_get_stride, METH_NOARGS}, {"get_width", (PyCFunction)image_surface_get_width, METH_NOARGS}, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoImageSurface_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.ImageSurface", /* tp_name */ sizeof(PycairoImageSurface), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ #if PY_MAJOR_VERSION < 3 &image_surface_as_buffer, /* tp_as_buffer */ #else 0, /* tp_as_buffer */ #endif #if PY_MAJOR_VERSION < 3 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */ #else Py_TPFLAGS_DEFAULT, /* tp_flags */ #endif 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ image_surface_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoSurface_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)image_surface_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; /* Mapped Image Type*/ static PyObject * mapped_image_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { PyErr_SetString(PyExc_TypeError, "The MappedImage type cannot be instantiated"); return NULL; } static void mapped_image_surface_dealloc (PycairoImageSurface *self) { PycairoSurface *pybasesurface = (PycairoSurface *)(self->base); if (cairo_surface_get_user_data ( self->surface, &surface_is_mapped_image) != NULL) { cairo_surface_unmap_image (pybasesurface->surface, self->surface); } Py_TYPE (self)->tp_free (self); } static PyObject * mapped_image_surface_finish (PycairoSurface *self) { PyErr_SetString(PyExc_RuntimeError, "The MappedImage type cannot be finished, " "use Surface.unmap_image instead"); return NULL; } static PyMethodDef mapped_image_surface_methods[] = { {"finish", (PyCFunction)mapped_image_surface_finish, METH_NOARGS}, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoMappedImageSurface_Type = { PyVarObject_HEAD_INIT(NULL, 0) "__cairo__.MappedImageSurface", /* tp_name */ sizeof(PycairoImageSurface), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor) mapped_image_surface_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ PyObject_HashNotImplemented, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ mapped_image_surface_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoImageSurface_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)mapped_image_surface_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; #endif /* CAIRO_HAS_IMAGE_SURFACE */ /* Class PDFSurface(Surface) ---------------------------------------------- */ #ifdef CAIRO_HAS_PDF_SURFACE #include static PyObject * pdf_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { double width_in_points, height_in_points; PyObject *file; cairo_surface_t *sfc; char *name; if (!PyArg_ParseTuple (args, "Odd:PDFSurface.__new__", &file, &width_in_points, &height_in_points)) return NULL; if (Pycairo_is_fspath (file) || file == Py_None) { if (!PyArg_ParseTuple (args, "O&dd:PDFSurface.__new__", Pycairo_fspath_none_converter, &name, &width_in_points, &height_in_points)) return NULL; Py_BEGIN_ALLOW_THREADS; sfc = cairo_pdf_surface_create (name, width_in_points, height_in_points); Py_END_ALLOW_THREADS; PyMem_Free(name); return PycairoSurface_FromSurface (sfc, NULL); } else { if (PyArg_ParseTuple (args, "O&dd:PDFSurface.__new__", Pycairo_writer_converter, &file, &width_in_points, &height_in_points)) { Py_BEGIN_ALLOW_THREADS; sfc = cairo_pdf_surface_create_for_stream ( _write_func, file, width_in_points, height_in_points); Py_END_ALLOW_THREADS; return _surface_create_with_object (sfc, file); } else { PyErr_Clear (); PyErr_SetString(PyExc_TypeError, "PDFSurface argument 1 must be " "None, or a filename (str), or " "a file object, or an object that has a " "\"write\" method (like StringIO)."); return NULL; } } } static PyObject * pdf_surface_set_size (PycairoPDFSurface *o, PyObject *args) { double width_in_points, height_in_points; if (!PyArg_ParseTuple(args, "dd:PDFSurface.set_size", &width_in_points, &height_in_points)) return NULL; cairo_pdf_surface_set_size (o->surface, width_in_points, height_in_points); Py_RETURN_NONE; } static PyObject * pdf_get_versions (PyObject *self) { PyObject *list, *num; const cairo_pdf_version_t *versions; int i, num_versions; Py_BEGIN_ALLOW_THREADS; cairo_pdf_get_versions (&versions, &num_versions); Py_END_ALLOW_THREADS; list = PyList_New (num_versions); if (list == NULL) return NULL; for (i=0; i < num_versions; i++) { num = CREATE_INT_ENUM (PDFVersion, versions[i]); if (num == NULL) { Py_DECREF (list); return NULL; } PyList_SET_ITEM (list, i, num); } return list; } static PyObject * pdf_version_to_string (PyObject *self, PyObject *args) { cairo_pdf_version_t version; int version_arg; const char *version_string; if (!PyArg_ParseTuple (args, "i:PDFSurface.version_to_string", &version_arg)) return NULL; version = (cairo_pdf_version_t)version_arg; Py_BEGIN_ALLOW_THREADS; version_string = cairo_pdf_version_to_string (version); Py_END_ALLOW_THREADS; if (version_string == NULL) { PyErr_SetString (PyExc_ValueError, "invalid version"); return NULL; } return PYCAIRO_PyUnicode_FromString (version_string); } static PyObject * pdf_surface_restrict_to_version (PycairoPDFSurface *o, PyObject *args) { cairo_pdf_version_t version; int version_arg; if (!PyArg_ParseTuple (args, "i:PDFSurface.restrict_to_version", &version_arg)) return NULL; version = (cairo_pdf_version_t)version_arg; Py_BEGIN_ALLOW_THREADS; cairo_pdf_surface_restrict_to_version (o->surface, version); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_SURFACE_ERROR (o->surface); Py_RETURN_NONE; } static PyMethodDef pdf_surface_methods[] = { {"set_size", (PyCFunction)pdf_surface_set_size, METH_VARARGS}, {"get_versions", (PyCFunction)pdf_get_versions, METH_NOARGS | METH_STATIC}, {"version_to_string", (PyCFunction)pdf_version_to_string, METH_VARARGS | METH_STATIC}, {"restrict_to_version", (PyCFunction)pdf_surface_restrict_to_version, METH_VARARGS}, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoPDFSurface_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.PDFSurface", /* tp_name */ sizeof(PycairoPDFSurface), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ pdf_surface_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoSurface_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)pdf_surface_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; #endif /* CAIRO_HAS_PDF_SURFACE */ #ifdef CAIRO_HAS_SCRIPT_SURFACE #include typedef PycairoSurface PycairoScriptSurface; static PyObject * script_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { cairo_content_t content; int content_arg; double width, height; PyObject *pydevice; if (!PyArg_ParseTuple (args, "O!idd:ScriptSurface.__new__", &PycairoScriptDevice_Type, &pydevice, &content_arg, &width, &height)) return NULL; content = (cairo_content_t)content_arg; return PycairoSurface_FromSurface ( cairo_script_surface_create ( ((PycairoDevice*)pydevice)->device, content, width, height), NULL); } static PyObject * script_surface_create_for_target (PyTypeObject *type, PyObject *args) { PyObject *pydevice, *target; if (!PyArg_ParseTuple (args, "O!O!:ScriptSurface.create_for_target", &PycairoScriptDevice_Type, &pydevice, &PycairoSurface_Type, &target)) return NULL; return PycairoSurface_FromSurface ( cairo_script_surface_create_for_target ( ((PycairoDevice*)pydevice)->device, ((PycairoSurface*)target)->surface), NULL); } static PyMethodDef script_surface_methods[] = { {"create_for_target", (PyCFunction)script_surface_create_for_target, METH_VARARGS | METH_CLASS}, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoScriptSurface_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.ScriptSurface", /* tp_name */ sizeof(PycairoScriptSurface), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ script_surface_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoSurface_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)script_surface_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; #endif /* CAIRO_HAS_SCRIPT_SURFACE */ /* Class PSSurface(Surface) ----------------------------------------------- */ #ifdef CAIRO_HAS_PS_SURFACE #include static PyObject * ps_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { double width_in_points, height_in_points; PyObject *file; cairo_surface_t *sfc; char *name; if (!PyArg_ParseTuple (args, "Odd:PSSurface.__new__", &file, &width_in_points, &height_in_points)) return NULL; if (Pycairo_is_fspath (file) || file == Py_None) { if (!PyArg_ParseTuple (args, "O&dd:PSSurface.__new__", Pycairo_fspath_none_converter, &name, &width_in_points, &height_in_points)) return NULL; Py_BEGIN_ALLOW_THREADS; sfc = cairo_ps_surface_create (name, width_in_points, height_in_points); Py_END_ALLOW_THREADS; PyMem_Free(name); return PycairoSurface_FromSurface (sfc, NULL); } else { if (PyArg_ParseTuple (args, "O&dd:PSSurface.__new__", Pycairo_writer_converter, &file, &width_in_points, &height_in_points)) { Py_BEGIN_ALLOW_THREADS; sfc = cairo_ps_surface_create_for_stream ( _write_func, file, width_in_points, height_in_points); Py_END_ALLOW_THREADS; return _surface_create_with_object (sfc, file); } else { PyErr_Clear (); PyErr_SetString(PyExc_TypeError, "PSSurface argument 1 must be " "None, or a filename (str), or " "a file object, or an object that has a " "\"write\" method (like StringIO)."); return NULL; } } } static PyObject * ps_surface_dsc_begin_page_setup (PycairoPSSurface *o) { cairo_ps_surface_dsc_begin_page_setup (o->surface); RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); Py_RETURN_NONE; } static PyObject * ps_surface_dsc_begin_setup (PycairoPSSurface *o) { cairo_ps_surface_dsc_begin_setup (o->surface); RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); Py_RETURN_NONE; } static PyObject * ps_surface_dsc_comment (PycairoPSSurface *o, PyObject *args) { const char *comment; if (!PyArg_ParseTuple(args, "s:PSSurface.dsc_comment", &comment)) return NULL; cairo_ps_surface_dsc_comment (o->surface, comment); RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); Py_RETURN_NONE; } static PyObject * ps_surface_get_eps (PycairoPSSurface *o) { PyObject *eps = cairo_ps_surface_get_eps (o->surface) ? Py_True : Py_False; RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); Py_INCREF(eps); return eps; } /* METH_STATIC */ static PyObject * ps_level_to_string (PyObject *self, PyObject *args) { cairo_ps_level_t level; int level_arg; const char *s; if (!PyArg_ParseTuple (args, "i:PSSurface.level_to_string", &level_arg)) return NULL; level = (cairo_ps_level_t)level_arg; s = cairo_ps_level_to_string (level); if (s == NULL){ PyErr_SetString(PyExc_ValueError, "level_to_string: " "invalid level argument"); return NULL; } return PYCAIRO_PyUnicode_FromString(s); } static PyObject * ps_surface_restrict_to_level (PycairoPSSurface *o, PyObject *args) { cairo_ps_level_t level; int level_arg; if (!PyArg_ParseTuple (args, "i:PSSurface.restrict_to_level", &level_arg)) return NULL; level = (cairo_ps_level_t)level_arg; cairo_ps_surface_restrict_to_level (o->surface, level); RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); Py_RETURN_NONE; } static PyObject * ps_surface_set_eps (PycairoPSSurface *o, PyObject *args) { PyObject *py_eps; if (!PyArg_ParseTuple(args, "O!:PSSurface.set_eps", &PyBool_Type, &py_eps)) return NULL; cairo_ps_surface_set_eps (o->surface, (py_eps == Py_True)); RETURN_NULL_IF_CAIRO_SURFACE_ERROR(o->surface); Py_RETURN_NONE; } static PyObject * ps_surface_set_size (PycairoPSSurface *o, PyObject *args) { double width_in_points, height_in_points; if (!PyArg_ParseTuple(args, "dd:PSSurface.set_size", &width_in_points, &height_in_points)) return NULL; cairo_ps_surface_set_size (o->surface, width_in_points, height_in_points); Py_RETURN_NONE; } static PyObject * ps_get_levels (PyObject *self) { PyObject *list, *num; const cairo_ps_level_t *levels; int i, num_levels; Py_BEGIN_ALLOW_THREADS; cairo_ps_get_levels (&levels, &num_levels); Py_END_ALLOW_THREADS; list = PyList_New (num_levels); if (list == NULL) return NULL; for (i=0; i < num_levels; i++) { num = CREATE_INT_ENUM (PSLevel, levels[i]); if (num == NULL) { Py_DECREF (list); return NULL; } PyList_SET_ITEM (list, i, num); } return list; } static PyMethodDef ps_surface_methods[] = { {"dsc_begin_page_setup", (PyCFunction)ps_surface_dsc_begin_page_setup, METH_NOARGS }, {"dsc_begin_setup", (PyCFunction)ps_surface_dsc_begin_setup, METH_NOARGS }, {"dsc_comment", (PyCFunction)ps_surface_dsc_comment, METH_VARARGS }, {"get_eps", (PyCFunction)ps_surface_get_eps, METH_NOARGS }, {"ps_level_to_string", (PyCFunction)ps_level_to_string, METH_VARARGS | METH_STATIC}, {"level_to_string", (PyCFunction)ps_level_to_string, METH_VARARGS | METH_STATIC}, {"restrict_to_level", (PyCFunction)ps_surface_restrict_to_level, METH_VARARGS }, {"set_eps", (PyCFunction)ps_surface_set_eps, METH_VARARGS }, {"set_size", (PyCFunction)ps_surface_set_size, METH_VARARGS }, {"get_levels", (PyCFunction)ps_get_levels, METH_NOARGS | METH_STATIC}, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoPSSurface_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.PSSurface", /* tp_name */ sizeof(PycairoPSSurface), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ ps_surface_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoSurface_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)ps_surface_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; #endif /* CAIRO_HAS_PS_SURFACE */ /* Class RecordingSurface(Surface) ---------------------------------------- */ #ifdef CAIRO_HAS_RECORDING_SURFACE static PyObject * recording_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { cairo_content_t content; cairo_rectangle_t extents, *extents_ptr; cairo_surface_t *sfc; int content_arg; PyObject *extents_tuple; if (!PyArg_ParseTuple (args, "iO:RecordingSurface.__new__", &content_arg, &extents_tuple)) return NULL; content = (cairo_content_t)content_arg; if (extents_tuple == Py_None) { extents_ptr = NULL; } else { if (!PyArg_ParseTuple(extents_tuple, "dddd", &extents.x, &extents.y, &extents.width, &extents.height)) { PyErr_SetString(PyExc_TypeError, "RecordingSurface() argument 2 must be a " "4-tuple of float"); return NULL; } extents_ptr = &extents; } Py_BEGIN_ALLOW_THREADS; sfc = cairo_recording_surface_create (content, extents_ptr); Py_END_ALLOW_THREADS; return PycairoSurface_FromSurface (sfc, NULL); } static PyObject * recording_surface_ink_extents (PycairoRecordingSurface *o) { double x0, y0, width, height; cairo_recording_surface_ink_extents(o->surface, &x0, &y0, &width, &height); return Py_BuildValue("(dddd)", x0, y0, width, height); } static PyObject * recording_surface_get_extents (PycairoRecordingSurface *o) { cairo_rectangle_t extents; cairo_bool_t result; PyObject *rect, *args; Py_BEGIN_ALLOW_THREADS; result = cairo_recording_surface_get_extents (o->surface, &extents); Py_END_ALLOW_THREADS; if (!result) { Py_RETURN_NONE; } args = Py_BuildValue( "(dddd)", extents.x, extents.y, extents.width, extents.height); if (args == NULL) return NULL; rect = PyObject_Call((PyObject *)&PycairoRectangle_Type, args, NULL); Py_DECREF (args); return rect; } static PyMethodDef recording_surface_methods[] = { {"ink_extents", (PyCFunction)recording_surface_ink_extents, METH_NOARGS }, {"get_extents", (PyCFunction)recording_surface_get_extents, METH_NOARGS }, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoRecordingSurface_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.RecordingSurface", /* tp_name */ sizeof(PycairoRecordingSurface), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ recording_surface_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoSurface_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)recording_surface_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; #endif /* CAIRO_HAS_RECORDING_SURFACE */ /* Class SVGSurface(Surface) ----------------------------------------------- */ #ifdef CAIRO_HAS_SVG_SURFACE #include static PyObject * svg_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { double width_in_points, height_in_points; PyObject *file; cairo_surface_t *sfc; char *name; if (!PyArg_ParseTuple (args, "Odd:SVGSurface.__new__", &file, &width_in_points, &height_in_points)) return NULL; if (Pycairo_is_fspath (file) || file == Py_None) { if (!PyArg_ParseTuple (args, "O&dd:SVGSurface.__new__", Pycairo_fspath_none_converter, &name, &width_in_points, &height_in_points)) return NULL; Py_BEGIN_ALLOW_THREADS; sfc = cairo_svg_surface_create (name, width_in_points, height_in_points); Py_END_ALLOW_THREADS; PyMem_Free(name); return PycairoSurface_FromSurface (sfc, NULL); } else { if (PyArg_ParseTuple (args, "O&dd:SVGSurface.__new__", Pycairo_writer_converter, &file, &width_in_points, &height_in_points)) { Py_BEGIN_ALLOW_THREADS; sfc = cairo_svg_surface_create_for_stream ( _write_func, file, width_in_points, height_in_points); Py_END_ALLOW_THREADS; return _surface_create_with_object (sfc, file); } else { PyErr_Clear (); PyErr_SetString(PyExc_TypeError, "SVGSurface argument 1 must be " "None, or a filename (str), or " "a file object, or an object that has a " "\"write\" method (like StringIO)."); return NULL; } } } static PyObject * svg_get_versions (PyObject *self) { PyObject *list, *num; const cairo_svg_version_t *versions; int i, num_versions; Py_BEGIN_ALLOW_THREADS; cairo_svg_get_versions (&versions, &num_versions); Py_END_ALLOW_THREADS; list = PyList_New (num_versions); if (list == NULL) return NULL; for (i=0; i < num_versions; i++) { num = CREATE_INT_ENUM (SVGVersion, versions[i]); if (num == NULL) { Py_DECREF (list); return NULL; } PyList_SET_ITEM (list, i, num); } return list; } static PyObject * svg_version_to_string (PyObject *self, PyObject *args) { cairo_svg_version_t version; int version_arg; const char *version_string; if (!PyArg_ParseTuple (args, "i:SVGSurface.version_to_string", &version_arg)) return NULL; version = (cairo_svg_version_t)version_arg; Py_BEGIN_ALLOW_THREADS; version_string = cairo_svg_version_to_string (version); Py_END_ALLOW_THREADS; if (version_string == NULL) { PyErr_SetString (PyExc_ValueError, "invalid version"); return NULL; } return PYCAIRO_PyUnicode_FromString (version_string); } static PyObject * svg_surface_restrict_to_version (PycairoPDFSurface *o, PyObject *args) { cairo_svg_version_t version; int version_arg; if (!PyArg_ParseTuple (args, "i:SVGSurface.restrict_to_version", &version_arg)) return NULL; version = (cairo_svg_version_t)version_arg; Py_BEGIN_ALLOW_THREADS; cairo_svg_surface_restrict_to_version (o->surface, version); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_SURFACE_ERROR (o->surface); Py_RETURN_NONE; } static PyMethodDef svg_surface_methods[] = { {"get_versions", (PyCFunction)svg_get_versions, METH_NOARGS | METH_STATIC}, {"version_to_string", (PyCFunction)svg_version_to_string, METH_VARARGS | METH_STATIC}, {"restrict_to_version", (PyCFunction)svg_surface_restrict_to_version, METH_VARARGS}, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoSVGSurface_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.SVGSurface", /* tp_name */ sizeof(PycairoSVGSurface), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ svg_surface_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoSurface_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)svg_surface_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; #endif /* CAIRO_HAS_SVG_SURFACE */ #ifdef CAIRO_HAS_WIN32_SURFACE #include static int convert_pyobject_to_hdc (PyObject *obj, HDC* addr) { HDC temp = PyLong_AsVoidPtr(obj); if (PyErr_Occurred() != NULL) return 0; *addr = temp; return 1; } /* Class Win32Surface(Surface) -------------------------------------------- */ static PyObject * win32_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { HDC hdc; if (!PyArg_ParseTuple(args, "O&:Win32Surface.__new__", convert_pyobject_to_hdc, &hdc)) return NULL; return PycairoSurface_FromSurface ( cairo_win32_surface_create (hdc), NULL); } static PyMethodDef win32_surface_methods[] = { {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoWin32Surface_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.Win32Surface", /* tp_name */ sizeof(PycairoWin32Surface), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ win32_surface_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoSurface_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)win32_surface_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; /* Class Win32PrintingSurface(Surface) ------------------------------------ */ static PyObject * win32_printing_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { HDC hdc; if (!PyArg_ParseTuple(args, "O&:Win32PrintingSurface.__new__", convert_pyobject_to_hdc, &hdc)) return NULL; return PycairoSurface_FromSurface ( cairo_win32_printing_surface_create (hdc), NULL); } static PyMethodDef win32_printing_surface_methods[] = { {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoWin32PrintingSurface_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.Win32PrintingSurface", /* tp_name */ sizeof(PycairoWin32PrintingSurface), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ win32_printing_surface_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoSurface_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)win32_printing_surface_new,/* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; #endif /* CAIRO_HAS_WIN32_SURFACE */ /* Class XCBSurface(Surface) --------------------------------------------- */ #ifdef CAIRO_HAS_XCB_SURFACE #include #ifdef HAVE_XPYB /** Convert a Python object from xpyb to a C struct matching libxcb type. * The object must be referenced if you want to keep returned data away from * garbage collection. * @param obj The object to convert. * @param len The size of the object read by Python. * @return A pointer to that data. */ const void * xpyb2struct(PyObject *obj, Py_ssize_t *len) { const void *data; #if PY_MAJOR_VERSION >= 3 // buffer function disabled return NULL; #endif if (PyObject_AsReadBuffer(obj, &data, len) < 0) return NULL; return data; } static int have_xpyb(void) { static int have_xpyb = -1; if(have_xpyb == -1) { /* Get type from xpyb */ xpyb_IMPORT; /* Some types are not defined in the CAPI */ PyObject *xpyb_module = PyImport_ImportModule("xcb.xproto"); if (xpyb_module) { PyObject *dict = PyModule_GetDict(xpyb_module); xpybVISUALTYPE_type = PyDict_GetItemString(dict, "VISUALTYPE"); Py_DECREF(xpyb_module); have_xpyb = 1; } else have_xpyb = 0; } return have_xpyb; } #endif static PyObject * xcb_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { #ifdef HAVE_XPYB int width, height; xcb_drawable_t drawable; PyObject *visual; xpybConn *conn; if(!have_xpyb()) return NULL; if (!PyArg_ParseTuple(args, "O!IO!ii:XCBSurface.__new__", xpyb_CAPI->xpybConn_type, &conn, &drawable, xpybVISUALTYPE_type, &visual, &width, &height)) return NULL; /* Convert Python object VISUALTYPE to a xcb_visualtype_t */ Py_ssize_t length; xcb_visualtype_t *visualtype = (xcb_visualtype_t *) xpyb2struct(visual, &length); if (length < sizeof(xcb_visualtype_t)) return NULL; return PycairoSurface_FromSurface ( cairo_xcb_surface_create (conn->conn, drawable, visualtype, width, height), NULL); #else PyErr_SetString(PyExc_TypeError, "pycairo was not compiled with xpyb support"); return NULL; #endif } static PyObject * xcb_surface_set_size (PycairoXCBSurface *o, PyObject *args) { int width, height; if (!PyArg_ParseTuple(args, "ii:XCBSurface.set_size", &width, &height)) return NULL; cairo_xcb_surface_set_size (o->surface, width, height); Py_RETURN_NONE; } static PyMethodDef xcb_surface_methods[] = { {"set_size", (PyCFunction)xcb_surface_set_size, METH_VARARGS }, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoXCBSurface_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.XCBSurface", /* tp_name */ sizeof(PycairoXCBSurface), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ xcb_surface_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoSurface_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)xcb_surface_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; #endif /* CAIRO_HAS_XCB_SURFACE */ /* Class XlibSurface(Surface) --------------------------------------------- */ #ifdef CAIRO_HAS_XLIB_SURFACE #include static PyObject * xlib_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { PyErr_SetString(PyExc_TypeError, "The XlibSurface type cannot be directly instantiated"); return NULL; } static PyObject * xlib_surface_get_depth (PycairoXlibSurface *o) { return PYCAIRO_PyLong_FromLong (cairo_xlib_surface_get_depth (o->surface)); } static PyObject * xlib_surface_get_height (PycairoXlibSurface *o) { return PYCAIRO_PyLong_FromLong (cairo_xlib_surface_get_height (o->surface)); } static PyObject * xlib_surface_get_width (PycairoXlibSurface *o) { return PYCAIRO_PyLong_FromLong (cairo_xlib_surface_get_width (o->surface)); } static PyMethodDef xlib_surface_methods[] = { {"get_depth", (PyCFunction)xlib_surface_get_depth, METH_NOARGS }, {"get_height",(PyCFunction)xlib_surface_get_height, METH_NOARGS }, {"get_width", (PyCFunction)xlib_surface_get_width, METH_NOARGS }, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoXlibSurface_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.XlibSurface", /* tp_name */ sizeof(PycairoXlibSurface), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ xlib_surface_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoSurface_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)xlib_surface_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; #endif /* CAIRO_HAS_XLIB_SURFACE */ #ifdef CAIRO_HAS_TEE_SURFACE #include static PyObject * tee_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *pysurface; if (!PyArg_ParseTuple (args, "O!:TeeSurface.__new__", &PycairoSurface_Type, &pysurface)) return NULL; return PycairoSurface_FromSurface ( cairo_tee_surface_create(((PycairoSurface*)pysurface)->surface), NULL); } static PyObject * tee_surface_add (PycairoTeeSurface *obj, PyObject *args) { PyObject *pysurface; if (!PyArg_ParseTuple(args, "O!:TeeSurface.add", &PycairoSurface_Type, &pysurface)) return NULL; cairo_tee_surface_add (obj->surface, ((PycairoSurface*)pysurface)->surface); RETURN_NULL_IF_CAIRO_SURFACE_ERROR (obj->surface); Py_RETURN_NONE; } static PyObject * tee_surface_remove (PycairoTeeSurface *obj, PyObject *args) { PyObject *pysurface; if (!PyArg_ParseTuple(args, "O!:TeeSurface.remove", &PycairoSurface_Type, &pysurface)) return NULL; cairo_tee_surface_remove (obj->surface, ((PycairoSurface*)pysurface)->surface); RETURN_NULL_IF_CAIRO_SURFACE_ERROR (obj->surface); Py_RETURN_NONE; } static PyObject * tee_surface_index (PycairoTeeSurface *obj, PyObject *args) { unsigned int index; if (!PyArg_ParseTuple(args, "I:TeeSurface.index", &index)) return NULL; return PycairoSurface_FromSurface ( cairo_surface_reference (cairo_tee_surface_index (obj->surface, index)), NULL); } static PyMethodDef tee_surface_methods[] = { {"add", (PyCFunction)tee_surface_add, METH_VARARGS }, {"remove", (PyCFunction)tee_surface_remove, METH_VARARGS }, {"index", (PyCFunction)tee_surface_index, METH_VARARGS }, {NULL, NULL, 0, NULL}, }; PyTypeObject PycairoTeeSurface_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.TeeSurface", /* tp_name */ sizeof(PycairoTeeSurface), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ tee_surface_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PycairoSurface_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)tee_surface_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; #endif /* CAIRO_HAS_TEE_SURFACE */ pycairo-1.16.2/cairo/textcluster.c000066400000000000000000000132171323762421700171110ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2017 Christoph Reiter * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "private.h" /* 0 on success */ int _PyTextCluster_AsTextCluster (PyObject *pyobj, cairo_text_cluster_t *cluster) { long num_bytes, num_glyphs; if (!PyObject_TypeCheck (pyobj, &PycairoTextCluster_Type)) { PyErr_SetString (PyExc_TypeError, "item must be of type cairo.TextCluster"); return -1; } num_bytes = PYCAIRO_PyLong_AsLong ( PySequence_Fast_GET_ITEM (pyobj, 0)); if (PyErr_Occurred ()) return -1; if (num_bytes > INT_MAX || num_bytes < INT_MIN) { PyErr_SetString (PyExc_ValueError, "num_bytes out of range"); return -1; } cluster->num_bytes = (int)num_bytes; num_glyphs = PYCAIRO_PyLong_AsLong ( PySequence_Fast_GET_ITEM (pyobj, 1)); if (PyErr_Occurred ()) return -1; if (num_glyphs > INT_MAX || num_glyphs < INT_MIN) { PyErr_SetString (PyExc_ValueError, "num_glyphs out of range"); return -1; } cluster->num_glyphs = (int)num_glyphs; return 0; } static char *KWDS[] = {"num_bytes", "num_glyphs", NULL}; static PyObject * text_cluster_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { int num_bytes, num_glyphs; PyObject *tuple_args, *result; if (!PyArg_ParseTupleAndKeywords (args, kwds, "ii:TextCluster.__new__", KWDS, &num_bytes, &num_glyphs)) return NULL; tuple_args = Py_BuildValue ("((ii))", num_bytes, num_glyphs); if (tuple_args == NULL) return NULL; result = PyTuple_Type.tp_new (type, tuple_args, NULL); Py_DECREF (tuple_args); return result; } static PyObject* text_cluster_repr(PyObject *self) { PyObject *format, *result; format = PYCAIRO_PyUnicode_FromString ( "cairo.TextCluster(num_bytes=%r, num_glyphs=%r)"); if (format == NULL) return NULL; result = PYCAIRO_PyUnicode_Format (format, self); Py_DECREF (format); return result; } static PyObject* text_cluster_getattro (PyObject *self, PyObject *name) { return Pycairo_tuple_getattro (self, KWDS, name); } PyTypeObject PycairoTextCluster_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.TextCluster", /* tp_name */ sizeof(PycairTextCluster), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)text_cluster_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ text_cluster_getattro, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)text_cluster_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; pycairo-1.16.2/cairo/textextents.c000066400000000000000000000117011323762421700171160ustar00rootroot00000000000000/* -*- mode: C; c-basic-offset: 2 -*- * * Pycairo - Python bindings for cairo * * Copyright © 2017 Christoph Reiter * * 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. */ #define PY_SSIZE_T_CLEAN #include #include "private.h" static char *KWDS[] = {"x_bearing", "y_bearing", "width", "height", "x_advance", "y_advance", NULL}; static PyObject * text_extents_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { cairo_text_extents_t e; PyObject *tuple_args, *result; if (!PyArg_ParseTupleAndKeywords (args, kwds, "dddddd:TextExtents.__new__", KWDS, &e.x_bearing, &e.y_bearing, &e.width, &e.height, &e.x_advance, &e.y_advance)) return NULL; tuple_args = Py_BuildValue ("((dddddd))", e.x_bearing, e.y_bearing, e.width, e.height, e.x_advance, e.y_advance); if (tuple_args == NULL) return NULL; result = PyTuple_Type.tp_new (type, tuple_args, NULL); Py_DECREF (tuple_args); return result; } static PyObject* text_extents_repr(PyObject *self) { PyObject *format, *result; format = PYCAIRO_PyUnicode_FromString ( "cairo.TextExtents(x_bearing=%r, y_bearing=%r, width=%r, height=%r, " "x_advance=%r, y_advance=%r)"); if (format == NULL) return NULL; result = PYCAIRO_PyUnicode_Format (format, self); Py_DECREF (format); return result; } static PyObject* text_extents_getattro (PyObject *self, PyObject *name) { return Pycairo_tuple_getattro (self, KWDS, name); } PyTypeObject PycairoTextExtents_Type = { PyVarObject_HEAD_INIT(NULL, 0) "cairo.TextExtents", /* tp_name */ sizeof(PycairoTextExtents), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)text_extents_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ text_extents_getattro, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)text_extents_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ }; pycairo-1.16.2/docs/000077500000000000000000000000001323762421700142065ustar00rootroot00000000000000pycairo-1.16.2/docs/.gitignore000066400000000000000000000000321323762421700161710ustar00rootroot00000000000000_build _static _templates pycairo-1.16.2/docs/Makefile000066400000000000000000000002661323762421700156520ustar00rootroot00000000000000all: sphinx-build -b html -n . _build clean: rm -rf _build .PHONY: clean show linkcheck show: all xdg-open _build/index.html linkcheck: sphinx-build -b linkcheck -n . _build pycairo-1.16.2/docs/changelog.rst000066400000000000000000000001041323762421700166620ustar00rootroot00000000000000Changelog ========= .. currentmodule:: cairo .. include:: ../NEWS pycairo-1.16.2/docs/conf.py000066400000000000000000000016071323762421700155110ustar00rootroot00000000000000# -*- coding: utf-8 -*- extensions = [ 'sphinx.ext.intersphinx', 'sphinx.ext.extlinks', ] intersphinx_mapping = { 'python': ('https://docs.python.org/2.7', None), 'python3': ('https://docs.python.org/3.6', None), } source_suffix = '.rst' master_doc = 'index' project = u'Pycairo' html_show_copyright = False exclude_patterns = ['_build'] pygments_style = 'sphinx' html_theme = "sphinx_rtd_theme" html_theme_options = { "display_version": False, } html_context = { 'extra_css_files': [ '_static/extra.css', ], } html_static_path = [ "extra.css", ] extlinks = { 'fdobug': ('https://bugs.freedesktop.org/show_bug.cgi?id=%s', '#fdo-'), 'bug': ('https://github.com/pygobject/pycairo/issues/%s', '#'), 'pr': ('https://github.com/pygobject/pycairo/pull/%s', '#pr-'), 'user': ('https://github.com/%s', ''), } suppress_warnings = ["image.nonlocal_uri"] pycairo-1.16.2/docs/examples.rst000066400000000000000000000003771323762421700165650ustar00rootroot00000000000000======== Examples ======== The Git repository and release tarball contain various examples showing various features of cairo and integration with pygame and GTK+ in the "examples" directory: https://github.com/pygobject/pycairo/tree/master/examples pycairo-1.16.2/docs/extra.css000066400000000000000000000010421323762421700160400ustar00rootroot00000000000000.wy-side-nav-search { background-color: initial; } .wy-nav-top { background-color: #2e3436 ; } .wy-side-nav-search input[type="text"] { border-color: transparent; } .wy-nav-content { margin: initial; } .wy-nav-side { background-color: #2e3436 ; } .rst-content div[role=navigation], footer { font-size: 0.85em; color: #999; } .rst-content div[role=navigation] hr { margin-top: 6px; } footer hr { margin-bottom: 6px; } .rst-footer-buttons { display: none; } .versionmodified { color: #a40000; } pycairo-1.16.2/docs/faq.rst000066400000000000000000000012111323762421700155020ustar00rootroot00000000000000========================== Frequently Asked Questions ========================== The paths in the installed pkg-config file are wrong. Why? Multiple reasons: * This can happen if you install from a Python wheel. Since you can't pass a prefix to setup.py bdist_wheel you don't have control over the paths in the .pc file. * When installing with pip: pip will sometimes create a wheel and cache it for future installations. In case the next installation is to a different prefix the .pc file contains the paths of the first installation. If you can think of any way to improve this, please tell us :) pycairo-1.16.2/docs/images/000077500000000000000000000000001323762421700154535ustar00rootroot00000000000000pycairo-1.16.2/docs/images/example.svg000066400000000000000000000012421323762421700176260ustar00rootroot00000000000000 pycairo-1.16.2/docs/images/pycairo.svg000066400000000000000000001410711323762421700176460ustar00rootroot00000000000000 image/svg+xml pycairo-1.16.2/docs/index.rst000066400000000000000000000024741323762421700160560ustar00rootroot00000000000000.. raw:: html
.. image:: images/pycairo.svg :align: center :width: 370px | | .. toctree:: :maxdepth: 1 :titlesonly: :hidden: changelog Tutorial reference/index pycairo_c_api resources faq .. currentmodule:: cairo .. title:: Overview .. include:: ../README.rst :start-after: | ---- Tarballs: https://github.com/pygobject/pycairo/releases Git repo: https://github.com/pygobject/pycairo Bug tracker: https://github.com/pygobject/pycairo/issues Mailing list: https://lists.cairographics.org/cgi-bin/mailman/listinfo/cairo See the ":ref:`reference_index`" for further details. To use the pycairo library:: import cairo To build/install the library:: python2/3 setup.py build python2/3 setup.py install To run the tests:: python2/3 setup.py test The Python 2 version supports `xpyb `__ integration which is disabled by default. To enable, build as follows:: python2 setup.py build --enable-xpyb # and for running tests: python2 setup.py test --enable-xpyb For examples of pycairo code see the 'examples' directory that comes with the pycairo distribution. For author information see the git history as well as the now deleted "ChangeLog" file in the git history. pycairo-1.16.2/docs/integration.rst000066400000000000000000000104721323762421700172670ustar00rootroot00000000000000================================ Integration with other Libraries ================================ NumPy & ImageSurface -------------------- Creating an ImageSurface from a NumPy array: .. code:: python import numpy import cairo width, height = 255, 255 data = numpy.ndarray(shape=(height, width), dtype=numpy.uint32) surface = cairo.ImageSurface.create_for_data( data, cairo.FORMAT_ARGB32, width, height) Creating a NumPy array from an ImageSurface: .. code:: python import numpy import cairo width, height = 255, 255 surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) buf = surface.get_data() data = numpy.ndarray(shape=(width, height), dtype=numpy.uint32, buffer=buf) Pygame & ImageSurface --------------------- Creating a pygame.image from an ImageSurface: .. code:: python import pygame import cairo width, height = 255, 255 surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) buf = surface.get_data() image = pygame.image.frombuffer(buf, (width, height), "ARGB") Pyglet & ImageSurface as Texture -------------------------------- Creating a pyglet.Texture from an ImageSurface .. code:: python import ctypes import cairo from pyglet import app, clock, gl, image, window # create data shared by ImageSurface and Texture width, height = 400, 400 surface_data = (ctypes.c_ubyte * (width * height * 4))() surface = cairo.ImageSurface.create_for_data (surface_data, cairo.FORMAT_ARGB32, width, height, width * 4); texture = image.Texture.create_for_size(gl.GL_TEXTURE_2D, width, height, gl.GL_RGBA) Draw pyglet.Texture bound to ImageSurface .. code:: python window = window.Window(width=width, height=height) @window.event def on_draw(): window.clear() # Draw texture backed by ImageSurface gl.glEnable(gl.GL_TEXTURE_2D) gl.glBindTexture(gl.GL_TEXTURE_2D, texture.id) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, width, height, 0, gl.GL_BGRA, gl.GL_UNSIGNED_BYTE, surface_data) gl.glBegin(gl.GL_QUADS) gl.glTexCoord2f(0.0, 1.0) gl.glVertex2i(0, 0) gl.glTexCoord2f(1.0, 1.0) gl.glVertex2i(width, 0) gl.glTexCoord2f(1.0, 0.0) gl.glVertex2i(width, height) gl.glTexCoord2f(0.0, 0.0) gl.glVertex2i(0, height) gl.glEnd() # call clock.schedule_update here to update the ImageSurface every frame app.run() Pillow (PIL) & Cairo -------------------- Creating an ImageSurface from a PIL Image: .. code:: python import PIL.Image as Image def from_pil(im, alpha=1.0, format=cairo.FORMAT_ARGB32): """ :param im: Pillow Image :param alpha: 0..1 alpha to add to non-alpha images :param format: Pixel format for output surface """ assert format in (cairo.FORMAT_RGB24, cairo.FORMAT_ARGB32), "Unsupported pixel format: %s" % format if 'A' not in im.getbands(): im.putalpha(int(alpha * 256.)) arr = bytearray(im.tobytes('raw', 'BGRa')) surface = cairo.ImageSurface.create_for_data(arr, format, im.width, im.height) return surface filename = 'test.jpeg' # Open image to an ARGB32 ImageSurface im = Image.open(filename) surface1 = from_pil(im) # Open image to an RGB24 ImageSurface im = Image.open(filename) surface2 = from_pil(im, format=cairo.FORMAT_RGB24) # Open image to an ARGB32 ImageSurface, 50% opacity im = Image.open(filename) surface3 = from_pil(im, alpha=0.5, format=cairo.FORMAT_ARGB32) Freetype-py & Cairo ------------------- See https://github.com/rougier/freetype-py/tree/master/examples for examples. Most of the ``*-cairo.py`` examples illustrate conversion from FreeType bitmaps to Cairo surfaces; the two examples, ``glyph-vector-cairo.py`` and ``glyph-vector-2-cairo.py``, illustrate conversion from FreeType glyph contours to Cairo paths. pycairo-1.16.2/docs/pycairo_c_api.rst000066400000000000000000000275201323762421700175470ustar00rootroot00000000000000.. highlightlang:: c *************** C API Reference *************** .. currentmodule:: cairo This manual documents the API used by C and C++ programmers who want to write extension modules that use pycairo. Pycairo Compiler Flags ====================== To compile a Python extension using Pycairo you need to know where Pycairo and cairo are located and what flags to pass to the compiler and linker. 1. Variant: Only available since version 1.16.0. While Pycairo installs a pkg-config file, in case of virtualenvs, installation to the user directory or when using wheels/eggs, pkg-config will not be able to locate the .pc file. The :func:`get_include` function should work in all cases, as long as Pycairo is in your Python search path. Compiler Flags: * ``python -c "import cairo; print(cairo.get_include())"`` * ``pkg-config --cflags cairo`` Linker Flags: * ``pkg-config --libs cairo`` 2. Variant: This works with older versions, but with the limitations mentioned above. Use it as a fallback if you want to support older versions or if your module does not require virtualenv/pip support. Compiler Flags: * ``pkg-config --cflags pycairo`` or ``pkg-config --cflags py3cairo`` Linker Flags: * ``pkg-config --libs pycairo`` or ``pkg-config --libs py3cairo`` .. _api-includes: To access the Pycairo C API under Python 2 ========================================== Edit the client module file to add the following lines:: /* All function, type and macro definitions needed to use the Pycairo/C API * are included in your code by the following line */ #include "pycairo.h" /* define a variable for the C API */ static Pycairo_CAPI_t *Pycairo_CAPI; /* import pycairo - add to the init function */ Pycairo_IMPORT; To access the Pycairo C API under Python 3 ========================================== Example showing how to import the pycairo API:: #include "py3cairo.h" PyMODINIT_FUNC PyInit_client(void) { PyObject *m; m = PyModule_Create(&clientmodule); if (m == NULL) return NULL; if (import_cairo() < 0) return NULL; /* additional initialization can happen here */ return m; } Misc Functions ============== .. c:function:: int Pycairo_Check_Status(cairo_status_t status) :param cairo_status_t status: :returns: -1 in case of an error, otherwise 0. Sets an exception in case of an error. Takes a status value and converts it to an exception if it represents an error status. Cairo Context ============= .. c:type:: PyObject PycairoContext .. c:member:: cairo_t* PycairoContext.ctx The wrapped :any:`cairo_t` .. c:type:: PyTypeObject *PycairoContext_Type .. c:macro:: cairo_t * PycairoContext_GET(PycairoContext *obj) :param PycairoContext obj: :returns: :any:`cairo_t` [transfer none] Get the :any:`cairo_t` object out of the :any:`PycairoContext`. .. c:function:: PyObject * PycairoContext_FromContext(cairo_t *ctx, PyTypeObject *type, PyObject *base) :param cairo_t ctx: a cairo_t to 'wrap' into a Python object. It is unreferenced if the PycairoContext creation fails, or if the cairo_t has an error status. [transfer full] :param PyTypeObject type: a pointer to the type to instantiate. It can be &PycairoContext_Type, or a PycairoContext_Type subtype. (cairo.Context or a cairo.Context subclass) [transfer none] :param PyObject base: the base object used to create the context, or NULL. it is referenced to keep it alive while the cairo_t is being used [transfer none] :returns: New reference or NULL on failure and sets an exception [transfer full] Create a new PycairoContext from a :any:`cairo_t` Cairo Font Face =============== .. c:type:: PyObject PycairoFontFace .. c:member:: cairo_font_face_t* PycairoFontFace.font_face The wrapped :any:`cairo_font_face_t` .. c:type:: PyTypeObject *PycairoFontFace_Type .. c:function:: PyObject * PycairoFontFace_FromFontFace(cairo_font_face_t *font_face) :param cairo_font_face_t font_face: a cairo_font_face_t to 'wrap' into a Python object. it is unreferenced if the PycairoFontFace creation fails [transfer full] :returns: New reference or NULL on failure and sets an exception [transfer full] Create a new PycairoFontFace from a cairo_font_face_t .. c:type:: PycairoFontFace PycairoToyFontFace .. c:type:: PyTypeObject *PycairoToyFontFace_Type Cairo Font Options ================== .. c:type:: PyObject PycairoFontOptions .. c:member:: cairo_font_options_t* PycairoFontOptions.font_options .. c:type:: PyTypeObject *PycairoFontOptions_Type .. c:function:: PyObject * PycairoFontOptions_FromFontOptions(cairo_font_options_t *font_options) :param cairo_font_options_t font_options: a cairo_font_options_t to 'wrap' into a Python object. it is unreferenced if the PycairoFontOptions creation fails [transfer full] :returns: New reference or NULL on failure and sets an exception [transfer full] Create a new PycairoFontOptions from a cairo_font_options_t Cairo Matrix ============ .. c:type:: PyObject PycairoMatrix .. c:member:: cairo_matrix_t PycairoMatrix.matrix .. c:type:: PyTypeObject *PycairoMatrix_Type .. c:function:: PyObject * PycairoMatrix_FromMatrix(const cairo_matrix_t *matrix) :param cairo_matrix_t matrix: a cairo_matrix_t to 'wrap' into a Python object. the cairo_matrix_t values are copied. [transfer none] :returns: New reference or NULL on failure and sets an exception [transfer full] Create a new PycairoMatrix from a cairo_matrix_t Cairo Path ========== .. c:type:: PyObject PycairoPath .. c:member:: cairo_path_t* PycairoPath.path .. c:type:: PyTypeObject *PycairoPath_Type .. c:function:: PyObject * PycairoPath_FromPath(cairo_path_t *path) :param cairo_path_t path: a cairo_path_t to 'wrap' into a Python object. path is unreferenced if the PycairoPath creation fails, or if path is in an error status. [transfer full] :returns: New reference or NULL on failure and sets an exception [transfer full] Create a new PycairoPath from a cairo_path_t Cairo Pattern ============= .. c:type:: PyObject PycairoPattern .. c:member:: cairo_pattern_t* PycairoPattern.pattern .. c:type:: PyTypeObject *PycairoPattern_Type .. c:type:: PycairoPattern PycairoSolidPattern .. c:type:: PyTypeObject *PycairoSolidPattern_Type .. c:type:: PycairoPattern PycairoSurfacePattern .. c:type:: PyTypeObject *PycairoSurfacePattern_Type .. c:type:: PycairoPattern PycairoGradient .. c:type:: PyTypeObject *PycairoGradient_Type .. c:type:: PycairoGradient PycairoLinearGradient .. c:type:: PyTypeObject *PycairoLinearGradient_Type .. c:type:: PycairoGradient PycairoRadialGradient .. c:type:: PyTypeObject *PycairoRadialGradient_Type .. c:function:: PyObject * PycairoPattern_FromPattern(cairo_pattern_t *pattern, PyObject *base) :param cairo_pattern_t pattern: a cairo_pattern_t to 'wrap' into a Python object. It is unreferenced if the PycairoPattern creation fails, or if the pattern has an error status. [transfer full] :param PyObject base: the base object used to create the pattern, or NULL. It is referenced to keep it alive while the cairo_pattern_t is being used. [transfer none] :returns: New reference or NULL on failure and sets an exception [transfer full] Create a new PycairoSolidPattern, PycairoSurfacePattern, PycairoLinearGradient, or PycairoRadialGradient from a cairo_pattern_t. Cairo Region ============ .. c:type:: PyObject PycairoRegion .. c:member:: cairo_region_t* PycairoRegion.region .. c:type:: PyTypeObject *PycairoRegion_Type .. c:function:: PyObject * PycairoRegion_FromRegion(cairo_region_t *region) :param cairo_region_t region: a cairo_region_t to 'wrap' into a Python object. region is unreferenced if the PycairoRegion creation fails, or if region is in an error status. :returns: New reference or NULL on failure and sets an exception [transfer full] Create a new PycairoRegion from a cairo_region_t Cairo RectangleInt ================== .. c:type:: PyObject PycairoRectangleInt .. c:member:: cairo_rectangle_int_t* PycairoRectangleInt.rectangle_int .. c:type:: PyTypeObject *PycairoRectangleInt_Type .. c:function:: PyObject * PycairoRectangleInt_FromRectangleInt(const cairo_rectangle_int_t *rectangle_int) :param cairo_rectangle_int_t rectangle_int: a cairo_rectangle_int_t to 'wrap' into a Python object. rectangle_int is unreferenced if the PycairoRectangleInt creation fails. [transfer none] :returns: New reference or NULL on failure and sets an exception [transfer full] Create a new PycairoRectangleInt from a cairo_rectangle_int_t Scaled Font =========== .. c:type:: PyObject PycairoScaledFont .. c:member:: cairo_scaled_font_t* PycairoScaledFont.scaled_font .. c:type:: PyTypeObject *PycairoScaledFont_Type .. c:function:: PyObject * PycairoScaledFont_FromScaledFont(cairo_scaled_font_t *scaled_font) :param cairo_scaled_font_t scaled_font: a cairo_scaled_font_t to 'wrap' into a Python object. it is unreferenced if the PycairoScaledFont creation fails [transfer full] :returns: New reference or NULL on failure and sets an exception [transfer full] Create a new PycairoScaledFont from a cairo_scaled_font_t Cairo Surface ============= .. c:type:: PyObject PycairoSurface .. c:member:: cairo_surface_t* PycairoSurface.surface .. c:type:: PyTypeObject *PycairoSurface_Type .. c:type:: PycairoSurface PycairoImageSurface .. c:type:: PyTypeObject *PycairoImageSurface_Type .. c:type:: PycairoSurface PycairoPDFSurface .. c:type:: PyTypeObject *PycairoPDFSurface_Type .. c:type:: PycairoSurface PycairoPSSurface .. c:type:: PyTypeObject *PycairoPSSurface_Type .. c:type:: PycairoSurface PycairoRecordingSurface .. c:type:: PyTypeObject *PycairoRecordingSurface_Type .. c:type:: PycairoSurface PycairoSVGSurface .. c:type:: PyTypeObject *PycairoSVGSurface_Type .. c:type:: PycairoSurface PycairoWin32Surface .. c:type:: PyTypeObject *PycairoWin32Surface_Type .. c:type:: PycairoSurface PycairoXCBSurface .. c:type:: PyTypeObject *PycairoXCBSurface_Type .. c:type:: PycairoSurface PycairoXlibSurface .. c:type:: PyTypeObject *PycairoXlibSurface_Type .. c:function:: PyObject * PycairoSurface_FromSurface(cairo_surface_t *surface, PyObject *base) :param cairo_surface_t surface: a cairo_surface_t to 'wrap' into a Python object. It is unreferenced if the PycairoSurface creation fails, or if the cairo_surface_t has an error status. [transfer full] :param PyObject base: the base object used to create the surface, or NULL. It is referenced to keep it alive while the cairo_surface_t is being used. [transfer none] :returns: New reference or NULL on failure and sets an exception [transfer full] Create a new PycairoImageSurface, PycairoPDFSurface, PycairoPSSurface, PycairoRecordingSurface, PycairoSVGSurface, PycairoWin32Surface, PycairoWin32PrintingSurface, PycairoXCBSurface, or PycairoXlibSurface from a cairo_surface_t. Cairo Types =========== These are only listed here so they can be referenced in the documentation. See https://www.cairographics.org/manual/ for details. .. c:type:: cairo_t cairo_status_t cairo_surface_t cairo_scaled_font_t cairo_rectangle_int_t cairo_region_t cairo_pattern_t cairo_matrix_t cairo_font_options_t cairo_path_t cairo_font_face_t pycairo-1.16.2/docs/reference/000077500000000000000000000000001323762421700161445ustar00rootroot00000000000000pycairo-1.16.2/docs/reference/constants.rst000066400000000000000000000065451323762421700207240ustar00rootroot00000000000000.. _constants: ****************************** Module Functions and Constants ****************************** .. currentmodule:: cairo Module Functions ================ .. function:: cairo_version() :returns: the encoded version :rtype: int Returns the version of the underlying C cairo library, encoded in a single integer. .. function:: cairo_version_string() :returns: the encoded version :rtype: str Returns the version of the underlying C cairo library as a human-readable string of the form "X.Y.Z". .. function:: get_include() :returns: a path to the directory containing the C header files :rtype: str Gives the include path which should be passed to the compiler. .. versionadded:: 1.16.0 Module Constants ================ .. data:: version the pycairo version, as a string .. data:: version_info the pycairo version, as a tuple .. _constants_HAS: cairo.HAS --------- 1 if the feature is present in the underlying C cairo library, 0 otherwise. .. data:: HAS_ATSUI_FONT HAS_FT_FONT HAS_GLITZ_SURFACE HAS_IMAGE_SURFACE HAS_PDF_SURFACE HAS_PNG_FUNCTIONS HAS_PS_SURFACE HAS_RECORDING_SURFACE HAS_SVG_SURFACE HAS_USER_FONT HAS_QUARTZ_SURFACE HAS_WIN32_FONT HAS_WIN32_SURFACE HAS_XCB_SURFACE HAS_XLIB_SURFACE .. data:: HAS_MIME_SURFACE .. versionadded:: 1.12.0 .. data:: HAS_SCRIPT_SURFACE .. versionadded:: 1.12.0 .. data:: HAS_TEE_SURFACE .. versionadded:: 1.15.3 .. _constants_MIME_TYPE: cairo.MIME_TYPE --------------- .. data:: MIME_TYPE_JP2 :annotation: = "image/jp2" The Joint Photographic Experts Group (JPEG) 2000 image coding standard (ISO/IEC 15444-1). .. versionadded:: 1.12.0 .. data:: MIME_TYPE_JPEG :annotation: = "image/jpeg" The Joint Photographic Experts Group (JPEG) image coding standard (ISO/IEC 10918-1). .. versionadded:: 1.12.0 .. data:: MIME_TYPE_PNG :annotation: = "image/png" The Portable Network Graphics image file format (ISO/IEC 15948). .. versionadded:: 1.12.0 .. data:: MIME_TYPE_URI :annotation: = "text/x-uri" URI for an image file (unofficial MIME type). .. versionadded:: 1.12.0 .. data:: MIME_TYPE_UNIQUE_ID :annotation: = "application/x-cairo.uuid" Unique identifier for a surface (cairo specific MIME type). All surfaces with the same unique identifier will only be embedded once. .. versionadded:: 1.12.0 Other Classes and Functions =========================== .. class:: text() This type only exists for documentation purposes. It represents :obj:`python:str`/:obj:`python:unicode` under Python 2 and :obj:`python3:str` under Python 3. .. class:: pathlike() This type only exists for documentation purposes. On Unix it is equal to what Python allows as a filesystem path. On Windows with cairo <=1.15.8 only ANSI paths are supported. With cairo >=1.15.10 all paths are supported as long as they don't contain surrogates. Many functions taking a path also allow passing in an already open Python file object. This can be used to support all Python filesystem paths independent of the underlying platform or cairo version. .. versionadded:: 1.15.1 Older versions only supported a subset of :obj:`str` paths pycairo-1.16.2/docs/reference/context.rst000066400000000000000000001667011323762421700203750ustar00rootroot00000000000000.. _context: ************* Cairo Context ************* .. currentmodule:: cairo .. comment block example reST: (add back '..' where required at column 0) . class:: module.C[(signature)] .. classmethod:: name(signature) .. staticmethod:: name(signature) .. method:: method(signature) :param p1: xxx :type p1: int :param p2: xxx :type p2: str :returns: xxx :rtype: list of strings :raises: xxx .. versionadded:: 1.6 links: :data:`cairo.ANTIALIAS_SUBPIXEL` :class:`Context` :exc:`cairo.Error` :meth:`.copy_page` :meth:`Context.copy_page` class Context() =============== *Context* is the main object used when drawing with cairo. To draw with cairo, you create a *Context*, set the target surface, and drawing options for the *Context*, create shapes with functions like :meth:`Context.move_to` and :meth:`Context.line_to`, and then draw shapes with :meth:`Context.stroke` or :meth:`Context.fill`. *Contexts* can be pushed to a stack via :meth:`Context.save`. They may then safely be changed, without loosing the current state. Use :meth:`Context.restore` to restore to the saved state. .. class:: Context(target) :param target: target :class:`Surface` for the context :returns: a newly allocated *Context* :raises: :exc:`MemoryError` in case of no memory Creates a new *Context* with all graphics state parameters set to default values and with *target* as a target surface. The target surface should be constructed with a backend-specific function such as :class:`ImageSurface` (or any other cairo backend surface create variant). .. method:: append_path(path) :param path: :class:`Path` to be appended Append the *path* onto the current path. The *path* may be either the return value from one of :meth:`Context.copy_path` or :meth:`Context.copy_path_flat` or it may be constructed manually (in C). .. method:: arc(xc, yc, radius, angle1, angle2) :param xc: X position of the center of the arc :type xc: float :param yc: Y position of the center of the arc :type yc: float :param radius: the radius of the arc :type radius: float :param angle1: the start angle, in radians :type angle1: float :param angle2: the end angle, in radians :type angle2: float Adds a circular arc of the given *radius* to the current path. The arc is centered at (*xc, yc*), begins at *angle1* and proceeds in the direction of increasing angles to end at *angle2*. If *angle2* is less than *angle1* it will be progressively increased by 2*PI until it is greater than *angle1*. If there is a current point, an initial line segment will be added to the path to connect the current point to the beginning of the arc. If this initial line is undesired, it can be avoided by calling :meth:`Context.new_sub_path` before calling :meth:`Context.arc`. Angles are measured in radians. An angle of 0.0 is in the direction of the positive X axis (in user space). An angle of PI/2.0 radians (90 degrees) is in the direction of the positive Y axis (in user space). Angles increase in the direction from the positive X axis toward the positive Y axis. So with the default transformation matrix, angles increase in a clockwise direction. To convert from degrees to radians, use ``degrees * (math.pi / 180)``. This function gives the arc in the direction of increasing angles; see :meth:`Context.arc_negative` to get the arc in the direction of decreasing angles. The arc is circular in user space. To achieve an elliptical arc, you can scale the current transformation matrix by different amounts in the X and Y directions. For example, to draw an ellipse in the box given by *x, y, width, height*:: ctx.save() ctx.translate(x + width / 2., y + height / 2.) ctx.scale(width / 2., height / 2.) ctx.arc(0., 0., 1., 0., 2 * math.pi) ctx.restore() .. method:: arc_negative(xc, yc, radius, angle1, angle2) :param xc: X position of the center of the arc :type xc: float :param yc: Y position of the center of the arc :type yc: float :param radius: the radius of the arc :type radius: float :param angle1: the start angle, in radians :type angle1: float :param angle2: the end angle, in radians :type angle2: float Adds a circular arc of the given *radius* to the current path. The arc is centered at (*xc, yc*), begins at *angle1* and proceeds in the direction of decreasing angles to end at *angle2*. If *angle2* is greater than *angle1* it will be progressively decreased by 2*PI until it is less than *angle1*. See :meth:`Context.arc` for more details. This function differs only in the direction of the arc between the two angles. .. method:: clip() Establishes a new clip region by intersecting the current clip region with the current path as it would be filled by :meth:`Context.fill` and according to the current :class:`fill rule ` (see :meth:`Context.set_fill_rule`). After :meth:`.clip`, the current path will be cleared from the :class:`Context`. The current clip region affects all drawing operations by effectively masking out any changes to the surface that are outside the current clip region. Calling :meth:`.clip` can only make the clip region smaller, never larger. But the current clip is part of the graphics state, so a temporary restriction of the clip region can be achieved by calling :meth:`.clip` within a :meth:`Context.save`/:meth:`Context.restore` pair. The only other means of increasing the size of the clip region is :meth:`Context.reset_clip`. .. method:: clip_extents() :returns: (x1, y1, x2, y2), all float :rtype: tuple * *x1*: left of the resulting extents * *y1*: top of the resulting extents * *x2*: right of the resulting extents * *y2*: bottom of the resulting extents Computes a bounding box in user coordinates covering the area inside the current clip. .. versionadded:: 1.4 .. method:: clip_preserve() Establishes a new clip region by intersecting the current clip region with the current path as it would be filled by :meth:`Context.fill` and according to the current :class:`fill rule ` (see :meth:`Context.set_fill_rule`). Unlike :meth:`Context.clip`, :meth:`.clip_preserve` preserves the path within the :class:`Context`. The current clip region affects all drawing operations by effectively masking out any changes to the surface that are outside the current clip region. Calling :meth:`.clip_preserve` can only make the clip region smaller, never larger. But the current clip is part of the graphics state, so a temporary restriction of the clip region can be achieved by calling :meth:`.clip_preserve` within a :meth:`Context.save`/:meth:`Context.restore` pair. The only other means of increasing the size of the clip region is :meth:`Context.reset_clip`. .. method:: close_path() Adds a line segment to the path from the current point to the beginning of the current sub-path, (the most recent point passed to :meth:`Context.move_to`), and closes this sub-path. After this call the current point will be at the joined endpoint of the sub-path. The behavior of :meth:`.close_path` is distinct from simply calling :meth:`Context.line_to` with the equivalent coordinate in the case of stroking. When a closed sub-path is stroked, there are no caps on the ends of the sub-path. Instead, there is a line join connecting the final and initial segments of the sub-path. If there is no current point before the call to :meth:`.close_path`, this function will have no effect. Note: As of cairo version 1.2.4 any call to :meth:`.close_path` will place an explicit MOVE_TO element into the path immediately after the CLOSE_PATH element, (which can be seen in :meth:`Context.copy_path` for example). This can simplify path processing in some cases as it may not be necessary to save the "last move_to point" during processing as the MOVE_TO immediately after the CLOSE_PATH will provide that point. .. method:: copy_clip_rectangle_list() :returns: the current clip region as a list of rectangles in user coordinates. Returns a list of :class:`Rectangle` :rtype: list .. versionadded:: 1.4 .. method:: copy_page() Emits the current page for backends that support multiple pages, but doesn't clear it, so, the contents of the current page will be retained for the next page too. Use :meth:`Context.show_page` if you want to get an empty page after the emission. This is a convenience function that simply calls :meth:`Surface.copy_page` on *Context's* target. .. method:: copy_path() :returns: :class:`Path` :raises: :exc:`MemoryError` in case of no memory Creates a copy of the current path and returns it to the user as a :class:`Path`. .. method:: copy_path_flat() :returns: :class:`Path` :raises: :exc:`MemoryError` in case of no memory Gets a flattened copy of the current path and returns it to the user as a :class:`Path`. This function is like :meth:`Context.copy_path` except that any curves in the path will be approximated with piecewise-linear approximations, (accurate to within the current tolerance value). That is, the result is guaranteed to not have any elements of type CAIRO_PATH_CURVE_TO which will instead be replaced by a series of CAIRO_PATH_LINE_TO elements. .. method:: curve_to(x1, y1, x2, y2, x3, y3) :param x1: the X coordinate of the first control point :type x1: float :param y1: the Y coordinate of the first control point :type y1: float :param x2: the X coordinate of the second control point :type x2: float :param y2: the Y coordinate of the second control point :type y2: float :param x3: the X coordinate of the end of the curve :type x3: float :param y3: the Y coordinate of the end of the curve :type y3: float Adds a cubic Bézier spline to the path from the current point to position *(x3, y3)* in user-space coordinates, using *(x1, y1)* and *(x2, y2)* as the control points. After this call the current point will be *(x3, y3)*. If there is no current point before the call to :meth:`.curve_to` this function will behave as if preceded by a call to ``ctx.move_to(x1, y1)``. .. method:: device_to_user(x, y) :param x: X value of coordinate :type x: float :param y: Y value of coordinate :type y: float :returns: (x, y), both float :rtype: tuple Transform a coordinate from device space to user space by multiplying the given point by the inverse of the current transformation matrix (CTM). .. method:: device_to_user_distance(dx, dy) :param dx: X component of a distance vector :type dx: float :param dy: Y component of a distance vector :type dy: float :returns: (dx, dy), both float :rtype: tuple Transform a distance vector from device space to user space. This function is similar to :meth:`Context.device_to_user` except that the translation components of the inverse CTM will be ignored when transforming *(dx,dy)*. .. method:: fill() A drawing operator that fills the current path according to the current :class:`fill rule `, (each sub-path is implicitly closed before being filled). After :meth:`.fill`, the current path will be cleared from the :class:`Context`. See :meth:`Context.set_fill_rule` and :meth:`Context.fill_preserve`. .. method:: fill_extents() :returns: (x1, y1, x2, y2), all float :rtype: tuple * *x1*: left of the resulting extents * *y1*: top of the resulting extents * *x2*: right of the resulting extents * *y2*: bottom of the resulting extents Computes a bounding box in user coordinates covering the area that would be affected, (the "inked" area), by a :meth:`Context.fill` operation given the current path and fill parameters. If the current path is empty, returns an empty rectangle (0,0,0,0). Surface dimensions and clipping are not taken into account. Contrast with :meth:`Context.path_extents`, which is similar, but returns non-zero extents for some paths with no inked area, (such as a simple line segment). Note that :meth:`.fill_extents` must necessarily do more work to compute the precise inked areas in light of the fill rule, so :meth:`Context.path_extents` may be more desirable for sake of performance if the non-inked path extents are desired. See :meth:`Context.fill`, :meth:`Context.set_fill_rule` and :meth:`Context.fill_preserve`. .. method:: fill_preserve() A drawing operator that fills the current path according to the current :class:`fill rule `, (each sub-path is implicitly closed before being filled). Unlike :meth:`Context.fill`, :meth:`.fill_preserve` preserves the path within the :class:`Context`. See :meth:`Context.set_fill_rule` and :meth:`Context.fill`. .. method:: font_extents() :returns: (ascent, descent, height, max_x_advance, max_y_advance), all float :rtype: tuple Gets the font extents for the currently selected font. .. method:: get_antialias() :returns: the current antialias mode, as set by :meth:`Context.set_antialias`. :rtype: cairo.Antialias .. method:: get_current_point() :returns: (x, y), both float :rtype: tuple * *x*: X coordinate of the current point * *y*: Y coordinate of the current point Gets the current point of the current path, which is conceptually the final point reached by the path so far. The current point is returned in the user-space coordinate system. If there is no defined current point or if :class:`Context` is in an error status, *x* and *y* will both be set to 0.0. It is possible to check this in advance with :meth:`Context.has_current_point`. Most path construction functions alter the current point. See the following for details on how they affect the current point: :meth:`Context.new_path`, :meth:`Context.new_sub_path`, :meth:`Context.append_path`, :meth:`Context.close_path`, :meth:`Context.move_to`, :meth:`Context.line_to`, :meth:`Context.curve_to`, :meth:`Context.rel_move_to`, :meth:`Context.rel_line_to`, :meth:`Context.rel_curve_to`, :meth:`Context.arc`, :meth:`Context.arc_negative`, :meth:`Context.rectangle`, :meth:`Context.text_path`, :meth:`Context.glyph_path`, :meth:`Context.stroke_to_path`. Some functions use and alter the current point but do not otherwise change current path: :meth:`Context.show_text`. Some functions unset the current path and as a result, current point: :meth:`Context.fill`, :meth:`Context.stroke`. .. method:: get_dash() :returns: (dashes, offset) :rtype: tuple * *dashes*: return value as a tuple for the dash array * *offset*: return value as float for the current dash offset Gets the current dash array. .. versionadded:: 1.4 .. method:: get_dash_count() :returns: the length of the dash array, or 0 if no dash array set. :rtype: int See also :meth:`Context.set_dash` and :meth:`Context.get_dash`. .. versionadded:: 1.4 .. method:: get_fill_rule() :returns: the current fill rule, as set by :meth:`Context.set_fill_rule`. :rtype: cairo.FillRule .. method:: get_font_face() :returns: the current :class:`FontFace` for the :class:`Context`. .. method:: get_font_matrix() :returns: the current :class:`Matrix` for the :class:`Context`. See :meth:`Context.set_font_matrix`. .. method:: get_font_options() :returns: the current :class:`FontOptions` for the :class:`Context`. Retrieves font rendering options set via :meth:`Context.set_font_options`. Note that the returned options do not include any options derived from the underlying surface; they are literally the options passed to :meth:`Context.set_font_options`. .. method:: get_group_target() :returns: the target :class:`Surface`. Gets the current destination :class:`Surface` for the :class:`Context`. This is either the original target surface as passed to :class:`Context` or the target surface for the current group as started by the most recent call to :meth:`Context.push_group` or :meth:`Context.push_group_with_content`. .. versionadded:: 1.2 .. method:: get_line_cap() :returns: the current line cap style, as set by :meth:`Context.set_line_cap`. :rtype: cairo.LineCap .. method:: get_line_join() :returns: the current line join style, as set by :meth:`Context.set_line_join`. :rtype: cairo.LineJoin .. method:: get_line_width() :returns: the current line width :rtype: float This function returns the current line width value exactly as set by :meth:`Context.set_line_width`. Note that the value is unchanged even if the CTM has changed between the calls to :meth:`Context.set_line_width` and :meth:`.get_line_width`. .. method:: get_matrix() :returns: the current transformation :class:`Matrix` (CTM) .. method:: get_miter_limit() :returns: the current miter limit, as set by :meth:`Context.set_miter_limit`. :rtype: float .. method:: get_operator() :returns: the current compositing operator for a :class:`Context`. :rtype: cairo.Operator .. method:: get_scaled_font() :returns: the current :class:`ScaledFont` for a :class:`Context`. .. versionadded:: 1.4 .. method:: get_source() :returns: the current source :class:`Pattern` for a :class:`Context`. .. method:: get_target() :returns: the target :class:`Surface` for the :class:`Context` .. method:: get_tolerance() :returns: the current tolerance value, as set by :meth:`Context.set_tolerance` :rtype: float .. method:: glyph_extents(glyphs) :param glyphs: glyphs, a sequence of :class:`Glyph` :rtype: TextExtents Gets the extents for an array of glyphs. The extents describe a user-space rectangle that encloses the "inked" portion of the glyphs, (as they would be drawn by :meth:`Context.show_glyphs`). Additionally, the x_advance and y_advance values indicate the amount by which the current point would be advanced by :meth:`Context.show_glyphs`. Note that whitespace glyphs do not contribute to the size of the rectangle (extents.width and extents.height). .. method:: glyph_path(glyphs) :param glyphs: glyphs to show, a sequence of :class:`Glyph` Adds closed paths for the glyphs to the current path. The generated path if filled, achieves an effect similar to that of :meth:`Context.show_glyphs`. .. method:: has_current_point() returns: True iff a current point is defined on the current path. See :meth:`Context.get_current_point` for details on the current point. .. versionadded:: 1.6 .. method:: identity_matrix() Resets the current transformation :class:`Matrix` (CTM) by setting it equal to the identity matrix. That is, the user-space and device-space axes will be aligned and one user-space unit will transform to one device-space unit. .. method:: in_fill(x, y) :param x: X coordinate of the point to test :type x: float :param y: Y coordinate of the point to test :type y: float :returns: True iff the point is inside the area that would be affected by a :meth:`Context.fill` operation given the current path and filling parameters. Surface dimensions and clipping are not taken into account. See :meth:`Context.fill`, :meth:`Context.set_fill_rule` and :meth:`Context.fill_preserve`. .. method:: in_stroke(x, y) :param x: X coordinate of the point to test :type x: float :param y: Y coordinate of the point to test :type y: float :returns: True iff the point is inside the area that would be affected by a :meth:`Context.stroke` operation given the current path and stroking parameters. Surface dimensions and clipping are not taken into account. See :meth:`Context.stroke`, :meth:`Context.set_line_width`, :meth:`Context.set_line_join`, :meth:`Context.set_line_cap`, :meth:`Context.set_dash`, and :meth:`Context.stroke_preserve`. .. method:: line_to(x, y) :param x: the X coordinate of the end of the new line :type x: float :param y: the Y coordinate of the end of the new line :type y: float Adds a line to the path from the current point to position *(x, y)* in user-space coordinates. After this call the current point will be *(x, y)*. If there is no current point before the call to :meth:`.line_to` this function will behave as ``ctx.move_to(x, y)``. .. method:: mask(pattern) :param pattern: a :class:`Pattern` A drawing operator that paints the current source using the alpha channel of *pattern* as a mask. (Opaque areas of *pattern* are painted with the source, transparent areas are not painted.) .. method:: mask_surface(surface, x=0.0, y=0.0) :param surface: a :class:`Surface` :param x: X coordinate at which to place the origin of *surface* :type x: float :param y: Y coordinate at which to place the origin of *surface* :type y: float A drawing operator that paints the current source using the alpha channel of *surface* as a mask. (Opaque areas of *surface* are painted with the source, transparent areas are not painted.) .. method:: move_to(x, y) :param x: the X coordinate of the new position :type x: float :param y: the Y coordinate of the new position :type y: float Begin a new sub-path. After this call the current point will be *(x, y)*. .. method:: new_path() Clears the current path. After this call there will be no path and no current point. .. method:: new_sub_path() Begin a new sub-path. Note that the existing path is not affected. After this call there will be no current point. In many cases, this call is not needed since new sub-paths are frequently started with :meth:`Context.move_to`. A call to :meth:`.new_sub_path` is particularly useful when beginning a new sub-path with one of the :meth:`Context.arc` calls. This makes things easier as it is no longer necessary to manually compute the arc's initial coordinates for a call to :meth:`Context.move_to`. .. versionadded:: 1.6 .. method:: paint() A drawing operator that paints the current source everywhere within the current clip region. .. method:: paint_with_alpha(alpha) :param alpha: alpha value, between 0 (transparent) and 1 (opaque) :type alpha: float A drawing operator that paints the current source everywhere within the current clip region using a mask of constant alpha value *alpha*. The effect is similar to :meth:`Context.paint`, but the drawing is faded out using the alpha value. .. method:: path_extents() :returns: (x1, y1, x2, y2), all float :rtype: tuple * *x1*: left of the resulting extents * *y1*: top of the resulting extents * *x2*: right of the resulting extents * *y2*: bottom of the resulting extents Computes a bounding box in user-space coordinates covering the points on the current path. If the current path is empty, returns an empty rectangle (0, 0, 0, 0). Stroke parameters, fill rule, surface dimensions and clipping are not taken into account. Contrast with :meth:`Context.fill_extents` and :meth:`Context.stroke_extents` which return the extents of only the area that would be "inked" by the corresponding drawing operations. The result of :meth:`.path_extents` is defined as equivalent to the limit of :meth:`Context.stroke_extents` with cairo.LINE_CAP_ROUND as the line width approaches 0.0, (but never reaching the empty-rectangle returned by :meth:`Context.stroke_extents` for a line width of 0.0). Specifically, this means that zero-area sub-paths such as :meth:`Context.move_to`; :meth:`Context.line_to` segments, (even degenerate cases where the coordinates to both calls are identical), will be considered as contributing to the extents. However, a lone :meth:`Context.move_to` will not contribute to the results of :meth:`Context.path_extents`. .. versionadded:: 1.6 .. method:: pop_group() :returns: a newly created :class:`SurfacePattern` containing the results of all drawing operations performed to the group. Terminates the redirection begun by a call to :meth:`Context.push_group` or :meth:`Context.push_group_with_content` and returns a new pattern containing the results of all drawing operations performed to the group. The :meth:`.pop_group` function calls :meth:`Context.restore`, (balancing a call to :meth:`Context.save` by the :meth:`Context.push_group` function), so that any changes to the graphics state will not be visible outside the group. .. versionadded:: 1.2 .. method:: pop_group_to_source() Terminates the redirection begun by a call to :meth:`Context.push_group` or :meth:`Context.push_group_with_content` and installs the resulting pattern as the source :class:`Pattern` in the given :class:`Context`. The behavior of this function is equivalent to the sequence of operations:: group = cairo_pop_group() ctx.set_source(group) but is more convenient as their is no need for a variable to store the short-lived pointer to the pattern. The :meth:`Context.pop_group` function calls :meth:`Context.restore`, (balancing a call to :meth:`Context.save` by the :meth:`Context.push_group` function), so that any changes to the graphics state will not be visible outside the group. .. versionadded:: 1.2 .. method:: push_group() Temporarily redirects drawing to an intermediate surface known as a group. The redirection lasts until the group is completed by a call to :meth:`Context.pop_group` or :meth:`Context.pop_group_to_source`. These calls provide the result of any drawing to the group as a pattern, (either as an explicit object, or set as the source pattern). This group functionality can be convenient for performing intermediate compositing. One common use of a group is to render objects as opaque within the group, (so that they occlude each other), and then blend the result with translucence onto the destination. Groups can be nested arbitrarily deep by making balanced calls to :meth:`Context.push_group`/:meth:`Context.pop_group`. Each call pushes/pops the new target group onto/from a stack. The :meth:`.push_group` function calls :meth:`Context.save` so that any changes to the graphics state will not be visible outside the group, (the pop_group functions call :meth:`Context.restore`). By default the intermediate group will have a :class:`cairo.Content` type of :attr:`cairo.Content.COLOR_ALPHA`. Other content types can be chosen for the group by using :meth:`Context.push_group_with_content` instead. As an example, here is how one might fill and stroke a path with translucence, but without any portion of the fill being visible under the stroke:: ctx.push_group() ctx.set_source(fill_pattern) ctx.fill_preserve() ctx.set_source(stroke_pattern) ctx.stroke() ctx.pop_group_to_source() ctx.paint_with_alpha(alpha) .. versionadded:: 1.2 .. method:: push_group_with_content(content) :param cairo.Content content: a content indicating the type of group that will be created Temporarily redirects drawing to an intermediate surface known as a group. The redirection lasts until the group is completed by a call to :meth:`Context.pop_group` or :meth:`Context.pop_group_to_source`. These calls provide the result of any drawing to the group as a pattern, (either as an explicit object, or set as the source pattern). The group will have a content type of *content*. The ability to control this content type is the only distinction between this function and :meth:`Context.push_group` which you should see for a more detailed description of group rendering. .. versionadded:: 1.2 .. method:: rectangle(x, y, width, height) :param x: the X coordinate of the top left corner of the rectangle :type x: float :param y: the Y coordinate to the top left corner of the rectangle :type y: float :param width: the width of the rectangle :type width: float :param height: the height of the rectangle :type height: float Adds a closed sub-path rectangle of the given size to the current path at position *(x, y)* in user-space coordinates. This function is logically equivalent to:: ctx.move_to(x, y) ctx.rel_line_to(width, 0) ctx.rel_line_to(0, height) ctx.rel_line_to(-width, 0) ctx.close_path() .. method:: rel_curve_to(dx1, dy1, dx2, dy2, dx3, dy4) :param dx1: the X offset to the first control point :type dx1: float :param dy1: the Y offset to the first control point :type dy1: float :param dx2: the X offset to the second control point :type dx2: float :param dy2: the Y offset to the second control point :type dy2: float :param dx3: the X offset to the end of the curve :type dx3: float :param dy3: the Y offset to the end of the curve :type dy3: float :raises: :exc:`cairo.Error` if called with no current point. Relative-coordinate version of :meth:`Context.curve_to`. All offsets are relative to the current point. Adds a cubic Bézier spline to the path from the current point to a point offset from the current point by *(dx3, dy3)*, using points offset by *(dx1, dy1)* and *(dx2, dy2)* as the control points. After this call the current point will be offset by *(dx3, dy3)*. Given a current point of (x, y), ``ctx.rel_curve_to(dx1, dy1, dx2, dy2, dx3, dy3)`` is logically equivalent to ``ctx.curve_to(x+dx1, y+dy1, x+dx2, y+dy2, x+dx3, y+dy3)``. .. method:: rel_line_to(dx, dy) :param dx: the X offset to the end of the new line :type dx: float :param dy: the Y offset to the end of the new line :type dy: float :raises: :exc:`cairo.Error` if called with no current point. Relative-coordinate version of :meth:`Context.line_to`. Adds a line to the path from the current point to a point that is offset from the current point by *(dx, dy)* in user space. After this call the current point will be offset by *(dx, dy)*. Given a current point of (x, y), ``ctx.rel_line_to(dx, dy)`` is logically equivalent to ``ctx.line_to(x + dx, y + dy)``. .. method:: rel_move_to(dx, dy) :param dx: the X offset :type dx: float :param dy: the Y offset :type dy: float :raises: :exc:`cairo.Error` if called with no current point. Begin a new sub-path. After this call the current point will offset by *(dx, dy)*. Given a current point of (x, y), ``ctx.rel_move_to(dx, dy)`` is logically equivalent to ``ctx.(x + dx, y + dy)``. .. method:: reset_clip() Reset the current clip region to its original, unrestricted state. That is, set the clip region to an infinitely large shape containing the target surface. Equivalently, if infinity is too hard to grasp, one can imagine the clip region being reset to the exact bounds of the target surface. Note that code meant to be reusable should not call :meth:`.reset_clip` as it will cause results unexpected by higher-level code which calls :meth:`.clip`. Consider using :meth:`.save` and :meth:`.restore` around :meth:`.clip` as a more robust means of temporarily restricting the clip region. .. method:: restore() Restores :class:`Context` to the state saved by a preceding call to :meth:`.save` and removes that state from the stack of saved states. .. method:: rotate(angle) :param angle: angle (in radians) by which the user-space axes will be rotated :type angle: float Modifies the current transformation matrix (CTM) by rotating the user-space axes by *angle* radians. The rotation of the axes takes places after any existing transformation of user space. The rotation direction for positive angles is from the positive X axis toward the positive Y axis. .. method:: save() Makes a copy of the current state of :class:`Context` and saves it on an internal stack of saved states. When :meth:`.restore` is called, :class:`Context` will be restored to the saved state. Multiple calls to :meth:`.save` and :meth:`.restore` can be nested; each call to :meth:`.restore` restores the state from the matching paired :meth:`.save`. .. method:: scale(sx, sy) :param sx: scale factor for the X dimension :type sx: float :param sy: scale factor for the Y dimension :type sy: float Modifies the current transformation matrix (CTM) by scaling the X and Y user-space axes by *sx* and *sy* respectively. The scaling of the axes takes place after any existing transformation of user space. .. method:: select_font_face(family[, slant[, weight]]) :param family: a font family name :type family: text :param cairo.FontSlant slant: the font slant of the font, defaults to :attr:`cairo.FontSlant.NORMAL`. :param cairo.FontWeight weight: the font weight of the font, defaults to :attr:`cairo.FontWeight.NORMAL`. Note: The :meth:`.select_font_face` function call is part of what the cairo designers call the "toy" text API. It is convenient for short demos and simple programs, but it is not expected to be adequate for serious text-using applications. Selects a family and style of font from a simplified description as a family name, slant and weight. Cairo provides no operation to list available family names on the system (this is a "toy", remember), but the standard CSS2 generic family names, ("serif", "sans-serif", "cursive", "fantasy", "monospace"), are likely to work as expected. For "real" font selection, see the font-backend-specific font_face_create functions for the font backend you are using. (For example, if you are using the freetype-based cairo-ft font backend, see cairo_ft_font_face_create_for_ft_face() or cairo_ft_font_face_create_for_pattern().) The resulting font face could then be used with cairo_scaled_font_create() and cairo_set_scaled_font(). Similarly, when using the "real" font support, you can call directly into the underlying font system, (such as fontconfig or freetype), for operations such as listing available fonts, etc. It is expected that most applications will need to use a more comprehensive font handling and text layout library, (for example, pango), in conjunction with cairo. If text is drawn without a call to :meth:`.select_font_face`, (nor :meth:`.set_font_face` nor :meth:`.set_scaled_font`), the default family is platform-specific, but is essentially "sans-serif". Default slant is :attr:`cairo.FontSlant.NORMAL`, and default weight is :attr:`cairo.FontWeight.NORMAL`. This function is equivalent to a call to :class:`ToyFontFace` followed by :meth:`.set_font_face`. .. method:: set_antialias(antialias) :param cairo.Antialias antialias: the new antialias mode Set the antialiasing mode of the rasterizer used for drawing shapes. This value is a hint, and a particular backend may or may not support a particular value. At the current time, no backend supports :attr:`cairo.Antialias.SUBPIXEL` when drawing shapes. Note that this option does not affect text rendering, instead see :meth:`FontOptions.set_antialias`. .. method:: set_dash(dashes, [offset=0]) :param dashes: a sequence specifying alternate lengths of on and off stroke portions as float. :param offset: an offset into the dash pattern at which the stroke should start, defaults to 0. :type offset: int :raises: :exc:`cairo.Error` if any value in *dashes* is negative, or if all values are 0. Sets the dash pattern to be used by :meth:`.stroke`. A dash pattern is specified by *dashes* - a sequence of positive values. Each value provides the length of alternate "on" and "off" portions of the stroke. The *offset* specifies an offset into the pattern at which the stroke begins. Each "on" segment will have caps applied as if the segment were a separate sub-path. In particular, it is valid to use an "on" length of 0.0 with :attr:`cairo.LineCap.ROUND` or :attr:`cairo.LineCap.SQUARE` in order to distributed dots or squares along a path. Note: The length values are in user-space units as evaluated at the time of stroking. This is not necessarily the same as the user space at the time of :meth:`.set_dash`. If the number of dashes is 0 dashing is disabled. If the number of dashes is 1 a symmetric pattern is assumed with alternating on and off portions of the size specified by the single value in *dashes*. .. method:: set_fill_rule(fill_rule) :param cairo.FillRule fill_rule: a fill rule to set the within the cairo context. The fill rule is used to determine which regions are inside or outside a complex (potentially self-intersecting) path. The current fill rule affects both :meth:`.fill` and :meth:`.clip`. The default fill rule is :attr:`cairo.FillRule.WINDING`. .. method:: set_font_face(font_face) :param font_face: a :class:`FontFace`, or None to restore to the default :class:`FontFace` Replaces the current :class:`FontFace` object in the :class:`Context` with *font_face*. .. method:: set_font_matrix(matrix) :param matrix: a :class:`Matrix` describing a transform to be applied to the current font. Sets the current font matrix to *matrix*. The font matrix gives a transformation from the design space of the font (in this space, the em-square is 1 unit by 1 unit) to user space. Normally, a simple scale is used (see :meth:`.set_font_size`), but a more complex font matrix can be used to shear the font or stretch it unequally along the two axes .. method:: set_font_options(options) :param options: :class:`FontOptions` to use Sets a set of custom font rendering options for the :class:`Context`. Rendering options are derived by merging these options with the options derived from underlying surface; if the value in *options* has a default value (like :attr:`cairo.Antialias.DEFAULT`), then the value from the surface is used. .. method:: set_font_size(size) :param size: the new font size, in user space units :type size: float Sets the current font matrix to a scale by a factor of *size*, replacing any font matrix previously set with :meth:`.set_font_size` or :meth:`.set_font_matrix`. This results in a font size of *size* user space units. (More precisely, this matrix will result in the font's em-square being a *size* by *size* square in user space.) If text is drawn without a call to :meth:`.set_font_size`, (nor :meth:`.set_font_matrix` nor :meth:`.set_scaled_font`), the default font size is 10.0. .. method:: set_line_cap(line_cap) :param cairo.LineCap line_cap: a line cap style Sets the current line cap style within the :class:`Context`. As with the other stroke parameters, the current line cap style is examined by :meth:`.stroke`, :meth:`.stroke_extents`, and :meth:`.stroke_to_path`, but does not have any effect during path construction. The default line cap style is :attr:`cairo.LineCap.BUTT`. .. method:: set_line_join(line_join) :param cairo.LineJoin line_join: a line join style Sets the current line join style within the :class:`Context`. As with the other stroke parameters, the current line join style is examined by :meth:`.stroke`, :meth:`.stroke_extents`, and :meth:`.stroke_to_path`, but does not have any effect during path construction. The default line join style is :attr:`cairo.LineJoin.MITER`. .. method:: set_line_width(width) :param width: a line width :type width: float Sets the current line width within the :class:`Context`. The line width value specifies the diameter of a pen that is circular in user space, (though device-space pen may be an ellipse in general due to scaling/shear/rotation of the CTM). Note: When the description above refers to user space and CTM it refers to the user space and CTM in effect at the time of the stroking operation, not the user space and CTM in effect at the time of the call to :meth:`.set_line_width`. The simplest usage makes both of these spaces identical. That is, if there is no change to the CTM between a call to :meth:`.set_line_width` and the stroking operation, then one can just pass user-space values to :meth:`.set_line_width` and ignore this note. As with the other stroke parameters, the current line width is examined by :meth:`.stroke`, :meth:`.stroke_extents`, and :meth:`.stroke_to_path`, but does not have any effect during path construction. The default line width value is 2.0. .. method:: set_matrix(matrix) :param matrix: a transformation :class:`Matrix` from user space to device space. Modifies the current transformation matrix (CTM) by setting it equal to *matrix*. .. method:: set_miter_limit(limit) :param limit: miter limit to set :type width: float Sets the current miter limit within the :class:`Context`. If the current line join style is set to :attr:`cairo.LineJoin.MITER` (see :meth:`.set_line_join`), the miter limit is used to determine whether the lines should be joined with a bevel instead of a miter. Cairo divides the length of the miter by the line width. If the result is greater than the miter limit, the style is converted to a bevel. As with the other stroke parameters, the current line miter limit is examined by :meth:`.stroke`, :meth:`.stroke_extents`, and :meth:`.stroke_to_path`, but does not have any effect during path construction. The default miter limit value is 10.0, which will convert joins with interior angles less than 11 degrees to bevels instead of miters. For reference, a miter limit of 2.0 makes the miter cutoff at 60 degrees, and a miter limit of 1.414 makes the cutoff at 90 degrees. A miter limit for a desired angle can be computed as:: miter limit = 1/math.sin(angle/2) .. method:: set_operator(op) :param cairo.Operator op: the compositing operator to set for use in all drawing operations. The default operator is :attr:`cairo.Operator.OVER`. .. method:: set_scaled_font(scaled_font) :param scaled_font: a :class:`ScaledFont` Replaces the current font face, font matrix, and font options in the :class:`Context` with those of the :class:`ScaledFont`. Except for some translation, the current CTM of the :class:`Context` should be the same as that of the :class:`ScaledFont`, which can be accessed using :meth:`ScaledFont.get_ctm`. .. versionadded:: 1.2 .. method:: set_source(source) :param source: a :class:`Pattern` to be used as the source for subsequent drawing operations. Sets the source pattern within :class:`Context` to *source*. This pattern will then be used for any subsequent drawing operation until a new source pattern is set. Note: The pattern's transformation matrix will be locked to the user space in effect at the time of :meth:`.set_source`. This means that further modifications of the current transformation matrix will not affect the source pattern. See :meth:`Pattern.set_matrix`. The default source pattern is a solid pattern that is opaque black, (that is, it is equivalent to ``set_source_rgb(0.0, 0.0, 0.0)``. .. method:: set_source_rgb(red, green, blue) :param red: red component of color :type red: float :param green: green component of color :type green: float :param blue: blue component of color :type blue: float Sets the source pattern within :class:`Context` to an opaque color. This opaque color will then be used for any subsequent drawing operation until a new source pattern is set. The color components are floating point numbers in the range 0 to 1. If the values passed in are outside that range, they will be clamped. The default source pattern is opaque black, (that is, it is equivalent to ``set_source_rgb(0.0, 0.0, 0.0)``. .. method:: set_source_rgba(red, green, blue[, alpha=1.0]) :param red: red component of color :type red: float :param green: green component of color :type green: float :param blue: blue component of color :type blue: float :param alpha: alpha component of color :type alpha: float Sets the source pattern within :class:`Context` to a translucent color. This color will then be used for any subsequent drawing operation until a new source pattern is set. The color and alpha components are floating point numbers in the range 0 to 1. If the values passed in are outside that range, they will be clamped. The default source pattern is opaque black, (that is, it is equivalent to ``set_source_rgba(0.0, 0.0, 0.0, 1.0)``. .. method:: set_source_surface(surface[, x=0.0[, y=0.0]]) :param surface: a :class:`Surface` to be used to set the source pattern :param x: User-space X coordinate for surface origin :type x: float :param y: User-space Y coordinate for surface origin :type y: float This is a convenience function for creating a pattern from a :class:`Surface` and setting it as the source in :class:`Context` with :meth:`.set_source`. The *x* and *y* parameters give the user-space coordinate at which the surface origin should appear. (The surface origin is its upper-left corner before any transformation has been applied.) The *x* and *y* patterns are negated and then set as translation values in the pattern matrix. Other than the initial translation pattern matrix, as described above, all other pattern attributes, (such as its extend mode), are set to the default values as in :class:`SurfacePattern`. The resulting pattern can be queried with :meth:`.get_source` so that these attributes can be modified if desired, (eg. to create a repeating pattern with :meth:`.Pattern.set_extend`). .. method:: set_tolerance(tolerance) :param tolerance: the tolerance, in device units (typically pixels) :type tolerance: float Sets the tolerance used when converting paths into trapezoids. Curved segments of the path will be subdivided until the maximum deviation between the original path and the polygonal approximation is less than *tolerance*. The default value is 0.1. A larger value will give better performance, a smaller value, better appearance. (Reducing the value from the default value of 0.1 is unlikely to improve appearance significantly.) The accuracy of paths within Cairo is limited by the precision of its internal arithmetic, and the prescribed *tolerance* is restricted to the smallest representable internal value. .. method:: show_glyphs(glyphs) :param glyphs: glyphs to show as a sequence of :class:`Glyph` A drawing operator that generates the shape from an array of glyphs, rendered according to the current font face, font size (font matrix), and font options. .. method:: show_page() Emits and clears the current page for backends that support multiple pages. Use :meth:`.copy_page` if you don't want to clear the page. This is a convenience function that simply calls ``ctx.get_target() . show_page()`` .. method:: show_text(text) :param text: text :type text: text A drawing operator that generates the shape from a string of text, rendered according to the current font_face, font_size (font_matrix), and font_options. This function first computes a set of glyphs for the string of text. The first glyph is placed so that its origin is at the current point. The origin of each subsequent glyph is offset from that of the previous glyph by the advance values of the previous glyph. After this call the current point is moved to the origin of where the next glyph would be placed in this same progression. That is, the current point will be at the origin of the final glyph offset by its advance values. This allows for easy display of a single logical string with multiple calls to :meth:`.show_text`. Note: The :meth:`.show_text` function call is part of what the cairo designers call the "toy" text API. It is convenient for short demos and simple programs, but it is not expected to be adequate for serious text-using applications. See :meth:`.show_glyphs` for the "real" text display API in cairo. .. method:: stroke() A drawing operator that strokes the current path according to the current line width, line join, line cap, and dash settings. After :meth:`.stroke`, the current path will be cleared from the cairo context. See :meth:`.set_line_width`, :meth:`.set_line_join`, :meth:`.set_line_cap`, :meth:`.set_dash`, and :meth:`.stroke_preserve`. Note: Degenerate segments and sub-paths are treated specially and provide a useful result. These can result in two different situations: 1. Zero-length "on" segments set in :meth:`.set_dash`. If the cap style is :attr:`cairo.LineCap.ROUND` or :attr:`cairo.LineCap.SQUARE` then these segments will be drawn as circular dots or squares respectively. In the case of :attr:`cairo.LineCap.SQUARE`, the orientation of the squares is determined by the direction of the underlying path. 2. A sub-path created by :meth:`.move_to` followed by either a :meth:`.close_path` or one or more calls to :meth:`.line_to` to the same coordinate as the :meth:`.move_to`. If the cap style is :attr:`cairo.LineCap.ROUND` then these sub-paths will be drawn as circular dots. Note that in the case of :attr:`cairo.LineCap.SQUARE` a degenerate sub-path will not be drawn at all, (since the correct orientation is indeterminate). In no case will a cap style of :attr:`cairo.LineCap.BUTT` cause anything to be drawn in the case of either degenerate segments or sub-paths. .. method:: stroke_extents() :returns: (x1, y1, x2, y2), all float :rtype: tuple * *x1*: left of the resulting extents * *y1*: top of the resulting extents * *x2*: right of the resulting extents * *y2*: bottom of the resulting extents Computes a bounding box in user coordinates covering the area that would be affected, (the "inked" area), by a :meth:`.stroke` operation given the current path and stroke parameters. If the current path is empty, returns an empty rectangle (0, 0, 0, 0). Surface dimensions and clipping are not taken into account. Note that if the line width is set to exactly zero, then :meth:`.stroke_extents` will return an empty rectangle. Contrast with :meth:`.path_extents` which can be used to compute the non-empty bounds as the line width approaches zero. Note that :meth:`.stroke_extents` must necessarily do more work to compute the precise inked areas in light of the stroke parameters, so :meth:`.path_extents` may be more desirable for sake of performance if non-inked path extents are desired. See :meth:`.stroke`, :meth:`.set_line_width`, :meth:`.set_line_join`, :meth:`.set_line_cap`, :meth:`.set_dash`, and :meth:`.stroke_preserve`. .. method:: stroke_preserve() A drawing operator that strokes the current path according to the current line width, line join, line cap, and dash settings. Unlike :meth:`.stroke`, :meth:`.stroke_preserve` preserves the path within the cairo context. See :meth:`.set_line_width`, :meth:`.set_line_join`, :meth:`.set_line_cap`, :meth:`.set_dash`, and :meth:`.stroke_preserve`. .. method:: text_extents(text) :param text: text to get extents for :type text: text :rtype: TextExtents Gets the extents for a string of text. The extents describe a user-space rectangle that encloses the "inked" portion of the text, (as it would be drawn by :meth:`Context.show_text`). Additionally, the x_advance and y_advance values indicate the amount by which the current point would be advanced by :meth:`Context.show_text`. Note that whitespace characters do not directly contribute to the size of the rectangle (extents.width and extents.height). They do contribute indirectly by changing the position of non-whitespace characters. In particular, trailing whitespace characters are likely to not affect the size of the rectangle, though they will affect the x_advance and y_advance values. .. method:: text_path(text) :param text: text :type text: text Adds closed paths for text to the current path. The generated path if filled, achieves an effect similar to that of :meth:`Context.show_text`. Text conversion and positioning is done similar to :meth:`Context.show_text`. Like :meth:`Context.show_text`, After this call the current point is moved to the origin of where the next glyph would be placed in this same progression. That is, the current point will be at the origin of the final glyph offset by its advance values. This allows for chaining multiple calls to to :meth:`Context.text_path` without having to set current point in between. Note: The :meth:`.text_path` function call is part of what the cairo designers call the "toy" text API. It is convenient for short demos and simple programs, but it is not expected to be adequate for serious text-using applications. See :meth:`Context.glyph_path` for the "real" text path API in cairo. .. method:: transform(matrix) :param matrix: a transformation :class:`Matrix` to be applied to the user-space axes Modifies the current transformation matrix (CTM) by applying *matrix* as an additional transformation. The new transformation of user space takes place after any existing transformation. .. method:: translate(tx, ty) :param tx: amount to translate in the X direction :type tx: float :param ty: amount to translate in the Y direction :type ty: float Modifies the current transformation matrix (CTM) by translating the user-space origin by *(tx, ty)*. This offset is interpreted as a user-space coordinate according to the CTM in place before the new call to :meth:`.translate`. In other words, the translation of the user-space origin takes place after any existing transformation. .. method:: user_to_device(x, y) :param x: X value of coordinate :type x: float :param y: Y value of coordinate :type y: float :returns: (x, y), both float :rtype: tuple * *x*: X value of coordinate * *y*: Y value of coordinate Transform a coordinate from user space to device space by multiplying the given point by the current transformation matrix (CTM). .. method:: user_to_device_distance(dx, dy) :param dx: X value of a distance vector :type dx: float :param dy: Y value of a distance vector :type dy: float :returns: (dx, dy), both float :rtype: tuple * *dx*: X value of a distance vector * *dy*: Y value of a distance vector Transform a distance vector from user space to device space. This function is similar to :meth:`Context.user_to_device` except that the translation components of the CTM will be ignored when transforming *(dx,dy)*. .. method:: in_clip(x, y) :param float x: X coordinate of the point to test :param float y: Y coordinate of the point to test :returns: :obj:`True` if the point is inside, or :obj:`False` if outside. :rtype: bool Tests whether the given point is inside the area that would be visible through the current clip, i.e. the area that would be filled by a :meth:`paint` operation. See :meth:`clip`, and :meth:`clip_preserve`. .. versionadded:: 1.12.0 .. method:: show_text_glyphs(utf8, glyphs, clusters, cluster_flags) :param text utf8: a string of text :param list glyphs: list of glyphs to show :param list clusters: list of cluster mapping information :param TextClusterFlags cluster_flags: cluster mapping flags :raises Error: .. versionadded:: 1.15 This operation has rendering effects similar to :meth:`Context.show_glyphs` but, if the target surface supports it, uses the provided text and cluster mapping to embed the text for the glyphs shown in the output. If the target does not support the extended attributes, this function acts like the basic :meth:`Context.show_glyphs` as if it had been passed ``glyphs`` . The mapping between utf8 and glyphs is provided by a list of clusters. Each cluster covers a number of text bytes and glyphs, and neighboring clusters cover neighboring areas of utf8 and glyphs . The clusters should collectively cover utf8 and glyphs in entirety. The first cluster always covers bytes from the beginning of utf8 . If ``cluster_flags`` do not have the :attr:`TextClusterFlags.BACKWARD` set, the first cluster also covers the beginning of glyphs , otherwise it covers the end of the glyphs array and following clusters move backward. See :class:`TextCluster` for constraints on valid clusters. .. method:: stroke_to_path() .. note:: This function is not implemented in cairo, but still mentioned in the documentation. pycairo-1.16.2/docs/reference/devices.rst000066400000000000000000000070131323762421700203210ustar00rootroot00000000000000.. _devices: ******* Devices ******* .. currentmodule:: cairo class Device() =============== .. class:: Device() A :class:`Device` represents the driver interface for drawing operations to a :class:`Surface`. .. versionadded:: 1.14 .. method:: finish() This function finishes the device and drops all references to external resources. All surfaces, fonts and other objects created for this device will be finished, too. Further operations on the device will not affect the device but will instead trigger a :attr:`Status.DEVICE_FINISHED` error. This function may acquire devices. .. versionadded:: 1.14 .. method:: flush() Finish any pending operations for the device and also restore any temporary modifications cairo has made to the device's state. This function must be called before switching from using the device with Cairo to operating on it directly with native APIs. If the device doesn't support direct access, then this function does nothing. This function may acquire devices. .. versionadded:: 1.14 .. method:: acquire() :raises cairo.Error: If the device is in an error state and could not be acquired. Acquires the device for the current thread. This function will block until no other thread has acquired the device. If the does not raise, you successfully acquired the device. From now on your thread owns the device and no other thread will be able to acquire it until a matching call to :meth:`release`. It is allowed to recursively acquire the device multiple times from the same thread. After a successful call to :meth:`acquire`, a matching call to :meth:`release` is required. .. note:: You must never acquire two different devices at the same time unless this is explicitly allowed. Otherwise the possibility of deadlocks exist. As various Cairo functions can acquire devices when called, these functions may also cause deadlocks when you call them with an acquired device. So you must not have a device acquired when calling them. These functions are marked in the documentation. .. versionadded:: 1.14 .. method:: release() Releases a device previously acquired using :meth:`acquire`. See that function for details. .. versionadded:: 1.14 class ScriptDevice(:class:`Device`) =================================== .. class:: ScriptDevice(fobj) :param fobj: a filename or writable file object. :type fobj: :obj:`pathlike`, file or file-like object Creates a output device for emitting the script, used when creating the individual surfaces. .. versionadded:: 1.14 .. method:: set_mode(mode) :param cairo.ScriptMode mode: the new mode Change the output mode of the script .. method:: get_mode() :returns: the current output mode of the script :rtype: cairo.ScriptMode Queries the script for its current output mode. .. method:: write_comment(comment) :param text comment: the string to emit Emit a string verbatim into the script. .. method:: from_recording_surface(recording_surface) :param cairo.RecordingSurface recording_surface: the recording surface to replay :raises cairo.Error: Converts the record operations in recording_surface into a script. pycairo-1.16.2/docs/reference/enums.rst000066400000000000000000000442071323762421700200340ustar00rootroot00000000000000===== Enums ===== Before Pycairo 1.13 most of the enum values defined here where only available as constants on the module level. See :ref:`legacy_constants`. .. currentmodule:: cairo .. class:: Antialias Specifies the type of antialiasing to do when rendering text or shapes. .. versionadded:: 1.13 .. attribute:: DEFAULT Use the default antialiasing for the subsystem and target device .. attribute:: NONE Use a bilevel alpha mask .. attribute:: GRAY Perform single-color antialiasing (using shades of gray for black text on a white background, for example). .. attribute:: SUBPIXEL Perform antialiasing by taking advantage of the order of subpixel elements on devices such as LCD panels. .. attribute:: FAST Hint that the backend should perform some antialiasing but prefer speed over quality. .. attribute:: GOOD The backend should balance quality against performance. .. attribute:: BEST Hint that the backend should render at the highest quality, sacrificing speed if necessary. .. class:: Content These constants are used to describe the content that a :class:`Surface` will contain, whether color information, alpha information (translucence vs. opacity), or both. .. versionadded:: 1.13 .. attribute:: COLOR The surface will hold color content only. .. attribute:: ALPHA The surface will hold alpha content only. .. attribute:: COLOR_ALPHA The surface will hold color and alpha content. .. class:: Extend These constants are used to describe how :class:`Pattern` color/alpha will be determined for areas "outside" the pattern's natural area, (for example, outside the surface bounds or outside the gradient geometry). The default extend mode is :attr:`NONE` for :class:`SurfacePattern` and :attr:`PAD` for :class:`Gradient` patterns. .. versionadded:: 1.13 .. attribute:: NONE pixels outside of the source pattern are fully transparent .. attribute:: REPEAT the pattern is tiled by repeating .. attribute:: REFLECT the pattern is tiled by reflecting at the edges (Implemented for surface patterns since 1.6) .. attribute:: PAD pixels outside of the pattern copy the closest pixel from the source (Since 1.2; but only implemented for surface patterns since 1.6) .. class:: FillRule These constants are used to select how paths are filled. For both fill rules, whether or not a point is included in the fill is determined by taking a ray from that point to infinity and looking at intersections with the path. The ray can be in any direction, as long as it doesn't pass through the end point of a segment or have a tricky intersection such as intersecting tangent to the path. (Note that filling is not actually implemented in this way. This is just a description of the rule that is applied.) The default fill rule is :attr:`WINDING`. .. versionadded:: 1.13 .. attribute:: WINDING If the path crosses the ray from left-to-right, counts +1. If the path crosses the ray from right to left, counts -1. (Left and right are determined from the perspective of looking along the ray from the starting point.) If the total count is non-zero, the point will be filled. .. attribute:: EVEN_ODD Counts the total number of intersections, without regard to the orientation of the contour. If the total number of intersections is odd, the point will be filled. .. class:: Filter These constants are used to indicate what filtering should be applied when reading pixel values from patterns. See :meth:`Pattern.set_filter` for indicating the desired filter to be used with a particular pattern. .. versionadded:: 1.13 .. attribute:: FAST A high-performance filter, with quality similar *FILTER_NEAREST* .. attribute:: GOOD A reasonable-performance filter, with quality similar to *FILTER_BILINEAR* .. attribute:: BEST The highest-quality available, performance may not be suitable for interactive use. .. attribute:: NEAREST Nearest-neighbor filtering .. attribute:: BILINEAR Linear interpolation in two dimensions .. attribute:: GAUSSIAN This filter value is currently unimplemented, and should not be used in current code. .. class:: FontSlant These constants specify variants of a :class:`FontFace` based on their slant. .. versionadded:: 1.13 .. attribute:: NORMAL Upright font style .. attribute:: ITALIC Italic font style .. attribute:: OBLIQUE Oblique font style .. class:: FontWeight These constants specify variants of a :class:`FontFace` based on their weight. .. versionadded:: 1.13 .. attribute:: NORMAL Normal font weight .. attribute:: BOLD Bold font weight .. class:: Format These constants are used to identify the memory format of :class:`ImageSurface` data. New entries may be added in future versions. .. versionadded:: 1.13 .. method:: stride_for_width(width) :param int width: the desired width of an :class:`ImageSurface` to be created. :returns: the appropriate stride to use given the desired format and width, or -1 if either the format is invalid or the width too large. :rtype: int This method provides a stride value that will respect all alignment requirements of the accelerated image-rendering code within cairo. Typical usage will be of the form:: format = cairo.Format.RGB24 stride = format.stride_for_width(width) surface = cairo.ImageSurface.create_for_data( data, format, width, height, stride) Also available under :meth:`cairo.ImageSurface.format_stride_for_width`. .. versionadded:: 1.14 .. attribute:: INVALID no such format exists or is supported. .. attribute:: ARGB32 each pixel is a 32-bit quantity, with alpha in the upper 8 bits, then red, then green, then blue. The 32-bit quantities are stored native-endian. Pre-multiplied alpha is used. (That is, 50% transparent red is 0x80800000, not 0x80ff0000.) .. attribute:: RGB24 each pixel is a 32-bit quantity, with the upper 8 bits unused. Red, Green, and Blue are stored in the remaining 24 bits in that order. .. attribute:: A8 each pixel is a 8-bit quantity holding an alpha value. .. attribute:: A1 each pixel is a 1-bit quantity holding an alpha value. Pixels are packed together into 32-bit quantities. The ordering of the bits matches the endianess of the platform. On a big-endian machine, the first pixel is in the uppermost bit, on a little-endian machine the first pixel is in the least-significant bit. .. attribute:: RGB16_565 each pixel is a 16-bit quantity with red in the upper 5 bits, then green in the middle 6 bits, and blue in the lower 5 bits. .. attribute:: RGB30 like :data:`RGB24` but with 10bpc. .. class:: HintMetrics These constants specify whether to hint font metrics; hinting font metrics means quantizing them so that they are integer values in device space. Doing this improves the consistency of letter and line spacing, however it also means that text will be laid out differently at different zoom factors. .. versionadded:: 1.13 .. attribute:: DEFAULT Hint metrics in the default manner for the font backend and target device .. attribute:: OFF Do not hint font metrics .. attribute:: ON Hint font metrics .. class:: HintStyle These constants specify the type of hinting to do on font outlines. Hinting is the process of fitting outlines to the pixel grid in order to improve the appearance of the result. Since hinting outlines involves distorting them, it also reduces the faithfulness to the original outline shapes. Not all of the outline hinting styles are supported by all font backends. New entries may be added in future versions. .. versionadded:: 1.13 .. attribute:: DEFAULT Use the default hint style for font backend and target device .. attribute:: NONE Do not hint outlines .. attribute:: SLIGHT Hint outlines slightly to improve contrast while retaining good fidelity to the original shapes. .. attribute:: MEDIUM Hint outlines with medium strength giving a compromise between fidelity to the original shapes and contrast .. attribute:: FULL Hint outlines to maximize contrast .. class:: LineCap These constants specify how to render the endpoints of the path when stroking. The default line cap style is :attr:`BUTT` .. versionadded:: 1.13 .. attribute:: BUTT start(stop) the line exactly at the start(end) point .. attribute:: ROUND use a round ending, the center of the circle is the end point .. attribute:: SQUARE use squared ending, the center of the square is the end point .. class:: LineJoin These constants specify how to render the junction of two lines when stroking. The default line join style is :attr:`MITER` .. versionadded:: 1.13 .. attribute:: MITER use a sharp (angled) corner, see :meth:`Context.set_miter_limit` .. attribute:: ROUND use a rounded join, the center of the circle is the joint point .. attribute:: BEVEL use a cut-off join, the join is cut off at half the line width from the joint point .. class:: Operator These constants are used to set the compositing operator for all cairo drawing operations. The default operator is :attr:`OVER`. The operators marked as *unbounded* modify their destination even outside of the mask layer (that is, their effect is not bound by the mask layer). However, their effect can still be limited by way of clipping. To keep things simple, the operator descriptions here document the behavior for when both source and destination are either fully transparent or fully opaque. The actual implementation works for translucent layers too. For a more detailed explanation of the effects of each operator, including the mathematical definitions, see https://cairographics.org/operators. .. versionadded:: 1.13 .. attribute:: CLEAR clear destination layer (bounded) .. attribute:: SOURCE replace destination layer (bounded) .. attribute:: OVER draw source layer on top of destination layer (bounded) .. attribute:: IN draw source where there was destination content (unbounded) .. attribute:: OUT draw source where there was no destination content (unbounded) .. attribute:: ATOP draw source on top of destination content and only there .. attribute:: DEST ignore the source .. attribute:: DEST_OVER draw destination on top of source .. attribute:: DEST_IN leave destination only where there was source content (unbounded) .. attribute:: DEST_OUT leave destination only where there was no source content .. attribute:: DEST_ATOP leave destination on top of source content and only there (unbounded) .. attribute:: XOR source and destination are shown where there is only one of them .. attribute:: ADD source and destination layers are accumulated .. attribute:: SATURATE like over, but assuming source and dest are disjoint geometries .. attribute:: MULTIPLY source and destination layers are multiplied. This causes the result to be at least as dark as the darker inputs. .. attribute:: SCREEN source and destination are complemented and multiplied. This causes the result to be at least as light as the lighter inputs. .. attribute:: OVERLAY multiplies or screens, depending on the lightness of the destination color. .. attribute:: DARKEN replaces the destination with the source if it is darker, otherwise keeps the source. .. attribute:: LIGHTEN replaces the destination with the source if it is lighter, otherwise keeps the source. .. attribute:: COLOR_DODGE brightens the destination color to reflect the source color. .. attribute:: COLOR_BURN darkens the destination color to reflect the source color. .. attribute:: HARD_LIGHT Multiplies or screens, dependent on source color. .. attribute:: SOFT_LIGHT Darkens or lightens, dependent on source color. .. attribute:: DIFFERENCE Takes the difference of the source and destination color. .. attribute:: EXCLUSION Produces an effect similar to difference, but with lower contrast. .. attribute:: HSL_HUE Creates a color with the hue of the source and the saturation and luminosity of the target. .. attribute:: HSL_SATURATION Creates a color with the saturation of the source and the hue and luminosity of the target. Painting with this mode onto a gray area produces no change. .. attribute:: HSL_COLOR Creates a color with the hue and saturation of the source and the luminosity of the target. This preserves the gray levels of the target and is useful for coloring monochrome images or tinting color images. .. attribute:: HSL_LUMINOSITY Creates a color with the luminosity of the source and the hue and saturation of the target. This produces an inverse effect to :attr:`HSL_COLOR` .. class:: PathDataType These constants are used to describe the type of one portion of a path when represented as a :class:`Path`. .. versionadded:: 1.13 .. attribute:: MOVE_TO A move-to operation .. attribute:: LINE_TO A line-to operation .. attribute:: CURVE_TO A curve-to operation .. attribute:: CLOSE_PATH A close-path operation .. class:: PSLevel These constants are used to describe the language level of the PostScript Language Reference that a generated PostScript file will conform to. Note: the constants are only defined when cairo has been compiled with PS support enabled. .. versionadded:: 1.13 .. attribute:: LEVEL_2 The language level 2 of the PostScript specification. .. attribute:: LEVEL_3 The language level 3 of the PostScript specification. .. class:: PDFVersion These constants are used to describe the version number of the PDF specification that a generated PDF file will conform to. .. versionadded:: 1.13 .. attribute:: VERSION_1_4 The version 1.4 of the PDF specification. .. attribute:: VERSION_1_5 The version 1.5 of the PDF specification. .. class:: SVGVersion These constants are used to describe the version number of the SVG specification that a generated SVG file will conform to. .. versionadded:: 1.13 .. attribute:: VERSION_1_1 The version 1.1 of the SVG specification. .. attribute:: VERSION_1_2 The version 1.2 of the SVG specification. .. class:: SubpixelOrder The subpixel order specifies the order of color elements within each pixel on the display device when rendering with an antialiasing mode of :attr:`Antialias.SUBPIXEL`. .. versionadded:: 1.13 .. attribute:: DEFAULT Use the default subpixel order for for the target device .. attribute:: RGB Subpixel elements are arranged horizontally with red at the left .. attribute:: BGR Subpixel elements are arranged horizontally with blue at the left .. attribute:: VRGB Subpixel elements are arranged vertically with red at the top .. attribute:: VBGR Subpixel elements are arranged vertically with blue at the top .. class:: RegionOverlap .. versionadded:: 1.13 .. attribute:: IN The contents are entirely inside the region. .. attribute:: OUT The contents are entirely outside the region. .. attribute:: PART The contents are partially inside and partially outside the region. .. class:: Status .. versionadded:: 1.13 .. attribute:: SUCCESS NO_MEMORY INVALID_RESTORE INVALID_POP_GROUP NO_CURRENT_POINT INVALID_MATRIX INVALID_STATUS NULL_POINTER INVALID_STRING INVALID_PATH_DATA READ_ERROR WRITE_ERROR SURFACE_FINISHED SURFACE_TYPE_MISMATCH PATTERN_TYPE_MISMATCH INVALID_CONTENT INVALID_FORMAT INVALID_VISUAL FILE_NOT_FOUND INVALID_DASH INVALID_DSC_COMMENT INVALID_INDEX CLIP_NOT_REPRESENTABLE TEMP_FILE_ERROR INVALID_STRIDE FONT_TYPE_MISMATCH USER_FONT_IMMUTABLE USER_FONT_ERROR NEGATIVE_COUNT INVALID_CLUSTERS INVALID_SLANT INVALID_WEIGHT INVALID_SIZE USER_FONT_NOT_IMPLEMENTED DEVICE_TYPE_MISMATCH DEVICE_ERROR INVALID_MESH_CONSTRUCTION DEVICE_FINISHED LAST_STATUS .. attribute:: JBIG2_GLOBAL_MISSING .. versionadded:: 1.14 .. class:: ScriptMode A set of script output variants. .. versionadded:: 1.14 .. attribute:: ASCII the output will be in readable text (default) .. attribute:: BINARY the output will use byte codes. .. class:: TextClusterFlags Specifies properties of a text cluster mapping. .. versionadded:: 1.14 .. attribute:: BACKWARD The clusters in the cluster array map to glyphs in the glyph array from end to start. .. class:: SurfaceObserverMode Whether operations should be recorded. .. versionadded:: 1.14 .. attribute:: NORMAL no recording is done .. attribute:: RECORD_OPERATIONS operations are recorded pycairo-1.16.2/docs/reference/exceptions.rst000066400000000000000000000015171323762421700210630ustar00rootroot00000000000000.. _exceptions: ********** Exceptions ********** .. currentmodule:: cairo When a cairo function or method call fails an cairo.Error exception, or a subclass thereof, is raised. cairo.Error() ============= .. exception:: Error This exception is raised when a cairo object returns an error status. .. attribute:: status :type: :class:`cairo.Status` .. exception:: CairoError An alias for :exc:`Error` .. versionadded:: 1.12.0 .. exception:: MemoryError :bases: :exc:`Error`, :exc:`python3:MemoryError` .. versionadded:: 1.15 Prior to 1.15 :exc:`python3:MemoryError` was raised instead of this type. .. exception:: IOError :bases: :exc:`Error`, :exc:`python3:IOError` .. versionadded:: 1.15 Prior to 1.15 :exc:`python3:IOError` was raised instead of this type. pycairo-1.16.2/docs/reference/glyph.rst000066400000000000000000000031501323762421700200200ustar00rootroot00000000000000.. _glyph: ***** Glyph ***** .. currentmodule:: cairo class Glyph(tuple) ================== .. class:: Glyph(index, x, y) :param int index: glyph index in the font. The exact interpretation of the glyph index depends on the font technology being used. :param float x: the offset in the X direction between the origin used for drawing or measuring the string and the origin of this glyph. :param float y: the offset in the Y direction between the origin used for drawing or measuring the string and the origin of this glyph. :rtype: Glyph .. versionadded:: 1.15 In prior versions a (int, float, float) tuple was used instead of :class:`Glyph`. The :class:`Glyph` holds information about a single glyph when drawing or measuring text. A font is (in simple terms) a collection of shapes used to draw text. A glyph is one of these shapes. There can be multiple glyphs for a single character (alternates to be used in different contexts, for example), or a glyph can be a ligature of multiple characters. Cairo doesn't expose any way of converting input text into glyphs, so in order to use the Cairo interfaces that take arrays of glyphs, you must directly access the appropriate underlying font system. Note that the offsets given by x and y are not cumulative. When drawing or measuring text, each glyph is individually positioned with respect to the overall origin .. attribute:: index :class:`int` .. attribute:: x :class:`float` .. attribute:: y :class:`float` pycairo-1.16.2/docs/reference/index.rst000066400000000000000000000004701323762421700200060ustar00rootroot00000000000000.. _reference_index: ************* API Reference ************* .. currentmodule:: cairo .. toctree:: :maxdepth: 2 constants enums context exceptions matrix paths patterns region surfaces text devices glyph rectangle textcluster textextents legacy_constants pycairo-1.16.2/docs/reference/legacy_constants.rst000066400000000000000000000174741323762421700222530ustar00rootroot00000000000000.. _legacy_constants: ================ Legacy Constants ================ These constants are aliases for enum attributes in newer versions of Pycairo. They might still be useful if you need to support Pycairo versions older than 1.13. .. currentmodule:: cairo .. data:: ANTIALIAS_DEFAULT See :attr:`Antialias.DEFAULT` .. data:: ANTIALIAS_NONE See :attr:`Antialias.NONE` .. data:: ANTIALIAS_GRAY See :attr:`Antialias.GRAY` .. data:: ANTIALIAS_SUBPIXEL See :attr:`Antialias.SUBPIXEL` .. data:: ANTIALIAS_FAST See :attr:`Antialias.FAST` .. versionadded:: 1.12.0 .. data:: ANTIALIAS_GOOD See :attr:`Antialias.GOOD` .. versionadded:: 1.12.0 .. data:: ANTIALIAS_BEST See :attr:`Antialias.BEST` .. versionadded:: 1.12.0 .. data:: CONTENT_COLOR See :attr:`Content.COLOR` .. data:: CONTENT_ALPHA See :attr:`Content.ALPHA` .. data:: CONTENT_COLOR_ALPHA See :attr:`Content.COLOR_ALPHA` .. data:: EXTEND_NONE See :attr:`Extend.NONE` .. data:: EXTEND_REPEAT See :attr:`Extend.REPEAT` .. data:: EXTEND_REFLECT See :attr:`Extend.REFLECT` .. data:: EXTEND_PAD See :attr:`Extend.PAD` .. data:: FILL_RULE_WINDING See :attr:`FillRule.WINDING` .. data:: FILL_RULE_EVEN_ODD See :attr:`FillRule.EVEN_ODD` .. data:: FILTER_FAST See :attr:`Filter.FAST` .. data:: FILTER_GOOD See :attr:`Filter.GOOD` .. data:: FILTER_BEST See :attr:`Filter.BEST` .. data:: FILTER_NEAREST See :attr:`Filter.NEAREST` .. data:: FILTER_BILINEAR See :attr:`Filter.BILINEAR` .. data:: FILTER_GAUSSIAN See :attr:`Filter.GAUSSIAN` .. data:: FONT_SLANT_NORMAL See :attr:`FontSlant.NORMAL` .. data:: FONT_SLANT_ITALIC See :attr:`FontSlant.ITALIC` .. data:: FONT_SLANT_OBLIQUE See :attr:`FontSlant.OBLIQUE` .. data:: FONT_WEIGHT_NORMAL See :attr:`FontWeight.NORMAL` .. data:: FONT_WEIGHT_BOLD See :attr:`FontWeight.BOLD` .. data:: FORMAT_INVALID See :attr:`Format.INVALID` .. versionadded:: 1.12.0 .. data:: FORMAT_ARGB32 See :attr:`Format.ARGB32` .. data:: FORMAT_RGB24 See :attr:`Format.RGB24` .. data:: FORMAT_A8 See :attr:`Format.A8` .. data:: FORMAT_A1 See :attr:`Format.A1` .. data:: FORMAT_RGB16_565 See :attr:`Format.RGB16_565` .. data:: FORMAT_RGB30 See :attr:`Format.RGB30` .. versionadded:: 1.12.0 .. data:: HINT_METRICS_DEFAULT See :attr:`HintMetrics.DEFAULT` .. data:: HINT_METRICS_OFF See :attr:`HintMetrics.OFF` .. data:: HINT_METRICS_ON See :attr:`HintMetrics.ON` .. data:: HINT_STYLE_DEFAULT See :attr:`HintStyle.DEFAULT` .. data:: HINT_STYLE_NONE See :attr:`HintStyle.NONE` .. data:: HINT_STYLE_SLIGHT See :attr:`HintStyle.SLIGHT` .. data:: HINT_STYLE_MEDIUM See :attr:`HintStyle.MEDIUM` .. data:: HINT_STYLE_FULL See :attr:`HintStyle.FULL` .. data:: LINE_CAP_BUTT See :attr:`LineCap.BUTT` .. data:: LINE_CAP_ROUND See :attr:`LineCap.ROUND` .. data:: LINE_CAP_SQUARE See :attr:`LineCap.SQUARE` .. data:: LINE_JOIN_MITER See :attr:`LineJoin.MITER` .. data:: LINE_JOIN_ROUND See :attr:`LineJoin.ROUND` .. data:: LINE_JOIN_BEVEL See :attr:`LineJoin.BEVEL` .. data:: OPERATOR_CLEAR See :attr:`Operator.CLEAR` .. data:: OPERATOR_SOURCE See :attr:`Operator.SOURCE` .. data:: OPERATOR_OVER See :attr:`Operator.OVER` .. data:: OPERATOR_IN See :attr:`Operator.IN` .. data:: OPERATOR_OUT See :attr:`Operator.OUT` .. data:: OPERATOR_ATOP See :attr:`Operator.ATOP` .. data:: OPERATOR_DEST See :attr:`Operator.DEST` .. data:: OPERATOR_DEST_OVER See :attr:`Operator.DEST_OVER` .. data:: OPERATOR_DEST_IN See :attr:`Operator.DEST_IN` .. data:: OPERATOR_DEST_OUT See :attr:`Operator.DEST_OUT` .. data:: OPERATOR_DEST_ATOP See :attr:`Operator.DEST_ATOP` .. data:: OPERATOR_XOR See :attr:`Operator.XOR` .. data:: OPERATOR_ADD See :attr:`Operator.ADD` .. data:: OPERATOR_SATURATE See :attr:`Operator.SATURATE` .. data:: OPERATOR_MULTIPLY See :attr:`Operator.MULTIPLY` .. versionadded:: 1.12.0 .. data:: OPERATOR_SCREEN See :attr:`Operator.SCREEN` .. versionadded:: 1.12.0 .. data:: OPERATOR_OVERLAY See :attr:`Operator.OVERLAY` .. versionadded:: 1.12.0 .. data:: OPERATOR_DARKEN See :attr:`Operator.DARKEN` .. versionadded:: 1.12.0 .. data:: OPERATOR_LIGHTEN See :attr:`Operator.LIGHTEN` .. versionadded:: 1.12.0 .. data:: OPERATOR_COLOR_DODGE See :attr:`Operator.COLOR_DODGE` .. versionadded:: 1.12.0 .. data:: OPERATOR_COLOR_BURN See :attr:`Operator.COLOR_BURN` .. versionadded:: 1.12.0 .. data:: OPERATOR_HARD_LIGHT See :attr:`Operator.HARD_LIGHT` .. versionadded:: 1.12.0 .. data:: OPERATOR_SOFT_LIGHT See :attr:`Operator.SOFT_LIGHT` .. versionadded:: 1.12.0 .. data:: OPERATOR_DIFFERENCE See :attr:`Operator.DIFFERENCE` .. versionadded:: 1.12.0 .. data:: OPERATOR_EXCLUSION See :attr:`Operator.EXCLUSION` .. versionadded:: 1.12.0 .. data:: OPERATOR_HSL_HUE See :attr:`Operator.HSL_HUE` .. versionadded:: 1.12.0 .. data:: OPERATOR_HSL_SATURATION See :attr:`Operator.HSL_SATURATION` .. versionadded:: 1.12.0 .. data:: OPERATOR_HSL_COLOR See :attr:`Operator.HSL_COLOR` .. versionadded:: 1.12.0 .. data:: OPERATOR_HSL_LUMINOSITY See :attr:`Operator.HSL_LUMINOSITY` .. versionadded:: 1.12.0 .. data:: PATH_MOVE_TO See :attr:`PathDataType.MOVE_TO` .. data:: PATH_LINE_TO See :attr:`PathDataType.LINE_TO` .. data:: PATH_CURVE_TO See :attr:`PathDataType.CURVE_TO` .. data:: PATH_CLOSE_PATH See :attr:`PathDataType.CLOSE_PATH` .. data:: PS_LEVEL_2 See :attr:`PSLevel.LEVEL_2` .. data:: PS_LEVEL_3 See :attr:`PSLevel.LEVEL_3` .. data:: PDF_VERSION_1_4 See :attr:`PDFVersion.VERSION_1_4` .. versionadded:: 1.12.0 .. data:: PDF_VERSION_1_5 See :attr:`PDFVersion.VERSION_1_5` .. versionadded:: 1.12.0 .. data:: SVG_VERSION_1_1 See :attr:`SVGVersion.VERSION_1_1` .. versionadded:: 1.12.0 .. data:: SVG_VERSION_1_2 See :attr:`SVGVersion.VERSION_1_2` .. versionadded:: 1.12.0 .. data:: SUBPIXEL_ORDER_DEFAULT See :attr:`SubpixelOrder.DEFAULT` .. data:: SUBPIXEL_ORDER_RGB See :attr:`SubpixelOrder.RGB` .. data:: SUBPIXEL_ORDER_BGR See :attr:`SubpixelOrder.BGR` .. data:: SUBPIXEL_ORDER_VRGB See :attr:`SubpixelOrder.VRGB` .. data:: SUBPIXEL_ORDER_VBGR See :attr:`SubpixelOrder.VBGR` .. data:: REGION_OVERLAP_IN See :attr:`RegionOverlap.IN` .. versionadded:: 1.11 .. data:: REGION_OVERLAP_OUT See :attr:`RegionOverlap.OUT` .. versionadded:: 1.11 .. data:: REGION_OVERLAP_PART See :attr:`RegionOverlap.PART` .. versionadded:: 1.11 .. data:: STATUS_SUCCESS STATUS_NO_MEMORY STATUS_INVALID_RESTORE STATUS_INVALID_POP_GROUP STATUS_NO_CURRENT_POINT STATUS_INVALID_MATRIX STATUS_INVALID_STATUS STATUS_NULL_POINTER STATUS_INVALID_STRING STATUS_INVALID_PATH_DATA STATUS_READ_ERROR STATUS_WRITE_ERROR STATUS_SURFACE_FINISHED STATUS_SURFACE_TYPE_MISMATCH STATUS_PATTERN_TYPE_MISMATCH STATUS_INVALID_CONTENT STATUS_INVALID_FORMAT STATUS_INVALID_VISUAL STATUS_FILE_NOT_FOUND STATUS_INVALID_DASH STATUS_INVALID_DSC_COMMENT STATUS_INVALID_INDEX STATUS_CLIP_NOT_REPRESENTABLE STATUS_TEMP_FILE_ERROR STATUS_INVALID_STRIDE STATUS_FONT_TYPE_MISMATCH STATUS_USER_FONT_IMMUTABLE STATUS_USER_FONT_ERROR STATUS_NEGATIVE_COUNT STATUS_INVALID_CLUSTERS STATUS_INVALID_SLANT STATUS_INVALID_WEIGHT STATUS_INVALID_SIZE STATUS_USER_FONT_NOT_IMPLEMENTED STATUS_DEVICE_TYPE_MISMATCH STATUS_DEVICE_ERROR STATUS_INVALID_MESH_CONSTRUCTION STATUS_DEVICE_FINISHED STATUS_LAST_STATUS See :class:`Status` .. versionadded:: 1.12 pycairo-1.16.2/docs/reference/matrix.rst000066400000000000000000000147751323762421700202200ustar00rootroot00000000000000.. _matrix: ****** Matrix ****** .. currentmodule:: cairo class Matrix() ============== *Matrix* is used throughout cairo to convert between different coordinate spaces. A *Matrix* holds an affine transformation, such as a scale, rotation, shear, or a combination of these. The transformation of a point (x,y) is given by:: x_new = xx * x + xy * y + x0 y_new = yx * x + yy * y + y0 The current transformation matrix of a :class:`Context`, represented as a *Matrix*, defines the transformation from user-space coordinates to device-space coordinates. Some standard Python operators can be used with matrices: To read the values from a *Matrix*:: xx, yx, xy, yy, x0, y0 = matrix To multiply two matrices:: matrix3 = matrix1.multiply(matrix2) # or equivalently matrix3 = matrix1 * matrix2 To compare two matrices:: matrix1 == matrix2 matrix1 != matrix2 For more information on matrix transformation see https://www.cairographics.org/cookbook/matrix_transform/ .. class:: Matrix(xx = 1.0, yx = 0.0, xy = 0.0, yy = 1.0, x0 = 0.0, y0 = 0.0) :param xx: xx component of the affine transformation :type xx: float :param yx: yx component of the affine transformation :type yx: float :param xy: xy component of the affine transformation :type xy: float :param yy: yy component of the affine transformation :type yy: float :param x0: X translation component of the affine transformation :type x0: float :param y0: Y translation component of the affine transformation :type y0: float Create a new *Matrix* with the affine transformation given by *xx, yx, xy, yy, x0, y0*. The transformation is given by:: x_new = xx * x + xy * y + x0 y_new = yx * x + yy * y + y0 To create a new identity matrix:: matrix = cairo.Matrix() To create a matrix with a transformation which translates by tx and ty in the X and Y dimensions, respectively:: matrix = cairo.Matrix(x0=tx, y0=ty) To create a matrix with a transformation that scales by sx and sy in the X and Y dimensions, respectively:: matrix = cairo.Matrix(xx=sy, yy=sy) .. classmethod:: init_rotate(radians) :param radians: angle of rotation, in radians. The direction of rotation is defined such that positive angles rotate in the direction from the positive X axis toward the positive Y axis. With the default axis orientation of cairo, positive angles rotate in a clockwise direction. :type radians: float :returns: a new *Matrix* set to a transformation that rotates by *radians*. .. method:: invert() :returns: If *Matrix* has an inverse, modifies *Matrix* to be the inverse matrix and returns *None* :raises: :exc:`cairo.Error` if the *Matrix* as no inverse Changes *Matrix* to be the inverse of it's original value. Not all transformation matrices have inverses; if the matrix collapses points together (it is *degenerate*), then it has no inverse and this function will fail. .. method:: multiply(matrix2) :param matrix2: a second matrix :type matrix2: cairo.Matrix :returns: a new *Matrix* Multiplies the affine transformations in *Matrix* and *matrix2* together. The effect of the resulting transformation is to first apply the transformation in *Matrix* to the coordinates and then apply the transformation in *matrix2* to the coordinates. It is allowable for result to be identical to either *Matrix* or *matrix2*. .. method:: rotate(radians) :param radians: angle of rotation, in radians. The direction of rotation is defined such that positive angles rotate in the direction from the positive X axis toward the positive Y axis. With the default axis orientation of cairo, positive angles rotate in a clockwise direction. :type radians: float Initialize *Matrix* to a transformation that rotates by *radians*. .. method:: scale(sx, sy) :param sx: scale factor in the X direction :type sx: float :param sy: scale factor in the Y direction :type sy: float Applies scaling by *sx, sy* to the transformation in *Matrix*. The effect of the new transformation is to first scale the coordinates by *sx* and *sy*, then apply the original transformation to the coordinates. .. method:: transform_distance(dx, dy) :param dx: X component of a distance vector. :type dx: float :param dy: Y component of a distance vector. :type dy: float :returns: the transformed distance vector (dx,dy), both float :rtype: tuple Transforms the distance vector *(dx,dy)* by *Matrix*. This is similar to :meth:`.transform_point` except that the translation components of the transformation are ignored. The calculation of the returned vector is as follows:: dx2 = dx1 * a + dy1 * c dy2 = dx1 * b + dy1 * d Affine transformations are position invariant, so the same vector always transforms to the same vector. If *(x1,y1)* transforms to *(x2,y2)* then *(x1+dx1,y1+dy1)* will transform to *(x1+dx2,y1+dy2)* for all values of *x1* and *x2*. .. method:: transform_point(x, y) :param x: X position. :type x: float :param y: Y position. :type y: float :returns: the transformed point (x,y), both float :rtype: tuple Transforms the point *(x, y)* by *Matrix*. .. method:: translate(tx, ty) :param tx: amount to translate in the X direction :type tx: float :param ty: amount to translate in the Y direction :type ty: float Applies a transformation by *tx, ty* to the transformation in *Matrix*. The effect of the new transformation is to first translate the coordinates by *tx* and *ty*, then apply the original transformation to the coordinates. .. data:: xx :class:`float`: xx component of the affine transformation .. versionadded:: 1.12.0 .. data:: yx :class:`float`: yx component of the affine transformation .. versionadded:: 1.12.0 .. data:: xy :class:`float`: xy component of the affine transformation .. versionadded:: 1.12.0 .. data:: yy :class:`float`: yy component of the affine transformation .. versionadded:: 1.12.0 .. data:: x0 :class:`float`: X translation component of the affine transformation .. versionadded:: 1.12.0 .. data:: y0 :class:`float`: Y translation component of the affine transformation .. versionadded:: 1.12.0 pycairo-1.16.2/docs/reference/paths.rst000066400000000000000000000006241323762421700200170ustar00rootroot00000000000000.. _paths: ***** Paths ***** .. currentmodule:: cairo class Path() ============ .. class:: Path() *Path* cannot be instantiated directly, it is created by calling :meth:`Context.copy_path` and :meth:`Context.copy_path_flat`. str(path) lists the path elements. See :class:`path attributes ` Path is an iterator. See examples/warpedtext.py for example usage. pycairo-1.16.2/docs/reference/patterns.rst000066400000000000000000000651371323762421700205520ustar00rootroot00000000000000.. _patterns: ******** Patterns ******** .. currentmodule:: cairo Patterns are the paint with which cairo draws. The primary use of patterns is as the source for all cairo drawing operations, although they can also be used as masks, that is, as the brush too. A cairo *Pattern* is created by using one of the *PatternType* constructors listed below, or implicitly through *Context.set_source_()* methods. class Pattern() =============== *Pattern* is the abstract base class from which all the other pattern classes derive. It cannot be instantiated directly. .. class:: Pattern() .. method:: get_extend() :returns: the current extend strategy used for drawing the *Pattern*. :rtype: cairo.Extend Gets the current extend mode for the *Pattern*. See :class:`cairo.Extend` attributes for details on the semantics of each extend strategy. .. method:: get_matrix() :returns: a new :class:`Matrix` which stores a copy of the *Pattern's* transformation matrix .. method:: get_filter() :returns: the current filter used for resizing the pattern. :rtype: cairo.Filter .. versionadded:: 1.12.0 Used to be a method of :class:`SurfacePattern` before .. method:: set_filter(filter) :param cairo.Filter filter: a filter describing the filter to use for resizing the pattern Note that you might want to control filtering even when you do not have an explicit *Pattern* object, (for example when using :meth:`Context.set_source_surface`). In these cases, it is convenient to use :meth:`Context.get_source` to get access to the pattern that cairo creates implicitly. For example:: context.set_source_surface(image, x, y) surfacepattern.set_filter(context.get_source(), cairo.FILTER_NEAREST) .. versionadded:: 1.12.0 Used to be a method of :class:`SurfacePattern` before .. method:: set_extend(extend) :param cairo.Extend extend: an extend describing how the area outside of the *Pattern* will be drawn Sets the mode to be used for drawing outside the area of a *Pattern*. The default extend mode is :attr:`cairo.Extend.NONE` for :class:`SurfacePattern` and :attr:`cairo.Extend.PAD` for :class:`Gradient` Patterns. .. method:: set_matrix(matrix) :param matrix: a :class:`Matrix` Sets the *Pattern's* transformation matrix to *matrix*. This matrix is a transformation from user space to pattern space. When a *Pattern* is first created it always has the identity matrix for its transformation matrix, which means that pattern space is initially identical to user space. Important: Please note that the direction of this transformation matrix is from user space to pattern space. This means that if you imagine the flow from a *Pattern* to user space (and on to device space), then coordinates in that flow will be transformed by the inverse of the *Pattern* matrix. For example, if you want to make a *Pattern* appear twice as large as it does by default the correct code to use is:: matrix = cairo.Matrix(xx=0.5,yy=0.5) pattern.set_matrix(matrix) Meanwhile, using values of 2.0 rather than 0.5 in the code above would cause the *Pattern* to appear at half of its default size. Also, please note the discussion of the user-space locking semantics of :class:`Context.set_source`. class SolidPattern(:class:`Pattern`) ==================================== .. class:: SolidPattern(red, green, blue, alpha=1.0) :param red: red component of the color :type red: float :param green: green component of the color :type green: float :param blue: blue component of the color :type blue: float :param alpha: alpha component of the color :type alpha: float :returns: a new *SolidPattern* :raises: :exc:`MemoryError` in case of no memory Creates a new *SolidPattern* corresponding to a translucent color. The color components are floating point numbers in the range 0 to 1. If the values passed in are outside that range, they will be clamped. .. method:: get_rgba() :returns: (red, green, blue, alpha) a tuple of float Gets the solid color for a *SolidPattern*. .. versionadded:: 1.4 class SurfacePattern(:class:`Pattern`) ====================================== .. class:: SurfacePattern(surface) :param surface: a cairo :class:`Surface` :returns: a newly created *SurfacePattern* for the given surface. :raises: :exc:`MemoryError` in case of no memory. .. method:: get_surface() :returns: the :class:`Surface` of the *SurfacePattern*. .. versionadded:: 1.4 class Gradient(:class:`Pattern`) ================================ *Gradient* is an abstract base class from which other *Pattern* classes derive. It cannot be instantiated directly. .. class:: Gradient() .. method:: add_color_stop_rgb(offset, red, green, blue) :param offset: an offset in the range [0.0 .. 1.0] :type offset: float :param red: red component of color :type red: float :param green: green component of color :type green: float :param blue: blue component of color :type blue: float Adds an opaque color stop to a *Gradient* pattern. The offset specifies the location along the gradient's control vector. For example, a *LinearGradient's* control vector is from (x0,y0) to (x1,y1) while a *RadialGradient's* control vector is from any point on the start circle to the corresponding point on the end circle. The color is specified in the same way as in :meth:`Context.set_source_rgb`. If two (or more) stops are specified with identical offset values, they will be sorted according to the order in which the stops are added, (stops added earlier will compare less than stops added later). This can be useful for reliably making sharp color transitions instead of the typical blend. .. method:: add_color_stop_rgba(offset, red, green, blue, alpha) :param offset: an offset in the range [0.0 .. 1.0] :type offset: float :param red: red component of color :type red: float :param green: green component of color :type green: float :param blue: blue component of color :type blue: float :param alpha: alpha component of color :type alpha: float Adds an opaque color stop to a *Gradient* pattern. The offset specifies the location along the gradient's control vector. For example, a *LinearGradient's* control vector is from (x0,y0) to (x1,y1) while a *RadialGradient's* control vector is from any point on the start circle to the corresponding point on the end circle. The color is specified in the same way as in :meth:`Context.set_source_rgb`. If two (or more) stops are specified with identical offset values, they will be sorted according to the order in which the stops are added, (stops added earlier will compare less than stops added later). This can be useful for reliably making sharp color transitions instead of the typical blend. .. method:: get_color_stops_rgba() :returns: a list of (offset, red, green, blue, alpha) tuples of float :rtype: list Gets the color and offset information for all color stops specified in the given gradient pattern. .. versionadded:: 1.14 class LinearGradient(:class:`Gradient`) ======================================= .. class:: LinearGradient(x0, y0, x1, y1) :param x0: x coordinate of the start point :type x0: float :param y0: y coordinate of the start point :type y0: float :param x1: x coordinate of the end point :type x1: float :param y1: y coordinate of the end point :type y1: float :returns: a new *LinearGradient* :raises: :exc:`MemoryError` in case of no memory Create a new *LinearGradient* along the line defined by (x0, y0) and (x1, y1). Before using the *Gradient* pattern, a number of color stops should be defined using :meth:`Gradient.add_color_stop_rgb` or :meth:`Gradient.add_color_stop_rgba` Note: The coordinates here are in pattern space. For a new *Pattern*, pattern space is identical to user space, but the relationship between the spaces can be changed with :meth:`Pattern.set_matrix` .. method:: get_linear_points() :returns: (x0, y0, x1, y1) - a tuple of float * x0: return value for the x coordinate of the first point * y0: return value for the y coordinate of the first point * x1: return value for the x coordinate of the second point * y1: return value for the y coordinate of the second point Gets the gradient endpoints for a *LinearGradient*. .. versionadded:: 1.4 class RadialGradient(:class:`Gradient`) ======================================= .. class:: RadialGradient(cx0, cy0, radius0, cx1, cy1, radius1) :param cx0: x coordinate for the center of the start circle :type cx0: float :param cy0: y coordinate for the center of the start circle :type cy0: float :param radius0: radius of the start circle :type radius0: float :param cx1: x coordinate for the center of the end circle :type cx1: float :param cy1: y coordinate for the center of the end circle :type cy1: float :param radius1: radius of the end circle :type radius1: float :returns: the newly created *RadialGradient* :raises: :exc:`MemoryError` in case of no memory Creates a new *RadialGradient* pattern between the two circles defined by (cx0, cy0, radius0) and (cx1, cy1, radius1). Before using the gradient pattern, a number of color stops should be defined using :meth:`Gradient.add_color_stop_rgb` or :meth:`Gradient.add_color_stop_rgba`. Note: The coordinates here are in pattern space. For a new pattern, pattern space is identical to user space, but the relationship between the spaces can be changed with :meth:`Pattern.set_matrix`. .. method:: get_radial_circles() :returns: (x0, y0, r0, x1, y1, r1) - a tuple of float * x0: return value for the x coordinate of the center of the first circle * y0: return value for the y coordinate of the center of the first circle * r0: return value for the radius of the first circle * x1: return value for the x coordinate of the center of the second circle * y1: return value for the y coordinate of the center of the second circle * r1: return value for the radius of the second circle Gets the *Gradient* endpoint circles for a *RadialGradient*, each specified as a center coordinate and a radius. .. versionadded:: 1.4 class MeshPattern(:class:`Pattern`) =================================== .. class:: MeshPattern() :raises Error: :rtype: MeshPattern .. versionadded:: 1.14 Create a new mesh pattern. Mesh patterns are tensor-product patch meshes (type 7 shadings in PDF). Mesh patterns may also be used to create other types of shadings that are special cases of tensor-product patch meshes such as Coons patch meshes (type 6 shading in PDF) and Gouraud-shaded triangle meshes (type 4 and 5 shadings in PDF). Mesh patterns consist of one or more tensor-product patches, which should be defined before using the mesh pattern. Using a mesh pattern with a partially defined patch as source or mask will put the context in an error status with a status of :attr:`cairo.Status.INVALID_MESH_CONSTRUCTION`. A tensor-product patch is defined by 4 Bézier curves (side 0, 1, 2, 3) and by 4 additional control points (P0, P1, P2, P3) that provide further control over the patch and complete the definition of the tensor-product patch. The corner C0 is the first point of the patch. Degenerate sides are permitted so straight lines may be used. A zero length line on one side may be used to create 3 sided patches. :: C1 Side 1 C2 +---------------+ | | | P1 P2 | | | Side 0 | | Side 2 | | | | | P0 P3 | | | +---------------+ C0 Side 3 C3 Each patch is constructed by first calling :meth:`begin_patch`, then :meth:`move_to` to specify the first point in the patch (C0). Then the sides are specified with calls to :meth:`curve_to` and :meth:`line_to`. The four additional control points (P0, P1, P2, P3) in a patch can be specified with :meth:`set_control_point`. At each corner of the patch (C0, C1, C2, C3) a color may be specified with :meth:`set_corner_color_rgb` or :meth:`set_corner_color_rgba`. Any corner whose color is not explicitly specified defaults to transparent black. A Coons patch is a special case of the tensor-product patch where the control points are implicitly defined by the sides of the patch. The default value for any control point not specified is the implicit value for a Coons patch, i.e. if no control points are specified the patch is a Coons patch. A triangle is a special case of the tensor-product patch where the control points are implicitly defined by the sides of the patch, all the sides are lines and one of them has length 0, i.e. if the patch is specified using just 3 lines, it is a triangle. If the corners connected by the 0-length side have the same color, the patch is a Gouraud-shaded triangle. Patches may be oriented differently to the above diagram. For example the first point could be at the top left. The diagram only shows the relationship between the sides, corners and control points. Regardless of where the first point is located, when specifying colors, corner 0 will always be the first point, corner 1 the point between side 0 and side 1 etc. Calling :meth:`end_patch` completes the current patch. If less than 4 sides have been defined, the first missing side is defined as a line from the current point to the first point of the patch (C0) and the other sides are degenerate lines from C0 to C0. The corners between the added sides will all be coincident with C0 of the patch and their color will be set to be the same as the color of C0. Additional patches may be added with additional calls to :meth:`begin_patch`/:meth:`end_patch`. :: # Add a Coons patch pattern = cairo.MeshPattern() pattern.begin_patch() pattern.move_to(0, 0) pattern.curve_to(30, -30, 60, 30, 100, 0) pattern.curve_to(60, 30, 130, 60, 100, 100) pattern.curve_to(60, 70, 30, 130, 0, 100) pattern.curve_to(30, 70, -30, 30, 0, 0) pattern.set_corner_color_rgb(0, 1, 0, 0) pattern.set_corner_color_rgb(1, 0, 1, 0) pattern.set_corner_color_rgb(2, 0, 0, 1) pattern.set_corner_color_rgb(3, 1, 1, 0) pattern.end_patch() # Add a Gouraud-shaded triangle pattern = cairo.MeshPattern() pattern.begin_patch() pattern.move_to(100, 100) pattern.line_to(130, 130) pattern.line_to(130, 70) pattern.set_corner_color_rgb(0, 1, 0, 0) pattern.set_corner_color_rgb(1, 0, 1, 0) pattern.set_corner_color_rgb(2, 0, 0, 1) pattern.end_patch() When two patches overlap, the last one that has been added is drawn over the first one. When a patch folds over itself, points are sorted depending on their parameter coordinates inside the patch. The v coordinate ranges from 0 to 1 when moving from side 3 to side 1; the u coordinate ranges from 0 to 1 when going from side 0 to side Points with higher v coordinate hide points with lower v coordinate. When two points have the same v coordinate, the one with higher u coordinate is above. This means that points nearer to side 1 are above points nearer to side 3; when this is not sufficient to decide which point is above (for example when both points belong to side 1 or side 3) points nearer to side 2 are above points nearer to side 0. For a complete definition of tensor-product patches, see the PDF specification (ISO32000), which describes the parametrization in detail. Note: The coordinates are always in pattern space. For a new pattern, pattern space is identical to user space, but the relationship between the spaces can be changed with :meth:`Pattern.set_matrix`. .. method:: begin_patch() :raises Error: Begin a patch in a mesh pattern. After calling this function, the patch shape should be defined with :meth:`move_to`, :meth:`line_to` and :meth:`curve_to`. After defining the patch, :meth:`end_patch` must be called before using pattern as a source or mask. .. method:: curve_to(x1, y1, x2, y2, x3, y3) :param float x1: the X coordinate of the first control point :param float y1: the Y coordinate of the first control point :param float x2: the X coordinate of the second control point :param float y2: the Y coordinate of the second control point :param float x3: the X coordinate of the end of the curve :param float y3: the Y coordinate of the end of the curve :raises Error: Adds a cubic Bézier spline to the current patch from the current point to position (x3 , y3 ) in pattern-space coordinates, using (x1 , y1 ) and (x2 , y2 ) as the control points. If the current patch has no current point before the call to :meth:`curve_to`, this function will behave as if preceded by a call to ``pattern.move_to(x1, y1)``. After this call the current point will be (x3 , y3 ). .. method:: end_patch() :raises Error: Indicates the end of the current patch in a mesh pattern. If the current patch has less than 4 sides, it is closed with a straight line from the current point to the first point of the patch as if :meth:`line_to` was used. .. method:: get_control_point(patch_num, point_num) :param int patch_num: the patch number to return data for :param int point_num: he control point number to return data for :returns: a (x, y) tuple of float - coordinates of the control point :rtype: tuple :raises Error: Gets the control point point_num of patch patch_num for a mesh pattern. ``patch_num`` can range from 0 to n-1 where n is the number returned by :meth:`get_patch_count`. Valid values for ``point_num`` are from 0 to 3 and identify the control points as explained in :class:`MeshPattern`. .. method:: get_corner_color_rgba(patch_num, corner_num) :param int patch_num: the patch number to return data for :param int corner_num: the corner number to return data for :returns: a (red, green, blue, alpha) tuple of float :rtype: tuple :raises Error: Gets the color information in corner ``corner_num`` of patch ``patch_num`` for a mesh pattern. ``patch_num`` can range from 0 to n-1 where n is the number returned by :meth:`get_patch_count`. Valid values for ``corner_num`` are from 0 to 3 and identify the corners as explained in :class:`MeshPattern`. .. method:: get_patch_count() :returns: number of patches :rtype: int Gets the number of patches specified in the given mesh pattern. The number only includes patches which have been finished by calling :meth:`end_patch`. For example it will be 0 during the definition of the first patch. .. method:: get_path(patch_num) :param int patch_num: the patch number to return data for :returns: the path defining the patch :rtype: Path :raises Error: Gets path defining the patch ``patch_num`` for a mesh pattern. ``patch_num`` can range from 0 to n-1 where n is the number returned by :meth:`get_patch_count`. .. method:: line_to(x, y) :param float x: the X coordinate of the end of the new line :param float y: the Y coordinate of the end of the new line :raises Error: Adds a line to the current patch from the current point to position (x , y ) in pattern-space coordinates. If there is no current point before the call to :meth:`line_to` this function will behave as ``pattern.move_to(x ,y)``. After this call the current point will be (x , y ). .. method:: move_to(x, y) :param float x: the X coordinate of the new position :param float y: the Y coordinate of the new position :raises Error: Define the first point of the current patch in a mesh pattern. After this call the current point will be (x , y ). .. method:: set_control_point(point_num, x, y) :param int point_num: the control point to set the position for :param float x: the X coordinate of the control point :param float y: the Y coordinate of the control point :raises Error: Set an internal control point of the current patch. Valid values for point_num are from 0 to 3 and identify the control points as explained in :class:`MeshPattern`. .. method:: set_corner_color_rgb(corner_num, red, green, blue) :param int corner_num: the corner to set the color for :param float red: red component of color :param float green: green component of color :param float blue: blue component of color :raises Error: Sets the color of a corner of the current patch in a mesh pattern. The color is specified in the same way as in :meth:`Context.set_source_rgb`. Valid values for corner_num are from 0 to 3 and identify the corners as explained in :class:`MeshPattern`. .. method:: set_corner_color_rgba(corner_num, red, green, blue, alpha) :param int corner_num: the corner to set the color for :param float red: red component of color :param float green: green component of color :param float blue: blue component of color :param float alpha: alpha component of color :raises Error: Sets the color of a corner of the current patch in a mesh pattern. The color is specified in the same way as in :meth:`Context.set_source_rgba`. Valid values for corner_num are from 0 to 3 and identify the corners as explained in :class:`MeshPattern`. class RasterSourcePattern(:class:`Pattern`) =========================================== The raster source provides the ability to supply arbitrary pixel data whilst rendering. The pixels are queried at the time of rasterisation by means of user callback functions, allowing for the ultimate flexibility. For example, in handling compressed image sources, you may keep a MRU cache of decompressed images and decompress sources on the fly and discard old ones to conserve memory. For the raster source to be effective, you must at least specify the acquire and release callbacks which are used to retrieve the pixel data for the region of interest and demark when it can be freed afterwards. Other callbacks are provided for when the pattern is copied temporarily during rasterisation, or more permanently as a snapshot in order to keep the pixel data available for printing. .. class:: RasterSourcePattern(content, width, height) :param Content content: content type for the pixel data that will be returned. Knowing the content type ahead of time is used for analysing the operation and picking the appropriate rendering path. :param int width: maximum size of the sample area :param int height: maximum size of the sample area :raises Error: :rtype: RasterSourcePattern Creates a new user pattern for providing pixel data. Use the setter functions to associate callbacks with the returned pattern. .. versionadded:: 1.15 .. method:: set_acquire(acquire, release) :param callable acquire: acquire callback or :obj:`None` to unset it :param callable release: (optional) release callback or :obj:`None` :raises Error: Specifies the callbacks used to generate the image surface for a rendering operation (acquire) and the function used to cleanup that surface afterwards. The acquire callback should create a surface (preferably an image surface created to match the target using :meth:`Surface.create_similar_image`) that defines at least the region of interest specified by extents. The surface is allowed to be the entire sample area, but if it does contain a subsection of the sample area, the surface extents should be provided by setting the device offset (along with its width and height) using :meth:`Surface.set_device_offset`. .. function:: acquire(target, extents) :param Surface target: the rendering target surface :param RectangleInt extents: rectangular region of interest in pixels in sample space :rtype: Surface This function is called when a pattern is being rendered from. It should create a surface that provides the pixel data for the region of interest as defined by extents, though the surface itself does not have to be limited to that area. For convenience the surface should probably be of image type, created with :meth:`Surface.create_similar_image` for the target (which enables the number of copies to be reduced during transfer to the device). Another option, might be to return a similar surface to the target for explicit handling by the application of a set of cached sources on the device. The region of sample data provided should be defined using :meth:`Surface.set_device_offset` to specify the top-left corner of the sample data (along with width and height of the surface). .. function:: release(surface) :param Surface surface: the surface created during acquire This function is called when the pixel data is no longer being accessed by the pattern for the rendering operation. .. versionadded:: 1.15 .. method:: get_acquire() :returns: a (acquire, release) tuple of callables or None as set through :meth:`set_acquire` Queries the current acquire and release callbacks. .. versionadded:: 1.15 pycairo-1.16.2/docs/reference/rectangle.rst000066400000000000000000000014751323762421700206510ustar00rootroot00000000000000.. _rectangle: ********* Rectangle ********* .. currentmodule:: cairo class Rectangle(tuple) ====================== .. class:: Rectangle(x, y, width, height) :param float x: X coordinate of the left side of the rectangle :param float y: Y coordinate of the the top side of the rectangle :param float width: width of the rectangle :param float height: height of the rectangle :rtype: Rectangle .. versionadded:: 1.15 In prior versions a (float, float, float, float) tuple was used instead of :class:`Rectangle`. A data structure for holding a rectangle. .. attribute:: x :class:`float` .. attribute:: y :class:`float` .. attribute:: width :class:`float` .. attribute:: height :class:`float` pycairo-1.16.2/docs/reference/region.rst000066400000000000000000000074141323762421700201670ustar00rootroot00000000000000.. _region: ****** Region ****** Region — Representing a pixel-aligned area .. currentmodule:: cairo class Region() ============== *Region* is a simple graphical data type representing an area of integer-aligned rectangles. They are often used on raster surfaces to track areas of interest, such as change or clip areas. .. class:: Region([rectangle_int|rectangle_ints]) :param rectangle_int: a rectangle or a list of rectangle :type rectangle_int: :class:`RectangleInt` or [:class:`RectangleInt`] Allocates a new empty region object or a region object with the containing rectangle(s). .. versionadded:: 1.11.0 .. method:: copy() :returns: A newly allocated :class:`Region`. :raises Error: if memory cannot be allocated. Allocates a new *Region* object copying the area from original. .. method:: get_extents() :returns: The bounding rectangle of region :rtype: RectangleInt .. method:: num_rectangles() :returns: The number of rectangles contained in region :rtype: int .. method:: get_rectangle(nth) :param int nth: a number indicating which rectangle should be returned :returns: The *nth* rectangle from the region :rtype: RectangleInt .. method:: is_empty() :returns: Whether region is empty :rtype: bool .. method:: contains_point(x, y) :param int x: The x coordinate of a point :param int y: The y coordinate of a point :returns: Whether (x , y) is contained in the region :rtype: bool .. method:: contains_rectangle(rectangle) :param RectangleInt rectangle: :returns: region overlap :rtype: cairo.RegionOverlap Checks whether rectangle is inside, outside or partially contained in region .. method:: equal(region) :param Region region: :returns: Whether both regions contained the same coverage :rtype: bool .. method:: translate(dx, dy) :param int dx: Amount to translate in the x direction :param int dy: Amount to translate in the y direction Translates region by (dx , dy ). .. method:: intersect(other) :param other: :type other: :class:`Region` or :class:`RectangleInt` :returns: The intersection of the region and the passed region or rectangle :rtype: Region .. method:: subtract(other) :param other: :type other: :class:`Region` or :class:`RectangleInt` :returns: The result of the subtraction of the region and the passed region or rectangle :rtype: Region .. method:: union(other) :param other: :type other: :class:`Region` or :class:`RectangleInt` :returns: The union of the region and the passed region or rectangle :rtype: Region .. method:: xor(other) :param other: :type other: :class:`Region` or :class:`RectangleInt` :returns: The exclusive difference of the region and the passed region or rectangle :rtype: Region class RectangleInt() ==================== *RectangleInt* is a data structure for holding a rectangle with integer coordinates. .. class:: RectangleInt(x=0, y=0, width=0, height=0) :param x: X coordinate of the left side of the rectangle :type x: int :param y: Y coordinate of the the top side of the rectangle :type y: int :param width: width of the rectangle :type width: int :param height: height of the rectangle :type height: int Allocates a new *RectangleInt* object. .. versionadded:: 1.11.0 .. attribute:: x :class:`int` .. attribute:: y :class:`int` .. attribute:: width :class:`int` .. attribute:: height :class:`int` pycairo-1.16.2/docs/reference/surfaces.rst000066400000000000000000001202231323762421700205110ustar00rootroot00000000000000.. _surfaces: ******** Surfaces ******** .. currentmodule:: cairo .. comment block example reST: (add back '..' where required at column 0) . class:: module.C[(signature)] .. classmethod:: name(signature) .. staticmethod:: name(signature) .. method:: method(signature) :param p1: xxx :type p1: int :param p2: xxx :type p2: str :returns: xxx :rtype: list of strings :raises: xxx .. versionadded:: 1.6 links: :data:`cairo.ANTIALIAS_SUBPIXEL` :class:`Context` :exc:`cairo.Error` :meth:`.copy_page` :meth:`Context.copy_page` ``ctx.rel_move_to(dx, dy)`` # code snippet cairo.Surface is the abstract type representing all different drawing targets that cairo can render to. The actual drawings are performed using a :class:`Context`. A cairo.Surface is created by using backend-specific constructors of the form cairo.Surface(). class Surface() =============== .. class:: Surface() *Surface* is the abstract base class from which all the other surface classes derive. It cannot be instantiated directly. .. method:: copy_page() Emits the current page for backends that support multiple pages, but doesn't clear it, so that the contents of the current page will be retained for the next page. Use :meth:`.show_page` if you want to get an empty page after the emission. :meth:`Context.copy_page` is a convenience function for this. .. versionadded:: 1.6 .. method:: create_similar(content, width, height) :param cairo.Content content: the content for the new surface :param width: width of the new surface, (in device-space units) :type width: int :param height: height of the new surface (in device-space units) :type width: int :returns: a newly allocated *Surface*. Create a *Surface* that is as compatible as possible with the existing surface. For example the new surface will have the same fallback resolution and :class:`FontOptions`. Generally, the new surface will also use the same backend, unless that is not possible for some reason. Initially the surface contents are all 0 (transparent if contents have transparency, black otherwise.) .. method:: finish() This method finishes the *Surface* and drops all references to external resources. For example, for the Xlib backend it means that cairo will no longer access the drawable, which can be freed. After calling finish() the only valid operations on a *Surface* are flushing and finishing it. Further drawing to the surface will not affect the surface but will instead trigger a :exc:`cairo.Error` exception. .. method:: flush() Do any pending drawing for the *Surface* and also restore any temporary modification's cairo has made to the *Surface's* state. This method must be called before switching from drawing on the *Surface* with cairo to drawing on it directly with native APIs. If the *Surface* doesn't support direct access, then this function does nothing. .. method:: get_content() :returns: The content type of *Surface*, which indicates whether the *Surface* contains color and/or alpha information. :rtype: cairo.Content .. versionadded:: 1.2 .. method:: get_device_offset() :returns: (x_offset, y_offset) a tuple of float * x_offset: the offset in the X direction, in device units * y_offset: the offset in the Y direction, in device units This method returns the previous device offset set by :meth:`.set_device_offset`. .. versionadded:: 1.2 .. method:: get_fallback_resolution() :returns: (x_pixels_per_inch, y_pixels_per_inch) a tuple of float * x_pixels_per_inch: horizontal pixels per inch * y_pixels_per_inch: vertical pixels per inch This method returns the previous fallback resolution set by :meth:`.set_fallback_resolution`, or default fallback resolution if never set. .. versionadded:: 1.8 .. method:: get_font_options() :returns: a :class:`FontOptions` Retrieves the default font rendering options for the *Surface*. This allows display surfaces to report the correct subpixel order for rendering on them, print surfaces to disable hinting of metrics and so forth. The result can then be used with :class:`ScaledFont`. .. method:: supports_mime_type(mime_type) :param str mime_type: the mime type (:ref:`constants_MIME_TYPE`) :returns: :obj:`True` if surface supports mime_type, :obj:`False` otherwise :rtype: bool Return whether surface supports ``mime_type``. .. versionadded:: 1.12.0 .. method:: set_mime_data(mime_type, data) :param mime_type: the MIME type of the image data (:ref:`constants_MIME_TYPE`) :type mime_type: str :param data: the image data to attach to the surface :type data: bytes Attach an image in the format ``mime_type`` to *Surface*. To remove the data from a surface, call this function with same mime type and :obj:`None` for data. The attached image (or filename) data can later be used by backends which support it (currently: PDF, PS, SVG and Win32 Printing surfaces) to emit this data instead of making a snapshot of the surface. This approach tends to be faster and requires less memory and disk space. The recognized MIME types are listed under :ref:`constants_MIME_TYPE`. See corresponding backend surface docs for details about which MIME types it can handle. Caution: the associated MIME data will be discarded if you draw on the surface afterwards. Use this function with care. .. versionadded:: 1.12.0 .. method:: get_mime_data(mime_type) :param mime_type: the MIME type of the image data (:ref:`constants_MIME_TYPE`) :type mime_type: str :returns: :class:`bytes` or :obj:`None` Return mime data previously attached to surface with :meth:`set_mime_data` using the specified mime type. If no data has been attached with the given mime type, :obj:`None` is returned. .. versionadded:: 1.12.0 .. method:: mark_dirty() Tells cairo that drawing has been done to *Surface* using means other than cairo, and that cairo should reread any cached areas. Note that you must call :meth:`.flush` before doing such drawing. .. method:: mark_dirty_rectangle(x, y, width, height) :param x: X coordinate of dirty rectangle :type x: int :param y: Y coordinate of dirty rectangle :type y: int :param width: width of dirty rectangle :type width: int :param height: height of dirty rectangle :type height: int Like :meth:`.mark_dirty`, but drawing has been done only to the specified rectangle, so that cairo can retain cached contents for other parts of the surface. Any cached clip set on the *Surface* will be reset by this function, to make sure that future cairo calls have the clip set that they expect. .. method:: set_device_offset(x_offset, y_offset) :param x_offset: the offset in the X direction, in device units :type x_offset: float :param y_offset: the offset in the Y direction, in device units :type y_offset: float Sets an offset that is added to the device coordinates determined by the CTM when drawing to *Surface*. One use case for this function is when we want to create a *Surface* that redirects drawing for a portion of an onscreen surface to an offscreen surface in a way that is completely invisible to the user of the cairo API. Setting a transformation via :meth:`Context.translate` isn't sufficient to do this, since functions like :meth:`Context.device_to_user` will expose the hidden offset. Note that the offset affects drawing to the surface as well as using the surface in a source pattern. .. method:: set_fallback_resolution(x_pixels_per_inch, y_pixels_per_inch) :param x_pixels_per_inch: horizontal setting for pixels per inch :type x_pixels_per_inch: float :param y_pixels_per_inch: vertical setting for pixels per inch :type y_pixels_per_inch: float Set the horizontal and vertical resolution for image fallbacks. When certain operations aren't supported natively by a backend, cairo will fallback by rendering operations to an image and then overlaying that image onto the output. For backends that are natively vector-oriented, this function can be used to set the resolution used for these image fallbacks, (larger values will result in more detailed images, but also larger file sizes). Some examples of natively vector-oriented backends are the ps, pdf, and svg backends. For backends that are natively raster-oriented, image fallbacks are still possible, but they are always performed at the native device resolution. So this function has no effect on those backends. Note: The fallback resolution only takes effect at the time of completing a page (with :meth:`Context.show_page` or :meth:`Context.copy_page`) so there is currently no way to have more than one fallback resolution in effect on a single page. The default fallback resoultion is 300 pixels per inch in both dimensions. .. versionadded:: 1.2 .. method:: show_page() Emits and clears the current page for backends that support multiple pages. Use :meth:`.copy_page` if you don't want to clear the page. There is a convenience function for this that takes a :meth:`Context.show_page`. .. versionadded:: 1.6 .. method:: write_to_png(fobj) :param fobj: the file to write to :type fobj: filename (:obj:`pathlike`), file or file-like object :raises: :exc:`MemoryError` if memory could not be allocated for the operation :exc:`IOError` if an I/O error occurs while attempting to write the file Writes the contents of *Surface* to *fobj* as a PNG image. .. method:: create_for_rectangle(x, y, width, height) :param float x: the x-origin of the sub-surface from the top-left of the target surface (in device-space units) :param float y: the y-origin of the sub-surface from the top-left of the target surface (in device-space units) :param float width: width of the sub-surface (in device-space units) :param float height: height of the sub-surface (in device-space units) :returns: a new surface :rtype: cairo.Surface Create a new surface that is a rectangle within the target surface. All operations drawn to this surface are then clipped and translated onto the target surface. Nothing drawn via this sub-surface outside of its bounds is drawn onto the target surface, making this a useful method for passing constrained child surfaces to library routines that draw directly onto the parent surface, i.e. with no further backend allocations, double buffering or copies. .. note:: The semantics of subsurfaces have not been finalized yet unless the rectangle is in full device units, is contained within the extents of the target surface, and the target or subsurface's device transforms are not changed. .. versionadded:: 1.12.0 .. method:: create_similar_image(format, width, height) :param cairo.Format format: the format for the new surface :param int width: width of the new surface, (in device-space units) :param int height: height of the new surface, (in device-space units) :returns: a new image surface :rtype: cairo.ImageSurface Create a new image surface that is as compatible as possible for uploading to and the use in conjunction with an existing surface. However, this surface can still be used like any normal image surface. Initially the surface contents are all 0 (transparent if contents have transparency, black otherwise.) .. versionadded:: 1.12.0 .. method:: has_show_text_glyphs() :returns: :obj:`True` if surface supports :meth:`Context.show_text_glyphs`, :obj:`False` otherwise :rtype: bool Returns whether the surface supports sophisticated :meth:`Context.show_text_glyphs` operations. That is, whether it actually uses the provided text and cluster data to a :meth:`Context.show_text_glyphs` call. Note: Even if this function returns :obj:`False`, a :meth:`Context.show_text_glyphs` operation targeted at surface will still succeed. It just will act like a :meth:`Context.show_glyphs` operation. Users can use this function to avoid computing UTF-8 text and cluster mapping if the target surface does not use it. .. versionadded:: 1.12.0 .. method:: set_device_scale(x_scale, y_scale) :param float x_scale: a scale factor in the X direction :param float y_scale: a scale factor in the Y direction Sets a scale that is multiplied to the device coordinates determined by the CTM when drawing to surface . One common use for this is to render to very high resolution display devices at a scale factor, so that code that assumes 1 pixel will be a certain size will still work. Setting a transformation via :meth:`Context.translate` isn't sufficient to do this, since functions like :meth:`Context.device_to_user` will expose the hidden scale. .. versionadded:: 1.14.0 .. method:: get_device_scale() :returns: (x_scale,y_scale) a 2-tuple of float This function returns the previous device offset set by :meth:`Surface.set_device_scale`. .. versionadded:: 1.14.0 .. method:: get_device() :returns: the device or :obj:`None` if the surface does not have an associated device :rtype: Device This function returns the device for a surface. .. versionadded:: 1.14.0 .. method:: map_to_image(extents) :param RectangleInt extents: limit the extraction to an rectangular region or :obj:`None` for the whole surface :returns: newly allocated image surface :rtype: ImageSurface :raises Error: Returns an image surface that is the most efficient mechanism for modifying the backing store of the target surface. Note, the use of the original surface as a target or source whilst it is mapped is undefined. The result of mapping the surface multiple times is undefined. Calling :meth:`Surface.finish` on the resulting image surface results in undefined behavior. Changing the device transform of the image surface or of surface before the image surface is unmapped results in undefined behavior. The caller must use :meth:`Surface.unmap_image` to destroy this image surface. .. versionadded:: 1.15.0 .. method:: unmap_image(image) :param ImageSurface image: the currently mapped image Unmaps the image surface as returned from :meth:`Surface.map_to_image`. The content of the image will be uploaded to the target surface. Afterwards, the image is destroyed. Using an image surface which wasn't returned by :meth:`Surface.map_to_image` results in undefined behavior. .. versionadded:: 1.15.0 class ImageSurface(:class:`Surface`) ==================================== A *cairo.ImageSurface* provides the ability to render to memory buffers either allocated by cairo or by the calling code. The supported image formats are those defined in :class:`cairo.Format`. .. class:: ImageSurface(format, width, height) :param cairo.Format format: format of pixels in the surface to create :param width: width of the surface, in pixels :param height: height of the surface, in pixels :returns: a new *ImageSurface* :raises: :exc:`MemoryError` in case of no memory Creates an *ImageSurface* of the specified format and dimensions. Initially the surface contents are all 0. (Specifically, within each pixel, each color or alpha channel belonging to format will be 0. The contents of bits within a pixel, but not belonging to the given format are undefined). .. classmethod:: create_for_data(data, format, width, height[, stride]) :param data: a writable Python buffer/memoryview object :param cairo.Format format: the format of pixels in the buffer :param width: the width of the image to be stored in the buffer :param height: the height of the image to be stored in the buffer :param stride: the number of bytes between the start of rows in the buffer as allocated. If not given the value from :meth:`cairo.Format.stride_for_width` is used. :returns: a new *ImageSurface* :raises: :exc:`MemoryError` in case of no memory. :exc:`cairo.Error` in case of invalid *stride* value. Creates an *ImageSurface* for the provided pixel data. The initial contents of buffer will be used as the initial image contents; you must explicitly clear the buffer, using, for example, cairo_rectangle() and cairo_fill() if you want it cleared. Note that the *stride* may be larger than width*bytes_per_pixel to provide proper alignment for each pixel and row. This alignment is required to allow high-performance rendering within cairo. The correct way to obtain a legal stride value is to call :meth:`cairo.Format.stride_for_width` with the desired format and maximum image width value, and use the resulting stride value to allocate the data and to create the :class:`ImageSurface`. See :meth:`cairo.Format.stride_for_width` for example code. .. classmethod:: create_from_png(fobj) :param fobj: a :obj:`pathlike`, file, or file-like object of the PNG to load. :returns: a new *ImageSurface* initialized the contents to the given PNG file. .. staticmethod:: format_stride_for_width(format, width) See :meth:`cairo.Format.stride_for_width`. .. versionadded:: 1.6 .. method:: get_data() :returns: a Python buffer object for the data of the *ImageSurface*, for direct inspection or modification. On Python 3 a memoryview object is returned. .. versionadded:: 1.2 .. method:: get_format() :returns: the format of the *ImageSurface*. :rtype: cairo.Format .. versionadded:: 1.2 .. method:: get_height() :returns: the height of the *ImageSurface* in pixels. .. method:: get_stride() :returns: the stride of the *ImageSurface* in bytes. The stride is the distance in bytes from the beginning of one row of the image data to the beginning of the next row. .. method:: get_width() :returns: the width of the *ImageSurface* in pixels. class PDFSurface(:class:`Surface`) ================================== The PDFSurface is used to render cairo graphics to Adobe PDF files and is a multi-page vector surface backend. .. class:: PDFSurface(fobj, width_in_points, height_in_points) :param fobj: a filename or writable file object. None may be used to specify no output. This will generate a *PDFSurface* that may be queried and used as a source, without generating a temporary file. :type fobj: None, :obj:`pathlike`, file or file-like object :param width_in_points: width of the surface, in points (1 point == 1/72.0 inch) :type width_in_points: float :param height_in_points: height of the surface, in points (1 point == 1/72.0 inch) :type height_in_points: float :returns: a new *PDFSurface* of the specified size in points to be written to *fobj*. :raises: :exc:`MemoryError` in case of no memory .. versionadded:: 1.2 .. method:: set_size() :param width_in_points: new surface width, in points (1 point == 1/72.0 inch) :type width_in_points: float :param height_in_points: new surface height, in points (1 point == 1/72.0 inch) :type height_in_points: float Changes the size of a *PDFSurface* for the current (and subsequent) pages. This function should only be called before any drawing operations have been performed on the current page. The simplest way to do this is to call this function immediately after creating the surface or immediately after completing a page with either :meth:`Context.show_page` or :meth:`Context.copy_page`. .. versionadded:: 1.2 .. method:: restrict_to_version(version) :param version: PDF version :type cairo.PDFVersion version: PDF version Restricts the generated PDF file to version . See :meth:`get_versions` for a list of available version values that can be used here. This function should only be called before any drawing operations have been performed on the given surface. The simplest way to do this is to call this function immediately after creating the surface. .. versionadded:: 1.12.0 .. staticmethod:: get_versions() :returns: supported version list :rtype: list Retrieve the list of supported versions. See :meth:`restrict_to_version`. .. versionadded:: 1.12.0 .. staticmethod:: version_to_string(version) :param version: PDF version :type cairo.PDFVersion version: PDF version :returns: the string associated to the given version :rtype: str :raises ValueError: if version isn't valid Get the string representation of the given version id. See :meth:`get_versions` for a way to get the list of valid version ids. .. versionadded:: 1.12.0 class PSSurface(:class:`Surface`) ================================= The *PSSurface* is used to render cairo graphics to Adobe PostScript files and is a multi-page vector surface backend. .. class:: PSSurface(fobj, width_in_points, height_in_points) :param fobj: a filename or writable file object. None may be used to specify no output. This will generate a *PSSurface* that may be queried and used as a source, without generating a temporary file. :type fobj: None, :obj:`pathlike`, file or file-like object :param width_in_points: width of the surface, in points (1 point == 1/72.0 inch) :type width_in_points: float :param height_in_points: height of the surface, in points (1 point == 1/72.0 inch) :type height_in_points: float :returns: a new *PDFSurface* of the specified size in points to be written to *fobj*. :raises: :exc:`MemoryError` in case of no memory Note that the size of individual pages of the PostScript output can vary. See :meth:`.set_size`. .. method:: dsc_begin_page_setup() This method indicates that subsequent calls to :meth:`.dsc_comment` should direct comments to the PageSetup section of the PostScript output. This method call is only needed for the first page of a surface. It should be called after any call to :meth:`.dsc_begin_setup` and before any drawing is performed to the surface. See :meth:`.dsc_comment` for more details. .. versionadded:: 1.2 .. method:: dsc_begin_setup() This function indicates that subsequent calls to :meth:`.dsc_comment` should direct comments to the Setup section of the PostScript output. This function should be called at most once per surface, and must be called before any call to :meth:`.dsc_begin_page_setup` and before any drawing is performed to the surface. See :meth:`.dsc_comment` for more details. .. versionadded:: 1.2 .. method:: dsc_comment(comment) :param comment: a comment string to be emitted into the PostScript output :type comment: str Emit a comment into the PostScript output for the given surface. The comment is expected to conform to the PostScript Language Document Structuring Conventions (DSC). Please see that manual for details on the available comments and their meanings. In particular, the %%IncludeFeature comment allows a device-independent means of controlling printer device features. So the PostScript Printer Description Files Specification will also be a useful reference. The comment string must begin with a percent character (%) and the total length of the string (including any initial percent characters) must not exceed 255 characters. Violating either of these conditions will place *PSSurface* into an error state. But beyond these two conditions, this function will not enforce conformance of the comment with any particular specification. The comment string should not have a trailing newline. The DSC specifies different sections in which particular comments can appear. This function provides for comments to be emitted within three sections: the header, the Setup section, and the PageSetup section. Comments appearing in the first two sections apply to the entire document while comments in the BeginPageSetup section apply only to a single page. For comments to appear in the header section, this function should be called after the surface is created, but before a call to :meth:`.dsc_begin_setup`. For comments to appear in the Setup section, this function should be called after a call to :meth:`.dsc_begin_setup` but before a call to :meth:`.dsc_begin_page_setup`. For comments to appear in the PageSetup section, this function should be called after a call to :meth:`.dsc_begin_page_setup`. Note that it is only necessary to call :meth:`.dsc_begin_page_setup` for the first page of any surface. After a call to :meth:`Context.show_page` or :meth:`Context.copy_page` comments are unambiguously directed to the PageSetup section of the current page. But it doesn't hurt to call this function at the beginning of every page as that consistency may make the calling code simpler. As a final note, cairo automatically generates several comments on its own. As such, applications must not manually generate any of the following comments: Header section: %!PS-Adobe-3.0, %Creator, %CreationDate, %Pages, %BoundingBox, %DocumentData, %LanguageLevel, %EndComments. Setup section: %BeginSetup, %EndSetup PageSetup section: %BeginPageSetup, %PageBoundingBox, %EndPageSetup. Other sections: %BeginProlog, %EndProlog, %Page, %Trailer, %EOF Here is an example sequence showing how this function might be used:: surface = PSSurface (filename, width, height) ... surface.dsc_comment (surface, "%%Title: My excellent document") surface.dsc_comment (surface, "%%Copyright: Copyright (C) 2006 Cairo Lover") ... surface.dsc_begin_setup (surface) surface.dsc_comment (surface, "%%IncludeFeature: *MediaColor White") ... surface.dsc_begin_page_setup (surface) surface.dsc_comment (surface, "%%IncludeFeature: *PageSize A3") surface.dsc_comment (surface, "%%IncludeFeature: *InputSlot LargeCapacity") surface.dsc_comment (surface, "%%IncludeFeature: *MediaType Glossy") surface.dsc_comment (surface, "%%IncludeFeature: *MediaColor Blue") ... draw to first page here .. ctx.show_page (cr) ... surface.dsc_comment (surface, "%%IncludeFeature: PageSize A5"); ... .. versionadded:: 1.2 .. method:: get_eps() :returns: True iff the *PSSurface* will output Encapsulated PostScript. .. versionadded:: 1.6 .. staticmethod:: level_to_string(level) :param cairo.PSLevel level: a PS level :returns: the string associated to given level. :rtype: str Get the string representation of the given *level*. See :meth:`get_levels` for a way to get the list of valid level ids. .. note:: Prior to 1.12 this was available under :meth:`ps_level_to_string` .. versionadded:: 1.12.0 .. data:: ps_level_to_string Alias for :meth:`level_to_string` .. versionadded:: 1.6 .. method:: restrict_to_level(level) :param cairo.PSLevel level: a PS level Restricts the generated PostSript file to *level*. See :meth:`get_levels` for a list of available level values that can be used here. This function should only be called before any drawing operations have been performed on the given surface. The simplest way to do this is to call this function immediately after creating the surface. .. versionadded:: 1.6 .. method:: set_eps(eps) :param eps: True to output EPS format PostScript :type eps: bool If *eps* is True, the PostScript surface will output Encapsulated PostScript. This function should only be called before any drawing operations have been performed on the current page. The simplest way to do this is to call this function immediately after creating the surface. An Encapsulated PostScript file should never contain more than one page. .. versionadded:: 1.6 .. method:: set_size(width_in_points, height_in_points) :param width_in_points: new surface width, in points (1 point == 1/72.0 inch) :param height_in_points: new surface height, in points (1 point == 1/72.0 inch) :type width_in_points: float :type height_in_points: float Changes the size of a PostScript surface for the current (and subsequent) pages. This function should only be called before any drawing operations have been performed on the current page. The simplest way to do this is to call this function immediately after creating the surface or immediately after completing a page with either :meth:`Context.show_page` or :meth:`Context.copy_page`. .. versionadded:: 1.2 .. staticmethod:: get_levels() :returns: supported level list :rtype: list Retrieve the list of supported levels. See :meth:`restrict_to_level`. .. versionadded:: 1.12.0 class RecordingSurface(:class:`Surface`) ======================================== A *RecordingSurface* is a surface that records all drawing operations at the highest level of the surface backend interface, (that is, the level of paint, mask, stroke, fill, and show_text_glyphs). The recording surface can then be "replayed" against any target surface by using it as a source surface. If you want to replay a surface so that the results in target will be identical to the results that would have been obtained if the original operations applied to the recording surface had instead been applied to the target surface, you can use code like this:: cr = cairo.Context(target) cr.set_source_surface(recording_surface, 0.0, 0.0) cr.paint() A *RecordingSurface* is logically unbounded, i.e. it has no implicit constraint on the size of the drawing surface. However, in practice this is rarely useful as you wish to replay against a particular target surface with known bounds. For this case, it is more efficient to specify the target extents to the recording surface upon creation. The recording phase of the recording surface is careful to snapshot all necessary objects (paths, patterns, etc.), in order to achieve accurate replay. .. class:: RecordingSurface(content, rectangle) :param cairo.Content content: the content for the new surface :param cairo.Rectangle rectangle: or None to record unbounded operations. :returns: a new *RecordingSurface* Creates a *RecordingSurface* which can be used to record all drawing operations at the highest level (that is, the level of paint, mask, stroke, fill and show_text_glyphs). The *RecordingSurface* can then be "replayed" against any target surface by using it as a source to drawing operations. The recording phase of the *RecordingSurface* is careful to snapshot all necessary objects (paths, patterns, etc.), in order to achieve accurate replay. .. versionadded:: 1.11.0 .. method:: ink_extents() ::rtype: (x0,y0,width,height) a 4-tuple of float * x0: the x-coordinate of the top-left of the ink bounding box * y0: the y-coordinate of the top-left of the ink bounding box * width: the width of the ink bounding box * height: the height of the ink bounding box Measures the extents of the operations stored within the *RecordingSurface*. This is useful to compute the required size of an *ImageSurface* (or equivalent) into which to replay the full sequence of drawing operations. .. versionadded:: 1.11.0 .. method:: get_extents() :returns: a rectangle or :obj:`None` if the surface is unbounded. :rtype: Rectangle Get the extents of the recording-surface. .. versionadded:: 1.12.0 class SVGSurface(:class:`Surface`) ================================== The *SVGSurface* is used to render cairo graphics to SVG files and is a multi-page vector surface backend .. class:: SVGSurface(fobj, width_in_points, height_in_points) :param fobj: a filename or writable file object. None may be used to specify no output. This will generate a *SVGSurface* that may be queried and used as a source, without generating a temporary file. :type fobj: None, :obj:`pathlike`, file or file-like object :param width_in_points: width of the surface, in points (1 point == 1/72.0 inch) :type width_in_points: float :param height_in_points: height of the surface, in points (1 point == 1/72.0 inch) :type height_in_points: float :returns: a new *SVGSurface* of the specified size in points to be written to *fobj*. :raises: :exc:`MemoryError` in case of no memory .. method:: restrict_to_version(version) :param version: SVG version :type cairo.SVGVersion version: SVG version Restricts the generated SVG file to version . See :meth:`get_versions` for a list of available version values that can be used here. This function should only be called before any drawing operations have been performed on the given surface. The simplest way to do this is to call this function immediately after creating the surface. .. versionadded:: 1.12.0 .. staticmethod:: get_versions() :returns: supported version list :rtype: list Retrieve the list of supported versions. See :meth:`restrict_to_version`. .. versionadded:: 1.12.0 .. staticmethod:: version_to_string(version) :param version: SVG version :type cairo.SVGVersion version: SVG version :returns: the string associated to the given version :rtype: str :raises ValueError: if version isn't valid Get the string representation of the given version id. See :meth:`get_versions` for a way to get the list of valid version ids. .. versionadded:: 1.12.0 class Win32Surface(:class:`Surface`) ==================================== The Microsoft Windows surface is used to render cairo graphics to Microsoft Windows windows, bitmaps, and printing device contexts. .. class:: Win32Surface(hdc) :param hdc: the DC to create a surface for :type hdc: int :returns: the newly created surface Creates a cairo surface that targets the given DC. The DC will be queried for its initial clip extents, and this will be used as the size of the cairo surface. The resulting surface will always be of format cairo.FORMAT_RGB24, see :class:`cairo.Format`. class Win32PrintingSurface(:class:`Surface`) ============================================ The Win32PrintingSurface is a multi-page vector surface type. .. class:: Win32PrintingSurface(hdc) :param hdc: the DC to create a surface for :type hdc: int :returns: the newly created surface Creates a cairo surface that targets the given DC. The DC will be queried for its initial clip extents, and this will be used as the size of the cairo surface. The DC should be a printing DC; antialiasing will be ignored, and GDI will be used as much as possible to draw to the surface. The returned surface will be wrapped using the paginated surface to provide correct complex rendering behaviour; :meth:`cairo.Surface.show_page` and associated methods must be used for correct output. class XCBSurface(:class:`Surface`) ================================== The XCB surface is used to render cairo graphics to X Window System windows and pixmaps using the XCB library. Note that the XCB surface automatically takes advantage of the X render extension if it is available. .. class:: XCBSurface :param connection: an XCB connection :param drawable: a X drawable :param visualtype: a X visualtype :param width: The surface width :param height: The surface height Creates a cairo surface that targets the given drawable (pixmap or window). .. note:: This methods works using xpyb. .. method:: set_size(width, height) :param width: The width of the surface :param height: The height of the surface Informs cairo of the new size of the X Drawable underlying the surface. For a surface created for a Window (rather than a Pixmap), this function must be called each time the size of the window changes. (For a subwindow, you are normally resizing the window yourself, but for a toplevel window, it is necessary to listen for ConfigureNotify events.) A Pixmap can never change size, so it is never necessary to call this function on a surface created for a Pixmap. class XlibSurface(:class:`Surface`) =================================== The XLib surface is used to render cairo graphics to X Window System windows and pixmaps using the XLib library. Note that the XLib surface automatically takes advantage of X render extension if it is available. .. class:: XlibSurface .. note:: *XlibSurface* cannot be instantiated directly because Python interaction with Xlib would require open source Python bindings to Xlib which provided a C API. However, an *XlibSurface* instance can be returned from a function call when using pygtk http://www.pygtk.org/. .. method:: get_depth() :returns: the number of bits used to represent each pixel value. .. versionadded:: 1.2 .. method:: get_height() :returns: the height of the X Drawable underlying the surface in pixels. .. versionadded:: 1.2 .. method:: get_width() :returns: the width of the X Drawable underlying the surface in pixels. .. versionadded:: 1.2 class ScriptSurface(:class:`Surface`) ===================================== The script surface provides the ability to render to a native script that matches the cairo drawing model. The scripts can be replayed using tools under the util/cairo-script directory, or with cairo-perf-trace. .. class:: ScriptSurface(script, content, width, height) :param cairo.ScriptDevice script: the script (output device) :param cairo.Content content: the content of the surface :param float width: width in pixels :param float height: height in pixels :rtype: cairo.ScriptSurface :raises cairo.Error: Create a new surface that will emit its rendering through ``script``. .. versionadded:: 1.14 .. classmethod:: create_for_target(script, target) :param cairo.ScriptDevice script: the script (output device) :param cairo.Surface target: a target surface to wrap :rtype: cairo.ScriptSurface :raises cairo.Error: Create a proxy surface that will render to ``target`` and record the operations to ``device``. .. versionadded:: 1.14 class TeeSurface(:class:`Surface`) ===================================== This surface supports redirecting all its input to multiple surfaces. .. class:: TeeSurface(master) :param cairo.Surface master: :rtype: cairo.TeeSurface :raises cairo.Error: .. versionadded:: 1.14 .. method:: add(target) :param cairo.Surface target: :raises cairo.Error: Add the surface .. versionadded:: 1.14 .. method:: remove(target) :param cairo.Surface target: :raises cairo.Error: Remove the surface .. versionadded:: 1.14 .. method:: index(index) :param int index: :rtype: cairo.Surface :raises cairo.Error: Returns the surface at index ``index``. The master surface is at index 0. .. versionadded:: 1.14 pycairo-1.16.2/docs/reference/text.rst000066400000000000000000000314361323762421700176710ustar00rootroot00000000000000.. _text: **** Text **** .. currentmodule:: cairo Cairo has two sets of text rendering capabilities: * The functions with text in their name form cairo's toy text API. The toy API takes UTF-8 encoded text and is limited in its functionality to rendering simple left-to-right text with no advanced features. That means for example that most complex scripts like Hebrew, Arabic, and Indic scripts are out of question. No kerning or correct positioning of diacritical marks either. The font selection is pretty limited too and doesn't handle the case that the selected font does not cover the characters in the text. This set of functions are really that, a toy text API, for testing and demonstration purposes. Any serious application should avoid them. * The functions with glyphs in their name form cairo's low-level text API. The low-level API relies on the user to convert text to a set of glyph indexes and positions. This is a very hard problem and is best handled by external libraries, like the pangocairo that is part of the Pango text layout and rendering library. Pango is available from http://www.pango.org/. class FontFace() ================ A *cairo.FontFace* specifies all aspects of a font other than the size or font matrix (a font matrix is used to distort a font by sheering it or scaling it unequally in the two directions). A *FontFace* can be set on a :class:`Context` by using :meth:`Context.set_font_face` the size and font matrix are set with :meth:`Context.set_font_size` and :meth:`Context.set_font_matrix`. There are various types of *FontFace*, depending on the font backend they use. .. class:: FontFace() .. note:: This class cannot be instantiated directly, it is returned by :meth:`Context.get_font_face`. class FreeTypeFontFace(:class:`FontFace`) ========================================= FreeType Fonts - Font support for FreeType. The FreeType font backend is primarily used to render text on GNU/Linux systems, but can be used on other platforms too. .. note:: FreeType Fonts are not implemented in pycairo because there is no open source Python bindings to FreeType (and fontconfig) that provides a C API. This a possible project idea for anyone interested in adding FreeType support to pycairo. class ToyFontFace(:class:`FontFace`) ==================================== The *cairo.ToyFontFace* class can be used instead of :meth:`Context.select_font_face` to create a toy font independently of a context. .. class:: ToyFontFace(family[, slant[, weight]]) :param family: a font family name :type family: text :param cairo.FontSlant slant: the font slant of the font, defaults to :attr:`cairo.FontSlant.NORMAL`. :param cairo.FontWeight weight: the font weight of the font, defaults to :attr:`cairo.FontWeight.NORMAL`. :returns: a new *ToyFontFace* Creates a *ToyFontFace* from a triplet of family, slant, and weight. These font faces are used in implementation of the the "toy" font API. If family is the zero-length string "", the platform-specific default family is assumed. The default family then can be queried using :meth:`.get_family`. The :meth:`Context.select_font_face` method uses this to create font faces. See that function for limitations of toy font faces. .. versionadded:: 1.8.4 .. method:: get_family() :returns: the family name of a toy font :rtype: str .. versionadded:: 1.8.4 .. method:: get_slant() :returns: the font slant value :rtype: cairo.FontSlant .. versionadded:: 1.8.4 .. method:: get_weight() :returns: the font weight value :rtype: cairo.FontWeight .. versionadded:: 1.8.4 class UserFontFace(:class:`FontFace`) ===================================== The user-font feature allows the cairo user to provide drawings for glyphs in a font. This is most useful in implementing fonts in non-standard formats, like SVG fonts and Flash fonts, but can also be used by games and other application to draw "funky" fonts. .. note:: UserFontFace support has not (yet) been added to pycairo. If you need this feature in pycairo register your interest by sending a message to the cairo mailing list, or by opening a pycairo bug report. class ScaledFont() ================== A *ScaledFont* is a font scaled to a particular size and device resolution. A *ScaledFont* is most useful for low-level font usage where a library or application wants to cache a reference to a scaled font to speed up the computation of metrics. There are various types of scaled fonts, depending on the font backend they use. .. class:: ScaledFont(font_face, font_matrix, ctm, options) :param font_face: a :class:`FontFace` instance :param font_matrix: font space to user space transformation :class:`Matrix` for the font. In the simplest case of a N point font, this matrix is just a scale by N, but it can also be used to shear the font or stretch it unequally along the two axes. See :meth:`Context.set_font_matrix`. :param ctm: user to device transformation :class:`Matrix` with which the font will be used. :param options: a :class:`FontOptions` instance to use when getting metrics for the font and rendering with it. Creates a *ScaledFont* object from a *FontFace* and matrices that describe the size of the font and the environment in which it will be used. .. method:: extents() :returns: (ascent, descent, height, max_x_advance, max_y_advance), a tuple of float values. Gets the metrics for a *ScaledFont*. .. method:: get_ctm() :returns: the CTM :rtype: cairo.Matrix Returns the CTM with which scaled_font was created into ctm. Note that the translation offsets (x0, y0) of the CTM are ignored by :func:`ScaledFont`. So, the matrix this function returns always has 0, 0 as x0, y0. .. versionadded:: 1.12.0 .. method:: get_font_face() :returns: the :class:`FontFace` that this *ScaledFont* was created for. .. versionadded:: 1.2 .. method:: get_font_matrix() :returns: the matrix :rtype: cairo.Matrix Returns the font matrix with which scaled_font was created. .. versionadded:: 1.12.0 .. method:: get_font_options() :returns: font options :rtype: cairo.FontOptions Returns the font options with which scaled_font was created. .. versionadded:: 1.12.0 .. method:: get_scale_matrix() :returns: the scale :class:`Matrix` The scale matrix is product of the font matrix and the ctm associated with the scaled font, and hence is the matrix mapping from font space to device space. .. versionadded:: 1.8 .. method:: glyph_extents(glyphs) :param glyphs: glyphs, a sequence of :class:`Glyph` :rtype: TextExtents .. versionadded:: 1.15 Gets the extents for a list of glyphs. The extents describe a user-space rectangle that encloses the "inked" portion of the glyphs, (as they would be drawn by :meth:`Context.show_glyphs` if the cairo graphics state were set to the same font_face, font_matrix, ctm, and font_options as scaled_font ). Additionally, the x_advance and y_advance values indicate the amount by which the current point would be advanced by cairo_show_glyphs(). Note that whitespace glyphs do not contribute to the size of the rectangle (extents.width and extents.height). .. method:: text_extents(text) :param text: text :type text: text :rtype: TextExtents Gets the extents for a string of text. The extents describe a user-space rectangle that encloses the "inked" portion of the text drawn at the origin (0,0) (as it would be drawn by :meth:`Context.show_text` if the cairo graphics state were set to the same font_face, font_matrix, ctm, and font_options as *ScaledFont*). Additionally, the x_advance and y_advance values indicate the amount by which the current point would be advanced by :meth:`Context.show_text`. Note that whitespace characters do not directly contribute to the size of the rectangle (width and height). They do contribute indirectly by changing the position of non-whitespace characters. In particular, trailing whitespace characters are likely to not affect the size of the rectangle, though they will affect the x_advance and y_advance values. .. versionadded:: 1.2 .. method:: text_to_glyphs(x, y, utf8, [with_clusters=True]) :param float x: X position to place first glyph :param float y: Y position to place first glyph :param text utf8: a string of text :param bool with_clusters: If :obj:`False` only the glyph list will computed and returned :returns: a tuple of ([:class:`Glyph`], [:class:`TextCluster`], :class:`TextClusterFlags`) :rtype: tuple :raises Error: .. versionadded:: 1.15 Converts UTF-8 text to a list of glyphs, with cluster mapping, that can be used to render later. For details of how clusters, and cluster_flags map input UTF-8 text to the output glyphs see :meth:`Context.show_text_glyphs`. The output values can be readily passed to :meth:`Context.show_text_glyphs` :meth:`Context.show_glyphs`, or related functions, assuming that the exact same scaled font is used for the operation. class FontOptions() =================== An opaque structure holding all options that are used when rendering fonts. Individual features of a *FontOptions* can be set or accessed using functions named *FontOptions.set_* and *FontOptions.get_*, like :meth:`FontOptions.set_antialias` and :meth:`FontOptions.get_antialias`. New features may be added to a *FontOptions* in the future. For this reason, :meth:`FontOptions.copy()`, :meth:`FontOptions.equal()`, :meth:`FontOptions.merge()`, and :meth:`FontOptions.hash()` should be used to copy, check for equality, merge, or compute a hash value of FontOptions objects. .. class:: FontOptions() :returns: a newly allocated *FontOptions*. Allocates a new *FontOptions* object with all options initialized to default values. Implements ``__eq__`` and ``__ne__`` using :meth:`equal` since 1.12.0. .. method:: get_antialias() :returns: the antialias mode for the *FontOptions* object :rtype: cairo.Antialias .. method:: get_hint_metrics() :returns: the hint metrics mode for the *FontOptions* object :rtype: cairo.HintMetrics .. method:: get_hint_style() :returns: the hint style for the *FontOptions* object :rtype: cairo.HintStyle .. method:: get_subpixel_order() :returns: the subpixel order for the *FontOptions* object :rtype: cairo.SubpixelOrder .. method:: set_antialias(antialias) :param cairo.Antialias antialias: the antialias mode This specifies the type of antialiasing to do when rendering text. .. method:: set_hint_metrics(hint_metrics) :param cairo.HintMetrics hint_metrics: the hint metrics mode This controls whether metrics are quantized to integer values in device units. .. method:: set_hint_style(hint_style) :param cairo.HintStyle hint_style: the hint style This controls whether to fit font outlines to the pixel grid, and if so, whether to optimize for fidelity or contrast. .. method:: set_subpixel_order(subpixel_order) :param cairo.SubpixelOrder subpixel_order: the subpixel order The subpixel order specifies the order of color elements within each pixel on the display device when rendering with an antialiasing mode of :attr:`cairo.Antialias.SUBPIXEL`. .. method:: merge(other) :param FontOptions other: another :class:`FontOptions` 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 :attr:`Operator.OVER`. .. versionadded:: 1.12.0 .. method:: copy() :returns: a new :class:`FontOptions` Returns a new font options object copying the option values from original. .. versionadded:: 1.12.0 .. method:: hash() :returns: the hash value for the font options object :rtype: int Compute a hash for the font options object; this value will be useful when storing an object containing a :class:`FontOptions` in a hash table. .. versionadded:: 1.12.0 .. method:: equal(other) :param FontOptions other: another :class:`FontOptions` :returns: :obj:`True` if all fields of the two font options objects match. Note that this function will return :obj:`False` if either object is in error. :rtype: bool Compares two font options objects for equality. .. versionadded:: 1.12.0 pycairo-1.16.2/docs/reference/textcluster.rst000066400000000000000000000021041323762421700212610ustar00rootroot00000000000000.. _textcluster: ************ Text Cluster ************ .. currentmodule:: cairo class TextCluster(tuple) ======================== .. class:: TextCluster(num_bytes, num_glyphs) :param int num_bytes: the number of bytes of UTF-8 text covered by cluster :param int num_glyphs: the number of glyphs covered by cluster .. versionadded:: 1.15 The :class:`TextCluster` structure holds information about a single text cluster. A text cluster is a minimal mapping of some glyphs corresponding to some UTF-8 text. For a cluster to be valid, both ``num_bytes`` and ``num_glyphs`` should be non-negative, and at least one should be non-zero. Note that clusters with zero glyphs are not as well supported as normal clusters. For example, PDF rendering applications typically ignore those clusters when PDF text is being selected. See :meth:`Context.show_text_glyphs` for how clusters are used in advanced text operations. .. attribute:: num_bytes :class:`int` .. attribute:: num_glyphs :class:`int` pycairo-1.16.2/docs/reference/textextents.rst000066400000000000000000000041321323762421700212750ustar00rootroot00000000000000.. _textextents: *********** TextExtents *********** .. currentmodule:: cairo class TextExtents(tuple) ======================== .. class:: TextExtents(x_bearing, y_bearing, width, height, x_advance, y_advance) :param float x_bearing: the horizontal distance from the origin to the leftmost part of the glyphs as drawn. Positive if the glyphs lie entirely to the right of the origin. :param float y_bearing: the vertical distance from the origin to the topmost part of the glyphs as drawn. Positive only if the glyphs lie completely below the origin; will usually be negative. :param float width: width of the glyphs as drawn :param float height: height of the glyphs as drawn :param float x_advance: distance to advance in the X direction after drawing these glyphs :param float y_advance: distance to advance in the Y direction after drawing these glyphs. Will typically be zero except for vertical text layout as found in East-Asian languages. :rtype: TextExtents .. versionadded:: 1.15 In prior versions a (float, float, float, float, float, float) tuple was used instead of :class:`TextExtents`. The :class:`TextExtents` class stores the extents of a single glyph or a string of glyphs in user-space coordinates. Because text extents are in user-space coordinates, they are mostly, but not entirely, independent of the current transformation matrix. If you call ``context.scale(2.0, 2.0)``, text will be drawn twice as big, but the reported text extents will not be doubled. They will change slightly due to hinting (so you can't assume that metrics are independent of the transformation matrix), but otherwise will remain unchanged. .. attribute:: x_bearing :class:`float` .. attribute:: y_bearing :class:`float` .. attribute:: width :class:`float` .. attribute:: height :class:`float` .. attribute:: x_advance :class:`float` .. attribute:: y_advance :class:`float` pycairo-1.16.2/docs/resources.rst000066400000000000000000000055661323762421700167660ustar00rootroot00000000000000========= Resources ========= This section is for listing various useful pycairo resources, feel free to contribute ! Windows Binary Packages (unofficial) Precompiled binaries for the Microsoft Windows platform can be obtained from the following sources: `Precompiled PyCairo for Python 2.x from Uri Shaked `_ Some Libraries/Modules Using pycairo * `Cairo Plot `_: a module to plot graphics * `hamster graphics library `_ - a sprite styled abstraction library for drawing and animation in PyGTK * `matplotlib `_: a python 2D plotting library which produces publication quality figures in a variety of hardcopy formats and interactive environments across platforms. * `PyCha `_: PYthon CHArts - a Python package for drawing charts * `PyGoocanvas `_: python bindings for GooCanvas which is a canvas widget for GTK+ * `PyGTK `_: GTK+ for Python. * rsvg: part of `gnome-python-desktop `_, it provides Python bindings for librsvg Some Applications Using pycairo * `A Shogiban for Gnushogi `_. * `gPodder `_: a podcatcher. * `Miro `_: Internet TV, HD video player. * pycairo projects at `Google Code `_. * `PyChess `_. * `Pyroute - OpenStreetMap `_. * `Shoebot `_ - a pure Python graphics robot. Tutorials * `Cairo Tutorial for Python (and other) Programmers `_: Generic introduction to cairo concepts oriented to python. * `Cairo Tutorial for PyGTK Programmers `_: Tutorial about how to use cairo for drawing in `PyGTK `_. * Writing a widget using cairo and PyGTK 2.8 `Part 1 `_, `Part 2 `_: A translation of the GNOME Journal tutorial by Davyd Madeley from C to Python. Demos * `A Basic Cairo-clock in Python `_ using XShape. * `A simple clock implemented in pygtk and cairo `_. Recipies See the main `Cairo Cookbook `_. pycairo-1.16.2/docs/tutorial.rst000066400000000000000000000102731323762421700166060ustar00rootroot00000000000000.. title:: Tutorial ==================================== An Introduction to Cairo with Python ==================================== Cairo is a library for drawing vector graphics. Vector graphics are interesting because they don't lose clarity when resized or transformed. Pycairo is a set of bindings for cairo. It provides the cairo module which can be used to call cairo commands from Python. .. toctree:: :titlesonly: integration examples Understanding How to use Cairo ------------------------------ The best way to understand how to use cairo is to imagine that you are an artist using a paintbrush to draw out a shape on canvas. To begin, you can choose a few characteristics of your brush. You can choose the thickness of your brush and the colour you want to paint with. You can also choose the shape of your brush tip - You can choose either a circle or a square. Once you have chosen your brush, you are ready to start painting. You have to be quite precise when describing what you want to appear. Firstly, decide where you want to place your brush on the canvas. You do this by supplying an x & y coordinate. Next you define how you want your brush stroke to look - an arc, a straight line etc. Finally you define the point where you want your stoke to end, again by supplying an x & y coordinate. Triangles and squares are very easy to do! More complex graphics are generated using variations of the above theme with a few additions such as Fills (colouring in), transformations (zooming in, moving) etc. Using the Python interface to cairo Nearly all the work revolves around using the :class:`cairo.Context` (or ``cairo_t`` in the cairo C API). This is the object that you send your drawing commands to. There are a few options available to initialize this object in different ways. Initializing the cairo.Context Object ------------------------------------- * One Very Important thing to realize is there is a difference between the coordinates you are describing your graphics on and the coordinates you will be displaying your graphic on. (Ex - When giving a presentation you draw on your transparent acetate before hand, and then display it on your overhead projector - cairo calls the transparent acetate the user space coordinates and the projected image the device space coordinates) On initializing the cairo context object, we tell it how to transform our description to how it should be displayed. To do this we supply a transformation matrix. Modifying the transformation matrix can lead to some very interesting results. * One of cairo's most powerful features is that it can output graphics in many different formats (it can use multiple back ends). For printing, we can have cairo translate our graphics into Postscript to be sent off to the printer. For on screen display, we can have cairo translate our graphics into something glitz can understand for hardware accelerated rendering! It has many more important and useful target back ends. On initializing the :class:`cairo.Context`, we set its target back end, supplying a few details (such as colour depth and size), as in the example below. Example ------- .. code:: python #!/usr/bin/env python import math import cairo WIDTH, HEIGHT = 256, 256 surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, WIDTH, HEIGHT) ctx = cairo.Context (surface) ctx.scale (WIDTH, HEIGHT) # Normalizing the canvas pat = cairo.LinearGradient (0.0, 0.0, 0.0, 1.0) pat.add_color_stop_rgba (1, 0.7, 0, 0, 0.5) # First stop, 50% opacity pat.add_color_stop_rgba (0, 0.9, 0.7, 0.2, 1) # Last stop, 100% opacity ctx.rectangle (0, 0, 1, 1) # Rectangle(x0, y0, x1, y1) ctx.set_source (pat) ctx.fill () ctx.translate (0.1, 0.1) # Changing the current transformation matrix ctx.move_to (0, 0) # Arc(cx, cy, radius, start_angle, stop_angle) ctx.arc (0.2, 0.1, 0.1, -math.pi/2, 0) ctx.line_to (0.5, 0.1) # Line to (x,y) # Curve(x1, y1, x2, y2, x3, y3) ctx.curve_to (0.5, 0.2, 0.5, 0.4, 0.2, 0.8) ctx.close_path () ctx.set_source_rgb (0.3, 0.2, 0.5) # Solid color ctx.set_line_width (0.02) ctx.stroke () surface.write_to_png ("example.png") # Output to PNG pycairo-1.16.2/examples/000077500000000000000000000000001323762421700150745ustar00rootroot00000000000000pycairo-1.16.2/examples/cairo_snippets/000077500000000000000000000000001323762421700201165ustar00rootroot00000000000000pycairo-1.16.2/examples/cairo_snippets/snippets/000077500000000000000000000000001323762421700217635ustar00rootroot00000000000000pycairo-1.16.2/examples/cairo_snippets/snippets/__init__.py000066400000000000000000000015751323762421700241040ustar00rootroot00000000000000import os import inspect import importlib class Snippet(object): name = "" """name of the snippet""" code = "" """Snippet code as text""" def draw_func(cr, width, height): """Snippet entry point""" raise NotImplementedError def get_snippets(): """Returns a name:snippet dict""" # list of snippet files snip_list = [x[:-3] for x in os.listdir(os.path.dirname(__file__)) if not x.startswith('_') and x.endswith('.py')] snip_list.sort() snippets = {} for name in snip_list: s = Snippet() s.name = name mod = importlib.import_module("." + name, __package__) s.draw_func = getattr(mod, "draw") code = inspect.getsource(mod) if isinstance(code, bytes): code = code.decode("utf-8") s.code = code snippets[s.name] = s return snippets pycairo-1.16.2/examples/cairo_snippets/snippets/arc.py000066400000000000000000000011411323762421700230770ustar00rootroot00000000000000from math import pi def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) xc = 0.5 yc = 0.5 radius = 0.4 angle1 = 45.0 * (pi / 180.0) # angles are specified angle2 = 180.0 * (pi / 180.0) # in radians cr.arc(xc, yc, radius, angle1, angle2) cr.stroke() # draw helping lines cr.set_source_rgba(1, 0.2, 0.2, 0.6) cr.arc(xc, yc, 0.05, 0, 2 * pi) cr.fill() cr.set_line_width(0.03) cr.arc(xc, yc, radius, angle1, angle1) cr.line_to(xc, yc) cr.arc(xc, yc, radius, angle2, angle2) cr.line_to(xc, yc) cr.stroke() pycairo-1.16.2/examples/cairo_snippets/snippets/arc_negative.py000066400000000000000000000011521323762421700247630ustar00rootroot00000000000000from math import pi def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) xc = 0.5 yc = 0.5 radius = 0.4 angle1 = 45.0 * (pi / 180.0) # angles are specified angle2 = 180.0 * (pi / 180.0) # in radians cr.arc_negative(xc, yc, radius, angle1, angle2) cr.stroke() # draw helping lines cr.set_source_rgba(1, 0.2, 0.2, 0.6) cr.arc(xc, yc, 0.05, 0, 2 * pi) cr.fill() cr.set_line_width(0.03) cr.arc(xc, yc, radius, angle1, angle1) cr.line_to(xc, yc) cr.arc(xc, yc, radius, angle2, angle2) cr.line_to(xc, yc) cr.stroke() pycairo-1.16.2/examples/cairo_snippets/snippets/clip.py000066400000000000000000000005161323762421700232660ustar00rootroot00000000000000from math import pi def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) cr.arc(0.5, 0.5, 0.3, 0, 2 * pi) cr.clip() cr.rectangle(0, 0, 1, 1) cr.fill() cr.set_source_rgb(0, 1, 0) cr.move_to(0, 0) cr.line_to(1, 1) cr.move_to(1, 0) cr.line_to(0, 1) cr.stroke() pycairo-1.16.2/examples/cairo_snippets/snippets/curve_rectangle.py000066400000000000000000000036611323762421700255130ustar00rootroot00000000000000 def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) # a custom shape, that could be wrapped in a function x0 = 0.1 # parameters like cairo_rectangle y0 = 0.1 rect_width = 0.8 rect_height = 0.8 radius = 0.4 # and an approximate curvature radius x1 = x0 + rect_width y1 = y0 + rect_height if rect_width / 2 < radius: if rect_height / 2 < radius: cr.move_to(x0, (y0 + y1) / 2) cr.curve_to(x0, y0, x0, y0, (x0 + x1) / 2, y0) cr.curve_to(x1, y0, x1, y0, x1, (y0 + y1) / 2) cr.curve_to(x1, y1, x1, y1, (x1 + x0) / 2, y1) cr.curve_to(x0, y1, x0, y1, x0, (y0 + y1) / 2) else: cr.move_to(x0, y0 + radius) cr.curve_to(x0, y0, x0, y0, (x0 + x1) / 2, y0) cr.curve_to(x1, y0, x1, y0, x1, y0 + radius) cr.line_to(x1, y1 - radius) cr.curve_to(x1, y1, x1, y1, (x1 + x0) / 2, y1) cr.curve_to(x0, y1, x0, y1, x0, y1 - radius) else: if rect_height / 2 < radius: cr.move_to(x0, (y0 + y1) / 2) cr.curve_to(x0, y0, x0, y0, x0 + radius, y0) cr.line_to(x1 - radius, y0) cr.curve_to(x1, y0, x1, y0, x1, (y0 + y1) / 2) cr.curve_to(x1, y1, x1, y1, x1 - radius, y1) cr.line_to(x0 + radius, y1) cr.curve_to(x0, y1, x0, y1, x0, (y0 + y1) / 2) else: cr.move_to(x0, y0 + radius) cr.curve_to(x0, y0, x0, y0, x0 + radius, y0) cr.line_to(x1 - radius, y0) cr.curve_to(x1, y0, x1, y0, x1, y0 + radius) cr.line_to(x1, y1 - radius) cr.curve_to(x1, y1, x1, y1, x1 - radius, y1) cr.line_to(x0 + radius, y1) cr.curve_to(x0, y1, x0, y1, x0, y1 - radius) cr.close_path() cr.set_source_rgb(0.5, 0.5, 1) cr.fill_preserve() cr.set_source_rgba(0.5, 0, 0, 0.5) cr.stroke() pycairo-1.16.2/examples/cairo_snippets/snippets/curve_to.py000066400000000000000000000006541323762421700241700ustar00rootroot00000000000000 def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) x, y = 0.1, 0.5 x1, y1 = 0.4, 0.9 x2, y2 = 0.6, 0.1 x3, y3 = 0.9, 0.5 cr.move_to(x, y) cr.curve_to(x1, y1, x2, y2, x3, y3) cr.stroke() cr.set_source_rgba(1, 0.2, 0.2, 0.6) cr.set_line_width(0.03) cr.move_to(x, y) cr.line_to(x1, y1) cr.move_to(x2, y2) cr.line_to(x3, y3) cr.stroke() pycairo-1.16.2/examples/cairo_snippets/snippets/ellipse.py000066400000000000000000000016261323762421700237770ustar00rootroot00000000000000from math import pi def path_ellipse(cr, x, y, width, height, angle=0): """ x - center x y - center y width - width of ellipse (in x direction when angle=0) height - height of ellipse (in y direction when angle=0) angle - angle in radians to rotate, clockwise """ cr.save() cr.translate(x, y) cr.rotate(angle) cr.scale(width / 2.0, height / 2.0) cr.arc(0.0, 0.0, 1.0, 0.0, 2.0 * pi) cr.restore() def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) path_ellipse(cr, 0.5, 0.5, 1.0, 0.3, pi / 4.0) # fill cr.set_source_rgba(1, 0, 0, 1) cr.fill_preserve() # stroke # reset identity matrix so line_width is a constant # width in device-space, not user-space cr.save() cr.identity_matrix() cr.set_source_rgba(0, 0, 0, 1) cr.set_line_width(3) cr.stroke() cr.restore() pycairo-1.16.2/examples/cairo_snippets/snippets/fill_and_stroke.py000066400000000000000000000005171323762421700254770ustar00rootroot00000000000000 def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) cr.move_to(0.5, 0.1) cr.line_to(0.9, 0.9) cr.rel_line_to(-0.4, 0.0) cr.curve_to(0.2, 0.9, 0.2, 0.5, 0.5, 0.5) cr.close_path() cr.set_source_rgb(0, 0, 1) cr.fill_preserve() cr.set_source_rgb(0, 0, 0) cr.stroke() pycairo-1.16.2/examples/cairo_snippets/snippets/fill_and_stroke2.py000066400000000000000000000007301323762421700255560ustar00rootroot00000000000000 def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) cr.move_to(0.5, 0.1) cr.line_to(0.9, 0.9) cr.rel_line_to(-0.4, 0.0) cr.curve_to(0.2, 0.9, 0.2, 0.5, 0.5, 0.5) cr.close_path() cr.move_to(0.25, 0.1) cr.rel_line_to(0.2, 0.2) cr.rel_line_to(-0.2, 0.2) cr.rel_line_to(-0.2, -0.2) cr.close_path() cr.set_source_rgb(0, 0, 1) cr.fill_preserve() cr.set_source_rgb(0, 0, 0) cr.stroke() pycairo-1.16.2/examples/cairo_snippets/snippets/glyph_path.py000066400000000000000000000012031323762421700244700ustar00rootroot00000000000000import cairo def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) cr.select_font_face("Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) # draw 0.16 glyphs in 0.20 squares, at (0.02, 0.04) from left corner cr.set_font_size(0.16) glyphs = [] index = 20 for y in range(5): for x in range(5): glyphs.append((index, x / 5.0 + 0.02, y / 5.0 + 0.16)) index += 1 cr.glyph_path(glyphs) cr.set_source_rgb(0.5, 0.5, 1.0) cr.fill_preserve() cr.set_source_rgb(0, 0, 0) cr.set_line_width(0.005) cr.stroke() pycairo-1.16.2/examples/cairo_snippets/snippets/gradient.py000066400000000000000000000011021323762421700241240ustar00rootroot00000000000000from math import pi import cairo def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) pat = cairo.LinearGradient(0.0, 0.0, 0.0, 1.0) pat.add_color_stop_rgba(1, 0, 0, 0, 1) pat.add_color_stop_rgba(0, 1, 1, 1, 1) cr.rectangle(0, 0, 1, 1) cr.set_source(pat) cr.fill() pat = cairo.RadialGradient(0.45, 0.4, 0.1, 0.4, 0.4, 0.5) pat.add_color_stop_rgba(0, 1, 1, 1, 1) pat.add_color_stop_rgba(1, 0, 0, 0, 1) cr.set_source(pat) cr.arc(0.5, 0.5, 0.3, 0, 2 * pi) cr.fill() pycairo-1.16.2/examples/cairo_snippets/snippets/gradient_mask.py000066400000000000000000000006721323762421700251520ustar00rootroot00000000000000import cairo def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) pattern = cairo.LinearGradient(0, 0, 1, 1) pattern.add_color_stop_rgb(0, 0, 0.3, 0.8) pattern.add_color_stop_rgb(1, 0, 0.8, 0.3) mask = cairo.RadialGradient(0.5, 0.5, 0.25, 0.5, 0.5, 0.5) mask.add_color_stop_rgba(0, 0, 0, 0, 1) mask.add_color_stop_rgba(0.5, 0, 0, 0, 0) cr.set_source(pattern) cr.mask(mask) pycairo-1.16.2/examples/cairo_snippets/snippets/group.py000066400000000000000000000007221323762421700234720ustar00rootroot00000000000000import cairo def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) cr.rectangle(0.1, 0.1, 0.6, 0.6) cr.set_line_width(0.03) cr.set_source_rgb(0.8, 0.8, 0.8) cr.fill() cr.push_group() cr.rectangle(0.3, 0.3, 0.6, 0.6) cr.set_source(cairo.SolidPattern(1, 0, 0)) cr.fill_preserve() cr.set_source(cairo.SolidPattern(0, 0, 0)) cr.stroke() cr.pop_group_to_source() cr.paint_with_alpha(0.5) pycairo-1.16.2/examples/cairo_snippets/snippets/hering.py000066400000000000000000000013711323762421700236130ustar00rootroot00000000000000#!/usr/bin/env python """cairo/cairo-demo/png/hering.c translated into Python""" import math def draw(ctx, width, height): LINES = 32 MAX_THETA = .80 * math.pi * 2 THETA_INC = 2.0 * MAX_THETA / (LINES - 1) ctx.set_source_rgb(0, 0, 0) ctx.set_line_width(2.0) ctx.save() ctx.translate(width / 2, height / 2) ctx.rotate(MAX_THETA) for i in range(LINES): ctx.move_to(-2 * width, 0) ctx.line_to(2 * width, 0) ctx.stroke() ctx.rotate(- THETA_INC) ctx.restore() ctx.set_line_width(6) ctx.set_source_rgb(1, 0, 0) ctx.move_to(width / 4.0, 0) ctx.rel_line_to(0, height) ctx.stroke() ctx.move_to(3 * width / 4.0, 0) ctx.rel_line_to(0, height) ctx.stroke() pycairo-1.16.2/examples/cairo_snippets/snippets/path.py000066400000000000000000000003461323762421700232740ustar00rootroot00000000000000 def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) cr.move_to(0.5, 0.1) cr.line_to(0.9, 0.9) cr.rel_line_to(-0.4, 0.0) cr.curve_to(0.2, 0.9, 0.2, 0.5, 0.5, 0.5) cr.stroke() pycairo-1.16.2/examples/cairo_snippets/snippets/set_line_cap.py000066400000000000000000000013271323762421700247650ustar00rootroot00000000000000import cairo def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) cr.set_line_width(0.12) cr.set_line_cap(cairo.LINE_CAP_BUTT) # default cr.move_to(0.25, 0.2) cr.line_to(0.25, 0.8) cr.stroke() cr.set_line_cap(cairo.LINE_CAP_ROUND) cr.move_to(0.5, 0.2) cr.line_to(0.5, 0.8) cr.stroke() cr.set_line_cap(cairo.LINE_CAP_SQUARE) cr.move_to(0.75, 0.2) cr.line_to(0.75, 0.8) cr.stroke() # draw helping lines cr.set_source_rgb(1, 0.2, 0.2) cr.set_line_width(0.01) cr.move_to(0.25, 0.2) cr.line_to(0.25, 0.8) cr.move_to(0.5, 0.2) cr.line_to(0.5, 0.8) cr.move_to(0.75, 0.2) cr.line_to(0.75, 0.8) cr.stroke() pycairo-1.16.2/examples/cairo_snippets/snippets/set_line_join.py000066400000000000000000000011011323762421700251470ustar00rootroot00000000000000import cairo def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) cr.set_line_width(0.16) cr.move_to(0.3, 0.33) cr.rel_line_to(0.2, -0.2) cr.rel_line_to(0.2, 0.2) cr.set_line_join(cairo.LINE_JOIN_MITER) # default cr.stroke() cr.move_to(0.3, 0.63) cr.rel_line_to(0.2, -0.2) cr.rel_line_to(0.2, 0.2) cr.set_line_join(cairo.LINE_JOIN_BEVEL) cr.stroke() cr.move_to(0.3, 0.93) cr.rel_line_to(0.2, -0.2) cr.rel_line_to(0.2, 0.2) cr.set_line_join(cairo.LINE_JOIN_ROUND) cr.stroke() pycairo-1.16.2/examples/cairo_snippets/snippets/show_glyphs.py000066400000000000000000000007761323762421700247150ustar00rootroot00000000000000import cairo def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) cr.select_font_face("Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) # draw 0.08 glyphs in 0.10 squares, at(0.01, 0.02) from left corner cr.set_font_size(0.08) glyphs = [] index = 0 for y in range(10): for x in range(10): glyphs.append((index, x / 10.0 + 0.01, y / 10.0 + 0.08)) index += 1 cr.show_glyphs(glyphs) pycairo-1.16.2/examples/cairo_snippets/snippets/spiral.py000066400000000000000000000007751323762421700236400ustar00rootroot00000000000000#!/usr/bin/env python """cairo/cairo-demo/png/spiral.c translated into Python""" def draw(ctx, width, height): wd = .02 * width hd = .02 * height width -= 2 height -= 2 ctx.move_to(width + 1, 1 - hd) for i in range(9): ctx.rel_line_to(0, height - hd * (2 * i - 1)) ctx.rel_line_to(-(width - wd * (2 * i)), 0) ctx.rel_line_to(0, -(height - hd * (2 * i))) ctx.rel_line_to(width - wd * (2 * i + 1), 0) ctx.set_source_rgb(0, 0, 1) ctx.stroke() pycairo-1.16.2/examples/cairo_snippets/snippets/text.py000066400000000000000000000012161323762421700233210ustar00rootroot00000000000000from math import pi import cairo def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) cr.select_font_face("Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) cr.set_font_size(0.35) cr.move_to(0.04, 0.53) cr.show_text("Hello") cr.move_to(0.27, 0.65) cr.text_path("void") cr.set_source_rgb(0.5, 0.5, 1) cr.fill_preserve() cr.set_source_rgb(0, 0, 0) cr.set_line_width(0.01) cr.stroke() # draw helping lines cr.set_source_rgba(1, 0.2, 0.2, 0.6) cr.arc(0.04, 0.53, 0.02, 0, 2 * pi) cr.arc(0.27, 0.65, 0.02, 0, 2 * pi) cr.fill() pycairo-1.16.2/examples/cairo_snippets/snippets/text_align_center.py000066400000000000000000000013501323762421700260320ustar00rootroot00000000000000from math import pi import cairo def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) utf8 = "cairo" cr.select_font_face("Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) cr.set_font_size(0.2) x_bearing, y_bearing, width, height, x_advance, y_advance = \ cr.text_extents(utf8) x = 0.5 - (width / 2 + x_bearing) y = 0.5 - (height / 2 + y_bearing) cr.move_to(x, y) cr.show_text(utf8) # draw helping lines cr.set_source_rgba(1, 0.2, 0.2, 0.6) cr.arc(x, y, 0.05, 0, 2 * pi) cr.fill() cr.move_to(0.5, 0) cr.rel_line_to(0, 1) cr.move_to(0, 0.5) cr.rel_line_to(1, 0) cr.stroke() pycairo-1.16.2/examples/cairo_snippets/snippets/text_extents.py000066400000000000000000000013171323762421700250750ustar00rootroot00000000000000from math import pi import cairo def draw(cr, width, height): cr.scale(width, height) cr.set_line_width(0.04) utf8 = "cairo" cr.select_font_face("Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) cr.set_font_size(0.4) x_bearing, y_bearing, width, height, x_advance, y_advance = \ cr.text_extents(utf8) x = 0.1 y = 0.6 cr.move_to(x, y) cr.show_text(utf8) # draw helping lines cr.set_source_rgba(1, 0.2, 0.2, 0.6) cr.arc(x, y, 0.05, 0, 2 * pi) cr.fill() cr.move_to(x, y) cr.rel_line_to(0, -height) cr.rel_line_to(width, 0) cr.rel_line_to(x_bearing, -y_bearing) cr.stroke() pycairo-1.16.2/examples/cairo_snippets/snippets/warpedtext.py000066400000000000000000000041371323762421700245310ustar00rootroot00000000000000#!/usr/bin/env python import cairo import math all_width = all_height = text_width = 0 def warpPath(ctx, function): first = True for type, points in ctx.copy_path(): if type == cairo.PATH_MOVE_TO: if first: ctx.new_path() first = False x, y = function(*points) ctx.move_to(x, y) elif type == cairo.PATH_LINE_TO: x, y = function(*points) ctx.line_to(x, y) elif type == cairo.PATH_CURVE_TO: x1, y1, x2, y2, x3, y3 = points x1, y1 = function(x1, y1) x2, y2 = function(x2, y2) x3, y3 = function(x3, y3) ctx.curve_to(x1, y1, x2, y2, x3, y3) elif type == cairo.PATH_CLOSE_PATH: ctx.close_path() def spiral(x, y): theta0 = -math.pi * 3 / 4 theta = x / all_width * math.pi * 2 + theta0 radius = y + 200 - x / 7 xnew = radius * math.cos(theta) ynew = radius * math.sin(-theta) return xnew + all_width / 2, ynew + all_height / 2 def curl(x, y): xn = x - text_width / 2 xnew = xn ynew = y + xn ** 3 / ((text_width / 2) ** 3) * 70 return xnew + all_width / 2, ynew + all_height * 2 / 5 def draw(ctx, width, height): global text_width, all_width, all_height all_width, all_height = width, height solidpattern = ctx.get_source() # background pat = cairo.LinearGradient(0.0, 0.0, 0, height) pat.add_color_stop_rgba(1, 0, 0, 0, 1) pat.add_color_stop_rgba(0, 1, 1, 1, 1) ctx.rectangle(0, 0, width, height) ctx.set_source(pat) ctx.fill() # foreground ctx.set_source(solidpattern) ctx.set_source_rgb(1, 1, 1) ctx.select_font_face("Sans") ctx.set_font_size(80) # spiral text ctx.new_path() ctx.move_to(0, 0) ctx.text_path("pycairo - " + "spam " * 5) warpPath(ctx, spiral) ctx.fill() # curly text ctx.new_path() ctx.move_to(0, 0) ctx.set_source_rgb(0.3, 0.3, 0.3) text = "I am curly :)" ctx.text_path(text) text_width = ctx.text_extents(text)[2] warpPath(ctx, curl) ctx.fill() pycairo-1.16.2/examples/cairo_snippets/snippets_gtk.py000066400000000000000000000065621323762421700232130ustar00rootroot00000000000000#!/usr/bin/env python import gi gi.require_version("Gtk", "3.0") gi.require_foreign("cairo") from gi.repository import Gtk, Pango from snippets import get_snippets class Window(Gtk.Window): """Composite widget""" WIDTH, HEIGHT = 400, 400 def __init__(self, title=None): super(Window, self).__init__() self.set_default_size(self.WIDTH, self.HEIGHT) self.da = Gtk.DrawingArea() self.da.connect('draw', self.da_draw_event) def put_in_frame(widget): frame = Gtk.Frame(label=None) frame.set_property('shadow_type', Gtk.ShadowType.IN) frame.add(widget) return frame self.current_snippet = None vpaned = Gtk.VPaned() self.add(vpaned) sv = self.create_text_view() vpaned.pack1(put_in_frame(sv), True, True) sv.set_size_request(self.WIDTH, int(self.HEIGHT / 2)) hpaned = Gtk.HPaned() vpaned.pack2(hpaned, True, False) sl = self.create_snippet_list() hpaned.pack1(put_in_frame(sl), True, True) hpaned.pack2(put_in_frame(self.da), True, True) self.da.set_size_request(int(self.WIDTH / 2), int(self.HEIGHT / 2)) # set focus to snippet list sl.get_child().grab_focus() def da_draw_event(self, da, cr): if self.current_snippet is None: return False alloc = da.get_allocation() self.current_snippet.draw_func(cr, alloc.width, alloc.height) return True def create_text_view(self): sw = Gtk.ScrolledWindow() sw.set_property('shadow-type', Gtk.ShadowType.IN) sw.set_policy(hscrollbar_policy=Gtk.PolicyType.AUTOMATIC, vscrollbar_policy=Gtk.PolicyType.AUTOMATIC) text_view = Gtk.TextView() sw.add(text_view) # set a fixed width font, so any tabs line up text_view.override_font(Pango.FontDescription.from_string("Fixed")) self.text_buffer = text_view.get_buffer() return sw def cb_selection_changed(self, tselection, data=None): model, iter = tselection.get_selected() if iter: self.current_snippet = model[iter][1] self.text_buffer.set_text(self.current_snippet.code) self.da.queue_draw() def create_snippet_list(self): sw = Gtk.ScrolledWindow() sw.set_property('shadow-type', Gtk.ShadowType.IN) sw.set_policy(hscrollbar_policy=Gtk.PolicyType.NEVER, vscrollbar_policy=Gtk.PolicyType.AUTOMATIC) snippets = get_snippets() model = Gtk.ListStore(str, object) for name, s in snippets.items(): model.append(row=(name, s)) tree_view = Gtk.TreeView(model) sw.add(tree_view) tree_view.set_property('headers-visible', False) tree_view.set_property('search-column', 0) tree_view.set_property('rules-hint', False) tselection = tree_view.get_selection() tselection.connect("changed", self.cb_selection_changed) tselection.set_mode(Gtk.SelectionMode.BROWSE) cr = Gtk.CellRendererText() tvc = Gtk.TreeViewColumn(None, cr, text=0) tree_view.append_column(tvc) tselection.select_path(0,) # select first item return sw if __name__ == '__main__': app = Window() app.connect('destroy', Gtk.main_quit) app.show_all() Gtk.main() pycairo-1.16.2/examples/cairo_snippets/snippets_pdf.py000066400000000000000000000025441323762421700231730ustar00rootroot00000000000000#!/usr/bin/env python """Create a PDF file for each example""" from __future__ import print_function import os import sys import cairo from snippets import get_snippets def do_snippet(snippet): if verbose_mode: print('processing %s' % snippet.name) width_in_inches, height_in_inches = 2, 2 width_in_points, height_in_points = \ width_in_inches * 72, height_in_inches * 72 width, height = width_in_points, height_in_points try: os.makedirs(os.path.join("_build", "pdf")) except EnvironmentError: pass filename = os.path.join("_build", "pdf", "%s.pdf" % snippet.name) surface = cairo.PDFSurface(filename, width_in_points, height_in_points) cr = cairo.Context(surface) cr.save() snippet.draw_func(cr, width, height) cr.restore() cr.show_page() surface.finish() if __name__ == '__main__': if not cairo.HAS_PDF_SURFACE: raise SystemExit('cairo was not compiled with PDF support') verbose_mode = True if len(sys.argv) > 1 and sys.argv[1] == '-s': verbose_mode = False del sys.argv[1] snippets = get_snippets() if len(sys.argv) > 1: # do specified snippets selected = [snippets[n] for n in sys.argv[1:]] else: # do all snippets selected = snippets.values() for s in selected: do_snippet(s) pycairo-1.16.2/examples/cairo_snippets/snippets_png.py000066400000000000000000000023621323762421700232040ustar00rootroot00000000000000#!/usr/bin/env python """Create a PNG file for each example""" from __future__ import print_function import os import sys import cairo from snippets import get_snippets def do_snippet(snippet): if verbose_mode: print('processing %s' % snippet.name) width, height = 256, 256 surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) cr = cairo.Context(surface) cr.save() snippet.draw_func(cr, width, height) cr.restore() try: os.makedirs(os.path.join("_build", "png")) except EnvironmentError: pass filename = os.path.join("_build", "png", "%s.png" % snippet.name) surface.write_to_png(filename) if __name__ == '__main__': if not(cairo.HAS_IMAGE_SURFACE and cairo.HAS_PNG_FUNCTIONS): raise SystemExit( 'cairo was not compiled with ImageSurface and PNG support') verbose_mode = True if len(sys.argv) > 1 and sys.argv[1] == '-s': verbose_mode = False del sys.argv[1] snippets = get_snippets() if len(sys.argv) > 1: # do specified snippets selected = [snippets[n] for n in sys.argv[1:]] else: # do all snippets selected = snippets.values() for s in selected: do_snippet(s) pycairo-1.16.2/examples/cairo_snippets/snippets_ps.py000066400000000000000000000025341323762421700230430ustar00rootroot00000000000000#!/usr/bin/env python """Create a PS file for each example""" from __future__ import print_function import os import sys import cairo from snippets import get_snippets def do_snippet(snippet): if verbose_mode: print('processing %s' % snippet.name) width_in_inches, height_in_inches = 2, 2 width_in_points, height_in_points = \ width_in_inches * 72, height_in_inches * 72 width, height = width_in_points, height_in_points try: os.makedirs(os.path.join("_build", "ps")) except EnvironmentError: pass filename = os.path.join("_build", "ps", "%s.ps" % snippet.name) surface = cairo.PSSurface(filename, width_in_points, height_in_points) cr = cairo.Context(surface) cr.save() snippet.draw_func(cr, width, height) cr.restore() cr.show_page() surface.finish() if __name__ == '__main__': if not cairo.HAS_PS_SURFACE: raise SystemExit('cairo was not compiled with PS support') verbose_mode = True if len(sys.argv) > 1 and sys.argv[1] == '-s': verbose_mode = False del sys.argv[1] snippets = get_snippets() if len(sys.argv) > 1: # do specified snippets selected = [snippets[n] for n in sys.argv[1:]] else: # do all snippets selected = snippets.values() for s in selected: do_snippet(s) pycairo-1.16.2/examples/cairo_snippets/snippets_svg.py000066400000000000000000000025431323762421700232200ustar00rootroot00000000000000#!/usr/bin/env python """Create a SVG file for each example""" from __future__ import print_function import os import sys import cairo from snippets import get_snippets def do_snippet(snippet): if verbose_mode: print('processing %s' % snippet.name) width_in_inches, height_in_inches = 2, 2 width_in_points, height_in_points = \ width_in_inches * 72, height_in_inches * 72 width, height = width_in_points, height_in_points try: os.makedirs(os.path.join("_build", "svg")) except EnvironmentError: pass filename = os.path.join("_build", "svg", "%s.svg" % snippet.name) surface = cairo.SVGSurface(filename, width_in_points, height_in_points) cr = cairo.Context(surface) cr.save() snippet.draw_func(cr, width, height) cr.restore() cr.show_page() surface.finish() if __name__ == '__main__': if not cairo.HAS_SVG_SURFACE: raise SystemExit('cairo was not compiled with SVG support') verbose_mode = True if len(sys.argv) > 1 and sys.argv[1] == '-s': verbose_mode = False del sys.argv[1] snippets = get_snippets() if len(sys.argv) > 1: # do specified snippets selected = [snippets[n] for n in sys.argv[1:]] else: # do all snippets selected = snippets.values() for s in selected: do_snippet(s) pycairo-1.16.2/examples/gtk/000077500000000000000000000000001323762421700156615ustar00rootroot00000000000000pycairo-1.16.2/examples/gtk/cairo-demo.py000066400000000000000000000050551323762421700202570ustar00rootroot00000000000000#!/usr/bin/env python """Based on cairo-demo/X11/cairo-demo.c""" import cairo import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk SIZE = 30 def triangle(ctx): ctx.move_to(SIZE, 0) ctx.rel_line_to(SIZE, 2 * SIZE) ctx.rel_line_to(-2 * SIZE, 0) ctx.close_path() def square(ctx): ctx.move_to(0, 0) ctx.rel_line_to(2 * SIZE, 0) ctx.rel_line_to(0, 2 * SIZE) ctx.rel_line_to(-2 * SIZE, 0) ctx.close_path() def bowtie(ctx): ctx.move_to(0, 0) ctx.rel_line_to(2 * SIZE, 2 * SIZE) ctx.rel_line_to(-2 * SIZE, 0) ctx.rel_line_to(2 * SIZE, -2 * SIZE) ctx.close_path() def inf(ctx): ctx.move_to(0, SIZE) ctx.rel_curve_to(0, SIZE, SIZE, SIZE, 2 * SIZE, 0) ctx.rel_curve_to(SIZE, -SIZE, 2 * SIZE, -SIZE, 2 * SIZE, 0) ctx.rel_curve_to(0, SIZE, -SIZE, SIZE, -2 * SIZE, 0) ctx.rel_curve_to(-SIZE, -SIZE, -2 * SIZE, -SIZE, -2 * SIZE, 0) ctx.close_path() def draw_shapes(ctx, x, y, fill): ctx.save() ctx.new_path() ctx.translate(x + SIZE, y + SIZE) bowtie(ctx) if fill: ctx.fill() else: ctx.stroke() ctx.new_path() ctx.translate(3 * SIZE, 0) square(ctx) if fill: ctx.fill() else: ctx.stroke() ctx.new_path() ctx.translate(3 * SIZE, 0) triangle(ctx) if fill: ctx.fill() else: ctx.stroke() ctx.new_path() ctx.translate(3 * SIZE, 0) inf(ctx) if fill: ctx.fill() else: ctx.stroke() ctx.restore() def fill_shapes(ctx, x, y): draw_shapes(ctx, x, y, True) def stroke_shapes(ctx, x, y): draw_shapes(ctx, x, y, False) def draw(da, ctx): ctx.set_source_rgb(0, 0, 0) ctx.set_line_width(SIZE / 4) ctx.set_tolerance(0.1) ctx.set_line_join(cairo.LINE_JOIN_ROUND) ctx.set_dash([SIZE / 4.0, SIZE / 4.0], 0) stroke_shapes(ctx, 0, 0) ctx.set_dash([], 0) stroke_shapes(ctx, 0, 3 * SIZE) ctx.set_line_join(cairo.LINE_JOIN_BEVEL) stroke_shapes(ctx, 0, 6 * SIZE) ctx.set_line_join(cairo.LINE_JOIN_MITER) stroke_shapes(ctx, 0, 9 * SIZE) fill_shapes(ctx, 0, 12 * SIZE) ctx.set_line_join(cairo.LINE_JOIN_BEVEL) fill_shapes(ctx, 0, 15 * SIZE) ctx.set_source_rgb(1, 0, 0) stroke_shapes(ctx, 0, 15 * SIZE) def main(): win = Gtk.Window() win.connect('destroy', Gtk.main_quit) win.set_default_size(450, 550) drawingarea = Gtk.DrawingArea() win.add(drawingarea) drawingarea.connect('draw', draw) win.show_all() Gtk.main() if __name__ == '__main__': main() pycairo-1.16.2/examples/gtk/cairo-knockout.py000066400000000000000000000067331323762421700211740ustar00rootroot00000000000000#!/usr/bin/env python """Based on gtk+/test/testcairo.c """ from __future__ import division import math import cairo import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk def oval_path(ctx, xc, yc, xr, yr): ctx.save() ctx.translate(xc, yc) ctx.scale(1.0, yr / xr) ctx.move_to(xr, 0.0) ctx.arc(0, 0, xr, 0, 2 * math.pi) ctx.close_path() ctx.restore() def fill_checks(ctx, x, y, width, height): CHECK_SIZE = 32 ctx.rectangle(x, y, width, height) ctx.set_source_rgb(0.4, 0.4, 0.4) ctx.fill() # Only works for CHECK_SIZE a power of 2 for j in range(x & -CHECK_SIZE, height, CHECK_SIZE): for i in range(y & -CHECK_SIZE, width, CHECK_SIZE): if((i / CHECK_SIZE + j / CHECK_SIZE) % 2 == 0): ctx.rectangle(i, j, CHECK_SIZE, CHECK_SIZE) ctx.set_source_rgb(0.7, 0.7, 0.7) ctx.fill() def draw_3circles(ctx, xc, yc, radius, alpha): subradius = radius * (2 / 3. - 0.1) ctx.set_source_rgba(1, 0, 0, alpha) oval_path(ctx, xc + radius / 3. * math.cos(math.pi * 0.5), yc - radius / 3. * math.sin(math.pi * 0.5), subradius, subradius) ctx.fill() ctx.set_source_rgba(0, 1, 0, alpha) oval_path(ctx, xc + radius / 3. * math.cos(math.pi * (0.5 + 2 / .3)), yc - radius / 3. * math.sin(math.pi * (0.5 + 2 / .3)), subradius, subradius) ctx.fill() ctx.set_source_rgba(0, 0, 1, alpha) oval_path(ctx, xc + radius / 3. * math.cos(math.pi * (0.5 + 4 / .3)), yc - radius / 3. * math.sin(math.pi * (0.5 + 4 / .3)), subradius, subradius) ctx.fill() def draw(ctx, width, height): radius = 0.5 * min(width, height) - 10 xc = width / 2. yc = height / 2. target = ctx.get_target() overlay = target.create_similar(cairo.CONTENT_COLOR_ALPHA, width, height) punch = target.create_similar(cairo.CONTENT_ALPHA, width, height) circles = target.create_similar(cairo.CONTENT_COLOR_ALPHA, width, height) fill_checks(ctx, 0, 0, width, height) # Draw a black circle on the overlay overlay_cr = cairo.Context(overlay) overlay_cr.set_source_rgb(0, 0, 0) oval_path(overlay_cr, xc, yc, radius, radius) overlay_cr.fill() # Draw 3 circles to the punch surface, then cut # that out of the main circle in the overlay punch_cr = cairo.Context(punch) draw_3circles(punch_cr, xc, yc, radius, 1.0) overlay_cr.set_operator(cairo.OPERATOR_DEST_OUT) overlay_cr.set_source_surface(punch, 0, 0) overlay_cr.paint() # Now draw the 3 circles in a subgroup again # at half intensity, and use OperatorAdd to join up # without seams. circles_cr = cairo.Context(circles) circles_cr.set_operator(cairo.OPERATOR_OVER) draw_3circles(circles_cr, xc, yc, radius, 0.5) overlay_cr.set_operator(cairo.OPERATOR_ADD) overlay_cr.set_source_surface(circles, 0, 0) overlay_cr.paint() ctx.set_source_surface(overlay, 0, 0) ctx.paint() def draw_event(drawingarea, ctx): alloc = drawingarea.get_allocation() draw(ctx, alloc.width, alloc.height) return False def main(): win = Gtk.Window() win.connect('destroy', Gtk.main_quit) win.set_title('Knockout Groups') win.set_default_size(400, 400) drawingarea = Gtk.DrawingArea() win.add(drawingarea) drawingarea.connect('draw', draw_event) win.show_all() Gtk.main() if __name__ == '__main__': main() pycairo-1.16.2/examples/gtk/png_view.py000066400000000000000000000012641323762421700200540ustar00rootroot00000000000000#!/usr/bin/env python """Display a png file """ import sys import cairo import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk def draw_event(widget, ctx, surface): ctx.set_source_surface(surface, 0, 0) ctx.paint() if len(sys.argv) != 2: raise SystemExit('usage: png_view.py png_file') filename = sys.argv[1] surface = cairo.ImageSurface.create_from_png(filename) width = surface.get_width() height = surface.get_height() win = Gtk.Window() win.connect('destroy', Gtk.main_quit) drawingarea = Gtk.DrawingArea() win.add(drawingarea) drawingarea.connect('draw', draw_event, surface) drawingarea.set_size_request(width, height) win.show_all() Gtk.main() pycairo-1.16.2/examples/gtk/text.py000066400000000000000000000015601323762421700172210ustar00rootroot00000000000000#!/usr/bin/env python import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk def draw_event(widget, ctx): ctx.set_line_width(6) ctx.set_tolerance(.1) ctx.select_font_face('sans-serif') ctx.set_font_size(48) (x, y, width, height, dx, dy) = ctx.text_extents('Hello World') ctx.translate(100, 100) ctx.new_path() ctx.move_to(x - 10, y - 10) ctx.rel_line_to(width + 20, 0) ctx.rel_line_to(0, height + 20) ctx.rel_line_to(-(width + 20), 0) ctx.close_path() ctx.set_source_rgb(0, 0, 1) ctx.stroke() ctx.move_to(0, 0) ctx.set_source_rgb(0, 0, 0) ctx.show_text('Hello World') win = Gtk.Window() win.connect('destroy', Gtk.main_quit) drawingarea = Gtk.DrawingArea() win.add(drawingarea) drawingarea.connect('draw', draw_event) drawingarea.set_size_request(400, 150) win.show_all() Gtk.main() pycairo-1.16.2/examples/pygame-demo.py000066400000000000000000000021401323762421700176470ustar00rootroot00000000000000#!/usr/bin/env python """demonstrate pycairo and pygame""" from __future__ import print_function import math import sys import cairo import pygame def draw(surface): x, y, radius = (250, 250, 200) ctx = cairo.Context(surface) ctx.set_line_width(15) ctx.arc(x, y, radius, 0, 2.0 * math.pi) ctx.set_source_rgb(0.8, 0.8, 0.8) ctx.fill_preserve() ctx.set_source_rgb(1, 1, 1) ctx.stroke() def input(events): for event in events: if event.type == pygame.QUIT: sys.exit(0) else: print(event) def main(): width, height = 512, 512 surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) pygame.init() pygame.display.set_mode((width, height)) screen = pygame.display.get_surface() draw(surface) # Create PyGame surface from Cairo Surface buf = surface.get_data() image = pygame.image.frombuffer(buf, (width, height), "ARGB") # Tranfer to Screen screen.blit(image, (0, 0)) pygame.display.flip() while True: input(pygame.event.get()) if __name__ == "__main__": main() pycairo-1.16.2/setup.cfg000066400000000000000000000001421323762421700150740ustar00rootroot00000000000000[flake8] ignore=E402,E741 builtins=buffer,unichr [coverage:run] include= cairo/* tests/* pycairo-1.16.2/setup.py000077500000000000000000000322621323762421700150000ustar00rootroot00000000000000#!/usr/bin/env python import io import subprocess import sys import os import errno if os.environ.get("PYCAIRO_SETUPTOOLS"): # for testing import setuptools setuptools from distutils.core import Extension, setup, Command, Distribution from distutils.ccompiler import new_compiler from distutils import log from distutils import sysconfig PYCAIRO_VERSION = '1.16.2' CAIRO_VERSION_REQUIRED = '1.13.1' XPYB_VERSION_REQUIRED = '1.3' def get_command_class(name): # in case pip loads with setuptools this returns the extended commands return Distribution({}).get_command_class(name) def _check_output(command): try: return subprocess.check_output(command) except OSError as e: if e.errno == errno.ENOENT: raise SystemExit( "%r not found.\nCommand %r" % (command[0], command)) raise SystemExit(e) except subprocess.CalledProcessError as e: raise SystemExit(e) def pkg_config_version_check(pkg, version): command = [ "pkg-config", "--print-errors", "--exists", '%s >= %s' % (pkg, version), ] _check_output(command) def pkg_config_parse(opt, pkg): command = ["pkg-config", opt, pkg] ret = _check_output(command) output = ret.decode() opt = opt[-2:] return [x.lstrip(opt) for x in output.split()] class test_cmd(Command): description = "run tests" user_options = [ ("enable-xpyb", None, "Build with xpyb support (default=disabled)"), ] def initialize_options(self): self.enable_xpyb = None def finalize_options(self): pass def run(self): import pytest # ensure the C extension is build inplace cmd = self.reinitialize_command("build_ext") if self.enable_xpyb is not None: cmd.enable_xpyb = self.enable_xpyb cmd.inplace = True cmd.ensure_finalized() cmd.run() status = pytest.main(["tests"]) if status != 0: raise SystemExit(status) class install_pkgconfig(Command): description = "install .pc file" user_options = [] def initialize_options(self): self.install_base = None self.install_data = None self.compiler_type = None self.outfiles = [] def finalize_options(self): self.set_undefined_options( 'install_lib', ('install_base', 'install_base'), ('install_data', 'install_data'), ) self.set_undefined_options( 'build_ext', ('compiler_type', 'compiler_type'), ) def get_outputs(self): return self.outfiles def get_inputs(self): return [] def run(self): # https://github.com/pygobject/pycairo/issues/83 # The pkg-config file contains absolute paths depending on the # prefix. pip uses wheels as cache and when installing with --user # and then to a virtualenv, the wheel gets reused containing the # wrong paths. So in case bdist_wheel is used, just skip this command. cmd = self.distribution.get_command_obj("bdist_wheel", create=False) if cmd is not None: log.info( "Skipping install_pkgconfig, not supported with bdist_wheel") return # same for bdist_egg cmd = self.distribution.get_command_obj("bdist_egg", create=False) if cmd is not None: log.info( "Skipping install_pkgconfig, not supported with bdist_egg") return if self.compiler_type == "msvc": log.info( "Skipping install_pkgconfig, not supported with MSVC") return python_lib = sysconfig.get_python_lib(True, True, self.install_data) pkgconfig_dir = os.path.join(os.path.dirname(python_lib), 'pkgconfig') self.mkpath(pkgconfig_dir) pcname = "py3cairo.pc" if sys.version_info[0] == 3 else "pycairo.pc" target = os.path.join(pkgconfig_dir, pcname) log.info("Writing %s" % target) log.info("pkg-config prefix: %s" % self.install_base) with open(target, "wb") as h: h.write((u"""\ prefix=%(prefix)s Name: Pycairo Description: Python %(py_version)d bindings for cairo Version: %(version)s Requires: cairo Cflags: -I${prefix}/include/pycairo Libs: """ % { "prefix": self.install_base, "version": PYCAIRO_VERSION, "py_version": sys.version_info[0]}).encode("utf-8")) self.outfiles.append(target) class install_pycairo_header(Command): description = "install pycairo header" user_options = [] def initialize_options(self): self.install_data = None self.install_lib = None self.force = None self.outfiles = [] def finalize_options(self): self.set_undefined_options( 'install_lib', ('install_data', 'install_data'), ('install_lib', 'install_lib'), ) self.set_undefined_options( 'install', ('force', 'force'), ) def get_outputs(self): return self.outfiles def get_inputs(self): return [os.path.join('cairo', 'pycairo.h')] def run(self): # https://github.com/pygobject/pycairo/issues/92 # https://github.com/pygobject/pycairo/issues/98 hname = "py3cairo.h" if sys.version_info[0] == 3 else "pycairo.h" source = self.get_inputs()[0] # for things using get_include() lib_hdir = os.path.join(self.install_lib, "cairo", "include") self.mkpath(lib_hdir) lib_header_path = os.path.join(lib_hdir, hname) (out, _) = self.copy_file(source, lib_header_path) self.outfiles.append(out) cmd = self.distribution.get_command_obj("bdist_wheel", create=False) if cmd is not None: return cmd = self.distribution.get_command_obj("bdist_egg", create=False) if cmd is not None: return # for things using pkg-config data_hdir = os.path.join(self.install_data, "include", "pycairo") self.mkpath(data_hdir) header_path = os.path.join(data_hdir, hname) (out, _) = self.copy_file(source, header_path) self.outfiles.append(out) du_install_lib = get_command_class("install_lib") class install_lib(du_install_lib): def initialize_options(self): self.install_base = None self.install_lib = None self.install_data = None du_install_lib.initialize_options(self) def finalize_options(self): du_install_lib.finalize_options(self) self.set_undefined_options( 'install', ('install_base', 'install_base'), ('install_lib', 'install_lib'), ('install_data', 'install_data'), ) def run(self): du_install_lib.run(self) # bdist_egg doesn't run install, so run our commands here instead self.run_command("install_pkgconfig") self.run_command("install_pycairo_header") du_build_ext = get_command_class("build_ext") class build_ext(du_build_ext): user_options = du_build_ext.user_options + [ ("enable-xpyb", None, "Build with xpyb support (default=disabled)"), ] def initialize_options(self): du_build_ext.initialize_options(self) self.enable_xpyb = None self.compiler_type = None def finalize_options(self): du_build_ext.finalize_options(self) self.set_undefined_options( 'build', ('enable_xpyb', 'enable_xpyb'), ) self.compiler_type = new_compiler(compiler=self.compiler).compiler_type def run(self): ext = self.extensions[0] # If we are using MSVC, don't use pkg-config, # just assume that INCLUDE and LIB contain # the paths to the Cairo headers and libraries, # respectively. if self.compiler_type == "msvc": ext.libraries += ['cairo'] else: pkg_config_version_check('cairo', CAIRO_VERSION_REQUIRED) ext.include_dirs += pkg_config_parse('--cflags-only-I', 'cairo') ext.library_dirs += pkg_config_parse('--libs-only-L', 'cairo') ext.libraries += pkg_config_parse('--libs-only-l', 'cairo') if sys.version_info[0] == 2: # Some python setups don't pass -fno-strict-aliasing, # while MACROS like Py_RETURN_TRUE require it. ext.extra_compile_args += ["-fno-strict-aliasing"] if os.environ.get("PYCAIRO_WARN"): ext.extra_compile_args += [ "-Wall", "-Wundef", "-Wextra", "-Wno-missing-field-initializers", "-Wno-unused-parameter", "-Wnested-externs", "-Wpointer-arith", "-Wno-missing-field-initializers", "-Wdeclaration-after-statement", "-Wformat=2", "-Wold-style-definition", "-Wcast-align", "-Wformat-nonliteral", "-Wformat-security", "-Wsign-compare", "-Wstrict-aliasing", "-Wshadow", "-Winline", "-Wpacked", "-Wmissing-format-attribute", "-Wmissing-noreturn", "-Winit-self", "-Wunused-but-set-variable", "-Warray-bounds", "-Wimplicit-function-declaration", "-Wreturn-type", "-Wconversion", "-Wno-unknown-warning-option", ] if sys.version_info[:2] not in [(3, 3), (3, 4)]: ext.extra_compile_args += [ "-Wswitch-default", ] if self.enable_xpyb: if sys.version_info[0] != 2: raise SystemExit("xpyb only supported with Python 2") pkg_config_version_check("xpyb", XPYB_VERSION_REQUIRED) ext.define_macros += [("HAVE_XPYB", None)] ext.include_dirs += pkg_config_parse('--cflags-only-I', 'xpyb') ext.library_dirs += pkg_config_parse('--libs-only-L', 'xpyb') ext.libraries += pkg_config_parse('--libs-only-l', 'xpyb') du_build_ext.run(self) du_build = get_command_class("build") class build(du_build): user_options = du_build.user_options + [ ("enable-xpyb", None, "Build with xpyb support (default=disabled)"), ] def initialize_options(self): du_build.initialize_options(self) self.enable_xpyb = False def finalize_options(self): du_build.finalize_options(self) self.enable_xpyb = bool(self.enable_xpyb) def main(): cairo_ext = Extension( name='cairo._cairo', sources=[ 'cairo/device.c', 'cairo/bufferproxy.c', 'cairo/error.c', 'cairo/cairomodule.c', 'cairo/context.c', 'cairo/font.c', 'cairo/matrix.c', 'cairo/path.c', 'cairo/pattern.c', 'cairo/region.c', 'cairo/surface.c', 'cairo/enums.c', 'cairo/misc.c', 'cairo/glyph.c', 'cairo/rectangle.c', 'cairo/textcluster.c', 'cairo/textextents.c', ], depends=[ 'cairo/compat.h', 'cairo/private.h', 'cairo/pycairo.h', ], define_macros=[ ("PYCAIRO_VERSION_MAJOR", PYCAIRO_VERSION.split('.')[0]), ("PYCAIRO_VERSION_MINOR", PYCAIRO_VERSION.split('.')[1]), ("PYCAIRO_VERSION_MICRO", PYCAIRO_VERSION.split('.')[2]), ], ) with io.open('README.rst', encoding="utf-8") as h: long_description = h.read() cmdclass = { "build": build, "build_ext": build_ext, "install_lib": install_lib, "install_pkgconfig": install_pkgconfig, "install_pycairo_header": install_pycairo_header, "test": test_cmd, } setup( name="pycairo", version=PYCAIRO_VERSION, url="https://pycairo.readthedocs.io", description="Python interface for cairo", long_description=long_description, maintainer="Christoph Reiter", maintainer_email="reiter.christoph@gmail.com", ext_modules=[cairo_ext], packages=["cairo"], classifiers=[ 'Operating System :: OS Independent', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: Implementation :: CPython', ('License :: OSI Approved :: ' 'GNU Lesser General Public License v2 (LGPLv2)'), 'License :: OSI Approved :: Mozilla Public License 1.1 (MPL 1.1)', ], cmdclass=cmdclass, ) if __name__ == "__main__": main() pycairo-1.16.2/tests/000077500000000000000000000000001323762421700144205ustar00rootroot00000000000000pycairo-1.16.2/tests/__init__.py000066400000000000000000000000001323762421700165170ustar00rootroot00000000000000pycairo-1.16.2/tests/hypothesis_fspaths.py000066400000000000000000000072131323762421700207240ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright 2017 Christoph Reiter # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import os import sys from hypothesis.strategies import composite, sampled_from, lists, \ integers, binary, randoms class _PathLike(object): def __init__(self, value): self._value = value def __fspath__(self): return self._value @composite def fspaths(draw, allow_pathlike=True): """A hypothesis strategy which gives valid path values. Valid path values are everything which when passed to open() will not raise ValueError or TypeError (but might raise OSError due to file system or operating system restrictions). Args: allow_pathlike (bool): If the result can be a pathlike (see :class:`os.PathLike`) """ s = [] if os.name == "nt": if sys.version_info[0] == 3: unichr_ = chr else: unichr_ = unichr hight_surrogate = integers( min_value=0xD800, max_value=0xDBFF).map(lambda i: unichr_(i)) low_surrogate = integers( min_value=0xDC00, max_value=0xDFFF).map(lambda i: unichr_(i)) uni_char = integers( min_value=1, max_value=sys.maxunicode).map(lambda i: unichr_(i)) any_char = sampled_from([ draw(uni_char), draw(hight_surrogate), draw(low_surrogate)]) any_text = lists(any_char).map(lambda l: u"".join(l)) windows_path_text = any_text s.append(windows_path_text) def text_to_bytes(path): fs_enc = sys.getfilesystemencoding() try: return path.encode(fs_enc, "surrogatepass") except UnicodeEncodeError: return path.encode(fs_enc, "replace") windows_path_bytes = windows_path_text.map(text_to_bytes) s.append(windows_path_bytes) else: unix_path_bytes = binary().map(lambda b: b.replace(b"\x00", b" ")) s.append(unix_path_bytes) if sys.version_info[0] == 3: unix_path_text = unix_path_bytes.map( lambda b: b.decode( sys.getfilesystemencoding(), "surrogateescape")) else: unix_path_text = unix_path_bytes.map( lambda b: b.decode( sys.getfilesystemencoding(), "ignore")) r = draw(randoms()) def shuffle_text(t): l = list(t) r.shuffle(l) return u"".join(l) s.append(unix_path_text.map(shuffle_text)) result = draw(sampled_from(list(map(draw, s)))) if allow_pathlike and hasattr(os, "fspath"): result = draw(sampled_from([result, _PathLike(result)])) return result pycairo-1.16.2/tests/test_api.py000066400000000000000000000212451323762421700166060ustar00rootroot00000000000000# -*- coding: utf-8 -*- from __future__ import division from __future__ import absolute_import from __future__ import print_function import os import io import sys import tempfile as tfi import base64 import zlib import shutil import sysconfig import cairo import pytest def test_get_include(): include = cairo.get_include() assert isinstance(include, str) assert os.path.exists(include) assert os.path.isdir(include) def test_version(): cairo.cairo_version() cairo.cairo_version_string() def test_show_unicode_text(): width, height = 300, 300 surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) ctx = cairo.Context(surface) ctx.scale(width, height) ctx.set_line_width(0.04) ctx.select_font_face( "Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) ctx.set_font_size(0.20) ctx.move_to(0.05, 0.5) ctx.show_text(u"ēxāmple.") def test_unicode_filenames(): # FIXME: cairo does not support wchar on Windows and byte support is # missing under Python 3 surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) dirname = tfi.mkdtemp() old_dir = os.getcwd() try: os.chdir(dirname) surface.write_to_png("foobar") new = cairo.ImageSurface.create_from_png(u"foobar") assert surface.get_data() == new.get_data() finally: os.chdir(old_dir) shutil.rmtree(dirname) def test_surface_has_show_text_glyphs(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100) assert not surface.has_show_text_glyphs() surface.finish() with pytest.raises(cairo.Error): surface.has_show_text_glyphs() def test_context(): f, w, h = cairo.FORMAT_ARGB32, 100, 100 s = cairo.ImageSurface(f, w, h) ctx = cairo.Context(s) ctx.set_source_rgb(1.0, 1.0, 1.0) ctx.set_operator(cairo.OPERATOR_SOURCE) ctx.paint() def test_surface(): # TypeError: The Surface type cannot be instantiated pytest.raises(TypeError, "s = cairo.Surface()") f, w, h = cairo.FORMAT_ARGB32, 100, 100 s = cairo.ImageSurface(f, w, h) assert s.get_format() == f assert s.get_width() == w assert s.get_height() == h f, w, h = tfi.TemporaryFile(mode='w+b'), 100, 100 s = cairo.PDFSurface(f, w, h) f, w, h = tfi.TemporaryFile(mode='w+b'), 100, 100 s = cairo.PSSurface(f, w, h) s = cairo.RecordingSurface(cairo.CONTENT_COLOR, None) s = cairo.RecordingSurface(cairo.CONTENT_COLOR, (1, 1, 10, 10)) f, w, h = tfi.TemporaryFile(mode='w+b'), 100, 100 s = cairo.SVGSurface(f, w, h) def test_surface_destroy_before_context(): for kind in [cairo.PDFSurface, cairo.PSSurface]: surface = kind(io.BytesIO(), 1, 1) ctx = cairo.Context(surface) del surface ctx.paint() def test_surface_destroy_before_surface_pattern(): surface = cairo.PDFSurface(io.BytesIO(), 1, 1) pattern = cairo.SurfacePattern(surface) del surface ctx = cairo.Context(pattern.get_surface()) ctx.paint() def test_recording_surface_get_extents(): surface = cairo.RecordingSurface(cairo.CONTENT_COLOR, None) assert surface.get_extents() is None surface = cairo.RecordingSurface(cairo.CONTENT_COLOR, (1, 2, 3, 4)) assert surface.get_extents() == (1, 2, 3, 4) surface = cairo.RecordingSurface(cairo.CONTENT_COLOR, (1, 2, 3, 4)) surface.finish() assert surface.get_extents() == (1, 2, 3, 4) def test_image_surface_get_data(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 3, 3) ctx = cairo.Context(surface) ctx.paint() surface.flush() buf = surface.get_data() assert buf assert len(buf) == 4 * 3 * 3 assert len(bytes(buf)) == len(buf) buf[0:1] = b"\x42" newbuf = surface.get_data() assert newbuf[0:1] == b"\x42" ctx.set_source_rgba(1, 1, 1, 1) ctx.paint() surface.flush() assert newbuf[0:1] == b"\xff" def test_surface_file_obj_error(): class Fail(object): def write(*args): raise IOError cairo.PDFSurface(Fail(), 100, 100) cairo.PSSurface(Fail(), 100, 100) def test_text(): pass def test_region(): a = cairo.Region() assert a.is_empty() is True assert a.num_rectangles() == 0 b = cairo.RectangleInt(1, 2, 10, 12) with pytest.raises(TypeError): hash(b) assert repr(b) == "cairo.RectangleInt(x=1, y=2, width=10, height=12)" assert eval(repr(b)) == b assert isinstance(repr(b), str) d = cairo.RectangleInt(1, 1, 10, 12) e = cairo.RectangleInt(1, 3, 8, 12) assert (b.x, b.y, b.width, b.height) == (1, 2, 10, 12) c = cairo.Region((b, e)) assert not c.is_empty() assert c.num_rectangles() == 2 assert c.get_rectangle(1).y == 14 ex = c.get_extents() assert ex == cairo.RectangleInt(1, 2, 10, 13) assert c.contains_rectangle(d) == cairo.REGION_OVERLAP_PART c.translate(10, 20) assert c.contains_rectangle(d) == cairo.REGION_OVERLAP_OUT assert c.get_rectangle(1) == cairo.RectangleInt(11, 34, 8, 1) cp = c.copy() assert c.num_rectangles() == cp.num_rectangles() assert c.get_rectangle(0) == cp.get_rectangle(0) assert c == cp assert 3 != c assert c != "test" c = cairo.Region((b, e)) c.intersect(d) assert c.num_rectangles() == 1 assert c.get_rectangle(0) == cairo.RectangleInt(1, 2, 10, 11) c = cairo.Region((b, e)) c.subtract(d) assert c.num_rectangles() == 2 assert c == cairo.Region([ cairo.RectangleInt(1, 13, 10, 1), cairo.RectangleInt(1, 14, 8, 1), ]) d = cairo.Region(d) c = cairo.Region((b, e)) c.subtract(d) assert c.num_rectangles() == 2 assert c.get_rectangle(0) == cairo.RectangleInt(1, 13, 10, 1) c = cairo.Region((b, e)) c.union(d) assert c.num_rectangles() == 2 assert c == cairo.Region([ cairo.RectangleInt(1, 1, 10, 13), cairo.RectangleInt(1, 14, 8, 1), ]) c = cairo.Region((b, e)) c.xor(d) assert c.num_rectangles() == 3 assert c == cairo.Region([ cairo.RectangleInt(1, 1, 10, 1), cairo.RectangleInt(1, 14, 8, 1), cairo.RectangleInt(1, 13, 10, 1), ]) def test_constants(): assert cairo.REGION_OVERLAP_IN == 0 assert cairo.REGION_OVERLAP_OUT == 1 assert cairo.REGION_OVERLAP_PART == 2 assert cairo.ANTIALIAS_FAST == 4 assert cairo.ANTIALIAS_GOOD == 5 assert cairo.ANTIALIAS_BEST == 6 assert cairo.OPERATOR_MULTIPLY == 14 assert cairo.OPERATOR_SCREEN == 15 assert cairo.OPERATOR_OVERLAY == 16 assert cairo.OPERATOR_DARKEN == 17 assert cairo.OPERATOR_LIGHTEN == 18 assert cairo.OPERATOR_COLOR_DODGE == 19 assert cairo.OPERATOR_COLOR_BURN == 20 assert cairo.OPERATOR_HARD_LIGHT == 21 assert cairo.OPERATOR_SOFT_LIGHT == 22 assert cairo.OPERATOR_DIFFERENCE == 23 assert cairo.OPERATOR_EXCLUSION == 24 assert cairo.OPERATOR_HSL_HUE == 25 assert cairo.OPERATOR_HSL_SATURATION == 26 assert cairo.OPERATOR_HSL_COLOR == 27 assert cairo.OPERATOR_HSL_LUMINOSITY == 28 assert cairo.FORMAT_INVALID == -1 assert cairo.FORMAT_RGB30 == 5 assert cairo.MIME_TYPE_JPEG == "image/jpeg" assert cairo.SVG_VERSION_1_1 == 0 assert cairo.SVG_VERSION_1_2 == 1 @pytest.mark.skipif(not hasattr(sys, "getrefcount"), reason="PyPy") def test_surface_get_set_mime_data_references(): surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1) if sys.version_info[0] == 2: v = buffer(b"bla") x = buffer(v, 0, 1) else: v = memoryview(b"bla") x = v[:1] assert sys.getrefcount(v) == 2 assert sys.getrefcount(x) == 2 surface.set_mime_data("foo", v) surface.set_mime_data("foo2", v) surface.set_mime_data("foo3", x) assert surface.get_mime_data("foo") is v assert surface.get_mime_data("foo2") is v assert surface.get_mime_data("foo3") is x surface.set_mime_data("foo", None) surface.set_mime_data("foo2", None) surface.set_mime_data("foo3", None) surface.finish() assert sys.getrefcount(v) == 2 assert sys.getrefcount(x) == 2 @pytest.mark.skipif( sysconfig.get_platform().startswith("win"), reason="msvc fixme") def test_surface_mime_data_for_pdf(): jpeg_bytes = zlib.decompress(base64.b64decode( b'eJz7f+P/AwYBLzdPNwZGRkYGDyBk+H+bwRnEowj8P8TAzcHACDJHkOH/EQYRIBsV' b'cP6/xcDBCBJlrLcHqRBAV8EAVcHIylSPVwGbPQEFjPaK9XDrBAipBSq4CQB9jiS0' )) file_like = io.BytesIO() surface = cairo.PDFSurface(file_like, 3, 3) context = cairo.Context(surface) image = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1) image.set_mime_data(cairo.MIME_TYPE_JPEG, jpeg_bytes) context.set_source_surface(image, 0, 0) context.paint() surface.finish() assert jpeg_bytes in file_like.getvalue() pycairo-1.16.2/tests/test_context.py000066400000000000000000000334311323762421700175210ustar00rootroot00000000000000import cairo import pytest import ctypes import platform @pytest.fixture def context(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 42, 42) return cairo.Context(surface) def test_cmp_hash(context): other = cairo.Context(context.get_target()) assert context != other hash(context) def test_get_antialias(context): assert context.get_antialias() == cairo.Antialias.DEFAULT assert isinstance(context.get_antialias(), cairo.Antialias) def test_get_fill_rule(context): assert context.get_fill_rule() == cairo.FillRule.WINDING assert isinstance(context.get_fill_rule(), cairo.FillRule) def test_get_line_cap(context): assert context.get_line_cap() == cairo.LineCap.BUTT assert isinstance(context.get_line_cap(), cairo.LineCap) def test_get_line_join(context): assert context.get_line_join() == cairo.LineJoin.MITER assert isinstance(context.get_line_join(), cairo.LineJoin) def test_get_operator(context): assert context.get_operator() == cairo.Operator.OVER assert isinstance(context.get_operator(), cairo.Operator) def test_get_set_operator_limits(context): max_int = 2 ** (ctypes.sizeof(ctypes.c_int()) * 8 - 1) - 1 min_int = -max_int - 1 for val in [-1, 0, max_int, min_int]: context.set_operator(val) assert context.get_operator() == val # https://bitbucket.org/pypy/pypy/issues/2741 @pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy") def test_show_text_glyphs(): surface = cairo.PDFSurface(None, 300, 300) context = cairo.Context(surface) context.scale(300, 300) context.select_font_face("Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) context.set_font_size(0.08) context.set_line_width(0.09) sf = context.get_scaled_font() glyphs, clusters, flags = sf.text_to_glyphs(0.5, 0.5, "foobar") context.show_text_glyphs("foobar", glyphs, clusters, flags) glyphs, clusters, flags = sf.text_to_glyphs(0.5, 0.5, "") context.show_text_glyphs("", glyphs, clusters, flags) with pytest.raises(TypeError): context.show_text_glyphs(object(), glyphs, clusters, flags) with pytest.raises(TypeError): context.show_text_glyphs("", [object()], clusters, flags) with pytest.raises(TypeError): context.show_text_glyphs("", object(), clusters, flags) with pytest.raises(TypeError): context.show_text_glyphs("", glyphs, [object()], flags) with pytest.raises(TypeError): context.show_text_glyphs("", glyphs, object(), flags) def test_append_path(context): context.line_to(1, 2) p = context.copy_path() context.new_path() context.append_path(p) assert str(context.copy_path()) == str(p) with pytest.raises(TypeError): context.append_path(object()) def test_arc(context): assert not list(context.copy_path()) context.arc(0, 0, 0, 0, 0) assert list(context.copy_path()) with pytest.raises(TypeError): context.arc(object()) def test_arc_negative(context): assert not list(context.copy_path()) context.arc_negative(0, 0, 0, 0, 0) assert list(context.copy_path()) with pytest.raises(TypeError): context.arc_negative(object()) def test_clip_extents(context): assert context.clip_extents() == (0.0, 0.0, 42.0, 42.0) def test_in_clip(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100) context = cairo.Context(surface) assert context.in_clip(50, 50) context.clip() assert not context.in_clip(50, 50) context.reset_clip() assert context.in_clip(50, 50) with pytest.raises(TypeError): context.in_clip(None, None) def test_device_to_user(context): assert context.device_to_user(0, 0) == (0, 0) with pytest.raises(TypeError): context.device_to_user(None, None) def test_device_to_user_distance(context): assert context.device_to_user_distance(0, 0) == (0, 0) with pytest.raises(TypeError): context.device_to_user_distance(None, None) def test_fill_extents(context): context.line_to(1, 1) context.line_to(1, 0) context.line_to(0, 0) context.line_to(0, 1) context.line_to(1, 1) assert context.fill_extents() == (0, 0, 1, 1) def test_curve_to(context): with pytest.raises(TypeError): context.curve_to(1, 2, 3, 4, 5, object()) def test_set_get_dash(context): assert context.get_dash() == ((), 0) assert context.get_dash_count() == 0 context.set_dash([0, 1, 2, 3], 10) assert context.get_dash() == ((0.0, 1.0, 2.0, 3.0), 4.0) assert context.get_dash_count() == 4 with pytest.raises(TypeError): context.set_dash() with pytest.raises(TypeError): context.set_dash(1, 10) with pytest.raises(TypeError): context.set_dash([object()], 1) def test_glyph_extents(context): with pytest.raises(TypeError): context.glyph_extents(None) with pytest.raises(TypeError): context.glyph_extents() def test_glyph_path(context): with pytest.raises(TypeError): context.glyph_path(None) with pytest.raises(TypeError): context.glyph_path() def test_in_stroke(context): context.line_to(0, 0) context.line_to(1, 1) assert context.in_stroke(0, 0) assert not context.in_stroke(0, 2) with pytest.raises(TypeError): context.in_stroke(object(), 0) def test_current_point(context): assert not context.has_current_point() assert context.get_current_point() == (0, 0) context.move_to(10, 10) assert context.has_current_point() assert context.get_current_point() == (10, 10) def test_in_fill(context): assert not context.in_fill(0.1, 0.1) with pytest.raises(TypeError): context.in_fill(0.1, object()) def test_line_to(context): with pytest.raises(TypeError): context.line_to(0.1, object()) def test_mask(context): pattern = cairo.SolidPattern(0, 0, 0) context.mask(pattern) with pytest.raises(TypeError): context.mask(object()) def test_mask_surface(context): context.mask_surface(context.get_target(), 0, 0) with pytest.raises(TypeError): context.mask_surface(object(), 0, 0) def test_paint_with_alpha(context): context.paint_with_alpha(0.5) with pytest.raises(TypeError): context.paint_with_alpha(object()) def test_path_extents(context): context.line_to(1, 1) context.line_to(1, 0) context.line_to(0, 0) context.line_to(0, 1) context.line_to(1, 1) assert context.path_extents() == (0.0, 0.0, 1.0, 1.0) def test_push_pop_group(context): context.push_group() context.pop_group() context.push_group() context.pop_group_to_source() with pytest.raises(TypeError): context.push_group_with_content(object()) context.push_group_with_content(cairo.Content.COLOR) context.pop_group() with pytest.raises(cairo.Error): context.pop_group() def test_rectangle(context): context.rectangle(1, 2, 4, 5) assert context.path_extents() == (1.0, 2.0, 5.0, 7.0) with pytest.raises(TypeError): context.rectangle(1, 2, 3, object()) def test_rotate(context): context.rotate(0.3) with pytest.raises(TypeError): context.rotate(object()) def test_rel_curve_to(context): context.line_to(0, 0) context.rel_curve_to(0, 0, 0, 0, 0, 0) with pytest.raises(TypeError): context.rel_curve_to(object(), 0, 0, 0, 0, 0) def test_move_to(context): context.move_to(10, 10) assert context.get_current_point() == (10, 10) with pytest.raises(TypeError): context.move_to(object(), 0) def test_rel_line_to(context): context.line_to(0, 0) context.rel_line_to(1, 1) with pytest.raises(TypeError): context.rel_line_to(object(), 0) def test_rel_move_to(context): context.line_to(0, 0) context.rel_move_to(1, 1) with pytest.raises(TypeError): context.rel_move_to(object(), 0) def test_save_restore(context): context.save() context.restore() def test_scale(context): context.scale(2, 2) with pytest.raises(TypeError): context.scale(object(), 0) # https://bitbucket.org/pypy/pypy/issues/2741 @pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy") def test_select_font_face(context): context.select_font_face("") with pytest.raises(TypeError): context.select_font_face(None) def test_set_antialias(context): context.set_antialias(cairo.Antialias.SUBPIXEL) assert context.get_antialias() == cairo.Antialias.SUBPIXEL with pytest.raises(TypeError): context.set_antialias(object()) def test_set_fill_rule(context): context.set_fill_rule(cairo.FillRule.EVEN_ODD) assert context.get_fill_rule() == cairo.FillRule.EVEN_ODD with pytest.raises(TypeError): context.set_fill_rule(object()) def test_set_font_face(context): assert context.get_font_face() context.set_font_face(None) assert context.get_font_face() ff = context.get_font_face() context.set_font_face(ff) assert context.get_font_face() == ff with pytest.raises(TypeError): context.set_font_face(object()) def test_set_font_matrix(context): m = cairo.Matrix() context.set_font_matrix(m) assert context.get_font_matrix() == m with pytest.raises(TypeError): context.set_font_matrix(object()) def test_set_line_cap(context): context.set_line_cap(cairo.LineCap.SQUARE) assert context.get_line_cap() == cairo.LineCap.SQUARE with pytest.raises(TypeError): context.set_line_cap(object()) def test_set_line_join(context): context.set_line_join(cairo.LineJoin.BEVEL) assert context.get_line_join() == cairo.LineJoin.BEVEL with pytest.raises(TypeError): context.set_line_join(object()) def test_set_line_width(context): context.set_line_width(42) assert context.get_line_width() == 42 with pytest.raises(TypeError): context.set_line_width(object()) def test_set_matrix(context): m = cairo.Matrix() context.set_matrix(m) assert context.get_matrix() == m with pytest.raises(TypeError): context.set_matrix(object()) def test_set_miter_limit(context): context.set_miter_limit(42) assert context.get_miter_limit() == 42 with pytest.raises(TypeError): context.set_miter_limit(object()) def test_set_scaled_font(context): context.set_scaled_font(context.get_scaled_font()) with pytest.raises(TypeError): context.set_scaled_font(object()) def test_set_font_options(context): context.set_font_options(context.get_font_options()) with pytest.raises(TypeError): context.set_font_options(object()) def test_set_font_size(context): context.set_font_size(42) assert context.get_font_matrix() == cairo.Matrix(42, 0, 0, 42, 0, 0) with pytest.raises(TypeError): context.set_font_size(object()) def test_set_source(context): p = cairo.SolidPattern(0, 0, 0) context.set_source(p) assert context.get_source() == p with pytest.raises(TypeError): context.set_source(object()) def test_set_source_rgb(context): with pytest.raises(TypeError): context.set_source_rgb(1, 1, object()) def test_get_source_rgba(context): context.set_source_rgba(1, 1, 1) assert context.get_source().get_rgba() == (1, 1, 1, 1) context.set_source_rgba(1, 1, 1, 0.5) assert context.get_source().get_rgba() == (1, 1, 1, 0.5) with pytest.raises(TypeError): context.set_source_rgba(1, 1, object()) def test_set_source_surface(context): with pytest.raises(TypeError): context.set_source_surface(object()) def test_set_tolerance(context): context.set_tolerance(42) assert context.get_tolerance() == 42 with pytest.raises(TypeError): context.set_tolerance(object()) def test_show_glyphs(context): with pytest.raises(TypeError): context.show_glyphs() with pytest.raises(TypeError): context.show_glyphs(object()) context.show_glyphs([], 0) def test_show_text(context): with pytest.raises(TypeError): context.show_text() def test_stroke_extents(context): assert context.stroke_extents() == (0.0, 0.0, 0.0, 0.0) def test_text_extents(context): with pytest.raises(TypeError): context.text_extents() # https://bitbucket.org/pypy/pypy/issues/2741 @pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy") def test_text_path(context): context.text_path("foo") with pytest.raises(TypeError): context.text_path(object()) def test_transform(context): context.transform(cairo.Matrix()) with pytest.raises(TypeError): context.transform(object()) def test_translate(context): context.translate(0.5, 0.5) with pytest.raises(TypeError): context.translate(0.5, object()) def test_user_to_device(context): assert context.user_to_device(0, 0) == (0, 0) with pytest.raises(TypeError): context.user_to_device(0, object()) def test_user_to_device_distance(context): assert context.user_to_device_distance(0, 0) == (0, 0) with pytest.raises(TypeError): context.user_to_device_distance(0, object()) def test_context(context): with pytest.raises(TypeError): cairo.Context(None) assert not context == object() def test_simple(context): context.clip_preserve() context.copy_page() context.copy_path_flat() context.fill() context.fill_preserve() context.font_extents() context.identity_matrix() context.new_sub_path() context.show_page() context.stroke_preserve() assert context.get_dash_count() == 0 assert isinstance(context.get_font_matrix(), cairo.Matrix) assert context.get_group_target() context.get_line_width() assert isinstance(context.get_tolerance(), float) assert isinstance(context.get_miter_limit(), float) assert isinstance(context.get_matrix(), cairo.Matrix) pycairo-1.16.2/tests/test_device.py000066400000000000000000000054371323762421700173010ustar00rootroot00000000000000# -*- coding: utf-8 -*- import os import io import tempfile import cairo import pytest def test_cmp_hash(): f = io.BytesIO() dev = cairo.ScriptDevice(f) surface = cairo.ScriptSurface(dev, cairo.Content.COLOR_ALPHA, 42, 10) other = surface.get_device() assert dev == other assert not dev != other assert hash(dev) == hash(other) assert dev != object() def test_get_device(): surface = cairo.ImageSurface(cairo.Format.ARGB32, 10, 10) assert surface.get_device() is None def test_type(): assert cairo.Device with pytest.raises(TypeError): cairo.Device() def test_has(): assert hasattr(cairo, "HAS_SCRIPT_SURFACE") def test_script_device(): dev = cairo.ScriptDevice(io.BytesIO()) assert dev assert issubclass(cairo.ScriptDevice, cairo.Device) assert isinstance(dev, cairo.ScriptDevice) with pytest.raises(TypeError): cairo.ScriptDevice(None) with pytest.raises(TypeError): cairo.ScriptDevice() with pytest.raises((ValueError, TypeError)): cairo.ScriptDevice("\x00") def test_script_device_mode(): assert hasattr(cairo, "ScriptMode") assert cairo.ScriptMode.ASCII != cairo.ScriptMode.BINARY dev = cairo.ScriptDevice(io.BytesIO()) mode = dev.get_mode() assert isinstance(mode, cairo.ScriptMode) assert mode == cairo.ScriptMode.ASCII dev.set_mode(cairo.ScriptMode.BINARY) assert dev.get_mode() == cairo.ScriptMode.BINARY with pytest.raises(TypeError): dev.set_mode(object()) def test_script_device_write_comment(): f = io.BytesIO() dev = cairo.ScriptDevice(f) dev.write_comment("pycairo foo") dev.write_comment(u"pycairo bar") dev.flush() assert b"pycairo foo" in f.getvalue() assert b"pycairo bar" in f.getvalue() with pytest.raises(TypeError): dev.write_comment(object()) def test_from_recording_surface(): s = cairo.RecordingSurface(cairo.CONTENT_COLOR, None) ctx = cairo.Context(s) ctx.paint() f = io.BytesIO() dev = cairo.ScriptDevice(f) dev.from_recording_surface(s) dev.flush() assert b"paint" in f.getvalue() # already finished dev.finish() with pytest.raises(cairo.Error): dev.from_recording_surface(s) # only recording surfaces allowed image = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) with pytest.raises(TypeError): dev.from_recording_surface(image) # No None allowed with pytest.raises(TypeError): dev.from_recording_surface(None) def test_device_acquire(): f = io.BytesIO() dev = cairo.ScriptDevice(f) dev.acquire() dev.release() def test_script_device_to_path(): fd, fname = tempfile.mkstemp() os.close(fd) try: cairo.ScriptDevice(fname).finish() finally: os.unlink(fname) pycairo-1.16.2/tests/test_enums.py000066400000000000000000000075411323762421700171670ustar00rootroot00000000000000import pickle import re import platform import pytest import cairo # https://bitbucket.org/pypy/pypy/issues/2742 @pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy") def test_type(): t = cairo.Antialias assert int in t.__mro__ assert isinstance(t(42), int) assert isinstance(t(0), int) assert issubclass(t, int) with pytest.raises(TypeError): t() with pytest.raises(TypeError): t(object()) with pytest.raises(TypeError): type("foo", (t,), {}) assert hasattr(t, "DEFAULT") assert t.DEFAULT == 0 assert t.__name__ == "Antialias" assert t.__module__ == "cairo" assert repr(t.DEFAULT) == "cairo.Antialias.DEFAULT" assert repr(t(123456)) == "123456" assert repr(t(0)) == "cairo.Antialias.DEFAULT" assert str(t(0)) == "0" assert isinstance(cairo.ANTIALIAS_DEFAULT, t) def test_misc(): cairo.Status.JBIG2_GLOBAL_MISSING def test_format_methods(): assert cairo.Format.RGB24.stride_for_width(8) == 32 assert cairo.Format.stride_for_width(cairo.Format.RGB24, 8) == 32 def test_text_cluster_flags(): assert cairo.TextClusterFlags.BACKWARD == 1 def test_surface_observer_mode(): assert cairo.SurfaceObserverMode.NORMAL == 0 def test_aliases(): types_ = [ cairo.Antialias, cairo.Content, cairo.Extend, cairo.FillRule, cairo.Filter, cairo.FontWeight, cairo.FontSlant, cairo.Format, cairo.HintMetrics, cairo.HintStyle, cairo.LineCap, cairo.LineJoin, cairo.Operator, cairo.PathDataType, cairo.RegionOverlap, cairo.SubpixelOrder, ] def get_prefix(t): name = t.__name__ # special case.. if name == "PathDataType": name = "Path" return"_".join([s.upper() for s in re.findall('[A-Z][^A-Z]*', name)]) for t in types_: for name in dir(t): if name.upper() != name: continue value = getattr(t, name) assert isinstance(value, t) prefix = get_prefix(t) assert getattr(cairo, prefix + "_" + name) == value for name in dir(cairo): for t in types_: prefix = get_prefix(t) if name.startswith(prefix + "_"): postfix = name[len(prefix) + 1:] value = getattr(cairo, name) assert getattr(t, postfix) == value # some enums are different, check manually assert cairo.SVG_VERSION_1_1 == cairo.SVGVersion.VERSION_1_1 assert isinstance(cairo.SVG_VERSION_1_1, cairo.SVGVersion) assert isinstance(cairo.SVGVersion.VERSION_1_1, cairo.SVGVersion) assert cairo.SVG_VERSION_1_2 == cairo.SVGVersion.VERSION_1_2 assert isinstance(cairo.SVG_VERSION_1_2, cairo.SVGVersion) assert isinstance(cairo.SVGVersion.VERSION_1_2, cairo.SVGVersion) assert cairo.PDF_VERSION_1_4 == cairo.PDFVersion.VERSION_1_4 assert isinstance(cairo.PDF_VERSION_1_4, cairo.PDFVersion) assert isinstance(cairo.PDFVersion.VERSION_1_4, cairo.PDFVersion) assert cairo.PDF_VERSION_1_5 == cairo.PDFVersion.VERSION_1_5 assert isinstance(cairo.PDF_VERSION_1_5, cairo.PDFVersion) assert isinstance(cairo.PDFVersion.VERSION_1_5, cairo.PDFVersion) assert cairo.PS_LEVEL_2 == cairo.PSLevel.LEVEL_2 assert isinstance(cairo.PS_LEVEL_2, cairo.PSLevel) assert isinstance(cairo.PSLevel.LEVEL_2, cairo.PSLevel) assert cairo.PS_LEVEL_3 == cairo.PSLevel.LEVEL_3 assert isinstance(cairo.PS_LEVEL_3, cairo.PSLevel) assert isinstance(cairo.PSLevel.LEVEL_3, cairo.PSLevel) def test_pickle(): # These constants used to be plain int. Try to pickle to int so that # there is no dependency on pycairo when unpickling. value = cairo.Antialias(42) new_value = pickle.loads(pickle.dumps(value)) assert type(new_value) == int pycairo-1.16.2/tests/test_error.py000066400000000000000000000046271323762421700171730ustar00rootroot00000000000000# -*- coding: utf-8 -*- import cairo import pytest def test_error_check_status(): check_status = cairo.Error._check_status with pytest.raises(cairo.Error) as e: check_status(cairo.Status.DEVICE_FINISHED) assert e.value.status == cairo.Status.DEVICE_FINISHED assert str(e.value) == "the target device has been finished" assert repr(e.value) == ("Error('the target device has been finished', " "cairo.Status.DEVICE_FINISHED)") with pytest.raises(cairo.Error) as e: check_status(cairo.Status.NO_MEMORY) assert e.value.status == cairo.Status.NO_MEMORY with pytest.raises(MemoryError) as e: check_status(cairo.Status.NO_MEMORY) assert type(e.value).__name__ == "cairo.MemoryError" with pytest.raises(cairo.Error) as e: check_status(cairo.Status.READ_ERROR) with pytest.raises(IOError) as e: check_status(cairo.Status.READ_ERROR) assert e.value.status == cairo.Status.READ_ERROR with pytest.raises(cairo.Error) as e: check_status(cairo.Status.WRITE_ERROR) with pytest.raises(IOError) as e: check_status(cairo.Status.WRITE_ERROR) assert e.value.status == cairo.Status.WRITE_ERROR assert type(e.value).__name__ == "cairo.IOError" err = e.value err.status = cairo.Status.DEVICE_FINISHED assert err.status == cairo.Status.DEVICE_FINISHED with pytest.raises((TypeError, AttributeError)): del err.status str(cairo.Error()) def test_error_context(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100) ctx = cairo.Context(surface) with pytest.raises(cairo.Error) as excinfo: ctx.restore() error = excinfo.value assert error.status == cairo.STATUS_INVALID_RESTORE assert error.status == cairo.Status.INVALID_RESTORE assert isinstance(error.status, cairo.Status) assert str(error) def test_error(): with pytest.raises(cairo.Error) as excinfo: raise cairo.Error assert excinfo.value.status is None with pytest.raises(cairo.Error) as excinfo: raise cairo.Error("foo") assert excinfo.value.status is None assert excinfo.value.args[0] == "foo" with pytest.raises(cairo.Error) as excinfo: raise cairo.Error("foo", 42) assert excinfo.value.status == 42 class Foo(cairo.Error): pass Foo("foo", 42) def test_error_alias(): assert cairo.Error is cairo.CairoError pycairo-1.16.2/tests/test_font.py000066400000000000000000000206251323762421700170040ustar00rootroot00000000000000import sys import platform import cairo import pytest try: long except NameError: long = int @pytest.fixture def font_options(): surface = cairo.ImageSurface(0, 10, 10) return surface.get_font_options() @pytest.fixture def font_face(): surface = cairo.ImageSurface(0, 10, 10) context = cairo.Context(surface) return context.get_font_face() @pytest.fixture def scaled_font(font_face, font_options): return cairo.ScaledFont( font_face, cairo.Matrix(), cairo.Matrix(), font_options) def test_font_options(): assert isinstance(cairo.FontOptions(), cairo.FontOptions) with pytest.raises(TypeError): cairo.FontOptions(object()) def test_font_options_copy_equal(): surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1) font_options = surface.get_font_options() font_options.set_hint_metrics(cairo.HINT_METRICS_DEFAULT) new = font_options.copy() assert font_options.equal(new) assert new.get_hint_metrics() == cairo.HINT_METRICS_DEFAULT font_options.set_hint_metrics(cairo.HINT_METRICS_ON) assert not font_options.equal(new) assert new.get_hint_metrics() == cairo.HINT_METRICS_DEFAULT with pytest.raises(TypeError): font_options.equal(object()) def test_font_options_hash(): surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1) font_options = surface.get_font_options() assert font_options.hash() == font_options.hash() assert isinstance(font_options.hash(), long) def test_font_options_merge(): surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1) font_options = surface.get_font_options() font_options.set_hint_metrics(cairo.HINT_METRICS_DEFAULT) new = font_options.copy() new.set_hint_metrics(cairo.HINT_METRICS_ON) font_options.merge(new) assert font_options.get_hint_metrics() == cairo.HINT_METRICS_ON with pytest.raises(TypeError): font_options.merge(object()) def test_font_options_hashable_protocol(): # make sure __eq__ and __ne__ work surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1) font_options = surface.get_font_options() assert font_options == font_options.copy() assert not font_options != font_options.copy() font_options.set_hint_metrics(cairo.HINT_METRICS_DEFAULT) different = font_options.copy() different.set_hint_metrics(cairo.HINT_METRICS_ON) assert font_options != different assert not font_options == different assert font_options != object() # make sure the other operators are undefined if sys.version_info[0] == 3: with pytest.raises(TypeError): font_options < font_options assert font_options.__gt__(font_options) is NotImplemented def test_font_options_set_antialias(font_options): font_options.set_antialias(cairo.Antialias.GRAY) assert font_options.get_antialias() == cairo.Antialias.GRAY with pytest.raises(TypeError): font_options.set_antialias(object()) def test_font_options_set_hint_metrics(font_options): font_options.set_hint_metrics(cairo.HintMetrics.OFF) assert font_options.get_hint_metrics() == cairo.HintMetrics.OFF with pytest.raises(TypeError): font_options.set_hint_metrics(object()) def test_font_options_set_hint_style(font_options): font_options.set_hint_style(cairo.HintStyle.SLIGHT) assert font_options.get_hint_style() == cairo.HintStyle.SLIGHT with pytest.raises(TypeError): font_options.set_hint_style(object()) def test_font_options_set_subpixel_order(font_options): font_options.set_subpixel_order(cairo.SubpixelOrder.VRGB) assert font_options.get_subpixel_order() == cairo.SubpixelOrder.VRGB with pytest.raises(TypeError): font_options.set_subpixel_order(object()) def test_font_face(font_face): with pytest.raises(TypeError): cairo.FontFace() assert font_face == font_face assert font_face != object() def test_font_face_cmp_hash(): surface = cairo.ImageSurface(0, 10, 10) context = cairo.Context(surface) ff = context.get_font_face() other = context.get_font_face() assert ff == other assert not ff != other assert hash(ff) == hash(other) sf = context.get_scaled_font() other = context.get_scaled_font() assert sf == other assert not sf != other assert hash(sf) == hash(other) fo = context.get_font_options() # FontOptions compare by their content and they are mutable, so not # hashable. with pytest.raises(TypeError): hash(fo) def test_scaled_font(scaled_font): with pytest.raises(TypeError): cairo.ScaledFont() assert scaled_font == scaled_font assert scaled_font != object() def test_scaled_font_extents(scaled_font): assert isinstance(scaled_font.extents(), tuple) def test_scaled_font_get_font_face(scaled_font): assert isinstance(scaled_font.get_font_face(), cairo.FontFace) def test_scaled_font_get_scale_matrix(scaled_font): assert isinstance(scaled_font.get_scale_matrix(), cairo.Matrix) # https://bitbucket.org/pypy/pypy/issues/2741 @pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy") def test_scaled_font_text_extents(scaled_font): with pytest.raises(TypeError): scaled_font.text_extents(object()) def test_scaled_font_glyph_extents(scaled_font): with pytest.raises(TypeError): scaled_font.glyph_extents(object()) with pytest.raises(TypeError): scaled_font.glyph_extents([object()]) with pytest.raises(TypeError): scaled_font.glyph_extents() # https://bitbucket.org/pypy/pypy/issues/2741 @pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy") def test_toy_font_face(): with pytest.raises(TypeError): cairo.ToyFontFace(object()) def test_toy_font_get_family(): font_face = cairo.ToyFontFace("") assert isinstance(font_face.get_family(), str) def test_toy_font_get_slant(): font_face = cairo.ToyFontFace("") assert font_face.get_slant() == cairo.FontSlant.NORMAL assert isinstance(font_face.get_slant(), cairo.FontSlant) def test_toy_font_get_weight(): font_face = cairo.ToyFontFace("") assert font_face.get_weight() == cairo.FontWeight.NORMAL assert isinstance(font_face.get_weight(), cairo.FontWeight) def test_font_options_get_antialias(font_options): assert font_options.get_antialias() == cairo.Antialias.DEFAULT assert isinstance(font_options.get_antialias(), cairo.Antialias) def test_font_options_get_hint_metrics(font_options): assert font_options.get_hint_metrics() == cairo.HintMetrics.ON assert isinstance(font_options.get_hint_metrics(), cairo.HintMetrics) def test_font_options_get_hint_style(font_options): assert font_options.get_hint_style() == cairo.HintStyle.DEFAULT assert isinstance(font_options.get_hint_style(), cairo.HintStyle) def test_font_options_get_subpixel_order(font_options): assert font_options.get_subpixel_order() == cairo.SubpixelOrder.DEFAULT assert isinstance(font_options.get_subpixel_order(), cairo.SubpixelOrder) def test_scaled_font_get_ctm(): surface = cairo.ImageSurface(0, 10, 10) ctx = cairo.Context(surface) sf = ctx.get_scaled_font() matrix = sf.get_ctm() assert isinstance(matrix, cairo.Matrix) def test_scaled_font_get_font_matrix(): surface = cairo.ImageSurface(0, 10, 10) ctx = cairo.Context(surface) sf = ctx.get_scaled_font() matrix = sf.get_font_matrix() assert isinstance(matrix, cairo.Matrix) def test_scaled_font_get_font_options(): surface = cairo.ImageSurface(0, 10, 10) ctx = cairo.Context(surface) sf = ctx.get_scaled_font() font_options = sf.get_font_options() assert isinstance(font_options, cairo.FontOptions) def test_scaled_font_text_to_glyphs(): surface = cairo.ImageSurface(0, 10, 10) ctx = cairo.Context(surface) sf = ctx.get_scaled_font() assert sf.text_to_glyphs(0, 0, u"") == ([], [], 0) glyphs, clusters, flags = sf.text_to_glyphs(0, 0, u"a") assert sf.text_to_glyphs(0, 0, u"a", True) == (glyphs, clusters, flags) assert len(glyphs) == 1 assert isinstance(glyphs[0], cairo.Glyph) assert len(clusters) == 1 assert isinstance(clusters[0], cairo.TextCluster) assert flags == 0 assert sf.text_to_glyphs(0, 0, u"a", False) == glyphs glyphs, clusters, flags = sf.text_to_glyphs(0, 0, u"a b") assert len(glyphs) == 3 assert glyphs[0] != glyphs[1] assert len(clusters) == 3 with pytest.raises(TypeError): sf.text_to_glyphs(object()) pycairo-1.16.2/tests/test_glyph.py000066400000000000000000000022261323762421700171560ustar00rootroot00000000000000import cairo import pytest def test_type(): assert cairo.Glyph assert issubclass(cairo.Glyph, tuple) with pytest.raises(TypeError): cairo.Glyph() g = cairo.Glyph(0, 0.5, 0.25) assert hash(g) == hash(cairo.Glyph(0, 0.5, 0.25)) assert isinstance(g, tuple) assert g == (0, 0.5, 0.25) assert g == cairo.Glyph(0, 0.5, 0.25) assert g[1] == 0.5 assert g.index == 0 assert g.x == 0.5 assert g.y == 0.25 with pytest.raises(AttributeError): assert g.z assert repr(cairo.Glyph(0, 0, 0)) == \ "cairo.Glyph(index=0, x=0.0, y=0.0)" assert str(cairo.Glyph(0, 0, 0)) == \ "cairo.Glyph(index=0, x=0.0, y=0.0)" assert eval(repr(g)) == g def test_context(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) assert context.glyph_extents([(0, 0, 0)]) context.glyph_path([(0, 0, 0)]) context.show_glyphs([(0, 0, 0)]) g = cairo.Glyph(0, 0.5, 0.25) assert context.glyph_extents([g]) context.glyph_path([g]) context.show_glyphs([(0, 0, 0)]) with pytest.raises(TypeError): context.glyph_path([object()]) pycairo-1.16.2/tests/test_hypothesis.py000066400000000000000000000135221323762421700202330ustar00rootroot00000000000000# -*- coding: utf-8 -*- import math import os import sys import tempfile import shutil import pytest import cairo pytest.importorskip("hypothesis") from hypothesis import given, strategies, assume, settings from hypothesis.strategies import floats, integers from .hypothesis_fspaths import fspaths @pytest.fixture(scope='module') def tempdir_path(): dir_ = tempfile.mkdtemp() try: yield dir_ finally: shutil.rmtree(dir_) def _to_temp_path(tempdir_path, p): basename = os.path.basename(p) if sys.version_info[0] == 3 and isinstance(basename, bytes): tempdir_path = os.fsencode(tempdir_path) res = os.path.join(tempdir_path, basename) if not isinstance(p, (type(u""), type(b""))): res = type(p)(res) return res def cairo_ver(): return tuple(map(int, cairo.cairo_version_string().split("."))) @given(path=fspaths()) @settings(max_examples=500) def test_fspaths(tempdir_path, path): p = _to_temp_path(tempdir_path, path) assert not os.listdir(tempdir_path) # filter out "." if os.path.exists(p): return if cairo_ver() >= (1, 15, 10): def path_encode(p): return p.encode("utf-8") else: def path_encode(p): new = temp.encode("mbcs") if new.decode("mbcs") != p: raise ValueError return new # cairo up to 1.15.8 uses fopen, which only supports ANSI paths under # Windows. 1.15.10+ uses utf-8 like glib. is_valid = True if os.name == "nt": temp = os.path.join(p) if isinstance(temp, type(b"")): if sys.version_info[0] == 3: temp = os.fsdecode(temp) else: temp = temp.decode(sys.getfilesystemencoding(), "strict") if isinstance(temp, type(u"")): try: path_encode(temp) except ValueError: is_valid = False surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) try: surface.write_to_png(p) except (TypeError, ValueError): assert not is_valid assert not os.path.exists(p) except cairo.Error: # Under Python 2 we can't produce utf-8 without surrogates # and cairo 1.15.10+ errors out in that case. # And for some reason writing to "\x01" fails assert is_valid assert not os.path.exists(p) else: assert is_valid assert os.path.exists(p), os.listdir(tempdir_path) os.unlink(p) @given(strategies.floats(), strategies.floats()) def test_surface_set_device_scale(x_scale, y_scale): assume(not any(math.isnan(v) for v in [x_scale, y_scale])) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) try: surface.set_device_scale(x_scale, y_scale) except cairo.Error as e: assert e.status == cairo.Status.INVALID_MATRIX else: assert surface.get_device_scale() == (x_scale, y_scale) @given(strategies.floats(), strategies.floats()) def test_surface_set_device_offset(x_offset, y_offset): assume(not any(math.isnan(v) for v in [x_offset, y_offset])) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) surface.set_device_offset(x_offset, y_offset) @given(strategies.floats(), strategies.floats(), strategies.floats(), strategies.floats()) def test_surface_create_for_rectangle(x, y, w, h): assume(not any(math.isnan(v) for v in [x, y, w, h])) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100) try: surface.create_for_rectangle(x, y, w, h) except cairo.Error as e: assert e.status == cairo.Status.INVALID_SIZE @given(integers(), floats(allow_nan=False), floats(allow_nan=False)) def test_glyph(index, x, y): try: g = cairo.Glyph(index, x, y) except OverflowError: pass else: assert g.index == index assert g.x == x assert g.y == y @given(floats(allow_nan=False), floats(allow_nan=False), floats(allow_nan=False), floats(allow_nan=False)) def test_rectangle(x, y, width, height): r = cairo.Rectangle(x, y, width, height) assert r.x == x assert r.y == y assert r.width == width assert r.height == height @given(integers(), integers()) def test_text_cluster(num_bytes, num_glyphs): try: tc = cairo.TextCluster(num_bytes, num_glyphs) except OverflowError: pass else: assert tc.num_bytes == num_bytes assert tc.num_glyphs == num_glyphs @given(floats(allow_nan=False), floats(allow_nan=False), floats(allow_nan=False), floats(allow_nan=False), floats(allow_nan=False), floats(allow_nan=False)) def test_text_extents(x_bearing, y_bearing, width, height, x_advance, y_advance): te = cairo.TextExtents(x_bearing, y_bearing, width, height, x_advance, y_advance) assert te.x_bearing == x_bearing assert te.y_bearing == y_bearing assert te.width == width assert te.height == height assert te.x_advance == x_advance assert te.y_advance == y_advance @given(integers(), integers(), integers(), integers()) def test_rect_int(x, y, width, height): try: r = cairo.RectangleInt(x, y, width, height) except OverflowError: pass else: assert r.x == x assert r.y == y assert r.width == width assert r.height == height @given(integers()) def test_enums(value): try: e = cairo.Antialias(value) except OverflowError: pass else: assert e == value @given(integers()) def test_context_get_set_operator(value): try: op = cairo.Operator(value) except OverflowError: return surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) try: context.set_operator(op) except OverflowError: return assert context.get_operator() == op pycairo-1.16.2/tests/test_matrix.py000066400000000000000000000042541323762421700173420ustar00rootroot00000000000000import cairo import pytest def test_matrix(): m = cairo.Matrix() m.rotate(10) m.scale(1.5, 2.5) m.translate(10, 20) with pytest.raises(TypeError): m * 42 with pytest.raises(TypeError): m + 42 with pytest.raises(TypeError): cairo.Matrix(object()) assert m != 42 assert m == m assert m != cairo.Matrix() assert repr(cairo.Matrix()) == "cairo.Matrix(1, 0, 0, 1, 0, 0)" def test_init_rotate(): r = cairo.Matrix.init_rotate(0) assert cairo.Matrix() == r with pytest.raises(TypeError): cairo.Matrix.init_rotate(object()) def test_invert(): m = cairo.Matrix(1, 1) m.invert() assert m == cairo.Matrix(1, -1, -0, 1, 0, 0) def test_matrix_properties(): m = cairo.Matrix(*range(6)) assert [m.xx, m.yx, m.xy, m.yy, m.x0, m.y0] == list(range(6)) m.xx = 42 assert m.xx == 42 m.scale(2, 2) assert m.xx == 84 def test_get_item(): m = cairo.Matrix(1, 2, 3, 4, 5, 6) for i in range(6): assert m[i] == i + 1 with pytest.raises(IndexError): m[6] with pytest.raises(IndexError): m[-1] def test_multiply(): with pytest.raises(TypeError): cairo.Matrix().multiply(object()) m = cairo.Matrix(1, 1, 0, 1) assert m.multiply(m) == cairo.Matrix(1, 2, 0, 1, 0, 0) assert m * m == m.multiply(m) def test_translate(): m = cairo.Matrix() m.translate(1, 1) assert m == cairo.Matrix(1, 0, 0, 1, 1, 1) with pytest.raises(TypeError): m.translate(1, object()) def test_rotate(): m = cairo.Matrix() with pytest.raises(TypeError): m.rotate(object()) def test_scale(): m = cairo.Matrix() with pytest.raises(TypeError): m.scale(object()) m.scale(2, 2) assert m != cairo.Matrix() m.scale(0.5, 0.5) assert m == cairo.Matrix() def test_transform_distance(): m = cairo.Matrix() assert m.transform_distance(1, 1) == (1, 1) with pytest.raises(TypeError): m.transform_distance(1, object()) def test_transform_point(): m = cairo.Matrix() assert m.transform_point(1, 1) == (1, 1) with pytest.raises(TypeError): m.transform_point(1, object()) pycairo-1.16.2/tests/test_path.py000066400000000000000000000031461323762421700167710ustar00rootroot00000000000000import cairo import pytest @pytest.fixture def context(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 42, 42) return cairo.Context(surface) def test_path(): assert cairo.Path with pytest.raises(TypeError): cairo.Path() def test_path_str(context): p = context.copy_path() assert isinstance(p, cairo.Path) assert str(p) == "" context.line_to(1, 2) p = context.copy_path() assert str(p) == "move_to 1.000000 2.000000" context.line_to(1, 2) p = context.copy_path() assert str(p) == "move_to 1.000000 2.000000\nline_to 1.000000 2.000000" context.new_path() context.curve_to(0, 1, 2, 3, 4, 5) p = context.copy_path() assert str(p) == ( "move_to 0.000000 1.000000\n" "curve_to 0.000000 1.000000 2.000000 3.000000 4.000000 5.000000") context.new_path() context.line_to(1, 2) context.close_path() p = context.copy_path() assert str(p) == ( "move_to 1.000000 2.000000\n" "close path\n" "move_to 1.000000 2.000000") def test_path_compare_hash(context): p = context.copy_path() assert p == p hash(p) assert not p != p assert p != object() assert not p < p assert p <= p assert p >= p assert not p > p def test_path_iter(context): context.line_to(1, 2) context.line_to(2, 3) context.curve_to(0, 1, 2, 3, 4, 5) context.close_path() p = context.copy_path() i = iter(p) assert list(i) == [ (0, (1.0, 2.0)), (1, (2.0, 3.0)), (2, (0.0, 1.0, 2.0, 3.0, 4.0, 5.0)), (3, ()), (0, (1.0, 2.0)), ] pycairo-1.16.2/tests/test_pattern.py000066400000000000000000000217311323762421700175120ustar00rootroot00000000000000import cairo import pytest def test_raster_source(): pattern = cairo.RasterSourcePattern(cairo.Content.COLOR, 2, 2) assert isinstance(pattern, cairo.RasterSourcePattern) assert issubclass(cairo.RasterSourcePattern, cairo.Pattern) with pytest.raises(TypeError): cairo.RasterSourcePattern(object()) was_called = [] def acquire_callback(target, extents): surface = target.create_similar_image( cairo.FORMAT_ARGB32, extents.width, extents.height) surface.set_device_offset(extents.x, extents.y) context = cairo.Context(surface) context.set_source_rgb(1, 0, 0) context.paint() was_called.append("acquire") return surface def release_callback(surface): was_called.append("release") return None with pytest.raises(TypeError): pattern.set_acquire() pattern.set_acquire(None, release_callback) assert pattern.get_acquire() == (None, release_callback) pattern.set_acquire(acquire_callback, None) assert pattern.get_acquire() == (acquire_callback, None) pattern.set_acquire(None, None) assert pattern.get_acquire() == (None, None) pattern.set_acquire(acquire_callback, release_callback) assert pattern.get_acquire() == (acquire_callback, release_callback) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) context.set_source(pattern) context.paint() assert was_called == ["acquire", "release"] with pytest.raises(TypeError): pattern.set_acquire(None, object()) with pytest.raises(TypeError): pattern.set_acquire(object(), None) def test_cmp_hash(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) pattern = context.get_source() other = context.get_source() assert pattern == other assert not pattern != other def test_get_extend(): pattern = cairo.SolidPattern(1, 2, 4) assert pattern.get_extend() == cairo.Extend.PAD assert isinstance(pattern.get_extend(), cairo.Extend) def test_get_filter(): pattern = cairo.SolidPattern(1, 2, 4) assert pattern.get_filter() == cairo.Filter.GOOD def test_linear_gradient(): with pytest.raises(TypeError): cairo.LinearGradient() def test_radial_gradient(): with pytest.raises(TypeError): cairo.RadialGradient() def test_gradient_get_color_stops(): pattern = cairo.LinearGradient(1, 2, 4, 5) assert pattern.get_color_stops_rgba() == [] pattern.add_color_stop_rgb(0.125, 0.25, 0.5, 0.75) assert pattern.get_color_stops_rgba() == [(0.125, 0.25, 0.5, 0.75, 1.0)] pattern.add_color_stop_rgba(1.0, 0.75, 0.5, 0.25, 0.125) assert pattern.get_color_stops_rgba() == \ [(0.125, 0.25, 0.5, 0.75, 1.0), (1.0, 0.75, 0.5, 0.25, 0.125)] def test_gradient_add_color_stop_rgb(): pattern = cairo.LinearGradient(1, 2, 4, 5) with pytest.raises(TypeError): pattern.add_color_stop_rgb() def test_gradient_add_color_stop_rgba(): pattern = cairo.LinearGradient(1, 2, 4, 5) with pytest.raises(TypeError): pattern.add_color_stop_rgba() def test_solid_pattern(): with pytest.raises(TypeError): cairo.SolidPattern() def test_mesh_pattern(): mesh = cairo.MeshPattern() assert isinstance(mesh, cairo.MeshPattern) assert issubclass(cairo.MeshPattern, cairo.Pattern) with pytest.raises(TypeError): cairo.MeshPattern(object()) def test_mesh_pattern_example1(): pattern = cairo.MeshPattern() assert pattern.get_patch_count() == 0 pattern.begin_patch() pattern.move_to(0, 0) pattern.curve_to(30, -30, 60, 30, 100, 0) pattern.curve_to(60, 30, 130, 60, 100, 100) pattern.curve_to(60, 70, 30, 130, 0, 100) pattern.curve_to(30, 70, -30, 30, 0, 0) pattern.set_corner_color_rgb(0, 1, 0, 0) pattern.set_corner_color_rgb(1, 0, 1, 0) pattern.set_corner_color_rgb(2, 0, 0, 1) pattern.set_corner_color_rgb(3, 1, 1, 0) pattern.end_patch() assert pattern.get_patch_count() == 1 assert pattern.get_path(0) assert pattern.get_corner_color_rgba(0, 0) == (1, 0, 0, 1) with pytest.raises(cairo.Error): pattern.get_corner_color_rgba(1, 0) with pytest.raises(cairo.Error): pattern.get_corner_color_rgba(0, 9) with pytest.raises(cairo.Error): pattern.get_path(9) def test_mesh_pattern_curve_to(): pattern = cairo.MeshPattern() with pytest.raises(TypeError): pattern.curve_to(object()) def test_mesh_pattern_get_control_point(): pattern = cairo.MeshPattern() with pytest.raises(TypeError): pattern.get_control_point(object()) def test_mesh_pattern_get_corner_color_rgba(): pattern = cairo.MeshPattern() with pytest.raises(TypeError): pattern.get_corner_color_rgba(object()) def test_mesh_pattern_get_path(): pattern = cairo.MeshPattern() with pytest.raises(TypeError): pattern.get_path(object()) def test_mesh_pattern_line_to(): pattern = cairo.MeshPattern() with pytest.raises(TypeError): pattern.line_to(object()) def test_mesh_pattern_move_to(): pattern = cairo.MeshPattern() with pytest.raises(TypeError): pattern.move_to(object()) def test_mesh_pattern_set_control_point(): pattern = cairo.MeshPattern() with pytest.raises(TypeError): pattern.set_control_point(object()) def test_mesh_pattern_set_corner_color_rgb(): pattern = cairo.MeshPattern() with pytest.raises(TypeError): pattern.set_corner_color_rgb(object()) def test_mesh_pattern_set_corner_color_rgba(): pattern = cairo.MeshPattern() with pytest.raises(TypeError): pattern.set_corner_color_rgba(object()) def test_mesh_pattern_example2(): pattern = cairo.MeshPattern() pattern.begin_patch() pattern.move_to(100, 100) pattern.line_to(130, 130) pattern.line_to(130, 70) pattern.set_corner_color_rgb(0, 1, 0, 0) pattern.set_corner_color_rgb(1, 0, 1, 0) pattern.set_corner_color_rgb(2, 0, 0, 1) pattern.end_patch() def test_mesh_pattern_rest(): pattern = cairo.MeshPattern() pattern.begin_patch() pattern.curve_to(0, 1, 2, 3, 4, 5) pattern.set_corner_color_rgba(0, 0.125, 0.25, 0.5, 0.75) pattern.set_control_point(0, 10, 12) pattern.end_patch() assert pattern.get_corner_color_rgba(0, 0) == (0.125, 0.25, 0.5, 0.75) assert pattern.get_control_point(0, 0) == (10, 12) pattern.get_control_point(0, 0) with pytest.raises(cairo.Error): pattern.get_control_point(1, 0) with pytest.raises(cairo.Error): pattern.get_control_point(0, 9) def test_mesh_pattern_error_states(): pattern = cairo.MeshPattern() pattern.begin_patch() with pytest.raises(cairo.Error): pattern.begin_patch() with pytest.raises(cairo.Error): cairo.MeshPattern().end_patch() with pytest.raises(cairo.Error): cairo.MeshPattern().curve_to(0, 1, 2, 3, 4, 5) with pytest.raises(cairo.Error): cairo.MeshPattern().line_to(130, 130) with pytest.raises(cairo.Error): cairo.MeshPattern().move_to(0, 0) with pytest.raises(cairo.Error): cairo.MeshPattern().set_corner_color_rgba(0, 0.125, 0.25, 0.5, 0.75) with pytest.raises(cairo.Error): cairo.MeshPattern().set_corner_color_rgb(0, 0.125, 0.25, 0.5) def test_get_matrix(): pattern = cairo.SolidPattern(1, 2, 4) assert isinstance(pattern.get_matrix(), cairo.Matrix) pattern.set_matrix(cairo.Matrix()) with pytest.raises(TypeError): pattern.set_matrix(object()) def test_set_extend(): pattern = cairo.SolidPattern(1, 2, 4) pattern.set_extend(42) assert pattern.get_extend() == 42 with pytest.raises(TypeError): pattern.set_extend(object()) def test_set_filter(): pattern = cairo.SolidPattern(1, 2, 4) with pytest.raises(TypeError): pattern.set_filter(object()) def test_pattern(): with pytest.raises(TypeError): cairo.Pattern() r, g, b, a = 0.1, 0.2, 0.3, 0.4 p = cairo.SolidPattern(r, g, b, a) assert p.get_rgba() == (r, g, b, a) assert not p == object() hash(p) with pytest.raises(TypeError): cairo.Gradient() x0, y0, x1, y1 = 0.0, 0.0, 0.0, 1.0 p = cairo.LinearGradient(x0, y0, x1, y1) assert p.get_linear_points() == (x0, y0, x1, y1) p.add_color_stop_rgba(1, 0, 0, 0, 1) p.add_color_stop_rgba(0, 1, 1, 1, 1) cx0, cy0, radius0, cx1, cy1, radius1 = 1.0, 1.0, 1.0, 2.0, 2.0, 1.0 p = cairo.RadialGradient(cx0, cy0, radius0, cx1, cy1, radius1) assert p.get_radial_circles() == (cx0, cy0, radius0, cx1, cy1, radius1) p.add_color_stop_rgba(0, 1, 1, 1, 1) p.add_color_stop_rgba(1, 0, 0, 0, 1) def test_pattern_filter(): pattern = cairo.SolidPattern(1, 2, 3) assert pattern.get_filter() == cairo.FILTER_GOOD pattern.set_filter(cairo.FILTER_NEAREST) assert pattern.get_filter() == cairo.FILTER_NEAREST def test_surface_pattern(): with pytest.raises(TypeError): cairo.SurfacePattern(object()) pycairo-1.16.2/tests/test_rectangle.py000066400000000000000000000024461323762421700200030ustar00rootroot00000000000000import cairo import pytest def test_type(): assert cairo.Rectangle assert issubclass(cairo.Rectangle, tuple) with pytest.raises(TypeError): cairo.Rectangle() r = cairo.Rectangle(0.0, 0.5, 0.25, 0.75) assert hash(r) == hash(cairo.Rectangle(0.0, 0.5, 0.25, 0.75)) assert isinstance(r, tuple) assert r == (0.0, 0.5, 0.25, 0.75) assert r == cairo.Rectangle(0.0, 0.5, 0.25, 0.75) assert r[1] == 0.5 assert r.width == 0.25 assert r.height == 0.75 assert r.x == 0.0 assert r.y == 0.5 with pytest.raises(AttributeError): assert r.z assert repr(r) == "cairo.Rectangle(x=0.0, y=0.5, width=0.25, height=0.75)" assert str(r) == repr(r) assert eval(repr(r)) == r def test_context(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) context.line_to(0, 5) context.line_to(5, 5) context.line_to(5, 0) context.line_to(0, 0) context.clip() rects = context.copy_clip_rectangle_list() assert rects assert len(rects) == 1 assert isinstance(rects[0], cairo.Rectangle) def test_recording_surface(): surface = cairo.RecordingSurface( cairo.CONTENT_COLOR, cairo.Rectangle(1, 1, 10, 10)) assert isinstance(surface.get_extents(), cairo.Rectangle) pycairo-1.16.2/tests/test_region.py000066400000000000000000000064651323762421700173270ustar00rootroot00000000000000import cairo import pytest def test_region(): with pytest.raises(TypeError): cairo.Region(object()) with pytest.raises(TypeError): cairo.Region(object(), object()) with pytest.raises(TypeError): cairo.Region([object()]) def test_get_rectangle(): rect = cairo.RectangleInt(0, 0, 10, 10) r = cairo.Region(rect) with pytest.raises(ValueError): r.get_rectangle(-1) with pytest.raises(ValueError): r.get_rectangle(1) assert r.get_rectangle(0) == rect with pytest.raises(TypeError): r.get_rectangle(object()) def test_contains_point(): rect = cairo.RectangleInt(0, 0, 10, 10) r = cairo.Region(rect) assert r.contains_point(0, 0) assert not r.contains_point(0, 20) with pytest.raises(TypeError): r.contains_point(0, object()) def test_intersect(): rect = cairo.RectangleInt(0, 0, 10, 10) r = cairo.Region(rect) r.intersect(r) r.intersect(rect) with pytest.raises(TypeError): r.intersect(object()) with pytest.raises(TypeError): r.intersect() assert r.__eq__(object()) == NotImplemented assert rect.__eq__(object()) == NotImplemented def test_equal(): rect = cairo.RectangleInt(0, 0, 10, 10) r = cairo.Region(rect) assert r.equal(r) with pytest.raises(TypeError): r.equal(object()) with pytest.raises(TypeError): r.equal() def test_subtract(): rect = cairo.RectangleInt(0, 0, 10, 10) r = cairo.Region(rect) r.subtract(r) with pytest.raises(TypeError): r.subtract(object()) with pytest.raises(TypeError): r.subtract() def test_union(): rect = cairo.RectangleInt(0, 0, 10, 10) r = cairo.Region(rect) r.union(r) r.union(rect) with pytest.raises(TypeError): r.union(object()) with pytest.raises(TypeError): r.union() def test_xor(): rect = cairo.RectangleInt(0, 0, 10, 10) r = cairo.Region(rect) r.xor(r) r.xor(rect) with pytest.raises(TypeError): r.xor(object()) with pytest.raises(TypeError): r.xor() def test_translate(): r = cairo.Region() r.translate(1, 1) with pytest.raises(TypeError): r.translate(1, object()) def test_region_contains_rectangle(): rect = cairo.RectangleInt(1, 2, 10, 13) region = cairo.Region() assert region.contains_rectangle(rect) == cairo.RegionOverlap.OUT assert isinstance(region.contains_rectangle(rect), cairo.RegionOverlap) with pytest.raises(TypeError): region.contains_rectangle(object()) def test_region_cmp_hash(): region = cairo.Region() other = cairo.Region() differ = cairo.Region(cairo.RectangleInt(0, 0, 10, 10)) with pytest.raises(TypeError): hash(region) assert region == region assert region == other assert not region != other assert region != differ with pytest.raises(TypeError): region < region with pytest.raises(TypeError): region > region rect = cairo.RectangleInt(1, 2, 10, 13) same = cairo.RectangleInt(1, 2, 10, 13) other = cairo.RectangleInt(2, 2, 10, 13) with pytest.raises(TypeError): hash(rect) assert rect == same assert rect != other with pytest.raises(TypeError): rect < same with pytest.raises(TypeError): rect > same pycairo-1.16.2/tests/test_surface.py000066400000000000000000000454621323762421700174740ustar00rootroot00000000000000# -*- coding: utf-8 -*- import io import os import sys import array import tempfile import struct import sysconfig import platform import cairo import pytest def test_surface_cmp_hash(): main = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) ctx = cairo.Context(main) assert ctx.get_target() == main assert not ctx.get_target() != main assert main != object() assert hash(ctx.get_target()) == hash(main) # we implement some hackery to change the underlying object after unmap # which would change the hash. Make sure this type is unhashable. mapped = main.map_to_image(None) with pytest.raises(TypeError): hash(mapped) assert mapped == mapped main.unmap_image(mapped) def test_surface_map_to_image(): main = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) image = main.map_to_image(None) with pytest.raises(TypeError): type(image)() other = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) with pytest.raises(ValueError): other.unmap_image(image) with pytest.raises(TypeError): main.unmap_image(other) with pytest.raises(RuntimeError): image.finish() main.unmap_image(image) with pytest.raises(RuntimeError): main.unmap_image(image) # from here on everything should fail with pytest.raises(cairo.Error): cairo.Context(image) with pytest.raises(TypeError): main.map_to_image(object()) with pytest.raises(TypeError): main.map_to_image() gced = main.map_to_image(None) del gced def test_surface_map_to_image_data(): main = cairo.ImageSurface(cairo.Format.RGB24, 2, 1) main.flush() assert bytes(main.get_data()) == b"\x00\x00\x00\x00\x00\x00\x00\x00" image = main.map_to_image(None) ctx = cairo.Context(image) ctx.set_source_rgb(1, 1, 1) ctx.paint() main.unmap_image(image) main.flush() assert bytes(main.get_data()) == b"\xff\xff\xff\xff\xff\xff\xff\xff" main = cairo.ImageSurface(cairo.Format.RGB24, 2, 1) image = main.map_to_image(cairo.RectangleInt(0, 0, 1, 1)) ctx = cairo.Context(image) ctx.set_source_rgb(1, 1, 1) ctx.paint() main.unmap_image(image) main.flush() assert bytes(main.get_data()) == b"\xff\xff\xff\xff\x00\x00\x00\x00" @pytest.mark.skipif(not cairo.HAS_TEE_SURFACE, reason="no tee surface") def test_tee_surface(): main = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) tee = cairo.TeeSurface(main) assert isinstance(tee, cairo.TeeSurface) with pytest.raises(TypeError): cairo.TeeSurface(object()) with pytest.raises(TypeError): tee.add(object()) with pytest.raises(TypeError): tee.remove(object()) with pytest.raises(TypeError): tee.index(object()) # the API is horrible, passing a wrong arg sets the surface to an error # state instead of returning the status. s1 = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) tee.add(s1) assert tee.index(0) assert tee.index(1) tee.remove(s1) @pytest.mark.skipif(not hasattr(sys, "getrefcount"), reason="PyPy") def test_image_surface_get_data_refcount(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) assert sys.getrefcount(surface) == 2 d = surface.get_data() assert sys.getrefcount(surface) == 3 del d assert sys.getrefcount(surface) == 2 def test_image_surface_get_data_crasher(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) try: assert 0, surface.get_data() except Exception: pass def test_surface_get_content(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) assert surface.get_content() == cairo.Content.COLOR_ALPHA assert isinstance(surface.get_content(), cairo.Content) def test_surface_get_format(): surface = cairo.ImageSurface(cairo.Format.ARGB32, 10, 10) assert surface.get_format() == cairo.Format.ARGB32 assert isinstance(surface.get_format(), cairo.Format) def test_pdf_get_versions(): versions = cairo.PDFSurface.get_versions() assert isinstance(versions, list) assert all(isinstance(v, cairo.PDFVersion) for v in versions) def test_pdf_set_size(): fileobj = io.BytesIO() surface = cairo.PDFSurface(fileobj, 128, 128) surface.set_size(10, 10) with pytest.raises(TypeError): surface.set_size(10, object()) @pytest.mark.skipif( sysconfig.get_platform().startswith("win"), reason="msvc fixme") def test_pdf_surface(): fd, fname = tempfile.mkstemp() os.close(fd) try: cairo.PDFSurface(fname, 10, 10).finish() finally: os.unlink(fname) with pytest.raises(TypeError): cairo.PDFSurface() with pytest.raises((ValueError, TypeError)): cairo.PDFSurface("\x00") with pytest.raises(TypeError): cairo.PDFSurface(object(), 100, 100) def test_svg_version_to_string(): ver = cairo.SVGSurface.version_to_string(cairo.SVG_VERSION_1_1) assert ver and isinstance(ver, str) with pytest.raises(ValueError): cairo.SVGSurface.version_to_string(-1) with pytest.raises(TypeError): cairo.SVGSurface.version_to_string(object()) def test_svg_surface_restrict_to_version(): surface = cairo.SVGSurface(None, 10, 10) surface.restrict_to_version(cairo.SVG_VERSION_1_1) surface.finish() with pytest.raises(cairo.Error): surface.restrict_to_version(cairo.SVG_VERSION_1_2) with pytest.raises(TypeError): surface.restrict_to_version(object()) @pytest.mark.skipif( sysconfig.get_platform().startswith("win"), reason="msvc fixme") def test_pdf_surface_restrict_to_version(): surface = cairo.PDFSurface(None, 10, 10) surface.restrict_to_version(cairo.PDF_VERSION_1_4) surface.finish() with pytest.raises(cairo.Error): surface.restrict_to_version(cairo.PDF_VERSION_1_5) with pytest.raises(TypeError): surface.restrict_to_version(object()) def test_pdf_version_to_string(): ver = cairo.PDFSurface.version_to_string(cairo.PDF_VERSION_1_4) assert ver and isinstance(ver, str) with pytest.raises(ValueError): cairo.PDFSurface.version_to_string(-1) with pytest.raises(TypeError): cairo.PDFSurface.version_to_string(object()) def test_ps_surface_misc(): surface = cairo.PSSurface(None, 10, 10) surface.dsc_begin_page_setup() surface.dsc_begin_setup() def test_ps_surface_dsc_comment(): surface = cairo.PSSurface(None, 10, 10) surface.dsc_comment("%%Title: My excellent document") with pytest.raises(cairo.Error): surface.dsc_comment("") with pytest.raises(TypeError): surface.dsc_comment(object()) def test_ps_get_eps(): surface = cairo.PSSurface(None, 10, 10) assert isinstance(surface.get_eps(), bool) surface.set_eps(True) assert surface.get_eps() with pytest.raises(TypeError): surface.set_eps(object()) def test_ps_set_size(): surface = cairo.PSSurface(None, 10, 10) surface.set_size(10, 10) with pytest.raises(TypeError): surface.set_size(10, object()) def test_ps_restrict_to_level(): surface = cairo.PSSurface(None, 10, 10) surface.restrict_to_level(cairo.PSLevel.LEVEL_2) with pytest.raises(TypeError): surface.restrict_to_level(object()) @pytest.mark.skipif( sysconfig.get_platform().startswith("win"), reason="msvc fixme") def test_ps_surface_level_to_string(): level_id = cairo.PSSurface.level_to_string(cairo.PS_LEVEL_2) assert isinstance(level_id, str) assert cairo.PSSurface.ps_level_to_string(cairo.PS_LEVEL_2) == level_id with pytest.raises(ValueError): cairo.PSSurface.level_to_string(-1) with pytest.raises(TypeError): cairo.PSSurface.level_to_string(object()) def test_ps_surface_get_levels(): levels = cairo.PSSurface.get_levels() assert isinstance(levels, list) assert all(isinstance(v, cairo.PSLevel) for v in levels) def test_ps_surface(): assert isinstance(cairo.PSSurface(None, 10, 10), cairo.PSSurface) fd, fname = tempfile.mkstemp() os.close(fd) try: cairo.PSSurface(fname, 10, 10).finish() finally: os.unlink(fname) with pytest.raises(TypeError): cairo.PSSurface() with pytest.raises((ValueError, TypeError)): cairo.PSSurface("\x00", 100, 100) with pytest.raises(TypeError): cairo.PSSurface(object(), 100, 100) def test_scg_surface(): fd, fname = tempfile.mkstemp() os.close(fd) try: cairo.SVGSurface(fname, 10, 10).finish() finally: os.unlink(fname) with pytest.raises(TypeError): cairo.SVGSurface() with pytest.raises((ValueError, TypeError)): cairo.SVGSurface("\x00", 10, 10) with pytest.raises(TypeError): cairo.SVGSurface(object(), 100, 100) def test_svg_surface_get_versions(): versions = cairo.SVGSurface.get_versions() assert isinstance(versions, list) assert all(isinstance(v, cairo.SVGVersion) for v in versions) def test_surface_get_device_scale(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) device_scale = surface.get_device_scale() assert all(isinstance(s, float) for s in device_scale) def test_surface_set_device_scale(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) ret = surface.set_device_scale(5.0, 3.0) assert ret is None surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100) with pytest.raises(cairo.Error): surface.set_device_scale(1, 0) with pytest.raises(TypeError): surface.set_device_scale(1, object()) def test_surface_create_for_rectangle(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100) new = surface.create_for_rectangle(0, 0, 10, 10) assert new assert isinstance(new, cairo.Surface) with pytest.raises(cairo.Error) as excinfo: surface.create_for_rectangle(0, 0, 10, -1) assert excinfo.value.status == cairo.STATUS_INVALID_SIZE with pytest.raises(TypeError): surface.create_for_rectangle(0, 0, 10, object()) def test_surface_create_similar_image(): surface = cairo.PDFSurface(None, 1, 1) image = surface.create_similar_image(cairo.FORMAT_ARGB32, 24, 42) assert image assert isinstance(image, cairo.ImageSurface) del surface assert image.get_width() == 24 assert image.get_height() == 42 surface = cairo.PDFSurface(None, 1, 1) with pytest.raises(TypeError): surface.create_similar_image(cairo.FORMAT_ARGB32, 24, object()) def test_surface_get_set_mime_data(): surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1) assert surface.get_mime_data("foo") is None assert surface.get_mime_data(cairo.MIME_TYPE_JPEG) is None surface.set_mime_data("foo", b"bar") assert surface.get_mime_data("foo") == b"bar" surface.set_mime_data("foo", None) assert surface.get_mime_data("foo") is None surface.set_mime_data(cairo.MIME_TYPE_JPEG, b"\x00quux\x00") assert surface.get_mime_data(cairo.MIME_TYPE_JPEG)[:] == b"\x00quux\x00" surface.set_mime_data(cairo.MIME_TYPE_JPEG, None) assert surface.get_mime_data(cairo.MIME_TYPE_JPEG) is None with pytest.raises(TypeError): surface.set_mime_data(cairo.MIME_TYPE_JPEG, object()) with pytest.raises(TypeError): surface.get_mime_data(object()) def test_supports_mime_type(): surface = cairo.PDFSurface(None, 3, 3) assert surface.supports_mime_type(cairo.MIME_TYPE_JPEG) assert not surface.supports_mime_type("nope") with pytest.raises(TypeError): surface.supports_mime_type(object()) # https://bitbucket.org/pypy/pypy/issues/2751 @pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy") def test_image_surface_create_for_data_array(): width, height = 255, 255 data = array.array('B', [0] * width * height * 4) for y in range(height): for x in range(width): offset = (x + (y * width)) * 4 alpha = y b = int(x * alpha / 255.0) g = int(y * alpha / 255.0) # cairo.FORMAT_ARGB32 uses pre-multiplied alpha data[offset:offset + 4] = array.array( "B", struct.pack("=I", b | g << 8 | alpha << 24)) surface = cairo.ImageSurface.create_for_data( data, cairo.FORMAT_ARGB32, width, height) # for debugging fd, filename = tempfile.mkstemp(prefix='pycairo_', suffix='.png') os.close(fd) surface.write_to_png(filename) os.unlink(filename) def test_image_surface_write_to_png_filename_and_obj_compare(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 128, 128) fd, filename = tempfile.mkstemp(prefix='pycairo_', suffix='.png') os.close(fd) surface.write_to_png(filename) fileobj = io.BytesIO() surface.write_to_png(fileobj) with open(filename, "rb") as h: assert h.read() == fileobj.getvalue() os.unlink(filename) def test_image_surface_png_obj_roundtrip(): fileobj = io.BytesIO() surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 128, 128) surface.write_to_png(fileobj) fileobj.seek(0) new_surface = cairo.ImageSurface.create_from_png(fileobj) assert surface.get_data() == new_surface.get_data() with pytest.raises(TypeError): cairo.ImageSurface.create_from_png() with pytest.raises((ValueError, TypeError)): cairo.ImageSurface.create_from_png("\x00") with pytest.raises(TypeError): cairo.ImageSurface.create_from_png(object()) def test_image_surface_png_file_roundtrip(): fd, filename = tempfile.mkstemp(prefix='pycairo_', suffix='.png') os.close(fd) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 128, 128) surface.write_to_png(filename) new_surface = cairo.ImageSurface.create_from_png(filename) assert surface.get_data() == new_surface.get_data() os.unlink(filename) def test_image_surface_write_to_png_error(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 128, 128) with pytest.raises(TypeError): surface.write_to_png(42) with pytest.raises((ValueError, TypeError)): surface.write_to_png("\x00") def test_surface_from_stream_closed_before_finished(): for Kind in [cairo.PDFSurface, cairo.PSSurface, cairo.SVGSurface]: fileobj = io.BytesIO() surface = cairo.PDFSurface(fileobj, 128, 128) fileobj.close() with pytest.raises(IOError): surface.finish() def test_script_surface(): f = io.BytesIO() dev = cairo.ScriptDevice(f) surface = cairo.ScriptSurface(dev, cairo.Content.COLOR_ALPHA, 42, 10) assert isinstance(surface, cairo.ScriptSurface) cairo.Context(surface).paint() dev.flush() assert b"42" in f.getvalue() assert b"paint" in f.getvalue() with pytest.raises(TypeError): cairo.ScriptSurface() def test_script_device_device_ref(): f = io.BytesIO() dev = cairo.ScriptDevice(f) surface = cairo.ScriptSurface(dev, cairo.Content.COLOR_ALPHA, 42, 10) del dev for i in range(10): surface.get_device() def test_script_surface_create_for_target(): # paint the script proxy f = io.BytesIO() dev = cairo.ScriptDevice(f) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) script = cairo.ScriptSurface.create_for_target(dev, surface) with pytest.raises(TypeError): cairo.ScriptSurface.create_for_target(dev, object()) assert isinstance(script, cairo.ScriptSurface) ctx = cairo.Context(script) ctx.set_source_rgb(0.25, 0.5, 1.0) ctx.paint() assert b"paint" in f.getvalue() surface.flush() image_data = bytes(surface.get_data()) # check if the result is the same surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) ctx = cairo.Context(surface) ctx.set_source_rgb(0.25, 0.5, 1.0) ctx.paint() surface.flush() assert bytes(surface.get_data()) == image_data def test_misc(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) surface.copy_page() surface.mark_dirty() surface.show_page() @pytest.fixture def surface(): return cairo.ImageSurface(cairo.Format.ARGB32, 10, 10) @pytest.fixture def image_surface(): return cairo.ImageSurface(cairo.Format.ARGB32, 10, 10) def test_create_similar(surface): similar = surface.create_similar(cairo.Content.COLOR, 10, 10) assert isinstance(similar, cairo.Surface) with pytest.raises(TypeError): surface.create_similar() def test_get_device_offset(surface): surface.set_device_offset(1, 1) assert surface.get_device_offset() == (1, 1) with pytest.raises(TypeError): surface.set_device_offset(1, object()) def test_get_fallback_resolution(surface): surface.set_fallback_resolution(42, 42) assert surface.get_fallback_resolution() == (42, 42) with pytest.raises(TypeError): surface.set_fallback_resolution(42, object()) def test_mark_dirty_rectangle(surface): surface.mark_dirty_rectangle(0, 0, 10, 10) with pytest.raises(TypeError): surface.mark_dirty_rectangle(0, 0, 10, object()) def test_write_to_png(image_surface): with pytest.raises(TypeError): image_surface.write_to_png() with pytest.raises((ValueError, TypeError)) as excinfo: image_surface.write_to_png("\x00") excinfo.match(r'.* (null|NUL) .*') with pytest.raises(TypeError): image_surface.write_to_png(object()) def test_image_surface(): with pytest.raises(TypeError): cairo.ImageSurface(cairo.FORMAT_ARGB32, 3, object()) def test_image_surface_create_for_data(): format_ = cairo.FORMAT_ARGB32 surface = cairo.ImageSurface(format_, 3, 3) ctx = cairo.Context(surface) ctx.paint() surface.flush() buf = surface.get_data() new = cairo.ImageSurface.create_for_data(buf, format_, 3, 3) assert new.get_data() == buf with pytest.raises(ValueError): cairo.ImageSurface.create_for_data(buf, format_, 3, -1) with pytest.raises(ValueError): cairo.ImageSurface.create_for_data(buf, format_, -1, 3) with pytest.raises(ValueError): cairo.ImageSurface.create_for_data(buf, format_, 0, 0, -1) with pytest.raises(cairo.Error) as excinfo: cairo.ImageSurface.create_for_data(buf, format_, 3, 3, 3) assert excinfo.value.status == cairo.STATUS_INVALID_STRIDE with pytest.raises(TypeError): cairo.ImageSurface.create_for_data(buf, format_, 3, object()) def test_image_surface_stride_for_width(): v = cairo.ImageSurface.format_stride_for_width(cairo.Format.ARGB32, 10) assert v == 40 with pytest.raises(TypeError): cairo.ImageSurface.format_stride_for_width( cairo.Format.ARGB32, object()) def test_image_surface_get_stride(image_surface): assert image_surface.get_stride() == 40 def test_recording_surface(): with pytest.raises(TypeError): cairo.RecordingSurface(cairo.CONTENT_COLOR, object()) with pytest.raises(TypeError): cairo.RecordingSurface() surface = cairo.RecordingSurface(cairo.CONTENT_COLOR, None) assert surface.ink_extents() == (0.0, 0.0, 0.0, 0.0) pycairo-1.16.2/tests/test_surface_numpy.py000066400000000000000000000031171323762421700207130ustar00rootroot00000000000000# -*- coding: utf-8 -*- import os import tempfile import cairo import pytest numpy = pytest.importorskip("numpy") def test_image_surface_create_for_data_numpy_array(): width, height = 255, 255 data = numpy.ndarray(shape=(height, width), dtype=numpy.uint32) for y in range(height): for x in range(width): alpha = y b = int(x * alpha / 255.0) g = int(y * alpha / 255.0) data[y][x] = (b | g << 8 | alpha << 24) surface = cairo.ImageSurface.create_for_data( data, cairo.FORMAT_ARGB32, width, height) # for debugging fd, filename = tempfile.mkstemp(prefix='pycairo_', suffix='.png') os.close(fd) surface.write_to_png(filename) os.unlink(filename) def test_image_surface_get_data_to_numpy_array(): w, h = 128, 128 surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h) ctx = cairo.Context(surface) ctx.set_source_rgb(1, 1, 1) # white ctx.set_operator(cairo.OPERATOR_SOURCE) ctx.paint() # Draw out the triangle using absolute coordinates ctx.move_to(w / 2, h / 3) ctx.line_to(2 * w / 3, 2 * h / 3) ctx.rel_line_to(-1 * w / 3, 0) ctx.close_path() ctx.set_source_rgb(0, 0, 0) # black ctx.set_line_width(15) ctx.stroke() buf = surface.get_data() a = numpy.ndarray(shape=(w, h), dtype=numpy.uint32, buffer=buf) # draw a vertical blue line a[:, 40] = 0xff | 0xff << 24 # for debugging fd, filename = tempfile.mkstemp(prefix='pycairo_', suffix='.png') os.close(fd) surface.write_to_png(filename) os.unlink(filename) pycairo-1.16.2/tests/test_surface_pygame.py000066400000000000000000000005321323762421700210230ustar00rootroot00000000000000# -*- coding: utf-8 -*- import cairo import pytest pygame = pytest.importorskip("pygame") def test_image_surface_to_pygame_image(): width, height = 100, 100 surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) buf = surface.get_data() image = pygame.image.frombuffer(buf, (width, height), "ARGB") assert image pycairo-1.16.2/tests/test_textcluster.py000066400000000000000000000012411323762421700204150ustar00rootroot00000000000000import cairo import pytest def test_type(): assert cairo.TextCluster assert issubclass(cairo.TextCluster, tuple) with pytest.raises(TypeError): cairo.TextCluster() r = cairo.TextCluster(2, 1) assert hash(r) == hash(cairo.TextCluster(2, 1)) assert isinstance(r, tuple) assert r == (2, 1) assert r == cairo.TextCluster(2, 1) assert r[1] == 1 assert r.num_bytes == 2 assert r.num_glyphs == 1 with pytest.raises(AttributeError): assert r.z assert repr(r) == "cairo.TextCluster(num_bytes=2, num_glyphs=1)" assert str(r) == "cairo.TextCluster(num_bytes=2, num_glyphs=1)" assert eval(repr(r)) == r pycairo-1.16.2/tests/test_textextents.py000066400000000000000000000026601323762421700204340ustar00rootroot00000000000000import cairo import pytest def test_type(): assert cairo.TextExtents assert issubclass(cairo.TextExtents, tuple) with pytest.raises(TypeError): cairo.TextExtents() r = cairo.TextExtents(0.0, 0.5, 0.25, 0.75, 0.5, 0.125) assert hash(r) == hash(cairo.TextExtents(0.0, 0.5, 0.25, 0.75, 0.5, 0.125)) assert isinstance(r, tuple) assert r == (0.0, 0.5, 0.25, 0.75, 0.5, 0.125) assert r == cairo.TextExtents(0.0, 0.5, 0.25, 0.75, 0.5, 0.125) assert r[1] == 0.5 assert r.width == 0.25 assert r.height == 0.75 assert r.x_bearing == 0.0 assert r.y_bearing == 0.5 with pytest.raises(AttributeError): assert r.z assert repr(r) == \ "cairo.TextExtents(x_bearing=0.0, y_bearing=0.5, " \ "width=0.25, height=0.75, x_advance=0.5, " \ "y_advance=0.125)" assert str(r) == repr(r) assert eval(repr(r)) == r def test_methods(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) extents = context.glyph_extents([cairo.Glyph(0, 0, 0)]) assert isinstance(extents, cairo.TextExtents) extents = context.text_extents("foo") assert isinstance(extents, cairo.TextExtents) sf = context.get_scaled_font() extents = sf.text_extents("foo") assert isinstance(extents, cairo.TextExtents) extents = sf.glyph_extents([cairo.Glyph(0, 0, 0)]) assert isinstance(extents, cairo.TextExtents)