pax_global_header00006660000000000000000000000064145147646640014533gustar00rootroot0000000000000052 comment=26b3287bffbd91b5a2a41be72090a3a23b1fc98c pycairo-1.25.1/000077500000000000000000000000001451476466400132675ustar00rootroot00000000000000pycairo-1.25.1/.ci/000077500000000000000000000000001451476466400137405ustar00rootroot00000000000000pycairo-1.25.1/.ci/download-cairo-win32.py000066400000000000000000000057101451476466400201570ustar00rootroot00000000000000from __future__ import annotations import logging import os import sys import re import shutil import struct import tempfile import zipfile from pathlib import Path from urllib.request import urlretrieve as download CAIRO_VERSION = "1.18.0" def get_platform() -> str: if len(sys.argv) > 1: return sys.argv[1] if (struct.calcsize("P") * 8) == 32: return "x86" else: return "x64" logging.basicConfig(format="%(levelname)s - %(message)s", level=logging.DEBUG) plat = get_platform() logging.debug(f"Found Platform {plat}") download_url = ( "https://github.com/pygobject/cairo-win-build/releases" f"/download/{CAIRO_VERSION}/cairo-{CAIRO_VERSION}-{plat}.zip" ) final_location = Path(__file__).parent.parent / "cairo-prebuild" download_location = Path(tempfile.mkdtemp()) if final_location.exists(): logging.info("Final Location already exists clearing it...") shutil.rmtree(str(final_location)) final_location.mkdir() download_file = download_location / "build.zip" logging.info("Downloading Cairo Binaries for Windows...") logging.info("Url: %s", download_url) download(url=download_url, filename=download_file) logging.info(f"Download complete. Saved to {download_file}.") logging.info(f"Extracting {download_file} to {download_location}...") with zipfile.ZipFile( download_file, mode="r", compression=zipfile.ZIP_DEFLATED ) as file: # noqa: E501 file.extractall(download_location) os.remove(download_file) logging.info("Completed Extracting.") logging.info("Moving Files accordingly.") plat_location = download_location / f"cairo-{plat}" for src_file in plat_location.glob("*"): logging.debug(f"Moving {src_file} to {final_location}...") shutil.move(str(src_file), str(final_location)) logging.info("Moving files Completed") logging.info("Fixing .pc files") rex = re.compile("^prefix=(.*)") def new_place(_: re.Match[str]) -> str: return f"prefix={str(final_location.as_posix())}" pc_files = final_location / "lib" / "pkgconfig" for i in pc_files.glob("*.pc"): logging.info(f"Writing {i}") with open(i) as f: content = f.read() final = rex.sub(new_place, content) with open(i, "w") as f: f.write(final) logging.info("Getting pkg-config") download( url="https://github.com/pygobject/cairo-win-build" f"/releases/download/{CAIRO_VERSION}/pkgconf.zip", filename=download_file, ) with zipfile.ZipFile( download_file, mode="r", compression=zipfile.ZIP_DEFLATED ) as file: # noqa: E501 file.extractall(download_location) os.makedirs(str(final_location / "bin")) shutil.move( str(download_location / "pkgconf" / "bin" / "pkgconf.exe"), str(final_location / "bin"), ) # On MSVC, meson would create static libraries as # libcairo.a but setuptools doens't know about it. libreg = re.compile(r"lib(?P\S*)\.a") libdir = final_location / "lib" for lib in libdir.glob("lib*.a"): name = libreg.match(lib.name).group("name") + ".lib" shutil.move(lib, libdir / name) pycairo-1.25.1/.ci/test-wheels.sh000066400000000000000000000004171451476466400165420ustar00rootroot00000000000000#!/bin/bash set -e set -x project_dir=$1 # Move the $(project_dir)/tests to a temporary directory # so that the tests doesn't use inplace build. tmp_dir=$(mktemp -d) cp -r $project_dir/tests $tmp_dir cd $tmp_dir/tests # Run the tests python -m pytest $tmp_dir/tests pycairo-1.25.1/.codecov.yml000066400000000000000000000001331451476466400155070ustar00rootroot00000000000000comment: false coverage: status: project: false patch: false changes: false pycairo-1.25.1/.github/000077500000000000000000000000001451476466400146275ustar00rootroot00000000000000pycairo-1.25.1/.github/workflows/000077500000000000000000000000001451476466400166645ustar00rootroot00000000000000pycairo-1.25.1/.github/workflows/test.yml000066400000000000000000000157731451476466400204030ustar00rootroot00000000000000name: Test on: push: pull_request: jobs: msys2: runs-on: windows-latest strategy: fail-fast: false matrix: include: - msystem: MINGW64 arch: x86_64 - msystem: MINGW32 arch: i686 steps: - name: Checkout code uses: actions/checkout@v3 - name: setup-msys2 uses: msys2/setup-msys2@v2 with: msystem: ${{ matrix.msystem }} update: true install: >- git mingw-w64-${{ matrix.arch }}-cairo mingw-w64-${{ matrix.arch }}-python mingw-w64-${{ matrix.arch }}-python-pip mingw-w64-${{ matrix.arch }}-cc mingw-w64-${{ matrix.arch }}-meson mingw-w64-${{ matrix.arch }}-ninja mingw-w64-${{ matrix.arch }}-pkg-config - name: Install dependencies shell: msys2 {0} run: | python -m pip install pytest coverage hypothesis setuptools wheel - name: Build & Test with setuptools shell: msys2 {0} run: | export SETUPTOOLS_USE_DISTUTILS=stdlib export CFLAGS="-std=c90 -Wall -Wno-long-long -Werror -coverage" python -m coverage run --branch setup.py test python -m coverage xml -i python setup.py sdist python setup.py bdist_wheel python setup.py install --root="$(pwd)"/_root_abs - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 - name: Build & Install with pip shell: msys2 {0} run: | git clean -xfdf export SETUPTOOLS_USE_DISTUTILS=stdlib python -m pip install . - name: Build & Test with meson shell: msys2 {0} run: | git clean -xfdf meson --werror _build meson compile -C _build meson test -v -C _build ubuntu: runs-on: ubuntu-latest strategy: fail-fast: false matrix: python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', 'pypy-3.8'] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} allow-prereleases: true - name: Install dependencies run: | sudo apt-get update -q sudo apt-get install -y libcairo2-dev ninja-build python -m pip install --upgrade setuptools python -m pip install --upgrade pytest flake8 coverage hypothesis wheel poetry meson python -m pip install --upgrade pygame || true - name: Build & Test with setuptools run: | export CFLAGS="-Werror -coverage" python -m coverage run --branch setup.py test python -m coverage xml -i python setup.py sdist python setup.py bdist_wheel python setup.py install --root="$(pwd)"/_root_abs - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 - name: Build & Install with pip run: | git clean -xfdf python -m pip install . - name: Build & Test with meson run: | git clean -xfdf meson --werror _build meson compile -C _build meson test -v -C _build - name: Build & Test with poetry if: ${{ matrix.python-version != 'pypy-3.8' }} run: | git clean -xfdf poetry install poetry run python setup.py test - name: Run linters if: ${{ matrix.python-version != 'pypy-3.8' }} run: | poetry run flake8 poetry run mypy . - name: Build docs if: ${{ matrix.python-version != 'pypy-3.8' }} run: | poetry run python -m sphinx -W -a -E -b html -n docs docs/_build msvc: runs-on: windows-latest strategy: fail-fast: false matrix: python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] architecture: ['x86', 'x64'] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} architecture: ${{ matrix.architecture }} allow-prereleases: true - name: Download and extract Cairo Binary run: | python .ci/download-cairo-win32.py - name: Build env: PKG_CONFIG: ${{ github.workspace }}/cairo-prebuild/bin/pkgconf.exe PKG_CONFIG_PATH: ${{ github.workspace }}/cairo-prebuild/lib/pkgconfig run: | python -m pip install --upgrade pip if (-not $?) { exit 1 } python -m pip install --upgrade wheel if (-not $?) { exit 1 } python -m pip install --upgrade setuptools if (-not $?) { exit 1 } python -m pip install --upgrade pytest flake8 coverage hypothesis if (-not $?) { exit 1 } python -m pip install --upgrade pygame python -m coverage run --branch setup.py test if (-not $?) { exit 1 } python -m coverage xml -i if (-not $?) { exit 1 } python -m flake8 . if (-not $?) { exit 1 } python setup.py sdist if (-not $?) { exit 1 } python setup.py bdist if (-not $?) { exit 1 } python setup.py install --root=_root if (-not $?) { exit 1 } python setup.py bdist_wheel if (-not $?) { exit 1 } python setup.py install --root=_root_setup if (-not $?) { exit 1 } python -m pip install . if (-not $?) { exit 1 } - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 - uses: actions/upload-artifact@v3 with: name: wheels-${{ matrix.python-version }} path: dist/pycairo*.whl macos: runs-on: macos-latest steps: - name: Checkout code uses: actions/checkout@v3 - name: Install dependencies run: | brew install pkg-config cairo python meson python3 -m pip install --upgrade setuptools python3 -m pip install --upgrade pytest coverage hypothesis wheel - name: Build & Test with setuptools run: | python3 -m coverage run --branch setup.py test python3 -m coverage xml -i python3 setup.py sdist python3 setup.py install --root="$(pwd)"/_root_abs python3 setup.py bdist_wheel python3 -m pip install . - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 - name: Build & Install with pip run: | git clean -xfdf python3 -m pip install . - name: Build & Test with meson run: | git clean -xfdf meson --werror _build meson compile -C _build meson test -v -C _build pycairo-1.25.1/.github/workflows/wheels.yml000066400000000000000000000025571451476466400207070ustar00rootroot00000000000000name: Build on: [push, pull_request] jobs: build_wheels: name: Build wheels on ${{ matrix.os }} (${{ matrix.platform_id }}) runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: include: - os: windows-2019 platform_id: win_amd64 cairo_plat: x64 - os: windows-2019 platform_id: win32 cairo_plat: x86 - os: windows-2019 platform_id: win_arm64 cairo_plat: arm64 steps: - uses: actions/checkout@v3 - name: Build wheels uses: pypa/cibuildwheel@v2.15 env: CIBW_ARCHS_WINDOWS: "x86 ARM64 AMD64" CIBW_BEFORE_BUILD: "python {package}/.ci/download-cairo-win32.py ${{ matrix.cairo_plat }}" CIBW_BUILD: cp38-${{ matrix.platform_id }} cp39-${{ matrix.platform_id }} cp310-${{ matrix.platform_id }} cp311-${{ matrix.platform_id }} cp312-${{ matrix.platform_id }} CIBW_TEST_REQUIRES: pytest hypothesis attrs CIBW_TEST_COMMAND: bash {package}/.ci/test-wheels.sh {package} CIBW_TEST_SKIP: "*-win_arm64" CIBW_ENVIRONMENT_WINDOWS: PKG_CONFIG_PATH='${{ github.workspace }}/cairo-prebuild/lib/pkgconfig' PKG_CONFIG='${{ github.workspace }}/cairo-prebuild/bin/pkgconf.exe' - uses: actions/upload-artifact@v3 with: path: ./wheelhouse/*.whl pycairo-1.25.1/.gitignore000066400000000000000000000011561451476466400152620ustar00rootroot00000000000000# top-level .gitignore *~ .*.sw? .deps .libs .lock* .perf .waf* *.la *.lo *.orig *.rej *.pyc *.pyo *.so .cache MANIFEST dist .hypothesis *.pyd *.dll .mypy_cache .pytest_cache .idea *.egg-info # 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 poetry.lock .vscode build-* .venv cairo-prebuild/ pycairo-1.25.1/.readthedocs.yaml000066400000000000000000000001761451476466400165220ustar00rootroot00000000000000version: 2 sphinx: configuration: docs/conf.py python: version: 3.8 install: - requirements: docs/requirements.txtpycairo-1.25.1/COPYING000066400000000000000000000012401451476466400143170ustar00rootroot00000000000000PyCairo 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. SPDX-License-Identifier: LGPL-2.1-only OR MPL-1.1 pycairo-1.25.1/COPYING-LGPL-2.1000066400000000000000000000636401451476466400153650ustar00rootroot00000000000000 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.25.1/COPYING-MPL-1.1000066400000000000000000000622331451476466400152530ustar00rootroot00000000000000 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.25.1/MANIFEST.in000066400000000000000000000005621451476466400150300ustar00rootroot00000000000000include COPYING* include NEWS include README.rst include MANIFEST.in include PKG-INFO.in include pyproject.toml include setup.cfg include meson_options.txt recursive-include . meson.build recursive-include docs *.py Makefile *.rst *.css *.svg prune docs/_build recursive-include tests *.py README *.c *.h recursive-include examples *.py README *.ipynb include cairo/*.h pycairo-1.25.1/NEWS000066400000000000000000000771501451476466400140000ustar00rootroot00000000000000Since version 1.11.0 Pycairo uses `Semantic Versioning `__ .. _v1.25.1: 1.25.1 - 2023-10-21 ------------------- * Fix a crash with pypy3.10 :pr:`344` * Fix the build with CPython 3.13.0a1 :pr:`343` .. _v1.25.0: 1.25.0 - 2023-09-26 ------------------- * Update to cairo 1.18.0 for the Windows wheel * Provide a Windows arm64 wheel * New APIs: * :attr:`Status.SVG_FONT_ERROR` :pr:`334` * :meth:`FontOptions.get_color_mode`, :meth:`FontOptions.set_color_mode`, :class:`ColorMode` :pr:`336` * :meth:`FontOptions.set_color_palette`, :meth:`FontOptions.get_color_palette`, :attr:`COLOR_PALETTE_DEFAULT` :pr:`338` * :meth:`FontOptions.set_custom_palette_color`, :meth:`FontOptions.get_custom_palette_color` :pr:`339` * :attr:`TAG_CONTENT`, :attr:`TAG_CONTENT_REF` :pr:`340` * :meth:`Pattern.get_dither`, :meth:`Pattern.set_dither`, :class:`Dither` :pr:`341` .. _v1.24.0: 1.24.0 - 2023-06-19 ------------------- * Dropped Python 3.7 support * Bumped meson version requirement from 0.53.0 to 0.56.0 * Various cairo dependency updates for the Windows wheel build * examples: update to GTK4 :pr:`307` * examples: add a clip_image example :pr:`316` * docs: fix the build with Sphinx 6 :pr:`318` * Various code cleanups :pr:`306` * Added Python 3.12 Windows wheels .. _v1.23.0: 1.23.0 - 2022-11-28 ------------------- Reminder to distro packagers: Building/installing pycairo using setup.py is deprecated, please use meson instead. * git: changed default branch from "master" to "main" * Windows: Update the cairo version included in the wheels from 1.17.2 to 1.17.6 :pr:`243` * docs: Document how to look up pycairo headers without loading the module :pr:`300` * tests: don't error out if cairo wasn't built with all features :pr:`293` * New APIs: * :attr:`Status.DWRITE_ERROR` :pr:`294` * :attr:`Format.RGB96F`, :attr:`Format.RGBA128F` :pr:`295` * :attr:`PDFVersion.VERSION_1_6`, :attr:`PDFVersion.VERSION_1_7` :pr:`296` * :attr:`HAS_DWRITE_FONT` :pr:`297` * :meth:`Context.set_hairline`, :meth:`Context.get_hairline` :pr:`298` * :meth:`PDFSurface.set_custom_metadata` :pr:`299` .. _v1.22.0: 1.22.0 - 2022-11-19 ------------------- * Officially support Python 3.11 :pr:`285` * PDFSurface.version_to_string(): Fix crash with negative versions :pr:`279` * typing: ImageSurface.get_stride() returns an int :pr:`282` * typing: Fix incorrect interface for Matrix constructor :pr:`271` * typing: Use Generic for Context :pr:`274` * docs: some cairo.Context fixes :pr:`276` * docs: try to make create_from_png/write_to_png more clear :pr:`261` * docs: add an example for how to convert a surface to pillow :pr:`281` * docs: cairo.Format.RGB24: document that unused bytes may be overwritten :pr:`289` * tests: don't depend on specific ref counts :pr:`291` * tests: compatibility fixes for cairo 1.17.6 :pr:`264` .. _v1.21.0: 1.21.0 - 2022-03-07 ------------------- * Require Python 3.7+ :pr:`250` * Require meson 0.53+ * Using `setup.py` directly to build/install pycairo is deprecated. Use meson instead. * `setup.py` now requires setuptools. Previously it was optional. * The complete API reference is now included in the typing stubs, so it can be consumed/shown by IDEs. :pr:`236` :pr:`252` .. _v1.20.1: 1.20.1 - 2021-06-03 ------------------- * Use poetry for development :pr:`232` * setup.py: Respect the PKG_CONFIG environment variable :pr:`235` * Make import_cairo inline in addition to static :pr:`224` * docs: Fix example in Pattern.set_filter() docs :pr:`221` * docs: Fix build with newer sphinx :pr:`222` * docs: Fix NumPy width, height-conventions in examples :pr:`231` * docs: Last parameter of rel_curve_to should be dy3, not dy4 :pr:`230` * mypy: Fixes for mypy 0.800+ :pr:`233` * mypy: Don't run mypy via pytest :pr:`234` .. _v1.20.0: 1.20.0 - 2020-10-05 ------------------- * Require Python 3.6+ :pr:`201` * Require cairo 1.15.10+ :pr:`204` * docs: support Sphinx 3.0 :pr:`207` * meson: add 'tests' option to skip tests :pr:`188` * Windows: build wheels :pr:`197` * Add support for Python 3.9 and 3.10 :pr:`198` :pr:`202` * examples: add a Jupyter Notebook example :pr:`181` * Raise an error early when being passed a file object not opened in binary mode :pr:`205` * Add a pyproject.toml file :pr:`206` .. _v1.19.1: 1.19.1 - 2020-02-16 ------------------- * docs: Add moderngl in the integration section. :pr:`174` (:user:`Einar Forselv `) * Support os.PathLike with PyPy3 >= 7.3.0 .. _v1.19.0: 1.19.0 - 2020-01-23 ------------------- * Python 2 is no longer supported :pr:`172` * Add machine-readable license statement :pr:`158` (:user:`Maxim Ivanov `) * travis-ci: Manually set sysroot so correct SDK is used (:user:`Stuart Axon `) * Support Python 3.8 on Windows (because of DLL lookup changes) * Fix wrong type for set_dash() offset parameter in the docs/types. .. _v1.18.2: 1.18.2 - 2019-10-24 ------------------- * Fix a minor compatibility issue with Python 3.8 (fixes the test suite) .. _v1.18.1: 1.18.1 - 2019-04-19 ------------------- * meson: install .egg-info to platlib * meson: fix configure error with meson 0.50 re absolute paths :pr:`145` * PyPy: don't use PyOS_FSPath() with PyPy3.6, it's missing: https://foss.heptapod.net/pypy/pypy/-/issues/2961 * Docs fixes :pr:`134` (:user:`Matteo Italia `) .. _v1.18.0: 1.18.0 - 2018-11-04 ------------------- Build: * Dropped Python 3.3 support * meson build requires meson >=0.47 (was >=0.46) * Fix various build warnings with GCC8 * meson: Don't link against libpython on non-Windows systems :pr:`120` * meson: Improve support for Visual Studio builds :pr:`121` (:user:`Chun-wei Fan `) * setup.py: Support specifying custom ``--pkgconfigdir`` :pr:`127` (:user:`MichaÅ‚ Górny `) Fixes: * docs: Remove a broken link :pr:`124` (:user:`Nik Nyby `) * typing: Add missing annotations for __enter__/__exit__ :pr:`126` New API: Some are only available when building with newer cairo versions, see the linked API docs for details. * :data:`CAIRO_VERSION`, :data:`CAIRO_VERSION_STRING`, :data:`CAIRO_VERSION_MAJOR`, :data:`CAIRO_VERSION_MINOR`, :data:`CAIRO_VERSION_MICRO` * :attr:`Status.TAG_ERROR`, :attr:`Status.FREETYPE_ERROR`, :attr:`Status.PNG_ERROR`, :attr:`Status.WIN32_GDI_ERROR` * :class:`SVGUnit`, :class:`PDFMetadata`, :class:`PDFOutlineFlags` * :meth:`FontOptions.set_variations`, :meth:`FontOptions.get_variations` * :meth:`Context.tag_begin`, :meth:`Context.tag_end`, :data:`TAG_DEST`, :data:`TAG_LINK` * :meth:`PDFSurface.set_page_label`, :meth:`PDFSurface.set_metadata`, :meth:`PDFSurface.set_thumbnail_size`, :meth:`PDFSurface.add_outline`, :data:`PDF_OUTLINE_ROOT` * :meth:`SVGSurface.set_document_unit`, :meth:`SVGSurface.get_document_unit` * :data:`MIME_TYPE_CCITT_FAX`, :data:`MIME_TYPE_CCITT_FAX_PARAMS`, :data:`MIME_TYPE_EPS`, :data:`MIME_TYPE_EPS_PARAMS`, :data:`MIME_TYPE_JBIG2`, :data:`MIME_TYPE_JBIG2_GLOBAL`, :data:`MIME_TYPE_JBIG2_GLOBAL_ID` .. _v1.17.1: 1.17.1 - 2018-07-07 ------------------- * `Meson `__ support (>=0.46). :bug:`114` .. _v1.17.0: 1.17.0 - 2018-04-15 ------------------- * :class:`cairo.Surface` and :class:`cairo.Device` can now be used as context managers. :bug:`103` * Fix a leak when a cairo error was raised. * Fix a leak when a mapped surface was GCed instead of unmapped. * Make it possible to use the C API with Python 3 outside of the compilation unit doing the import by defining ``PYCAIRO_NO_IMPORT``. :bug:`110` * Implement PEP 561 (added a py.typed marker) .. _v1.16.3: 1.16.3 - 2018-02-27 ------------------- * Ship Python type annotation stubs. They are currently supported by mypy and PyCharm. :bug:`99` :pr:`101` .. _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.25.1/PKG-INFO.in000066400000000000000000000013311451476466400147670ustar00rootroot00000000000000Metadata-Version: 1.2 Name: pycairo Version: @VERSION@ Summary: Python interface for cairo Home-page: https://pycairo.readthedocs.io Maintainer: Christoph Reiter Maintainer-email: reiter.christoph@gmail.com License: UNKNOWN Description: Pycairo is a Python module providing bindings for the cairo graphics library Platform: UNKNOWN Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 (LGPLv2) Classifier: License :: OSI Approved :: Mozilla Public License 1.1 (MPL 1.1) pycairo-1.25.1/README.rst000066400000000000000000000035761451476466400147710ustar00rootroot00000000000000.. image:: https://raw.githubusercontent.com/pygobject/pycairo/main/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.15.10** and works with **Python 3.8+** and **PyPy3**. Pycairo, including this documentation, is licensed under the `LGPL-2.1-only OR MPL-1.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. .. code:: shell pip install pycairo Installing Pycairo requires cairo including its headers. For more info see "`Getting Started `__". ---- .. code:: python import cairo with cairo.SVGSurface("example.svg", 200, 200) as surface: 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() .. image:: https://raw.githubusercontent.com/pygobject/pycairo/main/docs/images/example.svg :width: 320px :align: center ---- 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. * Fully typed and documented API. For more information visit https://pycairo.readthedocs.io pycairo-1.25.1/cairo/000077500000000000000000000000001451476466400143645ustar00rootroot00000000000000pycairo-1.25.1/cairo/__init__.py000077500000000000000000000012241451476466400164770ustar00rootroot00000000000000from ._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.25.1/cairo/__init__.pyi000066400000000000000000006503531451476466400166620ustar00rootroot00000000000000from __future__ import annotations from typing import (Any, BinaryIO, ByteString, Callable, Generic, List, Optional, Sequence, Text, Tuple, TypeVar, Union) del annotations HAS_ATSUI_FONT: bool = ... HAS_FT_FONT: bool = ... HAS_GLITZ_SURFACE: bool = ... HAS_IMAGE_SURFACE: bool = ... HAS_MIME_SURFACE: bool = ... """ .. versionadded:: 1.12.0 """ HAS_PDF_SURFACE: bool = ... HAS_PNG_FUNCTIONS: bool = ... HAS_PS_SURFACE: bool = ... HAS_QUARTZ_SURFACE: bool = ... HAS_RECORDING_SURFACE: bool = ... HAS_SCRIPT_SURFACE: bool = ... """ .. versionadded:: 1.12.0 """ HAS_SVG_SURFACE: bool = ... HAS_TEE_SURFACE: bool = ... """ .. versionadded:: 1.15.3 """ HAS_USER_FONT: bool = ... HAS_WIN32_FONT: bool = ... HAS_WIN32_SURFACE: bool = ... HAS_XCB_SURFACE: bool = ... HAS_XLIB_SURFACE: bool = ... HAS_DWRITE_FONT: bool = ... """ .. versionadded:: 1.23.0 """ PDF_OUTLINE_ROOT: int = ... """ The root outline item in :meth:`PDFSurface.add_outline` .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ COLOR_PALETTE_DEFAULT: int = ... """ The default color palette index. See :meth:`FontOptions.set_color_palette` .. versionadded:: 1.25.0 Only available with cairo 1.17.8+ """ version: str = ... """the pycairo version, as a string""" version_info: Tuple[int, int, int] = ... """the pycairo version, as a tuple""" CAIRO_VERSION: int = ... """ The version of cairo available at compile-time in the same format as returned by :func:`cairo_version` .. versionadded:: 1.18.0 """ CAIRO_VERSION_STRING: str = ... """ A human-readable string literal containing the version of cairo available at compile-time, in the form of "X.Y.Z". .. versionadded:: 1.18.0 """ CAIRO_VERSION_MAJOR: int = ... """ The major component of the version of cairo available at compile-time. .. versionadded:: 1.18.0 """ CAIRO_VERSION_MINOR: int = ... """ The minor component of the version of cairo available at compile-time. .. versionadded:: 1.18.0 """ CAIRO_VERSION_MICRO: int = ... """ The micro component of the version of cairo available at compile-time. .. versionadded:: 1.18.0 """ def cairo_version() -> int: """ :returns: the encoded version Returns the version of the underlying C cairo library, encoded in a single integer. """ def cairo_version_string() -> str: """ :returns: the encoded version Returns the version of the underlying C cairo library as a human-readable string of the form "X.Y.Z". """ 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. """ class Rectangle(Tuple[float, float, float, float]): """ .. 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. """ x: float = ... y: float = ... width: float = ... height: float = ... def __init__(self, x: float, y: float, width: float, height: float) -> None: """ :param x: X coordinate of the left side of the rectangle :param y: Y coordinate of the the top side of the rectangle :param width: width of the rectangle :param height: height of the rectangle """ class _IntEnum(int): def __init__(self, value: int) -> None: ... class Antialias(_IntEnum): """ Specifies the type of antialiasing to do when rendering text or shapes. .. versionadded:: 1.13 """ BEST: "Antialias" = ... """ Hint that the backend should render at the highest quality, sacrificing speed if necessary. """ DEFAULT: "Antialias" = ... """Use the default antialiasing for the subsystem and target device""" FAST: "Antialias" = ... """ Hint that the backend should perform some antialiasing but prefer speed over quality. """ GOOD: "Antialias" = ... """The backend should balance quality against performance.""" GRAY: "Antialias" = ... """ Perform single-color antialiasing (using shades of gray for black text on a white background, for example). """ NONE: "Antialias" = ... """Use a bilevel alpha mask""" SUBPIXEL: "Antialias" = ... """ Perform antialiasing by taking advantage of the order of subpixel elements on devices such as LCD panels. """ class Content(_IntEnum): """ 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 """ ALPHA: "Content" = ... """The surface will hold alpha content only.""" COLOR: "Content" = ... """The surface will hold color content only.""" COLOR_ALPHA: "Content" = ... """The surface will hold color and alpha content.""" class FillRule(_IntEnum): """ 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 """ EVEN_ODD: "FillRule" = ... """ 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. """ WINDING: "FillRule" = ... """ 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. """ class Format(_IntEnum): """ These constants are used to identify the memory format of :class:`ImageSurface` data. New entries may be added in future versions. .. versionadded:: 1.13 """ def stride_for_width(self, width: int) -> int: """ :param 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. 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 """ A1: "Format" = ... """ 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. """ A8: "Format" = ... """ each pixel is a 8-bit quantity holding an alpha value. """ ARGB32: "Format" = ... """ 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.) """ INVALID: "Format" = ... """no such format exists or is supported.""" RGB16_565: "Format" = ... """ 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. """ RGB24: "Format" = ... """ 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. .. [#] Cairo operators (for example CLEAR and SRC) may overwrite unused bytes as an implementation side-effect, their values should be considered undefined. """ RGB30: "Format" = ... """ like :data:`RGB24` but with 10bpc. """ RGB96F: "Format" = ... """ 3 floats, R, G, B. .. versionadded:: 1.23 Only available with cairo 1.17.2+ """ RGBA128F: "Format" = ... """ 4 floats, R, G, B, A. .. versionadded:: 1.23 Only available with cairo 1.17.2+ """ class HintMetrics(_IntEnum): """ 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 """ DEFAULT: "HintMetrics" = ... """ Hint metrics in the default manner for the font backend and target device """ OFF: "HintMetrics" = ... """"Do not hint font metrics""" ON: "HintMetrics" = ... """Hint font metrics""" class ColorMode(_IntEnum): """ Specifies if color fonts are to be rendered using the color glyphs or outline glyphs. Glyphs that do not have a color presentation, and non-color fonts are not affected by this font option. .. versionadded:: 1.25 Only available with cairo 1.17.8+ """ DEFAULT: "ColorMode" = ... """ Use the default color mode for font backend and target device. """ NO_COLOR: "ColorMode" = ... """ Disable rendering color glyphs. Glyphs are always rendered as outline glyphs """ COLOR: "ColorMode" = ... """ Enable rendering color glyphs. If the font contains a color presentation for a glyph, and when supported by the font backend, the glyph will be rendered in color. """ class Dither(_IntEnum): """ Dither is an intentionally applied form of noise used to randomize quantization error, preventing large-scale patterns such as color banding in images (e.g. for gradients). Ordered dithering applies a precomputed threshold matrix to spread the errors smoothly. :class:`Dither` is modeled on pixman dithering algorithm choice. As of Pixman 0.40, FAST corresponds to a 8x8 ordered bayer noise and GOOD and BEST use an ordered 64x64 precomputed blue noise. .. versionadded:: 1.25 Only available with cairo 1.18.0+ """ NONE: "Dither" = ... """ No dithering. """ DEFAULT: "Dither" = ... """ Default choice at cairo compile time. Currently NONE. """ FAST: "Dither" = ... """ Fastest dithering algorithm supported by the backend """ GOOD: "Dither" = ... """ An algorithm with smoother dithering than FAST """ BEST: "Dither" = ... """ Best algorithm available in the backend """ class HintStyle(_IntEnum): """ 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 """ DEFAULT: "HintStyle" = ... """ Use the default hint style for font backend and target device """ FULL: "HintStyle" = ... """ Hint outlines to maximize contrast """ MEDIUM: "HintStyle" = ... """ Hint outlines with medium strength giving a compromise between fidelity to the original shapes and contrast """ NONE: "HintStyle" = ... """Do not hint outlines""" SLIGHT: "HintStyle" = ... """ Hint outlines slightly to improve contrast while retaining good fidelity to the original shapes. """ class SubpixelOrder(_IntEnum): """ 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 """ BGR: "SubpixelOrder" = ... """Subpixel elements are arranged horizontally with blue at the left""" DEFAULT: "SubpixelOrder" = ... """Use the default subpixel order for for the target device""" RGB: "SubpixelOrder" = ... """Subpixel elements are arranged horizontally with red at the left""" VBGR: "SubpixelOrder" = ... """Subpixel elements are arranged vertically with blue at the top""" VRGB: "SubpixelOrder" = ... """Subpixel elements are arranged vertically with red at the top""" class LineCap(_IntEnum): """ These constants specify how to render the endpoints of the path when stroking. The default line cap style is :attr:`BUTT` .. versionadded:: 1.13 """ BUTT: "LineCap" = ... """start(stop) the line exactly at the start(end) point""" ROUND: "LineCap" = ... """use a round ending, the center of the circle is the end point""" SQUARE: "LineCap" = ... """use squared ending, the center of the square is the end point""" class LineJoin(_IntEnum): """ These constants specify how to render the junction of two lines when stroking. The default line join style is :attr:`MITER` .. versionadded:: 1.13 """ BEVEL: "LineJoin" = ... """ use a cut-off join, the join is cut off at half the line width from the joint point """ MITER: "LineJoin" = ... """ use a sharp (angled) corner, see :meth:`Context.set_miter_limit` """ ROUND: "LineJoin" = ... """use a rounded join, the center of the circle is the joint point""" class Filter(_IntEnum): """ 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 """ BEST: "Filter" = ... """ The highest-quality available, performance may not be suitable for interactive use. """ BILINEAR: "Filter" = ... """Linear interpolation in two dimensions""" FAST: "Filter" = ... """A high-performance filter, with quality similar *FILTER_NEAREST*""" GAUSSIAN: "Filter" = ... """ This filter value is currently unimplemented, and should not be used in current code. """ GOOD: "Filter" = ... """ A reasonable-performance filter, with quality similar to *FILTER_BILINEAR* """ NEAREST: "Filter" = ... """Nearest-neighbor filtering""" class Operator(_IntEnum): """ 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 """ ADD: "Operator" = ... """source and destination layers are accumulated""" ATOP: "Operator" = ... """draw source on top of destination content and only there""" CLEAR: "Operator" = ... """clear destination layer (bounded)""" COLOR_BURN: "Operator" = ... """darkens the destination color to reflect the source color.""" COLOR_DODGE: "Operator" = ... """brightens the destination color to reflect the source color.""" DARKEN: "Operator" = ... """ replaces the destination with the source if it is darker, otherwise keeps the source. """ DEST: "Operator" = ... """ignore the source""" DEST_ATOP: "Operator" = ... """leave destination on top of source content and only there (unbounded)""" DEST_IN: "Operator" = ... """leave destination only where there was source content (unbounded)""" DEST_OUT: "Operator" = ... """leave destination only where there was no source content""" DEST_OVER: "Operator" = ... """draw destination on top of source""" DIFFERENCE: "Operator" = ... """Takes the difference of the source and destination color.""" EXCLUSION: "Operator" = ... """Produces an effect similar to difference, but with lower contrast.""" HARD_LIGHT: "Operator" = ... """Multiplies or screens, dependent on source color.""" HSL_COLOR: "Operator" = ... """ 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. """ HSL_HUE: "Operator" = ... """ Creates a color with the hue of the source and the saturation and luminosity of the target. """ HSL_LUMINOSITY: "Operator" = ... """ 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` """ HSL_SATURATION: "Operator" = ... """ 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. """ IN: "Operator" = ... """draw source where there was destination content (unbounded)""" LIGHTEN: "Operator" = ... """ replaces the destination with the source if it is lighter, otherwise keeps the source. """ MULTIPLY: "Operator" = ... """ source and destination layers are multiplied. This causes the result to be at least as dark as the darker inputs. """ OUT: "Operator" = ... """draw source where there was no destination content (unbounded)""" OVER: "Operator" = ... """draw source layer on top of destination layer (bounded)""" OVERLAY: "Operator" = ... """ multiplies or screens, depending on the lightness of the destination color. """ SATURATE: "Operator" = ... """like over, but assuming source and dest are disjoint geometries""" SCREEN: "Operator" = ... """ source and destination are complemented and multiplied. This causes the result to be at least as light as the lighter inputs. """ SOFT_LIGHT: "Operator" = ... """Darkens or lightens, dependent on source color.""" SOURCE: "Operator" = ... """replace destination layer (bounded)""" XOR: "Operator" = ... """source and destination are shown where there is only one of them""" class Extend(_IntEnum): """ 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 """ NONE: "Extend" = ... """pixels outside of the source pattern are fully transparent""" PAD: "Extend" = ... """ pixels outside of the pattern copy the closest pixel from the source (Since 1.2; but only implemented for surface patterns since 1.6) """ REFLECT: "Extend" = ... """ the pattern is tiled by reflecting at the edges (Implemented for surface patterns since 1.6) """ REPEAT: "Extend" = ... """the pattern is tiled by repeating""" class FontSlant(_IntEnum): """ These constants specify variants of a :class:`FontFace` based on their slant. .. versionadded:: 1.13 """ ITALIC: "FontSlant" = ... """Italic font style""" NORMAL: "FontSlant" = ... """Upright font style""" OBLIQUE: "FontSlant" = ... """Oblique font style""" class FontWeight(_IntEnum): """ These constants specify variants of a :class:`FontFace` based on their weight. .. versionadded:: 1.13 """ BOLD: "FontWeight" = ... """Bold font weight""" NORMAL: "FontWeight" = ... """Normal font weight""" class Status(_IntEnum): """ .. versionadded:: 1.13 """ CLIP_NOT_REPRESENTABLE: "Status" = ... DEVICE_ERROR: "Status" = ... DEVICE_FINISHED: "Status" = ... DEVICE_TYPE_MISMATCH: "Status" = ... FILE_NOT_FOUND: "Status" = ... FONT_TYPE_MISMATCH: "Status" = ... INVALID_CLUSTERS: "Status" = ... INVALID_CONTENT: "Status" = ... INVALID_DASH: "Status" = ... INVALID_DSC_COMMENT: "Status" = ... INVALID_FORMAT: "Status" = ... INVALID_INDEX: "Status" = ... INVALID_MATRIX: "Status" = ... INVALID_MESH_CONSTRUCTION: "Status" = ... INVALID_PATH_DATA: "Status" = ... INVALID_POP_GROUP: "Status" = ... INVALID_RESTORE: "Status" = ... INVALID_SIZE: "Status" = ... INVALID_SLANT: "Status" = ... INVALID_STATUS: "Status" = ... INVALID_STRIDE: "Status" = ... INVALID_STRING: "Status" = ... INVALID_VISUAL: "Status" = ... INVALID_WEIGHT: "Status" = ... JBIG2_GLOBAL_MISSING: "Status" = ... """ .. versionadded:: 1.14 """ LAST_STATUS: "Status" = ... NEGATIVE_COUNT: "Status" = ... NO_CURRENT_POINT: "Status" = ... NO_MEMORY: "Status" = ... NULL_POINTER: "Status" = ... PATTERN_TYPE_MISMATCH: "Status" = ... READ_ERROR: "Status" = ... SUCCESS: "Status" = ... SURFACE_FINISHED: "Status" = ... SURFACE_TYPE_MISMATCH: "Status" = ... TEMP_FILE_ERROR: "Status" = ... USER_FONT_ERROR: "Status" = ... USER_FONT_IMMUTABLE: "Status" = ... USER_FONT_NOT_IMPLEMENTED: "Status" = ... WRITE_ERROR: "Status" = ... TAG_ERROR: "Status" = ... """ .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ FREETYPE_ERROR: "Status" = ... """ .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ PNG_ERROR: "Status" = ... """ .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ WIN32_GDI_ERROR: "Status" = ... """ .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ DWRITE_ERROR: "Status" = ... """ .. versionadded:: 1.23.0 Only available with cairo 1.17.6+ """ SVG_FONT_ERROR: "Status" = ... """ .. versionadded:: 1.25.0 Only available with cairo 1.17.8+ """ class PDFVersion(_IntEnum): """ These constants are used to describe the version number of the PDF specification that a generated PDF file will conform to. .. versionadded:: 1.13 """ VERSION_1_4: "PDFVersion" = ... """The version 1.4 of the PDF specification.""" VERSION_1_5: "PDFVersion" = ... """The version 1.5 of the PDF specification.""" VERSION_1_6: "PDFVersion" = ... """ The version 1.6 of the PDF specification. .. versionadded:: 1.23.0 Only available with cairo 1.17.6+ """ VERSION_1_7: "PDFVersion" = ... """ The version 1.7 of the PDF specification. .. versionadded:: 1.23.0 Only available with cairo 1.17.6+ """ class PSLevel(_IntEnum): """ 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 """ LEVEL_2: "PSLevel" = ... """The language level 2 of the PostScript specification.""" LEVEL_3: "PSLevel" = ... """The language level 3 of the PostScript specification.""" class PathDataType(_IntEnum): """ These constants are used to describe the type of one portion of a path when represented as a :class:`Path`. .. versionadded:: 1.13 """ CLOSE_PATH: "PathDataType" = ... """A close-path operation""" CURVE_TO: "PathDataType" = ... """A curve-to operation""" LINE_TO: "PathDataType" = ... """ A line-to operation""" MOVE_TO: "PathDataType" = ... """A move-to operation""" class RegionOverlap(_IntEnum): """ .. versionadded:: 1.13 """ IN: "RegionOverlap" = ... """The contents are entirely inside the region.""" OUT: "RegionOverlap" = ... """The contents are entirely outside the region.""" PART: "RegionOverlap" = ... """The contents are partially inside and partially outside the region.""" class SVGVersion(_IntEnum): """ These constants are used to describe the version number of the SVG specification that a generated SVG file will conform to. .. versionadded:: 1.13 """ VERSION_1_1: "SVGVersion" = ... """The version 1.1 of the SVG specification.""" VERSION_1_2: "SVGVersion" = ... """The version 1.2 of the SVG specification.""" class SVGUnit(_IntEnum): """ :class:`SVGUnit` is used to describe the units valid for coordinates and lengths in the SVG specification. See also: * https://www.w3.org/TR/SVG/coords.htmlUnits * https://www.w3.org/TR/SVG/types.htmlDataTypeLength * https://www.w3.org/TR/css-values-3/lengths .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ USER: "SVGUnit" = ... """ User unit, a value in the current coordinate system. If used in the root element for the initial coordinate systems it corresponds to pixels. """ EM: "SVGUnit" = ... """The size of the element's font.""" EX: "SVGUnit" = ... """The x-height of the element’s font.""" PX: "SVGUnit" = ... """Pixels (1px = 1/96th of 1in).""" IN: "SVGUnit" = ... """Inches (1in = 2.54cm = 96px)""" CM: "SVGUnit" = ... """Centimeters (1cm = 96px/2.54).""" MM: "SVGUnit" = ... """Millimeters (1mm = 1/10th of 1cm).""" PT: "SVGUnit" = ... """Points (1pt = 1/72th of 1in).""" PC: "SVGUnit" = ... """Picas (1pc = 1/6th of 1in).""" PERCENT: "SVGUnit" = ... """Percent, a value that is some fraction of another reference value.""" class PDFMetadata(_IntEnum): """ :class:`PDFMetadata` is used by the :meth:`PDFSurface.set_metadata` method to specify the metadata to set. .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ TITLE: "PDFMetadata" = ... """The document title""" AUTHOR: "PDFMetadata" = ... """The document author""" SUBJECT: "PDFMetadata" = ... """The document subject""" KEYWORDS: "PDFMetadata" = ... """The document keywords""" CREATOR: "PDFMetadata" = ... """The document creator""" CREATE_DATE: "PDFMetadata" = ... """The document creation date""" MOD_DATE: "PDFMetadata" = ... """The document modification date""" class PDFOutlineFlags(_IntEnum): """ :class:`PDFOutlineFlags` is used by the :meth:`PDFSurface.add_outline` method to specify the attributes of an outline item. These flags may be bitwise-or'd to produce any combination of flags. .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ OPEN: "PDFOutlineFlags" = ... """The outline item defaults to open in the PDF viewer""" BOLD: "PDFOutlineFlags" = ... """The outline item is displayed by the viewer in bold text""" ITALIC: "PDFOutlineFlags" = ... """The outline item is displayed by the viewer in italic text""" class ScriptMode(_IntEnum): """ A set of script output variants. .. versionadded:: 1.14 """ ASCII: "ScriptMode" = ... """the output will be in readable text (default)""" BINARY: "ScriptMode" = ... """the output will use byte codes.""" 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/ """ def __init__(self, xx: float = 1.0, yx: float = 0.0, xy: float = 0.0, yy: float = 1.0, x0: float = 0.0, y0: float = 0.0) -> None: """ :param xx: xx component of the affine transformation :param yx: yx component of the affine transformation :param xy: xy component of the affine transformation :param yy: yy component of the affine transformation :param x0: X translation component of the affine transformation :param y0: Y translation component of the affine transformation 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 def init_rotate(cls, radians: float) -> "Matrix": """ :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. :returns: a new *Matrix* set to a transformation that rotates by *radians*. """ def invert(self) -> Optional["Matrix"]: """ :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. """ def multiply(self, matrix2: "Matrix") -> "Matrix": """ :param matrix2: a second 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*. """ def rotate(self, radians: float) -> None: """ :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. Initialize *Matrix* to a transformation that rotates by *radians*. """ def scale(self, sx: float, sy: float) -> None: """ :param sx: scale factor in the X direction :param sy: scale factor in the Y direction 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. """ def transform_distance(self, dx: float, dy: float) -> Tuple[float, float]: """ :param dx: X component of a distance vector. :param dy: Y component of a distance vector. :returns: the transformed distance vector (dx,dy), both float 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*. """ def transform_point(self, x: float, y: float) -> Tuple[float, float]: """ :param x: X position. :param y: Y position. :returns: the transformed point (x,y), both float Transforms the point *(x, y)* by *Matrix*. """ def translate(self, tx: float, ty: float) -> None: """ :param tx: amount to translate in the X direction :param ty: amount to translate in the Y direction 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. """ xx: float = ... """ xx component of the affine transformation .. versionadded:: 1.12.0 """ yx: float = ... """ yx component of the affine transformation .. versionadded:: 1.12.0 """ xy: float = ... """ xy component of the affine transformation .. versionadded:: 1.12.0 """ yy: float = ... """ yy component of the affine transformation .. versionadded:: 1.12.0 """ x0: float = ... """ X translation component of the affine transformation .. versionadded:: 1.12.0 """ y0: float = ... """ Y translation component of the affine transformation .. versionadded:: 1.12.0 """ class Pattern: """ *Pattern* is the abstract base class from which all the other pattern classes derive. It cannot be instantiated directly. """ def get_extend(self) -> Extend: """ :returns: the current extend strategy used for drawing the *Pattern*. Gets the current extend mode for the *Pattern*. See :class:`cairo.Extend` attributes for details on the semantics of each extend strategy. """ def get_matrix(self) -> Matrix: """ :returns: a new :class:`Matrix` which stores a copy of the *Pattern's* transformation matrix """ def get_filter(self) -> Filter: """ :returns: the current filter used for resizing the pattern. .. versionadded:: 1.12.0 Used to be a method of :class:`SurfacePattern` before """ def set_filter(self, filter: Filter) -> None: """ :param 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) context.get_source().set_filter(cairo.FILTER_NEAREST) .. versionadded:: 1.12.0 Used to be a method of :class:`SurfacePattern` before """ def set_extend(self, extend: Extend) -> None: """ :param 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. """ def set_matrix(self, matrix: Matrix) -> None: """ :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`. """ def get_dither(self) -> Dither: """ :returns: the current dithering mode. Gets the current dithering mode, as set by :meth:`Pattern.set_dither`. .. versionadded:: 1.25.0 Only available with cairo 1.18.0+ """ def set_dither(self, dither: Dither) -> None: """ :param dither: a :class:`Dither` describing the new dithering mode Set the dithering 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, only pixman is supported. .. versionadded:: 1.25.0 Only available with cairo 1.18.0+ """ class Glyph(Tuple[int, float, float]): """ 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 .. versionadded:: 1.15 In prior versions a (int, float, float) tuple was used instead of :class:`Glyph`. """ index: int = ... # type: ignore x: float = ... y: float = ... def __init__(self, index: int, x: float, y: float) -> None: """ :param index: glyph index in the font. The exact interpretation of the glyph index depends on the font technology being used. :param x: the offset in the X direction between the origin used for drawing or measuring the string and the origin of this glyph. :param y: the offset in the Y direction between the origin used for drawing or measuring the string and the origin of this glyph. """ class TextCluster(Tuple[int, int]): """ .. 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. """ num_bytes: int = ... num_glyphs: int = ... def __init__(self, num_bytes: int, num_glyphs: int) -> None: """ :param num_bytes: the number of bytes of UTF-8 text covered by cluster :param num_glyphs: the number of glyphs covered by cluster """ class TextClusterFlags(_IntEnum): """ Specifies properties of a text cluster mapping. .. versionadded:: 1.14 """ BACKWARD: "TextClusterFlags" = ... """ The clusters in the cluster array map to glyphs in the glyph array from end to start. """ class TextExtents(Tuple[float, float, float, float, float, float]): """ .. 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. """ x_bearing: float = ... y_bearing: float = ... width: float = ... height: float = ... x_advance: float = ... y_advance: float = ... def __init__(self, x_bearing: float, y_bearing: float, width: float, height: float, x_advance: float, y_advance: float) -> None: """ :param 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 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 width: width of the glyphs as drawn :param height: height of the glyphs as drawn :param x_advance: distance to advance in the X direction after drawing these glyphs :param 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. """ class RectangleInt: """ RectangleInt is a data structure for holding a rectangle with integer coordinates. .. versionadded:: 1.11.0 """ height: int = ... width: int = ... x: int = ... y: int = ... def __init__(self, x: int=0, y: int=0, width: int=0, height: int=0) -> None: """ :param x: X coordinate of the left side of the rectangle. :param y: Y coordinate of the top side of the rectangle. :param width: Width of the rectangle. :param height: Height of the rectangle. Allocates a new RectangleInt object. """ 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. .. note:: This class cannot be instantiated directly, it is returned by :meth:`Context.get_font_face`. """ 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. Implements `__eq__` and `__ne__` using `equal()` since 1.12.0. """ def __init__(self) -> None: """ Allocates a new FontOptions object with all options initialized to default values. """ def get_antialias(self) -> Antialias: """ :returns: the antialias mode for the *FontOptions* object """ def get_hint_style(self) -> HintStyle: """ :returns: the hint style for the *FontOptions* object """ def get_subpixel_order(self) -> SubpixelOrder: """ :returns: the subpixel order for the *FontOptions* object """ def set_antialias(self, antialias: Antialias) -> None: """ :param antialias: the antialias mode This specifies the type of antialiasing to do when rendering text. """ def set_hint_metrics(self, hint_metrics: HintMetrics) -> None: """ :param hint_metrics: the hint metrics mode This controls whether metrics are quantized to integer values in device units. """ def set_hint_style(self, hint_style: HintStyle) -> None: """ :param 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. """ def merge(self, other: "FontOptions") -> None: """ :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 """ def copy(self) -> "FontOptions": """ :returns: a new :class:`FontOptions` Returns a new font options object copying the option values from original. .. versionadded:: 1.12.0 """ def hash(self) -> int: """ :returns: the hash value for the font options object 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 """ def equal(self, other: "FontOptions") -> bool: """ :param 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. Compares two font options objects for equality. .. versionadded:: 1.12.0 """ def set_variations(self, variations: Optional[str]) -> None: """ :param variations: the new font variations, or :obj:`None` Sets the OpenType font variations for the font options object. Font variations are specified as a string with a format that is similar to the CSS font-variation-settings. The string contains a comma-separated list of axis assignments, which each assignment consists of a 4-character axis name and a value, separated by whitespace and optional equals sign. Examples: * wght=200,wdth=140.5 * wght 200 , wdth 140.5 .. versionadded:: 1.18.0 Only available with cairo 1.15.12+ """ def get_variations(self) -> str: """ :returns: the font variations for the font options object. The returned string belongs to the options and must not be modified. It is valid until either the font options object is destroyed or the font variations in this object is modified with :meth:`set_variations`. Gets the OpenType font variations for the font options object. See :meth:`set_variations` for details about the string format. .. versionadded:: 1.18.0 Only available with cairo 1.15.12+ """ def get_hint_metrics(self) -> HintMetrics: """ :returns: the hint metrics mode for the *FontOptions* object """ def set_subpixel_order(self, subpixel_order: SubpixelOrder) -> None: """ :param 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`. """ def set_color_mode(self, color_mode: ColorMode) -> None: """ :param color_mode: the new color mode Sets the color mode for the font options object. This controls whether color fonts are to be rendered in color or as outlines. See the documentation for :class:`ColorMode` for full details. .. versionadded:: 1.25.0 Only available with cairo 1.17.8+ """ def get_color_mode(self) -> ColorMode: """ :returns: the color mode for the font options object Gets the color mode for the font options object. See the documentation for :class:`ColorMode` for full details. .. versionadded:: 1.25.0 Only available with cairo 1.17.8+ """ def set_color_palette(self, palette_index: int) -> None: """ :param palette_index: the palette index in the CPAL table Sets the OpenType font color palette for the font options object. OpenType color fonts with a CPAL table may contain multiple palettes. The default color palette index is :data:`COLOR_PALETTE_DEFAULT`. If palette_index is invalid, the default palette is used. .. versionadded:: 1.25.0 Only available with cairo 1.17.8+ """ def get_color_palette(self) -> int: """ :returns: the palette index Gets the OpenType color font palette for the font options object. .. versionadded:: 1.25.0 Only available with cairo 1.17.8+ """ def set_custom_palette_color(self, index: int, red: float, green: float, blue: float, alpha: float) -> None: """ :param index: the index of the color to set :param red: red component of color :param green: green component of color :param blue: blue component of color :param alpha: alpha component of color Sets a custom palette color for the font options object. This overrides the palette color at the specified color index. This override is independent of the selected palette index and will remain in place even if :meth:`FontOptions.set_color_palette` is called to change the palette index. It is only possible to override color indexes already in the font palette. .. versionadded:: 1.25.0 Only available with cairo 1.17.8+ """ def get_custom_palette_color(self, index: int) -> Tuple[float, float, float, float]: """ :param index: the index of the color to get :returns: a (red, green, blue, alpha) tuple of float :raises Error: if no custom color exists for the color index. Gets the custom palette color for the color index for the font options object. .. versionadded:: 1.25.0 Only available with cairo 1.17.8+ """ 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. """ def __init__(self, font_face: FontFace, font_matrix: Matrix, ctm: Matrix, options: FontOptions) -> None: """ :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. """ def extents(self) -> Tuple[float, float, float, float, float]: """ Gets the metrics for a *ScaledFont*. """ def get_ctm(self) -> Matrix: """ :returns: the CTM 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 """ def get_font_face(self) -> FontFace: """ :returns: the :class:`FontFace` that this *ScaledFont* was created for. .. versionadded:: 1.2 """ def get_font_matrix(self) -> Matrix: """ :returns: the matrix Returns the font matrix with which scaled_font was created. """ def get_font_options(self) -> FontOptions: """ :returns: font options Returns the font options with which scaled_font was created. .. versionadded:: 1.12.0 """ def get_scale_matrix(self) -> 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 """ def glyph_extents(self, glyphs: Sequence[Glyph]) -> TextExtents: """ :param glyphs: glyphs, a sequence of :class:`Glyph` .. 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). """ def text_extents(self, text: str) -> TextExtents: """ :param text: text 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 """ def text_to_glyphs(self, x: float, y: float, utf8: str, with_clusters: bool = True) -> Union[Tuple[List[Glyph], List["TextCluster"], TextClusterFlags], List[Glyph]]: """ :param x: X position to place first glyph :param y: Y position to place first glyph :param utf8: a string of text :param with_clusters: If :obj:`False` only the glyph list will computed and returned :returns: a tuple of ([:class:`Glyph`], [:class:`TextCluster`], :class:`TextClusterFlags`) :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. """ _SomeDevice = TypeVar("_SomeDevice", bound="Device") class Device: """ A :class:`Device` represents the driver interface for drawing operations to a :class:`Surface`. .. versionadded:: 1.14 .. note:: .. versionadded:: 1.17.0 :class:`cairo.Device` can be used as a context manager: .. code:: python # device.finish() will be called on __exit__ with cairo.ScriptDevice(f) as device: pass """ def finish(self) -> None: """ 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 """ def flush(self) -> None: """ 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 """ def acquire(self) -> None: """ :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 """ def release(self) -> None: """ Releases a device previously acquired using :meth:`acquire`. See that function for details. .. versionadded:: 1.14 """ def __enter__(self: _SomeDevice) -> _SomeDevice: ... __exit__: Any = ... _PathLike = Union[Text, ByteString] _FileLike = BinaryIO _SomeSurface = TypeVar("_SomeSurface", bound="Surface") class Surface: """ 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(). *Surface* is the abstract base class from which all the other surface classes derive. It cannot be instantiated directly. .. note:: .. versionadded:: 1.17.0 :class:`cairo.Surface` can be used as a context manager: .. code:: python # surface.finish() will be called on __exit__ with cairo.SVGSurface("example.svg", 200, 200) as surface: pass # surface.unmap_image(image_surface) will be called on __exit__ with surface.map_to_image(None) as image_surface: pass """ def copy_page(self) -> None: """ 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 """ def create_for_rectangle(self, x: float, y: float, width: float, height: float) -> "Surface": """ :param x: the x-origin of the sub-surface from the top-left of the target surface (in device-space units) :param y: the y-origin of the sub-surface from the top-left of the target surface (in device-space units) :param width: width of the sub-surface (in device-space units) :param height: height of the sub-surface (in device-space units) :returns: a new 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 """ def create_similar(self, content: Content, width: int, height: int) -> "Surface": """ :param content: the content for the new surface :param width: width of the new surface, (in device-space units) :param height: height of the new surface (in device-space units) :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.) """ def create_similar_image(self, format: Format, width: int, height: int) -> "ImageSurface": """ :param cairo.Format format: the format for the new surface :param width: width of the new surface, (in device-space units) :param height: height of the new surface, (in device-space units) :returns: a new image surface 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 """ def finish(self) -> None: """ 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 `cairo.Error` exception. """ def flush(self) -> None: """ 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. """ def get_content(self) -> Content: """ :returns: The content type of *Surface*, which indicates whether the *Surface* contains color and/or alpha information. .. versionadded:: 1.2 """ def get_device(self) -> Optional["Device"]: """ :returns: the device or :obj:`None` if the surface does not have an associated device This function returns the device for a surface. .. versionadded:: 1.14.0 """ def get_device_offset(self) -> Tuple[float, float]: """ :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 """ def get_device_scale(self) -> Tuple[float, float]: """ :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 """ def get_fallback_resolution(self) -> Tuple[float, float]: """ :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 """ def get_font_options(self) -> FontOptions: """ :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`. """ def get_mime_data(self, mime_type: str) -> Optional[bytes]: """ :param mime_type: the MIME type of the image data (:ref:`constants_MIME_TYPE`) :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 """ def has_show_text_glyphs(self) -> bool: """ :returns: :obj:`True` if surface supports :meth:`Context.show_text_glyphs`, :obj:`False` otherwise 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 """ def map_to_image(self, extents: Optional[RectangleInt]) -> "ImageSurface": """ :param extents: limit the extraction to an rectangular region or :obj:`None` for the whole surface :returns: newly allocated image surface :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 """ def mark_dirty(self) -> None: """ 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. """ def mark_dirty_rectangle(self, x: int, y: int, width: int, height: int) -> None: """ :param x: X coordinate of dirty rectangle :param y: Y coordinate of dirty rectangle :param width: width of dirty rectangle :param height: height of dirty rectangle 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. """ def set_device_offset(self, x_offset: float, y_offset: float) -> None: """ :param x_offset: the offset in the X direction, in device units :param y_offset: the offset in the Y direction, in device units 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. """ def set_device_scale(self, x_scale: float, y_scale: float) -> None: """ :param x_scale: a scale factor in the X direction :param 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 """ def set_fallback_resolution(self, x_pixels_per_inch: float, y_pixels_per_inch: float) -> None: """ :param x_pixels_per_inch: horizontal setting for pixels per inch :param y_pixels_per_inch: vertical setting for pixels per inch 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 """ def set_mime_data(self, mime_type: str, data: bytes) -> None: """ :param mime_type: the MIME type of the image data (:ref:`constants_MIME_TYPE`) :param data: the image data to attach to the surface 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 """ def show_page(self) -> None: """ 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 """ def supports_mime_type(self, mime_type: str) -> bool: """ :param mime_type: the mime type (:ref:`constants_MIME_TYPE`) :returns: :obj:`True` if surface supports mime_type, :obj:`False` otherwise Return whether surface supports ``mime_type``. .. versionadded:: 1.12.0 """ def write_to_png(self, fobj: Union[_FileLike, _PathLike]) -> None: """ :param fobj: a filename or writable file 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. *fobj* can either be a filename or a file object opened in binary mode. """ def unmap_image(self, image: "ImageSurface") -> None: """ :param 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 """ def __enter__(self: _SomeSurface) -> _SomeSurface: ... __exit__: Any = ... class ImageSurface(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`. """ def __init__(self, format: Format, width: int, height: int) -> None: """ :param 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* 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 def create_for_data(cls, data: memoryview, format: Format, width: int, height: int, stride: int = ...) -> "ImageSurface": """ :param data: a writable Python buffer/memoryview object :param 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 def create_from_png(cls, fobj: Union[_PathLike, _FileLike]) -> "ImageSurface": """ :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. Creates a new image surface and initializes the contents to the given PNG file. *fobj* can either be a filename or a file object opened in binary mode. """ format_stride_for_width = Format.stride_for_width """ See :meth:`cairo.Format.stride_for_width`. .. versionadded:: 1.6 """ def get_data(self) -> memoryview: """ :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 """ def get_format(self) -> Format: """ :returns: the format of the *ImageSurface*. :rtype: cairo.Format .. versionadded:: 1.2 """ def get_height(self) -> int: """ :returns: the height of the *ImageSurface* in pixels. """ def get_stride(self) -> int: """ :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. """ def get_width(self) -> int: """ :returns: the width of the *ImageSurface* in pixels. """ class SurfacePattern(Pattern): def __init__(self, surface: Surface) -> None: """ :param surface: a cairo :class:`Surface` """ def get_surface(self) -> Surface: """ :returns: the :class:`Surface` of the *SurfacePattern*. .. versionadded:: 1.4 """ class Context(Generic[_SomeSurface]): """ *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 losing the current state. Use :meth:`Context.restore` to restore to the saved state. """ def __init__(self, target: _SomeSurface) -> None: """ :param target: target :class:`Surface` for the 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). """ def append_path(self, path: Path) -> None: """ :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). """ def arc(self, xc: float, yc: float, radius: float, angle1: float, angle2: float) -> None: """ :param xc: X position of the center of the arc :param yc: Y position of the center of the arc :param radius: the radius of the arc :param angle1: the start angle, in radians :param angle2: the end angle, in radians 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() """ def arc_negative(self, xc: float, yc: float, radius: float, angle1: float, angle2: float) -> None: """ :param xc: X position of the center of the arc :param yc: Y position of the center of the arc :param radius: the radius of the arc :param angle1: the start angle, in radians :param angle2: the end angle, in radians 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. """ def clip(self) -> None: """ 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`. """ def clip_extents(self) -> Tuple[float, float, float, float]: """ :returns: (x1, y1, x2, y2), all float * *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 """ def clip_preserve(self) -> None: """ 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`. """ def close_path(self) -> None: """ 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. """ def copy_clip_rectangle_list(self) -> List[Rectangle]: """ :returns: the current clip region as a list of rectangles in user coordinates. Returns a list of :class:`Rectangle` .. versionadded:: 1.4 """ def copy_page(self) -> None: """ 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. """ def copy_path(self) -> 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`. """ def copy_path_flat(self) -> Path: """ :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. """ def curve_to(self, x1: float, y1: float, x2: float, y2: float, x3: float, y3: float) -> None: """ :param x1: the X coordinate of the first control point :param y1: the Y coordinate of the first control point :param x2: the X coordinate of the second control point :param y2: the Y coordinate of the second control point :param x3: the X coordinate of the end of the curve :param y3: the Y coordinate of the end of the curve 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)``. """ def device_to_user(self, x: float, y: float) -> Tuple[float, float]: """ :param x: X value of coordinate :param y: Y value of coordinate :returns: (x, y), both float Transform a coordinate from device space to user space by multiplying the given point by the inverse of the current transformation matrix (CTM). """ def device_to_user_distance(self, dx: float, dy: float) -> Tuple[float, float]: """ :param dx: X component of a distance vector :param dy: Y component of a distance vector :returns: (dx, dy), both float 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)*. """ def fill(self) -> None: """ 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`. """ def fill_extents(self) -> Tuple[float, float, float, float]: """ :returns: (x1, y1, x2, y2), all float * *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`. """ def fill_preserve(self) -> None: """ 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`. """ def font_extents(self) -> Tuple[float, float, float, float, float]: """ :returns: (ascent, descent, height, max_x_advance, max_y_advance), all float Gets the font extents for the currently selected font. """ def get_antialias(self) -> Antialias: """ :returns: the current antialias mode, as set by :meth:`Context.set_antialias`. """ def get_current_point(self) -> Tuple[float, float]: """ :returns: (x, y), both float * *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`. 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`. """ def get_dash(self) -> Tuple[List[float], float]: """ :returns: (dashes, offset) * *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 """ def get_dash_count(self) -> int: """ :returns: the length of the dash array, or 0 if no dash array set. See also :meth:`Context.set_dash` and :meth:`Context.get_dash`. .. versionadded:: 1.4 """ def get_fill_rule(self) -> FillRule: """ :returns: the current fill rule, as set by :meth:`Context.set_fill_rule`. """ def get_font_face(self) -> FontFace: """ :returns: the current :class:`FontFace` for the :class:`Context`. """ def get_font_matrix(self) -> Matrix: """ :returns: the current :class:`Matrix` for the :class:`Context`. See :meth:`Context.set_font_matrix`. """ def get_font_options(self) -> FontOptions: """ :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`. """ def get_group_target(self) -> Surface: """ :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 """ def get_hairline(self) -> bool: """ :returns: whether hairline mode is set. Returns whether or not hairline mode is set, as set by :meth:`Context.set_hairline`. .. versionadded:: 1.23 Only available with cairo 1.17.6+ """ def get_line_cap(self) -> LineCap: """ :returns: the current line cap style, as set by :meth:`Context.set_line_cap`. """ def get_line_join(self) -> LineJoin: """ :returns: the current line join style, as set by :meth:`Context.set_line_join`. """ def get_line_width(self) -> float: """ :returns: the current line width 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`. """ def get_matrix(self) -> Matrix: """ :returns: the current transformation :class:`Matrix` (CTM) """ def get_miter_limit(self) -> float: """ :returns: the current miter limit, as set by :meth:`Context.set_miter_limit`. """ def get_operator(self) -> Operator: """ :returns: the current compositing operator for a :class:`Context`. """ def get_scaled_font(self) -> ScaledFont: """ :returns: the current :class:`ScaledFont` for a :class:`Context`. .. versionadded:: 1.4 """ def get_source(self) -> Pattern: """ :returns: the current source :class:`Pattern` for a :class:`Context`. """ def get_target(self) -> _SomeSurface: """ :returns: the target :class:`Surface` for the :class:`Context` """ def get_tolerance(self) -> float: """ :returns: the current tolerance value, as set by :meth:`Context.set_tolerance` """ def glyph_extents(self, glyphs: Sequence[Glyph]) -> TextExtents: """ :param glyphs: glyphs, a sequence of :class:`Glyph` 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). """ def glyph_path(self, glyphs: Sequence[Glyph]) -> None: """ :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`. """ def has_current_point(self) -> bool: """ :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 """ def identity_matrix(self) -> None: """ 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. """ def in_clip(self, x: float, y: float) -> bool: """ :param x: X coordinate of the point to test :param y: Y coordinate of the point to test :returns: :obj:`True` if the point is inside, or :obj:`False` if outside. 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 """ def in_fill(self, x: float, y: float) -> bool: """ :param x: X coordinate of the point to test :param y: Y coordinate of the point to test :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`. """ def in_stroke(self, x: float, y: float) -> bool: """ :param x: X coordinate of the point to test :param y: Y coordinate of the point to test :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`. """ def line_to(self, x: float, y: float) -> None: """ :param x: the X coordinate of the end of the new line :param y: the Y coordinate of the end of the new line 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)``. """ def mask(self, pattern: Pattern) -> None: """ :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.) """ def mask_surface(self, surface: Surface, x: float = 0.0, y: float = 0.0) -> None: """ :param surface: a :class:`Surface` :param x: X coordinate at which to place the origin of *surface* :param y: Y coordinate at which to place the origin of *surface* 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.) """ def move_to(self, x: float, y: float) -> None: """ :param x: the X coordinate of the new position :param y: the Y coordinate of the new position Begin a new sub-path. After this call the current point will be *(x, y)*. """ def new_path(self) -> None: """ Clears the current path. After this call there will be no path and no current point. """ def new_sub_path(self) -> None: """ 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 """ def paint(self) -> None: """ A drawing operator that paints the current source everywhere within the current clip region. """ def paint_with_alpha(self, alpha: float) -> None: """ :param alpha: alpha value, between 0 (transparent) and 1 (opaque) 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. """ def path_extents(self) -> Tuple[float, float, float, float]: """ :returns: (x1, y1, x2, y2), all float * *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 """ def pop_group(self) -> SurfacePattern: """ :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 """ def pop_group_to_source(self) -> None: """ 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 """ def push_group(self) -> None: """ 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 """ def push_group_with_content(self, content: Content) -> None: """ :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 """ def rectangle(self, x: float, y: float, width: float, height: float) -> None: """ :param x: the X coordinate of the top left corner of the rectangle :param y: the Y coordinate to the top left corner of the rectangle :param width: the width of the rectangle :param height: the height of the rectangle 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() """ def rel_curve_to(self, dx1: float, dy1: float, dx2: float, dy2: float, dx3: float, dy3: float) -> None: """ :param dx1: the X offset to the first control point :param dy1: the Y offset to the first control point :param dx2: the X offset to the second control point :param dy2: the Y offset to the second control point :param dx3: the X offset to the end of the curve :param dy3: the Y offset to the end of the curve :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)``. """ def rel_line_to(self, dx: float, dy: float) -> None: """ :param dx: the X offset to the end of the new line :param dy: the Y offset to the end of the new line :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)``. """ def rel_move_to(self, dx: float, dy: float) -> None: """ :param dx: the X offset :param dy: the Y offset :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)``. """ def reset_clip(self) -> None: """ 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. """ def restore(self) -> None: """ Restores :class:`Context` to the state saved by a preceding call to :meth:`.save` and removes that state from the stack of saved states. """ def rotate(self, angle: float) -> None: """ :param angle: angle (in radians) by which the user-space axes will be rotated 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. """ def save(self) -> None: """ 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`. """ def scale(self, sx: float, sy: float) -> None: """ :param sx: scale factor for the X dimension :param sy: scale factor for the Y dimension 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. """ def select_font_face(self, family: str, slant: FontSlant = FontSlant.NORMAL, weight: FontWeight = FontWeight.NORMAL) -> None: """ :param family: a font family name :param slant: the font slant of the font, defaults to :attr:`cairo.FontSlant.NORMAL`. :param 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`. """ def set_antialias(self, antialias: Antialias) -> None: """ :param 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`. """ def set_dash(self, dashes: Sequence[float], offset: float = 0) -> None: """ :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. :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*. """ def set_fill_rule(self, fill_rule: FillRule) -> None: """ :param 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`. """ def set_font_face(self, font_face: Optional[FontFace]) -> None: """ :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*. """ def set_font_matrix(self, matrix: Matrix) -> None: """ :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 """ def set_font_options(self, options: FontOptions) -> None: """ :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. """ def set_font_size(self, size: float) -> None: """ :param size: the new font size, in user space units 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. """ def set_hairline(self, set_hairline: bool) -> None: """ :param set_hairline: whether or not to set hairline mode Sets lines within the cairo context to be hairlines. Hairlines are logically zero-width lines that are drawn at the thinnest renderable width possible in the current context. On surfaces with native hairline support, the native hairline functionality will be used. Surfaces that support hairlines include: - pdf/ps: Encoded as 0-width line. - win32_printing: Rendered with PS_COSMETIC pen. - svg: Encoded as 1px non-scaling-stroke. - script: Encoded with set-hairline function. Cairo will always render hairlines at 1 device unit wide, even if an anisotropic scaling was applied to the stroke width. In the wild, handling of this situation is not well-defined. Some PDF, PS, and SVG renderers match Cairo's output, but some very popular implementations (Acrobat, Chrome, rsvg) will scale the hairline unevenly. As such, best practice is to reset any anisotropic scaling before calling :meth:`.stroke`. See https://cairographics.org/cookbook/ellipses/ for an example. .. versionadded:: 1.23 Only available with cairo 1.17.6+ """ def set_line_cap(self, line_cap: LineCap) -> None: """ :param 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` and :meth:`.stroke_extents`, but does not have any effect during path construction. The default line cap style is :attr:`cairo.LineCap.BUTT`. """ def set_line_join(self, line_join: LineJoin) -> None: """ :param 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` and :meth:`.stroke_extents`, but does not have any effect during path construction. The default line join style is :attr:`cairo.LineJoin.MITER`. """ def set_line_width(self, width: float) -> None: """ :param width: a line width 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` and :meth:`.stroke_extents`, but does not have any effect during path construction. The default line width value is 2.0. """ def set_matrix(self, matrix: Matrix) -> None: """ :param matrix: a transformation :class:`Matrix` from user space to device space. Modifies the current transformation matrix (CTM) by setting it equal to *matrix*. """ def set_miter_limit(self, limit: float) -> None: """ :param limit: miter limit to set 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` and :meth:`.stroke_extents`, 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) """ def set_operator(self, op: Operator) -> None: """ :param op: the compositing operator to set for use in all drawing operations. The default operator is :attr:`cairo.Operator.OVER`. """ def set_scaled_font(self, scaled_font: ScaledFont) -> None: """ :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 """ def set_source(self, source: Pattern) -> None: """ :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)``. """ def set_source_rgb(self, red: float, green: float, blue: float) -> None: """ :param red: red component of color :param green: green component of color :param blue: blue component of color 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)``. """ def set_source_rgba(self, red: float, green: float, blue: float, alpha: float = 1.0) -> None: """ :param red: red component of color :param green: green component of color :param blue: blue component of color :param alpha: alpha component of color 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)``. """ def set_source_surface(self, surface: Surface, x: float = 0.0, y: float = 0.0) -> None: """ :param surface: a :class:`Surface` to be used to set the source pattern :param x: User-space X coordinate for surface origin :param y: User-space Y coordinate for surface origin 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`). """ def set_tolerance(self, tolerance: float) -> None: """ :param tolerance: the tolerance, in device units (typically pixels) 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. """ def show_glyphs(self, glyphs: Sequence[Glyph]) -> None: """ :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. """ def show_page(self) -> None: """ 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()`` """ def show_text(self, text: str) -> None: """ :param 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. """ def show_text_glyphs(self, utf8: str, glyphs: List["Glyph"], clusters: List[TextCluster], cluster_flags: TextClusterFlags) -> None: """ :param utf8: a string of text :param glyphs: list of glyphs to show :param clusters: list of cluster mapping information :param 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. """ def stroke(self) -> None: """ 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. """ def stroke_extents(self) -> Tuple[float, float, float, float]: """ :returns: (x1, y1, x2, y2), all float * *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`. """ def stroke_preserve(self) -> None: """ 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`. """ def tag_begin(self, tag_name: str, attributes: str) -> None: """ :param tag_name: tag name :param attributes: tag attributes Marks the beginning of the tag_name structure. Call :meth:`tag_end` with the same tag_name to mark the end of the structure. The attributes string is of the form "key1=value2 key2=value2 ...". Values may be boolean (true/false or 1/0), integer, float, string, or an array. String values are enclosed in single quotes ('). Single quotes and backslashes inside the string should be escaped with a backslash. Boolean values may be set to true by only specifying the key. eg the attribute string "key" is the equivalent to "key=true". Arrays are enclosed in '[]'. eg "rect=[1.2 4.3 2.0 3.0]". If no attributes are required, attributes can be an empty string. See `Tags and Links Description `__ for the list of tags and attributes. Invalid nesting of tags or invalid attributes will cause the context to shutdown with a status of :attr:`Status.TAG_ERROR`. See :meth:`tag_end`. .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ def tag_end(self, tag_name: str) -> None: """ :param tag_name: tag name Marks the end of the tag_name structure. Invalid nesting of tags will cause the context to shutdown with a status of :attr:`Status.TAG_ERROR`. See :meth:`tag_begin`. .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ def text_extents(self, text: str) -> TextExtents: """ :param text: text to get extents for 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. """ def text_path(self, text: str) -> None: """ :param 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. """ def transform(self, matrix: Matrix) -> None: """ :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. """ def translate(self, tx: float, ty: float) -> None: """ :param tx: amount to translate in the X direction :param ty: amount to translate in the Y direction 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. """ def user_to_device(self, x: float, y: float) -> Tuple[float, float]: """ :param x: X value of coordinate :param y: Y value of coordinate :returns: (x, y), both float * *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). """ def user_to_device_distance(self, dx: float, dy: float) -> Tuple[float, float]: """ :param dx: X value of a distance vector :param dy: Y value of a distance vector :returns: (dx, dy), both float * *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)*. """ class Error(Exception): """This exception is raised when a cairo object returns an error status.""" status: Status = ... CairoError = Error """ An alias for :exc:`Error` .. versionadded:: 1.12.0 """ class Gradient(Pattern): """ *Gradient* is an abstract base class from which other *Pattern* classes derive. It cannot be instantiated directly. """ def add_color_stop_rgb(self, offset: float, red: float, green: float, blue: float) -> None: """ :param offset: an offset in the range [0.0 .. 1.0] :param red: red component of color :param green: green component of color :param blue: blue component of color 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. """ def add_color_stop_rgba(self, offset: float, red: float, green: float, blue: float, alpha: float) -> None: """ :param offset: an offset in the range [0.0 .. 1.0] :param red: red component of color :param green: green component of color :param blue: blue component of color :param alpha: alpha component of color 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. """ def get_color_stops_rgba(self) -> List[Tuple[float, float, float, float, float]]: """ :returns: a list of (offset, red, green, blue, alpha) tuples of float Gets the color and offset information for all color stops specified in the given gradient pattern. .. versionadded:: 1.14 """ class LinearGradient(Gradient): def __init__(self, x0: float, y0: float, x1: float, y1: float) -> None: """ :param x0: x coordinate of the start point :param y0: y coordinate of the start point :param x1: x coordinate of the end point :param y1: y coordinate of the end point 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` """ def get_linear_points(self) -> Tuple[float, float, float, float]: """ :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 MeshPattern(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`. .. versionadded:: 1.14 """ def __init__(self) -> None: """ Create a new mesh pattern. .. versionadded:: 1.14 """ def begin_patch(self) -> None: """ :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. """ def curve_to(self, x1: float, y1: float, x2: float, y2: float, x3: float, y3: float) -> None: """ :param x1: the X coordinate of the first control point :param y1: the Y coordinate of the first control point :param x2: the X coordinate of the second control point :param y2: the Y coordinate of the second control point :param x3: the X coordinate of the end of the curve :param 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 ). """ def end_patch(self) -> None: """ :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. """ def get_control_point(self, patch_num: int, point_num: int) -> Tuple[float, float]: """ :param patch_num: the patch number to return data for :param point_num: he control point number to return data for :returns: a (x, y) tuple of float - coordinates of the control point :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`. """ def get_corner_color_rgba(self, patch_num: int, corner_num: int) -> Tuple[float, float, float, float]: """ :param patch_num: the patch number to return data for :param corner_num: the corner number to return data for :returns: a (red, green, blue, alpha) tuple of float :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`. """ def get_patch_count(self) -> int: """ :returns: number of patches 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. """ def line_to(self, x: float, y: float) -> None: """ :param x: the X coordinate of the end of the new line :param 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 ). """ def move_to(self, x: float, y: float) -> None: """ :param x: the X coordinate of the new position :param 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 ). """ def set_control_point(self, point_num: int, x: float, y: float) -> None: """ :param point_num: the control point to set the position for :param x: the X coordinate of the control point :param 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`. """ def set_corner_color_rgb(self, corner_num: int, red: float, green: float, blue: float) -> None: """ :param corner_num: the corner to set the color for :param red: red component of color :param green: green component of color :param 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`. """ def set_corner_color_rgba(self, corner_num: int, red: float, green: float, blue: float, alpha: float) -> None: """ :param corner_num: the corner to set the color for :param red: red component of color :param green: green component of color :param blue: blue component of color :param 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`. """ def get_path(self, patch_num: int) -> Path: """ :param patch_num: the patch number to return data for :returns: the path defining the patch :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`. """ class PDFSurface(Surface): """ The PDFSurface is used to render cairo graphics to Adobe PDF files and is a multi-page vector surface backend. .. versionadded:: 1.2 """ def __init__(self, fobj: Union[_PathLike, _FileLike], width_in_points: float, height_in_points: float) -> None: """ :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. :param width_in_points: width of the surface, in points (1 point == 1/72.0 inch) :param height_in_points: height of the surface, in points (1 point == 1/72.0 inch) :returns: a new *PDFSurface* of the specified size in points to be written to *fobj*. .. versionadded:: 1.2 """ def set_custom_metadata(self, name: str, value: Optional[str]) -> None: """ :param name: The name of the custom metadata item to set. :param value: The value of the metadata. Set custom document metadata. *name* may be any string except for the following names reserved by PDF: "Title", "Author", "Subject", "Keywords", "Creator", "Producer", "CreationDate", "ModDate", "Trapped". If *value* is :obj:`None` or an empty string, the *name* metadata will not be set. For example:: surface.set_custom_metadata("ISBN", "978-0123456789") .. versionadded:: 1.23.0 Only available with cairo 1.17.6+ """ def set_size(self, width_in_points: float, height_in_points: float) -> None: """ :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) 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 """ def restrict_to_version(self, version: PDFVersion) -> None: """ :param 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 def get_versions() -> List[PDFVersion]: """ :returns: supported version list Retrieve the list of supported versions. See :meth:`restrict_to_version`. .. versionadded:: 1.12.0 """ @staticmethod def version_to_string(version: PDFVersion) -> str: """ :param version: PDF version :returns: the string associated to the given version :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 """ def add_outline(self, parent_id: int, utf8: str, link_attribs: str, flags: PDFOutlineFlags) -> int: """ :param parent_id: the id of the parent item or :data:`PDF_OUTLINE_ROOT` if this is a top level item. :param utf8: the name of the outline :param link_attribs: the link attributes specifying where this outline links to :param flags: outline item flags :returns: the id for the added item. .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ def set_metadata(self, metadata: PDFMetadata, utf8: str) -> None: """ :param metadata: The metadata item to set. :param utf8: metadata value Set document metadata. The :attr:`PDFMetadata.CREATE_DATE` and :attr:`PDFMetadata.MOD_DATE` values must be in ISO-8601 format: YYYY-MM-DDThh:mm:ss. An optional timezone of the form "[+/-]hh:mm" or "Z" for UTC time can be appended. All other metadata values can be any UTF-8 string. .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ def set_page_label(self, utf8: str) -> None: """ :param utf8: metadata value Set page label for the current page. .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ def set_thumbnail_size(self, width: int, height: int) -> None: """ :param width: Thumbnail width. :param height: Thumbnail height Set the thumbnail image size for the current and all subsequent pages. Setting a width or height of 0 disables thumbnails for the current and subsequent pages. .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ class PSSurface(Surface): """ The *PSSurface* is used to render cairo graphics to Adobe PostScript files and is a multi-page vector surface backend. """ def __init__(self, fobj: Union[_FileLike, _PathLike], width_in_points: float, height_in_points: float) -> None: """ :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. :param width_in_points: width of the surface, in points (1 point == 1/72.0 inch) :param height_in_points: height of the surface, in points (1 point == 1/72.0 inch) :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`. """ def dsc_begin_page_setup(self) -> None: """ 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 """ def dsc_begin_setup(self) -> None: """ 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 """ def dsc_comment(self, comment: str) -> None: """ :param comment: a comment string to be emitted into the PostScript output 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 """ def get_eps(self) -> bool: """ :returns: True iff the *PSSurface* will output Encapsulated PostScript. .. versionadded:: 1.6 """ @staticmethod def level_to_string(level: PSLevel) -> str: """ :param level: a PS level :returns: the string associated to given level. 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 """ ps_level_to_string = level_to_string """ Alias for :meth:`level_to_string` .. versionadded:: 1.6 """ def restrict_to_level(self, level: PSLevel) -> None: """ :param 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 """ def set_eps(self, eps: bool) -> None: """ :param eps: True to output EPS format PostScript 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 """ def set_size(self, width_in_points: float, height_in_points: float) -> None: """ :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) 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 def get_levels() -> List[PSLevel]: """ :returns: supported level list Retrieve the list of supported levels. See :meth:`restrict_to_level`. .. versionadded:: 1.12.0 """ class SVGSurface(Surface): """ The *SVGSurface* is used to render cairo graphics to SVG files and is a multi-page vector surface backend """ def __init__(self, fobj: "Union[_PathLike, _FileLike]", width_in_points: float, height_in_points: float) -> None: """ :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. :param width_in_points: width of the surface, in points (1 point == 1/72.0 inch) :param height_in_points: height of the surface, in points (1 point == 1/72.0 inch) """ def restrict_to_version(self, version: SVGVersion) -> None: """ :param 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 def get_versions() -> List[SVGVersion]: """ :returns: supported version list Retrieve the list of supported versions. See :meth:`restrict_to_version`. .. versionadded:: 1.12.0 """ @staticmethod def version_to_string(version: SVGVersion) -> str: """ :param version: SVG version :returns: the string associated to the given version :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 """ def get_document_unit(self) -> SVGUnit: """ :returns: the SVG unit of the SVG surface. :rtype: SVGUnit Get the unit of the SVG surface. .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ def set_document_unit(self, unit: SVGUnit) -> None: """ :param SVGUnit unit: SVG unit Use the specified unit for the width and height of the generated SVG file. See :class:`SVGUnit` for a list of available unit values that can be used here. This function can be called at any time before generating the SVG file. However to minimize the risk of ambiguities it's recommended to call it before any drawing operations have been performed on the given surface, to make it clearer what the unit used in the drawing operations is. The simplest way to do this is to call this function immediately after creating the SVG surface. Note if this function is never called, the default unit for SVG documents generated by cairo will be "pt". This is for historical reasons. .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ class RadialGradient(Gradient): def __init__(self, cx0: float, cy0: float, radius0: float, cx1: float, cy1: float, radius1: float) -> None: """ :param cx0: x coordinate for the center of the start circle :param cy0: y coordinate for the center of the start circle :param radius0: radius of the start circle :param cx1: x coordinate for the center of the end circle :param cy1: y coordinate for the center of the end circle :param radius1: radius of the end circle 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`. """ def get_radial_circles(self) -> Tuple[float, float, float, float, float, float]: """ :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 """ _AcquireCallback = Callable[[Surface, RectangleInt], Surface] _ReleaseCallback = Callable[[Surface], None] class RasterSourcePattern(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. .. versionadded:: 1.15 """ def __init__(self, content: Content, width: int, height: int) -> None: """ :param 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 width: maximum size of the sample area :param height: maximum size of the sample area Creates a new user pattern for providing pixel data. Use the setter functions to associate callbacks with the returned pattern. .. versionadded:: 1.15 """ def set_acquire(self, acquire: Optional[_AcquireCallback], release: Optional[_ReleaseCallback]) -> None: """ :param acquire: acquire callback or :obj:`None` to unset it :type acquire: :obj:`callable` :param release: (optional) release callback or :obj:`None` :type release: :obj:`callable` :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 """ def get_acquire(self) -> Tuple[Optional[_AcquireCallback], Optional[_ReleaseCallback]]: """ :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 """ class RecordingSurface(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. .. versionadded:: 1.11.0 """ def __init__(self, content: Content, rectangle: Rectangle) -> None: """ :param content: the content for the new surface :param rectangle: or None to record unbounded operations. 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 """ def ink_extents(self) -> Tuple[float, float, float, 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 """ def get_extents(self) -> Optional[Rectangle]: """ :returns: a rectangle or :obj:`None` if the surface is unbounded. Get the extents of the recording-surface. .. versionadded:: 1.12.0 """ 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. .. versionadded:: 1.11.0 """ def __init__(self, rectangle: Union[RectangleInt, List[RectangleInt]]) -> None: """ :param rectangle_int: a rectangle or a list of rectangle Allocates a new empty region object or a region object with the containing rectangle(s). """ def copy(self) -> "Region": """ :returns: A newly allocated :class:`Region`. Allocates a new *Region* object copying the area from original. """ def get_extents(self) -> RectangleInt: """ :returns: The bounding rectangle of region """ def num_rectangles(self) -> int: """ :returns: The number of rectangles contained in region """ def get_rectangle(self, nth: int) -> RectangleInt: """ :param nth: a number indicating which rectangle should be returned :returns: The *nth* rectangle from the region """ def is_empty(self) -> bool: """ :returns: Whether region is empty """ def contains_point(self, x: int, y: int) -> bool: """ :param x: The x coordinate of a point :param y: The y coordinate of a point :returns: Whether (x , y) is contained in the region """ def contains_rectangle(self, rectangle: RectangleInt) -> RegionOverlap: """ :param rectangle: a region :returns: region overlap Checks whether rectangle is inside, outside or partially contained in region """ def equal(self, region: "Region") -> bool: """ :param region: a region :returns: Whether both regions contained the same coverage """ def translate(self, dx: int, dy: int) -> None: """ :param dx: Amount to translate in the x direction :param dy: Amount to translate in the y direction Translates region by (dx , dy ). """ def intersect(self, other: "Union[Region, RectangleInt]") -> "Region": """ :param other: region or rectangle :returns: The intersection of the region and the passed region or rectangle """ def subtract(self, other: "Union[Region, RectangleInt]") -> "Region": """ :param other: region or rectangle :returns: The result of the subtraction of the region and the passed region or rectangle """ def union(self, other: "Union[Region, RectangleInt]") -> "Region": """ :param other: region or rectangle :returns: The union of the region and the passed region or rectangle """ def xor(self, other: "Union[Region, RectangleInt]") -> "Region": """ :param other: region or rectangle :returns: The exclusive difference of the region and the passed region or rectangle """ class ScriptDevice(Device): """ .. versionadded:: 1.14 """ def __init__(self, fobj: Union[_FileLike, _PathLike]) -> None: """ :param fobj: a filename or writable file object. Creates a output device for emitting the script, used when creating the individual surfaces. """ def set_mode(self, mode: ScriptMode) -> None: """ :param mode: the new mode Change the output mode of the script """ def get_mode(self) -> ScriptMode: """ :returns: the current output mode of the script Queries the script for its current output mode. """ def write_comment(self, comment: str) -> None: """ :param comment: the string to emit Emit a string verbatim into the script. """ def from_recording_surface(self, recording_surface: RecordingSurface) -> None: """ :param recording_surface: the recording surface to replay :raises cairo.Error: Converts the record operations in recording_surface into a script. """ class ScriptSurface(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. .. versionadded:: 1.14 """ def __init__(self, script: ScriptDevice, content: Content, width: float, height: float) -> None: """ :param script: the script (output device) :param content: the content of the surface :param width: width in pixels :param height: height in pixels :raises cairo.Error: Create a new surface that will emit its rendering through ``script``. """ @classmethod def create_for_target(cls, script: ScriptDevice, target: Surface) -> "ScriptSurface": """ :param script: the script (output device) :param target: a target surface to wrap :raises cairo.Error: Create a proxy surface that will render to ``target`` and record the operations to ``device``. .. versionadded:: 1.14 """ class Win32Surface(Surface): """ The Microsoft Windows surface is used to render cairo graphics to Microsoft Windows windows, bitmaps, and printing device contexts. """ def __init__(self, hdc: int) -> None: """ :param hdc: the DC to create a surface for :type hdc: int 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(Surface): """ The Win32PrintingSurface is a multi-page vector surface type. """ def __init__(self, hdc: int) -> None: """ :param hdc: the DC to create a surface for :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 SolidPattern(Pattern): def __init__(self, red: float, green: float, blue: float, alpha: float=1.0) -> None: """ :param red: red component of the color :param green: green component of the color :param blue: blue component of the color :param alpha: alpha component of the color 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. """ def get_rgba(self) -> Tuple[float, float, float, float]: """ :returns: (red, green, blue, alpha) a tuple of float Gets the solid color for a *SolidPattern*. .. versionadded:: 1.4 """ class SurfaceObserverMode(_IntEnum): """ Whether operations should be recorded. .. versionadded:: 1.14 """ NORMAL: "SurfaceObserverMode" = ... """no recording is done""" RECORD_OPERATIONS: "SurfaceObserverMode" = ... """operations are recorded""" class TeeSurface(Surface): """ This surface supports redirecting all its input to multiple surfaces. .. versionadded:: 1.14 """ def __init__(self, master: Surface) -> None: ... def add(self, target: Surface) -> None: """ :param target: :raises cairo.Error: Add the surface .. versionadded:: 1.14 """ def remove(self, target: Surface) -> None: """ :param target: :raises cairo.Error: Remove the surface .. versionadded:: 1.14 """ def index(self, index: int) -> Surface: """ :param index: :raises cairo.Error: Returns the surface at index ``index``. The master surface is at index 0. .. versionadded:: 1.14 """ class ToyFontFace(FontFace): """ The *cairo.ToyFontFace* class can be used instead of :meth:`Context.select_font_face` to create a toy font independently of a context. .. versionadded:: 1.8.4 """ def __init__(self, family: str, slant: FontSlant=..., weight: FontWeight=...) -> None: """ :param family: a font family name :param slant: the font slant of the font, defaults to :attr:`cairo.FontSlant.NORMAL`. :param weight: the font weight of the font, defaults to :attr:`cairo.FontWeight.NORMAL`. 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. """ def get_family(self) -> str: """ :returns: the family name of a toy font .. versionadded:: 1.8.4 """ def get_slant(self) -> FontSlant: """ :returns: the font slant value .. versionadded:: 1.8.4 """ def get_weight(self) -> FontWeight: """ :returns: the font weight value .. versionadded:: 1.8.4 """ class XCBSurface(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. """ def __init__(self, connection: Any, drawable: Any, visualtype: Any, width: int, height: int) -> None: """ :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 type isn't implemented. Please file a bug if you need it. """ def set_size(self, width: int, height: int) -> None: """ :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(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. .. 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/. """ def get_depth(self) -> int: """ :returns: the number of bits used to represent each pixel value. .. versionadded:: 1.2 """ def get_height(self) -> int: """ :returns: the height of the X Drawable underlying the surface in pixels. .. versionadded:: 1.2 """ def get_width(self) -> int: """ :returns: the width of the X Drawable underlying the surface in pixels. .. versionadded:: 1.2 """ def get_include() -> str: """ :returns: a path to the directory containing the C header files Gives the include path which should be passed to the compiler. .. versionadded:: 1.16.0 """ MIME_TYPE_JP2: str = ... """ The Joint Photographic Experts Group (JPEG) 2000 image coding standard (ISO/IEC 15444-1). .. versionadded:: 1.12.0 """ MIME_TYPE_JPEG: str = ... """ The Joint Photographic Experts Group (JPEG) image coding standard (ISO/IEC 10918-1). .. versionadded:: 1.12.0 """ MIME_TYPE_PNG: str = ... """ The Portable Network Graphics image file format (ISO/IEC 15948). .. versionadded:: 1.12.0 """ MIME_TYPE_URI: str = ... """ URI for an image file (unofficial MIME type). .. versionadded:: 1.12.0 """ MIME_TYPE_UNIQUE_ID: str = ... """ 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 """ MIME_TYPE_CCITT_FAX: str = ... """ Group 3 or Group 4 CCITT facsimile encoding (International Telecommunication Union, Recommendations T.4 and T.6.) .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ MIME_TYPE_CCITT_FAX_PARAMS: str = ... """ Decode parameters for Group 3 or Group 4 CCITT facsimile encoding. See `CCITT Fax Images `__. .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ MIME_TYPE_EPS: str = ... """ Encapsulated PostScript file. Encapsulated PostScript File Format Specification .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ MIME_TYPE_EPS_PARAMS: str = ... """ Embedding parameters Encapsulated PostScript data. See Embedding EPS files. .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ MIME_TYPE_JBIG2: str = ... """ Joint Bi-level Image Experts Group image coding standard (ISO/IEC 11544). .. versionadded:: 1.18.0 """ MIME_TYPE_JBIG2_GLOBAL: str = ... """ Joint Bi-level Image Experts Group image coding standard (ISO/IEC 11544) global segment. .. versionadded:: 1.18.0 """ MIME_TYPE_JBIG2_GLOBAL_ID: str = ... """ An unique identifier shared by a JBIG2 global segment and all JBIG2 images that depend on the global segment. .. versionadded:: 1.18.0 """ TAG_DEST: str = ... """ Create a destination for a hyperlink. Destination tag attributes are detailed at Destinations. .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ TAG_LINK: str = ... """ Create hyperlink. Link tag attributes are detailed at Links. .. versionadded:: 1.18.0 Only available with cairo 1.15.10+ """ TAG_CONTENT: str = ... """ Create a content tag. .. versionadded:: 1.25.0 Only available with cairo 1.18.0+ """ TAG_CONTENT_REF: str = ... """ Create a content reference tag. .. versionadded:: 1.25.0 Only available with cairo 1.18.0+ """ CAPI: Any = ... ANTIALIAS_BEST = Antialias.BEST ANTIALIAS_DEFAULT = Antialias.DEFAULT ANTIALIAS_FAST = Antialias.FAST ANTIALIAS_GOOD = Antialias.GOOD ANTIALIAS_GRAY = Antialias.GRAY ANTIALIAS_NONE = Antialias.NONE ANTIALIAS_SUBPIXEL = Antialias.SUBPIXEL CONTENT_ALPHA = Content.ALPHA CONTENT_COLOR = Content.COLOR CONTENT_COLOR_ALPHA = Content.COLOR_ALPHA EXTEND_NONE = Extend.NONE EXTEND_PAD = Extend.PAD EXTEND_REFLECT = Extend.REFLECT EXTEND_REPEAT = Extend.REPEAT FILL_RULE_EVEN_ODD = FillRule.EVEN_ODD FILL_RULE_WINDING = FillRule.WINDING FILTER_BEST = Filter.BEST FILTER_BILINEAR = Filter.BILINEAR FILTER_FAST = Filter.FAST FILTER_GAUSSIAN = Filter.GAUSSIAN FILTER_GOOD = Filter.GOOD FILTER_NEAREST = Filter.NEAREST FONT_SLANT_ITALIC = FontSlant.ITALIC FONT_SLANT_NORMAL = FontSlant.NORMAL FONT_SLANT_OBLIQUE = FontSlant.OBLIQUE FONT_WEIGHT_BOLD = FontWeight.BOLD FONT_WEIGHT_NORMAL = FontWeight.NORMAL FORMAT_A1 = Format.A1 FORMAT_A8 = Format.A8 FORMAT_ARGB32 = Format.ARGB32 FORMAT_INVALID = Format.INVALID FORMAT_RGB16_565 = Format.RGB16_565 FORMAT_RGB24 = Format.RGB24 FORMAT_RGB30 = Format.RGB30 FORMAT_RGB96F = Format.RGB96F FORMAT_RGBA128F = Format.RGBA128F HINT_METRICS_DEFAULT = HintMetrics.DEFAULT HINT_METRICS_OFF = HintMetrics.OFF HINT_METRICS_ON = HintMetrics.ON HINT_STYLE_DEFAULT = HintStyle.DEFAULT HINT_STYLE_FULL = HintStyle.FULL HINT_STYLE_MEDIUM = HintStyle.MEDIUM HINT_STYLE_NONE = HintStyle.NONE HINT_STYLE_SLIGHT = HintStyle.SLIGHT LINE_CAP_BUTT = LineCap.BUTT LINE_CAP_ROUND = LineCap.ROUND LINE_CAP_SQUARE = LineCap.SQUARE LINE_JOIN_BEVEL = LineJoin.BEVEL LINE_JOIN_MITER = LineJoin.MITER LINE_JOIN_ROUND = LineJoin.ROUND OPERATOR_ADD = Operator.ADD OPERATOR_ATOP = Operator.ATOP OPERATOR_CLEAR = Operator.CLEAR OPERATOR_COLOR_BURN = Operator.COLOR_BURN OPERATOR_COLOR_DODGE = Operator.COLOR_DODGE OPERATOR_DARKEN = Operator.DARKEN OPERATOR_DEST = Operator.DEST OPERATOR_DEST_ATOP = Operator.DEST_ATOP OPERATOR_DEST_IN = Operator.DEST_IN OPERATOR_DEST_OUT = Operator.DEST_OUT OPERATOR_DEST_OVER = Operator.DEST_OVER OPERATOR_DIFFERENCE = Operator.DIFFERENCE OPERATOR_EXCLUSION = Operator.EXCLUSION OPERATOR_HARD_LIGHT = Operator.HARD_LIGHT OPERATOR_HSL_COLOR = Operator.HSL_COLOR OPERATOR_HSL_HUE = Operator.HSL_HUE OPERATOR_HSL_LUMINOSITY = Operator.HSL_LUMINOSITY OPERATOR_HSL_SATURATION = Operator.HSL_SATURATION OPERATOR_IN = Operator.IN OPERATOR_LIGHTEN = Operator.LIGHTEN OPERATOR_MULTIPLY = Operator.MULTIPLY OPERATOR_OUT = Operator.OUT OPERATOR_OVER = Operator.OVER OPERATOR_OVERLAY = Operator.OVERLAY OPERATOR_SATURATE = Operator.SATURATE OPERATOR_SCREEN = Operator.SCREEN OPERATOR_SOFT_LIGHT = Operator.SOFT_LIGHT OPERATOR_SOURCE = Operator.SOURCE OPERATOR_XOR = Operator.XOR PATH_CLOSE_PATH = PathDataType.CLOSE_PATH PATH_CURVE_TO = PathDataType.CURVE_TO PATH_LINE_TO = PathDataType.LINE_TO PATH_MOVE_TO = PathDataType.MOVE_TO PDF_VERSION_1_4 = PDFVersion.VERSION_1_4 PDF_VERSION_1_5 = PDFVersion.VERSION_1_5 PDF_VERSION_1_6 = PDFVersion.VERSION_1_6 PDF_VERSION_1_7 = PDFVersion.VERSION_1_7 PS_LEVEL_2 = PSLevel.LEVEL_2 PS_LEVEL_3 = PSLevel.LEVEL_3 REGION_OVERLAP_IN = RegionOverlap.IN REGION_OVERLAP_OUT = RegionOverlap.OUT REGION_OVERLAP_PART = RegionOverlap.PART SCRIPT_MODE_ASCII = ScriptMode.ASCII SCRIPT_MODE_BINARY = ScriptMode.BINARY STATUS_CLIP_NOT_REPRESENTABLE = Status.CLIP_NOT_REPRESENTABLE STATUS_DEVICE_ERROR = Status.DEVICE_ERROR STATUS_DEVICE_FINISHED = Status.DEVICE_FINISHED STATUS_DEVICE_TYPE_MISMATCH = Status.DEVICE_TYPE_MISMATCH STATUS_FILE_NOT_FOUND = Status.FILE_NOT_FOUND STATUS_FONT_TYPE_MISMATCH = Status.FONT_TYPE_MISMATCH STATUS_INVALID_CLUSTERS = Status.INVALID_CLUSTERS STATUS_INVALID_CONTENT = Status.INVALID_CONTENT STATUS_INVALID_DASH = Status.INVALID_DASH STATUS_INVALID_DSC_COMMENT = Status.INVALID_DSC_COMMENT STATUS_INVALID_FORMAT = Status.INVALID_FORMAT STATUS_INVALID_INDEX = Status.INVALID_INDEX STATUS_INVALID_MATRIX = Status.INVALID_MATRIX STATUS_INVALID_MESH_CONSTRUCTION = Status.INVALID_MESH_CONSTRUCTION STATUS_INVALID_PATH_DATA = Status.INVALID_PATH_DATA STATUS_INVALID_POP_GROUP = Status.INVALID_POP_GROUP STATUS_INVALID_RESTORE = Status.INVALID_RESTORE STATUS_INVALID_SIZE = Status.INVALID_SIZE STATUS_INVALID_SLANT = Status.INVALID_SLANT STATUS_INVALID_STATUS = Status.INVALID_STATUS STATUS_INVALID_STRIDE = Status.INVALID_STRIDE STATUS_INVALID_STRING = Status.INVALID_STRING STATUS_INVALID_VISUAL = Status.INVALID_VISUAL STATUS_INVALID_WEIGHT = Status.INVALID_WEIGHT STATUS_JBIG2_GLOBAL_MISSING = Status.JBIG2_GLOBAL_MISSING STATUS_LAST_STATUS = Status.LAST_STATUS STATUS_NEGATIVE_COUNT = Status.NEGATIVE_COUNT STATUS_NO_CURRENT_POINT = Status.NO_CURRENT_POINT STATUS_NO_MEMORY = Status.NO_MEMORY STATUS_NULL_POINTER = Status.NULL_POINTER STATUS_PATTERN_TYPE_MISMATCH = Status.PATTERN_TYPE_MISMATCH STATUS_READ_ERROR = Status.READ_ERROR STATUS_SUCCESS = Status.SUCCESS STATUS_SURFACE_FINISHED = Status.SURFACE_FINISHED STATUS_SURFACE_TYPE_MISMATCH = Status.SURFACE_TYPE_MISMATCH STATUS_TEMP_FILE_ERROR = Status.TEMP_FILE_ERROR STATUS_USER_FONT_ERROR = Status.USER_FONT_ERROR STATUS_USER_FONT_IMMUTABLE = Status.USER_FONT_IMMUTABLE STATUS_USER_FONT_NOT_IMPLEMENTED = Status.USER_FONT_NOT_IMPLEMENTED STATUS_WRITE_ERROR = Status.WRITE_ERROR SUBPIXEL_ORDER_BGR = SubpixelOrder.BGR SUBPIXEL_ORDER_DEFAULT = SubpixelOrder.DEFAULT SUBPIXEL_ORDER_RGB = SubpixelOrder.RGB SUBPIXEL_ORDER_VBGR = SubpixelOrder. VBGR SUBPIXEL_ORDER_VRGB = SubpixelOrder.VRGB SURFACE_OBSERVER_NORMAL = SurfaceObserverMode.NORMAL SURFACE_OBSERVER_RECORD_OPERATIONS = SurfaceObserverMode.RECORD_OPERATIONS SVG_VERSION_1_1 = SVGVersion.VERSION_1_1 SVG_VERSION_1_2 = SVGVersion.VERSION_1_2 TEXT_CLUSTER_FLAG_BACKWARD = TextClusterFlags.BACKWARD PDF_METADATA_TITLE = PDFMetadata.TITLE PDF_METADATA_AUTHOR = PDFMetadata.AUTHOR PDF_METADATA_SUBJECT = PDFMetadata.SUBJECT PDF_METADATA_KEYWORDS = PDFMetadata.KEYWORDS PDF_METADATA_CREATOR = PDFMetadata.CREATOR PDF_METADATA_CREATE_DATE = PDFMetadata.CREATE_DATE PDF_METADATA_MOD_DATE = PDFMetadata.MOD_DATE SVG_UNIT_USER = SVGUnit.USER SVG_UNIT_EM = SVGUnit.EM SVG_UNIT_EX = SVGUnit.EX SVG_UNIT_PX = SVGUnit.PX SVG_UNIT_IN = SVGUnit.IN SVG_UNIT_CM = SVGUnit.CM SVG_UNIT_MM = SVGUnit.MM SVG_UNIT_PT = SVGUnit.PT SVG_UNIT_PC = SVGUnit.PC SVG_UNIT_PERCENT = SVGUnit.PERCENT STATUS_TAG_ERROR = Status.TAG_ERROR STATUS_FREETYPE_ERROR = Status.FREETYPE_ERROR STATUS_WIN32_GDI_ERROR = Status.WIN32_GDI_ERROR STATUS_PNG_ERROR = Status.PNG_ERROR STATUS_DWRITE_ERROR = Status.DWRITE_ERROR STATUS_SVG_FONT_ERROR = Status.SVG_FONT_ERROR PDF_OUTLINE_FLAG_OPEN = PDFOutlineFlags.OPEN PDF_OUTLINE_FLAG_BOLD = PDFOutlineFlags.BOLD PDF_OUTLINE_FLAG_ITALIC = PDFOutlineFlags.ITALIC COLOR_MODE_DEFAULT = ColorMode.DEFAULT COLOR_MODE_NO_COLOR = ColorMode.NO_COLOR COLOR_MODE_COLOR = ColorMode.COLOR DITHER_NONE = Dither.NONE DITHER_DEFAULT = Dither.DEFAULT DITHER_FAST = Dither.FAST DITHER_GOOD = Dither.GOOD DITHER_BEST = Dither.BEST pycairo-1.25.1/cairo/bufferproxy.c000066400000000000000000000073511451476466400171110ustar00rootroot00000000000000/* -*- 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" 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); } int init_buffer_proxy (void) { 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; return 0; } pycairo-1.25.1/cairo/cairomodule.c000066400000000000000000000402671451476466400170440ustar00rootroot00000000000000/* -*- 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" #ifdef CAIRO_HAS_PDF_SURFACE #include #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, PyObject *ignored) { return PyLong_FromLong (cairo_version()); } static PyObject * pycairo_cairo_version_string (PyObject *self, PyObject *ignored) { return 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}, }; static struct PyModuleDef cairomoduledef = { PyModuleDef_HEAD_INIT, "cairo", NULL, 0, cairo_functions, 0, 0, 0, 0, }; PYCAIRO_MODINIT_FUNC PyInit__cairo(void) { PyObject *m, *capi; if (PyType_Ready(&PycairoContext_Type) < 0) return NULL; if (PyType_Ready(&PycairoFontFace_Type) < 0) return NULL; if (PyType_Ready(&PycairoToyFontFace_Type) < 0) return NULL; if (PyType_Ready(&PycairoFontOptions_Type) < 0) return NULL; if (PyType_Ready(&PycairoMatrix_Type) < 0) return NULL; if (PyType_Ready(&PycairoPath_Type) < 0) return NULL; PycairoPathiter_Type.tp_iter=&PyObject_SelfIter; if (PyType_Ready(&PycairoPathiter_Type) < 0) return NULL; if (PyType_Ready(&PycairoPattern_Type) < 0) return NULL; if (PyType_Ready(&PycairoSolidPattern_Type) < 0) return NULL; if (PyType_Ready(&PycairoSurfacePattern_Type) < 0) return NULL; if (PyType_Ready(&PycairoGradient_Type) < 0) return NULL; if (PyType_Ready(&PycairoLinearGradient_Type) < 0) return NULL; if (PyType_Ready(&PycairoRadialGradient_Type) < 0) return NULL; if (PyType_Ready(&PycairoMeshPattern_Type) < 0) return NULL; if (PyType_Ready(&PycairoRasterSourcePattern_Type) < 0) return NULL; if (PyType_Ready(&PycairoRectangleInt_Type) < 0) return NULL; if (PyType_Ready(&PycairoDevice_Type) < 0) return NULL; PycairoGlyph_Type.tp_base = &PyTuple_Type; if (PyType_Ready(&PycairoGlyph_Type) < 0) return NULL; PycairoRectangle_Type.tp_base = &PyTuple_Type; if (PyType_Ready(&PycairoRectangle_Type) < 0) return NULL; PycairoTextCluster_Type.tp_base = &PyTuple_Type; if (PyType_Ready(&PycairoTextCluster_Type) < 0) return NULL; PycairoTextExtents_Type.tp_base = &PyTuple_Type; if (PyType_Ready(&PycairoTextExtents_Type) < 0) return NULL; if (PyType_Ready(&PycairoSurface_Type) < 0) return NULL; #ifdef CAIRO_HAS_SCRIPT_SURFACE if (PyType_Ready(&PycairoScriptDevice_Type) < 0) return NULL; if (PyType_Ready(&PycairoScriptSurface_Type) < 0) return NULL; #endif if (PyType_Ready(&PycairoRegion_Type) < 0) return NULL; if (PyType_Ready(&PycairoScaledFont_Type) < 0) return NULL; #ifdef CAIRO_HAS_IMAGE_SURFACE if (PyType_Ready(&PycairoImageSurface_Type) < 0) return NULL; if (PyType_Ready(&PycairoMappedImageSurface_Type) < 0) return NULL; #endif #ifdef CAIRO_HAS_PDF_SURFACE if (PyType_Ready(&PycairoPDFSurface_Type) < 0) return NULL; #endif #ifdef CAIRO_HAS_PS_SURFACE if (PyType_Ready(&PycairoPSSurface_Type) < 0) return NULL; #endif #ifdef CAIRO_HAS_RECORDING_SURFACE if (PyType_Ready(&PycairoRecordingSurface_Type) < 0) return NULL; #endif #ifdef CAIRO_HAS_SVG_SURFACE if (PyType_Ready(&PycairoSVGSurface_Type) < 0) return NULL; #endif #ifdef CAIRO_HAS_WIN32_SURFACE if (PyType_Ready(&PycairoWin32Surface_Type) < 0) return NULL; if (PyType_Ready(&PycairoWin32PrintingSurface_Type) < 0) return NULL; #endif #ifdef CAIRO_HAS_XCB_SURFACE if (PyType_Ready(&PycairoXCBSurface_Type) < 0) return NULL; #endif #ifdef CAIRO_HAS_XLIB_SURFACE if (PyType_Ready(&PycairoXlibSurface_Type) < 0) return NULL; #endif #ifdef CAIRO_HAS_TEE_SURFACE if (PyType_Ready(&PycairoTeeSurface_Type) < 0) return NULL; #endif m = PyModule_Create(&cairomoduledef); if (m == NULL) return NULL; if(init_error(m) < 0) return NULL; if(init_buffer_proxy() < 0) return NULL; if(init_enums(m) < 0) return NULL; 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); #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) PyModule_AddIntConstant(m, "PDF_OUTLINE_ROOT", CAIRO_PDF_OUTLINE_ROOT); #endif #endif #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 8) PyModule_AddIntConstant(m, "COLOR_PALETTE_DEFAULT", CAIRO_COLOR_PALETTE_DEFAULT); #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 #ifdef CAIRO_HAS_DWRITE_FONT PyModule_AddIntConstant(m, "HAS_DWRITE_FONT", 1); #else PyModule_AddIntConstant(m, "HAS_DWRITE_FONT", 0); #endif PyModule_AddIntConstant(m, "CAIRO_VERSION", CAIRO_VERSION); PyModule_AddIntConstant(m, "CAIRO_VERSION_MAJOR", CAIRO_VERSION_MAJOR); PyModule_AddIntConstant(m, "CAIRO_VERSION_MICRO", CAIRO_VERSION_MICRO); PyModule_AddIntConstant(m, "CAIRO_VERSION_MINOR", CAIRO_VERSION_MINOR); PyModule_AddStringConstant(m, "CAIRO_VERSION_STRING", CAIRO_VERSION_STRING); #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); STRCONSTANT(MIME_TYPE_JBIG2); STRCONSTANT(MIME_TYPE_JBIG2_GLOBAL); STRCONSTANT(MIME_TYPE_JBIG2_GLOBAL_ID); #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) STRCONSTANT(MIME_TYPE_CCITT_FAX); STRCONSTANT(MIME_TYPE_CCITT_FAX_PARAMS); STRCONSTANT(MIME_TYPE_EPS); STRCONSTANT(MIME_TYPE_EPS_PARAMS); STRCONSTANT(TAG_DEST); STRCONSTANT(TAG_LINK); #endif #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 18, 0) STRCONSTANT(TAG_CONTENT); STRCONSTANT(TAG_CONTENT_REF); #endif #undef STRCONSTANT /* Create a Capsule containing the CAPI pointer */ capi = PyCapsule_New((void *)(&CAPI), "cairo.CAPI", 0); if (capi != NULL) { PyModule_AddObject(m, "CAPI", capi); } return m; } pycairo-1.25.1/cairo/context.c000066400000000000000000001352701451476466400162240ustar00rootroot00000000000000/* -*- 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); } #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 6) static PyObject * pycairo_set_hairline (PycairoContext *o, PyObject *args) { PyObject *py_hairline; if (!PyArg_ParseTuple(args, "O!:Context.set_hairline", &PyBool_Type, &py_hairline)) return NULL; cairo_set_hairline (o->ctx, (py_hairline == Py_True)); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_get_hairline (PycairoContext *o, PyObject *ignored) { PyObject *set_hairline = cairo_get_hairline (o->ctx) ? Py_True : Py_False; RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_INCREF(set_hairline); return set_hairline; } #endif #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) static PyObject * pycairo_tag_begin (PycairoContext *o, PyObject *args) { const char *tag_name; const char *attributes; if (!PyArg_ParseTuple (args, "eses:Context.tag_begin", "utf-8", &tag_name, "utf-8", &attributes)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_tag_begin (o->ctx, tag_name, attributes); Py_END_ALLOW_THREADS; PyMem_Free((void *)tag_name); PyMem_Free((void *)attributes); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_tag_end (PycairoContext *o, PyObject *args) { const char *tag_name; if (!PyArg_ParseTuple (args, "es:Context.tag_end", "utf-8", &tag_name)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_tag_end (o->ctx, tag_name); Py_END_ALLOW_THREADS; PyMem_Free((void *)tag_name); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } #endif 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { RETURN_INT_ENUM (Antialias, cairo_get_antialias (o->ctx)); } static PyObject * pycairo_get_current_point (PycairoContext *o, PyObject *ignored) { double x, y; cairo_get_current_point (o->ctx, &x, &y); return Py_BuildValue("(dd)", x, y); } static PyObject * pycairo_get_dash (PycairoContext *o, PyObject *ignored) { 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, PyObject *ignored) { return PyLong_FromLong (cairo_get_dash_count (o->ctx)); } static PyObject * pycairo_get_fill_rule (PycairoContext *o, PyObject *ignored) { RETURN_INT_ENUM(FillRule, cairo_get_fill_rule (o->ctx)); } static PyObject * pycairo_get_font_face (PycairoContext *o, PyObject *ignored) { return PycairoFontFace_FromFontFace ( cairo_font_face_reference (cairo_get_font_face (o->ctx))); } static PyObject * pycairo_get_font_matrix (PycairoContext *o, PyObject *ignored) { cairo_matrix_t matrix; cairo_get_font_matrix (o->ctx, &matrix); return PycairoMatrix_FromMatrix (&matrix); } static PyObject * pycairo_get_font_options (PycairoContext *o, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { RETURN_INT_ENUM(LineCap, cairo_get_line_cap (o->ctx)); } static PyObject * pycairo_get_line_join (PycairoContext *o, PyObject *ignored) { RETURN_INT_ENUM(LineJoin, cairo_get_line_join (o->ctx)); } static PyObject * pycairo_get_line_width (PycairoContext *o, PyObject *ignored) { return PyFloat_FromDouble(cairo_get_line_width (o->ctx)); } static PyObject * pycairo_get_matrix (PycairoContext *o, PyObject *ignored) { cairo_matrix_t matrix; cairo_get_matrix (o->ctx, &matrix); return PycairoMatrix_FromMatrix (&matrix); } static PyObject * pycairo_get_miter_limit (PycairoContext *o, PyObject *ignored) { return PyFloat_FromDouble (cairo_get_miter_limit (o->ctx)); } static PyObject * pycairo_get_operator (PycairoContext *o, PyObject *ignored) { RETURN_INT_ENUM(Operator, cairo_get_operator (o->ctx)); } static PyObject * pycairo_get_scaled_font (PycairoContext *o, PyObject *ignored) { return PycairoScaledFont_FromScaledFont ( cairo_scaled_font_reference (cairo_get_scaled_font (o->ctx))); } static PyObject * pycairo_get_source (PycairoContext *o, PyObject *ignored) { return PycairoPattern_FromPattern ( cairo_pattern_reference (cairo_get_source (o->ctx)), NULL); } static PyObject * pycairo_get_target (PycairoContext *o, PyObject *ignored) { return PycairoSurface_FromSurface ( cairo_surface_reference (cairo_get_target (o->ctx)), NULL); } static PyObject * pycairo_get_tolerance (PycairoContext *o, PyObject *ignored) { 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 *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { cairo_new_path (o->ctx); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_new_sub_path (PycairoContext *o, PyObject *ignored) { cairo_new_sub_path (o->ctx); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_paint (PycairoContext *o, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { return PycairoPattern_FromPattern (cairo_pop_group (o->ctx), NULL); } static PyObject * pycairo_pop_group_to_source (PycairoContext *o, PyObject *ignored) { cairo_pop_group_to_source (o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_push_group (PycairoContext *o, PyObject *ignored) { 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, PyObject *ignored) { cairo_reset_clip (o->ctx); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); Py_RETURN_NONE; } static PyObject * pycairo_restore (PycairoContext *o, PyObject *ignored) { 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, PyObject *ignored) { 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, "es|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, PyObject *ignored) { 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, "es: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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, "es: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, "es: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, "esOOi: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 */ #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 6) {"set_hairline", (PyCFunction)pycairo_set_hairline, METH_VARARGS}, {"get_hairline", (PyCFunction)pycairo_get_hairline, METH_NOARGS}, #endif #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) {"tag_begin", (PyCFunction)pycairo_tag_begin, METH_VARARGS}, {"tag_end", (PyCFunction)pycairo_tag_end, METH_VARARGS}, #endif {"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 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.25.1/cairo/device.c000066400000000000000000000326471451476466400160030ustar00rootroot00000000000000/* 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, PyObject *ignored) { cairo_device_finish (obj->device); RETURN_NULL_IF_CAIRO_DEVICE_ERROR(obj->device); Py_RETURN_NONE; } static PyObject * device_flush (PycairoDevice *obj, PyObject *ignored) { cairo_device_flush (obj->device); RETURN_NULL_IF_CAIRO_DEVICE_ERROR(obj->device); Py_RETURN_NONE; } static PyObject * device_acquire (PycairoDevice *obj, PyObject *ignored) { 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, PyObject *ignored) { cairo_device_release (obj->device); Py_RETURN_NONE; } static PyObject * device_ctx_enter (PyObject *obj, PyObject *ignored) { Py_INCREF (obj); return obj; } static PyObject * device_ctx_exit (PycairoDevice *obj, PyObject *args) { Py_BEGIN_ALLOW_THREADS; cairo_device_finish (obj->device); Py_END_ALLOW_THREADS; Py_RETURN_NONE; } static PyMethodDef device_methods[] = { {"__enter__", (PyCFunction)device_ctx_enter, METH_NOARGS}, {"__exit__", (PyCFunction)device_ctx_exit, METH_VARARGS}, {"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 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", "(y#)", 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 BytesIO) taking bytes."); return NULL; } } } static PyObject * script_device_get_mode (PycairoDevice *obj, PyObject *ignored) { 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.25.1/cairo/enums.c000066400000000000000000000407751451476466400156740ustar00rootroot00000000000000/* -*- 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 { 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 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 = PyLong_FromLong(value); name_obj = 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 PyUnicode_FromFormat ("%s.%s", Py_TYPE(obj)->tp_name, PyUnicode_AsUTF8(name_obj)); } static PyObject * int_enum_repr(PyObject *obj) { PyObject *name_obj; name_obj = int_enum_get_name(obj); if(name_obj == NULL) return PyLong_Type.tp_repr(obj); return name_obj; } static PyObject * int_enum_reduce(PyObject *self, PyObject *ignored) { PyObject *num = PyNumber_Long (self); if (num == NULL) return NULL; return Py_BuildValue ("(O, (N))", &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) #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) DEFINE_ENUM(SVGUnit) #endif #endif #ifdef CAIRO_HAS_PDF_SURFACE DEFINE_ENUM(PDFVersion) #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) DEFINE_ENUM(PDFMetadata); DEFINE_ENUM(PDFOutlineFlags); #endif #endif #ifdef CAIRO_HAS_PS_SURFACE DEFINE_ENUM(PSLevel) #endif #ifdef CAIRO_HAS_SCRIPT_SURFACE DEFINE_ENUM(ScriptMode) #endif #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 8) DEFINE_ENUM(ColorMode) #endif #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 18, 0) DEFINE_ENUM(Dither) #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 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_str = PyLong_Type.tp_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 = &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); #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 2) CONSTANT(Format, FORMAT, RGB96F); CONSTANT(Format, FORMAT, RGBA128F); #endif 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); #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) CONSTANT(Status, STATUS, PNG_ERROR); CONSTANT(Status, STATUS, FREETYPE_ERROR); CONSTANT(Status, STATUS, WIN32_GDI_ERROR); CONSTANT(Status, STATUS, TAG_ERROR); #endif #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 6) CONSTANT(Status, STATUS, DWRITE_ERROR); #endif #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 8) CONSTANT(Status, STATUS, SVG_FONT_ERROR); #endif 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); #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) ENUM(SVGUnit); CONSTANT(SVGUnit, SVG_UNIT, USER); CONSTANT(SVGUnit, SVG_UNIT, EM); CONSTANT(SVGUnit, SVG_UNIT, EX); CONSTANT(SVGUnit, SVG_UNIT, PX); CONSTANT(SVGUnit, SVG_UNIT, IN); CONSTANT(SVGUnit, SVG_UNIT, CM); CONSTANT(SVGUnit, SVG_UNIT, MM); CONSTANT(SVGUnit, SVG_UNIT, PT); CONSTANT(SVGUnit, SVG_UNIT, PC); CONSTANT(SVGUnit, SVG_UNIT, PERCENT); #endif #endif #ifdef CAIRO_HAS_PDF_SURFACE ENUM(PDFVersion); CONSTANT(PDFVersion, PDF, VERSION_1_4); CONSTANT(PDFVersion, PDF, VERSION_1_5); #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 6) CONSTANT(PDFVersion, PDF, VERSION_1_6); CONSTANT(PDFVersion, PDF, VERSION_1_7); #endif #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) ENUM(PDFMetadata); CONSTANT(PDFMetadata, PDF_METADATA, TITLE); CONSTANT(PDFMetadata, PDF_METADATA, AUTHOR); CONSTANT(PDFMetadata, PDF_METADATA, SUBJECT); CONSTANT(PDFMetadata, PDF_METADATA, KEYWORDS); CONSTANT(PDFMetadata, PDF_METADATA, CREATOR); CONSTANT(PDFMetadata, PDF_METADATA, CREATE_DATE); CONSTANT(PDFMetadata, PDF_METADATA, MOD_DATE); ENUM(PDFOutlineFlags); CONSTANT(PDFOutlineFlags, PDF_OUTLINE_FLAG, OPEN); CONSTANT(PDFOutlineFlags, PDF_OUTLINE_FLAG, BOLD); CONSTANT(PDFOutlineFlags, PDF_OUTLINE_FLAG, ITALIC); #endif #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 #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 8) ENUM(ColorMode) CONSTANT(ColorMode, COLOR_MODE, DEFAULT); CONSTANT(ColorMode, COLOR_MODE, NO_COLOR); CONSTANT(ColorMode, COLOR_MODE, COLOR); #endif #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 18, 0) ENUM(Dither) CONSTANT(Dither, DITHER, NONE); CONSTANT(Dither, DITHER, DEFAULT); CONSTANT(Dither, DITHER, FAST); CONSTANT(Dither, DITHER, GOOD); CONSTANT(Dither, DITHER, BEST); #endif #undef ENUM #undef CONSTANT return 0; } pycairo-1.25.1/cairo/error.c000066400000000000000000000214571451476466400156720ustar00rootroot00000000000000/* -*- 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, *int_enum; int_enum = CREATE_INT_ENUM(Status, status); if (int_enum == NULL) return; args = Py_BuildValue("(sO)", status_to_string(status), int_enum); Py_DECREF (int_enum); 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.25.1/cairo/font.c000066400000000000000000001016271451476466400155050ustar00rootroot00000000000000/* -*- 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 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, "es|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, PyObject *ignored) { return PyUnicode_FromString (cairo_toy_font_face_get_family (o->font_face)); } static PyObject * toy_font_get_slant (PycairoToyFontFace *o, PyObject *ignored) { RETURN_INT_ENUM (FontSlant, cairo_toy_font_face_get_slant (o->font_face)); } static PyObject * toy_font_get_weight (PycairoToyFontFace *o, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, "es: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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, "ddes|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 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()); } #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 12) static PyObject * font_options_set_variations (PycairoFontOptions *o, PyObject *args) { const char *variations; PyObject *maybe_none; if (!PyArg_ParseTuple (args, "O:FontOptions.set_variations", &maybe_none)) return NULL; if (maybe_none != Py_None) { if (!PyArg_ParseTuple (args, "es:FontOptions.set_variations", "utf-8", &variations)) return NULL; } else { variations = NULL; } Py_BEGIN_ALLOW_THREADS; cairo_font_options_set_variations (o->font_options, variations); Py_END_ALLOW_THREADS; if (variations != NULL) PyMem_Free((void *)variations); RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options); Py_RETURN_NONE; } static PyObject * font_options_get_variations (PycairoFontOptions *o, PyObject *ignored) { const char *variations; Py_BEGIN_ALLOW_THREADS; variations = cairo_font_options_get_variations (o->font_options); Py_END_ALLOW_THREADS; if (variations == NULL) Py_RETURN_NONE; return PyUnicode_FromString (variations); } #endif #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 8) static PyObject * font_options_set_color_mode (PycairoFontOptions *o, PyObject *args) { cairo_color_mode_t color_mode; int color_mode_arg; if (!PyArg_ParseTuple (args, "i:FontOptions.set_color_mode", &color_mode_arg)) return NULL; color_mode = (cairo_color_mode_t)color_mode_arg; cairo_font_options_set_color_mode (o->font_options, color_mode); RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options); Py_RETURN_NONE; } static PyObject * font_options_get_color_mode (PycairoFontOptions *o, PyObject *ignored) { RETURN_INT_ENUM (ColorMode, cairo_font_options_get_color_mode (o->font_options)); } static PyObject * font_options_set_color_palette (PycairoFontOptions *o, PyObject *args) { unsigned int color_palette; if (!PyArg_ParseTuple (args, "I:FontOptions.set_color_palette", &color_palette)) return NULL; cairo_font_options_set_color_palette (o->font_options, color_palette); RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options); Py_RETURN_NONE; } static PyObject * font_options_get_color_palette (PycairoFontOptions *o, PyObject *ignored) { return PyLong_FromUnsignedLong (cairo_font_options_get_color_palette (o->font_options)); } static PyObject * font_options_set_custom_palette_color (PycairoFontOptions *o, PyObject *args) { double red, green, blue, alpha; unsigned int index; if (!PyArg_ParseTuple (args, "Idddd:FontOptions.set_custom_palette_color", &index, &red, &green, &blue, &alpha)) return NULL; cairo_font_options_set_custom_palette_color (o->font_options, index, red, green, blue, alpha); RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options); Py_RETURN_NONE; } static PyObject * font_options_get_custom_palette_color (PycairoFontOptions *o, PyObject *args) { double red, green, blue, alpha; unsigned int index; cairo_status_t status; if (!PyArg_ParseTuple (args, "I:FontOptions.get_custom_palette_color", &index)) return NULL; status = cairo_font_options_get_custom_palette_color (o->font_options, index, &red, &green, &blue, &alpha); RETURN_NULL_IF_CAIRO_ERROR (status); return Py_BuildValue("(dddd)", red, green, blue, alpha); } #endif static PyObject * font_options_get_antialias (PycairoFontOptions *o, PyObject *ignored) { RETURN_INT_ENUM (Antialias, cairo_font_options_get_antialias (o->font_options)); } static PyObject * font_options_get_hint_metrics (PycairoFontOptions *o, PyObject *ignored) { RETURN_INT_ENUM (HintMetrics, cairo_font_options_get_hint_metrics (o->font_options)); } static PyObject * font_options_get_hint_style (PycairoFontOptions *o, PyObject *ignored) { RETURN_INT_ENUM (HintStyle, cairo_font_options_get_hint_style (o->font_options)); } static PyObject * font_options_get_subpixel_order (PycairoFontOptions *o, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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() */ #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 12) {"get_variations", (PyCFunction)font_options_get_variations, METH_NOARGS}, {"set_variations", (PyCFunction)font_options_set_variations, METH_VARARGS}, #endif #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 8) {"get_color_mode", (PyCFunction)font_options_get_color_mode, METH_NOARGS}, {"set_color_mode", (PyCFunction)font_options_set_color_mode, METH_VARARGS}, {"get_color_palette", (PyCFunction)font_options_get_color_palette, METH_NOARGS}, {"set_color_palette", (PyCFunction)font_options_set_color_palette, METH_VARARGS}, {"get_custom_palette_color", (PyCFunction)font_options_get_custom_palette_color, METH_VARARGS}, {"set_custom_palette_color", (PyCFunction)font_options_set_custom_palette_color, METH_VARARGS}, #endif {"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.25.1/cairo/glyph.c000066400000000000000000000174251451476466400156640ustar00rootroot00000000000000/* -*- 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 = 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 = 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 = PyUnicode_FromString ( "cairo.Glyph(index=%r, x=%r, y=%r)"); if (format == NULL) return NULL; result = PyUnicode_Format (format, self); Py_DECREF (format); return result; } static PyObject * glyph_get_index(PyObject *self, void *closure) { PyObject *obj = PyTuple_GetItem (self, 0); Py_XINCREF (obj); return obj; } static PyObject * glyph_get_x(PyObject *self, void *closure) { PyObject *obj = PyTuple_GetItem (self, 1); Py_XINCREF (obj); return obj; } static PyObject * glyph_get_y(PyObject *self, void *closure) { PyObject *obj = PyTuple_GetItem (self, 2); Py_XINCREF (obj); return obj; } static PyGetSetDef glyph_getset[] = { {"index", (getter)glyph_get_index}, {"x", (getter)glyph_get_x}, {"y", (getter)glyph_get_y}, {NULL,}, }; 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 */ 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 */ 0, /* tp_methods */ 0, /* tp_members */ glyph_getset, /* 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.25.1/cairo/matrix.c000066400000000000000000000273721451476466400160470ustar00rootroot00000000000000/* -*- 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, PyObject *ignored) { 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 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*/ (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*/ (unaryfunc)0, /*nb_int*/ 0, /*py2:nb_long/py3:nb_reserved*/ (unaryfunc)0, /*nb_float*/ 0, /*nb_inplace_add*/ 0, /*nb_inplace_subtract*/ 0, /*nb_inplace_multiply*/ 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 */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 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.25.1/cairo/meson.build000066400000000000000000000035311451476466400165300ustar00rootroot00000000000000python_sources = [ '__init__.py', '__init__.pyi', 'py.typed', ] sources = [ 'bufferproxy.c', 'cairomodule.c', 'context.c', 'device.c', 'enums.c', 'error.c', 'font.c', 'glyph.c', 'matrix.c', 'misc.c', 'path.c', 'pattern.c', 'rectangle.c', 'region.c', 'surface.c', 'textcluster.c', 'textextents.c', ] foreach python_file : python_sources configure_file( input: python_file, output: python_file, copy: true, ) endforeach python_dep = python.dependency() cairo_dep = dependency('cairo', version: cair_version_req, required: cc.get_id() != 'msvc') if cc.get_id() == 'msvc' and not cairo_dep.found() if cc.has_header('cairo.h') cairo_dep = cc.find_library('cairo') endif endif python.install_sources(python_sources, pure : false, subdir : 'cairo' ) if python.language_version().version_compare('>= 3.0') pc_name = 'py3cairo' else pc_name = 'pycairo' endif header_file = configure_file( input: 'pycairo.h', output: pc_name + '.h', copy: true, ) install_headers( [header_file], install_dir: join_paths(python.get_install_dir(), 'cairo', 'include'), ) install_headers([header_file], subdir: 'pycairo') # https://github.com/mesonbuild/meson/issues/4117 if host_machine.system() == 'windows' python_ext_dep = python_dep else python_ext_dep = python_dep.partial_dependency(compile_args: true) endif pyext = python.extension_module('_cairo', sources, dependencies : [python_ext_dep, cairo_dep], install: true, subdir : 'cairo', c_args: pyext_c_args + main_c_args, ) pkg = import('pkgconfig') pkg.generate( name: pc_name, description: 'Python @0@ bindings for cairo'.format( python.language_version().split('.')[0]), subdirs: 'pycairo', requires: ['cairo'], ) pycairo_dep = declare_dependency( version: pycairo_version, include_directories: [include_directories('.')], ) pycairo-1.25.1/cairo/misc.c000066400000000000000000000142641451476466400154720ustar00rootroot00000000000000/* -*- 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) { PyObject *real = PyOS_FSPath (obj); if (real == NULL) { PyErr_Clear (); return 0; } else { Py_DECREF (real); return 1; } } #if !defined(MS_WINDOWS) /* Broken in PyPy: https://foss.heptapod.net/pypy/pypy/-/issues/3168 */ static int Pycairo_PyUnicode_FSConverter(PyObject* obj, void* result) { int res; PyObject *real = NULL; real = PyOS_FSPath (obj); if (real == NULL) { PyErr_Clear (); return PyUnicode_FSConverter (obj, result); } else { res = PyUnicode_FSConverter (real, result); Py_DECREF (real); return res; } } #endif #if defined(MS_WINDOWS) /* Broken in PyPy: https://foss.heptapod.net/pypy/pypy/-/issues/3168 */ static int Pycairo_PyUnicode_FSDecoder(PyObject* obj, void* result) { int res; PyObject *real = NULL; real = PyOS_FSPath (obj); if (real == NULL) { PyErr_Clear (); return PyUnicode_FSDecoder (obj, result); } else { res = PyUnicode_FSDecoder (real, result); Py_DECREF (real); return res; } } #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) PyObject *uni; if (Pycairo_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; } #else if (Pycairo_PyUnicode_FSConverter (obj, &bytes) == 0) return 0; if (PyBytes_AsStringAndSize (bytes, &internal, NULL) == -1) { Py_DECREF (bytes); return 0; } #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 *res; /* Check that the file is opened in binary mode by writing a zero length * bytes object to it */ res = PyObject_CallMethod (obj, "write", "(y#)", "", (Py_ssize_t) 0); if (res == NULL) return 0; Py_DECREF (res); *file = obj; return 1; } int Pycairo_reader_converter (PyObject *obj, PyObject** file) { PyObject *res; /* Check that the file is opened in binary mode by reading a zero length * bytes object from it */ res = PyObject_CallMethod (obj, "read", "(i)", (int) 0); if (res == NULL) return 0; if (!PyBytes_Check (res)) { Py_DECREF (res); PyErr_SetString ( PyExc_TypeError, "'read' does not return bytes"); return 0; } Py_DECREF (res); *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_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 (!PyLong_Check (pyobj)) { PyErr_SetString (PyExc_TypeError, "not of type int"); return NULL; } Py_INCREF (pyobj); return pyobj; } /* -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.25.1/cairo/path.c000066400000000000000000000223011451476466400154620ustar00rootroot00000000000000/* -*- 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 = 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 = 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 = 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 = 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 = PyUnicode_FromString ("\n"); if (s == NULL) goto Done; result = 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 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]; cairo_path_data_type_t 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))", (int)type, data[1].point.x, data[1].point.y); case CAIRO_PATH_CURVE_TO: return Py_BuildValue("(i(dddddd))", (int)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()", (int)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.25.1/cairo/pattern.c000066400000000000000000001263031451476466400162120ustar00rootroot00000000000000/* -*- 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, PyObject *ignored) { RETURN_INT_ENUM (Extend, cairo_pattern_get_extend (o->pattern)); } static PyObject * pattern_get_matrix (PycairoPattern *o, PyObject *ignored) { 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, PyObject *ignored) { 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; } #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 18, 0) static PyObject * pattern_get_dither (PycairoPattern *o, PyObject *ignored) { cairo_dither_t dither; Py_BEGIN_ALLOW_THREADS; dither = cairo_pattern_get_dither (o->pattern); Py_END_ALLOW_THREADS; RETURN_INT_ENUM (Dither, dither); } static PyObject * pattern_set_dither (PycairoPattern *o, PyObject *args) { cairo_dither_t dither; int dither_arg; if (!PyArg_ParseTuple (args, "i:Pattern.set_dither", &dither_arg)) return NULL; dither = (cairo_dither_t)dither_arg; Py_BEGIN_ALLOW_THREADS; cairo_pattern_set_dither (o->pattern, dither); Py_END_ALLOW_THREADS; Py_RETURN_NONE; } #endif 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 }, #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 18, 0) {"get_dither", (PyCFunction)pattern_get_dither, METH_NOARGS }, {"set_dither", (PyCFunction)pattern_set_dither, METH_VARARGS }, #endif {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 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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 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, PyObject *ignored) { 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.25.1/cairo/private.h000066400000000000000000000245131451476466400162140ustar00rootroot00000000000000/* -*- 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" #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); 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; #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) #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) DECL_ENUM(SVGUnit) #endif #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 #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 8) DECL_ENUM(ColorMode) #endif #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 18, 0) DECL_ENUM(Dither) #endif /* Use to disable deprecation warnings temporarily */ #ifdef _MSC_VER # define PYCAIRO_BEGIN_IGNORE_DEPRECATED \ __pragma (warning (push)) \ __pragma (warning (disable : 4996)) # define PYCAIRO_END_IGNORE_DEPRECATED \ __pragma (warning (pop)) #else # define PYCAIRO_BEGIN_IGNORE_DEPRECATED \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic ignored \"-Wdeprecated-declarations\"") # define PYCAIRO_END_IGNORE_DEPRECATED \ _Pragma ("GCC diagnostic pop") #endif #ifdef __GNUC__ #define PYCAIRO_MODINIT_FUNC __attribute__((visibility("default"))) PyMODINIT_FUNC #else #define PYCAIRO_MODINIT_FUNC PyMODINIT_FUNC #endif #define PYCAIRO_Py_hash_t_FromVoidPtr(p) ((Py_hash_t)(Py_ssize_t)(p)) #endif /* _PYCAIRO_PRIVATE_H_ */ pycairo-1.25.1/cairo/py.typed000066400000000000000000000000001451476466400160510ustar00rootroot00000000000000pycairo-1.25.1/cairo/pycairo.h000066400000000000000000000211121451476466400162000ustar00rootroot00000000000000/* -*- 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) #ifdef PYCAIRO_NO_IMPORT extern Pycairo_CAPI_t *Pycairo_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. */ Pycairo_CAPI_t *Pycairo_CAPI; /* Return -1 on error, 0 on success. * PyCapsule_Import will set an exception if there's an error. */ static inline 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.25.1/cairo/rectangle.c000066400000000000000000000125521451476466400165010ustar00rootroot00000000000000/* -*- 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 = PyUnicode_FromString ( "cairo.Rectangle(x=%r, y=%r, width=%r, height=%r)"); if (format == NULL) return NULL; result = PyUnicode_Format (format, self); Py_DECREF (format); return result; } static PyObject * rectangle_get_x(PyObject *self, void *closure) { PyObject *obj = PyTuple_GetItem (self, 0); Py_XINCREF (obj); return obj; } static PyObject * rectangle_get_y(PyObject *self, void *closure) { PyObject *obj = PyTuple_GetItem (self, 1); Py_XINCREF (obj); return obj; } static PyObject * rectangle_get_width(PyObject *self, void *closure) { PyObject *obj = PyTuple_GetItem (self, 2); Py_XINCREF (obj); return obj; } static PyObject * rectangle_get_height(PyObject *self, void *closure) { PyObject *obj = PyTuple_GetItem (self, 3); Py_XINCREF (obj); return obj; } static PyGetSetDef rectangle_getset[] = { {"x", (getter)rectangle_get_x}, {"y", (getter)rectangle_get_y}, {"width", (getter)rectangle_get_width}, {"height", (getter)rectangle_get_height}, {NULL,}, }; 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 */ 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 */ 0, /* tp_methods */ 0, /* tp_members */ rectangle_getset, /* 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.25.1/cairo/region.c000066400000000000000000000455271451476466400160300ustar00rootroot00000000000000/* -*- 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 = 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { int res; Py_BEGIN_ALLOW_THREADS; res = cairo_region_num_rectangles(o->region); Py_END_ALLOW_THREADS; return 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, PyObject *ignored) { 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.25.1/cairo/surface.c000066400000000000000000002527771451476466400162040ustar00rootroot00000000000000/* -*- 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", "(y#)", 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 const cairo_user_data_key_t surface_buffer_view_key; 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { RETURN_INT_ENUM (Content, cairo_surface_get_content (o->surface)); } static PyObject * surface_get_device_offset (PycairoSurface *o, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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 BytesIO) taking bytes"); 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; Py_buffer *view; 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); view = PyCapsule_GetPointer(PyTuple_GET_ITEM(user_data, 1), NULL); mime_intern = PyTuple_GET_ITEM(user_data, 3); cairo_surface_set_user_data( surface, (cairo_user_data_key_t *)mime_intern, NULL, NULL); /* Destroy the user data */ PyBuffer_Release (view); PyMem_Free (view); Py_DECREF(user_data); PyGILState_Release(gstate); } static PyObject * surface_set_mime_data (PycairoSurface *o, PyObject *args) { PyObject *obj, *user_data, *mime_intern, *surface_capsule, *view_capsule; const char *mime_type; 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; } Py_buffer *view = PyMem_Malloc (sizeof (Py_buffer)); if (view == NULL) { PyErr_NoMemory (); return NULL; } res = PyObject_GetBuffer (obj, view, PyBUF_READ); if (res == -1) { PyMem_Free (view); 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 = PyUnicode_InternFromString (mime_type); surface_capsule = PyCapsule_New(o->surface, NULL, NULL); view_capsule = PyCapsule_New(view, NULL, NULL); user_data = Py_BuildValue("(NNOO)", surface_capsule, view_capsule, obj, mime_intern); if (user_data == NULL) { PyBuffer_Release (view); PyMem_Free (view); 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) { PyBuffer_Release (view); PyMem_Free (view); Py_DECREF(user_data); Pycairo_Check_Status (status); return NULL; } Py_INCREF(user_data); status = cairo_surface_set_mime_data ( o->surface, mime_type, view->buf, (unsigned long)view->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); PyBuffer_Release (view); PyMem_Free (view); Py_DECREF(user_data); Pycairo_Check_Status (status); return NULL; } 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 = 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("y#", buffer, buffer_len); } else { obj = PyTuple_GET_ITEM(user_data, 2); 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, PyObject *ignored) { 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_ARGB32, 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 PyObject * surface_ctx_enter (PyObject *obj, PyObject *ignored) { Py_INCREF (obj); return obj; } static PyObject * surface_ctx_exit (PycairoSurface *obj, PyObject *args) { Py_BEGIN_ALLOW_THREADS; cairo_surface_finish (obj->surface); Py_END_ALLOW_THREADS; Py_RETURN_NONE; } 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() */ {"__enter__", (PyCFunction)surface_ctx_enter, METH_NOARGS}, {"__exit__", (PyCFunction)surface_ctx_exit, METH_VARARGS}, {"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 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); } static void _release_buffer_destroy_func (void *user_data) { Py_buffer *view = (Py_buffer *)user_data; PyGILState_STATE gstate = PyGILState_Ensure(); PyBuffer_Release (view); PyMem_Free (view); PyGILState_Release(gstate); } /* METH_CLASS */ static PyObject * image_surface_create_for_data (PyTypeObject *type, PyObject *args) { cairo_surface_t *surface; cairo_format_t format; cairo_status_t status; int width, height, stride = -1, res, format_arg; 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; 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; } } Py_buffer *view = PyMem_Malloc (sizeof (Py_buffer)); if (view == NULL) { PyErr_NoMemory (); return NULL; } res = PyObject_GetBuffer (obj, view, PyBUF_WRITABLE); if (res == -1) { PyMem_Free (view); return NULL; } if (height * stride > view->len) { PyBuffer_Release (view); PyMem_Free (view); PyErr_SetString(PyExc_TypeError, "buffer is not long enough"); return NULL; } Py_BEGIN_ALLOW_THREADS; surface = cairo_image_surface_create_for_data (view->buf, format, width, height, stride); Py_END_ALLOW_THREADS; status = cairo_surface_set_user_data( surface, &surface_buffer_view_key, view, (cairo_destroy_func_t)_release_buffer_destroy_func); if (Pycairo_Check_Status (status)) { cairo_surface_destroy (surface); PyBuffer_Release (view); PyMem_Free (view); return NULL; } return PycairoSurface_FromSurface(surface, NULL); } #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 = 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 BytesIO) returning bytes."); 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 PyLong_FromLong (cairo_format_stride_for_width (format, width)); } static PyObject * image_surface_get_data (PycairoImageSurface *o, PyObject *ignored) { 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); } static PyObject * image_surface_get_format (PycairoImageSurface *o, PyObject *ignored) { RETURN_INT_ENUM (Format, cairo_image_surface_get_format (o->surface)); } static PyObject * image_surface_get_height (PycairoImageSurface *o, PyObject *ignored) { return PyLong_FromLong (cairo_image_surface_get_height (o->surface)); } static PyObject * image_surface_get_stride (PycairoImageSurface *o, PyObject *ignored) { return PyLong_FromLong (cairo_image_surface_get_stride (o->surface)); } static PyObject * image_surface_get_width (PycairoImageSurface *o, PyObject *ignored) { return PyLong_FromLong (cairo_image_surface_get_width (o->surface)); } 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 */ 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 */ 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); self->surface = NULL; } else { cairo_surface_destroy(self->surface); self->surface = NULL; } Py_CLEAR (self->base); Py_TYPE (self)->tp_free (self); } static PyObject * mapped_image_surface_finish (PycairoSurface *self, PyObject *ignored) { PyErr_SetString(PyExc_RuntimeError, "The MappedImage type cannot be finished, " "use Surface.unmap_image instead"); return NULL; } static PyObject * mapped_image_surface_ctx_exit (PycairoImageSurface *self, PyObject *args) { PycairoSurface *pybasesurface = (PycairoSurface *)(self->base); PyObject *subargs, *result; subargs = Py_BuildValue("(O)", self); if (subargs == NULL) return NULL; result = surface_unmap_image (pybasesurface, subargs); Py_DECREF (subargs); return result; } static PyMethodDef mapped_image_surface_methods[] = { {"__exit__", (PyCFunction)mapped_image_surface_ctx_exit, METH_VARARGS}, {"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 BytesIO) taking bytes."); 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; } #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 6) static PyObject * pdf_surface_set_custom_metadata (PycairoPDFSurface *o, PyObject *args) { const char *name; const char *value; if (!PyArg_ParseTuple (args, "sz:PDFSurface.set_custom_metadata", &name, &value)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_pdf_surface_set_custom_metadata (o->surface, name, value); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_SURFACE_ERROR (o->surface); Py_RETURN_NONE; } #endif static PyObject * pdf_get_versions (PyObject *self, PyObject *ignored) { 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; /* See https://gitlab.freedesktop.org/cairo/cairo/-/issues/590 * if version < 0, cairo_pdf_version_to_string will return out-of-bound * memory address and could cause problems. We avoid those by checking * whether the version is greater than 0 and only then calling * that function. */ if (version >= 0) { Py_BEGIN_ALLOW_THREADS; version_string = cairo_pdf_version_to_string (version); Py_END_ALLOW_THREADS; } else { version_string = NULL; } if (version_string == NULL) { PyErr_SetString (PyExc_ValueError, "invalid version"); return NULL; } return 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; } #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) static PyObject * pdf_surface_set_page_label (PycairoPDFSurface *o, PyObject *args) { const char *utf8; if (!PyArg_ParseTuple (args, "es:PDFSurface.set_page_label", "utf-8", &utf8)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_pdf_surface_set_page_label (o->surface, utf8); Py_END_ALLOW_THREADS; PyMem_Free((void *)utf8); RETURN_NULL_IF_CAIRO_SURFACE_ERROR (o->surface); Py_RETURN_NONE; } static PyObject * pdf_surface_set_metadata (PycairoPDFSurface *o, PyObject *args) { const char *utf8; cairo_pdf_metadata_t metadata; int metadata_arg; if (!PyArg_ParseTuple (args, "ies:PDFSurface.set_metadata", &metadata_arg, "utf-8", &utf8)) return NULL; metadata = (cairo_pdf_metadata_t)metadata_arg; Py_BEGIN_ALLOW_THREADS; cairo_pdf_surface_set_metadata (o->surface, metadata, utf8); Py_END_ALLOW_THREADS; PyMem_Free((void *)utf8); RETURN_NULL_IF_CAIRO_SURFACE_ERROR (o->surface); Py_RETURN_NONE; } static PyObject * pdf_surface_set_thumbnail_size (PycairoPDFSurface *o, PyObject *args) { int width, height; if (!PyArg_ParseTuple (args, "ii:PDFSurface.set_thumbnail_size", &width, &height)) return NULL; Py_BEGIN_ALLOW_THREADS; cairo_pdf_surface_set_thumbnail_size (o->surface, width, height); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_SURFACE_ERROR (o->surface); Py_RETURN_NONE; } static PyObject * pdf_surface_add_outline (PycairoPDFSurface *o, PyObject *args) { int parent_id, added_id; const char *utf8; const char *link_attribs; cairo_pdf_outline_flags_t flags; int flags_arg; if (!PyArg_ParseTuple (args, "iesesi:PDFSurface.add_outline", &parent_id, "utf-8", &utf8, "utf-8", &link_attribs, &flags_arg)) return NULL; flags = (cairo_pdf_outline_flags_t)flags_arg; Py_BEGIN_ALLOW_THREADS; added_id = cairo_pdf_surface_add_outline (o->surface, parent_id, utf8, link_attribs, flags); Py_END_ALLOW_THREADS; PyMem_Free((void *)utf8); PyMem_Free((void *)link_attribs); RETURN_NULL_IF_CAIRO_SURFACE_ERROR (o->surface); return PyLong_FromLong (added_id); } #endif static PyMethodDef pdf_surface_methods[] = { #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 6) {"set_custom_metadata", (PyCFunction)pdf_surface_set_custom_metadata, METH_VARARGS}, #endif #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) {"set_page_label", (PyCFunction)pdf_surface_set_page_label, METH_VARARGS}, {"set_metadata", (PyCFunction)pdf_surface_set_metadata, METH_VARARGS}, {"set_thumbnail_size", (PyCFunction)pdf_surface_set_thumbnail_size, METH_VARARGS}, {"add_outline", (PyCFunction)pdf_surface_add_outline, METH_VARARGS}, #endif {"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 BytesIO) taking bytes."); return NULL; } } } static PyObject * ps_surface_dsc_begin_page_setup (PycairoPSSurface *o, PyObject *ignored) { 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, PyObject *ignored) { 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 *ignored) { 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 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 *ignored) { 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, PyObject *ignored) { 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, PyObject *ignored) { 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 BytesIO) taking bytes."); return NULL; } } } static PyObject * svg_get_versions (PyObject *self, PyObject *ignored) { 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 PyUnicode_FromString (version_string); } #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) static PyObject * svg_surface_get_document_unit (PycairoSVGSurface *o, PyObject *ignored) { RETURN_INT_ENUM (SVGUnit, cairo_svg_surface_get_document_unit (o->surface)); } static PyObject * svg_surface_set_document_unit (PycairoSVGSurface *o, PyObject *args) { cairo_svg_unit_t unit; int unit_arg; if (!PyArg_ParseTuple (args, "i:SVGSurface.set_document_unit", &unit_arg)) return NULL; unit = (cairo_svg_unit_t)unit_arg; Py_BEGIN_ALLOW_THREADS; cairo_svg_surface_set_document_unit (o->surface, unit); Py_END_ALLOW_THREADS; RETURN_NULL_IF_CAIRO_SURFACE_ERROR (o->surface); Py_RETURN_NONE; } #endif static PyObject * svg_surface_restrict_to_version (PycairoSVGSurface *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[] = { #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) {"get_document_unit", (PyCFunction)svg_surface_get_document_unit, METH_NOARGS}, {"set_document_unit", (PyCFunction)svg_surface_set_document_unit, METH_VARARGS}, #endif {"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 static PyObject * xcb_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { PyErr_SetString(PyExc_TypeError, "Not supported"); return NULL; } 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, PyObject *ignored) { return PyLong_FromLong (cairo_xlib_surface_get_depth (o->surface)); } static PyObject * xlib_surface_get_height (PycairoXlibSurface *o, PyObject *ignored) { return PyLong_FromLong (cairo_xlib_surface_get_height (o->surface)); } static PyObject * xlib_surface_get_width (PycairoXlibSurface *o, PyObject *ignored) { return 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.25.1/cairo/textcluster.c000066400000000000000000000137471451476466400171320ustar00rootroot00000000000000/* -*- 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 = 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 = 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 = PyUnicode_FromString ( "cairo.TextCluster(num_bytes=%r, num_glyphs=%r)"); if (format == NULL) return NULL; result = PyUnicode_Format (format, self); Py_DECREF (format); return result; } static PyObject * text_cluster_get_num_bytes(PyObject *self, void *closure) { PyObject *obj = PyTuple_GetItem (self, 0); Py_XINCREF (obj); return obj; } static PyObject * text_cluster_get_num_glyphs(PyObject *self, void *closure) { PyObject *obj = PyTuple_GetItem (self, 1); Py_XINCREF (obj); return obj; } static PyGetSetDef text_cluster_getset[] = { {"num_bytes", (getter)text_cluster_get_num_bytes}, {"num_glyphs", (getter)text_cluster_get_num_glyphs}, {NULL,}, }; 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 */ 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 */ 0, /* tp_methods */ 0, /* tp_members */ text_cluster_getset, /* 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.25.1/cairo/textextents.c000066400000000000000000000142051451476466400171310ustar00rootroot00000000000000/* -*- 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 = 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 = PyUnicode_Format (format, self); Py_DECREF (format); return result; } static PyObject * text_extents_get_x_bearing(PyObject *self, void *closure) { PyObject *obj = PyTuple_GetItem (self, 0); Py_XINCREF (obj); return obj; } static PyObject * text_extents_get_y_bearing(PyObject *self, void *closure) { PyObject *obj = PyTuple_GetItem (self, 1); Py_XINCREF (obj); return obj; } static PyObject * text_extents_get_width(PyObject *self, void *closure) { PyObject *obj = PyTuple_GetItem (self, 2); Py_XINCREF (obj); return obj; } static PyObject * text_extents_get_height(PyObject *self, void *closure) { PyObject *obj = PyTuple_GetItem (self, 3); Py_XINCREF (obj); return obj; } static PyObject * text_extents_get_x_advance(PyObject *self, void *closure) { PyObject *obj = PyTuple_GetItem (self, 4); Py_XINCREF (obj); return obj; } static PyObject * text_extents_get_y_advance(PyObject *self, void *closure) { PyObject *obj = PyTuple_GetItem (self, 5); Py_XINCREF (obj); return obj; } static PyGetSetDef text_cluster_getset[] = { {"x_bearing", (getter)text_extents_get_x_bearing}, {"y_bearing", (getter)text_extents_get_y_bearing}, {"width", (getter)text_extents_get_width}, {"height", (getter)text_extents_get_height}, {"x_advance", (getter)text_extents_get_x_advance}, {"y_advance", (getter)text_extents_get_y_advance}, {NULL,}, }; 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 */ 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 */ 0, /* tp_methods */ 0, /* tp_members */ text_cluster_getset, /* 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.25.1/docs/000077500000000000000000000000001451476466400142175ustar00rootroot00000000000000pycairo-1.25.1/docs/.gitignore000066400000000000000000000000321451476466400162020ustar00rootroot00000000000000_build _static _templates pycairo-1.25.1/docs/Makefile000066400000000000000000000003131451476466400156540ustar00rootroot00000000000000all: python3 -m sphinx -j8 -b html -n . _build clean: rm -rf _build .PHONY: clean linkcheck watch linkcheck: sphinx-build -b linkcheck -n . _build watch: sphinx-autobuild -j8 -b html -n . _build pycairo-1.25.1/docs/c_api/000077500000000000000000000000001451476466400152725ustar00rootroot00000000000000pycairo-1.25.1/docs/c_api/c_build.rst000066400000000000000000000033021451476466400174230ustar00rootroot00000000000000.. currentmodule:: cairo Build Integration ================= 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: Similar to variant 2 but doesn't require pycairo to be loaded, which can be problematic on Windows where by default cairo isn't in the dll search path since Python 3.8. .. code:: python def get_include_path(): import os from importlib.util import find_spec spec = find_spec("cairo") assert spec is not None return os.path.join(os.path.dirname(spec.origin), 'include') Compiler Flags: * ``python -c "get_include_path()"`` * ``pkg-config --cflags cairo`` Linker Flags: * ``pkg-config --libs cairo`` 2. 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`` 3. 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 py3cairo`` Linker Flags: * ``pkg-config --libs py3cairo`` pycairo-1.25.1/docs/c_api/index.rst000066400000000000000000000001111451476466400171240ustar00rootroot00000000000000C API ===== .. toctree:: :titlesonly: pycairo_c_api c_buildpycairo-1.25.1/docs/c_api/pycairo_c_api.rst000066400000000000000000000243511451476466400206320ustar00rootroot00000000000000.. highlight:: c *************** C API Reference *************** .. _api-includes: 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; } In case you want to use the API from another compilation unit:: #define PYCAIRO_NO_IMPORT #include ... .. versionadded:: 1.17.0 The ``PYCAIRO_NO_IMPORT`` macro is used since 1.17.0 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:: PycairoContext_GET(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 CPython Types ============= .. c:type:: PyObject .. c:type:: PyTypeObjectpycairo-1.25.1/docs/changelog.rst000066400000000000000000000001041451476466400166730ustar00rootroot00000000000000Changelog ========= .. currentmodule:: cairo .. include:: ../NEWS pycairo-1.25.1/docs/conf.py000066400000000000000000000027411451476466400155220ustar00rootroot00000000000000import os import sys from sphinx.util import logging # https://github.com/sphinx-doc/sphinx/issues/10112 logging.getLogger('sphinx.ext.extlinks').setLevel(40) dir_ = os.path.dirname(os.path.realpath(__file__)) def exec_module(path): import importlib.machinery loader = importlib.machinery.SourceFileLoader("cairo", path) return loader.load_module() sys.modules["cairo"] = exec_module(os.path.join(dir_, "..", "cairo", "__init__.pyi")) extensions = [ 'sphinx.ext.intersphinx', 'sphinx.ext.extlinks', 'sphinx.ext.autodoc', ] intersphinx_mapping = { 'python3': ('https://docs.python.org/3', None), } source_suffix = '.rst' master_doc = 'index' project = 'Pycairo' html_show_copyright = False exclude_patterns = ['_build'] pygments_style = 'friendly' 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-%s'), 'bug': ('https://github.com/pygobject/pycairo/issues/%s', '#%s'), 'pr': ('https://github.com/pygobject/pycairo/pull/%s', '#pr-%s'), 'user': ('https://github.com/%s', '%s'), } suppress_warnings = ["image.nonlocal_uri"] autoclass_content = 'class' autodoc_default_options = { 'member-order': 'bysource', } autodoc_type_aliases = { '_PathLike': 'cairo._PathLike', '_FileLike': 'cairo._FileLike', } pycairo-1.25.1/docs/extra.css000066400000000000000000000010421451476466400160510ustar00rootroot00000000000000.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.25.1/docs/getting_started.rst000066400000000000000000000020201451476466400201320ustar00rootroot00000000000000=============== Getting Started =============== Installation: * ``pip3 install pycairo`` Installing Pycairo requires pkg-config and cairo including its headers. Here are some examples on how to install those for some platforms: * Ubuntu/Debian: ``sudo apt install libcairo2-dev pkg-config python3-dev`` * macOS/Homebrew: ``brew install cairo pkg-config`` * Arch Linux: ``sudo pacman -S cairo pkgconf`` * Fedora: ``sudo dnf install cairo-devel pkg-config python3-devel`` * openSUSE: ``sudo zypper install cairo-devel pkg-config python3-devel`` To verify that the installation works run the following Python code: .. code:: python import cairo FAQ --- **My cairo import is failing after installing it with pip** pip caches Python wheels from earlier installs by default and if the cairo version the wheel was built against ist different from the one you run against then this might lead to errors. You can force pip to re-build and re-install pycairo in this case: :: pip3 install --force-reinstall --no-cache-dir pycairo pycairo-1.25.1/docs/images/000077500000000000000000000000001451476466400154645ustar00rootroot00000000000000pycairo-1.25.1/docs/images/example.svg000066400000000000000000000012421451476466400176370ustar00rootroot00000000000000 pycairo-1.25.1/docs/images/pycairo.svg000066400000000000000000001410711451476466400176570ustar00rootroot00000000000000 image/svg+xml pycairo-1.25.1/docs/index.rst000066400000000000000000000027171451476466400160670ustar00rootroot00000000000000.. raw:: html
.. image:: images/pycairo.svg :align: center :width: 370px | .. toctree:: :maxdepth: 1 :titlesonly: :hidden: getting_started changelog tutorial/index reference/index c_api/index resources .. currentmodule:: cairo .. title:: Overview .. include:: ../README.rst :start-after: | ---- PyPI: https://pypi.org/project/pycairo 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. For examples of pycairo code see the 'examples' directory that comes with the pycairo distribution. ---- Alternatives: * `cairocffi `__ provides a large subset of the pycairo API but instead of being implemented in C it uses `cffi `__ to talk to cairo. In case you'd prefer not to use a C extension then give this a try. Or if you use PyPy and want to benefit from the lower overhead of cffi compared to C extensions. * `Qahirah `__ provides a more "pythonic" API with less focus on matching the cairo C API. It also isn't a C extension and uses the Python builtin `ctypes `__ module to talk to cairo. pycairo-1.25.1/docs/reference/000077500000000000000000000000001451476466400161555ustar00rootroot00000000000000pycairo-1.25.1/docs/reference/constants.rst000066400000000000000000000055301451476466400207260ustar00rootroot00000000000000.. _constants: ****************************** Module Functions and Constants ****************************** .. currentmodule:: cairo Module Functions ================ .. autofunction:: cairo_version .. autofunction:: cairo_version_string .. autofunction:: get_include Module Constants ================ .. autodata:: version .. autodata:: version_info .. autodata:: CAIRO_VERSION .. autodata:: CAIRO_VERSION_STRING .. autodata:: CAIRO_VERSION_MAJOR .. autodata:: CAIRO_VERSION_MINOR .. autodata:: CAIRO_VERSION_MICRO .. _constants_HAS: cairo.HAS --------- 1 if the feature is present in the underlying C cairo library, 0 otherwise. .. autodata:: HAS_ATSUI_FONT .. autodata:: HAS_FT_FONT .. autodata:: HAS_GLITZ_SURFACE .. autodata:: HAS_IMAGE_SURFACE .. autodata:: HAS_PDF_SURFACE .. autodata:: HAS_PNG_FUNCTIONS .. autodata:: HAS_PS_SURFACE .. autodata:: HAS_RECORDING_SURFACE .. autodata:: HAS_SVG_SURFACE .. autodata:: HAS_USER_FONT .. autodata:: HAS_QUARTZ_SURFACE .. autodata:: HAS_WIN32_FONT .. autodata:: HAS_WIN32_SURFACE .. autodata:: HAS_XCB_SURFACE .. autodata:: HAS_XLIB_SURFACE .. autodata:: HAS_MIME_SURFACE .. autodata:: HAS_SCRIPT_SURFACE .. autodata:: HAS_TEE_SURFACE .. autodata:: HAS_DWRITE_FONT .. _constants_TAG: cairo.TAG --------- .. autodata:: TAG_DEST .. autodata:: TAG_LINK .. autodata:: TAG_CONTENT .. autodata:: TAG_CONTENT_REF .. _constants_MIME_TYPE: cairo.MIME_TYPE --------------- .. autodata:: MIME_TYPE_JP2 .. autodata:: MIME_TYPE_JPEG .. autodata:: MIME_TYPE_PNG .. autodata:: MIME_TYPE_URI .. autodata:: MIME_TYPE_UNIQUE_ID .. autodata:: MIME_TYPE_CCITT_FAX .. autodata:: MIME_TYPE_CCITT_FAX_PARAMS .. autodata:: MIME_TYPE_EPS .. autodata:: MIME_TYPE_EPS_PARAMS .. autodata:: MIME_TYPE_JBIG2 .. autodata:: MIME_TYPE_JBIG2_GLOBAL .. autodata:: MIME_TYPE_JBIG2_GLOBAL_ID Other Constants --------------- .. autodata:: PDF_OUTLINE_ROOT .. autodata:: COLOR_PALETTE_DEFAULT Other Classes and Functions =========================== .. 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 .. class:: _FileLike This type only exists for documentation purposes. This represents a file object opened in binary mode: :obj:`typing.BinaryIO` .. class:: _SomeSurface This type only exists for documentation purposes. This represents a :class:`Surface` subclass. pycairo-1.25.1/docs/reference/context.rst000066400000000000000000000003131451476466400203700ustar00rootroot00000000000000.. _context: ************* Cairo Context ************* .. currentmodule:: cairo class Context() =============== .. autoclass:: Context :members: :undoc-members: .. automethod:: __init__ pycairo-1.25.1/docs/reference/devices.rst000066400000000000000000000005011451476466400203250ustar00rootroot00000000000000.. _devices: ******* Devices ******* .. currentmodule:: cairo class Device() =============== .. autoclass:: Device :members: :undoc-members: class ScriptDevice(:class:`Device`) =================================== .. autoclass:: ScriptDevice :members: :undoc-members: .. automethod:: __init__ pycairo-1.25.1/docs/reference/enums.rst000066400000000000000000000035311451476466400200400ustar00rootroot00000000000000===== 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 .. autoclass:: Antialias :members: :undoc-members: .. autoclass:: Content :members: :undoc-members: .. autoclass:: Extend :members: :undoc-members: .. autoclass:: FillRule :members: :undoc-members: .. autoclass:: Filter :members: :undoc-members: .. autoclass:: FontSlant :members: :undoc-members: .. autoclass:: FontWeight :members: :undoc-members: .. autoclass:: Format :members: :undoc-members: .. autoclass:: HintMetrics :members: :undoc-members: .. autoclass:: HintStyle :members: :undoc-members: .. autoclass:: LineCap :members: :undoc-members: .. autoclass:: LineJoin :members: :undoc-members: .. autoclass:: Operator :members: :undoc-members: .. autoclass:: PathDataType :members: :undoc-members: .. autoclass:: PSLevel :members: :undoc-members: .. autoclass:: PDFVersion :members: :undoc-members: .. autoclass:: SVGVersion :members: :undoc-members: .. autoclass:: SubpixelOrder :members: :undoc-members: .. autoclass:: RegionOverlap :members: :undoc-members: .. autoclass:: Status :members: :undoc-members: .. autoclass:: ScriptMode :members: :undoc-members: .. autoclass:: TextClusterFlags :members: :undoc-members: .. autoclass:: SurfaceObserverMode :members: :undoc-members: .. autoclass:: PDFOutlineFlags :members: :undoc-members: .. autoclass:: SVGUnit :members: :undoc-members: .. autoclass:: PDFMetadata :members: :undoc-members: .. autoclass:: ColorMode :members: :undoc-members: .. autoclass:: Dither :members: :undoc-members:pycairo-1.25.1/docs/reference/exceptions.rst000066400000000000000000000013231451476466400210670ustar00rootroot00000000000000.. _exceptions: ********** Exceptions ********** .. currentmodule:: cairo When a cairo function or method call fails an cairo.Error exception, or a subclass thereof, is raised. cairo.Error() ============= .. autoexception:: Error :members: :undoc-members: .. autoexception:: CairoError :members: :undoc-members: .. 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.25.1/docs/reference/glyph.rst000066400000000000000000000002641451476466400200340ustar00rootroot00000000000000.. _glyph: ***** Glyph ***** .. currentmodule:: cairo class Glyph(tuple) ================== .. autoclass:: Glyph :members: :undoc-members: .. automethod:: __init__pycairo-1.25.1/docs/reference/index.rst000066400000000000000000000004701451476466400200170ustar00rootroot00000000000000.. _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.25.1/docs/reference/legacy_constants.rst000066400000000000000000000107701451476466400222540ustar00rootroot00000000000000.. _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 .. autodata:: ANTIALIAS_DEFAULT .. autodata:: ANTIALIAS_NONE .. autodata:: ANTIALIAS_GRAY .. autodata:: ANTIALIAS_SUBPIXEL .. autodata:: ANTIALIAS_FAST .. autodata:: ANTIALIAS_GOOD .. autodata:: ANTIALIAS_BEST .. autodata:: CONTENT_COLOR .. autodata:: CONTENT_ALPHA .. autodata:: CONTENT_COLOR_ALPHA .. autodata:: EXTEND_NONE .. autodata:: EXTEND_REPEAT .. autodata:: EXTEND_REFLECT .. autodata:: EXTEND_PAD .. autodata:: FILL_RULE_WINDING .. autodata:: FILL_RULE_EVEN_ODD .. autodata:: FILTER_FAST .. autodata:: FILTER_GOOD .. autodata:: FILTER_BEST .. autodata:: FILTER_NEAREST .. autodata:: FILTER_BILINEAR .. autodata:: FILTER_GAUSSIAN .. autodata:: FONT_SLANT_NORMAL .. autodata:: FONT_SLANT_ITALIC .. autodata:: FONT_SLANT_OBLIQUE .. autodata:: FONT_WEIGHT_NORMAL .. autodata:: FONT_WEIGHT_BOLD .. autodata:: FORMAT_INVALID .. autodata:: FORMAT_ARGB32 .. autodata:: FORMAT_RGB24 .. autodata:: FORMAT_A8 .. autodata:: FORMAT_A1 .. autodata:: FORMAT_RGB16_565 .. autodata:: FORMAT_RGB30 .. autodata:: HINT_METRICS_DEFAULT .. autodata:: HINT_METRICS_OFF .. autodata:: HINT_METRICS_ON .. autodata:: HINT_STYLE_DEFAULT .. autodata:: HINT_STYLE_NONE .. autodata:: HINT_STYLE_SLIGHT .. autodata:: HINT_STYLE_MEDIUM .. autodata:: HINT_STYLE_FULL .. autodata:: LINE_CAP_BUTT .. autodata:: LINE_CAP_ROUND .. autodata:: LINE_CAP_SQUARE .. autodata:: LINE_JOIN_MITER .. autodata:: LINE_JOIN_ROUND .. autodata:: LINE_JOIN_BEVEL .. autodata:: OPERATOR_CLEAR .. autodata:: OPERATOR_SOURCE .. autodata:: OPERATOR_OVER .. autodata:: OPERATOR_IN .. autodata:: OPERATOR_OUT .. autodata:: OPERATOR_ATOP .. autodata:: OPERATOR_DEST .. autodata:: OPERATOR_DEST_OVER .. autodata:: OPERATOR_DEST_IN .. autodata:: OPERATOR_DEST_OUT .. autodata:: OPERATOR_DEST_ATOP .. autodata:: OPERATOR_XOR .. autodata:: OPERATOR_ADD .. autodata:: OPERATOR_SATURATE .. autodata:: OPERATOR_MULTIPLY .. autodata:: OPERATOR_SCREEN .. autodata:: OPERATOR_OVERLAY .. autodata:: OPERATOR_DARKEN .. autodata:: OPERATOR_LIGHTEN .. autodata:: OPERATOR_COLOR_DODGE .. autodata:: OPERATOR_COLOR_BURN .. autodata:: OPERATOR_HARD_LIGHT .. autodata:: OPERATOR_SOFT_LIGHT .. autodata:: OPERATOR_DIFFERENCE .. autodata:: OPERATOR_EXCLUSION .. autodata:: OPERATOR_HSL_HUE .. autodata:: OPERATOR_HSL_SATURATION .. autodata:: OPERATOR_HSL_COLOR .. autodata:: OPERATOR_HSL_LUMINOSITY .. autodata:: PATH_MOVE_TO .. autodata:: PATH_LINE_TO .. autodata:: PATH_CURVE_TO .. autodata:: PATH_CLOSE_PATH .. autodata:: PS_LEVEL_2 .. autodata:: PS_LEVEL_3 .. autodata:: PDF_VERSION_1_4 .. autodata:: PDF_VERSION_1_5 .. autodata:: SVG_VERSION_1_1 .. autodata:: SVG_VERSION_1_2 .. autodata:: SUBPIXEL_ORDER_DEFAULT .. autodata:: SUBPIXEL_ORDER_RGB .. autodata:: SUBPIXEL_ORDER_BGR .. autodata:: SUBPIXEL_ORDER_VRGB .. autodata:: SUBPIXEL_ORDER_VBGR .. autodata:: REGION_OVERLAP_IN .. autodata:: REGION_OVERLAP_OUT .. autodata:: REGION_OVERLAP_PART .. autodata:: STATUS_SUCCESS .. autodata:: STATUS_NO_MEMORY .. autodata:: STATUS_INVALID_RESTORE .. autodata:: STATUS_INVALID_POP_GROUP .. autodata:: STATUS_NO_CURRENT_POINT .. autodata:: STATUS_INVALID_MATRIX .. autodata:: STATUS_INVALID_STATUS .. autodata:: STATUS_NULL_POINTER .. autodata:: STATUS_INVALID_STRING .. autodata:: STATUS_INVALID_PATH_DATA .. autodata:: STATUS_READ_ERROR .. autodata:: STATUS_WRITE_ERROR .. autodata:: STATUS_SURFACE_FINISHED .. autodata:: STATUS_SURFACE_TYPE_MISMATCH .. autodata:: STATUS_PATTERN_TYPE_MISMATCH .. autodata:: STATUS_INVALID_CONTENT .. autodata:: STATUS_INVALID_FORMAT .. autodata:: STATUS_INVALID_VISUAL .. autodata:: STATUS_FILE_NOT_FOUND .. autodata:: STATUS_INVALID_DASH .. autodata:: STATUS_INVALID_DSC_COMMENT .. autodata:: STATUS_INVALID_INDEX .. autodata:: STATUS_CLIP_NOT_REPRESENTABLE .. autodata:: STATUS_TEMP_FILE_ERROR .. autodata:: STATUS_INVALID_STRIDE .. autodata:: STATUS_FONT_TYPE_MISMATCH .. autodata:: STATUS_USER_FONT_IMMUTABLE .. autodata:: STATUS_USER_FONT_ERROR .. autodata:: STATUS_NEGATIVE_COUNT .. autodata:: STATUS_INVALID_CLUSTERS .. autodata:: STATUS_INVALID_SLANT .. autodata:: STATUS_INVALID_WEIGHT .. autodata:: STATUS_INVALID_SIZE .. autodata:: STATUS_USER_FONT_NOT_IMPLEMENTED .. autodata:: STATUS_DEVICE_TYPE_MISMATCH .. autodata:: STATUS_DEVICE_ERROR .. autodata:: STATUS_INVALID_MESH_CONSTRUCTION .. autodata:: STATUS_DEVICE_FINISHED .. autodata:: STATUS_LAST_STATUS pycairo-1.25.1/docs/reference/matrix.rst000066400000000000000000000002631451476466400202140ustar00rootroot00000000000000.. _matrix: ****** Matrix ****** .. currentmodule:: cairo class Matrix() ============== .. autoclass:: Matrix :members: :undoc-members: .. automethod:: __init__ pycairo-1.25.1/docs/reference/paths.rst000066400000000000000000000001561451476466400200300ustar00rootroot00000000000000.. _paths: ***** Paths ***** .. currentmodule:: cairo class Path() ============ .. autoclass:: cairo.Path pycairo-1.25.1/docs/reference/patterns.rst000066400000000000000000000032311451476466400205460ustar00rootroot00000000000000.. _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() =============== .. autoclass:: Pattern :members: :undoc-members: class SolidPattern(:class:`Pattern`) ==================================== .. autoclass:: SolidPattern :members: :undoc-members: .. automethod:: __init__ class SurfacePattern(:class:`Pattern`) ====================================== .. autoclass:: SurfacePattern :members: :undoc-members: .. automethod:: __init__ class Gradient(:class:`Pattern`) ================================ .. autoclass:: Gradient :members: :undoc-members: class LinearGradient(:class:`Gradient`) ======================================= .. autoclass:: LinearGradient :members: :undoc-members: .. automethod:: __init__ class RadialGradient(:class:`Gradient`) ======================================= .. autoclass:: RadialGradient :members: :undoc-members: .. automethod:: __init__ class MeshPattern(:class:`Pattern`) =================================== .. autoclass:: MeshPattern :members: :undoc-members: .. automethod:: __init__ class RasterSourcePattern(:class:`Pattern`) =========================================== .. autoclass:: RasterSourcePattern :members: :undoc-members: .. automethod:: __init__ pycairo-1.25.1/docs/reference/rectangle.rst000066400000000000000000000003261451476466400206540ustar00rootroot00000000000000.. _rectangle: ********* Rectangle ********* .. currentmodule:: cairo class Rectangle(tuple) ====================== .. autoclass:: cairo.Rectangle :members: :undoc-members: .. automethod:: __init__pycairo-1.25.1/docs/reference/region.rst000066400000000000000000000005541451476466400201760ustar00rootroot00000000000000.. _region: ****** Region ****** Region — Representing a pixel-aligned area .. currentmodule:: cairo class Region() ============== .. autoclass:: Region :members: :undoc-members: .. automethod:: __init__ class RectangleInt() ==================== .. autoclass:: cairo.RectangleInt :members: :undoc-members: .. automethod:: __init__pycairo-1.25.1/docs/reference/surfaces.rst000066400000000000000000000037521451476466400205310ustar00rootroot00000000000000.. _surfaces: ******** Surfaces ******** .. currentmodule:: cairo class Surface() =============== .. autoclass:: Surface() :members: :undoc-members: .. automethod:: __init__ class ImageSurface(:class:`Surface`) ==================================== .. autoclass:: ImageSurface :members: :undoc-members: .. automethod:: __init__ class PDFSurface(:class:`Surface`) ================================== .. autoclass:: PDFSurface :members: :undoc-members: .. automethod:: __init__ class PSSurface(:class:`Surface`) ================================= .. autoclass:: PSSurface :members: :undoc-members: .. automethod:: __init__ class RecordingSurface(:class:`Surface`) ======================================== .. autoclass:: RecordingSurface :members: :undoc-members: .. automethod:: __init__ class SVGSurface(:class:`Surface`) ================================== .. autoclass:: SVGSurface :members: :undoc-members: .. automethod:: __init__ class Win32Surface(:class:`Surface`) ==================================== .. autoclass:: Win32Surface :members: :undoc-members: .. automethod:: __init__ class Win32PrintingSurface(:class:`Surface`) ============================================ .. autoclass:: Win32PrintingSurface :members: :undoc-members: .. automethod:: __init__ class XCBSurface(:class:`Surface`) ================================== .. autoclass:: XCBSurface :members: :undoc-members: .. automethod:: __init__ class XlibSurface(:class:`Surface`) =================================== .. autoclass:: XlibSurface :members: :undoc-members: class ScriptSurface(:class:`Surface`) ===================================== .. autoclass:: ScriptSurface :members: :undoc-members: .. automethod:: __init__ class TeeSurface(:class:`Surface`) ===================================== .. autoclass:: TeeSurface :members: :undoc-members: .. automethod:: __init__ pycairo-1.25.1/docs/reference/text.rst000066400000000000000000000052711451476466400177000ustar00rootroot00000000000000.. _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() ================ .. autoclass:: FontFace :members: :undoc-members: 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`) ==================================== .. autoclass:: ToyFontFace :members: :undoc-members: .. automethod:: __init__ 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() ================== .. autoclass:: ScaledFont :members: :undoc-members: .. automethod:: __init__ class FontOptions() =================== .. autoclass:: FontOptions :members: :undoc-members: .. automethod:: __init__ pycairo-1.25.1/docs/reference/textcluster.rst000066400000000000000000000003411451476466400212730ustar00rootroot00000000000000.. _textcluster: ************ Text Cluster ************ .. currentmodule:: cairo class TextCluster(tuple) ======================== .. autoclass:: TextCluster :members: :undoc-members: .. automethod:: __init__pycairo-1.25.1/docs/reference/textextents.rst000066400000000000000000000003361451476466400213100ustar00rootroot00000000000000.. _textextents: *********** TextExtents *********** .. currentmodule:: cairo class TextExtents(tuple) ======================== .. autoclass:: TextExtents :members: :undoc-members: .. automethod:: __init__pycairo-1.25.1/docs/requirements.txt000066400000000000000000000000551451476466400175030ustar00rootroot00000000000000sphinx>=6.2.1,<7.0 sphinx-rtd-theme>=0.5,<2.0pycairo-1.25.1/docs/resources.rst000066400000000000000000000053171451476466400167710ustar00rootroot00000000000000========= 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 * `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.25.1/docs/tutorial/000077500000000000000000000000001451476466400160625ustar00rootroot00000000000000pycairo-1.25.1/docs/tutorial/examples.rst000066400000000000000000000003751451476466400204370ustar00rootroot00000000000000======== 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/main/examples pycairo-1.25.1/docs/tutorial/index.rst000066400000000000000000000001721451476466400177230ustar00rootroot00000000000000Tutorial ======== .. toctree:: :titlesonly: introduction examples pillow pygame numpy other pycairo-1.25.1/docs/tutorial/introduction.rst000066400000000000000000000101401451476466400213310ustar00rootroot00000000000000==================================== 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. 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.25.1/docs/tutorial/numpy.rst000066400000000000000000000014011451476466400177600ustar00rootroot00000000000000Integration with NumPy ====================== https://numpy.org/ 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=(height, width), dtype=numpy.uint32, buffer=buf) pycairo-1.25.1/docs/tutorial/other.rst000066400000000000000000000050211451476466400177330ustar00rootroot00000000000000Integration with other Libraries ================================ 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() 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. ModernGL & ImageSurface as Texture ---------------------------------- Creating a moderngl.Texture from an ImageSurface: .. code:: python import moderngl import cairo ctx = moderngl.create_context(standalone=True) width, height = 400, 400 surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) texture = ctx.texture((width, height), 4, data=surface.get_data()) An example can also be found in the ModernGL project: https://github.com/moderngl/moderngl/blob/master/examples/integration_pycairo.py pycairo-1.25.1/docs/tutorial/pillow.rst000066400000000000000000000043741451476466400201320ustar00rootroot00000000000000Integration with Pillow ======================= https://pillow.readthedocs.io Creating an ImageSurface from a PIL Image: .. code:: python import cairo import PIL.Image as Image def from_pil(im: Image, alpha: float=1.0, format: cairo.Format=cairo.FORMAT_ARGB32) -> cairo.ImageSurface: """ :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, ), f"Unsupported pixel format: {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) Converting an ImageSurface to a PIL Image: .. code:: python import cairo import PIL.Image as Image def to_pil(surface: cairo.ImageSurface) -> Image: format = surface.get_format() size = (surface.get_width(), surface.get_height()) stride = surface.get_stride() with surface.get_data() as memory: if format == cairo.Format.RGB24: return Image.frombuffer( "RGB", size, memory.tobytes(), 'raw', "BGRX", stride) elif format == cairo.Format.ARGB32: return Image.frombuffer( "RGBA", size, memory.tobytes(), 'raw', "BGRa", stride) else: raise NotImplementedError(repr(format)) # Create an image surface from a PNG file (or any other source) surface = cairo.ImageSurface.create_from_png("test.png") # Convert to a PIL Image im = to_pil(surface) # Use Pillow to store it as a JPEG im.save("result.jpg") pycairo-1.25.1/docs/tutorial/pygame.rst000066400000000000000000000006341451476466400201010ustar00rootroot00000000000000Integration with Pygame ======================= https://www.pygame.org 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") pycairo-1.25.1/examples/000077500000000000000000000000001451476466400151055ustar00rootroot00000000000000pycairo-1.25.1/examples/cairo_snippets/000077500000000000000000000000001451476466400201275ustar00rootroot00000000000000pycairo-1.25.1/examples/cairo_snippets/snippets/000077500000000000000000000000001451476466400217745ustar00rootroot00000000000000pycairo-1.25.1/examples/cairo_snippets/snippets/__init__.py000066400000000000000000000015671451476466400241160ustar00rootroot00000000000000import os import inspect import importlib class Snippet: name = "" """name of the snippet""" code = "" """Snippet code as text""" def draw_func(self, 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(f".{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.25.1/examples/cairo_snippets/snippets/arc.py000066400000000000000000000011411451476466400231100ustar00rootroot00000000000000from 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.25.1/examples/cairo_snippets/snippets/arc_negative.py000066400000000000000000000011521451476466400247740ustar00rootroot00000000000000from 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.25.1/examples/cairo_snippets/snippets/clip.py000066400000000000000000000005161451476466400232770ustar00rootroot00000000000000from 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.25.1/examples/cairo_snippets/snippets/clip_image.py000066400000000000000000000006161451476466400244420ustar00rootroot00000000000000from math import pi from pathlib import Path import cairo def draw(cr, width, height): cr.scale(width, height) cr.arc(0.5, 0.5, 0.25, 0, 2 * pi) cr.clip() image = cairo.ImageSurface.create_from_png( Path(__file__).parent / "romedalen.png" ) w, h = image.get_width(), image.get_height() cr.scale(1 / w, 1 / h) cr.set_source_surface(image) cr.paint() pycairo-1.25.1/examples/cairo_snippets/snippets/curve_rectangle.py000066400000000000000000000036601451476466400255230ustar00rootroot00000000000000def 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.25.1/examples/cairo_snippets/snippets/curve_to.py000066400000000000000000000006531451476466400242000ustar00rootroot00000000000000def 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.25.1/examples/cairo_snippets/snippets/ellipse.py000066400000000000000000000016261451476466400240100ustar00rootroot00000000000000from 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.25.1/examples/cairo_snippets/snippets/fill_and_stroke.py000066400000000000000000000005161451476466400255070ustar00rootroot00000000000000def 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.25.1/examples/cairo_snippets/snippets/fill_and_stroke2.py000066400000000000000000000007271451476466400255750ustar00rootroot00000000000000def 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.25.1/examples/cairo_snippets/snippets/glyph_path.py000066400000000000000000000012031451476466400245010ustar00rootroot00000000000000import 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.25.1/examples/cairo_snippets/snippets/gradient.py000066400000000000000000000011021451476466400241350ustar00rootroot00000000000000from 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.25.1/examples/cairo_snippets/snippets/gradient_mask.py000066400000000000000000000006721451476466400251630ustar00rootroot00000000000000import 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.25.1/examples/cairo_snippets/snippets/group.py000066400000000000000000000007221451476466400235030ustar00rootroot00000000000000import 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.25.1/examples/cairo_snippets/snippets/hering.py000066400000000000000000000013711451476466400236240ustar00rootroot00000000000000#!/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 _ 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.25.1/examples/cairo_snippets/snippets/path.py000066400000000000000000000003451451476466400233040ustar00rootroot00000000000000def 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.25.1/examples/cairo_snippets/snippets/romedalen.png000066400000000000000000011464611451476466400244650ustar00rootroot00000000000000‰PNG  IHDR€TBMè pHYsHHFÉk>xzTXtRaw profile type APP1xÚÕ»MÎ,»®%ÖQÜ!ðW$‡ÃßB†mÔün|{Ÿ{öy¯ .w,!3B+(RҢĄùý·ý?÷ü÷þ×ÿý?þ¯ûïÿÇ~ÿú׿þåðä5ñ€„%8ü¤€€÷Yþ\~pú%úý®ƒü#ñ[ôßåüý¸þÄ¿ü¥‰üŠ~™bú±ŒòS®ßŠèïòßï›n ÿ~п*2?|ûîíßï D$Ä$>Ai uUeø/RÉŸÝþ{ùûi>';'3#;'Ó/\`1`ðW‹™>à€¿Ñ/{ò'îïŽWø3V`ä¿›ù뎂þ`ëßþÏ_òŸu@ÿb¯~Uð÷ƒÿvËß<æ?»† `Âæ?@âòÛ%ùO¼~©ü@þNûýeù·ý¯ñý/3ö§Ÿþ‡ò÷oÓ¿®ïWëø‡é?äù×ç—b¤_øøþ>ñðw·ì§êoœã C’ÜÁ?é?ÆÿÙ?þYü«k‚ª*œMMÞ½yhòâ1Á›wOžþjÿ6Fÿ/“æ»wo>!£wfÆODÕÿ”C$À 3…â ³ÿÏ[ôÿGE¿ý…à/Tâ`ÿ…ýcâ~ €øŸOPÂÿt‚þ•ðÏZÿךý;Üü3jØþLžF ?øï ñý3jý}ø/E@âÛXoÜ÷_-èwãwS.À@@}ÿdþ@@ÁAAA@@!ÁÀàCCBCCABAÁÀ"!ÀÀ"ÂBA!àC@DþPPQQ¡áÐÐñ¡ #¡ ¢ÿ2    (0P0(ÿÎßß ÿ;ù?(ºk@0H$BF¼kLú5š øþ•ÿ™~"–€Â‡€„Âøg|¿_.†6¿C"(!£ 5u ÍÇOž¾÷ìù‹—Æ&¦öÌÌ-,]\ý¹¹{x‡„Æ ûÂ#"“’SRó¥¥gd—”Ö++¯¨ljnií×ÖÞÑ94<2:o쟘\\Z^YÝ·¶¾±yxt|rzïìüâòW ÂÿÿXFþs–ðK ök ÙÏõF%d„‡$¨öЙˆÉE(0±°‚˜Yéõ‘Ñ $>’e‘ôð/®þÍÔÿ„§?iúþ'<ÑÅÔ߉úþw˜úE-¯|ðôXº›€†ß³ø.Õ„ÏßQ”[œÞ£ÃSæG³¯áJîÕž‘ç>Ÿze8Ã>ÅTÀ#ΚúÝsñvrãȬ’!§m]ÞR³N¦ÀGC©ß“c¿–y©©Áš*ôYúkØÈ1õ¤I-²yÙ­¼úÀxËsŸeˆzJcÇÊòð|% ² òH XÌqö9`ë³³'jó GH<W).PÜû4ŽÎ†&™I†@|PŠÛÛ Œ$ÈJ•¼¬ ªðü.Mïå=J\Šü _O£vhãÆ–¬O櫼W¦VO9ž¿‘·¡)ª¡m²Z`êVíc7ÕÄ¡s¹¥|¥‹1¹x;+Å)Þ×[“Öˆ‡C}Ú†ê´×cvŒ b[·鄨ôô‘zÞ÷døô)50S´ ®Œ}ÏÒ=Ð0–*&9‘+Q—wŒ@ß½Ø×G¯0r Ä¤EÉÚ7/{ŒQPUg7ôISÁcïÇfÂ2TU8B¢Q]GP±åºsá_™±«ëÈÚ¹ê[ ªéPªÂêZõÐçjÏLïX&Pò~ßUÈŒwW`ê㚎{ynuoÞMRîÓê¸[ܪ£íe,V‰ãJùlßÅíú-m7® n¹¼6îÔ‘c" “¨ó÷ÔG]žq$!ç·àJà¬ë˜OÝ®…#¶KñÕ ³º -¨ºOM‹7*jHP8ñ·÷HlŠq-ÕðaÖ±({äë{†ºD2m®t‹Åð ^ù#Âxï3©çĤñØ^ÃÚX쨑àÛ†R}¤ŽÚáû)XÞËû”XiOØW¡pàœ¸Ÿf™ké•UW>8,Ðç©$­DÑOÕŸåãCœOÔ†yaϧwìÍŽ÷˜á†ÙIY9»êkG‡5'Xy̾¼¡ÆÚßdt…ɳ¬‰9ëf²ÈM–*‡$#*‰3ÈÉÅä oNrD ¾fgíT/Qb¢òf±|GÏÃqÓ‹™Du¹z0ÓýíêÏðNÈ]hËRÂðËܼOƒäTï0[ËG'MTÔ›Öå4ç[«b6Z÷‹²{a7ùžë!¯_b×;Ó%”‹"ä jÁuu3ã‘bÃ;Ðøbj IçUdNëJknî³À|±èñž=’B²‘•È ýÞó•àu«Ì ‚'t³XÀ ľ¯dÒˆDÚ¥Ü%`B«6áìÛç==!å¤a9»îuïÝ\å1}R^#Aä„BÄ Ä¾¨Þ` þÏ‘‘œ±†Ý{±ªú(‚мŸXÚšž¢2 vìJÇŒ·yÙôçöxÙRG’ñ©RËçXž¶;½y5šÆû$’#ÅïÉù³+Mü°žæð•4Ä­oíÄ£¶-xa7ÁÃÞ†ct®z%`μô¡6=¸äÍ×¼ZZõñ`Ú°‘· l³_)¿›õíw’IçGŸ(¶uÊøIΰxhßÔ*—-¯7Üg‚*FÏ…g#·¿ä,Pö-tÎÐ_¦ÇUL Û¯¢âNÊÍI…ð„,x®§=æˆðùHMì2YäqÏNÉœË-rµ½rÁ<톭´©eã½~ÀúItå2P%i†ç™\Ì;µòy§X^^³j¡“$^Ì…ÜÅÈóIðl1©05¯u ¯AàylE®…Œ N8ïö” ¼ÝÙç!tþµ÷¼fÖ‚zCÍOëuéT»Ÿ^øQ-“)A\åÞ\a¦ßGi]ó jÓžo°Øj¥IúÀ–mÈ÷‹¢ÝX¶ x‹áƧ|’_úè=¡ÚP3šÎÉN šˆ§®¤eÖ7õÓ:®yæŽXèoù«g¥VåÚ2â¢Æ9¤§^™„±ðtP¼í\®®Ó¶üøÁ‘lyoÁqC÷”3óyOîÖܲu,d³¾ŠØµæ¡×¢žïålòMœor9ŸöFä‰znÎ ='Uè ŠÎÊXASÔ.}øB¿1å¢ÜìçRËXÑجçáÜø?‹´\ót~=ØAp˜ïZ¹ VÐ>Ÿf*8n[²Ô×éW"ÆÇçYÆåHk|-2Êa-‡ùõc&oÏy^% õƒ5ã®[ŠÛK¾æ+‹GeSvy•q´ƒZDľ¦ð5q€áÈmò¢ªy²Ò¡m¡±]úLŸ…)Õ®UÄuÛÆ8¬Ã °T‘¥âÍòZ»³J»ÃÛÐ[]0åHÓP14ëhµè¨ào-Bg&öºì¸{³I!Q‹±¡OÑS‹™Æ»eA Û__§ß»oUK¢‰±H4+Ÿ¿l“‰f‚§î§ «v—m³9/&gª½®}í}±sk¬ƒPGo 3Hw‹è^Ú›tÍ×H´çý(A÷•¯ï>õ¢ÔÞO`#Æj\ƒ V‘‚^ŸªQg³sìã°d}á#U1Ž.ZðȾ%q;&±}¶¥ëB²p¡7P†x”Òô.÷àéú8XzÞÓsýðpó¬a6ÂæÖ£Cä.^ ðwÇNÜ"·åãÈ­}Æ~5 aô¯ÇÁWIŽè¾õ3~gÏc±Aã1ÞÅÚá†>SR"¬HP¸o=ÁŽåB'×´$_®1gMUÊ›ÐI³¥ò­ T»Õ<²hà¸-odÕ8Ȱ˜ùI좪·aU¦S«ûœÞË#><´÷†·i †iñ}ýæÕl9ÞH·âÙÆi®ö[Zöç/²c=0H&Ža“3¡¼<òÑÞGÜÞRhoúy4|Më#¡ñÀX  ¯¥¿B?}¢0¥ó’|?zùÄÙQƯùUÅ£ã=&E Ž «gu‹ºö˜q 9M¡8Šçóeßa ótßä›VMs)DZ»š^x\|nU BÚS3B°ÜßêkäÓ>á“ëêC„z™=8Ñž¯dºw䤪ʸ½wûÛù\}"½AÎ<Ám}—íŽqiç*ÓG]’M¶{%„-“Vâ½wDªJô)Y¾E7àëËyº©I:/î¸ j{+¨¼ÕRÝZ~¶%ºWÑ^…>zVŸ_à€{kyË·¬T÷üJ›á„šj^š¥v>{Va9¹û¼ºL߃Ï2 –#gËæ=¬r€‹ÎÊ£Š½À©ƒ<Ùè1¡àÝ—/p‰G¬?6œ6&­Þê6n$yæí7b5öÏoïzÏNsPõvð;þöÆX7WŸHÊPiÛ̵¼Ñ·DÏ'óy:õÓXñª˜êïð´_@Üs«SX¿ OÉÂ3RKßñ^±TÊÑŒ‡/*ºn±%•Ò·?^Êó‹%£ÞWèûŽ²Ý “äªÛÕƒ¸¨[ÐÈC?s6‚ºïcª2}8|p€KµB»9jšV·bÊÁÏø@S{κÞaRMÅö¾³òãa Üfcêd{‰/°ßE{d~íbÊm ŒÚ¹Y¸‘ú<º•*ØÀòIú{‘,B$ýñ²³ƒñ¥±F†$m¿w2‚Ù‰¤‘dÏ%HNf<³»²æ*âQû÷ìÌ¢£íªæÕPšÒy÷S)9“î÷{וæ¥Ü’jçñ-«=þ†óé#¡ÁÀNööVËÌb cæˆa«$á$磔7ˆm„XÞ7p’þ=$óhÇŠ¶ûÙ£DïzÛÃ6ÊR‘äÇñ”ìÈQÎùSŽlAo8æ²vÁ¶‘±4èÎhÖi7‰ñÄôWÅÍԲɛvýQްž#õ­•·¯<0e]Uk•Cåµ°{زßãŽôW¤Ÿ;&û »‰à27ìi"Xó@nŽÁ’X(A(ŸÆÍ«îî[ªn'ÓÕzzMOñ»¬ø==jرFîÇÜï3ϤZBf éWxQ1ɾ8`¥fý‚|§ˆÞZæ$¼@´Ç\±_¹vðéÆžæ+˜$¦”MÈh¤"Z>îãÓ¼˜b­äq9Aï3&„§ßÑ*‰w½á¸ž—Ó êÌà±X-FÄâ}iDõ|b›V¥ AC ü¾ó°9뚈ïó,ª”lŸÐBÓÇísœ¹äó®’Þ<ÖíwoTô+ué'+Eï ™=®«ʇ¶ÁuUýnL9½âP-,iÜšMÆQ ïi™rìØ-—è¾X~Ù^©K}êùÙOûñ…-ë |TÇ3d™"Gǯn ßðÉ‹HžÅ×6ƒüŽäbG^…±™mÏG'¯ÂÛ/+.Tàš/ÆeÍŠƒ‹®¥ŸBP´.䨩ÚLúœÅ'}AÑtÃ8|1ÏwÐDU`‰#W9ñéìÄ¥æZާñÍ Ä§4ïI>©}UàùŸ4Ã%òðQ6DµDšÅ‘Ô½f–U^jù|yÃ{ ‡]2ëL‘©hzMf69½]2{¿¢l+x?çû}@}ó½DN˜bB‹Xæ ð·Ów’÷UB“¾Úì ËxÒ¼›ØÖ©RП¯e¬ØÅIv>Oö³„§jÓâ‚!ì—ÑA|ý깤Œº ‰U6§·}9£UÚì@Ämû(ív|(±C†$£}e¬Ó”´¸p{¡Ì›>tÁ£möM•¸¡hkª‡J£žn¶Wߦ,%oöYEpX ¥ù¥~älý†û-EdB.¿ëB¦«7=¬’¯„8Æ‚z¬n§ìxG~Mw§™ŠK2²&ÔU…ý @Ÿlwp E½:¡Z (ROíNÿª;A«úÅFŒ•¥ò”ê¡Ly—ÌÓW±Öù*¨›ÅÛo^Í …ä}V*ðbïŒFF+ÄTªÆL-¢%ŒBÛ®¬.‘UÞ;Ä—ÞåGŸ„ê:P¹Rm>´ÐN¤-´7>ó´-;2Õ”tµW›©Å*| >ðkpÖ"+ç×t,Q=² ‚œ· @åÈÑê e…„eev_×J?»Y’È¡U)ÑB$ŸÓ‚®fUõvWTy×n\ZyèxߢöõžîT›AxD_§­>ÜE-°Ó&ƒØzhT6fšª“>Éß“¼)&Ç>ì~ͬ(¶øj#– Þ¼œ3oÉn-_·|vØó®¯óËí¾À9åuz¡$ ®ªè½ÖM`G©@“‚A‰½v®Sx]‘¢”í÷Iöe¼%'Žz¡>£ÌÎ.è×FbjD91½çàU1ã¹(V‹Yñ­*½ÚQç@žñš“ð\\PÀLH˜ü: }Wžm¨Ð&I¤ hŠÁG|J[è¾k`|ÑØQÕ)=¨ì5î;%§:ùv-è¤Ê ðÂÞ!ù·uŒãêgëb’ë§'2˜$å¯K.X‘›è嘑ÜU`,ãŒî7©œGÙkýŒUåÚ›Ë*}k5’’ùă¯™ûY=`ŽÏq^Î.Èa¿Oªæ£5’›Ø[¡«·Î`u†çjOB¹G?BÕzUyçôd££ƒl¤7JN†K!XnäAÍðñ´.éSÔlüH°}'ÚØÛXmªy^vÝÖÓ‡7+Š¿~}q†¦Iê{aK†d’êîh"à A8z–Ì È*CæÆÛýØ®<À¸¼€=Ýt•Ð(§‹êKì‡à"/ØŽ$‰g­ïà´…g¢:9 j_Ýë«1’B~V^B¿Ù1ˆ…0ÅÀ¶·¥¦ ö*÷=ñÎ`ïàKÈõTŸ×©åõ#+X?Ï#²(=•vç[±œÏð[·‹±by%™{9ÞObN9­ôÑCw¢ó™ã†¾Þ|c+ân+`Ð_3q\jÉ©íÓÇòÆ”Ä ×¸³Œ ‹ýç ÞF‰‘Q¾ é'àã…y´IfCloV3õºó¸\ñ,ú +ÚÛž§Ñ þÀëfɉéÀ_c/™cÃREMJr² Kû›‡ž3ñ–ž“è µOªCV°ŒÚxx˜Vß«®¤>9Ä7I­i$ÍΕ]ºØ€Ñ'g'×[MÝïvHVgÛW3èí÷v_JI S7b¶óizä<ê&Ù!ÀvÜš:ÉCž èÓ‰GÞD‰ƒSy—é¤ ¿¤#Ö©ÖåØT"®—#AšÄÝÕ¦KS8òøŠZß¾BAò)ŸJ& ÷ Éi#F?Žl·CUßÀW C“ÚrïÊMαàq·½~¼±uŸ”K*™Œ¼5ꕨñõ’}ÁJ±ƒIÜf×ÛÉdØx¯õ…ÞóÉšúª“:‡†Ì°AââJœ¼»-@]•Lò*I}b–G¬‹;KZS%ËïëV°(„¹:Êq–SÒ&äaHËÀyåÑÓ3Iøžn!Lá7^ØÆT¸’137¯ìdTFSQUàBÃTn@z$SJ¨<¤|ÛŸ„ÉÏ7šÇÊó O¶£\¼VÍÒ;7šÉÞ²ùy‘€'û}¸OWNÚ„˜Çø$û`öd”bçç½£ªÔ­{š­!øâÝËyÇݸû¾÷¦ Ž;½ ¹m&ÝäνàÜX“6Æ€•|Hø^V¡&“,?ÊøHNŽ&pà~– SÌrPÊaËÚX­@Š £5O[Ò;€&ÕÔ‰õË/žЌ쭖vôÐʕڴµv2o߈Æ5l¡­GÃÊNP8¼û¾^†î¡j#DdÚå^”…gy|ülKãµJîÉtï;ËÖ7¢ùY¼…‰©­°Ú›¦WNÄ1á$o”:Ú{­l‘4´ZíGMsô[ö~=ÆoÒ«¡\IàTÁ8HìPE…˜ª "uºCrh$oéãÚâ’A˜{Q9æN(kC³ܱOOòö•«é{Ðhiµbdéw[¾¥þR5½+‚‡ö™Ò'¹Ù6X©¯ôiÚÄœî‹1}÷Šûe‡a .¯íÆ,Vô ¶¡ölV~ï…ÚíKi}KòtÚö­äÉë{mÒWKÕpO•aÅÂôvV‡gÅ>/kÙƒ9¯w¹´a¢•õª‡ÙP®xIøæØ{­`«ÌLlÙb}%[ëd>€“ŠÍIÇm¶å§;zÏœ³„TBSbÏ8^‰Î oW}8ꚆOIL rç‚5%–xXCž øÛ…zXm3[˜çïÃ5•·–ÎÓ9V UH¨WOº؈ì°­lU}$}Ã#ŸÞ•rËёۉ2/=ÏW@sšJi‡O—M£#Ÿ@ùÚQÖÁ§7û²ˆd¨_ŽCöÑ×ñ@ìé(;ÅU±¼Ùב0öîá³÷œð«ð•~wìÀqÖ70ÊG'Z9¢oßÑ$—™{^‹ÜÕz;ÉÁ„ní7ŽÃžýÐ133ÇÚ#Y䬖°¨È<‘X.ˆ4Á(ŧÎä3¹\+“\³¬wÜB¬.±â*0PBZÔð¸,áUb¸¼,£Ïsð„CŒ´"›UÝ'ÅÉ¢L”óöøeè:{ï^sê#õYÖ+.«/\&ß6xóë@##5ö©1þù‹®½á7‰Üœ¾Óñ–¥üí©úG;±êž‹Býæ(€ ž˜{?Q~è>>§ÝÆbØDÒ”Óò†ˆs—¾*y³6}ó*‰9ض¥Ë;“¶:·ͽ(á.±Rµöp_ù'? ﵺœÇeÍ0ÄÒ£È þz_I¯Q€¤,§ÍÀÀ3œO.¡M‡[TòmÃÁàôï[¾¡äÁåª"_ºâj[³ÞLyÌßµF<;ÌC>Ä—¸cøTk®ô…àSÒ”~ÓÂåF(ä“ðÀòñ—KUO•L©+” GÙIÂãq¾Hœ“=[ÉU¦+»ÛÛ0?§ ‚µó¢—8JÄvOâ 5£ø²O•‹éZÖc<]sÖŽW==ôÕËGì[F½19-A”2o é©¢MŸô‚ÿœQäjçÄ£GEÓ _Ì[YãXæ¶´²ÕCI¥­Â+h\²Z'á«yÍLýt5zº >xVA²¼I¹9=+9ÈX *×ù v´c¯ oµ­iTúræ€vO}u£)ž[ÛC\"co’W›Ÿù¢,×å=ÞQØPCcbs ð ù PDZ}º!€ƒ /Î2ÂXFWæaµ··¨çÝl LÓªP`@Ù–Öiõluy.GõêöÀ”è= fJ‡‹åZ</(íPÒŠð‡:„O-fÙúfUgªj9pGY[Ð$^¼!]Aš‚@O‰à!¾èŸ÷‘ØÍ€·*¥>íHµ¡V­Û.ÑŠz>ã4ÄŠcËØßníh¦) Ó¾Ž_õ©‡t5íĬ“ÉÝhE±Dy†aeÒ¶nKä¤ñ¤dW¸R( Àź6ájžk¾²4Ñ'cžýäsLiQ %¡à~p‚mc“iAëôe¦ûî–äpéªÄõµÚÇWß:q öbø“k©lJÈ‚õ6{´QB€ÞÓÉ6'{ìè|zò-§aPQ$§Êë^£7r¯éöoWKÈ>yïtyÀÉ.{ûúËú6+IO7^¼¹­€†´naÜ6ˬ늓ÅR¶½—•Ééý½yg{ÆnF›EIÅížU^@AL:p8MûÌiK©°Ê'IŸö·:#†°üÏÆH )z9xã4g{¥fÔP¢Jƒ ïnâïÿšûþÇWÃišÜšž€IDATxÚìýi³lÙq®å¾Ï‰¸÷ 9bNÌ ( g‚EªÊT’U·¤ª¶¶þÐýúô×þ!ÝÖê’ÔJ¤(’ @R$EREEŒ‰ d"™ï½{oÄ9ÛÝûƒï}âDÜ—ÉÄ”™¤Þ6C"ÞˆgØÛ·ûòåËùÛ¿ý$E„$Qˆ !¤¤@A‚B HRB„J @P\(ýˆPd`X@Àœè_`€d ˆ5 @ŒÈÒ‰ ƒ@ $à` BHVkàhÂ#!"ýb1ˆx˜`^7ó¿$ó–?FD)%ú`ËñW¯0á‘÷9pødD¸WYŽPäÇÂEør|wý†,?½:UDøräŠ(÷ö1‘vnËÏ­¯‹ŒåêÖ×¾¾o9OòË»!bu‹È¼÷$„hû-’Yý.)í-UEΠݮw?ùÅå–y ÀÝ—«[ÎóøY|¯Æáñ½"?÷`<ß­Qr]¹»ˆpC8(‘ÿòÈåJƒ “ Ã5\Á ƒbD0€0hË@Úº¨`ôÜ?"Íè¶ ÀÑ œGD„ˆš5  Èh¦GòÃUµýÙ7ŒfJò¤W!ùË "·4 "i<ón,c1@ùOU=9ò2ë,"ù[d‰pÌ;\ÿP»Qy&aÍz¢kwïGÆúºíi’·‡Õvæ¡V; N®âxG9²õk¼¾Þ¶£ôŸŽö¿övÕ Ë `õ8Ö[Nߥ¤ŸöáªO~îèwûÙæ Ç«a‚y˜¼x±‰ñ`<¯ÁQÌ,_5׉¤ n¦ª€¡Dx¸¤G’ž¶Ö„âFîíPé!tv#àîÆú–Ó¬™Ž¾<`¤™ŒûŽWW€@wÏ;á € y÷îíørØíHïçiñ‰Ü|"@ˆ;$ß$Ö&èÄV6‹ƒÅòåß ŽTNýúåTUu¹®WkE=0ýÆ_£QÐÁ¤Ek  ÂÂEdÁqÒ:†›1mþÞ‚_@† o±}Dx¾§ùQKPBù--CHD@â4$à Íú À@À¡”@; a–—áiêk¥G®bDD8)¼¹ýÑLX Žè` =¾>ÇÇÀ4±«¿$>–gµ„5"x‰‚yGŒi³¢'¶¾ÿôù­­dÚ>`9&3Ô Ï]ÆZÁ1¶sÀ£ ZÞ„XB õ>k®ÿóØOoû=[¿Ë¼O×O | b5Nï9yý×ï ^Ys¼Þ ¿¯?ŒW~”Œ²Iš™ª’âžÆƒV#`ÃþpÄñ¡¤Ýq÷bN—8íàKh7wQ EÌ\ºu ¤û߆Ãs³Áâö:ˆ`¤Õéȶ·ÀŽ9ƒ7º64Ëú wà¿ dDÆ ´ðL$|}ßwIÀn7ƒ¤žF2 ×q t‡xè‘?Bá»u@ÆËq÷Ê—·rw oÉáé\»ŠþyMëLɧ}¸ð!ız1kµì <ü>^yJDÈüLs6Ž¢½kfñú_Nº¿¦c j-×õjŸÔƒñ7|È”I÷ºˆx¸†:Ü H¸ÃA†p¢UÄgZ=Éܤ€…§7)Ncær¤D„GÀwCTP=‚@[ÁÑL··ä¤éÏŸM ƒÁƒ! ö² ó´àÂf¶ä笷@eH„ËfÕ=t2àáÉÝC( Ü]@0Zê‰'Ex»aä#ái‹È»ÑöH0º›ßN6:|¾¸½ËÈM"Zl†õçÖÀ÷Ú56÷|®íë Å  Ëþ+ÂÏg Ï«è?/tE9`evWÉþþÏ8D,¹¹¶gäK¸Ã>ÌÍ8| ˆ]×I晫MTÚ†ýZÙNüU»`ºJéZåkY§¸ŒcßÅ`±¸O¤€!Q‰pàB0}UJNgºÏÍ÷£ä¢ÒÍ)͘E:ÿÝâ­ŠÃÒµ°òºà<„é¿:ºå@;”Ý;¬âœbAáWft½öÜ]‚Ñ t°»£ÕÇÌL“”“¾ðr}þ² +Bé¿J4\<§Ôö2Ò4BÊä Y5+ǃ1e¬ü}Br'ÍQ¸‹÷õ…â„È.‡Í£YÏÌQ߇ã„%¿ºo'ùêõä!Øiÿ΃¯N¾Ý¾_´dÙî æœ¸ù÷ý÷u™_-»y=.YvM3[_òú[QkMë_8ëÁx0°Š‰(ÿþ ÅMHB0EÏ‚ì@»åŠ „df˜´pDEÛ¦ ìÓ=’ŸÙO²9÷ÒÍ„%^Ñ]D"±~g4OÃö„þá Ož`f¥ãQ×ïTf#s¹Ex@Ãó¥JºÇèìš%n8Ê#@ŠJD0YW- O<Ú¥–ìpoɼÊA«–‚¯“I°à*d¦#H‹€¬=ëö²$^ïÍ |m¯—ÿ¾˜û¿>Ÿ“#/ØÑºJëÅ&Ù‰A_ "‹É>ú­“Ø= [~k½´ú•W›ýyr½‘¥‘Bsܼ(†a|™}ç¿…vÆß¤±Î„ᘚñmâœ#HõààE4F¦FÒù›s-&Á0 î"TH˜QwÅ[VI×$`,ÐáA ¹G {P›cƒ‘pJóS#–ãôõ|عª˜m%ÆY‹ÆHb`ÁÖcñ7W¤ ¤ßç7²4 •)ð$ô´@ð Òpz„¶Í wÅÜ—r#£0³¾Je¤""™·ã£ÞÐÌl{Ò“ÜD@–•Þc›ÜAxÕ Å2M‚p„GÂ[­zC7 Paº$ ïgǯÖûÚÙžæÎËBpö@(( ‘(J‘èèÿòÈz9új“[œúZë}ã•8®Ú»o|ðÊo ‡_Œ`ØÙ¦Fe¢¤Æj¼Lì"ާèkd³%Ç:á·öw¯3^þ(n ¸h Œ k¦ÐZ–Ž‚á&(ÉÀ f¦”0§wæÖ–„)Nüñ ’æžlÜŸ0«‰| ]ìCv´ùÚk~ˆ°ØÐ 3+•Y@9²’íÆµ}æp—O×8%ÜCZêòùÎ=JcÛ3¦Ñ9?Üôñ¼DÍl@V¬öÜʲ!J2/#²d-Pc¡ÇÀŽ YæÏ@`áï_sÆ…\ÒlYc,O„ˆÈ2:úB]–’f¯Õã9×à;báDu*nÿ¿Ä}úÄêF^'ÊËS^!|=ŒŸ—Ç ðk'öªn·[9Â'¿û'ö𹨗;Ö€Þ_‘…Za€}¯÷;/v"bá|‡-Õ¯TŠY:ú Ì© ÃD ¤Ù>!  ¡”°‚Bw4¤;¶\üÃZA?¸X´¢1xPAmàxY‘cü—dDÎŒæc–NÍDCK>ƒ'Ô—Åò-6+¡Y*_²íÆ's±T·ý‚hÑÇâ‹H¸{rïû!šElç€Ìª³1o%XѪ9)•›Ÿo\ L(ÆRq†vI®õ%ôÁ±ƒ,’¹+ŒNöÅ¢šÐ €k\Òµï|â /ý)åÅÈÑæAr/¡ª,JË>""™‘áñÀ©›ÂXƒr²JhŸ|÷ÕyžëhæÕ=Ÿ×ÈXž‘»›Y­`³Ù Sé„áðððCÂé%´X¾Õ39 ¿Ãc~¯ÇÉÂŒkè÷ÉÇ^ì»ËK8, ?pe"¸¶R.¸µoš4#¢Ts’B¡5å7§ÂÃØ¶ 7ËwXØD'ߤÏ[Sü+ѺƒL NÂƒÑ€Ýæ=›Ú ’SÔvãk¤8<‘q±5+kâ†#ÜÛ{,„âèw£íæ.‚Ep¢?ƒƒ %4w šN쌌p*;?2®‚YÝ2•íÀ`´;#kPHcEÞ_þššÅXfƒ»e U•.9·LÄ¥2ú4s³žµ ßWDÌl­´®¡;¹¼ª‹ùµ““xíŒ5dѽzÖê³*E# æ0°‹ÚÊzæZÝpIÆïüÞr%‡µŽ0^³(ÓbÁ—³Íqßû|3a…¬®G™««ªIÂw©  ˆæÚ2zÙT¬f¶‡-fX(©ê™Ec™ÍŸÌ ¬ëWRJY€ÝDÃ$5ºÜýô´ÚžÎäj»>â .·¦ÿVt 6¬-8V6eÁA„oÕ‡xUâ’KNñ:(Ñò‹Ó,"¥”ë÷­XXxˆÐ…”}fn!b€˜¥ý îÖÃÿ<•ö,«]”ðESÓ¬ $¼ÞÒªÍò°Ö*Ôd¸ ´gMYÿpŸ+k28LŠõ ‘ à^TqàÐcÁ‰¢ë.°æ,·t…Ò¤i*>Þ³™ÉYJ&hJ»…-º§hÛ`K¶¢ŠÆá<8æ+W@+ef4Åæ\ËÉä39ìE}ÿK Š,~nf—ŒDß¼EÒ ê7 mÕkÍX÷ûp'—yvÙY4ýà™;ÏÂ\¦™w–þÇ ©<=òz-]_x'Ÿ<©>YŠë^ß^±Uú`Üw,ŽE>U-ó4§°¼GhѬW©jdÕ„  —÷W—p–w÷Ó4ŽC4x5ÖþÐz3¸ï̹/ÿ=]ë_\,ûõ ìï[­næ!03ˆq‚ž³Ù‚ 0Û mé¬9dAjâÐÖj ‹f‘–L‰„̼ÙÁÆóšYÀºW™†`17¹ÁºX¦»‘ºÔOå /rfÎt€}ñ¸™ûafÚØÖ=IıÞ:w°¥ЊsòŸé[„tOÿ:­8 <¼C½€ Px$ohÑ„‹N”‘#-û A¢C:Þ3ͳîeeÙõ SZÛÆŽK9Ÿh™›~¡lTüC¬z¨×<}?ùË}™Ã_Žâžñ¥Z,³¬\²³þì—s߃¿ÌÁ¼Þþïëþ¯OûdÑ>Ø ^­q“‘(ƒ¦"ìF`æfà4ÛÎ ]eJ«dü-øÝkêðÚ-˜çÙ—bÓEtæ~ˆ8žT¸ŸõÅnÚÚ»?ñÌú¥Á=ÜŽpzÀJ!„ÌJ¦å”Úøû5æ=B'é^óµkÍp kð¤VëËÏ„ZÍ4©nì¥]ý1ˆH¸P$Z4¢Þðîfõ‰€üÒQYÄ–^£" ”™óÔlDÝó+©úÙtxÆåj{8PŒÜónö,.V¦ÿvôõÎǃ£Ýç³D²@Ó‡®Âg³©éYÕVܵL¸€,TßHVSpµ=¬¢ 6¦çi íòÔ–°ñØEÖ'èwþ–_ÿe©ôbgú´0]dÁîNìþ·g—kYOÂåö®#ƒ\-™dz1îЃ=àUk»¼  `,œæä>»™@J)¡°’´ 6Jñ}3ŸëC¯È‰¨$!è“#ä8áׯ§ÊÉ‚úžâ?«-§{–™9_c;f¬ÜÃ,,‹Ï³E–™d(YtÅô(>K3ÂdHÌ«WDµ™Ñãmwb Dœ³!!‘ùT8ªD@¯ÖppËS®¤ê,KÕp÷¸±.U]¬÷rG „^4çF¬w òáAzÜÈóÏCEß?#<ÀÈM odi[÷rWv–-pVêк ¸d˜âÌÆgHî½î® -BrØcúÄõäÒ4f$=ºTu¿ç™ÿ<£V†ŒDHS#]y=ËÇNfí²H'ý°ÚÕF–I7kɦÀ;}‹I¨M•·ôHPRåߨçÄè_·¿/qÕ,lýÅ댈õŒ]߇ÖÿU'fta£1÷‚Ø‘ÝÞ"Ô³q:lÌŠ!i›ò˜‹¡Op_UÍÍÜém›†ApdÖé0›¢ ¶C˜ûk!Ëižß›=`õA33 ó„U œ6ÕðÔ¡¨ ݼV£ySó"T„Ãk„»áQàÕ)ª%è’vcÇÊûõ;:II·A®ZÜ-]ÿhÄ• àö›»rØ"«*ÚD’žÎ\):éž µ,_2#ŒÍ : *ÒjÍ€`6&PIG·Gf‹0C£ýe?ÈÅTEDj…&q ¸Ò° …—,¹Š,'[,NS8Mh"³µæyãÒvHYËë ^$êM½ÓÂp8—fKB—”p§ä.2ýb#zÒ4MhƒÁE ýmFëÙ©Ýev­¦âi-ذ3â¯o*ùÖzC]ÈÈÌñÂÛ£ ,"©Á•¹>¶ý§¿×8bKËh, {U/–}ùvyÙT–`mèOv—U°|`£=Ø^•±XÿZ[Ì}Ò½y=72–b;& f†ˆ¹Æä´P6åà[¨j¢:í·Ðhܱ”ȬJðNø×=’“0eùãõ9öÝõ'Ö»N–°~V…§íkÖé°ø ¤cÝÍ4ôŒ ˜#Àd´(X.kUr4¡†ˆZ„ Aª{4ž/”íêÿ Ò{!’»gP.’Ü%ë#¥D@¥º·½DD,j#¶GʽiÞÛþ_’I@B£ÛÈã°ÖÎ¥ÙÊ.>Ú]Ë4ãa0:› ƒA‰À¢5(&ºÄf^åÌvĦ!Â%ÔuQgR#E%й«=XAÏý6ÆA‡t„̽` M¬“kôâÚ_Ó¥;¿-&[fïÚ=YÚ%¢Ð%>A?ÁÕ²i´¥uúaeëûÅâ Þ~ªÕ‡#ËýZÚæ(tû«Òh/æ¡_wÇÒv¬kÖ0×úÚ×À‹¢ŒWf¤õOþ÷õqúÜ‘*D¡ÙTU­ºyøXÆA[‚íä‰ã$iv¿qâþcP.hR¬z.½Ø´y±àà;¹E™æ]^G„;=šrÂ#Þ}ÿÜçøf*Ç,s>_ saGÀѺ0ŠA$ʜ̂ ¥Ó0 `P\ªˆ˜yvÎCT”ÙZÝ ‰‰P(•)\€iQ­åVΨ¢Fîàõ¹#€*‚­yckMO¬sæÅ_F=@´–Ü"¢ûä{¦´m6 ¨ˆHx³ä9eRY’¹â Š3<(ÚÉQé’·MqÙÖÓè±é3õëÃæq¿ùÚvÐ%<䪢¥y[PiÚ|1Âu2àAe:§l>âå›’öýèt/±^_!×Wo^c^òúÎ,ÞŽ÷ïnû`ü•ƒ½ùÁqÔû-æ²~Ǽ̓HqͲNJt2sÖ«þįúVÇú·ÜÝÂ=+‚fI;D8,ñþC·­ã¤ªßç&´¢¥Xby„ éÊxî¹göç~¾\]î…´2šÂ¥»åÍ—¬`¦6Î|R[ŒpDd0î‰Cª4Ì¿¶…*YÂ$d&‘L6Èa›¢¨¦ˆ EYI=¼˜ª}3ñˆÚ8úÙíDÂ5¢Dz¯¤0¾º5—©¹æ)ÂÃfÀ£©”(Í,¦“~胖Õ#™æ<±eKä®°Èp6Ì !³Ù<ÈÎ`—•'¾Lô“PàÄhFÏÆH–ãÊË,šÁêÛAÊùs‰.¹Ò­^-›£¸øð|áËü\VÈõ®oi鮵¿lý±e'Xf}ÖÿÕ'ìÛp¢ûW€Cê»9– vηîû÷ïN¿ŽgOþØž”žVýЮ‡Œï¡Cs'„®á¡åV-9ëCîúˆçzàœ\ËõXêÅVÎ1öuŸ[ñQÅ·ëu>ßÑøüýWèôÖÐÿ}gàI¦áÅ&áKÿÊÉ?sŠˆåǽa>°Ü º²|Ú†îUX-èÚ3L)úÆmmîd{/ÿA¢Nõ—ñÃñ‰OWj¹wqUÝ€5BleÊ~V‘¹ÔR²¬JBk”!)•ªÅ„aVçý\Ͳ Áj¨ˆƒ¨Z ¬åªÊ¢JÎ*BP T-EŠBòLÉ IQ„ùdµºyë—5–r¾Ù¨j(@ñ,ªE5 ¦²=›Ä¾ÑšCNÂ#s¡Ñ°iôÄ]Òd·.¨î$5¬—uuZÎ!×Ùï®&AÖLH?rY«5œN³ˆc•ÿÅVFDªžÌ­ÅÊŸ”8-?±>úuxí¿œTQx7ÀÑfsßY½Nóö«Y}ÈLÀëE§ý-œÔè:"³SÇO-G8®QÀŠ¿°öÀ®^Ge_â&¬3½«×±Øöðˆ†«à¡ñÕqÄ|LóHÙ/´Í£0µWùÈï}ø×í¢î¬€R§E³eu9 ŠP"6ãPÆYUU¤È~Т,à|5O:i„×iÚ_íÍÍÕ˜`é1Ï„Šs’1'sdQÕv¾p™CŠ …î*ãr¿ßí¦ËÝ È¶ŒEäjë7ocQeŠfÛa•aJ Ü@†€5Is1'Ѥ,’üã¦LŽ, sÙJ̃B@ë·ž´W¶¶ïhÜdv¤w…l=~— ´<ž–«\õnôž)EÛ˜µžõÛ'h)ó‹ .ÏfÁ‹Øôõ <™©'ÉÑ$æÚ½A…V«×ûzÎäsçEktÆç‹é¸ñ~YôWË<ßݱ̄¤ê¿f÷€“ý龘Õ}ÉfxÓ¿Ùï7‘©µ6IÙ†t²btÏ¿ÿT®ý4²‚œ;êºÔuÐ?Ü©d¹wï…ßøÍ_ÿÿý÷.§)Dáau.wçó4c#öTlÆaB0¼VçAQG•†ª3¢B(“Š"kam޵„dƒõäWÖðˆ˜+E9ˆa Æ8EèƒU©»iÞ`(C™TÇdv5Mû]Ýïë\mRÛ ã<»H93–‚‚N%gŒ„†¢h´KÚù˜ž’x)OíNJKn#U+pØK]Д §w°õsñ•bOB6  ±žI\µ±mÎ5Ù›œEÖÈæã[æÏá9w4ÿÈ(7RÃã$ÓƒÌê)s-ƒs/ºž8`è‡kiWÒ4¦»E €Ã^yÐò}Þöúb[µt{éUúŠY„ã;×±‘×ì<™~<&}žà¨ëµv=uý°XÑ4.V)·—XÄ-[Ī•H¿¡×"òXП# ÅaQ_ýò~ößÿܧŸ|ÒðPJÔ“«Žˆj“ªÌ^ÅE†¡Ö ÂÌf«Et"F7k¾¬È$E9–¢a·"ð6{†&36P„¥çÍ¢TÇV Å¸7«¢`“+÷T±0³¨Õö»i®6WŸªG`ˆiŽ¡È ŒàPB‹jÊÊY­YPÀÊT "w+Éj¢ŒVGçÙ‚2™M²ÚÃn›hç“ôüh–÷Ï$êIeÞXÜÝܳcÌR—«têR»M>¹yÖvÉ©òe'XQY²‚,kËZ1ƒ;O¦;­u=g°iŽ.“å¾nØ©_ÄÁ¹Ç’nî Næ=NŽzÈ÷íí¾Ë&ºjÛ VðšµcƱ{Ûú/ù}ã;”×PØïþ8™ü~àÍc5± D/×_…쫚†ëMª—ôò":Ù*OÆ`LÊ"¼ÿlóWÚöèåOHZyôñ’‰‹Þ 0Ïzˆá™¯=õÏþ_ÿŸ§ïÞÙÃk"ÞSX‰H £š£È4ω<Ía¨Z‚1ÖIÉ’P3g`Ô)j2[ŠB†Ù4›õ _(¬¦¬‚—B»¡N•P ZÐÌáP°* (FFìöólØïfƒWÀèî¦pt?OWu'äÆ1Je<\Q ð C»º³¶Xá_ VËÞ.µfm6˜¹Hk+–Nó¸ÈúfÁ³ŒÍºŒhR¬½ÔVR_!¢EDÝâ·²5Ò=Hø"ŒšYÕžYAâB±*óóUîUš¢u;ƒ Ø&—ÿd"(Iš P³)/oq@ËèæM‚÷Ï{‚×É¥ £'¬º•¿?d‰•‰_ûG,þ+9òÎ×ZkuªhѨU)ßî³x91Ü·=1ïÑññ¬aÐèâ£=¤>ÌáüÀ:>¾®JÛAÿNéñ$f}ÖB#•tÿ LŽ{LRZš7] RÍ-˽Ž"•Éö¿ùÛ¿}÷â’Á¨®ªŒ°¹ZTF}ïßý‰Ÿ½÷]ïÐM¹¸¸²ðÉBI7ÙOñV¥PsOsOi³V¨lÕëlðH)7wó)´ê ô¼_Mõ{­Nîæf^­V3kÊG‹‘20(€€¥5‰ŠVp¸‡…E§È¦Ê{SižMÛV“ÆsË[fáié›e\nb7H ’÷ÞÛ·“G¤»Ítvê')@¤PuÚÜ5âà5D0UYkñÂåcÇN Í<3ÛóœA†”ì°f€!A:`irÙyF­lxÁ¬N~ºÇ1-ºèÅt¹%‹ #‰ëöÅõj]¶KPŸ„}/Öùƒ‘cÙû¯¦ºŸ9UñHß ^¾} @ÿ»þøå{11â ºpT °¼8ÆKï_brÀmV.ÿÒœ øZNÐceºÃ Bzwðc`J hå ©èé]b-ƒÜ¯ ¿ò¡ÿÎïþ®‹\Öꪀ‡×êý4%6Лç[Œþµo>˜ÀéUT¨l9j!ÜbV@8äæÀ0Xøl¥¨»Ï†$mZÊCG AŠ;wµ:˜°ÖJ  € ™ÇäIáŒA#Ì<Ü% DJ„Õ bžê%Ya…³×y¢p_tÐó2ÌE7c ƒÃ0#DC‘ÕÂ^=u:%{ÕˆJxÒdI—hE EPKZnÏ$¯#i›nF‘ ¬©àew-jöÜ hª å! ¢-ù,÷ãêäh^ƒ4O=ƒC»séâ®íM·Œ4µÍ?øâ´ŽdKñš zí“éöuuZZu´ßô0 'áÒõ²‡)kÔé°Z–Þñ‡r±¾BN«û%$Œïõh™*D °Ò1Œ—¾9ù:VNîZEø{q¶‰žîËëï$dY9éèë‚É~ÎcwŽú¡¥Ý2“×w2_¯½¨n÷ ÙÓMNg ‡›‡þ3‡ÌpÇ'ò½ÖÛd:<‹‰‚î‰VRTÈ?úèý½|„CÙífC¹ó9Ì´d¿Â(n> ò}ïzûÝݘ"h£‡Šº³šÕ:oŠŠ³*Œ!4;ÿV¸USÑä°ûl澟ªƒRŠÍ>Ó¡J‘¨­¤—f A`7U‚Ô¢s‹fsQÝÔ#ÌV‹rž§êBÊž¦ŠJ‘ËMTÆQƱœo¶76g¢(EE R@a0&Ûß{[n'üùÏÚê¡‘f·ç 2y+Ò©„AXJG#ë°œ8Hî´6¸q¸Äý±ÂSºY3Pó«;òY¨Mþ”ëØ#Žøi8"¥$U úã^fOxß2­Ýv\ ¿`íõ×G^QJį ½>tù­@ç ®Ñö.FÊç|§cçÿp™ æ#b>H¯ççã¸(¢{gdRß‹è3_ûÚ¯}øWîÞ½wïj_ú”afå°Š%¢LŠJˆ˜ ƒ"©åªŒÈLM"W*)ãï™Ãé( —­¾ÏŸ¾óC¤¥M¹G´((ÜÁ¬§È”y›wD(ÈéTËèå²'y'6éä\c{´"À$2÷sGq†ÖÞ;™AÀZƒzõϦŠÊ%ñÍSŸë£;6.Ë¿S ôD•zmúO6†ïp1?ßõµzµœèD_ŸkÊV …#l,Z4éЧœÈûŽ—xÜ‹‹° 4'éY\‹¾Õ‹:YY™‰½~Âk`gɇ­¾µP½—=µ5*ÁŠGŠFùÞ=ýxèr2;Ôòp¢kNy?rKòÜÓßø7ÿöûôg?W#,bγ‰*áîVU3+:J)Å9ë0„…W*H%ݪWUUIÙXT‚Ó\#bP‹–AgÛ»«bôÀÙö<Â/quïbïÎʶÖ*¤B(F Ÿ¬š…€)0 z ›Ag7¯•MÚ^ÂR“§3 îÁedAÐc ` O˜ÍTdž/Ï«m6{MðΡ,EgÊ C)gÛm)ª K˜± Ð›T¨GP$ÈÚz €ªÊî=(`µ®?H9Ó¤ðÃ4 AºÀàJ€Æþl£…4«Ks0D¸f»ô¦=Û*6‚M4¡Óƒµµ^ÆŽí€ çAÜ æ®I8‚Íè[ýÑ%ü¼fÍ»Ü%ŠúÖÛñšÌýbYر>æI„¾¶þk õ[]ÆÆ·=ÖåÅZ`™ìä|³¹¨T*Þícöœb¡)eKVÓè B4en5ÛhŠš:½™Ç¡Æðe>îÅÊ_ODçžä’< LqÍ”Ÿ1m %Â2¼.àÒ} r 6g.+E_D-¤À›|wÔZ#)zx~B–äb­ê«™täšmra‹¶pp€|”ž{þßÿ»ŸýìçŸtu%1Û<ïá(Înnß]^ºc»cF)޳Ĭ^ëÊù…tÝ̪ÍTH˜%’Àir‘’T!ŠèßúŸ¤R”¥ˆdky …R§ù›O?;–ATDĽª–¤;`΢s“AܳA–šY ¦yŽÀ0ŽÄÃaÎ0Oº=Ã!Ðhöƒ¨Í³’*EDØ–™åvL‘Üb•,ÊR4œ‚A‚î>ÏÕœÓd©£$[’ÕÍûýTgŸ&›kÔ l")RT4"T” £æ>DÖu¥EVP–JŒÔqpK@“ ØòÔ¢[¡Ÿ‡’²jœ’Û¸7¶¥“@ŠT9JÒN e”;PsWIŠJ¯f#¼™ÿF%ƒ/bÃA U0Hd~4ßl±à]¨zõÑþ»¢ú_çö¬—åB–À±Ïµ¬çÓ ãøŸÆ+0¢‹‘eçq³¨³p§;æê³Édœ€•Eò?RŒ ëlâl*ô V}2î\æÉ0»Ì®“KuºÃ²;-NÙ_¨ç`¢9©Uÿ‰D$óp]»p=ˆ\µ|faý¯8ûùº/Úç8 õ8x>­¯Èò%©¿­ëäE·J­%˵’îYNéºÇ«õr8yÒ;6€£¶ƒd0û«ý¿û×ÿö/?ùÙK²µ}gìæ}ІDã"ÌlŽ ¶nXsÝ—M‘¦ã/Eø¬:8Tã€ÉCÆ¡¢"0pSÂØÜ!t6E$¢A¨Æùfƒˆ+÷¤:íë BÜ †„a¶PÅ âÕW#UŠFTÖ«|(ƒLÂP·:ÎuÆQ3èADˆ‡„h„­h±i6šŒcИw—éQ JDU-bœ.§pš×¡Ju¿qv£6’2EqHQxÈ ñðL3@pšH"çpiŒ¦PmЇ·R0I.Òµe/‘†…eÖ&„žû‡G²¨¸¥;’J×aæa 2 ‘©.èÍj"®;dFj M3ó¤`€Ú&1(ÚFô,F² <3•©k-ìÁ}Xü'VEô“¥«tbwNÚCÆË#ž?ßÝÑÒ<ó0@ v`6w0(-%ª†Sm3ê %<½ætµzìÃI$åßÝe*á–îFrZZí¼Ì fw†„PæZ-Pg9 :†U VD JQ 0IÙŠ$Õ…‘QêR'Ï•übÎáˆp„ek&QIÈ’Qøz²ãû}J{§ó e„³qIÊh9Ñ ë„›.Ró†#Â:«»ŸpWŸ\L±$ÝáÔ ‡ÁÊ8l樰b6¹Š»Ûì`0… B´º«ˆ×J Ló^ËX¤ˆ¤'ª¥ö64>jen‰^錊¬†¥Žª$ 03Ÿ«£Q½åY=e™„;‰B(á5bÐâ–ÁPsû-C ˆê®Áê¾—ÚHö0HDT½àƒŠUC@Áq[f³j(¢1Ç”)Uñ&Êlá`›àþÅÅ|qv5nËÍív; IªuÒ€’R •adß™€ M~i½#ÚRb$¹S:aÀ™¹n ŸÖ ‹hdÃhÈWÊé!PkM½š‡žz!WšNÏÖÂü ÚJl¹å8ÖƒÆu®“¦¬ì¥q8šØS¾knÏ‘Û~ yú\í%8ÖG{ý¿Â〧»»Á£¤4¢€… e” qUÑf¯:å&ÝgA  8UŸCîÐLG-ñ_çÏä"“÷à ç4…ás€Pq¡ÑÍZ3áf&¤h¸›"CÍÿ‡„GÏĵ^­ ibíõ_K7¶¾{´ÎàOœÇi^ Ñ>Û ÷¹—´â@÷?ÆÉÿÒRXÙ¸¤Nzüí`±.Ü ÈlǨûze´ˆ©hT÷¨ªê¦NîÊÁ1%¸-5Lac)V' R0™=fC‘bsõDª ¥Œ›¢F«s¸ÛnÞœŸ…Èåîêj·ß–aš­) Dˆš!Ü ª´¨¨W ð D E+¼ZrzÔ<ܬˆ0bõ,S7Vg ŒÃà5Ì ¡¹ƒ¸ªÓy˨Vͺ0ÂÜÜD(©òà‡>1ÍU¤(æýîªH‘Gæy˜™„m™¾<³ ›†¥S/£Sº"+ÔŒuP<¬1·‚ 2tFAwHÒC#³Âd@Ræ£ÁöÞuÜÚÔˈ2'Å"Bï©],é¨E ´—… ØåCpð²ÉUqVb–I;eKL…ŽÈv ÂÒÍz¬'.q„öô5ÃÇ“ïÄ>¿»Pv ·:8鳊ûí Æ+6´”¹ÖZQˆíت!)Lg¨“É&É”¢‡Š ¥á„ƒÊTcWÍàLε†Jé’ ·y PKváC„y¸À³¤=‚•D7Qk:W†™PP$Š@µ‘b• Îê–µ£îPŽˆhm8p73ûz ù³'y#a«XÈy?:ëÚ¯¥4Ö;Á’ËÜo´Ü_ôýc [št±0ŽŽè°Ì(Ÿýôg>ý¹OïëÅgxÑRœÅ8Ž£³#¦É«‡»S0ŒZ-·oIÑJ ä⢒¢J)°9Üœ*Î ÎKÙ¥²´Á³ó³»w/¨C­6ß¼ VxæRUªªŠÖi/*[-à`V¨",[roWAßÍ{C g½0FJqª%ÓJJ8‘Ȫ’D¢,R¢bš|³©VÈFË`³íæPM±""ù˜=àV=B¢¨ÀmP¼puYZ¥ÔâÎó3ÕQ˜þ|§è¸»r•P™â]¤àºøš¤°\.a–1@Ã5x!{2‰–›m\¹ƒo±ÔîJ!ˆdcq¦c¹½D@Z¢­Ë½E;H£å-‚šdÿª[<û Ò;³'e¥rQQ’kt˜Ó-#ÑkÊZÔË¥dl!x>¶Ìþ5èù€óóêŽúì¥ ?2†"äQ/=(̬R¸{µ˜)‘Tá\À !ƒXÁ#j8Y€V²e4æšV<³T2Ÿá“Ùº£k¢5ÀfE¹Ù „ Z}É=G ô¬‰w [m ߢ³ê²œÙú{!v§Ÿu Éõ{³ð1Oî0î7Ãç;`Ù¸~Ld1éá´yø\ofK‹Ê¼›ëw~ûbwUéô}nÓdE„ÇœT{ª…¥hQjxQa#gÔ[çÃ~6-`¤ C=lÔ"Œq,ZJ¸×:¹†ÀeWë+6‰æî {)ƒ@*H)¢ˆ°·‡¶Ü¼÷oïûÞjõò…{Ïþå§?ó©'?_ÇÍTM¡D ©p’Zggk$FJ¨R%àâA—ø ˆ™|Þ»*[ex}ô‘GŸ{þ…Ëýäá^‚¢%;íLf٦;Wqeõ|³Ýì† µ° ¨± ÍÍ*\•Y†Lí+E Ï ë–%ÛDé%ÛÖÖlžDHDnq]Ï£ïG0 R,*©†îR¥-Y'·Ð=­pó¬E: šÇB¥7’cvþᚤº·."\fõÑÒZg—5zQë‚%zHá’~QèqÀõ´ðƒñJŽUŽ•„ *îQŠÜ£[äÌR1Hó0Wˆ8¼jMdS†`Jð”³M[.Y Ò‰Ä2nHÖZ«›Ô…ñ]Á1“½h» Œƒœo„-ÅÉkÐq–W3×…”_„ÊT×:8÷°OKgþäbʪI{© \ÿ•Ôêi¨o¦:Ö¾Åȵ‡‡´\w¿î<çÃÿñCö‰ÏR€ÉÍV}ÊÛïj­aµ¥ˆC™fRæaœ¶77ûùj JÜóív£$I3¨ÃH«åλ7·[¥Þ»ÜEˆJ„óòbãì\@£º«Ê0@Q݇q£¤Ro ½õõo{ÿûÞûÄ[óáªZyKÜx÷»Þô‡tû£úgQfáE* Œ­(Í…â±G7™^0$3,9úEQ¼–JÆ )bs\É1™¸Ò£ÌnfÄ ,,©’óó|iSÝ :{ͧ¦ãM¯3 "b³…G‘I€³q«Z‡£2 IDÒË´„ ŠÃá‘ D+¶€HzGY¡•4¦ÃD9hÂàÒ "ö6ôǽ!V¹Ùí&Ù¦ñkÍæ)];[:4#RFèÍ·IÚ^&,Z‘r_$ÑÔ¡såô¬q“fv2,ºÕ‡|ÀI€¡À+5:ÀÝY‰^£)%jQ’í¹»Â¬ÕZÝ`‘´ d}aæ º Ò;”a‰/ܬC †F]Tr ±U†bˆˆ¸sµ3“lî-ZGE6ýöðˆ()w:gdm\E$+ W‰%YÒ¼@¯‹ìÄi²³.W<…VäØÑ©àÖêk¤¸ø)dEæ¹þâèþw¯¨¿)µµLt)5>½-wp©lH¦_sYÀÝ»ÿú_þ‹Ï|þsê4™›U)¢©$ØÄ0´Œ:lPkv@±ðro?M&ç™.e3C@ç†gá´js–2`ŠÂgÍ0B¥Jâ|sfŒ©Ú4×ó³¨Ä…¹ÃÝÙz%/:„ãozèüG?ì]ï¤ÂƒR6ƒþôOþè{¾ÿÝÿëÿïßÍAÆ8BË0ìm’s²«1ÕP•Áà6¥ŒRfŸf:U)Jz„ÕÁ`ùæ7ïM5e»Ýl@ÄêTmÑt):Ís65ÈVŽÕPëHs•iº¥PhQ -,g=.P0(¨f5Ÿ‡Ùì ŠHÀÂ Š¬.Mã)ñ?×&þ ±zÒ952îA'%°E¦‹GsáÛ_°è ‡ä*Ó»eÒÃú߇%uX]-Ò•cIÒ=…Ö‰+G¾ F_§ -Œkïïó•ëI5Ïsmª4é€2"èØŒT"Üà«æµbot!M¥Ôèt²Ò%h=øÝ×îÃÚ4u!lÊnÉüZƒ……êÓ÷‚½'#‰¬hw`áøÑý›×+~±üÄò™ëÀƒà»>ë_«íç:v^&ã²7Vh Öà4{­á`X˜U › ³‰y‰q4¶¹±•ólln$.ðäêçDgè“$|,¸¹•óM’Ž—9ÔЬi`¢Ýåàâ[ »,xyÓc‘³G„÷ø#6Úò‣.‡Xj aŸühn¿°§—ZâÞ'}§9šÕ@ç.ç@_øB=,ö.9ÓJDô?y"K!Ä@þùÇ>þ+¿òk»¨•ÞðFº)EÜ"¯Õê쪛¡ŒBS¡s­(ã8î£Êìà bE‹ƒn6OS¨`»)6ªZ¨ †ºV¹Ý–ó³Í\°`Ì^…<ÛlA–Aqµ›TU)ªÃlfuÞß³¯þÁŸýæï~ôæ­³³å¬ ü©Ÿ|ä±[¿û‡¿û¹'Ÿº¼QT€S­¤fE®Öp¢P4°)%`¨t „„[n)ðj@™«ïÍÒ£ßbÕ¦ýNTÊÙ¦ :sõð˜ÜÌ©3'§9jxAH•^¸»Gʰ/¥ "JEë4ýù'?õCïÿ»EƒðÙæZÍ÷õââÂkæs2Õ½=tó¶£KfvbêÚÙ–Ò%!NX×s¾¢5Ð,»Œ€ûl­aÀÚÔ2S¸­³¼,ôå „IhêE,-Æ]LúÊšK¯I¼Î ÇïùÞãe×·£k¦ñÎ7üâ/ýÚæìv@¢¢ºÝ>¿9½óüRt{c{µßQÎnœk¶˜ ‡á½ï{÷¾úù/åÙ›G{ì‘7½íö —ßüÔç>]c²5ÛSKsmÄØcðÝDŒê%Pó¢ ŽM̧}Ôå|»1Ûkq‹:Ïœ-Èbfƒ¨[…µ6¶¢Å£º;E 3k*™Üx-2•¬¬“Í5FµÄ/Eª™ì{üÍçW—Ï}â3Ÿ½¼"eÈœ«°»Á¤»Õ°GyœP•´¶Az"T‰î8éaBJDdú6;G¶º–Þ„=‹µó "ñiý+‘8C“á"Â]ÙCn!4ä{„Á2›¤ ùï‡W ý8x·EÏ71ïÏnœÅX/÷w£îolÏ©Õã®™‘á<×gïØ‡ÿÓ‡={ä¡×¿î‘Gã¦l"L¶—÷.G•‡n?¼³ÍG–±lFÞòÄënß>ÿ‹¿øóü¡¿û§ŸüÓ‹;ØòчÎÎþçúº¹ûÿþg¿m¶AlæÉ§éj6/"ÁÑAKMƒh}àL%çêE¤¨ ÅÂ(4«]YÚªÍÔa,óÚ*©8HÌnž•W(³[dÿ„ˆØ›Š@³*j„EU Žj¹Úïj)–@9ênšîíä_þ܇¾7ã0hÑ®¿¢š•À÷vÓ®VçÛ[?òxd»LÚ, †UJ¶è’´Š-8 ‚¨ÌÂHdv){‘yDšl )éé÷• #³Ö%H|ä3dÛ·Ì2…/èWÌZ¨ð"-åÖ×b±nan!3Eh^”¤cqY1ïáÂy‡o<üøCoxèÖùåô¾þ¥‹‹ý~¦°\î.M|„J¸¨=üøí?ÿ‹?yç÷¿ûÿøÏ/vúÐÙ#oyô¡G•a³ÿÙ_úÅÝU ¡âr® èF8Õ!nA,<"$D]$f@,– n:Õ¦q3îæ™¢@lJöæ•]õ*2zi$Â}3” @8Œe·ŸØ cFH4`g^Hqóc>üèÛ>ýÙ'«q¶*BU+¬sÕ!yÿPT4ü*; e˜÷~uwÿ¦×¿á=ïxçîê^xÌó î³›‡)€¬Ï¢x0ÀðÔÊ22§…†PÉ.À’ˆM'ô·P"±†S*‰Ô¡eHl^^O©u´Gî¶‚‚•ÓÍV`ÐC œ® ÓÛ«Íý/è ìJ@å¸Á÷ɰæ‰öuø`o¸ÏHX n>ÏVƒ (¥ !líænæ$DK„8aF‡XТ‚–yQêã@aCã[±Þ‚À (gÂcÍ«2DD5¡Qï±y„d›mþ˜+"Öœ¤õ\_MKé£ Fóz áõ ¹OÝ4ôMÝ'a5¬Ù§¤×x´ÈÊËŒ¦£uk^^§ŠpûiÿñO|¼rv˜„“¡˜Ö`¥X8ƒŠÏ•´qU$,”¥Å‹þØþ¤–`Q™æ ˜£Ôªn¤ŒÕªW)e6¥ºÛìEÊùfÜxëßôÓ?ó÷ßòö7›í7Ÿ{!æ¸}v.˜ŠÆFu[t[ÊÕ~ÿ¹Ï©Œå…çîmå¡w¾émïyÇ[ÿ§òÇÞ"úõ_úÒŸäö Õ¡R#¶eÜŠlÇ!SE¥w7Ñ¥!Ûq3”Vª8Œ›ZÍ#ò1[@Çq?͵ZQˆÍ ‰þ¹‡ ä<×2Œ­˜Õjjmš‡»kiºŽjpQ(Ãö»h»ÝÕ;Þúöøþwãé¯V 'Í-¼Ö˜Œaó\óV}?ù4»U3³ý²5 ga'ˆ,S7} vÊQ +“&×®‘$ŽÿA¼XhxL|»]Ïmf©èd§X´¼\K+Óȳø¯ˆƒòOOà-’-}C‰Öù§üGÿù·kç–"üE‹PwûÝlUTŠªˆ¸U-óYTI½°`ÀA*ô‡âÇ!2 g"²Ùr¶:U‘8»¹¹M•Ý4…EݦÉ@ª”"T:€læÒPôcTÂÝ5¨#TÅ,©M…³•á•ý49áÕî=÷Íç)›ì‚ "Bíkfˆ0ójQͬγ{Ìuúìç>s~vþ¦7¼)¤»¢dj,y€K¯¶•”ú<ˆ2¯æãÐ#ÌÊ™L$-E>–ß‚ÐXBxodÑ3Å™à]¹‡•³Cí³¼zذ"áñú7né±ðÉ‹ëé<Ø^dtàM7]ˆ¨›¡lЍäDRµZ­†w˜G…€Š à›Q:“ÌôŽE³ ø›rÏÓL—R´œœ¥(ÈJúçìåï!ì¢ÄXºã5òÂzBriUfO²&˜¹ºžîõÆän5”Þ:¶46Zv¯gSØ£ïåW”J0%>ö±?þù_úó4yujÑà4Oû:'Í[Ò<À=,¢’1 Jh*N1±jÕªþèÿDûib»ÙN2Ã}#Cá°ß»áe¿÷Íæ& õrçeš|ÚÏ6U~ô!ðº7>úŽw¿íßüúÅå•òüᛯÃëÿïþÇŸü/¿÷›óŒž¿éõ¿ý½`ßø÷úŧ¾z¸¥€¨ºobÞ>ž•3 ªÈáÑZhƒ5¹ QmžêŒ4ön"ÉÀIzDQ fkHxSÏÆa`Цىš›5$A•”õ§ÒY|8›4ÂE…"—»ý ÷®JD¤Ö À]Ì(£R pxD4ŒPàˆÙ­jÏ=ù¹7¿ñ=r‹éÕß)õ“3A5£«ßDÙš«ž= €¢ëòÁAXXÿ@S.BoV:ˆ¬=$zW3ÏTóR'|°È­]ã<$¥Ë.ЗVi_`Ù?–ËRÉb™Ð§p?»rïzÅ®¹C'‹ùÕ¶'¯¹±x¥¹†R²UQZÿ|"ZJÇ2 ªŠaPº‡×"qó|P&¤=ß^É÷7äV¯bÓã¤)W¥ªšUìƒÔØýd¤.Q_Ù>ö Ž´¾99QkÍb Ï¢e½QIÙ‰DMì±WY÷Ce…q‚®ÑZªyìì v„úgñ§ú•}óÞ½¹zPƒ°¨B'pÍÌA­ BŠÂÜ¢zxfá5æÙ­fËÑŸü{?RÆ0ìÃmÞL5FÛU-:[­>O1ÏV¤Päj·9–QEvW÷žyö釻uó¡Á0«wîÞ¹¸ØÙ?ñù‘ï×ï|áþôOˆÍv~ê§~èÖ#ü³O}ìÏþø/Ú¼nÞCφó Îÿö»¿ïŸüOü™Ÿù[ïyïë>ñ™¿h,¬@DkZ[««ˆ½ÍÞ;E4¬¥ô2 -N ˜Ç”þ´fÍo-ƒ”M)"âÕVa„…4w!RDÇq a©Åƈ0ªLf5œ*Ž `HTÒƒNBºd[“ML%7Ð,òÉO}æ oxý£>QS.;ÁP«Й%jA[MXhb¼­Lfåõsá!x¨ # acÿ³©×1›t®t–Õ’‘µõσ¥YìÍ‘)_›ŒÅWêÛÜÁ¼áEëUúÒkøå|ì¿Á±ÜüÕýO¦Ø‘kx"²—h!7ƒŒƒlÇÂîäbµÃ¿Ú—õݼ?×cÍg?€äRèbÒØ ôç4,Æ8$™ûF_E´qHÃzwŒŒû}UAÖ>ßJž)_Ê‚I L"Ü%àóô¿÷¿ÿò¯øîþÊ<µ)¹É@&Âná*yÚ¥htG5sÀ µÂCU)J-,ú÷þþ)¤:ÃUʨ#0ìgšq(ãf³½ºØ в exøöÍéò²PUäÖùÙÙÙf7]~ù©/|âÓŸxáî Ï?ÿÍ›·nö3_Ú_ñÆùG½ýs?ÿ‹Ï~ãjà­óR^÷è Žòëÿù·¹a¾ÙÜ”ñá›7þOÿôÜxxºÄ ¿ð«ºÜ»r+Asw-ƒÕIüF€Ø C‰("už<%7#ÆqÌžÕ}6¤²éfÔðYÀì¯ã(*†˜¬Š*ÁAT]Fbö0t± y¾Ž¾ÿ#CìÉ©¢ÔyÒP‘•è½$'$ $f ýÂç¾úþ÷¿³))¥Ь ªYbîJ¤§dD`¹$„@ïVºuJ<‘4i“X¦MQµAÃè¥8Ù8l…û/ in+k?ƒ®˜û'¹Ù‘–·²g0:êzäˆ-Ë ƒ÷=þñ¢}°üãúÎzòîª\’ðõ¯Ë}} žØõYôWÊݺõoÁÓ’Ü:™«ôy,×]ød¥x,¸Mœ +:u„zªùˆå]Î(©)µ¸¤RÇ@ÙÝ»øõßø•ÿô_~#(QužÝƒRJªe0·j> ¥¨è0Öê4ŒZÌ瀥…TÕ¢ºÝŒã0¸ú#øI%ëT°pRnœßÄælsqµKan–”e¢¹;µ:µŒÑ"ݸõÈ퇾ú•§?útq÷ê‘[î/ëÿؽî 77·J‘ryqÉ2<ùůýñÇþ2¦¦“¥ ,n}è¡÷þ·U½úÍßýÍ/}å›á7…ƒÐ‚PEÜlDJà ºJ1c/¨‹PÉ©š‘Ƴ}F U¨Ã0 „@Ö]ª£¨#f¯¡‡‘Ô !ª9!ŠDSüEHx †J–ÞWˆ„4b˜Gjîß2°¡MoâM̕鵀’öÕlpd‰GúbØ£7½lÍdB"A¥Ó"ꢖ›¥”I¢NsG$ý’Õ‚þÏ^cLAG.´\B58sꕇ°•¤ýÏÉ+­,"N2Éëú:Èsßb}¬6›ãÛËþÐÔî¯éXLóú_Þ·ò?IíëËa©ƒÉäŠd¬p}ȯš¹{˶w³¦æk‹< zrO×Ìé–™l}E¤‘‰D„’2È—W¿ü?ô‘?ø}ª*¥˜‘„ö)¬!½ cØïkÅ 9”M®NŒ¢JŠŠ‡ëPô?þAÒË€a=Xçº7›µHtÞCTÑêQjñàf3lŠ ,"¼V=þºÝnž÷v¶ÝRF•'žxó\ñ‰¿xrÔÛ7·oxããïzï{¾ÿ=ïzרúìÓϺ)ïz×Ûžx×ãò‰þÙÇ?#8ÐA‡AÅ#„Úz«[ÔtX‹*af!ZD(ªQ݇2(Ž0ŒZÜg›«’f&¢ãfÜl7àgÛANIeñj †¹rT–Öˆ‘L³&F IžNÔÄ£ºBánªÐ_Ñ›5½­¥8°uýêSO}íé§¿ÿ½ïÝŽE5“fäáYT) "ÔÀÜxÍü [‘M-ŽâÞIǽ@Bؽ~â­1{þ÷h*Su/,!.ß8ö0Wî[*èí%ÀÕ—¯/Âë9ñô×/lÿÍŽµ•Õpw3[+©åx9ódÉè®é=À"Ò‰^€î»ù+t ³°j¨Ñjîâ@*=¨Œ2S!p°Uå‹{Sœ ÷ÕÖ‚‚nÏ<ýå_þð/þáÇþh¤Œœ÷s–vâÄÎgsˆ`ð^9ï§$†´¨Ó\k­Éþ@è\íâr7»SŠþôOýTÙpæžjJâjÚ]Ù^ áõ¬ BªPèg£Þ8wWû0•.ÂyÞÃ|ž§ËË{7oœß¹ûBçaÏÏοÿû¿ßÜßÿw~øßÿþþÁ÷¼ÿï>ñŽw<ú¦7Ý~×»Þúøë^ÿÈC¯ëïxÓ[;;Çןzê£ùØXšf@x¶ T–ahRP…Èìná›±”"C‘j¦$é„cÚY­Çqóº×?Tç+D%êóÍÝÝñlcÕn ãÿåŸü“yº7í¦³óóZ÷ˆ7#È #\Im®$uª¹C,ðqQc6¯–}z¡@QÍÍ9´XaèíÚ ¿ùÍ»w_xá}ßÿN#E‰š@¹äô`Vÿ¥ø:ä‘Ó#’É#}~öøQDL­FÐ[1æ•7Â.îNF×"è’ìÅ1|ßÈÉéׯ€#mm¥´í+ó:Ús¥½ï~ù9ƒã•×K7ð]zLË1}5–-a=a›þr~wù|÷½7…ϯû¢!͇Ï"öpGš~O9uˆÔjÔ;÷ð\Z½84[ûEÐÚÞpÔ&Þ=I"^‚· ˜óúñÿÑÏý‡÷É'?cR"R^î®(ZơڴŸvnNPµXõÙlïÕÅ£ħºßÍûZÍjªˆý¼7¯éšêOðïÛM¸ÐECIÌQQbx^pûÆÙ¸Õ©îƪңîæ*EÎnJüüæùÕnç‚Wû£>üÈ­;—÷ ¼{ïr3lßþ–'nÞ8¶Ê1œp*o|ããï|ç›Þö¶ÇŸxâõoyËÇaÃ{W»ÝÕ¬¾Ùòæ&Î6ræu**£nGÑRFƒÌÄy¶=#C@XH6Ž0«é;ϳMsu¢lTÄ6£0M;·Z«]\\í«‹–ÍP¬îÇÂûÁ»}ó‘ˆxú™¯«l„%^½Š†¢ž:YR’“³e?Ï*Z{d”¢5̳ÚPàÂî’ú(š|x¡¹<óì³_ùÚž¿xÂÏá ¯ÃëSèq„8ÒüüPwEH3è‡ÂE[Ñ5rt·»ÁÙz,7†h°X¾!‹6Ø;T¬I@kÙ.f‡ëbv…EÁË©/µ0±ŽK!"‹àíËY±÷Ëã=¯¡Á•¦ñò¸¿+ÕÝË¡Òô/\¿XLù·&ÆÑh³1­|4½sFÐ]¨æÖÅ3<Âëµ¼0Dn‰š¶¢"o–Z³u•YÛÆ–@ å]•ÓþÞGþà·þÓoýÇoܹc,à R Yw»¨u(nužÍÍ$ÝÚYÍá>ˆr6Ÿëœ]jE˜¦¹Vss%©±?þ÷~.=ôÐX¸šæ«©Î ÐeÄf[¶Ûí –QÌíj·¿ÚÍî^u(Z }ªݺ=¨ÀC€a³¹Îõ‹Ÿÿò»Þù®[·ÏBR_šBˆho0ÒP83¿yóü]ï~â-¿îu¿î­o~û[ßüÖ÷¿ïïüw?ó·>ñú矻3Æ­bç·oÜÞŽ1_î.DË E(§:yÄ ET‡A…> eš÷S­³‡» C)EÌjJ6…ØlÏYÆi¿«óà3Ï>/¾ÿ‡ÿà§Þÿ¾·<ýÌçžþÆ3G£9g à&T¡Ôj9'„áá&˜Ì2°Œ¥Ì¥ EKXˆÕ €"4„‹L„Ý>÷½/éî'>ñåË‹xßû~ÐÍCÅ®.?o=It¶òÍ`¡ëïeJûÜB«|‰N%"Ѥ%ÝÍÓÌ7«6KÙ”àʽM'Ž Ó™Çr|+ð˜Jtöô¢^w}IŸ¨Å-¿¾:øƒ àµ5""¹ÑèOy½Á‡G^^œD';Í·dý—0ÂZÓ€úÑ !mˆìR™-Íݘ·ø "›Þ1‰×¥â2[‚´Ð¿£Bë8) v GáçžüÔø…ŸûÈþÁs÷vêAJÀ橈‚pÚäv9§®h2æa`8Ä¡DxµyªµÿÁ B3\(¢ªzëü¦þôì¡[·”˜ë~Žy²ZÝ…EbDlwW¡̾Ÿd0¡¸ËùæÖù°­Ó¤:Žgg»éj³ÙâÃQ§DøÜsϼëÝïØŒƒ´h$Ç]U77ÀË ¸ûÍ[çozËëßüæÇßüÖG_÷Æãy¼îñ‡äþöÿлà‡ßþ£xûÛÞqû‹_ýô‹;2l *ÂpcãÕfñ—‡Y¡”RDÆaÜ l;HªbÍS ƒTüÖí³ýnÞí̪åégŸþâ—¿øÆ7>Æ‚?ýËO”²aPCBX ŽZ(*F§ %×¾¨ERw\# (… ‡P·›óÂÎÄPƒpõ@ Ð% ~µ»xÇo~ìöM oäíÈ4®t ®ì´EOnBV°$#\ª‡5À,?I[dFZÔl8ÃFuc×D"ÙiyC%ÉËÏ܃ƒ–…îÅÃùn–hœ,H¬*°rÛ×üºÒÃú­ëï®üÀkd,àuZÒBIhþ:oòÛxp<k±Âå/ßø“ãMJ#½OG‹çnž*JðÖ¸5|ÍÏçu:ÂsO±Pª¹geô^‘“¼¦ÎEÏe”-‰µÄ“Ÿùøï~äw¾ðå¯\\NŠ"Á@‡ª–QÝÃ&¿¼Ü[èps¯ƒp@°V£ïç}µ:ÏQk^’¸ËTc6s¯NÑqTýà?üQÃåÕüü•_ÎÄeT‡Œ²-1lÊV¦) χr†ý<¹É€MÌqóæ×¿ùõsÝ]]ÜÝn‡qæy¾u~Ó¢^í/¯¦}u¿w÷Þ§?ýÉ[ݼyó†6Q)Šd»MO‰e–=2Sâ2„ù.¸gÙ]ÖoüæG~ýßþÜ/=ÿ<‹¶Âfö {É¥„Eç%DdªMJv&²½h‚E‘ܧFŠ4Ú\£*/ +ë¼Þî»’¯¯óëiáûæl¯©‘æ³ÖºL€Cá̲€øvµÅ_Ûýã,.^æñ×°RF¤éç†UpŸ­Úc‹ È鎾w°÷w$³$é.MQëpÕÑ$± Ñ3‹¿ Åæù?ÿÆoüÇ_ÿµçîÜÙÍûÙ瀋”íæ\¥ÔyVrðîå®zK¦¸J)¥¨†cžmšf‚^Ãkf)膨 ©CU(EYHþ?þŸÿwàÊYw“Õ`5‰½žñv‰A¹š¦:ã|{öèã7C/®ö»Ý=³]Ql7gEƸÚ]¨»W{ø‘G«ù8êó¡Öýówî\^ÍSå¸ñÐí‡Þô†7þÈþð;Þñ®@2pM¨­·¢zu­—Ó7ÿøãòÅ/|½°œßÞ<óô3‚"R¾ô•/í®Šè¹–a†¢0 €Õ&ódˆæ& 1ˆlu³Îþoÿ×ÿ³”ý¿ø7ÿü…Ëýl¢2DÄfSÆAÔÃÕq÷bö(gçeÐ2í/v—;úèAQ)¥ êÙ¶Lîûê”2H9Ê4טZl¢¤VÄÕÕ~9ß  ¢Aàl3¼ëoùüg?7M¡åÆfØ<òÐc›­>óÜS/ܽC(EE%àEøîw¼å¿ÿàÏl´ÌÓ´Ÿ²žÏˆ”½ðÖt¸Œ¨Š‡/[)¹J tÂAÙ¬7"(­+}  â@!¥7ºP‘€“â$…J!!Áº6máú´uðc¦Û0–Uy¡ËqUAšŒE‡×¬Rv×D&^î‚0þÊqd§Ž‹]s𘤻Pq–ËW^ «y àúo½ÄI¾Ø^zƒY}˜ç†‰7ºŽ§A$ž“‰ïªÿ ËIÈ™ÒÌë%â 2”%¬hõ›í4ºXÃl{ÑÀ¢öçýè~ø?ý§vW“U*peÌneØzE­³2tSî]ìv»I¡îC)ãfw7Ÿç:W›l¹ßÍVM†aHW´pguâìü,¢ Cäïÿ ljH˜ƒç gEw‹Å#®æé²p3›qÌëàÕveà¸Õ'ÞöæÝîjš÷ØŒºÙ ¢zïêêj«É(›iÏ={÷sO~îòêêl{~ûöm€! ©`„…Ôçï=õ/þÕ¿ùøŸ}ñî ñÂ7ï>óôåÕ•~ýë—_ÿÚ½ýn<ÏÆ¡w¯NpÔ­šû4{8aB DDQ)äמúê>ðÃw_xî‹_ø²ê ¡ ƒÖ:×i )Œpº £ž ‹HE)ºeé±Î^³ ªV+CiȨ³Ws7CQ ÒS‘(jµ»/¼*Åsßø†›ß÷žÇ>ù©?Î=µxúyþ›ÏÙ´ÿ¾w¾QNA­WwïÞÊV…Þzlf3G¶æ")ü°¬‰–@P[$‘‚ãΠ&7!éF͘Kß>:ìB ‘`Ùq,IH-ILiòÎlœ£èæ¾mE½¦†}¯Xö—ÊåÞ×4\·þ÷]ü6€ïÊXnþH}ìË//Öúê9ùÖ}ÿy=°{±¸ïfÿ!àKl-égÔZͼšOûyšj8@ O¹ÅÄyÂsD°ˆê^37Ð’e‰Ø¤MGgò4ÞŽ€Ñåû;-#š"\c×å‹Î ”!ï}óîÏýüÏíÞÝ‹ioa±Ýn ñj"J•ì}ÞÍó4Ù £R“Ÿ² ÜçÙ®f»¬Vi1ÍfÕ¨MJm†¦ìžucán•„~à§> )¦ïbVKÁùÙXŠ÷¡u’Ruàl6ÏAdˆjfµ-%Æ*¸qvn†Ý®N“ï÷“È@ÍXPŠl÷{£  ¼¼ºúêSO}õ©¯>tëÖë{¬Új˜Ôgï=óÿý×ÿêÙoàæöužaÜŒQçZJ‡ !âÂVƒ†êN¸¨¨@ÈH¥y):Ž*%¬Öy¾÷ãøÁßÿ½ å‘@7=¼"¡O•Ð4›#ª-âM¢Lœ¾V ÖÖÔ>G¡”­£hO×&t›mТ‰ “áRJˆݼxuyùÄ›ßô¥/™#BE¥™¶õÙo<{q÷Î^÷ºív; øÒ—žüúןV=»ýÐ#aÁPBAÉÄT¤–¦MØê~íIQŠlA·†f.ŠH¹_¤°,]éso@d¢¶o/qø^QšâµÙÁŒ}CY:ÿð½ gyë¯Lí¾˜Ûø­†üÆË×iõ‹¹O‹ŸXÆð¹Žà-GX^¯~_c½ÞH¾›Xan——WÓìµú4Ù<;‚­úŠAó¨ê¨ &´m®{ãƒÂ=ÌmaH‹´6÷’ù2¡ ¡? -Å¢®t(šIÒ–ìZàw~ë·?ñÉO^Ø\gE  ETÆ ³…¡ÎFÌB{;ïý~Úï§jnæâa³Íû™ÔqEHmí înD¨ˆ~àǤh!¬ó<…a”ñ|C.'^L˜ÍÊ 7Šª–àþü¡ˆawµß« 7nܰjܹ¼3c†Hx Ûíý~_½ŠTá¤ê^aƒpT|í©¯<þºÇÎnœA{þâ™ö/ÿù wõÆù£*ƒUžmnÙTvW;˜ ‹ ø7ãv¶ô©5Â%†Rơܸy6íw½_úòWös|á+_GÙˆ Ý{¨„HÑ2¸0TæÙ" ªá1×ÙÅŠrC}äÖͺß; §›yÑ2[\¤Ñ{§A„ÏsÖþja)žÜŸ@UÍŒ-¥Âæ¹¾ëíoþÙç.¦y”QKq¢ºU€øÆ7î<óô ëûÞ]dúýþ×{—õ…î¾ãmoJé*©áhwF½@è½ÿ²é|vÑAÉy›bÍç—¬üJ*[,œº$•2õá¤+¥$­¨ë€6Gf… õÕÛÿËÙae¬¯Gë' ïÉq}ŸX—|'àò+?¾+üÈïúÉDÄ<ÏfÕÝË¿vöO è²Æ+·!§ —šq4˜š‹×¼ÉÖ ÓòÖú±â;~¦É™ž§ùòâÊ,a}¦:š/WT³ÉlЍ–eñ©ÿÛ.B3ï¥b]~;‡  Ñ·Z©M$kˆ¦Øà®„ƒLíPÙ”òçöñ_þð‡®ê>èãP¿ùè£ÎuÚÍ»½]žÝ<Õ©z@«Å c‘­™泟½¸sñøëÃ0èÿúÔ—îazä|¸=r{&=~ë­ïzâí?ðþ÷ܹû4Y¶ÛÛÃp® ·Š­›Þ»»¯“#âì¼”‘2¨gø¾Z0Áw§JîÿË?þÇ_úâ“÷./ÁâQå4U-JâlÜ2ÜæYUI™æ9f EËÙí„}µZ´„ƒ!ª"pD*Dö6OQ©¢ á!*ö]!›éi‹2z È0OÓóóçï]Ì£zxë¾kI-wïÞ{øÑãFÿ£¼¯Ã½{û§Ÿþúßþ¾ï É:H&u+·døt覩‡z®½l2 Ètk­sv3½t ëN"”KU@÷Xç’ì=,TžeòÈä­-û²ì×îÞ¡¨¸wáX¿»¶õ/†½4RüZ¯K/~žçæ,]˜ïRùáî‹eÖå`ýSK½¿ux\Ñ4¯ÃDK ±ì4¸FûN®.WWÓn7W‡ƒf}BVqÑ樎9`Oj¦Gkó”%a~Ô6RH%T¨’ŽÕRÓçvÁ%Ùë︴kp¡ÔúgöÇ¿ð¡_xáâbvh8Hu+ª"aõ*|v·©Úì˜ÌݽºÕ0 Šröº³)¡âÍ¥¥PŠ"hfÁf;Ž›Ñ"&Ÿ¡ÐåÖ­ÇÊŒª¦ó³s‹Ø]înm ÙïjµÙÂÃC‘qÜú¥ãr{cxèöÍÛÊ€ª^Ü›~øáYvî> zïÒ†²ÝT^ÞÙm7ãF¤šÉ½UŠLóÕg>û¹á\}ýÍÿÉ_¾íÍ?øÎ·¿÷懹ýÈoyüæCR·ˆg¾ñÔÝ@ÙXByèÖÞðØùÍñüVyáî7~ÿÍçŸ 2Ü!ᵪÕ(¢5Iyáù;_üÜþþOüè¿ýù_,Û‡"b @p¹»Ú›w£ 7ÃnÚ” »itœ|Ñè)!Ëþ¢Â±”ˆ™áµ…rf6R Š:Å͆QE£–a°n.›bæO=ýµÿÃ?úà½Ý7žûÆU5•!Ùr8K¨þ‡û“÷Ü{ârJ!NOãC¿ú«ÿôŸþÃð«Oüå_\]Ìïz×ß:ÛžÍS¦%ÉrÃ̾zŒdB¶®BB#(M¤¢u,Zq·{™X«E²áH¸³%»ú I¦ÎÛw_ªµˆÕwÑûq¯_¬-ʼn-¸¯)¹ŽB¼Ö"ƒÃI^Åó©µ&‡ÇÌ—I"ÖØ² ¸ƒÔÜ Ü–r¿¾Ïgy×Âlîóêù®4pÜtÙûVÖê–vws3̳ͳyÀbIÀº#ã¶NÛI£ŽVƒDW¥–™h54Yð”BôDXⱫÓnüŸžî ]³ö¥5ƒ òÓŸùìÏÿ‡_|þâž ( ¥ÊÕtqé—"¤‹UPTæê»}½n6cø¼Ÿv,â8GÐg‹Ù‹¨BÀÍŒZ†!¢ŠÄ0P,$|R=ßõþ£ÞnbT"tË8¨¼Á¢ÃòÑ/íùO}ú³¥Èë\ÐtÜɶÅqÂÙ–¢§ðxgƒZ+p!éíƒÑË¿Ú[é@nÄ"„Å=\0£å_}åßßa‰××ß:ñ(Oÿj:¼“/‡åòJŽÔÒÉ®X4,W§·ºíhì³ègyíyÜò¹®>âZ8Ìû§…ðçÄëÿV#€ˆ°ZÍmšçÝn¿ßÏ»©îg›«Õ'ƒ´ˆôàÜÂR ¥·Í6x 8ÙN‡’49aöyU¢)È>ä¹ÁEÿgåoËý²Uç´Ìo—ŠKÂ5 ‚pû‹¿üøø¥_øÆ½ç‚Ž J!ÕÌÊ(µîªMˆ›B0ªS&`P=¬º™#ªù¼Ë"'Í"ûaò†¡ #¨A1…EE†CÔ¼åú3ü!hÄ îÁË{³Êpólx)m²ª2ˆ"¢Nó4U3œm΋ʴßݼqcž&¸œ§}æ0+dî÷{ ª›¨Z ”³Û~žÞðÆ7<ûì7ÎÏn dÜž=ûÜsÏ>ý§?ñäÓ_{ú½ßÿ^UÑ2¤î‚H£¤à’œ‰¿sÿУÛ}ü¿~ó›wàjîÃ0¨w*UZ IAÌÓîÉ/|áÞÝ‹ž‘E”æ¢R౯ÕUæy®u**¥¨yÍôoDåvvÓn?×7Ã8A‡„ óv柳Eafªˆ‚ŠD”up’Ã4G\½ïï¼óü÷?ùÔ—Ÿ¼Ü@UI2™¹©j„˜HB!2WéýÚ׿ù™Ï>œ™K ýÊW¿þÔW¿òæ7¿a;lôì Ðq ñlÓv¯< }† ìPu|Pú<\NVcO?´¼ïj‰)ÿ¬¬ÉQø$g¸þËúw×f2¾nåO Ä}ÿþª[Û z^Ý‘¬B®gÝÿd!,缓Eï¢èe(Û” w[4GW)e}ëÄVŒ¯“ið#ÏÇÌf³i¶iöê¬Fw5§u`'+¹ˆ ™[«üJògœ¢É±cQMU/iw#²À«ùÖ¥½ x1€h}º!¡%å‹Dã!»«{¿ÿû¿ó¿ýâÏ=¿¿D%M0S bªWÓ|a^Íè•»)fÇT=Ü HØ(^àáî„”¡”aáæ“*†QDÝÜDt,›A7uš5}‹P?ðã?”ó›g,îæ‚a6æ¶ÙŽ*6”RT ÈÍÆÏζãfK"²Þ¸ñØcÕ:£ª¡”×=öè0j9Ûܹw7BŠŽáÑMè.‚«é Š;÷. ï{ï{¿ñÜ×ÎÏÏÍë½ýÝ?þØG¿ô¥'#üÆ­³ñLæºi€Í¶sì,.ž¿øòç¾üÉýò¯|öÓ_n#²PWÜœQ80ªœ eÚ_ˆÊÅÕîl<ߎÛÈê-)…ˆZU`fV3¶›ÍPÔìÂ,BD­æ¶Z¨¬QIˆ$Ænnff˜kµ0Jª»ŽE¤Iû‹WÅÁ]uHùÚן~òsOV¯V mºþ P÷ï ;=±9/Ëùö<F@ñàÿŸ½?í–,ÍÎÁçÙ{¿ç˜Ýëî‘Cd*ShB”$”ZH¥’ ¨ªéÕê‚Z«êK}èoõûzt5¢]$1$T’@RÎcÌ™ƒ»ßkvλ‡þð37¿×#4¢é¶ëÆu3»6³³Çg¸½=¾þÚëŸxõì«Ô·w¬êx.¼dK cB9ŒAO˜~Éñã$W2ÎY}kž¿â‚!ï\Ï ¼,îÎqä^%~ý ë"ûýCj]?úd¥6IöW I©p3ÜŸRåéÍñ¥—_zòø&ÓÍÌ ¯ôu=¬k" ©ãòä­×¿ñéâ»ïÝxd?"J¾òõ·¾ñ7¼tõ±O½üôö郫ŸþäÇ2óK_üÊ<ÏfúÚk¯ÝVAÛO½—XQ%¥¦Éê…}KñÅÊŽ‰U)R=á E*EmÎ2€Óýpt ©£·²—®_~rsDqYÂv¦œ**Y*œt^—µ²ˆœÌŠ!DkÝ#9†„ª,fdoÖTæeYÅæ÷¯TdÀ¹¦6E¬Rˆp›´G…§ˆ J*¢@î®÷‡ÛÛè TTVÉã[ÿ¥òÏÿë¿üÓ?øý.#e]B‰Aõ"OÊ$ÂÈPž;mø6¦­SãÎgÍ86U¸SÜÚªŸ³ Ñ\úÌó½^0Ýîy?þž÷À—áéþ?/#û%nä,+t§kù0BÓüËÆå?…Ë9þž½n"8”óÚ†ä<Ï8Á7ï'Ý;­ÛØ}ÎçÐåyÙ᯿¼ç¹3(ÀÃ3r]{%Æf&~ɳoì\nšÌ™¹ÍeNc¨ÑuGÞyH5`ûšŸ¿ÑäÜ ýãgŸ¥ÁÜ–ç÷N€µA¦Y$MYT™´¯|áË?ÿ÷þÞ»7dHÏj¦Yᾪњ¸P`Y®ŒžQ EY"Ea_‡M­$¤¤|0¡N"ÍaÒ@Õ€# À4µy?¹/K?¸*‡óìd;ýÜOüÈõÕôòKÍ̳çñ° ¶Àzè±TµI÷Õ½´ßïÛ²×µ†CTôãõ~ÚÏh²aÁÌt=/ëAÍVÇOžöîû«]_»½•¬Ó¬Ó¾eõÃzØíí5iffÓq=öè%ðÌ¡ã‘ï¿ÿt¹ÉÇß¹}í›ï|ëßε­·õä½[f›tÒ¨ilJ™Ìöû…™ëZC¨‰’é‘ÂVE©j¦*Jh”"ä47J‰¤DÕ#‡…ôd2MS÷È1H…*Ð*%2©¬L”(¤©QR¤@DVB˘„WJ„ù'ÂXˆ¾³VRY%¦:©§‹ŠWF¥W†Áä0*¨áß”Y‡ÃaõuŒ$6;K<ë[o¾9ïçO¿ú1Af±D¡‘$ƹ;h½àfäœù(Czìx…ƒÜAlß @£ Ã¥‘ŸˆÚPÿÄq'^o'¶ñ~t¾Ó<;í_¤qç‘/³Â‡m}ïå$à?bða]Οù¥N⬗¯í|ðÍì|Íe¼¾Ó¢]R»ïá3Žë’Rð¬–x:nˆðèî1¶¯™u{X·½÷Ê”,ö¬åQ=У"‰,zÁ£"‘UQ5@>yÚJ£0ìv7.€ ÜØþ`Onzî#†×yšsqà¶wº‰F`ø9žíðDÈyQišH¹ÿýŸÿù¯ûõ[?8²GÏ,Éý^¢OÔÒÃK|hsˆ4E¦{ò4JEd¦G ×QÊ‹¦I]ív° I( Å&ËŠ5–ÅYÙY˜df¨þÌÏüä4›XŸö¢ÚÖÌeI_¡B›œDzùèGkZ¬d,ý("J¸/ón†bC¯CD^_?Ì\ir8®á…²uñ««9kÕ½ÙôðÑ£ý~¾YnÃÓtÚí÷*,ƃ;_–*hÛ‰L£UÑeõeé¢b‘ÞÃ#}8ž€ HVKMwWûu=·Ê¶Ÿ÷ó´[zwá„ÈÔL–¨™¶Jï!ÒH4³Šr¯T•‡»}SíÝâ~ž§A¼.&¥"}@ \ï§d¬}Þ‘™å^¤ê¸ˆÌHã¤:¿ñÖ›®§¿ðç¿ÿ›¯¦¬‘UÈ ¢€¨¶È*VVžÁÔB Sä,Jæ! À!ôÌw¾ý6Ó?õÉOŠ*DŒúÌœ—›o4e„ÿJEÊ©ȱpk!…¢B¡Ê¼Aä™ö³lãÚ­ZºTv‹êD9{ ð_ÒÞé^8뿳W¸C2z!"èN†ø3‰Âÿé$€óѸƒÄ=×ìªzÿÈßÛ|hf½Œé—¿àâ#;ß3¶ajõî™qReŽ\W?.ë›(ÛðàF\™°’cì3¤{²2ëÂ+€IDAT«|ëNoX Ú,V‡ðPˆ¬îuC‘móÝ>zó¤ãê ÈÓ‚dà6 ‰¤ ëÙq’Z‹Ä²¯ë¯þê¯ü‹õ/ºÀȤÓl­Ñýp<,«!ñv<(ª¶F.«÷HTM¦‘õL|”BIZQÙ¦¹55òjš¯çk¦0iHÈð-DH¶¦{Òz†þÕ¿öSó´§À¬ÌØ×œši“à )3R\§”V¢z¸  ´¹ZÌ¢ˆÌ>8.kHeÍXÃéÕC‹\އõÑÇñàÁÜ>~ï¥G/e”ª\]í³÷'—õ_‡7!¯÷ûG®•²ަMEÚÔ´ÙÒ{ôÁ°ËÕ׈¢)„>U$Idö5^cß0ÚXk65Sµ¦ÖTP Ô$3×µk»j”Ù4Ò…¦ÊrVÔÝ=œ@36 ë´KRr2ñX¢”€¬ž"ê‘©*jJ¤n¢"P*nÇ·ßy—bïU™J°[˺érœ)":„>Ý]„…µ*žgüµõï øÎ;ßýê×¾öéO}êc/?jJÕ±¢ÔQé·ñhÀö]—MµP¸Áš)E‘í4šÕa 4t±10pÛ9²u [¾ûCüËMÆiÒ|·„ü°iÏýèþÃÎô?:ÆÝ®;ë?Ü…Ï_þ#<ãñUŸªjf£=]þˆ/ò·~Þ.\2Èο??á‘m ?üÙcÄqúØT**##Ò3£8¦›•‰Qý,Ö6ôXr˜¹°¨µ…þÊ=Á@ýµ¯œÔú‹ƒ/ÜZýî83/¨â¥¶?5µqŽlª)ݨTÕõxü?ÿ÷ÿù¿ú—©ì™™Ttmi­*³¯Á*Ôðj³Øc؈{E@M èáUPÕ‘#Te?MûyVr7ï¯w¯æë™š}mÓ$TÝ×B!JÙ[|ép¸ùÁüÞ·ß};ÉÛCGÊ+@øôémÆÀÚØÃë+ÕjÚ^zôòÃëùéÍceΦ¹&Ñf¾¬ek¿%«'ÔìD¦‹J1¡²Ü½@e"­™5'ÓêÞ×¹©*šjÉ(D¨îµô ÐfËê‘‹ÁŒDUdR´Ý—uEr¶yj»*‰(UQ)mC´™BUHeQèjª6"ƒàdMÀÝÜV5SÚdjŒÀiÊXRk¬¹éC•Ý}Äè&bfVlžój•mk Ô!§f½÷o|õ«¯~üŸüÄ+TE…äi®2:•ÁZ'EEUžÑ¢2¶›c&›ŽIÙpo2úÔ0$9ùqó7ª›.Ê=ÚF™;1ýÎ?ïw—¡‡÷€Fwî|?£¼ð?âåýû ¾†—sz¾TÙ»¤ÝÝO±Õzœ5!·zÝ<Ÿ1ž{÷™¸‰*äYC‚-†òT!“C~að (þIß<7«–Œ¬Øº‡ÉÌ*JeVõÌò¨HFr¨xž…[6ÀÃ6࢘l[™B*”E¡ ©Ô³Òy”9NÜá·!¤‰˜`pQ›ð +I°¢~ñ—~é×ã_?]Kúº.ƒm/šóLº d]¼YW¯ U ψšÔö67êÖÑE.KÏ@9ª`MgmW»Ù¬ÍmzéÑC=ûÒ¢"”e=ôì^Þ+E¦yÚ#‰(_\î¿ÿÙeY³Ð&³†¬2QF”%Ãv‚Õ»gšYdŽZâ§··Zꮜ«´}YŽÍ¸$2å²F:öûöê«(kïQ%ëê=<.‡oç=¡bºš?$r7ïw» ´ã²d€õHêÕýó?þ¿ü/ÿóýð§ÿàóÿYs›Â;*T ÔÍ P@Tg3T1+z m–¬Ì¸ººº¾šˆî•0Ñe=îö“ûZ¬î®PÙØj‘6¢§I5 ¦÷UXÍd\Ÿéª2„”›Ð=è¾5â!ZPJZûëñØ´EýÔ¢÷4nßx07ª‘Ì‚³F†¼Z•ˆ‘¨ ¢Len@wWU…–—‰‰ ^ù­×¿ùê«/앇Í(„RÇé­ªcŠ£ª¢ª"[p7i“MÖÆ?ÍDUT·Úÿ Vi œ·AB¶‡Úˆgs%œéA÷îOθC¼hìƒ{¡yl î v.£ÿùþ—4´Ëè¿·8?ѸRýÏ<úãCš’;×ܹó8Îî>8Ãw üqqÌÍT‹ƒCµÝ [ù€»« >è)¨úëÄ+ÞÉ•5<í’ÆÖ+Ôà2ý1Jû!í•Å¿ƒ™ˆ,€)"8›èmO“5°=" T–l ÿAo8»mèSY?X›øi æõìªT3UTýÖ¿þ­_ú'¿|¬X#†¨ÉyÒýdÙ×›¬5ªguÏL¬«g–§GÁZÓ©QU)„ +£»ƒ³Ýn¾ÞïvošÚK/=¢éÓÃÍš>Ö±#–Ê=Y²›®Ú»=ú?ÿßþúñ°xyg5Ä{,óܬé4[•—¸ÌœöM k¬­µ,ö^¦û‚¸÷F5¡Í²ÖV»bµ™îGï!%®*æO¼ôê~Ú-Ç›GkW‹º¬ýIc»~¸/Àƒ LS›§òõ(QRl¬ìÓlŸÚµÿôç~âgÿò|òÓí¥WøÎ;oøŠ~tdg%e̵5‰O~òååãím33kóÃt—~¦æ6F¥™»S=Í?)›“(†¸–à½ñ;ø™%NT¸˜aÃÆ^à<ü!j3džQï¿ûþßù;ÿÛÓu9d÷H4e75SfÅía©$,ŽPƒ¨ÈHMijŠŒè˺¤R›$¢X­éÇ=úÄK/!&ÓnzøðzRY—ÃíáV &êîO7R,LѵûHÒûy¯?ñ—àêzoÔÉÄÚšÍW,+XQ*Åi¡S©BÓ,UǾ¬±Ènš…®”tT ‡OËk÷N«Ãêë’D>¸ž)(ÖJz³ìÔÃWRZ9ÖÚól¢ÒZSÞÜߦ¶›lQ¡š©5še¡/þô°<.z!²Ý #Œ d²T­¯ÑËšMÈl6FI’Èî™.¦rµŸ„0rk ÚtXפ*$3Cyô¾U,Å*˜š2‰ÌaëÝ“L€FQQ:Ì{+'µðÍDÚ€[‚‹,õr?ï"ªÄ Bш‡þtRÇ:Jàñ¯}ë­ÊüžO½jÚ¶‘ýøÞ“B˜ÂÍÄ„¶M{ BSͪˆŽ»ë3#øË²»™šDUç©5;!Lǽ7ZÍÆN;ETÞƒub )N c<Ý9¬¿0L×ó—ûÁëÎLãòIï‡ø;ýþ;ŒËey¨ÉS˜ÞÊü´ä oÉÜÜзQ{ž8‘uòÈ-•`YI i “âÐö¤Ì—jôçÑéH ‰!KÁáÈ8¾ÛÃOÛT„Û(õ$Ž^j§æU6IHš òMk6 ŽÎ0M"§¡Ö†lQšQu¬Ö6Ó€*¹}òôïÿüÏùמöÛ¥JæfûI+×ãÒ+¼ÔcÈ É(T(³ÐÄX¬ˆ¾3³MS3¸*öWóÕÃë5\•ÓÔ>x`­-Ër¼=ôuJÏ:®  Övô!…á…ªˆ0“yn¶0—§ïî°¿}’E“艠ipcå.cãZfÖÄKáݯ®w·~{Ì^©m™¬me¦ùγ‘··±>8<]ðð¡kÝÜ<íO>XßýÎî{¾çêúåË»|ͽM{³£´Ùlš+W5ƒ2êøðc»ýËO_úäúö»_yë7¾ñÍo¾ùæ{“¾ôΛá>2½Â©TÓÖd¥½kDº¯½WeO÷Ì5‰**#+«Zk¸¹]ÕšY{8ït}UÍ:ãxÔÆJxàææH×ýd»ëë'‡›ÛH×fž!`V-t¡4ST4+*¢T Ù’hé^ûýuxvkÖ#£@©¦²zD®H–}ϧ?³.KT¼óÝïzæ4iw,Šdä ž% ¦Œ µù_ÿöïó·ÿößü=gÑ)¨Õy‰+¬St]|H€%Ï8ªFõ´ÁϤ°ÖÚ8HrŒ§ãq {]hEŒÛ7i¼“®õýáþ™¡†ç“.Êüósÿyg«|'¾_–´ÿÿ y9»±Ÿ'm8±±ÎÊQ®_¨IlÀùØà*ãÊ“ïfS©*Õi6’<>=Pt÷èÁþjFÕOÞ{òøƒ¾8 „F±2Ïžˆ¡71Ü:1M¶®]ÿÆßú±B”dO‡j3ªGG:2AغÔr(厩í=‚ZÉ.s±å4k#ŠŠXËx%¶J |ÍåàÇÛžQûbS¸onªÓþÊÚ4µÆÀÚ{z{”‡8º("×Büù°|pù¼½¦þÿÒKÝ»`ˆä©DÞB:ªÎD)`HJ]Ø¡Ÿo8=ÊPàÙ8…y"ߎÎ3PP…M”p£­Œm+áe4³Bªh$"‡T2ÈÔAÁ=);W"BmÈZ‘Š'Ö.°I¡jsã®ÊQs`ä»s/ Ó–€nnUDV%×Ûþ ¿ðKß}ò$k%`I…È5Žá¹ö\ÝSŠCß§22Luž'ëÚ3AZfB'Ûíg yjSÛÏû½Íîý¸º¯ý½Âv¸Yno;e‡œ²Ø= L*@÷BªPA8¢—;òØW¯ ”gõ¨LjYÃC!³šŠfäÀìV‚µ¯‡å– ¯}íý¸tÑÖ{DD"Ä"›>ƒHSŠª‰éº.“*«"C•&¢¢ ¨UÌTÕ¼gU™•jVVôìÝçÝ •<Õ1J”³0ªRHÀ# ð\Áº½}<íðöwßyÿý³9=E„*‘C/phUñ4!…g¢„ÃqýÒW¾ô?ð}ûÝ<>µ‹‰Ð3ƒRrst9 6ð45Å ÙLòÜBꀌÞñk××øêŒ"m‹éäæK€3'à²8‡ÔS¿ÿâÀ„Õï¸ßãEÞ¹æ>\õüçç9¿‘;ýÄ×€oþ³I'ˆ³4p¶6¬s]PÏJé»ïýüå9=à‰9U`qe> ˆ*6¼Ðin„áw„m!€mÔ®'?ŒÿU¥©l_ûÁÇhë P™E•ªÊ‰Š’¨Á?§®g{bÙÖÆƒ tjIO'ȃÞÊš2é>T¤iŸÿwð›¿õonú¡&:55ed_ýjñîÈD"euTkíj·ŸÔ½"´Â³Cj¿o›+G¦nXÁ,ÁÚ—¾.ëºzï9^Ê0­±¦mnÖš£ŠT³µ÷¬Ü__YkJÎÖô¯ü_~¬PLM@Hš5‚•))ƹ|Ìd“FO/f"¢¼²–cßï÷%€5)@Eöµ‡ÇÌi6«ì@˜ÊÍír¸ æNU#ý(ßþöck3mÝ?äîáT¹î¯ÛŠõ¸›ì”4cïK轫$…jF ÕÌò ÑKkËÿãSÊ(Ñ9#«P¡zÕêÈÒ&íz¿k@÷“µ÷f "UÃCÙ¥Ò‡e bÏPe3‹%gÓ&–ë®TBÖô´eR)ÌRÑQ! +Ü«JM²²JÝD„ÙW:$ähjEµ-îÚZ!‹ìUža•«…ß}ïý×ßü@tTFÅ63IѬ,2³2¶à:Ü=U­G|ë[ß|õ/¿òðîÀþ6LÛyb~§ ¯ªõþHÏ`ãçBÏ×Ï(‘n«j^§§žùÎN)Ÿ¹õaÅõý {ùšÏïîÜ…œQ°—Ë€s ¿\\>ò‡%|$8õ?›p>’—o8ÍíNUù©`Ñ;s¹»Ø*l«Ý* ÆJàäň‹´Š HØÆ#@¨R”Ôm•E*æ&ÉP0•Â6Ø<®|Ö½¢6}ÿ EF@1ì5*ÏŠçu¡‰Ëá—@n}ï‰çµM´ÀŒg$9Üáþá»ß¿‰•"­Õ~¯„¯Çc_3*<@9½'(f6›ÆºöÈÕÝÓU)L“2«¦…t¤g±zôãr$“ðÝd$zz)¥*2ªj𦡻‚îš…Œ,o»ùÁõ"Â{›šþ7ÿýFÂ{†Ç¤–@“y殀+ å„‹`ò2Dˆ¨)M鞇ÛlºŸÌ*×yoÉîÙ£’”Œè45¶p=°¡¯yûDúQ›Y›‰š£s·Û-Ç›«½\=œo·ûùa_ãæ¦g4ÓÉš˜M‘µ$Ã=#½dlʲÂÔS½”ɽšX³)#»‡MV¨Ž²Ù2‹T–fåâ=+Ej2ÉÌî•·ùf1Udî§¶o“‚Rh*™‘áÍ´÷¬¶›P••k_ƒ”iž§yáæ`¼ÉWE¥t¯ž©fEôî£9®}ª(!¨Ì>®RD¨D_½µ© žÈãêà ˜Ìd&iS+$ÅÉ•µGFee*´Ù”T/ѧÇõ÷ÿàÖåø™ïûÞ¦*›mLŠzîö±—ßï;mÒygËr[(Sì/¡V¥ç1ªo,SÔáp$h¢‡ÛCScVE˜jtGd“LƒTlH`1­pD<¼~ÀL©*XÜ ¥ÝÍ-s˜ªUÏб¬­²fC¯G&ÐÝ[Sjª€ +¦£@šDdÄLmŽ‚ÌÁ äqYEL·ò&Ã}¹ºš»k¨œ‰ Õ+Ç7"Ò„R‘“µªMç“t'*#AªJT@d@2" bOž._øâÔêS¯~LMÈ*é‘ä– 0Äï=úOçŸÅ>Ü›ƒ¿°¸ÄðœSÈå„ýy°&/nÚx;[æØrpX2=Ö/‘þç,uç>/ swÒÌeXùC#ò(ù§¿|ôñü|¹Ÿ ïdÖ!#ÑÚ3Ù8³­G,”ž:†:Îmµ»é䵫çUE±rªÎê ÛÎ* Ø8@ØÖbã×(è!„mðž\x7ÞïØ?]2r“©Û¹˜Ô"¶–…›Ž:Æì93‡²Pf€Ã_>Yeb_ÿÊ×å×þÙ’tUhå²»§PRÉôªÀ6ƒB…”Õ=…ÖÆïbbF3iÖÔš{VzÆZÌb˜1ÝÇ)>Ådm·ÛïæY=|m2”ÞéjRQ„©y_Ö\ô¿ý[?(¬&Ʋue_X"¦²¹œC2Ðl7º½c÷§‡…¶Æˆ  Èá°"H‘‡g AAVUIf]˜Ú¬©LÊ©ÁlSñ¶8o–ãûï>™š>¸žTc¿×¥?¯äÉíãuíŸþÔgß|Óvó·ÎE'¹ºÞ32<¼Ù4O3µVMš/¾x°ÙŠ.MDm]Ý{ªMƒT‘›VƒÌʺž÷C“‡$&Ê‹UnÊy²L Â{0¬I÷ãPdÌ™«{•rRkkæ¬f ÃÍDD¨–-f”‘®Rª§'9*Ûe=ö`œÆ­š’—# %°°kó:P Ä$=²Š&¶yMeo‚1z‰ðˆÌl_ûêko¾ý†6ëÛßøÍßùíö¯óËßøú—¾öÅ/}ý‹ï}ðwß{çéÓ÷ZÃú˜ûÿü3¼Üé.»«qÆÚ'v9U•2êyàù«²€¡Ø|Zø£JÌf ð&GݧEÐF"¡œø¨ûˆ±[^#<6?÷ÁÜÜ“´Öè1/ Û;ŠÓf¸rC&Õ¨1¤€ªÓÈj°ÙÆ3oApÃ<%&™~å—ÿù;ßþNÄŠì*•å‡î½p’:-„È0YIJÒ{ËšF†Ú$*œZkÚPé=–@ŠY •¬ ¶’¬©*­éziÞM:Þcï«wdU¯°©·¹*ªG†/Mmj*×8¬Ob½ò£L{½Ú%çë§»„MWŠéðÒ«ûÛÛõª°<}òÍ7¿ñpÿÊr»ÌvYǾ.ë*%ÚHН±ßOÔ:ô•LÑ6íÛ“Ãê…ÙZ= $U­µiÎŒu]mšz†©VÖÜ$ÇãHaU­ÍJTDe MÝ‹feÀ“~t¯˜oŽ]ZÊmïC„§Ñ*«LK"<šL1ìÚ´F_}¦Ö2{D ÐÈ„€PaF(M¡¨ÌÌ^LˆÂ¤ìÓŸüøûO¾óôö)C WD2#™Ë²˜YDªhf5S‘^¬Øä¢ÆÞLIÍ1WAV¦Ty¢G §¯½ñøË¯ýz¸C&ÑùÍïÜ*C•þo¿Ã‚J=z¸ÿ¡ï{õ'þâþ¹Ïþ¹Ö&"+µ³”ã Cáe¬¼,ÌÏaô ÇÄóró8ü—ÉcDÿPJ„—~évçoÿ4£˜3Сÿ¹ñüý/£äŸ&Â⢠y!þõ?ËåA¾Ÿyç½eÆ(pä÷|¾Ó¿…ÂÌa~|c#âÙ!Ž¥ä&èLtB(L"6ñçÌBB ` l•êøªÜQ$=—:ÔII›ÍK^ÿ^1R ’9•ÛÏ:‚Ó.Å,ÿ(Aù<…8ˆ³„Ùó©èÅ!%üqCêÔ‡ÅÜÿD.—Ÿïý¡ÙVëo‡3Ç-öîwß Ïeõžu\\LEAKQ'=sµ&“pRW¯ÕĦ‰ÐˆìT:JÈF1”–hÓ%AUõ¢GnÐpž&÷¨¹µÔ&). 3QÕ„Ó¢rU #ÕvµöP›Æ^ÕPU2¥g• a"Åñ) ¬ifŽ™†GöʳÅůý¯üìO=þà½'<Ÿ vÏ!iº ñ¨6³“ 8¬“ (¡PfˆJ@èUY~ pE ºs|ë ºçØY ƒU íß¼~á«ßøü—¿ðÞo¿ò±‡ûýƒ ž9”¸ˆÂuâë^†ÎKÖ3VÑÅð÷#ªÈ;¿ãù¢û|Íe“1v ¬ÐYtg>ù°ØwžkÝYrüÉ"õƒs¾òœ]þÌÀG4%wn:'€:kœŸ”sNCžMy™g%5ÙÄø‡ïÒ˜Åæ»5ä@2+0æEà™C5lú¶ÅÀì(€‚ ]ýdUEm”9aÆÃŒóîœò¥w̦„‚â’ÎÑ[ ê¤"l>‚bæ×¿ö•Ÿÿ?Ÿª7ëñf] âkïd©ï=Ñ4‘Ù¦Ùf3‰è½‰h© '±òM( ­ ‘›f\%3RYÍšª ÅÓ{v ìžëê·‡EDwÆI•¨„—$ *‰‚„þÕÿî'Ò%SK옱.áTª‘šCàu¬üÖÞ÷ûÝÇ^þ„„N~|2ïµ°f-­I3¥-“A-¥ zôe _½‹qš¥MJÐ@¥fêa]û¦IÉZ i¢(]ŽkõT)ÞƒiµJïµvïK¾~ìå—=¼öðŽ€jáp5Š‘ÎR-™Ô Qªšå”!»Vs]$eõšLÕX÷.boCª2ÍÖ¦¦Ô~åU=½d ÷Ít†pØCHŠÉ,mò¡äŠZk³é4µ¹ww–¨(œš SQÅÉikœò Á(!Hæ¾ü•7¾ó.Û¾ÍWÃ"Tó4UÅhˆÇÎwÌ7§iþ¡üÁ·ÞzËlZñÒ<í«$3ø|=~gl‚ç«þK}à³ÌÀ Oâ —h"<Ÿ9polr§8ýãÎèÏ‚ø÷u„.”û}Ì ÆaÎý×pyëýè#¦»Üëý,çlw§Ã;ÿžÏ]¶[6½ 1¸ƒëM]g°sENÎÕ:v>cú’MN#`ŸðÅšˆ‰ŠÓ‘D„£SÔHŽ‚,ãiÝ{R ÅCT§í.€Íúüä%6¨bA%Œ$‡ÂÒ×ßýßú_ÿîÿ=‘=â°vÓ¶Ÿw}]¼\…fD_WHXÓQ¶+5cIDT/• V¢¯}ñ%‘9¼`Ý×dd…jS¦B“fS£±*Ó‡Ã8Åéè!=-D %$µôÒ‚ÄéKZúÿê_P"Bš×`/¤'0ƒE–~lÓ䞎Úï§Éòú¡=øØþý§ï-K.‡æÝv; ¦–“Xe2Aí¸v5$3›÷˜æ ZëZËZmn3$³ÐvmºbÈŒÝnrw_c×ö×ón=,ë’ËZ7‡¾¬´W[—P›ºƒI d,cZ¦Ž€¥HxFU%Úªûë}p)õ!ªjÖfBM'kÖL»]«tJE Ñ!JÏô¥„D­ªŠŒØª‚EÅ3©*VA›-*AD)Ì4!ÁJ…•!@3!+‘dɘ]RX $S¥*Z•På¥Ý•U…w+VUç0Ɖå‡èûþÜ÷|úí×^wT´ ƒþ*i]FÜf!+ccÚ]¼Æ·<óáõn7·¾öܨ˜Q„äµ7ÞùÆ7¿eZ¯¼üHÕ>"ºƒõÙú[_XãóÂíë2à"܉³—þÈ àrˆt‡Ò|¾Ü±NÄ‹2Í%@ß ëç×9d–Ï Óó§.ý±^Ï ‡û/üÈÆ‡rˆ>Ð.\ÀžÉ‚ŽÛG/ƒ »éŽœd5GÀ p¹é q“©îE*‡]o©ÚØ^£}ȧsHà tP…lÌe•RƒÄ¾‰w N°Ó±@NYJ’â Ä ÊÄ3r¹†É] äƒ÷Þý…ÿýüê¿øÕ%¢Dº‡ }\õ¸˜æ}•FbÀ3Jh=cźĚUAQB ¨qžgTUî4MBaQiQ¯ÉöfMŒáîku(X@šr21…šCWJÑq#ES$QПù?LÕ‚ù!'îòÈîé‰Õy<†ŠíÛn]û±òÐWßÍ%hIÑÇ×ã —‰¹¯e6UBT––`ôLß$A¤Ó¨;“I¸k­Í )ï)nÍ&• Ö˜žem'%Õ}*ÝOWËkÄa]—(¥îZÛOÖ&.~œç¦Â¾çfÃkÍî•¢(zi/óÒ¡¸íK[Q bMÐPDù FgÎJ2œQ’=ºª¢r-d›DÔáBUH“%ºÄ&º÷ ßæ‹Âî^§’‡$ÄŽà4Ö[/v_D e€ŠhZk=´ ¥Ùu]Ú4 ÉL÷ÕÓ7VfVl‚ãxëí·>õñ—ú§þÒ—¿ú%O¨¶Ó¾,ªHqwUŒô¨p ™F®WŠÌué^¦f¤ˆvïPÒH~þK_~ÿý÷^ýÄÇ÷ûýýp|î/‹÷&ÜK‘<^8G‹ÄþèÀ‡Õï—Õ=.¬ð|áÿÂǼ¿I¾¼çˆ9ÚK Ôýèÿï=œ5>ñ|b»óúï|FÃõålÿrÇ!àB7ô¹[Í1ŠóWòÎáÄáÚv›rÔÅ0,ÚîF©˜e¡ð¹YâˆBrâ¶0Ò* …’¤0ÊÿÀ¦—9<å9ä…铴ѳe44ÀØ+¼ùÆk÷ûü޿܃ªfc tïžY Š¶¬ôX»¯MÍT‹ɵ×Þ+ѬÍ:W¯ªÁ4OÚ,¼2©ŠŒ…ÈÝ|…´uÐL›M“}]ªAfn[¹êªh³”tÐ¥RPRkŒ¼HêÏüÍÏ©©RýX~4M Èâ\]z§–N*ÔBc™ Q=š^¡xûdEM¨ P÷5‡«X›tš8Û¤!蔲L©UÒ#ç«G½w5™&E¹H •®ž%k4%Ä=k¨¶½òò²K¹¬ 2öóä¾î¯vá«ûÚ)Å”†©‘`í÷³  âå9dwŠMÛ4iäJ†)M öè‹n+–„ ÒÁôŒBÌbR5)'•¡Ý™’²“”RC?uÀÍÝ«x<U¥™¸ŽP#â!2ƒ2¼*©?ù×~ ¯aM!~ U0ö×­”OŽËñ¦¯K7ÓBdAMH6Ó¦b&™‘ÂùÁƒ=Y½w›šÊ ¶LY<¹Y=z¨&O+¤ÍóƒãKO*Ä\gôµ›°¯ýðØÙu?½Ô»“ññW^™Ì96ç*iRm§AO†©…,º'•@š©ikf´ ,¨¥±6&ï}Hâ4z¡ ² W•S]4§‰Ã«°:™™ؤe…±†gÂp iÌrÏ@–RšÍà±wÔÐ#H5a¹$„JU_Ó³ÒÝY$”&=2U´¡Qµ { (¥DÙ˜ˆ"!,µæYÝ}j&¬Šlb@ Ù—õ­7ßüá?ÿC_ýÚ× š%'ŠWÐÔ##%#oDÆ6ƒqOl 8ÊÞ>aD<‹€‰Ìmšiåé%eí[¯½öþï}üc×Ê$D³X5œCjè³lPŒÓnðÓ‹ty>çAÐéž[  xALpÒ¬–˸|É;ûä€Ë€Xõ¡”…s,¾_G_ÆÓI/SŬã^š(\>Ý—ÄÍÜ#?zpÿëN¸Ì”—³»ó–âÎ5ç† ÏM~ÎýÎöAÛµ¬‚?KÞÅÄævŠÖ¨*Á&Äzðò÷öÕ7ß| ”!=í‘¢JJz*%@ªˆj†DÐh°‡5‘²1åYJ”=ú`ÂoÅY–ÈüÎw>ø½/|ñß~þ÷ßxçO|ü•]k*ƒaƒ²òœbe^†¶‹*û¤âs,=ýùÝ}ïe‹ÂÿO¼8ÿùÙZàRÿà…Ñÿòçå¼è2gŒ5ïXçã2:×ÅjántÚE_vÏV”«Ë‡zQ¦|–9.W—»Üó“´ÏÉð}T­Ïå‰Ó󢊙#ó¼ 8…jlz?( OŽ_Û³œÖà§Ü¿m‰9fñc ÙDÎkä‰-è×™RÀA@ÕÀÕYq¨ðŒ‘j""Q±‰·9 6dªp³Àf à k •¸yòî¯ÿú¯ýâ?þÅÛµƒúp¿kC®ÑtõÕ3ÆSxôBE^¹»ÚK“ô0³>dI[SJd-ÉUµL5 OÖ%¢o‘]!V`¨"³ç0Ë, •¥P©¹ Å”s];Yz3s¨L‚È,æúÿ›²©ùêDXŽÇfsx´fmmiUØd‹{eIr7YÛkÉúÒK”šòº}º¼÷ÞM®jè+‹¬(ÁíºVõ‡Z›;eQ 5=ׯV`ÒY𕬠ný¶*´B¢—ÈÕû,Ož¬ŠG{ÛQ+é~<¬»iž”N¤(z_Y‘±¿Úu÷eÍÈŠ6·ÝU£úf5ÊžU¢Vå'Ÿ B”„ ÑfEF'D¡ÂfM=½ jSx¤w";ÔªYE5³¦z\"*,²n}u¢Í{ûÑ+@JDo&¶õû(@›ŠI?fS#Çdm˜ L°gQ­`E„ç™q+¤¢ÄF»¤Mõéã÷ÿêÏþôoþöoI› ã¬% ÊÜ€¨ Q* À‡J5ĆÅ*5¦ÂÈè&b*ÆÁ÷Fh·Îc—ï¾ûô+_þê·¾õõo¼þµ×ß~ó°UûA6ð q·Åñ‹2‹KwŠîS|¶z½ éãŽ#ÐñlÛͻß?ÙàN”ÿíÏû™æN~a®Â:ÁiFÌ=ßtçßÉ‚—ÅøýÇ¿¿¨ø°wtçñÏ~.ùñ¬!;§„á‹ñsHåŒ.ît‡á†“9*ϯ&7Œ Faž• l¡ž$·iOQr«(.^VATN+ÿ“w 7 9}»oÔ&'±‘³2Òk³t„!ù3ügb”8Ã) CÔ:åùÇçæýøÖÛ_ý¥_þÅßùÝÏ/Õ65¦¡«R={†7¬«è±Š ‰NlR‚Ê©™5óîËq`?Ïàæn¯J¡«¥j€iT éGž„NªMÑšì¬@(ÀBxEUjÊD›Ä&nÆ!Ü<ËT¨ˆH/TIyù¼zÏêÊœôÇæsKïùpX¦ ‰\{,Yhó·ß{OT÷óž@xxæH(ÁÞ•~xøÒu¢"m÷ÚßÎ=×2$ÙfYâ¨÷êá^~8µ¹"‹lÖ Œ,3i;³«]z¯Ja,‚Þ3:\ï+—Ãá†Èv¨>Ùîö&» КÙq¹‘V¢…ò@ïÕoŽO¡ÆjÇÃŽ =<3öóÄ’J! ’ÍF›#h²PQRdŠ¡5°‘ˆX×U£]ÈLHquWÑ1ŸY*l*¢*E ¼’1°L³Nè~5ï*kõ^ ¯t«D*56“Æ“ÛÞ€µ‰@@ÕŽX#D´ª¢w hz^Í{ >芃^ï™B‘¾,ÇúÏ~õ[_[Y -ÕN¦¢cï_97ËŒa™¨ÄÈ2šcB ˜1™ž^qò5L˜@!^,¨NžúîããÛß=¼öÖã/~õµ/|é+ßüÖkMÍÓ3s’á­Ê˜L›ITlš*L¡ s#è‰ÞÜô/å›××W/¿ü@åY ºI'¨.+߱㩮TyRÃ6ýޝ‹ççÜðÉà2Ï |îñûOÍ»íN¹}ç.¯¹¼Ã¹º¿3¾Ç=²^Ô7Œ‡:Cø¸{ïýüIDæ©âßêýlu ÙYc ‡Êb±‘›iŒf'öÏó³ûDžVìÒmš+ ¼¢Û)ª"‘L0‘)¢l'Oo¿ýíoú{>uuun“Wçs$X`3 <÷Ÿ›Å_‚è‡KåqÍ Ò_ à|¹ßϳŽbî ýï((àba{ý—ú—Éàà üNî<Â9µDD3Ïæï&|®8+ñg¢£²h‘åÛïc4æ¨Â*çñ…cLTØøS¹Í†FÉV'–À¸ÃsãçýÄ…>km4*tüa c¯!T›ecý”ˆPvd' q©@…ª'g±<5£Cšt]nï÷~÷þâ?øæ›ï|pXŽá»ë¨T$2»w2›²$DÙhpYzƦ’* `=®ÙãxX2û4)™½Ða I– %;+  Cb¹$DJŽ­; 1:ü–JÚ„ LÙT6›HRTtØ*&ÍVA©LdEx²ô/üìˆjF-‹Sæ‚b¦“ÚÍ“'ì*cYܦ-EêñÐIU5¡Ž ŸUs›È²V/¿²{ôpzø`ÙNaã ™uôõ¶¯esÛ³d=úã–õýÈJ›w{˜ÕøÐ"ÝëzžMäæfíëÞ„óã–eÉv”>ϲ›ˆtf,½"£ÙSU†h±©PP™Q”ôųRMš*Ð(ëÙZlY,Š’…΢„ðØ»Jó虫)PEÕĈ”šB -Z¥¬¥^"…±­Jr ˆô¨Í´ÇðyÌ¢²A$àMMKª¯f#­$ÅK«W% "„0£<š&’*‘1¨s!öÄJ0l•Be…‰˜lUgD†H *MDYEr˜ï}‚Añ“Þ£À*ÉA|)k¦&]U£22óô'™}2ÉÊ RYrssû…/i9>óÙÏT ®4Nýg±k”—Š;—¡öŒY¦öÏ'gõ¼­ù‹Kø?AÜÇó%ùe”a~Qûß-ÕOÅë‰úôŒi•çǼ¼sÝ? Ýy/ìN÷aøPxG†*R•cŒ¿)yŽû‚Èô‘Û4?³PÏJûªÊ‚ã<©6/­gcy^ø Í‚¬ªØÔ˜@N/èî‡Åaó²ý{h2Ÿ•ª€<Çî:³jØ9ªdlÚÎPÒ”*"Bå3Ò­öÞšøzòÁã¿÷ÿüù_ÿW¿ñÁÓñ‡G\_]5Õ~X†ó@”›R`$ l™ˆ1ÍÚÌ'çyŠôc?Df÷T³yš£³{§„hy„§$µBæP•.’6™Eƒ\Iá郧֨ͬXP˜Šª–WfE¦¨V"‹½€X+K"ƒ4 wПü™ž“ÒDÆ®¼"#CLK É(“{ 6ºš¨½,ÈbU–WeU¨Ž(ÈD€ÕZʺô©Í‘EØ$¢³Ò<õpÌu|¥ÀDeÚ·˜óñrì©UMÐ<Ž™«E¤úJQEÑWº§Š˜î3äÉÓ§‡ƒW ´®®÷U8ׂf±DzuJZƒ)£R¢â="S͆ԔŠL —zY¹d›¥Ø)P6)έe¤¨ ÚrÓE´œdJ†4›æÖr­¦;à$7ÇÚ¤ê+¢„=BÀÉšjfv„°4°D+½[“ÍV{kÃC);SÔŠŠm©¦ ŠÉ Bµ›Là"‘Ý0¡ y¼ôÈHB½ŠbÈc¦Ef¡çy™:àšØŒßA&¥ÉŒêCW(€D1 šÒˆ¦âáµé}AŠ•`¡YókR©Ê(ñjo¿ûíÖÚ§_}U6q°ç&ì#nŸÂz]ÄýÓ²¯.ðÏ_¦?Ô»ø{¹lDFL?‡×ûEúÜ0øS—‡q—ÁDqd‡ ùìmɉ%W—ØÙûKÝ˧»Ü4œï–9ä ¥Š5´Î6Œ`lÅõåkËÊ*ÏŒ¬^Õ#Øvç§«oƒäg±FFÏM6g˜5fÔP>A²„o²’•›ˆ?ðÌ/øŒˆÅàâtÀ@È9IÕ€ñ†:Œ¹?H È2pRUªP)§wͨ³LåöÉí?ø…ø…¯|­¨H«DS›Tr]Y>MšEW-aTä€d®ž‘Y !‹@fo—Jª¶›Zà½<°‚é•á%`å u™8@6Y«hŠPJd,e"ǘTI0ÕØÌL´2•0¢Q´É,rÉNf³lìÂÔ*ñ ŠŒƒ_JýñŸý/”PÖd6·¦*° F¡š6[<º£÷P‘É&SKÏ©M*kDÖÐm-¨‰y_k(h(˜ªÒÔ2kñ¾.é+­í é±N¶‹>¹Ô) rXÂdºnû¦Öc]sݦ“²…Îêžî«6ñáì®íÝoßú:g¶åxœæ6Ï»Þ×j8fGJUœo¤(DX¤Š(YA•™N°©©Ên§Ü–éE–ŠRU@®T­´ô2…oç}¸¾Ú½ô±—>öÁ{ïå¨(©(:9@ô$m’ ŸšMb•+Ñ…%Ôb0³QPÕÑÑ*ÊU A IJxa@$H oKk¢±*‘•«2ÆýƒHJxÎ6—d7ǃÇŠ ß\!ª ‘iªc «¦D©FÉ.Zª4f.ƒq£ 2ÌdͨDø8Y£TÉ ‰HR<˜©“d%}ëÍ·–ã᳟ýÌeø¿ˆ×u°ÏwÎYá2(ß)Šñ|ù(ÿ=Žƒîhp¯9x~Fÿ|…2l¸É‘„Ç«}&Ÿpn#ÎËð; æòõ\<ѳÿ2OÚ:­I6 dJj+þGÍ^™Už#ÜË(ä‡ ùNYµ ujðÒ‡ŠËøŒ²”C3+·2;U,Tä6Ø«RPAìßSqR =:së0*Çk-T @‘‘·U 9ªù*£›çŒžÀjÅá¶=WI·zTVþïÿèÿö¿ý·ÚT&5· Hòêú™ÇåÖš ŠQ} GÑ{GBfjêÇ®Pkººk³Dz:P•=ÊAvï‘.VjPA†C‡,Ù­©Dx@(T­¦0ÝTä3¡¢cë‰ä–G« P„T§°eò´®û„–*²\ô/ÿpXFˆÙ¤ª³š„X}q§Ù4X{%LTªTÚd7O±z†Dh‡tT¯L7)4uÐ¥AoRb’ºVëPEÏcäz–÷™ÕÔfS_×!g'ʬHϹMûI’ÎÆÕ—FY¿ºÞÏ{>z¹‰áƒU6Ï“§O³N;[ýF•©%­µ´U)•*d6•kšÑL3fmn³£#V<¼¾ŽZB½Ìi©dì'…‰­ÒäFqBT–ÆüÀgÿ§¿õ·>ó½ßóûð{> 8I’`Rlã¦B“%ŽÅRÕ*ôŠ”ŠR™B*ªŒe”±hÅvJ ĆRÞâÅ~náëÚ¤á‘%"*Ã%=%"Ò»gT“fB"Tpñ0“‰lf "bnM k÷N˜ÚØ%Qjœü¤B…A ‡ÞVkEGÑH¥ÊôpmÖX¨DxV‘%|ðþºÞ~æ{_=U»g¼Í}\M&B/€ºŸâÆ–øC+÷ûW~Ddáïãr–ð¼3ô¿÷Ç}Eô4Bfœo©áP>4œž½‡1|;‘žÏ”ÙÓ°ˆ”<1'.'矧ô'Öô‰²‹M1Ò#³Jt€ #ÀŽiOU¢"3‹‰Í8¶Š1ö¿câ’9À yÊz0Ž*Šô¯< 0œÇ\El–¿Ë2¸T¥ Ö0F’¡ º5@}Ä0äF–á™IŽ ¼,*˜`lÍ6Àó»2¶Ž¢ )¨·^{ãþÂ? VYÝL³¼PfMU–õpsû¾)+0F¡‘Œ`«L)}]×̬SJ5@jEw8*%KµhQQ+% TÊXWkšB&‰¥#>FB%H ÒMQ‘ѤŊrc´è›`@¦j¢ÂJ¥Q,Íl©?ö_ý#ô#IçqYj2)hM•Ì’e¡Ô853•µ¯CÒE‰¹5¢¬‰¯¯'2dtêÕ¸D¤0ªl6Ó®ªíPXTK§‰BÏÛ°1‰tøt5¥U_—Ê4iÝã°.‘™¢Ùfú¼×ãz3ï5óv·×«ýîÑÃG=züø½Â:ϸj-Ý+«WöªJEÕV¹I!'Hˆ‰M5¡”*‰¡ÏϪXý@ƒæÝ”Õ›R%§&ÆÚ ê$cŸ™!Êï|÷Í/}õw¿÷>½»Úýk_ŸlbÅPð]¡l @Y¤ç.Q¥ªYe¦ÛØ7K(××{ ×uQ5¡)&)cÖ®©){yVðñ—N =ŽÐm.‘, 1|±þbžÛà7Vv;«tdëÉknM T!&&ͪJ€¨DHPeõrOBÌLµ¹#¢²i¿("à$V&ØM¶›¦ R¤Èržg ÍL¥U’•¤xúw¿ûÝ¿ôò+/¿r®÷/ú—±û¤òù¶á¹MÀšñý¿ý£ø÷ëýˡ‰]_d‚sùÿ X9˜a‹2æ'´ë¦ ´Á`žõ —In‹üUÏÄê«j·9ëF@© oÞØ0üCCŸ5tFÏk¨ëƒâƒ"RxѹmèÌ3À©6 gä ì>G_û¤Ëœ½qzk£ dÖPáøÝʞ͎1«P<1‘@m W:1G¶›±¤œØ!5òÄ8Ì…¡ QUBJH™úëÿò7^{û5hªA¨±VD¬ÙÄ€l×ÓÒÓE ,¨hTöi¦¬œLÈÈìD|jIvèštTµÉDQ‘­E‚°ºiapZ4U33‚;}«)´¢%µ¤Uhu­U†\`£MD‘YìÚdnˆ`ºxJéç~âÇ„ ÉDí^•˜çÕ–Õ#V zï£1XÙíw‡Ãq8˜“Ø?h6eä‘H°„辊Ê~jY9¨$Á %'ÓIm­›ÄãÒ£¸¬ìNãÄ”õé**"º,k¢:òèKÁ]ElÒžCê(m÷#¥GÜF¬¯¼üRïÇÛÃí4_íç}öʰE’¨ýlj˜÷Vøëß¼Ü]=ˆL@!•Ó”ÓÞ©Ö¢cÂŽiB¡Â+ÒÒ&­è±5¥MJ$‡b¬ð¦ÿÝ>ÿÍ×_oÓ<ôG7]©F…Æ eÂ’¬rU”tkåJ;‘ $Ó=ENp¢ø}úÓûñ¿øýï½ûާGyUÐÇãñ¶T{!KTÛÐä²D†þ[T¡Y[—5¥‰HqÆ4MK_{¦ŠšhmKa’Å­@S¥†Ó;Pª¦ÛØWT ZgM"S•Q•RmÒi2!ÔFsí"):¤I| чáéPŸøàý÷~ðû¾¯5ã‰Ë|Öƒ8•´ÏÄg><‚Ÿ áºÜ œçà :÷³Âyb~){yGóWóüç9ý "žmzMùœµžõ;±q-œð3‘§p¿ýgB §#_‰/"·AMž›F&ë±F¶Þ"þTˆÊØz‹ÓHdI!"Oã–óœjŒ¶/0B§ÞâDÃâpa”„l« QЬ¯:½äÂ0Ú=¿³g;é:Éîoî,£Eo—§ôQÌ$ `å–óÆËÏFrì6_ìô+"³×iA=\È !åï~çí_ÿ×ÿbÉV!„ed3Qå².·ývåÚ¬14½‘UŠáö’Ùæ ‚R#%KHUN“‘å¢&ªãÄá¶°Žá•8TÆîz¼Á1î2#•KVq˜Û” dèâ1ªÖdOFi‰’‚j° TBˆ1·`•~î§~jh™J±¦Æ6¡ØÍjR¨Úº&JMMHUY½zÁÙÔ2Ú$Ò3(jm^{4ç=o×§)êó´0}PncíjzôcïA–™ˆ È A¨*PóÕdjÃ!@Å,Ë#ª/EÔõ•’y<ÞúÚwMÅè(‘¸yúþõõuÁž<îËñ°Ûž.•:¥$Òa¡ZWƒíö¨•ÖÒHÊENdš »fÕ󥇄‰©Öƒ«y× 9ŠcErß&S+VfêàÑŠ’Úl7ëÛšŽ)@1 Å*RÆÎ/jè¢ÔÐÕ‰ŠQQH•b,}-¡hiƒnnnÞxýíîÕK¼C9°Ä(Š‚mŽÀ!£ZR¡ ª@ÛdhÆâɤxE(¬‘1Í@\ˆ@™èÝØpJeQôÊ R ÀS²ØÍ¶Ÿ')DâöØÃ=+¬5õž1¨c¢E.žß}ïÏÿàlÈŸaö\—3ü@bî§€sÀ½\ÜþçßïôwÊü;X;%ÿBñ®¨òyu‚Q&6Ô#N€ô‹$ÁÜ¢ÛAÊ™¿zÃw«ëDz5O0Ðý:rã4iñ1ÁOTÒGi_ÛJv,O¯vL€F­BEŽÑñèY¶–eXXà:j|Ù ægáý³4ç3‰gG8s£‰Q“k ÷àæì‚òwPƒŸMÒ'‡±M5瀿M•¶\5:žñf*G.8‘ÎE #² ‚7ßøæ¯ýóöÁãŽ}Ì3`ºf,k_ûêÝÇØ‰T_—M"5cp”UEQè¢ ¦ªªbX’0S•Œ­fØd ½"m4æLD‘ÑcD‡E NÞÈ"¦(aŠfcªºÕÊr•j ¨@{£{R3²”E"dãrˆþÌÏüW»iVJS˜MÛº¬P^í§—^‡w1%„Ëq-‡ikó®5eE›`áYí¥Ó<õÝ,#áBѬDMÊ«÷¿ûäj¿«êY ‚Ù+zFlßOB4UûnŸ6%µÒK¤T4Pw{#Ktïsg³ŠòÇ··0¯LUz÷d`X ÎíŠ)Ž0Ñèk!E+2¦]+‰µŽhe³ eæ2IíM\û-èÚÆ&êTY‘b2M3뢭í樈ð¡ÄSQÙS1G¦²M;¦„£’MÛh`‡[´JSE4µJ"“BŠFâ¤ö\"20gŤ¤êðx+‚;kš…AU¯J‘î—*ôÚÐD²EiTÕ$ÒÁ6pÕBU÷lÉ ^™U1¢Pä¶­4m¨ 1‹ªHQã[R‡BêõnÚ5SAfݽ*©lÍZ¤+`Ô†›¾=>ö¾|æÕW…Ì î†æç€@ÜàK2\þ¼#}|ghsÑg¼Cùˆ/è_þóþ5Ä ¸rºSÏ\±˜9˜´¹Í‡°­÷N;’¬çP=5zϪ¡ž9h£«“Éô-P0ü x_¬ÊÜ~`Áæ=­ ”œÁ"ÇjödÔÔÀ¼h=ÐDÛë|ñܱÜáÍc½NEC+jœ;Yw€[ý?|ãÁ‘î6@)u2mgÌùÖ!)hŒã/Çæy0£B¡OÞïÿò/½õöÛOoo¢ª‰6À6ÇìÑRôÌª¶­sÖÞ—Þ‡¿‡‰)…`x¯ZM“’ #|+bLŠ%S6¸êR+µÅbÄÐQ´‰Ê…‘ÿ•Šœ ’ªÓ’ÈÎ m DVI$z²TL9© ¢È¡Á"Õ ú³?û_6 •¢¢›–0Øíííò4_Þ¿Œ TU {¸6#³‘M†f1”ææ»æk9¬‡èìj-Á‰’¹=¸žfF›E)ß_*Js€½ˆÈȬd:|xïøZÖC³„PµVP$êÞo5­ ›¦ÕëpìëꞥfÔ*¸¨DU9&Ý7ì´UµV‡§EÏÈ !^m«hT‚‚®«‹G¥ªšê™”“O¨Šì&ÛÉÕÍã~¼…pª!6‹$a aôÇ›4iÊbÉ ¬‰Li¹7å óÅýn¢Â•Öf”!§æº*P4³IÛLÕ* J3-DK!t§Hk¢Ü:zÉÁ°R€Õq¶F§N%Të‘cH`B0Aˆ4SZÀ œTìä)§c !9ºšR2ÊAè$Éðƒ*¯÷WRè‘^¹f‰²©šˆ½; N¦&õ­·ßÞïæïùÔ'«b 8ÏquQ¡ã ‘Äi.tþ9Âdzþà2”\†¤{“zœ‡<—@žìPîLxî<ÚÅ5Ï=é˜ìऌÁž=yÚž ×Ñà‘È©ŠN¢Ø6í[‹ÚÄ,s£>]N´X™äèð6p{!UvpÃøshŠå3 + qjPNúÓpo“˯< v†%KnÕÎÖ·nÇf ˆ3k«Ósز'·QR%P:¶Üüß³’56"|f+³}"U§œ5¬X%Ûø¨j@k3Éí5¡ä´:8?ÜVÝ’2`©deHå{ßyóÿò?úæëo{4µLˆXÓ©‰Uï‡ÃmD„Ge5rY×C_ ΩÐÓ¨,/.¥•£räÉj€&8¤ÃN2ÕR)Òh(F•›j±Ñ¤TÐDšP‘ÏJdJtd¯ Fœð] JŠÈ@‡zfF/¸sØ“EfUTé_ùë?%ÂÉv†Ùr~Ø^9<ñG^J%Ùé73üêჇ«ßž,®hs°KéÐLÕÒëù*32ûn'f•<Þö*iÚDôÿCן>I–dÙ}๋ê33÷ˆÈʪêîê ½h,l ± Ð9 €Fæo‘9B²!† ¥÷¥–̬¬Ê52ÂÝí=ջ̇«æ‘ÅKR*SÜ#ÜÍÌÍUïrÎï„»ñ†éÇù¼qêñàôíoý¬Å˜ñ”‚án ”-Z8‚2)œD·\éw—S$…gÂýþ¾± nþâŽÏäH*•Í—º„t³ˆáíÔç8Ηœcd áÝ:öðƒ4NÍ·Ô©'-ÉR‘ÒÈ|$'7D„<ŸÏoòôdã Ÿíx " Cz´¹›GæÃ 1að%Ä&mÚ(Bwš).TjxÎà14°üÔ}¥Ö¤Ãƒ‚38Ê?‘ÄÂZ³ª´tV $Hj_Ãp§IšøÁn ©¨–'7÷ÌpŠätðMúKÉnYàN ‡J—ò÷ÿ‘æéý÷¾-rš߸{qwÿù›/.õË&[Fîï¿zïþ~Û+²=>Îm;ɩߟò"® Ž€jùâþ¼æÕ+v«ò2=ÃÝæô¹}“yƒŸ¿øâÍånÛ.mú`‘q̦۳2Œ‰‘f§­OsæÜÏ]…Ù#Da1æ ñUD´9i޼»\X&Ò.B5Á™0ÏyÌãÜî/—ûý˜"rº\,'q¿>™´ÉI±¥QF›S"YH¶Þš`Œc&¢çó9Á&L®Ie4Ê «Ë¬üĪ´)¥™’&“Óָ̄%’„2U6‚V‡í°ä°H+Ô4"µØ“½ÀYž“2ºvJ4&¥Åþ_ÿÃðÿáß}|xýñÇ?ÐÎkèÊËžîÎä"Ä„9ަ:|Ã3[oˆšñ‹È¥: &*¹8±ŒÂÄá!LT¹Ôh™Z‚q$G¹J§ý‰/_Ü7á1g¸U`'KýºF"šŠ Gx€Dû‡~ø3?õÍo¼÷²2·U)–ÙèkÅu¾#7þgEñüÜ"|MUº†_¿ž¯™?î?ס?ym¬ûfŸó¹°[“õ:µâVÞÇòÐfDòu¸¯VæVŸâ–¥UGWUž7[Ö!Wå¹×ó_>ÚzJ¢QçïmtLeS Ï[NÛ»J?¿vÄ—jÓ3+sëùü­¢þæíÊpÈÖ¾:ÉÉëÑÔïý2²­QI}Hˆ‰ RJ¢Û^‡*à9nv^Ðz½r)ž<¢ò³~‚fÂj|´T¯” ¬çQÛ²’._½þüÿóÿýÿÁwÿèÍ›§ Ri§Þ•I"„øÅýq}z…C6Ÿî\,Ff¦L333e8›ñ„D+#¹ÁÀ`†¶ÆI9¼DWŒL³ Ϭí­kU¡$­F=D‘ ÖäÊt <à˜ƒÒADÉ™pUb&Ò4„;e„#Í23EÑ™úÖNµp™òÿÑß?÷¯î_^.:lÌ}¼÷Þ{üõ¿ú×0ìÊåÈmpÏ$ÛÎ}ØafyïþåW_¼n² i ÷}—SrkºíûÓùÒ=&(=S¸»!‘ï?o[ÖDÏ'ž›´–È O&4÷µbUcRJdëÓunÛ‰™À< ÛÝy;u¦<®C¨o›F™ÞšxØ1F&ÀÌJÓ‡´$`ßËv>mž#(ÀDÔÇL›é檼FÞ‘Úätî¢LÀ8;’š“Í ÓhWÒƒG ˆ<=a,+ƒ@6A`3¹'Á)VDraUVâ•IAÕ ¤ƒf×w-d‚XS '–~>ߥçŸüÑþüÏþÌ?ý'ÿðþ÷úõ7L‹§ ÷á9ŒŒ˜™\Â)3ÇÜËŠ„¨‚Ùéâ¤\Ë¢¸„¥•—[ë”Y0+Hí£ƒšDzŽ9³ø<)6}ŽqɤëqX$ X!f3<š#T˜Øˆˆ _¼þäý÷_Üß]ÊYkq ’zGøÏOx–,5«p )ùvWÔàå}÷y(ÿç¡:_ÿøO~‹ÌçÃ}•âÏôç[¤4aˆÚÐz À™u9Þ¦7±_‰Aáψ…'¯\,Px½?P£|­L ·D ª}o$(™œcùyì~kSéµÕ]s'¢ú†ëÊ*Mú»W‰ê‚2"ê¡—‘Ê“²d?™3"2j{7që­Gs¦,S:DBô bf&§åUÊʦ@ñC“œ¹Òð@‚‹¢çæ^ŠƒEѸµÔ”É•â‘É4£ZŠ`ð›/¾øw¿ý?üñGÓbN§Ì.ÂY¬ó‘‡?>=^½ÊØi eUåÌ AÛZ Ó a&F„d#f4ƒB˜) ,9ÍêFæ ›áDÁI)¤ VÁm<²Š H:9l y£)qÀ ‹‡w'ñ$ rˆ g:I$ܺéE¤b@rÛúi;ËßþÇ¿"rÎTUé]ß>=¼ùêÍ7_½ÏɧÓÝþ˜n9ÃëbwDv:ñÖI…l®VèîîÞæäHŽÜ÷y ¿l÷JMh;÷;eÞß_úIãþ¢Çñ¸ÏÙ¶Së 1í¹_Ÿ|ºŠÀåíë=(åÔS'8=ÒêB¤M°#Èåî|aØŸŽ§Ó¥»ÇxLñëÜE$/^ž¥ñH2ævdçÅvš¹ƒq<í˜9XìtÚ³Ûa6B¬€ð˜1¦×IÌ,*ÂêF#€$—NÁÓiΰé{ÒÒ÷"ÆÖ¶î  ‡qÙ $<ÎçdÁÝ„ l¹š~$ÁÓµ‹,¼ÎªmN;ñv‘sÓö»¿û»áþ_ýÝ¿÷G¿ÿ‡Çô1+yÉ媻B:E‚Ü} ˜XÀ²J[dF6È&Í#†Ï è*™YŸdÑoMÃA‘ºÔwIȦڄ…•Á×§}L{ñòB"EÂ$P¸éÉìTÑ„O·Lšfü§òððög¿óÓ¼¨D¼„б¶‘Ï3<Çàï·ßÝT $ÄÚ´fð ш$Ê¥>ÉLÔ>Yš@¥PÄZ>—]8s½kÖªu]o5ðZꯛ† Yq‡Ê[Ü jy[ÇnÅJ'ÄQ°YQP¾ D{7p»5C\K7¦L„ƒn㹸ýÁ•-¼Ú2 ÝßÙ3Ò"%®°ïýÙü¯ÿËÿôÁ0Ž £â b–m:ç|ûö»EÜÄÜMœDáxšÛÁÒ“Z±„³&\8…Q~j׃•ƹð´ÌJ¬Ä'! ‘rjAK„€Œ“`švò©sÈ<Š#š5sc¶)’…4àI®M¤ {#m‰ Öð˜kVþ_þó_ðs>vo­õÞÞ>Bæ>Í{»€t@Ž }ÌýÔ·¦Ô» cz|y95U€¿úêUJ&ë«ä¾ÌÂ)HY2g %âƒ~x>Ÿ¾õ­oVzÚ³Ó§ÊN"Êÿ,èkÒÐçMlÍGsM»óV¹Þ8Ï"Π۟Ya¶Ïúýº<üQŽç ¤I™žkà^ðDz¼Öð[w±,²ætÓÐxÑŒ0î¹Ä§“²ŒQk+àu7PéúÉ‘F99Á·ÓüfG"×>9×,¯¬ _ïo¾#áe-ŽçWâyÏuo…WõÍ%?Œð…c^a^ü5‚)Àˆ5»Zf§º¹=¼nœ¼™¡#0dz,IH%f`-5ШÔ,YMCm¹K^•‘^lfÀ#`η¯?ý·ÿöú½ßÿO_]Í­w|Nf kkÒçðéûðG£ëô=Â…+;Ã<ŸfŠõNgbd(ꛃ4E‰ä°°ªHêMçÉAäBJfß0Y©3“g€­~ÝÓ'Ò»›ËÒ /K[deæÌ´1ö*ˆ¥ü^¬Nw¬ýŸgñ3Ʊ»Íc’_ÿ{?»m*¸Í4ú˯*é[TçxáÞú¾ªm†º‘v¹ãˆ­i©«&Ñ´q:u"šcÒãè§– ¦¦Sí]^4§|{ÝÏw÷cÎãØ:]NôêEëMlNÇL€HU{)dˆ‹ˆd÷wÚÕÏ][SæDL‚÷®¢m *5U'y|ót {ùòþÆÅ`¸ç©ŸÆ2CIª’8<&·Ð&Úõ¸Ž4ß´ ‹[æäǯfzhÖ N! m¢½õðšO§ŠT.61© ±Dzä-ßá¦mz:µVKHbMÎéé.JNæ’»b@œH OF 3¢pý‘É,DìaÃöÃscn™ä1]äãÏ¿üà‡?–v2 ÁáTc$'25xã&,žŽ “jOqŠ2Â7ÇPͤÔJ phã.ÄXXGT2e‰њ.‚Ew›† &UŽpB2Eï8Ü "½±²‘à M• ÐÇŸüè—~ñçϧ¾À/ϱ[6Àó:w8òQ™Þ]·±v>—öïœe©ÍxVõ¬Á nQ(‰Rè!×./ò6›Š…9*†þ¼ÀkFk-ü<±©ï¼„ñ‘î´â©ó¼¾4¡¥Z3zDÑrp¬ý@‚*fµ ÅZ"ÔqÛJÇmÓ” ÎóuU+žØšÙ¯1Lí„k“º^w—c®›/<à5—«Eòr0Ô¨~:±|Éï¶Þu /ÿWŽôj |¹‘3}]±5ø¯o‰4 YäÈBIS>W·÷‡¯¾üÿÇóg|øh°¤vê GXç K!UV¡9÷§ù8qXXµ)QñÂ¥eIKÛ….:5"OwSPΘÉ)ÊD˜‘0ÏLA¤ø’©,$šÈ&‚ɘ Nœhb'™¢ðiN0”z•™’Ó8"Ò§OO÷ô1É ’L&0,ÊïÆM©64fìÇ¥g˜ãp H‚IþÉ¿þ/Ú©µÖ>ãñ)ÞJç—‚Œ¸Žùø´¿Õ“°¦ ¦=Z>´3·ÖzE‡Kqµ4UÚôDÉ]zvóyõ¹ûÜz{yw6Û÷¹?η€qÌýˇ§ÆMIä$Çuó1-#Ëåt:Ÿ[²° fO¯ªÅ|2s:š6sh&%%1<ó«·c&éÒ˜eΣ)µNIC;‹¤ùщp¸ˆÞV]~:7e¦à1ì8"<û&`‰NÕ”tGîW~|ðM^>=0“jc7¢Ô­¿ ÛæLbL¡ÌpóåÖÌ„ÏiÌ•>S<$ƒ…’†å- ;o3o(¯þ_›¼{£"Œ)ï.—óé|ì;³˜M›“êªðjBÊ” ×[v„«*Üb|™ºòâÐ(ÉêÔ‚)'e°»§‘§€˜¥i«:ËÜ•¸¦Ÿ"]¥‚$@Á,JÔ@lv¥ϘfcS©†{0· Dm ¥Rgë4ÇgŸ}úké/R-"oåüÒ‘ü9Óoý‹Z§‚Ÿo®ìH$k¦±æµæ\V·[nÉmDø- …ýÏ)Û“Ç}ÈkïæµwÌ@x¸ûªpQGYäº$ÂvSƒ­iÆó¡^Æ×¬çŒºVïS§=n®Ýõëó´œW¸9z¾¸žëà®/ùNg¹6K½åk—±šŒÛ½U“CB’'¼¶Êî|ûyx¦'J)v‹eNfF–£ ‹Ü¨KrÑ|<ìþNRµ¼cÅ¡ /™¹?S’nÊ×RЖ?ã\TZÆþÕçýûÿï¾ûýx3ŸzcÀwëÒ[Û®sO†tuš#Ÿö¼f†€83)8‘éäz‡v—§»K‡K&Í$¸1ËÀTV-T Q¨²¶¦@& {£¡ ˆD3y†z*2'«oä-“áù\ H‰À1a)µ"”&Úxƒ3C{ÛX´Þr#‡± T,­5îB"éÙ8Í<äŸþ«_IÕ¹6Hßw{ºÎJm9ÛnÛõ!>›òfÇkç=ä¶Lj*çM/çÞZn›<ûp÷ÈËùLAw§M(§s›>ßîO×8Ð30zgfsJé-Üž¯×Ãà|öÇÇ'wÕóÖ^žO]õz}œn»&Á´£µ^#`j Qݺö&¤§)_ÍÆ˜÷ç>)cˆè­¦t@a’`]…E°*Cé1·Së'õÌ9é|º;m½Ió0DÂ,ȵ·Ó°ùå›§ûË·í`„ØäÇ·ùÕç;GkÔ2€ì6¡¡Dšååþ䘄‰ î^ŠÙÈTd4¹Y¿ãFÏ[µ),™…Úefpå0E8ާáOÓáÙ·“¹9aª¤ ¥'”“%°NrOA!S*‘éD)BÄ`a³u97JuK ÷*XÃÓ&܈DZ%Ä&„I·Ö„êÇ$Bš>»Òð1"F@»y&qAäD <*•(Âý&aF„#s×Ï?ÿâ;?ý½ùð—ìvÐßÄ?·QÏêøÆ*àÚµFRTˆàmœ‰…Lß÷çòvÅ#dTüÖì¤0)uÔ¬¢-¼Fù¥½¯)µ ÏmàïüÀ(#õs„ám§]$úÚd;@±Â3ó6A!|ý‹cõ «ò%"‹ô[†×Rýß´‘uGT~º×:º‡ák;0¯Þ†üÝʺT®þÜ%ÕýñuAíí?–¶'}9ŽÓA(ßGÀ*j&3’Óêøíb^k "‹Vº¾t¡VÖð'@õd\·J_~þÃ?ü½ÿðç?~òé§Ç4ÝNÑ ùî}óéĹ$y²·3^Zª,]œÖÔKè]jgJò  +Ü’ÛM7Llæ x¤€Ý§6¡ð€kNi³¥Ñ¤‘*‘IŒ§°‰¢ÛˆaÓÃjYœŽð4'›1™²%5f”˜¡ Á’Ɉ d¥7aø’n•/ –üßüò©«pФ*Ÿé¢Ú NÂ)’‚¦ã‘ÛÞ676<-ò|QVrÏS×÷ýáñíts¶óÉŸ{l]H‚æ˜W°t¼\^„ƒ%û&¡*n>‡i“¾¡7JÏÖ/DüððöÔÚO}ëý»Ó‹“nûu”N‘€pòLÌ™y#"u•ðÙ›2ñ\œZšG\ÎR|€¡aÙ˜Åå|¦Þätê"%òq&*Å‚û¼\úi“ËvÚßîOo÷Çë(á³Ú¤ë5æn*ítyñé'Ÿ¿¼¼Œ=现Ü.'KcRð´¢Ì‚Z£b€‘Sç-8Óƒ"[Sb‚8È dN!F$¹±9”kU! ™`ÍLIÐ%ƒÙAÃgJuÍy>ÝcX(Χ»¿ó·þËûËÝÛ7oޱ³0ˆ×;= ¢­7®ã1Ò=,ÂEœÅ‹îÌʬÛô ÂYÉN‚< wÊ0š3ÊI ¸¥ܤ@T¹øQèM$s“žgê½#3-T¸5¸7Ë„ª,)TH¿zûæúôø‹¿ø¦x.ÿ¹ê‹%³PÏ¡UþÞäáU?g’<ã×V¡Ê¸aM\ðns‘B[/ýI¥_Uð¬#=}˜Ö]Yr•¬jÚ«,}'\)ãÀÁ¹` …Å/ÛÂÍìVíBQ1j/*ìÕTË×òžg7K>IðRm–Ã;óYiZ¢²â报}ŒwäµÂÆE™?(n¯ã²ÄÆÒùÔÀÍLDB\Rº}Îר qáºç\^»Z&XÔ=ÃÓ“ É7ûÖ×h«¥Ñz·ÉÛkkYäœc<><üè³O~ðÿÃÿöƒ?|ó”×§™íMDÒž½+¥!=yò~ØÛaOD©L”$hiœ“Ô;iÝ2Å“ÒmÖ9Jœ7€¹z›Ìy2Éâyf’*ÉÐpÉÙàšV´çŒ&Õ§f˃æˆÝÈ¡ð…þŽ çtF8‚H„Y‹©ÃŒÄ4‘iž¶ä¸Õ ~ª‘°1ÃMþÁoý¥aNL­ œ'ø$t9kkÈ“nnV=‹ô ªØ?;ŸX…"ÈG2çvÑv:=<ÍÇ9fîÉÑÚéÔïûvžc^÷kGÚ>ܹ}öå›·ûãz:]ܽ©îÓ§ë˜Á¬îüt½‚$¹ ÷cã²é7^¾ˆð7©­½dk´?í1е¤*>ÓÆó¤ÔÌÆ1Ǿ³lÛ6§|ñøt´ÞˆC§®a“€¥óOW%¡@ÌÑOxù²¿¼¿Ô;íõõéjóéºàÞÌÒxùêüðöñúdž¹{dÚ¤qÐØ™¹g0‘cšï¢\`tOà‡ÀO­÷à#Ö[{Å”zé,Ø–¼bæn÷ÃLAYÏDÊR”yv¯J.§M̃æÌñoÞýwÿòŸýò/þÜw¿÷ÝãKd‘LRïúòP®QÍ #yF£·Æ¥qŒJcýŽÓóp„ƒjK¢ÊždÊ©Œ ÜLÏénçÓN !ÞTÅ1-ÑºŠŠ{0³Gäí5ImíõÛ7_~ñÅ/þÂ/2¯È²R¡PëL\ËÒ:¶|,b À¸™uA(EI FrÖÆ»|WéE4Œ¨SoµÏ!-E–_Ô¸é—ÿ¬vÉÛqY…r¨lóú©CŸoS"°\2!7Ê3É¥dàðÀ³·kñàÒÜëîA²gÚ×v±üSkè_ZUó0 }= Ê„Û*ÀŸ•f~JÝ6kÝ‚X5ñ-¡÷†1õXZÓX©½i¾†d‹¥Jéy[º¬<Ìýv}>S´ŸÚk@”$@«gŠ% äüà{¿÷ÇòŸ~ÿÿðÇŸ½± ÙDîN'„å>ÞT–Wîá2ÌÙ*S—œÂÊA멦´§téŸpãÖÎ`ö°™ ¢&Ì™à²ðsÊL\§U'ßb*…1 {3qOnfc†G„nŒÎ-ŠâU±õ â !Q–BC's²…%£P4KÿÆœ”Ž˜æÇœæé3ç‘søô”ßüþ’G»G2‹ŠˆÍÄœ‰é¾.}»K„ÙcëÙ6É­aëÄjcŒŒ»}§‡G{ózÏí›cóJb\NÛeëÌ”™’¼ïsŒ!MD…¹ò èxÚ/Ûvÿ’¯OÃMÄH¡||ûdN×Ã&Ì}zDNçí|ÖÖÛ¾°èÔÛ«W÷×±öÙ[÷ÆzizÆ8é|_âÌ ƒÍxúé¼%0S‚4²–lîq úÐ ¥F’fÕð 2çƒ:]Ç8ß÷» ¿÷j»»ç»,'‡ÐÓÃŒÁÂq÷jcá$ÇD¶ôþøv”°½u°†Ót)‚ÈÂ9[Óöþ7^Žã)<,Ù½2/5½@Y. «*ê6 ˆ´póD)m ÑT—"ˆ’F nL™Ó))~ôÉÿôÿð×ÿÊ_»¿»û³?ýUX|< Ù„³ ó-x„à›ª†IÂL0B‚dZDµ©ÐI6“d&)Ì+-MLtÕõÕ2@ày€(™¾±\të$ã˜Ã —À­J>VÂxºe¤è›‡7w§þŸþvÞf%ü)x Ý’ÍßÁu‰^ž‰@œâZSWaía…¸Uå´¢èA^$y TI¬]¸ûó‡Â#n´äš(zP‚×.ùæ÷¢ÕoÑͼ0 äÅ쥅œ^pÏbØ‚sý ¨"x(•wE+3ä–ÊR#™Ò d¦UË’ž·É~¬A¢{D’aÝ[Y…I•ØU”Ç:¡×éaA%WE‘¦¬X&¹˜Ê³lmq³¿Å³á­´Oin•ó|‹xÆp›¦ ¸=÷Lï6`‹º¼ÖemÿÚÆ1³»}úÉ~ïwÿã÷~ðƒÇÇD4%>m N–’GÎ@nM2wŸrÀ¯™F€r#g›33ÌsJ#Ñ:“3’0¹cK'‹ ²Äd@I){§I€IDAT’‰§;1 ¤0΢áL¡"NœÉYðx#õ¶šíǰ‰tsp¸[dGo"¤žHK&&Ü¥\ Ĭ*€Ϥé”uØ´ b–®ÍÇŽH8Â"=“³V¨+÷üÖ/×›Ü,ÆÈ.šymm áÔÚ±Ç< æMXú©FÀ"ˆ)·M;Ë|ÊœwB}Ø(G`ÌtÏ€ï>ä|ní.ãðÞåîNN½ÏÂÔz'‘Ëý‹Þš0R…#&WÌ•PD£¼+*‡ ³ Xï8mÜ›²èôã`fæ~OíéÍ~ÒÆÜ„šP‡ <ó0³ˆ1Æù|"'N‘gNRš¾=®OC['@™»ª§YÒ|ùj{q/a㮟:Í<]{J³»—}»ËWïqëGr©„³´W/_>=îdn¤tÀ¡ ¹`0RçÌi°w D&S6"ò<*˶£ä))”ÈtRJ¬Én#eH"-ÌžÐ9§'ˆY ä,´]÷ëÿþ;ÿþîÛMÛ›¯ž"S›2#<‹c§¢tñTÆ’À(“˄夶¦¢TM0h9+178"¯?øÞþïÿ¿ßþüÓÏöݦ[dôm‹4‹+’|$‡½ê]Ôióà™áWß™›â4<íÓëêä”®U¿±¹#¸Ë‰ƒ03@ÒƒŒ,]I‚„‘=gÃTÉNÎ%"VB¤sϾò:íÈI45¬º''+”©Q3¤W´ !Ë:D6ü°Œ™n‘óðL2 VR%Û°œ‰$sóL(e@„ØE¦ü½ö«É Ê sgáH#Nf»»ƒû|zÊyè]{/œÁ´]ÎDí˜6G¨ô»Ëé¸îûu<¼Ýš”ÁqØL’c·ýzìÇlítÝY·NsÇ´`ê›ÌðÇëuÃÜöÁMÁpŠd"ÌòáÔ/pŒ§ r7UÞštÂ3âþÜ/M¾±½|Oîu€ˆ$b mtçNcLnÌM"S(z £v—,\­»£ÑõzŒÃÃSTDÙšví'?_úÛ¯®ãÊðFLÂ8_äürôû»%å8FïÚ7IŠÇãxû¸?<§~ƒcbø cÉM¢mrž¡Ÿ~þ•ôl3®ÁÉ"µ¬ô<Í)œ"QqÑœ3Ê“&1‹H=Eæ´pæŒLaQ‘4OwgGð™ò§?øîÛëDcôÎE& ]´¨®[?5é>"áLXfsÍ£Y+\HˆšÍpOZ}Z›UAh¦Ï,#hF&j w?zorj>½Ò‘T«HÔ¦¥ô/¨×ÂdÚþøæ/þê/‹ÈóÊ·¡Õ°0SA+šjý#BL…7 PÊ**DII &nÒT„iÙ²+L¢ð¼ú¬ØV¢Š"£-H2pKuŒ%º%·D nDVº¡ƒr‘ÚžU’5œ’d^~b&"œŒ ŠÄô<2IÚFÉÈpŸûáÓÁ¤BYlÕ„˜æáIDÚ[ù]U…t÷9^¸’ÂÙËŠS›½lEÏdVd*Óë/?Çõg¿ó3eY%fZ†€5aæúäÂ)W»P^L¢.¢‚Ö¸7îMD¨RX{“®Ü…›J)ÀjSQ!. Xcn*,Zß]˜+äˆà’KÿZ÷黾ùßþÝoÿÑÿQ&«lD”æS…)ê\o!ºM¨EN3‹-›f›WÛ¯Q(§4BN•y’{$7VJŒ˜æC½¡„²B=«O•dIe“´æS•¸*”ŠÃp²RrDDLðÔ6;&˜„d(sލD¨Ã‰D¹ž´ÙQ4‰saEÃ'˜%ÜýÖ<é\Â6 lŠ®PJùgÿú/ $ ”¬Ä¬-21lXNî"[;Üß¼y«R»8BÊqÌ®‰¤ qƒ*ßß¿(9W‚´ñ¶5†‡ïû‘c>õ z¿ûå_úµW/îsÎ+!2-5=©ž[kL­Ð0B 0T¸‹4‘^pÖ‚waeÒjmÌEn]ÉgP ¢Û优n·à–Ly9ˆ¨ü€Œ¨RÑŠÏPZOÜ|ÍI¼pï¤Dx6{ø ÓaÖ)‰ µr +³‚ n‘»ÁTÏ—˜å˜Q!B–žiÙЖ+¢8Mï0¯+¹¢k^”TZ²Ì¨½}D’'Çôñðö«¾ÿƒßûÞwÿdŒƒEÜ'‰“º6׿$#yB3ÕèdÁ3ÇJc¡ûƒfj@ €¬Â@ÓØ|ùÌ}ºS¤rµ ,«tŽAá.e0Â!© ë’¤pÙȘ”†ˆäV·~äðyÂEssfÊ[—W²Jb+¸`zÀœnž–µ{™3Çt/TÀ ¢„ª˜äŸþ«ÿBX˜“}S¢è]Á$­™çœç­õúõq˜KèY<#Œº^âÈ˶…™2z빤n$Ôæ1¾zýÆ/­ù<¦Ï#üðƒ=>>|ùé›o¿ú¹³jI$ˆÊ[EMeŽÃm"ãÊaQ¦SW®±n¤€Ïçóq ‹9|<Žk@bÒ©õ»»sïm\½q÷ôi6Iéi#ΧWŒÄ!ÐÞž®Çu7•¾é™¦(”œÊ)[? óùDÒÉ‘£Æ%“‚òÓ/>üƒ?üÓåôë7>ýá§ÇÕöÃHX8UÚußì·Bü³*@¦Ú,q$<nDSÎp·°=Ù•d̑Ҩ·lš2óÈ93&cò‰-–{Ð*®C¨¶‚B$ÍHfaˆO”uùæþ "D:ˆÂÃaFGy…šjSqs–„$q*Ck<=¨æÎ0÷ @•“¼p(ûo}c ŸW–¥Œ%"'FX§ÖY…Ô¬ÐÂÉRHÜ0”N–qF¬5Õaƒ¼/b"¤ŠXàíãõ“O?ý•¿ð‹M喤ɸïLaÎ&V¨¼Y ˜éöÉÊ8,}IIJ×­qcËÝè:D\¤dTˆ ÕÊ)UHÂfá*1¸3uf³u¡M˜AzÛzs˜Iª|½ëZ»‘H‰Y")è¿Y wlÔ*r{2ÂLH=Óêf}¾3×ì¯6äU`SdÖò±°µD„¯¥ìÖªT¯;˜‰¾%ºpcŒÄ-ê2ê>‹°Õ¶`èŠóÌHÉÌÄȂҮ֩.ÊNå ÷ñöñÓïÿð?}ïÃßÿþ¾~s$w‡¡Í¶á´Ik”ìlMT“ĦïIa–”ÒhÛèâ;=ùî”ÚH¡Z<«t·eö¨%”j<i"ÂÂJPwÌá>—×Y)!ZXzx¤‰P‚¦gXVÆq“NI3fá–Šmã³PKJž5IØÌ„ÑÐä.Yq¤¥ŒU0‘d²'’˜8‰ óH\ik–pðqK©ów˜%èîîåÖî$U¹™›ó¤J©¾õôDp(Wò)1ˆY”„-ƒ…@°iM¶ËEéáàBD0{ë„<æPaeé}‹Ä‘`†²KåŒ*+jp–ȉp%¦`"¶tðªs9£«fÐõéúé'?þÎÏýTß´ÐÊA7ááO^><ò'ÆÐ_;:3oèéuDi0ßQýŸý´XKad.Õ-શD„ÛÄÌHø:Qcñ¥E-á}!°˜Td-¶«bF*S«ugåÒ2 wL$I’$Ìùµ˜ÌwÝ’¸¸ü749’—,)sáõWùÏP9^™`7+¸!™o,ç›ú6“œ×3ºå2fÅÜcÁ&<(aQq•òÁrû>ÿªIX9ŽkÔ_J¸LNd€8ß¼þÑ~ðûýð{?üÑŸL’Á›÷»l=Aî1Y¨wañ€ßêÄ Ïš§qØðÝøªºRcR"*âÛ°Œd­.“RtM} I]Ì!>yNŠ#í!Í€dÔe$x‰AÝ1f¤ût?Ò-É-™ÒꊉJÓÖ”AÈd8'I¨Pý&l9Jy¶Û â}ŽŒËa1=ƒ,¥ÏSŠ­åvQpgVá¦,ò¯þÛ\ã4‘ö¸ïá§Lyû°¿xñþÓÕ¦ãiýJOFν2N1ÂEZÆ1#õáqRnc€¨±¨YôÖµ58Ù´ÑD IcZ$î^\þê¯ý5˜Û~Tb…v=>¼í['昡ҷÓ9‰=Ì(q=œ¥ƒ¹ËYr{z]Ïãˆ"PzEd!܇ᑺïö¨Y8¯Ç8ÌU›²\øÒr£`mzºÛÄ2O`JêÇÃ<-6ŠËÝù²m(žkøò– õëžlޤ`N¢»Ó{ß~ÿ/¼w÷Ï~üx}Èq¥4JØnf„d8ÈiaVÄÙþtÚ6JL¬ˆ/r!/žcV'y:5 ö*ÉÁy}ÄdjM:‚*†EYžf£j±)’âY©pϤ9Í«nK0äÔ7aò´düÆßü»óýÃÓ™YLVø-×#,µôHkoA RF-…À)‚›Ê¿3Tx vÝD›§Ns …q’ÚíúÊKJhd‚8“ÍÓD„%…‚8Ù¸¦&ËáKn}ôá{ßúÆår¾­8ùë'ý ?ƒÏ¾vÖß>ò5´å³¼ý'n…*´S¾<­ùŒØÅ¶_1Œ·öôämL·‰ÐÚz–})˜Vò%×ø‰ˆª óE b¦•GÍ ÕÉ›ÀD”ÂÎ’àZàùTÎ@é°™9o¥z]AϨԨ­#=¯žï¯Ý%Ä^u@&xŽˆ[Œ×3쳆BïRk–€§˜¥Ó­pÒE§¯©n¸ÁÔùþ¯œËq<¾þêŸùÇŸùÁç_<<î° V:ät’&Dž{ßp:‹Ç¨4d0í¸HžÆðA3š§81À!0ÂdÌdí‘0÷#Wl 9e€„•i°”VVÚ¥ƒTD´Â¸ØƒâFUI;'q¹6ƒ!L¤E•J!íÉ)µË£0JQkk ¦ôÀœá 0aƒ#F1ÝGÚ¬ ðT¥.ÔÄž’ÁÕ`g&QÒ†ÞYþÞ?ûësz׳ðéíWG‚û¶Ý¿¼ûø¸Þfèa4ƒEÛ4#†(÷MÀiõkñø´_÷c> O×'b0aëíõ›××9ID«»¯'<‡?üè‡ÿô7¿õ~îçÎgº¯#ƒ"TŠë °D¶÷V=£dŠP{q¾ßß29ïOS¨ IRÒÓÍ™Y:æˆk´14<Ãl<]ß|þÕgÙXûÖd‹ ›gŽÃ`ß,ÃɈ­73ÆÖѷƽ±Ãgd]¶ûo¼ø†0MìG\=%¡ÇØçÜ_œïß{ñM;ÈPª2%"2§H2aŽ l eðœs˜¥8·-µ#J Ê¥–Áf™HiÂ\¹µÇ˨¤HG:“4Oçªö•ˆ¸˜,ôœü”QSôp€R•¸„x„ wØ‹þ²‰\ŸÞþÙÿÁ/ÿÂÏÿÖÿõ7óo^5Ý&³q)Ô‰˜V& "›ta™>‹Ph+ÓÐs€ ì¸é=÷mÚ` Jw$$%¦2©U7A­ñÓõéþìO±ë›ï÷¶É2ÓmþÏö¥¯57 ÿ;£lQžlï¸4‘¨­g@ ’Ãà ^§) DJ¬Âåïâ„ÐÂ~Ô <ùÌ BTÎ9¯‘<'dÁ&"@ÁHá Œ¥›ì¹¼X)툊2…SÈ+­HãD±†gxõd *¿VÁÊêo”_BÞ öLËߦ̕܂5ÕUpqdõ$µ­­íDž·åíRÖr˜b5"H¢J±ÊD:rºÕÝðìÆ¾¥s""Çë7þàƒßÿáÇ?|ýúqÌ.¢¸§Å Ø/÷ 2sw’Ó)» ²ÉLj ”žÄC(š ¥À —ÆÉä ÊAĨ>µÖ–*:!ÚŽqhï/^ÜŸN9¦ySåŠà|QnâK­HÚÈÝžž3C·þh×Çë‘_ý•_a¤ùãIõÒOáé\N'%l™Ó-µuGs̱÷ÞXÈÖôzX1£•˜„(‚æáeÿPR‚Êe{‘>§Ýýíx´œ]U¡g¾K'0ﶃQŽ˜,dûq@HÐØ7%}k¶c˜Yëýç~æç‰Â±Oî3Žc~þöÍÃãÞÚùiû0m›afVB) AИqAŠÖ)á\Õ\䡦ж¯ °(†$ÌZ¼D¡¶qrP0XI‹ $Ì‹ÊŲð³cNuÕÒy’(ÞîW¿zùžþð»ºïÿâŸÿóïüÌÏ}ðƒl–Gpz•Û„÷î_„YÂ…×`ž!Ê"Yd­10€×o9qA^\D…·ÖÂlºÇTUN#BTèÒæ4dÖ‡M5Õ^É*©‹âüñ?ýðÃ_½8½¸ß’VDx¹ÃòvnÞ:€U¶â¦Š¯g)d"Škºp¹jÙ¥™¬Ë£¶¦´´ë'HÄ\{Ñ:£y­ô¹þP&%?çÞÖ©WMB$/}Œ/ÙÆ²%”öçF<ÈÌÒûûØC/‹k™¬Q,þU|mQ²¢ý·±{É·¸G¿åÁÓ²8Ç"¸Éê»Jײ¼_R›eÀËÅ%Z%rp,6œßüb"·àš£WaDÒ2¢äÊŸYnmz¾¨‰I˜°ï_þèÓ?úôóï~üñ‡G¤snÔN`­—Ñ›J2Ó,¡Ó0F¥@¶§‡qìîsp;øtP3VbQŠçx’Hm„‚Y„˜9KBÆ1±¥õ†.,)ðôºÚ)“(EQÂb·43Ÿ‰h’X¸”œêê¯Y-(‚æ$#JòB÷G°™ná‘6§Y±(q™4–.¤P á&* =Çvâ»mš]R…AtÌé™òWÿþ¯NÛ3ˆÑT¸ŽC·-#÷¯žîN]YÂsŒy¹œÀiak#¿†\Ü”šJ#e"æT–sïL)œ[ÓMùÔÅÌD›03Ñ‹÷"¢*æc7{:æ›/ßÛÞ?Ñ™SÊ£ÙIÒ"3ÀÄ a:ŽCD•=<¾Ýš0’HŽiÄ:<ÌS™Í¬É6GDdk-ª *®-¥g s–~ãØ½Q¯1îéÔ˜(ÂÁ™äªš«Æ[‹Ò³È@²¨8<²¼á–‚2)#"Wêu)4êÖ¦(aœPˆ&’à”D#üí~ÕÞš¶>þá}ðWþÊ_üÛ¿ñëßýã?½ÚŒZiåŒ0eé­ÏéÚÄéÌ»ËÝËË=Ü’{ÌiTñòL¬Ä ˆµQE21q†‡SªF¸%A„O­)ëp« ަ™û©YF±´†‡<‚ »]”X– îrÝÇ÷?øàÇŸ|üÞ{/Îçs.Ld>gÆÜ.€w BVf½¦A…­¬¹ŸUbWÕháµV]Gy½ÉqS¹Ü¾þ³´ý',Ë ÔSEñóÜåy'½æþ¨ÎdmÖ¾7p[©ì9Ö¬¤Z—ò`Ývð<³*RК[áÝô 7hTŽàò3£zq'¦Š(Yž†õÒÕ¸êÝp©μԛ%ÔÁJO/Ãó’™Ã]¨(Ëea£(lßÂÔ¹ÿd`r$2 ¸~ôáüøGr}|ûùço-¨Ì [deSœNr¾´ÃÌ™ZzÎcº¡6óiìÐг߽P‘@‰î6)‚’‰šäißýðcS–ËEºœaJÞ2„ÁRwh¦² ©ûŒœÉž,›w2dÓÖeÓÔ꫺0#:4³¹ó#sðœÓçœcNó¤cVCèIaÒ{‚DZkzºô•çGeõ¡º³Uqw’÷î·¦pVã\e¹;Ÿåïýó¿ž ›9öÙZË0"b’Sß¶Öø–©IÌlªÂ,ÂEM’ÃÜÌ™ÉÃ÷9 JÉnFLÛùüöáÚ;3›9öë £·_=eM3nãHÚäØñÁŸØLp·ó¹g$1†Â#Ïps?õm‘ºñT‰¢o%M&†2vê Ìʤ Ö²éÊ• ´4Ù$Sî¶ûûþâÔNÈ5îçdÊ$i}ø¼ÃHoðv=ÜcÚa#Ê*¢k‘ÁÔD6f­A¤îzŽ` …qLø¤šÊ5mK‰' åç„Y…„(aDDá®,ÌI)L\SYŽä ´´˜îžaÕUïóHD¤—œŒNÞ‹’tb4骛hYfl7÷D êßßµó…¥grFBµä¼mœPa–¿ñwærÚ¶Ö’®Á2-眔A1cZ&¨Fe¸ïfIJ¶3‰¶mŸ¿þ2™[ÓMIn£yÌ Ÿá ƒ2CA‚Öû´Ì”»¾YÆ„]};Ƙ§óÝ~Ø—oÞHSiJÁÎ ¥pã%"Œ”µU*ôtÔ™äÁ‚àð9*(šúÛ7ûPÑtW!Õh[ ûØÍÇn×7óQ»4‘—Û«úв{Ìï5’™ÈÙ¥mí¾q³ùhò”Œ;}‰)ÁpL¤#aÚÙc^ÇuDî6òáqüú_ÿãj¯?ûêþþ¥›“3/å¶R—6ç$1Û4 ºl7O§&Ä=jª ¦ ˜&B¬4,-ÀÓ“‚L ºé!Da!Ä7.¯Äù “pêmÚ@H ³+³‹Ð´YcHþðãOÞ<ìB-­v4IšÙÌ`Ö˜ÅBÑtø„4&bsöT'…Ò™ G‰(H‚àÒ än f†¦ËH˜ qz0±Š 1g¸y&HÓ¦JCÞ¼]Åt`ˆ Ò3œ™ZïsÆîøÞ÷¿¿õÓO}óÛäÏ-À»>™(>CL +dò¦ ¢eĪL˜”¹1 A¸ØYåáz÷wèIñ5¹Ìæµ!)¯O¬ÅgÞš„›¢&—Ìtý]Z‰7e¨Í-‘Xˆ•W|ôúDé>²·³ cxx&ºê‹»ËýËóÃþÕq\Eƒ8)sîÇýét:Ý?–¬Z)bðÄdKsËa#{ܽ8ßë™ ÌœË;™LÂÒ@”ˆévº»|ùɧÿ—¿ù ù𣠊OŠH§…tÁÆTU2¹¢¦ªmž6™RÌ™à4÷Î'N%&¡”tŠ(q¨â8Pf©"5Á%f_.²Œ\ÐNOv°p ­ 7ž‘É.”B-B <`ž ‰pªðú`ñ(JE¡˜<&QQS böLÉmñNŒg¹'ƒ…lÈhªB–"rÞ¶"²Eñ¬DUµ<2@”±èc Ϝ᜴µB"ò£þèÅË—ï½÷^†#WIû «Ï¸‰—èÍmxE /?e2¥ô±‚en2Ó"×c~â¦ZÃñ›êf9»n„Zv3&â”Ûá-ÄRoKäSvªå«¢›™•lWCÌ•ip#´Ý’ÃnržˆçcaI—/k-Ç—˜ˆ àgôôíiSY©s-‹«˜/IÕ‚"o¹…ü«Þ…×¢d¥®¸à¥·Ê[Ï-ðÀoß232…À AÚüêºüýïÿÎÓã§CU¦í§ΛrpšÝßáî>¡qÇÃu^w:v» å˜Ó#gPöSkêeÏ4ÀA Æ IÓ<ÊÓ“Û²YÙâ“s2¥ Ve@ªÈ\ ‡ÌªÂ>í°p÷̤$0óz“F°h Ü@áäÁžBI s7à>Š¡‚$¸çp/ØCS¨´p0ØF%Ø"ÁÙÎr>ó«ûv:£’P–ð*•˜I`. ‹)gÚ!ÿõ¿üÕÖ*SŽçô­5&v‹L¶à®çÌ´y¸M9Ÿ{mÏN9{ÃôqúùÅô˜s*1ƒ* ´,}NÒ}V´hë]HÞ{ñrΧ¾qbò D ƒiKйû>à |=âa¦ç˜>=‚ÒÍ˹†Ž8®;ͱ÷®æÃá×§9¢k¿;]ÜGÒäS‹È¾‚r÷Ã"Fàˆ ÄËËùÒÚÃãWûkhÌÜŸæ›·0ažÇ¡­_;¬"·07ÇýùòþË÷ë´+¸ ‰Ù·¦ $¦ëõ‰ Ÿ~òÉ_ýµ_CÒ'Ÿ~fŸ!¡¤˜>g¸Š´h:— h­ƒ[Š؈‰[é(ÃIEšM'ÏI#&¢@­}¨X“%¡€2i ”•!ÃÈX„PRKWKEž’ã†Þu5a&ÒÌDß459)˜xyöc"çù¼em³bQZˆÀÂ5"¯I|­ { R¢sñÌR¨‡;æJ–_’‰´j¢EnÊVoð¢â “‘JDÂehÏtádðøÑ7¾ñêå‹û´§j21K.ߨªd+Í·~Ù±\¯·L½8é¯_: ,Rñ*„áÈå–â[€Êšó?³›oÍg㥎×$_s{DÍWV†×yòsDZ!J ™\MLdf)Ÿ‰àLN¯ua4Ë*]XbR"­[GX˜YÛla‘õ1Á 6]2¾u9ëaÔê·LȉE®¦Bê¯õÅڂ峿w©ª–ž(o‚,^„çLÿø÷ž¾ÿúÍ÷?ûü“Ï¿|ë)¬,Rÿh"/îÛݽ Dîû<ŽÈ‰4á`Þ§Y•Jœ·¦RdmÔ×}i°éæ PkRÝOÍ+·XÓÄ U‚D°´lÏD6m?ÆQž$HÑîž‘Á,Â* ­xK îHqÂ4šîÎ`¸ÏyEs"mQk3›JáH8»#œ„¥Ôœý„wúò®ow¼mØÔ›’°dú¦|Ùdkyn¬LÄäH˹ÛL•„6•ô/ÿ²èixP)îAY;ô»SCØûßx•áîë>nÄ‚ÌpÝÎgf™©$aY-9N½õÞ<ͧ—w[?µéB¸]ú–’F×ñÄÊÌrwº4a—,D¶Ó9ÓFIfœà}7sŽ¥‚d$5í^ ›@¸IãÖDˆ„y¿îUC̰HŸs€ÙƒÓÅ’,<œ"$3Îçíîþ4ãØ]ü“/>9ætwaA*›¨ûÌ –LöDZ?ͽm‹¢½‚Y¹mÌ™3Ü"ìÇŸ}úK¿ü‹­ñÓ~=¦{¡Œl†a˜kÏ­sPF¤h §[ác2‘©en !IR¦nîeõÊR˜Ül&yRˆ;’%9ƒ˜Z‰Á<‚º=ÄÁDÉ^1…yj,‘D–éVæbí%eò"‚­4B hÞÝ_®W²:fu@.‚tdFU±ð ÈqO¢È4„T*@ß„ØÒG¤pUi­…{Q¥Q!¸…Ì*26!؆D¹õK¹ŽÄ?ùÑÛ§×Úä|> S…üÈDfÒm›»V¢‰ÌRUÓÍ"pËa_ÁŠ(»Ýš|"ò&ø6˜Zµµ¬~n›–°ªÀξüT¬’3Õó¯4^g}Éhé÷±?ýèõŠx|óæñõW×$I•Ì´ãP—/Û‹{fÓ ×«¦UgcÓ|¾Që|nr–Ö–‰›á’… 'X†2AJ¼‰†gÅÁ¾C±EÆ´IkBD9¶<–3Ãv$C¥!’HJ­¡`f"²p(¹2SpF†S1‹3aÌ`á:Lo&tuK„¤QD°vѓꙶ ÎNB¢y:iSœU¶­g:`ªÆì"\˜æÃ ™½qä!Éû¿øòË/ß¼¸¿õ—¤‘>ê6ótK;wcWwo*,\;$3'fðêþîÒYy,cŒí´­f3RX¦¹×ƒæ ÷9¦ bx,ª :öýñzÍÄ8†hÄœ“—v¡“$ÎH!Ä"‡9’–áGûˆê•„K€P•K€Ý6j\B<’áQY[û0b}qÙ4Ï= SÜÉhŽLz‡ª·r9FôÓùq<ìÇc–8œØÚ:ƒæ­ qdîžÓÂ~üÙÇ?÷óßÙ÷ážsø¾Ob.O|‚Ù fÉs;E¤så` ƒH$„zëBZ[\D03H,*A…+I•Iá¨ßn'ejcD²N&Q‘Ì8ÁœP±&I:Ýr³*ȾN¢ H©¡d•ždé >owµ"ôÚPRM‹™Óæõz:ñɜ̉Ë"FM`¡X|_„ex"©Äì öáçínŽ8ŽéDɵìå:AÈÆ­òèg¤$DÌs†'À$J„Y€ HVe³ùù_|øÃ>úáGÌywÙ˜Õ‚,JU•7⢒ò“h³Ž®ŠâZn¯ 2—ÊfeÖ‚Ðå²²Ò ¾Ze¸äA‘l+ö$o[ÝÛñ½vŒ•aŃZú¦«¹É"«Ç&)ÊÕµ‚2‰‚Ká“^Sh2´Ö v ÔIR<ªó[·¢¯¤­¬zVRauB”à¥(¨/~Û #ƒÒ–)+@óÖås>Ð2aÜbž‘ÀxxûãϾúO׌ëë·o߸[Wn]"Âlyßú§î…°ƒì8æÓÕlp˜îî>2l&'_¶vêÂDÏ¢«'‡i¦Ff¦1Y'g*I†ÛHß±ñYÑ‘4ÜÌ‚©)7"N&(‘”i$â‹bm E$ -¼‡4Í]3zŠ:¢l9=”A¶Ò:¹V."ÜŠ+Æâ*e¦œ}ƒ4Pälªtêz> ³ Ë$›–Ü@\Ó#Ví j‚s§ÞbÛètRù—ÿú¯ûýûëÓWfNBÝÚt?®¢Ü{÷Œi¶]Î5ÓàézLKâbÑfãèµéãõ)‰Îçóé|" ó9¦17• JÌ*~š‡´~w¹o Ä¡Ï[Ûº°´§«z¦(³°Œõo­Í}ûÑ{gQˆ¸ÓqøaÆòÞæ–áa¡"*\ÍæfÃe(gïrˆ¡§~¢Œ­³Åí‘üð¸GRyqwÙãñtjc×ëUD…Eµ‰ˆPqéútÕÖÍ+¿cN!±a™HÂÓ¾¯°"*9×þãÏ>:ì*æp;lzƒ*ýԄ¬ËØ[#àå«Ë˜;P@œÈUÔ†×È—‰(Sf³µÍ¤ý8âéÑçPʾ¡L›i° È¤ ¼,·S°‹“&$› ƒ¦‡2ƒca‡3Cˆ)Â-jë§Bœs¾zñREý°J¹'¦ E.~ùÿóøÄ>ôÉÇ,•O–ä„e©iBREÿrùª˜ªü¡ž“|r°Ä¹4DƒT[&1Ì£¦L$$snÄ`"ò –5T©z"iºÿà?øàÃzo/_½d¼Ct–Ì"5?bðúY×/„œ*Km5“`"ÌD²²ÉÏãx^+æ…aöˆÚ…7ÝämÒCï’OÖTÐ#€² £ óÍï{OÒb¢&1›‡/ÃÚr7ÔÁ\ „0¯eõÃi‘1Ãoù+¦¬¼¶±ËöÐ-ùl­’ék0RvègWu•ü7ôÐm½À7Pµ7ˆzv`¤}öåŸ~öúwÞ<}vŒ9¦Í9‰I„„üÜí—á¯^Âçã{D< {»Çu¦YxÒa1œ§«g&¶¦—“ {!)…Eœ/[ïjî,`-S¥Œn,ÁJÄÍfh…¹g ÓÒ n¬6¼vž0C¦¦‡Ç$rQf"‘lÂDäC‚E*Ö‡|dÆIâì©6ìQÒÿûßú­ãáé£~È­›g†L_D·ÆÌ'd_E9ƒ©i÷[ì Up@1DX9"§gЫ—÷6&3KIž¥ebCcÁÈzjLb³•‘"Ý ?úø³/?ÿâg~êýí¤É¹$:åÎÅ­VÊheR@‰”©«tᮤ’ªÄœLuôCŠƒÆ$Š#˜ ì#Â*„Hf*Iyñ²Pr`¢uš ‰Ê'LÌÈXùW,LJE»iyª@¯*>=W VݱVÝX˜h>È#,#éìž^é]÷¼·¸'‘‹y¼æQ†We¬EneA%óJ‘A.Rô²†Ò .¸ÉoëQS]u¹5’)òøãÏï£ÿ`ÌÃ-œf§M˜±ßÝó7ÞS§7o¯s”SòéɯW zO3ϘÓ‚{Å=Qµ&²m4棊6Ý^½¸@H»f!{ß8ÑE¶Ó–ŒÝ’(.'!Ö>,ïïî¿õþ«S¯í‘ßÝõ9®ûõÉžÊÖ:œàÁÈI€6¶8ÌMx³D‚8˜á“Y87ÌéLááÓg)øH‚$<&³2±Î¸erkJÉÇî‘âÌvwz|xˆÃjÉç"lÓBæ„›²¸{X0C 6† Ÿ$­Ø/Ê„°¥+äV¿SJ„Û ™6ªPlÀ)Ó|°¨A©sz¦*o*Ò[;†8ÃÔµ?¾ÝÍãti—3o[¶.NÎfÑ™•©‹IÁæ•™)Õ»’•”€„“8Pó”›”P&¤'aœ¨ìITi`fp:¼Æ2ÚÚôñ~ôßÿ7ÿ÷.òý?ûSimÖ)-)p½¡)3‹±B"m“SáR / J§à# Wô¬PÞD´æKˆŸÅjsT}ÖØÑ•ÓæŒtmAíáúôÁG|ë[ßxuŸD·DE•[ÿ+W tŸ7¼?32å–-‰J§òL/”“ UAk²RQ¦2°Ó’ê€8™kµQë^¼n"Kº˜ùwF…åÍå%Ĩ™z±@KjÊœ,à€ÏÒ»§,àŽ Z)Æ·ØÑ|FF•3I¾Þ©VšÎú[‘qÛ¯I,OC"IËF¹"?QVªÚ“#~ú?þìOöë{PŒ®Ô(l>é¿ø ßÜZs>îãz ¤Î)ùpu/"µ{ÍUÆ0>Ÿ{ƒ°SL÷t±*ƒ@Æ~¨[Lᤠ#ÃÂÀ.’K±Ü$©öáLð¦±G¤ˆäá™$nˆŠ(r¿»³³PV–“OBð$«u~¸'“ö>ûôãmë¬ )Um3"˜%r*ÛÖ}ëyêDZHÒFSH£1ç˜>-‰¤oÌL§Þ $.K‹•3žù:Žrf2KøÁ@x<=íQ…Ä·¾}wŒë1’IšHX0©[û~›·r¢¾ EÔ(ª6‰ô¦’«ÕUQ´äDHUY!¨Éµõ1i•×MIDÓд¥[n"ÕÈ; ÈÜNsHEÝÝÒ¥1³1“°ØcƒC¹«´GìÄìÈiîÉæ®"§®ÂYáNŽõÖ§ $NteÆ»/ê¯Ã (³d—>2U\$YU¾|ûúwÿðwãoüú§<§•F–“PÒ’X©RÝ4È|õò^™Ç>²¤(Å(›=€J†K¤g«åcú ‚P)¾µ¦*X “»±i…U–¡´w|ôÁ°±º¨¨jÞÂãŸM²K3ùd4¾…6‚‰«Ô®]k9]kfTðæ1ƒîž‘•ñ7}faéæ+ú‚pE‚(³HÁV‹iÛå´ôªëQ•«¢+Ϙ ^gb ³¶\DÓ•¬‚gÅëòj­MxÄr‹­;Ï!–·+ñuákÜ·ˆÇõ203‘*ßrD…™Ñ„•©IøxøÑþÓ>>޼Î9™bÛ8|ºíïóòoŸŸÞ>>]ͬb83ôñ)®GDŠeN‹L2s$ZÙ£ÐÒÅ­x;™àà7{`Ì“2B•¤¥IË®Qi?$åd‹f“æÈ‘™áˆ¤LcJ7jp‚0„,½ÔnD™<¥[È2H'7®,«°Ì€O¯p!aŠå–kËËáÊÙ$O8ƒ€ó™_¼ÒÞ²2>ŠåJL¬¼Ï}ššK4Ŷñv¢mc•ÏþW?úQo½¨@ró㌹‚9,4‚6ÈDÄÃÝýv]=“EÆã‰‰FFyÔ’BDîý«ä´ècŒ À}Læôÿf§ql äfC?ÁH}ûæé§?ÿù—¿ùòr9?{vWKÕ¤Q°ÿön²nÓª1fc‚1…¡"4èF"ãÁÇDäî£ôDý_a~£-Ç-+9Ö‚wR¾gbÚoƒu0 c~+ð­â;Þ¥ã-",Ê¢¬*<‚›¦GÁ…¸€t”„?î¤oÝ´‘&¢ab‰L§t‡ù1·Ç[‰‚oI$*ªKÑÊ" eÖ±áÛ@Œ‘Xj™5Þ¾ýé«7?:?ý"ò2POô¾MS|÷{ÏÌ×ë¶wën=bNm§mK38È#ݽuˆ…§¢…(÷pq[”Ü”Ü Æ}Wwb­Ba)QÐãU[D=³z`ïÖs$F´—“È<Ñ"^ÜoäÅÛ[’)¹C=¨%PÒÙ;Ì= á* V" ‹ƒC7º×Éæ¦JeJˆIÉZøp¨ZxÌ<¶OÐ0‘$@ šªY+ýÔ2—e*w‡ã\ËaR{ë—ëõ|=Ëßû§ßýá=Õº[¼ÿpžëHó±ͰòXìu¡ºè@ØÉÖ<‚ÂRtp›MQ¶Þ”néVU9’#µV†¶õÊe6 '¤$ê:éÌ4 ÓÝÍY´[¶–¬µ®ÛÙ{#æiÚÖ½7¯¥z÷Þ;3) ÝŒw÷GxJAfÀÞ‚‚”Kú(ðs:W2D÷ÖÍ"’¥&#¬Ã=,ŠNSYÆÚÞ©Ýà–Ý`%"à|¹dp:„JD0KOßÝ™,‘dî>Þò¡fÙz<]VËô!ÓÈôf…ÄiäVn‚_¢B$~Ë…¹…‡¹C8%¸d™%F'ßC†ž…KŠPDv˽[°©…(Kd&'m …{0©É;X¸:d­ïf{‡æq#°ƒ™ô½â–Ô&¸{"$`*Y »G7Ñ[ª2’¡<GQT8[d0åxŠq¦Éøl„Ç\¦CÌÆúŽ„iÊâAf¦¤}³I|<µ3‘¹g‚…»Ûh\å­a &‰D)%3Ó £ÉÅZ¬KÛýÍ›7?ÿùÏ×ýZ«KQQÕR«Ö"¥j)¢·Þ-TešJQ.µŒÃ,¡±){T¾ÞÌàe]×¢*´T®2fa"%µ”±$‹ÁÜ·ß’;þÝå„é#mnÌã@C™¤(—¢2º»#AG@4Cˆ[hŠ1ìÈ·‹ë!ŒWëÇÛ‹òã-&ÄŒ›«‰`!®E‡æ™$LŠ›s.T`•!¼ÿø§ÿÝ—ßüÅyµ¶§@ñ(çËÓTý÷÷ÓeÒ뺽;_w ¹§9,É,{ ¾n­µÝ{³L!Ò*•]|EFQ  yiÉá-|¼¶$ÎL$R"sf")›ofÔ;Zä0,’ù(i"Ò2sàñ‰HT(¸Y<»gKò1°ƒ¹ïF8ux(s•fg÷¤Ö©ÌÊD!šÓAXsZêTt™JF@”ã8/ŒÈè ÒíúiV"›gL5OÇùtXO‡ãqZú¾uk;Ùûóå|íù§ÿì÷YÐmƒ7”z|||R¦¶o¾÷¶f»çÞÚ¾û~-eÔÝ@÷®B‡¹îûéLPe-Lw÷îûÞ·}Ýúrº€j¡, I¸‰ÈaY¤”÷׋Z÷ßßßOSE`Yê¾µnØZ“"ÛÞYJ’šÓn±í6/ǤÑlãRˤ\D®Ûþá²µoØ7¿öØ2GÆ”uš ]…ÓÝšsÊA˜NVPud%\‹Ýþ-Ð-½ƒIE»÷ˆA§áÎT r Pºrr·$sdJ8¦dI.jIa=Æê.SptÃÜÇã€EXGºPG ƒƒm1QÁí AL$J\™D"c¦>TŽâ÷èÌ„ á"Tƒ¼ùš’BÉH*¥Z亷R´VqôAÄäa ½-F?&Gl“É|üîÛø¿–:£ß¦äHeUT’ÝY¤˜eÛ½JíܱôÌÂJžTDï¦ã¤"k­n6Í¢µ{tf™ëTµzKU)”dÑY0üµ™”ᤃ^¸í]Ýiì™$Z¬ßZãÉ<ïoÞ~øÉOöôáÝw¾óùñPŠB„äVJÈ‹›Äq,&2?&ˆníY"º¡ånTMëãøÿÛGøM@HÍs9.ª•¥ª.ª*ÜÒ>bãnðô·Ñ¡01&s¢ˆ ›šÆ Å@›·Dÿ]\J°e¤ÛMû>ä+¿mêØoÉBJ\™é6ÉØ—Œòy÷¡ßºÉXHk-¥–$¬ýÓÿïý/ß<ý„ÈúÕ’ðÞ>|ûóÓw¿ý°nïß_>\»›3…D§½‡‰kXî»=]·ÖœB4¤² eaWx0$“ÄY\¡¹6õ&ÂIJ©Hå‚d¹]¹ÈYè Û°vØZÆšš%%0I(‚I2J“,RG=Rˆ‘‘Ê–Zë ³°c›åáÐ"¥×âw÷²,¸;ÎZÅmrfg† J„[ï&­v%§ôû»C)¸;ÖûÓ|\êT¥bÎu[Ÿ®k7÷¤pžÊÒ-Ì\þ½ÿà÷DrÔ?ZP=vº;ÎÓTuš·¾UU®ª¬(KµnJ\„æaË\ƒ,áÐÇË: :j$iT,IXs„]/×ô<,¸Â†¬4ó¸>}ñн]m=_ÎU%¼3l nñòås÷ÝúVªR¸ŠtOên[7$‹K4'ìÖµÎ["ºAØI¼çºîûÚ++E)|ô.{)sˆda£€ŒQN0KU!ôd®¥Òà7—½gÎs%‘µ·b·f „5ÂAALž´ŽT²{4¾» K ‰É‰¶A/ åѸ]Crs»¤ ™ÔŒ¼¥Â-2(P•¥ŠŽ¼˜”ÂNÔºŽK „ÕÃ’’Ü‚@,è1 ¸$Ä<;®˜ãÆtØóX’:–4—JŒÝÝG¬3úá0ÿñý¯¿ür¨‘>ÞoXXªáÎ êá2<&,ËÈ ²&¨’.e*Ì^– Ìéä~ 2€ °!kÃ4 ¥p"lH „9#|¼â6Ú6ÞH€D ™écÕÌDðÁCdu£ÀôxÞ~ö‹Ÿ¿ÿðN•ïŽb¹Õ>æFGÚó·8ÍÛ„˜yt¢µNÄæ7Õèë~|šËÝsZóß– XR ’¢²r"ÃÁ” !VÕq:§^èQeö’ñÐ'w"¸¢I1¡ÈìãŸI7l¸£Ê7jÕÃ)ã-ï£M¸Áˆ’‰‰”IdÔ[¹ˆ(sQâ!B¬$œB JB°Ð4éé “àÃÓ×ú£ÿúõÓOd2"ñ†ô¦h/ž•ßÿágëúæñéýymæÈ¤pNHkNÈ¢çK{Þ{ƒF©pFÔ_‰Â]ˆ‹ ƒB0‹eîá–â˜^½}üó¿ú«oïŽóq®òñQ?üÑ,"ªzÛ$b˜×nËÉèfyë‘åb:*Ê·´òàšŽgLJxöaåŒ[ÙXµjoëWs¬Y醶ŒŒ¸œŸÞ¾{ÿó/¿üÙ¯¿|õömRžN‹0D™DzÄÚúuß›y ³Œ³¯p§‘ÔÉ @™9+YjQU)r[€Ü‚=™LÉ,̪\Š=Ìå´LÇIE–ù{/^ÜMÞ}ýçù/Ïí7”¶nëåº]®«ÖøîwïîîËãã»uµÞ¤÷¼éŠznÄ=3œŸìü”³äDY(…„ƒÐš!Á"iî¥VOkn¹í¾7Ï€ð@c‘è„ä §‘“‹G®Z"bOØ ²D:*ZFÝYÇ=× …çI¦YŠ‚n‰/xJrɤð”±îË@’2Af·š÷æ]ª/ ך󜧩Lå!{ æ:Íe𔢠™f½¶Ì”ÚiÑÓ2M\4׉‚[÷½õf}ïqÝâ|éfÉÌ}3ì}¼Ü˜þóÿó?ZÎöøa{|´q²¡\©"Êž±ï ,cžªÅ|sßO‡E8{o9ˆ„¨…Ì{ËÞûÖö:ÕZ‹¨j-"t=Ÿ=³Yž¯Û$V%„½yû¦[fd)h .ÂÓTŸÝ݇Eß:"EF,™µjÖ*uRÒLòÃA#-Â9S"†O™ˆåÚZ‘¢,$ÓƒB:­÷ëÞôãŸÿüWß|¸ô }ñâù@ô¦Ûýîÿôüýo¾~ÿæÃºYö$0>ÿüÓ‰éÙéðâþîÓ—Ï á´Ì‡ir‹mk{·ã²k]ŠNÊc×-CÌÆÉB*ZÆq¼6D–©ž}ùìôp\N¤Ê#µöõÇ?ýÓÿ׿ø¯¾yürÛ×w¯Ïæô;ßýÖw¾}ïq}|º<ž×õbÛš¥m-,Èzd‹~íþ´ú¶‘`.(…èÙ³ãy»œ·a¤ X”jV‡XšàR¡“Îa4·a’ÌEUÕ³_±‘R-B™1ð öžHrÃX¡¥™+s•›ÚH)…Á•H=©‘q˜á< !މ¥ ;B´Ô™D·å Rd™&„âÌp¤¨V-³*%]·5ÄC”ı,%‘Ô2¹+•4¤Lår¹¾º\z_Í @²ˆ"q9_#¨wH:ôi–âþúáC™r™Ÿ~öâñýÞÚõáÙØ÷}…¢µxºî &Æf)·¶Ìói9™ûn]XÌãý‡­Èa*`Fó^ç²íVÔ§ED¸·½È$šDÎÔÉãn¹CSNµXk͹–§ËJÌót¸;qk½™Ÿ×ÆÅ•‰ÃE@ÑgU/¤"‡óõéþîðÙ·>»^73Iæl½…gFaÂy\& dúù²¾}ÜL'U¸ ³–qhe*A±µ>ÕÉ=á’^&±Þ3@,\dÛšh!u¤qñäÌÐýqÙ”ºGx]û¶9dù8âMÏž4¸gœDá-öNÈ*2VUíº f1çØ)˜‚cƒ7ÞòˆÕ[°(1³HÁ`½Zë”~8PОžD…ÔšA1" áD„$'i‘J‚D†U•Êh™ž§©˜b…3[Œ¾ "ƒA#ç>àí"ÃCjƒë&Ì ãžÎAL…É“[’Ù¾qy)Ì·MQ‘&±ƒß¼"[0RåÆO{ONÊëv™%/OŸ={¸?ÔTI,›5À=›K¢pí4›¥T‡ŰLs¹‡QÀç”IVÉôLg†°l1 s N¥2‰¨èjæá¢šf ´9Û«óÿíÿþ_ÿ³ÿñ?Yæ ÈuÝ{sbz|¼¼~|zûx½®Ý žÜ̃ؓ̃ÉGW“ çÍn™DœËaÙöMÇãçŸ>»;ÌâIÈÝ|Ýö¢…@7o4çvݯ{ýîññr]·vÝ÷/>ÿÖW¯Þ~8o»!hâfzÿþ]ú›ø;_ýú—￟¶uP»Å¸,Þ¿þzªË‡§·ÏîïóÝg/ïˆÈ=^<¿w Œ´¹jªr¦ÜTÉDãØÁDžáÈu˜KUÎZh®¬œÌ€x´Ÿÿú¯ÿõŸýË·ß|õõÛóå¢âßúâá‹oÝõ¾^Îï¯{³RÝœX÷n››¤šçÓ¶Yd-’»Æ/îÓ¨]­¬ûjé$ð´L#0<[ F‘ÏÙ‘âžÝÝ™ƒNïÃJ ä… ŠŒN·Ó Òƒ‚Š–ê4ktbE*€2‚(´h‰RE#ÜÝ#Ò½bIë=‘9IRŠØKe–B¬ûu3k‡»R‰(|_G|™§2[øe[뢎<Ô™ðV…Ó²ï½VUžlë×ó9!Pé” ^ǧë¦"ÌbŽýº1óÝi —%’5"³Ñÿá?ÿ_r0âpw8Îoß½ûêõ›Ë¶>ûìPj?ïíi @áΉtaвˆg¢«ê¶îÄ…@GË¢²n[ã*Vv®Z¦¹<>=Ý"}"pw5ÇÞ\jU%Jȹ.E‘ˆ­õOëÓe¯³FI*¥nͼè¤eÞ¶M(³´v=¥J¸·Þ3Éú^k¡$¦!uRsÿÍWï.gKâ‡g'QâÄ$êðî¡ÓtÝVd²†»[[–IH¬{&J-,TDA¡Ezïi|wwÜÚ™€Z•™öÞ è=ûÞXeö*RTÎ×-ÁU%ƒ(eX¡ˆ}ñâÏþâGRêf­ùÎ"E«ŒMéýÝÃÖ®ZJ7o­·ÞzzQ1³j-ÒI„Ja•J–áƒ%Q´à I‹(/ÓqDŠ7 1EB…ò;Ÿ?|û[ÏŸ½øñO¾Nž^ÜõõÛÀ´—E‹@ë¬óáô³_ùxYƒÈ} †ˆ‘ ûH°Ùm…Lr¿©B”|™ôåýñó÷w‡)‰ž—ë•„~õÕ×_}óTž½øäÓO^lëŬχå/ò³î ÒìþéËgË4}óúuÓÄßûâÓ·¯¾z\·ÍIX"@g*¿mêŠHº“ˆ ½x¸?Îu®5¢úöÍ;YÓ2—C©…•>Z6ƒCK©ªÂ¶L|˜—mßÖý)3tÑÿößü‹ûÿ*É€0÷e‘Ï>?0]öm=_lÛpÝ[³MyŽ€;íÍä—ëîFµÔZK»úõºŽž‡ ‚hk»'™Ý ¦l{ '$0k©fff£ÜFIe*:ir1VÉìÖ“oÝ"㢓ê´^W‹K³.*"•³X'‚¦ÃÂ)!·—yd¸Šd²¥«‚™Ò(y8ÌS888@,$5#mݶÃIOwŠtk–ž$4M¥*Êi™¦¹h!-P¥ŒŽŒðT.rsbÚ['.­å`ï?]¶µY™+18# BeY–"šÖkË,L“uÐÿæ?ûOŠÎÙ0ÉAR™Öi>”úâëoß>þ&ô©ÜÏï®×ëlÓöÔ¬çñT_|rØ[OÇTU„Þ¿ÿp8œ„õîî š ¯E3ÓÃz7ÕbæZ´í›U}ìÜ'¤x0P˜ÑY>ây#A¡*`§óºYß•©ÖºîÝ-8ew;žŽJ9Or¾<D¤0©–âÔ™¢½^V‚º§*±rfFðÓ‡þöÃc©3%)¬Qª¨ '2}¨ÚÇó.¼Ìearb=X6­:/“PFº”âá7œÅGk§\.þáÃ¥N•2«§g²Ä‘œÉGr$1Q­ºí› Ü&PdzØhY"ÑÇÐp'M@“ÜS,K­UöØÆì÷v 6hafvƒY&DEÝ,"QUHKšíá«LHND*…ÍÝ“ŠTÊt÷‘Š4†:jx2ò«"™Ñ<»AH'ÕÂÄ`"u·6RæÄ’WNéÌ#8`Uá¤JòÏ¿M_ÿæëµYpC™ç:€ã4ÍÓTmï9м{ì,=ÑÖáž*Z'e%Q ˆ‘™*EHlëÐ:MEŠ(’#¹G¨(À[3e)Œc-sÅŸüí?úúõõÃÅz8'û³Oþæßøâ8ñ»wO?ýõW׿oŸÖÝÉGzÁ’Œ(ÄøÏ³¸G’'¦4§£OµÐ¢dû¾­}:ܥ蛷O¢z:N/ŸŸNSùõ¯óáÒj- &ªË´|þé§OE¥Ô÷ïÞýÁçßüùŸùúM§âÁÌŽ Ï?}öíÏ?ûõÏ_½}÷˜Âvó·Pªºõ64ÅUd™+í{3ë…å“gË~ÿóYPyÖRÆb(Ì•¹HI„JPò«·¿ùWöß¼½|ݳ?]žT`­ßß-Ÿ¾œTÛÞöóµ¯{\¯}Û<âF© ëÑöè á\Ë’ëmwÓªÈlÍî·_ë½[ŠÊô¤ 倪|´á Â*B ;•1&¼ŒdJëfvÓy2’„ŠwóèQI M ‘2íéF­hŠ„¹ñ­_}kÏeƒ<\Jˆ™È]¦ ”µÀûÖÌ‹hõR3àó¬"‰tUU¢¤(“Ì••òt<0KïÝÝ à b¤£7+Rð cÖÖ¢wgðÓù’ã‹ë±ïW&‘f­ïP>0 %Éð?ù£ä –èŠ>…Ï­o›=j•ZæðútÙ§eyÿái½6¦™™Qì‹èqªE’¶Y4'VF†÷N‰ÖŒJ$‡…–Â,*¥m{Ñ9JˆÄÂf»õ>‹‘ÞÚ.41t|7ÍýîxoÝX8"Öu}:¯:M¬ºm×ü0·Þ=<žVjY¯[&ó ¤j1‹LLµ,‹&°®¨Ô2 Æ¼˜”DµN$µÐ¼,ª¥3ÛÀU™%HÌÈœé‘;g"¼ª STÛ¾ÕRåp˜&Îq•‰Ìi:Lr"…¬¡ê FòGcá#Ò ¾i—†'Ê=XðÛ]«‰& &UJjmg†x ©T+—ð>&äMž`óÈÀ扨[˜u&JÒ‰tDGú¨Ù_ƒ4Ðc é ‚Ó’@ Å€éç­Øz#+ÃnÂÊ »$EæP $3‰Ž–pH8£¨ñ/1ûî·¾ˆnmß?B@93Y„‹ž¯NþîßµÖÏëf”™cä"ŒI6‚ Dl ajÝ=¥»¹ù0¦ ÷1„ícÿ™ Ýýõ»·nÐNðÓùéÕëW_¾y÷£_~õú©Ÿ÷0#q¢›)‹€ŒÞ­¹wÎÐ wå|~·Ì’ N7kÍÛîO«_š/÷›ùÓ¥$)7ïoÞ¼_7{öðü‡¿ûÝð÷þÖï|ñò{ßzvw¤ï|ñün)Ñ7k×þà{ÿæßþٯ߼]Áq« 3¼-ÅÿÎÿð;÷wwßm½ 9æÈ¿ƒF×™(2"Ä ²në¶m½™ûe]×m›jµÞÝãå‹gS¡©2S™Â2܇ÙÆÇzª,—öýûE !™’¥×¾h:ÖÓ”ÇBÇóû-{¡iÑÓÃLlË2Uæû»…Ø{o*Zµ¶ÍÚî©uZ·VJYæÚ¬{ ”ŠL”¢æÆÄé"k7s°p™‹çBÛM¸(˺y©ušJ7kn\æe™³àR‚ÙË ª¶×ÝÃò8ÏJ ô± ¤±SK X¢Ô¹yt7=—»ÃT$U²”ŒLO˜(=bo­ÔiÝ»dIާŒ…%Ä,G@¨›íÍ"ÇdÜÝD¸Èõr¢LE•T‰ÂÕÌ»5ð`´%‚z3³ê8ø#">Le-CœÉ€…ß2Ÿ™€+cžÔÉ!Ð"æžL1¥º…°äMÈÀ­$H·ˆ„÷ÝÅÁmééÌ"£èÆÌƒ^<ˆÿ)‰J2`–â‘vgstKqxŽZir¦Þj§ˆÌ´H¤axæ¸jŒNê@Â'·¬(ƒŠÞ@ð"ó8_.w÷uìŒÁ $ÈKáR¤m[oÍ=¸(a· ’ŒT>’DãiÌÃâLÄ¢ÌbÃé÷[ç»PR¡µÞ’à‘– –nd04IšóãA2OåáîN”·¾[Zöî½#<¬›õfÝ,"ÂÌ÷faãzÚÎOOÛº¯û^…¿ÿoÍEÏëI lÝz3ÏeJ~ø½/þýÿáßþƒï{)øë¿üóׯ¾úî·¿ØÛú³_þâÇý³ëf{Ø7ïß^Îkëqƒ×ÁÉ”­µŸþô'ÓL_|ëÅÓõòæñly£1e‚J4© ½H<¿«ßþôþ;_æÑ¼›;yÖh¢ÈôRdœy ÄI’R…8#˜D4=²…wôª"Iä¤Th\ê‚ALⵈµµN$˱ԹJ¡ãAE·ŠTO×E ÐJµjµ@Ùv뻫 2zs³ôHG67Q™§©Y0ëÄ'_/;ˆA˜«"©w¬Û¹ÛfžÝ`Y&­|q¹Ê¿÷ÿæ‹û—ê¢(™·c™ Ž[£mïѨ`¾ŸÄùåóç×óEÐ7¯ß}ýúõñ®–’ Dx‚–ëºí{;ç:KØ>/˶­,¥mA½õëåZëDÂû¶×RÝ]„…©7SJÀ-«NÛ¾]¶UTeÛ› QUª…ç©LEÚz=NAòq9ô}ÙÄì.ªŠÖ{³p"×}÷ĉ«pÅñ°I%©ªž~¹¬Þ‰¤ ÚÍ,àQ¤´üîwØöR"³Ç¾Šw¶¾­ëùé©o‡‚yô‚âÆÈ¤Lޱ¶›yÓ‹Èýéþîx˜‹ôm}ÿø¸[+'Æw?{þ½/>ù½/>ùãïç[/O}»þéŸýù_ýôOëöÙßýÉÏñW?þù»Çí;ßýþÛóõׯ߽9oç­ídÈŽ„'uâþå×oþê§¿:¯{ÜÌì#ä‹1§MóL"†G§°EU2NǹVAÜŸ‡INGUâBÄ¡jï?üê/~òß>®_–Úïïë'/çï}ëþPbÛ®oÞ?½z·×~¾vâiˆ,¤w껢|º^ 0¢ÕZƒhµ}ëûår=¯hî{z‹R´ï½™›»uêT&&fh`Z„J‘Rá¹A-)"[Â(2" ž %Ý·žNd!Ä4óð`B¼SI‘d—’Ó,€Duo ž F+Â"Ý£ùÖÑXSSå:QYtº×ùN–#çu½¦š§cU)§µ?¼x.šË¬LdÍÒ¸ê‰RŸÞ_ö=™ÐH\Öý|ÙÁʬaî™á 0Rº¡{è¾÷ÇgBeVë™Qj=–":1JDô¿úßÿóJ娇c=®Hç}þ“?øGßÿã?ù‹_üÕŸýèO¯žÐì›o¾þ°>}ï÷>{ýæ7Oëãéazþ⮨™­æÑz‚µµÜÖàð)œŽ)¾,éçËÉUK-µõÆÊÂ4KñȧËŇÃ=ƒ.p£Ykd¾zóæùËçàŒ€õ^”Ku·f}šæníi}ºn‘9Srv;ÌSóN…#©*íë*\zóÓaU›n]E”³L2ͳ ÜŸsšµ~Y÷_~ùu]N, I‡¥Ùýr—™mÛ+k¦§f2m{#V‘êŽÖ¼whÑ¢„ØK!.rS, A¤u/Dää{s W–Þc7‡Šù€òs‘3ð O! H˜mŒ‘CÑDI faÊ,e¨÷ ‘n~í„'*­Z­LQKŠfïÝ÷ ÷¤ Dª Àû–Q \”’éÚƒ’ÉPˆ,¬ 2#™9E3 HaJÆ-»äÊ ØäPF2˜IÆÏ—L©E˜)s á‚ §»ÐqÍ¥A>.ÄÂê„ѦÄÂå“»g_¼ü|½î®—÷—3˜N§#(÷ýÂDUç¶{)õi?o¶…ò0‰y NûX¸^·>©,“Àf1,_S•¥Nµ,ƒ™!Œkk­!"LŒÃé.94~É@¦ä€C8=å&.ºÖÀœ”Òf¥%¢0O"Ÿ¿xùÍ»÷kë¸Û³»Ãi9žŽw_½úêþ´fY·uÛûùéâID(µh)½¹›átZ>ýäù—_½z÷áÚœ‡h7Àš‡$‚ù–C"$3ó†qÎ ãGPÀ‚S…>¹?þɾ÷Ù'Ÿr–õº].k0]·íç¿þåj}9RØÛwï~ñêݯ„bÒ|ùl¹;Õðíz½¶=Îko­aïûxuO7ê=ÃÀI…0Ïuµ¶uWQFDæÚòýÓº­ë§/îwoS؈S×mZ7b09,á:šP0’I 圜 $’î%ó­oÄ%ƒúÞ)Aá¢jn$ÁÉ$É“hR²&tìÜ23ÀáŽÞ#@)‘0,^ÄÃ.ÁºöýîÙáp A+"ÓTîN‡°«°{Òû×ÖãåˇRS5UëùéÌT…×ÕÎg§2ù4ÑaQd¸w÷(ldüÉO×½.s˜g3îîî¿yõ>BïŽÏ'åI¾P¡ë~¡¤Ãt¤ÿíÿñ?mn²ý“‡OO¥ª—ãôâïüýô÷þÑ?Ë»ï_½þæ_ü‹ÿÏŸþë½^¿øüù<Ѻ¿§bRbo«!{æe]{¦NÓRfÛ»[Hѹè<3i¢rm½”ªÓ´|óú ¡' –ej»YsOn}«U‘4M‡tÔ©>>=yó°Ž£Ö©ïMµ$õHg.Ñ{¾y½š·(Ê‘}*z,ÓÖW™4Aæ9×j½H™#BU÷sÀ®—óq:!•bZ×þî«ÇÃé«uïK©u©Öû¢ó¤…Â×ÞöîÛî½Kc™§}Ua):Žð6RNáL {vçn~[=k· G¼¤“[sF€3=‡‘ÛÝÁ\EF3%n¬. MˆŒê¦€däí –è={O °È<Š6*ÍI)UI´÷îÄÐhiÀ F2NáãŒ3ª ¬ƒYéîÐ2§SzÔ"ž£+D$‘2¢%”‚QnU5O†*+|¨Ò2ÂI*Ê>pAI¤™ðL"IäG¨ÃàÉK¤{FQePÿà;ßýÛü'?ùé/òÓ_šáîþ~žë¶¯Í›X„%²Ð‡óÙz*WJ½{ÂÌYJa"Dtk@Ĥ¬…=Ýá€XO!Ò"E¸Nuªu̹÷lû`¬ q.Ç…k AÂ83È=oîE»áãšGx¤' žUÇG¢|¦‡Húï}çÓüÎaýëo¾yóîéíãê9r\y8÷mÆ­RÔúx @¶îCE6À‚’•ÞÈ å<̪^5_}ýUw—ã²ÚÚî½±ðP%çåézÛ;z$óݱ*õ*RJÝÍÁåz½²HoÝ##òáÙs…n—µ™GŠuÕ:{ôeÊZ¢çª•#L@‡²Ðÿîÿô?ß-ö=$tFëI@R®§»÷Ï?¹?=<;ÝÍÇÖþ_ý—ÿÏë»§‡e*…7Û¯Ûvw:~¸¼ÙòÊSnÞͳ&.ÓÖ÷»ûãRªõiR59ާåééòêÕcZ)ZEQáÂÇð°æHw-ºíWfš¦ã㇋êÁÝŸ=ÜùáÃ.Œdwx˜‰èõ›w»¥¥ö7O‹ûÓ©õ š—yоœ3«è¾íR¸.ż Kô`+'%SÎeC VïëÖ²·ÆEYJÑ"™¥ŠG¬k?_P˜¸·‘ZkzG¤ŸNµ{ßib’$…y†§€T‰Ô‘$\­E†fšd9Ô"£•ÝißœPTKt«¥L§#Dc¸)˜Ä#ÇZê¢Nˆñ º™î!,ÙÁÄΜ§Ãòƒï}þünaÄ_ýäg¿yóÁIÁ:VB`PÂ)Hwóidén9ˆL1†‡,u`(ˆ$ „h,·‚“tŒ·@Œá0 IÒƒ¸'ÈÒPzïýÃn¯Ü_3]Uøîp$X-`Ö»õ¼œmÛ¢L3Ø#;±zë½™Y€Te ˆ&³÷$‚a»ìÛîÃöùp??ÜiRçZ•ëã‡ëû÷Wo¨4 €>ú)c(’©Ì)´GºS ydX ˆá{÷=¢0›•ˆÂlYŠjiÎ7¢¶Ö=œ%‰9UUoW˜&¹y=§™U!"ëÖŸÖæ™/îÙWPNË|Äñ D=ºÊÞQ¦r>_­ƒ¥F—ëúôÉ'÷m¿¾~ýútÿP*/Ç2χï/…§¶^–EÊ,ÍUÂᆶµ©-B¹D'P1¹.»™G¯5•=#ë¡zzDöÖéýŸý3s°TL"<ï•$=ÇŽËÌÏçëuÛ[³Þ|©%„¦OŸ÷þèõËŸ„]›]ß?½K•w×Ë&åa^l³"¸8¦—'uï*ì=Ök³.Çûûµ]…ìþnNæ©LÞb™ëãûw÷/îˆq¾\˜ç}÷ms†–ZëüxÞ»g´(„|ªuß·þá}w×}ož9ŽkQÎàÖ\Tއ…f-#„ªT¹l ªR …YH‹j‘—wKoç v/™}>yÿt~ºtÖCa%D­º·Ö[DòuÛtX–¢ÚzèžnÝ3E8#©ûi9µ Ï\X›·žŽ`%‘Ý—y»šíÁL™)"û¾/ËÒÓ#‡™‹Ñ‘XÎ'¦ìÀÌ¥ È8â·nÛ¡Adáñ‹«Í½¹G'kˆùX+÷"®2KJìæÞ3\´Â‚µ–­5ó¡!À ¤ZÇÖd™A(™Tж½¶2iøÚA¯ ¡ˆ¤ä>p¤ ž-I&'’U™}ÌÙAŽ]*,bg‚$ßîÿÆïýðËß|õt¹Ne9,‡¤Ølk­-s±°kÛ·nÎ!7^¾¶žÖo7-:ö 9ÔÄsQ•AW·ˆ‹¡d{öpj¶·€ÍÐöPÜÁ̇e)ur¨ƒÁDÞHHRŠb0'¹ŸT¿õâù‹/ýÕWIøôå˾m€éõ7ß<¯ÍÓ‚“•A"”aÃXIÀäÃ]“ÙÜ{PE& )³Œ5Òètgz„ü¶ßH÷à›™Ð†C ™Ãà ¢q!¾]V·Ð|‚º°{¿ìÛ××öŠÔT¢*2¼°FĹ­ Ҥ춷Øê$*i-[æ¶í1×9<‘rÙûÖ…‹ zï»_®½{p8Ö/>`l@˜ÓõŠ§Ç½m–IUE>Z ˆ4"2ƒ4ƒ™EŠ÷tä­üHá}(> ˆ¨U3¢[ưåpÖ)Іd:ÂTF'€")‚èi¡C¶´f{3s\×^TEØÝK­Íp¹^¯ëêÍèžFÇãñz½Ô©¬OBT %Šˆ»«°P¸Ù¾[Q ÀÌÌ-f”yž@q¯×!3^×Þ0h÷vÛI8Zï` JO†´Õ×K»l›‹ß?¿›¦òp7/M“fàzéç§~Ý"ÊÂÁéÁ–ä‚R%á‘®eÌ¥ï±w³‡çਥo*äÞX0MJDªT MŒ‹@ô°nžNáÃÍHLª‚±Ü· ÀÝœ-hTô6iM"¹ÎX–îL1•²o›»?{v˜'¾^¯Ë´¨ê¾Åºæ«¯>ì[tZJ©üìA?y^^ÜŸþð÷°ÔB˜skÙº[wwbZ³(ÉjÙö¦Rj2HxöÞXÂyíØXÄ[ss¨èTEbs È?þ¾W$ç*CÒöÉ·žïæ÷_¿}¼\º‡%ÑuÝ—ùøíO¿P®§ùn’å‹/>ךebOïd{¬ù³?ÿ³¿üWZñGëoüÕOþÔúZDtÊÞ6 <;‹ôF¦¹L‹¶ØkU!*Äûe5·iRïkk[ÑR'¹é«ÂXÄzw÷Öz$‡‹¨Dx&@ÚÍü (úåòÔÓÁLž¬:-3XÖ}ÿèÓ€VÍ›Â%æ:ßNÞ†éØ(C†;½õØvg–Â¥H¦0‹îmïÖúÇTz€%ÂK)ªešf³Ñ=²÷&„:zL@&yÀPH8ÈŒRÊn+(‹2 ™í K¸õÏ &Jp Á´õ$ÇV¡$³Ðu÷Ã[ð?‘™¦ J2óÞ}4H™Ç8†@…‡z4)=NéÞ¶] JÈ(*S•ZEµbšH·@ Ãg)ãyãŒd &¬däØ Â=”QˆÊà]ƒXd4°˜„IFtˆÄ‰8“2#):¥A'“@º#À Ë7®ÄCufÖÖRH+iŠÊðhÍÓLÎÂê‰æžÂ&¬ãžÈŽLr&1JÒø³ÈHãûaÉí–™4Õ‰˜㚈ëÍý6eÉajÔ¢”©* ψ vðÞ½÷¸ní²û Òar†1 #ÂG‹á”žaÌÄŒ$8¥‡"yˆ½nË ®.8q€J±€§ 0D>c¾ŸEèþ´ìÛÙ# €"(‚Ç× e¿†¼„½õýWà×eê…Ð#ý¼næÜ-¯«½ýp=ïÑBöæÂ•‚•ļ»wd kß»7ÎäÞ :gÊu¶uõæ]*¾õÉC(¢¥Ç¶ÛzöëSdL™J`àæ=bg4dëU%<Ü èáAd†ZJ)âaNé r™jQuA™˜(~O4³ôP1Y ï–n7J6ˆ¬…YL'_Žz8Ö""L\*“Ì•ŸßÕãBÄ>W™ka€@÷÷'<Ï4imWßžXòøÉËûÏ>ÓÓ}"Úé0סídËôËù²^ÛÞýÃeÛ{.Óݬóº®Í»£ÛxQ%RU¼Ëºf¸L:ËTÔ=÷µ]–CU‘yžÇ{âíyݺ•2ÁKùÿgHmû~Yw·lÛVŸ<v¿ûÚZoW[[^Þ?}Iê,ôù'Ÿ.E^>ów>ÿüþx"!wZ_½ûÙ¿ý³ÿæxêuê¬AÜEÃ| „gÕÓÝ8Xýxœ„ f›¸{¦Rüt¤O?™¦:±T4ÛzkIÔš›àÇãÌÊ™1Ï“û¹¥43#p©É„‘C˜‘wG½?êÌ32ZÛ™ußóñ1Ö³¹Q&¦¢Ê"d7‰yFRÖÍ" 1Ð<ÀäîÖ=üQæÓ$2,±î~Û ðÖÂnIf&£l­·½ «Ž)!<ˆ¼Ö8žt9ÖÞÖãR—J•ã0Ѥ8dš1ULU湎»úñpP†&•‹êR¦§ëºµ+t½!u³(óiªC3j–ëÚ÷_¿zm*‚ÀTæµ­-ÖiÒ©NEÊa>xG†ñ»7ÛÓ‡Ý#ïîgÖvi×kï­§ò$®IV!mkÛ7t*sŒ¼Ãú¿øÛ¥Ì[oïÏkî›hžµTùÉüüålÙ×­§ËåqÝÚþþýë+óUe8¦£œNõÓO^¼xþ¼Öiš¦Rj©:x>Ör§²W™åæˆ:/ªz½né¡Dˆ~w?Iõ½Ÿ§‰8»mÇE”\YËr<ÍݬgˆR„!†œEµ÷VkñìN¤ûÞÍ’ˆ÷µ]w­•…©',‡y&Ò÷Öœ„ó­3+¦¥4ÛE˜’¢»€ ¡S!¦ªJIpx¸¨Mûe³½ rªSGón>Øw*”áªRUK–찞úXŠTa0"¼y¤GütXú¾3 .KáhN"ÅщIEYUñÍ¢:pÄ[Û2‰t•$X J<%±™8—cÑâµæ²ÔZ³Öœª!Ì#i÷ÁIGzZ‘š1ö´‘$׫÷ÎÖa>¤I<µ¸YÃÈ (@pR˜ Q"»§ef@>íaæÖi»ºw<xvZäî8 »€­ëupÐ )L‚Œ¢ÌâDïGŒŸˆRrt³dX˜!Áä±YšçR«Š¢Tv¡@“d<î3ƒ@Eð K -¨Œã\U!&¤(ê§]PMær¹lÓ¤§»i®R„™xž&¢`½g4 æâ3.IY«¼>§¹.Çù>l`ÊRU‘äé2Íu9Ô¤ Ö§§mÝÛPÎE%¥7kݺ93Oª"eï]4žM‡…}»šb.²l«Å jÄ¢ÉÊe)“0 QaVaù'ÿñž×¾n®Rû¾{ôã]U寿zµ,§çÏË”iÌØÂ»»ÈtøúíÛëfë¾ÚF*ÉÁ¾™‹ ¨óaº?Î÷Ëó»éaÖåp“Pª÷`ûÞʤ%PìÍÜé(k- JËÞsH@É„ãé Œóã{¦ìû* ’T$©æR”÷Ý̹÷¨ªÊlîÇû{÷ $ÂY0Mˆi.‘ᄸ}ŽyÄIë\k]®Wë=k­BÁ2æ—M„¨Z‹hf‚14™Y‹%±‡Üe²äÖs»z7îÍEUgžf<<ÌE˜ºÁÉ æY™«²p”ád¸‹è˜P‹p€˜¥‡;9”a4 ÃC6K¦A&%ËÊJ áÈТ߆<‡n^Îdc™‘ìE„4X¦’—bŒ;€¼ÙÌ<æKû¶AJ%âmïHVzb¢ª%`t¢/¢Œ ˜à‘FM¢1vÂ-2”ÉCFŠpeæ$!œà"“;Çm&ã i aPRx§t‚ËM &S/03ŠLÏ 29yÀ‘ä™cúÅŒˆP0ƒî9ÀT ± Áa"/¦²âLbJÿð;ßþþÑ?øö‹£bw¿üê«¿ÞÛWïÞýåõò‹e^ç)2íí»ûÖ«·ˆ$ÑiÛÃ~¾è–õM‚Ö£³¹¹·l[gà¸LÂd½okƒ£ˆüþ¿'Å–¹fºY„YïéÔ÷¡+¤L#ÂÐŒ÷n‰d† GX²'Z)ÃÝÀÑCEƒÑz ’§ˆ1@rÀ%qCÌ`±Io©r©>XJÖJªŽÝv£jÓâ/Nzefád}öl¹¶LS%B,\$ÍZD' š§Ù̽5a¢´ˆXæƒÊÜ÷دWF ÏH–ׯÏÖ™eñn;±‡[„‡³™Àøþ´¨À=·îçue-s9p %×ZD©Œ‰Ò=¼'CÒ`æ‘’9»s&©Eº\€³¨°Êßþ‡_HHá˜J™Š<<ÌÊ%1yàrÝöÞëTæCíÖ¶½wG¯?==>=®çÇu®ëÛ´ b—È»e ·wÞuØãúfß‹¢Ù:íâœeâåápÿÉËÏ_Þ?ÜËËOçäµõMD"aDfr½6$Žww÷ßúäùÝ©y @°fëº5kÓ¤Ö»²0—'HK¦Z8 V””‰A:ÎwƒÉNÜvgÑß÷è-@,Et’ ënH©s­“\®' Sƒ½÷$Ùv B2‡Ûá0õ¶Î“¨òq9 ¹[4ë‘ÅYè¬YÕÃÝzÛ÷±³ÌLfšµ,¥Ú¾-õÓ+sù(ݦð.Dšq\ª£‘bo{D-¥0zk24ÜL ”©F¤[ŽVäÈ&"„IˆS”€Üš¹“GLUê$Ù†¹¦«ÒÝq:Þ‰(¬»wOîáLP‰"Éœ¤ìDò‘(Ç Ò ãÐho'DÄ1¤»ùpWU-Ж9­ ɤ  !fIu¶r'N#NpaV&†V›' /02‹¨ r \˜Óã6ÜGêt0™"üº_×õªL•ø³g϶u-¢áÎ`!ÒR„¨‚ŽwÞ‚’ÆAr ñÆõ9=8¡ãÑ2˜BD¬bnà ø0Ze™HO!±%zº#Í3#™é7()’`îæaC]òäž„ ±ÈRˆÞ@ˆÉ€”ƒ˜A`&Ž ü6žôï‚Vã›’œDÌ"±e¢üð‹¿þñÿÅ¿úïþôGÿúG?ûWçý7ïI®R:K†Ó«×eGö–{Kw±FmO³ôé9J‘2Ì{ï½™õaÊÅHëÍ¥|ÿ;ßYªTÍRÜ»ûaîÞ[_{ôÈ,ÂÜ…ˆÁ#횈±KèÝÃ’I‘A”‘h½—ÊÉ‘ pö©B9g)7êz€,oŸÕÌ€kÕ‰g&ž—¢Ç»Ig&A¦j-Ó\ê"‡YŽ ßežx*„e*ËTµÀÜzgk0·ãÝ<hY&ÕÐ<¬µ­9Ìó2ÏÙ÷HSÛ”ä8#[„¿y}}ý~í)NÔ¢̸pÝ®¶®$ Ü›í;ª'¬‡¤z ©”õº¹CdjëÓrOY»¡y@DY”°T-<>'4*á"ùüãïÁù°œjQ";Ý?<~xz\ûžËRß}x÷°Ô9ˆò|î×'ë;@`î÷§é[Ÿ>%Á­Ç2-æ-Ä€h½¹Ë4EÈmƒl§ÇóoZªSª¸JRNËýýò°”ùÅÝñxâÓ¡ÖIE(OïÏay½¶§§í²î|š§—/îÆÍµ”JŽ]‹œ–Ó\—ÞÝ̓ТEúP‹H)Ý\µs‹ %¹”Z+•Ê@0C+ƒ:(¶ýÑÛ¾ ³H̳Œ*S’«ÊÞö îI=Âa ¬[©æ¦ŒÖÖîÎ*Ý#•¹͵”aÔÜßMwZNS™YE‹rJscâ¢*ZÌ}_שh¦Õ"¡VÔˆ½²˜E—ªžØ6 gdF1JUDTåÞÆ:\˜XnC±ôtb& [ïî ¨%9a^8ÑÌ"<¼äLm®¸¿«Ë ¢Ö­GRk¾í}Ìf$ÊD>F$!”Š,`Nap"‡ð€¡Ìp ºïÉñüùÝí´2ü¦Ì#DF %*p2ŒÂŒ"LH ÊÎ0±‡<Ì$˜’•,‚˜ü#2‘·y ·Œ«ík߉IH^>{~X—uÝÂT•‹Ò¡ÌìÜž¹ÝP۞̚·ÉK‚o ÝTóA‘)ªå-eªRP²y¶€ 7îØF€gÜV"¢™[ÂÆ& Ø“"é¦Ç@¨2s2'SŒ*5#˜à$äÍÌ• *³d ˆ…åîpOâ XfšÅ¯~ýúÕû7¶¯¯ý+ä‡ãbÓdµ$Sz`Û ¨UJ:…ëׯÞ?~X™Õ,ZÛ‰Hx|JÙ½-n¹o……Á8ïݳ“¯]2Q2Õƒòöy Þ÷Ü·],઒™D#T,‘¢È„;!GøOˆ)Â2xX…T(¢¡¢¢"*ƒÞMû¾FŒÍ_q¹E&{º°F©!”Á™U¥ 3’ “ÊÃa>Í\ÅKA©Ò{+¥-Ý·íýãÓåÚA\ Ž3uáL6° ñétRUݼuDHá9m³f´¯×ǧæuïRËqžï¦ééér8ŠÔ¶§»’ˆªôÍ)jÕ2Oó$Kö¨E¥ ཙꔩn¢2©·ÌD«*%Œ¨K–`Ê©V( üw?+Ä÷Çyž „Î×õÃûË2¦©<Ü›mw÷¥G{ÿnÝöÜ[¾~ÿŽ ½ýðnYæ©è4•óù<ÕJNÖãéry¼žuªórhû¾õ lA"Å餯 i×í5ñ–ðËe/ºÌÓݡޓse§R…îÓ<Ó|P¢( k[ŸÖëûLÓ,’wwõÓOîÓü›oÞ?ö¼( óa*§S‘Ú Özn›M“5dâNK-"NÔU½N —㲨Ðñ®Î‡2$Ù C E7Û{\Wï.-òºíît<‹6ÛK‘©’p0ϲí{d2чïµèj]¦)<^8×õ¬(*K)j­GdÍËT ##ÂKËiA–¢µnÖ,LK†{ƈ󠳇K‘:U`¤—0¡a»ÍfÞDêá\@P²`š‹÷®“BÄÒEAðÞ ¢,‡Ýß("<„ÔbË-$ÁL3,ÓAÌž.LÄ”»G°:ñÍ©í!çuÍDU%p‚zfämÆ‚Ìf"¬ ò”# Sfövá Lºd@ Î_cøÄh€K@¯‡;aÜJi—¶%ùýÝé‹O>¥„»]¶snéLTþLýk%˶ž‡kDfÎ9«ª{]öÙ›‡¤(é˜d $ [† ðE†!Š’l ¶ÿƒ~²ÃÉs¸÷^kuWÍ933"ÆÅ¢a ?¬ݽºn™c¼ïó )#´nIsR‰DÀè DÁÈÌl3Ï“„‘Ÿác°án©˜î”YDfI "œ˜ }Þ‰03ÃÃÓ#"§7…RÈ™giúäx6îb¾g—kšÜ§„‰ ÿÉüùËõýý·á1,!ÍÎñÛ_û“~»lCdzF÷°6â¹Û´m‡Ûyö£ù²Ö·Û•‘F·DZ– éG³ –¸,…™"¢”òåöBn Eua$ÌL7xî- Gæ°0sòdGE&À$òŒn=Òg²ŸçWaÎdû'(  O Šs3B&°äH(EKEdLˆÖ;`.›h ÀÈDQbNQ'‚ ²Ñ–Z¤i°¦( "Pš›pi#~ùíýqú£ƒ(¿Þä§®‘Øum[ÆÈÞ†£C8¶{}t Æý8ÞŸOùx´çÞƒe9ž÷ŸÞnsQIs|žîHȰ)ª çµ0KZ§L–a8­¿a*„éù9¾4„A U)=žÏs?;(± @¸§[ðÿå_ÿ‹e[ö~6kçÙŠ–ªe>:óåeSÁ÷oÏ¿þåp—ŸÿôÃí‡m{Y¯—MIàìçr­Û¥~ÿø•©,Ïs}}'Á ŸÐüÉñ4!ÚeóÖûácAD×’>z¿¬7Áí‡×?a2c©R—¥ ùRHÌ€>ü8[ß{ß»[ŒnÂò|Üøò12ÃXE+/Þ-ÍþðÓ×çãc]5aÔJ˜ÆLÇ®*Œ@äªP*»Jn‹H&Pýq¿kêZ/î„#¬.\×Ê[ÕyÊ-’EÐ "éÛ÷ï붩жÕu© 1¬<ž¿}ÿ $I„>Ü,KÕRaÛR8¢–2zoûyÙ.Ì<|$¤¥9xdQ$fúËucf"–™ Èa}Bèè~Z&J`63\D?Y!2u¸Ä,ŽnÉ èäÌ\ ûGÝš‹ (—/Õ‚€†S“Qª‡PÌšILa$!*rÌÆ 3KfŠ$0b)„âNÂ=”‹EP2ͳ5f¤@"GÜ蕜ì¹ðߟÿS©3 6ÈŸQÇ™–D̈>)zD ™ÖÛ÷ûÇ~îÿÑ?þÛòóψôxžÓºC ÑR+†›ÂçÐjÖf~?ÃD Î:(  - ÐgE?ý)DÁ ˆs÷JÍH@JTD"N¢@Ìßõ ä3ØŽ³Ÿ¡ä†™¹ÅÀpŒ÷çãßýå—Ãqx$œcü6Æ_€þþrõUƒÒØ“ͬ›õîÔº óvZL“P„»9 “²GºŒ>JÕe‘u+“œsœÍ,(1ƸlËZxÛ”8™RÁ݇àqô£u›=¿d@Šp3tHð1]>WMi>31˜Q„Iˆ8~_ºc&@kƒÈ“P˜"ÓTh]–R=²ŸÃFïÛ*ubŒ¤L(+j5R_.ú™Ž%fDäý{däíº~ýr½^‹g DnçÞÓÒ‡3Ö: ÇÀÞ.Kb­½?öýœ–uNàÇcß÷ûÏø²­…(öóÙÒ~}üú±GJ)z½.ñþxôÑYhX3*s¦b±NöG$w‹ýØÍÛ È(«;œÃÏÝ¢8zÜ÷ótãþ/¿¶Ñ“ð8Í›ùyš–ûˆ…7?­ÖòãOo‡ß½·KY¬·~žÏn½T% @{<Ÿ|X8 ¢€C;‚U" 8’N" èK%Ž”æ‘yÇý~~<=Þ?Ê¢ÏûcáŠRÖ*\—ÂBÀ„)‚g6@°,e}ì{³ŽÐ^/—Ê8åµL„D£[&!.Ko#¶­®+fÚZ…fÍÏÝ}Ìï¹¾®¢À¥âíV¶k…ÛMª†rŽq2b‘Ò{˜± T)ÛZÛ¹‹²»çQ¥¼\oÛ¶ªâðC/ë†UàrukÅ×·Ëýù±Öåøy[ôãã;¡´žÌ\XT˜)·*™îÊ ‘ÄS'€œ(c†š2ˆQÒ ¯È@:m_$*N‘€ Ò‚€Á±T" D[­KñÞ@…¡¹õ€îŽ ¥òº°ÏEB™Á~Ž ,*ž™Ä$ð™QFþ]DÀ€ ”*ªT'Ìáª* !ʉDé€@ÎÂäžÌ"LÌsLÌÄ"2“Á¿O½§J˜˜È=¦j‡x¾ 3™fw,ãÙ÷¿ÿË?ôÑþæ‡þé?úÇm?öc?íphF@I È4W‰–>£«D|»\˲$*žî$Ú»10ùÀÞ¼wßÖ-|`@ g`FA¦>ÎÞÆR+æ‡EÄ¢ë¢o·+»÷×Ëõ§Ÿ¾¾}]ŸÇîîA(‰(Z=¢ †™N!³@ˆPäp@sG óD¢Þ;@ÎC©Ûˆ˜¹dÔ™ŸV$dæ–™>E©µ,Z #9+Ñ ÷0’X/IdbqÌ K&22SNäÚÔ Mêµ{Ì]'1"3E&qÜ^.D˜óª4AA3Û=X—¢1z`z& ‚`ºwcBš—ÏÌœ+؉te@æþˆ$Dúœ$Ì­(%däûãþëû÷ZÊ­V%l£÷˜6± NÀ†"LÉ6æ&àó|‰˜™NÊ-ÓÀ#É•…I`z0"ÝgjFŒ’'•‡>ÿZ’<š•7˜pQâYÿû¬{}®Ô??ªœKïH„äÐÝç ¬¥ß#þñ¯‰¿0=˜cŒˆˆIDà£Ù[¶îΈÈèæŽcx­[?mXzb눸ÔcŒ€<Ξ ªêcÜ–ºnb1ºÃc÷ûqFfŽ€î9Ü”"ÂÂ,™ ÁcrÜÀs¦¡“Б&a.´æˆq’Õ [ìç0OfžÉ‚¬’†âem•T‰e¡ËZ®kY„­Ûy„‘,µ|½-KÅ"T…Šp!f})‚GoA9ÜÏvDŽ—Û¢Ð¯›%4³ctdAãtMçªRKeXkY‹ ƒ…‘ pf¶ë¥ °ßöíýQj)U1éº^UkžÌRd[—ŒŒÀ÷Ç!¥&ÀlŒšE¢ã}÷a™>ºaÈ@ý @”IŠA*Ek)acð¿ø_þ©Št‰†—›þðãåçŸÖmB9¾ß¿¿¾¾öÓ®²ñe}a”ÑG¶­sïb”ðvÛŠ€H&Œ£ÿþ~ùó?|{|1?„Ó`ˆ}4%PÈ „‘‘8»ž³9õ©)ÿDJO=%bšc&áïæ÷D3ð¤@:lŒÑ—º‘ùÀHŒ BX—BÀäÝæ4ž"ýUšÁŒSø5ï+f>ðJ4‘;Æ8g>$$ŸTщàGd@HLŸ/cô 1Àͦef{À§!pö3hÂù0"ìnö—1þǯEÛè»ÏRätôȳ·êFIUYµHbZrxP‘Z™Vee@˜ndšWŸZdQÚ + xƾŸm·‚×û3[úˆDOˆcD¤ˆ¬ Bä8 P<(D€Ø¥À² ¤…™æ$Lð„6ÂW!…Èv6@¤" )Œ, ä:£(¨EY%‰Û°a¦"_®7Dhí f¬UæÞ@™”I •Z•A—4r‹²(r4;Xðãþqž=JÑ£5 g†R@"ä<ü²\–Zª–ïï¿ÝßÍcÝÖu)Šˆƒ0ËcwOaÕ_ÎvZ±ð¦ËËå…I…jáÞ[·° Æ’æéN,@Àœ*P+Mü/ßß¿?w©zÙÊe«Ë¢áa$‰ È•8=ÀÚhÇÉÿ×ÿæ?&„0¯¢è¶2¼·Ñ=ϳ—R¿}ö‘í4óèáøãëþ£?ýÇxûy‘•ŒÈÁ­÷ÀTbíf†ÖšµÞÞ~¸[k=1“6YPyŒaˆ´¬—î]ŠZ8‹²Ö@9‡…&µ¦’HÓ±'º§¤™yó°@a¢ãÑr  Ðe½fΕc´q¹Ù ,n­Í,\_×jÝFË~ˆh#€„ˆ 8zwð$¢>0 ‡p"Ķ.E$‡æL#¢T–"%Ü‘œØo—U)“TT€T(DQ”8ƒ“#ò8ŸÛ²N~=)™'„ùhm­e]*AbÆËíºnÕ¼"K‰D¤¬+)Ŭüs~"|±–º,B™îÄ$î˜HÀºP€µ6º…;E €2r‘‚™‚„€ÞM¹$׳[ïC®—m)µõC %š[B30¥ªUé÷#”¹›Oã˜âvD‡4‡Be–†ès02ÕºÓ$ŽàÁHB¨DÀâ€nA@BLIøY,›³õÙÓ"TOŸDOBDþÌËªí™ 1¦‹€(hR¢'r sŒA€3þáž@LÌ™1DR «È$±Åg€'sâ“`:ý0s:zfD''«&¬a^V¦¡—")¦ö'Ø.2"!âÓI›Î™3ØJ–€óç 2äÃǯ_ÊoýüöÔ‚áÁ¢=¼h!âï÷Ç󗺂ÓèÆL×[Ã3ÌM˜ªÈE«"*óÙ[@ 9EdUaBÁ$ !ˆÌfæàb=ߟï)YQPY 'þ°tý°a`€*Œ`D™žé€À0'Š@sÅÅL93SIèÌ&:ê׋h¡U«$CÄÙbo†"º2rXónNÌó`D„ª ”…ñ¶Ö¤¶lTkª$†xF¦Q¸PṪjÝ~Y/K-î‘ó fހ̓ˆˆàŒŽYÊÌ­¤°Ô²ô€ï÷U¯·åËëvÝ42¨Ô­Ô2ÿÉÞ" `x& ð¿þoþÅ¢ŒJQ•Öîíy<ÛÌ«®º^äíKErz}ÙÊŠöøÿþý¿³ÌÇóY%ÐÏ/ׯÿèëßÝ–?‚…4}Y ò²^J¡R"ò`)”)é<)@Ìz½Þ~ýí—ïïßÖmàu¤È ÏŽ”,ÅÑÜX%3‰ ÈiÒ¦ä:ÃzýŒ!…KÛÏц÷°Ê«÷,¼,ËÊÊÈ™áÈ9¼“âíeC„¶–‚ñý~?÷NI9`ß{¦ ¨ðO6'3PxŠhó^ 3C·1mV6Ò,ÌŒÈo· )@yÜ8)(#D¶Ó„´X`qOc" Â`Ê„-¬‚…§‘ês¬Ó–Ïó:É*ê#Ì ÂCQ ¨gBAĤ‰¨wD`œ´†ÌDOòyÒf"e Â@Ld¤ðÄD™µX"Âɇ˜(1ü„Q|¶³8€"<|@Žy¾žDD„áž‘3dàó 6Q$€;MŒÑ|Í3™Çœtó70áïÍL‚y]‰ø|Ì[¸Cú§òsRÄÓ¦ä-g’u2òÀÜ=ÑÝ"½·ñëÙþ?ÛåðñüøþnËZ‰’3£mÝÖýÜÛ°ëõFIÏý<ÚXê:ÎññhH”DPT!óåú޹Ÿ'g"1/K­‚LIÌ6:"Df<›µ’‰™„º€3A¤š¦…®—ÂŽý÷gJe*’žÍÃÜÃ}~*)FoÓ¥ìŸ>Kgñ²Àë›\¯T$Yˆ€c¤5gT(‚ɉœ‹ADúx<ŸÏ½¢@"‘¸X/""ž9ˆÉ† iîÎG‹G;º÷¿\Wb`¡óÙ¼Ã_~èv¬—Ê$U·ÇGûö8“h½¨.¹]… ª(&ˆ¨–B$}øÑûs?‰¸ÖjcÌV%)˜0Ö®>àñ<pú  §^ƒÑÁEÕ³µÞJÑuÕ×—Ëëµ^Š„ÙÑû0¿,‹r~ž¢DËõº¹{·D.üø?ÿfÖ¢™ô8ì~¶åRo·íö²–%ŽŒSf¥ìv“zûúõ„\Š^W•zöøÖúþõòöãí¯ë|ûÛÛåëó¹C&½e*êcrÒÊKoƒ˜@èlN¤?üøcYË÷o¿•º0r-ªš`£ˆ†;3e UêílÍ;®¥rÒt‡`esŸØ¬Ha‡p,¤$zîÖ*&%©ÜÇQµy¹^¶úrÛ"ÃÍ!FÀpwàf‰©ýÌt)zi§!+•ˆ¢T>Û!\™øíËår«Sdûñq|{ßY׺.?ÿáËÄiMêA& óg3sϰHDKpBB0,U9ß?îîÔ‡—e1wÒ?~¹}½.*M†>,Ü.›ª¦ ŒmUˆHÏpàd%â"¬„Áž˜«äP2µ¢ž&"$„ Éd³¼fi ‰3qŽHŸ›gVÕIŸñÈ™ŒHŽZh]¥*U&Œ°pk†Àˆx´çïz®ÙŠ®¥¤ŒùX”‘‘ÓCœ€æhÎHŸôL” „´ßÁA˜D!L€$€ @˜€9q“¦Æ€ÉsŽ4Gò„ññ$!$œÇê0¥‰êó$žkX)RU¬H`ü}rŸI )ÌU4Ã’‡ $"fÀéô¥LˆðÈ#Ã"=À?98þ)x™Ý·ŽÌÀø½RœóÅ!p‚ÿŠþW¦oªOë羟™P‹2BÎ×Þ°A¯·xdwFJÀ}ß!b©…•s^Íœˆ-À<ÛÀ)AÌÊ è ]™01‘©á–md&™§{²2@ªh`Θ†1ÂÞ,(gÓ›t`3J-H<<2>¡ Èf1†K ©±^òõ•®0¸"]{‹6´âe]–¥bš"ÊRIUÜÇ3pDŒî‘q»ð˯ºAš;.u=±Ÿ½÷d$¡% C ±"OïVFU&•b=?¾ïítV~ý² ue¢x<öL²>‘ªˆZ•Ž=Q  DŒÑ™Õ<Í£1|LÏn„º*+ oˆ^ ·ÞŸû>Òµ–´`·ðÀûó<ÏáÃÓÜÝûñ>Ï¿ŒñÀ¨é·"?þí?úg*uï}ŒÀÆè™È”£ÛpG!ƒøöxž‡ù€Ì¸ÞVD7·6»e;Û<à –C”rô.¬1P˜TÂæm.‰#`xvÏÔGb7 ìcÁ$sQ¸ÕºþöýcÙªr2&Rx4óóãñ›g—Bó7?¸<Ç¡µX³¶æ¥Y­€ž6anÙ[SHÊD;ö‡õÈ‹¬¥®½ËºþõßÿµÀdtô ‘ÂU ëfŒœ=#Îã9Ò•ËÛËEˆ¨(gæÛÛ+÷6&¶lôán"X*.K Åç²R —Eª¦û±("Ooê'M‡(§(ÚÜ2²0ÃôbyŽæácD&E¤¹]fÞiÚ¬@”Q×­°%x3wŒ9 f¥9 ™Ñø)JBwÀác*!•µh™ÏÄD‚d`0†©5þ=P ó&=_U‰à HÌÓÇ ø{ЈhÚŠ?-<ÓB‰súŒHó‹Iøûªˆ p"}|zAÜÝ=30‘’‚™uY"?Ë ‘À\È}N2Òsæ«(‘'){ê¨ a~ø0[h‰ðIÀfDpÃ8`¼Ÿû¿aþ¥”Ç÷ïßîá´mëíºn˺¬Ë !Á<# wsócˆ01ŒÑ‡"ˆ°šåè>|pQ$\]*32ó\ÞÂq6b:ÏέÇiUŒ B¬„éLhæ­™öæéA1…É€<Ã4=eD˜DŽÖÃF0rkvž#-=ŒÄë’/¾­ºªŠLˆŽäIÃCÔ¯¯¼låØÏ³Ep, ý8[ëc¸[Xb–*Zòz«¢Y4‹È±Ÿ×傎Çq6­w·,\ZëÌ´.\+­ET)l(H>vK÷Ç>DÈj¡ëVÝW½T·h="ˆ´–ð#0$Έ–\˜ˆçŒ̳F}J‰íRŒØ{â ÁR! Ïnî µ3%0ñ9Æs?€òãy´$“ÒÐ#»u)r[/«.ü/ÿ×Ü÷ž©ÌkoþÃåöõå¶.J̈‚þ"¼Œ8@ ¶?ÿyp\£BŽG€{XëçÑËóíí:Ž>îùRþŸü³ÿìëíg ig¾?1–e½.—uD³h‹–­‚AÜË’çÜ„µfBUÊ5A‰ªhI$š1¼ni–œAµ.惑ÒÓlV„Š*"gεÍiR]ëÅ<„¹Ž ÈÐ’Ò"GİñóO_.ײ]5¢-«¬k°Ÿ~ü²®zÛJQ@´Ìè#»22`$š‘ÇRʰ‘Ÿå¬ ˆ07Øw3cH6"IŽv 7³F¢·³5"m'˜a&¥G Ïù3ÐO¯×k%X‹¨ð1zï¾ÑEae¬[‘ëZGk^×í<ÏÖšùX¶º^õra–Ô"­·ÄHɺ, $y¶žÂ˜ÌX„ç‰lª2€<&h°g‚2W¢âˆT„(…pY‹jzv¤‰vÑpWB%fÉmÕm(‡¹™MÍo˜O_£»± Qš™0á/@ ú'ÜŒ ç %!)'û“›–‰AìŽÎÌ„ÉDsŽbI‘@$Ÿ›©÷ü9t¤È„ÉÄž¡éßLd˜/š¹ È @@ G¢Ûívž{B"ÑtºÀüÈæñŽçý#g[à?¶sf4GQ™óRfÏñnãˆþr¹6ö|6`ÆZðöºfÚ1Æoßß=@ÏÓϳ'p;}?F{âÞšgH­@R„j‘Ëp-e[ Sjaf`BUð˜¶÷LÍó|ìŠ&p qHboý̘/ÖÒzBøÜ%'%Ε†Àä4C·>F·ˆ°Ã3ˆˆ†5WãK¾¼–ëE…€˜´(qzX­e©Zªðº*m¢²!H"ñ #éîÏc×BÛµ|y­//òåKÙ6¶Þ X)ÑG P­WºlËËm[—/¯WU\eJ|¾·çc<ÎØ-ö³]V¹ÝÊåÊ—kIŒ°ÈÀpŽ  ÊÃl?›}"¥ŽÎíðtê ‰ÀD£w$†DÏŠ‰ÐÆèîZËr©—º¬¬`{ˆ¼-Ëñ<¦é0ƒpY²¿Ü*‚}ì(ºÝ6.Ìá—mS-\„ÿÕ¿úÏçúÔÆ™£Í/‡uSV È.•p€p¡ü~¿®ûG/Lõryá’  Þzïýüþø³,}X?QpùéõoÿÓ¿ýŸ¾¬_Ÿç@ŒÄ1Æ)' ³àÈðD"„DO¿lëº(fØ#Ù)|!¼d2¨bkO-DaîZJ`ËÔ/šRIæÉŽ€8eJ•>i²’ˆ1i |  ¦'õÑG´?ƉÌûq/•Gœ¿üúïÿðǯÛE–‚?½¼.DE’!a$N&I1w)"DHRrXîl¡ª¥h1w‡ìîE‹V ðýl™ÔFÓR3ÑsJ?ÈÎá-"yQ ?ž;-KAü$˜;XÏqÆ™œß?¾«h‘2ξp}½]1†*(‡BpæeÑÛU_o…™ ;¢I¥¤é£adfa±°Ïx}£†™Y ³^”#hßg>}‚'èÓãå–£Gï~½\#‚˜†ÅÑSËÂBH…‰(S Ãm-‹23°Gœõ BR&aÊb²fd>ž, €N˜îD‰Hˆ©Ÿü²`ŠÂÀ‰iÉLDà ¬4c£èa–2 i&‚>‰Ë836às¯›„) 2'`4;§™–FDJŒîi>ñÎ ÞÛ)J‘³y0Í—“üÿ9ŒšŽ5‹„Y1ËŒ NütN÷dÿhíÂÿù7â'¤G;ÎÖÆñÓOo×­,Epo€Žã\—šaª’ˆŸ³Þ{?‰™…>ky{]Ö “0²"œgëmd@ëýýþ°ÄžÑ"Ì =âºUŽœ9»9§Ñ‘é@~ö ³â©ÌhfLɘÐÇèçy):[o* îŽdZãõ­þðv½.¥Š6›Ib‚ZDE(@‘1޽§Òu[–RïÏóÛÇs˜_¶òõëòöVn~{¹ ¶R2=2€S )’ñ×wƒÔ"˜9|œ1ö}_×ņ}¼ïíÄ>òqŒ³ÊâXJõˆoï߀y.§ê±[&–Zºçp°L UY‘²;³Ù( ׫&:&ê“™¡*‹ÐR·¥^‰(ʼ¬AªaE v#é­!DUÞj™•rY.*…Ù‹b)¼^µÄp@hvòÿþÿôÏ„€²ÕË… »goqÿþ,uÀÑ;ò‘Ð eÝ#GfŒA6ˆ‘èãù­Ù£ï‰»Aûöþý¹wkðã—Ÿ/ËöåëOÃòqoJ ưьCÒÕLT*!¸·î½ee\¯›™A–Ç7¿–ë" 8Á ¯Û !»dNÈmd$‘ÊÙÇÙ{­‹¨2’A ‚åéÑ ƒ§-µ®ËzgÚ”gS¦¥( 0€ÆqîÃ0°ਠ‰‹L ÁgúΑ…-z]ЍºON@'L®ºì÷}¤‘I3ÉÒ"ÑÌÜ=K%ƒ¸m?GÈ@yôxiæq©ÛF´ÞÖÒÚÙšÔêÑ«²`áˆqžILGf(ª(¬6ÚRW•ŠÊ°¬úò²Ù뺄éɪuS)DÄ’Ä.EÅXˆ8 ‘gÔ;Aòïרp žBøëee OGFV&–\R 2…§iªDBe)Â>f~Õ w£de!FBW!¢ô™ršÁ"ÌOjÐTD  H›‚'˜ºöŒ‘Dˆ¨–éIÈ<Ý^˜Ã1RU't'Óe‡fÒfw >áˆÓ|‰€ ¤€˜žs1=!æn3†á™13ž³ºÿÁ0ã3`3×~‰ ™1=  þûö¸ÿ÷_Jíæm >ÜÆ¶-×KUMÈ0‹‘q§¨eA 1ÚͺùðTƒê¢ëZŽÖøzY©`P° ƒv€¤}o6Œ„ Öes  Ä昤™0­ÅóÅ9ÿ“<Ð ÂÍÆ ìA,1" ÛH†Lìm„0C)…UUQk¥Ròö"—ÛJn£‘dYH$”A‰Ü2“,`x­;Àð™·Ëeø8}×~øZ·…#¢D„A"s!d3sB‘‰2$¾{ –HE®÷omÚ€üØÛóÀ1X˜ I’ùz»]¯×"šf¨Àé—uñfÞÓz¢T@ HóNb†Š©Ø‘0™P„Dµ™uë^‹VÑŠ…Ó2ÍG­ÙL£õngï¡,˜< Œ¸1ºùˆ¥nŒ€à ¤E %³5„ÈÿÕýÏG?C ˆûþ&ÔʼP©”9†µÄÐU‡fĤ˜k‘°ÓÍFÌz¶îè~ö¾ïç÷ûŸûó£=i¶~T½âؾ^ÿôOÿöŸ,‹|<îX(ÔÇô…8oëŠû±£ÐÞú9Ì܆õe)ÙÚu•××’¸ëªüñ<3cÝØ³‡;z2²¨:À° T&ªK­U˜89¹`¢ãD,@€wÃdŸ@$Œ Õê=æ× Ì×R‹VaËÑó<í³±Lœ¥Ðþðõ²qFSdB3 ‡~¤`2#": "‚5#§‚%3€¥¹>q]—1üýãÙz (QFÂÑfNŸT8Ã÷½=Ÿ=Æéß¿µ£áýéûá[½ô³‡§»1cºaøHæHhg?‡ª(—Ê­  a…ÌZu[ÀÑÃ’™zï ‘n‰·—Ûtå¹ëµ.•ÛyNè1;Ì o&ÀóÄdL8Ï¥VID#!•i³ L%`LádÊ…³rÔµ +› snf.BÓÛÇ8Í+îa6A˜“?á"4½Ì”8ÇýäAžÓ9–J(„†ˆÈIš„ÿÿ$5 YH!!Q†ÇÔŸfòÎ"ᬶy rÆ\^ÀeOLFBÎ}HD83'Χd@8xâçg/?¡v0?31N4 ?lüÒŽ;Ú¿ß.9Ü̆3‘2å¢4_"„¨"ŒÐ{c˜ExŽû³e@$G@ÖZte]i½”e-µ¦õÖ3¸ïö¼½OpƒpLg>†Ïfˆh$ÐGC¦Èp·""ˆ!‰é1õ6c˜C‚{¸›GwŒ ‡˜J»UD˜µ,¢R•EL,Îì[­9ü³±¿ðíÂ/«.Hîð<Û¹ûyF0<úh~?¾ëŠ_¾,¯·¢á2|ôÛõâæ{k=""Ñ3ÍM®·åz¹5üöK‹\÷Ó#ø<Îó|¼¾m¬ôñx¸—s& ½µHÃì—­œgï}”BÄ,L…‹÷Ì䣹9F’HÄ£ŸfoD"²á½‡;îg÷€ã´ûýü¸ï™\ËN”0ú ‘úxœç9ÚÝ¢u'¢²ðíe+µÌ2ÁþìçæHÄ‚ÔZ´(å8» –Ç90ùüÿw_Þ¾¨®È£™ pæÔ ÇqLX/)X0bØØ}œÔÎ<û0ª§{ Äfqt纎ȽÏöáxüúñÃ&Ð0.rùùëÏ—¥Ô"Bèã`ñÈ£yûœq!:ª`¦Ý®«:Ïãýý±ïñ|oœùå­HfÙNp£Q­UÒ‘˜QÚ¾c’Ä$JYH4pÄHd]—7R:{áA„ÌÜZ ÷ð` „â¬/Z™$ ¢Öm˜$`k-­F©|½Vd&Š‘n¨`æSá’i––˜– ÂE‰ bجŽR©j~¬ª9ReÉ a^+®Âqx8õæ»Ó½Ç12Ò·EJ©Êêc@‚C:øð²F¢ ÂÌ7;ôfUJ†m 3{䨵þúË· ¼,K>t) ™­5"ݧc€Â"Õ g&BP-ž9ƈ°"Dˆç€)¿ÓTF€1¡ˆD€''èœ>M> ¤' j™7•\·ŠDÈš„–f@Íb’œ˜Ñ<†{°03Cb"¥Ç LaÎ)² ÂTep&TAˆÎ˜À(ˆ@€Ó#Á” -‰ €#Å? £4¯“€³wN=»¾ŸÈëü”CbLWË %è¬d@ÐTÛgÀšÀùìí[;þâã×·+^W©UcGJzy½. /UÎfZ¶ýìcdëч}?GšdÊ ž$¸¬Ì’uE*"áÞÇD2³ W%Q„O} ¤g 3ófI4§!ØTf ±‡ k­nnmº"“’2²ŽI…9%,‘„dð‰ùrÛ2ÓÌ€‰™¡(V¦Ì|<Îç>z—¥2£ÌÂäãÑzƒãïã±w-R/o«|ù²–’™˜e­T ð㑹]¶ªªÌ†ðúr½lEHÞ¿ïéüë¯ûûG'æí¢×í¢Êµ¢–,ˆÙ†÷s\·ëõº²ÐÜ!ÂÙÆ²\u*Íp h="¡ˆ*‹@t³“ˆÓäyû1Z‹ÇãÜwëÎæïïÏãLu­7îýœs€¸ŸöýcGaáõ²±p):Æ™øy+Ï>ü´ègs )Ë2Æ8ÏvœílmXðÿñ¿þ›/…_®ÛÛËúöåKï¾ïã8@.Kf9i#1Â@P‹Ê²-$0ЩÈ~¶oGóÓà8¬ÔÅÜÛ‘î‰ÝL‹þå·{þâÑ! ½^þpÑ?}½ýÍëme%)üþx!°O«&¡cDO4fº\/¶?öµ^.— À07UF.r>öó™èc¸êR C îmŒ€Œ ª .,£w;÷ªÄ䌦”p»]k‘1z„OôŠÃè†îè#!ØG¾l/„bæ!Dé,Œ©„qZ7Z·Bèèc¸§{gNUų¹5çðÌérYDôléAà*àß>ÍŒ붉*`ǥ¼rœÇ°áI‘ˆgo¿}| –Lr@02 @‘(ýºn­•¢EÀ!ÖU5b0MpOë>‚q>ÓZA‚Éç~vKV%æL÷,4 -)´¨(|~3&”áÐF7Ý|œi"3hæù‰ÙJZ¨™‰«ÑÛèf#ÝÐF $ £0ÑŒûD`"3â§Yç½>" g¦“&"›0€¦È†9( µbâ`B ò‘„<ÿ.‹˜¹(„Ä™Þñô©#Ÿ|·YØLÈD"ä)€›‹’D„È>·Ëዉ0cO D” Hš'çoa¿ôöËþøs‘VK¨âqgkª"…n—kö¾(ÕBâˆ|ÿ8l¤HÑe=‡rï×­ÁëZª2A€½èãr]·K%ÁÑa߇yš@‹ÈHŒ|¹\|Œˆ "fd³Ì”çã°S?ñ)ÔÝ<-‚ÂÙ/Â8›™"ä\‹³PV†`ŠRÚÙmxf–*¥pë£GþúþþË÷÷sxw|ì þôóË×/¥ª×_oq¨bâÜÍ«{Œ¥è¶–¥ÂV‘ØkÈ÷÷v<âýé÷ýLˆŸzy»ª@B2 ÏûýìÍ.Ûå²®U¸(mk…¬¥ªTÙº!2 ÷ÞÝA?ß0ÌîǾŸÖÃzßOiÝ̨0W7÷LZª®•+Š÷böíã1,ÇXŠ2jõ³p3&003#ÏÞ“p]J ?™æ`Ð÷Öϳ™ÿ«ÿÛB„ÖúþññŽd?þðÓ?ÿ»ÿÙº,ûññëûrÒ1,"£EjZöúõ%Àýèç̧çÓÜYÊy˜ Ý·Ë`‘£õöý¾Ÿ#ŽãDŒ¿=Ï÷Œ!•‚/Ëõ‡/ Ô6`÷ª˜Fó "Ê&\×¥µ.ÌHIë´ûº._¾\…ÈŒŸO»¾Ü€|Ä@€¹Ÿ íh™Ã “B?w´ž9›A$hî½õÇ~&R¢¥Eÿ„ »¦ù<ÓÝïÏð,‹ c¶, cšy³´¬ëííìïß?þ*‚o/·*E c"»Ezìnc¸EI7³1D À‘‘<1 Q@>ÏÞ"”­ªê`v÷Q˜fÙ˜I&!«YGë@I WŽáx¹Ôk½E’¥³Èyöãp3‘ÄÛ¶¼ÝêR¹µs™÷˜‘C%HIÂRZKƒ1&§:!Q( óív…tféÍû çPTÇè–™Ä}ØýÞlðÔ¬# y’Ø„™ef&3#a!a‘Îu‘µ”¥ªÎØ[$˜‡wð9ˆ‚i†9§µEXtú‘˜‰, ¼§™€RQ]ËRu@eœ3&`üt‹úpð$J˜³ÕLcJˆLKp‹IÙC@ÀœÈÆOð(} &#9Qhj“çù÷´8tÈ_‡ÿ›fœßÑZìzuåãÜÇ)Z¤h†9€gâsïs —ÇG·Ž½Åy Õ Ãüº•µæ?¼ Äd(}Üw€\VqÈç~®ËÆ(ûó8š{º%$ÍF¤`¢Hì"X• ž„y¹mEȬéÊ ð|xŒµ–/·ëJÔŽýìÃJ­K-ªÌH«.Ö­jÉH]· €|¸ ݲ7;Ž#²#91B~¹mÄÉä|ð÷ïÇqtH47Ëàÿê_ÿ"'Âc?>žÏ¢,÷÷_ãX–›*ÿüÓW$ðð¯?ü‰û~v‡ëË[ïçËee‚cßÝ“±\/ÛíZÖ•ëÂ˶l׫œž=`]¼^/¯×ma’@¡º•å¯ßþþ}ïc´cïF}àíò–Šr´V—¥TÁY¤L{6‹žÝö£}¼_kA eÞ€ÂÃ9‘äy>‹£a™®µ–öç²UÌH)ò8îNÎE¸h üöíûºÝ‘Þ±¨ƒJJ§É(Op°Ä8Ú@ÈLLåvûzÿxbŠd¢B˜Ã20@kኞEÅmš@eöã ÖµT!¢ã8teÉ32ÓÌQTÈGW†ZÅ#Žs|¼Ÿí"iEÞn‹£.dÞ÷óð$fÆDNÂÏVRf‹°€²yö„ýìAâAõœ-ÜH¹ŠÈ²ˆESc,R† fæ´øòúÂLU•)"rÌU{Ø­.J¸¬ê‘ñRd2Ѧ%3g¡ÆŽ‘ΠΓ môî@”Y™³V-T”L3Á2Ì!<5i…O;&PeH‹ÌLÊôR$gœøìÑÇ>jUP­‹VrPNѸ^êR™%-€Ðb˜ÛÔ ˜ÏùO¸*¨ä*„hžîÐá=:ñ{RÜÁ~íÏgûëÙ÷î'¸]ëeU÷öñ8¿oÄeYIxn¬c]tQNw @ 1â8ÇåRo·Kbzº ß®ååmQ „p£1‘,\XÒ"2bô†™”ì‰æ1¬'¹(ÔU=Œ˜fÉ%zw7>›L„~Ž™ˆ6 #s½-²²T\/ŸÁ$Ѭ Šæ¥æ¬ UbX*M#zHl[Y /…´`]ˆÙ·µÔJ"‰ ÀÔ†õ~je¡9)š¢…tô#J;÷Œ&Œ"H¥ªˆöfß¿µû»û`D `=ZÏÖÂm¡2q&Y‡¶{- ØhUKx³ªSkã<f¬²Éñ´cwК=Ÿ»(×EMTX˜˜Ã"ˆ­%(RÂS0…#³wÏ÷.…¶•ò~?Ûé6Ò=HETÍGkǶ•——eÛd­¸¬E)I”çý|ìÇHBs>.וÿ‡ÿç¿hÍ" H†…»ï{óÄ_ÞïþížµÒ¶â~»]äõzAÌŸú9|ÔB¹, ²yãT†Ë¥zúoïß>ž÷oßÞB…·"S¸VEù²½¼¿ßÏþ(×¥!\ÀnÐSIÝâ8ÆÝ:}yý¹r­¬ ]0çú$ 5 ¬n+0ìÇñýûGº¬õ%¶sÈd×<žÛÛ5%´Ê8Çýñ\/­+#çz©£7aJ=Î3!^^¶ôÓÌ,¥”²~¼ßU‚º[__7(`Ù¥0 Û0w7óÇ㘤¯ZVàaÆaµò~<"½c•µ”Ö0£ƒJA¨J‹ba¼”rÛ*£1ÌÑ4Ф cDDH)l~2Qa-ZRÎv>Ý£õ!¥Ff)RžXxI@Ï–ýôHéÙ|@º OؘÛ~ìÓ¢¬\%º3àqžf^Öu!•%JÄ£Ùû@ž¡ôL&aáÌ`¦Þc@m£á´ªJµa™)Ä‘ÃÝ@(¢ô>²qA.ÂGk‘H *º­ê؇`AI¢ÀšH>l( J(ôIâ÷‘î1ƒÓ"Ó”!Ã>gŸ”ŒDœ1ë`IÔäÂg? ÊRiññɃfˆù£%%ErêU!9ÍÑ<ÝÁ"")bú*DB4fB²w# $¥4ÀgÂ3ò½·ïçñxî$b‘m)¯ÛZEž÷Gk¹”úõË˶2ˆ’(ŸíTBúþþ|¿7Áª¤ÓkžàLQ/×Z+0MrtSÌ»®‹*óã­ÃqÚ¾·óÈÞ`ÒìlmBí˜2¼·Þç—y~Ú21<<ÃcdLj„;1@iŽ6 ¾Ü–ZI)/B¯k¹]ázÁµæZq]Y•‰R4.KY«X·ô˜âíºM0â¥,µVõ€µ^˜Ák€Ý"Æåe•…=†È„çÞz‡÷÷öýãxýr]»Ÿu+ææDâ#÷óû·óãã\–-) Qàso÷~œÆª×ËÖÇ™ ïߟ­{@ÖE‰1Ý!{Gë÷ç°lÏfùÜ{kƒ™ˆ’¤Rº§¹)8 ñ¶$ÂLLŸŒXŸ³©÷÷÷튀 ô/ùøö}ï=28-{Ĉì¥Ðå¦/¯EØ…¦“*Z k†A‰ èBÏcÈmÕmþoÿûÿL• ²WË~ìíz]øñv{ÝD²ƒ7³£÷yŒñ܇»-Ûöïÿá·óÈËz[u©,nÞºebQ}}¹~}»\¯úõm{¹–Â9Ïíô $æuÕ„CëªÊ$JZqäñl¿ôsžñþ}>‡!çõe-‚”Ž`×kiçáF*"’ Ä PÔܼ² É¢ZÏóHÀ>|ôN_/ÊJÜ®×uVAHñ÷äoB¦ ëÃÆ8.×EK±¤²”R˜8×¥(áÇû㦶)òvÝ€"²‡÷¥hÑ•¨t3‹ðáT¤T]~üòã¹™ŽS/КMšæ8΀*ªÂEy­ºUQ!DâÅRˆ ðóûl "ܶ‹Vt3ÁŠä$L€6¼ ?ϰ0.b˜%‚r$DLœ3•¢ŸpUÖªŸ] ðpj="€IÜr::ÙÌz?.›®JKÕ”ac4w[V%ÆÖÚ²”ëËÚÏs]6 &„p9[–áPDDA…a©e²íæ"!’0Ã#¢åèi©Yª£Ã±ÇåºX4­ éµönC”d!®@šE9"G÷œ­…éÁ¿Sø`BÈ@ˆÌ{³ÃÉztóHˆî~X$J„‡™A<à B!ìBÉ€Œš ÝrX$T"ÂÎ|”Ò™û~Þ÷vîmôè™T˜ Ô‚oÛ2Ú8;»—m}ýz«Eù¼?!23ÏÞòÏý%–R[kÏæçb1÷ûóôÙ“Ï ƒ4D¸]–Þûèæm¸µŽ™è‘c Ïâ†?¿qìz)‚ÈÈ£ðË à}„w´a !ÉJ%'¶™?Ñ!Ä4ltÁV–|{«ÛB¥”¿þòíýãž0^ß–dGf)Z¸õ`–R˜™˜°rh¥œ}o7DlÞ ]%Óµ`]8Á¶maBBFOD(µ €‡é"ÌdÃ14ŒD ËÉ CN:ûx¿ßIõ?üx½¬çq¼<ÝØÌE±s ó´áž[-…鲬ˆ<úp3 ê™Al‘mtD}>ìãý<{Kˆ©10ëÈÆ/·ËeY)°yK±ÀᣠUÙ†õišŽ~½-ÌÔúðîg‡ð$ -K$îgÀe]ˆrt›Ä–³Ùã°Ö‘´£cR)´\d6±”ååz 7F\u‘dþþ»ÿyáš!HÌ?|ý©¨¶Ñ§x["ǰÌZ¯/+KO8ÓÇeÓ~¸¬ ¥×Ûe]ʈS”ÍzÕª¼(o­RØ0ËuCÎóØ£»J©µFú Äç³9Ð@Ï3!¯—2ÀüÜw!P¢Ì,뺟­oí,*Âõ8GïaæH¸ÔškðÛº`¤)qa±ðg;‡y6<Ü< ˆ-1-/ë†Ð<Í 7KÈ)ÃŒávöî‘"jáè‰Í:)”ʹÃ!’fÛ6ÿø‡Û_——Ë"HJüúR^nõ²-¢îËzyÇóq}¹FïûÄØh\1¨á ÀÎ`΄Sº'œKÅË&c´6NÇ0·ù󨂆DÇn§§Ë*:Üœèèv´*¬/ÛV…‹=Ÿö¾{?¤ˆ(Ý.ÛZ”À¾¼]¾|¹)µTr‹}? ’…Íû~œÏv$‘j1·¤±l¼lâÃiÛt­Åº ƒfé`Óź­%3ŽãDÀ×—×Z¸J !)Ë"½íçq»ÖÊòx?û™žg³} K¹mÂÀŠÉÖý¼Ýnáž$Ê¢Ûmim‡,Ô{û¸ïÃ"ðPæÊU¨þ—ÿ«×ûþñëo¿ìÏýãÛ‡¤luƒ€ëåÅF€Áãþ¬ee–™›fwOwg¥ÖÛãñ(E[ŒªåíËÝŽs ’>úi£oR§"¼[;ÇYTJUë`âëO—m“ú·ú‡÷﬇¹'>î‡Rá¤ô\}>~#´a­01$s$ )´ÔÅÝ—eC©âÎÄU˜2XaXGQsˆ aÑ{¯µˆ°»ŸgŒ°H#ÆZ—I Hy¹ÖÀΈýÌóŒH" *T”)Ìc$#eD8Yϰ|}Ù:`º2@)‚ÄÃÚÃÃFމª"Ê wFz¹½Ï»PÖ¢î–`© Z¥( Òe[S„Â\‰"²›gR!Eޤ0€È:Çù“fÄDéNĤE¶Ka L´¥ÖODðÀãÙ)“˜Y‰YÊdü#Š0¹"APþqÆ4@G´€!Â…%'% Ùí“i¯Lé£cf] 3\ÖÂhÄTª&€{¬ë6N{ÙÞ ¸·B0Ì–Î* ™Ê*Àìàµ#3¨HEÆ"dý _ª,ŠÊÉ‚Q SgY˜%°À²H-¸U© Œˆ3å «J" ”Âì£:s2ePvðGJ"H ˜ü ‘\$«Ž­¶?þa}Y£ß0‡Æp·ð½÷À ‰ëµ"zï=ÏӎöËòåËk¤Y¸ùµ˜›°ôÖ{kûÙº±œçÌçy五*Äéim»ÔeQ¨Ê„À*ðøØÉ£Gµ>Ü=Â=̼W-ÖŒDDˆÁ3<<3 ÍÂ#=¢1¯„DB°–B@™0ÎN@k•Û­œmͯ¯åzÑ*´°VẰkÖ>îÏÀ$ÍeeÕÐÂÏý! "Çy" t³æ£{OrÒ, E´ºðº­3íÆˆfžÀG7äO…$!r{>†§pGqc7¾næÐå·çsDÜÞ¶ZbQ^7Yùñë×ëeyý²†Ÿ„Ä@33z‹rÕfúc;=!“È^_×Z…X(Ü‹Šc%‹0D&%ø06¥@áA,á„—m-Li™¥µóå¶,Uï÷ó8‡AôëR·ÂU‚÷aϳ°@ ³0#"’|x$>žBÜ6½ÞJf¦Ãè¾·nü¿øßþMëÂpœpöDRï°éVœ×åõ²½ «G ?Ýûÿ§?ëµmÝÒô V}Eï}ŒY¬bïsNĉŒt)c$°¨$Ò¦°/¸€ŸÂ\ |øs€Ø™IDFĉ³Ï.ÖZsŽ¢÷¯hc'÷SS³èýûZ{ßçqu¡NÄî,R…%e˜ŠöË×›Îøôúéõé$ž_)$‰«q¢e«Aaˆh)ñZkM c†ß¾ýÔÆ¡®¿,Ý«ïšÓ&¹Ö¥ªzáÙ£ði[^R^˸ß¹5»]"%ADšÛz‘€ð1ZÉ©G 朘èØû±÷óËúáó '¾Ýîf(•ó)?*ë‰Xµi?üøþöÞ21Ô5Y p SDb~ÿúͤˌ®SÌ50Ñ#Ð Íüáì6 >ýAâDÊÛz^·ÓÔ™…(Žvó˜ðÐ —œ·ºœ—u­)‚a„"à\Ff@ÂAþt8*%¯E"<Æœ€H(À9aJ°®R«””²¤ð@᦮¶-[­Œ0‰üÁ„”Q‘T˜…ˆT™o7c"¡”$¥ÄKI‰bÉ=1Ìs¦”œ)já’À}l53X-–Äuö_‹ @ð@†êëy-‚í¸Kâ ,‰³ „¡¹ †A¦þèœÑt ´Çû˜|hw@"‘_O5ë ' `ÆÇ°N2±ÏA¡Ã] ‘(±#ø]M5áZ¢äö|‚ç“÷ÛÛ{PRµÑ‡z½9{Ye]åù”Ï«ôc¶>Z;êRž^O"8gs3 —,F[³ m6E˜‚îï¢$‚Ä”ÊCÝ™¤”4ÆŽµŠkôœmÞn‡;E°Ncʈ¹·pãÄE§­%ÞDäá}p3cC„9]gLs°€aä6?ÄÍlL=Žý‡“¾<—µÄo>¿¼œëóšï÷ö~Ù-çhz¹ímh.ËÇç§ÄàÚ“¹š33!¹[ï]§ƒ,µ2#…ŸjM˜$Ä&üøã/·Û$ZÛt@LKI¥ˆMدæ&½ckÁH4Ôšw+)=¬Ó6§ªŽaÛvÊ^6Äýù)½<­:8ž·§Ñ‡dn‡ëÀÑ•‘H-4âÚ>§?ZѦD’DÜǺ$›ASQÍJÊ•är¿£¤ÑèØƒpŸÓœ¢”Õ,n·û}ßÁ÷ëÝ,¸–m9'ºí{ lëz^NBFÉK* 1M;Z?~þñˇ¯½Ÿ?úá?lë)1•Dä%U¾íÇõzYI=¦ŽR2F¸:"?\MÛ¶Îq Âûû[{*Œ·[k}ÞöošQj®”Q®²U©SÛ—_þ—ºçÑç>ÆÛõø×ÿêÇÐúéã¶­0Æ€¹"tw’4昪€lS-fÁ1G›#„re³Áˆ LÈ$4Çp7¡ŒætŒ°9}Žîh˜ !%Æ¥¦”%g"$òðmMkI™1$‚ˆJ’„ˆ…ùqÌC ¡$$‰y̑ʒR²þ¡»¨9{ f•,H`Ñ£g–œA)lk"Ò’ÑC„81‚ª,™…],…Ïpj:»©Î>0PT¥µG›,dèZj^k0Õ£ž9¦Ú¾wð@Àp;V¡Ói)¥Øàn:#œ…!¨õ)œg×èÆr~S‚j),@ 1éÑ5eJÌ®½§,þ@:3¸G<Øsl“Ѓ1’ "Ρ¨fâßsÒóÊ‚íãkɤàsßÛ½yßo#.{7×€‚T ¦H‰ŸÎ[kã§/_/ûL)?=ŸëZ޹¿ß®I$³D R;Æ×·k×d¡zùÖŽ6^^Ïu%)~Œ›ˆ/+iJ@è !ºyk³wYF÷vh6õч›Ñã&Tq"ƒ05U7s¬P!ÀBÇA$@Õù(T?jYáx¦>ÿîe]Ä$‚Ç•ú~;ön÷6‹ä˜³V&‘iíõ¹.2‘£›œ $À%×ðà„eËH¶·÷ÓsþüݳÀƒð*\ÙÂëõØw}¿í¥Êº<œf·oýýË J„¶,eïûqô9‡j„N Qvŧó²n”3>7SŸch-…œç°ýÞà ̄yèdá{;¸”{ÛI .D„RR†0õN‚tŒ¹·6ç 3hm # ˜‡ßnc?g©‹äŠÛZ3‹NCÕã> ”¼Iâ:úh}Ìm[OË f³¦>êZR"‚¨¹>A~:ñóÓ)Lô–”Q’£9Æ~?LŠœ3þßÿÿë©s¨MJ˜`oiÑFí>×e9Ÿ6WÂde«êCûÈ9‘ ºÝö;‹¤T¾üôõóÇO÷û±žŸZïëº<=/£·5­EjÉyêè³_.×û½-÷v8@ßÇi9øø´ï—‡mšCìG#ÀLˆ µ8G°APâ%åòó—? Ñùt&Œ9f–œ$‰"Lë½G*2ç‰'˜¸‚+ :’Ló·ëûËës¢ð1«Ni„7Ó $U3×øvy_ê™BN+,)æŒá¨j £¦b—”´$!õ@‘ÀH æ8Ц $7C…™…h4bÆR1"bF`F0@‘¤0@€m«@Î6G*eÜ›FȾ7BÊY"LgJës̉D©M?†ºÛy[ẗ „’EœÂ=( =®üè­wÌ…)DÄ<‚fø”Ã&2¼½_ûð——×$ÎdBÄÄ$ Éݧïmnçga™ª½ùPjËVúù§ë>–ZRÎ@9…Ætð’ ?®€Œª1›‡CŽ©)åTÑ"¼–•¢´cÒ¯’1wÇ9ˆ1‚dy›áÑt¤\bÚ¶®9ƒª™šÙÃ9Ê ÈºBðÞ‡ûƒ.‰‚l:I<݉ÃÝ8ã¶ðVR`öÖû~¨¹µá ÷6ÍÑx®Yr”X°µ ¿üüÎR>~8mKñÙÛh”¹Oצk]±£íˆHû1Í ל·s˜¹0"½‹ÐiÛÌTm†kÎá½OîÃRfwãŸ~z+)?JHÁ‰$ƒ«‚…{°[ôÞr&@0©Ù†ƒâè Ì4U,'ùôáÅÍö~˜uáœóiÛöëîslÛʉ~þúm?œHæ4J"ß·mO¢qÏK®ûµmO§oǽ¦Ôîãa~ã„@ ä”9D(isÀ ñÓ—/½yJ‰K圩äìÓãç_ŽËû#C‡Â,B뺼ïocts=­Ëé´¥">)B"šDó±»ÚÖo÷æ“Àrk0ŒG?-çèÛºNu@:’°+B’Rn÷ûhúÞ®©¤Þƒ–´$¢ûû¹Üé„çSþÍw/mÜœrÃ"¹õn¨×û{]“pu«}Ib­Rs23¾¿·°Aw‡À1æ~ sVuДàÃë0†$䄆„5±¶1ºEüŠXé£ñÿò?úÝœÓ $=6~@ǽŠZ¬ËóçÏß… ³ùXyÎ1fëèî1-¦"%ˆ÷1žŸž#†Øó‰îû»¹þÿúo.—ÝÝŽý²‘R~üòõùåU$­ëúüòüúñuoocô®3˜²$b¦R 1ª;2ö1ÕÙÍ q?n/_ʲpâ®GÓÙF6»N cb³Ñû1u$‘½íëº%NǽM…0$äç—óÐnîr3 ‹l{gLá§’ÖB$úòRE(QÒ ’–”‹:æ]8 KÄ\×µ7õéH0TUbÙ–À~h§\PƒH"‚1ÙÝæNóõP÷‡ìØUÃÔM‡M›æ: ÀL‘¨Ô’Ï[ZVJ•ŽÑˆH‡.e©’ ü軈 A.Œä,0]÷Ñ>Ì¡¤Dád”K1wfFG@› ŽÂ!@ûq0cÌ)׺2‰«eNL4ltd9aÊè·~üí~PçÖÛqܺ÷ÛÌ´o5ÿá„F¨r=ج¡†nªfFÌžX(%^jI "TÂýv03‰NUF†$®Bøˆ×1#&NDäîðè@A„¢¸¤ìFhF". #eæÌ€„±A¸‡0å„OOòò’jòšì¸Ý.mÌû}ïCáâ©©?Ê*%ÓRE„´co÷ûý»O_·š„öûíòþ¶,µæ‚`‰Ùæ4·´¦¼ ,)‡{Jüô¼m§ZrRm,ž+­§R ‹€ÎÖZïÇô6½«¥\°÷>M)‹ú†”9§‡‚^¬í}ô‡§Ì¦úA÷ðGÓpHLfŠÊ s +UX ¢¿>-KæÄT“¼žêç—§LtŒþõýÛzZ_ž_ö[ëm¶>šîO/ËR‘0%Àœ²"!UG x4õxYVW…}7Wz¿Þ¾]Ž{G ZÖ” Îe]¸$ª… ÷þ¾õ}ª‡³”¡6æÌ%­¾ûtúóï__žN£Û­B)¼m9gÞ÷½,+W®›Œ©ûUg‹1qïñvïÇÐp¾ßûœf®Ä˜HFŸ˜ÝÕlºÐÃRQW©™k΋”D| ¨c6Akaw»íív¨{,Û )Š@æ ÷㘮¥$&Ù1¦_¯G;üèCCMÁ»\Þõ~xkÚZz¹PÕ>§ J‚"¹Äº"c `¸ï÷ñþmçÿù?ÿ‹@§,L”¸«„…¦Lha#æ}´[ë_¾¼¹áVN™$!aHÛM ´»ÞÞEN©J’$ôü|* Ó¶dBøøñ#":¨»÷>#$qÇýåéT“ÌvôãŽÄ!¹¤ûý~ŒÑÆtw&J™s•R¦¹š×ZÍ!TçÃXRð\'L™@uFJ¼Öµ.2¡:œ)ËZ¾~{¯¥’’²ô®®ˆ@ýh\¸Ä ô@Sb2wF&D3mª st7M˜ÃÓÑg›ayªßÿîóŸßŽûãçÌX„d¿ße£¤Â(¬fHLœ„Q„˜ ðßrÄÐÃÑ‘~rd Tó˜ÓÍ0åTž¶E@CCØ4"ru7À¿ûãŸr*UReªÄ:4 ¯5xÙ²ø¶Iݸùa`Óí¨ƒÐðI”dA’1›™ —pŒI·÷>GÈ)—Âì>Z?–ZsÊø(mš¹p}ýð¡ɉ{?RΓÙÌ»ÙíXK^SÎL™éÁˆ!$ÌE‚ Í1 Æ  &JÜ{#t¯éÑbΣõ"bÓÉñùü*9yŒZa “›–D˜–Ê"•;$&D Ó˜c ‰à’kÉå´,s¶Rd gŒB"àŸ^·ç‹ÌÌÑn·9ÇÑúÞÔ‘o{;<ŒRŸ®îjóá`’µÒZt8ëôéñù»ç5 ºë¼íÀ8žJY™²™§”ujfÌè³+9eJ[Y–R  eq™2 ™ûD„÷Ëíò~Ý3 $æmYMç˜ÃÁEäh-e΄N€ˆœRÕ1L‰LY[aÎ( †à ^“üZDJ‚5‘pPhJøá¼l‰ C’ô`ôÃÑïûl÷¶K¦×§¼®ùç¯?Õ-½|\?¨OçÖÃ4ÔS*w"J-¥Œ¨Ë&Â&¢cæ‚Àsª¹s–®jŠ%åçSÍ ‘MÝڰ뵿]FW’².K>Úûé$>œ³Ài+5¥cß¿}yK¹:`.üô”só΂Ȣa­õëeŽÉÒìÝï]{ŸnCÇô`Îît4ÓˆD$ï{›3¦Z͹æ\kBÖRd[ª;9¬KÍ,£wF¾ïǽ0LƒÆiÉ`#Üzë·ÃÔiuµ°€>áò¶k‡ý:fð¬ÄƒšE·bI)< œ‘Yušs.©VAç€î íÞcÞö¡A Èÿü?ü3‘3ÑÙnû×ð‰.( Ó}¿P…a‚ø|>oë†@ÇhÆq;ö> ™ÍQ§ýòÞ»Òåýv»ì³Y‚ÔŽ:Pˆ’ª?t"þôáåË·/û}ÿío~ûþõMÍ¿ûô!ˆ0 P’ºlÇ¡Ep»ßŽm]½dQ"GSG0ЉaÀˆÌÈHiYŽif ÓÔ»dFŒÙ†®EJÉ€X—¢³ §Ñ4IA \ÊÐŽˆB⊮dŠ ‚oËš3“› Hæ˜YjÁ¨·7ýýoÿâýþ‹Æ. -ìè’’è tÄêáö@:š>EGÓÙÔï·;#Öuq˜u“õ´ ±š9„;Ž¡ªžêr¨ß‡N³º¬ÇýÞŽŽªÊÄ) ‘£!tÓk»7í Œ"x^²†&bv̲wãÄÌ¡ó¨’áz»# Qv§Þ§‚“jH’å\€ ºhg×d»åT’Pffä9ýíÛý¶ë1†F]ÊÓÓ²®Èÿ‹ÿè ÛDxd¦cNs| ’p¨Q`ÎÉ1fL…Ù­#Q]ª$@ É” ךÎ[•DÀÂá8G•ZÎß¾^ÜœõA´iýöþ¶¬u9Õý¸mk­+ýí¿ù›×óëiÛHb;­ˆ^OeÙ2ò 8Žvß÷7›þ˜Ã†ûÔcF„XÀ4ëÃÛ1Ð!T®é6R@ Nû·\·—~Œ¥V× ñ€ä¿ÿû?_^DH˜~ùö^×Ü| c$pƒ~ ¦,”€80bÎfÑF\‚: "3¹¹N'à’ "„1¦Ìm.§lj„nKÍC‡Hz¨ØqSUðG¤ ºDW›è¦¿>ìk©ëºÖ%%Œhç§U5g&„’Êi݀ė¼lk  ‘ÌØÔl(„Ó\V>ŸË²ÐHdœ’ÉJ\°¬ŒÉ‡N"É:áïþöËlï7cæRØÜú®äÙ”ï{Û÷fÐP€êÃôH’hhëfc*! ºÕ\–R,1 '"wó~ !ɉÁÁÜÍÂýx\Ý qr_AÿDH(Âçm‘0„éæ,)‰€!£Oô¹d~$>ÏëšH2Sò1mºN¿ß[ï*Rû´þXÉiL{X͕ݱŸôøótu‘uMçÓzÜFê=n׎̟?¿¶~½¼ûå—·iè÷û…J·ÛΜn·‘Âl-)gtÔ_ª­VJf†D3 ,ÀœZS5ÿÿ[YúÔ9aŒ˜ÍûP&Hs*¹QëzoG°ÂÈ)¹{fP»¾·Þh°dZÖŠèYð´”óR2#!¬ËæFa”…"æoÿì“ZÂGŒýíÒYÖ>%ÁZqÛh[%\‰%ÿŠ¿æð0sgIëº ˆë`â0.yýôéc­ù~¿½]¾¦%1@NeÛ6„GºE„ ‚÷C§ÆhÚáæ_NÿÎ_~ÞÜæôD=48¥œp)òx¯ÖÖÃ÷ûÀH½ù˜Ãöî¤S "  xh·~èhfž •”À F·ý˜­›Ž1÷q죡ˆ)—m˜¡…Õ*ÏOkN,B4†^öãz?$e›#'ª5‰pI¹Ýçý:„ "¥,€ A¢"œ0–Ä™NŒ}à€IDAT#̵Ûè: @®"ˆnvk‡ 68gGäDC§C#ñÿê?þKf`†1Þ^–- $11„[Ä£Rˆ8u0#Ô’™iŽa)I€­k–„È®1Ôt˜ ôÑÆˆà×c‚ѸgfÄdî$d¦îÓËR~~û%/Éæ|LŒãöt^·%Z]Ò²ÖÇ‚—K2€1•Y’°…»©N „`÷JI²ªÐÔØïÝœæ 5l‡ÛéLèLQ“”B¥ j:? ¡¶†’ò°~>m`¤¨‡Tùúå-suC$RÂL„àá"Èž#„™™Ï9 ÙÌEäQ)>Ž!\µû²=½_n·# 1gÀ_¥Idà€!D,ä @á¡ê`@ΉR¨kWsÓÆê§_Þn%ÑRùûï_ϧúáõ„Ñ_^¶çsýî»ç—çõË/ß~óÝGð¡{gãOOú>Ç@ä H ¢ìGëh$€±Ú ƒ„[^ø´–§­,9…Ë<9áùiÀ,¥HB0@­% ±N›SMƒA‘Ä8IЖŸÄŠOtp¨µÄ£ÑSXÎërZK&b ×ósX A8¡€¡™AŸG¸gÎsX;º°$¡œätÚ\J´¤DÈIDR‚œ¨$öÄP³•’ÄôÐðœÊC¦ªŽ8=¤íöí­\HsæóiЇÄe­‚£Šdª§”7úð²=×,)%! (‚—’rå‡*±ÿ³þ;›ê6 aY–ö»äá’pzË¥ {x(ήa®CÁht ЩÇmßo»»†óJ(£ïcÞK•Ñ÷@AƳžm†Pâ æèj‚Å=N/ íûµ7ë}lëŠooï)K.ÒÆž‹¬çÓT­µ Äé¼m?z/uI™‰ÈÝ‡Ž‰Hí˜á©ÔsS•R4Âuz¨.ia$ÀŽ©³NL) Ýn×§ÓÙÀÇa\r¹½ßn·; ¯õ<[,ùtaŽéÍ\‘()ˆƒÐ) ˆP(Iby˜e§*£h÷˜N’ Rl¹˜aJŢº>,±Ëº>¦<‰ž <$ãîÐÇD ÓòTËๅa(Ž}Ö\sABÓÙg×ûåx9¿&&JHíù5¯k¼¾.¯ÏÛi«ÛsM‹”-¯[¹^Þù1 ÁdšöÛ(©ö}º’HRU¤È™C‡éX*ý£?{ùðœKbŸŽFn(,ç5‰”MÀ8Î61P8=&]–0ÿÅoþñ)ŸcÂ~¿©ID –3ELÀŠ”d]¶’XR C©E2Ö•9#%!H๔óËéõ·Ÿ¾ÿøò‰úòóÞîfà(Hðô´Îy@XWM9©ykózë~Vk °ELs€`!5›>‡©F8’d$ôæ$˜…NÛzÚ ¡×$¦±í~´?ÿíïÿÛÿ­ºm2lßß.·ý?|yz}^–jc–¥>øBéùùùùù\kBU?šµ¥œ…¨$dB ”½Ù¡¶HÇÑãQ6éjÓbÆ£çfÁèÄÎ90ƒ'”1•ÐN[*ŒD(aÆ,û~¸ÂlîËš·3?ñéL瓬•_Oky¸`‰kÉ€F%B¦T*kRï׋:ÐûmŸSç²°×%†gp&Jct!®)å\Ý©æõÑ4 4H"ÌùzÛ¯÷¸ÞšHÊ)%¦RÎ{ŸGo—#¸\övŒIÉ9û>†¦,Ÿ>m§)X¨í‰ÕF¦6ÝÍÜç|°Jý>އžtLèÍGÕðˆÛÑI!§”JN¥ä9G Çîjà§Ó²¬UÍǘ÷û¾·vÌÑÆ `¡\¯÷£õ±”…á鼘ÇR²O upaÚêÂ1ÕÁ@8!pëã:îyeIHá ƒ‰ÊíÒƒæô£O”JRðéi}Þˆ©nž„«0!¢bb(pP˜9-ÿ“ÿüâªhª±¤%"$£dbdìÇ€p&xxà€Ié,Ž¥œJÎG)õv›Ï/ϻƀˆ|¿w”ÄLu†p. f)%UM5­/ëÉ<Ü58)¥ î AЇ dGe­3US©{;ÀÂÕÐ,FØÔ‘S† pDw@Œ1&qÂÂ)L§Ç âÙ1ÅRQ×@s„¡G’GÒ{Ó1úéi}¨SF SUÁ²Ì9€È|Žóº` c„E€C­ °-\Ó×Ë% §>†AY2õ1ÔUÈI‡3ñT‘œ²‡ëaSFrb2fú·8Ÿ–e!wÍRÎëËœ# Þ/c­ç픾\zy9…NóÀu]Æì’ˆ ,iNïÍ/o  ­̵ff6uJd€½dFC0úüá3~ýv¹7Sƒ­™}ÍÜ^ŸO% @º¼ßSJæj1©`áÍüíç?[ÊúþvýÓÚÛu9§¼Ð´{.9‰I23˜E˜!8kS$y~~}=¼^n÷Þ÷}ßÛÌ)QDï:#BPlZh¤Lœ°ë$à —ÛÕ™Ke@D&>ŽcYÖÊŒh)•ë½û¯zG L€dx:ŸZïCÍÍÝ•S*³œ>¾~ØßÞüáË7üíÚ/·÷Óy©’Ï뉎qÜûýÓyÎ@ÙÜûìªá®Ÿ>>‡)¸Lj° ÁÓÔ1ÐùýÛˆÀÌ"è'yExÎ1u:‡,R §¯ï7áºUÎ)€ OGÀ½Ï6•%áJ¶ÔôúzR퀺ÕJfN9µ9Ô5 3âRKJL€­ÃÇ­5”5œþéàØ¶úá圉ÖRöûµÖ<Ç,¥Šp‘ÚqÙo¾­år¹Ðé´¶~$7F’ôírÿÃÞ®ûLë’$ž·üüœ‰u*~ý¦¦ØÇýÇí»ïÏCçìî$)‰çš¨æ‚)Zß¾Îð2µ?7dx¿¼›AÎkJËûí2ç\ 8úœÍgƒ¡ÑMs~”Šç²Ôãh­Ç½õa áO§@€ÙËÓÓœjáxìã²÷÷Ë=qzÚÖ°‘râ’Æ¾—çÓ¹”¥èK‘¥¤Ù§k\o£·þòüñ§_¾s`bBš]ea`œS{Ÿˆ,È¥¬÷}èp†°eã§çÊá^Ò"@Çè—Û‰0 {@ïJ”Í}jלKŸ,>P 0†«…¹ј Ä À)¢zÄð„á˜8y A&`@OÌëíÀ0¸ìK>Ýß.©À˜˜º·k]O÷[+’DpN DþæÓ1'³»à‰õôtZ5úºÐŸ~ùöíÚ—u=¬eÆÖµTœªÌ✕‚´6úÝü'wI)g"˜Öûœ—¼pµ™rSu6HŠáÄ|º»%C05Sm}ff”îÀœyªa¡è4äH9E(…ÙpGÈaᜉÌmNÇš+„Ï>`Ë‚©zàíºmÏIvíR9—ÚJÅTRk IÆÖì1á„鉅Â]ç‘s’%Ùò£è3XˆÃ!¼7ÕÏÛ¹ïsŽÞ)츖BàQ6‘¢‘íÃ놌”î×ööË.Ì’-Wö˜eI˜+–>|~šD¶ÑÕ'AdÁz>o/ŸNÿú¯ÿ…Ï©jAlÇ1{Ì,Rzÿz!’œ©nå\è/Ÿÿ¼õÖû^[3Ü֜Ó;@(P|yÿái}ª‹üîw¯ï׌ sÁ ˆ¤910³äe¨#’šéÉç€Ëm¿¼]ÑÕ1RIÏkI‚f2ƒ÷6zkÌ 6š…ãÞÛ}ö—×óùuSSˆÈÂu³i³S^M5tBИªˆP–:u2@$””ÓýzápdNÌ@Dí˜çíÓ§çï[{ÿúöóm¾ÿôõ—·«{\ϧú_?ƒ‚¾_o’òv*ÛS “>ýöþžŸNÅÅ·uaž$8‡iȨ—ÛqÛÍ•˜‰…CgÆt´1ÝSµ)IHz pBhGÄ,+X}Z}ô îÄ”™“¤¥PÍX¤¸ifJ”·Óó‡çó×/?Ëš]ª˜…öQÊ’’@À>ÆíØÆù|n{ŒŸ?|&Q&}^ŠÝïmo÷å$T%]®7ÏÔGMA͉‘·mÛ÷+ >d|ÂÙ&0çá‡Çˆ‰Hnxôãùù|ýöíTk©Ì”ŸŸ>:úÏï?©¹pI¥Üî7’8î÷çóËœ cª=ÿv«¯×övm?y Ì "A©zÐ!Tz§õÉT# µ©îžR3e&nGC S À0Ä Œ‡B} ûÃáEDLÈH È„êhŠ)oŒ¸®ë÷E^$å/_ÿîíòw"Í5tv5ê°÷ð0B¶Iï‹)£Ù€ÌnÆÀb†fn3ÐÌ84A×µª*€„¸cÔ\©uõ€ÄLHµ”С\â˜÷/ïïcz-e«®cøPêÛÓðkû!B§…E”” ,Uª)3Ðöv¹ÃjYïû¸ãh¢Ìé`‰ $ùœ#¥Åìa#ˆ¥Taž¦—}W‡\}ÉÈ ”ù´ÖS­ûåFAÀŽˆI¸&òšÙgû’°Äi[Èý㇗··¯]û1æíÖ Ó§OŸç—ûû²7u±-ççóóûû·1÷§çE昒D¾]oYXL±wµ)£ºµÝ d]µÞCï÷ÖÛLÌ¥dGAâm)Þ»2þðË/¹Èëiý‹ßþæÇ?ý`!cš$ûôú¬Ãg(Bè´Ñ !Llͦ£z"`„¼lG·ã ‡,‰ÕýÚ§M[R®µ¶9l©Ü|ÝÛ~ïƒ8bItÞ*"šE?ÚÓÓI„ÝðËÛÅCŸÎ™Ð®÷‰°Ýïj1×…ŸÏ‹$ bÞïÝFDàù|fAµ>ÍÝx¨ ‡QbÎ%Ý}N5}Î1¥,Hïïûq³1]×¥xØãÎwÚj©bsŠäcomöáZj dŸ£$éªmLAH€4õøv=¦šN}9U'Œ6 F¦É ‰@s&œc0‹;êTä\ïý.À "`)tbÒ9ÜÐuO\€Áƒ¢.)ÆèYÄÚ^kžh>CàòõÁj/¹I·Ëåõéüv»ÿåïÿ lNÝs‘Ñç­µËýÐøu¤ Š0‡2J.ü’—uŸ¡Þ¯UQ3 LÒÎI$ ÆT2õˆh袘E2ÃoóùPÎx¿½›’ËœÇo¾ÿ¦Cû¥Í®ãõË$ž£ŸNkæúÓ?ü¼nÛzÚú˜ï×k†j6Öss7$¤ºdCEÊíØUõQ£”xhЋ¤’йMuH<æ waAD ¢ðª…DÁ1ç¿ù›?ä´þî7ß#tN:߯ïåi%@à8\ÇÞ×¥°Ðyáôûøø»íŸü»ßÑqüývŠàôHÆWzÎiÝN[ÀüvùùO_þƒîÊBCBN\‚(x€¾VøÊ™À×Ne÷Pe3õðR+;CzºX€(œV¢dn®S{P8ùD{x«GÛÉ|gˆÃ¾üðÇú¼ è˜ ÁLXŠÔ² öeEd`b×¢SJ)‹TŸît{?bb˜§ÁœjÑG³" aDIè!>¡d&uDD,R>lß§ôôv»ü«¿þÿ¬ ~ú¸EÔÑ’ØëóKï}Nõ§Ó‰ ½Çû·/ªöt:ƒç‡êÖs¦>Ý T >‡ÿôó¥iL‘5 `X¸%ˆˆPSIËýØs–š2>Vîæî3ˆ!Q87‹y,)-[bBóÃÝÏçs0ÓÖ¡Jœ0-é¶_ã#Ÿ½íózL‚ªí~»30["‚}î’Fïï—,…qM‚„:ûƒø}¾ÞîªÇãùõ¤f¥fÈKùéç÷1ÍB=Œ·º´6Úî)‹·½=?=µhEÒ?ýýï^žW}'¢ÌuK$2Á”KÊrDKUKY¿¾ÍËÑçŒçççpo{Ûo]R&ˆ5¯—>û˜-2HN³ÛT£Lî¡h8‘|ªŠðºsí¸¿¾<•¥ÇN(uY±$ ‚8ULe¡Ì’s=vML$ sšMšÛšÁ§ÚÌ93ÏIÇÑÜééü,² MMU…œ™$å9éÛ·^ò’’Ì0_j„Rž÷s÷i³«FaPv –iuÂýhæÁÄ<5 UuWŒY…·’kNò‡Ÿ~V³RëqŒÓy­5=€ŽD²$™Ã‰0Buаù Dt 1& »‡Hªk½í-&€QÊih Poêf#AÀ#®®a4]8±$‘Ì€KsB¨Y°¸Î,~´#ˆÈã’mÎý}gÛ—ÛÓi)”maÜJžmæ>›é·Ëå*Ìî6Í&qLB ßÖ $9/ªW JE\ՌРYr›QÓ`$ˆš–§‚LMÐÀ»$I)¨ç©óÖö÷}ß–u¿¼-ÛË–DJefèÀùå¼9ô6Ûý¾Û ‘b©P~>úès"2> ç”1@'vN”KîCë’ Ý¢,îWM§âôèƒ|÷éÓiËq?Þ×¥‚Òˆæ=Ì|ÉkâRxÙ˜ä»s„lÏ¿üt?­ùÓËÇSMK]PR>-íxclûÿüò>$Pà£uÂ0‘5̼¹á¯=ŒL‡á¯\ D¶»B Æ£ᎀ„±3±º‰qèCdYl0#ƒ¸i}LÃ(îD€4‰I͎ㆄ§—ô±|>oO)çõôlæÓ­õyL›÷ý6‡a^÷»Ïg0Ñ·Ë/ííò‡õ\ìÃókö$œ‡ÇðÇGSwcäÖš‡wkª±2k¬râ´„ 9ÚÔ/ïû§÷ŸÖOøá9#î(!\jŸnái©5‰Ž>•x,‹D¤RdŽá„îPs¾í—owøð|BoßîòòrB ÞÝ4àA÷¦ ßÛ^—ê3À<–Rœt™“»Ïm%JIræ~Œ’h[’¤$©{a7 '–*nÀYžžžÿõ¿ù›z*ççõ—÷·140-Y–ÂӼŬ׷1ÌÐ+s–œ"`ßûåÒò"?}ù%S­|šs›C5'2µTk›½É\?ÿîÃ誦1\$$ÃùDÛö|¿ê?}Y×Óõ혧§’“ß.—ÄÈ)?Ï™SI0~üùËp¦YŒÀá8®½!12š–œƒØ‰Ú´³÷£µˆÈäµ*‹PÒÑ §@ m§óf•Ôœ9•-±%ÓœM{ëAC‘®×ƒ²¤"R¸d&¢9LƒÄsöœ‰r:]ÞÚíÒ¶õô´±Ok|»¿»$IŒ4 Áô`&¨‚Ì0)qbHIÀ#8qÊ,,L´&jÇq‹‰¦%eIÙÃÁpŒÐ®: ‰l©Uƒ…~Éà$ Šÿûÿô?$¢R$åèþo%ÚŒ¤Ã¦F}ÀÔæŒ”ÀuD’HšêLÉÜ™ÁÝ "aJ’ú¯ „ Œæ a0?  1‘éÌ%!“£«A<¦™>§ Bk=¥YR?½¸9Dl[ñÐ÷÷«Nøz¹{Z²œô>"ôûß|dš"±.l6Áu«)Â$¯ÿðÃ7LËå~,u»^üéÃË F äÚ»J*:õ~;Ž},u €fûù9½<åsYØù—¯o$ÉïGW£ÏMR)I¶êª b-Éu\ïwªU'¸bÐOK©kæ½w¬©@àußocl§S";îï/_KY~ùé Szy~bPN¼÷#@g £ ѧM©Tsñwh²àì çpÚÛ ä$’mö÷÷+¦L’²ä0W›{ï±ÔÌæzôÎ,èfŽ„è)?J(:îµ&NNý8<êR‡ªàe¿çDËRÝmαԒ@E›u•’3§ó¡1ÌzƒƒÁzŸY¤<[9—uÙ.·_€3´y$cÉ‘’˜>ÁÜøÁs~„tzÛ!„#Px ½øµ5Ia9¥’Òé´õ>+ñwŸ>;üôÓÛ’ÓŠ"ðáeñ á.)ʲ´ÁÂb 9 ˜zQÓ9]t:"¨˜ÇíØçÏ—oÏ/“S)?nÀI¼]By)´ÔÍÀµw$2÷1-—²méëׯOÏ'á@Ö×Óâž™-éý6€ùÓÓúñõÄHÈŒEҚΰžùüÝËpç,ªz»^§S‰È9Dív £«‚œX å"BAªs̃„[oízLõ\$-â¦ýÛ— }ùA‡vG=oÏ’ÒÞ!Ë×É"Àò(…“×ÌH„îè’ópbžfsö`bšsº:ƒ "%Ò0ÓI€(97õº,ˆáÃ8Ôš-—E„€rZÓ$©¥æ¼Q;îG¿ÍÙE$çjsêZW"i×ËëëÙlŽq5‹©ïˆàÁ€D8Ý‘‰˜Ð!úT Jœr7­[25hèD”ž××9¦$šc/§øøœf<„aÌ “‰$2“00çúþþîÓC ‚9§>±sï­”%„IjêmÜ®o†@˜.zsJ0õ‘0t–(¥fIAÆ"æ#1 ™ÂºäZEu˜ªpbN’ «5‡1³HBp€`G00avÕD2¦ö9ð8öÞ€¸æ’¶ZÅá°hQò¢½gNŒ¨ªêf3DRŸH)•£õÖ:KÎ¥˜:£ 02‚önRÉ“HLp@@!UÍE4Ž\(\Õz^KP B@DâüÀY¤œâr$tdñ¡æŽlcvvŽ!æXDjá Üt†¶À¾·Z3àÔL)õ9tz‘äª]wõ>õÐ62-͈"âò~™Íÿêßù«Ñ¢Öš2'133ss>zÔõ5å™ùáUsôqÛû·T“‘Sq#H¼ºzx1lˆpäê €ìFúÓÏ·û‘DbÚt˜6çì=/Ï÷Öî½%¦­®\ÒÏ?ÓLƒPÊ–Ç1¬{N¹ë°ðÞ›&Áe)µTW3dp7Dpð1u©%bx Ÿ¶"âH31D˜ç’(Ë ½|}{>}´éZ+avª¹ €»OÓÑZI¢®·{ÿõÊ(º·ŽF0ýûÏ·SýáOt#5žfeMH~¿ô¿ûÃår¯/O9GIi)ùô”ëCïÄŒ‰Ô“duCzж½µÞÇI£9U’Ü—šJ*¶ÏBúúñä)1bLí0Õåçïýo¾˜zzY™b΀€An`t:Uĸûœþíí*«„½œ¶§e%w"` ìcZ(Ã|ÚòŒ0N½MífÓKY€cÌy»L9øÃÇÓ~@¨5óZÊZ6Ðm^»aãi‘”ä~×ËõþñÓy)÷9‘t[¸Í~þñòí:¤œöû=üð²œN5LcJÊ)•Ëå¶·Náà8:€’Záƒf3–L)SYIØ Û’ùè}ꨵ€ª÷Ù¦’J`€þgÿ—v´ûÓËÉܧº«&IDìîsÌ9DzlL@0gŒTDU‰$¥¢s#öiˆDˆ„€n¡æÄŒ1u­…')p; B 4×5búl «kx¸$17÷p ÷°ˆ©&¥p rÏŽôpB˜9“äZo÷ƒ"ÂÐ ?¼~Þ÷Ë´îáC=I~Ú¶šSÍeÙN}ŒßþæezÿùÛO¹”m;Ýïï%•ǾÀͨf$Eâãî˲$BÇ9q" x*)*qä*Ëy{êãH…ýv»õѻμU Ÿn:ç(¹¸Æ§ßÿñïÿDè@q¹]Dòºž[»kØÞ3Í’Ý4°0b ðDI0™=Ϋˆ &,s*!H8y@JüðW01LÂx$×áážvw æôP¥À˜#Ü™¥–‚€„@ˆHD@fÄH„ÌlD£3@ XhFøãŒ‰@8  ª €0§ p$ÀºžÜaΉ¡,)ˆ-"Â)Ì(ùaЩYVÆ$Bˆ¡:<ȇ©‡1#¨…‡!1ÃfD€üö!a.9C "ø„²¼ ŸÑ3ƒ”¼‰T¡aêGßÿæïÿÕ_ÿá_ ß-"ñº-¥”¾TšÃ¦)åÌèJñ4 æÒ{½9'@ž}0„ßM\¦šr„À¿üë¿>T'ÄýÖÍœèñ“I4Ž˜eÙ¤`F€mgÂTÒ´‰DnþPàÞ{Êe­ \ŸN˲’&&FAà½_ƒEr©mïµÔ­5]Þ¿‚@­¹–ôPØ`15íGÞN ÑÜöq<·U* xûz9?½Á×÷w7@"ßNËq?þþï¿ì‡‹”/§u!)T 1Ú¶–}¿·u]Fï_~y#”Ó‡3B$Ir»´º#âhûœ &ðQ—•8mO9Bo·ÝÝÌ úÃ<çí—_.Kx¹¼ !‰Ž\`Y÷‡1Ôêzê³ }ªÚû’ÓëÓ9ÌÀmÝNîþo5iÀ J .Çýè} ¦|»÷·¯G’üü’—š`[Y²3cÈìÑúq\j2o"2m¬+‡E®ɳ„ÏþvØú äRJ;&¸ÎÓZOÛbfS0Ýïóýýz?æéô„ˆ ÀC {zÝjÅ’S€F躞ˆj÷a=Sòéû}ϹŠHÊ, øŸþÿc8n÷-ŸŸÏŸ¾¼}#æôiŠÌlŽí§²A„á·û%aB$…ðRŠí`Â,‚€”¤NŠˆ"B$cª#F8›ck€Ë‚„j32Ó¡Ú‘™˜Ýóׯoê¶O$ŒA~z:éè>8"¹GkÝÝs©:ƒ1»aÎÁÔ5Rª‰„–m-‚ŽÆ‰Rͽ q8žZ›(…ù<úõõçÐ4›}|þôñãwy]öq¿Þ¿~ùåáT’L›{;Ìôô”Ë f)i׺IIU! ¤¬CkÍ}ܧ*D„` C5Š{»/Ë6»:‚º`¨iX0›…“!;F01A8 ¥©îá’X¤<¾0Ì™ 0OB& 4pNì>‰9"‚S6sDHŒjFLî6ÕÀcæãˆŠ@ÂÌðPn!D€23y@0@àã8¨Ž¹Q€¹#²ûƒCL‰X„Ù¦²pb$J\Ì"tÕá æ¿Z°©”bháBæjæÄm‹Ù&€ÇçÄÇNá~»Ö’ h* J¨Ûœ¸õCRʹˆ¤my¨Âõ¿þoþÅïÿü÷Ä™ÿáÇ8L{BŒ1j*‰ê—¯÷ˆ|zúðÿü—ÿïí¹üî»—×§%eL®ì~ü‡ŸÞÙŽ~»Ý»™"ì÷)¥@ Ï)`„*L’G–Ã=I&¦1P¤Ä&H1Í! ¨Žï>Bò½½œŸlvÈxô±ÖSM‹ûl}O™–5OÕ95'ÉÂêp½þgqô[D­¢ê”5EÆþôÓ_þ£¿b£ýv;öã˜]CaÍY»°y¨ÙœÓ!rIëRJÎ’“Ú¨„Ü›Nm[Õôv9’äZ úÐã0ð”SA„£ß‰ÁOÛ™ÜÜ!BlÚd$w ë>¾]njþgßýþë×}o* “ȱÏpä,ÇѦË–×uÎß¾^Ô#U1ŸæZˆ×œ—R{o6CrV×i“[Dk—Z âr½Õô°á%n¿|yKŒ¹b>oçÂ$ "‚Äîn衦óáœÜ÷(#s]Äu¦,ŒäsñÍšBH.ã6tÌQórZO¦†—{óˆ”$Ü.ï×û}œOÏk]çÔ ²ðëõâæÌ\Ö, &Ã#Ž‘ÕÐ@ ?å,Žû1úÔ LŒ53þþ³ÿ~­¥ÝÇÈÏ‘¼ åD1¦:F.ɧr0ª0 ¨MRUH,@€!8ÌT½”ìfðÐx‡‘{|}»nëSMB@1ûÄÇn=<Ü Eª›'rW îm2óC8LL2ú`‹G/ŒÍŒƒ¨·È’tœÃ‘Ð Ƙ9¥Ä‚L©¦$2çÀ„nôíëõÿå_½¿¿Ö%Ëi]^SÊç­>Éúñ†óÛõM–eÙªû²æÛq¿]—çsJ!‰5I"ìØï¥äœÄÕÀä\?"ªãs( @´½ÄìÄÁìî¦@äfN€j“8EÁ…!³ @€ƒ¹#“[²y>z}ÈæˆáHD83¢˜Aä>‘€0Bt$ ‡Gñ€ q,Ç Œž% ? „!D!‚HFè„,é!˜e¦‡èõ߈PÀÕ0 ±ëD@@Ž 3Ì¥æ”Ð@HðÐ&)Ï6ÁMAÈÇÔÄH¿šËÁ‚ˆY‡)Å$Gwp×pA ÷ðI„¼|úôé?ü!Xhw¢t»û½=m§´”ÿ×ù_ýÓ¿ú§[Ý£͛Å\ÖE§÷¦YRë÷õy]Oë±OOÏÎ „ABõãëw{ôo÷oê}¿Ý®ïûåzûv Ÿ|ó ö¸È‘ì·¡j"RJácîYR‘ÌÀAµds›c¡rä@Ð"$ˆ˜¤èœ¶,õ¼.y¡1ŽPªy™>ní¶ž–šfYUçÑvÄG‚4¶å$œ†Í½í³T!‚÷÷·Óv–ŒËRÒ×/÷〇%É`]Ná1ÛøúõDR.œ2b822€8âœó¨eÉRÛn³Ö%Ç¡×ýºmçÛí0 D1UdòÓ¶˜Ž§Óù~ßE}J¢D àS‹0‰;~{Û( ´á×/ûöt&ŠœùáþáÇ÷ã>j?ÿópþòõ½õÙFËYÖ’î·»E<==Ùt7GÏ5[ø}ÌýÞ2ç*Iöû½–²Ö’Sšª@ØŽª:Ü$ÉËó)1"€ª{`릎’BÈB£ä|Ç4ÄTÊ´©Ó  ÖµbŸ‰ Q‡†ª¸™g@7áX²$‘ã®×÷æ cªlÏõ¡eÍ)Öö~ÙR28›ç©x½Þ‡>•š@ú¡{›H‚„ÿ»ÿãˆK®Cûõúíåé¥ÝÛw?2G×€’„™ÏYsÂDÓÔ4È™)•š‰!g2Ÿ:g¸"Æ£'C‚(à0F0fΙ§k›NUêyfcŸ ²«™Îš Ó €pàQ×~ÕØÎ®D’ˆçœHH95: C„ÇP$B!´$Xj*¦£ÍÝ#ˆá!”šÓRxZ³QΦHXRªOOçÑ[–tÞž~úåç¿þé|.9EÀDNû°þòáÓ°/U(Ëývdðãaœc[+¢'!fºÝô¸ÄŸýî»סƒ…Ä5€±VR³G8 õÌé„þ• íáäî  Ó4ÃÝ”˜-…LÈÂH2õ¡c˜xDÎlÞ{wæ‚lcôpL©c„…¡™3!Q΂€>C('JÖ¶G¸0“P.Èâ£w¡Œ(êJÄøë*ÝpºZøC“ñˆï”’ MÕ‡N"ñ ÷aI‰b˜sb":%–p¿·¡H´NâD44t‚ê¬kžSuž^ȹÖ%y¿ÞlF×û?ýËßDì—qÍ’j- DˆÈé|:Ú]„Ì%»Ï™ÓbNµfÀ8Ú¡nÌÌ€svwB7› ÈLÈŒ,’(UUg¤/?ý8‡}{¿íÍÓœ~ì×D(H4-‚Üp´©>'cN©˜wI®QsfACMä wD@Y²ƒ>=o‰bIŒnŒ AÇ}­iɉo÷¦†mÚûýëˇ'ö—ñO¾}ý¥Ö QJy»¼Ÿž®÷+2I™µdabúË/—û=RZ/ïËû·ï¾{!ð9UÇŒ`ÈIrr˜¦cÛf½a]b!½ÕuÝŽc¨r;lôöý÷ßýøãOû¾¿¼¼¬ë™ÜGM‚nh><šRxÉ" ‡s É·ûœ³”ýþ~tS“R$g¶°©ÖÇÃÛîÄq>o®ðò|Öi—ËÝÝjIøÓ·oRëëË«}ß'È…—嘮×cLc¦9{]SÉâSbÊ™ æ½]®·ÞñÓë á?Œ©î>§›Âë‡Ïúñ‡9û-'Î%&êíèíX–Zr2í2‘ >bëfÀ¦íØGIUhhÊlfˆ"\Žq³F$@dBRNâà”BCG7U¿]÷œ2‹  ™†;ç,#× ’8eTFF'p×a(yP¸ a"Ä@$‡ˆ`‚†„8'˜;#"H·ŽÑúÔá%´p3”Ä9ÂcN"àL 6l´62§¥”ZR¸;ÿZ¢BǯÜlz˜CÊ |Z@0bÉ%,€ˆ8ˆäíÛÀ8ÿãßÿû…²¶ñíý­qÝüc.½ÙÅ…Á­1zªŽ5% ûüééówOœÐ}1P¹¹¹“¹!« î­IN`ªsÚÞ:‘„E?úý÷c¶6[ï96 !"ÓHªÂäîá¤mN ð a¾Ô‰0»}˜z­% $¶pÏ© `β΂$‘3ßo÷5—Ói3NX+«öp¶Àùmwöm©RajG‡OÔ=Ýa¿£ÍŸÞÞŸ_ŸÎkI9a$¾Ývf*Iæhsboî†D(‰ÔµõžR´¥ †àÞ- ù¦DŒ‰ØLKJÒÛá‘®—–ó¢êïïß>ú¸¬ÀçSõ‘%;ŸV³®ê{ëëÓ“›ù´>2éŒv§{SÕx>­1§XHdêS‡«™”ôþí­–*R0hÙ2Sº¼_ÛÑ^žž¾ýòÖ¦>½¼¾ÒR)ñ˜#‹$^„ùõõé¾_¯·÷‚…9I"J8 ᘃB-§to‡2Rx !3q¸›:fv„TÓ8޾ ‘ªåRbêÇhñ1Î ssgp ó”¥YA&Ê)AÄh] ³d~<»H˜DL#ŒJÉ„a¦aˆ!È|¿ïÚDzŠûq á¶mÁ$ˆLˆŒ¨@Ž®†ˆ”xèD@aÙ÷!ü ,st¤0ÀÈ)›FN‰@˜R¸Cx¸«<.yÀDaND¬æ(©`ƒ;˜‡#ÀÃo)%wC0ˆ $ñXU‡—vØíz‡0D§9˜ðÓ¶¾\ïß~üúÇnÖý"â§µøp`CÌzY°Ç=¯\2 "1±~y¿%IµTB {¬0‘Ìm¿·Ñ¦«»9ªzŸ @¶TF`üÿõ/½ºekžôÜÆsÎ÷²Ö¾Eĉsòœ¬S•TfcTP2`„K–¡C›¶-!!YBØ WYNÙHF%,Ѱâ3ðhh!Dáª,—3ÓYy®;öÞk­÷2ç¸<7æ hìнߵö˜c>Ïÿÿû"Æ<F~¹­¡Ip¸…;îRDsGNœŠ”ÑMRÑÀ[½å‚9ÁœqH’Üb™r)i¸ºéR„.×ÛátÈ¥ìÕ„N`@<ª¥<5×íž³L%¢Ž‘“d’ëz–}T<€rÊSJ£wí}D“”mDÉåËçOÈá,œ“˜ ÐÚz¦D¶_Ü2C(†™Á005ÌÂ%óÚj)39ذátßú}ë0—"SºßïÈT¦ÌÂÛ½š:8½}óhÖŸï/ŽÁ9 SBnuì?DYX.· NË¿ûþSW¸Þ¶¦ýt>–y*Yë¨uŒTÏ/×,—2eJHL—ëjj‡å˜“èPŽ$°2Ñ\È<~õíOâY‡®÷þÇ¿ü[ß|ýÎtÜnõûï?~¾|ýíOÇ)Íépä¼Þ®)Ï£>0¼®s¦ÄdeNfîûû/ Ž¡Ÿø4-Ç<ÌZ‘6zk½!sNºVóÎcø4-eŽÃrDJ¬œk|ýø~~{üÝï~w(]ûuýáºi^¦‡9½\Ÿ G;¿Ÿ¯—Ïÿì¯ÿ?6¼· nm{<žtŒ¡]U#•pÛjLoçaÚFD„¢Ù€§/ €l˜çÑ|]G"ŒI0 NRz7‘)×V™) k×\ÄU«iík?'ÂìªÈ„Ôë „ÎØ}ú°FDæ>å$È$§éQÕµw5š§Ä“„«¹—©X¸:ã‘§Ú*qÎaµ5Ý֑̽óñ¶*¨—EPÀMßžÏf>†"àªkž ´Ñ}( 2KNˆ,‚%`Âxw.°Ûix"·AA„âÍÑÃ9hbÁ`³pÈ‚À¸S™ "BEÁ#Àˆv™‡3"90cƒSY¯õòñz}ÑVñzio†µãÛüð~*³0"ŽñQÒý<é9ÏC“Á06Íã Š˜6UwG”¥õ¸¯/$ç6+"eÄØê&"ªºÞWˆfBpGa:²x ³˜½Þç"’LͧœãÔÈppf ¤>À;&ZNçëõöõOÞ(®7ÆšØ9ÍŒ‹ŽÃy!L^×Ó2¿yûõ^ûœóï~ÿ»o¾úÀDc4g}¾^æùxœg.|@#ûeÝæÅÒ©”’úV…1¡»oCQrWúøùËùtž&,“œp½ßÔº)órˆ “³øÐ!u­"’rQY C¼\ÖËÖnc¤€áÇe²aȹL”2¦Ä\»ß·U˜Ôº,3E)“šÕ6„‰ç© a~8´õÜ‘‰Àݬ»)Pˆ‘³hˆºÞn¡´îáÆ‚»ö:M(Ž“©™»ºYŒTávk×­K:qJ´äih/…(°/óDX5‘0ò®:ÜõxX ØŒxë ÌU˜(Q"pÎÓY¸wàÖÿïïÖÞ·íþ“¯ßMBHØÚ8,Ç’skõáíÉÃú¨H$œ†ÚhUˆÂééå>Í‡ÚÆáô0ÆV¿zÿv9̹ðó—Û_þåõ'çoŽÑj»ïôàLY¶Ú0"\þè—òéÓŸ‚—œ b÷òŒÖ’"ñ^ø!ùÙO¿u°ïŸ¾k½Î2ŸO·Ûí?ÿ³>-ç?ü[?ÿrýA£9İÌyÛ¶2M¯3$dªµšZN‰ˆÌ±#y8!NÓRkêÓ´ S"Üú–§e]-4¦)¯ÛV[ŸæÓºÞ%9‘1“)%€c¸ÚãÃc„«5"`fa‚°ˆW¢ÍÖ¶óùÈÂ!Iº ºîÜk‹BØÍ))J)å,"Ö j»y(‰ X„Æð®Î’p'T#¾fBKNË\Ü Ü ÌœY%Ü8ñÖ«û`Â1¼½^.ü«¿þír8üò—?;§’Ü-… Ff G"'÷°½@,á4åEÇPF¶¯³÷]u 2x¸ÓKâ]éȈaJéfÞ¢¾è”>äü³œ¾š§‡$öÏþùÿ÷ã—_÷ñWÇã)bP‡7óÏ™y×ö™"ôÞ³”ºªÜÖ~ßn?ýù7€vš‹ Ûîöô|U¯y:ÖÞ-Y‘ Ük^’:ö®„A”þúWߎKa5e±ˆëõn-2OӜǩÛÊLÄ¬Ú ¸5ÛZKI‚ÐÁÑݦBÛ¸'™Ì×Kã\¨@„ùè9M÷{",ˆÜ;ÿê·?ÜníxZˆì݇·fÃ-L½mC;Öª\ètȇCi­'aj’D$›ê”’zu§Ñúù(ÇÖ†tuaÄD¦%sJ8†q ®u¦ ($ìáæYJ˜YX €Ðz߆Z’©o#ÔÏg'ÃŒ£ ²ÅåV?]nÄy™¦~ï]M!Ê\–¹,sBÂÞ´µAÄÆ)OÛÖkó­5•œ%§>Æ4%AK’€Tuk»,>rÊÂÒÔÂlY¹þ¯þׯ,™%D0Ôr.Ûý¶JJIP¾ÿýï~úíÏÎÇÃr˜×Ö?~z®«ýü~¾Õí¶­½öÓ|xÿöíÛw˺=ß®#§Ãñt(sÙßq¾|y "„ôíO¾h¿ûý¯ÖUÇ §Ãüøîp½ß¦ùž¿ùú~û›ßþä'_!o?~÷òrÝ)»÷ñH$¦[Éi´jèÈîÔ†rICGôž™¹à´,÷ûZR‹yžTÝÂǰû}=-gwª}tDáòŽI’j¤”“äÑ;ƒCÉ“º«G…»ö¦ªÂyYNì¶ RJ9å­n¦ÝÜ$%5-e óÛº!‹ª#áTxÊ3Ñ.´‚ÖF.I˜‡ Õ‘rr×eža'»“0¥R S yÓ¾k À‚wÒá0E8I);u}º7³ŽÈDêèA`n™ÅÝÜÔ]E¨uí£qm½%W;æ2GaÚ ˆLÈfÑv]"Bï÷äGÉ%ýµÆÎû‰™4Ôl Æ^Õ À@57ˆÀ`sfg@ ‚b Wï€È i½bè»"ïÞœþà«d}«×Ö‘®ÛÓçí2ÌúXoõËù1?œÓ­ÝØíÞ Àúp£P°p5UuÂäNhèá¡£»*8Å>ÁñaaÂìŽÃ «îžuÁä­†zNSžçry¾-óLæãr½4$J’JgOL@˜„åôæôn>È÷ŸÑÆè¹”Órì÷-K,K15CÁm´ç§§¯ß¾§ ,œDn×ë4’4º¾\.ËiŽ’‚¦‚ÐÛ@fM¬£mõ~\Ž%Ï%M×ë¥õÑšД¦2'õfî Êýéz»’Œ“9èp@d’„ùz»M‡b:Öu³@ éuûö›w)Që5 0ì4Û:ÜåÝ»¯j{jº^ïWLr<žµÛµ==ÝJ9,‡ECÍ41ÆT± ³Ô6ÌØœY¶­p3LR‡Ý×ÊÌ,ìî­¶å°h·zëuëB¦T2œ—ƒ0±d™'‰ðmÛ"å$mlT7=,r<Ô¬ÕŽHór3aòЕ„ch7cÉ÷µ"s˜OYrb]³LŒÜ]k¯¥Ft³­Õ>ZfîµbšÜ‚X0ò6lk†ˆSÊ>Œ3I&÷œ¨÷nf9ç€@ã—ç{~ßüv3fóAòRÌp.…Q‰ˆYhÏô–$¹c¯=›A„•,¥°jÇÿå¿óß?yšœ8J™Ýìéùy:ùËÓåÝùÍ4¥¡ÛépüüÃS߯Û÷o·¡öüåfÝçùt[ëõºþÍ_übÊøáýc.§Ãá=`£›µTì¿üËöOÿìŸ æåÿèñÝ‘SÜÖË4ODðñkSø£¿õ bûîã÷Ÿ¿¬çûŸ|x Òÿñ·×[Ûq¯oÎçãt½¾HÊmkIRιö Ž9e„CÕ-Ý©®CG?Ÿ S·ý–2%))é舂´Çéˆ%j«0å €ÕQÁZ« p:´5ÉyôªÝ<òá|¸Ü.ó4Ÿ¦£›­÷{ÕæÓ<·ºÚÛãívÝêF"ÃŒEJ™ÓÛ­½{÷Õ¥^™Ù̘P£P 2 O’] ÔS‘axïQ"šv àTržRJ„È rJ6#tljc9˜XÕÆèÃFóJaàÃÁÀ\‡ÉÉ!TÕ0€ ÉD‰…sʦûÛ‘ÂM˜Ô Û0@fÈ»M'Ü~\È…áÞ^@|mb¸»{DxD`˜;íÜ D@@Å@À=ÌÊADA°«ì5"ˆH$ûM¶çòÍ›o¿:=æ…JÑ §Ëm«7ÊFÓ¸®ŸníÚôŽi”’†êÞ "”Dé0]£ÕH™Jë£Õ5aÞ/éhêÛ6.·»™:x@„zJy@hx]ÕN‡#†iëŒÂœï£ÿæ÷ßÏË|T ™‹ ß‘00-¹¹mÛ–Ö[M‰YBrBH­êºnë¶!ç6´cŠ·ïOó2jN¥É‡ Êó—çåxÉL‰€ï÷ûã›eNt<äÚjí H(X‡—y¾µõùö‚oŽgtªÝ$ŸrÎL`½¯%Í)ã¶µÃñ­…ö±10Q÷ŽHY¦xå÷»»³ìHXU W@7UBfÎ-<öªBJ‰À=LA˜„SJÂÍ[àhêjF°¢Ž€Ü†í©8dêîÚµ”Œàctwøoª¤IdÉÅMM5%FDG$¦ˆp³݃¼û‰ˆðÕ¬`D´Ù@äŒÈHîN»y]’äÒ‡ŽÑÃu÷f»‡0{¸BsPò@GàÂ$€¡Öͺª‘83Qà.›‚ˆ=ï)a˜+óþ{C!qsÕÃÄFüæñøó%/“P¯CAŒS|÷Ý_üå_ýãËþòkaÚÚ–3 «#±2™:úÞ±B gpò€Z7 RÕV·õº¾}|ÿøðþùùúüòÂÂHÔk­­¹00#bß:: EïÍG÷¡î>4TÊlÖ˜\§2ʱÕURäÄÛºµ>>¼ÿæpÎÝ®Ir¦òéóç·ïÞÝ./h>ÏKm›Èëæìt<]/—ùxªµû°Äq:Ÿ—<Á}} º¿?<_~8œ&$ŠËó-ññ˧«QÁL°ÌóPߺ„dVkî½ÑÇ[kxz8?”ã÷¿û2/éÍ{ÜÎoO}ôÑÎeRë˜üüp3om ¢‡¥œjnÐk7sõXk¦É|´®ÌY¨­Í³ªOs™²Ø}§£#ëĮ́7gÎÐG=óù±@8A#~øøùx:–"`æ£"µ®//÷ŸƒÀøôûÚ¿TwGD5›çÓ½¶nÕCà~[%1—2!¬mÄ9ç’x õ­f’M‡S ›"¡! 'ô €7FIfˆÃZJdC“$'"Dòá“$¦€T“ÌP2©ÙZ«º1–Û­°ß|ÿë·ïÞˆ8Êtìµ]./ážRrðw‡Ó¼$b.FDa Ýêè†Ìá:„¸¤)‚€ä|< #‚õÞRb¦Þ "ö›r¡›%)êfàêênÂe¨×ÞÍÔFeæ2Fc€aËž rbáa‘Ó$"溗H ÑLC˜öÿ"¡CfII¶Z€™†Hs¦ûQëæˆøzâx # ‡í9~ðØMnaaÂHÈ„ˆ†H€ÀÌá †„¡!À„) ©oÍÌÃ) 0 pˆðÞâ25¦  TSäHDûV5<ÜÔö•IBaE†i*ß"þÌí0¥#!é}{ùøù¯¦yKÅ £öº1¢cGpÄÓt°¦yZRž–ÃÜÞÃL¡ÕQÊL”ÐíùùéÏÿòÏ?~þôõ7ßçÓÇß|z~>fÖǰðf>rž¯×K,Y„ˆQÑÂÐÁÌ‚ÝÂDµOS&K”%» ”vo¡ÎPX!D¦Ñœƒ1z-…kL`¡@4Î÷Û–ó!(îë$cJ/Ï·‡‡¥æd:tJ“©ªk™¦ç—K)‹BpÝÔ@µAÄ^Ó 54D 4 Ÿ¯=—%hß@.l 8Kõð˜–ÉB™[c)¨šMi¾½ÜÛ¦?ÎAÍ6³ûºNÓlîI’° =¼™91ÕêîHCÇžîµ 2¢¥Lîná¡#ZSœ9ÜïÃL†Ö{Ësq‚›KqkÓÌ"ɉ=ÜjÓØíÄ© 7õîÎŒCCÈQÌöykG¤ZÛ°H,sšÃ)€Ý¬º§’³Ža¦9'ü_üÛçíÛ)Kh™§·oß"%µ£EXC»F™§¡ýx|89h™O§‡7ê›Zýíï~sß®‡cJ…í՘’»“ÀÇ¼Oó}»Ìç™P¼×a,‚ ® "ë0DHYˆ¨5wŸçÞkO”#8ÌEÙÌöUüŽv ˆ=JŽ”r‘„ˆF½)Ni ‡˜§ù¾ÞÕ[nxXd–í~ ‡Ãœ¦Ä@D(IÜ-O_ÉZÞ{35s#$â?}¨Ã˜q*RûÝ@Óì¦È¨°»âqŒÁ@ # €w ŠHÚ)nÆ$fÂb œRºyì-@!FD‡Ðp $bñj‰ÌŒw‘¼B0¥Ä)ÜBC"‚…vÏ3€Â$@G@@DÜSˆADfÜH(ïÉ%t¬êŠ˜)vî?…"“™º DÀžGDØ­á;bU 16mÎFB¸ƒMÇð@¦,û6ÈÑÅúã›ÃüµéaYGè—B°k(rf»ÞŸ ¼útû¢ÐY¨äĉ“°` ³0SÛ¶-Ì!¢{„{æÅ­ý¹ºnýË—gIeš‹p3] 1Æv_ûèÝM²¤Â‹p¢A Aª'÷á#ÎËa½_˜QÃJNjÖ›F`™æ9/Ó<ÿæûïbʹ¤<ÏÓÖÖy*§yþôô[§ ly*/—)A ™™:æ,)C°xdIä¡€2ºûðÞA‡Õ6zÓ4—Iz¯ë¶Îó@´Z·Ö¬æçÏ·¯¾þùuÝ.ëÓ»wå'?9.™ÍÜLT£©Me‘$îjmj£÷Q¦ã}kï…%z(®Z‹u/i2Õçmm·{Lyé}(‘ù8.iJBDCõzÙÖÕzGBÆ@n‘Rª÷M²ð^úC „¡cèHYòTH0PÝ”(Rb&0sŽˆ9'Ç$9IræÃÕ†125÷­QâœXJ…@ˆ`ßY÷$œ}dz¸»»ïõ€c@F¸dÆpëJ„œ z#@!,9Mº?ÿ…€ ÀQØÜÌ5"BÃwÁFDHJöz©Ø%ã à`ûCl÷¼À^ÑÀ¢ €îစ ÜÁ)ÂÍ,"˜™ltB„0°[A´Kwªš…qá]óÉ„‰ÉÁ€ À™‘ͤ­ø¸|`(]µjŸæBá (QFHSí«;œÞÍócá³:|þòù~{éu}º?]¶›†ÙèZëµ®Nè‡eúú«÷”HȼYÛ´L’²˜»{ƒºç\æ2y¨›Îe9Ï}ô,É#öô:¸üÝo'áœÄÃG`«CÕˆ)lx"ö¡ˆè˜D­÷Ѷ­§´”|N,î½”´¶{50ºÙåò"Ìç%T·íÆÂ§Óa´ AÌRká O’ÓíÞŽÓŒÖ{ëݶ޷m›§ Gë;"÷®f–’”2w« jê·Ëöþáñ§?ýI&qAƒ uX{åÄᮦ”¤ÈD6ZÌI ñºµ®ôÛß}_“qœça½Q5¶»^Ÿ+CZ¦åËm+¥ä$9É•EÜi½w3@díæctB,E˜åœçyÒèƈ.’ÐÃSŽœ Ð3¥i.ÍtÇÁAš pØF6íL–K™¦i»oI{0‚¨[*Ĉñ|½ÿþ‡/‡ãùí›G EªÖZäÂj LI=º+8¢!óÖz·. 'íô¸ÄhMG¸#·:†Ái9}ùòˆÓaNÙ—2qðm­÷1愬u fº|Ùꊒçþöý9SL9˜™óÁ(z¯um¦î†aØûPuw¹ßëÐq:Ï_}õ0FM’©ÞFPH–<%üþ“ÿ©ùfC3P±u Ë?ûö—>¼?>Ì÷ë—ï¿ûíwßÿæñýI±ÎKoúùãSïZJî£/KA"ß}úôæÝû¥”¶öÞ€R‘ãq *‚!€!Úâö² ñé\‚gH®Ì ™x½­µUÉB’H²¢õAAèJ™3##¹…» ±¹.Ó䮺7ôÜ|Gl¢31ºËëAi¦ÀHL´Ûjö˜d„§$·{нé”SžÒV×,r8ž¦eVY€öé¹:###ì§1÷@€S7DAVS `„dÞ¥›‰)3ÙÐ4 G".yRWs4S'I» F`Ü÷¦¸؈)‘€KžE’‡± öÖÍF­k¸95ôýšŽÈf€Hðªp&s†ªN±ßôÉa‰ DÞ—‚9ˆÀ!Ø a_Þ™Y€ €È5"È=àz{™çùxX´wî†I˜˜‡{Wóˆ1úãiapF 'bb Þîõã—/ßþôÛÌ€HÄŽF@0D+lWÿɇ_<ÌïoO÷ežy90I•2µ¾ÞÖ»~ür?jDÕ 0‚YTm«Õ=¦²\.7"8ž¦r`dCF®›NÌ¥ˆƒ±"ßoýrÛãt^t))1‹L„½Õj›ÆøøéËó¥ÎÓC¦òé‡çÃéñóóÓÓåËáüpœæínjØF›§e™2ø0§óÑÇèC~÷Ýå¾—œÀ†0žŽ‹ÀCm*…I°VÕî,€ ç’)¼xžˆÕÌ ŽËª;83M™L1Í’c‚©ÌÞÝ-ÀAÕ»úÚÚR¦™qâ}­’ å”ï·ÛõzKY–CÒž.·¶6Ó$hæÄžÄCûÃñp|8"ãÐÑ·&À44ZïïßÔ»½<7µ€ÜÜê0ä ˜ç%Ü’P7zúrO KÌSúô×á<"E‘î£o:¬™Ý<=ß¶pHR†Ž4Óá$çiÎ R7½Ýï·ºjØ<åóñˆúüý¡´ÞåÃÛŸýüg_ÎgÉ8ìò»ïþÅí~qßÂÝÔlšåùrñ`ù«_ýæôðöÍÛ„Nn‡y–$MÍ,&ám]EJ om\^^˜8‰<žÏqߪv ">Óá(CWä¼UOŒÇ¹¸usCápŠpÙÙ\h‡´ï¬i÷‘§$i´H[«£÷Ãr˜§iØp‚ÑGJaß1¢¤´#X˜y´¶­kJ) 8 ´®£rÞ_ SNÇó|8•Ñ+"’: eFF€Ö·x›PbA‡ð@߉,€»´P5‘#€$³ia Ä,bÚ1,ÌÉ ó´xÿòùåÓ—ûí…ÈHh‡º©©šì¹ËÝ´ñŠcFŒý‰·ÿjD˜8F ï¹)s`Bt Œ~ëHûã‰p'ý©u0'J„náˆè˲¨sa”V›Û@tdr†Pû>Ù“ÐË—/)É™$ˆ÷ñE€[ì±Os ˆ t $@êÀL¥ˆŽ^„#œ„™ˆùUQ×#Ü<€8"ñÎÞøÓwò/ÿíé<Ÿ­:gš‹#ô®¸mm«• ÝÚóe}nÖ‰ÀÐFTƒÆh‰R­ 0Ú¨ºLEÛØ¶@ÈÛÚ‘Ù¼OpHbw“„ .Ä(Y¦æªæøòô\¦),Öu+)ÏÓ¼+4 bk›ªA¨HR·u­ó²h·ûv;>ÌÝúÔ™S:|Oæ'&£{xÎÉCÁñv¹C<œÎ6lÛZwƵÖ"i™fè;ZÉK!@ç\J¹·:Ìj×"yÏ D@8>?ÝÂáñÍ™Hp.D]5çF¦±µÓ²|üôr¹lõ:>?]¹Ì˜¹÷öõ»÷Ûº~þt7ã7ïÎsžm ÓáàAX›ÅÚõ¶ÝÞœy½¾œ–2O˶u¢c a¢”ØF37Øñå˜ÎË”kæ1ÏœI„¸÷ˆžJQMëát@w¡Ý…ˆ¯Û$[í"2§„àØêà”F3\ž_ŠÈ2g‘hÖïu€'WtÃÑMÇ`†ÓiFt3sÂwoζçn‰Óhêæá¾Õz¿wç䇄¿úõohRbŸ—éåzÑw—I2rk}97ǰġ~x¾—¹¡ÞFØ[8Ò4[GWøx¹ÁqʧùÍ»s*¬® ÁZËIjë—û½™Š$6¥Œÿçÿÿ%³|øú§îðÃÇ_}zú}ëÛ4gÉ`Ñ)(ŒÍ)€ïÛ:ež¦Ô{eI÷[Ýÿæ1f‡€„­W S2OŸ/" JNË>•ÄȬîm´ 8/)_®ÍpJNIõmøi9BÕ#8eÂÐщYÝcO‡3¨ÏsIYÖv’&psjIJo,ÁÝK™Z«î¾,ó]XÂùumù# ™…Õ]Ù™€ óÔš1OY–ïýdf†á nn]%ënQA Ç1 )‰0Ôn,91 Y`wK‰! ˜H €‡da¤òG$Ú9»š—"öüÌ+>#ÜÔ8`_ ›¹ÓëtçÇ.Á0G& ‡P p 'ÇÀÂS¸G( «ZƒƒyÀ>“#`Õa7Ø?$@ŠˆÿïDä@Àè¡#vrP@„¸™#`”©ŒÑ§TÃTm8‡d t¶ B$f&¤Ñ;…ƒÃ‚ÀP%ÀTò«‘ÆL aþж¶w?yy³¼a$€èZÆÚo«ŽæÞ-"`˜z tH¦¶˜C$„Ø_h0\µCbW0f&DD Cá4•üýÇï¿ûáS­õÇ·'*Âæöêl@L nfÎ@,`¯owÀU;³‰«%ÉÄÒZ¿Þ®Hâ®;i´!KbwWU$ ë¦]K™=OÒòüt{||sŠèê 9i€z¸‰ðÐqoë‡o”EFn ——ûù|žÅLSâ\¤µŽ—ëM‘ ±®MˆgƒÁ,™bnµµï¿û˜K™æ™S^ï+_¯k´Ö×:.7Ï2ŽB$®`Š/÷ºuÕ,tzXÌûrX¶µRŒã$’§Ï—>6ŸËÔÇ6/)%Ì™'á@èŒmÛ–4%ÉË4…ëåvIERJ ¥m} åœÒÌÓDY`»]§2 åûm5Ã'FuU®ÁDEØz7ï1ÍX'"7÷NŒlˆan7åTн•œj­9%af¢\­u¦ÎÀë½^n-¥9d†_«,sFµ%Ïßü²©?æå»Õ­éíÞ—SžJ)IL›à¤ ®×‹£òÓÓ::DÎc 3eß>ƒúÃé‰Ãö©0˜E·Ðpíý˜K¸óTº¦„ŽN9%±³™™ ™@‘S Wbbß&N´c€I"‚˜#©š*p³ÑL‘„Z8‰¼Xà 9Ìpôan–8E`Dì±Ë@ b &™JJ ®»ÇÌÝašfï¶1áP}U!Õ¦ó<{˜{tÀ@Dp4%äÝÁ`&"û`™="ÜðÇ09Z8C0±«Uà}´¯nÖƒR‹H ˜)÷ Rà;8Žö?—ºsJà Àˆá Œ9"ºj%Â` ÀîcôA@SNŒÄä}´2e@f)”†`X×Þ ¥`˜‡™i£ *M2 {L%#D"™ò’RFŠ s»m7CD³…>]¿UsÛOä±/€Èm€xx„3Q˜kĬá¾ÅÀ÷ B # qJE‡…ºsP¢]Æ@D®!<¢ÖhOæocIçCy4צdaݽ«íU;„(iÒë:ÜÑÝ3çy>Œ>|˜ê0ß)IÀÞe†>€X@ #6ÕN@¡þ—õ«?ú£¿±skk(ĺõÑü°Ü4\E8¥´ÖZkæ)çp W„ȹ¤’89€e.Y¦îîæª¯i2D4ì]›¶ðV«=¿ µ¤a8'ÙÚ¸^Û.OÞúz8åy.‡ižË Þ’xšæÛꟾ{–DÁ6Mr\–I„ Fè<—¹¤­¯êÖZGJLÕa¤"yæ„0åÄ’n÷U[»^»*zD™ÓæÜcáÃuô.ÈĈbûò了9MóR@ˆ,Lc}”²ÌÓA}¨ 7ßÃ)Ÿ>=¿yx>p΃ØûŽ­!BDð)eße'Q‡Î}XoMÜ$I9ïDDÄ,¦NÌR˜ÂÝ4È´‡ª#‘ï0Ì}’Ž4º»‘˜Û¶uÊ)§,{ºƒBÁL83 ÔŽ*Ìnˆ±·£~ÌUîñztwfD¾WG÷ÓáÐm°[ñ4Mæ}Œ pXbÑ1Fx’œ9©¶jÕ ™‰ˆ%å]ùEDa»X& "Ô"Ü%Éîü ô]®¦è„æûk„+Ž>vTÁ~Ží˜ïð½:½'y‘8€ACÄ>ÀA wÁ€œRbNˆøüüdjI ÿþ»ßy‘´nót˜ÓA ”||ûø–‘Ý}:,²¿©åÂjͰöØ"KJ\0È#­[f݆Å"ÜKÏ€v¶™šÝZãî1`·!:ØÞj À:¶áFÄ? mÿ@DÊ®Á(YJ–)¥)Ì¿|ù%gt Ð=>*\ˆˆÙ]O_‘MÝ¢ªöÞêVÁÚÚŸÒ!¦IS !‘› Dâs¶¿ô §ôðØ=æ» <¥Änƒ –yÚQä„ëVk«óaæÏŸŸSšæ)#@ÝjoÊ”®×UՉ辭)¥o¾ùšØÛ¸«væ”r¢„€îsšBQ»G­#O]k÷m„VÏ9­›Ž!?ÝjõíæªÜÌÝQ—%MsêuGÓ8Oe™øx(œ„rÙn÷>6$bÐH,fÝJÉPò @ö}¼Y·A8¦‚µÖ¡6úØÚ¶Ìóq>[wºÞbîÚ9E™ÓéxÔ>Üs ™Z'‹"30Ç¡Î,Äézk®ˆDóœ×u]k+¥ØP.s™¦ÑW¡Q,——{mëáTd©L±§G ˆ(‘\]ÍîuÜ»™D$‘ÃR.Ïõå©'.Ô£;µïÎ…pÛ6É,–rf Yï~»¶6<µ*ÈDSFfÊ9Ï)üÏþOÿ³= îîL¾#1œ „°ìRZˆ@WÇ@SK9:"Ðp«½å\¦R`€„ Õ퀊äDT[;Ì ¡ÂÓóYùãwŸÏø“w@v««yN€Ô«ê°œ0’!¢{W•œzï$”$ÑÃã±÷¶Þo„Lw§=!í»np…ØëLdŽfØ«ž–CΠ‰ÁÔ“LL‡Ã AZÛÚØêØ)I®íâÞ!@8'áŒn›CíacPè¼äwèù~oŸ®¿§y}û¦:Ó.eØ•Ñ;²bíF€*Ô­e–œ‘Üc`ºãþvßsÅ*ÂÈ{aek}]«©¯kom¼\o~<…äþÒÜĦ¥Ü·Ûå~ï×”NÇôþë3RÜoÕ,$åe^0ìtÈI€„#ãÚ·¥,dÚ#FJÒ›Þ×:ëjëÍ^®ÍœÖª×‹†'³~:—_•ÇÓAû¨M¹Ìþx>,s6ÓH€:†º÷n>"çD‚kÛÂ!cÎ2-‡¥Žë.<(Ë—ËGƒ¡æHr¹W0\Òña~<–S–̹üú÷¿¡ÉVÇ DBY8ÂÜ|¢HRh64"AÈmkÄd÷› בHÆ]ŽHcèÓçkípœçƒ<3²¨ÃºÚØÔU!qÊ)a›ÖÃRÐÝ †ÃçË¥Vó "xXë½®ëʔƲäDŒÀÓ´ 9G„‡…5~~¾×¡èèáæÓ”sɇ%ƒ{a¢Þþ§ÿû3`{C€#H IÁG„#¿ÆÃID’™™[˜ï4@H9© 7SÛRNœó$À–E"ÌXØb&¬¡np¿­`ëz•"ÔHÒÚ*X䜙…Ü 'J‰=ì^×®Ãv}8121Žá{Ø$F¬ë–§‰H†Ž­õˆ`‘ûVGÃL‚/33G*¼Õ5§4O‡[[}*y´."ž$#Ðõ~»l×y>$*è’%M…‰k‡wm Í´{–Ì$6åâîAÈ)‹sÄDjªúº®$¡D} êû‚ÙU‹$Ú5]’Іå”-BÕRÊH£€pð@¯£šu"s@H$ènDä ^WˆÃG†ƒ+„G £r h ì1‹ü)"€-À"Iˆˆ"€‚²,¿ÿõm±ÞÆÓó ©\îš%¿}óÕ‡¯¾­ÝK9æµ^Æû÷o Ö)‹isÔªµº7­Ë!#€àŽf 1—i?ÛCÃö<ˆXÜ xÊs˜S줹Ð0…(œÀm7‘:ì«pÀ â}¿=z37Dˆ×˜›ƒä”s¾ßW#gaƈ Ú¡fJàÀHè@@H0Ô÷o±ðnçWEÀîh?ÓÀñçÏW¤ƒÈé¾vó^¦8%¼b쟱ì+D®u@¦F”L=1x7]Û ‰ cRð]ºOÑ1ÜJÎ÷ÛöôùòîÍÛ%ÏHN±m m'¼mõr­6`š²½|{žÎ…¦7R*VëÕ£ëµ^?¿|!ÂÑGÊLn(­ûíÞ/—>¯Ã»z]ï•‘JæyæÓQiÎùxZ†Æ”D’€£ŽÑúhªcèT&$7¤˜t7,Ç r'ë³/òî°/×'&`sãyúêí×O/P¾Ü~œžï_zÜ9’11¤DY$t„…¡¹·Ñ“€ '–ÆPïa Æè,v~8øõå¾ÌS.‰™“”Þ‡Móìn·õŠÌ±¿ õÛz¿Õ„€”e…°ˆ6ú¦-ñ?þßþk憄ÄÄÌD’s‘$ôß7pÀH€¸ÿô:ºCp*d£‘„…Ž1SJ ØÇE» ²n¦¦#Ü#…hJ!t(ƒšF ÄŽ.ppÚ­Fµm¹Hí=‡™v-œ“$@eTNâ º7¡Ð‚0©ª¤´E¢µê@D(…Á_)’™RÉdIBDèî= À½ÞïdTpÏsŠÈËåùxšÜÚ.IAåz©—çû¨í|šsæ”xžK ¹ÓN|£€LjÌan掄 äè# 1%É0³p À¹dp÷ðáÚzb wBØ¿„ÄÍtDÎîG·î¯ß1"‹@¤9ëÃwè„›í{`BóáU‘1`JÅÕ v©@„×ãEx'ó„#xÄÞic ÎD¦J×üóöéö…‰Ë7_}õÇô‹ï¦ÃM33µÖHDÌ,Ì C€’1GªëF)¯µnÑ!1/Ç‚ÀSžç9xExm+€™Œ¡æ 0ÔÜBuÀÓíþýÇ—’Þ<0ë.u»^Ú÷ß?-ÇÓ4/ß|ý>‘ ]E( Y˜# p€(’b@°†;íd†À$_^¯ÒDÈÌ}4aò1€ÀЋ0¹@¸[ëÁ‚jfy2˜›…³°› &„äCv/JD@ # ëŒ$}ŒØñk8¡ð>Þ6P7÷=žÇ(2L÷)„«"‚ª¹{8º¹‡"”¹|ýxü6KZÛx6oAîÐjü“ü/þ•ùïÍË:ì 0çˆýÈ“çKýË¿ø¿üÃ?|ÿviÖÍË—ÏÛŸÿóÿâ¿ûßùÛY}Ý*<_äxøz»Õ¾5fZë¶µúå釧/OëÖúXñ‹óÿä_û“1î[»§@"~Ýmy$r $ä N<ÛÓ6ts'Tr t%E€‡à^007&f@7#f‡èªœd_J¹““AîÛ½m×mJœ³8óáp B"2Ó¡ÐÁkë"=æó0»lÏK¦CÊf®ˆ¸”2»F’=t¯­Õx9!F„cOÀáÃm¯J7 @D ƒ1z u'w€Þµ¶@yb!œDL˜%qNÂ(6œAq¨ ½ÎÏ<! ½þ4†š¨Òî•sB¨mônänÌ”$' 7Qk%äy*x¹ÝDøí›#&CÀ„år¹ßÖ~:DÈl@á¹kÔVÑœ§Âe«]±§LÇÃãǟǸãiyçÊó”Í›BG°R²v]ïÛ½^ŒF°¹+Î%!QÆ,}èh¾ÛQÍ”ÁóÖµx˜Ï9ØÕSÉ¥LÛªŸ~xqðü+\„AØË1:@8{ëuÛª¡v[‹Ù˜ær½Õ>Öã¹LKéÃ|Ðp@„iJJÇc! SÛq.ÀI&3ªÇãqkuhßzC­uÐi¢’Ùµs–¦ݧTÀÐGܺI.ÇijÛÕ)ƒ„z%ü‡ÿÑÿpÊYE0z_sJ`9ßWcL$DŒøåóçÃñP–bî‡ã‰ï·VR^R.99Xw¾‡ÄCG.’ÜueçIÀ•<ŠäÜûIDBH:úÞÄBÄÞ{“‡!àÎzØ£ü 6\= G ˜rZއûº5ëÄ(H%¥ÖÇ~ŽÀ>LHF¯ó’!1iXD0Ñн_ÜouËËQ¶µ]¯÷óéÁ¿|y Àä,î¾­ÛºÖ™çãá“Ô¶†õeâ)%@""bŠ®ê€Âœ9Q8w…â½ï {G ’$bFÿ-œ¼S€ºw#‚‰Üi¿:!š«ù@@D& ðH¥D š«’ ¡0ªV‹Wi×\fW7÷áƒ<ÀAM,b—@"`¢x%üñ+ ÛÜ"ÐÆ:¹5ÕnŒdê£[Îó<@µF (åˆ@DŽèÌŒ¯80Uç÷ï¿q¿"má&€A@œÈ#&Yúªÿïÿ×?ù{ÿ£¿»µÖjL…Ê$HFço¾þÅyz{šÏH©=ÝzšNyÊ÷ûZ› »þ_ÿoÿ—?þ“÷e ”aèµ+‡‡šþU DdbÓA„¾S7Ðl` ‡…ƒû¾rŠY‡@{VèG6†{ ²H@1åÚî0 ¤c£õ,I˜z„‘™©@6 H@À(1ƒ™0"Y„¡‡‡m£…Ãq9†#83 „ºB½ƒíÅnØÝŸn†‚ÔÍw¥˜ï º¯w‡B. ä6h„\»õˆÂ ÷Ûv½®‡e1íÓ”sISÎ%¥Ä‚@fîáˆ;WÝ î0mG& 3DG¸ÝëÎNLCµ»RÉ¡ó"Óaê}\ŸW0z÷øöùö2À$¥yžîÛ S*¦BP%—%ž.Ï›UFœó!½«bÇ%×{Uoi–,“usõÚ*N1›Y#" Øz•Ì™'ïŽd£+cšòÂ$q¿wµÁa‰1#Òý¶¢ŠU\ÎË•um9ÉO¿ùƒ„Ó|ó7rš$'ëʈ÷ûíÿþÿøþÿößýðáëÞïÕî £ö—§ËoƸ ƒÄ@A"ÙÔ 91IQa-Ð8^5Èèîf αÿöÉ‘PPaOnSE€0`¸3’š«;’î¥ß'é€BÅ4bÏt¼òôÀÍ ™‘Ø=  å\ ^ÃÑ´wӜҞIõݘ9…ïèýõËK„3’ƒ)º†C8©CÝM÷TI©m•Ä9•Äe‡gõ6̘×^¯·þçU¥Ý0„Á„f§\ÎÎÌNLîŽÁ¯,,"ß5¢`€€›u W5!ÉÌêj€8MSb¹\FÓQµE“x¥¡m:HbN\"Œ‘yt§ÙÔ‡‹‘KªkS©dJ”ëæˆbÌ&(ÚBÇ`Îi–a­ª¶)KJ©®]8MIšvÀ°>Ð#Õ>Öªˆ)K9”#sfŽÃ9Ð6\{ónÖ´´ ÝèíÛ·fÖ[ÕaOë—tôÞîÈ#/ÂÌ·¶ÖÖÍ Ë,©tÓ)§S΂ 01f<.™À«ÆPz9Ïäé¯~ý«ê}^Šöö|¹×ôø0ÿÁ·H¾€‘SJN®ænÁI¦¥˜›v»<ßÚê——~k“ž©ÃR)ïÞÃçï>ã?øÓÿ»æÂ €Ð˜rÉaF;üšwx™Ð4M"RJaä=b°¯ Ã|ÛêéxHŒ"„„ÀDèÀÄûK×î„L€˜ˆÃ¼‡J¢„¼µ±Ö¡fœ’ "£[˜©2 ©"‘p&&A€ðhC ͉4Ôbl—m}n£aW¸·¶gr×e.oß§¹˜+ $ :v“²rž˜91†i¸"ÑŽ°·ËãÆÌØ{O9¹E"VÕ”Õdâë )ÜÍ8¥hûˆè;xq¸i8D0‚#€ï:0Øß†×È0‚¼&Wi¯Ç!"q¦W¨ƒî:Ñë>³÷=¾ €¶çUbìÿ9àh#ˆÊ<#;B Px„;A¡EsFì¬"÷@wÜ¡…?Âã^Cˆ ɘ !("q ŠÈþ`×î÷ûŠ¿þÕ÷Ãüó— {žpN1ÍÇÃ|>¼ÿáÝÛïÞ¾f1‚™<ôóÓÇ­½´±Î‡Â> ö+QßKg˜Ù1ƒ‰v{9"8ˆ¤nÕÀØ€Ñ}W£¡#*€q8"Cx {î4*ØÙ Lž#BHÔÔÔÝ=R’¸åꜤXtW# Ä¢ª@ˆdîf D€D€€ÌänHÈ`€¾S3ÐÜ!qFwáõgî¶·‘@•£{§BP߃»($E²‡á‘XTÝ M÷ú|×g.`8O ¹÷y¦Ñõó§g&f.CqXä9ÍK¾¾¼Ô­©ºÎÇmë÷Kµ,!íø€IDAT– ,Tr"Lˆv˜Ò,Ro+þ£ÿô_!sC`3t× `yž0 ‰ì'  ³ì!¼·°aDnîªf’‹ £¥œt(¡Œ>{kĆ"„ªŒHîm|yz!æói)‚ˆA"°û°Ì%…A„A2¥ˆ¤1FP !ª¬/Ý,ˆ)edN¾Kÿ²ds¿¯+'Ab'”œ&Qm:Àc¸5BŠ ÜßÌwƒ¹íÉšˆðÈ)98ÐŽ2&tBd@"rßãàîND)0öèÈþ€@ÀcŒº/ t˜*" ‰€;€‹B °3ÿl@h)²É!àU‹ƒ"„à¦f)%7Нƒ rr÷‘$¥”TÍÂBˆ‘÷ q„yøŽtóýCاBcèV[Îi^R˜&I;¢c÷¶G#ˆi Àï¿ÿòô¹m›yÀ—/—Û½ ‹rÄùx¬mô­·ãñ<çòþÝãÃùðæÍ…"E×µ$”:tØÈ)…[Û”ˆ‘H hß¹:°S(í 4°Ø#®LÃìC sdŽÎaÿM9."0ÀÃÜØwÔµ;JÀ~í¢}Â,DÈäÀ$¡Ð‡=¼ÿÉñüæ7ýWi "íŽ÷0BpGŽ×>…ãž3 77ÞŸðn®LÁÁ´× AÀ@(³ƒ„Yî,’ó07e&Ú[‚œäiçfБIz7Àȉ%¬}Ô>Ô˜Y„(I µÖ5$«CmÂEÄ,rN ƒ"¶¦Ï·›”›„Y pÒ¡‰é4Ï… k[mîAΠè[]E˜I¶µê¤ä}h’ÒÖ±­æHŽ1Í Ñ¦’™ØAÅÚø±Ó1N§E͇Ú}ÝâñÍqâÒîÛfÍÙ™©¯f#–¹æ´]×ÛZ‘§¯?üôùó3ˆ/³¸Úµ+´ÖGIXfÎs‚"¥7JµV‘Ô«¿;}ýôtÃÂ<ð»Y%=e4„¦V[¯[O"o>œçÌà>Ô‰òý¥õ¾Î'Â]Ï+¾/Ø<ݯã~oïߥóƒCWjÝ܃êºaàép¾\.Ã\‘-™Ë‡ƒôÚ^ž6S¼­k·I:O, …IÔ£,s™ŒuMìËaÂÿÝ?úû˜Dˆ÷«“Ç„á€fþz/©S׎èž›{8hWBD5SÕœóžKE!B1sS½Ý®鸜˜RNlÖÝ›sIÀ‚ä¯ÄOÏ%«¡:š0!†ÃÞUS@pÿñŸˆI Z(0’è $ÛW»{ŽÂ^ç!Ž;S3ÐÝöÖ¢…»º #‘303!‚zD'" sعgä@a@ÈæáÄn¾]ör¦ý‰è*L`˜=P‘Iu˜!0!ºí WB’+EÔ‡›vUD!”ˆn…àèªÃL%IJB Ä=ˆÈ‘Ý_Ÿk{I„4: @¶P"fØ”µjÉež‹Ç·”‹HÂ0tЗçñçÿåçO߯§¯ˆ¥õqÝ®‡y~ûöí×~òí×ß.S>¦7oN£Ö:å#…Îe „—õÓ?ýóÿß°–ZI}íÆZ íÍ>”33ªu'$ ýEN €D殪åÕä€Ä(îÝc/„¡¿–¥_‡dôºš DB$Ý?+ßiyæ@(èn€¼oû_¶ìAA€ˆj>ö_40Ü›‰ˆ>öŒPFðê‚Aaû¦=tØBrع¾¶ÿ ‚˜’°‡1¡{$ÉLØÍºY˜££1²¹šà0Àœ2BDÉ9LÝ"Á€0m}#¢]g½W% éèµÛVuÛ: '‚ã‡Y ¨Ž@IkÛºv>ÎK&öPÄ a!æÑ5Õª$´@Ddj®Ž°ëÎÍ´6í jóÛm=fJÜÔ™ˆÌrž8åÑ;€†¹ãí6î÷ÍB?|x8Í’%'æÑíåv»lmÝš«ýîÍ$(èªH¼$9®kx¿¬ÛmÛVu-Svê£5rTuÉÓ"“6¿^j.KÎé|ž¢nÚ4,¢yÖû¶]^žJ¢Ó)M'.ešÊ”rÖ>Z¯çiƀ˺nc¸ÊíÞq)s»YÇ6M”3e)ÂLƒSŒá×˸·Á’ÀéùóuT›®[Â2ËñPŽ“¤Œ:ìéóZW7¥ ÎçŒ0²p_c»©¤9Þ”w§~¿‰À´üÓÿï·:ÖºõÐ{_KJIø°¤Ç7‡eÉ­õÑ:HJÑ{wóe™rB07÷àý^`áDÈœ)ÈÔ:£¸Kr3#3#bB!"O,q@°:#¤œ",ÂûhÄbcOèSxu¸îmG¤Ýo$LÂ0¬iX"‡aÀÁœvˆñ>25÷ÚS“ƒv2«n÷G:(!îLL¤Wù-¢q!EfôÚÜ»H :‘;ØË€ B&°7a,¼§æ˜p/õÄØß®ÌÀ5 ‚2“C #MÓ´÷ "pÅ uíHháæÄRÕlXÄ^~ý=Qx€)0c„ F dâýÐ"ðý îüJ…@dB‡0w —$áÀˆæ–„™™˜~4Èðç^¬¥o¿ù“Û:ÂÓ<-o¿zÿþíã™ÝØXRmuŒî®Õ€ÇOÏ\ŽU۽ߟ_¾üçö?~ú”J)³Ž3x?æÌt8.m¨z¸;cí#)ضªfûˆçöÐ<—å…9 Ü5çT#Œ™„9¥åmt@tˆÝßîXöZôk38v‰æb v„`À}A±{Ì"öÂÓ+[ÂÃÃwÖ7øN’ t 'Bƒ´·" À™)»íÅqµØ¯ ;e‚w{"º›Û °D2 wÀ¦Ž"æCµaÎSR"!Ön@HÁ™ÉÃö©`˜1R  ŽÞUA’0Q! dƒ0fp $æ”G„…3Ó~S–>ÔÀ™ÃÌ Üh]Ž–Ü4¥È¼sd =ÜcF$À®ÖÕ½©¶nàˆ@œ¸õû<§mÛꪦ(’8¡dd¢ÌA V·­®·Þ)Þ¾9–I|ô!\./Û¶iUÈ™çÂiFpó6ö¡·Žïo÷ ˆïßÍ"Þ›_.}tɹõ[½´Ã±Àöæñœ“‘¹}~¾¦©µ-€°µ!|Ô¡jöòT_.U&ûùßx/ì™yh¥R&áæªc«í~­÷{cNˆL$£$”„Ipž ßï­µÑG—Ì{¨) Œ^3E"ä %±y‘RXæI˜ÿÃð?CY'¾n·ŸŠê4WdVÝÍzs8œÜ[’[zÈà©*Ëf¾)‘‘‡çóyë£þé–E¦ãñùêjVöeZ(NRO§:ÉnžlËïžNN ε Q83³ŠÔ²«…"ŸŸnn¯T™•˜ˆˆ?~8¼ûö°”ý~7IAQÌuJ§Ói $˜Ë2gæùtôÀ¶®ÓÌÓ$ªe=ÆñxJ¦Ã©ŸO¨;~õéîjÇì᫸•Öi‹^¹^ê¶¶‡§çm³Þ|ø“j‘Ýn™jéæ™ê†óyUÍy¯WW;vDïZ8É©$šp©)™$báA úÇÿá?9I„)«hs/"ðpw)Doƒ«žnÁʃ¬’ƒ £ÊZ@LLC÷j>zZÎ "D·±‰JŠî©‘ Ànîƒ9Üɸ 4·BO>ç`[š ’'±deŒ&f¤‘©œá9ÚO¢‘k †Q–d(‡gÆ-"¢–R„E8‰#óp<¶Ö‰YED p-ž"âYX„Ü}åA JŽ×Z3Æ÷¦#DÁÙ½oÝœÝíúêJ‹dKÃ_‹DÀ… ì{‚A^dÉd¥01Á{ô sXª0 !ÓÜ<ÉÜ…¹¨±g„wUR7ßð ‚2xQ òÍÖÞ]HçZ’2ˆÂs´™Dä>O3È#B¸ˆ s„Ç–AD •" ÷d‘ˆÌ  MÖ#û˜’ G ˜3{¦gÒáy{ýòUx@D¥¬ÛöÝ7ïÝâöÕ‹Rdª¥2ÍunÆm•~–·¯¿¼{ù†X›åñ¸ž×¶Ì;æAÆñäUIó~ÿøüîÃ÷Þ=>ûðô«/põöÓkɧ§s—™%„ÃÂ…¨R€FئÌñìfƒ¹GO &È[ä&€2 Ù39Pˆ=’EZM(<#'cE4fH‰L".‚ § Þ63ï,Ü-æi_w×uÙ!m]]2~ˆAXohXôð€’“1*Àæ[B˜•²#65Psgf†0³’h21Œ]U(áa™á ÎL’('aˆ’DI™”€ˆ\2d0 À k›žîp ×¢çs 9Qðtx‚ŒDŠEn[#¡w7Ìåéá¹NÃø!,¸@3ùpZ!B”îmд˜tÛºˆNµ<ÒR"¹šm1_•Ûë{³€¥F³áµ²ÖJ–fpÌuGIi.¤Ó\Oíd½ ˜˜[sBq£ãñt<Ÿ,]¦’ˆ"—‹iQ ÜÜÌH+káãsô›vh‡÷«'7@m·¿Ù×­ŽëÉ}õ:×ë«=¢/³’¦je7?<>OS¹ºš…ؽ—‰“B‡¼5@,ΰðn=3‰èý{ÿzrn6&¾Y’„U Q0²ªšÇš Qb(óq¤¸"ðýid@rOKšœ…%8-s#/Y&ª$ rOxä85QlFA, ï–` –ø±L¸g:”•E“âx<”¢ª³J͈ÖONÄ­uagasÓRˆ¹[I£ ˜ƒºû½ÿvèE†TîmÙUfjÍÌaróp'᱄CF²“ sJD/¥¦£÷ðiZ2°m‰çeƒ/bbÕÖš_–lH"¢´°D"¹èÄDî™FÙ5DDÉá]UœF¬‡€ á±`Ì™‰tÏ©ˆ»KjC1à£YFY’ä„”ò'ù›$‰0”JãìïÄÉÃÞH8€FȈ…*sagŒîP‰€ˆÊ¢tÑæ$(‹£†“™UÕzc0³P’Šr õh€lg?òzwEçm53ð¤Ë®f˜['pÀHqs{ãÝá(Ì~\×yž‹Tppx$8z¬Û6ͳ;Á8ŒÚºÕR¯oö§~ðlSa÷ÈZåšî=üùt²Hs«*Ë\Y¼TªUàÙ63‡j‰¤0~~ZYɸ7üx|~J}q7ßÞÌË4o¶n¶fº’”Z–¹Î*“ 3ºmª<¬'DÔ[÷ IŽ FzZ’·F,“”äHJXºQ$ýûÿë¿OÄ˲Œ\[&AeË”R2°­ÏÞ;¬Ùá´@ÌÈ¢{•Z—$`/BàK›†F±H‘¤,fý²,Í’HX ‰˜YˆIEÌÂ,ªh"Í{¦¹E‹›y¸3‘’–2ûÅå‘ÿ?™q8¶m¦IUDe<¿ê4 §õuµžéˆ 0’×ÖUh™•3…(È{¸-`›µRd™'FzïcmÕÍXÔ@¢\28“I’ȲdkÆÂ­9eµÞA!‚ZŠ‚Í#D’¸õžv.¥$@,œ9¶‹–ÖÑÚÌHJ1Å(y&#3˜éÁÄÌìá#{JÄÃçKéʱF§+ *"[³pbÅ2@ˆ”`á)¤Y†$œ(‘îRJdP¤Û( _Þ+i.<‚F08sM°¹gëB¤StŒ_!™€R.Œ{÷@‘Òá ƒ3…ŒÍ)'…%§ýÝý!RçiG˜ˆ®¾øüw^Ý}~5_÷uëáƒë7ב©Åݧu=l}¥¤ãéÉù9è@,”°Ö·ô`™X¸[W–´3™»çøÔC´$@ßÿY˱?§€[Zw–Ë{#$ Bd6[Ó“™Í“ˆ‘>”`IÃU„AS©ˆ¤$°t¶JÏB:Új‘"ãŒp©_\D$ 7ËL÷P•”$82%RÎqV–Œ’I4å2"$r‘H@I…ŠY€©Öâ>¾±½΄*EF„“Š{SU ïRT˜w {öùC(Æ,*9›ot áIVeâp·0„ÙÂ!€‰ 4\‘aá,LÂBDLÂ$Í›bòè[xl½%ät꽃¸@0OÅݪ–y*Ãw”faflçž›÷¥ÊLU}j-¾ýîÃØuÂãáyªStšo÷·¥(k®mýxÿ¸šiQo¶n§:×ÝnÚÍEE§¸Z@•®÷Ë<1K2SíÝZ7fMй­Ha0¹e$­k…JÌ“™›{æJœÆ^«ÄÚGf9"3s𷒙Ͳw×ZH<ÍÚÖY´Î…ˆE ’Náéô?ý_ü·ÆW–1k·pJÀ<)ÇJIÂr°â¾8€@¥”ácʈP©ð‘-OQÍî­mµŒG VoD¤Z‘èÝÂS„"œ9YU™Ñ{‹@ëd˜{d–y r-Ek›j*aBRš÷yž‰D¸œg³^Š–:Ð+3%’UÖfìÝj‘ý²‹p÷èÝÏkŸ&ž—Ê6¼‘ X7¡R´žÖ3”‡y*Zg°¨ìÔ7ÕiR¡ÊAÙ2'’"F^§D¸„§ äéæ,ÌÄ96‘¤%Fº£››[¤Vb Çps†9Y¢»[#ÆTŠ–bݤˆŒ…@f ,"€B<¬ñ[ï¬2Â0£„‘Á½©‰V)Ì¥jdŒu"ŠðdF©’i"ä`b¦Ì2ª(!“ Bæ]I…% O¸õŽÓÚ¾¹™æ"E‚GX<•u̹I½¸ ËÙ"=òëÙŸÎŽeºúöëÇ¢7/^|òwÿÕ?¾½Ú«J­§ð4i• ¦¾Ù9±¾ûðU©!j›oïцažS¨)3¥ 7t„‡ûþꪙ[˜›¹5 'rœI·Öƒùo>(¢Lb­›¹[ïfUT"LXq¡»†( ,å¸î"Ýýû@)‚™=1vk4"¿¤fÁ ôaaÎpKŒIep7Kº0üD™ÕºµÕò_'š˜"3Ìâ‘[oH33g„P¤ŠHѼð"9¬T™Ý„!ÉÎ aªµhÕ"Þ“…H9ǹ`6h‡C*E˜™8˜¡ÃtJ,F¨j‚{PRVÂ23{öÞ{d6ësöË.ÜÍz÷îN, AEÌ{db¢¨ÌÑáf6•i=›Yåá|üä“»„s&Ý9K6[z Œ#×ù9¾úÙãÇq8xdÿâó«·_L·wûîAĥȂ@¦e÷°<¬íØ:[ÛV&¾ÝOpPðùÜν§âöúZÍÖ ¬­¨{˜»{(’É!†~jÄ &±d’ƒŠ'¤hFH ÌOÙ¨jaŽ ÖäpòNÞ‰“˜=àNˆ‹>õ¶9)X‰ „™Û¶ºýOþgII ¢%²Â"™%- !",:HY 3%e2‡1»{_L¯ñý'5‘–Ì@z†‰ˆ ømfïP0 Óe*€D H8‰·îSŠ;ï½zK™Øc%P¦J]<² ÷H‹ÓqpQÉŒº«@O`=›HÕ…R2ƒ¬YH‚²[l=[ fÎpo*­ŒL³p⑼˜Er€Š:÷)ŽÔBŒÈaOf³R¨&Ä#äƒÓÂɉ $ “aìºâ2I,TdÁ‰‘n+Ý£¹ ¬L,¬ãqàî1kåL%0§Å@\‚…RàpS(Iê™!râ<Ì¢R»{2ªjáïÓõ™C6@i¥ð¸› @<ôD‘¡ÂÂJ(;Ò¶m¯Ì€Ú°zÐf‘™W»2UP4‘*\gÎ$‚žÎÍ2>þöþÝ·§ûgûÁg?úÉg?¹º¾sÈiõ—¯ßÎÓŒÌ$Ÿ‹ÌªŠ(JZðôð-Ã8OïŽþÐruúv©ìµ²{2¸l÷ ©›'ZÈÝd<^“ǽzŒ2Â=ÁIãà ŠˆR§È<Ÿ»{ºYtŸw×Åå„Ké£êµ¹R!–î`wÿÞçsiùQÆX|yP8…'X="ÓKáIEU,}Æ68“=AB¢z>ŸÇ(‚fJE‹¨"s,ñ=3(‚\Š´Ö(“Gä7òû½&w3†$=‘F ÐèCpKkŒæ01(8<‚ƒ‰”аœE}‚E¦©”Ö¶Þ¶RÔáÝ#‰…DÀ woLi‘¿­\ ×H²p;žOŽ\J½® 8ç#8Yàn b0e2ƒ˜EÕ-ºg™‚)ÇH-€¸eoíÜÏ­æY®–yªsxTD‹0œ€ô¯qÿ‹Ÿ×FIXf­%–ÙDúííòƒÏ?ÁÈMeŒýwxÕŒHOóÁ šhFgd¦ %™J§<·Í[#ÐÕþ ë}h5X™Ñ##A¼¶¶¶ž VŠpòÌ ;°‚Šªz‰T)v£0DØK!ÆÀ¶'«P‚ :©Š¦çym[sââ*ŒÌ ¡JrUNå4s 'ìpœNd”8¬DyÐ È…i…É»s-µå8ú%Iý^úÚ»µ R-àÿ€8à2—î³€¢‡ÊD ­œŠË!‚…z7ë.UÖíœÞgÖWw;&ZÛÖ-Pa®µð-ÎvfeeKÓ ]«²”IB <Õº{|| 7g±°LRa º,¶œà ŽJ˜KIæsïIIᙌK"™É‘Í<‘ÁSQM¶­5¤alÜI•)’žæ–JBÄYH’8 ª*ˆÑ-0H©Sf*;«$Á3YT¥r$óˆBZð˜ Ô"¬Ý¼»;H¤T™,Zˆ³÷5ÙFÂçöön j°j‚Ø/óNâ1Bš i*@P¤sabLeWB YØÂKÑnfx!!&ð€úÖRPÚ:N§öð°>=>×~:X¸"ËÍí‹·×Dw÷x{ûz¿¿®ZÇEs©*t{½_*»ì«ßþÕ»ÇwÝÖyWާ§ãñP´ÜÓ_úúþÑ=ÅYd·›Áœæp‡JE(s& ÷>êÌp·Ë6_ 1!9IÞ¬ vsÙÖ ž –ó«Ó…GAd<vÌ ̰È@Ú,Úª "îݺ'à€S²¤’2+—ôñJE@B p„ËHÝy&¢(”U2;Á3"C܆o”¡aQì—êfãÝ–lcÂAP"‡™TÌʤÊl`p"ɇŸGN\¤zfJ&%•T³æœß½;Ø‘(éæöj{]¦ô8÷m¥*Êõõ "ía*Òa™êÄ%]‚¨(ßí—Ö[3O ÑOx4H ”+Q¢¨8È9…‰îœA@¶Âå|\ßxè!WW·û+ ïL ´$³]¦)Se!3ÓpUÑn.wKL2WfÕ  *‘aéLc4ó0wxObQ1·ŒdɈ„$i {í´“uDY=¡”™Ý¢¨dæx¥r"ªªá°fán…sµ³e ÍᮕÂuGˆ“QÌ3EKßzâqÝ–:WaÜ,·AIE¹™©LßÛƒYÈͶ§u‘L" ‘’„!À!¢Ý2y´ncïš›¡’ùÜŽ‘>M“[d¤0O3[‘â¤n!ÄÝ©G€áUT.Q‘Dr¡$ç$ S¢ C)˜±B'VQ˜¼ˆ$º+<á>Â?j6ø@Þ,׆u³öéÖÌ3ŒtµŸ—Ù >×…TKø¥`‘AD’#x°JÊ!”€UJÕ€')E@uëÂÔÖ³ŠÂ‘Â.˜æy)³B[{|<¹[#6ެuzóðÍ»Ö_¼|ýòoýä“W/^ϵªòT*%1a™êõÕ4ÍSaR%‘l¶=ÏïýøþÜÏv<¬÷·uµv|-E÷†¤å»ÒM9^¾ÜŽÏ=ÀZDJëE Ф˜JI·1£¥¥8óðÑQ· 9±H]†Ñ% -ƒ(# *AÆœBi>‘—=+!Ò<ò¢ÐŒä°ä¢nÖÖÓÐsj) "H¤RŠdÚˆV0S"Ô£Ox$ ‚@7Ó"½TÉÐŒ3sñH-ämÌ—B)!œ^ež—+&‰È5ZFgN3÷$æb.â–™ÄÌJ”¬#ç7 ߌÈ@•Š‚S;¸…Š”Z¦©˜÷J¼±?B„c謋j•bsQ% ÅhØ@Ì,¼³ ÖÔRÜ=U(z°ÖMUXF²/0Vñ™–f‘nƒgÇá©\£Õ ÂL‰ÂšNœc”•T¬átîÑééÐß=žŸŽN=—Ùæªç“·m[öe.ûëÝžï>¾“)×~dŽQ(©e2s¿hÿ¨µîž?ŸžrR*Ç–/’^ÞݦÑú÷gséf­‡Œ™¥‹ on:Yï‘!Z€taFϱæ«ÄZ4| åjDXk2ãöv©»²žO+…°•|±ÿøèa$`?¬}^D„¯æéîzww{MÿËÿßì­]n¡™D2°æ™éa™An” ¦ÔÊe ˜ÒÌ(T“„C=D™îFàp-’u3dÎÓ|:mE'–‰GÃÆ½m„YFe›E Ò¢žP&RÊLw@¨åÐiŒ¤s¤É#2•‡ ‹·n©ƒÊÀ´ö¾®ÚÖ˜¦©5kî03Þ_íYTØG“(ƒ½;+Í¥T•qíîÞ™Tyé)i½YkÍ<—Ý~Y*Ó6àŸ#‡>fe#½R$‘äÁcöÃc}mP)ÊB™–|™8o ƒ»{É#…ÉDŽp¸yxêùŒÖRËR„Óºeò4•i*¥ªjq‹YØ)²5ó 3pre•¡'­Ú $Þ¶ÆJ™[Zª”ÕzRŠ"=…™“¬÷RÔF‡@“"ò4bòáμmE+I12ŠHDtwžëÄ4†à>î"ðh™’I‰Òú¶­Ý:kñnDNäa*© Jprï>ÏI3¡p¢Ñ¬fÖ Ê G˜»k<À „) ð l#(º»Ra* PZ×Z´pT,„ˆîÝ­uDÌug¯Þ­™±» åTÕ‚ ÉÑbÀÓ¶s§PoÞ=¤J"bUf*˲•¤lîÞ†õxŠHKní\fÙ]MÍV8??·wß=LËrs»g¡ûûÇÛÛ»¶µ¶m×·ûi_΀ožóºzF¡¥‘YD`ž&3»D½Ù8^pÌ‘€EU…Äy=1ˆˆ½÷Lw»E¬;‰ª¹³õ`Iº{3KÖZ™j·ó´èt†sˆNˆI)³yªŠõŽ„»ƒé0–x·«ÝN«4k"ª(JÊ•3»{ÏÈtŒm‰I¤›•¹£Œ«·r·ÆÊ,»¶'X0²lŠ‘½òäRgkm¼ ÁhÖdìÓ.®EJâÌ‘­Â%å410œL™!ÌS碽µÖ1-“(!ƒ‚ˆ‚…3Gâ3":G?äb²'çùãòý $c1ÉXƸsd €¤_vÔÂÌBD‚47( Z!BP23sa"NÖ ŽL'§‰Kô,{œêTÝ cJb~<»ÅÝí &9W¢bf€‘¤Á!R$Ä;ZÄ4ï(%Z²#I±n-RFn‘Äœ$b&¨;":‰10’U#ÚOÉá9ð@Dððñßrf#áH0•LLXÌŒY" ³r¸Ïª°Ìp01#ˆÃÓ‚„ˆÌ  :Ï­û¾îÈÒÓ %Ànf}­Z“©Ùêc¤Åz§Èñèf*ê¹yZ$D4Ër„7³V"fÝÌ@êé>ÍqFXfÌeÁhúQšU ï#ålÏN”…kf&.‘éámž&åjÞÆx`âä¤$rd2O:g7·Í³ò´Z„M“¶­¤­k™D ‹‰¨È0F&„=3 S™áÎÿGRÃ<Ì"l»X6“ˆE$J2F®– Ȭu´\{x$Á\ˆ†ºy‘Rʸ³7óLb¡ èð´ìw#;ãù°ÍË<•–al–¡ ï6뼫ói=²ÌZwžB½mç“=?Ý·Hk‡ï®—Û«ý8]l[×·«3ß^ݨխ…ÛªDirX×ZgVvï–þáôïªH„»ñp°’Œs©²Ç8ôÓ÷ú D:€"’(Ý-‘DÎËáºÜÚ˜™àÞŽ$8<BZæ žµœÚÚa&Œ$"e–¢ªÜ9¤LÃÕíÞ™‹°¸îFnÊ㋚ÌÄDœ:BƒÑ¢’6º—ÄÒ jŒZÌX!¸xd÷ bʘk¦îžBÌÜ[ó’§wIK¤'D-‚ÒÇyeôüÓ2Ʊ"3 Hì`AŽLáX‰#Éá<Þ ™Û?&E*âæÄ…KÑ¢çó‘L \~Ceô±ëHD)SÃð;ä‘ã!AfªtÙPPañÃAÌ"ˆìÑ· f.Dãê—4÷ Ÿ"š Uݶ†ðe),½(TëùÙÛ3}ûë§ô›÷÷Û¿ýoÿ®¯^<[3ÂxˆG’{]W†]-…ѯ¯¯–Ýn»Òúñ|cí÷çoïO_7?f88=c·»­áq>œ‚Éî.‘dAÃ…+œAÙAáÆ¤”ÊT‰„YçÄ¥Î&ìšTIz4)SÄxÉÁI7kDé¶-¥‘9‚üÜÌ)¬äîN£÷GQ¹Œ ïÓéÑUj¹\f"áŽ1îKIÂc@|¢ƒ(B¬Ì½§ØĬŒI‚ÍÒL­;¥ÍÓ4|cT",n®Êwï‘ ¤ƒaäÉ @åMJëéîS­ã„C”ª*¬¥Ì…xÛÜ:¤¨V´X‹’Rp&‰0HÄÌ, "Äæ[)ÊÉÍãtóx¸ú¨}–Ì4 í .Äà” ‰t‡CQˆÄ“|q ·ÍÚ‡ûS™>{ó…YêTXËù¼e†÷^TºÅÙ£ÓnÚ Ö• /SUÒqúÌЭŸÎíÙÞá=—y—éO‰ c¥%zùÕW_ÝÞ^—B Ÿ§ºÆÑ}‹Þ½ƒh×"šÞIe.=ûñ¸>=oÇ£«”í|ªóˆv×õåÝÕñþ¾Ì ²¥VÊ$åÓÖaµH¤¬ëŠÄ¶5ô  §3SÕ¢µ„{Õ¢ª9x!I[wíK @,¶¶fؼ«eW_Ýíï¿Õݼ¸™hF„R9=oÛÙæûiö­õÞ§y¦ÿà?þwQãÐêă÷1–6Þj3ÏQtJˆè è\ 0áéŽÌŒÐR˜©÷-Ü.)1à ÔFGRa#PÄ÷SáÏA{3<²[ EêdŠòX*#Àþ>›¦dq·N!N°&‘nÀ™éÌŽ ·¡îN¶„$s‚ÓlR*¼èì6¦ÛÉH³N4Þ)œ²>$3Ü,"éRÇK2„hÄcœ _ ”Ðð¸œ"™„4"%Ó’Œ‘E43Gg«TõŒ$rs%ŽÁñabÔ„Xi…úž•Ã霺í¯öUI8nöËáðt½_Òýùyµ(÷«9N§—/®÷/3'ÇÚ7Kê!}ë{-DÊÝR¦ôÜN‰œ¤r²1{r€D„"„`Ûë 8k)INÎ * 9Ò“V‹îáié­K׊««J”H¡ZØ}j§]oÆT­‘ЄÔfÖÚ¦,U•þñ?ùwˆHOÇ|e)¥˜{7C„°Æ( 2Ò“!bQHj["“Tʰȇ ó•e’Ži:Hˆ§ô/ÛÚ°pKßΩÕ1VË–Ö'-ÊRjí}«µán ¨ e’¥X¤axhi™"ÑR’DXôKI’< ~Üú¼{§C»½}óöó·¤ÒÛë[…Мu;3|½Ú%—p߈iš–»ýË7¯îÜí݇‡_ó݇Ó{’Íñ¤Ú„£YsGB¨Á,  S‚* KxšÅP¡‰ðÐ"‹ªÃ‰2<­…Hs33 U˜ù2²ÞÆ4”D‡ë‰p`Ñ‚ Ê%‰˜©·3qcí[):wNˆ$BB¥Xï!RÌ"„N|Ä!"BÈ##i”cTËX®në¶Ì3œˆu·»ÉÍõ‹žñÝûßÞ?~w:=OSឤqVµðÄ]ZpjË "Qn’X§º›çeVa!v룰$€ÎL”h·xx8žÎZê¼ÈÝË¥h@†+“ªÌ…*±y‹ôð$¨#3©P¥bw"ó12`) ó¥N BeïAçæà¥J ÝNbœ/CI•)fê½9R§€àe=zo©Z~ôå—ëvÕ“î[³³jÙVýÍ×ço¿½¿½‘å÷?ïýt<AxÿáHŽgy÷ Øæ…æZ¿{÷-«”©2|?O ŽLs³ðRÕÇp†aänáÙ,<ùþþ)SH§ešf2Yâ´ž#=¼;«R€"T´áy=[f­ƒK’;<qÖªJz€Ø1ìJ4\ËéE…K-ÞÆhQÖÖ·<@ô¹žÎ'$BÁÕõ²Ÿçóimî:ÉÕÕáëjWón–9,æi9ž·fFLEøz¿£ÿðý÷j­ÄwgR0H8”ž~¡Ý€à1Õ&\‚>"EËPÃsQ¶Ö‹Hz¤'3Σ¥•hmëÞUçn¹®ë²LÏǃrÝÏWkߦ¹Ú‘IJ’)JM&ÎïOm ‚AÈ€2¿/ÐÔºÄNe*¡²™FŸù"%4‹Lb.Æ‚H9}¿H“‚ÆÛ! >X˜< ±ŠšusÀ” ½¢+ †[ ºãââAePz0' ¢2’)kÑŒ` ùX g:dkF<øx#«5Ì<Žï!œ`²HK—L¡Z"RRŽ$$ ʈ`óÌ¢J™Ñe¯¤ôéù IBžÖ,<Ò»²ô{ß×¶Ûï<°,wEn‘u™—yWB¶eÏ¿ýú—ß~÷õ—?þÉõÕK¥+rËÕÍõ­è¶Ÿi?hÝí¯zÛ@IOûúÝW?ÿõŸ7œæk¥4÷ÖmÀ4)ƒ‰ê%)ó<%ùê­ÛÆÄE¡qßq³•-5‰}(£=8!—Œ6k]/ZɱM Ê ‹– ÌÁú'! ¤eFá È“¦…É/i–m[K=1®RÐGä×pÂå€w(«›¥E&,¹PV•Èð•âÖ3cX¸s`u¥œNí|ìS™çåêþéyó­.2U¡ŒpPQqë1ÜÙ[Œ"#3q‘B9°œVÊð›ÙÝIRPE#£™=ÎOOG•òâöjىȈ2Ù¨¦x\¢`®*éQ´v÷ÞœœTT§2ð×@‚œ¥2—ýÖâã‡ûZ³,ÁÚ]2Éûå_gª%ÂÒÛšŠë_ýòùx^ðƒÏ‰1/óÏ~ñËT}x|lëúæÕÝínþâÓ·ušÖm=¯‡L3§ÍËÖû<Ù‹›2O÷ˆ0"šq„°ts‰n@¨êEºJ ßÜG¯Æúæí\X‰4I=àé™Á¤‘lÍ!‘H­ ,Ȉìî¼­~>­µ”i*f ¦R´,ÏO'ëcv`»:3P´$ÁD.Ì6ƧªàAHF$Àjˆd¢D#Éû§ÇûÇÇDÔIon®E¸÷µ¨Ö©d WÞͲëçdÒ‡ÇÇS;–Rk)u’·Wô?ÿ_ý·—y~q!²¤°¨Z’@"[·Ö· /¥ôœæ¥Ö@¶ÖHøùñùf·ŸêLĬLpdðÀ”ÖÚ¸X 2· ‚„§0•™FR"(Ü¡Z’8X$œ,¤’³{Ä @(zÂY‚‹ÊõòÒ„‡ƒ4ƒ"¼A€‡GÅ,Î9ŒÌL× ðˆ–1ØÜ}„^ˆ  B…39Ý™"/ý}&"„§Ÿ·Í¬/Ó¬R=h*àÌ XRV.éH°Eúæ=", I9xT‰„’ˆÅÏ.!i`°è°| Ç“eånÝÌF¢î?aBS°ݽ*UV¸I´¹‘Ê€ðQ¦Ã×­#Y“«”¶kÑ©NN²N«åÙâ춺ƒ‡M0ïw¯‰®Ræùê¶.JÜkUÕ)zcö$ÿîþ·‡Ó‡m;$üÇ¿óƒÇ‡gÍýËݧ¿ûÙO?}ù™ÛyÝNZ»¯g{ùò÷•ØO§§wO_ýöþgó•ÔªµïÝ­·fÄ21Uƒˆƒ4'Œ¤<·s¸íæ]ĸy€TI°T.3@S)ƒ ¬¥ÎDa¾E¶u=—u]Í3²ô#La=mHd!ˆh^æ1¯@™CÞ¨Z”u`77•æµ”m;33ebè©Y¤õ§¬áH"Ö¤ˆ !uó áµn­]ž²Þ}ªSÆ„¥›‰ÐП¥«¨§˜8‰Ð{K·ñú±Þ#“ŠrQ[o¥è‹΂ûSNTŽ V&Vå!€À¨í2˜Éêð‹2c´XŸŸ“LŸú©j)²;› µv:ŸOk„™o®^œ·çäãÖv»Ðç§û««Y¯“†ÛœOçãÍíνe&‘î§›h Lòðôxê§eÙ'B*í¯fúþé¿Ó#5;#l™ënYJ­O‡'™ˆ€í°~þêíë«7/vŸ^ïnÔC"éùñéëo¾ÕÝõ<_—ª­\Û‡³½“eV9<Ÿ¥Q¶vΉ¦áþ4\B8ä™ÂÖ8›™K­CÉfaI$R*±»%1¤0ª¥má›P’ øpçF0ñ¹ÛæD(}óñj±Ö ¶a­R·¨h&˜¨{cÎñóÍ¥šÛf-I<ÇúˆTpa ÏîðGŸêÕÍW¿~÷íoõGç'ŸÜ]òâåáé1$¯ïnÞ÷õ²¯¢ìfµN={ëít>íê´›¦Zdš÷ Bë+˜<@wœÏö|<\_ívs! ›u`Pí˜R†Ê0€H'&¢(ÌÜCY‰8@ç¶™õ1:vb8´h$ÉZdðÚOg{‚”Ì2úïSTŠw·Í8Á¢±ngJ-„4ó„d`³sÛÎÂÌ* btëÑ"2Rª‡³PdD ànéÁÇsߺ»M*‰LÊiÀô"iÖÃS„hÖ‡ÿi À§Zö»ÝýǵJ]&"m'³>•9"Tøx8MéÙ›øp<»ò²L™v{»ÔIè?ùOÿÇm|îzwëv|> Ë<©(É=FCf!¦LDRD •}Ía.EͶ€g‚CU¬[k „Ö»ª 6 woCÕ=„~bkMEŠ ðÆ!Jo…„ îÝÒCU{˜g€…XÌb`îg"¡”°x0À.~B‚Òy”Ð PŽ„”)ÈZD‰={^ŠAA3Âà˜‚0ë13Ì£ûbaxW½Œ×™%S¬·Z5¢e&¥²Ž )ÃÐàŒ´E3T%܇ófÒ…@§õ@™'ëAÓTáfÖc’)=檬𠄇HIÏÌ,,ó4÷Þ•Å#³”ìôüáôõ¯ÞÝìoß?|Ü667Ÿ½~>lÿ·ÿç?ûÃ?üÝëk]öµÎKÝß”I‰lRp4}|>hÑ)z4ßOO"¥m¶+˧/ß|ùæGŸ\}6ÑNó¾¦H·í¼ÿ«¿üóûuýôÓ—§ãwû]$Î&±°h7ÇHÀ w12<¶>¦šñJWjfIi}ÝM äp=šû¼,ÄÒ»„²€©‡Ûæ adDg²˜A©RRëk­“jÙZïTÆ¿o½[¸0+Œíº‡]N‘" ‡Õ¹ŽœB¸'ÐÍ“ˆDZïHUèR§ÞZ›5p¤è¤ZZkÇù$¸”‰"žÝŒITKº»7K r›¸ˆ#ˆÐÜ“1¤”d‚ÑËň*™eÂÝY¤‡‹rLµz?KÉÞ“¥ºxd©’™¹²åõt,R¾ýæý·ïï¿üòKB>|ø0׺¿½I"$ýæ×_þÅÖõtu5+ãtÞœ„©to‡ÇÍp}=¿¼»Z¦…ÒX‚$v»]v"ò!ÚZ‹ì$lÞM‰wû}ku¦#ͽƒÒÃFÜ·Ž ÝõÍá´ÛT±[ª[G’÷RÖ‹ÌŽ ¤olúÖÞÌ=3Íz0©L•'eŇ„¨L›…!Nv´à:Ý MÙs˼­ÖÖžNÍWOp)Ò­_ðˆ)ÚÍHØÌª–¾5d{NºwÎ ¹( wÉH¸q$ŒÙ¶Îéá^Š"B¶ÞXˆñ T­¡TÉZËXî–eWåxxüöþýó¹ÊËÛ×Þ­7ùâN„Í­m«Oçf=)—ý®”Üïôöf¿Ô‰þ·ÿéÿˆ£sZdzp0˜ØZgJ–g0§‚óB;‡g²jaÐ@=RFŽì$ä â’¸b·nZ§:Í™>â1îãE\›õºTÇvÓÝF¹H)µzô„#\ÄÚ-™T™…³û¶…wwáâÖ»7Jf–áxQ‘*0Ö„ÐÚœ˜"R‡ØÔY†¸„‰jƒ™ŽäaÊù/(2rI8JBRÀJ¾ìÝ6i‘™ˆYÄÓ[ÛJ¤c$PŠj-,d½Áœ“Þ==h‘ýnc,Ô•™0&N‘̾("Š K×,RHO§­ÈÔ¶´·7×* ˜£Ïëyõ¢b#Ðz´û§_üì7Ó|õñÃógo (½9m+=žo^/=ÖåõÕøùùø8׺̻‡‡÷±ÛOÝX»Å·ï¾{ûöóãÓIƒ¯vW,%œ~øÙ¿|ýåÂón·CFïáYžžOë¶N2íwsÃñŸýWÿÙ)¾yqwU+'bÝVJ©½5G…ylmŒþ£ª¨–¸PƒâÂÃ(%Äáv³!àMpõf¥Ì‡óªÂ’$›­Þ„Ö’K‰ŒˆLŠ€’½ÍµzÄikH!Po-Éœ!Žð"EXBåRâr_¦êݘ©Öº¶­»1kŒØ§ÈºZ@EÄÝ,³™®Z)¹–ÝõÍ‹û§ÇÌ-¼)ËÝíË ~|<ì÷w7ׯ¾ùöýÏ~ñ/½oï¿ùÇkëuÙ­ÏöáÃÓq]_¿¾YZ?~òéë$Û-“÷~^·›ûãñ~ëë¼»ÎÀ~žºm Dàéñxµ¿fÕßüæÛ¾áåËOæë²_8{¼ýä³?ýÓÿâíÛOUÅ¢AéÃÇ÷•fëç­=ß½zI:Sr*œ™A É1ž .ekýB¢ÊIŒ°ÍÀQŠª*% ÷ÍÂ… 3·î6<«é©Bî” Qï€ð¾n§DZ„*y‡;ƒêûÏ_¼}S4êÄÂHNÎÈî”3N …T-ÖÜÜ’1$ãmí­wTÝM׊:ÉÔ·­;T(žOGºsw«Jùþd˜Hq§ãɈB•X¸ÔÒzÄ“”²xX[ï…Ø[WÕaŒ" 6jƒœ,¢ b3Wƒ°µ-Ýb*Ö;àA‘#8`‘fûiI÷5|³ÎJ9³B´žWa}ý굪>‡ó¡Î»Çûó\wÌxx|º¾ºzu÷¢ˆÞ÷¼®±¶íÔ¤TUDúOÿÖñôðDÿ‡ÿã?@&³&QK€g7b4;ƒË˜|*³¹ES!’È/θ0¨‰"”¸ˆbëm$+ÂWà)=‰ˆŠhÕš•’Ì}¾8{;3“°"“˜"¢L…@æ *LË_"Ì›PZoà ¢nIT"pñ¥1ÀÈDÚáidîÂÑ×­Š"“ªÂr)”G¦¹ÛÐû U-#Ÿëˆè½¨Žª SxaVÕ¡mBbª †G€ÅÜÃl*³gbkkAÙš•:c@:ûª,L¼[öëºÖ¹öµ)‰ …§¥IÔ¥Åy;YÀ 0®2ï–rÿáÝûóóGùó?ÿÍÕþú¯öõû§TÜÜÍw/—ëëý‡w÷}ãWwŸþü¯¾º¹ž_¼ØòæÎ½ëá´‚h*åùé1EÍüÓÏ>ýŸþxº)áøÝþ˜,Ó¼·~sw·¿žÿúWõíw_¿zõêó7Ÿ2ñ»÷ï¯vûoûõÍÕÝïüäoÏåj7í…©­Gk}mñô¼><>ï¯oTgÿ`ò¾Ë‡óú±Ÿ­ê®ÌËi]7ïU%ÂZ[™ZJ2 ‹ Œ„”‘Ф!>&3öN}ké}.9yj¨LéänBÒ{,û+Ñéùãi?íöËr8?×ã?ø‘·ÎIß|ó~m^ ‡ÙËW/ç£S>|8½úìó}õ믿øòó¿úù/Íú?ø¬·óýÇ÷/n®×Ó±0×:¿ÿøt{ór¿Lχwó®ŽGïXtÞ/uÙ-_÷]lç~ûâæùpFN/ïÞLw;ˆÄÍõõù¸ŽëÖÚ?ÿ³ÿòÓ·oYåç¿ù—?üáÛ›Ýü—ñWW×wÛ¹ŸÚ¶Ü.ÌýîfÙÏË\燇§íì/n>y÷Ýwç~úÉ«×ÏO‡ûÇû¤¼½½¦É3~óÛßöÞ>ÿ쳫ëÝÓá!Ñ—eÖô©–¶mW7/¶n·¶`ém&ÈÂHD&&o¶z6PÖR4—ªãv–C\&æ.ªæ‘a ’²n› Û žHPQ®œÄ4Ydf/•,×ÌÑwãÞ2j]2Gš4F=ãl¾®vî-”÷¢ÓTÕ]àðܺ¯¥ ƒÒÆ®ÅD­§BF ÏÜ“Fû"Å=™5S2„³ (Üë**ÊÜ[ÇhêcÄF.™òŒntî`Ži>Z0ó€c”À²60EV.@¦CF XXIF…“"‘yÞZOl« ˜¤ _-SPto+2U´m½7k‘xôÆTÖˆÌÈišJ-»©^ï–(E{Çzî,rÞ$$†>~\?¼;¬vÒÍ»}dnÛé‡_|VYžŸéŸüÓÿn!‚§w J’au¤¡M”ŠôÖˆÀ¬ˆD²²"ÅÁ±õF`I¦”Ä b2@DÚ{C&ˆk„Ž«Èà+#$Ñi™—ÓéY›ŸˆE¥®ý˜Ø„‹…3S$V*»ˆ¤7 謁®›yêi fÖ"µ2qª¥w)”i æ*…0QŽ8©ŽP?™7b´‘¥Tª&–¥š‘žžt¡[óH$„e-‰!\zϯó]Ûúîzº¾ÝM¥x7` íå¤5,zë(˺më¹ÍÓ~ Ó©§÷~:[ós ¤A²Ìåûû°z}ûÉÃožÏ2OŸ$äw~øù~·xzz÷ñãÃé©yyûj=6Û¼uÿÍw_/Ëuë½.:Ïâ¾¶ÓÛÏÞ¾yýéýí?º½ºþÁ?ÿÿþóÿüÿ÷ù£ßýý?úÉßþÝ~9)îïNçþúîîÅíÕ¶ÿùŸþé«»W?øÁIÕá ‹YQE{ïf–áÛÖÿêg¿ÞZ’(دoj§ÇõÝýá×_üð…õCk›÷íùp4Ћ—¯)Ñ×-ÌY£oæ"TÀ0l €“˜Üìü|:V™ç]nþôŸýEbùôÍ›/æÊU0õÕw‡cÿâ‹Ï›?\_/×W7‡‡‡ýè'ï?||ÿøøgñW÷Û¬ó~Y^¿}ù'òŸýƒãßÚNýõW¿øí»ßþ?ø=oöæõ§ïÞ°Ì_þò×ÉÓ‹WožïßÜ]U‰i¿{÷px>^-Wo^½p?>>~ -îOkÇ‹›Û·wwWK9o'©2OõÕ‹ëõ|4÷yÞQ`mÇóº^ß¼¼{ñj==®}ûøðÀ*R„ȯ®®TI”J‘v^“*¥-:µ¶z¬æf®*h=Ý$2´+W7W7ï?|×Ò ÊLs-}šŠÙÖ­‹2 ÷Þ€bþÂE‰ç:,r-óf}kmðwºo[§Meà?y”nÒ‘S·õy{÷ã¿Ý¶ÖzžŽg÷¬“"ƒþÑÿî¿d¦ P•ܸ ‡ûu죵Viëù¯ÌD #)4Ì!:MÄ”æ¥NnŽ‹–“”Ĭ¥ž·S„¨TævOïî­7À‹2+cAF¨(ˆ²[“ë:àoh[óžÄJRDF11e ‚OëVf:,i*NÉÜ…r–©Ö1>¶óz äÐøh¸]¸x¤…¤ ÛÖU¹¨œNGRuÏmÛª %–y¶mŒæÆÊbR™®o®Â»’´m{z|¨už–¥T2ïçÃùp:ÃS]X¨oÞ·<­íáñéöÅ5 omÛÜ›ÛëW¯ŸŸ3b¿Ô¢´ÛMíù¸øyêN§ÓÚÎm.e™'0\âáùy*WǧÃñ°ž›ù²”e§Ÿ}öR«¼ùì‡ü‡ïËÏÞ*x¿Ünçç‡ûû«ëkG>žî¾ýçÿ埾~óéOÿÖß¹Û¿ÚOûÞ/±ýZ¢ ôÓñéj¿³fÌÜ{[·­µíp8ýÙŸý Ö9R:|wë4=ôxz÷áÝ'Ÿ|Än™J±m='!LeÖë§ç§nÞzKf•rx>}ûÍûWw¯®vK³þúÍ‹ÖO´ŸïžŸŽEëû®nvÏ[;–¹$«r½™o>|øŒÝ\3º ]_Ýnݧª§Óöøôâ,ôúî®W¨Ó¼¯ËÃÃG +K=õíjw¦*Ë´ëž— ª•z„êlîÈ$Ž„OSM0‘ºÌ£çàâƒF¹{ïR Ñ"ëºÒÀµ,æ4MûRêfG"ó0‚\í_œ·OwG„‡Gzp’›¹Åj†~~|œw»æˆÄþj5/½mÖ:1çåÛ â d:­"bÖ";±×²GPÚ@Jr‘Â<­§õ#+gò4_µµ­ëy3ߢC\$gsÌRеFĈ P¸Íµ²ÌÃ@jÖ|ˆ’¦iA¢haÁù|ÚínÒÉÂ,¢µŽÄT*3º­Ì.³6)¬Nœ¥gŽ™%¥®ÁæžB 8l '÷Üp‰ô ‡'s²yz’‡¹…ˆ˜ÑDÃF‘1:©:|0Gfd“PRó±ZRaæì2”ÝÄt$“P"2Ì£Ô2¨XÌÚ6V"n}HN£BRjs«¥FxÛ6ÅZV7kÌbÍYÄ<¼Gï™­ç¿ÀC è-Ë2©Ò<Ë'/ßn§þpÿøx¿N}^äå«å¸Döwׯ–:ù¿øë_¾xy{÷ê6ÜgáÇçÃfÞÓ¥úÇÿô_Ë˯DŠ‘S‡°€Ð¶&D*DE‹r½š˜Í,"h4|áÑI`™U$©€Å»Gt-äÑT8|¡*‰dXÛL¤D(f©›»1ˆHXXFµöÂ)]×v>m be†”ªK)5Ó¬a–>-¥ÖÒÍ>>>?=îîî–e|™óžˆf[k…ï÷W‡Ó¹[Så"¥ò”=ÝÇ1áO‡ýÕÕ~¿_çôœçIy€wxž&ÌóÔ¶µ–jݬ÷«ë«y^¬7ŸOëÃý£¨2r;?3×Ýr=”ŠA½{#–dýðî¡è"Z›Gá’–¤)Ê=ºNJœäHâpÀ:øæi¯/*-ãˆr:<™µë›Û‡§ƒÎ{†L»ýé|^æùêz~zzO⽯sY>¹þÉÿÑÿŸÿ/ÿ§óvþ{÷_ÿ£?øW'-=Zoæÿ¯?ù¿>Þ/Ë‹/>ýég/>}y÷‚‰î?>><ìw·Ÿ}úáS‘§‡ûçÃóóñÔ'뺵ÓéhëæÍ^¾~õúÍk)šÈe§=·p wa;¯G’dæLNpD’wAXëÌš\®S1 ±H„‰""ÂG0í2!B‹nÛ¦EÌZ„ K-ó•ÜÌÌEjoriCµ‚ ³Fœ@v·ÌPU°ha3S©*uõ!A”m[U¦p¸…ŠnkËÔ¢Åͬu×l%òóùxw{Ý{³nµÌc~ èC!¨gvo™E er¢Ôšëvrc¤hqfˆL*Ó¶mÌÔš{bs9sòÁ³ªµHe°\Ñ…Y!„ÎÂÂ…7ßôòhȈ ÕngófKzz>­Í^\¿´fu"âÎÒ@–éòNZ2b«õŠü…móÓã#OgžŒK #“(„ifˆ§y¶ÈNøN2’eXNGuóÒX†!<"ÙGŠuèRÌ-ÂÉP‚"žnÚ™,Âl†DÐÅ{ËpIDšuyŠ[Z"EX‹ˆ²»G¸0ÃÝá”H"á‘§áð ÆÛÍrížB2ˆ#ƒv À·7·»eçÝ@e¿,ßxø°n+XñæÓ»ÝNÃЛ¡ùáù±Lµî&-šý||\æºì&úÿ÷_Š67&©e¶¶¥B^8ð’ðˆŽ$(UÌ;.h¢ÞŒEX8݉xsëá×»ëÌߨÞ7 8™Q2Ù=•RDZošl ³uŒð_€ÑÍÌ#zjÝE²0Í•&Fߺ;—i"Ée*EJëÛÓáÉ3j™æ2#SˆŠ·(Se ë=˜<Às1 ܺ q_“°-UÖ­oÝjÕõ|Úï®™t=Ÿχ››«7Ÿ|RU2¢õæf"Ü{_×óá|:lk)…˜kUÞkY#T7 ÁR’É@K!)ª$š,ŠŸ—e]WU3Ì'­çþÕ¯¿ëÍ>}óæzµŸw¥ÔïÞývšusûtØ2õðø<—Ò·­™‹ÎÿÊOÿÐbý‹ùgo?ùÙo~û›ožÎ7××Éy8õ°2ñn–ùãÇûçãsÙݪÊýý»ÛÛ«yZÄö?þò÷ -Æe™Ïkß¶&U~ùÕÏ?yó²hyzzþâ?øÍo~ST_ßÝ=ÎçÖç?ûË?ùôG/ÜÏS¡úÿùÿÞm§ÇíÍ›ÏNÏÇ~ž¦Ú¶\·8mç»—76/Û?ø7þ5º˜žv:nIúpÿtssûôtÑÓÓñph_ýú}f çZê~™ž>ìå'¯Öµß?>ìv Ü9:-2Íúù›»Ÿ|ùò‡?~¥;r²ÝUEZI¢’žMtÏÍÖ$e%M" ê4îéI°Þz­s$fY–pßÖB­Óù¼íæ¯ë©µ6Í;.£‹lU„ˆ3¥™™o /¥D U7Ôe¶z·¨µ¶~_„ZŠ›ã"÷$®\Zëc ¹µhNÄ2Uñè»Ý…¼FH>OR´0M,[)µ‡—ªHy½€Xæ²®ÇÖ"œ˜ƒÂ{s@T9÷žÂÝ2æYDÆ„)i9’Ë-JNSÝ© ½LŠ2hÖG¨¶Ó"Dà£SR°zlg&ŒèW-S©Ôúöø°mg>?ëºæõÝôòÓk–­êÖ‡5œ¼Û<«Î´õ•€ï×Ƀ—Fƒl.*Õ<"B+dþ…bKž™$æ9J”½ ¡äB¿p»;ƒÙÍú0²¹©–nF f­îf½g©Ê"¼S Êîî­„ÇOÂ‰Ê “¨¨»›Y†º³<{¤! G ä¶ùzö×/?µ–ÝìË}‹ß<ŸÎѽyn7WóÝí'÷ÏÝûr}»­çyªS-Þl½¹Ú‹à|:ú‡ÿɿƜJfrÈć %%“"¢ %AK-™f–nÂàózÚZ“¢ Xo»R3òùp(Ë,s}>?_½|Y+!û¢‹Ô `ŸŽÏ뉙·¾“ªÞ^ßø'Kn¶›¦2 )©NQánvZ×e7Ã[!ªU3}kVêTˤY O•y¿¿nÛy®¶6w;¯](áÀ~õpxZ[›ç™"a]”{7¤Ôi l\ï®ÝÍÉ“áÌâ~¹ÏFºµ¶Î»y†¹y³û[ï·/_IÕÞ6·šz3DÖiÇZNÛp„±VáÊ:W¡E2‰êä銠ŒØÕšÞ{Ûšùº¶­7RRÅ\‹FI×̼úNš÷ËÓãQ³f§©ìÖ5Λ§TçúÛ_ÿÕŸßþ­ßûüÅ‹eݶÖú4-‡Ãéý‡ûçm{üpð5öó~¿ßÍN§,ó|sw-:©ïú“?ÔØÏõêp:N¹ž‡‘›š·"eÖºÔòéÛO>>~øù/ù|¶H÷öô‹Ÿÿùw?|<@É‚×3…;¥H&íÖƒEˆ1Æ#?üòæ÷~úêå ôS{x·¶µþú·ï6waæu[‹–´˜ªîwÓ‹›ë‡Ç {ûÙ«üèÍÃÓãÃáéÕ'/ïï뼸ùõ¼ŸU÷óò›o¾i­ÿð³Ï~õÕWß¾ûðûðãë[o7ûé§¿ÿ£¤V&ΞçêaÌ$E#ü|>¼ž{Cß ‹˜Üˆhݶà\ DÖZ(së§§‡ë«ež "„Ôœ#i³5`ª "÷逼fRˆPA »[2˜9SÛÚ‰x=¯­wû‰Á½ã´¹w™¤ çn?§Çù´îvKë½»Çð5…õf šæ ðKO˜òÔWGhk¡2…û~·sën§áœ=  ÎIùz™™)ªÄHd¸Ó<í™y X(™DD @ItZ-Ã3ržw fŠÞÓ̬žiÂÊ\·ž-Vp°·¤ ÀvûâÚ½|ûÍñp¯nªZ ë'o¯ˆ[·5à (e*eΰD³~÷5b.Jc_!D@‚Ô‚éE83Ý#HF´LŠ V1ï™(¨èìÉ[:§ÃC¨$$EÒM)káfÝrÜ©ÖeëáI ‚PX_µ ¹Ó…Ÿ•N¤RX2ÂÂ73„˜0(SÌc¾.¼tq€"[ DdCâx´ÓÙ÷ó 'gÆÝË·ûëûOªËé¼Ýü ZjhØ<4k‘y.ÊÈŒÖÖRÊnYÖóÙÝéóOþ³Fd„œJÑ-<9%26‡°Ð< ÂOÇÓùÜ—e·ž[Ûìúúf]×îVT»µåz.S­*»© 3±ˆ°› ¥™Ed\̘(,LÚ͘Z¬•™u™6÷𠘥N;ë 4ôKÎp&&‘Ý2­ë–)ª@ôÖŠN™ah r”nA4OÓn¿w·n[_{ßúTwçucvPöÞ=èúæNàݶîYfê<AT JæݳEtgG?­[„t¿ì{ JÇÐÆFJ²@ÈÑY1UU."ÑÛµsék#žæÝÕºµÓÚXjdêí|:žÖf¯_zZ·è¶Ì2ÍúþÃÇÖr·ß}ýþ×u‘/¿üâ|li #N§5X¾ûðñå'¯ß¼¹[f _—¹<==úæÍ_ÿìW}EÑý«Ï^%cmÛznmíOáýñÜ6‹/¾øéÍ|û“ÏŒŽ—··[?þ‹Ÿÿ¹N»y¹qÇ»÷îïOë¶õ˜—][×gÕLV-Ö×_üü/ÿå_ü¬÷yx^Í’œÊ$Î|L7[äæz7/Úái³¦cÌHà €¼Ìõöz™ª âáãsóž©”€%ItQXFd­åºÖÃãÁRz J¥ðœk¼»[~ðã»Woê͵î—2 ¦:-ûe·—««ºm-ÃX3ÂÌüz –Óz^Û6׉)…QЬýÔᙨZÍ#,k©½›#Œ‘%Yˆ’„YDekÛTk¹„;³DF‘T)áèÖ9 ̪ò||UåIuî=šm¢i­3   b©çcï[{ñâ&Ý™ÔÜAƒ»y±GÁŠf›™O>(Ý[ËæH-uþÿÓôg=·eÙy&6º9çjvóu§‰q¢a“I©È*Q–h”l¸lɸ ì¿âßÚ%6àºñ/üG †ÊBÁª’²Éb’™Ì&2NDœîkv³šÙŒ1|±Cacc­5Æxßç‰ š¡‘)6ƒuiªX\×ËR4RŒ²ÇÄÔÐ]M›™! k”x%W«BõhÔÅ~çóy55êÒPké¾{¶q,£»ˆ”µ´Öv»Ý|$ŸN‘¨O™$Æ ºZ )žn™–\>>§µ€ãWŸ}’×¶Û_w1\oé¢Cì äJ¼70`phÙôÂ!B b îxY̆XÌ€"@Ï#ú¥k Z­µX lMÍjk-H¼È7˜±ÌЈ‰¤oP*Õf5…CXÎ ŽÃàèÎÄàÚêì~Ù«¬nTr6]n^¼8Ÿ$.J›ã¦G`Á¾®íp~¤,ÌáÂj#ufÀÔ• k©J¸Ý\3‡2×2‘IB2÷æu­µ5!p0XëZµ "º‹#uÝxx:å¢Eáp:ì6[ÍòñÝú¢p7MÕÍjÅÔÇãt<‘<ôéðñôí›úͰ¿ºK"psµËë2n¥ëÓ¯¯¦åütÕÊ€(!Æ;IB+­ª ÛÝÍþzì#ym¥œÎsߨ¢×zaä9ž§LHII]í”]´Xѯ‹5kýfxýÕ]í͇‡ã/Ÿ´®hŠæ’^ßÅü?ù½g·Ãë×Wky¢ª/`¤^8x³yšç¾÷iG4pø‘vœÇÃf³‹"‹:’p‡Rê0ŒÇÃ+îÓ’¬å$¦ ½j-žºjÊ,ÌÑL«›©50'V€Vgª«!Q-JP… ‘pn¹AnR• kËH”Kqd@dpðvIB*Eo­ÎÅÁ±¶JbNªNóZ¼™ œKnÎcHcê;•j-ÙŽÛ±Ö)ƒ›iSm挱ë$;‚UP×µ®î®µQ.'3°¦ZJvÀaè*¬­UU€†B†F)FóºÖªPÍX€cˆ ”–I‡ÛqÇ~.3r®Í†.2ik̤©_f*È \ÉZ+ ƒ£›u©ï0¶š]Üɨ+X¯n„ ^–C"ìn‘ØÑÌ, AÝ.ÍÑÖ¼ ^"+™ L‰*–©d÷#A@ScP¨ ÎÚ¬=Ot‘cc§í5Uƒ¤yÎÚrÕ…ˆúЙiHÑš8•rñÿ930£‘™#;ÍÇ9 'In­äzÿñüáá‰R¸¾¾î‡ÐÆBÞÀ½©SXW­Ù…¤,e³ßÍËŠÿÕý/„ÙÝJk…!"#kSa!¡#‰€AÇÀJ]Í̵ (1´Ö‚¤ÖT˜]Š©°8ÁÇ讀^µ""w!\ 0뺒R3oææj BµV¦ÀÝÐtaB a×ÖZ­ª~iÜYÝŽ ÐsÓK)APš*£{0Ž…®5ÍK0B¦Ãá!ðP2HÄ®c4Gƒe®ŽÁµÈQ<ŒI$…µ4–˜ºЛÎunT6ÇÃá!¢XC¸ìû¬©zJÄŒfJ˜Ò”—RË¥ŸÐÇn©¥4'A! cß-糪A)óv7r ß}ÿî›o¿ˆW××êU­ Ãøüöªžçu­!õ×·;Ór{{;tRËt<>ä\ŽÇéêêöúê6ÅD^K[OÓi³ÝÓÇÇ·›aû7?ÿÍ‡ÇÆéúáøöú:½¸Û £yØïw›¡ó†­˜¢ÌÓRV»Þ½~võÕöB8tbàÝ8à¥MM¬jÕìáðÔLOçsˆaY§Þ,ËÜ÷é¢%˜Î­–’ëZÛheQ‡ãù¼¬kõ*"Ã0§Kåðt`"’0­ëškJ N,îÞuýí³—iÜãÕº®}ß…4QdªuÇ> óù”ó©éx:ÜÏZ$Äžï¯hYŸþÝ_ýÝáÔ¢óíÕöxš–Òr+Ï?¹ûôõ‹o¾ùÕ?øÙgúO¿ï—y=ç~Ø>Üõ«7±ëïž=Ÿ§iÓ÷_½þüâQ¯æ•„@["FÂKÌCÁb €Ò"‘aJ©”•™ˆ©Z3U !‰0ÔVÕLUY Ü´¶•áÒ DpREsRóè’(œ–eÜõBÉùB ›c1S4@z8œŽKJãÝí3"w=crknVkk‚$PbÁˆfÊÌ­VSk˺ðf7:˜›] kääîBˆ!ƼæZ/´róR 1vC·æÙLUPT›ÄÀ"­6PÂ͸#F „FhÓºÚ¼âñ0ÝÝm®ö( K)jjMÝ‚–°A¤*R–9¯œBµlÖÍ[k"’úØ!¸y0§Z´9’4Ûuž÷‹ýÄEÄšye"6¤Ë*ÜL‘ØÁ›šµÚÌimÍ4ʼn;ޱV'7$ç\k)cÆ1çc˜ÎÓ$ߪ*T@t ¤‰(zÖâlîHT ÄLJ².ÀcêÈ|™õÍ›‡§óq—>ýä&Rèûnؤ\–ušj5¿4ÑÜÈÉ‘áêîNBÂÿÇÿó_¨¡"¸–µš]¬ ¦ÆÌ—Šº‘·Æ(áR w r±·ZXÍbP8"’‚«9¶R€ iuBAºp›32¡0’ ©þèÉ"ü±~âª(q*€…1IÉksôÈXBè)tލ5»·¬•I.=èâ,¬“ï6W¹”q«µßx)ÐövüðÇ?<´"Ûíí×_öþþ»÷7û;A«­-¥¹ÑÝÝófíêöêþÃûN@÷Oç×_}^ò9 ÆÀo~ø!kýê÷>cleƒp+í|:çÒÆqç@=¤´ÝnJY‹–Óù”ÆË’·›«\Ô¼8¸9MóÒõ½ c²Ó4;Ä\Ú2/÷îwÛ«Òt³ÛÌçÓõ8ì·=`ÐZZk°ærs{×õ=‹×ºœÏ'mVjíwÃñ|ZÖzuu[‹6ZÇ¡ LóiB£f°7}ŠçãÝEÒÅ0öÏoîöŸELWÛkwj@ ÍÖ¥¸jÉKîº~Y–_ó›n·Fmõý'ÿÄ«‹hsäínŒ(‚„¥¬„¼LËØ'ß\]=>÷û«ZŒ%H._yÈTM™"ƒ—ù\òŠ$çyj†oßúa_š"P.5k͵þáÏ~æfàˆŽ÷Þj>’h7Ä·W–k”äN)E(':œ§Ç÷ŧ‡ÓãûÃÓßÿîÍo¾}šsÂùŸý³ßÿã?zÕtiMõë靈i[´½½÷ÅçŸ|ùé«ÈäŽÈ‘Í´mº¾êRÛ¬–›UB!g7sTÕÚtF@$¤ZÛ@×ÔCv™µÖÜ…µU4ÕzY™ª±s x ø—œEbuÆÙ/!îæ^´"mˆ@µTWRµ¾Ûti¬¥¬ÀkUwl¥ÄÀ~¼C˜¨ASo­Å.©éÅ {«æ^ œ ½‹1†Tª Ç‹ÕR›"ÑepHCmh°6 1u‚K^S !±ä¦àjjkmkÓ±ëúŽ8”µ9Ž¥z`ëz­¥±iAFøí›%kH)‚!F,Ú<8j®ìH.<-SØŽ½"5ÄË j6v à,ÄHU„Ì´µ†¢Ú„üâÐf1Esk-«;b d&Fp€V1` ÞCèÖ¬ç9«Aqbt%€g··÷ïsi¥™2«P¬9A$8(`¥â(Éù0µÚœ9ʰ‰×çãRjA!B™ÏíÝû£K{ñéîë/^Ë2m6‘žÎOçìS»ºÞŸæ³ºýv7ìðÿöÿ_”Z)  BÃDÖ/üX$$D TU5`”ÈŒŒÍK3Uý{vw/kw4$²bhì †~á'^†T r«±5¡¾Û¥Àçõ±˜vݶ”Lî}Š`ZæÒwC3œká8¤´==ÎÏîž?>¼Ým%—3 |¼Ÿ¾ýݱ ×󲤔^}òŠXOÿéúO§óñx:þÕ_ÿüéi~xšRŸRÿøþñvãëtº½½=œÞÕ¼üò—ßÝݽJ] éZk3Øo†‘(Nõ|}wõòù«.€ayûáòÔÓ´¦.¹Ùû·ïÿôOÿ óרòœµTtXKn¦BÌD¹”9g#Œ$D«õcg MMÝ´Õ¶L¹ïv"rúj«N¾ÙíîëZ§óz¾ÜÞÝåy=?øúööêz|x|'Â××»ežö7wóútšOã°ÓRçÓéñáQw×7Ò±Çd¥æiÝ^íO§éééðí›~òõ×c/­ÕZªˆäœ‘ävw»w‡§‡ÐQUj?N}vÛ!Cµv¹Á¸â†N¢ ÿý¯~ÛmnZ"üäÅ+lmEПN‡ëÛ¤KJ8†XVíâ–1=<>]]_ð~˘Œ,uƒ;©1¤8ä¼DÆétN¡Sò·Ÿ–ó\Ñ)†n]ÖÔÅ¢HBâRóšg´üüz4«Ûq3¤hum57å œ—Õ´ }× +­ÿï»Ûýýééÿëÿï_ýêpÈ› ÿ“?ùéíÝæoþö—7»—çãS?„«ë]Õåönu=jVžóS`soŠŽäQXk%Utf>ž»ÝV‹p3”Z+`^Kcâ¢{VǬ¦f] ¹®äÎHjJAj-K)„ˆÊDAbâÎÍ/7HP¨ Ü~œDÁyŒrQm(cè–yqj¼¹0«¶<•Zk7ăª¹:°tãÓᬭ)XH„8ôiì‚{‡q½Õê— xSk –%7µú ,âÓt†]ˆÜZnZB`ÇÕŒLÄd©”º"𤨅tQŽ-y•Ø#¡ÚÅüŠMØ­ZŠ#…þ~ìúï®®®Þ³ýÞï½úõ7?Û¶ëîx©DoÎçǃŒò݇7OÇw©ó?ù'¯Ì¡is·Ú ‡û>¦«0{w|ûÃãÁ^~òêjÜuv;â> cˆó4GIdrCáþðøßüë¿üâõ³W¯ž}÷ݷ穽}üâ«/w»Í³—W‡ZÉëTö»ë@´ßŒAÂù|>ÍÓœ×qŒ óoßü%>»{ñÕg¯Ï‡Ó4ŸÔqZ €}ÿôøt>Í_µ­-‹§‡Ô>ÞŸžŽ!'Œqªg§Š#Ôµ˜u¥¶æ%Ì1äóTò´Kã®»¢Qß—7üx^žÎ}d íã‡e3lowÏÚTû8äÑö³ëͰ ‰ER«hOÍsñ9+ Û0—ß|û»b6½²ÀxžŽÕ¤‹©z„â‚§õýÓ±¾==»½ëzûðqÞŽý2—u^CŸxiN µ•ÓºOÇׯ?Ÿ}¸¿?ŽÇ/Óç ~˜ÆÛý§Í¨ëÆ C ±,MFÌËTP×¼O‡inMñÙfGí\I¤Ûö­µÃ<í¶1Ÿgkù²–,­nÇáüpðÕ¿}<|õÕ—çó6”óB?V:Ãéã=Æîp>ÏÞþî[5{ýúyè`šZ A½ýü¿žfclÞ6×v´ßõ± ­aýáéIÁ”Ù‘û4^@­ë2k%Á;žêYÁ õêæ†ˆ+!‘éš­¢!¡YñÒÜl)%…óš‰ÑÔ1¶ÕÌ,šckF]8& ̹V15uêû‘j®]ǵdŽi,µ9à˜vä”u5ñƒ›#¢Õ†$žjê7’AC²Z³;ÎË9öLº. ‘û82¢¢6#cŒR µb!rH±œ§¥¹2j;·¡µ34”NYAcN¹UÂb~éI·jP*2c/é‚yWS@É\”ü8ŸEràÐÈÓ(̰ÙtÍÜ™š[ëRpǵ¨`𦒂“V×RÖ.ÆZ2²™{Ó‚ænÄ“€0‚kŒ—20PmÅ\$Äí.ìwû(¥^€b`D¤U7±ëÓn-mžŠÊ¼–R­UE0³Ê  ÌLd’ÕÔôBµ›—…cà$¡jcá^zkü¸6äHÑ 0¨µ¬ei‹£;é«×wA0‘XUà¨ÕJ-VÛ²ÔyQ œ"E«V—¶ÙŽ(nÆþ×ÿ—ÿr³ßNur,ÈÕ°"ªWìjmHfÍbè]=H` ¡“¢°ŸÖÃñíZ2""‹ôqpÃãñ!„€&"ÝZk¿é¾ùí·o¿{xùüÓ4ˆêºÛ)%UÿoÿíŸ mcHŸ~v{8|Ü„Íõõ.çi»ßþðöw}û¡sV§F‚Cß1rà…%`ÓÚr"©“¬J)Œ؈µ( P.%u‰„BHÀ"1†²N:\µü÷þ×ãæ¶‹¼º.È~¿¿Ú 9/@—æ›—\—ã´ ¥ínHÖiY—&õ’¡p:¶ûMê6M¡äÓfè­µû‡‡i^»®ç@)ÅaبÁ‡û'P½Ùïòº>==>3ØïÆš×±ß}òâîþéáýÃájÿl3 BHD˲² ø4?IrBû+BªmEÁÃé0MKp,9lÆ]ê¤üüf¯Úb s^ˆ$‰œ§G D¬!¾¿hæ}ê„pµµïFP솄Á¯ÇN˜à|œ$õýi9› Bóš×¡ïTµÔ2 Ããá°6­ÙÊ¢h cän×Oë².¥‹ƒr0 A[c§Ã d»ëÍœ—a³Ùmú.IßuÖ4NKÍ+|òìËçׯÆ4†ØÕZ¬é¼–Òðãá¼–$Êq©n8¤.Åpÿ±ïúeÍˆä Œ°RÇÐE%hþþêÓWŸ¾|vsuHØJ­¥´ºüê»oþîÛ_¼y|³{¾yv{5ì7çœÍšp[Öóßýíw?ÿë÷ÖøŸþ³ŸýÑü ™ ÖÉÏG«kýxøÝ›{u½¹ðÓ/6ãÆÜˆ\-[«H!HÔf}ו²š6·‚¨i®uY‹8@ä1˜©!7à¦-t1ªƒR@^×™ @ƒx„Á s)~±®×¢­™CŠ=&‰Â’¬­t1õ²Ñjóz £5tÀ9OÓ:áív¤¯¥"µVÊ¥'¿¬S«±×êˆi¶)h™¨5ÍNVª¹a«µëÓÅ P´!ä²6¨Äˆê è€îÜ€ÉÑ `(Äfæ Z›{«­Å˜ÔÍÜ!¥d®àªf‡ãy™ÖçwÏ™ÄK]‰çi©<䥯@!R®~žŒçóyèºØk胣¢·fVˆQ/éG S9áЉƒ[[[G !xC·x ‰¤ŽÔ2!šâYD¿Ü[Õ¹*8am…Á\ÕŒçÉ­1¸·º:[  ÆLÄ‹™p\³>NFÌSØ—µÃñ¸€‹ŽcâÀ¹ÖÃéøüÙõ¦ïÙ±åv:.´½ºùðñ~>ϵ´µÖ~W¯îЭ–6-sˆ$­kÓÖðÿð¿ÿÓyµA1%‹ihmÕÇcÛ²œŸÖs~ýé—ä,D}ß-åx<¯›þÙ~×N®®¯Ç±›¦£Y}ÿþã³ç/k­¥µ¼¶íö*H\ó¤z)I2°â0t!²Y›òi6ˆHè!P`Ô¢yi!…†êêAD½ÕV¬OC^ª`èºDì¥&êS ¥Öf5—ÕLcfzùѪžNç«ý59$’N= bÎUU%FP‹IXÈ›‘Qƒ¶Ö•ƒ\ZØæ&$­T7s¨æ@Ì„ŽãñpþáÛ‡ûÓv7¾}÷ñë¯ê°ªëÓác·í·Ïoïþý_ýÕ§Ÿ¾º½Ú”õ¼”ATáx<\__…>î†MŸðððq7Ü…¾}÷í7ßèºÛM·ÑaèrÎ1¦e™9ÐÕõ¦µÕÍ6þïû%/Íj.¥euu9ŸÂ×_ÿÿýù_0­„p}sknZˆÍ‘ió¦À MÍ)àõÝþ4?ÁÝÍóƒÖõXUKuwŽû^J]µé<—yZ7›ÝÐmrÉݺ.4m§ÃÒŠ_¸I讥 @kP.ÆâÒj®•8H ¼–‰ÅSSêšf³*"}7jƒãáÜõ»yQùì“Oûn{½ÝoºaÍ8—xœ+±lÇñýýCsrfvSk-©ÍÌ …!!!$®¢³3^í¯ØjÜlj)n6Ÿ¼xùôxÿx8 Ð\æ÷÷oÿõ¿û·ï?ý£¯¿øê¥·s.§ógÿþwoª—ðÙËî_þËÿd·µVÚ2ñoûþ¿úþýÇy³éÿÑŸüá'/‚œb¯ Í é¢ßY´éŸ; ½ƒ3¡¹I^K«¢¨U4ŠYš¹™³P6bõÊäŒàÞˆ0çæ!È%ùZÚâ¨M›6c?R¼ºØiÀBŒfµy[rN±7uÀ¦šq;\ õŽ„‚Ž:/m6tÛe=õ}?M«ª;6b3(¥U¼$…ˆ¼ä…É™0Å`v1?# ŸNk×õî­æ*Œ1 ª7@âªö#4É š ¹“²™™:8˜š"2€X³K#I.ˆH%¡„@.$ 5k  æÖjI]ˆ]XVGÝÕl­˜©…n£˜HDXµ¨7s¯E8™aŠ‹4]ÔÔEk ýæª4EÒ(ê¶:²Vo¥5m¹V$êcÇÌŠŠ,„,ÈB<Ïóy®Ëª¼‡»#Zt¹0“¡º";Œ}‡„çót\Ö)×)ºÚ¼@öáãSSðaHDw··Š`j&µáoõÝi©Õ(†t:žq¿K/ž_¥Èf:·Ìd‘FÍËÌÿì?û"†À—ÍW»d©ÔªÇ0ÜÜ\wcxöòY?ÆØ¡$ƒ)ñîv+£†DL  ¹.ÍŠbëûhu%±ÒVXò²ä ™Öœ›åÔó8tý»!®y´¾‹Q#¡!ÔºjÓRŠçskÖ~d¢him™dRô%¯Z %† ­iaWr3ÕZªª3ÇZµzYK ]—qlê‚ÓÅNV‹©Ä¡©XÓ*̈T¡“©!¸£‚@,Yµ¡8 2)©Ú²ê_ÿü›Ç£¸?lÆ¡¬Ëf³;—º¨&Wùõ/~íλÝ. ×ZÆ4¼zù©ˆt}£Ae^Ÿ€<õ»€buº¹ÙÇçcŠÝáp^×2OËáxî»aë:7¦ ÌËù¦k^Àš[³VV‰õ<½#(cߥŒÉƒ2"š&boV—¼4e ­”(ÔFlæ~>OÇǧéᘧºÎðöíÓºäy9•²y.Ë4-ûí- ®y>Ÿ§ºÖé8ÎuiC·EäRê´,¥¶È Ú˜(Di­´VK®9·u-K[b¤)!óšsY×ZëéôuZÇM¯^)m^¾¼Ýn¼µói>·O?ý„0Ýœ~ùëߦ!|úÅóŸÞ¼}÷f]Ö” 8/9Æ.„PrP"M‘/(E6ÕZ³HÜŒ›;$†>Júþ±ï#…À±ë ÉÌjd¶R­UC(ãvÈ%ƒ[!VBG&!„‹ò»ë{«u;+î¸öäBD]ߥn`IݰAÓjZmì·ë2™»šç:»c®Ù ªU‰‘ȱ‹‘QÀQ‰Y‚:‚ºÚRfI"8d‘”‰~¬ÿ uL]ä dG"’ª®ÎjŒàG‚´ã ‰H„Z+! 29JEòªþt:ÄÄTé²§fvÛlÆÓãº<ƺÊn·7¨ÛýözÿÌԛк€IDATÌ H Ò G"‰D!Æ¡ëGóFâÈà! ³YÓ\òšsv3b0[ “Ilf­åf+‡‹{ÉîɃ`J²%H„¡ëx‰Ñ7cHcPÏH¶ÙŽ}ß5° „Â%@“ »¡±ßôœòj¥ oÇíØmÞø8-eZÖ.FS#‘$ÝvèY`.ëq:77‚ˆ©“®K­6U't$ —ã ÿÿ›¯Q$„ !Š[e@aŽšÖÀ’B&Wk„‚†ä(Ž5g7m­’ª:3Wó ´’ñÝÐõ}ˆ}ŒÍ­T[sS€êÞŒÖ5_LKÑÒ°isDŒ!Ä‹­À…y3n3 !drlHnÍ©i+ÚbêGr€˜bÑÌ™šéýé<ŽCkÌÜ‘‘óº:Àt\>¼jÊŽ´®yYË´¬Q8S`‰Àaž—¿ü÷wu7ûq3¤(qÛoKþQ®ÞŠ•5k3Wµúª¦"øøôP=“€“·6:ÆH©+Z‘¥¹uƒ "¥$¥G›ËRK‹1™c«JÂó:õda ŸÎ÷§å¨ÐJ=tÝ2—wU§ºe5ujf€èè«V#pò¦IB Ø] úäåËÓᱬs×÷2öJD,5·ÝÐsHÇÃY8ÖÖˆñËϾØl¶ßÿðî0M›ëëÔ…ífûåç_|õÕëýn4õÖ臹.üýþOﳫ}:Ÿ‡!Å6ãxÿøx MU‰PбûÎUE¸6!ÄCˆ}×çeÝôCkkÓY­ÃànÄ1pÆ™„mÓ÷¨È(Íôýý#B´*nœú±´ÒÅ0¤„KkN„cäI‚³xêCŸúŽƒ€»7bb)BdÛ #º !“piÍKuh!ÒÆT™„øÇ6x5lŽ­Ô"$µå8\XÃ,!„ îŽ@ ŽŠä8HjêµÁ¶†x÷}ÕÅÁµ‹=O' €»²ü¯24t‘v01þh•`‚Hæ“àD-&jʈ"BÈà^êZµ¥nHÜ40µZ²Nó2Ÿµê0nD(Eî¥ëúc`a$m…˜š7@uÐÕVw›aÜuiC6”Š”:¤´L‹¡K”>†ÛÝÕÐoSêµ9JÙ´q ŽàÛíxsµW­ýf·í#š?>MU›\ü¶;þçÿóÏÙõò0E¸(RÌ Ñ…ólè äâäHÀˆÞZ@jf­!6ÀæfÞÚ¥ÂGˆ‚ÉÉ@»Ø! 6ŒÞ”Æn[s  y˦j«ª#’^l7D$D}×]ü;Ì„~Ô¡8‹‡È})æ?ö .®œXr)ù’77$¤Ò’çÊMÉÝ/œ@¢\tžsJb¾¿Ê‹1Hä„HŒ„MÛáô4çåýýñ/þâ›Ýæú˯^HpÀ‹5]ï÷Ÿ¿~ùú³›§‡?|øü³ÏÏÓ|žõßýùoÞ½›_þü³Ï÷ŸÿäîÕ§·]âÀ0€bᦦêóšÓz^óqZާòôxFâi]RŸú%’¾ÿ¾Ké“»»ýnÜî6Ž–úÐ.©AffpE¨¥­¥eBY—“‚ `”ø#fíª Û 2râsžOë¬à!FG¬¥ âÕnß'^×SÎsŒ±”J`ýÐMËTjÕ¦O‡óš­4œ–úîþÁ¹?NøñãétZOóJH$[ãØÕŠ}Ú‡¸%JAä|~r/"py¹(Þî_NÇ%†îÄÚt’ 8™×uíûá¢[ººÚ5ÍÍçqK¿{óÛy®Ûíó¼44—ÜÁÍAAˆ‘Y[ L‘ ÁŽç'ª­Ü={6ŸN—|‡ ÇyÞ\]QŠkÎc× ¿ÿQYlY&Ÿ—ùx<´¼x±÷ïÞ¾|y³Û„Ø¥Ýﮯnn¶»}9Víï6$.‚1&¤pIã8:á ÍÐŒ‰‰¨ ] =+80œ–“!z5½ÏSßwê*ñ²‚VÕ.E8MË´¬"¤à$1¥þt8Ym­´W/_>><ÍóÒ÷}ŠÉ¼ÖZ°IU³H ¡_ÎåÃûæVM7ûýÃÓÓ›~Øí®÷›Xë:9·Ïž÷]WWµ¬‚tš¦@²Ûô7·ÛãùÉü‚»©ÛÍxxzd —†„  ½aÓùP­Œû«â # ›ØubuíR÷Ã÷ç@¯ŸßýãZ:3 ©ëÏç™…cU[^¦]ß=¿¾ê?>üðÓ?øú|> ]¯yíb‚äui5¾oZ,±þÁO¿ì7ñþpØl®¾ÿá]Ò'ÏŸkkªå‚ W÷˜4&G× Ð­ÕC6mf©‹Z ¹+0¡DŽ~YqàºÖ¡KbqSf”ÏóªZYM™¡Ö†˜úÔ Cmk½t‘ÊºŠ¤ÔmK­"^suõKV§ZF7FìEÆœWóEÄÉ8—ezÄp8N‡éL!t)í·›–'Õª`Dé|X×il¡gGÖc—£yk à\*”ì)$³2Ž)Å`nH~J{ÓR¡6Wo,À —=9j5f[—¹Ö*!6sA”@’Ùq]KS5oDbΤ‹Â"‰©w#³R`jžÍœ­c°KÏ`.ÓrÞŽû{u[òúÝÛ‡ºØ6}—Ö|Ûì\áøt$Ä›»¡aØ0¢wRm¥wbN€¬¦ô#7CHæPÛŠˆLÁ]–µSž ­yqvŽ¢µ¢ƒº¹]ÔRDU×KA+ñ˜h“KE‡ÇušýÃÓ쌛a$cÂË0ÅÖŠµ–KiDÈ-—u™IB7Œ›¡;>r.S©×w·ËéxZ–O^]í¯ÀñmÇa3öÙæí®—fZKåþ/þ°4C5WuwEâ¦ê`ä~ùÚ§eÎÚJi9t)„äFÛ~+$ã¸Ýïn6Ãîöæîõ§¯SH‚²7fRD¢(ÔÇØõ½_œ µikÈ¡¡lÍÌ@EUP$`ö ‚¨L­‚!‚HèãÀjvBr­‘„$¥nuÍ$¦žBêBc"b5K)1¡ªØfìc v@Co~¹ YNûýµ ²XÓZ £°2)j­ë2¯ËÒ Öœ›wCäZmžWWìS>Í”€jnïß~xøø¤ÕŽOeµê_ÿÕÏ×L#ŸA¤†~6›.F˜§éæÙÕíËÛã<;Æífœ§§ë›Mi9õ‰‚„>¬e¹x‹½Ùj Ûá3°«»_=NÇÓüþúªï8  k!›§üúõ—O"q·¹v•ù\jÓi! )¥¡»›1u‘A#¶í8!r«×Ûq·Ù½LÓ±¬…1ªù/óíÓlËb-[H} ]'¡Tk«y]“[«×ËŽ£]í^”5Ýì~e; Ã8ŒAy²šŸßÞh­ëûìDwû§Ãa^GÍm¹¹{&±okIAr^%H.E8˰ÛOËêê¿ùö»ÿáßÿÍßþæÝ‡ÓÝõMŸÒááàFFáí»Ç‡ûÃóçûq‹9¯ZÙŒÈÑYÁ¶ã耥©ª1QÍÙLU5ÅÄH™£0‘"¡cEn)„Z´h-¶")‘ºW‘ tù„$·KbJUf6­ šAËy©ëŠ`?&E‘$Dr,Ö*h®MÍ^óê^›-kÍ€V5#¹š:BiË4rY–eι¨­ózšÖsб©7b `ܦ9ãEeÓÅ®ÖÕmœ–”‹⮢¯enZŒÑLM«Ö £¢xˆlîöc„O.aw3³‹š±´’µTËébÓñ¦V´úE¥‚äæJ]Hîn¦îÍ¡%qahZ ÈPÅ»„)x=FÍÂãÃòtX™Í½Õ¦ÍÙ òZÀÁTµjY–åéi:Ëšm9¯ªÞ ×ljBÀhj†äÌ$Ipk*I5á"¬i9Ûwï¦Ïç9Ÿ§umEPŽÇó”W`Qµ¾ïP‹•\Bd$;žÎh»ßtñ¯õÐ…nèù|8<œž²¶˜Ò¼>m¶áæz¸½ÞÜì6Û¾ß÷#ÿgÿâ'Bt©ÙQ14r¿7›qÛõ]ùäå§7WÏRRê·›¦¶Û}’®ëz ðøða>žÝ©äŠnQH€ˆÑÑ[ÕuYÖÜ´ä œ"¤:»(ÜQR Ûq裰{¤bÜô};D& Šh´Ìy]Š»"þhqgpZs9—V@–¹,Ó|z:><ælÕP­•ZK-뺖\k3lfç鬵–RT}žæyZ¦u™—ÅÕèC±ºäRJ)yEbçDL¬jËZZUGDGhîóZ–ÅN§õÃÇÇÝþ:…ÞÕ$HQ«J‡Çµ®˜0j^kÁ˜NÓùxž‹º½ÿ¡4(­¼ùþÝÏþ®æçóÌ@Û~ ÄqXR]ާÓãépZW :žÏsΧÓÔLÜ݇a4§µe³ ¨Q݆‘×ùÜê:ôýããÓÃa’”œa^ç¦åúæ*†á¿xÿó_œnï^×Çó·Cç»®£¦¨-¶Zש<¿}~>æuÂ@«Öf-u‚LÛí¦ï{²j»~ `ÚÖÓt¸ºÞ#ú<C Í¶/X ÀŒº4n7[uXÖ5EÉy6ÝÍÕ šGâK_|*š¡uý¸ÛߪûšÛКס¯ªé÷?¼·ýv#„­©º7Àª>Œ›››­š×üðôúøðñþ÷~ò5¢Ìór>þÍ¿ù7)¦Ï^ Äx™‘y»Ý6³¾ë¯o¯ö×Ãv/¥L™<,Kûøñ©šþìü~cT¯(¾¶©èT!;š¶A$º›AAV`Š©ë»>ˆ º¹#  3!: 9xim)Ù¼n¶]m33š¨Z—f1Sw'Š SJ‘|¶’ ï;p$Lµ€V«Z.ÈæR$U7§BB, ‹/Y…V­q$ÊÕBÚÄØ1ù“9‡í¸ÛÈÀº42ˆVsbZ—µ•*¾¥µyšJ^SÇ€5o»AÕJ©Õª_ؼˆ#‘90“ ‘ »3Ñj(qD´„ ìâÖ-ZsÎ}ˆCˆ)&˜ÐEH„)ŠfB²†„‘0:±»¹7uS»¸"ˆBˆ‰3;¸.ˬn(>lÂõÕ™8pǸ6ÕÆËmóª!J—B“7°ÔG÷˸”×\ò4¯yZË´L9ÏèU[jͶf?=Ùm¤W§Sz÷nýð°>Ï( Ñ[ìDÆHìÐI nu™§séÖ9çµ ÇÀ(D(QX ßôã0¢a-u¼ïžß¼zvKªÓ²¶ZKÉ뺬K6%þ_ýÏ^OÇ·ïÞ­9›Y ‰Ð¼ë‚ZEJ)l6i·é6µä¼® ‰ VD]ò²æuY¦\æ÷ïÍ,ŸÎOóz6P@¬ªÈÁœŒ˜cäHK-ÆÂ]2ÃbÞýâbŽLî­•s$ÖZ-ͬ¬ÙÍx­­YSTÏU×Z§\æÚÎk­@ÙËjyµºÔ’kiä™@›6'Êæ äèꦦ—Ér ‘†‘SS „!uÛq+AŠªº GPGwW#B‚*èµOLâSÎïïÏó‚ßþî‡u)Zý‡÷ÇûCv«æš1Ðv³#ǧsUï6ýá|¶Û.uDþñãÓf|öðpÞãͯv» ñüt\Ïe]j):g'J×¼LsþìåëùxnµªÙñtªM åR†˜æ©¹æ’‡a쇑˜çÓ°n®wûíÐ%麰÷yYß¿ÿaž]gUßåò}–æ«iµR&nÙ’Œe©µdw‹Q´5GüpÿP«ƒÊ¦¿îdSÎ9¯+ âÕþŠBÀàÅ ‘êZîïïÕ4u}ý°Ùï¶»«ývâfHfuÊçS9?NÚæjH}¹¬&p<œÜ}¼Ú~e­ïÒ€Në¼€SX– É»(ǧûLJûÓié»ñõ'ŸžÖ¥~÷æD¦«ë«O¿øÂóšy7ŒVŠæ2ŸÎVÕjRu5î®åùóñîf,¥î®o¿ýáÃîj×E.!>v»!$’(B…»>•šKË,8 ‘Ȉ=]ü€ÂîÞD‚™×j­V075@`Uev0s¦àæ?ªMЗ< ¯eUo!H³j^c­™‰P(ŒÄìÀójßÿpÿðt®îU+JÝå.^Ü›;©™Qnhìº>¦žC[ ¶ÒÐmìBµH{‚X ÖjB‘  C (‰š™äsñZLÝ@­ÖÚæ%Ÿ–¥¸5l 2CB @"G0CEÂKêÅkddT"`rBˆ’Dd6P"L¹l$Œ„lDЛqkJˆ!pÈÄ•[%­ÝÔj55j .ì}fd!aÀ$Bˆh,Ô‰Z½eüðýÎÔÑÑ*tÒ¡q®KWû¶ŽeÄà.­80r× 1ʺý¸ ,T žÓy& ]¸âzÕóçÑ?…r³Ý|:twÃpûð4}÷þãÃ2Ÿ×µ™IÌp³_ÝÝ Â­V6ż¶\ën¿GBoÈ8vI½†tq±ávU ‰oÇxµóá0EK…kÉu9¯øý¯þ×kÉÈ$ŒÃ(‘NOhR×BóTöýf»éÓÇ¢ ˜3Ç.Mód !ÈE¯£ÍÀ]"å\Ýi3lÔÁY¨j^ÖÅ€@«VL+˜:r©NQÒгRÊêîn„!¨*2Uµ=½LABЬ­!Is'¦Ú ¨W¯ ‚™€ ’»«ƒ+( ÂåÃÌnFÈK- ‰\µ13: ±âÀ†Ž­¨2_b®¾æÙš]F'D`¦fúýÛÇ¿üËïŸÝ|"è7W¢†°mî?~HIÎù,Ñ¿üòÅØñ¶ë´jÖe*3 ÷qssµoµþÿþú—o˜·»kÅúÓßû¬ã&¨!ÊRJUd ]èê2[+±“’×’px:N¹6fìR ¤RZìoÞöW»ižÑݺ¯®ö]—DЛ¢Q):­‹k›§izAÉsÍB@³2ÏÙ1Þíoò:»Upó\PäòË”Z³úv·ËçE€—óúå—_ݦõØåñþqs½‰DÈœN Qˆ‘RâaØ6Dr·œs--¯å\æ¢e»»À›ú8îv7k©§é‘IJÚãqÙŒ¯vã×›á•)ãnžp(%¿x~»Ùtm­Çoöå'ËéqªFiw\µw+¥!úr<|òü#ZÑõó/>ûæW¿™ÇŸ|õ…º½}÷î³WŸ~ÿýwoî÷~ún¥ÓÃôØõýŸýÛ¿¨Îgÿƒ¯¿ÎÇc¿ÙY4éÚ—Ÿ?BØA„bVÕLM˜Í̽^”º!D0GmY„Y$jkZZ«cb&óRÛìb™CÎ3³‚Ys0Bgä°æ$¹9âÅ”NàfBt²WÕ¥”i™½ßtÖJÜw£ÎsžWd ]O}\û.ž§Ó0öª-çlFˆÒŸò”Z!а¹˜08 ˜ƒøøpÑÿ¦§ivD¤S0wT±Ô¢1FÆ@ìfî†H¬è DÀd¥(P+턼¬þáBZ³¼žá²ŒFzx<Ü?FÀxš ä]ÀÛý›?a Ívì»Øj>Íó’õÍ÷A¤ZuЯòY@á§ã”[%ÄÄv®­¬ëñé@knï?>õÛ¶§\bß«µòân_ó) ÆÎÇór<¼x¶{xÿ^sÛöÉ=XH‡y^×ù͇oÿ‡¿þ³Â§Ãò€nùåËíôJèf¶ß]?<Žóü³?üšñ<ö`µ‚Öæó\]­¹g àèæ¾®%…`ªÅÝZsf!æÒŰ”„Šfè*{)Yµ:š¡‚»P¬Ù:Wa ¥7wÕK&Á½–ÒŠ• óâ÷O§a³ †žwÛ¡“؉­)oïß±èf‘£;NÇBn+°ÃfÎÓTJ[êLŒÄb µ¬óz–!BAFêSê{é‰6}T+1B¤Ô[cÕ¦LE/Ë”¢[3­. ¢À œX€ƒtNèˆNÅASU/Y—ÅÖ µ‘2Cr ËìU±6×ÊÓIϳ6Å5—R+€ÅÀ„ÐѰë®#mjvW¶ÂZ‰±Ë«˲L¹U-¹ÖÒ¦sI¶WÝ«W7Ÿ~vÛ ÂÁM]«5wëº~ÆMGL.Œ­Õœk.†HŒ²FAw¯) DZÛÕJ¤¦9†f9×9ÛjØœLBìB ˜¢¤V½®Ê Sˆ)„Zá<Ãy^Í´ï‡Ü*é».Óáé´ä¹zŽ]ȹ°„Z%@所˜0u!H"Œ-“H^¡Õ–«j½øÈ10—²ª#7&&3Í9¢ZE!Åâî­i 2 ps²æ…€(vc. ©Mˉ «:™9#¨ûÅ4Priª„úÎêL!š›¸2ªjzQ?!cbâËK€%! ZÖ €jÔ{÷.FFÔ–IÆ¥¬ÓZHPÝš5B„J@ˆLÑÑŒ›© Á%FoîªîênN(~äö5-j5çj†]—6ã\ö×›ØÇ_ýâíá|>*ˆ€¦ô£ì«ÜÞnYÚ~ÜÎÓBP}:žàp^$ö¿üÅ/¯öûýÕ¾Rê<‰Ë’%mÜTÕMÁ¢È0Œ mº\òÇûûZjÎ5Ä´ßíÎó‘#ÆcìrnF6•ùj¿ou‘ÎZ[ÏÇv³ß¡ò!l·C­°æs)a‡Ó1{–÷÷ï‡Í–9ƒa×3ñ:gu¿Ù_×Ü–uÝl6§ynkÛ¾¸~<V-S- >-õá ö»Í://_¾¦²Ì ! é÷o¿_ËúúÓÏ®7; át®»q›K‡n>/9/܅ܵió%™Oëyw3P ör÷z ׇ§…)ì¶»ív?Ïg% ‰‰<ƒBäüõ¯ÿøþØ¡æbÚÊÛ7¿ÛwáåíµÖœb¼êÃÓÑ èöùËo¾ù^úátšï6»eͼá¿üå_ò’ÏøtúS×|ö|#Ä?ÿ›ß^]=ÛŒ7No¿óÕWû!¸¹3…b¨ŽÞ d@ a!ñŒRL îy͆ÀËR‘–˜AÍ€™€D;!¸AÉ–›cDöæ……,Q³®ͼ™¹aß1K¸ÿp?ÍuÊà¬[èûÞ‡žCp`n•×6»i‰Ò~ïõ3ÄàÆKÖuÎ)]£Ib©kžß©:ሶ–…™5ÆÀ,¥( ˜®î6v½»k«$bÌ»ÛÁ¼ ˆÌÙ«1 Qc­h¦D>‹»ç&D]$k–"uµ¶”º\Zq}É2¸E‘ÌKÉJÍpÎ-7Ûtc†eY ,ÄkɹVm‰#銈ÚL$aî˜9çÊIÝ=Oæ‹ÎDRÀZ¡¬híjØJÛ*¸!DWТ¹i4¹ÙR߯."j9µa¿‘¡ K>ϳƾ¶²ÖÆ!µ²šTµÎkG Á¨¥Q 4Û]Ó@¤LŒÖ}÷íÃo>ü0WC’¡ï›µ~Sä¼Ne×ºŠ ,ØsŠ)=>–y lnðúv; Ýããǧù‹Ý«/†.Õ²œŽŒ}·–2ͳĸ·Á`ž¦( ­PŠÔt]1!1×Nbn«b¬­¬êʈ¸)@¹†¹äÜêÒ%EʺZEY³#´V«ŒÜ9‘­¹˜W­ˆèÃØ£»Uõ–MÈÔš#ý``^kAE¦ $ˆ ¦@†Že-]ŒÂÌ$­‹ 0 ¤É•‘˜ƒ©®µº©­¨Š¬âf10Jô’FGk(á”è8M§%ï®®Ö9›7F 3³fê—!T]Í ‘—µ8‚± #¨å2ÍKžÖöþþ˜Æ«Y×(10$ªwÏž}úÕÔu¹Ø-7»M1íC×÷R«^ÝÜ•Z¶ÿø÷s®G\Ui˜ç Fç²¾ÿøîåË—¥æw÷OŸ}ò Ñ/@Åp:/Ä©‚65*5u€zmYKqƒòRjßYÓZZ ´rÿtÜ﷈О‡ÍÍþúæÌÞýðîþñc·ÛŽûý6 ›q÷ü™5ÿøxxÿñ@½µ¼¬$‚€Ÿ|zws3ÏÓ<Œ×üæÍ›«›;v&´s©)EÛìxSÁ±‹Ë²êÚ¶cúÙϾF¦ãéÛ¤Ž弬nÈŠ­ÅZ›K©»Þ½.µœç§«gûù|šíö^¡ÞÌ><=¨czÃ¥UcN9·Ý¸)jæÆ^|Ò}÷ôt”˜¶ÛmLé±h9ëéáp½Èíîæ ˆÁ´Jà˜¬,OÏŸ]ÿü×óÇ÷OË©7Üîw¥–·÷÷¿÷~ò·û»Ô÷]R§¯>»½ÿð¸Ýl‚lc¢ìùñ8£„Óé|uµsk¦FNà ^«7õ€@yµÔ¥e]ò²¬¹Ihëºcdd¡ŽL`æÎ¡ÖfjÖüt\ª;E и90 ƒAiËšËR‹#äÖ¥Àq#ZÊÞ[«Ëaš=Ýۺ΂éããªØfèúaœëZ¼ Q)zñg-kcNóRöýf¿æ:Ǿÿö»wo¿_þ§ò/Ÿßütš×¢MbD¢M»LK`â¦õ«/?ÏËù·¿ùõŸþÓ?}zx|ûýÛׯ_ß7Cd¨?|÷»>u$‘‰Æ.Þ\o ïïïMè¿ùïþÛ?ûó‰~ò³ë×_H¦êç)ÿê—ßü£?úS‘M©VWóq+oÞ¿½½¾¯Û1Ä5/‰¹ïS.kimZ$x% eõóya”®Oî¶ßuˆ~1jbkv>ÏC×ÍÓLD›í¨e÷&€èrIJD½ôÏ Ì…-±bM!—fnj#Š ³ƒ›c“RüpZÃ4Ï)ø¸$Q»¸.9¥Þ‘Ð’DFZ–…bˆ‡ãS×uW»l­–šK­  ¦È€@à‘ ±¤jjÌâ˲t8Gtw×’»nÈÙT£{ç.0£^øsY¸¢¹:µfÍõâxB“Zp^Š„ ýT¢ÖÚˆ!´f€î®à ‘À /xãЧ¥,î+xéSc¨µv}*µ¶b®ªªKiż¢qHB]Ÿbב7E·¼‰˜)! ­k»H±È‘ ™¸ƒ^\èfF%7C"A RÍ[ó–éplêØZ˳ϫ6wxõÉ †6Ÿæ÷ŠYê’iýìå³!ɇ÷ïs)/?û´û¡ë[«èxò&I@wf³ Ø\EP½kÕ Á[©Ö¬i5Ôª¥µ¬µ c·é“¡ß~óöñ>—Å_}òÒµžO§èõëODLÄk+±ý6Qð\³#­¥Mç\«!Ñn—š.ãf£î­æy>Cw8²–µaSÌks0PjÈbjjó²h­ŽhHŠVj®ÀçY§AR+ööýÃqž†M2(N` p{½qw{wµ%Ï Ú§Ø§¸¿ÚÖºF†ÓããÃÃ}33'ä]ß'+­ÌµÌEOó*1MçìÆó\AyÕâ‘BS߇8¼xõyÓØŠ ³ÃHHQ¸KaYgf&ÄÓÓ“æ•ÇǪõýýKìS¨uÝ_ï‘;ä±Aàsm@ñx*O‡3Åðoÿâ¿ÿýþßE`¼%”µ‹i7ÞqÀ2ÿéŸüáv¥ÎÇÓ²¬ùñøt˜§Uíï¿ýæÍwo?¹{áê„„ˆµêýÃa³¹ŽÝ0­X˜å0MÀtµßµ²_Õ3§Ô1BL\kÉ­4sUÒDºˆ ¦€Î)v—zÍFHj IÜÉÈx9æ9ggc6÷BL@‚˜c!Æ€ÚÌ1vƒH¿Ûí¯÷›W/o^Üm†Ž6CfI‘‰ÀTÈ[­»ÔVaäÎ뺬k-u·ßsTW…@އõãÇ\J\3:ÈátXë! ­ë]‚K@"f³ji8¯>­>--gÕù´Òˆ/?»Þáá‡ûÃS^+™H±£¸¡6˜×všó\–ÐÅnìJ]ÏËéi:fh0Æþj{-óT\‹0¤®xv!äд²V1KÌÔ÷°æ².5OK×w\ÏçS’à fv‘¦YS(¢F 0„æë¼,¥T5ÐK˜!º_l§ª­Ø¹M™B’a—ëë+‡ên­_×Z+•V5«:ZVH ºÖ’݈1ø“¾Òln­is0̦˺¶9×U‹ªõD:Ð*Ä \Á¼‚AS+Nä, U’¸‚ƒ;°\¸ÞÞIPuh‘˜Q0炎HˆÂÂTšªY©­¡ÁÒZtcô‹ÄÙ ½Ù´L¹>ÍÙ¾ýþá¼ ðé'×W×Vonv›±ÓªµÕ~7CŸ§óÐqˆ›9{¸Ú¤²Îû«n»v®î°éS øüîÎ8PQM(çÃL„Ÿ¼øÔµÌùh­Ì®ˆR«³H ®åÜ,óöÇÝïÞ¼ÒfÿùÕ2O›íЯqssýnžrÂk CA_NgÇ ?»Ú;YÎ@€Ú‚m®SÚõ$bµQ€¤åzz<œwÏžqÃÛ§œùêæšØ(’™ i¨R¤!%3Ë XÖÂh>î¹y3y^wc_­ÚéøôêÓOJ+تÆ$„Ø0r¼¹¹)Ô¦DýÓSè%QëRÙ:tòññÝùáñáüýþÑ«e·øÓ?ü»¿ù»õXœôÕ'×ýнû>8^ÁwÛÈÒI7Bà®b µ¬ÞêùðnÝ’æeOÇu©_}þ•xTêza°³ž–Ô*ÁÝ æb­ö!™–¥f Z²äS9}?6c5Å.Ä«ù”½Öóº€ô]¯€¹i3…¹ÖæÑ\±‹bÜ‘)jkUUûqtaX׉ÅÍÄ›šC죚µ>a —Cà ¬ 4Õ&H,RM+´æ5†P½R®‹yuo ,pûb³Ù·u:‡®ïú1¤. ©ÖÒª¹CkNÄ­9"k„Z9%NÁ¶WcÑêžÕÚ4뚎cú±­«‚’a¢€x^Wt „1õÓÂ,ýÃÃKkZJYSŠÏž…Òj© ŽÌY3,dÍû4dkÖ tÛ¢Õ±…ä©O„B1raS­ ÁŒ.^Œµæ9g¢N§“U„jÄQQY€ÅY01 :¸º6@0hÕŠi7Âv»a²TIy”ÝÉŽçÓºæb`OÓá÷~ÿÓO_={ùÉ­¶ºÌ'"?<óæûëg/¿xý…CoKöš×@!Å~è­ï·c/2¯Ë´ÖE!¢¤†a$Aùþû¤Oq^ IèÇN$<Í50 Ç 2—™RØ#ò.¥ñx8¶‹šžú¢º«šöãÖ‘1’ÖÙqtCdS­X­U"'$‡êÞ„(²·BÕ,`(i@"ffwHZx)‹â%QÑ GA2oÞDXÈáÒw[ëÙ€€P¬zž[10â.Æ Úª™ž… –Ù¼iÏØï˜ –âÈ jÚ\ ŠÐ¸óòÿŸ¦?é™vËÎ3±Õìæi¢}»¯;ßiòdGR$E²¨¦TªR ªlÀcO Ø<ðÀžøذ]€Cyæ™Ó‚d%£$£J²HŠÌL23Ofžöëß6º§ÙÍZ˃7…E Ï^{ïû¾.vb¦`KƒiɈ¨Õf¨Ä dà‚7Ä”K.‰€€ÍLˆ‡9+¨˜V2@™…©ZU¨(§š®ïO>¸µ³f㢀ã.v}Œ}Q56 €ƒéÄ=j‘ýn/à ý4MŽèüüªèÐõÝû÷×jØD~÷þÕf½]4«i–1ZK×-î÷÷ŽÀ{ ‘cl»lÑ…1O€ r*6ÎÛÅf»]\^vdž}øâ»ôÓó“¦[‰@Küòêüòér½Ž›õr:ì8¶”ˉµq‘ˆÈ‡†S§ýy»jšè–kcÏ¥¾{s{yu¶ˆg¯¿þîîýéå§/RиåªØî<tíi‚ny~¶yJÚyŒHªöíÑš\Òæììp‘ ã8Œ»i.ïN§S±üôåYpΊÔT@¡ êcuCŒ‚G2ˆ10²‚½{÷ :nÚ°ìÛR+3NÓ(Z Jðlª›h-,à+€¡VTO¦¦Î!1‚åazpø"b11Sˆ ·7月X2˜‚ª23©‘jPEŠäl™À¼[ÒiDO}ªštÁUST©Ì šÐ *BÅãñ°Ú®Ë…CÇQYÕðüéåaw·êû®Ý2aÛÆíjUJE-:›"㤆N€==ÊHb×Ìy,©"ϤµT) ¢ U1U$ó–êIÔB\†i’‘  ÞAtÈ€ »ÂL J„ŽûØrBsP©&Ñ**îöý~8Ù1MHà€j>îöÁSו‚Íbóäcêû5¨¦Ó˜CA‚Ëm×°kýò0‡ã)¥,UEÐIÅI²Ã‰Ðó?ýŸüO>tÎ‡ØÆè£©EªhÎó\µ˜˳–93¹ZÐý–؉Ûv.Y Ø,3WçLª°Ic ÖÇÐ6Q%ÏѹÈÌ\ÈIÓ wàÑrð€ eJ–D«š¤b–Ø  SdH%­1:¬‚Ž›’I¥€PA Qsª)•<—l`„PkËbEM5¥J*Õ,ÅÆ3ƒ÷ì;µdE†j2L“Øão·‚U‘TEDÀ K-UJ®eª2gç’’NÓ8§ª–¥ê£,‰ј“÷Ô6.:×7Më\bã= þ6œ¬ÊŽ÷]Û>½Ú>9_¿xrùäü¼ Þ;ôŽ] "Îóh&¨Yj®’‹&Éè ]6® ì<# (Eޱ].û4À|‚®mf±|Œ±æiYªíwÇ*¨J‹¸jBx8Ü™•e×®Í4Vgí4Ÿdµ WW۫˳®c\‹ÞíæÛý "T©Ð-¢‹üø'6±‚ÞЩ p¶]w±3³)%r¡]nþå¿þ÷¡[t›eœÉ\\œ†¼{8…Lòr3Ô÷·ÃÃÎ.¶ß#뼋ÛÍ¢m§1yçµHÊ©0‡’ë‹gO–]{8ìk@6µœfrø¦ŠŒm¿@vÑßËóÞÐî»¶kînwû·Óþtøæ«ï>yñéé ‡Sýë_þ¼Úðò³sÅ\4«YÓ÷ êƒ6 7­'çRž¥–ZÓzղ㪇ašrš+‚7áyÌ˜ÊØ-Û¾íËTÒœ®ž^u‹Ø…öîænÆÍz#ZZ R³ßÆÐ®º¥' žM…‰r…’qVJÀe± Ì*’­ mß/šÐ Úq¿wŒÞxEUAkI1ÐùùF$§º7KhÅ!¶¡qì"a·?Ùý^îuÃ0x©Á±¯¥˜Z©€ƒU–L*4¥"UõBHXÕD«™¢3âÇÏ@¡Ô `€fbLžUºÆ  ‚q¦ì|khbsˆl€’¥ Ñ–’Í™j‘qœr)ÄPj‘\JJÅû¸èR2ÅÇêµø(Í£i­Š¾éˆC•Š$Æ U° §qDGåQ‘R+ *J’œe®ZÀ¡ Bô jX´›’E¬äX •ˆ ½þ¶ú¦Èä`JÒt›Ã(c¶Ðõ>4a8¥ýn˜J>Ó·ß½™rÆgOßÿÞ“?Zo7þâ|»Ý\ÜÜÞ§:/7ýùù%A¸:òÑóçιœóiwûppõäb»Zy ):e™“¦TSÊ¢UULÅLsÊüŸþÃ8„ MëqœJ®D4çF4$Á…à*ª€V͈¶m£ã<©0šŠš2³Ÿrª&>R·! xÏRÓýõÝë·Ç?ÿó/>zòQ׆®ãØ<Æi›2ëé8R•²X/Óœæi ÎÕZ÷‡½X>Žª© álµÆR?yñѲ_.úÎ{C‘>.ÎÖ«óMüþ§Ï>þøòööý0hߞ眿ùî+p<î†/~úeõúÃ5T©·÷·«Õºi;hˆ£CGsM®áRsže¿ß‰!< ;¡ùùËÍË—Û?¾h[Z,W9㯾x½êÎWÝjÝ/†áDìçR¼ ¦<‡è‰¬m[Ii®¢!¶Ǭ ÎQN£ïP¤¬×Ý¿þWÿâG?ø¨m‚©ÊölõÝÛ_}õúo²ÍÝby~±RƒÓä*i.hˆ§yДJ5qŒMôfZÕj)³Jñ Ž€X‘ L‘À*š‚V{ÄeUuµ¨Ú#^ÂÐc×…¾ñž¬¤ÉŒŠh™ë$¬ÀÝýýx8é4Yš%—¬m»¨Å¦9 ò³§Ï¶ËnÕòóËudÙÝߎÇÕf ŠÃižr!ï›.xßä”îө-<æ)§ˆHó<–’ç9ϹŽóì¼#‚”jÎÉ1„è˜ÿ³ø9!‹I•BäÚ¦7¤TklÚ›® !8!R.‚øÒ©ªRUÌ€˜|0C ±S`!—BÆÈ¬T皪¢'pìÛ¶³à˜ˆ€(t=R õ±àZ%4³è"eƒ\E*–Šsæi¦Ø.œwÎS¸ìârÑ1“s,"¢ZDœw „"BD•À$x(1`ÑŠ¤HV­Š’/Z $fïoBìÛ.°ëšH¬ˆbøÈÁF@«Rˆ¼:UaÓ&pQË(Õ{`F& Á’Øã† ×2Ï¥V3âLj@EF‡ŒFÁ?b.rôHŒ&µÔ”'ƒäœx ¢ †¹ˆ€‰ap‰ #9üÛëûñ/¿@׿xº}z~¹ì×Ì®X1®>pÕyN‡® ÓpDDÉëÕÂ9^/[Op¹Ý6±Eß§ýþ8+[T*rsw_EÏ·ëš³Gwq±8·‡Óœ²þîï~þãŸ|òäâ/¿÷Ù§Ÿ¾øèIlx½]NûqC 9×¾]»¶í:ïNû”f@ò‚ôã|ÚøòGðùv½¸½~8ÜÇýøìéGüGÄX®ÎÏKÕØö*ÐûÑ÷?½ø0ϧ¶ %—4Mž>½šæaœÆ\ „àÀ;OĆV¥²gçq³Z½xúôÕWßuM#’÷§»ëûï¦Ø†\Jìâ¨ÓÛÛ7Bé?ÿÏÿNž÷ß|ûöÕ›[ï¼÷C˜æ©ÔÔ?Žãá8CþöÛðÞG^4ÇÇäKùø“gMƒ!ÀÓ«Ëõj¹èz-5«Ù4NÎ{E+Zš¦Ýž¯Ø•4M+±Rä‚Z­¶­w †6NcUBpÄžHM”х詳ê—Ý(ƒ‚‰" gj›39èÛåápèû~‰S–jªTGlj*BÒÂŽœ£ày¹ˆmľÃí¦],X®Õ朌« ض.î¢'¸ä˜û¶crŠD‰‹h-¨ªhʵ ¨S¥Ø´ì€œ¥,i´š!g;“ŸR6çÅ@ ¨‰½‰‹n|c`1:ÌùäBa‡H$쌊”ãé0§QLÔ„CCBÕhÎuJ= ¼¸ˆÌ ÂjŽ1²C ­P‘ˆ‚wžœgòì›Ø©˜‰! ’Ë"U€ç$¹j1©’r‰¡‰®aײsD¥Ô¤rȹÄZ LJ|¸/Þ 7ïö××·7·7U,%¹ß§\û~}¶Þ:¢ýþnîŽåfŸ”÷Áµq­…ÚÐÆ<Ù锆¡Üïc.ÌEZ-mhÓ¬)Ãi˜Ã4N©æŠHjXK¾9Û^2Gþþ΋”‹•G25ècÛVͳ1ÍYÌr-â¼gÃRª¢sô±E«"¢B .`ÕdV5g‡DŽ#y§®ëVjÖ8b«ÒÆ•–Pfñe¶’«cæ‡óÍEÛ³ÍÁ=RÀŸTfë—«óª:¥ì¹Ñ*&âbàiR™MD«J5)Z‘<33ývZP#0‡ìŒx.9ˆ>†èØœóˆ …À¤&EM¥ˆJ©YDMY”r‘G ¸h1.äÀ³a‡Á3c!%˜j~ü«³÷JŽÈ| ¾­sĬŠɛؔæ*µŠš¢waG#0 UˆÎ·MKH½CÖ*Dì¼÷Lì B„Üw‹¾],ÚšÞîînöã“—øû/ž?Ûx‘RJvQ]Ž­_-{Žsi«g`R5×TTNãx<çÓ¸è»i,7ïSäË?üý?¹¾}ÏÎm×gÇÃPK™æãœ'¸\óåE7žîeÏþW_þú0ï åqºoZ·Z÷λ\kɲ»ß×$u.ï^¿_-ÏçTÒ¬÷Ça?–¬’òÇ/žxÿîa¿Wäà;Í|w{:Íj€MÓÄØ‚1ßÝ^‡¿ÿ{?^.U\óîýÍýn¬FkK©sIóG/^ §“÷ç=qIɱ‹M#¦õîÙC8&ï‡û$Óöl3Í'5›æœrºxz^öó_Ç®‰mgˆ8NuJÙ7íO~öÍ×_ž^}u„—ç›ýi÷0ûMÿÙgŸoÖÁù®é±>Ò§ˆTÓi.ÇÓÐwí²o›góÞšè!˜t}d!6o™vMNUе±gdŠÊŽÐ!9&r&ƒÑumÃŽÑ‘"*©¸™8täS= 2B ðdDH@Œ”çR …¸L)1ùຒÕûF„L8ø¾+Çs£–Ñ(MÑ€ØT‰œ³c€(Ö¶*Pl\Óù$4ŒõNøÄmÎò :x¦ÀÑ÷Ü”R™q4NF…±Ç€P¥¶MtD¦Š¸×›•86„ÊŽŒR1œsˆŒH8ºè}ÇȆHL‘J-ÌìÙç™0x'µª‰XËF9aª¨UAAZöf_k‰ªcIµÕYD H!LÇ"è€ßýæþßüÿ¾xs»·È›'‹®k1¥¼{8–Œ©¦aÜïw‡Wo¯}Óþí?ü½g‹ÖÄf'Có PÙ75Ùáaf¹;<4}Ӵݲ[HNÓ0‡tÊ阃O×7§! Ãh RUª•T‚ @C‹ªˆúŠf5£*"sšh•,¥¢9ÕÚÑ ŒT­’ù\ªˆ´1†¨& mÓvmÓD«S­YDs®ìüf±Ž1îö»‹å¢ä›r—Ž©ÔQ¥j-¥fCØ(5wiJ¶Z^¦);Ž5K)sfçÀµE¨ŽUëÌ.x×6zTœ510È4MÎG[“ÜøÁU“1žœi=÷`@è q諘Uc‡ªjÊ€„މØÂoM¯øèGuH†ÈÊh­A÷(JpžÄ”@ª¨“#QU5V}ÌDt1–ZͬÈT§™˜ ȉyÎ;VMˆÆŽÍD‹ª™ÓyƒI’w.† `—gÏ.//‡ñÄÈó<å4D&Ù*†¦kié"ŽãÑë×NÀÅÞ«$"$-¤¦iº¶Mó|¸=åcuYcÿ—¿øïDÓjµéWËЄË˳Ó霞æaØ›©£Õ4̯?|ÇàüÝÝ~½^æâÁÀb Mï†tšJÎëÍJ¤¾¿¾»?Ô*¸Z.çãxõòübsþpóaÑ,r‘ûýýnwüÓÆ?ï*[·êƪ}öü馿øù®íª¢lΗD>6MÊ3¢!¹ð°?<n kÎUEVë¥B*å¿þù]¹s®Š j5"wûáúp¶zòï¾üæ}—¦c¦íÏñÀ¸©ùí~ô<6œ¦$RJ¡šmѬ`A–¿ùõ¯?ÿá'«¶_6«ÛëûeÛ2¢8è;¯5“”&0˜(#³¦¥#׺aÍpœR©ŒJGeÒä“wŒÎ@Þ_ß-½gvä¬0Ä9i–)—ã¢g@t¿½‹+b¦VÔq0•à‚a%¥e³Q%bPçd`3Xª¦ˆؘ´V«¨‘jwov±ÞµÍ’få3®'K&ïbä\öNEÚ®/eõ³Œ>";õŽsÍRaÎ9ϼhV}ìÓ|'PTŠ ájÙ·MkŠfÊl€bzJ2O™ò\CY! RË˜Šˆs±‰]ô¡ñÊq(»üå·ß|ö£ççkQ)ņ<NDæ½C‡Yª%ëšÎ‘? #9‡Á{çÐ1xX8G*¥«,æ©€Co¢Ù¤‚© (¦¹J ’ÑÊ ¨ÀXĘ•щBuìJ6UûÕ/~¾Y^]^¼üë¿þÍíÝÔ=¹X_öŸ¼8£4¤IOG=r·›DO˳xv¾êÚøúîx˜íÂ×Ã~ß¶n³]V³P1—4M2Ïè¨M…§ 3¸ÝýqJózÑÔ*ûãx’)š  ˜ýV%šªLÃXÌV}ïÚèŒUÍÔj$M*„ŒÌPňÑ!š™s'žÕ¤ØkMü˜ªò@3Dddd)ɱ럆#!”ª}Ì%«Ôa§C©%—ä™Ó¨ÃðpR„j¥b«ªs)¢@S.ÉÀÔŠ™xd‡Dž@¼™I+ìÅHÕ;ˆª¥ÀryÆâE2igýq&œk‘aÊ6ê `E?U}àûGì¸Y1s€Ì  Ž;çjP{ü․*º ]`±Ü4Tr!$*U˜Ùû0夠¢âkÊD¨D`h¢@lÜ*Pêüyuä‰ÜXFµfŽX À¬ÉR‹È<å¦i"•¦óZTDK­Düäü 2ZÍ9ϳw…YØ»è’PžÅ…¨]ná4ïÓ0Î*Èž//.û>YMm\Æf±;îlgM ÷»Š„µTJÞÐÀṪyl»…†Š™r›iìxrl/———/qÙùx7þügï¾}ÿÍÅù… ÙszrõäÍ7oö·#ú% »[DX,ÄÁà㺰?ŒmhÙäÃííÛ;¢vsyuYç¡iÂÛë[)§±”¤Á€gV•ͺS©%™™©‚Ìõâl]§c³\¿½}÷Åoï÷×I¦ÕÿäO¿wuÑÎà .?ùů¹q‹o~ù¶í›ý®žæúîõOþÉ?úƒëWóÕÕvµº|x¢-óéŽ4˜êÃÝþòì‚•¯_íÒ!Ÿ/¼ç»û›åv=œRÓº‚9לjõ>Š4AcMŽDÄ{Akã!ž­ɪôQLI¢¼Z, ­’ÝîoÑŒ€O§cׇ£ŠÙ<ÆÌ>xEÌŽcM*‚ãaŒ­÷¡-³€r8žæ,‹Î‹å*€Ž*ƒQUÀR5ÍiÌS³j€*ø€·÷{•ÉaôÎç4¶Ô` ¨ít8Mcí?ZXn½€ˆ–GG·Ló›&ú†ÙÍ6äS®¦ã8Zç»<€IDÖ«³Æ-kslÐǸÇ¡ª¸Ð 1ho† **ÊÄR”Õyhê8,›E Áì0'§Êž<(>6yG–±ŠSÄS-”©æ‚& ÆÄ³©3)H4¥¢¦Õ‘£T€šhcï«€‡]$bX.V=²qJeš§¡žo¯´ºß|ùõýáΖŸ\n—mîOføáýþÝûã0Ç Pvc}õêîÅóÕïþø{Mh¦i2«‡i˜æTªÆ\Ê8d$°ûq_•“ÈÙ¶»?Þ9r«Eè»æáî8Ò™™Ø©Y©"fÅ£òh¬dG„`Îq ~µh׫fч¦qmë›ÖµmŒÞGï}hblLÅ;&¢¼ªÌ:§ZÁ{<rAæ j„ šöãqžGB“¶m\ë\Û$Å×ïoïï‡åjÕtÜ,xÎûZF•X‰j© ¡ñÜ÷´Y·ÛEßòÙª¿Ú^””šÐº&ôe¬%Û¯¿{ýåû÷_~÷ú¿ÿ³?{{ÿWôì“þòiG,1Ðx:ì÷‡iúöõ›å¦}òüâÕ«W7ïïºÅbs~¦æS’ƒ ã¢ßïÀìa·Ó„Ä踂‰IàðüòI>Û¶{zv> Ç_ñË¿þ«¿Ð’žœmÞÜÜ @Óů¿úUßÅ?þƒ?ÚÝï¼ã«Ë³OÎcðOž>9ß.-/:Þžu€ÅLº6^]=Æú—?ýbÊîW¿¹>¶;¤T,F·ZuçÛ5¨ǶõfÉ|ÁFÙ—ûÝÍv»6‘R22™Y…Ç̵EpÎ%•Ä‘TX`nM™k-"9—Y¬-QD&}l}ô‘ÛÖ1 ƒxDfS+YJ% 6D­‚È€DDfµ”ɱ‰ @  Œê\q¡ø†¬Öä@¤”ä©eÑ´Xt‹å2†;E&ߙмXvýjq¿Û¥4«ä”NiNûÃPÈá4°(a³{Ø9BB7NEj@pfüþíÃõ‡›Ãi¦z}ý³šQÊÈj*P,Ê⼠шÍsGÌÔÈ–û«Í™gì×KP5Uð¡,){욆ªˆ«ðw߾ꚶk\àë¯_½øøåþáµl×]OmK½8ŸrE<§)mXõk¸|r6ÌÓ?}!–ÇZæñ¸¹¿ÿöêrÑ·/Ì/ÇASwÇëËç?DpûÛÓÙrûbûì7ß½‰Ñ3¨•ixûî»aóèn ëXç~ÓÆ–S™#æÞAÜÿøÿïáõÛ×ÿâ›Won”|™ž®ŽÓñâÉÕÕE·ßÝ>}þôéÓ'óüg›u_ß_¿¯Âû“ûËŸ¼M¥ˆꩺáêãóí“öúæFUŸ?¹óCß¶›‹†8 1¸ªµÖBªÆÌÛ)|8Ýy$‡.T&T!3g.£«5›UÀGÏ‚9v†äˆ‚ËE@™0Š$$nCïŠUÁÀP6Mˆ„ˆ²˜cÐ;Í¥qÞTÉAÕ©ª±Ñcˆ.ib䨵H Zç2´]<î½óÞûi:1BCï]-V»œ¦éò¼sÁ/ÖÍíÃW£RKMóý±ëÇÜ51¶Q R©5`c†=Ár-ZlÈCð$VÇ÷Y æö˜«1b~¨îÓÏþú»ÐÙ÷?¿ I橦wû½ ¶>ëW]$ª2MeFjn£sÍÀq׆åq?§y–²h[d7ÇÕäcÛº¸lÏÉøt˜w„d8!Iô¼jº(îÍ»Ûã<úãq?͵dÁè]t1"@ 1 ¬5¥ZÂ]­YALÕ”‰²‰Õ"Å#çJ™-—IÍÌЭ¨™"& ¦@«H&7L¥hIU™£VCDä@ч¾ë|ƒ¹N¢"hŠº ¡s=€J NÕ àT¦ÇÜp­C#403RdB©9Ù4ŽÑù>6y.©V!‚a|(¥.K$63…É 96T‘¬*–ªTÀ‘7%ôÍiÎÄä9¢ziŽÓ~’;Ù<ͫՒ½§ÝÃ}\¥fLª6§\?¤¾ïO§1:>¦j±b‘”Š r Ñk.„X¦9X¤ÂÝú™ îû³íÒ$9W‡ýuŪª缪0@J³ã8*ª¡¡•T«Tx$îT­d„JôÛÊ5"FË&µ’a`p!8FT¥Ç|Ì㘫óË_þü‹eÛ­V¾hA×4=!<çøäìj»=Ke®Z ª˜Î¹2>r.äp:×ÔRÁp.¹ÖrvqqöÌlãï>\¯6çÆñ4“èpH­/¯·]V+ÐJæÃÃ|JöëoþúêòìßûdíXSΩ 5üð“Ï¿üêý²›e‚€Ne<}ñÅO=œïaÙ?ÝOéîþá£ò¢í8α è/CtHJÉ›‹³qš¾÷ù'ÇýäònwýÙgŸ¾{õª9¹_~´\-Ý?ýÇÿ£¸n¿úögòg³§é°ßw'Yo·ú'à\N"×»ô¯þÕOo?X.¸\Á~tõäbãT‚ñ|ÛÆ°8îöc9}ÜnÌD¦|pl® æ¼gv¦42 8­obŒY s`G¹ÌÁ‚’2H`51E&EUÏŒ@ÈìÔpN£Ãß2DsM8ÏÉ#®ºeÎsJRj–&‚QõÞj©JšæqžóÃÝÔö;#6a‡†\«"Q*B’™fkpu:LU¦õz…V[ïÜt<©€ÍaWdž£y›Q0<ABbçÐ#g84¡1Â㡲;×M#08 ºà+ÌR¥Aj%Vnq±^ê¬sJ®q"ÅLÚµ~ö;ËYj²Éq„PßÞÜÌ9mÎzßãÙf…B]çÁ5ì|L©VµêÁK1‘ì|Õ2'#M ˜á8î :æ…Iî»ÈÆdYfñLRJ¥ˆV ÖÊ%[½…PÔ¤1´1Œid0b+9!Ã8Oû‡ÕùÙ\dº½¦Òö‹Æ“`j•»#öq¡¨‹•kX,FjÛåý‡yÿ°ß§©Ð”„£Ë‚ÎySz¸½5ñÇ¡¸ˆO¯Î/¯>¬%—ýû‡ëë‡It{¶ì±ÝúRì?ÿ »•»:[!µMÃü°¦Só¸½$þÿÑS#Æ¢Šì°HQS±ª&¢)CšuËólÅPˆÑ×TMŒ•´ÖRç4O%Ÿ’LU&±lX…H‘ÙbÓ.WË6òŶk¼v wMXô!zh"5ÈùÐÄÂÁ›AÎ ô·u2`Ç¥fG£wìÚ¶5À"ªf)•š³” `&¥ñÞ¬päØr` @ "5§”æ’¦2=Œù0æ¤\„¥`©8%K³2zK©ŽcžÆ|ߎùä[ÿý~ÿ˯¾<œæÃxºxr–e×,ëýþ]NòÉËÏøG?ú½ë·UõÓÏ>ƒ»÷þÖ„Rw÷Ñ{ï¼#ï\ì˶ëLåb{îÉÏÃüþí‡÷÷»O>ýôëßüæ‹_ýòTŽO/ÎÎ7ç×7§¿ùå«§Ï>Zõ]óý݉ »~÷ðå×ïSq~»jþîŸüÞrÙüêë/–Ûè{Ú<¹|s}W+»¶WKU#À®f’dŒ®kÚà ¢†É "€¬Lè×ZJÉ¥Š×>Ö/½÷ ‘«RSžÕ‡ çZïâÃý.Õ¼9?3ÂÍvÓµml£¢§2%à’­”Ù±!dfR@­Òø3Ûèä„o¾»Ñ ï¢IeçE@­¸àš®;ŒS%æ¹"-8OìDmµì.Ïú>x"jB]GР-CmºmJ–gÙï&ÆVŠÆZ2Öɶ&Õ3:rR¥Íyö]³³v³ Ûes±Y?¹Úž]ôýÒ],V›ÕÅÙùª[•¤¥ÂTEКÆ;FBql ’ŠÌ%+r8Ä@Á‘cl[¿X4}Ó²!2“‚:çÛ&DÚа‘ÍX&›'fI bJdj!0V!GйØt‹¦í¦9A¥·\,/ζ]ÓÕbãÆi\,Û«‹Yi£Ûž-º–7ë¶ Áj¢W¯îowãi.Ç!O€¬ú¸ˆQ²NS=N»O¾÷äòr{¹:[¸¸l›>4®?4Ëî{ß{y~¶Ü®"XÁä;þèùÓ§W}ºË9éiLŠHüŸüƒ'Ž˜ÑõMWRqˆV«ÕZÓì¨êtšºØyò y2×4 vq'&—sÉbY1'AƒæHÀÈ93!0Dƒeßt Ê›µ9B“šË4:€4Oó<—œ§y§!ÍSžGQçYÕ¶.xBÖ…XS5SSU+"È삟s@33‡Œó0Õ”sšs))ã\|Žãº çf­Ð摨ú*U\ž­$¥ËDRÄV]s¾èŸœ­V]\÷}df|Ó4Ž<6¾qÌ„:£ 4±7dÑêØªw›ø¨›!Ch]Ë„E§Ð…â=ÔgO.ÌŠjª5åZ‡Tv§ùá4ŽHu Ìê,Ižµd•\ÓTKƾYAÁé˜:¿˜’FG9îÓ8f‡¾ÎBèç¹¾ysæódÃ>íîÓëonßM»Ã4LÓ˜¾ýú Zx÷vWªÏRÉM×­ÏÎËetÞ©•a"™“3NÃÝÃá8¦÷ïî,s™ÍU©±‰ ²6œ Á•šªT  åHݲ}T'Õæ<͵ԜÊ4¥á4M‡,ÕJ­E+8¸:ë_<¿h#5žâ.6‡Ãþ0ºeÏß_Ó­ÚÛ»CÓ­D$•qJ‡y.Ëås‚etÝ4ÎUdµZ1SJéÝíÛÓ4<N!®Ä¼‹ýýýîÅóg¿óƒÏ´Œñ?ü›«ó'w÷‡Ÿüì¯?úäÓ³³ÕþöÃGW/Ÿ}¤‚o>Ü~ñõë?ûɯɅ|š§Ã8³½¿><<œrÍܸ~ÙMåd -~üró£}ty¾Þ.×?ûÙ¯Õá÷~t¹Ú A 1CÊå8&n;×ösJŠPN%£ è½ïº™Ô™ÐcÊ,øN MÉ*šÕˆ4§)•G>¨‘pÏšpÖºUIÝrL: cIv&æ6Zȳiµàü0L±ëû®slˆ)×ñÑ8åêÂjµTž¤´Ë%¢'Žè<2.— (–Ó89çšy®9)‰k›¾XEÆívC$&ÕQsá4Öãq–JÃi|ؤJÓx ­µãœJV3"ïB3ç\І—ýUš¼ŠÏ¹  š‰B-4žŒ¬Ï“0² JTÐꡉ̔½/!HŒŠV¹ÆwÅJÁ^šà—MºÐ,šE˜®úF¥ª”,ó#|Œ ϤF†S©SUc/f¼Z³k=7LŒÑq`ŠÌV¨ñgݸ穈€2sÎÙjaÂTô_¼z}³W0癀R–¾m¼wÃxò>æ!íîLJýÍ\Ú>n7‹ÆÙó«óÖótœç8瑜WC&ßx¯&]lšèA³ZÉ¢}·(¥æi®*Å* Ô\ó,(”SN)‡®/¹šý6ñÊÜ%±l ¬]ç< ¢3!-ꉫTPB£qCãûÖ5]ƒKç©ïšœffªµ˜!f~¬v€T­äBΊäšÐJÍ•' ÀR+J©y*‚Ž4˜ å°;­ÛZ’‹\‹sÜöùx˜Ø{ ¢%xÇ‹÷‘0víòááδ2s)2Ϲ –2•¹_õ±áÈäÕX½sZÔ“¯Yr‘Ãq @"ÄÈ‹E‹U¹ÃÃt½? Âúl]rzvu1ÇãE—]CŒÁŒlH)öM¿j  T¬¹6]sOsI„ƒG°”S©µévÈÌÌŽ/¹¨iIÍÐQA4<öŽ»R³o9öíáp`ª}ôLUÓaö›?Ü¿;å]{sóñ'/™º¾½Ú=¤›ë TÒøÙgŠ©‘ÓôôÉ¥‹áùËO_½þp8Mýïüð÷w7yNd8××o‡‡ÿâŸü“4§óWÿNÕÿ¿þù;ÿ«ÿåÿì÷ÿG_üòo¾÷½onþæ×óí»ïvÃýÓgÛó, ãa˜óíýñáaŠ©Ìˆ«¤íºÿôã¬òp‚ûöÛ÷¾mŸ½8ÿþž0Õñ0-Ú¢¦ÙŽÇ:M‰Cãv÷]×ÄÆ…À£Z¥d;&fÁ­Ömã9‰RTœwŒ”S**Œìƒ™Bè´T˜ Î ÇÕbc£Z¥–Óxdr&àcswÿpØ¥Ö¾‰Wç€"¬æ©æ½©t}WЇa.‡ÝÔÆÍÍõ}ßµÝ:”:ÏÓ¼[õ „º\´EжÍòááp¿?朲ïgËíé8\]]žmW@šÐ5vLÇáÛˆK#ëW®Jf `ŒÀµÖ¶]§<‹¥&²»ÛϦ X]¯(8˜ò\t&vÃI§”.Ï61:p²»¿;_lULȪ$f|œÏjJHŠH*¤ÂJRQˆ‰•¨"(25jXj¬ƒw!6aw¸,Î9“Ü8fr9딵ˆOÕªVÇíá8­7ëÍb3Ÿ­¥a¯ ½[ÜïOJ-Íi¸¾{g(.:b1zâE®?Üí÷Ê­G–¶ñ*ÆzÜJÕwtu~9ÓÃ]~ØM¿8?ßv ïË$ŠdÙú4Ç95í¢MÛ¸¾m ‰ˆ(°3߆v¹18Sžæ”JÖ‡ÛÃÍû)œ,sɹ¾[àÿúó‡iJÞ"—ç«ÙÇ{$šÒ<ͳ‚µÞ«Xô±–|só]pÞ@Û-Eïûi˜Z×yÛÍÆ5Õ{=M©…Ø”b‡ã´ÛvÛ®ÙZÑ'ç/‘¶:Á´»[®ún±ðM;ŒeNµë‹¾[öm)CôTTËjµ<;;ÛNûÃp¿Ûý×ÿ×ÿzÙ7ÿèþýßÿñïµ!œo—1º7ï_NÃýñæ_þ÷ÿÍÕóöɳ…÷Ø´Ýiœ¿úæ»¶[Ħ!ŽÃ<Cß¶›õÖùæÝëïž\l•=.Î’Ë|¼?®ÚÅv³úp½{ýænHuµZ!™wÔ÷áülÅŒL<ŽcÛt¥ÔÛ»»¢p†ÍjªçÛ­I"FLÓˆ›Ø‹¢‚Å@ÐR.IªF­(Ù";P+¦ÆX¥žm–ªÕEç¡Ìc­š¥ÊjÓGO5CצΑËEÆiÒi>¹À}kª³fY†U×tèàx<äRœšË ·gO¼‚Ö:îos‹NªK©bì\ì۶挲ìÈY`j‚ Ð<φ”’|xW5.VÝjÕGr$üþö¾H®¶þüìê¸?›€ªT7Œ3!… Ì@Í@$PD\0)fðØÝ1BΡ™š)*’‰•œˆŠÆà•XÈ*b0K9Ïņ *úbà ɵ­wH‘ƒóñþ”g9ŽÓýá>.ÂjÙ™”*9šæùæá’]]lJ¡iÆ2ª:Àjº\5¥æã¾\¿ÇÑJ"lB €5kãúûÓ|HÓzÙKÊã\É·ÎqÛ’HeB;«Õ3oÏVW—§ÃÕÆaPGhe:§“|øp¼{ÆRÈs¿h¼C·].ºççYRw<8ï‚÷ù4i.R$ÄçcÄ*CßÁÆ/s®Ì½‘¥©L³Lµ˜FT¨™Àb­¥iÜïn'çóËE0KÇã³'—Ž"îîbç/ŸŸ Ë!틸 „~ò“_?{ñ鯋‹Õ‹Ï>Úíns™×}“Rª‚ܲ_u!Ô©<\?ÜÞÜ7}lkѶYœ†S1uàoïwñòùS-‰}å<©{ýúíî°ëºH= ÁýéôbõT-¥2Ï:ßìv.4€žC;žL‹,š•A?™0Z»„Ø-ÏžÔZC>þäã*u¿;\>yI|öåW¿ÆiÕôËØïßßóÕv;‡ÿÅÿüz:íþþßùÒx¸Ø¬ÏVÛ»›ë'çgMëÞÜýÆ÷€ r Ž˜mþïþíï¯Ö«ýi|ýÝûqšx®¾sÇÓItï‰ÆÃ|w8š§'uùâÅr³:ï N'â(Û³Ð$èzºººZ´Í<œØ20I»í‰Ùo·OÇ9¥Ü›Õ25MÃĵ–f½ÊiN%‘ ²Õ2*)š¨Õ &s™ Ý0§>Fص‘‰Ç9MsÍu>kWL³yÈ¥tmóðð0¢“60†Y+šŒåÔ÷}Ûpµ„>` ú¶††»Z4ú¦?2¥)—læŽ0½úöç¡YU­äKÛº¦§Æ‹-ù˜æi±<¯5 “ˆJt.ú&*b@i†a˜ÇAëÜY‹†¬ûú«w&¹_õËeÓ. _4)‹ ašN)pYµ®V0NT ÌÌD 0²Ä£àát˜óÜ÷  f/UU3RURƒZ• ˆ÷®ZbF¬UQÀ¨†¦¦ Ýp,§zjÛ~8Lgg«S~p®U`Z.oïÞ|ù›¯Š¤'Ï/—Ën±ÚÕè@û¶þÍû0ØœŸ;Tжѥ(³úA’šS„°Yw˾CÓ’Ëñ4uëbœsY-žív§7)‰¢¯±sOÛm)T¦2" †Óýéèã §ãáÐöÍÅ“+-þöú]·j T;X*:£_ü?üïÿAµ¢ R+ÑGl ϧ ûÅREв¨i¿Z"S"a\.×Ãi¥#«xöe.,ULÔ¬enã’k=8ÛïUa¹9«’¦ùè4M0öM.•JÎó>rüT´–b% "zÇ«EphÓP² `izR¹»Ýt³Z±YãÚE¯fÔ_½¾©9Œ{½»Ç\3hèÂz» ‡Ôö1Æx<Ó¢hž¦a`óÃîßõÿ‹ÿòsàGÐRTSà îñ\‚¼môEJÖZÕŠ)„`‘2— § æ7·oŽÃTk©ZŒ¥æœÒét:ìwÎSlÈÌŽ‡tsó0ŽyÊ5IÅ€Ô¸c>U‡®óÂf‘ƒƬàœkßµí¢Û<=ëÏç/Î>þüÙÓ›ógÛn›VÛVÌŽ ¬HN&æAI­šeA )V‹ÞÞî†ÀMtžPµVGa±X k©S±b®r ®o•j…©ÀdˆÕ¢S’b§iµ4MbEª‡i¿†qžr*h£–ŠÆìˆ9ºÈHÁ9Dõ½GÏ»}tmÛÈçÖy-Êà¢gF‰ÁC’’K.¥¤\‘ɉš*øûTkU“*bfb8§<§:ŽE pšg"6U ! šèQˆžEkÊeš³ ©„÷ÆÃÄÎ÷§ã¬VͪsÝùò\³–œCÓvµêfsv:‡‡œ«¨‰Ô®›Õr{Ö¿|yñÙ'OgT-Î振¾»ž†*™µÒ¢[¶mW´úÇù(0Çåts|pM³Z­%Õ”êÝþøîîÉ4±ÊvµX,âbí¤i§¤2Â0îö7c>J“‘ä<×"Lí<ÃýÃŽHŇǂ>„ÀŒäˆÛC ùÔSÊG“ùj½`43=Žów¯¯owÓýNÞ¼;c­éêrq¶]#PD ·÷Ç»ûS*ZE†é¸ZõR2‚(Ô"å4¥ãiȹ"@[¬JÁÅà])£bŽ {æ.,÷Ó4ã8¥)«–jšPëcÓAÀ w^ÕDTÍÐ\Î:Îõ4ê<ÃÛû›]y}½¿Ýï{ô~œKqÞ1«ÔqŽó\^¿¹? Å1•¢`xs³'#·¼xóúöí‡ý×ß]Åq”_ýêÝ»›éë·»ý1kõi¬ ÐÆÀS:*;7ÍYŠ^ßÝÞNoïî¦)cVǪ’DjQ¨U­æÓ”‡9£©åYö÷Ãî0Üìwš§q8¦ITŒƒRÿÏÿ—¿Ÿ%³I$7ªÌ¥Ì¹š¹ŽºÁ{&#lš ¤T#C¹L„V§,†“ä©.[WÄ|pjuŽÁ¹ÕºÛl6µÀn7ôË•,RÇ}×6Þ¹*åQ+ZröÞ1ƒJñšà›Ðä¢UUD<Ù\ЍŠV@@DQuÜ€E$?̓šjFU‘¢#¬%wÝfs©É9c’ÇÈW®Šì|t¢ŠD€ˆU Ò£ž,TËb 7PÕ(†âCµ”Š™™ïÌ9Ï@Ñ; rA1‡À¨Ö7-€L5§<Çèýµ1Í©o]I8žÒÔ4J̪ÊÁÏRSV)àЩ fêæ±Ì¥BhƒC[÷©XCt}¡VdT2C"t¾±”SÎ)—J>4žvÇ¿üùkׄèíb³Z„nѬ$Áñ¶lûíép¿X¬œwU´‚é°ØÑ|}ùä|¹l×}ËŒüq›¶Q)sÉ£<ç’’²5Á2ë͇»~Ñ)Ô¡ëCØíÄaJÜg®ArÙ®6Uu.Ƀ¨Ô.ÏμóŽÙ ¾{#â‘cEúîÕ»óó§Ó4uqéåÜòºíÏ|Óvý–¨£у.»ööþ!‰výrš'@X­}מîwM·ç4Ž}öôIÝ]?{¶ħWÏÇyžJ®lÀöí·¿Óñ/~òÓõÅz»&;ÃqÎC V´iÎDý?ÿoþ‡ÀËO>þônwÓoš§//ϯ¶÷ûý—_¾þõ¯÷ûI…ÛÆo6ݳ'îïýÝÏ7Ë(µôˆª:Éq“ÕLJ-sÓ¶F\æÔø¨ZC sÉS)Ã)çYq*CÛwmÛ¦4v1°‘ìò³×ãm>z±½|¦ùš—ý¶–¢ZÑ[}dbZÍD™}CÛ›ÛUl»ÙD³÷ê™Ðt²h ªpw·_ŸuÌP¦Lÿú'¯¾þú¤ r~q+xþñ9G|D—³…ñ4ä:6ë¥Ì)¥üÝSæ€$Uì»oï¿ùn¼»Ã‡‡©ïy½Œ.ªo/¶Û¯¾yãºõr±yõê• C9ßúÏ>¹üø£+«³Ažs:ž¦T1W#D4]t‹6DF‹ž™ÀTÁ ÉPªÍÜÜGûp;NYK©]×ö‹Ø÷üÉG—Wç@þú«WÇSæÐÞÞÞ~ù°j.Õä”ݪ¿ºZŸ­ÎÇaÊRÎ/Ïnß¿ŽCß/}Ó̵¶--¢C/ÏÖ`0Ï3NiNôõ«*`dÇyšLGȪ c‡dÄ&föì]3•yÈã˧W‘xw˜æZL‹V¤iDçQy8NJèbÀÿÓõw)”J‚ °€!@šjè§¶ R xö¥·Ž9tˆˆ„ìœsî8ìªTd"cj};Õq?%¢žA™•ÈØÓ8ÍÎ7}××4Oó‰É¡y&‡(Γu]+ÕTÕGD­PªC2‡äœÃRF%$Ç*µUŠCôL!„*¢bYr+"9Iðíœæ¶iAr0޳)c‰a¹Ý¬­Îl 5«Õ®¨‚ÎÐSSƒZ+‚'öªÂŽÄÔÐ1–RçD¾$‰1ZµiFʽ&8îjÑ5ny¾þÕ—¿úèų»¯§yß-üïýÞïЦ"Àn½YÍÓ`˜‹Î@ˆ„DÀe²_üô›Ý.¹¦U¨]Ë?þü“š§ÃxÂàW«¥ÉäœV­ýr]Šå9irLLjY‹4±ŸŽÉ»˜UþíŸÓ÷WÓ” "øÐÞ=»Xuç6]s9gwuñ1[ !¤•‡«óó÷»#wën±BÀ¾ë>ûôÓýÃÃÏÿòÏùþpŒ]ë˜m¸ýæ‹ómÜ^l/6—»û‡§},äcÛ‘˜O»¦u¢)ÍÓÿýÿù;·ÝŸ?Ù믾ø jøæËwµ¸àÚϾ÷Qåýò¢S*}l~ö—¿hÛøãßý[DnJsÎówß¼¹½9<ÿhóüYwq¾Íg›µÖR³Ö,‡!/׋Ðr)É!{r.j&UæaZ.—!0˜R¢àw§!´ñæþmØïÍ¿úêáßÿÕ{äÅæ¼ûäÓËï}þìõÛ_‹ÐíÍéââüÓŸ}óêË‹óMÛ2ÌïöÎunîUóüÁ=á—¿¾ž'÷Õ—oÚ®yùÉÓ\Hå|óüÏþí¯ïª !g›SÞœ…ÕÖ^¾<[­Úqžß_»]ÚßfÉìo.Ç|¶gËnòõýÍGŸ^~ú½«åš}£f`HÃ{z±ìݶ÷ë:[/îïnŽépLùön½ÿïnùa»nºÎ‡VËÍ»wïs•Åòl³>?‡!MðŒÔu͘çûÝõ¯¾ø‹¯¿ýù¬z}8üÕ/~¾\5?úÁ‹/~ñÍñ/^\|þƒuìEu8Û¬ÛO‡ãÃqjš¥gwwÿËß¼þîÍ8 x:ÔÆ…¾ƒóm¿Ý³ñóï?¿¹h›öÅË?ÿ›_0BÇ<ór±Ƥž÷%•e߯7«Û‡ëÕ¦+uð)R§9üòׯÍÅãx¼zröüÅÓûÝí·__§„Ÿ}ö‰YþpsŸú2²ÿgÿ?¯y1ÆœV úOÿé<ÜÌÿêÿós°…˜–’£÷*²h;)bDYT Ôhú?|òÙç«egËuIõ8–ñÿþÙþÆ#C!DpLf‚ÞB«/^ÒÿéGýRÌ;wqv–G‡t< Uøápü›_|Û-ÏNã˜rÙ.R­3@ ÆË«Õ“'‹O>~>ž†ë»‡‡ÃÍö<üèŸ:£E¿8î÷iœ€}28M @Õ¦˜ˆs¡ñN‹¨¢ã`Ô¬ÖJHhFÌÌ\Šæ‚µb`ÈŒœr9Í“2"p®º Þ‘¢åZ²Y®’gÕBRŒÀµMX,"‘‚© ¼sûúý]éú‡ÓáÙó‹íº „VJÐfå·7ïnj΋sЋ޼¿ÛíÕ°ëº2ŒX¡¸Û SÉ"{à ZSqªy*¦ "DD@ ì8xŽ‘½Çç/žŠÔ4Ì÷CN«ífž¦\³oq¹‰Èµ¤ÑYeJCàÿì=“j"XÅÌÀsì»åýýƒŠ™™ì<9­"¥:@4pÄ1Ñ’Žû‡*iJc­YSÎÃ,)ל«ÚP,i™JžKàZl*’Š2™Sf5«bµT!Ïj–²ÎYo¯¾ù0 ©ïºi8Õ\Ò<¡©™Ž§‘‘qœ2ˆb.¥ ÍÙfµXÄØ1° TbÕ”SÎRU]ôìÑŒ\ËUr$’RA MÈQ£˜™À¡õg”Z«ªÎÓCìºþêü² íª[EïƒgÕ‚h `jÌà8oL(µ X.Õñ¢ë]ß><|¨’r)Û ”30 "Š Å8–*¥˜r0p†•ÀTD«2²gÏ„„ÆÛíb±ð¡Áb¥˜rlr‘ÐŽÔ,‚¢Ã6@©æÐ5®¡õ²3+Þaô€V;Ò«7w?ùù5ŘeZ¬Ú««uß;ÇõùÕÙ³‹‹>´ŽÝéx(©œ†ñîaŸçÒ†öb»mœÕZd±X-—Ëa<äš«Ôyªwã—_¾í—çã mì¿~óúnxè7óظHä™=UÍsʱiª-LFmhÖ‹ së}\®ºqiJǶ—Å6ç€OÓ»»Wo®ow×.êÅyûgö¯?úôeE˜ËÍýñ7_{.º*õ»×¯¾}õ ®.®jÍ×ï^/Z7‡Û›»è›à;ä°Ûﯮž@)™káxÓT»¸ðîÞßl7W9ó<+~ôâ\-=y~±ÚâÅS¾|Ú^÷Ï.–ç«6²ÎçëŲñëE¼Üö¿ûÃg¿÷;ÛgOQ"F#2(ò'?zùâÅõ‡ã÷ôû1vÛ³ó[¯ZWë3ó‹¿ü›×¿üúøþº¼}7¿z7¿½>SŽ¿|rÞõ]ww_ÿꧯ_½>Í«áæl±9[šàryùó¿y}:€»¾Ù‹Òi˜‚?þáïä,¿ùÍ»n±\mÜ“g«ÐÉÕÅæx¤X‘p³Ù( ´œdðl»8»XM値¾i§4 /±óã8O³JE6ÅRLŒ¤šV—fFˆïߎ_µ;àÛW»Ý¡þÙŸ}ù³_\¿½>5ûä“ss.çWµR.›6囯™8λ\íg¿ü*©œ=9?;?O©VñsÖbtš2a¹kCÛ4Á…èãcÔ‚²ª¥,‡Ó0ÕH5[U<\?a 2eɈ}0DtØ¡@‡ú¸Ÿ0OØ×ψÀ¤dBUlN¹ª¦T/.ÏŸ=?ÿì“§]tP­‹=˜Y±àBšRÊ… ƒ#‘’Sš‡tûæøåß}—¾}s¸Ÿfv!95WgD¦–‹Ú㨉: àØ;¤ÆûàA]`5ç2˲Yå1§,H°Ý´Ÿ}úbÑÇšfÏ”Ó`§}™&Hðßû»µ€TðìMEUæ4å’˜™CŒ¢VÕp¢UÕˆÅ,«A d2t䉖úˆl²Ø\28t¾e @ŠŽÍqE‡úØqÊ"Fb4ç1¥$ Ç!?Æ›‡ý‹—ϧqÜ﹊ˆæ,~¹ÞÂÝý>Mµ‹gOÎáxšdJž¬hRÊàäñ4¢Ö2繦Ç[6­ˆ ÙˆŒP«©€U³\ë¬j@ÈÁ9Sd&ß6¨X­™ï”%¡QQB Á皦uìk®`äÈ{çg©“ÙlP‰ÑØ;ßxCmÛ–Ÿæ”K=¥dα!bªµˆhQ©ÚÅ&x ž;Ç9U­ªó¢sMp]çÌŠg{Üê¢c •}ð®ob™³w¡T3bF Á=®'Ëíêù‹õöþé¢ïÏ\tHÀÈ%'µÊ/®.nîo¿ùöÛÏ?ÿ~Ó¶Ek³è`µìs™‹I Í£¼ûÍ›7gçÛyœ»¾ÿù¯õâåG‡ÃÃ×ß}½¹¼í ¨].ú®Ã¬ÇvaÝ‚¯.¶/Ÿ^´ ›³èÛÀÁqô®_u›.´Ó4…<òªi?yrõ£ïôôªùñåðI-JÜŒ©Lóä<Ä®.Ÿ~úñóÅ·÷»!U{ØOçOÿ¤”R”oö—O.V‹¸^ô%ç°Tñ~ù³Ÿ½ûã?þÇVBs.Ä0ŸÒÛ7w7×'C˜ËéòÉ ½l¶«yœ÷»Ã÷¿ÿò¿øò“Ï.~𣋫§áêrõÉgO Ëj»™ËÜ’_÷ÝÕÙÆ3D‡M ¥$vøüÅù“« 6oÛƒ_,{ƒº=k//7‹fõ'ô{»Ý»’ıcrLŽ€´Ðûw‡›zûA>|Ú…ÿá?¿½É¿þb4Ɔ9ä\û,9\ßYAVË…ŠQ.ÕÅön·¯µ®7‹œò<¤<™d<æšëqk­`¶ìÚš3«oýbÑ.˜»àЛs3 …°]/× €ë(‹v)µ8@U,Rt>°C}ôþïµmÐPáñùð(LR=“w (ŠÊR W ί/ÄyšÇi¸»»»½¹A…uÓARËÒ¸p~vf SNÃÙÍûôæ»ñ8Ð~´ûCJÙ‘XI¥T]\lb®÷'¤JfèØ)²s(ªÞ;…ÀÁŠZgÈDRëœæ\çÓpÌu6,ÎA@¨Er±RÍ ùïüÇÔ¶ D2UU0Äd\D Е\ ÍE6­µd0¬ª†è¢kQ ˆ ¹š±˜7djš–‰,vM…: G¨x¶¼xÿö½ƒÐºDŠûÿÓô'½–fYz&¶ÖÚÝ×þÜ{í^kݼ÷è3#32™b%ɪ"P,H!Ti" 5ѯÒDÍAT© A&ûbZpwss3»íé¿n÷KKçœÑþ°Özßç!™ÛÁ•ª|qõôâl.1JVE‰™Ú~PÚ”Uu<ÞwÇDY7)ó8 C×K"¥c$…>{N1y&9I’2i¥QÌ™r‚ĬJ“Ù+IMYK¡„‚H BäÄY3+¥Œ1)EÄ9Œv°1DïdD$L$¤¬Êr:ZRB"æ Ì sÌ)äœH’4Z"d€X–ÊG›c$ É£‹ÉºHd(Ç,”RœRŽ)0s¶nL1…»ÑÚ@1ɺ6J°"Ê1IÌÀ‰‰1ø{2gc´)ª¾Jcˆ |Š1d;x$bN³IYTH:i£8‹ºœ÷ö÷¿ÿîpì"§Å|6™ÍömÛ¹1fvÎ电.uQ{€Ñù~Br­µ_þþÍ©‹¿ûúõwww§ûõ“Éųjõl2™«Ï?YçxªL±š-‘@Ù¡e¡”R)æålUK£0)ÕÌçå¤|ühõÙ‹çÏÏ/ )í)@îã Jaê2„4.ërb¤^MÏŒh^¼ø Å´)B’÷61K­º~‹²áBâélBDCK=EfùøÑå»w¯Oöð¯ÿÓ¿ÔeQÕÀ,eî;—3ø0xwjÛÝÅÅùb6Æ~¿?¼zýMko'Kª]¦4º*LU4§Ößn»ÿü·_î·ýÍ»íÐÆÝæxwÿ`ƒgƒs1³uQ ö>Q6ýþ›7Çvxúôy9‘U­SŽ)ñ~ßþóþó݃¿X=ÛmlQW¯¿»†Ÿ?]|òñålZJ¡Š²’Jc´T/Ÿ¾¼Z¾ü«ñ..×BGë»Òèõòüõë×$ò£óõ‹'WuÑŒƒË1))¤!¦ðüù’0>{|…’»¾ÏÖfgf½tSÈJ1æï}ÿÓ>|òÉg/>úèñÇ=ÿ‹?ÿ‹?ùl,‘@Ì•6œX›â³>{±z|¹<ñÁ¡ŽÚPH!„3v>ÇQÄ1#ñùU¥KõøéÓ›Û{"iŠòáa¼¾Ûc’÷9Sˆ2#òlÚ¸”vm¯”ZÍšY]æäC夌Éÿþ›¯›ù¤,eUé¼at!Ät8}²2¼¯zÅ™“I¬ƒóJ $)µ’A(¡RRÊ1X—\†((#'e޲Ô&§Œ6 L¾(MfÈ2˜•Rš@R¥*æÄÑ>Z.Κɲšr`S4B)%"°~T²Dhîo†û»þ4f— e€Ä "'Þg7z;;Æœ#%Ÿ1ƒï}¦2ù”c9gÎH(„$œ‹ißörQE¥’ˆr¤•v£ÌBHdˆÊ”¥!½í´’1øœrʈ(J£„ȇãεR¥¤à™DÑ­1‘eÌ1Å4@Î9Å÷J ¬›ªÖÆ'–‡ÑyËà” ©.'9æë·ïÆ£ÇÃ^ðÅã) (óú”ݱYN›úüéË_~ùkiôbBQ5¥ÒÁ·6æJ°à}:…Áï·ÛÙlB ³eU)­dÐR³ÊJ(E¢ë!eR$¤ Ì¡ª 3}æ„ )ÄiÝH`P….ô`]Îc$"£Ì¼Ô)%ïG0EðÒÈè“`Șß_/¢ spv¿»mš‰™sN™™…ƒÀÈHƒ¯+•ûÑùèç]H“”DÒÔÈ@)ô‚„2À 3sL‰ˆ)ç„D !æ,BÀa­íêB–J Ì"K£u&BŒHRJ!Èc{œ”&eb`"Ž'³™ºPF ‘ fâqtáŒ_õîa{TUýìñËI] m÷úö¶wVjŠ*DºÐ4oä4Û] vRTÉÇ(“'ÚT ©,˶?¬ÍAäº.5e R…cŒ1…!X¥ÉhSöÉ…|H…¬2( y'QÎ I9mno¶Ç“éÐu¦hXp€($­Ww¡Ë,›r>mÖ…j&ªºþîÍëÝoþôÏÿ¸ž(ϪþõÍ}Pñ|¾Ô¨ž>yö×ÿá­PBÓä_ÿÕ_ýéÏ~l½L*¾¾ù]‡·Û¯î÷×ÝéðÑG/!šè¬$RÊœ]\ø­]Ÿ]®Ïϓ׿âf®J#äííÍiß 61‹îdm¯v Þ½½s6ç=Zú“Pòâlþüé¥À\OÄÃÑK#ÖzÈ|oOµ*2`ðž³/ËùùÙ ýôg?üþ§Ë³ÅzñãÐÉyK*0Ðèr±šßܽýéÿWõ?ÿ\†~T*-®fÇ®_­&qJuûfÜ6gW«‹ç4N›ýèEQÛß¼~…Z=º\7ËÆÙñÃ/ž-f5ÅQýåñ_í÷Ǧ¨ž?}¾˜-ß½y'ÇÝâ†ôz2Ó§ãvª§Õ¬,ŠÉìéâñ£—o®¯ÿìOz}óí_ÿç¿¶6=ºxþ?ÿËÓ'lÖ7kyõl¥ |ýæëG—³Ó±{¸ßd ¡T35˜“|œVµ6¨,´X–³¶;*™•ïînšiUTÅjqN oo¶ÛÝ~ñÉW—燛ÛÙºl²H$O¥AI!C²))££‹„˜BðQ$àÈ¡YMØ#D„ä93笡€LŠ Zï%ÈŒ2¥ÑK$N¦u „ % %¡( @93SL™qdÈ@À )¥$¤2;€à³£·Ë)!cr^ JM˜'Îm×Ãà­/tŒÁŽ!Œ>ŒùïÄ R(b(9+% ¦ÌH@˜!1Äĉ‰(gfDF€sÌܹÁ§œQƈ ‚1ÆÄñýÐŒ¢F )•Ê@B.ô{sU†”’ŸM&ˆ ŒB‰Êh!(g@”9d™ K#ENÑG?:ûþ_9ïRJÌbBǬwÃÐ}ßöýwoo·»S{ꀣ&(+ùäéÅ|6ûæëWûÖŽ‰Y”j솇‡R9­Î”09cUVÑ;‘DóiÓÚÁ%f7:b·Ý¯ÎK’…Á†2¨õ„ua”FH€˜9e&£¦«ÉUö$Ñ,+­!†«ffJST…¸»Û}óêît⮋ÇÈYbÖWÄL*íÚ»«gë­*ÐÅq÷9÷ß]ÿ¾™ß½{£‹jwÜWµ*µæÝz=_­}õêÛWß~ã|BZ?|óúK’)¥ápÜûÍ›i³\.WÊ”@0+ÿâ_ÿþ›¿FŇá)&¶wý`Cη×{Œ³?ùá_nß=¼¼zöãOÿøŸüãÿí~q1{ôŇ?úøù§És?äûïñìÅGmÛ/– S¨”œV¢Ðê|½ˆn˜Og}7þ«ùë×ßìnÞݾxúhÙLÿä?ýäêÓÔ±RÀÌÈtØvm;2p35uƒ‘Qä ®0òóO?MÌBˆÕlñìòI©ôŸüôÊB¾úÁÑ÷]«TýöúªrtýÓ«GÒóGOÏ×O¯žÛÓÝøÅçŸ×u½š/Û}ö þöW?Ïl§M1ŸÎ1ÃÕ储M5/&Ÿ<ýðéùE%å“óÇïOþìG_|òþòÏ^\^üø<Z?yRüà‡OŠBo÷Çw·‡Ö÷6…>M&MÝ€ìƒSF¡ œ9Ũ¥H)¬Óõ²iÛ2)§m~/ÓÕ¶mŸ92§è‚R:B’&e¥AªNIH9wŸ§1;eŒ6 EŽì…ÎZƒ6R €,”6m?ÞÜþðí›!ÄÈ!AÒÊ”Es!PI*u%I¥¡P*¡9r#DU”eUmZÀD(D‚‚È»1Žãa{ºÛîßÜìÞÞv­ïzç|ÊÀ¤P(bÈ”3ÆÀ)pNì=§„(ß“ÞS ‘ÆÎfï30*-P$QTV8_Fƒ³ãaㆣOð½Ý0FTXTÒhP”ÅŸ®s”@däÀÁPi·?œbf&V…,ª*%Ž ˆ A&…<Ø!b6u‰DÚ( ÔÌŒ) ø¡YLIÉÈ)Kcî·û_ýò;×9U]K%»ÖµGï\¨MQõvwÜoN®9É»›³.Œ&CûöÔ ~<? ‘³ZIâ·÷›á8ÚÞ- çF)ÀHfÎ\˜b‡q e†”rÊ D‚ 3äDJ–B×£µƒ·dä¾Ý'À"¤LBj­ S0C !3“Ô.FÀÌœ‘S Ì$8C$…1'DÔÚh£”")B♳d”Ž#§€€#“$e„” B£5'F F )ùÄ13 ©cÎ(0qP’ªB…²ãhíèƒc¦œ¸4E¡ dGBJ¥åßå¸y´Z.g“©)ðxÚ[{ÿз½o»p:ŲœO‡¡kBmÊíæäF×Ìʘ¬#ZI&…’c@"U”RŠÁ¶­;öîà\çÆQ}óå»»ë=€ÐE9_®ö§ð·»âböøÙùÓêÇ‹g¦gH!|öéG»Ã)yp#IaÓøÝëÛý»oß}UÔÚ…îÝÍÛ鬴6 #+Ý!"Óÿòóÿøp¼îýh9ûîÛ¢Öõ|r¾Z]ýþË7ò}ç¼åÐíþõßü»7»·ß=\'΀DJú­åD.þðë×ù§ùç?ú‹—?íÚ(‚úüò£?ØN×7]xþäù‡Ï> ãà’?œ]?0“·3¤œU!$Y¨Ï¿øìÇ?ùáÓg—G×þòÕW6ú¯þðuÕTÇûœ3dB¤¾ £óIaT3­çëùwoÞÏJ«ÕYy5[=>»ä”cŽççﮯ۱A³I)lwísv½¼ T(¡{AtóæfèZ£¹=íÏg˜1:{@`-ªÛÛ;ëÆËË'ÉæÕl%ÉŒ½K˵ªëÆgO?˜ÕÓÏ>þT üìóÏ0‹éâæÝ&‘åðøÑcØžN¥.'Õ,gzwwóÁ‡/‚KSx—vû¡³®í „<u©¢sJï )3ÄLdFgc0¥Y/–«™",Œ",³(¥©4ŠH •*8S©K78‰1)!¹ˆ©ZM <¦―љ9û±?O›íðÍ›ÃÝ~´QZRˆRQÓ˜i£ %rˆBÊØù@ B"$€!#ÈcÈ!rŠRN‰s†“‡L…(+%ßï¶Ö½r|J=*…ºҥ‚Y|øi) K‰‹Ùt2ŸEˆ‘]‡ƒÈÓÙ\)+CB "tÁ…”V.ùzÖ„YJšÍ&Ã8d@iŒTrR¥Vu)¤ ¦\þæËwÓe¹œÏ×icBL$øìryì[B;ø¶ ÷·{B¡umLUÔúþ°kû¼ß½\L”¼·3f—$"`ƒí}(µæœ˜ñ}YLiÝÐbLœ2! H9Äè£TXª(UQ cH+R`Î9%%…RŠ!ÇdG7¤”‰¨ªK©¤P*ƒ¡eˆŒ £Gf"ä„"'†ˆ” ¢ ”3"ë yf–ÒȪÄB³$º¨ˆÊÕr.0F°DÍ€>¥Y 6ÆäE£bä¥@D$Éy3ÓBvíièûað‰ B°¼¤\JPJ% !ñýÎ2K’DQ–EQÔMUf6i´2ˆXUºÒR!²ÒJI]UÕz½üðùÕ³'ëóõô“Ÿ]œÍDZ}÷ö&Ø@˜!΀L]TU1i&6DBY@Ìvû6 lDí×Tu1º €(@öÐ;ìà Svý©ízçCHè²x8Ø_þú¶OòW¿¿þ뿹iøg?ùéÿOþépßýäÓú^ü×ÿàŸ}ù›on¯ïÏׯ!ÄD›ÍæÔo›Yµ=ív7w›w›íæâüÑÕù‡lû£*€fÓuŽùÔŽÍtúoþã¿ 8.׫—OŸ>~þìÙÙÐw«ùJRÕL×£OwûÍ~þ›ÿü˯~¹k·~°°©›CwJ4e#³ž–‹ùleʪ‡ßýî7÷Û×›ñöÕÍíï¿{ýv÷Ý`»Íþ…ŒÇÓýnsj;$*ËÚ;_FÕCq=_4EýlýâïÿøïÿÑg?þßü7ÿô{?øã?øüÍëׇn[W¥QMˆ(•RZRw§Ñúü°ÝÛ¾ïCðüøò1B¼¾þv³ß¶n(*™!fˆ>Y¡(¦¤´œM—íɦ˜ð=Îúœ`Ú,Œ¤ärð1ûnÜìwBðöt—Ä8¦ö·_ýênwst‡!ß×slO»`ý}ï›/_çúáT×õûÛUU˜o¿úFsûð°;lßݾ]®ÎNm¸¹=îÃ8úå|ƒ­Jœ›ÔÓ ¼Ýï¥QÍ´B‘lt.ºB£å÷?ùÁæ®m{;™VU£ -UQšÞùÃi8´ÃõýÝÅ㳜»ùTçäö‡m=3Æ„¦”…Ac ,JâÄÙk¥)dÜÀ‘“ç,ŒAÉBåÂ`¡QH ï;P™'Í€Rö™“ó‘1ùè3 T…bD€¬ˆ†¡ÆÃØ;Nª‡“ëY æ 0@dÇaw²7[¿é=h•€sH ¥©´’‚C‚ŒB™ÊˆBi$Ì9£@… ÀSNüžpœÄÀÀÄA°”ąĺҀ!¸}.t™2 ̤&]JFÈ)sȘ„m½ø'ÿͺ‘c„”Y ÞFç£gŽ1 B‰Íþ8 3+E €æ«å|=„˜²É YœZKª¨š’É%îS ˜åXV5Šxv1­£DXL'ŠÄr={öü ä<=xRÈÉr¡S”‰ÓÝýfè#‚aÄÕz¢T.Ke¤©Í$ù 5U‹pö¥ÑUY3Òi­ Çn¸ßí„Rœ³ÒZi#+!£·B0C.+•yOÅÂxo@’¤9'AXÍÀ‘“Ô¤”LчàCˆÎÅÑÚ˜Bˆ>z—cfFb1ølm>CfHÄ)cŠWЦËzFœS´)ù÷^ïà‚$%‰¼³Z ä䣋3#¢à )‡÷©UŽHY0˜’Ѳ,Œ’ïÂhÑ4E¡)¥RN %¤@ác™! ÌB""03CÌ‘(Rºèa )ÅB´É…à0¥bŠ ˜1‹!8.ŠºjfóÙ”C.Ä"'ܰ¨kší~Œc5-U)<»™PeÕLšW߽Π—‹G}¿ÜVjTF)Ù€ÐÃ8|ýõ›CëMýèÍõatYËÉ£³ó4¦»kÿ£ïÿÿöüõ÷ýìÓ'?úì“~öÙžx)±)'ZH2BŽ2f”€Cf”æý 3H)8 €I„‰³ª„¬‚®ÀTz ÖÆŒJîú}жBÊ +3{Ø´¯ß·§÷ANʳP(DΙPb–šH°O1"RÈ0'ÀsΘ˜!gàŒP‚ÒTÕ¢(0yç8@ôCdd„Ìœ“gH"ÅD Ù{d`¦àSf!þ‹¿w%èýn¤R!Äœ9¥$„(Bâ ÒyØm[Èb½ZÛQ>;›—F*É…£r¶˜A)µ’Ò>;/kS’”Jéà“ï=DYªZË‚½}÷XÖÓɱ="Êœ‰ÑŒ ÂT77;£j bZ³©YœÕÓiYcŒ©›fý袙T‹éDdFÌ9BF)ÖFªº4R¢ˆÄv4jI$‘¤)Äi=1ºPJ1T…TŠÖBJ*´VRÀ{ÿ*bN9'&¥´I@)¿/½JD]”µV&Nž%TaÌûrÎ#”²°£!å˜|ï†Ác2†-HÅàsò rBæœSmte$¤3G.f¥³¦á"§,“ÞúSŠY«BK¥¥R0a&,›‰(´(™0!U­’š3Ž£c½RÂySòÁç˲4J1ä|Ê)%è»pÛîïÇW¯nï·»Î:ÓÌÚ¡? §}çû(Ò`‡œ“w‘ÎV«¢„çWE¹ß³ùÚ% ÖYçGú.Z›KÓ v|}ýÖÇ‚ïÆ¾†SïÅv¿mÚ6»ýæÅÓ…)û»/6wí°ûöþ[{s×_o»‡Wß½þÝ«›˜Èº8PÊŽ䜄)ËQ:å|ñèb†B¾Ï¿úÅR·÷Û 1¿xö3^ž]õíQЍHMmßÍóín#‘üè’K…*…Ö ¼ß|póùD &Öº`è²…·i1‘8q#"k¥ŒÖ*¦™aìGd!IǘI)1+%„ÒBé’„"ÌFƒ6ÌÂcéËY.+®gº(¥Q2e8¹°†½wmœsÊ€(ÑJaSei1'Œýè¼ÏÀB  @‘Ò{" Â{‹ %…Ò¢(…®¨œ1$Â2³@ÊRcÊ>g†L,%æ”c@`‘³ R`ÿä¿ýÌcYz¯°J)2 ]„œI‰Á¹q ÖsïbYT];m¾ž…Ôï9;©Q**+#ãñ4ì] R*%TY”()¡Œ.ª"Ĉh¼mÛÖÕ“ÚTr»¿÷ÑŽ]?†v pê_¿y8õ2ÏMÓ(%ó¤QºÁûÝÝè@ˆ):¼³–ù½t%ÍgÕ¼™LMqµXTZf)cŒJʦ)„̤$)­µ!+­•”Ñ{-…DR¨H‘á½é8øBâ ïßúEŽH¤b 9saJ!Pi2’‡$‘$’’*¾OlŠœ0ú€U¡¥Ôï#žÈÚº4:782'f1…˜™9Æ`C°lÌ’€ˆ€‰ FïR¤”Ží±0…Ú;¯¥æRH¥II%Qbgœ$É"'­ )åœR n…’uÓ„B°9Ç””eU+UJ…Ì!gÄJ+BH ²VØÛÑzy1¿{xw·½),¦TÍê¯^ÝÜ^Ÿ.Ö/‚ÏÑÑi?Fï ­&Ó:€Ë„ÞGtÞ:çʲ<N‚ RÓ7oŠjòöú^ë)‘É 3E®«Á©?ÿÿíbõô~ø'Ÿ}ñÅÕó—ñ÷ÿkS,¾úêµݼ®ÿæ?þõi»Ó*Ùo^ÿþ»ë7mï$êR˺4QKEÀFé¾yRV—gçJâ¿ùë¿:ºNÙÚ¾“ŠË²N!K–qsß6Õ<§|sóÎê7¯¾^]>zöüédR÷}ký(•^ÎVÏÏ_üèÃÅ“rõäçý7Ó¦‘¬›Ñº¨” aÌ<0Œ~£›Í©=I!rH©ÏçÞ¥»ÍŠP^^>­³i0¥ìº}LãÕÕåvûn»{»=ÜíŽÛI‘òPšüáË—ûíñáá!¥þÅëªNgÅåå¼ï[¥T?ØÃ©•Z†ä†ql«Ë‚‰snšª*Kˆ)Z$ReQ;vB$HÁ3ð8ô¦Ô?þñèÍ»ë1xV9b˜Ì&R)ȸßî»®•RÄäËBo7»'WÏßݽ½ß½ce# ›ý;2Aq¶(«JßmîÏÏ'/>8ûð£ÇJò`]ˆˆ §<Ÿ79e`ŒÎëž~ñ¬2Jæ‰Ç”Fk­ë„ÀÍvÛ Îù”’cŽãЀR…DM@Á»Æœƒ.DæˆÀJ½xPPLAj@‘Hd†H„BH”$0j u¡êR•*&BÕ8YÉË'õù…^.gJK!åbº\Mç…)¥ œ‘$ÒZ  D!²I`ÖBT¢‚@dir3•u-KF€À÷bwJ…$3g΀™…È„9§,QSæì9:àDÉ£ø‹?_jI…’):ë†f>%©¤2œ³QrR×EŽáãÏ?’ÂËç ƒ°pƒ• &Ÿ išÉ|:]®VgÓfZ”i!$J)”$­HHÚí:øâñ*à 9\]¬.Ö“³e5_¨ûÍvwŠÖ *'RV аºš7K…”¦Ó¦ªKm$QöÎw]B" BŒÉ#&eDAìŽmðQA„ïý´ZIEÀ¨Pj \™ò½W$%"3J©CJ ™)gÈ!z¡¢$€R !Q–’bHD‰D,(&‚ÄÈ!ÅœrŽŒ$–eeD]"ÔJ1$¡ h´©´P¢SQ7Cô}p£™EtY¡%œ/&“B–FLšr2©«ªàœªª’¤&-ëB Á”="ú÷;À”F‡1m2ƘÒ()¥”BTº,U‘‰…À¹©êª¬¤”Z*BÊ)o"éïLY!g@”ùp:µ~ÁÛ˜ìêl‰RNg‹q´vt‚Ì0„Ýa¸»mwmY4„DÈÖ»˜„÷PU•1r}±–J‰S?êbÖ4s)Êýq<¶î~sô!Æ«õ•Òåã‹g½ø¼”«/û¦jΘôÃýþË_ÿáŸÿ?ÿ_¿úåÏWçË/¿ùÛÛÓï[ÿâÃGÛíۻ͛›û[#P¬'&e È!†ãi_V•yƒû‹ßüz:Lf³ËÄ].uÕžŽBòÝíwÝikžNÛ£“§®;žºÃf[½X̪²Y.ÎoÞÞ SVí©¿½½ÙnO§.ÖŬ= Éeö4©–Î%gy»ï˜©4MQ”}ßqo;‚Úc¯…9[¯}´mAȸ?ÝÄ<¤œHPïF¥uSUƘ§ÏׇÓ;†c{ u#Bì¼%©ÍÃv2ŸÌõà6võT7µ!ëõÅ|6WB¦Ì9ÕUY•†ý§Ÿÿº‡Åj±Ýož=¦ B,Œ‰1¢ f2éG‹Z½¹}[N B(T(úaIiVZTEuyöø“—Ÿow‡»íµw»‡w›Òâæö¶(ª¶ëÎWÓ?úáçÏÎí¡w­lò!'>&©e°ÉûTÖUÊɎ㣳µsÛ“PÚZ#Ýßm˪h»ñööt¿;êªDI6º¡wí>^¿éïïÃí}{ì,KâáprcpcÐJ+R»í±í,•Jy?dHw›ûnt¡„Æa<õ¶݈"¢ˆU%›Ò4…œr?X …B°œ9&öH)"dÎŒ(£‚"qÊ)x⤀ÄI©çµ9›×«•yòdþèbV—4©Ua„P©¬p:/ÊZ R²·›f™© ‘‘T¤ŠŲ̈n°,)aò9æ÷ô4äÈ%“¤ ¤ !¦ÈÀ¥ˆ9‘O DB£0, Ÿ~¦HéÀ9ä<ŽŽ3çÑŽB¨¾³77{ßÙ«óõz9k»Åd:öÝv»1eóæ«·‹fÑL溬‰ôrzVªf9]dÅD"å“v´ß¾~óÍ«w7·›Ãñ˜)¬ÏkEVƒ›êS>ì¶ÍDOgª˜È!¶²aj¢ž&P¶Z•\U…ÐTUSVÙ{ï†c¿?ŽÇÈ aÞ¨ Y[ë»ap9ÆÄJ(!±, A$¤ÑÚ¢ èC,•$ƒJj)’&y‹r$ésö!¹˜P¨œQ¢’(1ÇàBˆ1ab!¤"‰É qP´&$µ"¡ ‘@U”…1J¢€,ö»#0ìûÌÉ;‡È™#€KÃÉîNv F,TÊ<©k#央ŒA£¨4RKS0F¤ì½·)"’´Ue¤EQ¤˜ìheYTJI­% bÀ²¨ºnÜï!Ī.‡qˆ!I2n%fH> ¦\*U#Y;v}c„@Þa{K¬ˆ%73su¹Z/'O®.ËùÃÝî¸í\ïr Äò«oß¹!°|ò9E´! V»cdRTecÇðæí]?FUL,½××ÛÛ»}7†¦œÍ§+N „©L½\?}ùÁÇ·oße>ûâ‡Ï_¾|ôhùë_þ‡o¿ûÛÙYÅ89C3 Fë¶™ú1G{¸¸<ŸOk£`¹\=¾:qtÖå Œ2gáCº¸<óyÜaÚU­”P’—‹e]6n´)ÅóGgÝñ %Åz7Ran7›Î¹!äÄ\j¹˜2FÐ9‚Ýn¶ïªºÀ¯¾ùæawH,bJˆdmD2RÖΦ}×µÎKÁ²=tûãQ×å|µTJ]\<„œF­a1Ÿ\,Wóª9nï…L6Ø×oî÷íÐÃçßûþéØ*‘KYûÞíÎ.›Ë‹•Ö*ø ”L)|þÙË٪ʞ>½Ê!kÙÄ€Á³’U YR6Zsï9E2eY7"—¥AcLßuÓ¦¹¼¼œN§Þ;ÒðæîµËÃrÕ 02O¦Õ0´Ói9›T“ºªêÒÇ9Kc®ïo^¿ûFUä“?t§“sLp{ÿ°X­éؘDùÕ«Û×o·»mÇ c"ùØõc=©û¡UZŸwÇý8öŠ`R‡ÃI’FV³ÙÒèâÉÙ³O>¸º:—2-Î¥q½Zÿþ7¯¿üÃýf×_\._¾X½|±Üoe¡ºa|{½a¥ï7ö·¿½Þœu°ÙûÞS6Umí8mtÌ6/K­ +…LœGïlJ>ýÝyd’€“R$€EfÌ Ë™ŠzŒÂE`f …t1 Y0i’"³$$"©´”(e®*9™èÌ®læ\T¦¨PD‘3d¢$µ¬Ù”RbàÄyR7"eò1ù”ÐBÊÌÌB’’‚„H̉³  0 kƒu-Ä?\ ëNVM v÷=±\ÌWëõ£«GÊèÝf—­¯„( ýúú> ˜Ï&“¢¸¸¸¬š²*q>ŽÝé°ëv›ÍÍýÍÝÝö´ÛîNÀ…1z:­/¯Î‹FI‘fªø`õäb}ѺÞˤ*3XWTòéÕÙ‹§ç}pþüÙâù³ù“õüƒ‹³U]VZ´§6XÀ‘£.UY•€„™…ÊŒ!FóÿŸ9´¥!G%É£K– De4"fF*ä˜RÖZ?X7:\ˆÞçL •@à”Ø“ÀYõ¿DR×Umˆ y$`ˆZ AäB´1ŽÁÅ£? ì‚Jû!nÊÔÚA•ÌLE’”(çµiŠŒ˜cªŠJ ™Gä4Žc7!€ä½³£UB+¡²Q’Âèïo„”‰YÈ"$)k¥RpºP‹éQj&YÕSïƒwP0—Ué‚wÁ1fD"ÃØŽc'-狺(!¢Æ'\ FÉI]L*3)d:öƒ? îîþáÛ77ÇS&®mç÷Çñpò}Ÿ ²Ä¢žÔ.·åT–SS˜Tͬ™"ë¡õvˆJ5ÎcŠÐ÷ãnw<õÃæp2¨‰ÑŽ¡2 7 ¦œbÇÄÉÍœ\tBi˜ºSËÉÁ’l#$P¤ºî´k·HÅ`á«ëw×ït}tõ›/Î0êŠÆh'Óf9›5eyj[`1 £Òty±–€.tC:[^Ø.î7{)Dð®=˜s3› ÞÚ®íÇ–!Å€Åz}v:LaÚ®}|õ¸*릚L§óB›yY ÎeY¤}´6öZ‹RZ@¬«FJs8`R×ã°3Fôý¸Ý·ƒOý´Vëe»o7ÛãõMû‡?lîîûÓiô!N& `²~È?úðƒqh«ôf·Ì…ZÀË—/_¿Ù<{úÄÛRòC@–“zùÍ×߆”Ǻ...}òÑçò“Ÿ]-/Ÿ¬ç UÌ õáÓ'WçZ‹ÀñÐö UNœç«úÙó—M=«Œ¸X×e­”¤BÊ”|Ž%J ¢)JÎ)§èâ€Ë¢lJUPD¡Jæ(!³a]îÆ$u,:ËŒ )&N‰sŠ˜=Øl nÎûÑZk=°H)dÜý8Ú0ÊÑf *«’SÈFƈ¦&­QçY&ÖÉÂØÙà3‚ô6]² ÄHHÎ9Šˆø=€ Ijƒu%JmÄßû“+Ni6ŸbˆxØ÷…2IftF)qèíØÇª\\_?Q,f“Â`YVg‹‹gWϵ4r¾X¦Î.æoî¾ë¢E)‡±- ÈÁHÉ9Ç<2w}÷°»“¥ÔuQfR™±©f«fq>[QˆÒµ.Rˆˆ™0sÎ)Åœr&ïSŠP5¦˜¥,C@@™8ûè²óMQ(%¥ZQ¡t¡4 ±)d›d˜,{©IZ )KÉ€A „œ æÄ€™…Ö¥Ê -<]?«Õ„#E~¤èe}Â舢€”vûãn¬ë™ ¾;! g´,ë‚ENræÈ˜CÒZ×uÉÌRʪ*VU¡Æ¡›Í§³I-)+! ]pFc $„”RZ3ƒ³#Ê纜CÞ[ï]rÞ‡£¥`3Ng cBÈÃØ%öïf!gü8Ų́MCJE¡¥”Æ”“imTV**ÍRáàÆÓЫ¢šL×§ƒ“P¸Ž·ötð»Ý˜“JœçÀÑ4¸<ÓÓ%­/¦CoÛž²Ê‘vw§Jν¶-'_Ø&ÍZBa°Tª~þÁG.¤>þ"eñôñó/¾øcþòw¿v£»w÷Ý«¯Ÿ^^}ôìéþáæ·¿ûò~sˆ®oïvè}Øïìngû.µ­“¨J©œKΧÃáXh}1›|ïÃOê¢Èēռ¬¦ãèþîB ¥µýÐe„²)I*RæÕÛw_~}Óön¶ªú³ï¯ÎL5Å¢”ˆ¤µiûŽ·wo¿»»~{¸­Vå|¦– þðO^|p™(@!÷CÛ ÖÆ½/LI2ç”m?,êúåÕÕ´©Y¤é´®ý(¥) s÷p;Xw{¿¹ßœbÌ Y`Z-g÷›ÛÃéXÔgƒ³áxìc¤¡®'„R™š¤G'ˆ˜s>g‚ïú“PPT*0ĶïXŠë‡‡º®èthµÔÓÉ„ÙO'µ‘ï39û°yF·ß²söp:´Ý8¸”Yë À[o‡^ T ힺ7ûvtÑŽž!K¦“òêѳë»þ›W·ûý°?tu59»\îûù|c–Bç½s@òþîa}Öh-ìªzy}»Š~ö“¿xx·­ëºž6í_¿ýúì¼1…$Äõú¢ß÷*‰?ÿÉϾÿÑŸ<ûxVž?ú“õìÅî¡ë»Ó|ÞÔU=iÊóõär5¹\Ï*]BLM]ÌçÕdRhÄZjð (Ù(QKSTÎÙ(Y © 4f‰)BNs )ø”¾}{×õ!£ L@’(j‘ )M•Ú”RT`“wÑ ɈLDD¨”dŒÎ¥àŒÈ¥dòG‚¨ÐB ,„¬¤™Â!)ź?Ž}m„Œ$8 …È1"d,¤sÈÌ$¤RV¥–$Å_þÃç“yÄ™“uNk£ÕZŸ/{ï]NÙ‡Œd¬K›mûøê±s'c0„˜_û.'ØÜoÎW«á´ŸLÔòÑìñó«³Õ‚ Í狱9Q…Rúé“«JÉy]i)¥–6%&fETHUY*!rðV̘HI¡TY59)(ÅŒ(uQ RFZDÁÀ1y„ÜT…ÖªÐZqàº()óØwJ’B":7J…“ÞÇèCä  d@8EYJD !" Ì’²–Ùª½ÛqsèÚ‡!,¦óé:'öÎ0 Iº(DdC¦BÖóŠ eÊ(ɧÀœ• ŒœgóYÎAp"Æà"f‡!&'€KSi© $ŒÑ !´)È{‡@¦("³6†8x}–$ © ­Š²&IFªÊ˜ºÐ¤•òn̸P¦ª.„6‘F”!§Àœ™€%ÌÒˆÑù®·íqH1V…ñÁJ“AYÇøêú¿xeG7:w¿íw'›˜“*r1ÑÅD_>Y|ú½¦,¿{ýÝó'WÓÚœŽ;‰Uwˆ•X6y¿á¶ .Òâìñtù¤™]Nëæòâr·Ý?yü,Æ|:‹ùÙíÃÛÁ^3Ù/¿ýz?öÿÿ÷ÿè2o÷ûþä/ΟԦ™4“àü›7×.pÜ÷N˜M&"Óz}¶ÙÝÏ—U×ï§Ó ©«Ýþ°;ì|v‡ã~è»Ò˜ÒTŠÊÃé” N—SQªn÷§a»s#Í·x{<Ø«GW—g Û×ëeQ‰®ßõC‹Vˉ)`63guµjÊçÏ¿øøÃSÛ—fryö8öñã>õÈÇÓ³ˆ197^®ÏSàÒ4¥)í8zò 8ƾÒTh•HäfbRö§Ó$ùº”e¥ÛöX](™†Áç3@`æÓ©¬ÛîÖ‡œhì#¡i&ÓÁŽ ä\8?¿â¬ m”Ð!$©J;¦aðÀ44ãØÎ¦å|½ )#©ÝY×1áöxz{÷€RZ7v]—ë­¥† ÞG?›O3‡I£‹JI­‡S?ÆÍ¶+ŠúñÕ#燪.VËGÑ‹·¯ß̦…6Pjñ½Ï?¹\­Oû]YTCïc€¢€ËÇ!ñø³?û¤™Hf”¢î:wþèlèû^~¸yx˜Íæ»íÞ=:/¥î{;›Ìƒw››Ãi{ùèéÅÙÓÑÆ³Õż¹yr:„œŒV¢)̬ª+Q ƒÅ|9…0ZןúÓ©&“I]iI—PJJBk]ogF«È.¼Í>rÒSï“tê,Šb»ÿðêZW Rep‘”R묟Ÿ½\7O®è½V—Ré`'@R*!9D'„$DA 0kUÁˆ£LÌ <ˆ¨µRšŠB¼ïø £·.$f•Ì…Sj]`ŒPê}¶™eÌb”1"b!þá?zÒ;…ÆGv1JõÄ&@È )ÓápÚï TÅùùÓ©6‹E}~¾,‹YRËÕEQN¦³5’¼½»ûæ›ßßÝ^k-9{­d¡K²6Õz=KÁÝßß»AÈÙ¢.hj“H¡ë èZ¨R’@gGÛ[ˆÀ€Á³RFk“8æK¥ #•"­•ªk“³Z!!EÙÔ#Íb:iÊJD$À¦q Îå#p"fŒ1" Ê,r~ >&ë’wèFÈ^pŒïcƒk{Î$©¦UQk%¨oû·7·ß]¿F˜Ê¤˜¥ÐÀL(¦“¦*ÿ®!Œ!¸”“õ™$«Õtùäâ*ôN¢ˆ.Õ¦J>’¶KŠ‹³Õj±h€3iYpfΑ„Œ BH1äŒ@.䓳N*I’¬‘ÉÆ|úÖÚ~a,S¨Œ®ÊRy-¸ÒBÖU©4R꺚fªd…BÛ”2 fÌÀCpƒ÷)s!‹Å|²ÛÞo7›÷&ínpÖòõÛíq?h£•R’ðl©ž>®./ªÇ—õåå¬ïãp,ŠôüÅ対ü÷¹H¢’õ¤~´}Hß½9Í&çUQ=ûè“@üñç/_¿ýÃh÷£;N7_}óÛÉ´:žö19"þý׿yd§óų§3ÓŸþìOIäŸþôÇœÃï¿úòÛÛ7xûjÛ¶ÍdVšJdüüÅ'ÿìÿÓ¿ø£¿÷é‹u¤Ãý†sš/óßüæRÓz= qxùü)$žM«é¤L‰_¼ø¨¬KB®taÇ®m»Ãé¨K\­'oï÷>¢*ªîØ—˜Ñ E% b^¬ö»=Zë]?*]÷C÷Ýë·ûMï½ËÁ}öñ“?XùtÚl6d­,òúѬ,š¾ëbòZà ™‡þdJùøùyNî'?üRàÛÛ›ºªÏÎ.ºq‚w™ß¿×©ïZÆ<™×ï‡à²©»±o¦@ÀÛÛëóó‹is&Ag€Þ›Ýž¤&`- )Å|^ÖÝÔ*GÕõ©ûÑö1ÐwßÝtC}ßAB-‹”rÎ\•åt:aF!LN™ˆ9çý¾}Øœ6]ׇùÉÓ§‡ö$•>?»œÏçß¾þn21çë‹WßÜ@w·Óùz»9v}»\5º”»ý&¥œ§ój½š]¿½)TݺÈç³É´æÝnßõ]YTÇc« £ åý‚#ÁŸ~üá£õâlq¦DI,&Õì|õ„°ÙŸ¼D5žìñ`'Ó™!™Ø†qômçÊ¢¨« ¨†~̹ÐFg“èœÜoÓqŸÚƒÏIZŸ¬ D*ØÄT>l‡ýÑ3ÊÊ4† Ba*-ÌÃÝæÍ»×™SLá½…„“@V9 ÁÄD …ªŠ†À,„VuSœM_-ÏV“¦‘M%Η“Å´ZÍjœ! qð£„.:™« …a UÖI£ES‰Õ¢™ÏLiPJDLŒ8ƒ’*¥(>úLîvIzhÇS޾ªKUʦ©“ ñöv·}èR’Ô©=Ùpª'’·C׆ñhœ$ØE¬ÏkŽä|òcö.ŽƒÍ’Çr93ä,bà“–F¢©Ê¦GïcŠÙÛà\Tºh¦óœ€3JRcïJbÒÒ £"çltA¤¢Ï•iÜïn6Ö†»û‡›Ûí]´^"i­µ4ÂyÚ dR‘"æ]Jñ}%Ðä"§ÑÅ”ÑÇÈÛã1#å,CbÊGªœvý!³ÑŽ…FaÖª@P~䮵]Û¡ ɧ”8Ge…€)&ïݘدÏÎfóåt¶>¶žD•³¨Êúâ|qy6{|6ý{ôé÷_žôxþÑó³çO–<žòlöG?¼üâóÕj-.οùù…Ëö@ÿî_ýÎZSLÖEQ)Y¦¤ž={ñÁ³rLÓºrc[•F+‹B  ^©¸ÝÝs¢¦º Ne*Cã°ûúõï~ûí—¯î®_ßÞìÚ~ô¹*&ëåùf¿k¦ËÍíñîí¡.…)øìòbs8„ä‹i‘²­+rH>I¡Û¾%E$tßu›‡}ßyÈ ‰3!ÉõriHÝ^?´ýц>²_¯×¹ïgë9%°‡xÚ ʘH— 0çN‡“Kau¹Ü·§ã©:ëe•?üðül]ðâ ;ÄÃl]þýÏÚÝÎÛ¼£ C6öÃÉçq¶¨æíÝÆVk}ºbR¯ÎÏ®ïî®ïv1‹ãá9R•¦lªz2iʲHÖºzRµmKµ6ͤΉÕ¯~ñëª)t¡„Ò1²RÚ§«ËÕåÙzìFÀØãÐw9{ØÞŸvÛvCÛ ˆÈ )q?:”9S)$0KmºÞOÝÍí¾##)-wÛcLéââÊ»X—“åj®~õêÚ¹|<½µ  ¦ï}ï{§ãh­w6wm‡xs½ÛîmȧMiíÑûûo_…œÇSat>Ä —5)‘/–ÚÓðöæ›Áž€ti*%M]ÕŒdÊj½¾üìà ^ÎçÏ…lˆÕ¬®£ïsÎU1íú!E'‰Ë¢¨ª©–2Æ8Œ¾ëCw Ég5ø$µ©›’03°µ)záG|¸?F’rR\<»8;_*ÛM;ºdCŽ)¡Ä Ù—ÈyÞûÍá0†€‚bŒ¤DSÖ)#$ $ŽU¥g“²®h9WëyqqV/f97RFQ”È2³bYêÌIJ@B BAˆœ‰¤„E£ B‘‘ JA4«M©d$ñgÿéíÍ~Ò¬ÇÎ妳I5ç—sS*RÁïöGïishïN;O£,sU«Ãñ€$Qa3+‘¢i´û”Úœ;#ò¼)“zì[­4 0…* î÷7ThQJ2¢޳¦Hè2³PeÛ9ëÂ8:ëÇ÷ŸGÊ\–%HAUeÊÒ0:`)¦˜”49³H}²Î9VJåí8 ”À4Ú1åsɇBp.†Á¹˜ª¤r‚`Óåúñ“Ëç÷7›œˆ¬Ù§€Ä€ 021)–a (Eß!pocÛ¹°,ªÒ”gõ|UÍ(Žpyq•B"”ÑåèùîaCΩï;ÁÂZÏL©˜OŸ\ftÕ¼D‰™sŒÙ¯¥’BåH9sö9q @™!¦ì}ŠŒtjmŠŒ|Ì9¡³QJãÆPjS5›TDYJ ½wÁ…¡÷‘} nT SJ‰C„¡÷{41“/UY)51Zc´ZŠ¢0!%"ÝõîßýÇ_nwÝf3¦PÐçg«Yuu¾xt¶ˆ„™SèÛƒòÑrÖB)¶®¿½{0¢TßÜœfËÅgŸ|NÛ‡Ñ[”4ôñîawhO§¡ua|ñâã²*îw׳YÕžN³r’£*ÌY©¥Fu=»¹}Ó‡ÍÝîõׯ_Ýnw]ï}H0Øqß¹¬ÍwßãñíÃÛëíëÃp:Ž ü0›Õ1ZFX­ÎÞÞ½Õ¦ˆž¥(¤ÒÇöáéÓ‹Jd à۾͈À¢RX*8[W³©Z]4Í\é’›‰ÖZù!¤¤0E£ ¹, äÌmÛvCûøÉÕÃÃmf7™Êj&ϯ榖£bލrYÓ|VF×f%ql;EÒhSLôê|ÖLŒ1rtöñã+ܾ=&HJ£ Œø^ …"!…Î2SJB syvmØ>< Ô’Ht§þâì²,ë~è¥ýÐŇÓn·lÏ%áö°ë½s™Ÿ?{²šM$c{îï¶÷‡]À‚‘ rÊ‚bæà½B]0¦BTu#¤Ê€‚ÏñÔw‹Å¼®j;¸õÙÂÚ®Pbs÷p|˜/—ß¾~Ïž?{¸»àªÖBêÄ»·÷ã¤4™®W“õùrßÜã«eŠ~¹X¿þî¶ë-JJø}ǘVËÙ´ªn¯ï~óÕ—ºQ(èÙÓ*]¥ ÁGÛÔe¥LiêédÁYhÙLf«±SôÖƒÆÐSÎËÉlìú˜beʺ¨•0$¥,Ätjf³šST2ÍçJ•!“Þã»›ãõöˆu1_-¼÷ÃàBä_þúË]{œLK£IK‘sïr߇í®ûÝï^>6eÃ!_ß>$”Á;)…!°%‘…ÈR2@°C|èÆÎ'OŠMõTÕ3›×“YaJžNU©EU(A”˜µ¡º¤Ê(%€cæÑº¡w9QÔw!G” ŒAÀ „jœKüpÚ0rÅc<-/ê”\wêJ-•2ËÅê|½xôx~þ´™¯•”‘©¨*LSÔU)]Ó˜”|QHF— °DTj>›“Æä¢Fšº)1£F#€‚Ï9‚ RRÉfV#‰à#g±X¡ ¡4‘@¡Pb`„LÌIÖº&’‡Ã ‰´6!£œÆÜeô!ÛŒ!f?rðIªIÑLe8æàBŒ™»SðÁǘ3$,d©Ðø1iQÉ,ÇÓx:öR µ)q )á0XBmÛ1ÇܻæÛnNΧ”¼Þ†àc.ëb¾˜v@ÁU]Fo릨§¥ªÊýÀ"fŠÊH4F/•Œ18k‰ÒÔU]'Ž6Xç½³>%p!!º”\Š Ø+–JWª€ÓºQˆM©ÃØ[Û“¢¢E9&ãC 3$’b:Ÿ‡ä¤„º®b`lÇä¼õ!gHÛîÍëÛ®µBˆÅbªT‚J,Ûã1 C»iß~sÿûßÞ|õ»‡ßüíÃ/ñ¶ž\üí¯^YÒB‰Éböîv»y‹ôùÏ(Ân³ÿäÓïÛöìü|¾\L糫ÇW—gE)3úöô`$<ìßÝܽYÎç`óžk¬½Ï„ª,kÚ¹>úð¯þÅ¿ùåo~¹k÷£÷>dçBYš¦R/WÏ_¤¶ÝI…Ož]”SV:ßÜn´i§S 1†ôøÉS*¡p9™bæä# ÌÌ1§X¦)ËZÖrÝÌX`5)d @£ÒIÈDÙÏšZŽm],¢ó³f"Aõ½eR‡}â”R˜-–Jª‹óµQ $/çõ´)B!亮擦$Ò,†ÓÀ,.Î/çó£„jVÖ“eßæÍÃ1å ‹i½;í'ó©íÇý®ÍY0P×óùÚÛ(•ʘHdÆÁúœ8û¤üè†1æÈ…*$‘ðãØ4œǎ§=!¯ç‹qFH9Å‚DÌa°C×]<š}øÉÅbYˆx3iYÔE³Ù=˜F*>Œë³µVZ"d(U•K£¼ ĪëÝ0øÉ¤û–0åäWËõ«7×1«Ãa »ÍÉGÿ¾òš9!0‘ð>vm¿^­ó%bñÍ«wWž<½º4’ÖçëH”S^L뿨 ó“ïýt9½øé?ýÓ/þ|aÖå{5`]WÃ8¤”Ñ9qþ(nÌbÖœmïUU—¥YÎæû‡Ãa ŒÂ”EQw}jGQJY+SEˆChm ß¾{xs»Ëë¦JÀÓ'çWW‹Ò†( TSýôÙÙźža»Ã AúÁƒlÈ@6{]—U5½»9v§¾·]1©Hh $"AD™‘Y² ”RcŒ® ³œT³º˜ÖÅrVMŠ‚°iªåb2ªÙ§ •…@ÌÁÇ”ØGBJ™(¥SJ™™™0JÅÀYüé?<{úlùâÅâé‹ùzmž]­ ÝéT—µQB&Á.4¥ÖˆÂr:;[Lž<^×µZ¯ÖM=«´ñnÐJat1!]fHŒÙEoÊr·=C"£tY²B*¤¨Ê m7«g„²ÆIUqònMS*áú>øp:¶9gB”4 Öú Œ‰<öã~ £,M`’BJ>»Ñ÷6Ž sBH!e‘dŸOÉc¿³îäS‚®™¤Ú‡8Ä@R—¦ÒRAH‚‰2F ‘Râ ¹ž–BÊSrY¡¢Ì$fÕž¬uñúþ–QÜÜl9S‚¸<›E°eSfÈóù¢ïûº©ÀG/´a’(H ÈÑ&Î!ël?Xf¡Hð{‡QÒHBšz¦$IUYf:ifu5)‹Õt:)Õ´QM%‘‚Àºžˆ¼KÇÀTŒ6îtrR)g]Šr&QGSIDêÚ1…„(ÆÎæ’¢Ê!$&Y .º“‹ýÛ/}¢ªš(¥GkÇq>½”rZ–ÍaÓþâç¸yp¯¯{©ËÕ£Y ØÕËÅÉÙ¯¾}[”‹'O>|¸oÿý¿þÖäþ»ö?týÙ_ü-'<ÿt=¿XÏ.>ýðóU=È÷›wLV¨”–´cEí²—’Hr®ËÕÙôüp÷òùúÿø“ÕbùÁ^ß¾a䲬ÖËÅåj±»7º>DŸ9£BßÄ„º ­™HªëÛ¡„Q’€ŒF™r†áÔ÷,U`½+§ÕàÚÉTW% î¡™Ò³Çgµ‘’³’älHYDO)£¸Ý·ßÝo¯6Õ¤ ~$I„Te°C¡q½lΖs-eðÙy&F#…`;ÁQŸN#³ìH)ÊþÐ7÷~è.Öç”ó¾ü2æ@R%J꘼.d3-‹B¶§Ž3ÚÑ !¤¢ÝéÁAWÕågŸ}þêÛïîö½BÒt6ïFwlkƒP2aŠ95“ÉéÔ“.2 笄L œ Æß[™pµ¨ž=¹,u¥¤vnðnd­uQ”Ày:›WUCs¾©&m—¬Ïmçö»>FX­V¶·mÛºc5-WóÅñø°Z6’¨*š·¯6Ã!HQ¦4™4Ö¹’’:çbÊ O‡–vûÎv¡ÑÓ_|â\J'õìg?úÙÓõsÌTÕÅî´É)®&ëYÑÌË…¦R•u×$å®mARŠ©(ÊÅl~Øï1fNfÊÓ) œ|óÝÃx:_†£ÍKŒ‚!³÷IªÒ”õt1Ïk­!³g e¥¥1fÈ"F.ŒY̦ÓI=-UŽž„·)„à9„è}°>0㤜vû¡"@žÍŠÕjÒ†c A($ ýÞoÌ1€BT(%1ÂØ»lÃÔ”” Rf9™­šé¼4µ¡ºÔBäº1‹y9«•)YD3pÈ@‘©½u,þÏÿ—?j ©VÆÌ§³I]æœf³iÓ”!x£,¥4<º*ÉŒ)p’E‘S®kSUZëbÚÌÀ{;½ÊÇÄ}Ž,¥RÊEÁ‘˜RŒeY¸àëÙÄFïR8M*[ï†qHœI*(”d"DBFöÎ{|°¬óƒÒÚTu7öžíúcH!0’Éî]²žèY9×QÒ˜ ÅÌ@>…Œ"ƒ@œ!fŸ!¢J)$ÈõdOfS¹™N•Òg ""ÈÁ9΂³èÚ£¤,Dš@àêl¦KÊÛ¾{<ž‰3#`Ê)B(* M…scÆTV£´Ñ„ˆý8"¢ ¡°¬µõsFX”Êh¥”’’bpœ¼À9‚DÑT•ÖRÊ,d)„Œ1Š¥ j’Ð…4&%ëÝ çí`O£¤ YKjÆ3)RNDXFGìX€A>…×o¶(‹Wo6£ƒœ±÷ôÕׯÛÞš²Z,—WO.¥Él3™”…)TÂÔúì³—ñòêûÿ·ÿëÿýÐÑÉÊß½ºy{óðê«W’èíõÍ¡ë"ÇÍöv9«–³¢0é°¿9XJî4vZi-™™‹Bål ­ïo¶‡Í8›=b äã“ùÓ/>øb8lÇ;,p2-ûã¶­*KF’ÒLšißµ§C¯´Ž'ó‰©äÍýíèÇ—/®8 ~ŒÍd6=´G©ê¦™Ÿ·»”¡sÞ:÷Á‹§Ù÷“Jh™rt‹ÉtÞL%ÉSÛv­•Tç¨R]ë^߸”MUZë3 ­kˆ\M“é¬;õ¦œÚ­n‹EYà¼Õ’œÏEUJ#»Á†D‹Å¢oÛ`]ßw‹óE‚Ä”æË¹ql`%@GÇJèÑ/?|¶}x@€Ä)R8{4»Xϵ–mwÊtQhm¼ Þ'Ž\¤BŽ.†ùáv_éFkÝÖT”:qbŠËESªëºe;†> 11³Öz>›»qpnÔJj)g³³qLçW§c{s»}÷nçƒÌ,šf2ØQæØŸf‹æÙóLJÓVÀŒ™~õ‡ÛÛ›ž1Æ¢RR#‡àcô—WgÑ/ž_¶‡>yˆ)†œëª–²v6ÿî¿Æ"¤8¶û`W×R`’á‡O^Ümîo7÷³érûpœNë=p¾º¸Úm¶9†¦©9qŒ©žÔ×7·O?QÊ\]>ŸÏŸ}üñÿð³?Ñ\Ý?tý˜J©*°®K˜"'ýét(ŠBuýÐÚAUôp8ôûcߎÞZ—¢·Cz¾ßž¥¤,£2rt¡·ÁFàÈ”™»q ™—gգŲd¤˜ sFH˜e¡ÊªVJÃècˆR+QÂyqßÚ¬b§Ãà,c¤Œë<&Ô$€Yєդ¬¦ua0U’¤¤Ì™3eÀEŒ*'!þ×ÿå³Õl}vvémTB{C` ™™BB2XÖ†sÔRIú;²BÎÜwƒ$ñ°Ü·!"§àõ^uòΦà€õ|jf ƒKcÌB*`€0eÊYâ{Š$¸àíh«ªÐZ…$¤‘Hä„!'Ji&UïÇŒ(¤âcˆ1³…Q%²àŒÑ%ïb Âpýòâã}¸»Ý‡1¦sN,uIŠ2„ ûíᓊ©mOEiÆq4Z]\œÍ¦SBâ’ JR–‡vdDa(Q\¬æBÉö4îw#3Ÿ_¬“@À)'"lH. ݈ÈûÓÎç‚–Ëg\-/ó‹³³G>rQ{Ÿ‘àÔT O^œ‡|Ü·›Ù|i‡8Ýè ãû…êé4¾}{ H9ãhýù£s$t£ÃDuˆ€B¹ÎVE}ÜŸÚÖ>lãh»Á¦Ée?¸cÛºC¦ðøé#$,Œ¹zô4ÈžÚÃOãpj[F`BS˜ÃþзƒÑ:ÆX•ep‘„æ$Ûîöv÷úíM7†n°EY½üðÃë›R•œMš¦,ª¦™±®fß¾z³ÙŒR«÷ ýª)­³$•éã^ôý&¸üp7ø@ue–³ÊŽãÃî°ë÷:<™L¾{óE^,'1†G.´T/Ÿ½üWÿö¯Pâr6× $‰¦jrˆZÊ2zëÖËUY)5¸>S,Œé]ßÚ¾÷®K¿ø›/þ˯¾~uóîzs³uΧœº¶s~Ô³zÞ4½³@Žb¿í{lýi!ăF:l÷wû»»Ý®A«Ó©‹MûC¿;Yê,¸žU±(3™4_u)!ÅîÔyŸlpãè2*&ÉDÎÚÓñ˜9—usêÂîèßÞl}ç1U“Š`–ɳcŒÙûœ˜€$IRÈSFë|ÈÉTªjd])%DΔÅÿé¿û“««'¿ÿúÕ©ëI(Ç1ú˜Cd¥JæŒ9÷Ƕ;öœ)…Ä Œ6…QUcylbäL9d‡)fEJ«A 8g@ RZqæa E¦ÐõCNÐ4Íû´"QU¡ŒD„ÃþÈ…@‘$Fä œr†L9ƒwŽb˜‚O1°µÑÚà\`!&”¶§›·×ƒÇè ³@”.F†¤„À~Ȫc×[d ©dIY"#2¦&UÅ9ÕeœÛº¸|ñäÉL/Ü!¿ùêô«_}ûõ«ëͦJÏ+úÔÙ*D®ªòOÿ芤ÿñõbh_}óÍgŸþ8Gé|,Šª)ëOž­Ö«º*ÚÓ>º~µ˜í{UÏÌl¹m€ùáîæÑjåÇÞz›…xþì¹V’ÛÖ1—BÍ3›±!âh#l·?uÿáoþãd6ص혌.½‹¶³J–åx²óÅr2ŸØqœÏVÖŽõ¤9;T7‹¦šgÂc|üä餙ÅÝ!q\÷âå)än{@2£õMÝ e-¥Âw7·‘ÁßÞE¸ÛíîvûÃ0nÚcRiµžIua¼rÎÞI¢Ð*xwùø‚ " މ‚M}ÜæÆÚ!äDu=ˆ…’·×׉ ãòlÝ45ˆ<Ø\lºÃÁöÞõ¾ŸÌªf®»¾Ë¨„6.„Ì\–õýÃöÔ[×¥ñäµ®ó…BBAƒ B˜ùü,:qj‡ÄƒÏ)ÎW“‹‹ÕlR7º±;´‚œ”Píþ4öýà 8›7E©WëÕ¤*€¨”$âcDŽ)ÝÝoNmj­Ä•–ʨûÍ®mý©ï&“úÉ£ËÚ”9¥þ4*2Wû®í†í÷¿÷ôxÜ™ª"ðûCO¢ˆ)§ÂH¹Û ‘ùåGOŒÆÛ»ÛË'—.ö‘CQUmË™iõ®½E’…˜Í!7´ùçV.VÓ…Clšz{kÇù¼ Û‡ ƒìbŽ—WWžÕõ¬=í›Ú<{úü?ý§_¾y{¿?Ç®½ÛnBÄ¡ó›í~2©ªRb†®BðÏ?Y–S×;çCïc7Z)¥Ö:{öÞÝŸîzç ’òCj¡øØ:RT2ùèj~qV×5,W…(RÓ˜²Ð™)$¦Ì ôíöè8•ÖRÅBˆÃ˜º.=ìÛ1x]ëzRb  iEÈ9‚Ъ "Ž9Øè–«õd2‘ZTU±˜4óªj eˆŸüyý»×_mÚ½‡8æèN‡SÛ1åÈ)E>:ïŒÑEa¤*2`¨ëZ‰º,'ZéèC ¡*K""Ò9rŽ9æä‚gÀ”“¤¥ÄÌFjÎÀ¤T"Š)òßI„’P)¥¼µ)$² ¥Ò¦J91¥G9æ8a D cLcžc¨‘¤uA ¡CH)¥" &ç²ô.fNr#äŒB¨˜¢–ZiM$€I’ÖBz;ðñØn¶Gçân³ëÝr±ˆÁ÷£=umdNƒóm;ÄȦª‹ºþæõw§v|óíÝíí©ýw×÷»as8uÝ(Pmïw9BHéÛ7ï®o÷mç÷»ÑöÖÙØw.:ö6õ½÷Ž cöÈ,%%N™1$\>¶ÎŽ9G”¤ý½ÍBu=É™s{ô) †$¢çq¶ )øI£g3=éÙLIsgÓÂ…!¿GšB®Ï§m{ùxäÖ릳‡ÁÛœ%'õÝ·û·ß^Ϧ¢œÈíɕӳýà§OÖOþ‡ÿÃÿñ/>˜ÕuSW/?ýìåËÿýÿî¿ßm6ó7¿ÿÕ/ß½þv×÷±iV‡±[_\~ñƒöùnïÚCŸSDRÊ'Ožw§Ñ9&,.ÏŸœÍ/ƒ«ùE)Ë?ýÉO*+öa6kŠ¢j»A@ ´ÔDÂû¼MœïËËéæ´;´]ו’)¥“OQ¼Õnmë½ !e ]Ú.ßÝ>Üß?TåT‰jC¦”r8[.–ͼ¢R[7»ƒÏžEÖJc–w»f9¯êB0 §ÜžønÓ¾½ÝÙ®žœMUÛîo¶!cÕ”~U†G«U\ߺÙtÞu]H>§PzZ–ÖÚí~‡9 Tjw<0'g‡Ýé¾÷§óËu3«ïwoµ,üß~{í|È›IÍ™K¥çuùôÑU%™i3iê*Åøð° ïÉ_1ˆ 3ƒ|ss»Z\LÌÒ`Ó;›9Eö£³Q¶}/$!ñr>1ÿ?–þkY×eIÏÃ2³ìg3Üôk®½¶ën hèP$!1B§#]†n@' FˆTH €Úìµ—›fÌ1Æ?~ó™ò•:˜¸…:¨ŒÊzßç‘jŽÉç+áZ2Õ4ƒQíéñ ðåËWD¤µÞnG«Í<Í©f—BAò!X-öc_cYfbê:c­´Æ~üåãÕþî‡>Üݾ>'cšoÞÞîzQÑÙN¶=>ŸŒ±Ì°ÎaYürεpÓÒ›·7ÉqE1¯Ëû·ï0óíæê›WïûþO«ÓÓs£õýÇOŸ>>üþ·¿uÓüÍËo{³Ë†qœ—E¡ùòtàyuçùâËr½¿êºqš–š¸m†àî?§‹7¶]—p<œSÌ›Í(… i§)“sÕÏõøìç9j«úξ}½LS¡*4]õ]§¥@RU _§³°&”X!o·cÛ4Ìâ|ñŸN§im7cE$C× ¤yY\ ÝØ*-Bq³’d´2B)eŠs%D. Q)PÄU Þ v?hñ/ÿÇWŒ=|ù«¿ùivÅZ=OK«UNÞHBBiŒÑ( €2c™/§bÍÅvÆv&°­EãЬ몭!#dCªÁÝuu7ø4Ì— ‚²ÑZƒ€Ì ¤U]òjÅ€Åט‹$0ÓeÛ dlU ‘§çµ3›Î VY¨Ð K=OÑGuxÊ~&‰Fk# o¯Í¸%Óz¥rήµ¦k»¯0T©”1¶iÛf0RømIÔ¶U* ´C³ÆùþéÃÙ¾ýîU?4ÆŒ«S ÷ƒ½Sb<<_>|yXœ†õäûþwËìÿßÿûÿï—/Òèï¾{÷áÃÇèøù7ÿ×_½ýî?þÛ?χûZ"@åÍfw{óúþááöúÅ|ºp./î^!Jõt9‘¡yy¾¬çnÓþøË—ù¼¿ÞÔBR®PI‚P®ðÏ÷ŸæpA„W/ÞœNgc Û^J-6›n3Í3H)È¡¼~ùâû?þ¡@¼½¾Ã,Vùøù»ß~{<>ïC¨÷÷ç%øa;®~ÝŽc£›m³mdKB¢B,á2¹š–¹ðî®yqÛ½¸1úÛ—¿ùõûÿï~ùðá¸ï7ñû?k• ŸR×Yatb6m·Ý_͓ێ»ÃéÂB­‹om{™.«wÛÍSóêõÝÐóå|sÛ½þrÿ¥ï†Û»»nhr£íÃÃ1e>OñáqZfßCJI)YR0·»MÛµF©ívó|<®nεÖ"ÿøý‡y9ÿÙŸü¶ø•„‹›×°ºi$j)©uN¡ÔÒ¶ýé|0ZYÛùX¦u™×u³Ý‡˜RŒ\K‰e:­—i]S9^–ÓùÒ6VPJ¸+¢D¸ºÞ(-¾8çÛFçÚÎU…âÝf nnîîÚ~¸¿÷sØn·Ó=?Å"P˜yq³KÛéRÓº.]ßoûÁ_ÖùtiŒÅŠD4 Ã` ¸ë®ÂR†¶/)OÏ',…SÚ_M£ûn¼ººÇr¹\ÎË|9ŸvÛn»Ý¬Þ}øtÿêý´åïýÉoþÛò_þ“ßÿÿøÝŸ¿yór¿Ýd‚+O‡%2Ž›]eö)-¡þøÓ!&9-išø2%$] –çSHYVóê—‹¯Ó¦9\¦s¬pY¼Ò]ò|^£ ^ȹ„˜À`7šëýØ5V‘Y&ç\ñ}üŠžà~+篾“ÆÝIѱéÀ+Y¡Vbʹ–ʈÜ#ÖZt-"xŸJ!)”†”ø—ÿúºµ’JR(´Ð1C×—F -iØuR MJ¬Hát>Åäžžæu Η•´šÜZ‰b.B(ç}©U®•Ð$Aé¶kz£IdïeÂ(.‹ïÚ–K )ÅœVç…TFµµ‚w!¤l•ê­N%È>…Åǘ1&L.çåÙ÷vˆ.ŽÃhˆTE¨è—ÄUp&ÎE¥À!$!)§B%)”‚ «ÖеbhÄÕnxy{ÛZ½N³ó„‚•–ƘÍvÜïÆN5½î‡fÈ)ÇJI‡nDÈ1%$ŒFjc´±jØw¨Ë曦ßôí›×W›Á©¤M£ë‹—//çã04ýØ‘ÀÛý Œý IÖTƒwáí‹×5æuZ+ï8.,Á®s›ÞÏ‹@$æB)|L¥žç%q9ΧfhÇq;Ÿçóóy³ßýôÓ÷üaÜôÏÓs Q¹Ùõ·×ûoß¿]üôü<ç\–y àv³Ýíw!ø›ýÍv{=4ÝË—wÞ;ïã‹»;¿>­Mçu±]»º …ùöW¿}>ÎçiÆê$¦iòXuÛß~ûÝ7ï^½}{uw½u{×7r ëO?=êÆ*Qàåö•ƒOQ¶ºéÕдž¾<>ÿôÃýØîšàxìFkÌår6öéé`õ8§W/ßUàÇççnØÞ\ßþüËçu)êt>Í.Ýߟ“X”@écY—´Ù ZÑ2­n]¿ýö¢Ì‰ŸžÆÍ€·/n]pãvÜn÷Ìüâf{uÝ_¿´çûÓ\;¡®‡AœÎ—¡ï´ÖDôüüt:?mFk¬ñ±,«÷ÞIF«C†:liM¬õ8]BŠÚkõÕÕ •ð>öý&ÅÚ¶íÍõF@‘ º¦3ZlwÍÕÕ^+Ír®“¿¬~yqõR£æšOï‚ÿÝïoÿÞŸÞ-ñ€’›Æ6­1Ĝ߽{Ñ7Í·ï~{:Î]o??|¼|D!6Ãæj·óêõrZ\t›q¼¶·7wÓe!)§åLº6º)!”àçu’ºB ýhµFäZÒ§c_ÜÞõÖ¼¼{ñêî®%ÝÜ\ÿúWòþåûëÝí´ú%,Û«6z†¡íjÂãÑ­KÔ²«•@NøéçËýSºõ¡¬sñ—Œ9q-\™åšs)I£¹<¯« >&¬xzr_΢¡Ý¾»ÁêNK»·ó´~y|t)g®Öʶk+WA´ÛŽ›±ë[« nvCÓö)ÅW¨œ™k­s!àZ˜„ÖJ!°Ô9•Dâ/ÿq_J•R–\ñz Æ¨œ2À"QhJb—\ålsž/íÐ ­Ú¡µ% « 1ÔR:Ûh!iÓ}÷ê½w‹Q‘¥¨’jÎÅ»t¹LÎ9E²„RrRøä”ÕMßhc¬Pïo^õȱÆÄ%¦âCN*ÉXà4Íçuõ9ÖRŒÔûí¾$X¦ ˲քZµ­m¹$­¨±ÆhXÛ¶5Z£À·ß¼:ž¾ ”è}‰9…²Nþ2;K­¢¬•Ö%4¦i”1BåTý×Ôž„Zr ùë .œRÌ\1Æ5÷A̵&Ã…˜‰k5Ö.>ضa(ˆ „¬•ö»ÖšcÒRé*Œ6BQ®9q&AnõËìšvX\LPŒµD $‘`ïçÝnˆÉõ›N"ABŠ®otk«T‹/10–*Bµ6>OÏÀÅ}9L?ýíGQz,ærò%‘À†„–”\sæXÒש‰)d¿¸”°&ÁIæ„_Ïièí~l^ܼx~Ê1tRwF¬,Qc éööNHûöO~û ûKo7w·¯ý«ïæur5û™ùÍë—É{¬<ÛO÷¡²ÏÙ¹°xçÒóä¿è†ŽçãívÌ~!Âm¿UŠPóù!ÕüîÍ»yzöqÇ!ùPbǾÖõí‹ñýéwŸ>üÈXcŠ«Þ×y^œ_§ù"м¼{aéšA$! …„Õ/ó²Ìç¥ošœüt>NÓi™Ï7WÛ’*TID7w·Çã±iÍóñÉXÀW[+DžC67÷Ÿ~p—|.—OŸ¾l6W)—Rèû?<œŸÃºxkZ"›RÝì¶mg\8»4Ɇ*¼Ɯ9¤r¾¸ÂøÓÏ6û«ùt<__õŒ¹@úÍï|^Çáæïþî‡íö°Ô­>Mƒúôé™P§œRª9AÍ™+EW””ZS? —ËñõëW×Ww­´°Ï¯^¾%hR@›mòe‰×i-)¾ÿæÍÕÕ¸øHñ•žccµU¤ˆJÊqñêíþ¦ë¬TÐ4f¹,¸RLeº, uÜõRPkÛœJðq™‚à̵<ŸžÏOß|óíét>_ަæyQB• >—%¹÷ŸÿäÏÞï¯Ìn?¾~}÷âvÿpÿ¨å¦Ñí4]^¿~EŒ÷Çà*ùáþó°jM¿ùÕo¸”ÿú¿ø¯ !èööqsÜl·€Ð Ýõþæó¿ØÖš®É%§³ çãÉJYץ|ÔBüñûœ~ùéoþîÿöññGâ°žÏÓåx™ˆ¥ÑŠ xúq—*ÜÞÝ !×5Äë:¿RB‰M#¥ÀëýFjZ},@,$4æ~.‡§åtž°ò<Ç/Sb|ñöÎJ³LkÉ…+|­y½sF #jŠ1l7›’òñðMÚÐ:{?G D j•B™ÆØmד€i»a(%ï¶ck[däÊË<…°ÆC‰.Æ\¸fèÔnlw>†¬µÚ캫ëMÛcšó¼:_s¤¶i-¥À:Ž5‚1qa®µHE›Ýø|<„˜k*6ûa§U“jœÜ’‘S)ƘZŠR° W’F6½e`£DÕ5mŒåp>¯>ÅÄë9£}½½ÆÊ‹[`Ìåk}#—ì¢+9­+rA`ççÆJ£…™cN9g¥ VH„"GŽ9Ý\ï J ÔÊ\_mPs–e-Îö’rg&.µT€~;¬ÙÅ’Qê\(ÄR¨è³F«ÖȆXË K©Ä‚3"k`}:Ló%—¬ÃB˦CüñŸ˜åyY–¸¢"XJ ‘g̹3¢G B‘K«•0ô­êx\Çë7û»›OŸ><<ܵÄu×´¿ùæ[føá§H’‰ÓÚŒžtÅÛAKSYΗEl†^"ž„_]Çoß¼|øòñí«W Šß½{3X-‰+¯!=£©¾<§Ù46äâ] Šw»[Míãý?Ü @©@7C)u]üãóÓn?l¶-ˆêSxóî[.p9^ž§ õÛï¾{>>·MÖyõK6jô^ Ã5 CßC¨%(¥ŸžO‡ËáÑ=>,ó쵡뛱Û%†½ŽyYý¹¦L>´B¼zy×ï›çã# ŽÏ…¹ÓÍýýC*°†iØÚ¦7Î…VmF»½ÿðÃyzvÁ½ûæÍöjóãÏ?˜ÆJ‰PSßšà˜¦i»í\ÓéqÜH2}7h¥û~3ÏËÿøW%2f:?Ýs=½ÿõë*é?ü§ïµ´»QßÞö]OÓz LãhF«ýzÑ’·½ÑT¡@²ÚžOçvhûM"ƒŠê|:ÍË,Mì9§~4Û«vY.¥!eNüôôh­í»F*ººÚŒƒþío¾­%I)s*Þ/D ÌÌÕù÷ÿä·C«b˜[º~“b¾¹Ù]ž/?ÿðP*L>쯮sJ9…Ù‡Þ^ ÿø'ÿìõõtÿùËۻw·o·¶ —ðåãÓwßþÚ(ùøå¾išœkÛ _žž‡Ý^hÕvíóåRµÑ‚¤zõ.¤p:Ÿ?ùðù釦­¤f–GÆÉÇÓt9ü§?ü‡ªRX³G¬ÃØum7ô[mÔí‹«~þâÏÿü›7o7Ã8/ç~Ð$KŒ¥m[­ùý·wZÒºF ‰\kçxu¹Ý´ÛÛAka4ì¯Û~ÐWã(±I±ÖÄ5Á<ïKJužç’ W<ÏsE¸ºÞ—R¤çyy<Ÿæ9p¡M7FrΫó¹2 ` a>»äK̹b­Pr L¼Ý_ÅXÄû¯^™®Ëˆp^WŸ"HaÚ¦o:M*”œá¦ï²÷ËùŒÌ1¬Ø_Sn”nõ>”RRôë: ‰üÕ<ž’ív¸ Î;/ˤ¤tólµR†]S)k-$’S-+*²Æ¶‰9–‚‚˜Q‘YSLÂ`»«áj ®¥¶“­"‰DøUÜÙ¨n´M'”ªZc©)¤JFZk«mLŠJ²Bf+_CŽ!uM_ R-9åP17qÑ1q­,¥ÖJ—œHrŒŽ™Á‚„Õ/¦3BÉòóé2­®[™ÓcVï…½n0Ä—WW²Ì^7J º­¡¢F­5¡H¡ a«p¹,µ@EÉ>ùyŸOóå,9%6›þñé©fN±” …i^¼¹k{£t.e‰qwwÍXsÊ$^ÝÚ4­jM.sF?.r’se^Òq ¹ Ÿy^Â2»é2×Z^½yqsµÙÃËÝõûwoAJra}ÿþ×\Ë«qûæåÐ5ù×ï_ý£?ý“FèyöKˆ‡ÇÏ/¯†_½º$ÿoÿëÿëÛïþdšÜ¦ÛŸÎ÷OÇj„mûÌX‰ÎëtvOßø«³Áå­éÛ¶ùòp¿»Þ›ÎfÈ‹÷‡çvhM«Ës¿ÝÜì¯ÏϧãaÙŒ·Ïóùàžîç§Ÿ¾|Î…K.!úq3pLéóã—Ëùüêå«W/î”$cín· !lwD¼º¾ûù§Ÿ˜ðùrÚÝÞ„ÚFõ½MÕŽ­ÑTkM±ÄH Bcyxúòôôüü|ùüéñêöæóÓgÙ¡ù4ÏÿéþBB½ÿöV(·¬Ëï~ûë°8Nþ|ñ“ÿí»ßëX —C×ê»Û=`G-(i•ïn¯Ù;÷ñ—Ù'¿ÌZ¢Qb]Ï…`B‘­•R kk…¦²Û ÛqŒ>ôvã<û´ˆ1lj*$âÆàí¶í#¨ÎáÜŒ‰sÀµolñYƒHÛ¡k$ìZ-¸´’JÔÊ)æRŠÖ†l£l+×éôéç @÷ãfÛ¥Óé¡mÅíms»3·Co•P¢BÍÁ—§ãòâå‹ÝîjPš™ãꦘIò!°K5ç¶ïRŽ‚Ä|YÚ¶ Î)¥CHÒH­ÅõÕõ‡÷U@ß›ãÃãrš•ÔÞ§”Ón»=Ï>ønÓ²¨É¥»«W¯o_ÕX¤ÐÞ¹ÍØ‡abˆ  2L—¹æl”¼Ún§óóíÍ/(éöz#%J£ÏŸ¦tÈ8Jë”~þåј],•k­Œõj¿ kâ(•”·ûáÝÕÕïÞ¼ë…zµßnF£xùêöúêj·n7o_Þjc_¼|Ñky9®9bI…³KÚFux> -wã°¶1”Õ%çóyž×?DÀ€IDAT§é|¾H•]†¦ë«W7-ër),b®kˆËê¤jÒþ c*¹¤Â¬*S•ˆ v»þúÅ;ŸŠÖök][ü£¾{¼Ì÷‡S I ÒJs.VÚN÷÷Ÿ«’dÚm7\rŽ+1r¡ãiê7@%®VÉËåbò)I¡ˆ¤4 ˜h‰nM.Wv)¸¼V$I¨õCSj"R>¬Lˆ ª„"; A’·º³º©™°J rP-%ȱT¡¤Ù͹dBjÕ÷}7´€QPâä ‹Ïs)Q(™¸Æ” rLP+ f]s+ 5»PRŽÞ‡š ¡Ø*­PA¥š@‘T,Û­™3JN5åZ*BÎÙjc¤”RÚ¦Q†+ºV ’R)ATƒ_ŒPÀl¤jµm¤­Èvóñãç/—“'nY¸æœÜÝÕ5sUÆ ¡šFÈòõ ¢Æ±ë[Ý-‰)ú|>-Öl¸¨¶é¥Rm?(!©–œSÛY­4`ÕÖH¥×5Ö„ÎÏSÆj ¹"aÓh¡°J„ahm¯„®¶ÃuO¦d )¥êröq­BØív{9ýtì[Å%žÞî^¼®{;üþí_ýá—_i×7ùÛß•PŸNjØüúïÿ©håÓºd¡ÎÁbQ%c=Ÿæs<ÆnînÎçgcÅÃóq[£áxy|œÿá?üRÉ¿ýþoono’Ï‚3ÄNëis}óx¾œüñäüùûev!D­µ’r™'Aä£q{cE³ß\ž…k¸|û«×§ÓóýçÇu-_î49Ä»›ëœ­u}zÖµ F-µ–™I`ÅBñññÁ¶:åp¼w»Ý~µwȬ%]ÛoÞ¾–Æm7õý«íõм{õ—§/É—ãSÈñêpHC;J€y^󼦸´YM’ûÍK–XÞ¾}¥½® ¾<ý#0¬.^¼÷9T®Y1ŒcßXhìv9:7?b™Ýò¬$_Ýlw›áý›ÿÕñOþù?ý—§ç×w·/®¯~óþÝ?üËdTóúæv3î§õB¶û~/)eÊ%Äñjl Å,dRZçäÃ⎇ ¢Æ-7­½Ùï¿n 2`ÊÀµn¶Ñb™—Þv£n0•£íû®N÷Ï—óœrÉÒ AP‚«wSe/þ鿸3mÃZIâÈV[)ÄñòX¨¤Xº¾c.9†âc×vãvÛõ}Ó7]×”èiM!AÀN·c,)ääsŠ9I!QÈ\R̾:ÜÐŽFX£´˜KeHÊÊ¥p¬…%Éú>œ/k,YJMBôc‹ÄR©¶¬n¶Û±ÖÔt¶ÛôÒ¥¹æà‘³d.!6¶©ºéO番F–—RÊ~uJZæ¼8Ÿ 2’λ•A"HïœRB .`9ÃÅ9B„5,‡“m®UK]‘€¤QH!¥@¢ŠX”Q™‹mRBI«”J!|ЧåJÎ%·M냳FÛ¦/ÙÝÝ}£Þ¾z]—% Ô I­„"m„sÎè¶mûXy͵ Ý - d(ί$TŠì×x:vÛA ÓÚ¡¤"JM«ñòª`\gT1³ÒMßtFjH°ž-ô~·áš$•¾3Z mHkôi9W#ÇÓ}<Þ_~üýàNœü‡í-]Âóßüò·¿<ÿäkÜï^oº«e]NçÏÇó«×ï÷Oÿì/þÑ«ýþˇÏm×3Q© P óâf¥ˆCþŸÿëõ²ÙÝöãõvèzÝznG[8¹ާÓÃý—/?¾|qý«oîr9ƒ,§õ¢Zõ0ý’èÜô´ºÅ‡èS††MÂ*i§“ëûítñ}oQ,‘c*ñ2O>åeuÉ­ï¾y[ +fåsZ§W,±Æ nÅZ1ç›ë«§Ã£1vws÷ð|‡ýífÿçògÓåãÝL%¯§c§ÕÛ·-ª­îýÅ}üüÑ9ÿåËôó‡ev‹ÃùRÅÐÙ]oZè|,¬jŠ­i£V «¨ñ|yž—U*«¤ÀšEŒ½ÁÝØ`,uf¿†jJ¥–øöíÒ±iÊfP¯®7o_\aoßÿn3ôÉÍ?Š—Õ4‰ˆ‰Š(ý:[ÝQm¸`æ¼?CÌ}d®ZÛZjp!Å”|}z˜—%Ç\ÔÕû²†V59drŽE”*J1B ¡JeTØ´Íëo¾¹}¹UR€ïlŒ0BøÉaT¤øêvè©RpHF%€ýÄÉw­•ÄVAKd…j­î[Ѩ²†7·/£n®Ú÷ïöïÞ^›æújûÛï¾{±ÙZ¯ïn¿|øY š–¹JúÕo~»Û^í·»¿þ›¿úåþ§ÉJØu ©:—\ôåùðTK*r.}7)îï?ݾ}ýíùx®5¥ZÎÞɶ‘Fm÷[¡p³ms?ö†$ FÙˆ%¸PâÖŒ)¦åÕÕÕ·wߊb~øã«ô÷OŸÿé?ù‡ß½}w»½~ÿíÛþ_þ£ú—þëïÞÜÝmö7ÝÍÍæ7¿z×¹ÎsÛt\kctÓèüe^”–J+7ƒR2÷M×Ú™KÌ^YÕ¼º{±íûìÖóéx\§fh¯÷W>§ŸïŸ)¡b©XVæå²L)“øïþõ+⪤@­E弫%ýUi«QчûOÇç Øª®7½@¬©”Ì)åZ+r-µâùì+ ’Òy/‘ŠÆ´²í ‡m;î:Ó)­@ÔTÝšP •ZR«;Z¦€Hˆ*€¥,çËÙ­kIUH@Èuè{A¸œgY%´ddZPIëÖÚAi ”\l›n^¼ ɧ ÇnƒÈ›ýŽ+IT(j©¥±öz·Qjâ£lD;Xæâ\MUd” ôf³­ŒûÍ ¦Õ‹q†ÁnvO `hÛ>§¢´BÐRBÍ¡"Bª\C ±.D¡4 5¬i62†:×çéT˜SJÆeU7š •” $±¸à+»T*ÊR çœK !• ¥9ïmcäéâÖÙ×XKïóáñ™|š¹#4Ft'?'ƒv9yH²7;cɹk¬ÕJj«¤ºÚík€“¡&®ù¯ÿêÓ™^¾þõa:âëÛ¦«Ö.×·°½iÃáx¾œse¹æ¤´¨Lò>ÿôù« !—š¤B)"…WÛáþ—¿~ÿvèÔþx^/…ã—û/‡óìc !>=}QZ6­vƒîôÏ?ýt½¿ýôñËñðtµí­ÀåröÁ}ºÿXKøË¿øÝØ‘ÕTb‘dµéøðófcKJÃ0~ü|_ jÑlú ç¸Z¢øf?Òtdw! pN1ÖZ8Åéôd¨öF‰’­mÓ&dɪԛÍV¿³Äeí;¥­(ÙW燋Qšˆûa¸¿?ßö וÇ%DÙv™Õi©(÷¯ï^¼øü|>-ÅÈE@9G&$Küúz¼Ù45®5{-jcP6ºc¦~r)mßåRŒ±ûíÕínüíû›±Ã¡i×y ΕÝ|ùôéóÓáòåðÜîÚáñødŒÝmFBö.#*ݺLµTA"…L@)äÏ÷̧ó”|ùrô¾n÷WdÄáñùz¸›±¡ö¿üËn@ûyM©ÉjÍX*Äà»ÖbMëù¤›Fv]£I@,uN”‹!6T±ÄÆ(0NXŠ&ZÓ·-2 n ç¾µ·ûý«oœw»«^¨:nÚ±k{۴ƶM.œOÇç˓¾PŽeyýáÇ?|¼ÿøx:<žçåi^ŽRÒÏ~üë?ü»Ÿ<®çÃòx^óóññáx¿ú¹Ƕbr@­t)1 !DŠ~[Û%•m Cù IŠ…HDBæZcN«Ÿ3/§ã§Ÿü~YÎ.Mq·ëeœÇÖ^ ã®mu͆ÓíØ½}ýæÕþvßuF«ÌY$æeaf¡•’MÛjƒwW×½mSˆ_ R#ÔØu5mk”±ÂÄL£¥"®¥ßmß}ûv³®Á‡õâ~úñs­€”â¿ÿ—wZIIÔ·1&ø0O‹si;leûÖ)ö›ñf»Ý\Å”ÏËåñø‚“ˆnYCÞyï|ŒUª61†%Á`›ýfkiV¨–t^"äŠrLÌUJBÎ,QA‚ìÓóá¸.Qå"—ý’O9ÕÊä}>­á4»àÓééT#[aúrÍç秸úãáT+º5犪‡<“ ØjÓJi»Æ^NçìÃvJ‰Vi#$•l$‚d˜kN1Õµd$¶Þn»óóãtž—󪄽}ñruëñxŽ> ¬ZQŠq™£Ö}ß%EÄÚ4v]Ý×b4—šc’(¤”!9 L #&$$ÑÍ}göWÃÐö%ƒm{_Š2BiCBJ%û¾™–ÉÇè|¨¥JçË%×B‚°21h¥s‰¤XiB¬µæuYÐû˜KI¥ ,ˆ”d¬%¥22 ’4ëV¯ë€ÏÏ?|øx8\–K,ž¾üržÙ;LN¤UB¶§§‹_bcLk‡?|ÿé2/kŒÿî?|ÿéÃcöÌ1‡É=~zÆÎ6mH5åüþõÝï¿{ùg¿?lÆŸ?.B0p)° rf˜¦ÉûÅ(T‚~üéÇø÷ÿÁ¯Þ¾_×Ëß}ÿ×Ó:¯.LÇËÿò?ü÷Ÿÿðw»Vßl67ÃÍíðòÍîõ(·í^oßýîõŸÖ¹näæÅö¥$Ý5ê›×7‡O¿Ün7ûí@ Û~ H›­|ûbÔPv›öñá…µ•ÜʲijoÓ¾K•WŸ'©‹ Ƙcb-ôÐuD,¥ ·ús\'Q|«ÙÈÚ4ÒçE™¦SÉuqy^jÉR)Í)£íÇÅM%)dÊ$µ]Öe³Ù àõþéðãÏ¿ø’\ˆçÓr|˜J­5C 1NÓz:œ1W,IkYEÞ-‚ Õ‚5p.Ä¢D¯•4Z7¦ç*§iÑJ ‰Ã¶é7-g׋"ư¿m÷×½Tˆ@J4ÿñ¯ù»ïï驪Óqös-@,K˜–E5J3l7Œ(”Üíö©FÛÙ®ë_¾xíç.gÁÕ(¥…>?%ƒ5f .‰rX§L,¥J °"F­…’’¨2—sh{C˜À…8 …Àˆ@™f¯¸J¡UB2i­tkûœÀ’bH><Ý?§0¹xz:ÀWã—àÌyZ._«s˜„Ÿîpe¾ºÝv¦ÿôåCéãéÃÂg—'2XD u=œ¿<œ?<]>×ÃÏŸøÃÏû¼Ü/yŽ%× Š$碕R”œSÌ%×0; ˆ)9¿®ëÖ]„Z±pð!岮˚ÃR–§õ!ñÒ4âúfÿåËÇËåðøüp|¾·š?ßÿóBÌ AÈB Ûõ(´@ÒR* ÝØý0½•ÄÁ?£È¥Æe>çàTÁU Ñ’\kŽ@µæÂŒóâJÅ›ýíñøl¤<>Žñy K¨Z% ÿïÿ·£µZÖKÛÚu]re!U® ¤:=*eD®BʈŒ>ùÅ;‰’*XmPTeeLPì†m×ôˆXóµjÑ0§Z×Ì!ÄJ`šÖÇ´Ä©føÏ•œ"2t£%"k¬Ñ¶–ê}H¹T€TK`‰>¬Vˆ†ÌééÄ™›ÞöÛ6&‡ZSnJ„±ï£w‰³Ïåø¶i°&Ήûn¬˜Ÿ/OJÒfØÅ%¥•Ò…9ç ˆÊ()1ø¹°–œí ³ËçÝv;'¿¤Ì’…®˜9ÅÌŒ9-uÊ>¥òòÅ¥áp¸ÿîý·n_D£n^l~úù’ò2Mßýê}7´÷‡{aøõ›÷½½õ>žÿ‡ÿæßüÛÿï_×/ÿê·ÝnjeäZóõÝþåË7Ë|ù釿&ç%~yôÒØû‡¿ë{¹é5Ø ûß}÷Ûý8>?~*5½|ýëõÏ?¿.G.E¢ð1ÿöOþìt:!ãïþþŸü?ÿ×ÿǧ/CXú^I«šËùô¤P –„ˆ˜¡Raª‹_¸|U”’ŠmׯÂ9FAÀ¹ae!!*A$„@D TZ×Z”ѧËeF¥€(q¨dªµäªÅÕÍÝááÓ|N±+®(¼C$ˆþæ¯h›N½|uóáÇšáz?lzµÙXÒäb0²Á\°$­É1Re‰(„! Wc¬š‘OëYµº"H¡6Ãà組jÍ û4Ÿ/'P?üøù‡ŸÖy‚¶o¤‰R±Ö¢5k|ùz»¿é»Î“¶äµÄ\šÆJ¡rÀ”]ðkA*ÑÙN“Êž/—è«§& ÎÅí°±FWª…UP1¹pws}|~ªÈÊèTbH¾r±ÆXk”’9–‹PÖÚs®ÔhÍ ­:]Ž]Û—R+³Œ‡Ç#å’§e%$ȵ¤8ôÃ7ïß!ÔÌ0-«@q{u CNR‰ûOŸü²lº‰I‚OÎ…U4­Q ýè½ûå—RÑ~¿µÆ¦˜1W.µD@%EcäÕõÕiºd¨1çÊXSU$r.Î.xmZBüÏ)i[®ÕXíýZJ¬µ Q×t¥‚f¿½>=>IF¡”2×uÍ9¦š2—¶iº¶/\\ Œ°z|@D¿®9GD¬ŒÀp>NDr°–jVZÛM,ŒÑ%”Å9–JeÏ—sg»ÃÓéûï¾$ À›Ö¾ºÞ VŠÿéßü*‡È©ÛžgÏ ¼s%… 5DÕ˜^I¡öCo´zùbÿêÅ’RkÕ6ºë›ýfÓJc…X4À…kŠ9—Šëìr­kMܨà*FldU =lÛqcúÞn·½2eܵâê.‰½´U­àÛ^l·ÖªºÔØË¦AÛˆëÛ͸±MJ0§h¥È9Ô”RŠ„ä V+¨™+ùTªV‘ÁŽ+)ÔT J+™¸i{ç“[Ö«Td¬Üï÷Jªãv³i”¬>`å¦mT«UcJe"‘K™çàCŠ9"!úàRN)D†ü*€rÌÏÏÇšÅ8\I¥¤Ôa•Zújb)õñ<§T”0Ú˜˜r®œsqëê]V²“B“s.Ô$F6JˆÃӣі+qÁ°DJ¬nÍ%לJÉ•ËfýÎϳÕC œ 9Ǽ&È`ŒQ‰BIÒmƒJCß·M¯Û»Q!Áùò\ ’5$ Ö \ß¾~ñæÕõÕU/amûþÍ7„…ª“臾¼xÓœçÏU.7oÕõ ¾¹e¡žHµY¤ò)zAäœøò‘DŠÉž¾ì6òÅ®y}÷«W¿ýݯÿÞÝÍÝÐXw:lš ŸŸîï:>ÿ8/]|tñIȤ%=<|ò!¿yõ›ä›Z[•FïB‰Õ @^+U£1ç”k(ì”&® Œ.,DµíZÉJ1àà#G„,R,Þ»¡kŒÑJÉZkÛvƶ_aÝ$„¶Ö4M-5»x{uUJê»Ö‡5suΩÇíæâ—\º5Þì·V¤ýÎÜÞnÛƾÞnõû·›Ý [nLÞuòÅ~s³Û`É ¡1Ò•²3†¥@,Ì52Õ9ºÉy’š+J¹ä“ª–LTP°@æ”c)ÉÏó|ž–yéúÑÇJ¤5Wé\q>XcŠ ð>»¶Ûf³±ÆhkÇuŽŸ?^ÎÏéáó±–ª´)5ßÞ¾4¦=]ŽÇã9TÊ©Æa«•„Ù¹±m_nnÑ‘F¡ØnvRÚÃñˆ‚ EL)ådCJ`ôY€VÔZÙ_&8Ï9ÉóÑå˜wÛ›Âõ<\L—eYœ9—šsÍÓ´|þxŸ}ÚŽ XrÓ˜ìƒBU3ÀÔuÃå2m‡Mòáôü¼ïÚ†˜·ÛMÕˆŠ–àæu¢ëù|\–sJ!†àãÊP1§Â,B®>ÅÅϳ[f¦iI)¯K¨dÕ˜XU ­éIJU˜µmbÎÆZcmÉ5SPRmÆÝ|Z2”‚9\SNBPÉÙù%昩Æ\£—À­PÀìSlu+­P%ɺ3]£Œ:§4O“ ^5†¢ÏÇ5@&`QPäœ×Æ6Zj®•9£P³$hŒÚVüëõ2Å•H2£3 lú–´TRÕ”%UDC74ÚPeM‚ p©)g!…‚C®±”’ sŽ5¤sÎeÊØC3t …lTÛ[!HPmzj{Ù·²ïµP…K@ÈÖÚ”)Ùu]cÕ4„RRoµDÌ1¢RcÈÑ)•nŒÏ©‚0fˆ‘— ²Ö- ãjÍAhzýÍK’,Zm–CߟžRH™Y7Ú‡X3"¨\YK9j-jí7ãþf'2Ç®±%È©æHº Cb,Xª¸ú¦³FÕªBaÁ¡dÛ0s%„<ôÍv3”Ì"9àT“ÏÁ')u™IBÈ%Ô‚¥@)@BåR‘È6*åÕ6"f¯µDJHÝ 2cLc[c´B‘¬s®Z+A€ K¡¾ßIáWFT§ÓE+}Ô’€&Ñe¥@.’ˆ+#lg­(’x÷î;«?N—‡Ã)fJQœ§ušC×lmˆI° ÎÏË1úåè·óááùpØïº°žü|™Öû~ü„Škµ²v×Énßln67ïÞ}wx84>ÿá—ŸÿÝãóŸ>ÿåËOÓü¸,÷¹œ/ˆYa/ë=éãéÃÏu9ªà ¤e^S‚Ëy*ÙÝ\íº¶3Bo‡MßwBªyž€±ÔÒhœWESá’Ù‰êa9®–Ú¸DJ yÿðà\4²©…N§‰¤®\‘™+) fÓîaY•¹fT(­°1¦ÙÍDl¥èÇ6eÀ*¦Ë¢Œ¨51¤\i캾o[MØw¶ëu+­»øÃÃYJ#´Ž1pÓ¶¦ÑsȾbíwC%`„ƒ>”âcŠ1OKLš.‡•©~¥Ê@ÓµMÓ&h·BiŸS¥Ü8tª‘pw3^ïš¿øýË_{×X¹F,ˆUô¦ÁZ´$­ÍÍÕ~]æš# †qÜ ã¶'…J‰Rc¿éÎî¢ Ÿ.\$W¨mÓ5ªÍ.KMmkd§"åRKLÕ-1¸c9<Ÿ óýÃépX×Pª$BÌ92WI*¸cV$¤Ýt¹žžÖu"sXç2Wà¢#³[<3’”Î…Zjɱ”pxþ’kb®Pj£ÌЭiýêka)t.€‰€¡Îm¯%™ù¼Ìó´¬ÑÏžP.£ÖVÚ’pMeöUˆ&¹Dž1ÆR+¢è†ñxy MkTcBLœ9®¡Fî»”­È@€’Ìv¸y¼?Mç)`„\BŒs†€„d ¼^Ö¯‚x©tcšù8QEA9å鼜ž/9sÛvM×B3ví8î÷7B pAk ˆ(P7û°"±¤HnÛk­k…Râ_ýϯ•!£M)UÈb- ÉUp,V®F+Ð4ˆ§y®™ÖK¼}IàcY|"Hr ¥¨Æ ‰RQ }Û †FŠN+£ Õ:+@"\Ö)ƈ€5s-sþ*P¡|½TgNηM“S/>ykQ²­U/3ÇD)‹ÙûÕùyM•å²&F9»äBñ±*ÔŠd­±Õªº`Š„¥dÝêK­$C—H6íà#gP¹ L5:7Ç¢ÕºÄ]„̤”št£S)ÀÕ(iöZ[¥°dB¨P§°ÈNu£RI2sb.ZK期N—àâQ¯kD%cÍX¥&¥Ò·mMI¨†„ʶ›½²”K‚Sô\« YÞ¾}ãÜ‚µ°J +HÆÛÎân»¯¹´Z)B …£”\rh›&—s5¦¡*ÕpNVEJ T¤rÎëºX«•€¬¿Zú/牨úìS­Jià¯Ë%U*)«ÇÏóóμNñr\ÒZNOçK.Â{çÖµ3ƒDÙ¶Àåôðñç4‡Æl×Å“l´íŸççÇ¿=<ýqZ*G¼ÏáùrL9"@cšZ‰¤¤*J†kXý”Øç˜+2YÓÒnÛß^m d#$ÕŠ5çä—éœR5ÊebÛ´¶ÛôMg•¹Ù\¿{ýîí«·ß¼~÷Ûï~Ói»o®¦ƒó> “ЄÏGxò6ŸNóÙbÓ)Ö\T–B£”6nåÐÐH…¬‘Œ‰jI•€‘+—ŒX7û0rYýi™www‰iYcml£y<>š­ÎS.) MdÍ€sð¨Ä×dZÈéìœîÆBâ«¶ïû’“iŒí›T“–Õj9ý¦kŒ„¡Ó­cgv›n·LcB uì;YY núv?öQP‹ Úl6™s­YTšÖš¶µ£’z3 «[˜”X‚w))km×ìnnrevÀB¡ÆZ}ôË´†KJ3&Ï\¡`ÍT.ë3XÕÔR úó|Y»œ§é²–š‘ør¹.((ŠbúFkËjNZ›’J +¼{ûf³wã¶×]Y f9Onš×»ë—ëŹÉ×ÌFÈÆØãó32vMÖ¨ÀŒíV“‘$$ , R¡Â„;/Óy)'H9ú°N³rÍÁÏÓúéË—sX‹©UU²Â¥ ­A@¨´NáôtZÖ5ålm˹"cá’±„Zl߆Âsô Ê" c¥R6¤¸¸™‰QP)E UsqÁûg!Å0ŒÅóÓsÊeÇR3‰" Ù("âÆ(«ŒÑ²– •¬b(ç˹@Ö•bÍ2aǦk´ÿóÿôF*¥*Ö)q*À)&dL¡32 À\(€s*•eAr5GæÌ‚¤ ULŒ¨VHL™D•DÒ­kÊÑ·¦e‰óœœç¸D¿†ð|9$Î.EÝ´ j( S%)‰dIZV DŒ!dx|žtÊ §Ó¼,%g@”§eö> 0J ó9»¥–ˆ~ Uri~šd‘C·3ªÑRû\…Á§R+/sß·FÕMßi¥ƒ)ÅèÀBek|ÍkŒÂê5ú5ÅB”P&€J5×DDÌU ú~vÑU^Ü"µÎµl®÷w/îö›Þ(Ñj]|Öd•n¢O>e—ªjÚÌ”i2ƒ0"£ŸÃb›ŽÀ瀂¶›­wkŽJ‘° D!Qicë²NŒ°,« …‰©¤œR4J‹Ì1åi™XJ!CËz&b"&(J r!`£DŒEéÖ辪¬”´Æ´5s)c®v¶ÓJ"TÄl´ÔB5Ò¶ÃRk*µTÎkögÉ(A ùŸ_IdÈ©¦í®W² ,ÇOÏÇÃáp’Bi%™ÛsÌO‡Ç¿Ëî‹ó—y–0W .…LDí«¤(¤)2¨•–9 ÉTS­_àõ—Ÿ?!%í|ò%ã²®!$bLQÝh›§X„Ü,DmZ•KZ5v(E„X×%“«lµÓàTrZ?âíî徿zz¸÷Éwm ‚¯Ÿ??U¨¸h¥k©ÎM~öqÎn‰À¶‰¼%—ZX’s±±eºM¿„Em³½Ú÷]OŒ98„Üš.'ÁlR¥Å;hÚ–Ý\]½1FŠ\ë´LB#`É95Jo›¾†(…húî<]†aPJwm?v;…ÒJ+¥F&ÁµµÍâb.¸ú\rõ!Ä”çyÆúŒ¬´¤RÛ*-ÈÖtUl¤èT#QU.JÓØ7›mW‘Û¶1F#‰êÜkA% 7Å’!„S®¹¶¦¹Ù]5ÊvM§„´ZK)RLËê2€l CVZåšmÓXk•ÒC³½Ý¾Ðh$ÑÍþªQF±ºf¿–1NÑ€Eî?ÖÀ –‡ûg«[£Áüåþ>§²7äê’ói^ý²:DÙÚQbc„UBÝU$s7îÆÍ¨˜F30TVRV¨ÝЃ`ÓÛ«ëýضPØÇØhƒ™ØC\œ«nÄn?4ZŒ%Š€I ›îfw³í»Â…$(.%Rªíúa*R½ÕmSŽ¥”Z q.P+0#6ÚLçyžýº: Ú·mÉ• ³¢”¢‹Õ31 ÝZjbL’„–¦±]- D#ES3k¡Åó/n¹`J%ú\Š Ã’Ã!a Y°ÀŒ9–u¥RÉ ®!%æÂ¬´!Åsõ,AʦéR©.åPÙçŒ};Œ› Šúíâ‚2åš™7Ý~Óîr¬„˜jVRjajªPH’@ $CBV„º±íê},œc”jÍ}¤BàeE·pIòù4Ÿç¸ VMfqpøñY)3-ËÖv³y>O_ž…s^’¤*J”»Ý›çÃòæÝ7—å\bÎ¥rÌ9æ˜YÆJZ©lH€™ #5rb]ÀŠÄ}×¶V £6V‚\)Δ=Ðau@Ka %50;QJ°ŸÜ,•E©D¦”k‘$S ÎM‚jÊ9®ˆ±U¨À˜cY*$Ûa,!iaJD«‡kc{ɲ+Ȫ5˜à£ÒJè&¤ •ÐÖV&CD…ë!¬¡3Nà–ÐHc¥†Zjª1T)dôÑ(Å©hirNòxÕùp,e•+j™r auëe^çe]Ÿ}®ïßÿöñË£ð1ôã¦o6›R"$àSY¢Ñh«†a¸,Ëýñ°†,Üâ%‰óùAÔŠ1—œKòÉ ±J‘¬ )C’ œ–ãêAP9 Iœá²„Pp†y ó}NJåBÞMëâs˜Öóy9=]ž?>Mù<ÇX˜ãêb,©^.+±¼Þl®·#Q¶ìZcUç×ê\Øßì ÓÒÈœI°°¢WÅ " ¾,ç*a{CRC¥òiš˜XD¨µi€t‰ÕL§óÂ!Æœ£p— ¬3Ðyž*ÛµíØgçófs[3¥R.—iÒJ€¨è¦øôåvíXB 1¬É-1æ¥pLù«öðô˜|R£…3!3çX²O9&V²‘¬‹F6VAiÛ¥Z´Ñ5ÇÆ¶.¥XS,¹ä}êt»mûFj%„”ØwÍqZ¹Êœ²R,q¶³¹Þ\ß]i Bb®®Û¶o¤†»Û[ˆ¥•j°öÅ͵Ò$­ ²ÄØšdZ}gÚ¡Á6ÍeYʇÃé´,ÒÅ_XÖÄéËá²öû¿þþoU´ %•\ #‘â.$Cþòø`ŒL!~ùtØtí jÁ“ì[«•ȵDb¨(±û”s-5Ƙª–sxúòTØ7xûúÅÕf„UE-0—Œ„À˜B„ÕÏŒÅ6Šk)1)bpÞ/ h©Kª1eŸcE¨È¹f`hµºQ’ªŸžO¥âÐŽé8&DÑeHÌ•7݉“J¥ôÝÝ+%t®Y$ÊñOþÙMˆ%Ä’ ”Œ9ÉA†‚Ä,£Ï)Ôè3‚Â"Q…ZjÎ…cÈÁ…’*0øàR(q1$®„,5‚JÁŸŽÏ5åËq¡,-íºM– á%Öì9z‚ ÒÌÅÓt ÓqMQ”Ñ¥äñ|)!ÈË%¹ÜÂçç"›i.¥H?§Z% –J¥Z—NÓ¬µüæýK©ê‹oî»Çéñ7¿ÿí0Ÿ~ù°ÛŒãØ‘”ãfK$…4w¯¾ÚF®kð…¨l¯v.¬€ø5ÉS!–§ã…qÍÖ +6M+ˆ€KEFÜÜ\µVj‹…sˆq™Ö0‡ç§ã2§u-.ÄÙ­§óYjJim—}!Âýõ( fƒÜÝ4–©2‰¤P²m”±jÜl[£•–™* ÐJÔ\HK]bÄRŒÑZi«LôITJ×Ì%dª&\g/A*4aMí‰H¥œIɦ±ZH‰¢ï†››«óéI)®¥Ä¾mú¶­©41V Bæ Pܺ‚ÒT1™È@TR„ªiúÍQ½ûæÝ².mÓyx¸Þ]]]ÝÕ ~^1sæt¹\6Û­R’\œI± `MP"çÈù—ûÇ¿ûáðýOóåP”(J¢$)SHR¨\kÍE YeJ(Þ§dŒ*µ¡c’îè¦Å¹à ¿&·–%†ÌA5Kº\‡¦f9Ï!ÄZP†\ñ|Õœˆ‹¬Â°Ô‚_V—rmÛ »t uNè0†ì]BúàšVZ#¶»0Ba`$Dªœ/ËåìSª…‰§Ë”c"A]×7¦Í¡HTB)ĦQ¬D)œCˆø»Ÿsªë"×®”¤®³.¬H¨­Îµ*­}N?|úð4]š®K)µ¦#hæÉû˜–BuqKɵ&N1‡¼¹ï]NÕ-9¦`ÛØ.­‘2ÕRSrˆìcþüåxzž´ótñq%M¹æúuzš&FBd ”’UŸæ” 0ôݸ7»‰”0­‡æîÍÕ«w·»ëív³m5n»nhú%U‘8/ˆ²P $r­šŒ&RtÓ¬”.„©¤”—\lm›sîzÛ]?öÖ*”u{5ì®z¥@iD‘Æ}{}»»{qK…_eÝBìú­fc$#§ÊM3œ3¸Ìi3înާyº\ÎÏç ¡@ 檬"MºÑ±ÄÕÍ9Äóãåç?~YcV­ÚoGM øÖ}ð¡äÅ»Ë<Åœf·8·pIBˆ¶mrr!ùÙÏ!ùšSÊѹy^.©äÉEW—è=f¦ŠÙ(Õ´%jk¼yM 6üòp9_B)²iGAº±}޼œ—ÓäQ«ô»»—Wã™*ˆ ¢ˆð϶±&’¢|Å\&æÌs朔dd„iŠjYJ®Jʶ±¤¸ŒnDÅZ‘3ÕŠ3¯kj»!rñ9Q—–˜ °l¬5öf{½m·Zµ5B£NÂRwúx>ÜO%ˆeŽJ[EÚ»r:憠sJTMrŒ•泆2¦{¢bAU„àýÝ«—7ww¡–d´Ê9vƒí¶¬Ó<ô›ë›‡ó„ªudÛV Çõª‡²h#ƾ[ýE¶õqú,,­s g§ª*>"’UJFLÓrÚmÇqèžO_î¡fœK(Æn ¥Ð)­ÀÕX½Ùn} ýé|Y§´&!Ý÷í6/yYbpuìvZ™’¢„R‚€XrŠœ\á„­6½U1®ÌÅU8¬êù²œ'2œ/ Um _>žürÀlµ’BÕpåZŠóAÕ K,¹„b”)•KqÞÏR*i¤0…XÖõt>{ïµTp™Üé0EWr`Sc…Ê9Åœ J­%qÎ}Ó Ã6.¾•ƒ®ÝrŠ¥j­Ûå’°ˆ””‚°é¬nmÕÔmGÓ)çÒµ½m›Æ-DŽ)•xÿü¸Ýí¯Þ×èöÕ‹Z ¢¼Ùc·­¹çf·˜F§¤ÐÄrž§Êq{µ'œÙÍ«¬•ÖÅç̹äX“ËNÀ\S7´©úX"I ¢Ï\1Å\|Û Xmº¦Y½›Â´øsÛ5R˜y+dR µäš¾~+.ç¹3Ñ ‘’)g!$3±ijŠXcÍ)&ª@… )Ö°½Þ¢M×\æé8=»0ßÝ\ç­i´ÖBâv3J)ŒmJáÑô›]KœKŠÓù¹Ä ­¤JQ~¹¬}3Ží8¯'!¨ïÇÌ|ÿð%p.D¥âõõÍáð|9_ÖÉ%—}ˆkpÂŽ«¿Ì ¡Ø.ÖèBšbY\ŽK¸œÝ4-1‡Ê…IèË´®>TæœCeŽ1@MÁ‡5Õ\BH)æàCµ6˜k ¡æ¬„(J…œŠ >d×íÛ·oÛ¦PråŸ?}ùùËáir¹íš¦±Éû”ÓÃéxñÞ6Mô®Ä¸íúÞ¶~™} ²³â¿ÿ×ßJù•|  ·m­4I Ú°2¨´”‚-­5EªÜhÝÛvlÆAµ/®®Ö¦¶·,I! I" ÈyÓt ™}·¿îZÕœy Ÿ¿ÿ`“.Sâ€Ë)d'ü¹ 1£äÖà}©¨ˆ,±Œ!ºÉϳ¯@htÄ,,5ƒT_\o_¿¹Þìl£Å«»›®k˜+(Ê”d’2ŬHI¢\r‚z¸œµ’m×…àúÁ(k˜bvR¡0‚±NÓÚ ½‹áùxÔZ_ßÜ1³h¥”DVÚRpž€µ¤’cðÞ1˜¶.ƒZ¦$É„ðŸÛ€•f®)e® ÒÖtÞù¶mkÉ(Âó呤”†Å Ë0ÚìsXbß©ýÍ(ˆZ@UR¹Þ_Ïë:‡åéxh7M†DBZÛ.«K%3WDÊ资ĥ–ÌD¢ÆB4î®~ó»?›–ù<_®®o„ÌCž'G¬/gßZKXj®)ÇL k."†´>ŸŸ×u²F¿¼{a^Ü´¬3±H«üþ?}14(Ñ” 1ÆÍ0>žŽÇgA¢”:‡¹rÕV1– Ifi•â£s%É…KDQ3§óry8ºãÑk©w»Ì~3hbAu³¹ºß¼ÿîx8A©Ûí(5¦’BŒÖ6M£…ªJQ×6€µi­¶ ˆs)9Irh[E¸®«¹ë¶XŠâåËëíØc­_éa-P¥$Cˆ9ø0û8%ʺD†ŠB Ôøîí7×»WƒÝPAwYS¨’ôÐtÈœbkrk* %ê22b0»ëíÕ¶ëV–Mñõøt>ܺÆ\2Éœ¬é²1¦”³±’QˆµU¶ÑýfÓ´­6R+­¥µªË>qJÀ•¡êV]]m6ýЫÖS¦$«¬r†ŠBȆ«6¦E¢Â9¦HˆÄX™g¿dªšZÝbe¨©†j ¥¥®×¯ï®5!×Ô´Á¼¸”áùyÊžÝê.ç#§©lûw±PÔoFmšçÃyYçÄ D$¢6 a]—Õ‡+D¬„ ‰Iflg„æ’C-+'Ÿãn{]]þîõ¯Ž_ c–TõɧÈa-\hž¦RJŽÙÏ.¹— Aõv£…úî«8æðòÅ‹®mΗ Ê\X@×´¥”Â5sÚ^»}¿Ùöãf(%ÍçËêü¼¸X™ SIB@ôñóçó§‡ËùyŸ£÷ÖZmm,i^âãÁÍ>ºPA;4©…˜W¿ % 2I”¥–(:Ó(ÐX%G€Bµ“çsf «›ûë»q³9^N©Û5ϧ¡BRŒÒ˜¶TÄÌ)­Tpbá¥ô$³Ÿs\¹B©9¤hmë]Ξ;3~¥l×Z×5ÕŠÖj’¨¥ÊK Ú¦¤yö‚•!˜¡B±tªæÇçÙè¦ïú¾Ûl¯P¦L~þǨ!R¢dóåúë_æþøËá|yž¦É{2¢1Mñ¸œƒ[¢Õ-±Jsy~¦Ÿþ\2¹3ÁótBI•yl›ý°å\·W›"²T0n­°\J¼Úî5éä2t½‹¡0W†BÀ„Îǣ‘II”˜™P©!qY–Ãê!+ä‰*°s.®¾¦«)³ÀÌP2 2 !µ]kŒ‰‰SFmÛÊY @,§ÓÙv]¿Ù|e.ÉB¹dÂz·`ˆ×XbLR¨ÆöÁEŸ\ŽP)! ×Àë¸íÏçøµ/_ïDSr‘a±WÛ7}Û[k]œ ÇÓej:‹Z™Ö´Z©~7®Ás¦owÚ¶Îùì\®±ï›°¸Û«kÝj·Œ Ï—ù#ÓÜ´5óe¥6ÓééðsH§¦T®Œ‘Ì%ùÕ(‚\—ó‚˜Ëì—Ù-)g·.Òi8œ5§F)BpÎ¥RKF¨¢V–Z ªÈˆL‹ 1Wm-¦R|Ž©¤ÌÄHÌP+Acmò™ªûýáø UÕ†¬¦—×»Öên¯ö7- X_½ 1<ž¤ÒµV"La-ICÅRJæZ…TJ*¡¤®Œ«Ï~vçaÛí¯7Ò@.Ù4M;¶ÝF“È„ ˆ”Uí¶1¦¯ c…‚t™W¦fùáÓó².kö.x#µ©¥d¡Åíë›çåø·üÅÇ ²Lëœ2‡ä•qI5UA²”2MçÓñYB"’.D†* ÕºÆøeN.qï’[âù²>^·w{Û7FK…Szüòàæ™P„Tï!û ‰„–•¨NJ¤P*TŠ‘‹$·#ÛP©°ßî¹T!%TÈU’”RD H Qj"ÂÂŧ5—|º½y1-Ëóሠ®Úí úKh†®d:<œ*W¢Ñ¶7R ××7Ó4GL•«Ö`EVÉ#ëS  뱇n(Îûe1Ô¼ØcY­óÅù9Ä5çH 4 Èœ|…±ÖR ·ªW`’1’TEÉ××·TäÓçS‰øæÕûóó¼^Üç>j­ã°éû¾ëT«[+µ5ú<]Öè]pÀµ¦"kH)ÆÓ´xA¦ï6¿<|ö©»«ÝŸÿù_,S:>/HâÍ‹ëï^¿TÌFµë”ÎÓåÅëwŸ¾œ.KX]^\z>MÓ²¸à+6²SEA¨%âtñOOÓé0kcºn(¹FŸsÈ)g®¥mZAzõñãÃñxö¥¨ÖikH!#ú˜bL)G 6ûÛÛ—ÃfŒÙù0+£;eˆÌ\jPr«ÞtÛ¡í²µòñ2‹ÿ柾 RdNU±/aM9¡_99s¬Q,ÇÀ‘>’ËËŹ%®K>NsðžÝs¨šì®Û'Çóä—5JÒBˆe™Äé–Ìn‰ÓR!Æ5Õ ζë\޲Uc?«JÚ¶&7“&TuqgcEÎÁ;¿¯1[NæîæEÓ*yv§ÙÏ$UÛ›ý®WRüøó/ï?_–éîöå~{ÝtÖ4j»^Þ^½|uýâíU‚U˜”aÎx^ÓaN‡Š „¼–sLëº^˜¨.ó‰K!‚¤”â«QÀ´ö²N!ÇÕ»˜|€ª"V6J¢®Ý¦QJ­K…\ëi> M³›e#}u±R“ÒstKöKtí¦3­$$ØhYjñ11p‚””FKÀ¤ÌW‚e–¶†ºý岜B\c\rõL%f×õJË’ÓšsœÝ™•Õ!%b$Hè‚«œº¡ED¥D;4.¸X“‹þ?O¬•+ˆZJ.9#)­ºíÕ>¤4¯+"ÆèO‡ç‡ûGÌ5ÉŽPr-àÖõt|¾¬g’ ú° ¡n®¯Î§óáàóñ|ŠËBóA ÕÁÆ]x™ø2G”J* 4Ý ¤\*ÑGRt}ûþíûV´·ýÍ»ëo–§õû?üp8†Ý([[cÊÑ£µ6Rhɦ°°`¡ÅêWDBJ¡æe–F•Zƒ/,ˆ%T,@´ *c¯¶C+5Æœ+€Ð‚$ØV¥äBYM¯–0³dçý/?} "ÛŸþð „aMÚ6ëN'B=ûí°mµê¬–RLó"•v.Ì“?–¸ÐzŸz<Ÿ]f”¨Û~y|v¡’’˜}ýôñq.ç8Íç}®)æXb.…«ŠPr© …[ýóqr¡ ©”@¬U²ÐÔÜߟ§qØ?<>/³Ÿ&7…yØ™Êét:[ÝD—§ËÜÚ wÛÝÓÓÓåt‰>im €ªí6çãÜ6Íe9î®Û’µtµÝihÖc,9÷;û»_cYðšÎÇåóÓúpžöûí`–¼Æ© èÆ1¦ÊHµ&ÀŒVµ÷ŽïOOg—Y–Bˆ,I ÖÁ…œÂâÊ¢#Ç®5¦}:žœØëN K  ”ó´øÂ”C2¨wíæfØíšáñËáx Æ ¥¦‚©`ñůÁ—ÌŠl¯¬&y™šL#þñ?~7­±0Æ"HsÊ•s*ÁEB’(š¶»,^¶}9ÇJ!%sæZ¤¤ÆêÎ-áütö‹OHêÌ •”JAV5F÷©`3lB B VUzñö¶¢ë6¶ì‹··Ãu3b»ÓÆÖë}óúvóâöÊÕwm×ê·onß½¸µ9û®UæyùòEJV¿6mk›68WSÌ®DŸc Úd´Ú k4céÇ¡æ,K¶ˆíJ,•!*j´­¨ŠF4"CZ=1èÿ?KÿÕ³í’g‡}•Ó•îô¤7íÔÝ“9CZE’%ZN ,þ¬>1`ØaYmR3=³{‡7=éNWª\õ÷ÁæG¨£*ÔZø-Îj)P+Ê€ ¦À1ˆ”+`Z ëBÅyVDT"Y ˆâIgKÊ”rE8gJvf(uÛ~¸mÍ[L·¹Òè¢sÙ_÷ðáƒÙ¨/O?1/O/˜Óe$\,·˜s‰]Ï_~D½\Ÿþ¯ÿ·ÿûâÂÝà 0`†cŠÞùï¿ûAýxú¼æ«Ô¤ßªn¯§4ÎñìóH¬àBu'"$¥¤³+a‚0VÀ1—cΩT¤JQÈ>åp½^r.¥T„pÛ6Œc„3&5§ŠÙ4ZQ¶±xd×RE(E\’fÝV+#ucç6ZÄ @–Rt¦AP0omM¥”c®­F%WÎ9ç,Ç„kÅ•†7·íVëSŒ ˜,0GTãÊ+×|¶³é WœRñå—cJØ4Ýñt}}]¯c}=Îm»_g_"Dc 1ù©@YV‹ªPKÊ5TªˆR€WÎiÉ‘P’›†íwZ ª¥:ã­ku7 ½løþa7l:‚±Öªæ,1+>o†áöa`¥Ëê*%fÓç£Ïqññ8Ú¯O3%˜Â…Õ\^_Î!Õß\I¢cbÓî:3(%}p Åàýâó¢róf'{c6 hõ“Мršk%L¬ö·Y„ >CA‰MN¥V´¬¡Öè£ç\Üì²ÏÉ(ÕE1#„eŸ³RÝòBbA™K¦Œ2M£™ýÊ$ÓZÉMßÉVg¨ãÅ¿<Ï—×Å®¹&Òéíõ8]OW${GÑ¢ÍCói>çë|@± „ŒË4;ëR( ¥1EŸÜš'ŸC´†0/6—’3Ðÿ˜ûW  ”®/ë\q‰s-9Uä¢}Ÿ*6…ٹѷ‡Ý_ýåûû»mÉ/K¼žJù2®­c¾,!¶ßÝBȵ"D1€Z­qEû¦G!Ÿ¿^ž>_O'Ù²ñ‡ßõ•þÓ¿ÿÓ§§Ë?üòô2{ÂX#i/Ñwïn¾ûáþ_üíŸ ÓxŒvJAJBªxœEùþííï¿}cöÎÛÕ§Tœ]sŽ!ÀØ.«_mY)þöÍÝ»·÷FÉŠQ*y|^]`BÉM×®Î>½¾>/ç뺄ç×q¼XŠ'˜S¦•"„·í†•:N—«ÿéã׈þ›ó é{‰p)5àsI…3Æ8ã‚aŠ1#Âh—#P@$›VÅicšTB% F”VMÛ4¦Ö\PEŒGÞ{%ùÐðýF½}»ûþû»¾§ï?Ü ƒ¼?l·þöáÆ°2hb$ÑœF;¡rH‚g-)°m[?n×i¡,6Äv±1øàmÍ®!+BIJ›·ß|wÏʲΥD\"ɑԪ(‹vÅ5Gç?>nÛ¡„‚ K±®Ç9º@õËj§EA)C•ÕBkÆ5¡(%…èsÉš’ AŽ•B1V„*‚cŒ2B1ùÛö·m×½}ûáÝÝîòAÌOëGO•'‚‰æêõüô믟6»ÖôXõäëËËç§—n·y<¾¬Öb`—ë”rñ!0)þéç_þŸÿãÿˆ8v»vË”lŒëÚ†iB¼dì¸J©N€KªnôOSülÓ¹í•÷ή"U€ irÊPrŽ>ÅP Ù`+ÉXAAÅGŸkª¨„0F”QÎ%®„b‘Ìó¥RÆr,œ)‚…w%¸*¸®"¥VLéЄ8X·Ž×JQŠ F0€b,…:ïRŽŒ3„pðŽ3*_&÷åãKp!Â¥\¯ç3!'Ȭc¬¹ÄyÃ¥æÓ:"††¡¯!ÇPr øùõX ;žfâ°ÝQ©C×öÍp{û.%L+~{ƒ SŠ™‘¨ 1Ž`CE˜É9„óË Õ ¹JÄÙg†¹&D_kòÁ[¾ýîwŠ71”·ß*Ñt¦›¯“],d$Ùl†»Û[¨Ù­óÃÛC¿m„¡ÛC×õýÓ×ç~x‹!A®Ä°ér)5£(`Ñ7»÷?(Ò.㕈bY§ÉN#䨷†Sѵ}Í( ¥˜ çf™ƒw)Øèlt‹Ã@`%$Åܮ˼Î)d{ÓÚ˜NËL8/±,³­Rˆë²‚)RûÃŽ¸óeœ.ÛÛáîfP¿½ßq\ÖùkîúÖOëéùQbŒT˜`©äuœ'³‘C«Ò²ÌãlíšRÆ ÁÖ›¾e”¬Î/cD”0Î ŽóÔ ¾5ÍnØ &.—k®…qÎ0ˆݦkº¿ø³¿lu‹*Š1®k`L¸Õ.¯3* Ù¶Ýí0\ŽÇÓiÊ…4m¯µ¡ÿ»ÿüÏ$ÁcTpŽxž,£L+Í)¥3B9!PjɉqcbŒQŠs޵–ŠJH‹’…3R"N…¦®»½ÔŠ6ÃííN24!j¼oZg'iMëÞQ€eœrJœ ‚¡UR Vkjz¥•Xæ•0þéùëÜÓuZ" …1EëâºFÎÔÍþH1κ¶íŸ¥,0ЍbP!Û˜–$ˆÈÑcȵ–_?þá‡ÀMk^“DB (ëŽ_¦ #ºÌ¡f®EœgXÆ€kŽIi„ùöÛoޝGT*ª@(Tj&$¡˜I¾¿Ù¥0sšBž^OçãËåú5£É£óëø¹í7„ËËiñ6 ÉÂÝF<>ýüó?}züe¹ßíoöC×I¡”óåîæÐÁùã?ÿÏÿó§÷oßýÍ_þNòz¹>¯KJÝlöã®U›ÁÔâk°É{;)È%Û\<©–¤¹lÕfÛî¦ñ 5ÔäpÉÊèJªd•5PKÁj,œp ˆ"ŽÇB*£/˜ÖJ Æ(‡BkÁV) —J·`jLB¬(žr1%K…®…®¥²*$R3ÀXµŠaà€“Ëœ*Á„VŠ3BQÒÜÜîÞì6£å‚wµúäs 1ø7oÞ£RQе¤Í~›¯³gÀÛÊ`Çåv·çœnºí~3@ÍÒJ A'è—ZýDû "¸^Ö%%B*R—u™ýJbŒ !›N#L|HBjŒYתѩ„TjÛogocñ¥$!DÊñ|~MÑ]N§ñx]'[ ²a„à¡þæwÝs ÉrÊ0à`×®Qv>5šÞÝöCgÚ¦¿»ssw8]Ÿ1FP1dœ.U\§e^Ob(å|½^–’FšV …›FA)µdΩ€jÁPrŽ JÛ*pÁ‰ Tk”¦ˆäÍn7ÍkÁ¡ Èa”#IbôŒâ=eÉÒ´RRŽ+Ú-Æ %»Å6Lïôæaw£™ò6›jÅ¥fŸmB¡Ðb“·!\Æ«už nš†2zsئ˜eÓ(¦å››¾ß4­ÖûvP”íšnÐ AX+ÅGO“[\ Çc.SNø¾ß†=®Tq]2Ô (IUÆ0Àøæ÷½lÎÓeñ‹QG$€IJPŽ­‘B°Êu ŸÏW,Ô§#úòz>iÁ(Æ«u)æV5ÉÅ—ÓQUkÍ!B³w1&© e"…cœ¬!r@lµ+çD·Zµ:£Òmgº´¸×§G¡I׳~Û¥//»Æ¦mÚÎ@J—ózY³õÅÆìkÒ-¿¹ö{ÅeÛô Ë*A˜‘ê—å˯ÏÏÓ<:£t×¶œ3DÀ;_+J¯Ë ©ÖRö¹:TKr•’ õ9ÆïïÞ´mïül}Ì•¼bú/ÿbÇ€ D S»äœpôA ¶ßo âqZ(ˆLP²vh»Ýn8A¥’„T&d*E5š2ºßmµbF‰äC ‰¡ %[kàZQLá:Ï©b@8–è’[}ÐýP1—+”켿Nëêªsèññ¸†4…P(s‡ŠàÑ»˜ŠuWÚH3Óyœ2¢¹æËxÊ€W·þ+MýÒZü’8×çÓõéùüéëWBi§÷(’–ë?=.!8Q!d!j¼:FR ¥¤d´ßÞ¿{ÿþ<¾úWŒÖ§¡£Še€qæª`r˜(õ͆\–¯/Ç_+ò_*s™Ì ºƒº¬/çËQ2)8_/nYïÇ××}?„èc†eÎ]3¼{¸m0ŸR­EâÎÙÏO¯¡T)Ù¦!l(1Æøíû7Zr·ZÁh-¹B¦˜h*Œ,1Ï9NXRšGJ)¥„’EbѺktÁhoE:oc¥¸tš&—Óù2ǵPD£¦5€ å|gkã°ß›m‹%n{ƒ¡ÆB^3Ž!¡„ +®XQÙ2£E‹CQLß¿ýÁ^} ¾¤ð°•fT2L”à˲B¡R4m£´¤’éËqÂ Š”ó¡Ûõý®5÷>ÇŒ ^Æ®µNó¼1wïÞú˜RŒ¨"F8b²³Ëé·†¢:/sÉB™ŒB€ã«…¢8ãR±¡i·›-fTi#i˸¾\/Œ ¥6»íÞº£,(aT0AmXŒVj\}I#œb\˜¢˜D4”pZ=>¾¤ Ýf'…N>nöJ)Ê’˜B\2ÎÏ×s*‰ðÒôüp¸“‚ûÚ]çóâÜ”sB”l»„J³mL¯U'¨D\Ò`Ýoº# lú~0úfèî‡Ýf£$‡Z¼L !’Sˆ¿ÝñµVDQ Ž ¡…& 0Æ„"„*Â(CMÒ(Tª`Üz·®.ÆÂ¨°«=ž}°µ`Jø~·Ùï”V¥â¤)#Q@WÌ!Š€d„kà e#Zä¡§ú`nèe\)#];tÍs*%¥)ÅJðmÛ**Í—qM±(©9¥”"J1% UB0ÝnúœÂ|^%7U%Ä4»‚)c@h!Ö`L%—­¾\ŽøÝw»ArB\ñHÀ¶ëq…HP‚šcLPlðÞÎJ¡RCÉeöi\Üé:Ï6Ϋ:¯³K¦k?>=¾žíèrbp­xóæ/ÿì;#dqÎy¿¦ 2]÷Íw?Ü´›õ:ÏΪFÐ~M×%¼Žëª8G¢8Øoöm¯‘ZO–"þôúºXßo6BiWð~ü÷?}yq¶éÎá|žÚv/˜@ŒsçlÛµ‡û‡ÛÛ{Jèç/O>#,å`5‚÷ªR&aµëììé¿úçï+¡>—q¶R4\6¹¡ÔO(*È*MZÍ ×A)Ñ*2\nLÇ-©(¥owÞ®)L6ŒOÇgÂEE¤ ´ø’3%J™ÁCª°:)Íœù\®ó2-‹ù2Ÿ±õ`=Š™Ž>Q®£KPIHSš+Ts­!ïpÄ1†é2Ícʉ É…KM¹F›(V—ã\N!cÄRÉÛ]/¨ÆÙ<~ç !?üù"H.À¨ÂÌ´ÃAIµ*-šV5­Ôx½<)Á§¿ú›¿}÷ýۀ쮪!óz–WŸ¯µz@S_ðb:ì ŽX•ãx¿\ÇÇçãKˆÈ}!•<ÜÜÙiáY;»i1TöÆ(Á(ã‚®RÊ¥PŠWŠ ›æî~óí7ßÿ°;lÙíÁܽÙ ŒˆnêŒ@¸4½ñ)¦„!I­¥D\{gªÎ®˜ Pc‚ÜÝnßÜÝQÊ\I °šK-gôÞv·×Ñ~~>]ÖX¯ ºa¯¤@µ H{9¯Ór.Ïk©ˆDbª>¢óãõ§?=ÿøóëç§ùõì×Rÿì/þü¯þüB°7ß¼}óÍ}¬ÎÚIs£ÿå×ÇZEJˆ" )àÂt-Ó²ïzDè×Ók¥8•Rœ¦kÌ^*哳.<½LÏÏ3ýÏþÕÚ-QLië%K΂÷¨d¨QPN1Z£@Ð:9ešŒŠ!¥âCt!zïk.Œà’£é|9'(”±à“]bŒ€€Ô½_mŠ!Öeñ¨¢u^S¢9¢ßæ’‰µDÊab&˜¦% ¿&FdN@)¦p#MÉà–5gO’Šö¡Pö›N0’sª 8‰”¨®Õ›¦ÒL"˜1b¶o÷gÿìï<Ì>žŒdRÈÃÍM¿(¯)\ ÷¦¾iQßa„æ7·‡‡Ã’n}s¿;Üíî^dzKKÛ7Z Nq© A-)Ç “O_>Ž'?GT*ª#\¬É4‚0Tjd”xçÕnuG3P)!µ– ’ì¶C%8Æ4ãÍv R\ïoÑ'·®F )°Ô´ßiÙƒ/–8ät:_ e¹¢Ç—£Ï8ø4ô{Æ¢|Zb޵äJ„,„ĘkÊ(µ€¦¸O§AD`æÏ1Q‚ÔR)%UNQ+Å8ȹ$µzçBRh)$0È(UTŒƒn™ !…iB ˜ .¸u!ÄÔ C7t¨à2ï]º»¿»Ž¢tq±b’Ë%¸9nš†9ªà¼Ã@´l ÀñøJQm7l‡‡ÛCˆ  SÞª#†iCzM[# œC°ÎçZkA9•’3êÝ‚!ï¶eäÍÛ‡û7wP3'QD(IÁ¡ZÖÉ_ž$—Rq]Ök±2Øöˆà‚0ZÃ(«*B6D™é:*9f8å,MC(UZKÕ4íЈáz>­ëdãt^Ž‹[–Õ„ f×?½œs(œ Á°ÑMЉcÌ1Ê)œ®GÓ5R»®)DΪ!]« \ÎÖžÇsÓ(ƨ³¶TØîn@b§É§À%#œU€œcŒž ¢;Ŝ֔!UN9#„bS"5¦²åDR jÈ.BL*ÃB ©Äoüâ$ÔU6XjÊ8ÑZõ}gŒÖJIΆ¾Õ¨mô«-aAë9Ïcª‘ŠŒj bÇñTq—Ù…B0ÄÁ0BlŒk„X9ð‡Ã&ôúåç//® Ñ…%ë­`¸×êÐC7¼Žãšlåà“·Éýuö«‡\´]'™.1Tw›jTk¨¤3}r±R”¡2ÊFúºlc²©"H83†)D2fi{ÓöÍnÐɹ5²itpéø8FGÏg÷õùòã¯_NççëZC˜A·mŸ\xzz&\îûaè¤V1k=F˜!’|®•æB‹€¢ø¿ÿùã—“=.0noùóYbøîááþæàœûúõ°Ì”}}~¾^§’Š 2Çúùëó/¯Ïÿá—?q%£Ö0ÛS®€ñuYf¿d DqŸÒe¼ÒÿÍy¯[A8ÞúÕO ”3Šl†A) PK©>– F$_üZ—‚+£¤…bÙèÅβÏ!•Š\ÿv6¦å,æŒΙÆD)ojÅ)×fè×Õ“[æèmUR¯ó’sι`ÌRHó¼æ óºBg] ðøësñ%Ì£ˆ—ÆóÌ™8Ïc£•÷Q‚()t#ú­¡2l¯aüøùçíöÐè¾ë-iÎãéô+tØÜ Æœ['F"¨+Sµi•R ¡4]_j)çÓ˜J u\Ãtzûþí¯Ÿž¿>~â”6·%ÀjÝóx–Fµtv‹5JßßÞŒ*˜®4F/WD+£PS¨Þ+ea§ó„‰Ð¦ÓŒ¡†\ã—Ç×?ýéyº:‚xJI(á¬7ª·.BÅŒ ¥ø¼Œˆâër®@¼«¤àñ|•\IÉ ÈEsa” Ùs-Å„â§R3£‘ZNn=.—ã|ýú|ùôù…Pæmô®@DZBè2¯ëì/×qZ—·¾ùüõ™2eL1]W‹1S²Q¬³Å„B†hÊ c¹Î®QºÓçêl\l¨„ªÆ”ZìäqU9Ãjg©F9B¤$ø ”Œk¦Z±‰ŸÎ×i^¤æT  ¾Ýˆ·¶¡XÓjŠðz³+1W„±R&$•<ì>Œ¯SI9§XCå\Ƙj.ÑûŒcFIõ¦t™F 8g—E¶†eš¯µTF° ëu^—%`Æ-ïxx÷ýí›ûƒâÒÛt>]7›ÝáfƒQº=l¤!Ã]'V’•‚µŽ1ŃqIaB—Ç5;Š*íZ³õaA¤öÂp“R øî~—–‚-P°"& Τ¶ë&%gï“`fýaw‚]®¯©©%ÔJ0 ¨J¬Å•´úÙ…uØô’ ÁxŽ™b" g•$Ÿ %1Œ1Í1•\QAˆ0J%”Ì"¨V#$¢UôÍí7~µ¥fŒä¢mÛÅ®!Bˆ`¼ÑÚh¡…Üõ[ÉùýÝ]kšœ"Ð:ÎëÇO¯/kp¤úÒ™ÕÌ­-ÁcÊ]ˆ¹@(„?Üܧ5øœ.vÍ8Á4Ñ#LKª«4hsL–ŠË§/O¯§u y…0ÇÉg‡)(M7ƒi;½Ým”ä(eRQpIɦ3ŽEX"c:%¨9·Z%„¾ÄþfHà¡z­yN1ÿ&÷—ÌÒJ msè·Fˆ#R,³#…¸%}\®¶\Vï08ª@µ¢mßõ-Û÷*»°ÌþÇ_¿úD7÷Œ £èa7ÌÓ4-)Eœ õ9ûj)«ó׿ûOÿî¯o‡¡U8W?¯Óùz½ºåËùõe¾T\ßî®/—¯Çk¥âîpG ýõËãOŸ—P(ÃÍÐb ”£œ+8Å@ A)ØÍÁÙTpÎûNÓ¿úÛþùËkƒ5/Dª†i½¿»Å¨Öšœ³Á'¨LpRJÑ6½Æj©œ0†* x-i­5q*ϯÓ:{Š(%@Ha ».D‡ #%\rÉ(’’2ư’†sE9§5\0*µT¨@±ˆ>K.  F‹Æèò~[pÝ¿Ýú¼¬nÅ„îînä`>?L BûÆ û$(B•j^¯§ótžçqh;Åäß}KPÊù¸,O[®ˆîÚÑ_jMÎÎó|ÉÕE¼Þ¹ñr ÎÎó{»RœQ)ÖÏ_¾þýHUR¤qE7oßG‚)CÉ­n]—›~Ç(!RÎ3˜É9Å… vsØ–”aF6Þ§Ëäl@›Ý-Ô:ŽçÂêW"ârvö»ïß_Î'ç}(eZÊ1¡Õ; @ž_Î9³Š™0ÒÅlׂAÊ®aš•»¾“J¨F皥dv%@+SSJ b×:½®/9¥^õ[Ýn $SŒ›¦í´^ý ¬2*¶ímX¦ŒJµ¬¶Æ<Í×T°é½ÚtÎ{LqCÞµ»ËËñ%Å„ /U6®Ke Zkà´êVTT'ÓÊqQ))†RRÊ¥ò>NãØ˜qqáŒÙ  ³ZI.Ð ûëâÌÐ ûv¹Œ±dD¨“*…V¢{y:¥`Q…˜pŠjå’I# ©Sˆ—ÙQʾ}ÿ.¥h§5Ùˆ .¨†ä´n›¶’0I?|w;­×ªøúzÖXN¯SX“[½`œj´¾ž/ã2ÉVß<Üe æ¡i8'©T+§"ýn{ •vzüÈWšw‡}ÎȨv³~¼\5»Í®²„UåF¢”Q,êùxBGn´éæÙÅnn:‚br+¯´S}«Œ²ïº¦5}Ûe г›9“Zt›ngÁ'ŸKÀ<ûJ*k›.•L‰ð®Lã: ƒT3Je˜QJ©äµTVJH'»ZK,Qp¥–RRÎ>$ë\.jÍ Ñ Â1†”<Ãøf{CÁ‹]*­®„q¹&Hݦ¥ »ZLhÑû°x[ ЂÁW¥ ‘ŠÝh)(®.{—½Ð²šûÛݶ5ÊèJÈãùtq‹ÍžpŠú¦˜k!…”Bˆ¦i¡Âжû;5Ý:Ùr­¹’‚Xñ9b*r†ÕFÊô‡‡o:Ö z·\—ýfÛ6JJ„ýÐ1ÆrHŠÈâ ª1!!B¡¤àp×ÜÝ™÷÷ý]/ﺶ×ìÍÝæ»oß]ΗŸ?½†x´Žk¦ C8sF7›wvœWnÔ»oot›†Ž”4ÖäPÃÀ´¡h¡(ÖÜ6 Åè:^–i’R_Wÿó×ã4y%Øáf»xgs½,«óÎh¨¤’]*@h 0]ÂùÇ¥úXÛ¶mµ¢¨ÒýŸÝm7ƒÑJp¢%úN6äâž .³\(! £Š!aR…b‚B’¼¢½>/ÑÙºÆÁg¨L5" °p÷°yÚ´MvX ¸úDR‚©®Ô<4C^s'ºõ2i!Bq/Ï'-Éd-9ʤQM£n‘FH›÷[q_B·»¡o%'ˆQ¼ßm¥”ÁFAÔdíäÛ÷ÃO?ÿìç„÷ªÈBÑÇ×ÏÛ›îr}:G)Û¾B˜½wJI.X‚øº\c¤‹]|´'Â0&@M)-vÔ Ýß6@ìjÇeºRŒc‰1ú|ò¶@)¤âÖ¯§iL€Pû‡»7ïÞjΫOµ„ÕÚ y2}°øóñ¤{Ó62d»z‹JÎ7·}¿³=nwójŸžÆFmÂìRˆR4_ǧ¯ËÐîŸW)ÕÅ…ÉÙýÍîp»Z§uRºýã?þÄ·ÞQN]ðXc*1Áa©‚ÝhÚ€Cë4u¦ÕLk¥wÛ¡VÏ8;g·ä®éc­%?%Rén¿m÷ÚÛôMAõõøº¿9ÔZ6í 0+©,nõ%ÕŠj%«ÏÕjë,çÔÅ8Ûm†_ ͳ¡bŒåÆH#*Ìp!ócyyžnonÛÖ¤‚\b. a;ï0açqÄ61Ùδói¥Eov†›;f¨è(33Ô´Æ[;˜.Îá׿ÿÈ ãTb Ðxš0p)4—tØì[s›CúùÇÔ†lYKr)PåËë (Å”®Ë¼½º½>]¯Ÿ¿¼êFK%Ó‚3‚!Æôü8Žc=]/7w;JÉ4ŸÇiÚíîqeÅ#F›’¢wÎÙsFi®!WçìâW»ZÉdñ „T !¹’Œcüp¸#ˆsN¥DjZÓPJc©£MׄârI˜‚² –"B1®a,À®S©K–R€ñׯ¯©B ‚Ê Î;çþüûïÿîŸý®ÛÓÌÖ*¢êe%ùt~Áœ¾Oëâ“Ë’òŠ3Æ€~<¿ŒÎ–Š%—Z²i¹®)¸àBŽŒ0It±¨8ʪh¸Øïú/ÏŸb 1&(Xñf3l}Œ±æë¸¾<Ÿ—År®W7ݦcšRšQõ8Ƙ`MÓø'BNŒŸþøñóO§QLåz¹ômw³=ì‡<ÚC- ‚M9ׄÑÕÍ\‘¿ü‹?ï„–$o¶ü°WûVõL"Ÿö}ws³í{óW¿ûþ»oÞ}}~ñ¸ Î]×PÌ”šóF˜Š}¬á¿û?þw%øä–FñgW$ø0ìŒnöÛ=ÃÌèæýýCtþëóKÄ1¸NËy΋¯¦•ïîwËt™sv¥Ž!Å}• H@0]|:úeEœ\)X1Bÿûÿþ/ûäˆ1èZ±¬'&&iF0¹5"²X7OW¦(1øëÓ3Á2gªU'™FÝ<¼WK|û݇”A5Ûv¤Fþåù eÜÈÞ/Õ­‘ŠM}÷»Ö ŒÒ”Ižk]W‹E”pÁî—”àl~sÛsû½1M%ÔMÓëñõùÛ·ïÇËøôt|}¹â·͆¢¢4aŒ|y|ºœ¦qõU¦UK íš–fà-ã•0&“[ÖÐv»\Ðõ:¥5CB¥ E¶N—3gìpØ·mW $LÆÕå‚´i|ð*Æ„SŽ Ú`kÍ!†\°¦mOî4^BHŒHJp)yZÆ_~ù©ä” ¶¾LS²3êô:—׾㒦TœÏÀ8_½½Ìë—OǾÎ/××çã·¾Y§ån{›]ve˜ÅP 5£ `µN1å&7´»¯¿<ÿò_ß>$W_ŸOÓ\Šóé2®”ìüzáø·Ù }™O–‚è†ýÝ7ïBÌáP •,–3tÛí?üü§ëì¯ãš 0Åi#¹Ö°÷JÝïv^×Ù®óŒÎ+AÕífÛµåâåx”L `JhF©àl¾LÙy(¸ÿf0Û˜TÔ7=“´¢Ò)ÙkíVçBö./k(˜P®^ŸNÙ%ŒÙ~¿“’|øææºœ¤Ù§øûÏïÞ|X¦¹ÑœðÚ íérŠÕià&¨0l·(Å®iœâ‡oßb‚r,‚q!h×ki¸äŠ#˜ÎvÅ3IRIwo^./››ÍáæÀ)=ž_sMʈZ£ ´3½ Jˆ3ê²ošVIE?/¿õÇ… R2Jùìæ›·mË©IL@+7~-)WÕÝö㼬ËôpÓŸ~üûÇñw7=•Ô4[)7¯ç‹Ðf™ÃçO]«úF2„ƒsûþB—iõ6·Øq^ýurƒéî÷w˼œÆ×„<ਥ·„3)m£Z£0 Îx'ŒQ-!˜¤¥Ò¢%€½u¸"Å”¢’E© Âk* ³’Ó|]·Ãý<.¥f.d-x—Tê´Î6Ì@j)±¤¬…dœRΖeþúô9@è{ýöönc:œ€"X¡Bö¢a¬¡ºaÆÈylˆT Bi­Å{‹0Š)&€RÉÏ¿¾áó§ñõey}=µZýÙï~茱ÑcÉ&.¸Õ®„Ñ ìéé„!B@`’|\ì*µþáw¿ŸŽ×ÕZ„±àœÄh¹äsŠ¿¼¼|½ž¦`3†‚Éé4¿¼Ì + ÜÎɯµ´Z+ßm÷P+e¤3f_J‚TH¤ó5OSb´]Ã(æˆÒ ÿüÏÿúÃÍÂPTŒIÊ!–Ѭo…ââOÿáÇå2­ÖÅ„B¨ëªÃ¼Hä]·k¸¹çÿXyŠ!§(ZrÄ’w&8*Ct#R±T¡hÛ† ªRá¿{wWr­u®g<Í!‚§ÿêo C¥HKqÓRQ¼+‰§€wûû~ß‡à†®9ܢǼ•Ã~û`+I¡Ø?ýückºËüéáfÏI©ÕŸ(s(ˆ`9Í.C’ß}¸×ëãóçœÒÅq»ëÚNn÷fл®WoÞJ]Þn¶YêˆÈB¹eÝ8ú1“Ê•ôaœ)¡ŒêïoÞßïót™ÖÉÇ@âŒ3Ì9Ö×/Ÿ_N/¢QM+ÂwžRʼn®©];^NóêPÓ´жß(áÁÅš½_sˆ¹èÛ¶W&Øøôx,‰ÔHJB×ëZ ¥\!Äb,ÑG@¥àÒt-%¬o ·ºÕ®^ S2T ©¤M?h!¤ B–ýzûf ¼ln÷Ü ¶S×§§3)&,Yq-©¨ ¢/ðo»®mZ@xZìežæu<<Ük…»N†´>¼{°ÎÏëåeÞu;£uHžiýõÓ³ä†JîÀqƒ¥æºQm«šF4FºyúæÍ}×*ëçwß¾aݾݷ‡þÇO¿>>?þô…¢©¸¾ŽÞ'@ˆ ¸–Z8gFjAYð^)us³+$I-3€õî2Í“K€°R’#ª m:Sq½\¦b¾Ù´Ñúì’sé<Û—«Ýo7dgÚP[JªØy? úÍ»[`(WøôË—Nu‚!ë–˲~ûý÷ç×`#÷>`BKÅó¾žÜÓe-ßÝí)ƒ¿ÿõ—‡wïÇ\¥ˆ!J¶7›PV!aØ4”R)Ì4O³×s-ôøtµ×°oa.ÉáTH¥jµ¤ hÁ—ÓõéùTTJ÷÷‡\‹Rænwƒh»Õ¢DwúM ˆ¼Ý4Ÿ¿üŒEiu—ùüøJkû†pqó¯Ÿ)ÃÚ°ët^V×5Ý»7‡~0×X“+1aÔm†\bÉ^й4ý¡V*i£™"”# ›á°ï÷0gLÊ¢MkO󶻡LöZ˜^µiMZ´§óù:žsLÕ×^l’O¯Ëì³b)iõËe|%aŠ¥œ³ ¹ „9\ç5טҚP"µ.´bA•lb¨ãÑŠ°Ùln%—Ûm×µbÛoi o£+Páöþ®7ޏF0¦Ûµ¯Ïãù:%\= sO—3ÂÔ®+â–DuÓÁ ªRpL`·é6}ƒP”¹ä”¢V+;M§ë1¢û`#˜‘Õ®Z°ßxhÌnÐZÎY®õO½ºi öóñøóǯ³K„ÉÝv¿o¶ßß ±ØË¨!®—å|ŽO/öËóü:†óìC )‡˜ýñù%.Ed¸¶ÁGŸìb³Q1×”S©uöáâl¥ š¦m7‚ªù2ýúËËÓãé:.ó€Êë:#R›V.nñþOÿçÿË~؇ùÒ5˜‰¢Ê fš*Å(ʵ$A¥T*ÆHݺá¾Å2Ûd/Ö&,èÿúoߤT\Þ¥ €±.•X4îrÂ)ó|IÙ÷]‹Q–ú–·­¤¢lï{Äðeœ¬µw·{ÓК¤f1RT¥Z Æ+%•äW‹r©Á“š*˜ÖTír}MãX B%q’•Ä«›RŸýT#ä„RFP±‘}°¨kûËñ\SîLkDƒQZ–k-%D›²'¤ŠR)Æ.ÉùzîúM×m¸ktŒë˜!¦ µ„æi§‰aѨ&Å8MSA؇„0Á„(-1×e¼ŒÓººíf £„+D„ >£ 8+. 0»Ø¡×%J‰à ¢@•3Ù™¾‘†`Ä8¢„ÙÕæ’ §1®!X@¹iÛ¤D‘Øt[».ã´”„ !Šù~{ ˆ`ëäþøÇ_öû[ÆÔÃÛ7Lã¡—9[B0åœb@BÒc×ìZÓaÀZkJÐ`¸[–ÒfØV€àC-ŒRùþûw²Åˆ£‚â´¯×Ö L*,éêí0tMk%O¯§øñWëåBKöîþ@ ʹæ¾o„¤P2†ºé‚qÊSÈ5‡bˆµF°¬ÑŠZrXPÀµ”5,1ç\ á@PE :Ý7ªSzûíí÷¿¿oZêÃʸhš]ã²ø›í~hÛoßóþ?ÿ^Iõpw»oTô~^Ýù4µ¦¿´ç‡oïÍ¡}øð¶ßî¡RJªÈzwsØî7-Vl\óËËu¿iJ ¸²yrPI.€ì†N2\t.=>ž)gmÛH!ß¾y»Îë<ÛÑrõ+%Dk±¸8˵2!úíà‚-œwƨN5$’ê3e¨ ‚0¸Ðe^®ó…*ú;N˜Ó°ÓéJª¤XŸó²ºýͶÝhF1a8•B×ZpFgã?Ÿyú›¿øž±œ_¯0ßìv×qœ¦ ¶@kc­´é´· *éõå±–Š1›&w³½¿î$—LñóreJ¹à1ÅRŠQNÉÐv½Ñ†éõê¡|^F”Tœ}y 1úçyfŒgïgF6/—8×ä+#¬kÚ_þô')4l^æûû·v™½µ9ÖËeRºéº.zg´À¤H%ŒlZÑvÂö!R6BA‘¾ëkJ‚‹X©s.å”c©™ä ¯—“«~µÓ:Í\ßÈ7·÷Û¾o=ÙSBžp´Ýls,.æŠ1ÔÚ)sÓï;Þ ‹_Î)WÁU©—J3ÎTÓSBsе¦Šª1åsê†8c¸Æ‚’-K• %£ ƤRš±sažì²XΙd\Rª”„mûÍa³‡`÷·»®SŒT™ä¤i8ªåJ ÓXlšM£Ûʲ†\3.¨UÍõz:¯”Êó8ºÖà\òPFH8Š41…K‰œÒ?ýøSô‰U¢'©HBg.æÑÅ˺œ—©2äK~< ª­îŽçe¹²1Ç!…œS)Q^ßÝ¿ÿþ‡ÿ¦”Ã…Ór¥J*ªÀL0¼÷Þ×RÎãõù|ªŒÝÝJÎ>EÎ`ÛÒ7‡Nprô9 Až^ŸF¿TRŠ]»‘ˆP\(Á%Fʨ02CŽ9á?=Gâxu‘~hšNÐÿâ?mbN!Ã8ûÕæá„2l½õ.ºTS„uZÁs.«O§ëúñËë&ëc‚KN%iƒ@öͽ”;—ð¢v:¿Óf¢~ýõŒ‹PLÍã5×Sš—Õ´F(6Žçe™8cË2ÏË„0‰±`L‘’È’ g(€ìº†+© Šó>—”S’T´ªc\@N)†\kL¥ÂJ™Ývç-5cLš¦ÉåêúNßv8çݶ)$öËzE¤úc®JêŠðö°·É‰ÏËüËç×óÅ)£ÅF™QUêsîö@ÕZn¶MI~¯]{¸ÙÝzŸŽãæŽ×åJ™4Æ R*&³ „!ÉöæS<ù3ÒÔ¥òùËÇïo;£8Â×ӥѠz¼Ìwwûi™ ¦Q#»yt\èãitÑëÖô[ED^Ö%§ZŸ¯cÊquKHîvxúú²Úä3¯3ˆR9‘ŠÆÛÝn]Ý:¯——£b\1^r >ºÅk­)¥«u¹À¼ºTQR äXV›|„óÕ…X×5¤‚™a´“ʰ¦`¦é+жÙüüÓGÓ Juëj}Y+<å³È…\4¸½é”¦ûû½EaÅéá»o…T‹¿Þv›»ŽvÜÆü»?ÿ³üÓOÛÍÍu\šFW”ºAjÃLcö7»ŸùUqÑps³Ñœ"ï\I(§úÛècý’ºL^*]jqër¸Ë± 9V_`œ–www»Ãe^Ã?úˆJnµêt#1ƒ”ö› **iÝZoçu=_g£7nq)„éxÌn»;„ÖeÎXÕÑ×R3e2–H×H8S㴠Ƹ ~œŠÏJÂI”Œ!Ú0Ê$bÐû};#¦P]U 9G””œr~=]?=>WLB,ËêÆitÑR1Eæem¶E<Ì1-y>ÍiE1-ÊH£ºãùôÃ÷?4²i¤TשMÓlFo×è1BÑ[ÆHL5¯ÀºNk®SÔ¦¢*µ,(¦ä†vƒ^¦‘RÄ7F‚•’„ BB©ÕŠk9gˆ!‡ÜhC 7ÚD9T¡ÖZ §šÆ9AÍÈÛ,h×7}NIrµ.áë×˼$mô04qq×i]ƒ­$³ßr!AbI”Ãøfh»¦ .þñã§ŸŸÏ«--ïž?? %ûM$sƒ·{Ý.Þ:£”‹)‚b­€HΉQ„PAqLÂârÉ“[\ˆœÑeöÁdX]ªcJë´Òˆ@®9Ôj=-k³iÞ¾¹a$^ Žvcº¾E¤Hfкì7AÎ N´Raըݶ3 ׆ßì·ïÞ?ˆ–цeZK äô_þm[1´C«´6aã%6Û(d3lvº1)ÇRS,™¦;m¶êðáIF€…Ðçã5¦Rÿã^Bmû.¥’sáˆæ@H)%È•cL[œØïwÈa{Û›nÇœ‚uëù|j‡S潟.áæp›k¹Î#7*ÖDçJx¿æ9¡5¨ ¤Çå|Z튠²¾ßÚVïg©Ö˜ òõõ\)•R )ã”ðRI-ÅÙc”sQ”B>ÇótÉ9IcðË<)ÎÆŒR%Õår]­•Z®ÃvàB®Î+Óìv[¨Y*æÂšŠ¿œ’Èûá5cÜõ;Ù4”B悇c<§Š€ôm›*üútüùérœ2A Sú:M6ÄakžNÏO—«ÏtwØ~úúËf¿=N×ùòæmÿþ]¯ Ù½Ÿ­mp©”S¶ÁûŒ¦9ÙÑ_Žñ/þêïDƒ_¿|üµ3gÄ(ñéóׄ+õ|zÞßmß|óp¸j‰C×¢ZjM*¦j!HÁç×ë…P|{¸ÌFʶŸ° y³ÙëÂ9güº¸šÊÁ7ÚlšÖг DsÅ [Æ^ÿíï×2+„aÊ BJÞß¼™¿¬ÓùüòöáC AHhzŹv>y¦¦í^¯—_V;ÑßwÐxžžž_77?ýôz ôz™i’Šq0 Ã$Ú™¡"¦¥’\HÁÁ¥uuÃn³ÝuÙ'wõdßnÞЂ«jÌõ²zŸ5oK¤ç‹¥@¿}ÿTæñøüxyùúøé0 ·›lWSÜìvŒñååò ¬d”˜Öœ+ƤÏ>Ô š²tÍ@*Ë)Íf_rA•R “„¨œënpÅ®›a0B¶­Ñ­¢£_¾¼<ì-ˆ`ŠEæÏÉ_SöuÍkÆ©‘’ÔÂxQÅ AJ(8mz5)I†Ns™…B€âvèw›-!EI¶Ì£Ðdò—KœÀZ Ã¥æüÍ»ÃÍn³ï65å——ë×§ãëõØví¶Þlïª/Lp&xc4áìÃï¾Ë5I#rMˆ€”jõ1åcq6 !pZ‰fZbA2zx¸[—5¥¸†%ÓÜtz¿Ý§CpÚ4Œq†‰à\7Š+ê‚C¹4JAE!æœkò¡”b„Þw7ÕÒës|yP×(†‰sþx]^/£i Å}Y–CBPƒMI×ô!dÉt'»`·»yûæÔÂZ$ÚßÞôý6¤œQÙÝn*„ΈNñ›m'91škÉ¥ývÃf¬¶Øt²5dÓ*ɨâ,%OåR­)d…6ϯóiZ<ÓwwŽr†ÉŒiÚF÷-'4‘‡Vío:!Th)$«P˜`ʨ~;`ÀœI*—RJqwsÿ0DB‡~ÿ»¿c•âT5e govÛ···»¾£(#Hô¿þ·RSÓÑR}j] ¾pÌàͶג·Z§9åµPɵ ¬¦€ z¿0BzÝi¢Ñ )Úõ[Ù¡ëu¦@0(5¥\* •0Bðx½]o¸!¨ÔèÏ/_œSñ¤%Õ‡wï%e8ÉÀ4 ‘d:AHÆqÁP-*Ã(û¨•ü J-óIDATqÎ_§¥mûÝ~è7’r8ŽG*f€QM£ZK×vK¿”]{ߊÃÍþýËåår=…h¡V!dÉuö~ I2Áˆ‚‹‚‰R(øä\hÚM©èùëK$ØÊ©òÎÚy‘„H"þáùcÍåöp@!nd³m†€aúÓOŸÚÁ´-Éû’Þÿî»i£ 17E årööùriû.ßKSg>C«ªJ%pw·´æ´NóËÃðوCßV7M},Ç™I%”’F6¸^®¨Âëy¦½ž¾”µP—qñúaûøüz8Ü;ïÇuƘþüã—§Çk«[F…Ôbw·e-½ÿæŽqšC¦H9æ” #Ü^ýrqó¸ÔZß¿''„¼#ÀÂŒ”\I¥œ(($§Ê…¬qŽ»^IÍ #„bu:€Š(†ZcɇFéVšTW"3kªH·og{U-Ùïǧy:º—ã6NËÓñr¥ a¨ó4cÖ[*u©ôùûß~{S²]¦yè{Íy#TtÉù˜sÎ)SÄ“£vßrÎ0ªBRn(7P¡œšNû;Õïõe9ßÞß)m®£ýòå@ûˆînOëâj ¦•á»ÝMpqµn\VÝ·ã:J¹à5*µo{Óu‚‰é-%­Y0ªµ¨5…çu%€úΠ’•”¨V.hÉ>Å „Úa7ìR¬»áðæîÝã—§ïÞ~WcñÖ*%© ؇wß-Óœ‹‹9xçíd“/’(#{HtºÚà ¡4ä˜k²Î.‹åTÍcüû¿ÿøùe½¬v¿k††Õè ®Wg×ëÝÃ!÷éËëì²6šP"8_O×ùî›ß‘B(A]Û¥5ìÚÕpèÞvÑ9­%e`”ؘ¶ÆSH¨R+oáZÓLt½Úm§• xhz†çBjé$ˆ)ÎZ#05˜ý›ÃÛ‡÷†‹¸Ì„"ª¨4\( ˜æ’… ·wû·oî»®¹û0l:-DNq\®™À»o>ÜÝÜ7ÔÐ Á®˜Âáv¿é†à£$Â-ÎÎ+й×}«úÁôv^.˹QjÛwµ„Š3ýoþß>½\^^Oª’t·ïÛ¡%)ÍcqŒ³e\PŦm)çVL‰h“œF‘,¡b„ÚAdAx͹–‚u)Œ³'D ™¢n×v­ÔF®óòp{{zy¾\Çãåôx>M«w®VD £b#N9§$­à* LÒß’Iˆâ‚%q-®ó•B…à0Ê}£0'¦×˜deH(¶@¢÷cz‰0ò6¶÷]·¶ƒËK!©íÛ] >çz§çÓåzµËœç%L6ÅŒ(e•ß&x”ãu|~¶ÛÃ8®Ëì¢/œ·„éñ²¨¦o´YíRq©P0&ˆ±Ó2TÞÝù”ׄD#½5#Åg<¦ˆpY»Vi.n6@ʺ®JŠßÿðf·]+‡M[ ºeŠveSƹÐ5¡ñ2BF5Áå2.KÜ,SXæ uëÖ¨ãöÛ¦oåíÍnšÖ÷ïþ5FĦÝýø¿Æ¥tMÃÛæóçGÃuÛôSBżXcºiœƒs­Ô5e¨h]¼ÑûŠ‹Ï–bÖ¨¶SÝÃíä<*­Ìuœgœ3„ ¡’N0!˜Ä”¬wë2cŒ0CçXbˆiZ&* Ä¥D@À(¥ŒAE.T‡:ÙPFVª§O—œëok…6¹BAu¼ÇþŠe@4QŸ~úòþþöÛo:#ª¤¢mAØ/ž"F-jD(Êa³W%‚X?mÎ4á‚dœ˜aÜ0ç]Û6B ¼SœúåÓ¼øãy&À!“.0hÕ¶ífs«yWJJ%¦“µ€aúåóçahG¶8Õig-ÓŠ(ÄÕçˆçá‚JY°.„˜oo#)å¼L/Ç—ÅE y:.!î¶ÃFpÎ?}ür·?ÄÅ¥1ÙS˜/;nšF-v!”]§ëéüº,sˆuõ) ”X;SFŒ2´âÆ4„"ÊhkÚ«óiq!ÆÜèîåùôúzœÖI j!JtÑ××ãÕ­Ñ-ÁÛ¸®««K^µ¢’cô”“Póä-æ,„€3"ìó®ßqÊûfCŀ呒ÀÛ¨eƒ*\¯W)B™R‚16ÊÜßì÷»^kyºž¦5\×ðó§Gàâ<]”Óuú§_?¯˜ÕeqËš/ãJE‚þøåéy­>ç÷wû}§¦e¬T«e+SŠ”—4Œˆj¸<=€±EðöÝÃûõzMÞ*BiÞ4¬P7Îv+‰„A# äꣃZ¤QMÛ`†×ä<_áñõ²X¿ë‡é»a£¤l”¢œ)­”’ót-c*!¥¦Uœc9Ù5:G (Å$£’Ë’Q.…P¼ïºNiVàv»Ûµ’*¨”h£Þn©óá|”Ñ‚ÿœ|óî›ïÞ|øý7?¬×õ|<_ír&Bȹ5„!`l˜+úoÿõ¿ #ÛMgp‰û]Ÿ¢OÁ­JJ’ªyr/Çë´,9%JÐíýp Á??ÕI) ªkX3dʘ÷ÞÇ%åB—€¤aJ%ȇàÍÑùÅrÊggOÓu\l·½é··¹ÒÍæ@ ÞW¨.¹J¡ à”á PWš3Î0$Éh éø»â9É#VåŒö½.%ŽÓu³o1É.…_¾\®3–ª7mûïþßÿæíûëezüò"9o; $’ppaPÚñzn{u;Ül%©”|Éý¦5ŠˆJfTœÎWïX¬%Œ§ŒRÄëR?:»€»¾O)1ÄÝšì✋×ÑqÙZŸ“)Å’JMÅ­ž3ÞLY9-çÃa»ÌËéx§ðüüùÓ¥j˜fC냵år¶ãÕaDÛ¦Ï95ªÙtÛÛ‡7ÿðñG¦ ¥(ClzÍ)5oŽÃ¦cBhÓiiÄo±KÛuR²Ý®K9 ŒrÁPrT‡Ã&Av9 NÁgÅÛß÷ãËy>/~-v\Èqž3IMßpB¯Ç‰bI ÉÙÁ‹óûÛæïþù71Ž¿~þK ±¬³åLä\(·×çSIŒQU¡¸¸"B*†X2¢ÆŠI13¬¦£OS%…Q*ðñxƤ2Žs®)¤FɶUƒQÙ‡Õ%„ÄÃÝ;€¤¼^.Óâ(ãnõÇ—£Ò‡P*h¡ÇiÌ5j-æi¼ž¦^5R}o|qÐeº¾yûæåñˆ .m6}Êî/ÿêw§ó“Ô‚ öüz¼¿¿ZÍÖq>(ÁkN)æ’qŒ>FgM9uÉ!„‚÷Ñ9\ ‚jIÑ®n"œTƒ[½[}ðÖ9®˜T&˜LÁ7Æ„è.Ó)¤µíŒ!U\[}ˆ%Ó´³w§å¼Ä)#¨ô2J-3©‰8шŠ+'$…”S¾º5ÛÅ{¦iîx7¨~ÓtÁ8¥0-ã§/Ÿ ÖÝvך¡o{¨cÌ!Dg‡¾Ûm·MÛ˜Ön+ä7w·%{ e{è1‰J‰\à4Íí¶eÙ÷Í¡**ÓlÁ›VõÛRîwûš¡°? Dr#y/ÊÄ0³iZ·Úç§×Ç׳ *A…V·ž×9²<æ™jÚJͧé´Îª Gض½QD„¼Žv‚Q‚SPJLrÊ¥„+¥€p9Óêâ䫈€KÆeõ+ Êö֭˲Nkö€“åŠJ .–P4æî¼\ž/ã´¬ÖSÌW›¦¿Ý¦Óõúz¶Ó\SnŒ.LÛQ.˜d×*)5üåúº„P¥ÿú_> ‚Äóer <GŒª”sáCüòñX*mƒ(I% A ¤Zrr¡fTr&$!Z‚HŠÑæååU‚§Rt×Þ½¿¿½ïµ!WJ¨uqmÛ·kX6»#¤† ¹£…fµzDJ®!Õìs Ólk&‚ËÖ˜¾U‹¹¤ë¼¢Â{½Ýô[IeE0M©$”%”0ÇBˆÄ˜Ê*Â!—”Sð®ïÛí~óËç_~üåóurBÊa¶ûÝé:bÌ £Þè›]/9*%l†~è‡ýþcž \ŽÇF‰û»ƒnůŸž.§H*çˆK&K®1Äš£àôÍýne!èù²üéóÕ'úp³ézþíw7„ÂÓã×oÞ½Õ¹\¯P1ì¦ÝmÜP$°ÑŽRkX–ì,j»3ƒyÍ* Wœ Ա뻻›Í´œ Ìøüu9÷ƒä´b(×˹"$†Þ\®ã4®ã¶£RàíÐ(Í6»ž ƒ/È› ' ­¼ó¸ †eI¸Ôöóó²N©ÄyÇ㤵iÛÖùUwFµ²æ¦ùéËÏ 3gh;lÚ¾ ÅSR‡Öhõ[(cJ#›VQ†½ó>ÂÔ"škñ5a†¬uB(©•T®kß SŒÑ²LO_ŸJAŒHÊU¿nvBc%XÃUƒ]â›Ã݆ó^Šó4r£n}¬®@i‡A7ý×ϧÝÐ ‚„@6M¿éC´M+ e„Qft›}­ ·f¼U²M¾â,2ϯK*ãâŸ^NÁWÀrµ5$$o6¢a´k{ëBÎ|ºvÓmçqAP¦ë²éöw7ï¾~9–L¼]ÁŠ3TжÛ"\CÊTÌiÅ 0J‹àÊfshÍî矽xóøõ¹Õª&”œ ûá›ÁHöq±ŽUpe#Ž3¯›7íáý³Š(®µæœwýb%•__´!R"Œ %„ Â˨&« ŒbŠQN1Å@¡¸”è[cv»=¦üË—SÍ\³æ|zy¥ Ùä}LÝ0ÉB‘ýv[KUJ•TZŠ`ýrvçオ¨•Ïçãtî¶íï¾û†!jGçmÏãûoÞ_¦ËëåÕ—„9ã” ÆÆëbmYÖÕÇ8·n¹œ_PûýM žQr9§qÚ})±Bº®†ÚHµ;t›ÁŒ šòÝ~c“œ„ä‰ ‹¬÷¥äöï00DhÊŽBÕXNÓûŸ^O‹ÖÃeY>ŸŽÏÇ'wž`Æ-Q¸ ˜ Z3”J&ÉMSÎC@® D*¸ÅQÁˆ @‹ ‹unÍцPJ4J "¸0J\©)¡JJpI… êÓñô|œÆ%ËhC,™Qœ=NJ©ëëõÓO_ÇÅgBúÝ– m}çõ|¹äR1•/ÇÓjí´LJkçbH©kšwoï²_Y.ÕãXö€èþo¾µÁe¨ÎæœHßÜ_NkJÕ¥ 2Êö‡Í0Æ«2„PŒ 1"„«‚èu±ËšýBm“]C¥V̸jó¶$kl”Àµ„lr˜SÙÒRÒ:zŠ)àŠH…ZÖi«]Vë­Ôaôr¾p¥Û¾+¥p–ՎËzלˆ¤­_LJïHZç b“=Ÿ1&1€(Á’I-—ybPöÛ- 4Úµ0üg÷‡þâ‡ë<ŽãåýÛ7ùç¿'m›LSå¥R€˜hÌ­·o§å0«Y@Â$ZÁ¿ûfQ¼ys£º Úîšwß=`R•1_^Oð—dz`ŠBÝ êz=5­YíµÅ?¾¼pγ¯qûîö›‡ßxûAIÖ¨ ¼<¾ú51*KÉ]£ßܾ!˜0… ýn‹$—5g-øÝa2"Yrw·:YcšÇI›–p~ÇËåòþöæ»w6žš–öCctÎ%—úë_£/w·‡¦‘ÖùeòPÑ4-“s¼QÝB$—¹Â†›Vvf‚ø`u£×eÄ¥šB]0Ëœ0\qh”˜! %U\I+†P ÆhkÍŒa uZ¦˜$)W˜cÀœsÈ¥†œrlZS¬€(•1gïSò5‡ª¸Š¥§ó¼\×ýf§9¿¾žýZ•€â‚’`bžæéºJÚ(¢I ðñy|}Z8ê#*a3F¦…sv<žR‚ZiL©z9×Ët½º§§óêÂh-•ÒZÖ<1ÒíÛ~¯u'§uŠ¥MÛ>??ÞöÑóËÜ™áûï¾›F߈m°…žB¨9öM§„¢TsÌJ¥4Æ2Y2p*—KÀÕ³?í-Á$Ì9Zÿõñ•P6ôÝÃýmÉåx>cB†Íðøõ .”b^QD¼îo6‹—y\Ö!´¬áë—WŒÅêV `ZUrä˜2PZ÷.”T ByèU-©Ä¬XÓŠa™Ëåhݘ棟æ`sMF•FeTwÃîÛwÛ›õ2–0A뺎ץ$<]לòËói]êËWÿõóâÒºQF…ä*#c¸L×O !¨ …\/ã 㜭Ë(•’Rë1hû!äè³[œ)ù`§õŠYžL+‡¡%ãJ/g{¾Ì}ßZ‡Ö0N‘j¿(Å\Ò‚J»íkFãia@‹/ŠñV7µÆ(J55][1Z}ÚÔ’¹A¬%Ínà†ß¿Ù7Fö]³Ûl‡aƒ)§’s´æ”€fm@’ TÓµM[QÅ A±Æ)AÂ.¥ÆÍÐ1N¹ BR!a|×ïHÁ¥”019·Æ§‚CÈ1ÖʧÓéå41Üœkªäöææz9Çš …Ë2ÖZP-¤–eš^Oçó8Ÿ.cð1¥üéÓÇãË#®• UJT… ?üð-ýOþWï\ô€*I /'B±6rØtºUCËqvœk»¦u ~öœPBp…SŽ r„6UÆJê’÷‰¢C„,³ûúåÙY)çŠA% Ô¿½ýÀ/¨ž®ëç§Ëç§QÁ—BPŒú¶ï[qœB!åIÊÔÛZ"D•ˆ”n}vXWÑ¡ˆœøþÐwf„Ÿ2EÝn0FaÀœ*Áùn×KC­½Ú×ktë·ß¼¹ÙwšÃn++ý 1 øÃûnCv÷›59íûww¯çÑð„oHj—r9-RˆÞb¨ÓxùÝ>T°Ë4&—/Çq Ž)E¤À¸î÷ƒâòtœö‡8?˜îþæfÛ÷%yÁT¡ä€1þüåïít¹HÞöía¼ŽF¶Ñß¼ÿæ:+¶‡Û®1¢Õ -y?^ÝÓã £árs·’"„¬s\ɦï¶wû¯¯O>ÅVJ X+º½éSImÓŽ×õç_>Ï‹oÚ^q-u£EžÈÂZn‚3JÉ ÛÓ×ëåä•Ö›}+Þ#Rj‚ÓfÓ2VŸ_¿P\0Nc”2†"`_Ãä0fµb(ˆs†P­%aŒ&Œ°¸†vè %µ’d¡á]®ø²,×Ñæˆå7û[»:·¤¸ pñˆTVKÅŒ¬ÓêÆ4Ý®¿Ýoøíû»›Ûmð6¸Ü·›ûÃ^QBSæ±J×}¿‘’1ŠZÙï ìB ¡@¥ËêsE—q,µ|ýô(¥È5_íKFŒäНÇ%¯¨&rBG¸¸„¢Àc.·oï§ù"q¼œ0æóT~ÿ‡¿nwÝËôåùø8moŒl±0”íÓãÅÏÑ/Á¨¾•¯ë庯n-«]Ýç§TQ¢±2¿Ýµ”°3äe~†~óÝ»\Š ¹®P7mC2ök:×i —ëâ\–¬ƒÌrB©B®ùt}­8©†ç\žŸœŠ+)d^Òëe~üú"(»mnP¤óK©ãñ4­ÞUòùñúO?>ÿ7ÿõûððPjÍ!ª«¯½ÚÚ;”é§_>õz³ko45P P3y=ÎÓÕÙžíñR.ÖJ.ZŸâꜵîvwÓ©W¶Ìîéñ²Œ)yètϹˆ!¥PkÅ/§×¦i‡nBx*$„eï6}gZµÝtZp•pšj¢ŒrN¥ WÙgTȲxL%rµ³nÅt—˼†©‰}»¥ˆiÝ£L8e”‘¶UJÑÃp07›¿úáfSÍT/Ú÷û·†hŽ‘`€HáRöÃÍñ夒Œ ºeˆ¹uA F¢ˆáB ¦r)¡rÆ•–„%±Â¸Á¤¡Œ¢Ê9i™ 5÷ÑRH&fks©*Wì–—ñ ŠÏ—õr\¿<±â¡zŒ çìr>/³_æŽO‹õ©ºKZ1ÇÔHñæö€r˜Ðñ/¶vYi¨ƒP˜&X!ë;s¿ïÇ«/×¹„Èœ+§S¼ŒžÐß¶ØH!´ ªd¿ßn–ùLp>Å„cƤ¦ÉZ…2L¨\‰wWžVÖJ²¤\ÇɧXQÝßw›Ü´C!€6m˜„ Â@€ÓùRre˜l÷ƒ0j¡j.›¡wÞr)‡}w{¿Å,;½¹iE¯\Ž* XýJxqiZCüüøzºÎJ7n±qÉà"¾Nþåé䌮—K«Õ:9N¥5…µ5Ïiœçãù)#[pª¼ )À­Åì^ž¿ÊN—1„Ü6Û°Š®™¾ %*-QE—× aBµ#4„ÕÕåÃ7·ïn›F÷›‘Mrñó—ÇË4K)ŒR„!¥%¡ÒÙT2hn(ц3$Éør›¡û¯þ·ÿ…¯¤Ö“)æ‚ ÚîZ­B•0àœ1Ì —¡ÆjWûùó׸f­[DŠÏ>eì]˜¬‹8ÕÉT2c U<ŸwU·º`ü˧/¦1ºQnæËäW_#* (ÁT)Ùt=`öòõ ®•V×ñ½kd«¤ÙïûÝV\zóv¿y~ʹT„5×qLðlW.çˆQ4­“M Q„Ô’ Å©&‚„[âÑóè‚‹JeTr:O˜rÙKÕpm”à\p¦T—<ä×enZÎqj…+¼¼<ÿ»ÿéÊ0*àÍ7{`Áç3¡A?ž^¥Ôïî¾Í¾¦P‰—e i~ûðáÿôS„Ôm¥„îuzý%fÿÏÿ“¿´„–kL¡FŠÿÿ·t§»rfçu€÷<}cU‘S7Õ­¶9ˆ¢4Øpà È•'pȈ"Gšd“<䙪ê›ö¼÷ëí{X¿ÖÂS¶Åo6ø’¹f²¡ªçÃnD >¼{ˆ{»mëêœV' ¡2"¬ÍÙUD(ÔRK”Š+­ W÷OÇeá9ìFçæÃ~¼<ÎóúpZÝosxøò,ˆÐZއ½”z=ÙQ·n^k-¦c&Ó<Ó¼yõ«š .±Býz^æ>—+&…Ф•¢ÇXVžŽíÐΩ¤‡§'.ͺ%¥£rÝüói.X@Aƒw+Ô¢”0¼µ‹7ÚPJKɃ_ì_Ñzk…Äí()§5‚?û†5‰„ðÓ¼œ—Ц±Qœ DµîÇãäÓãÓ9rèvëÉù÷WCÓ+¥h?¶Í(ÛÁ(©BXÏç'»z’Ai„Þ¦õøôìW&¤Ô]ßîvmÁèFS0dˆJ Á¥w!†3¬ë»ÃÐïW7ùl3xJˆfçlývÚÎ1çäJ%¹"°æTRA ÔZ¥@ji™üîÍÛo_¾Ö>Ï÷‹[ žmXæPR56»–3vº~žÒ)3M¨°ùr©”IÓ=|y¼»{\×pšýçû#ýñ·-”aŒK†!W2t;Z Ã8y‹© DP&bÍADe±Ó¦Y'‹ÇÀJFJênîŸ޳]Ö$ëz¡1xŸ¤’ˆàR1&bÜާÅù¼¹À•¬¤$+˦%j70-(#t[áBJ.”Ü]"¤Š2ÄÝýáÐï/[ŒB׊‚s¼ºm]·à|Í„05üó~J¹¾¸>4Š<Ü}M6Õ”X×ãŒàJ1МÊûïû±†æpu˜Ýö‹V&¹z8ž &„1FBu³Ûáâ¢ÔL1b€¶Q»¾Ñ’ }K[Vû|œj%èÊËÝã)FL±dTûÓ²v}ws}õøø<ÍnwØív½÷þþéÑ{Ç9 ZÎÓ<¹RXÄs–+%…à‚¡m†è‘Miú®Süy:ÂK¢ó1 Úæ9”^«Ûë+-¸’jõ«/®@¡­i¯¯.#’"IEkÚZ bC¨ŸNkßõŒ0Š„T²¢‹ v"%I.íºŽ¦1B|ÿí7Þ¯Á;·Ù_*©8Øä·h7/™ªY¼xù«yÝ|ô)—ótÆ”"ÌŽÏËù´.‹/c˲­8§¤¢›ýe§4§(•zž§\2Fˆs!¤à’µ»6äøøøh­SFRrõWŒYôU«ajš®édÆó¼sJÓyyz<3ª¢+P¨”mÛªUÇ'ª¸je?j ÔnëÍÕA 8§„j)*)¬ÁýÀi‰‚ÉRæøòvÇ”!¡@&Ü•@H¹¹Ø EC‰Þ§eZ ê¡ßÿÍËÕï§Óý|}qƒHyšÿòóϧãt}{UqÁ¨”’÷ûqµÛx¹ûüôÙÚˆ »¯&øÓÛFvmÓ7f:?÷ûþÅËÛçÇÇe²‚õ)¡u³1¦Ízë#¢t^WÆnyʼn¸í(ÍP3¢H·íüìR¬±B®ˆ&ɺãзM›RšVRÜ96šbHÖ/Çéõë—ýEóðôøñËÝÃù”8î.÷WCÓ}úøQ7nô¸Mkbv„ `AÌyÏêFÝ Æm›Œ‘Ôj¡„{óí7¯ûÞ~8´£nZýË ŠÜ?Þ׊ÏçÅ:O %•ZÁJ©¾1ÐVuói^—íúòö|Ü>~y^lޱ  ]Û ¦3TaDö»Cr5l Ô4Ê9¿úÖÈ_œAUÜ2h‡± :¥uÍj-…þú¨Û#ª•­$4J  ÎÛuu¨0Æ)&5W˜–õ¼Î±—Bc¥…¶²””±aÞ¾ü¦øXkÎ5 ÆífkÅÓiN>J)´Ñáš¡fÄß\JcÌ(£rÈ I¤B]£KJ9¥àâ|Þ¦Ó‚°Œ‚6G["ÓjóÑÆˆ¹t± `ÓbÏ.§ 18Z)* V‚kÅ\ˆ“‹kÐãxýê%ý§[¡¨µ+$(ÓR)0ª., "dÅiO‘||<ŽãX£7’c„¶m5F1B95¿úî7w÷_¸`¦i1C)oE€RKŒ NL£¨`çmF¤4­æýðwßð¶,é©â(f‚R!úŒR*”6.FÊ8ª¨¤’BÌü¡Crž—ÕùMƦ’.Ö¥\+F@I&ôÏîú4s"þÓü®mÈÕõÅãéùçOïßÝ‘Ê)H\Õy²á7oßPÃ\´Wì¸ïÚ^cVÚ}Ç:ùùáëçÏÏ7ׯJ.çÓizJx;v±Æyš[Ó¾ûé}NH0±.Ó‹—º‘9‡‚n» Ü Ãǯ_áJ ÂÈt^cˆÔÎ4­éþåOÿßúÄ×Ψž×-¹Â)ÆCi´”„û±Hµ$¤Ò¡»d\mÞŒ¬ww_¸`/^ÝƦy>Ÿ¦¡j‚™µ!úœB¤˜EWJ&¹–„ „TÁe“]2Üx—–Õ/[nÛ–”s œT(@Š6ÜpWg'§¨J6tRKLHA5ÁÐ ¡»/wW×W³äR´±–:îvª1.„àãåîºÕÝ—P“Tín¸‚B`ŒêºÎ4Êú`WÞ[aÐ P8a¨ÚpQ¨%§¦i˜@€ð|q»ÃL0a„Ôfdc.n®Cö§ócèáþ‹‘Š!”QL("µ–ZËét².ø˜€àc y]7(¨”šc%µB)AA #’0¿ùÕùˆ`µîô¼¢Bk‚RX½Çˆ»)Ü9†ˆ+Æ«·>•˜Ðóýóãý£ó^"¾¬›ìµè$’ˆ0¼­ëñáY3½.l›ý´,çó±•:‡lÝúëß¾¥ºh‚¶ÓÉ­ë›o;¹“äp¼ß’KZ²çûÇÃᢖŒ "R·„”‘]+–óñ‡Þ*ƒKÙÆNvFÓœÎë‡ÇŒ‰;¡y)1Ä€b k!;ÙjªZ&Á9\‘nš%ù?þÀoóçÕHr¢ Æ»¦Ç5EÛ¡-1£À4¯ë¼¥Q.#F¨–´¼¥ÌNçnh•–„À™SE ¦ ¡P‹«Á—Ÿ>¿ýæÛìSJI2¡µŠÉ £jŒšK¥kA)z(Õ˜v^çÝÓñ‰I9 ¦°¬ë:;‚uÁF !ŒŠÏŸ¾äœ›¾y¾®©ÞÞÞpB1%\Êëf#l¤*¨DHˆ -[®XŠ®ÛÞ5-'U@Õ *†„B ¿üŽK.ŒHNL£ï“u!ÇJ+¡˜0L&ÁºyžbŠM#†CŸq.|\«O£ åZc)±.óÆ8çœw][1RRK.1PÁÃΕqJ 3ªü”Q,8a”!(ä}ÜïÇýØ/çÓº:a³ÅºrÞ‚M•JÎÓ¶åThJµ¦Ü*Mÿûïwœ3ÂiÁ4‚CŒ†s K µOçRàrµÍóa×v½"¬0™¹ÈŠ#Áå?üͧÖNH$8+ÎHE¸‚ 4¥y!×ÃÐI+äe[cÈTJpŒ3bT`À%WX+•CJ6ø-FBÙþ0j¥†nÖ3F[­Ú®aš!N')¥¶i»¦›æó¸ë^ÞÜ„Íg)„ Ê0•Óª”ˆÎ·ÚtCK%7¢ét 4o5r%JMJ2Œ«4˜àÊ9WÆp©š¶ )­Á©VKÃ]ɳ_\²T"Ì dîûñææÕxxóÿð?þËïþéoøñÕí¯ã«Û«·¿ÿÝßÿëŸþúî§‚™Æ µæe^*à⣠am•ÔŒAª¤R’¨aú—¸RŒ5åR¨ÒÐô9$FÉÀp‰5ô®• Ì0á„ጜO§œæ˜“ÏÅ£äÁ®9æzÚ6('4têêEïÒ‰£D|"Pon._¿~ùñãÏ)¤ZjðŽÒry9V „óyÝb,ÓüžÎ‚·Çc>Ÿâ:Û¿¾»;CÍ„Tèäаa>mÇãrN%™ÎHM¤@»qÇMÞãŠQï"*8¸” 5kÝÌÇpzôÕmÃ`@Lp®9Âݼ†U*)ìù¨d;Í®i !¹–<´íôt¿NëÿüßüüõùÓýç5ºeÛ¾Þ?®«Ýì¶Ì ‹1ÇÑ—JÀ…Rtš‹CO0T¿9o3ª¼V Œ %ŸžšýSx83IDÔ aº/bŠ©XŸ|kZÅåf·cðII] ,‹ó!ÏçeµvØJ˜šÐù¼œÖ…´<¡Ì*›ó´N¦kbŠ”sm4å¢âŠk=/S@QŒŒRP!–´†P0®Þz¿Cµßü´l ÈìÂy[SŽ”bƈ’²”Â*I6®6.[ÈDàšƒlX¡‰+zyqõ›_ÿfÔý˛ۧ‡‡e Ả2žr))Ä ¦’ ˆP3f„6R•à Ô ©fÏ%†v†77' ¨a•"!•w¡VRb R©©"\JýæÛ·˜²eµ„â¶é^^¿úé¯%„%.0ŸúßþqGØ¿R0D .UPŽÅRRƒÍ5ocOû&·å²aV”þ¥)вÛW·÷ÇŸ›‘——ó©””+ÚlÀ˜eˆ¾”Å…eIxk8çpí÷@T²5û 8 1ä kt”.¹0‚išŠÃr-„ñT@j.Õ ¯5Vˆ@q @[eÆvšŽ}k”Öóê>üüøùÓ9GzåÍ YsŽ[YŽóùiÅQŒƒnsnwãn9N³Ÿ>ÞOöø´”ŒßüÒ »ã´~øðäV«ïw="XJƵ‹›OîÐ_<<<ݾzõîýç)Ïœ\*8—ŽS²•Šiûñw¿I~Å!~ÿöÍy~† 廋!–X<‘]Œ—ßÿêËý]Bµ1FPÖ)&¨F·Ñ @Q)u]לBÓ©Ãõr\ƒ§·œ‚ѪԠ4?M'!å0Œã¼µ‹T̃1æ‚c'{¼[Ì^š'€°ß ¢5bWY•ÆhÍ´QÁT²â‘L1J>p…û %ZãŠ9Áœ)2TDaT Ùg`&¸4²i¤ÔEŸKÖF7}K(!g­Ý‚[»Q\$£ÓižN FŒ3NÍ ƒœü6-›÷?}¸|q½¿¸‚¤â»]×ïöÀøoûûï¾ý»o_ý#÷´[ð6Ç/_L4ÒôxLô?ÿø_ÿùÿZSðB&æ¨Û·Ö\*.©ë´P”b„Q%yï1ÆZ›”Ó;Ÿ}.™†GyÁ8åqhû^1 €7;ÉUIÕ%H§yjŒ¹¼n#ÌzG²œç·¿Úw{¦$'%ïô®C?Lç2A¹p‚$£áNëÓy¦ýôùñý_¾¼~û:`õvl¯Øî¥ ©ÜÝSÖѯ÷îý§éãƒ}˜Ó– —²Ñ’ :Ž}Íd}ÞXE½6!äR±`•l4o‘PÜœb¦˜æÛ—;Îw6† Œ»ëýpe'; ru¸½ûôä=œçíÓ×»›W—¯Þ¤‚ÍY·Øm-ÿëÿ¾ûù8_^íºV)Ma_êŸþüóêJÆlqù_þßOYÖHâ–\1‘McZÃ9;=?mÙÞ¾¹¹Üûýwo^¿|q{Áášø´Zg)ÁÇ‹±SïôøæöÛ÷ï?Ä\žŽççã’+æLŸÝ¥ \›¦Ýq¤(f6ÚÎtJ ±bÆ#­„1.hŒQp0Îb ™ ª%Â$¥ c¼­6eØ\¤Œ5­È€RÊqbÆaõ>ÇÔ1QBŒ)B­Fkï¶­³]]¹·YkW*©ÖBrª¹”\ T ç/÷‡¾{ýêżÎ>Yˆ¡–Œ83Ç“‘"ÀÃ0”\ÊyY€¢ŠjA%ã¢í:³ÛZq#ù®o5ãV½–”—4Õˆti”JÞ¡RrÊíÐU 6»ýÍáåÛÁê:B¨«CÿT:b“㢧IEND®B`‚pycairo-1.25.1/examples/cairo_snippets/snippets/set_line_cap.py000066400000000000000000000013271451476466400247760ustar00rootroot00000000000000import 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.25.1/examples/cairo_snippets/snippets/set_line_join.py000066400000000000000000000011011451476466400251600ustar00rootroot00000000000000import 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.25.1/examples/cairo_snippets/snippets/show_glyphs.py000066400000000000000000000007761451476466400247260ustar00rootroot00000000000000import 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.25.1/examples/cairo_snippets/snippets/spiral.py000066400000000000000000000007751451476466400236510ustar00rootroot00000000000000#!/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.25.1/examples/cairo_snippets/snippets/text.py000066400000000000000000000012161451476466400233320ustar00rootroot00000000000000from 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.25.1/examples/cairo_snippets/snippets/text_align_center.py000066400000000000000000000013501451476466400260430ustar00rootroot00000000000000from 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.25.1/examples/cairo_snippets/snippets/text_extents.py000066400000000000000000000013171451476466400251060ustar00rootroot00000000000000from 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.25.1/examples/cairo_snippets/snippets/warpedtext.py000066400000000000000000000041371451476466400245420ustar00rootroot00000000000000#!/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.25.1/examples/cairo_snippets/snippets_gtk.py000066400000000000000000000065461451476466400232260ustar00rootroot00000000000000#!/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().__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.25.1/examples/cairo_snippets/snippets_pdf.py000066400000000000000000000024711451476466400232030ustar00rootroot00000000000000#!/usr/bin/env python """Create a PDF file for each example""" import os import sys import cairo from snippets import get_snippets def do_snippet(snippet): if verbose_mode: print(f'processing {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", f"{snippet.name}.pdf") 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.25.1/examples/cairo_snippets/snippets_png.py000066400000000000000000000023101451476466400232060ustar00rootroot00000000000000#!/usr/bin/env python """Create a PNG file for each example""" import os import sys import cairo from snippets import get_snippets def do_snippet(snippet): if verbose_mode: print(f'processing {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", f"{snippet.name}.png") 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.25.1/examples/cairo_snippets/snippets_ps.py000066400000000000000000000024611451476466400230530ustar00rootroot00000000000000#!/usr/bin/env python """Create a PS file for each example""" import os import sys import cairo from snippets import get_snippets def do_snippet(snippet): if verbose_mode: print(f'processing {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", f"{snippet.name}.ps") 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.25.1/examples/cairo_snippets/snippets_svg.py000066400000000000000000000024711451476466400232310ustar00rootroot00000000000000#!/usr/bin/env python """Create a SVG file for each example""" import os import sys import cairo from snippets import get_snippets def do_snippet(snippet): if verbose_mode: print(f'processing {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", f"{snippet.name}.svg") 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.25.1/examples/gtk/000077500000000000000000000000001451476466400156725ustar00rootroot00000000000000pycairo-1.25.1/examples/gtk/cairo-demo.py000066400000000000000000000052731451476466400202720ustar00rootroot00000000000000"""Based on cairo-demo/X11/cairo-demo.c""" import gi import cairo gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") from gi.repository import Adw, 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, w, h, data): 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 on_activate(app): win = Gtk.ApplicationWindow(application=app, title="Cairo Demo") win.set_default_size(450, 550) drawingarea = Gtk.DrawingArea() drawingarea.set_draw_func(draw, None) win.set_child(drawingarea) win.present() def main(): app = Adw.Application() app.connect("activate", on_activate) return app.run(None) if __name__ == "__main__": main() pycairo-1.25.1/examples/gtk/cairo-knockout.py000066400000000000000000000070751451476466400212050ustar00rootroot00000000000000"""Based on gtk+/test/testcairo.c""" import math import gi import cairo gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") from gi.repository import Adw, 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 - 0.1) ctx.set_source_rgba(1, 0, 0, alpha) oval_path( ctx, xc + radius / 3.0 * math.cos(math.pi * 0.5), yc - radius / 3.0 * math.sin(math.pi * 0.5), subradius, subradius, ) ctx.fill() ctx.set_source_rgba(0, 1, 0, alpha) oval_path( ctx, xc + radius / 3.0 * math.cos(math.pi * (0.5 + 2 / 0.3)), yc - radius / 3.0 * math.sin(math.pi * (0.5 + 2 / 0.3)), subradius, subradius, ) ctx.fill() ctx.set_source_rgba(0, 0, 1, alpha) oval_path( ctx, xc + radius / 3.0 * math.cos(math.pi * (0.5 + 4 / 0.3)), yc - radius / 3.0 * math.sin(math.pi * (0.5 + 4 / 0.3)), subradius, subradius, ) ctx.fill() def draw(da, ctx, width, height, data): radius = 0.5 * min(width, height) - 10 xc = width / 2.0 yc = height / 2.0 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 on_activate(app): win = Gtk.ApplicationWindow(application=app, title="Knockout Groups") win.set_default_size(400, 400) drawingarea = Gtk.DrawingArea() drawingarea.set_draw_func(draw, None) win.set_child(drawingarea) win.present() def main(): app = Adw.Application() app.connect("activate", on_activate) return app.run(None) if __name__ == "__main__": main() pycairo-1.25.1/examples/gtk/png_view.py000066400000000000000000000012641451476466400200650ustar00rootroot00000000000000#!/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.25.1/examples/gtk/text.py000066400000000000000000000020201451476466400172220ustar00rootroot00000000000000import gi gi.require_version("Adw", "1") gi.require_version("Gtk", "4.0") from gi.repository import Adw, Gtk def draw_event(widget, ctx, w, h, data): ctx.set_line_width(6) ctx.set_tolerance(0.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") def on_activate(app): win = Gtk.ApplicationWindow(application=app, title="Cairo GTK Text Example") win.set_default_size(450, 150) drawingarea = Gtk.DrawingArea() drawingarea.set_draw_func(draw_event, None) win.set_child(drawingarea) win.present() app = Adw.Application() app.connect("activate", on_activate) app.run(None) pycairo-1.25.1/examples/pycairo_examples.ipynb000066400000000000000000006412451451476466400215300ustar00rootroot00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Cario example snippets with outputs\n", "Based on examples from lazka, stuaxo, fomightez and kolibril13" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import cairo\n", "from IPython.display import Image, display\n", "from math import pi\n", "from io import BytesIO\n", "\n", "def disp(draw_func):\n", " surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 200, 200)\n", " ctx = cairo.Context(surface)\n", " draw_func(ctx, 200, 200)\n", " with BytesIO() as fileobj:\n", " surface.write_to_png(fileobj)\n", " display(Image(fileobj.getvalue(), width=200))" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " cr.arc(0.5, 0.5, 0.3, 0, 2 * pi)\n", " cr.clip()\n", "\n", " cr.rectangle(0, 0, 1, 1)\n", " cr.fill()\n", " cr.set_source_rgb(0, 1, 0)\n", " cr.move_to(0, 0)\n", " cr.line_to(1, 1)\n", " cr.move_to(1, 0)\n", " cr.line_to(0, 1)\n", " cr.stroke()" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAABmJLR0QA/wD/AP+gvaeTAAACuklEQVR4nO3cTWoUQRgG4FdN1DNozAG8hV5A8W/EU7jKGfw7RnCtK3d6Ad0oaDBGEH9WCmpcKIbExfSACGPrTFf1/DwPFISm5uPrxctUpasnAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgL4dTTJIcjfJVpJvzdhqrl1p5sDSuZhkJ8lBy3iV5EJPPUJ1R5LcSXsw/hy3kxzuoV+oapJwjMbNHvqFai5m8nCMxvnqXUMFRzPcT0wbkNexcWcBDTJ9OEbjcuXe6YhN5HhdLo3OdVgLZsLLdPcNslW5dyhuN90FZLdy73TEEquO/b4bYDICMt6HGa1FRQIy3pMOaz3usBYVCch49zqsdb/DWjATVpNsZ/oN+k48KGRBXcj0AfEMhIV2O5OH40YP/UJVh5Pcyv+H42bs8Vgi5/Nve5Lt/Puyai3JRpIHSd4k2WvGm+baRjMH5sJqhgcPN5O8yPAJ+W7z92aSS82cNuvN/L20B26vmbve4X3AzLqa5Ev+f8n2pfksLKzrGR47mXTTv9/UgIUzyHTh+D0kg8q9Q1EnknzO9OEYja9JTlW9AyhoM92FYzQ2q94BFLKe5Ge6D8jP+M9WcR5klTdIslKg7kqGv+RIQQJS3tk5rQ1VvE33y6vReFvxPpbSob4bWALfkxwrVPtHkuOFahNLrBoOCtb2rnthAlLex4K1PxWsTQSkhmcFaz8tWJsISA0P57Q2VOFBIbRw1AT+wmFFaOG4O7TwwhS08MottPCjDXPCWax+rSW5luRMktNJTjbX3yd5nuRRkrtJ3vXSHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATOgXPqoDzcCGeh0AAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height) # eg1\n", " cr.stroke()\n", " cr.set_line_cap(cairo.LINE_CAP_ROUND)\n", " cr.set_line_width(0.12)\n", " cr.move_to(0.5, 0.5)\n", " cr.line_to(0.5, 0.5)\n", " \n", " cr.stroke() #eg1\n", " xc=.4\n", " yc=.4\n", " cr.arc(xc, yc, 0.05, 0, 2 * pi)\n", " cr.fill()" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " # a custom shape, that could be wrapped in a function\n", " x0 = 0.1 # parameters like cairo_rectangle\n", " y0 = 0.1\n", " rect_width = 0.8\n", " rect_height = 0.8\n", " radius = 0.4 # and an approximate curvature radius\n", "\n", " x1 = x0 + rect_width\n", " y1 = y0 + rect_height\n", "\n", " if rect_width / 2 < radius:\n", " if rect_height / 2 < radius:\n", " cr.move_to(x0, (y0 + y1) / 2)\n", " cr.curve_to(x0, y0, x0, y0, (x0 + x1) / 2, y0)\n", " cr.curve_to(x1, y0, x1, y0, x1, (y0 + y1) / 2)\n", " cr.curve_to(x1, y1, x1, y1, (x1 + x0) / 2, y1)\n", " cr.curve_to(x0, y1, x0, y1, x0, (y0 + y1) / 2)\n", " else:\n", " cr.move_to(x0, y0 + radius)\n", " cr.curve_to(x0, y0, x0, y0, (x0 + x1) / 2, y0)\n", " cr.curve_to(x1, y0, x1, y0, x1, y0 + radius)\n", " cr.line_to(x1, y1 - radius)\n", " cr.curve_to(x1, y1, x1, y1, (x1 + x0) / 2, y1)\n", " cr.curve_to(x0, y1, x0, y1, x0, y1 - radius)\n", " else:\n", " if rect_height / 2 < radius:\n", " cr.move_to(x0, (y0 + y1) / 2)\n", " cr.curve_to(x0, y0, x0, y0, x0 + radius, y0)\n", " cr.line_to(x1 - radius, y0)\n", " cr.curve_to(x1, y0, x1, y0, x1, (y0 + y1) / 2)\n", " cr.curve_to(x1, y1, x1, y1, x1 - radius, y1)\n", " cr.line_to(x0 + radius, y1)\n", " cr.curve_to(x0, y1, x0, y1, x0, (y0 + y1) / 2)\n", " else:\n", " cr.move_to(x0, y0 + radius)\n", " cr.curve_to(x0, y0, x0, y0, x0 + radius, y0)\n", " cr.line_to(x1 - radius, y0)\n", " cr.curve_to(x1, y0, x1, y0, x1, y0 + radius)\n", " cr.line_to(x1, y1 - radius)\n", " cr.curve_to(x1, y1, x1, y1, x1 - radius, y1)\n", " cr.line_to(x0 + radius, y1)\n", " cr.curve_to(x0, y1, x0, y1, x0, y1 - radius)\n", "\n", " cr.close_path()\n", "\n", " cr.set_source_rgb(0.5, 0.5, 1)\n", " cr.fill_preserve()\n", " cr.set_source_rgba(0.5, 0, 0, 0.5)\n", " cr.stroke()\n" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " x, y = 0.1, 0.5\n", " x1, y1 = 0.4, 0.9\n", " x2, y2 = 0.6, 0.1\n", " x3, y3 = 0.9, 0.5\n", "\n", " cr.move_to(x, y)\n", " cr.curve_to(x1, y1, x2, y2, x3, y3)\n", "\n", " cr.stroke()\n", "\n", " cr.set_source_rgba(1, 0.2, 0.2, 0.6)\n", " cr.set_line_width(0.03)\n", " cr.move_to(x, y)\n", " cr.line_to(x1, y1)\n", " cr.move_to(x2, y2)\n", " cr.line_to(x3, y3)\n", " cr.stroke()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "def path_ellipse(cr, x, y, width, height, angle=0):\n", " \"\"\"\n", " x - center x\n", " y - center y\n", " width - width of ellipse (in x direction when angle=0)\n", " height - height of ellipse (in y direction when angle=0)\n", " angle - angle in radians to rotate, clockwise\n", " \"\"\"\n", " cr.save()\n", " cr.translate(x, y)\n", " cr.rotate(angle)\n", " cr.scale(width / 2.0, height / 2.0)\n", " cr.arc(0.0, 0.0, 1.0, 0.0, 2.0 * pi)\n", " cr.restore()\n", "\n", "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " path_ellipse(cr, 0.5, 0.5, 1.0, 0.3, pi / 4.0)\n", "\n", " # fill\n", " cr.set_source_rgba(1, 0, 0, 1)\n", " cr.fill_preserve()\n", "\n", " # stroke\n", " # reset identity matrix so line_width is a constant\n", " # width in device-space, not user-space\n", " cr.save()\n", " cr.identity_matrix()\n", " cr.set_source_rgba(0, 0, 0, 1)\n", " cr.set_line_width(3)\n", " cr.stroke()\n", " cr.restore()" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " cr.move_to(0.5, 0.1)\n", " cr.line_to(0.9, 0.9)\n", " cr.rel_line_to(-0.4, 0.0)\n", " cr.curve_to(0.2, 0.9, 0.2, 0.5, 0.5, 0.5)\n", " cr.close_path()\n", "\n", " cr.set_source_rgb(0, 0, 1)\n", " cr.fill_preserve()\n", " cr.set_source_rgb(0, 0, 0)\n", " cr.stroke()" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAABmJLR0QA/wD/AP+gvaeTAAALV0lEQVR4nO2dT6weVRmHn9s/gRbktsW2CUSS22KQWkOkiQVK1ESbkqhRKU1MWGDSFXXl3oS7cmfQFQuNIUSMLqC6EG0UScV4i4EFpZDYKBI0sRGpmAA1tOW4mN60XO8358yfc857zvye5E2TztyZd745z/1955u534AQQgghhBDVcWfuBoSwzK9yNyCEZRxwd+4mhLCKQykixEwcShEhZrIsiFJEiFVwKEWEmMmVgihFhFiBQykixExWCqIUEeIKVgqiFBGjs/dSlchqgihFxGjsAc4CbwF3ZO6lD6sJohQRo7Asx/KgKlGSWYIoRcQgVspRqiSzBFGKiN7MkqNESdoEUYqIzvjkKE0S33EoRUQwoXKUJInvGJQiIoi9NAM+VI4rJbH8EXDIMeivDkUrfeUoQZKQ/pUiYiZd31aV9nYrtH/NRcT/MZYcliUJ7V0pIj5Ah7dV85eqyLdbXQTXXEQAnZJj3sEJBy842FJiknQRRCki+sjhLlWRknR9m6i5yIQZIEexknQVRCkyUUaQo0hJugqiFJkgI8pRnCR9BFGKTIgIchQlSR9BlCITIaIcxUjSVxClSOUkkKMISfoKohSpmIRymJdkiCBKkQrJIIdpSYYIohSpjI63j4wpx3KdcMZuSxkqiFKkEjImh+kk8ez/gFJkAhiSw5wknn0vKUUqx6AcpiTx7Nc5pUi9GJbDjCQBgihFaqQAOUxIEiCIUqQ2CpIjuySBgihFaqFAObJKEiiIUqQGCpYjmyQdBFGKlEwFcmSRpIMgSpFSqUiO5JJ0FEQpUhoVypFUko6CKEVKomI5kknSQxClSAlMQI4kkvQQRClinQnJEV2SnoIoRawyQTmiStJTEKWIRSYsRzRJBgiiFLGE5IgjyQBBlCJWkBzxJBkoiFIkN5IjriQDBXFOKZIPyRFfkhEEUYrkwMAXLJRSg74IYgRBnAtMET1fZCSUHJ2rd5KMJIhSJBVKjt7VK0lGEsQ5pcj4rFnl/84DF8M34cbqpQLWsfpLmorFkJUeitzEJLgdeJPgFFky8Ns7dz3vYHPX9MC/btc+9IlWKvRWK7gsTNKX6w8hPWguMhJKEm/1To5lRhbEOaVIWiRJPDnw/1yfvvSJVmokSRw58P9s3/6UIqmRJOPLgf/n+/aoFMmBJBlXDvzbGNKrUiQHE5ZkdDnwb2dIv0qRXExQkihy4N/W0L6VIrmYkCTR5MC/vaG9K0VyMgFJosqBf5tjHINSJCcVSxJdDvzbHeM4lCK5qVCSJHLg3/ZYx6MUyU1FkiSTA//2xzompYgFKpAkqRz49zHmsSlFLFCwJMnlwL+fMY9PKWKFAiXJIgf+fY19nEoRKxQkSTY58O9v7GNViliiAEmyyoF/nzGOWSliCcOSZJcD/35jHLdSxBoGJTEhB/59xzp+pYg1DEliRg78+4/1GihFLGJAElNy4O8hZooqRSySURJzcuDvI6YgShGrZJDEpBz4e4kpiFLEMgklMSsH/n5iC6IUsUwCSUzLgb+n2IIoRawTURLzcuDvK4UgShHrRJCkCDnw95ZCEKVICYwoSTFy0NJXYkGUIiUwgiRFyQHeHlMJohQphQGSFCcHmBJEKVIKPSQpUg4wJYhSpCQ6Pp+k9/M5cmNMED1fpCQ6JEmRcoA5QZQiVzKXu4EA9gLHgPmB2/kPcAB4bnBH3VgP3ATsABYu/bsDuBG4iuaJwi24uN2tyhJwl2+lY8A98XsRIXR4u5U9Oa4HvgR8GzgOvDOg70wJEpwiemKuIfpKkkKOXTRPjz0JvN+jR4OCaC5SIl0liSnHTprnLr/coZ+CBFGKlEroxD2WHHuAx2ieJx9RDAuC6LpIqfiSZGw55oCDNBP8BFJYEUQpUjKzkmRsOW4HfrfKfiYiiFKkZFZKMqYc1wPfAy7gHyAVCxKcIlVeFynhOoiP5eskMN51jq8CPwC2jLAtYAOwm8uXQJYvh2wGNgFXX1rnOmDtOLscFV0XKZ29jJMcG4BHGPxbf5uDQw4edvCcg/cMpIDmImIYtwIv0VuK7Q6OOPitgwsGBvTYpesiU+Zu4Cy9xPi8g6cqlUIpIuArwLt0kmKdgwccvGhg0CpFRDwO0/lTqv0OThkYrEoREZdDwEWCxVhw8DMDAzR3KUWmwGeBcwTLcZ+DswYGp5Wa7nWRKXAbwTc8XuvgUQMD0lopRWplHniVIDm2O3jBwGC0WpqL1MjjBMmx4OC0gUFouXSPVm0cJkiOjzk4Y2AAllBKkVpYAN7GezJvcPCagYFXSmkuUgtP4j2RmxycNDDoSiulSOl8Dv8JdHDUwGArsTQXKZl1BN2AeMTAQCu5dF2kVL6O98TtdnDOwCAruTQXKZE54BStJ23OwXEDA6yGUoqUxhfxnrD7DQysWkpzkdJ4htaTtdHB3w0MrJpKn2iVwk6833D4DQMDqraqby6yJncDkfgarV9IsRb4ZqpeJsSdNN+b0coBNBfJzklaf4sdMvDbttaqL0VqYxfeE/RLAwOp5qpnLlLjW6z97Ys/THNxXcTjodFWyk2Ngny6ffFBmmfaiHgEz0XMp0htgszhnQB+IUkjYjFkJfMpUpsgtwDbZi9eA+xL1cvEuYMaUqQ2QXa3L/44o33drgig/LlIbYLc3L7Y2gNua6f8uUhtgnx00GIRgcWQlcymSG2C7Gxf7AkYEYGy5yK1CbK1fbHHHxGJcucitQlybfvizWm6ECso9x6tiQniWSwishiy0rciN9EZCSISUeZcpDZBhGnKm4vUJsjb7YvfSdOFmEF5c5GJCeJZLBKwGLKSmbnIxAQ5m6YL0UJZc5HaBHmjffGraboQHsqZi9QmyJ8HLRaJKGcuMjFBTqfpQgQQFBDZ5yITE+SPaboQAZSRIrUJ8lL74lPAv5M0IkKwnyK1CXIa+Ofsxe8Dv0/Vi/Bi/+9FahPEAc+2r/KLJI2IUBZDVsr2iVZtgoBXkCeA80kaESEEXxfJMhepUZBfty/+F/CbJI2IUOzORWoU5BW8k/VHU/QhgrE7F6lREICftC9+Al00tMZiyErJ5yK1CvJTmgn7DC4C303ViwiirHu0auAZWr88eaODvxn4omfV5bL3zfBrU+4sMW8A989efB44Q/NdvcIGHwFOAH9pW+lm4Gng9RQd1cwc3kdAzzl41sBvTpXVFKl1DgLNC/kd/yoPAv9N0I4Iw+4nWjWyHngZ72+kIwZ+c6qspkjt7Mf/Yjs4amBgqC5XPU+pKoEn8b7Y8w5eNDAwVE0pRVKyQPP36p4X/AYHfzUwOFRNKUVSchj/i+3gFgdnDAwOlVIkPY8TJMmCgz8ZGCCqwBTJ/rfrtTBPcxUq4EXf7uB5AwNk6qUUSc1twFsESXKNgx8aGCRTL81FUvMZ4BxBkuDgoIOzBgbKVGsp5DwpRUbmEM1tvYGSLDj4uYHBMtVSiuTgMHCBYElwsN/BKQMDZmqluUguvgy8SydJ1jl4wOnCYupSiuRiH/AmnSS5MlGecnDBwACqvZQiObkV7+3xbbXdwYMOnpYsUUspkpMNwCP0lmS5tjq4z8HDDk44eM/AwKql0qbI3Fgbqox7ge8DW8bZ3AZgN7CD5raw5X83A5uAq4BrgA8B68bZZdXcAxzzrXQXsBS/l+myjUaSDh8FqwyV5iKJ+CRwnPwnXNW9dI9WIuZo3nYtkf+kq8JLKZKBPcBjNF+LknsAqPw1KEVq/tqfWPwDOAr8mOZhI9uArVk7Em3cCPyo7w/rU6xx2EVzb9e9wCfQ62qN3p9o6USOz3XAp2iifR/NydmYtSNxjOaz4c5IkPisB27igxdAdtBE/9XoQkgqdF1ECCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBiAvwPFluLyZRFrbgAAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " cr.move_to(0.5, 0.1)\n", " cr.line_to(0.9, 0.9)\n", " cr.rel_line_to(-0.4, 0.0)\n", " cr.curve_to(0.2, 0.9, 0.2, 0.5, 0.5, 0.5)\n", " cr.close_path()\n", "\n", " cr.move_to(0.25, 0.1)\n", " cr.rel_line_to(0.2, 0.2)\n", " cr.rel_line_to(-0.2, 0.2)\n", " cr.rel_line_to(-0.2, -0.2)\n", " cr.close_path()\n", "\n", " cr.set_source_rgb(0, 0, 1)\n", " cr.fill_preserve()\n", " cr.set_source_rgb(0, 0, 0)\n", " cr.stroke()" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " pat = cairo.LinearGradient(0.0, 0.0, 0.0, 1.0)\n", " pat.add_color_stop_rgba(1, 0, 0, 0, 1)\n", " pat.add_color_stop_rgba(0, 1, 1, 1, 1)\n", " cr.rectangle(0, 0, 1, 1)\n", " cr.set_source(pat)\n", " cr.fill()\n", "\n", " pat = cairo.RadialGradient(0.45, 0.4, 0.1,\n", " 0.4, 0.4, 0.5)\n", " pat.add_color_stop_rgba(0, 1, 1, 1, 1)\n", " pat.add_color_stop_rgba(1, 0, 0, 0, 1)\n", " cr.set_source(pat)\n", " cr.arc(0.5, 0.5, 0.3, 0, 2 * pi)\n", " cr.fill()\n" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAABmJLR0QA/wD/AP+gvaeTAAAgAElEQVR4nO29Tc8l2XHn94s4J+99qqrZPRLZ0pAegVxp0b0wYAjSYgiIXnhgy4PxjC0SMGxgYMCgVhrAn4APd4aBAYQhDKMNGN43t4K0ZOsrGOheaEV6BhRGTUmuZtfLzcwT4UXEycz7VLHZbHY/b5VRuMi8L5X3Ppnnl/+I8xIBu+2222677bbbbrvttttuu+2222677bbbbrvttttuu+2222677bbbbrvttttuu+2222677bbbbrvttttuu+2222677bbbbrvttttuu+2222677bbbbrvttttuu+2222673WqTm/4Br555nPPL7wvvvyW8/eYnX4P3P3Te/sC5/J7HC+Jf9C/cbbUdkC/KLi8V/lD56V8Lx99RvvwfhZ9+RXn9H4SnF3HeX/u58Oy4XoOHh9h/Oq4QPDg5D78Uzz9+7rz2zOFg/N3PndPR+NrvOvyVcXlp1/jXvTK2A/K5mAuX7xX4UOGJ8tOvKPWZUkalTMrFQTgNgs7KWIXjc2Gqce4Pp9j25wAPgWkOKIZjbMfZGWZnvHDsqXF84FyMDoPBY4NqcDB4ZPCBcfm9tqvNr287IJ/Vvv1u4W0KP36ifKUU9A1ltIJMis6KzIpcKNKUqQjSlKEI8yQ0FeoktBLnv+aW5+ffUYZo4HNzanPKwWN/dijGNDuuxqNi8MygxOOpNWwwXmsNHhnv0/jhd9p1np77Yjsgv4p1KB5TOFH4EoWRwkxBZ6VJQZqihwBDTMGUqoKY0krAUWahqtDmOP9FX34digUgzRytTjOnNI/X1ZhbbBHDi/HgZKDGaA0vxtEaz1rjwdx4/GbjDdoOy69mOyC/zC4vFd6qPKYwHCujFSYvPKAwe6FRODwvnAZloCCWYNQVEFMBV8osmAqlJSgiWHvxGgyb/eaOmmMltn3fZ6NUh8nwhKTvV2+4GIM3RmscrHF62Dha46k1psczb/yTBh/Me+zyybYD8ovs8keVH/+48pVS+OiiMtTKAwrPT5UDBaPQpDDkvpjG1hWKxtZiq6kgpoK2gERF8CboRj00YTEP5aiAmSPFMXPUc1scxFBzaKkgkpDMRklAqjdmb1RrTMfG4A3GmVNr2DDTHszhhv1k5vJyvonTfNttB+SqXf6o8vjDgeFY+fnHlTpUSqk0CmWsNCmoVoxCpeAUMMUpFAp4wuGKaGxxxUVQCyUxCUBoxBYwO78WmpD0rWjAgRjqnq8nHAkJYtAM9UapDWajeaMMAQrzTLUGdQ43bJh5/fmMHmeGxzMffTTtoJzbDki3774z8Og3KvM4UA+VZ7VSTwGHlopMAYVoxbtqtIoUpcz5vCg+FyirenRANN0sFcFNkATDTRZIANiEB+KOaADi7og7qqEa5k7ZQNEB0VQP84YSkKAzxRvNG64zNWGhzDDOUGcYZng68/o88ejRzJ/8yXSdp/+22g5IV4wOhs0DWiveBqRUJq3oHFCIVqTVRS2cglJwia34xs26oiJuQlHFPJTEJSHZqMiZNRY4xH0BRNzTpXIwQ18CCGIYDfV4NNoCCDpDC2DQOUDRmcqE1JlJpgWUXVFeYUC+/W7h0ZOB3/rNgek0YMcBmwfKWLFhQOeKaGVOQLZwSLpYZV7h8HSvNLemSnEFVhcLV9QFQXA/VxHik2cm7mDgkuqBY+IUCwVBjJJuFmaAIbQAR9sCyaImbabVxtDmBRR0RlJNmk8wzQwPJiaZeCATz3TirUcT33k1e75eQUBc+NO/PNA+HvBpwB8MPJgHvA0LGF4HJKFoLeGQilhsI+6oq4LkNpSinMUeEKB0QCRdLE1AvKsIxL6B9AE+CxU5UxAN5XB3dAuHbADBcBqSYJg3sDkgkRlsju0GklCVaQGlMjEzcfSJk0/8Zpv40z8d19/2atirBch33xngawMP5wNtGvDjgCccBxsWMLwOSKtgA6IVpGIJh16Bw7yucHRQeNHFAkW6a/USFRE/vxbiV9wrHBHHW2y3YCjrvnjDU0VEG/i8qEjRGU9YtqAoE7QZY2LQGfOJxkT1idknDj4xtgkejnyV6VWKT14NQC4vlR9//cBv/ebAk3bA54GBAzYEHNhALQPusS9ScR8WxcAqJut+xBsBSYdCrKT7pYgVzBVNOKQD0tUDxRFwFlC6KUAOTYgEGNDdLcNTUcBwtzMV+UXq0ZVDWirIVkUsFER9QizgKEyLijSfGHxC68jsE+XJyLPfmuAn46swhnL/Abn8UeWnHx94OB947geYByoHvA4UDrgFFO4DVYcFDNcVEPdhgQMpCySku6Udjq4eFNQVSyXRrigiGcCHcnTV6IBcvRrSEg5xnB6HGM4mQMfAc7uNPzaAFJ9DVWRGNgoiBBRdRWad0SkAsTph00QZJqSNNJ+QOnJk4snzER6O8DfjfQ/i7zcgl+8e+FsOHDlw4sDAgYkDhzrQEg71Q8DhA/4SQPABpCIerpZYbLEEYrPvCUh3uUADFM1uXwTQMxcLWNysrhwKoS7d32+eEw9DOcQ94LDzGESyB0toeGuLi9XdLr2qHD7jOlFsxpkWUIyExCewkeoTUkaMCZlHtI7U08hHxxE+HLm8HK/zsl6n3U9Aukt1eHTkmFDE+HcoR/MDymFRDuVA8djfguE6UHyNPxZAvAftqRy5j0YcIhagiCtIwKGqAUQG6uIZg/RrsI1BnFQLQjnEwfvDApYEQ68AIjRww70hMgMN+r4HGNr3ExRnijiE2JcEZLaR4gGM6AgtYBnLiEwBih5Hnh9O99Xlun+AbF0q1yOTHyj5aBxCMSygaAkGPmAcUB9Ah3ClGOK5rCqCnysIUkM5POOQVBH3gkq6VRaQCL3LdxOg9yDdogerK0eYL6D0WKQH62fxR7pYKgmFNVxbulINtCGewbnMFJ/PXCxkxlsCIgmIT4iPuPfXR1rCIjoibUTKyDjF9qGfeHw/Xa77Bch33xl4/cGBdnHkxAEpxxWMfJgfEA5YwiEcQi36PgNQUYYNGAN0F8sDlPhMAeoaf9gah8i2NyvhkB6HtOzNQgBJaFiD8+UvCtdKPGKQmF4S8Yds4g/NwBxPN0sTjoQiVGUGVuVQmyGhEKZwsWxegFihGfO9EZExtjqGq1XiYXKinkZaO/H66+N96uW6P4D0eEPqESlHqh3w6bjA0TgwyBFPtZB8kGC4D3TVcE318AFnCCioSO5bKod4ulYZrIsnIK4gZem9Wrp5U0Gi70pTJGJMpNsLKtKVBFtVxDP22KiIW1vjEOIhzPn6TKFhCUlXjohPAgS3CdEARVsCI2NAknCIjZhPOKdVSXTE/ITWkSYnRjndp7jkfgBy+e6B//d4pOoRfXZclEP0iKaC0I7oBgxPKCRdK+eAd0BSPVSjG1ikIh7KAhsVkYJQgZJxSY6HeE5cRKO7lxWUHqhjEmrCZgxkAcXjyvSxkAQjYPAVDl9VxD2DcoveLJUVDvG2KkdC4jbFZ1I9NF2rDkp3sfAR1Qnz8UxFnFNA0wIQKSNHP2F2orUTz56d7gMkdx+QP/2LI/z9EQ5HKEfQI80PHOYjrsfFpUKOaDucqUdXDpEARlI1YEggcisRk7AoSQCiVIxUEyvRBbzd923s0VVEclBR0HSvgHx9/btkUY6uIl05fFWOpXvXwp1alKMtPVdLcO4zwmZfp0VBuou1gMKE2UjxEdeARGyEVJGmI4XToiDupwBmGvGLE40Tr3ECTvybf3O6vsbw+dvdBuRlcDDlVkIxaEcsAVnAaKuKkHCoD2AH0BWOcL8yPvE+UJjdvj1o94hDerAuPVj3cgbHOSgZfyzu1joWsszHslSR7MFaQTkPzhdAem8VGX9IA87VI55Hb1UAEzCQW2FaVYMJk/EcDl8h6QpSONHaSOWEp4K4n3jwIAC545DcXUC2cLTDBYxHJMHo7hRyXJSjA2IcUDsuqtHdLLFDdOv2wUNJUKzHJBmsp4K4x/bMxaLkfkFEwdfxENmqiEi4WGegbK6G9/2rcPjL4fBN/OEvxh/KGqALGZxvAOk9V7EdM0YZz9wskYCi2Ij5iOppAYWExTlhfuKQsAzDc+44JOWmf8Bnsst3Dzz7+OIXwiFypOgF4he4H9HcN44IR9AL8NgXLsAuUO37R+AC8SOQgPV9j2PDRf7fI8ghj3UAjvF9HIF4naUz4PBL9s9V62X7mj1s3dWDPrq/KlpXsx4TKX30P8ZpoCtbWaCVBDhioehpU4uZAOrRibB1CVXiuQvgQikr4CKhgiLQmlCyif3BHzjvvXfnZgTfPUB6QH7gAsoRny/O4CjlArEL4AKRI+Ln+yJHxLKByxHPrXCB2Nr4kQvoEHgcfz1evt6h6TD4AZVo8CRUnwjEtkF35TnbTwgSlO3/WUCRHhNl/JNwxH5djyXp/nUg0gVcOxCiZ00klgfTe9c8OhNU1smVAjEbeelUCGCKC0hO7wrOOJ1gOMUp+eY3uWuQ3C1AvvvOwLMHRzhcUP0iYg0uzuCgJSzZ2Lt6CEdEQ1HQC1Tibi8bCISLRUWcIyqhNC5Hiuf3dBXp+x0UurocN3AcN25Zd7dyzKMnSux/nH+a/ZyqskBwDo1Qfyl0iuKygnIGB4pnT1v/5xIN3wlIJOOmDs0yGxlQiR65SnS0McefXCX4fWN0/pv/3vnzP78zI+53B5DLH1Xk6ZH54gLGC0q9gOmI68XL4ZAjutknXanFrcpGrFxAVxmOoSISAHVF0XS13OOY0fAvXlSRBY7KOubBi0B8Jjh+wf9foKnnMKaqiG971PoUmLUDQRKOBRRJWLx3UfeBzEDIExD1FJeen04i/FElB0FDQVCYgFKgODyZnX/6T5333rsTkNwNQC4vlZ9+5UjlAhsucC7iDs8Fbqvb1OGQVI1o3KEK4he4ZDyyuFzR0Nk2eunxx+pKecYkZQHiKhwBRSjELwHic4XjZftKd79iMuWqImvM0Uf5o9n7Jv6I/58QZKwhZy4Wy/OuMHT9yb4EsYQjAanmsT4rhe83T87vfavx3nu3fvFVvekf8Knsx18/8I/mmJF7sPDjazvSSvRWacYSi1p0BdkE1yQQbuvdXoj5WmIRF7hEb1bECQMq2cu16e5d3JqlEab9So14/T+fLxzb/y+sgX4ODi69blO6WyVe28QvnurRVQQk1aSrS7R8y1WQotmhBph4QCIgkllY5pgu03I9y3E2nr5hfP2x8UIqydtnt19BLt898PRwQU3l0PkCyqoCnurQe5e0bxMOp7tP8TklAm1fFOIiP9d7nzpM8XpXi64YsvRQ6S2G4+q+rorywriM4KQrZWvs0VVkee7pVnV1oa+OhBKxOS4Rh7h7TDoWKCX+hxPulxbw56AH+L1v3vqerdsNyOWPKn/79MjABXM5Uu2I+ZEisRW7wDPwFo+AHMu4osPhaxAeAXbv1Yr3+meV7m5loC4djg5Kh0O/oEb84v7nf1xNRTkf3Y84Q0G33b1XBjPDt0KMUAmN2ENcekcXavFjnMznpeFuGZEu1XI8p7WYfPlac37/W3ab45HbC0iPOx7MR05cUDXh8COm4T45R9QiriAVAtkG4RcLHM4FKl05UkkyQJelR2sTW1hCtKhInqs7C8d2v/eC9UmTL47us12zot1ly89IUKD9B9jy0hKwi4MSc8gKjltsG85QnXl22mt+2+OR2xuDbOOOSqznIGflSsvpJEtjjpHxmFt1HnMscKQbRQ7kebpL0gf6/JBuWsQgsoxn1GtvxF/Ucc+/Q/Lm0afnX5kvlmMhJYNzLEBZgIgNaqASLhXumaIo5oyZ5WKvXBFpblSM5sbghs6Npxhf59bGI7dTQb77zsCX3zzyxC44pMvUVaN0l6gH4hxjhNwvEI2uXO+j3Z5ulFy8CEcfz9gMJLJ1ybLx3E84tsfqvVrno+WLWpBq0AOJrhyb48rmh0mqhxMpitQdy22MvDtFHKuhLsej8/fV+Pa3b+X4yC1UEBf484EnUyRYmDhQa6wdN49JhX1O1XaLHDCLfZVNb5WcK8dZ0J0DgoUjnuqjdOW4/kb8RR33l3+HEm5n9Fw5fdQjsrCg6/hHN/FAytURC3JUQz08VzhKi6Tamq9JaWhrmBvSGlUbnBqPtMHfNNzn25Z36/YB8qd/eaDMB8bMPlLrEMtmbQWjZCOOWbkxrZ2t27Wd/kEfENy4VUtc0uHYAER9xeDY7h/w7mIhuKc6bFc6imPWVcTBcq2KRpyBe7pc4VaJJyQ5qdLdEGsUiZWP89zQ2ng6Nn7wg0ZMbrw1djXZ5c3at98ttI8H2hR5qzyzjyzLZTeLnZap6zl2IQmOeH8vG35Oe1/cqmW0OwYRvQfqXPBqw9H3K5ydk/5Yz110lWfsltNu3HJ2tB5w32wzD4Dkc+WAlvAGmh+QMjDbgXIYKH8/8O67t8rtv10K8ujJgB8G/LUBs4HiB8xioG5JsJBT1LWv59iA4jngRwLT9/vFFVndqmXMY4k5yg7H8n9KKi2hInkg8+iZQlgCcPGceu+xTr67VeKGkJlWxDBrqMQ6FSeTScwzRRo2NaTNyHHmyQeZieV22O2h9fJHlYMeOZWcA2V5t8op63Uzh2rpxpWLpXu2u0/L3KqcUqKbrlxygDCmjGwD8h2OF/9/DijK+vpS68c9gvH+//t+zyVMxCWikcPLchvulgdMZqg4sxlSAy6dDH1g/GffvDVjI7dHQR5/GNM4HjBwYl0H4YRaLEth+9JY2bhcFhIe3bwRsC/TR1JdejyyjTl2OH7Zd5Q4bxmQ44SkkL1ShEosCqJ90VbUShRvuEZALtoyL3BDdEZrLAsemJnnOTI81hl/NvP667nA6+btdsQg330n6nPYcU0k3XPlVh8omYnEe3I31mWyYgdUe/qezbqLTazinmMb3S3b4fgVvqOwdnuv57cvV17GjTL+659Ri+uEDajmezJQZIj9NkAbmHVAygBlgHnAh4H60cA772wrNd6Y3Q4FefQbsYZhngdk6GscMlcucSJjNV1kHunZR8hlsrFkNt6PCXox8VB9haGv1VhX/O1wfPrjppJkjq6uIpKZHnsaIvFQCe1xxpLpMVIOFZ9xaes6+V5+wWekxHLgZ9PMQyY+epKTKm/Wbj4GufxR5cn/lwN6lj1Ntk43XyYPSo9JNgN5mgOHy0rAWBW4TlmPOGU7NT3gGHY4fuXj5uTM3n3LmtBuSY1KLxnnCUzEIVGKId2xjE0ix7BRLUpY+9yyQq+hg2HPjD/4VrvpWOTmFeTxh1H6DCpN19hDvELbLC/Nh2uWKMiUPJ49W0ImWJCevidjET93A169QcDP87cfzjI6OoZmRseebohUB8keq55RRXwOFWHOVEkVp2K1opbXvoWSzD7xkMr8+sANxyI3qyCXP6pYO/JEjtTpYlEPyflTPSuJbKaVyNZN6u/3Hi2Oy3R3cvpJrA+5YF0OKzscv9ZxdVWLVISuFj2hXc8fLD3zikSvVVcR726ZxlbNEGkUN5pGV7HReKQ33qN1swry4x9XHhwqVStSNiqR2Qy3qlEss3sQGQ+xl2T9kIhFvC92ynhknXiot6CBfT7HvbnfroRi93RDqRw9D1ff72UW/DyTPMwUmTFmtE2YZvI9GzAmqlfmTMjnVvk6lRtUkZtTkMtLpX75gB+PFD0yayRH8PkYKXiWuCPHLfqILX3Nxzrwty6Z3UxxX+Zd9Snrh1vSwH794978b9+qyIvKQe/+pb++qohL5PBSDEsXLZJvG5WGiVHcKDSOT436vPGf/rMbmw5/gwryVuUjKg9L+qNTLgfNmoC0iktkMTSrqGxik1QXz3IFmmriEr1dPY3oqi47HJ//cQ+hFoQySKY9Pcsi35PVyRTXkJqq3uuQZB0WJnoa10KlZXyCVKZSeYsK3Eie35sbB3lMYaiVRkGmTR3yBKLXBFxSfm4To/kKi/Y8UVJzKsq6hrx3F69Fam5TA7vLcMD5mveNm+sDPeNkf5gPqAw4EZD3tfGaIPSt91zHrVCp6KEwaeU/PL4xT+dmAPn2u4XhWHlAibrkHY62llpeawJu4JDKWcKEpXZHJlWQSAmq/c60XDxuYQP71Y57O3/7Fo70BHS9Jr3WyjYB3gKEncOh+ShTqIjMhZlKORbeGCrvfvtGILkZQN6mMFrh+anSZIWjlzPrpZaREsD0h2fpgSXtZl6AXp7Auou1zT7CLW5gt+c7PvtxU7HTBV664PtNrCuKrcntpK1AiGdmFYntXApGeBA6Fw5U9GGBt28EkJuJQR5TmLxwpNB0U0459yWryPpS7mxVEZOQ6a4scXca8iT3xNLb1Dy3vYHd/Hf8esftpSFm8GlRC2Mg6h7GdXNq1JzfKkdCU7xgFmlSi9bIMkehzBWZooowz18RBfn2u4UThQcUbPMouY0TGNWbtJc16zUBe9ZAX10s7/sZh3jesXY4rvO4/Rqs7m/pXfSbWIQW+YJFSlw3icR2AU8m2raCtHzUwmkoPD0WPnyj3ISbdf2AvE3hSxRmLzQpVMriXpU5lSQVpRfJ7GXONMGhZy0/K0EQd6cVjtuc1O12fMfnd9x1ZPxs3zbBerpSkQ61l7CLa4/FNRaNB+lmTa2gc0HHQn12I27W9QPy4yfKSKFRGBIEKVFb3CXgMF/drqX+X+abFYu7kOVJD+Uoy4XZ4bip42aMuFyDNWujp4ulqRZGz+RYFyiEDShWqChSQkX0UCgPCk+uv71e8xe68JVSmCkcnneXSkM5ZFUO7Q9bXSz3FRg2wJBu2ZqwuV8k7lgDu77v+GKOew4HCQR5A9PlJpbX2SvmWbfECtYTbWt6DB2SuUQcciqUjwu+fuN12PUCcvleQd9QdFZOgyKmeMYeWzhwRawsyiF2Xocc70qyqey0xCKRwubuNbC7DAfEuEhPSLdek1791zMI1+5aSaFIqkeWZUAKZgmJFuZWcFFclCbKpMr3L6/VzbrmXqwPlXGI2GPYBOeUhCUTl/kiwQmJap7kBCaLZbpvlMT76/WONrAv/ju++N++UXdfgejFfegdMZJAeCiHSn8/Cvo4CqJIy8z0VpCLcLXeut6b+jUD8kSRR4o0RSSzh7virWCa8YflCdM1098WGOiFaNbnvj3JHneYu9nAvrjvuJ7f3uEoL+wrUR777LqxVriSDUS93nzJjI+TZHEf9LrjkOt1sX76lXCv9BCKQUlIygqLaJ4w6yc27iDua2Zy73cVetWkHY7b89s3121T3co8SyugUQ6uxxx53TxBIUHYPgaU47OY1jjeV0AuL5X6TJE5FIS6QoHF1rpq9OpGvqqISqbIlHTLJF0s6ZnK+92JO97A7vpv72Ww01VidYu1j3vY2vi7W9VdK70KiMS2ifIAZUa5vLy2dnuNNP6hUkZFLkI9xAKMiC8ChOIrIKpRZTXkd5NY2a/UHverkh5fd3cb2F3/7V0RunpsymCT13wDRXedsBWOpR8z4bAOyRPlDZQ/vL52e32A/PSvhTKlenQ4NkB01wpyv4PiEbB1lYFQl6s1Lq6vJuCvf9z7Cwf0molL9dztw9br1lWkv74oStMzhSnpYlmCMqH89U+XX/FF2/UBcvwd5eIgTEWoKpgKqrKAwBUVEY+TbJpwyAqEvhSO+FvufgO7D799c7PrDztXkcWtsuiw0Q0oiuIt3S8T5iaUKtRBODwXTsd7qCBf/o/CaZDowUo1EFNcAhS3KOnlvTRqb/QW7tb2pG9drPO6FtyTBnbHf/svcKucLDOdLpPberNzska7Zmk3FcSiPFwVXdYePjsJX/ryPVSQ3oM1FKEVocypIhYqUjZuldim5Bc99f5aXLID8aKKxHfd+QZ253/7y+EQ3wKRNdc3lawURdvqWokJzYSmgjahzsJDvdaerGv6Ihde/wdhrMI8xR9s+UfjiopgLmhWUnUJRdkG5EshPN8WlvwULlY+v1sN7PYc97N9x1U4BMibHv0arp8xiUpW5oJrAGOpHpo30ZJu1vOD8OBj4ZqmnFyfgjy9EI7PA44yxx9sKljCoFlhNcCIuwke+738sLQ8wQsQedKXikjckwZ2O477mb+jl2zrYCxd+bJ4B+t7ca09rzV5/cXD9ZZsG1qEsQl1Ei5eu2cu1uX34w+aavyBVVM2e0H6rhpdRVgL2AurBLvkncfyfeKE7nDcxt++VYt+I9MzL8BZXSz6jbBvu1eRbWW2uLHWQ3zL9y/vkYK8/5bw2s/jD2pFaHMWh2yylILoJ0V60UhnBaMrCfE68pJaeveugd31376CsO6fX9NCjy9Z4PAOTFrzVUFKjdd//lR46/17BMjbbwrPjsLhtP5R1uLuoOlidVBcZCPBYcsdqCtLfLC/w9n4B9yTBnbXf/tGJZYGn9evx5Pbz3oqRr5k6Y6pClLWz54m4fhMePPtewTI1moRip7/cd3VOgOlK0c/kQZ0F+xsQLCDknZvGthd/+1dOWC9QptrZXGNi68qorCAsqhIJlXUJkztWqDY2vUCMtUX/0CzK7DAmcQCsMQfq63dv/e1gd2P3764ws7Gusu8eWVzzfuKD7nSNgDqcK2QXB8gDzO42taL1yt3BIUcKAzrd5r+Xt/fnvD73sDuxW/P//HC/99eW1hueGf/S+W8TMhTODy8Nkiu38V6qW1rNl45aYv5i6/r5r173cDu8m/fJmbflpPmxde31/bmK9cA1zoOMjoPN88HwNxf+NxSSH570l64SJv/d98b2D357ZJPtp7A9toCUeDzSqWDYusHLnI7Pn2x3XxBds0xyPziH6Ydko2KyBYc78/X15YTbv7KNLA7+9uX6lPr654VqrYm/iIcqi+2l3m4NjjgJlysMvhyV+gLfqNUl5+dJBFHWpT3Wu80CYr75mLE83vbwO7sb08I+v/3LA2Nb2KOrLWeXkMBVBy3eGzNmtNecoP9gu2aBgo/dB6cnOG4/oHNHbMoJyz9TtHrbPv5HcZJeGRVkqhL0eHw/sF71MDu+m/vyrEBJa+fL4VA+/+J1/60P9wAAB2OSURBVPwloJg5ZaMkx9E5PXA+fP9aYLmmgcIPnIdfij9obk4zR82Rsv6RkidI8mRBynNb7zKyKMeqJOv+fWtgd/23b+CwLPaZr4ufX1MhrrX7+oBM4SCON6cWp2V7+dLHzgdv3yNALr8Xf8w4O7U5Wh0rcXcQXU9Kh2NbQXWrEnGSbbkDnYOSdm8a2F3/7bEmkFT+2Le4CW7KSXv3DLoLJnGjdF9dLSuOzc4w+xKDfO/yWgC5vrQ/Hz+PP1CPztRSQdyxDRCLLKtDs/RN80TmCZeEBLflxCpduuNy3Y8Gdpd/e97QtsU+YyoEpasEG7fZbFEV92wb6pjG50qLRyvOxcl5/vBa4IBrC9LFee2ZM144c/6xmv4lYmjGHSapKM1xdfSszl2HIKGRuCNtPwP3pYHd9d/er0fWJ9wovm9vclkJVzeqId2rsPhMsQDFijNUZz44v/HRi71gX5BdY+K4g2FPjZowzDUDdI87CGIUy5Mmq4u1BudZkJ4oH4xdhcP4IrKa7HB8luNeKeS5gLK+Jr23qnsB7svnrBkqhiQctUV7kcmpbvzsa9dWFvr6unn/7ufO8YFDiQbuc0Ch6Wa55LbX204gVOJz7hZF7LOi6lU4Yj++6+43sLv+21cgtlCwuWaWN7jte55KohLehYuj+f/Vo/rtdHR+++/um4sFnI7GxehMc7pZNdwsMIrYoiKaYLgnHPaiWqivJ58zUO5LA7vrv/2Ki7VV/yz5rBiWnoAkBNJyu3lYd7Fmpw3O+Nz596d7qCBf+12HwXBNF2kyaKkIEjAUNs/7ic33Fjiu3o3y5MfF8HvSwO7yb/cX4XBDdH2t10UX24CwudmZbyDJa66EggzN+N2v3UMF4a8MHhuPSrpMmtuWoHRYulqkK9UV5Be7VQ2kIbTY5643sLv+26NeutCvySbu2IDT99FwtxYg2vq+dTjSa3juxqEZf3V1TsoXZ9cHyOWlQTV4ZniHpMcUssLBxq3qCtJVxGm4NdzbciGQjE2WC8Mdb2B3/bcnGPS4seE0aLn1htsGFAt1WZREV5XpoMypHtWNB7NFW7oeu+a5WAeDYjw4pYt1FZCNWxUnuSEej4Ai39OEI9/D1rvW3W9gd/2357WxVdXVGyJtVRKJ1/p1Uw+gFtfKjbbZqhujGdWutQcLrh2QR7b2YqnBHK6V9pPYpTlPWFcUoSG2whLqsnWrru6n3ckGdpd/e5x/TyA4uyap8ukSI3mNe/xhDZWERhs1gRJfe7AGNx5dn3sF1w7IB8ZTa4zWqN4oCYZvXSzSlaKhuvqxrnHiYAPEohzz5kLkIuY72cB+tePevt8e1yFAyf10sTxvbprQGBaQbIDZBubNDVpe86nhpaGHxpv3GZDL7zVsiBjEMwYptWHesATCadn1F697W0/uIskyx3PZwjEnHI1Pmv5+uxvYpz/u7fvtnnDMyzXpW+37HQhLtyqvYbwfKsJGReI9YzqGe/XYjG9dbpeffuF2zQoizmutcbTG4KEizJmWOCERb4i2TFUc+yJznLQ80W4JUu4HHP2u1UHhjjWwT3/c2/nb+3lPKPrNaqPunpCINNznuMaWQGzgcGnU1qLXUhsXY4PaaD9rXNMUk243sCb9kfGshZs1e6N1SPJOExI8h6p47EO/oyQQMiOLilyBw/tFumsN7PZ8x2c7bj/vAYrndRRvoPG6+gYYWYFBGqLzAgfWwsWScK8oDQ6NR9+4VvcKbgKQ92k8mBsHa1RrlCFOYKMtUHRQSj/B3hBPEDoYniedGWSjHPLpVQRuUwO7Hd/x2Y67wqGb/eU6WAAjnhAwLy7WAkkqSG2xLT7DHLGH1AY/b/D+tbpXcBOA/PA7jcdvNk4PG9MxVKT0gJ0GFuqBxEl1wsXyhKKwwoHkxWhbeZ82+3elgd2O7/jsx00YZIoGn2DEdcv9TayorC4WluBIumXa1uC8P541ODa+88NXABCAN1jjEOaZ1l2tFiet6Iy0gETlHAbL/e1dC53YyrswAR0U7kADu/nv+OzH7TelCTyAiGuVzzeur2t3v9atEqqiqSTmq9tlNsPYkKHBG9cOB9wUIO/TeGoNxplqDdc53KyayuEbV8pCoktXDWa0y3dXC4+LpAmG+4R47N/+Bnbz3/HrHTfPs0xgcQ3EpwCFOa9J7EuCopuH0xZIPOEoHjdCL43jxYwebsS9gpsC5IffaUyPZ06tQZ2jN6vNDG1egEDWrW72hVUt4sTH3UuYsLP4Y1rvbHCLG9jdhkMkz7GlSyWrogjT4mJ1pdmqR1cQT+VRnxc40MahzfCscZrmm3Cv4CYzK77xTxo2zIwWblbpvR1yDge2uliar7lNiE4ssUhXFOtAbOGY6Bk0bl8Du8tweLpVea5TSaRlHMKMWO9V7O9v4OhuV7peqrHfXazBZyiNeZpvyr2CG009+sFMezDjwwwlXCxabrdq4Zv9fK6LUkwvPOIz4+JuhQsw3sIGdpfhAGHk7EYkY5xrWd0sk2kJ3DsQ/TqpZiwiU6hIxpfV4tFsprWZ56/PfNBjyeu3m8uA+t57zj/7F4VHzwttjuLzUgpuBaQgXlAvuCpiBdEClKVuoVypctuLQ8q2/l0v/rmUbNsr4X4+x52BEfyEcEIk9pETmq/DCeW0fKZIvA8jMKJtPHvujBQ94TriZaTNJ1obmT8a+V/+bJu9+lrtGtekv8x+MqO/M8OYkjzPUGfUJlyHCM5txpigVUQrQsWoKBXPh+QWD4icinjBKSglX9+LfX4+xzVgxH1EGXEmsDGUwSfcxlSN1e1yJswmVFPVLdSlLHHkjMsU7lWqyXGeKa/PvP7bN6YecNM5tN97z/ijbxVODwvVFDQURKygWVy+F5ZXFJesmy6bIvVLaehVOSSVI2pTZLFPhLjUdYfj1zpuqIISd3/xE86Yr4+4pKp4vBb7sVU/LeoinHCJh8oJTeDUR0RP2DDSbOSf/68jN2g3rCDARx9NUAfkwcw8TxSvNCrVBuaSgbmvAbvohPiqIpZqERXvKp4qIhRI6CTrr3fY8ANwexru3YFjBB+RdIvEwzUSQkFcRtTXuE+z69ezG9iYopv3rBcyFKNJqo1MuM2YzfwnX74x16rbzVdheO8941/8F8qzC4VTQYdCpWAeReVVo2HzMhXxVS2i+KdmfcMsVI8s6kLozfr53kGxw/EpjzuDnRAJBdgqgdom5mATi9gJkxHlhFgoCTLirMohEv+vq0e1ESknip5uWj3gNigIwKNHMx89nRkeTExzBa+UjC1absUrSEFbgYxFPJXDpYClivgazHcXbCkZ7Zvy0Qh42eH4VMdt4Csc7uk2yQlsxCVVpSsHsTWZUMaITaR3CcdzSigK00StE1Oqx0OfeDbPPDndaOzR7eYVBODP/3xVkWpKS5eIqpTFLRLcupII5vEeIqitcYa8EHMISy3u5XXOYpYdjk86VsJB3P3XnqtUkYRGNooifsI8lcNH0PicMMb/kxNiY6iKnHA7IfMJrSeahHr86//9xC2w26EgELHIgzcqz6hUj/hiniqUilt0+SoVl4J7oXjBtKCuGLEVFPMI8CVjDiFcsgUgJPIpJyruR6TfKHY4ruxv4ThB6w39hPuISMQh4iPGiMoIFnHKsi/R4yV9PEp6T9aY8WQOMMqEPJsor0+8/vDGY49ut0NBIGKRb/4r5Tgpk4WClEGhCaWPc4gsaoLm1hX1dJ8k4oxMqL+6VS6UpZy0ZIluiYYgQHb/7nDwcjg4gfXYInqrZDPGgazKASdEu5pEvCEyZvySPVsWSiJ+QjWUpnDiqZ/4+PGJf/VnNx57dLs9CgLw1qOJD55WDl5Rr1gLpZipFIlxDbGCaqiImNLjDReluGagvnb/Oopo1lx3QCVyBXRny8lGcYRPm9v3VYPDt8rRg+0EwHsvVvRoqYxYqgoSvV14KoePiE1QR7SFatBGphq9XYNMDE9ujXrAbVIQgB/+0Plv/0vh46YcBmFypRbBRTGL+EIlsiapZWwhEYSrrAG4imT9FslerYBCu3Kk9QazNpBPMdp+7+GYz90qW+FgA0e4T/meZ3zh0VvlnCge2x6fSB5LNI9jJ6SemH2EdmIYRh5y4l/+3zsgn2h/8RfGX/0/ijSFGlB4ulmooLbpzt26VR5g9H0RQZ30odKtcujKoRClSHoLicAkG1Kcl1cPjnHtypXxLOZYunV7Q899SZdLZQVCM3DXHFD0rSuWbpXIiXmK76g6MpxO/Nf/x4nvc6vsltRJ35iI81UmypORIxMyj1SfEI2gz3yK4DADwGJjTnXI920dwbXu++bFjcdzkOc4z1Geg+eD54g/B3uO8Bz5pGzx+fz+wGFxXvw5InEusDhP/RyJx3npcCDR8Hs84hYj66rhauEj6PlWJK6j2MgsEwwjlYnyaOSnTFxzQoZPY7dPQSC6fb/5PyjTx8JhEEZRahMoPZZQbFGTUI644F0t1kB8URGP24GQysHmCbAtNLkWoOwDjSxHB+4ZHDM9zugxR7/jd3VY3apz16srSFccXQYJ47mkS6YdoPY8Pl9OWItesXI88Q9/N/I//1+3JjDf2u0K0s/sJyN8ValPlJGCVEVmhaK4KYWIOTQDcPWIVdQj5rAGKhIkWLIASAclq+yKRPEWx4BNebelxsUAHFjHT+4LHE6fst4nHi4BtUePk/feqow5zuOS54vrtcy/yu7f7nIZq3IXTrQyQku1n0d4MFKfjPzkG7cSDritCgIxHf5bv+ecXheqKPMk1CrQZIlFlphEQFJJXOK+Lw4usgDhcN5ACHcunnsqR4CzgrLZBz7tyPvth2NKtYiBv+3EwyXO8HWrREAu6VbJNmjvn+/xBxmL2IniI64ZpJccECwnSjvR6gmmE7/xj0/8T9ebDO5XsdsLCMTYyLd+H4Z/FIH6UEMtaIIWyUBboBfvFInkfeliiQc4SJQkEcA1XCmR1a0KLQq3qhcLJesnhl+cNS4wQLg6ZnJ34JjZThnpDdy3cGzGPFY3a/v86hjI8/h/FsG557aPupfuftkJKye0nSjDifb8BP/4xD+/vFW9VlftdgMC8N57jW/+d8KXngutCtYEt1ALy0G/UiL2gIACBAxKZye7eDs0S9yx9FwFHL3SKr6BQ7Zw9GpI2QI/ARS4TXCsC5zg6t0/Xvds+Grr9BHdgrEJyJfpIn2aSXbtkl27QvZqeUxjNw3oajkxt5hS8vMnJ/7HP7sV00k+yW5xDLK1n4w8/qry+hPFh6g35AgVwSRUxTNKcCVG1gE8u3E1wwrCZdKsorpUz+0A9KI9PcO8RFaVJaV/n3bvM3hMmISa++t3wm2AwzlPB5rLliUTLHgsk/VlHf86ZV0yFrE+ttGnt6dCxGfO4VAi5lhcrJbrQ/REHU9rnHO89XHH1m6/gsAaj9QK8yBcNMHnUA/XaJrFBRXwFmXWu+elvbc2G4+qh8dEqoWBaK/V3gP1VA5e5mJFGn/pZcTOXg8abxaORl+XL9vAuy9v7VM+JBrwdvqIb/b7eMbievWBvz59fTvm4SskngG5WW7lRNGRuYXiPD2cePPL422OO7Z2NwCBiEf++I/hscMwCXaUmPOm0scCI1DPiFxI9ehulTjRqeU55WStyS1ZxxuP5ysQ6766JW0diEy0vajLtmZJBPV9Lljs8wXB4XFXYDoHYjNNpAfh3gf0JGbS9nUboQoZjHPuhi2g5JqPot0FG5fu26twtPacks9r9mZdzCdGPfHzZyN//G9vxVT2T2N3BxCI8ZFv/T6UAm0QZIJDBus2h8PoInHzF3B3ekgiHQz3ACdLT8fr6XpJKMgCx1nVq3ZFRc4V5ZML+uRxJToS4sd9Fjh671rPaD/l3X5Vi3VuVI8ZtioyLvGE93GL7NLdBuPKOoYhGrGEJygdBtm81iclXoXD8v83TpTTifa1kX/9b291UH7V7hYgkEH7N+GNB8IwQGuhIKrRnoUIxlXiRq6eYEi4VZpulXe3yhw06nF7QiFy7lbJ2bbhZEXepbHaRjnWDPVL1sCeJ+pKBvSljFwqEmeKtKl50qeEXwXiDI6YQq6ywtGVgw00fWyjz51aFKO7VakitrhlAUPZuFpIKFH0dq373a3qcBw4MeuJkRN89cR3Lu9E3LE1+eUfuaX27/7dEYjHNF0gcoTxiOgR5Ij7Id6XI+oHzI6IHtB2WN4XDogMiB9wDuCxjwyIDyADeDwiIB/Og3OLbCoqBbzS18JHRhUl1pmsCSbItSnrisbt6saXKUe6ftn17B7gXh3MFFoUzNzAtQLYE0uv68CFCbE5V/xlNhKmWEPeciWgb2bh5qCh2mmZNuKcKJbLZ4mBxKtwjOU5Iyd+kxN/9INb32P1Mru7gMA5JM+eHRE5ohpb5iOlHKAlLAmKc1iA0ITE9QA2LMB0KAKILSA1wNmkG4olvpVtiqEA4xfBkRNeEg5POJYO4xyTjO5mWDoNzgYtr7p4URiz1wBc9pkzTsoMhpkrd0niJucZKMVjGayS09Il51VJQFESmg4IGlCQoBgnhtw2TncdDrjrgMAGko+PUI48lyNDAiFyxPxA8QDFymGBpMNhMiDtgGooCJbKkaBIwmG5laVbt6+Lj7Xy4j3/1iaryhYQ6+tTJNeqbFWEJZiHHnPkWA190HI7uv9iLORLtdi27vd0rtZdta2rl3lyfYVjyXPsq2r0dRzLQ8dFOfAR0RGT6MqVMt4nOOAuxiBX7S//svEHf+BwiPZZSgxVNIsAvViMebhEPOIec69EPcoOu0edbs/nvWa3rWMj7lGnXcSyK7jHJL1m4jb+mJcqr70uhthaWKY31NXlmZYGuybjHkFymwkPeiKEs94qiwZKzm6OYLt38a6j2c55IL9MK/GR0teE5zyr3rsVU9OzWzjHQJYA3yImkZIDixYqMrforSqniDn+5f9252KOq3b3FaTb5eWBNznghyNejsx2QHRVEOuqokOoiB9QwrVyIu4oqR7mAyqhJl1BInNjuFeiFVp5If5gE3+opILYZmVjrmPpS4XXDuBNV/CmypgsykEC2N2tzWTK7DzwTanlPsjZKzmJR/Ea10wm3RNJ+5wgTkhmOxRb14gHaNOZeohM+HSCkmvOy8ggJ3QeaX5i9hP81ngXA/KX2f0BBOCddwY++uhAKUeO8wHXI80ONDtQExJlA4ckHDZQNvtKXVwsz+BcbY07WFytTHOa8YclIIKClE3MEUuBNeMP6ashfV0/DyzBueZ+jMP40iVdcq5YV7FzV6st215qOWqRR+2Nrl7iawEb6W5WpgPtCras3ej7bVrXdOS6nA6HtACD48jzcuLZRyN/8n/eqa7cT7L7BQjA5WXlqxx4+sYBeXqk+YHhcKBtlETagJbDAkTvyeo9V07dQFMXUJSKtARFCpHhMeAQL5hE9hWRgtuV4FzWhNpdRWJty3Yty6oiLp6TMc/niG0HLx1DExK3DNQ3pZZ7sO697FkWH1qrPCUgqRpK5EEWCyAkyxl0tVCZYqFagiFtRIaMQZ6OvPa1kf/88s4MAn4au3+AAFxeKl/nwHhx5GQHZjsw+IF2OCDzQCFdLh0ClnqAlj1WEm5UD9Z102PllpBkcN57q9wTGDR6sbqbRaxd6TmGY75YBOiRfihnUBobUMLWCZEBh2T8JMQ4jVnA0ae7QFQKRhqW+71iU98XelWnLFijM9Kiu1eYUJ+XkgXSMjVPj39sREquBGy5nmMY4TTyZDzxk2+MXF5eexXaL9ruJyDdelxyev3AcQ5QaoLRPGBRDogOAYgOGZOEi6WtRi/XJpu8Jii95yp6uApFSrpceg7IBpSe9jTH9emrS7zDke2rL4T23pPV1cO7ejiKYRqdCYurZelmpXJ01djud0BWV2sFQ7Pr12RC5gQllYMyMo+xTJYpJh1yGu9TvPEyu9+AwMbl4sDFowOcBmY/IGWg+IGpDQw6MCckgw1YrQso6ldcrIw7kIK0GnVLsn6JWck4Y1NuYaMioRYJSs5ChphoeWZ9oFDWafnu64RK7+MhvadtAWWNQ5CG2qYeeRbK9KWnLavSZumzM0ASDt0MHs4ywRxryOVivK8u1VW7/4DA6nL97YOBR+2A1CF6uaYBKQPMuW1D9nJVxIazOiTbeiSlQ9IL+1iOg/SeKy+LemzjD/GYnq90NWGJRSCVY9uLtcQdxIxLM1Q2I+o5BmIW3dPqDXNb3KpeexxZa5QvNQF1rQ+oW1iyB6vNAUiRiUknmEaqRIKFv//b6b66VFft1QCk2zvvDPA3A085UA4DMg5IHZB5gBJw2FRBBwobFdlAIlKwVA6x1cXS7LnauleYnrlaPcNjXwXZUxcBKzBpku6VbwP07M3SzWCh9XlivTcroegul+i8vLatJttLoFlCUXxmlomaWx0DjioTJ5kYykR9GtlH7lEv1S+zVwsQCH//Bz84UP5+QI4DchqgrirSqEgLQIy6bLegYJEn+BepB5yDESoSymG95yrhMF8KMUTyCaIHCwtHzVMxxHxRD8FiJnLbzscKWHQDRyz42sAhbVGMXjCzlKwN2AGxmUkTjmcTzyQyHr5WJv6rH4xr58GrYXdkReHnaOHXn3j33ZknH8zYgxl/FsVEn00zAxUpM3Mm0W4bSHSqzKVQNCBZppSUF+OP0gcHW0IiAi3SoOIC1t2tVT367Ur6WiJZp+iL+trl2zOwaALSMmAXw3ugrgGHa6O2Btowm5exEWdm8BnbzDB2iQI3Dz1Uo7w+Mf5tpAP9o5spw3zT9uopyFW7vKy8/vpA/WjgIRUfBmavMEcMUnsVq1YWUKQUpAUYkiXj0OzBspJduglJ7+YVyR6ucwUBMJeXTvpx81CR7lrlAi9rEYtcdbHEAwzxUBDfKAgttksdcmlUm7FhpvlMkYnZZqpOjPPMoU68+cZ034PwX2Y7IN3eeWfgyZO6gDJRmakcsohPpSJzwWQFJADSJVh3eQkgKJ7KUeg5hnOwEBaXq9sWFE+3CgISlZhXFoG5n4GhGA2jSqMlKLXFfvE5FEVawKFRh7yXWj7OM/ODeQHjH57Mr1Kc8Um2A3LVuqK8MVVOVrn4qDJJRQ+RZV7nErDUwtSidHVFmVsoyQIFSpG1fJxYTDFxFNWIPYCYdrLZdlNNMLqKmOciL0Otr4a8Eqj3KfCtxx05JjKvLpaXxqHNUBqtzUzzzGtfmjlN864YL9oOyC+yy8vK16mUjwvPSmXSSjkWDlRkKpyGgs4FqQWZUz1awOJEOYauIppgNItMkJLb5rEl26RkJu1iayBs5pRUDlOn5FY9VSTVQzwUpLtZmlumhpcAhLFxvJjhWWOeZp6/PtN+1vjGN+YdjJfbDsgvs8tL5S0q/+Fx4Y2hog8Leio8PRZ0LOihIFMCMhdMlCEh6ftzi+yQLTNBqsmyL2VzDV7i1RR1vDlWnNICjtrSzdIYUVc35tyqG0yN6WhcjA1KQ2qDZw0ZGnponKYZ3mh8wPwqjGX8OrYD8qvYu98u8HaBx4UP3yjUZ4XyIIBpouihYCjHZ0pLBTGUUrOmSRNKZoWcLbYA2l5+HayFktTi2BxgWHFaSQWZV0CKG6PF1kujmkFtcGjw8wbHBm80eL/xnVezR+qz2A7IZ7UOyxOU8nFhUkUflkzZoDxAaU9CReogNJQ6C6UKYxNK7gNMVwC5yG2bA5BWnGEOOIbqtMkpbrQhts/dqG5UMwY39NB4bEb7WePRN2yH4rPbDsjnYY7w/cvCWyhPUEaUGeWNmM3E4bnw7CQ8VOX5QaiTUA9x7k9TbOsg8HQ95jwEHMfRl+cXJ2c+ONWM6eiMz52hGYdmPJiNn33NeITxJsa3LturNqj3RdgOyBdll5fKH6L89U+F01H50peFEeXBx8LFa3Hef/5UOD5br8HhYeyPT9eGfXrgfOnjeP78ofMbHzk/+5rx23/n/PuT8btfc/4K22OJL8Z2QK7besGF718Kb70vvPn2J1+DD993Pnjb+d7lJonDbrvttttuu+2222677bbbbrvttttuu+2222677bbbbrvttttuu+2222677bbbbrvttttuu+2222677bbbbrvttttuu+2222677bbbbrvttttuu+2222677bbbbrvttttuu+0GwP8PWoy7b/qUssIAAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " pattern = cairo.LinearGradient(0, 0, 1, 1)\n", " pattern.add_color_stop_rgb(0, 0, 0.3, 0.8)\n", " pattern.add_color_stop_rgb(1, 0, 0.8, 0.3)\n", "\n", " mask = cairo.RadialGradient(0.5, 0.5, 0.25, 0.5, 0.5, 0.5)\n", " mask.add_color_stop_rgba(0, 0, 0, 0, 1)\n", " mask.add_color_stop_rgba(0.5, 0, 0, 0, 0)\n", "\n", " cr.set_source(pattern)\n", " cr.mask(mask)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAABmJLR0QA/wD/AP+gvaeTAAACLElEQVR4nO3dwW2DUBBAQRO5JAqkjVATPTkNkCclxv4kzBw5rPbA00pcuN0AAAAAAAAAAAAAAAAAAABg33T0wG3bHkfP5DzmeT78nTmzj9ELwJkJBIJAIAgEgkAgCASCQCAIBIJAIAgEgkAgCASCQCAIBIJAIAgEgkAgCASCQCAIBIJAIAgEgkAgCASCQCAIBIJAIAgEgkAgCASCQCAIBIJAIAgEgkAgCATCffQC77Cu6+gV/pNl9AI/sDw7wAWBIBAIAoEgEAgCgXCJr1jfWUYv8Ad9jl5gx/TC2S4IBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUCYRi/wJsvew8ebl+A14iVenp3tgkAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAiE++gFRrrKH0z5PRcEgkAgCASCQCAIBAAAAAAAAAAAAAAAAACu4AvVCgs0Of7NigAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " cr.rectangle(0.1, 0.1, 0.6, 0.6)\n", " cr.set_line_width(0.03)\n", " cr.set_source_rgb(0.8, 0.8, 0.8)\n", " cr.fill()\n", "\n", " cr.push_group()\n", " cr.rectangle(0.3, 0.3, 0.6, 0.6)\n", " cr.set_source(cairo.SolidPattern(1, 0, 0))\n", " cr.fill_preserve()\n", " cr.set_source(cairo.SolidPattern(0, 0, 0))\n", " cr.stroke()\n", " cr.pop_group_to_source()\n", " cr.paint_with_alpha(0.5)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(ctx, width, height):\n", " LINES = 32\n", " MAX_THETA = .80 * pi * 2\n", " THETA_INC = 2.0 * MAX_THETA / (LINES - 1)\n", "\n", " ctx.set_source_rgb(0, 0, 0)\n", " ctx.set_line_width(2.0)\n", "\n", " ctx.save()\n", "\n", " ctx.translate(width / 2, height / 2)\n", " ctx.rotate(MAX_THETA)\n", "\n", " for i in range(LINES):\n", " ctx.move_to(-2 * width, 0)\n", " ctx.line_to(2 * width, 0)\n", " ctx.stroke()\n", "\n", " ctx.rotate(- THETA_INC)\n", "\n", " ctx.restore()\n", "\n", " ctx.set_line_width(6)\n", " ctx.set_source_rgb(1, 0, 0)\n", "\n", " ctx.move_to(width / 4.0, 0)\n", " ctx.rel_line_to(0, height)\n", " ctx.stroke()\n", "\n", " ctx.move_to(3 * width / 4.0, 0)\n", " ctx.rel_line_to(0, height)\n", " ctx.stroke()" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " cr.move_to(0.5, 0.1)\n", " cr.line_to(0.9, 0.9)\n", " cr.rel_line_to(-0.4, 0.0)\n", " cr.curve_to(0.2, 0.9, 0.2, 0.5, 0.5, 0.5)\n", "\n", " cr.stroke()" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAABmJLR0QA/wD/AP+gvaeTAAADcklEQVR4nO3aTW4UVxiF4ePIUlgDP70AlIy8ArIIjFgFi2qxjLACTxKJDQBzzCQgW+4MXElAio7dP7e6oZ9HqolV9ele+b5SddsJAAAAAAAAAAAAAAAAAAAAAAAAAAAAHJeTfS/gyD1O8jLJsyRPkzyafv4hydskb5K8TvJ+L6v71mrwfGeRfy2SLJNc5/bgtet6unexl5X+5651bntBkuRFksusf4Aup2f3RSAM9yrJTTY/RDfTjH0QCEOdZ7s4vo7kfOa1Z4v1CoQ7PUzyMbs7TJ+SPJl1BwJhoGV2f6CWs+5AIAyySHKV3R+oq8z7zdZRBvLTvhdwBM6TnA6Ye5rk+YC5fEUg4/32nc4mApnDLwNn/zpwNvlB/ry/OjtbJcnJxcUh7udzkp/vc+Pq7CxJcnJxcd/ZX5I82GhV67v354QN9pEc6Fkc8W68K5t8cFvnmbl+IfeK4wBnE69YUAkECoFAIRAoBAKFQKAQCBQCgUIgUAgECoFAIRAoBAKFQKAQCBQCgUIgUAgECoFAIRAoBAKFQKAQCBQCgUIgUAgECoFAIRAoBAKFQKAQCBQCgUIgUAgECoFAIRAoBAKFQKAQCBQCgUIgUAgECoFAIRAoBAKFQKAQCBQCgUIgUAgECoFAIRAoBAKFQKAQCBQCgUIgUAgECoFAIRAoBAKFQKAQCBQCgUIgUAgECoFAIRAoBAKFQKAQCBQCgUIgUAgECoFAIRAoBAKFQKAQCBQCgUIgUAgECoFAIRAoBAKFQKAQCBQCgUIgUAgECoFAIRAoBAKFQKAQCBQCgUIgUAgECoFAIRAoBAKFQKAQCBQCgUIgUAgECoFAIRAoBAKFQKAQCBQCgUIgUAgECoFAIRAoBAKFQKAQCBSn+15AcbLGvasNnpnL5yQPBs3+a9BcmM273AY84no34z5G7eGf6yB5xRrvz4Gz/xg4mwhkDr9/p7NhFoskV9n9K8nVNHsuR/mKxTyW2f2BWs66A4Ew0MMkH7O7w/QpyZNZdyAQBjtPcpPtD9LNNGtuAmG4V9kukptpxj4IhFm8SHKZ9Q/Q5fTsvgiE2Sxy+yH7OncfnOvp3jm/sfo/RxnIIf5rxjF5nORlkmdJniZ5NP38Q5K3Sd4keZ3k/V5W963Rh9hZBAAAAAAAAAAAAAAAAAAAAAAAAAAAgAPwN+bOm5itb3PKAAAAAElFTkSuQmCC\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " cr.set_line_width(0.12)\n", " cr.set_line_cap(cairo.LINE_CAP_BUTT) # default\n", " cr.move_to(0.25, 0.2)\n", " cr.line_to(0.25, 0.8)\n", " cr.stroke()\n", " cr.set_line_cap(cairo.LINE_CAP_ROUND)\n", " cr.move_to(0.5, 0.2)\n", " cr.line_to(0.5, 0.8)\n", " cr.stroke()\n", " cr.set_line_cap(cairo.LINE_CAP_SQUARE)\n", " cr.move_to(0.75, 0.2)\n", " cr.line_to(0.75, 0.8)\n", " cr.stroke()\n", "\n", " # draw helping lines\n", " cr.set_source_rgb(1, 0.2, 0.2)\n", " cr.set_line_width(0.01)\n", " cr.move_to(0.25, 0.2)\n", " cr.line_to(0.25, 0.8)\n", " cr.move_to(0.5, 0.2)\n", " cr.line_to(0.5, 0.8)\n", " cr.move_to(0.75, 0.2)\n", " cr.line_to(0.75, 0.8)\n", " cr.stroke()" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " cr.set_line_width(0.16)\n", " cr.move_to(0.3, 0.33)\n", " cr.rel_line_to(0.2, -0.2)\n", " cr.rel_line_to(0.2, 0.2)\n", " cr.set_line_join(cairo.LINE_JOIN_MITER) # default\n", " cr.stroke()\n", "\n", " cr.move_to(0.3, 0.63)\n", " cr.rel_line_to(0.2, -0.2)\n", " cr.rel_line_to(0.2, 0.2)\n", " cr.set_line_join(cairo.LINE_JOIN_BEVEL)\n", " cr.stroke()\n", "\n", " cr.move_to(0.3, 0.93)\n", " cr.rel_line_to(0.2, -0.2)\n", " cr.rel_line_to(0.2, 0.2)\n", " cr.set_line_join(cairo.LINE_JOIN_ROUND)\n", " cr.stroke()" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " cr.select_font_face(\"Sans\", cairo.FONT_SLANT_NORMAL,\n", " cairo.FONT_WEIGHT_NORMAL)\n", " # draw 0.08 glyphs in 0.10 squares, at(0.01, 0.02) from left corner\n", " cr.set_font_size(0.08)\n", "\n", " glyphs = []\n", " index = 0\n", " for y in range(10):\n", " for x in range(10):\n", " glyphs.append((index, x / 10.0 + 0.01, y / 10.0 + 0.08))\n", " index += 1\n", "\n", " cr.show_glyphs(glyphs)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " cr.select_font_face(\"Sans\", cairo.FONT_SLANT_NORMAL,\n", " cairo.FONT_WEIGHT_NORMAL)\n", " # draw 0.16 glyphs in 0.20 squares, at (0.02, 0.04) from left corner\n", " cr.set_font_size(0.16)\n", "\n", " glyphs = []\n", " index = 20\n", " for y in range(5):\n", " for x in range(5):\n", " glyphs.append((index, x / 5.0 + 0.02, y / 5.0 + 0.16))\n", " index += 1\n", "\n", " cr.glyph_path(glyphs)\n", " cr.set_source_rgb(0.5, 0.5, 1.0)\n", " cr.fill_preserve()\n", " cr.set_source_rgb(0, 0, 0)\n", " cr.set_line_width(0.005)\n", " cr.stroke()" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAABmJLR0QA/wD/AP+gvaeTAAAD+ElEQVR4nO3XSXIbQQxFQdKh+1+ZXsiQbJP6nLq7psyNFFz1BniF8+l0uZyAP87nz7+fc/Gr5adA7z6+/63JgRXdfkkpCAQf1z+5SVhJfjkpCAQ3ClLcJMzssZeSgkAQClLcJMzkuZeRgkDwQEGKm4SRvfYSUhAInihIcZMwkvdePgoCwQsFKW4SerbNS0dBIHijIMVNQk+2fdkoCAQbFKS4SWhpn5eMgkCwYUGKm4Qj7ftyURAIdihIcZOwp2NeKgoCwY4FKW4StnTsy0RBIDigIMVNwjvavEQUBIIDC1LcJDyj7ctDQSBoUJDiJiHp46WhIBA0LEjpY1PQi75eFgoCQQcFKX1tDo7W50tCQSDoqCClz03CXvp+OSgIBB0WpPS9WXjXGC8FBYGg44KUMTYNjxrrZaAgEAxQkDLW5uF/Y74EFASCgQpSxtxE6xq7/AoCwYAFKWNvpvnNUXoFgWDggpQ5NtU85iq7gkAwQUHKXJtrPHOWXEEgmKggZc5N1q+5y60gEExYkDL3ZmtvjVIrCAQTF6SssemOs1aZFQSCBQpS1tp821uzxAoCwUIFKWtuwtetXV4FgWDBgpS1N+N9Sns6KQhECxek2JT/Uta/KQgECvJl9c2ppLcoCAQKcmW1Tbp6OTMFgUBBfjT7Zl2tlK9REAgU5K7ZNu3sZdyWgkCgIA8bffPOVsJjKAgECvK0kTbx6NVrT0EgUJCX2c4rUBAIDAgEBgQCAwKBAYHAgEBgQCAwIBAYEAgMCAQGBAIDAoEBgcCAQGBAIDAgEBgQCAwIBAYEAgMCgQGBwIBAYEAgMCAQGBAIDAgEBgQCAwKBAYHAgEBgQCAwIBAYEAgMCAQGBAIDAoEBgcCAQGBAIDAgEBgQCAwIBAYEgo/WHzCuy6X1F7A/BYFAQZ52Prf+Ao6jIBAoyMPcHCtSEAgU5C43x8oUBAIF+ZGbAwWBSEGuuDn4piAQKMgXNwfXFAQCBXFzECgIBAsXxM3BfQoCwYIFcXPwOAWBYKGCuDl4noJAsEBB3By8TkEgmLggbg7epyAQTFgQNwfbURAIJiqIm4PtKQgEExTEzcF+FASCgQvi5mB/CgLBgAVxc3AcBYFgoIK4OTiegkAwQEHcHLSjIBB0XBA3B+0pCAQdFsTNQT8UBIKOCuLmoD8KAkEHBXFz0C8FgaBhQdwc9E9BIGhQEDcH41AQCA4siJuD8SgIBAcUxM3BuBQEgh0L4uZgfAoCwQ4FcXMwDwWBYMOCuDmYj4JAsEFB3BzMS0EgeKMgbg7mpyAQvFAQNwfrUBAIniiIm4P1KAgEDxTEzcG6FASCUBA3BygIBDcK4uaAoiAQnN0a8DMFgeA3/9h6J1+cU/4AAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(ctx, width, height):\n", " wd = .02 * width\n", " hd = .02 * height\n", "\n", " width -= 2\n", " height -= 2\n", "\n", " ctx.move_to(width + 1, 1 - hd)\n", " for i in range(20):\n", " ctx.rel_line_to(0, height - hd * (2 * i - 1))\n", " ctx.rel_line_to(-(width - wd * (2 * i)), 0)\n", " ctx.rel_line_to(0, -(height - hd * (2 * i)))\n", " ctx.rel_line_to(width - wd * (2 * i + 1), 0)\n", "\n", " ctx.set_source_rgb(0, 0, 1)\n", " ctx.stroke()" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " cr.select_font_face(\"Sans\", cairo.FONT_SLANT_NORMAL,\n", " cairo.FONT_WEIGHT_BOLD)\n", " cr.set_font_size(0.35)\n", "\n", " cr.move_to(0.04, 0.53)\n", " cr.show_text(\"Hello\")\n", "\n", " cr.move_to(0.27, 0.65)\n", " cr.text_path(\"void\")\n", " cr.set_source_rgb(0.5, 0.5, 1)\n", " cr.fill_preserve()\n", " cr.set_source_rgb(0, 0, 0)\n", " cr.set_line_width(0.01)\n", " cr.stroke()\n", "\n", " # draw helping lines\n", " cr.set_source_rgba(1, 0.2, 0.2, 0.6)\n", " cr.arc(0.04, 0.53, 0.02, 0, 2 * pi)\n", " cr.arc(0.27, 0.65, 0.02, 0, 2 * pi)\n", " cr.fill()" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " utf8 = \"cairo\"\n", "\n", " cr.select_font_face(\"Sans\",\n", " cairo.FONT_SLANT_NORMAL,\n", " cairo.FONT_WEIGHT_NORMAL)\n", "\n", " cr.set_font_size(0.2)\n", " x_bearing, y_bearing, width, height, x_advance, y_advance = \\\n", " cr.text_extents(utf8)\n", " x = 0.5 - (width / 2 + x_bearing)\n", " y = 0.5 - (height / 2 + y_bearing)\n", "\n", " cr.move_to(x, y)\n", " cr.show_text(utf8)\n", "\n", " # draw helping lines\n", " cr.set_source_rgba(1, 0.2, 0.2, 0.6)\n", " cr.arc(x, y, 0.05, 0, 2 * pi)\n", " cr.fill()\n", " cr.move_to(0.5, 0)\n", " cr.rel_line_to(0, 1)\n", " cr.move_to(0, 0.5)\n", " cr.rel_line_to(1, 0)\n", " cr.stroke()" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "@disp\n", "def draw(cr, width, height):\n", " cr.scale(width, height)\n", " cr.set_line_width(0.04)\n", "\n", " utf8 = \"cairo\"\n", "\n", " cr.select_font_face(\"Sans\",\n", " cairo.FONT_SLANT_NORMAL,\n", " cairo.FONT_WEIGHT_NORMAL)\n", "\n", " cr.set_font_size(0.4)\n", " x_bearing, y_bearing, width, height, x_advance, y_advance = \\\n", " cr.text_extents(utf8)\n", "\n", " x = 0.1\n", " y = 0.6\n", "\n", " cr.move_to(x, y)\n", " cr.show_text(utf8)\n", "\n", " # draw helping lines\n", " cr.set_source_rgba(1, 0.2, 0.2, 0.6)\n", " cr.arc(x, y, 0.05, 0, 2 * pi)\n", " cr.fill()\n", " cr.move_to(x, y)\n", " cr.rel_line_to(0, -height)\n", " cr.rel_line_to(width, 0)\n", " cr.rel_line_to(x_bearing, -y_bearing)\n", " cr.stroke()" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "import math\n", "all_width = all_height = text_width = 0\n", "\n", "def warpPath(ctx, function):\n", " first = True\n", "\n", " for type, points in ctx.copy_path():\n", " if type == cairo.PATH_MOVE_TO:\n", " if first:\n", " ctx.new_path()\n", " first = False\n", " x, y = function(*points)\n", " ctx.move_to(x, y)\n", "\n", " elif type == cairo.PATH_LINE_TO:\n", " x, y = function(*points)\n", " ctx.line_to(x, y)\n", "\n", " elif type == cairo.PATH_CURVE_TO:\n", " x1, y1, x2, y2, x3, y3 = points\n", " x1, y1 = function(x1, y1)\n", " x2, y2 = function(x2, y2)\n", " x3, y3 = function(x3, y3)\n", " ctx.curve_to(x1, y1, x2, y2, x3, y3)\n", "\n", " elif type == cairo.PATH_CLOSE_PATH:\n", " ctx.close_path()\n", "\n", "\n", "def spiral(x, y):\n", " theta0 = -math.pi * 3 / 4\n", " theta = x / all_width * math.pi * 2 + theta0\n", " radius = y + 200 - x / 7\n", " xnew = radius * math.cos(theta)\n", " ynew = radius * math.sin(-theta)\n", " return xnew + all_width / 2, ynew + all_height / 2\n", "\n", "\n", "def curl(x, y):\n", " xn = x - text_width / 2\n", " xnew = xn\n", " ynew = y + xn ** 3 / ((text_width / 2) ** 3) * 70\n", " return xnew + all_width / 2, ynew + all_height * 2 / 5\n", "\n", "\n", "@disp\n", "def draw(ctx, width, height):\n", " global text_width, all_width, all_height\n", "\n", " all_width, all_height = width, height\n", "\n", " solidpattern = ctx.get_source()\n", "\n", " # background\n", " pat = cairo.LinearGradient(0.0, 0.0, 0, height)\n", " pat.add_color_stop_rgba(1, 0, 0, 0, 1)\n", " pat.add_color_stop_rgba(0, 1, 1, 1, 1)\n", "\n", " ctx.rectangle(0, 0, width, height)\n", " ctx.set_source(pat)\n", " ctx.fill()\n", "\n", " # foreground\n", " ctx.set_source(solidpattern)\n", " ctx.set_source_rgb(1, 1, 1)\n", "\n", " ctx.select_font_face(\"Sans\")\n", " ctx.set_font_size(80)\n", "\n", " # spiral text\n", " ctx.new_path()\n", " ctx.move_to(0, 0)\n", " ctx.text_path(\"pycairo - \" + \"spam \" * 5)\n", " warpPath(ctx, spiral)\n", " ctx.fill()\n", "\n", " # curly text\n", " ctx.new_path()\n", " ctx.move_to(0, 0)\n", " ctx.set_source_rgb(0.3, 0.3, 0.3)\n", " text = \"I am curly :)\"\n", " ctx.text_path(text)\n", " text_width = ctx.text_extents(text)[2]\n", " warpPath(ctx, curl)\n", " ctx.fill()" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": 200 } }, "output_type": "display_data" } ], "source": [ "from contextlib import contextmanager\n", "\n", "@disp\n", "def draw(ctx, width, height):\n", " cr = ctx\n", " @contextmanager\n", " def saved(cr):\n", " cr.save()\n", " try:\n", " yield cr\n", " finally:\n", " cr.restore()\n", "\n", " def Tree(angle):\n", " cr.move_to(0, 0)\n", " cr.translate(0, -65)\n", " cr.line_to(0, 0)\n", " cr.stroke()\n", " cr.scale(0.72, 0.72)\n", " if angle > 0.12:\n", " for a in [-angle, angle]:\n", " with saved(cr):\n", " cr.rotate(a)\n", " Tree(angle * 0.75)\n", "\n", "\n", " cr.translate(140, 203)\n", " cr.set_line_width(5)\n", " Tree(0.32)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.6" } }, "nbformat": 4, "nbformat_minor": 2 } pycairo-1.25.1/examples/pygame-demo.py000066400000000000000000000020721451476466400176640ustar00rootroot00000000000000#!/usr/bin/env python """demonstrate pycairo and pygame""" 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.25.1/meson.build000066400000000000000000000071171451476466400154370ustar00rootroot00000000000000project( 'pycairo', 'c', version: '1.25.1', meson_version: '>= 0.56.0', license: 'LGPL-2.1-only OR MPL-1.1', default_options: [ 'warning_level=1', 'buildtype=debugoptimized', ], ) cair_version_req = '>=1.15.10' pymod = import('python') python = pymod.find_installation(get_option('python')) pyver = python.language_version() if pyver.version_compare('< 3.8') error('Requires Python >= 3.8') endif configure_file( input: 'setup.cfg', output: 'setup.cfg', copy: true, ) cc = meson.get_compiler('c') main_c_args = [] if cc.get_id() == 'msvc' # Adapted from msvc_recommended_pragmas.h, since we don't depend on GLib here # Warnings that we want to look out for main_c_args += [ '-we4002', # too many actual parameters for macro '-we4003', # not enough actual parameters for macro '-w14010', # single-line comment contains line-continuation character '-we4013', # 'function' undefined; assuming extern returning int '-w14016', # no function return type; using int as default '-we4020', # too many actual parameters '-we4021', # too few actual parameters '-we4027', # function declared without formal parameter list '-we4029', # declared formal parameter list different from definition '-we4033', # 'function' must return a value '-we4035', # 'function' : no return value '-we4045', # array bounds overflow '-we4047', # different levels of indirection '-we4049', # terminating line number emission '-we4053', # An expression of type void was used as an operand '-we4071', # no function prototype given '-we4150', '-we4819', # The file contains a character that cannot be represented in the current code page ] # Silence warnings for stuff that should not really raise concern main_c_args += [ '-wd4101', # unreferenced local variable '-wd4244', # No possible loss of data warnings '-wd4305', # No truncation from int to char warnings ] # Silence warnings for using non-MS CRT stuff main_c_args += [ '-D_CRT_SECURE_NO_WARNINGS', '-D_CRT_NONSTDC_NO_WARNINGS' ] else main_c_args += [ '-Wall', '-Warray-bounds', '-Wcast-align', '-Wconversion', '-Wextra', '-Wformat=2', '-Wformat-nonliteral', '-Wformat-security', '-Wimplicit-function-declaration', '-Winit-self', '-Winline', '-Wmissing-format-attribute', '-Wmissing-noreturn', '-Wnested-externs', '-Wold-style-definition', '-Wpacked', '-Wpointer-arith', '-Wreturn-type', '-Wshadow', '-Wsign-compare', '-Wstrict-aliasing', '-Wundef', '-Wunused-but-set-variable', '-Wswitch-default', ] main_c_args += [ '-Wno-missing-field-initializers', '-Wno-unused-parameter', ] main_c_args += [ '-fno-strict-aliasing', '-fvisibility=hidden', ] endif main_c_args = cc.get_supported_arguments(main_c_args) pycairo_version = meson.project_version() version_arr = pycairo_version.split('.') pycairo_version_major = version_arr[0].to_int() pycairo_version_minor = version_arr[1].to_int() pycairo_version_micro = version_arr[2].to_int() pyext_c_args = [ '-DPYCAIRO_VERSION_MAJOR=@0@'.format(pycairo_version_major), '-DPYCAIRO_VERSION_MINOR=@0@'.format(pycairo_version_minor), '-DPYCAIRO_VERSION_MICRO=@0@'.format(pycairo_version_micro), ] pkginfo_conf = configuration_data() pkginfo_conf.set('VERSION', pycairo_version) configure_file(input : 'PKG-INFO.in', output : 'pycairo-@0@.egg-info'.format(pycairo_version), configuration : pkginfo_conf, install_dir : python.get_install_dir(pure : false)) subdir('cairo') if get_option('tests') subdir('tests') endif pycairo-1.25.1/meson_options.txt000066400000000000000000000002071451476466400167230ustar00rootroot00000000000000option('python', type : 'string', value : 'python3') option('tests', type : 'boolean', value : true, description : 'build unit tests') pycairo-1.25.1/pyproject.toml000066400000000000000000000010411451476466400161770ustar00rootroot00000000000000[tool.poetry] name = "pycairo" version = "1.25.1" description = "Python interface for cairo" authors = ["Christoph Reiter"] [tool.poetry.dependencies] python = "^3.8.1" [tool.poetry.dev-dependencies] pytest = "^7.2.0" hypothesis = "^6.58.0" mypy = {version = "1.3.0", markers = "platform_python_implementation != 'PyPy'"} flake8 = "^6.0.0" Sphinx = "^6.2.1" sphinx-rtd-theme = "^1.1.1" coverage = "^7.2.3" sphinx-autobuild = "^2021.3.14" setuptools = "^67.8.0" [build-system] requires = ["setuptools"] build-backend = "setuptools.build_meta" pycairo-1.25.1/setup.cfg000066400000000000000000000011221451476466400151040ustar00rootroot00000000000000[flake8] ignore=E402,E741 builtins=buffer,unichr max-line-length = 100 [coverage:run] include= cairo/* tests/* [mypy-setup] ignore_errors = True [mypy-tests.*] ignore_errors = True [mypy] disallow_any_unimported = True disallow_any_expr = True disallow_any_generics = True disallow_subclassing_any = True disallow_untyped_calls = True disallow_untyped_defs = True check_untyped_defs = True warn_return_any = True no_implicit_optional = True disallow_any_decorated = True disallow_any_explicit = False strict_optional = True follow_imports = silent exclude = ^(examples/|build|docs/)pycairo-1.25.1/setup.py000077500000000000000000000402351451476466400150100ustar00rootroot00000000000000#!/usr/bin/env python import subprocess import sys import os import errno from setuptools import setup from distutils.core import Extension, Command, Distribution from distutils.ccompiler import new_compiler from distutils.sysconfig import customize_compiler from distutils.util import change_root from distutils import log from distutils import sysconfig PYCAIRO_VERSION = '1.25.1' CAIRO_VERSION_REQUIRED = '1.15.10' PYCAIRO_BUILD_NO_PKGCONFIG = os.environ.get("PYCAIRO_BUILD_NO_PKGCONFIG", False) PYCAIRO_BUILD_MSVC_STATIC = os.environ.get("PYCAIRO_BUILD_MSVC_STATIC", True) 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}".format(command[0], command) ) from e raise SystemExit(e) from e except subprocess.CalledProcessError as e: raise SystemExit(e) from e def pkg_config_version_check(pkg, version): pkg_config = os.environ.get('PKG_CONFIG', 'pkg-config') command = [pkg_config, "--print-errors", "--exists", f'{pkg} >= {version}'] _check_output(command) def pkg_config_parse(opt, pkg): pkg_config = os.environ.get('PKG_CONFIG', 'pkg-config') command = [pkg_config, opt, pkg] ret = _check_output(command) output = ret.decode() opt = opt[-2:] return [x.lstrip(opt) for x in output.split()] def filter_compiler_arguments(compiler, args): """Given a compiler instance and a list of compiler warning flags returns the list of supported flags. """ if compiler.compiler_type == "msvc": # TODO return [] extra = [] def check_arguments(compiler, args): p = subprocess.Popen( [compiler.compiler[0]] + args + extra + ["-x", "c", "-E", "-"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate(b"int i;\n") if p.returncode != 0: text = stderr.decode("ascii", "replace") return False, [a for a in args if a in text] else: return True, [] def check_argument(compiler, arg): return check_arguments(compiler, [arg])[0] # clang doesn't error out for unknown options, force it to if check_argument(compiler, '-Werror=unknown-warning-option'): extra += ['-Werror=unknown-warning-option'] if check_argument(compiler, '-Werror=unused-command-line-argument'): extra += ['-Werror=unused-command-line-argument'] # first try to remove all arguments contained in the error message supported = list(args) while 1: ok, maybe_unknown = check_arguments(compiler, supported) if ok: return supported elif not maybe_unknown: break for unknown in maybe_unknown: if not check_argument(compiler, unknown): supported.remove(unknown) # hm, didn't work, try each argument one by one supported = [] for arg in args: if check_argument(compiler, arg): supported.append(arg) return supported def add_ext_cflags(ext, compiler): args = [ "-Wall", "-Warray-bounds", "-Wcast-align", "-Wconversion", "-Wextra", "-Wformat=2", "-Wformat-nonliteral", "-Wformat-security", "-Wimplicit-function-declaration", "-Winit-self", "-Winline", "-Wmissing-format-attribute", "-Wmissing-noreturn", "-Wnested-externs", "-Wold-style-definition", "-Wpacked", "-Wpointer-arith", "-Wreturn-type", "-Wshadow", "-Wsign-compare", "-Wstrict-aliasing", "-Wundef", "-Wunused-but-set-variable", "-Wswitch-default", ] args += [ "-Wno-missing-field-initializers", "-Wno-unused-parameter", ] # silence clang for unused gcc CFLAGS added by Debian args += [ "-Wno-unused-command-line-argument", ] args += [ "-fno-strict-aliasing", "-fvisibility=hidden", ] args += [ "-std=c99", ] ext.extra_compile_args += filter_compiler_arguments(compiler, args) class build_tests(Command): description = "build test libraries and extensions" user_options = [ ("force", "f", "force a rebuild"), ] def initialize_options(self): self.force = False self.build_base = None self.compiler_type = None def finalize_options(self): self.set_undefined_options( 'build', ('build_base', 'build_base')) self.force = bool(self.force) self.compiler_type = new_compiler().compiler_type def run(self): cmd = self.reinitialize_command("build_ext") cmd.inplace = True cmd.force = self.force cmd.ensure_finalized() cmd.run() tests_dir = os.path.join("tests", "cmodule") ext = Extension( name='tests.cmod', sources=[ os.path.join(tests_dir, "cmodule.c"), os.path.join(tests_dir, "cmodulelib.c"), ], include_dirs=[ tests_dir, "cairo", ], depends=[ os.path.join(tests_dir, "cmodulelib.h"), os.path.join("cairo", "pycairo.h"), ], define_macros=[("PY_SSIZE_T_CLEAN", None)], ) compiler = new_compiler() customize_compiler(compiler) add_ext_cflags(ext, compiler) if not PYCAIRO_BUILD_NO_PKGCONFIG: 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 self.compiler_type == "msvc" and PYCAIRO_BUILD_MSVC_STATIC: ext.libraries += ['user32', 'advapi32', 'ole32'] ext.define_macros += [('CAIRO_WIN32_STATIC_BUILD', 1)] dist = Distribution({"ext_modules": [ext]}) build_cmd = dist.get_command_obj("build") build_cmd.build_base = os.path.join(self.build_base, "pycairo_tests") build_cmd.ensure_finalized() cmd = dist.get_command_obj("build_ext") cmd.inplace = True cmd.force = self.force cmd.ensure_finalized() cmd.run() class test_cmd(Command): description = "run tests" user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): import pytest # ensure the C extension is build inplace cmd = self.reinitialize_command("build_tests") 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 = [ ('pkgconfigdir=', None, 'pkg-config file install directory'), ] def initialize_options(self): self.root = None self.install_base = None self.install_data = None self.pkgconfigdir = 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( 'install', ('root', 'root'), ) 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 if self.pkgconfigdir is None: python_lib = sysconfig.get_python_lib(True, True, self.install_data) pkgconfig_dir = os.path.join(os.path.dirname(python_lib), 'pkgconfig') else: pkgconfig_dir = change_root(self.root, self.pkgconfigdir) self.mkpath(pkgconfig_dir) pcname = "py3cairo.pc" target = os.path.join(pkgconfig_dir, pcname) log.info(f"Writing {target}") log.info(f"pkg-config prefix: {self.install_base}") with open(target, "wb") as h: h.write(("""\ 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" 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): def initialize_options(self): du_build_ext.initialize_options(self) self.compiler_type = None def finalize_options(self): du_build_ext.finalize_options(self) self.compiler_type = new_compiler(compiler=self.compiler).compiler_type def run(self): ext = self.extensions[0] if not PYCAIRO_BUILD_NO_PKGCONFIG: 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 not self.compiler_type == "msvc": compiler = new_compiler(compiler=self.compiler) customize_compiler(compiler) add_ext_cflags(ext, compiler) elif self.compiler_type == "msvc" and PYCAIRO_BUILD_MSVC_STATIC: # these extra libs are needed since we are linking statically ext.libraries += ['user32', 'advapi32', 'ole32'] ext.define_macros += [('CAIRO_WIN32_STATIC_BUILD', 1)] du_build_ext.run(self) def main(): if sys.version_info[0] < 3: raise Exception("Python 2 no longer supported") 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/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 open('README.rst', encoding="utf-8") as h: long_description = h.read() cmdclass = { "build_ext": build_ext, "install_lib": install_lib, "install_pkgconfig": install_pkgconfig, "install_pycairo_header": install_pycairo_header, "test": test_cmd, "build_tests": build_tests, } setup( name="pycairo", version=PYCAIRO_VERSION, url="https://pycairo.readthedocs.io", project_urls={ 'Source': 'https://github.com/pygobject/pycairo', }, description="Python interface for cairo", long_description=long_description, maintainer="Christoph Reiter", maintainer_email="reiter.christoph@gmail.com", license="LGPL-2.1-only OR MPL-1.1", ext_modules=[cairo_ext], packages=["cairo"], package_data={ "cairo": [ "__init__.pyi", "py.typed", "cairo.dll", ], }, classifiers=[ 'Operating System :: OS Independent', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', ('License :: OSI Approved :: ' 'GNU Lesser General Public License v2 (LGPLv2)'), 'License :: OSI Approved :: Mozilla Public License 1.1 (MPL 1.1)', ], cmdclass=cmdclass, python_requires='>=3.8', ) if __name__ == "__main__": main() pycairo-1.25.1/tests/000077500000000000000000000000001451476466400144315ustar00rootroot00000000000000pycairo-1.25.1/tests/__init__.py000066400000000000000000000010321451476466400165360ustar00rootroot00000000000000import os def set_dll_search_path(): # Python 3.8 no longer searches for DLLs in PATH, so we have to add # everything in PATH manually. Note that unlike PATH add_dll_directory # has no defined order, so if there are two cairo DLLs in PATH we # might get a random one. if os.name != "nt" or not hasattr(os, "add_dll_directory"): return for p in os.environ.get("PATH", "").split(os.pathsep): try: os.add_dll_directory(p) except OSError: pass set_dll_search_path() pycairo-1.25.1/tests/cmodule/000077500000000000000000000000001451476466400160615ustar00rootroot00000000000000pycairo-1.25.1/tests/cmodule/cmodule.c000066400000000000000000000013671451476466400176640ustar00rootroot00000000000000#include /* not pycairo3.h because we use the one from the source directory */ #include #include "cmodulelib.h" static PyMethodDef CModMethods[] = { {"create_image_surface", create_image_surface, METH_NOARGS, NULL}, {NULL, NULL, 0, NULL} }; #ifdef __GNUC__ #define PYCAIRO_MODINIT_FUNC __attribute__((visibility("default"))) PyMODINIT_FUNC #else #define PYCAIRO_MODINIT_FUNC PyMODINIT_FUNC #endif static struct PyModuleDef cmod_module = { PyModuleDef_HEAD_INIT, "cmod", NULL, -1, CModMethods, }; PYCAIRO_MODINIT_FUNC PyInit_cmod (void) { PyObject *m; if (import_cairo () < 0) return NULL; m = PyModule_Create (&cmod_module); if (m == NULL) return NULL; return m; } pycairo-1.25.1/tests/cmodule/cmodulelib.c000066400000000000000000000005001451476466400203370ustar00rootroot00000000000000#include #define PYCAIRO_NO_IMPORT #include #include "cmodulelib.h" PyObject * create_image_surface (PyObject *self, PyObject *args) { cairo_surface_t *surface; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 10, 10); return PycairoSurface_FromSurface (surface, NULL); } pycairo-1.25.1/tests/cmodule/cmodulelib.h000066400000000000000000000002101451476466400203420ustar00rootroot00000000000000#ifndef _PYCAIRO_CMODULELIB_H_ #define _PYCAIRO_CMODULELIB_H_ PyObject *create_image_surface (PyObject *self, PyObject *args); #endif pycairo-1.25.1/tests/hypothesis_fspaths.py000066400000000000000000000064671451476466400207470ustar00rootroot00000000000000# 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: 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": hight_surrogate = integers( min_value=0xD800, max_value=0xDBFF).map(lambda i: chr(i)) low_surrogate = integers( min_value=0xDC00, max_value=0xDFFF).map(lambda i: chr(i)) uni_char = integers( min_value=1, max_value=sys.maxunicode).map(lambda i: chr(i)) any_char = sampled_from([ draw(uni_char), draw(hight_surrogate), draw(low_surrogate)]) any_text = lists(any_char).map(lambda l: "".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) unix_path_text = unix_path_bytes.map( lambda b: b.decode( sys.getfilesystemencoding(), "surrogateescape")) r = draw(randoms(use_true_random=False)) def shuffle_text(t): l = list(t) r.shuffle(l) return "".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.25.1/tests/meson.build000066400000000000000000000020161451476466400165720ustar00rootroot00000000000000test_sources = [ 'hypothesis_fspaths.py', '__init__.py', 'test_api.py', 'test_cmod.py', 'test_context.py', 'test_device.py', 'test_enums.py', 'test_error.py', 'test_font.py', 'test_glyph.py', 'test_hypothesis.py', 'test_matrix.py', 'test_path.py', 'test_pattern.py', 'test_rectangle.py', 'test_region.py', 'test_surface_numpy.py', 'test_surface.py', 'test_surface_pygame.py', 'test_textcluster.py', 'test_textextents.py', 'test_typing.py', ] mod_sources = [ join_paths('cmodule', 'cmodule.c'), join_paths('cmodule', 'cmodulelib.c'), ] python.extension_module('cmod', mod_sources, dependencies : [python_dep, cairo_dep], install: false, include_directories: include_directories('../cairo'), c_args: pyext_c_args + main_c_args + ['-DPY_SSIZE_T_CLEAN'], ) foreach python_file : test_sources configure_file( input: python_file, output: python_file, copy: true, ) endforeach test( 'tests', python, workdir: meson.project_build_root(), args: ['-m', 'pytest'], ) pycairo-1.25.1/tests/test_api.py000066400000000000000000000215311451476466400166150ustar00rootroot00000000000000import 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() assert cairo.CAIRO_VERSION == cairo.cairo_version() assert cairo.CAIRO_VERSION_STRING == cairo.cairo_version_string() ver_tuple = (cairo.CAIRO_VERSION_MAJOR, cairo.CAIRO_VERSION_MINOR, cairo.CAIRO_VERSION_MICRO) assert tuple(map(int, cairo.CAIRO_VERSION_STRING.split("."))) == \ ver_tuple 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("Ä“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("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 with pytest.raises(TypeError): 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: def write(self, data): if data: raise OSError 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) v = memoryview(b"bla") x = v[:1] recfcount_v = sys.getrefcount(v) recfcount_x = sys.getrefcount(x) assert recfcount_v == recfcount_x 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) == recfcount_v assert sys.getrefcount(x) == recfcount_x @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.25.1/tests/test_cmod.py000066400000000000000000000003661451476466400167710ustar00rootroot00000000000000import cairo import pytest try: from . import cmod except ImportError: pytest.skip("cmod not built", allow_module_level=True) def test_foo(): surface = cmod.create_image_surface() assert isinstance(surface, cairo.ImageSurface) pycairo-1.25.1/tests/test_context.py000066400000000000000000000345671451476466400175450ustar00rootroot00000000000000import cairo import pytest import ctypes import platform @pytest.fixture def context(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 42, 42) return cairo.Context(surface) @pytest.mark.skipif(not hasattr(cairo.Context, "tag_begin"), reason="too old cairo") def test_tags(context): context.tag_begin("foo", "bar=quux") context.tag_end("foo") 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://foss.heptapod.net/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 context.set_dash([1], 1.25) assert context.get_dash() == ((1.0,), 1.25) 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://foss.heptapod.net/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://foss.heptapod.net/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) @pytest.mark.skipif(not hasattr(cairo.Context, "set_hairline"), reason="too old cairo") def test_hairline(context: cairo.Context): assert not context.get_hairline() context.set_hairline(True) assert isinstance(context.get_hairline(), bool) assert context.get_hairline() pycairo-1.25.1/tests/test_device.py000066400000000000000000000061401451476466400173020ustar00rootroot00000000000000import os import io import tempfile import cairo import pytest def test_context_manager(): f = io.BytesIO() with cairo.ScriptDevice(f) as dev: dev.acquire() dev.release() with pytest.raises(cairo.Error) as excinfo: dev.acquire() assert excinfo.value.status == cairo.Status.DEVICE_FINISHED 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(TypeError): cairo.ScriptDevice(io.StringIO()) 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("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.25.1/tests/test_enums.py000066400000000000000000000100511451476466400171660ustar00rootroot00000000000000import pickle import re import platform import pytest import cairo # https://foss.heptapod.net/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, ] if hasattr(cairo, "ColorMode"): # cairo 1.17.8+ types_.append(cairo.ColorMode) if hasattr(cairo, "Dither"): # cairo 1.18.0+ types_.append(cairo.Dither) 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, f"{prefix}_{name}") == value for name in dir(cairo): for t in types_: prefix = get_prefix(t) if name.startswith(f"{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) is int pycairo-1.25.1/tests/test_error.py000066400000000000000000000045761451476466400172070ustar00rootroot00000000000000import 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.25.1/tests/test_font.py000066400000000000000000000255001451476466400170120ustar00rootroot00000000000000import platform import cairo import pytest @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) @pytest.mark.skipif(not hasattr(cairo.FontOptions, "set_custom_palette_color"), reason="too old cairo") def test_font_options_custom_palette_color(font_options): font_options.set_custom_palette_color(42, 0.25, 0.5, 0.75, 1.0) with pytest.raises(cairo.Error) as exc_info: font_options.get_custom_palette_color(24) assert exc_info.value.status == cairo.Status.INVALID_INDEX assert font_options.get_custom_palette_color(42) == (0.25, 0.5, 0.75, 1.0) assert isinstance(font_options.get_custom_palette_color(42), tuple) @pytest.mark.skipif(not hasattr(cairo.FontOptions, "set_color_mode"), reason="too old cairo") def test_font_options_set_color_mode(font_options): font_options.set_color_mode(cairo.ColorMode.COLOR) assert font_options.get_color_mode() == cairo.ColorMode.COLOR with pytest.raises(TypeError): font_options.set_color_mode(object()) @pytest.mark.skipif(not hasattr(cairo.FontOptions, "get_color_mode"), reason="too old cairo") def test_font_options_get_color_mode(font_options): assert font_options.get_color_mode() == cairo.ColorMode.DEFAULT assert isinstance(font_options.get_color_mode(), cairo.ColorMode) @pytest.mark.skipif(not hasattr(cairo.FontOptions, "set_color_palette"), reason="too old cairo") def test_font_options_set_color_palette(font_options): font_options.set_color_palette(42) assert font_options.get_color_palette() == 42 @pytest.mark.skipif(not hasattr(cairo.FontOptions, "get_color_palette"), reason="too old cairo") def test_font_options_get_color_palette(font_options): assert font_options.get_color_palette() == cairo.COLOR_PALETTE_DEFAULT @pytest.mark.skipif(not hasattr(cairo.FontOptions, "get_variations"), reason="too old cairo") def test_font_options_variations(font_options): assert font_options.get_variations() is None font_options.set_variations("foo") assert font_options.get_variations() == "foo" font_options.set_variations(None) assert font_options.get_variations() is None with pytest.raises(TypeError): font_options.set_variations(1) with pytest.raises(TypeError): font_options.set_variations("foo", "bar") with pytest.raises(TypeError): font_options.set_variations() 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(), int) 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 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://foss.heptapod.net/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://foss.heptapod.net/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) font_face = cairo.ToyFontFace("serif") assert isinstance(font_face.get_family(), str) font_face = cairo.ToyFontFace("sans-serif") 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, "") == ([], [], 0) glyphs, clusters, flags = sf.text_to_glyphs(0, 0, "a") assert sf.text_to_glyphs(0, 0, "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, "a", False) == glyphs glyphs, clusters, flags = sf.text_to_glyphs(0, 0, "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.25.1/tests/test_glyph.py000066400000000000000000000023461451476466400171720ustar00rootroot00000000000000import 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 assert cairo.Glyph.index assert cairo.Glyph.x assert cairo.Glyph.y 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.25.1/tests/test_hypothesis.py000066400000000000000000000140201451476466400202360ustar00rootroot00000000000000import math import os import sys import tempfile import shutil import platform 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 if "CI" in os.environ: # CI can be slow, so be patient # Also we can run more tests there settings.register_profile( "ci", deadline=settings.default.deadline * 10, max_examples=settings.default.max_examples * 5) settings.load_profile("ci") @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 isinstance(basename, bytes): tempdir_path = os.fsencode(tempdir_path) res = os.path.join(tempdir_path, basename) if not isinstance(p, (str, bytes)): res = type(p)(res) return res def cairo_ver(): return tuple(map(int, cairo.cairo_version_string().split("."))) @pytest.mark.skipif( platform.python_implementation() == "PyPy" and sys.pypy_version_info < (7, 3, 0), reason="PyPy bugs") @given(path=fspaths()) 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, bytes): temp = os.fsdecode(temp) if isinstance(temp, str): 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.25.1/tests/test_matrix.py000066400000000000000000000042541451476466400173530ustar00rootroot00000000000000import 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.25.1/tests/test_path.py000066400000000000000000000031461451476466400170020ustar00rootroot00000000000000import 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.25.1/tests/test_pattern.py000066400000000000000000000224321451476466400175220ustar00rootroot00000000000000import 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()) @pytest.mark.skipif(not hasattr(cairo.Pattern, "set_dither"), reason="too old cairo") def test_pattern_dither(): pattern = cairo.SolidPattern(1, 2, 3) pattern.get_dither() == cairo.Dither.DEFAULT pattern.set_dither(cairo.Dither.BEST) assert pattern.get_dither() == cairo.Dither.BEST pycairo-1.25.1/tests/test_rectangle.py000066400000000000000000000026441451476466400200140ustar00rootroot00000000000000import 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 assert cairo.Rectangle.x assert cairo.Rectangle.y assert cairo.Rectangle.width assert cairo.Rectangle.height 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.25.1/tests/test_region.py000066400000000000000000000064651451476466400173400ustar00rootroot00000000000000import 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.25.1/tests/test_surface.py000066400000000000000000000562561451476466400175100ustar00rootroot00000000000000import io import os import sys import array import tempfile import struct import sysconfig import platform import cairo import pytest def test_context_manager(): with cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) as surface: surface.show_page() with pytest.raises(cairo.Error) as excinfo: surface.show_page() assert excinfo.value.status == cairo.Status.SURFACE_FINISHED 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_context_manager(): main = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) with main.map_to_image(None) as image: pass with pytest.raises(RuntimeError): main.unmap_image(image) with pytest.raises(cairo.Error) as excinfo: image.show_page() assert excinfo.value.status == cairo.Status.SURFACE_FINISHED with pytest.raises(RuntimeError): with image: pass 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) refcount = sys.getrefcount(surface) d = surface.get_data() assert sys.getrefcount(surface) != refcount del d assert sys.getrefcount(surface) == refcount 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_error(): cairo.PDFSurface(io.BytesIO(), 10, 10) with pytest.raises(TypeError): cairo.PDFSurface(object(), 10, 10) with pytest.raises(TypeError): cairo.PDFSurface(io.StringIO(), 10, 10) 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(not hasattr(cairo.PDFSurface, "set_page_label"), reason="too old cairo") def test_pdf_set_page_label(): fileobj = io.BytesIO() with cairo.PDFSurface(fileobj, 128, 128) as surface: surface.set_page_label("foo") surface.set_page_label("bar") with pytest.raises(cairo.Error): surface.set_page_label("bar") @pytest.mark.skipif(not hasattr(cairo.PDFSurface, "set_metadata"), reason="too old cairo") def test_pdf_set_metadata(): fileobj = io.BytesIO() with cairo.PDFSurface(fileobj, 128, 128) as surface: surface.set_metadata(cairo.PDFMetadata.TITLE, "title") surface.set_metadata(cairo.PDFMetadata.TITLE, "title") surface.set_metadata(cairo.PDFMetadata.AUTHOR, "author") with pytest.raises(cairo.Error): surface.set_metadata(cairo.PDFMetadata.AUTHOR, "author") @pytest.mark.skipif(not hasattr(cairo.PDFSurface, "set_custom_metadata"), reason="too old cairo") def test_pdf_set_custom_metadata(): fileobj = io.BytesIO() with cairo.PDFSurface(fileobj, 128, 128) as surface: surface.set_custom_metadata("ISBN", "978-0123456789") with pytest.raises(cairo.Error): surface.set_custom_metadata("Author", "Author isn't allowed") @pytest.mark.skipif(not hasattr(cairo.PDFSurface, "add_outline"), reason="too old cairo") def test_pdf_add_outline(): fileobj = io.BytesIO() with cairo.PDFSurface(fileobj, 128, 128) as surface: res = surface.add_outline( cairo.PDF_OUTLINE_ROOT, "foo", "page=3 pos=[3.1 6.2]", cairo.PDFOutlineFlags.OPEN) assert isinstance(res, int) @pytest.mark.skipif(not hasattr(cairo.PDFSurface, "set_thumbnail_size"), reason="too old cairo") def test_pdf_set_thumbnail_size(): fileobj = io.BytesIO() with cairo.PDFSurface(fileobj, 128, 128) as surface: surface.set_thumbnail_size(10, 10) surface.set_thumbnail_size(0, 0) surface.set_thumbnail_size(1, 1) with pytest.raises(cairo.Error): surface.set_thumbnail_size(0, 0) @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()) @pytest.mark.skipif(not hasattr(cairo.SVGSurface, "get_document_unit"), reason="too old cairo") def test_svg_surface_get_document_unit(): with cairo.SVGSurface(None, 10, 10) as surface: # https://gitlab.freedesktop.org/cairo/cairo/-/issues/545 assert surface.get_document_unit() in [cairo.SVGUnit.PT, cairo.SVGUnit.USER] with cairo.SVGSurface(None, 10, 10) as surface: surface.set_document_unit(cairo.SVGUnit.PX) assert surface.get_document_unit() == cairo.SVGUnit.PX with pytest.raises(cairo.Error): surface.set_document_unit(cairo.SVGUnit.PX) 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_error(): cairo.PSSurface(io.BytesIO(), 10, 10) with pytest.raises(TypeError): cairo.PSSurface(object(), 10, 10) with pytest.raises(TypeError): cairo.PSSurface(io.StringIO(), 10, 10) 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://foss.heptapod.net/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()) with pytest.raises(TypeError): cairo.ImageSurface.create_from_png(io.StringIO()) 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 _ 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 _ 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(TypeError): image_surface.write_to_png(io.StringIO()) 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) @pytest.mark.skipif(not hasattr(cairo.Format, "RGB96F"), reason="too old cairo") def test_format_rgbf(): surface = cairo.ImageSurface(cairo.Format.RGB96F, 3, 3) assert surface.get_format() == cairo.Format.RGB96F surface = cairo.ImageSurface(cairo.Format.RGBA128F, 3, 3) assert surface.get_format() == cairo.Format.RGBA128F pycairo-1.25.1/tests/test_surface_numpy.py000066400000000000000000000030661451476466400207270ustar00rootroot00000000000000import 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 = 300, 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=(h, w), 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.25.1/tests/test_surface_pygame.py000066400000000000000000000005011451476466400210300ustar00rootroot00000000000000import 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.25.1/tests/test_textcluster.py000066400000000000000000000013611451476466400204310ustar00rootroot00000000000000import 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 assert cairo.TextCluster.num_bytes assert cairo.TextCluster.num_glyphs pycairo-1.25.1/tests/test_textextents.py000066400000000000000000000032241451476466400204420ustar00rootroot00000000000000import 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 assert cairo.TextExtents.x_bearing assert cairo.TextExtents.y_bearing assert cairo.TextExtents.width assert cairo.TextExtents.height assert cairo.TextExtents.x_advance assert cairo.TextExtents.y_advance 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) pycairo-1.25.1/tests/test_typing.py000066400000000000000000000022041451476466400173520ustar00rootroot00000000000000import os import types import cairo def test_typing(): mod = types.ModuleType("cairo") stub = os.path.join(cairo.__path__[0], "__init__.pyi") with open(stub, encoding="utf-8") as h: code = compile(h.read(), stub, "exec") exec(code, mod.__dict__) def collect_names(t): names = set() for key, value in vars(t).items(): if key in ["XlibSurface", "XCBSurface", "Win32PrintingSurface", "Win32Surface"]: continue if key.startswith("_"): continue if key.startswith("__") and key.endswith("__"): continue if getattr(value, "__module__", "") == "typing" or key == "Text": continue if isinstance(value, type): names.add(key) for k, v in vars(value).items(): if k.startswith("_"): continue name = f"{key}.{k}" names.add(name) else: names.add(key) return names assert collect_names(cairo) <= collect_names(mod)