pax_global_header00006660000000000000000000000064131512112130014500gustar00rootroot0000000000000052 comment=747b29215c4a9d0c6b0d268213b669c348c24d1e tiled-1.0.3/000077500000000000000000000000001315121121300126025ustar00rootroot00000000000000tiled-1.0.3/AUTHORS000066400000000000000000000122541315121121300136560ustar00rootroot00000000000000Main developer and maintainer: Thorbjørn Lindeijer Other contributors: Stefan Beller Erik Schilling Samuli Tuomola Jeff Bland Petr Viktorin Mauricio Muñoz Lucero Jake Petroules Mamed Ibrahimov Yohann Ferreira mauve Alex Vega (semtiko) Martin Ziel Hiroki Utsunomiya Mike Thomas Parker Miller seeseekey monolifed Roderic Morris Will Luongo Ketan Gupta Michael Bickel Olexandr Nesterenko Porfírio Ribeiro Sean Humeniuk wayfu Ben Longbons Jonatas de Moraes Junior Manu Evans Mikolai Fajer zhaosting Alejandro Cámara Oskar Wiksten Peter André Johansen Tamir Atias (KonoM) Tim Baker Hendrik Brummermann Mohammad Mehdi Salem Naraghi Omnomnobot Andrew G. Crowell Balázs Úr Cheuk Yin Ng Clint Bellanger Dennis Honeyman Henrik Heino Igor Laete Meireles Michael Woerister Mohamed Thabet Sebastian Pidek Yehnan Chiang ekeimaja Alexander Kuhrt Andreas Abraham Arseniy Tsyro Bdtrotte Bilge Theall Champi080 Christian Henz Christoph Schnackenberg Christophe Conceicao Clyde Dale Kim HenryJia Janis Kirsteins Kenney Phillis Kim Maus Nathan Tolbert Niek Pierre-David Bélanger Porfirio Przemysław Grzywacz Seanba Wodann Yuriy juniperbrew nuriu oktonion tolbert zigal Любомир Василев Aban Acuion Adam Rippon Ahmad Hamdani Alejandro Alvarez Alessandro Portale Alex Koz Alexei Bratuhin Andrew Motrenko Ansis Māliņš Antonio Ricci Ava Brumfield Bendegúz Nagy Bin Wu Brandon Dillon Brian Cain CaptainFrog Carisius Dennis Hostetler Dmitry Hrabrov Dmitry Marakasov Dobes Vandermeer Dylan Wilson Eduardo Medeiros Pereira Edward Hutchins Emmanuel Barroga Eric Kidd Firas Assaad Flyte Glavak Gornova Gregory Nickonov Guilherme Rodrigues Caetano Gurkenlabs Hanmac Harri Berglund Harry Hsiao Hermann Döppes Ian Langworth ☠ Jack Roper Jared Adams Joel Leclerc Johel Ernesto Guerrero Peña Jonathan Bayle JonesBlunt Juan Rodriguez Justas Bistrickas Justin Jacobs Kimmo Rundelin Kody Kurtz Kyle Delaney Lennert Raesch Leon Moctezuma Ludolph Neethling Luis Garcia MHendricks Marce Coll Marco Fras Mark van Rij Matt Styles Mattia Basaglia Michael Aquilina Michael Williams Mitch Curtis Mohammed SLIMANI Nikita Razdobreev Nuri Uzunoğlu Okami Oliver Zell Phil Hagelberg Postremus Prayag Verma Robert Maes Roberto Raggi RyanSchmittDev Sausage Johnson Sebastian Grillmaier Sharganov Artem Sibiot Simião Sébastien BURILLARD Todd Carnes Tom Linthwaite Tomasz Kubiak Vincent Petithory Vitek1425 Vsevolod Klementjev Wade Brainerd Xenodora YFdyh000 Ying-Chun Liu (PaulLiu) Zach Reizner Zachary Jia arcrowel arntro-4 assofohdz bitJericho buckle2000 devnewton endlesstravel endstation erem2k fireraccoon i-ka iskolbin kekd.ck leeonix luan-cestari mhussa mogemimi nicolaichuk nykm ranjak theHacker tomerdaniel 최아영 Translators: Ahmad Hamdani (Czech) Alex Vega (Russian) Antonio Ricci (Italian) Bilge Theall (Chinese) Bin Wu (Chinese) Damene Abdelkader (Arabic, Algeria) Eduardo Medeiros Pereira (Portuguese, Brazil) ekeimaja (Finnish) Gornova (Italian) Hiroki Utsunomiya (Japanese) Jonatas de Moraes Junior (Portuguese, Brazil) jurkan (German) Jānis Kiršteins (Latvian) Laete Meireles (Portuguese, Brazil) Lyubomir Vasilev (Bulgarian) Mauricio Muñoz Lucero (Spanish) miru2533 (Korean) Nuri Uzunoğlu (Turkish) Olexandr Nesterenko (Ukrainian) Peter André Johansen (Norwegian Bokmål) Petr Viktorin (Czech) Porfírio Ribeiro (Portuguese) Sebastian Grillmaier (German) Sébastien Burillard (French) seeseekey (German) SshipSunBee (Korean) Tamir Atias (KonoM) (Hebrew) Thorbjørn Lindeijer (Dutch) Tomasz Kubiak (Polish) Tomer Daniel (Hebrew) Úr Balázs (Hungarian) Yohann Ferreira (French) Zhao Sting (Chinese) Acknowledgements: Most of the icons are from the GNOME and GIMP icon themes (GPL) Some Icons are Copyright (C) Yusuke Kamiyamane. All rights reserved. Licensed under a Creative Commons Attribution 3.0 license. See http://p.yusukekamiyamane.com/ The dice icon is based on an SVG by Steaphan Greene that I found on Wikipedia: http://en.wikipedia.org/wiki/File:2-Dice-Icon.svg Inkscape icons by Barbara Muraus, Jakub Steiner and Josh Andler (CC-BY-SA 3.0) * src/tiled/images/14x14/hidden.png * src/tiled/images/14x14/visible.png * src/tiled/images/16x16/hidden.png * src/tiled/images/16x16/visible.png * src/tiled/images/24x24/hidden.png * src/tiled/images/24x24/visible.png Tilesets: perspective_walls.png - (C) Clint Bellanger, released as Public Domain isometric_grass_and_water.png - (C) Clint Bellanger, released as GPL2, GPL3, CC-BY-SA3 tmw_desert_spacing.png - (C) The Mana World Development Team, GPL sewer_tileset.png - (C) Blues Brothers RPG developers, GPL Replica Island - (C) Chris Pruett and Genki Mine, Apache (except hotspots.png) hexmini.png - Public Domain, http://opengameart.org/content/pixel-hex-tilesets-enhanced buch-outdoor.png - (C) Michele "Buch" Bucelli, CC-BY 3.0, http://opengameart.org/users/buch examples/sticker-knight - (C) Ponywolf, CC0, http://opengameart.org/content/sticker-knight-platformer tiled-1.0.3/CONTRIBUTING.md000066400000000000000000000036121315121121300150350ustar00rootroot00000000000000# Contributing to Tiled All kinds of contributions are very appreciated, be it documentation, code or build system improvements, be it a small patch, a feature or maybe even becoming a co-maintainer of Tiled. Bug reports and feature requests are of course welcome too! ## Reporting an Issue Make sure to mention the following things: * How the issue can reproduced * What behavior you expected instead * What actually happened * Tiled version, operating system, etc. if possibly relevant. Also, please consider adding a screenshot or video if it helps illustrate the issue. ## Requesting a Feature First of all, look around the already open issues to see if the feature was already requested in some form. In that case it's better to comment on the existing feature instead. If you're not entirely sure about what feature you need, consider to [post your problem on the forum](http://discourse.mapeditor.org/) instead. In any case, be sure to describe the feature in enough detail, to consider its implications on existing parts of the software if relevant and to describe how it would help you in particular. Also, please consider including a mockup if the issue includes UI changes. ## Submitting a Patch * Ideally, start with something small to get familiar with the review process and work up from there. * Make an effort to follow the overal coding style, which is roughly based on the [Qt Creator coding style](https://doc-snapshots.qt.io/qtcreator-extending/coding-style.html). * Be prepared for detailed feedback on your patch and to make several revisions. * Each pull request will be built automatically for Windows, Linux and macOS. If the build fails anywhere, please check if it may be a problem with your patch. ## Making a Donation You can also support further development of Tiled with [a monthly donation to Thorbjørn](https://www.patreon.com/bjorn) on Patreon. Thanks a lot for your contribution! tiled-1.0.3/COPYING000066400000000000000000000017401315121121300136370ustar00rootroot00000000000000Several independent works are being distributed along with Tiled that fall under different licenses. You can find the license that applies to each file in the comment at the top, but for clarity they are also listed here: Software Directory License ------------------------------------------------------------------- Tiled src/tiled GPL Tiled plugins src/plugins GPL automappingconverter src/automappingconverter GPL libtiled src/libtiled BSD 2-clause license libtiled-java util/java/libtiled-java BSD 2-clause license qtpropertybrowser src/qtpropertybrowser BSD 3-clause license tmxrasterizer src/tmxrasterizer BSD 2-clause license tmxviewer src/tmxviewer BSD 2-clause license tmxviewer-java util/java/tmxviewer-java BSD 2-clause license The full text of each license is provided in the files LICENSE.GPL and LICENSE.BSD. tiled-1.0.3/Doxyfile000066400000000000000000000221101315121121300143040ustar00rootroot00000000000000# Doxyfile 1.6.1 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "Tiled (Qt)" PROJECT_NUMBER = OUTPUT_DIRECTORY = CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English BRIEF_MEMBER_DESC = NO REPEAT_BRIEF = YES ABBREVIATE_BRIEF = ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = NO STRIP_FROM_PATH = STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = YES QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 8 ALIASES = OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO EXTENSION_MAPPING = BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO SIP_SUPPORT = NO IDL_PROPERTY_SUPPORT = YES DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES TYPEDEF_HIDES_STRUCT = NO SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = NO EXTRACT_PRIVATE = NO EXTRACT_STATIC = NO EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = NO EXTRACT_ANON_NSPACES = NO HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = YES SHOW_INCLUDE_FILES = YES INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_MEMBERS_CTORS_1ST = NO SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_DIRECTORIES = NO SHOW_FILES = YES SHOW_NAMESPACES = YES FILE_VERSION_FILTER = LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- INPUT = src INPUT_ENCODING = UTF-8 FILE_PATTERNS = RECURSIVE = YES EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = */moc_*.cpp \ */ui_*.h \ */qrc_*.cpp EXCLUDE_SYMBOLS = EXAMPLE_PATH = EXAMPLE_PATTERNS = EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = YES INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = NO REFERENCES_RELATION = NO REFERENCES_LINK_SOURCE = YES USE_HTAGS = NO VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = NO COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_ALIGN_MEMBERS = YES HTML_DYNAMIC_SECTIONS = NO GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" DOCSET_BUNDLE_ID = org.doxygen.Project GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO CHM_INDEX_ENCODING = BINARY_TOC = NO TOC_EXPAND = NO GENERATE_QHP = NO QCH_FILE = "../tiled-0.1.qch" QHP_NAMESPACE = org.mapeditor.tiled QHP_VIRTUAL_FOLDER = "tiled-0.1" QHP_CUST_FILTER_NAME = QHP_CUST_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS = QHG_LOCATION = "qhelpgenerator" DISABLE_INDEX = NO ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = NO USE_INLINE_TREES = NO TREEVIEW_WIDTH = 250 FORMULA_FONTSIZE = 10 SEARCHENGINE = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = NO LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4wide EXTRA_PACKAGES = LATEX_HEADER = PDF_HYPERLINKS = YES USE_PDFLATEX = YES LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO LATEX_SOURCE_CODE = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml XML_SCHEMA = XML_DTD = XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES MSCGEN_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO DOT_FONTNAME = FreeSans DOT_FONTSIZE = 10 DOT_FONTPATH = CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = NO TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png DOT_PATH = DOTFILE_DIRS = DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 DOT_TRANSPARENT = YES DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES tiled-1.0.3/LICENSE.APACHE000066400000000000000000000261351315121121300145360ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. tiled-1.0.3/LICENSE.BSD000066400000000000000000000023041315121121300142150ustar00rootroot00000000000000Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. tiled-1.0.3/LICENSE.GPL000066400000000000000000000432541315121121300142400ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the Program a copy of this License along with the Program. 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 Program or any portion of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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 Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) 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; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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. If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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 to this License. 7. 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. 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. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 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 Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. 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 program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. tiled-1.0.3/NEWS.md000066400000000000000000001123761315121121300137120ustar00rootroot00000000000000### 1.0.3 (29 August 2017) * Fixed crash on reload map (#1659, #1694) * Fixed possible crash on undo/redo in collision editor (#1695) * Fixed tile replacement to add tileset when needed (by Mohamed Thabet, #1641) * Fixed the display of the image source property for tilesets * Fixed shortcut for 'Copy tile coordinates' (Alt+C) in Portuguese translation (by olueiro) * JSON plugin: Fixed reading of tileset column count * JSON plugin: Fixed reading of custom properties on tile collision object group ### 1.0.2 (27 June 2017) * Added read-only tile and terrain properties in map editor (#1615) * Fixed Terrains view to display all tilesets with terrain * Fixed hang when trying to fill with a pasted stamp (#1617, #1624) * Fixed crash when editing collision when tile image wasn't loaded * Fixed rendering of tile objects when the image couldn't be loaded * Fixed rendering of tile object outlines for resized objects * Fixed labels shown on objects hidden via a group layer * Fixed updating of label positions when moving a group layer * GmxPlugin: Fixed tile type inheritance for tile objects * Restored Ctrl+N shortcut on "New Map" action ### 1.0.1 (13 June 2017) * Made the zoom level used in Tilesets view persistent * Fixed mixed up polygon and polyline icons (by Ketan Gupta, #1588) * Fixed reset of font size when using font dialog (#1596) * Fixed several issues with the Properties dock (#1583, #1611) * Fixed centering on object on layer with offset (#1600) * Fixed handling of symbolic links in Recent Files menu and Maps view (#1589) * Fixed labels for objects in grouped object layers * Reverted the file format version back to "1.0" and added "tiledversion" attribute * Lua plugin: Fixed group layers being exported with "imagelayer" type (#1595) * Added Korean translation (by miru2533 and SshipSunBee, #1604) * Updated Russian and Chinese translations ### 1.0.0 (25 May 2017) * Added support for editing external tilesets (#242) * Added a text object with configurable font and wrapping (#1429) * Added layer grouping (#1038) * Added Tile.type and inherit tile object properties from the tile (#436, #1248) * Added a start page * Added selection of underlying objects with Alt modifier (by Yuriy, #1491) * Added an option to disable safe writing of files (#1402, #1404) * Added invert selection action (by Leon Moctezuma, #1423) * Added support for isometric terrain overlays and tile collision objects (#419, #757) * Added 180-degree mirroring mode to terrain brush with Alt modifier * Added short and consistent map format names to use with --export-map (by Marce Coll, #1382) * Added Swap Tiles action (by Alexander Münch, #866) * Added tileset background color property (#227) * Added 60 degree tile rotation support for hexagonal maps (by Victor Nicolaichuk, #1447) * Added a check for duplicates when adding tiles (by Simião, #1227) * Added option to run commands from menu as well as edit them (by Ketan Gupta, #943) * Added custom shortcuts for commands (by Ketan Gupta, #1456) * Added optional ID and Position columns to objects view (by i-ka, #1462) * Added an executable picker for custom commands (by Ketan Gupta, #942) * Added marching ants effect on selected objects (by Mohamed Thabet, #1489) * Added all open tilesets to the Tilesets view * Added auto-show/hide all views (Clear View) action (by erem2k, #563) * Added minimap in the resizing dialog (by Yuriy, #1516) * Added drag-n-drop support in Layers view (#178) * Added support for storing object type definitions in JSON format (#1313) * Added cut/copy/paste actions for custom properties (#515) * Allow changing the tile of tile objects (by Mohamed Thabet, #409) * Allow selecting a folder to fix multiple broken links at once * Added support for dragging external tilesets into the Tilesets dock * Added support for dragging images into image collection tilesets * Write out Tiled version in TMX/JSON "version" attribute (#1416) * Remember last view on map also for closed files (#905) * Remember tileset zoom level in the tileset editor (by Artem Sharganov, #408) * Change current layer depending on selected objects (by Glavak, #1424) * Improved support for using Tiled on HiDpi screens * Improved the behavior of the tile selection tool * Made Ctrl+D duplicate objects instead of deleting them * Use an eye icon instead of a checkbox for layer visibility (by Ketan Gupta, #1127) * JSON tileset: Save width/height of individual tile images * Linux: Added MIME type for tileset files * Fixed hexagonal rotation of tile stamps (by Bdtrotte, #1476) * Fixed handling of broken tile references, which now render as a red marker * Fixed manual reloading of images for image collection tilesets * Fixed Offset Layers tool to wait until mouse is moved * Fixed current stamp to always update when a tile is clicked * Fixed handling of pinch gestures (#1305) * Fixed flipping a group of objects to work like expected (by Vitek1425, #1475) * Fixed stamp brush to work better on staggered maps (by Bdtrotte) * Fixed objects offsetting while resizing (by Acuion, #1518) * Fixed fill tool for hexagonal maps (#883) * Fixed potential crash in Terrain Brush * Windows: Fixed menus when using OpenGL in full screen mode (#1576) * Windows: Added Sticker Knight and Python example scripts to installer (#819) * Windows: Fixed bringing existing Tiled window to foreground (#1256) * AutoMapping: Fixed object groups always getting added * AutoMapping: Improved map boundary handling (by Stefan Beller, #1224) * AutoMapping: Apply custom properties set on output layers * terraingenerator: Made the amount of columns configurable * terraingenerator: Copy tile properties from the source tilesets * Added Ukrainian translation (by Olexandr Nesterenko) * Added Hungarian translation (by Balázs Úr) * Added Finnish translation (by ekeimaja) * Updated Bulgarian, Dutch, French, German, Russian, Spanish and Turkish translations ### 0.18.2 (21 February 2017) * Fixed crash when deleting multiple selected objects * Fixed crash when moving multiple selected objects to another object layer * Fixed updating of values displayed in Objects and Layers views * GmxPlugin: Added support for image collection tilesets * Object Types Editor: Improved behavior when adding new types * Linux: Fixed shipping of image format plugins in AppImage releases ### 0.18.1 (23 January 2017) * Fixed terrain brush for isometric staggered maps (by Clyde) * Fixed crash when resizing map causes objects to get removed * Fixed crash when duplicating an object layer * Fixed position of image layer after Resize or Offset Map * Fixed the quality of the minimap on HiDpi displays * Fixed Alt-drag behavior to not override resize handles * When adding a new layer, insert it above the current one * GmxPlugin: Fixed positioning for non-tile objects and support scaling * GmxPlugin: Export tile objects without a type as tiles * GmxPlugin: Support horizontal and vertical flipping * Windows: Fixed encoding problems with command-line output * Windows: Fixed the architecture of shipped MSVC DLLs * Updated Chinese translation (by Clyde) ### 0.18.0 (20 December 2016) * Added Layer via Copy/Cut actions * Added support for Paste in Place action for tile layers * Added context menu to change custom property type (by Dmitry Hrabrov) * Added support for higher precision for custom floating point properties * Added %mappath variable to commands (by Jack Roper) * Added snapping to pixels (by Mamed Ibrahimov) * Added right-click to clear the tile selection * Added a context menu action to reset the size of tile objects * Added exporter for Game Maker Studio room files (by Jones Blunt) * Added Move Up/Down buttons to Objects view (by iskolbin) * Added pixel coordinates to status bar for object tools (by iskolbin) * Added Sticker Knight platformer example (by Ponywolf) * tmxrasterizer: Added --size argument and support local file URLs * tmxrasterizer: Use smooth pixmap transform by default * Linux: Register tmxrasterizer as thumbnail generator for TMX files * Allow scrolling past map edges with mouse wheel * Enabled HiDpi scaling and improved the quality of some icons * Reversed the order of the objects in the Objects view * JSON plugin: Added Node.js support to the JavaScript export * Updated TMX schema definition (by assofohdz) * Fixed unfinished objects getting saved * Fixed OpenGL rendering mode when application is scaled (HiDpi screens) * Fixed Remove and Rename actions for predefined properties * Windows: Fixed console output * libtiled-java: Use Maven, deploy to OSSRH and code updates (by Mike Thomas) * libtiled-java: Added a basic isometric renderer (by Mike Thomas) * Updated Brazilian Portuguese, Chinese, Czech, Dutch, Hebrew, Norwegian Bokmål and Spanish translations ### 0.17.2 (28 November 2016) * Fixed bug with editing type and name for multiple objects * Fixed ability to change the image of a tile in an image collection tileset * Fixed wrong layer name getting edited when switching maps * Fixed possible crash when missing tileset images and using tile animations * Compiled against Qt 5.6.2 on macOS to avoid crashes with Qt 5.7 ### 0.17.1 (4 November 2016) * Fixed wrong alpha value when opening the color picker dialog * Fixed saving of object group color alpha value * Fixed tile id adjustment for newly added tilesets * Fixed "Object Properties" entry in the context menu to be always enabled (by Erik Schilling) * Fixed out-of-sync tile selection during layer offset change (by nykm) * Fixed hidden objects becoming visible when offsetting the map (by ranjak) * Fixed problems with using predefined file properties * Lua plugin: Fixed type of animation frame properties * OS X: Use standard shortcut for toggling full screen * OS X: Fixed compile when pkg-config is present * Windows: Include the Defold plugin * Windows: Added support for DDS, TGA, WBMP and WEBP image formats * Linux: Added 64-bit AppImage (with help from Simon Peter) * Chinese translation updates (by endlesstravel and buckle2000) * French translation updated (by Yohann Ferreira) ### 0.17.0 (15 August 2016) * Added a platform-independent theme, which can be dark (#786) * Added Paste in Place action for objects (#1257) * Added custom property type 'color' (#1275) * Added custom property type 'file' (#1278) * Added option for removing invisible objects in resize dialog (#1032, by Mamed Ibrahimov) * Added support for editing multi-line string properties (#205) * Added %layername and %objectid to available command variables * Added support for scrolling in tileset view with middle mouse button (#1050, with Will Luongo) * Added a rectangle erase mode to the eraser (#1297) * Added export to Defold .tilemap files (by Nikita Razdobreev) * Added simple full screen mode * Added "Copy File Path" and "Open Containing Folder" actions to tab context menu * Added warning when saving with the wrong file extension * Added color picker for setting transparent color of a tileset (#1173, by Ava Brumfield) * Various object selection tool improvements * Allow creating rectangle/ellipse objects in any direction (#1300) * Enabled nested views and grouped dragging for stacked views (#1291) * Fixed updating object drag cursor when exiting resize handles (#1277) * Fixed tile animations to stay in sync when changing them (#1288) * Fixed preservation of tile meta-data when tileset width is changed (#1315) * Updated Bulgarian, Dutch, German, Norwegian Bokmål, Russian, Spanish and Turkish translations ### 0.16.2 (7 July 2016) * JSON plugin: Fixed loading of custom properties on terrains * Lua plugin: Fixed missing export of object layer drawing order * Fixed tile index adjustment when tileset image changes width * Fixed --export-map [format] option * Fixed shortcuts for some tools when language is set to Dutch * Fixed a painting related bug affecting the top edge after AutoMapping * Fixed issues when compiling against Qt 5.6 on OS X and Windows * Fixed crash on maximizing with Maps view open on Windows (Qt 5.6.1) * Fixed focus issue while typing predefined object types (Qt 5.6) * Fixed silent fail when saving to restricted location on Windows (Qt 5.6) ### 0.16.1 (6 May 2016) * Fixed auto-updater not enabled for Windows release * Fixed saving of object IDs assigned to tile collision shapes * Fixed crash when pressing Backspace with Custom Properties section selected * Fixed crash on exit when leaving the Tile Collision Editor open * Added Norwegian Bokmål translation (by Peter André Johansen) * Updated Turkish translation ### 0.16.0 (28 March 2016) * Added checking for updates, based on Sparkle and WinSparkle * Added default property definitions to object types (with Michael Bickel) * Added types to custom properties: string, float, int, boolean (with CaptainFrog) * Added Properties view to the Tile Collision Editor (by Seanba) * Added a reset button for color properties * Added eraser mode to Terrain Brush and fixed some small issues * Reuse existing Tiled instance when opening maps from the file manager (with Will Luongo) * Allow setting tile probability for multiple tiles (by Henrik Heino) * New MSI based installer for Windows * Optimized selection of many objects * libtiled-java: Fixed loading of maps with CSV layer data that are not square (by Zachary Jia) * Fixed potential crash when having Terrain Brush selected and switching maps * Updated Dutch, French, German, Japanese, Russian and Spanish translations ### 0.15.2 (6 March 2016) * Added Turkish translation (by Nuri Uzunoğlu) * Fixed hiding of object labels when deleting an object layer * Fixed updating of object label colors when changing object types * TMX: Added image size attributes to image layer images * Updated Brazilian Portuguese translation ### 0.15.1 (30 January 2016) * Fixed adding/removing object name labels when set to always visible * Fixed a problem with 'Execute in Terminal' on OS X * Fixed mouse coordinate conversion for hexagonal renderer * Fixed image layer offset handling * Update Czech translation ### 0.15.0 (4 January 2016) * Allow loading maps with broken external references * Allow plugins to be enabled/disabled * Allow changing tileset image parameters * Allow changing the images of tiles in a collection tileset * Allow changing external tileset references * Allow panning over the edges of the map * Added Terrain Generator tool * Added column count property to image collection tilesets * Added a combo box for changing the current layer to the status bar * Moved the AutoMapping while drawing toggle into the menu * Removing tiles from collection tilesets no longer changes tile IDs * Unified layer offset handling * Default tile layer data format changed to CSV * Deprecated pure XML and Gzip-compressed tile layer data formats * Fixed random tile picker for tiles with zero probability (by Henrik Heino) * Fixed saving of alpha value of the map background color * Fixed crash in tmxrasterizer and tmxviewer * Fixed tmxrasterizer not reporting write errors * Fixed isometric rendering bug with odd tile heights (by Ryan Schmitt) * Updated Bulgarian, Dutch, French, German, Japanese, Russian and Spanish translations ### 0.14.2 (12 October 2015) * Added Polish translation (by Tomasz Kubiak) * Fixed layer offsets missing in the Lua export * Fixed JSON tileset format missing in 'Add External Tileset' action * Fixed language selection entries for Portuguese * Fixed an issue with copy/pasting when using image collection tilesets * Updated Brazilian Portuguese translation ### 0.14.1 (28 September 2015) * Added missing 'renderorder' property to the Lua export * Fixed editing of properties of tiles captured from the map ### 0.14.0 (21 September 2015) * Added support for custom external tileset formats (JSON format added) * Added support for shifting layers by some distance in pixels * Added back object name labels in a much improved form * Added tile stamp variation support to the fill tool * Synchronize tileset selection when capturing tiles from the map * Change tile in collision and animation editors based on selected tile object * Keep the active brush when switching maps * Python plugins can now add export-only map formats * Fixed updating of current tile when changing map * Fixed animated tile overlay to look less odd in some cases * Fixed Save As dialog popping up when saving fails * Fixed tilesets view collapsing when switching maps on OS X * Updated Russian, Spanish, Czech, French, Japanese, German, Dutch and Bulgarian translations ### 0.13.1 (6 September 2015) * Added Bulgarian translation (by Lyubomir Vasilev) * Updated Spanish, French and Dutch translations ### 0.13.0 (10 August 2015) * Added persistent Tile Stamps with support for variations (#969) * Added Select Same Tile tool (by Mamed Ibrahimov) * Added option to disable opening of last files on startup (by Mamed Ibrahimov) * Added tilecount property to TMX, JSON and Lua map formats (#806) * Added tileset properties to Properties view, as read-only (by Mamed Ibrahimov) * Added Save All action (by Mamed Ibrahimov) * Added translation of command line messages (by Mamed Ibrahimov) * Added menu item linking to online documentation * Object selection outlines are now drawn on top of everything * Select new objects after they have been created * Made the starting point for polylines and polygons visible * Use the tile probability property also in random mode * Ungrouped position and size properties (#892) * CSV plugin: Extended to export all tile layers (by Alejandro Cámara) * Lua and JSON plugins: Added support for layer data compression * Fixed crash when changing flipping flag for multiple objects (by Mamed Ibrahimov) * Fixed Ctrl+T causing a crash when no maps are open * Fixed availability of 'Execute in Terminal' command on Linux with Qt 5 * Fixed drag object mouse cursor to appear only when it should * Fixed selected file format when doing Save As with a non-TMX map * Fixed problems with infinate scaling factors when resizing objects * Require at least Qt 5.1.0 * Require compiler support for C++11 * Updated Russian, German, Czech and Italian translations ### 0.12.3 (1 June 2015) * Fixed updating of map view when rotating objects with Z key * Fixed updating of map view when joining, splitting or deleting polygon nodes * Fixed a crash when reading an invalid TMX file * Fixed live automapping updates when moving the mouse fast * Made Backspace work for deleting collision objects and animation frames ### 0.12.2 (22 May 2015) * Fixed updating of map view when moving objects with arrow keys * Fixed compatibility issue with tile objects affecting the JSON format ### 0.12.1 (19 May 2015) * Fixed updating of map view when changing objects from properties view * Fixed updating of Properties view while objects are moved/resized * Fixed terrain information getting lost when reading JSON maps ### 0.12.0 (14 May 2015) * Added support for resizing any object as well as multiselection (with mauve) * Added Control modifier for preserving aspect ratio while resizing * Added Shift modifier for resizing with origin in the middle * Added Alt modifier for suppressing selection changes when starting to drag * Added a Magic Wand selection tool (by Henry Jia) * Added tile probability attribute to tile properties view * Added a Donate button to the About dialog * Added a Patreon dialog to the Help menu * Added an --export-formats command line option * Remember the directory used for external tilesets (by Henry Jia) * Don't set a window icon on Mac OS X * Changed the way tile probability is applied (now it's relative) * Fixed a crash in the terrain brush * Fixed object selection behavior when Shift is held while clicking on nothing * Fixed grid snapping being applied for staggered maps even when not enabled * Fixed infinite memory allocation loop on invalid tile size in TMX file * Fixed file icon associated with TMX files on Windows * Fixed automapping of tile objects (by Seanba) * Fixed 'Export as Image' to handle out of memory errors * Fixed TMX files to be written in native line endings * Fixed .desktop file missing %f argument for passing files (by Ying-Chun Liu) * Fixed cursor position resetting when editing object type * Added Arabic (Algeria) translation (by Damene Abdelkader) * Updated, Czech, Dutch, French, German, Italian, Japanese, Portuguese, Russian and Spanish translations ### 0.11.0 (11 January 2015) * Added support for hexagonal maps (offset coordinates) * Added 'Export' action to repeat the last export * Added a shortcut for the Reload action (Ctrl+R) * Added ability to rename custom properties (by arn00d) * Added unique IDs to objects (by Mark van Rij) * Added a CSV export plugin * Added visual feedback when properties differ between multiple selected objects (by Parker Miller) * Added command-line export (by Brandon Dillon) * Allow dynamically changing the map orientation and grid size * Suppress the standard main window context menu in the collision editor * Lua plugin: Write out tile terrain information * Lua plugin: Include Tiled version in exported file * Flare plugin: Fixed ability to open maps with absolute paths * Fixed grid rendering for staggered maps * Fully support building and running Tiled with Qbs * Updated Czech, Dutch, French, German, Italian, Japanese, Portuguese and Spanish translations ### 0.10.2 (23 October 2014) * Fixed hit area for polygon nodes when editing polygons while zoomed in or out * Fixed another possible crash in the orthogonal renderer * Fixed Select All action to work for object layers * Fixed map pixel size preview for staggered maps * Fixed repainting issues when tiles extend beyond their layer boundaries * Fixed repainting issues when using tiles smaller than the grid size * Display errors non-modal when applying automatic automapping rules * Flare plugin: Fixed coordinate format for import and export (by Justin Jacobs) * Lua plugin: Write out Image layer position * Small updates to the Italian translation (by Omnomnobot) ### 0.10.1 (21 September 2014) * Fixed a crash that could happen when using the terrain tool * Fixed missing background color information from Lua export * Allow using up to 3 or 4 GB RAM on 32 or 64 bit Windows systems respectively ### 0.10.0 (14 September 2014) * Added object rotation (sponsored by Ben Wales) * Added support for explicit object ordering (sponsored by Ben Wales) * Added new Properties window with a rewritten properties editor * Added support for writing plugins in Python (by Samuli Tuomola) * Added image collection tilesets (sponsored by Jamie Rocks) * Added map file watching and automatic reloading (sponsored by FlatRedBall.com) * Added support for moving objects with arrow keys (sponsored by Ben Wales) * Added a 'snap to fine grid' option (by Xenodora) * Added support for JavaScript (JSONP) load/save (by Dobes Vandermeer) * Added more zoom levels (by Joel Leclerc) * Added shortcuts for finishing and canceling object creation * Added a tile collision editor for defining collision shapes on tiles * Added a tile animation editor and play defined animations * Allow changing properties of multiple objects/tiles simultanously (by Parker Miller) * Added tile rendering-order map property (by Lennert Raesch) * Added support for changing the object line width * Added support for CSV-encoded layers to libtiled-java (by Alexei Bratuhin) * Added support for ellipse and polygon objects to libtiled-java (by Hendrik Brummermann) * Added terrain properties to JSON export (by Dennis Hostetler) * Added support for moving image layers in the Properties window (by Michael Aquilina) * Added option to include background image when saving as image (by Sean Humeniuk) * Added options to control layer visibility to tmxrasterizer (by Nathan Tolbert) * Added display of tile ID in status bar (by Champi080) * Added support for objects on staggered isometric maps (by Remco Kuijper) * Added support for staggered maps to tmxviewer and tmxrasterizer * Added a tool for moving the image of an image layer (by Mattia Basaglia) * Added button to the tileset dock as shortcut to add a tileset (by Erik Schilling) * Allow changing order of open document tabs (by Sean Humeniuk) * Changed object position and size units from tiles to pixels (by mauve) * Allow adding multiple tilesets at once (by mauve) * Make highlighted grid cells outside map red (by Sean Humeniuk) * Allow changing the drawing offset of a tileset * Fixed hang on Mac OS X when drawing certain ellipse objects * Fixed removal of polygon/polyline objects when resizing a map * Fixed writing of tile offset in the Lua export * Fixed updating of image layer when changing its image * Fixed start drag distance check when editing polygons and moving objects * Fixed console output of tmxrasterizer on Windows * Raise the Layers dock for editing a new layer's name * Avoid saving truncated files when compiled against Qt 5.1 or higher (by Erik Schilling) * Made Tiled registering *.tmx as MIME-type (by Erik Schilling) * Added Traditional Chinese translation (by Yehnan Chiang) * Updated Czech, Dutch, French, German, Russian and Spanish translations ### 0.9.1 (27 July 2013) * Added saving of map background to JSON format (by Petr Viktorin) * Added saving of terrain information to JSON format (by Petr Viktorin) * Object Selection tool now always start selecting objects when holding Shift * Increased maximum for tileset margin and spacing to 9999 * Some updates to libtiled-java (by Oskar Wiksten) * Install the automappingconverter application (relevant on Linux) * Avoid using Windows 95 style (was used on some Linux desktop environments) * Removed layer name checks from the Flare export plugin (by Stefan Beller) * Double-clicking an object now opens the Object Properties dialog * Fixed Object Properties dialog not remembering its size * Fixed object drawing order for image saving and mini-map * Fixed some plurals in English translation * Fixed line widths when zooming in Qt 5 * Fixed updating of image layer when its opacity or image is changed * Fixed display of grid in tileset view on certain zoom levels * Fixed save in wrong format after opening a map with plugin (by Mike Hendricks) * Fixed closing Tiled being very slow with many maps * Fixed saving of image layer properties in the Lua format * Fixed escaping of special characters in the Lua format * Fixed handling of relative paths for image layers in the JSON plugin ### 0.9.0 (27 January 2013) * Added objects dock and per-object visibility toggle (by Tim Baker) * Added maps dock (by Tim Baker) * Added terrain tool for automatic terrain transitions (by Manu Evans) * Added a minimap (by Christoph Schnackenberg) * Added a staggered isometric map renderer, still without object layer support * Added basic image layer support (by Gregory Nickonov and Alexander Kuhrt) * Added display of current layer to the status bar (by Tim Baker) * Added editable combo box for changing the zoom level (by Tim Baker) * Added support for multiple input layers to automapping (by Stefan Beller) * Added option to apply automapping rules while editing (by Stefan Beller) * Added a converter to update old automapping rules (by Stefan Beller) * Added support for objects layers to automapping (by Stefan Beller) * Added support for random mode to the fill tool (by Stefan Beller) * Added Replica Island plugin (by Eric Kidd) * Added option to change the grid color (by Stefan Beller) * Added support for ellipse objects (by devnewton and Christoph Schnackenberg) * Added name labels for objects on isometric maps (by Andrew Motrenko) * Added map property for changing the background color (by Emmanuel Barroga) * Added shortcut to manually reload tilesets (Ctrl-T) (by Michael Williams) * Added toggle for showing tile object outlines * Added support for pinch zooming (by Pierre-David Bélanger) * Added initial (non-GUI) support for individual and/or embedded tile images (by Petr Viktorin) * Added reading support to Flare plugin (by Stefan Beller) * Added a TMX rasterizer command line tool (by Vincent Petithory) * Added man pages and desktop file (by Erik Schilling) * Made the size and position of most dialogs persistent * Respect the original layer data format of a loaded map (by Ben Longbons) * Marked Tiled as high-resolution capable on Mac OS X * Improved handling of external tilesets in Lua export * Reverted tilesets view back to tabs, but with menu button (by Stefan Beller) * Allowed plugins to support multiple file name filters (by Samuli Tuomola) * Allow saving in any format that can also be read (by Stefan Beller) * Fixed eraser skipping tiles when moving fast * Fixed bug in Flare plugin (by Clint Bellanger) * Fixed compile against Qt 5 (by Kenney Phillis) * Fixed resolving of symbolic links while loading map * Fixed a crash that could happen after trying to load a faulty map * Updated Portuguese, Dutch, German, Spanish, Russian, French, Japanese, Chinese, Brazilian Portuguese, Hebrew and Czech translations ### 0.8.1 (7 May 2012) * Added MacOS X Lion full screen support * Fixed crash that could happen when painting with a pasted stamp * Fixed zoom sensitivity for finer-resolution mouse wheels * Fixed issues when using quickstamps in combination with the fill tool * Fixed stamp tool not to miss tiles when drawing fast * Fixed automapping to work with external tilesets * Fixed crash in automapping when dealing with broken rule files * Fixed object type getting erased on pressing Enter * Changed the license of libtiled-java from LGPL to BSD * Updated Italian and Hebrew translations ### 0.8.0 (11 December 2011) * Added support for polygon and polyline objects * Added support for tile rotation * Added support for defining the color of custom object types * Added a Delete action to delete selected tiles or objects * Added random mode to the stamp brush * Added Flare export plugin * Added JSON plugin that supports both reading and writing * Added ability to rename tilesets * Added a mode in which the current layer is highlighted * Added support for specifying a tile drawing offset * Added a shortcut to copy the current tile position to clipboard (Alt+C) * Added a command line option to disable OpenGL * Allow custom properties on tilesets * Many automapping improvements * Improved tileset dock to handle a large amount of tilesets better * Made the 'Show Grid' option in the tileset view persistent * Raised the tile size limit in the New Tileset dialog from 999 to 9999 * Correctly handle changes in the width of a tileset image * Worked around a long standing crash bug * Added Russian translation * Updated the German, Japanese, Spanish, Chinese, Czech, Dutch, French and Brazilian Portuguese translations ### 0.7.1 (27 September 2011) * Select stamp tool when selecting tiles in tileset view * Enable anti-aliasing for OpenGL mode * Small improvement to the Lua export plugin (incompatible!) * Fixed a bug in the Create Object tool * Fixed reading of maps without tilesets but with a tile layer * Fixed position of tile objects to center on the mouse on insertion * Updated the Czech translation ### 0.7.0 (20 July 2011) * Added support for horizontal and vertical flipping of tiles * Added copy/paste support for objects * Added merge layer down action * Added Show or Hide all Other Layers action * Added actions to select the previous/next layer * Added Crop to Selection action * Added a Lua export plugin * Added Droidcraft plugin to read and export the map files * Added option to turn off grid in the tileset view * Added hand scrolling while holding the spacebar * Made the object context menu available in all object tools * Display tile coordinates also when using object tools * Various improvements to running external commands * Automapping stability and memory consumption improvements * Objects that fall outside of the map on resize are now removed * Fixed problems with watching tilesets multiple times * Fixed several issues related to restoring previously opened files * Updated Brazilian Portuguese, Chinese, German, Spanish, Japanese, Hebrew, Portuguese, Dutch and French translations ### 0.6.2 (2 May 2011) * Fixed object layers losing their color when resizing the map * Fixed the tabs in the Tilesets dock to use scroll buttons on MacOS X * Fixed window title to update when saving a map with a different name ### 0.6.1 (3 April 2011) * Added ability to open multiple files at once * Added Ctrl+PageUp/PageDown shortcuts to switch documents * Added an example to show how automatic mapping works * Fixed bugs, crashes and leaks in the automatic mapping feature * Fixed starting point for circles to be the click position * Fixed a memory leak when using lines or circles * Fixed layer opacity to be taken into account when saving as image * Fixed endless loop when tile size is set to 0 * Fixed crash when passing an empty string as command line parameter * Fixed problems with the tileset view after switching documents * Fixed tile objects to be removed when their tileset is removed ### 0.6.0 (26 January 2011) * Added support for opening multiple maps in one session * Added support for placing tiles as objects * Added automatic mapping feature, allowing placing of tiles based on rules * Added ability to save/restore up to 9 stamps with Ctrl+ * Added an object selection tool, allowing moving/deleting multiple objects * Added ability to run external commands * Added support for drawing lines and ellipses with the stamp brush * Added icons to distinguish tile layers from object layers * Added "Move To Layer" submenu to the context menu of objects * Added option to use hardware rendering based on OpenGL * Added a T-Engine4 map export plugin * Added a simple TMX viewer application (BSD licensed) * Added a New Layer dropdown menu to the layers dock * Added a checkbox that enables snap to grid permanently * Added an initial version of libtiled-java (LGPL licensed) * Added Chinese and Hebrew translations * Allowed dragging an image onto Tiled to add a tileset * Center the map when it is smaller than the map view * Remember the selected layer across restarts * Changed the default layer data format to use zlib rather than gzip * Store the tileset image width and height in the map file * Compile fixes related to linking zlib * Fixed the current stamp to get updated when switching tilesets * Fixed the maximum sizes of the resize map dialog * Fixed build issues when an older version of libtiled is installed * Fixed saving of property when clicking OK while editing on MacOS X * Allow Backspace to delete properties to make it easier on a MacBook * Associate tmx files with Tiled on MacOS X * Changed the license of libtiled from GPL to BSD * Updated Czech, Spanish, German, Brazilian Portuguese, Dutch and French translations ### 0.5.1 (2 September 2010) * Fixed saving of objects when tile width is different from tile height * Updated Czech translation ### 0.5.0 (30 June 2010) * Added support for import and export plugins * Added support for external tilesets * Added undo for adding tilesets and ability to remove tilesets * Added error handling to the New Tileset dialog * Added ability to change tileset order by dragging them around * Added option to draw the tile grid when saving as image * Added a context menu and tool buttons to the layer dock * Added Latvian translation * Added an install target to the Makefile * Open local files when they are dropped onto Tiled * Allow changing position and size of objects in the Object Properties dialog * Fixed rendering issues with tiles wider than the tile width of the map * Fixed eraser and fill tool working on invisible layers * Fixed a crash when using some tools when no map is loaded * Fixed compile errors related to detecting static builds * Fixed the Save dialog not suggesting any particular file extension * Updated Japanese, Dutch, German, Brazilian Portuguese, French, Portuguese and Spanish translations ### 0.4.1 (14 April 2010) * Added support for saving tile layer data as CSV * Added shift modifier to bucket fill tool for filling the selection * Added Brazilian Portugese, Japanese, French, Italian and Czech translations * Made values used in the New Map and New Tileset dialogs persistent * Fixed drawing selection highlight where brush is not painting * Fixed an incompatibility with Tiled Java in 'trans' attribute ### 0.4.0 (30 January 2010) * Added support for isometric maps * Added automatic reloading of tileset images when they change * Added Offset Map action that can shift a set of layers by a certain amount * Added a fill tool * Added ability to duplicate map objects * Added support for choosing the tile layer data format used when saving * Added mouse wheel zooming support to the tileset view * Added an object display color attribute to object groups * Added ability to edit tile properties through a context menu * Made writing out a DTD reference optional and disabled it by default * Made translations functional * Updated Dutch, Portuguese, Spanish and German translations ### 0.3.1 (22 November 2009) * Enabled undo command compression for stamp brush and eraser * Fixed reading of maps with non-binary-encoded layer data * Fixed a compile issue on Mac OS X related to QXmlStreamWriter * Fixed a crash when loading a map while holding Ctrl * Confirm overwrite on the right moment for 'Save as Image' dialog ### 0.3.0 (13 November 2009) * Added a tile selection tool * Added support for cut, copy and paste * Added current cursor position to the status bar * Added keyboard shortcuts to switch tools * Added scrolling the map view with middle mouse button * Snap objects to the grid when Ctrl is pressed ### 0.2.0 (1 October 2009) * Added support for zooming the map view * Added an eraser tool that allows you to erase tiles * Added ability to save a map as an image * Added support for masking tileset images based on a certain color * Added a slider to change the opacity of the current layer * Fixed the minimum row and column size in the tileset view * Fixed stamp creation when not dragging topleft to bottomright ### 0.1.0 (1 September 2009) tiled-1.0.3/README.md000066400000000000000000000064731315121121300140730ustar00rootroot00000000000000Tiled Map Editor - http://www.mapeditor.org/ About Tiled ------------------------------------------------------------------------------- Tiled is a general purpose tile map editor. It is meant to be used for editing maps of any tile-based game, be it an RPG, a platformer or a Breakout clone. Tiled is very flexible, for example there are no restrictions on map size, tile size or the number of layers or tiles. Also, it allows arbitrary properties to be set on the map, its layers, the tiles or on the objects. Its map format (TMX) is relatively easy to understand and allows a map to use multiple tilesets while also allowing each tileset to grow or shrink as necessary later. [![Build Status](https://travis-ci.org/bjorn/tiled.svg?branch=master)](https://travis-ci.org/bjorn/tiled) [![Build status](https://ci.appveyor.com/api/projects/status/ceb79jn5cf99y3qd/branch/master?svg=true)](https://ci.appveyor.com/project/bjorn/tiled/branch/master) [![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=52019)](https://www.bountysource.com/trackers/52019-tiled?utm_source=52019&utm_medium=shield&utm_campaign=TRACKER_BADGE) [![Translation status](https://hosted.weblate.org/widgets/tiled/-/shields-badge.svg)](https://hosted.weblate.org/engage/tiled/?utm_source=widget) About the Qt Version ------------------------------------------------------------------------------- Tiled was originally written in Java. In 2008 the Qt version was started with the goal to replace the Java version with a faster, better looking and even easier to use map editor. Qt offered many opportunities to improve the performance and usability of the user interface, and has a more extensive feature set than the standard Java libraries. Compiling ------------------------------------------------------------------------------- Make sure the Qt (>= 5.4) development libraries are installed: * In Ubuntu/Debian: `apt-get install qt5-default qttools5-dev-tools zlib1g-dev` * In Fedora: `sudo dnf builddep tiled` * In Arch Linux: `pacman -S qt` * In Mac OS X with [Homebrew](http://brew.sh/): + `brew install qt5` + `brew link qt5 --force` * Or you can download Qt from: https://www.qt.io/download-open-source/ Now you can compile by running: $ qmake (or qmake-qt5 on some systems) $ make To do a shadow build, you can run qmake from a different directory and refer it to tiled.pro, for example: $ mkdir build $ cd build $ qmake ../tiled.pro $ make You can now simply run Tiled using bin/tiled. Installing ------------------------------------------------------------------------------- For installing Tiled you can run `make install`. By default Tiled will install to `/usr/local`. You can change this prefix when running qmake, and/or you can change the install root when running make install, as follows: Use `/usr` instead of `/usr/local`: $ qmake -r PREFIX=/usr (Recursive needed when it's not the first time that you're running qmake, since this affects nested pro files) Install to some packaging directory: $ make install INSTALL_ROOT=/tmp/tiled-pkg By default, Tiled and its plugins are compiled with an Rpath so that they can find the shared libtiled library when running it straight after compile. When packaging for a distribution, this Rpath should generally be disabled by appending `RPATH=no` to the qmake command. tiled-1.0.3/appveyor.yml000066400000000000000000000064361315121121300152030ustar00rootroot00000000000000clone_depth: 200 version: '1.0.{build}' environment: my_secret: secure: +3IhWT10lCSC4GE4gGfWt8WiZdIXuMUfaImgvQUullg= matrix: - QTDIR: C:\Qt\5.8\msvc2013_64 PUSH_RELEASE: true TILED_ITCH_CHANNEL: windows-64bit - QTDIR: C:\Qt\5.8\mingw53_32 MINGW: C:\Qt\Tools\mingw530_32 PUSH_RELEASE: true TILED_ITCH_CHANNEL: windows-32bit - QTDIR: C:\Qt\5.6\mingw49_32 MINGW: C:\Qt\Tools\mingw492_32 PUSH_RELEASE: false TILED_ITCH_CHANNEL: winxp-32bit configuration: Release install: - choco install -y qbs --version 1.7.2 - nuget install secure-file -ExcludeVersion - set PATH=%PATH%;%QTDIR%\bin;%MINGW%\bin build_script: - FOR /F "tokens=*" %%i in ('git describe') do SET COMMITNOW=%%i - set VERSION_DATE=%DATE:~10,4%.%DATE:~4,2%.%DATE:~7,2% - set TILED_SPARKLE=true - if defined APPVEYOR_REPO_TAG_NAME (set TILED_RELEASE=true) else (set TILED_SNAPSHOT=true) - if defined TILED_RELEASE set TILED_VERSION=%APPVEYOR_REPO_TAG_NAME:~1% - if defined TILED_RELEASE echo Building Tiled %TILED_VERSION%... (from %COMMITNOW%) - if defined TILED_SNAPSHOT set TILED_VERSION=%APPVEYOR_BUILD_VERSION% - if defined TILED_SNAPSHOT echo Building Tiled snapshot %TILED_VERSION%... (from %COMMITNOW%) - qbs --version - qbs setup-toolchains --detect - qbs setup-qt %QTDIR%\bin\qmake.exe qt - qbs config defaultProfile qt - if defined TILED_RELEASE (set TILED_ITCH_VERSION=%TILED_VERSION%) else (set TILED_ITCH_VERSION=%VERSION_DATE%) - if defined TILED_SNAPSHOT (set TILED_ITCH_CHANNEL=%TILED_ITCH_CHANNEL%-snapshot) - if not defined APPVEYOR_PULL_REQUEST_NUMBER if [%APPVEYOR_REPO_BRANCH%]==[snapshot] set PUSH_TO_ITCH=true - qbs build --all-products release Tiled.windowsInstaller:true - qbs build --all-products itch qbs.buildVariant:release Tiled.sparkleEnabled:false Tiled.version:%TILED_ITCH_VERSION% after_build: - cd release - cd installer* - move tiled-*.msi %APPVEYOR_BUILD_FOLDER% - if defined TILED_SNAPSHOT move appcast-win*-snapshots.xml %APPVEYOR_BUILD_FOLDER% - cd .. - cd archive* - move tiled-*.7z %APPVEYOR_BUILD_FOLDER% - cd ..\.. - if defined PUSH_TO_ITCH dist\win\push-to-itch.bat artifacts: - name: Installer path: 'tiled-*.msi' - name: Archive path: 'tiled-*.7z' - name: AppCast path: 'appcast-win*-snapshots.xml' deploy: - provider: GitHub release: Tiled $(TILED_VERSION) auth_token: secure: 57ahePdHlJPeOX8/MqsIg5ho4x512wvAbwRA7TkXAOav/JTHvkTG5gf8k37/883r artifact: /.*\.msi/ draft: true on: appveyor_repo_tag: true push_release: true - provider: FTP protocol: sftp host: update.mapeditor.org username: bjorn password: secure: Hx5YfCOtpeBbftD4qnVCRLUGmMU9nogJTlSxq0xNbJQ= folder: sparkle/snapshots-win artifact: /.*\.(msi|7z)/ on: branch: snapshot appveyor_repo_tag: false push_release: true - provider: FTP protocol: sftp host: update.mapeditor.org username: bjorn password: secure: Hx5YfCOtpeBbftD4qnVCRLUGmMU9nogJTlSxq0xNbJQ= folder: sparkle artifact: /appcast-win.*-snapshots\.xml/ on: branch: snapshot appveyor_repo_tag: false push_release: true notifications: - provider: Webhook url: https://webhooks.gitter.im/e/6e48d432e0e0dd1b2d22 tiled-1.0.3/dist/000077500000000000000000000000001315121121300135455ustar00rootroot00000000000000tiled-1.0.3/dist/appcast-osx-snapshots.xml.in000066400000000000000000000015321315121121300211570ustar00rootroot00000000000000 Tiled Development Snapshots http://update.mapeditor.org/appcast-snapshots.xml en Tiled @VERSION@ @VERSIONDATE@ https://github.com/bjorn/tiled/commits/snapshot 10.7.0 tiled-1.0.3/dist/appcast-win-snapshots.xml.in000066400000000000000000000012351315121121300211430ustar00rootroot00000000000000 Tiled Development Snapshots http://update.mapeditor.org/@APPCAST_FILENAME@ en Tiled @VERSION@ @DATE@ https://github.com/bjorn/tiled/commits/snapshot tiled-1.0.3/dist/archive.qbs000066400000000000000000000020001315121121300156650ustar00rootroot00000000000000import qbs InstallPackage { builtByDefault: false condition: { return ((project.snapshot || project.release) && (qbs.toolchain.contains("mingw") || qbs.toolchain.contains("msvc")) || (project.linuxArchive && qbs.targetOS.contains("linux"))); } archiver.type: { if (qbs.targetOS.contains("windows")) return "7zip" else return "tar" } Depends { productTypes: [ "application", "dynamiclibrary", "qm", "installable", ] } property int bits: { if (qbs.architecture === "x86_64") return 64; if (qbs.architecture === "x86") return 32; } targetName: { var baseName = "Tiled-" + project.version; if (qbs.targetOS.contains("windows")) baseName += "-win"; else if (qbs.targetOS.contains("linux")) baseName += "-linux"; return baseName + bits; } } tiled-1.0.3/dist/butler_creds.enc000066400000000000000000000000601315121121300167050ustar00rootroot00000000000000;` Lӣp/:Gr%u{PVt$r2,_tiled-1.0.3/dist/copr/000077500000000000000000000000001315121121300145105ustar00rootroot00000000000000tiled-1.0.3/dist/copr/build.sh000077500000000000000000000016551315121121300161550ustar00rootroot00000000000000#!/usr/bin/bash BUILDROOT="$(pwd)/tmp-buildroot/" rm -rf $BUILDROOT [ -d buildroot ] || mkdir -p ${BUILDROOT}/{SOURCES,SPECS} pushd $(git rev-parse --show-toplevel) VERSION=$(git describe | sed 's/^v//' | sed 's/-[^-]*$//' | sed 's/-/\./') git archive HEAD --prefix=tiled-$VERSION/ -o ${BUILDROOT}/SOURCES/tiled-$VERSION.tar.gz || exit 1 popd cat tiled.spec | sed "s/^Version:\(.*\)/Version: $VERSION/" > ${BUILDROOT}/SPECS/tiled_tmp.spec rpmbuild --define "_topdir ${BUILDROOT}/" -bs ${BUILDROOT}/SPECS/tiled_tmp.spec || exit 1 pushd ${BUILDROOT} FILE=$(find -name "*.src.rpm") cp $FILE ../tiled.src.rpm popd rm -rf $BUILDROOT if [ "$1" = "srpm-only" ] then echo "Wrote tiled.src.rpm. Exiting." else COPR_CONFIG=" [copr-cli] login = $1 username = $2 token = $3 copr_url = https://copr.fedorainfracloud.org " copr --config <(echo "$COPR_CONFIG") build ablu/tiled-dailies tiled.src.rpm || exit 1 rm tiled.src.rpm fi tiled-1.0.3/dist/copr/tiled.spec000066400000000000000000000234711315121121300164740ustar00rootroot00000000000000Name: tiled Version: 0.18.0 Epoch: 1 Release: 1%{?dist} Summary: Tiled Map Editor # tiled itself is GPLv2+, libtiled and tmxviewer are BSD License: GPLv2+ and BSD URL: http://www.mapeditor.org Source0: https://github.com/bjorn/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz BuildRequires: pkgconfig(Qt5Core) BuildRequires: qt5-qttools-devel BuildRequires: zlib-devel BuildRequires: desktop-file-utils BuildRequires: python-devel BuildRequires: libappstream-glib %description Tiled is a general purpose tile map editor. It is built to be easy to use, yet flexible enough to work with varying game engines, whether your game is an RPG, platformer or Breakout clone. Tiled is free software and written in C++, using the Qt application framework. This package contains the tiled application and tmxviewer, a simple application to view Tiled maps. %package plugin-python Summary: Python plugin for Tiled License: GPLv2+ URL: http://www.mapeditor.org Requires: %{name} = %{epoch}:%{version}-%{release} %description plugin-python A plugin for tiled which allows to write Python plugins. %define pluginwarning Warning: This plugin does not offer full compatibility with Tileds features. %package plugin-tmw Summary: The Mana World plugin for Tiled License: GPLv2+ URL: http://www.mapeditor.org Requires: %{name} = %{epoch}:%{version}-%{release} %description plugin-tmw A plugin for tiled which allows to export maps as eAthena collision files. %{pluginwarning} %package plugin-droidcraft Summary: Droidcraft plugin for Tiled License: GPLv2+ URL: http://www.mapeditor.org Requires: %{name} = %{epoch}:%{version}-%{release} %description plugin-droidcraft A plugin for tiled which allows to save maps as .dat droidcraft maps. %{pluginwarning} %package plugin-flare Summary: Flare plugin for Tiled License: GPLv2+ URL: http://www.mapeditor.org Requires: %{name} = %{epoch}:%{version}-%{release} %description plugin-flare A plugin for tiled which allows to save maps as .txt flare maps. %{pluginwarning} %package plugin-replica-island Summary: Replica Island plugin for Tiled License: GPLv2+ URL: http://www.mapeditor.org Requires: %{name} = %{epoch}:%{version}-%{release} %description plugin-replica-island A plugin for tiled which allows to save maps as .bin Replica Island maps. %{pluginwarning} %package plugin-t-engine4 Summary: T-Engine4 plugin for Tiled License: GPLv2+ URL: http://www.mapeditor.org Requires: %{name} = %{epoch}:%{version}-%{release} %description plugin-t-engine4 A plugin for tiled which allows to export maps as .lua T-Engine4 maps. %{pluginwarning} %package plugin-defold Summary: Defold plugin for Tiled License: GPLv2+ URL: http://www.mapeditor.org Requires: %{name} = %{epoch}:%{version}-%{release} %description plugin-defold A plugin for tiled which allows to export maps as .tilemap Defold maps. %{pluginwarning} %package plugin-gmx Summary: GameMaker Studio plugin for Tiled License: GPLv2+ URL: http://www.mapeditor.org Requires: %{name} = %{epoch}:%{version}-%{release} %description plugin-gmx A plugin for tiled which allows to export maps as GameMaker Studio room files. %{pluginwarning} %prep %setup -q # Remove copy of zlib rm -rf src/zlib %build %qmake_qt5 -r PREFIX=%{_prefix} LIBDIR=%{_libdir} RPATH=no USE_FHS_PLUGIN_PATH=yes make %{?_smp_mflags} %install make install INSTALL_ROOT=%{buildroot} # Clean build artefacts find -name ".uic" -or -name ".moc" -or -name ".rcc" | xargs rm -rf # Validate desktop file desktop-file-validate %{buildroot}/%{_datadir}/applications/%{name}.desktop # Appdata install -D -p -m644 %{name}.appdata.xml %{buildroot}/%{_datadir}/appdata/%{name}.appdata.xml appstream-util validate-relax --nonet %{buildroot}/%{_datadir}/appdata/*.appdata.xml # locale files %find_lang %{name} --with-qt # Removed development file (this version does not install headers anyway) rm %{buildroot}/%{_libdir}/lib%{name}.so %post /sbin/ldconfig /bin/touch --no-create %{_datadir}/icons/hicolor &>/dev/null || : /usr/bin/update-mime-database %{_datadir}/mime &> /dev/null || : /usr/bin/update-desktop-database &> /dev/null || : %postun /sbin/ldconfig if [ $1 -eq 0 ] ; then /bin/touch --no-create %{_datadir}/icons/hicolor &>/dev/null /usr/bin/gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : fi /usr/bin/update-mime-database %{_datadir}/mime &> /dev/null || : /usr/bin/update-desktop-database &> /dev/null || : %posttrans /usr/bin/gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %files -f %{name}.lang %doc AUTHORS NEWS.md README.md COPYING LICENSE.GPL LICENSE.BSD %{_bindir}/automappingconverter %{_bindir}/%{name} %{_bindir}/terraingenerator %{_bindir}/tmxrasterizer %{_bindir}/tmxviewer %{_datadir}/applications/%{name}.desktop %{_datadir}/icons/hicolor/*/apps/*%{name}* %{_datadir}/icons/hicolor/*/mimetypes/*%{name}* %{_datadir}/mime/packages/%{name}.xml %{_datadir}/thumbnailers/%{name}.thumbnailer %{_datadir}/appdata/%{name}.appdata.xml %dir %{_datadir}/%{name}/ %dir %{_datadir}/%{name}/translations %{_libdir}/lib%{name}.so.* %dir %{_libdir}/%{name}/ %dir %{_libdir}/%{name}/plugins/ # Core plugins %{_libdir}/%{name}/plugins/libcsv.so %{_libdir}/%{name}/plugins/libjson.so %{_libdir}/%{name}/plugins/liblua.so %{_mandir}/man1/automappingconverter.1* %{_mandir}/man1/%{name}.1* %{_mandir}/man1/tmxrasterizer.1* %{_mandir}/man1/tmxviewer.1* %files plugin-python %{_libdir}/%{name}/plugins/libpython.so %files plugin-tmw %{_libdir}/%{name}/plugins/libtmw.so %files plugin-droidcraft %{_libdir}/%{name}/plugins/libdroidcraft.so %files plugin-flare %{_libdir}/%{name}/plugins/libflare.so %files plugin-replica-island %{_libdir}/%{name}/plugins/libreplicaisland.so %files plugin-t-engine4 %{_libdir}/%{name}/plugins/libtengine.so %files plugin-defold %{_libdir}/%{name}/plugins/libdefold.so %files plugin-gmx %{_libdir}/%{name}/plugins/libgmx.so %changelog * Sun Jan 22 2017 Erik Schilling - 0.18.0-1 - Added subpackage for gmx plugin - New upstream release 0.18.0 * Sun Jul 24 2016 Erik Schilling - 0.17.0-1 - Added subpackage for defold plugin * Tue Apr 19 2016 Erik Schilling - 0.16.0-1 - New upstream release 0.16.0 * Sun Mar 06 2016 Erik Schilling - 0.15.2-1 - New bugfix release 0.15.2 * Fri Feb 05 2016 Fedora Release Engineering - 0.15.0-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild * Mon Feb 01 2016 Rex Dieter - 0.15.0-2 - use %%qmake_qt5 to ensure proper build flags * Sat Jan 09 2016 Erik Schilling - 0.15.0-1 - New upstream release 0.15.0 * Fri Nov 27 2015 Erik Schilling - 0.14.2-1 - New upstream release 0.14.2 * Mon Sep 21 2015 Erik Schilling - 0.14.0-1 - New upstream release * Tue Sep 08 2015 Erik Schilling - 0.13.1-1 - New upstream release * Sat Aug 15 2015 Erik Schilling - 0.13.0-1 - New upstream release * Fri Jun 19 2015 Fedora Release Engineering - 0.12.3-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild * Tue Jun 2 2015 Erik Schilling - 0.12.3-1 - New upstream release * Fri May 22 2015 Erik Schilling - 0.12.2-1 - New upstream release * Wed May 20 2015 Erik Schilling - 0.12.1-1 - New upstream release * Fri May 15 2015 Erik Schilling - 0.12.0-1 - New upstream release * Sat May 02 2015 Kalev Lember - 0.11.0-2 - Rebuilt for GCC 5 C++11 ABI change * Sun Jan 11 2015 Erik Schilling - 0.11.0-1 - New upstream release * Mon Oct 27 2014 Erik Schilling - 0.10.2-1 - New bugfix release * Mon Sep 22 2014 Erik Schilling - 0.10.1-1 - New bugfix release * Sun Sep 14 2014 Erik Schilling - 0.10.0-1 - New upstream release * Mon Aug 18 2014 Fedora Release Engineering - 0.9.1-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild * Sun Jun 08 2014 Fedora Release Engineering - 0.9.1-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild * Sat Mar 15 2014 Erik Schilling - 0.9.1-2 - Fixed detection of plugins on 64bit - Splitted plugins into subpackages * Sat Jul 27 2013 Erik Schilling 0.9.1-1 - New upstream release 0.9.1 * Sat Jan 12 2013 Erik Schilling 0.9.0-1 - New upstream release 0.9.0 - Dropped now obsolete patches and files * Mon Sep 3 2012 Erik Schilling 0.8.1-3 - Fixed preserving of timestamps in install command. - Fixed typo in permission setting. - Talked with upstream about license mismatch in headers. - Those headers were outdated. * Mon Sep 3 2012 Erik Schilling 0.8.1-2 - Added note about which parts are licensed with which license. - Made sure that the copy of zlib inside of the source is removed. - Fixed handling of locales (using %%find_lang). - Avoided plain asterisks in %%files. - Made description clear about containing the tmxviewer. * Sun Sep 2 2012 Erik Schilling 0.8.1-1 - First version for official fedora repos. tiled-1.0.3/dist/distribute.qbs000066400000000000000000000223621315121121300164370ustar00rootroot00000000000000/* Installs all files necessary to run Tiled and other files that should be shipped when Tiled is distributed. */ import qbs import qbs.File import qbs.FileInfo Product { name: "distribute" type: "installable" builtByDefault: false Depends { name: "cpp" } Depends { name: "Qt.core" } Group { name: "Examples" prefix: "../examples/" files: ["**"] qbs.install: true qbs.installDir: "examples" qbs.installSourceBase: prefix } Group { name: "Python Scripts" prefix: "../src/plugins/python/scripts/" files: ["**"] qbs.install: true qbs.installDir: "examples/python" qbs.installSourceBase: prefix } Group { name: "Qt DLLs" prefix: { if (qbs.targetOS.contains("windows")) { return Qt.core.binPath + "/" } else { return Qt.core.libPath + "/lib" } } property string postfix: { var suffix = ""; if (qbs.targetOS.contains("windows") && qbs.debugInformation) suffix += "d"; return suffix + cpp.dynamicLibrarySuffix; } files: { function addQtVersions(libs) { var result = []; for (i = 0; i < libs.length; ++i) { var major = libs[i] + "." + Qt.core.versionMajor; var minor = major + "." + Qt.core.versionMinor; var patch = minor + "." + Qt.core.versionPatch; result.push(libs[i], major, minor, patch); } return result; } var list = []; if (!Qt.core.frameworkBuild) { list.push( "Qt5Core" + postfix, "Qt5Gui" + postfix, "Qt5Network" + postfix, "Qt5Svg" + postfix, "Qt5Widgets" + postfix ); } if (Qt.core.versionMinor < 4) { list.push("Qt5OpenGL" + postfix); } if (qbs.targetOS.contains("windows")) { if (Qt.core.versionMinor <= 4) { list.push("icuin53.dll", "icuuc53.dll", "icudt53.dll"); } else if (Qt.core.versionMinor < 7) { list.push("icuin54.dll", "icuuc54.dll", "icudt54.dll"); } } else if (qbs.targetOS.contains("linux")) { list = addQtVersions(list); list = list.concat(addQtVersions([ "Qt5DBus.so", "Qt5XcbQpa.so", ])) if (File.exists(prefix + "icudata.so.56")) { list.push("icudata.so.56", "icudata.so.56.1"); list.push("icui18n.so.56", "icui18n.so.56.1"); list.push("icuuc.so.56", "icuuc.so.56.1"); } } return list; } qbs.install: true qbs.installDir: qbs.targetOS.contains("windows") ? "" : "lib" } property var pluginFiles: { if (qbs.targetOS.contains("windows")) { if (qbs.debugInformation) return ["*d.dll"]; else return ["*.dll"]; } else if (qbs.targetOS.contains("linux")) { return ["*.so"]; } return ["*"]; } property var pluginExcludeFiles: { var files = ["*.pdb"]; if (!(qbs.targetOS.contains("windows") && qbs.debugInformation)) { // Exclude debug DLLs. // // This also excludes the qdirect2d.dll platform plugin, but I'm // not sure when it would be preferable over the qwindows.dll. In // testing it, it seems to have severe issues with HiDpi screens // (as of Qt 5.8.0). files.push("*d.dll"); } return files; } Group { name: "Qt Platform Plugins" prefix: FileInfo.joinPaths(Qt.core.pluginPath, "/platforms/") files: pluginFiles excludeFiles: pluginExcludeFiles qbs.install: true qbs.installDir: "plugins/platforms" } Group { name: "Qt Platform Input Context Plugins" condition: qbs.targetOS.contains("linux") prefix: FileInfo.joinPaths(Qt.core.pluginPath, "/platforminputcontexts/") files: pluginFiles qbs.install: true qbs.installDir: "plugins/platforminputcontexts" } Group { name: "Qt Platform Theme Plugins" condition: qbs.targetOS.contains("linux") prefix: FileInfo.joinPaths(Qt.core.pluginPath, "/platformthemes/") files: pluginFiles qbs.install: true qbs.installDir: "plugins/platformthemes" } Group { name: "Qt Image Format Plugins" prefix: FileInfo.joinPaths(Qt.core.pluginPath, "/imageformats/") files: pluginFiles excludeFiles: pluginExcludeFiles qbs.install: true qbs.installDir: "plugins/imageformats" } Group { name: "Qt XCB GL Integration Plugins" condition: qbs.targetOS.contains("linux") prefix: FileInfo.joinPaths(Qt.core.pluginPath, "/xcbglintegrations/") files: pluginFiles qbs.install: true qbs.installDir: "plugins/xcbglintegrations" } Group { name: "Qt Icon Engine Plugins" condition: qbs.targetOS.contains("linux") prefix: FileInfo.joinPaths(Qt.core.pluginPath, "/iconengines/") files: pluginFiles qbs.install: true qbs.installDir: "plugins/iconengines" } Group { name: "Qt Translations" prefix: { if (qbs.targetOS.contains("windows")) { return FileInfo.joinPaths(Qt.core.binPath, "../translations/") } else if (qbs.targetOS.contains("linux")) { return FileInfo.joinPaths(Qt.core.libPath, "../translations/") } } files: { // Since Qt 5.5, the translations are split up by module and failing // to include all the .qm files results in the loading of the Qt // translator to fail (regardless of whether these modules are // actually used). var modules = ["", "base", "multimedia", "quick1", "script", "xmlpatterns"]; // TODO: Look into getting this list from the Tiled // 'translations.qbs' product. var languages = ["ar_DZ", "bg", "cs", "de", "en", "es", "fr", "he", "it", "ja", "lv", "nb", "nl", "pl", "pt", "pt_PT", "ru", "tr", "zh", "zh_TW"]; var list = []; var p = prefix; for (i = 0; i < languages.length; ++i) { for (j = 0; j < modules.length; ++j) { var file = "qt" + modules[j] + "_" + languages[i] + ".qm"; if (File.exists(p + file)) list.push(file); } } return list; } qbs.install: true qbs.installDir: "translations" } Group { name: "Runtime DLLs" condition: qbs.targetOS.contains("windows") prefix: { if (qbs.toolchain.contains("mingw")) return FileInfo.joinPaths(cpp.toolchainInstallPath) + "/" else if (qbs.architecture === "x86_64") return "C:/windows/system32/" else return "C:/windows/SysWOW64/" } files: { if (qbs.toolchain.contains("mingw")) { return [ "libgcc_s_dw2-1.dll", "libstdc++-6.dll", "libwinpthread-1.dll", ] } else { return [ "MSVCP120.DLL", "MSVCR120.DLL", ] } } qbs.install: true qbs.installDir: "" } Group { name: "Misc Files" prefix: "../" files: { var list = [ "COPYING", "AUTHORS", "README.md", "NEWS.md", "LICENSE.APACHE", "LICENSE.BSD", "LICENSE.GPL", ]; if (qbs.targetOS.contains("windows")) list.push("dist/win/qt.conf"); else if (qbs.targetOS.contains("linux")) list.push("dist/linux/qt.conf"); return list; } qbs.install: true qbs.installDir: "" } } tiled-1.0.3/dist/dsa_pub.pem000066400000000000000000000042521315121121300156700ustar00rootroot00000000000000-----BEGIN PUBLIC KEY----- MIIGOjCCBC0GByqGSM44BAEwggQgAoICAQDhi01QvbUkZPifoPNJCQzmhUEHE9LF sdSAhmQku9/4P+3uqu1a2e6Dz8HN26NdRxdJ/h/ZbWroAUShSEpagxyXbR9uHMHc xBaWXjXO7sxohGMUeylGA6KGq6UGpzs4u4YbmsI3x9gzQCLPvpit74B86K70pIkt thDGjA/yV92k3XRCXJ6Tf3oVTAYqt8+VN6gd3pEIufzgyYuwtc0GGD4u/8A7iasU eSWt5vfFndpQtVDKMKPbGNO5PRfozTUryANOX2je6RT3hlSnlUP6CxwxEbwFcfQu SU84SdO5upBHUzTQ00xWkG2WVXUtNGe7vlgV6d5GHKMQw0xYcTMZeMpvSgkJwF8y 4jTyHtlFGxkyKWtAsC1AOzTU3AkdYutHjIQ0wK3iKjUnFk+udLRleIzOusCshwfD +hVAlWqbvViPcZaQURC1DnSq5UZQIICWugE0Kbm1vYYAyHK31jJdRWaB7PTZnZC1 BlbXacV/dEuY/WJTmpoWr+iUfgIiNQ6yRrF1w+26eR0aFwEUYTHU7fFu8fn8xsvP f3/FSx4NVQf5X+VZ5NhFlI9btNgkqCABoA3fgHIhpNa7ruBlr58QbYnAxR66tHL7 OXCp95iTGXtr3fb3k1uOVIbdnNRDykVfeYsHixonXA1d3AFvhsXLB/L+Dv5pRfgg eTMn1oURGx/xbwIVAPG/1CsN6Lwi7+x3c0vvIx1qLp7DAoICAHOTSmLkh/ci+H5g dnk6Skd8FrLaR89Rw3Z0DuJjnun49T9x7za4FZ5VqL2HBG9q/bAUAOSNCuXBdd+r urYJuH1NdAZsDYOW6gqWSAdarRu7V8nS4ggSbdG6tpK1KDa0gF6j4AXHMY/bq6e6 DYD3aeckUtkWgaZEd+UX/We8k3A7Q/B6wyWWQ+OLb4FZ5G6AbKnEqivAOJ/ux7AJ NBS/4XHabxgpxw2oQkiMZDj+C83I3Mp37FCF26BphDcUE8xn1ueiYBW3nKJPPGbc 7VSufxEsD2yWQns6eSOFryqVZG3YnxFwaYQoZNrsuKvWvWiZ6VGsTLDkDlnh60zp x+yuXCfoj/fNugcCgkWN3nxfC9iUyB4oy2rox3T+FsVwotBMBEwFfyAwPTx9DkrZ g3j8lny14DKcofrzEbT+M8MBblgbeFvt6GqaypveBbO/7KprUq+itgDXoJnHm0NU 2+fo/ZaC1ZiwjsfWqzMrySX6k2YHTC331xwS9j0pKDPVkIWIRhw6dRNOKzKFZkja wvvOKDbOLagliHrwftzl4WDLKva7N0DY5Drhv2NBBFleCl4Ol+ANghsgA5aiYuoc qe5NYU7HSGTVNnHEV8IBrwGGxmqm8TKC2kO7Tnnmse+yrd90tskoewiB0NfqcYvt 6PV+PKuaIw3WitTpdMSk00HQHnrKA4ICBQACggIAVprDZMCNzSQuTwCqm3sUY16M YnjcLFG0bDsQ9ALMA4WqxmAZfMLJGTODYDoke9XkbfXaAMMwb9oXTqld5bjpdLMT pOGepVKolGqHg7dqkMcJMkm5I/xqT/tFgahvwAL0SXr8+jK0pMNYJtUmgDbENqYC oz73l4ApO7b4TrN05G9BOvu/dzd5U8YZZcH/cKRqT6O4Lcr8aN9QKGfJMx0JmM8A y4OwUCt2cjI0zuhZNRfiPgnOivsOifUGofJOsCaAxt2DPHYkemB5VKGzFoXLneVd MWF+RxeZSGbeCsIVbB4z9Qm1rPHXzzlMsbGvD5caoB3Gv3r0b0wAxk6sO8oErzHn uDLDT9O4KAyeZh7e3IFta0rGI0q3hqV3cB1/Qh0HabpJ70GdldTFwFOTGegYci4l 7bU3z8BIlU4F6jZ7n8KYiTMPfbylfjaso+5ZrhXSgvthVjFkhNzvoiq3XZbhY+A0 opPJScTLMLV3GFQD7fO5GecKNC0VymDGS0zOqPzp/2ieNCfTbiEU4TNL4pYsBh5a MyAXsoMxBWCX4ZXxsj+8Oz7pJTUrecI97UJkKEzkreP/48EPkjxLDvMhUzuGz8gS eMcu2g+/qRW5CWv56rqIGwRK6UTwA1vQxxae7r/HW3H4kK9mqRsb7E6go4CqN+gR Lok191BJb2+wjBV1CJs= -----END PUBLIC KEY----- tiled-1.0.3/dist/linux/000077500000000000000000000000001315121121300147045ustar00rootroot00000000000000tiled-1.0.3/dist/linux/push-to-itch.sh000077500000000000000000000005751315121121300175760ustar00rootroot00000000000000#!/bin/bash set -ev openssl aes-256-cbc -K $encrypted_498dac83364f_key -iv $encrypted_498dac83364f_iv -in dist/butler_creds.enc -out butler_creds -d mkdir itch mv Tiled-$TILED_VERSION-x86_64.AppImage itch/ wget https://dl.itch.ovh/butler/linux-amd64/head/butler chmod +x ./butler ./butler -i butler_creds push --userversion=$TILED_VERSION itch thorbjorn/tiled:linux-64bit-snapshot tiled-1.0.3/dist/linux/qt.conf000066400000000000000000000001061315121121300161740ustar00rootroot00000000000000[Paths] Libraries = lib Plugins = plugins Translations = translations tiled-1.0.3/dist/make-dist-mac.rb000077500000000000000000000057611315121121300165220ustar00rootroot00000000000000#!/usr/bin/ruby # This script generates a mac release from an already compiled Tiled.app in # the bin folder. You should compile the release before running this: # tiled$ qmake -r -spec macx-g++ CONFIG+=release CONFIG+=x86_64 # tiled$ make # tiled$ ./dist/make-dist-mac.rb # Dependencies require 'tmpdir' # Get various directories baseDir = File.join File.dirname(__FILE__), '..' binDir = File.join baseDir, 'bin' binAppDir = File.join binDir, 'Tiled.app' raise "No application at #{binAppDir}" unless File.directory? binAppDir # Get the version from the info plist if ARGV[0] version = ARGV[0] else plistData = File.open(File.join(binAppDir, "Contents/Info.plist")).read version = plistData.match(/CFBundleVersion\<\/key>\s*\([\d\.]+)\<\/string\>/m)[1] end puts "Version is #{version}" # Create a temporary staging directory # This directory will serve as the content for the dmg file Dir.mktmpdir do |tempDir| # Copy things to temp directory puts "Copying files" ['LICENSE.GPL', 'LICENSE.BSD', 'AUTHORS', 'COPYING', 'NEWS.md', 'README.md'].each do |file| FileUtils.cp File.join(baseDir, file), tempDir end FileUtils.cp_r File.join(baseDir, 'examples'), tempDir FileUtils.cp_r binAppDir, tempDir FileUtils.cp File.join(binDir,'tmxrasterizer'), File.join(tempDir, 'Tiled.app/Contents/MacOS') FileUtils.ln_s '/Applications', File.join(tempDir, 'Applications') #Symlink to Applications for easy install # Use macdeployqt to copy Qt frameworks to the app puts "Running macdeployqt" `#{ENV['HOME']}/Qt/5.7/clang_64/bin/macdeployqt "#{tempDir}/Tiled.app"` raise "macdeployqt error #{$?}" unless $? == 0 # Modify plugins to use Qt frameworks contained within the app bundle (is there some way to get macdeployqt to do this?) Dir["#{File.join tempDir, 'Tiled.app'}/**/*.dylib","#{File.join tempDir, 'Tiled.app'}/Contents/MacOS/tmxrasterizer"].each do |library| ["QtCore", "QtGui"].each do |qtlib| #find any qt dependencies within this library qtdependency = `otool -L "#{library}" | grep #{qtlib}`.split(' ')[0] next unless qtdependency #skip depedencies that are already using relative paths #macdeployqt seems to fix some of the plugins next if qtdependency.include? "@executable_path" #if we get here, this library has a dependency on a qtlib with a hard path on the build systems disk puts "Fixing library #{library} dependency on #{qtlib}" `install_name_tool -change "#{qtdependency}" "@executable_path/../Frameworks/#{qtlib}.framework/Versions/5/#{qtlib}" "#{library}"` raise "install_name_tool error #{$?}" unless $? == 0 end end # Create dmg from the temp directory dmgPath = File.join(baseDir, 'Tiled-' + version + '.dmg') puts "Creating dmg at #{dmgPath}" `hdiutil create "#{dmgPath}" -srcfolder "#{tempDir}" -volname "Tiled #{version}"` raise "hdiutil error #{$?}" unless $? == 0 end puts "Done" tiled-1.0.3/dist/make-dist.sh000077500000000000000000000003201315121121300157550ustar00rootroot00000000000000#!/bin/bash if [ "$#" -eq "0" ]; then echo "Usage: make-dist.sh " exit 1 fi name="tiled-$1" git archive -v --prefix="$name/" HEAD | gzip > "$name.tar.gz" echo "Release ready as $name.tar.gz" tiled-1.0.3/dist/win/000077500000000000000000000000001315121121300143425ustar00rootroot00000000000000tiled-1.0.3/dist/win/README.txt000066400000000000000000000043501315121121300160420ustar00rootroot00000000000000 How to create a Windows installer for Tiled =============================================================================== Prerequisites: * Qt is installed * MinGW is installed * NSIS is installed * Tiled executable in release mode has already been built Tiled's windows installer is created using NSIS. You thus need to install NSIS first if you want to build your custom windows installer for it. You can download the latest version of the installer from the NSIS project website located at http://nsis.sourceforge.net. Another requirement is that the project be already been built. The installer script is called "tiled.nsi" and is located in the dist/win directory. In order for the script to correctly produce binaries we do however need to modify the shell environment from which the script is run first. This is due to the fact that a successful compilation depends on some variables like the actual location of the Qt or MinGW installation path being correctly set. These values can not be automatically inferred by the installer script. Three mandatory variables "QTDIR", "MINGW" and "VERSION" need to be set to the correct paths of their respective packages. If VERSION is not set it will try to read the content of a file "version.txt" located in the root directory of tiled into that variable. The commands to set those may look like the following: set QTDIR="C:\Qt\4.8.6" set MINGW="C:\MinGW" set VERSION="0.12.0" Optionally you can also set the program architecture which is then used to deduce the resulting installer filename. It can either be 32 or 64 and defaults to 32: set ARCH="32" After setting the above variables to the correct values you can compile the NSIS installer script from the command line by executing the provided batch script "build_installer.bat". Make sure the nsis compiler is in PATH so it can be found by the command line interpreter. The resulting installer will be placed in the same directory where the nsis script was located and have a name similar to "setup-tiled--.exe", where is replaced with the value of the "VERSION" variable explained above and will - depending on the actual value of the "ARCH" variable - reflect the architecture (win32 or win64) for which the installer is built. tiled-1.0.3/dist/win/banner.bmp000066400000000000000000002477121315121121300163240ustar00rootroot00000000000000BMOzl:PO  BGRsPE/]ߗ7$nKR7J<'Ãэ. qMlIlIsMr5$khFĄ>pLmJmJmJmJlJnK1vok4#nKlImJmJmJmJmJnKnKfE"ؐsySH0nKlImJmJmJmJmJmJmJlInKlIJ1>E.[bEP7oLlIlJmJmJmJmJmJmJmJmJmJlInKfFb7'eZ[CZAoOnMmKmJmJmJnJmJmJmJmJmJmIlJmKmOrWSEUD<SM8eJnRnQmPmNnLmKmJmJlInJmJlImJmJmLoQpWq_rgztj0/wsr=4$oNmOnPnRnRnQnPnNmLmKmJmJmJmJlJmMoRpXqasitnvsutyy2"sOmJnLnNnPnPmQmRoQmOmNnMmKlJnMnOnSp[qcskupusutwwM((ߜ\ArNmJlJmKnLnNnOnPmRnSnPoQmNoNnQoUp]resluqutuuxx2''秼h:*sQK4 V:oKmJmJmKmLmOnPoQnSnSoToUpYq`rgtntrutww[[vss鬖ps=-zWuSuQpLy>*) X_WU;+*뤛飛뤛륛꣚頖鞒雍蘋斅擀}yvx|芀鉂臃烁肁rBA.!!履짞咽﨟吏xё꣛颚꣛飙韕靑蚎痊疆撄撀}{}鋁錄ꊆ釄{zA10"咽륜lg6%#[?<{桗ꤚ颙蟕蜐蚍昉旆蔃蓂}~茀芃銄vrNMMF1.褐yTPmMH뤜꣛뤜栘|v [?;頖盐蚍瘉症蔃撁}{y{}}HCRKKbC@T;8f`즜뤛ꤛꢛ룜쥜ђbD@ um虋瘇畄擀zvst2дꢢYJI`[2"!xr履륝뤜ꤚꢚgb-]>9瘈똆~wswaC:-ۮtttiQM{u=+*Γ륜륝룚렗vmL2,>(#k[|UF`bLMKKfaѕ/! 觠蘒꟔雎ꚈgA8 X\I2..yꨠ"列霍瘉֋y~js_/hМ1#"Ж쟒€t 蔀yuploA442%ЗhffB-+vOKZ;7ꛌ藆~xsnjہdpW*~iZSR]>;#wr획ꖆ摀ysnkjoqdOG485쟟bRQ_[㣜 ݛ횏ꕉ瑂|ustw{~|PO`HGooooVS{uup?-,얌ꑅ莀}~爀腀烀x=<>>>!Ӗ픍됈ꍆ댆鉅膃ꆄrpD55'&&so颛픎푌쎊ꊇ鈆ZY[[[}x쎋6""}}0ЇfeeccnffF'%օ9tiled-1.0.3/dist/win/build-daily.bat000066400000000000000000000031131315121121300172270ustar00rootroot00000000000000@rem TILED DAILY BUILD SCRIPT @echo off rem The following assumes US date format! set VERSION=%DATE:~10,4%-%DATE:~4,2%-%DATE:~7,2% set TILED_SOURCE_DIR=E:\Projects\tiled set TILED_BUILD_DIR=E:\Builds\tiled-daily-qt5 set QTDIR=E:\Qt\5.3\msvc2013_opengl set ARCH=32 set MAKE=E:\Qt\Tools\QtCreator\bin\jom.exe set GIT="C:\Program Files (x86)\Git\cmd\git.exe" set SCP="C:\Program Files (x86)\Git\bin\scp.exe" set DESTINATION=bjorn@files.mapeditor.org:public_html/files.mapeditor.org/public/daily/ echo Waiting a bit for the network to come up... ping -n 3 127.0.0.1 > nul pushd %TILED_SOURCE_DIR% %GIT% fetch %GIT% diff --quiet origin/master if %ERRORLEVEL% == 0 ( echo No change, nothing to do. popd goto done ) else if %ERRORLEVEL% == 1 ( %GIT% reset --hard origin/master ) popd FOR /F "tokens=*" %%i in ('%GIT% describe') do SET COMMITNOW=%%i echo Building Tiled daily %VERSION%... (from %COMMITNOW%) call %QTDIR%\bin\qtenv2.bat call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86 rem This allows the executable to run on Windows XP set LINK=/SUBSYSTEM:WINDOWS,5.01 mkdir %TILED_BUILD_DIR% pushd %TILED_BUILD_DIR% qmake.exe -r %TILED_SOURCE_DIR%\tiled.pro "CONFIG+=release" "QMAKE_CXXFLAGS+=-DTILED_VERSION=%COMMITNOW%" %MAKE% popd echo Building Installer... pushd %TILED_SOURCE_DIR%\dist\win makensis.exe tiled-vs2013.nsi echo Uploading installer... %SCP% -B tiled-%VERSION%-win32-setup.exe %DESTINATION% popd :done echo Shutting down in 30 seconds... ping -n 31 127.0.0.1 > nul shutdown -s tiled-1.0.3/dist/win/butler_creds.enc000066400000000000000000000000601315121121300175020ustar00rootroot00000000000000k9} o㫓LC˲YlYtwf"!L7tiled-1.0.3/dist/win/dialog.bmp000066400000000000000000016060721315121121300163150ustar00rootroot00000000000000BM: zl8   BGRsffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333+++FFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333VVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFFfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333+++FFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333VVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFFfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333+++FFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333VVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFFfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333+++FFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333VVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFFfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333+++FFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333VVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFFfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333+++FFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333VVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFFfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333+++FFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333VVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeeeeeeefffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFFffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeddddddeddddddddeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeddddddeddedddccdccdccdcceddedddddeeeeeeeeeeeeffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeedddddddccdcccbbbbbcaacaacaadbbcbbdccdccddddddeeeeeeeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeedddedddccbbbcaac``b__b__a_^b__b__c``b``dbbcbbdccddddddeeeeeeeeefffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeedddddddcccbbcaac``a^^a]]`\\`\[`\[`\[`\\a]]b^^b__b``caacbbdccedddddeeeeeeeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeedddedddccdbbb``a^^a]]`\[`ZZ^YX^XX_YX^YX_XX_ZY_[Za\\a]]b__b``dbbcbbddddddeeeeee222333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeddddddcbbcaac``b^^a\\_ZY^XX]WV\UT\TS\SS\TS\UT]VU^WV_XX`ZZa\\b^^b__caacbbdccedddddeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeedddeddcbbcaab__a]]_[Z_XX]WV\TS[RPZPOYONYNMYONZPOZQO[SQ[TS]WV_XX_[Z`\\a^^300200cbbcccddddddeeeeeeeeeffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeedddeddcbbcaab__`\\`ZZ]WW\UT[RPZPOXNLWKIVJIVJHVJHVJIWLJXMLZPO[RQ\UT^WV_YX_[Za]]a^^b``bbbdccdddddddddeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffeeeeeeddddcccbbb``a^^`\\_ZY^WV\TSZQPXNLVKIUIGTFDSECVGERDCTFCUGEUIGVKIXNL2)(3+)]UT]WW_ZYa\\b^^b__caacbbcccddddddeeeeeeeeefffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333+++FFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeedddccccbbb``a^^_\\_ZY]WV[SRYPOWMKUJHTGDSDBQA?zxqdbQA>QA?SDBSEDUIGWKIXNMZQP\TR]WV_XX_[Z`\\a^^b``caacbbdccdddeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffeeeeeeeeeedddccdbbc``a^^a\\^YX]WV[TRYONWLJVIGSEBQA?P@>կ髠ѮC1/3"QA>SDBTFDVJHXMKYON[RP\UT^XW_ZY`[[a]]b__caacbbdccedddddeeeeeefffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeedddccbbbc```^^`\[_YX]VU[RRYONWKITGESDBQA>R@>٭߁rjWzi橞trR@>P?;QA?RDATGEVJIXNLZPO[TR]VU^XW_[Z`\\a^^c``cbbdccedddddeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffeeeeeedddddddccbbbc``b^^`\[_YX]VU[SQYNMVLITHERCAP?=TB?ޯ|lfReRhUiV{ݭk[XO>:P@=SCASFCUIGWLJYNMZRP\UT]WW_ZY`\\a^^b``dbbdccdddeeeeeeffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffVVVFFF777ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeedddddddccdbbc``b^^`\[_XX]UT[RPYNMVJHTHDRCAP?:QA>SDBTGEVJHXMLZQP\TS^VV_ZY`\\a^^b``cbbedddddeeeeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeee222322dcccaab__a]]_[Z^XX\UTZRPYOMWJITFDRB@O>;ZIFૢp_kXiWhVgTfSfSeRdPdOxf䨞{ljQ?;`OL櫡q_lYkXiWhWfUfSfRfQdPcNbNdO{٫fVSP?=RB@SECVJHXNLZQP\UT^YX`\[b^^c``cbbedddddeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeddddddcbbcaab__a]]1--2-,[TSZQPXMKVJHSFDQA?O>:PA=槝q_m[lYjXiXhVfUfSfRePdPbNbMaM`MjV圐ȨXGFSCATFDVJHYNM[RQ]WV_ZY`\\b__dbbdccdddeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeddddddcbbcaab__`\\`ZZ]WW\TSZQPXMKUIHTFCQB?O=:m]Z椙q^n\mYkYkXjVgUfTfSfReOdObNbMbM`L_L`Kyh⧝ylkTECUIGXMK[RP]UT^YXa\\b__caadcceddeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeddeddcbbcaab__`\\_ZY^WW\TTZPOXMKUHG3$"%3"ufdé䞒q^o]m[lZlXkXiVgUfUfSfReOdObObMaLaL_K_K^IaM~ثg[YWLKZPO]UT^XW`\[a^^daadcceddeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeedddcccbbb``a^^a\\_ZY]WV\SSYPOWLJUIGSDBQ@>O>:~pmǨ㙎q_p^n\m[lZlXjWiVgUfUfTfReOdObNbMaLaL_K_K^I^I]IkX蟓ƪ_VT\UT_XXa\\a^^caadcceddeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeddddcccbbb``a^^_\\^YX]WV[TRYPOWLJ3'$3%#Q@>O=:wuͭ╇n\m[o]n\m[kYjXjWiVgVfTfTfReOdObObMaLaL_K_J^I^I^I]I_J|k⫡}ww_ZY`\\b__caadccdddeeeeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeedddcccdbbc``a^^a\\^YX]WV[TRYONWKITGESDBP@=O<9~ֱscraq^o]n\lZkYjXjWiVgVfUfTfReOdObNbMbM`L_L_J_J_J^J^I^I^IbO摂կmjjc``cbbedddddeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeedddccdbbc``b^^`[[^YX\VU[RR3('3'%UGERCAQ@=Q?<ٳߋ}tdrbr`p^o]m[iWhVjXjWiVgUfUfSfRePcObNbMaM`M`L`J`K_K_J_K_I_I_J^Hs̏ebbcbbeddeeeeeeffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeedddedddccbbbc``b^^`\[_XX]VU[SRYOMVLIUGERCAP?;]KG빰ᔈvfsbr`p^p]o]o[mZkYjXjWiVhUfUfSfSfQePdPdPdOcObNbNbNaMaLaLjW駜yvu`]]`^^a``bbbdddeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeedddeddcbbcaab__a]]2.-2,,\UUZRPXNLVIHSEDRB@P>;aQN沩}o~n㡕콵귯ߏtbq^p^p]n[mZkYkXjWiVhWgTfTbOaMfQeQeQeOcOcOcOcOcObMyg㯥jgf]\\\[[ZZZZZZ^^^aaadddeeefffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeddeddcbbcaab__a]]`ZZ^XV[TSYQPXMKUJHTECQA?O>:gWT毦|mxhxfvf|l塖캳鳪ފ{q_p]m[lZkYlXkXiXhVgUgTfTfRfReRfRfPfQdPdPdPdP}ְa^^][[XXXTSSPPPPPPVVV\\\bbbeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeeeeeeeffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeedddeddcbbcaa2//2..`ZZ^XW\TSZQPWMKUIGSEBQA?O=:n^\櫡|kyiygwgvftdtc|l椘뺲鯥ކvm\lZlZlXjXiWhVhVhUgTgSgSfS_L_KfRfQfPgT蜎Ȱ_\\\ZZVVVOOOHHHDDDFFFNNNXXX```dddfffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333VVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeeeeeeeddddddeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeedddccccbbcaab__`\\_ZY\VV\SRYPOXMKUHGSEBQA>O=;ufdë榜|m{jyhwgwfvetdtctbr`|l楙칲諡݀qlZkXkXjWiWiVhVhUhUgTgSfRfSfRfRp]誟wtt^[[[YYTTTLLLDDDooo]]]NNNYYYaaadddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeedddeddedddddeddedddddddddddddddddeeeeeeeeefff333333ffffffffffffffffffffffffffffffeeeeeeeeeedddcc211200a^^`\\_ZY]VV\SSYPOWLJVIGTDAQA>O>:~plɮ㡖|m|lzixhwfwfuetdtdsar`q^p]~n秜캱訜|klYjXiWhWiViUhUhUhShThTgT~lڪiee]ZZYXXRRRJJJGGGӖaaaccceeeeee222222dddddddddeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFFfffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeedddedddccdcccbbcbbdbbdbbcbbcbbdccdccdddddddddeeeeeeeeeeeefffffffffffffffffffffffffffeeeeeeeeeedddcccbbb``a^^a\\^YX]WV[SSZPOWLJUHFSCAP?=P=;wuͰ㞓}n|m{kziyhwfvfueuetdsbr`q^p^o]n\݀p骠칱襚zhkXjXjVjWiWiViUiUiU摂Ӱ`]\\ZZWVVPPPGGGSRR𪪪fffddddddbbb```^^^^^^^^^___aaadddeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffffffffffffffffffffffffffffffffffeeeeeeeeedddedddcccbbcaab``c``c``c``c``b``b``caacbbcbbdcceddedddddeeeeeeeee333333ffffffffffffeeeeeeeee222211cbbb``a^^`\[_YX\VU[SQYONWKITIERDBP?=O=:}Դ~o}n{l{kzjxhwfvfuetetcsar`q_p^o]n\n[n[߀rꬢ츰衕vfkWjXkXkVjVlZ頔ǰ^[Z[YYUTTMMM"""ONNܙddd111111___[[[VVVSSSQQQRRRUUUZZZ___ccceeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffeeeeeedddedddcccbbcaac``a^^b^^a]]`\\a]\`\\a]]`^^b__c``b``caacbbdcceddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeedddcccdbbc```^^`\[^YX\VU[SQZONWKITGERCAP?=P>;ٵޓp~o|m|l{kzixhwfvfuetetcsbraq`q^p^o]o\m[m[n\u뮤츰瞐uckXkWvd筢tqq]ZZYXXSRRKKKFEEȄbbbbbb```[[[TTTNNNIIIFFFDDDEEEIIIQQQZZZaaadddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffeeeeeedddedddccdbbb``a^^a]]`\[_[Z_ZY^YX^YY^YX_ZY_[Z`\[`\\b^^b__c``caacbbdccdcceddedddddeeeeee222222ddddccbbbc``b^^`\[_XX]VU[RRYOMVKIUGESCAP?;[KG亱ۊ|قt؁r؀qo}n|l{kzjyixhwfvfvetdtdscrar`p`p`q^q]o^o^p^p\o\o\q`覚ų^ZZZXXTSSLLLEEEvvveeebbbbbb___YYYQQQ$$$:::iii`````````___^^^___```bbbcccdddeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffeeeeeeddddddcbbcaab__`\\`ZZ]WW\UT[RQZPOXMLWLJWKJVJIWKJWLKXMKYNMZPO[RP\TR]UT^XV^YX`[Za\\a]]a^^b__c``b``b``c``b__a^^`\\_ZY]WW\UTZQOXNLVIHSFDRC@O>;aPNۋ}كu؁s؁sـqo|m|l{kzjyixhwfwfveuetdtcsbraqaq`q_q_p_q_q^q]p]|k氧ron]ZZYWWRQQIIIJIIuuubbbbbb^^^WWWNNNFFFuuu齽oooZZZYYYVVVUUUTTTSSSTTTVVVXXX\\\___bbbdddeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffffffffffffffffeeeeeeeeeedddcccaab__`\\`ZZ^XW\TSZQPYNMWKIUIGTGESFETFDTFDTFDTGEUJHVKIWMKYNMZQO[TR\UT2,+2,+_ZY`\[`\\a]]a]]b^^a]]`\\`\[^YX^WV\TSZQP3(&3'%TECQA?O>:gXU뿹៓څv؁rـpo|m|l{kzjyixhxfwfvfueudtctbsbrarar`r`q`q`q_q_{޵gdc^[[YWWQPPHHHYXXޢgggbbb```\\\TTTKKKKKK򣣣ZZZiiihhhwwwdddTTTPPPLLLJJJHHHGGGFFFGGGHHHKKKOOOTTTZZZ___ccceeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffeeeeeeddddccdbbb__a]]^ZZ]XW\TSZPOXMKVIHTFDSDBeWUfXVRA?P@=QA>RB@SDATECTGEVIHWLJYOMYPO[RP\TS]VU]XV_XX_ZY`ZZ`ZZ_ZY^YX^YW]VU[TRYPOXMKUIGSEBQA>O=:p`^沩هz܌媠»꿷⢖ڄuo|m|l{kzjzjyhwgwfwfufveudtctctbtcsasaq`q`r`皍гb_^`^^\[[UTTKJJqppЏbbbbbb___YYYQQQHHH[[[ܙeeeaaa^^^YYYSSSMMMHHHDDDBBBGGGLLLOOOLLLGGG@@@@@@CCCGGGNNNVVV]]]bbbeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffeeeeeeedddcccbbc``a]]_[Z]WW\TSZQPXMKUIGTECRB@m_]vhfUC@O<:P>;P@=RB@4%#3%#UIGVKIXMKYONZQO[TR[TS]VU]WV^WV\VU]UT\TRZRPYNMWKIVIGRDAP@>O=;vif᫡وz؆x؅w؄uڈz⢘뿸䧝ۅw|l{k{kzixhygxgxfvfwfvfududucuctbtbsawf誟ñ`]]a^^a__\\\XXXyyybbbbbb^^^VVVNNNFFFsssƂbbb```\\\UUUMMM######VVVzzz˼tttJJJ>>>BBBKKKUUU^^^ccceeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333+++FFF777fffffffffffffffffffffeeeeeedddcbbcaaa^^`[[_XX]UTZRPXNLUJHTFCQA?gXVݰĽĸzx\JGN<9O=;P?RCASECUHFVIHWLJXMLYONZQP[RPZRQ[RQZQPYONXMKVJHTGESDAP@=N<:~pmɱ㩠و{؇y؅w؄vقtقtفsڃtᝑ껴婠܇x{kzizhyhygwfwfwfvfvfveudtdudud߂q峪pll]ZZ][[^]]_^^lkk駧jjjbbb```\\\TTTKKKLLLnnnbbb___YYYQQQHHHDDDmmm…IIIDDDNNNZZZbbbeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffeeeeeeddddccdbbc``a]]_ZY]WV[RQYNMVJHSEDQA?bSQکڨڧܩ⹲Ŀl[YQ>;O;9O>;QA>RB@RDATFDUIGVJIWKJXMLWMLXMLWLKVJIUHFSFCRB@P?=O=:wuε⦜ى|؈z؆x؅wՁsցqكtفsـqpـqޕ趭谦݋|zjyhyhxgwfwfwfwfvfveveue㐂ݶb__ZWWWUUTTTUUU\\\wvvדcccbbb___YYYQQQHHH[[[ٖdddbbb___XXXNNNEEEdddfffNNNZZZaaaeeefffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffVVVFFF666ffffffffffffffffffeeeeeeddddcccaaa^^`\[^XW\UTZPNWLJTGERCA_OMګک٨٧ڥ٤٥߯Ŀ}olYFDO<9O=;P?=QA?RCASEBSEDUGETGETGETFDSEBRCAQA>P>;O<:}Ը࢘ي|؉{؇y؆x؆wمvكtكtفsـqـpo}n~nݐ鳪»鳪zjyiygygwgxgwgwfwf研ϵ^\\YWWRQQKKKHHHJJJRRRaaacccbbb^^^VVVNNNFFFuuu€cccccc```XXXNNNMMMѝyyyhhheeegggoooppp]]]ccceeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666333fffffffffffffffeeeddddddcbbb``a]]`[Z^VV\SRYNMVJISED\LKڬڪ٨֤֣ؤؤؤ٣ڡۦ⺱cRPO<9O;9O>;P?=QA>RB?QC?QC?QA>Q@=P>;O<9P=;ټޝً}؊|؈z؇y؇xمvلuكtكtفs}n|lo~n}n|m|m݊{筣붮ᔇ{lyixhxgxg}l认²~}a]]][[VUULLL('')((EEENNNYYYaaajjjllldddaaa[[[TTTKKKJJJ몪mmmddddddbbbZZZOOO]]]ꘘVVVEEEJJJQQQXXX]]]000111eeeeeedddddddddccccccbbbbbbcccddddddeeeffffffffffff333333fffffffffffffffffffffVVVFFF666fffffffffffffffeeeeeeddddccdbbc``a]]_ZY]WV[RQXNMVJH\NLۯڬڪ٩ڨئؤأأأآءڟڡ௧þмvgdT@=N;8N<9O<9O<:O<:O<9N;8M96R?<޽ޚٌ؋}؉{؈z؇zمxمvلuكtكtفs؁q؀p؀o~o}n|n{l{l{lކw稝컴䛎~nziw嶭qnma^^a__^]]_^^```[[[bbbdddccc```YYYQQQHHH\\\֔dddeeeeeeddd^^^TTTjjj便dddBBBBBBFFFKKKRRRXXX^^^bbbdddtttݧrrrbbbaaa```^^^\\\[[[ZZZZZZ[[[]]]___aaaccceeefffffffffffffffffffffffffffffffffVVVFFF666fffffffff333333eeeeeeddddccbbbb__`\\_ZY\VU[RQYNM\ONܲըզګ٨٧ڧؤؤأآءءؠ؟ٝٝݤ滴¿xx\IFM96L74L74L74K74T?=⿹ݗٍ؋~؋|؉|؈{نyمxمvلuكtكtقs؁r؀q~p~oyjyh}m}m}m|k{l߃t磘ꭣܹfbbb__caa111544___bbbbbb^^^VVVNNNFFFvvv~~~dddeeefffeeebbbZZZdddޟ^^^@@@@@@EEELLLTTT\\\aaa222IIIyyybbb```\\\YYYVVVRRRPPPNNNNNNNNNNNNPPPTTTXXX...000dddeeefffffffffffffffffffffffffffVVVFFF777fffffffffffffffeeeeeeddddccdbbb__`\\_ZY]WV[SQ[QPܴڰۮڬ٪کڨ٧٦ؤؤأآؠ؟؟؝؛ٜڛ۝᯦¾˹jXUN74I30VB?徹۔؍؍،؊}؊|وzنyمxمvلuكtكt؂s؁r؀q~p~p~n~n~n~n}m}l}l|k|kށqb^^b__caacbbdccrppՁbbbaaa\\\TTTKKKJJJ騨jjjdddfffffffffeeebbb[[[򟟟pppؖUUU;;;AAAKKKVVV^^^bbbccc```\\\WWWRRRMMMIIIGGGFFFEEEDDDDDDDDDDDDGGGKKKQQQXXX^^^bbbeeeffffffffffffffffffffffffVVVFFF666fffffffffffffffeeeeee222322dbbc``a]]_[Z]WW^WUز۱ۯڭڭڬڪ٩ڧڥ٥٣٣آءؠ؞؜؜؛ؘؙؚڙޥ張׾wt潶ړ؎؍،،~ً|ى{وzنyمxمvلuكtقt؂s؁sqـpp~on~n~nxhwf}m}mނr貨~{{b^^300311dccedddddddd~~~dddbbb]]]TTTJJJ\\\ӑdddeeeffffffffffffeeebbbQQQVVV]]]uuuҎTTTIIITTT\\\___\\\WWWPPP%%%###FFFOOObbbsss~~~yyyLLL222AAA@@@DDDLLLUUU]]]bbbeeefffffffffffffffffffffVVVFFF666ffffffffffffffffffeeeddddddcbbcaaa^^_\\`[Z߻۴ܲ۰ܯۭڬ۫کڨ٧ڥڤ٢١٠٠؟؝؝؛ؘؙؚؗؗؖۛ维渱ݝ؏؍،ً~ي{ى{وzنyنxمvلuكt؂t؂s؁rفqqpon~no~m~n~n~丱okkb^^c``dbbdccddddddeeeeeeeeehhhiiiffffffeeeaaaZZZPPPxxxzzzdddeeefffffffffffffffeeecccsssDDDMMMSSSUUUTTTlllΕbbbZZZXXXRRRKKKFFFQQQzzzПddd<<<@@@JJJUUU^^^dddfffffffffffffffffffffVVVFFF666ffffffffffffffffffeeeeeeedddccdbb300}zz࿹ݵܳݳ۱۰ۯۭ۬ګکڧڦڥ٤ڢڡٟٞٝ؛؛ؘؘؚؖؖؕݤ辷ড়辸ग़ڐً~ي{ى{؈z؆yنxمvلuكt؂t؂s؁rفqڀppڀooۀo܀n~n~n㚍ڹ"2..b__caacbbedddddeeeeeeeeeeeeffffffffffffeeebbbbbb祥jjjeeeffffffffffffffffffffffffdddqqq@@@DDDGGGIIIIIIGGGFFFzzz|||UUUNNNGGGTTTߖNNNDDDPPP[[[bbbeeeffffffffffffffffffVVVFFF666ffffffffffffffffffeeeeeeeddeddcbbcaaݺݶݶܴݳ۱ۯۭ۬ܫ۫ڨڧۦڤڣ١١ڟؘؙٜٝٝٛؗؗૡ渲ٓؐؐۚ峪ƿƾ尨ܖ؉{؈y؆xنxمvلuكt؂t؂s؁rفrڀpـpڀoڀoۀoۀpp稞ʲ_YX`\[a]]c``caacbbeddeddeeeeeeeeeeeefffffffffffffffpppЏdddeeefffffffffffffffffffffffffffeeehhhIIIDDDDDDJJJ```|||TTTLLLIII~~~྾|||jjjQQQ\\\bbbeeeffffffffffffffffffVVVFFF666ffffffffffffffffffeeeeee222222dcccbbsrrྲྀݵݴܱܲݰۮܬ۫۩ܨۧڥڤڣڢڠٟڝڛٛٛٙ٘ᰦ㵮ؓؒؐؐ؏َڑच躲ߞى|نxمvلuلt؂t؂s؁rفrځpڀppڀoۀo܅v賫VPO\VU_XX`\[a]]b__200211dccdddeddeeeeeeeeefffffffffffffffsssyyydddffffffffffffffffffffffffffffffffffffmmmἼИcccVVVLLLZZZ݊IIIgggeeeeeedddbbb...000uuu```dddfffffffffffffffffffffVVVFFF777fffffffffffffffffffffeeeeeeeeeddddcccbbcaakgg޶ݱݯܯݮ۪۬ܩۧۧۦۤڣۡ۠ڞٜٝښڙ䶭㱨ؕؔؒؑؐ؏؎؍ًٍܘ泩ǿļ䪠ێلuلt؂t؂s؁rفrڀpـpڀoڀoᷰf\[[RP]UT]XW_ZYa\\b^^c``caacbbdccddddddeeeeeeeeefffffffffffffffmmmkkkeeeffffffffffffffffffffffffffffffffffffffffffrrr˞qqqaaa[[[OOOnnnﱱ{{{dddeeeeeeeeeccc```ZZZTTTLLLHHH቉ccceeefffffffffffffffffffffVVVFFF666ffffffffffff333333ffffffeeeeeeeeedddeddcbbbbbb``c__qnmÿ㿷޲ݯܭܬݪ۩ۨۦۥܤۢڡڟ۞ڜڜ弴ᮦڗٕٔٓؒؐ؏؎؍،،~؋|ى{ۏᤛ龶ƾ跭ޗمv؂s؁rفqڀpـpڀpޙήZMKWLJYPN[SQ\UT]XW_ZY`\[b^^b__caacbb111222dddeeeeeeeeeffffffffffffffffffeeeffffffffffffffffffffffffffffffffffffffffffffffffffffff|||ξllleeeddd```VVVuuu{{{dddeeeeeeeeedddbbb]]]WWWPPPIIIYYYdddeeeffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffeeeeeeeeedddddddcccbbdbbb``b__daayvuƾᷰݭݫܪܨݧۥܤۤۢܡ۟ڞ»ૢژٖٕڕِْٓؐ؎؍؍،؊}؊|؈{؇zهyݗ紫Ž꽶⤙ۉ{فqqڀq檞ŬusRC@TFCUIGWLJYONZRP\UT^WV^YX`\[a]]b__caacbbeddeddeeeeeeeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflllnnnkkkgggeeefffffffffddd___jjjՃ\\\bbbddddddccc```ZZZSSSLLLHHHyyyޠjjjeeeffffffffffffffffffffffffffffffVVVFFF666333333ffffffffffffffffffffffffeeeeeeeeedddeddedddcccbbdbbcaac``b^^hdd_][»߰ݪݩܧݦݤۢܢޣ੠ڛۙۘڗڕٕړڒَُّ،؋~؋|؉{؈z؇y؇x؆wمwۊ|⤚ü䮣ܐ維jYWN<9P?;QA?SDBVIGWKIYOMZQP\SR]WV_XX_[Za]]b__caacbbeddedd222222ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffddd___MMMWWW]]]______\\\VVVPPPIIIYYYdddeeefff333333ffffffffffffffffffffffffVVVFFF777ffffffffffffffffffffffffffffffffffffeeeeeeeeeeeedddddddccdcccbbcaab``c``b_^nkk㹲ުݧݥܣިߧ۝ܜۚۙڗۖڔڔْڑڐڏًٌَ}؊|؉{؇y؆x؅w؄v؂t؂tمvޖ꾷҆wtT@=L85M;8P>;QA>SDAUGEVJHXMKYQO[TR]VU^YX`\[b^^c``dbbdccdddeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeennnIIIFFFLLLRRRTTTSSSPPPKKKHHHyyyݠjjjeeefffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeddddddedddcccbbcbbcaab``b__633OKKļľᱪ߭ަݟ۞ܜۜۛܙۗڕڕۓڒڑَڎڍڌ~ي|ى{؈z؇y؅w؄vԁrԀq؂s鷮姜޸~aPMO<9O=;P@=RCATFDVJHXMKZPO[TR]WV_ZY`\\a^^caacbbddddddeeeffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333222ttt\\\AAACCCDDDEEEEEEDDDVVVdddeeeffffffffffffffffffffffff333333ffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeddddddddddcccbbdbbcaac``b^^hdd}}୤ݢݠܟݞ۝ۜܙۙۖۖ۔ړڑېڏٌٌڋ}ڊ{و{هyنx؅w؄t؄t㨞娝ـq~oځq䳫еsebTCAQ@=RCATFDVJHXML[RP\UT^XX_[Zb^^c``cbbdcceddeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffjjjvvvLLL>>>;;;>>>wwwڞiiieeeffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeddddddddddccdcccbbcaab``300300lih㴬ޤݟݞܜݚۙݘܗەܔےۑڏێڍڌ~ً}ԄwՃvچyنxۉ{趭¼؀qp~o~n|m|n܈y䦛ݸ~|`ROTDCVIGWLJZPO\SR]WW`ZZa]]c``bbbcccdddeeeeeefffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff~~~Ͱ~~~dddeeefffffffffffffffffffffffffffffffffffffffffffff333333VVVFFF777ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeedddeddedddcccbbcbbcaab``b__c``urr᫡ޟݛܚܘݗۖݖۓےܑېێێی~ډ}ډ{وyޒ꾷뾷ޑفsـqp~o~n|m|k{k{j~p☌㴫ɱshg[PNYON[SR^WV_ZYa]]c``bbbdcceddeeeeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeennnڝjjjeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeedddeddedddcccbbdbb200300b__gdd}|巰ࣙݛݙܗݗݕ۔ܒՊ}ԉ|ۍیڋ}ۊ}⡖Ľ跮ۈzلtڂsځrq~p}o|n|k{k{jyjyizj{媠ڹf^]^WV`[Za]]c``bbbcccdddeeeeeefffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffdddbbb]]]WWWWWW```󺺺~~~dddeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFFffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeddddddeddedddcccbbdbbb``c``b__lihĽ䭥ޝݖݕܕݓےې܏ێ܍尦ļ嬢ۇyچwڄuقtقsڀqp~n}m|l{kzkzizjzjzhzhހq㜎㷯ɸwsrc__b``cbbddddddeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeebbb\\\TTTMMMHHH|||؛iiieeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeddddddddddccdcc211200b``b__da`spoᶮڞޘݔܒܒݐݓ꼴⡖܈zۉzچwچvڄuڂtځqڀqo~n}m|l{l{j{kzjziyiyiyh{kᎀ豧Ϙgeedccdddeeeeeeffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffccc^^^UUULLL[[[򸸸|||dddeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeddddddddddcccbbdbbcaac``b__fcb}{zʽ沫ߝݓľýߙی~܊|ۉzۈz܆xۄvڄuڂrہrpn~n~n}m|k{l{jzjzjzjziyhz浬}||cbbedddddeeeeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeebbb\\\VVVךhhheeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeddddddedd211311caac``a^^khgºޓݏ܍݋}ۊ|ۉz܇yۆxۅv܄sۂsہqpo~n}m}l}l|l{k{kzj{k染׸iffdbbdccdddeeeeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffdddppp򸸸|||dddeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeedddeddedddccdcccbbcaab``b__c__spo¾纱᠕ސ݌~܋|݊{݈yۇwۅw܄uۃsہsہrۀpۀo~m}m}m|l|l|l߅v鳫c``caadccddddddeeeeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffrrr֗gggeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333222eeeeeeeeedddedd322211cbbdbbcaab``b__fba{xwƹ¼籧ߗ݌~݉z܈y܇w݅w݄vۃtۂrہqۀqo~n~n~n}m䚍ܸnkjc``caadccedddddeeeeeefffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffff˷{{{dddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeedddeddedddcccbbdbbcaac``a^^jffѽ澸妜ޏ݈z݆w݅v܄u܃t܂s܁q݀p݀poޅu豦ɷb__c``dbbdccedddddeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffpppiiiffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffeeeeeeeeeeeeeee222222dccdcccbbcaab``c``c__qnm路㜐މ{݅u݄t݃t݃r݁q݁q㕈㼵vrrb__b``dbbdccdddeddeeeeeefffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeddddddddddcccbbcbbcaac``b__daazvvŸᾹ讥ᓅޅu݃tބu謡Ѹebbc``caacbbdccdddeeeeeeeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeee222222dddedddcccbbdbbcaac``c__ieeϻ廴窡缵~{{c``caacbbdccedddddeeeeeeeeefffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333+++FFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeeddddddcccdcccbbbbbcaacaadaaommjhhdbbcbbdccddddddeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeee222222dddddddddedddccdcccbbcbbdbbfeedbbdcceddedddddeeeeeeeeefffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffVVVFFF777ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeeeedddddddddeddeddeddeddeddedddddeeeeeeeeeeeefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff222222eeeeeeeeeeeeeeeeeeeeeeeeeeeeeefffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffVVVFFF666ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffff333333ffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666ffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF666fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff333333ffffffffffffVVVFFF777fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffVVVFFF777tiled-1.0.3/dist/win/gpl-2.0.rtf000066400000000000000000000400031315121121300161330ustar00rootroot00000000000000{\rtf1\ansi\ansicpg1250\deff0\deflang1033\deflangfe1060{\fonttbl{\f0\fswiss\fprq2\fcharset238 Verdana;}{\f1\fmodern\fprq1\fcharset238 Lucida Console;}} {\*\generator Msftedit 5.41.15.1507;}\viewkind4\uc1\pard\nowidctlpar\sb100\sa100\qc\lang1060\kerning36\b\f0\fs28 GNU General Public License\par \kerning0\b0\fs16 Version 2, June 1991\par \pard\nowidctlpar\f1\fs14\par Copyright (C) 1989, 1991 Free Software Foundation, Inc.\par 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\par \par Everyone is permitted to copy and distribute verbatim copies\par of this license document, but changing it is not allowed.\par \par \pard\keepn\nowidctlpar\sb100\sa100\qc\b\f0\fs20 Preamble\fs24\par \pard\nowidctlpar\fi142\sb100\sa100\b0\fs16 The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. \par When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that you know you can do these things. \par To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. \par For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. \par We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. \par Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. \par Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. \par The precise terms and conditions for copying, distribution and modification follow. \par \pard\keepn\nowidctlpar\sb100\sa100\qc\b\fs20 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\par \pard\nowidctlpar\fi142\sb100\sa100\fs16 0.\b0 This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". \par \pard\nowidctlpar\sb100\sa100 Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. \par \pard\nowidctlpar\fi142\sb100\sa100\b 1.\b0 You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the Program a copy of this License along with the Program. \par \pard\nowidctlpar\sb100\sa100 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. \par \pard\nowidctlpar\fi142\sb100\sa100\b 2.\b0 You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: \par \pard\nowidctlpar\li284\sb100\sa100\b a)\b0 You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. \par \b b)\b0 You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. \par \b c)\b0 If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) \par \pard\nowidctlpar\sb100\sa100 These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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. \par 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 Program. \par In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. \par \pard\nowidctlpar\fi142\sb100\sa100\b 3.\b0 You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: \v \v0\par \pard\nowidctlpar\li284\sb100\sa100\b a)\b0 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; or, \par \b b)\b0 Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, \par \b c)\b0 Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) \par \pard\nowidctlpar\sb100\sa100 The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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. \par If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. \par \pard\nowidctlpar\fi142\sb100\sa100\b 4.\b0 You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. \par \b 5.\b0 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. \par \b 6.\b0 Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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 to this License. \par \b 7.\b0 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. \par \pard\nowidctlpar\sb100\sa100 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. \par 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. \par This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. \par \pard\nowidctlpar\fi142\sb100\sa100\b 8.\b0 If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. \par \b 9.\b0 The Free Software Foundation may publish revised and/or new versions of the 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. \par \pard\nowidctlpar\sb100\sa100 Each version is given a distinguishing version number. If the Program 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. \par \pard\nowidctlpar\fi142\sb100\sa100\b 10.\b0 If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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. \par \pard\nowidctlpar\sb100\sa100\qc\fs20 NO WARRANTY\par \pard\nowidctlpar\fi142\sb100\sa100\b\fs16 11.\b0 BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. \par \b 12.\b0 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. \par \pard\keepn\nowidctlpar\sb100\sa100\qc\b END OF TERMS AND CONDITIONS\fs20\par } tiled-1.0.3/dist/win/headerimage.bmp000066400000000000000000001032621315121121300173010ustar00rootroot00000000000000BM6(9 |  PE/]ߗ7$nKR7J<'Ãэ. qMlIlIsMr5$khFĄ>pLmJmJmJmJlJnK1vok4#nKlImJmJmJmJmJnKnKfE"ؐsySH0nKlImJmJmJmJmJmJmJlInKlIJ1>E.[bEP7oLlIlJmJmJmJmJmJmJmJmJmJlInKfFb7'eZ[CZAoOnMmKmJmJmJnJmJmJmJmJmJmIlJmKmOrWSEUD*) X_WU;+*뤛飛뤛륛꣚頖鞒雍蘋斅擀}yvx|芀鉂臃烁肁rBAHHHmmm666.!!履짞咽﨟吏xё꣛颚꣛飙韕靑蚎痊疆撄撀}{}鋁錄ꊆ釄{zA10```===uuu((("咽륜lg6%#[?<{桗ꤚ颙蟕蜐蚍昉旆蔃蓂}~茀芃銄vrNMM---hhhNNNrrrF1.褐yTPmMH뤜꣛뤜栘|v [?;頖盐蚍瘉症蔃撁}{y{}}HCbbbccc TTT999SSSRKKbC@T;8f`즜뤛ꤛꢛ룜쥜ђbD@ um虋瘇畄擀zvst2дNNN___ppp222OOOWWWYJI`[2"!xr履륝뤜ꤚꢚgb-]>9瘈똆~wswaC:-ۮUUUJJJ===gggmmm HHH^^^tttiQM{u=+*Γ륜륝룚렗vmL2,>(#k[|UF`bLWWWFFF)))---MKKfaѕ/! 觠蘒꟔雎ꚈgA8 X\Iddd+++&&&cccFFF 2..yꨠ"列霍瘉֋y~js_/hМ###1#"Ж쟒€t 蔀yuploA442%З }}}EEEhffB-+vOKZ;7ꛌ藆~xsnjہdpW*~ivvvfff555ZSR]>;#wr획ꖆ摀ysnkjoqdOG485XXXbRQ_[㣜 ݛ횏ꕉ瑂|ustw{~|PO`HGccc777((([[[ooooVS{uup?-,얌ꑅ莀}~爀腀烀x=<]]] >>>!Ӗ픍됈ꍆ댆鉅膃ꆄrpD55SSS'&&so颛픎푌쎊ꊇ鈆ZY[[[AAA }x쎋6""ddd}}0Їfeecc nffF'%օ9tiled-1.0.3/dist/win/installer.qbs000066400000000000000000000061111315121121300170450ustar00rootroot00000000000000import qbs import qbs.FileInfo import qbs.File import qbs.TextFile WindowsInstallerPackage { condition: { if (project.windowsInstaller) { if (!(qbs.toolchain.contains("mingw") || qbs.toolchain.contains("msvc"))) { console.error("Unsupported configuration for Windows installer"); return false; } } return project.windowsInstaller; } Depends { productTypes: ["application", "dynamiclibrary"] } type: base.concat(["installable","appcast"]) Depends { name: "cpp" } Depends { name: "Qt.core" } property int bits: { if (qbs.architecture === "x86_64") return 64; if (qbs.architecture === "x86") return 32; } targetName: "Tiled-" + project.version + "-win" + bits wix.defines: { var defs = [ "Version=" + project.version, "InstallRoot=" + qbs.installRoot, "QtDir=" + FileInfo.joinPaths(Qt.core.binPath, ".."), "RootDir=" + project.sourceDirectory ]; if (qbs.toolchain.contains("mingw")) defs.push("MingwDir=" + FileInfo.joinPaths(cpp.toolchainInstallPath, "..")); else if (qbs.toolchain.contains("msvc")) defs.push("VcInstallDir=" + FileInfo.joinPaths(cpp.toolchainInstallPath, "../..")); if (project.sparkleEnabled) defs.push("Sparkle"); // A bit of a hack to exclude the Python plugin when it isn't built if (File.exists("C:/Python27") && qbs.toolchain.contains("mingw") && !qbs.debugInformation) { defs.push("Python"); } return defs; } wix.extensions: [ "WixUIExtension" ] files: ["installer.wxs"] Group { name: "AppCastXml" files: [ "../appcast-win-snapshots.xml.in" ] fileTags: ["appCastXmlIn"] condition: project.snapshot } Rule { inputs: ["appCastXmlIn"] Artifact { filePath: input.completeBaseName.replace('win', 'win' + product.bits); fileTags: "appcast" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "prepare " + FileInfo.fileName(output.filePath); cmd.highlight = "codegen"; cmd.sourceCode = function() { var i; var vars = {}; var inf = new TextFile(input.filePath); var all = inf.readAll(); vars['DATE'] = new Date().toISOString().slice(0, 10); vars['VERSION'] = project.version; vars['FILENAME'] = product.targetName + ".msi"; vars['APPCAST_FILENAME'] = output.fileName; for (i in vars) { all = all.replace(new RegExp('@' + i + '@(?!\w)', 'g'), vars[i]); } var file = new TextFile(output.filePath, TextFile.WriteOnly); file.truncate(); file.write(all); file.close(); } return cmd; } } } tiled-1.0.3/dist/win/installer.wxs000066400000000000000000000714711315121121300171140ustar00rootroot00000000000000 CMDLINE_INSTALLDIR CMDLINE_INSTALLDIR INSTALLDIR NOT Installed tiled-1.0.3/dist/win/push-to-itch.bat000066400000000000000000000004651315121121300173630ustar00rootroot00000000000000secure-file\tools\secure-file -decrypt dist\win\butler_creds.enc -secret %my_secret% -out butler_creds curl -fsS -o butler.exe https://dl.itch.ovh/butler/windows-amd64/head/butler.exe butler.exe -i butler_creds push --userversion=%TILED_ITCH_VERSION% itch/install-root thorbjorn/tiled:%TILED_ITCH_CHANNEL% tiled-1.0.3/dist/win/qt.conf000066400000000000000000000000661315121121300156370ustar00rootroot00000000000000[Paths] Plugins = plugins Translations = translations tiled-1.0.3/docs/000077500000000000000000000000001315121121300135325ustar00rootroot00000000000000tiled-1.0.3/docs/CNAME000066400000000000000000000000221315121121300142720ustar00rootroot00000000000000doc.mapeditor.org tiled-1.0.3/docs/css/000077500000000000000000000000001315121121300143225ustar00rootroot00000000000000tiled-1.0.3/docs/css/extra.css000066400000000000000000000011031315121121300161520ustar00rootroot00000000000000div.col-md-9 img { max-width: 100%; display: inline; padding: 4px; line-height: 1.428571429; background-color: #fff; border: 1px solid #ddd; border-radius: 4px; margin: 10px auto 10px auto; } .future h2 { border-bottom: 2px solid rgb(255, 148, 90); color: rgb(254, 89, 0); } .future a { color: rgb(254, 89, 0); } .new { font-weight: bold; font-size: 80%; background-color: rgb(254, 89, 0); color: white; display: block; border-radius: 4px; float: right; padding: 4px; margin: 4px 0px 10px 10px; } tiled-1.0.3/docs/index.md000066400000000000000000000024041315121121300151630ustar00rootroot00000000000000# Tiled Documentation Welcome to the documentation pages for [Tiled](http://www.mapeditor.org), a flexible tile map editor! Here you will find the [Tiled User Manual](#tiled-user-manual) and the [TMX Map Format](reference/tmx-map-format.md) reference. If you're not finding what you're looking for in these pages, please don't hesitate to ask questions on the [Tiled Forum](http://forum.mapeditor.org). *This documentation is currently work-in-progress. Initially the relevant pages from the wiki have been ported over, providing a limited amount of documentation for specific Tiled features. Over time, this should become the place to refer to for any details about using Tiled.* ## Index ### Tiled User Manual * [Introduction](manual/introduction.md) * [Working with Layers](manual/layers.md) * [Editing Tile Layers](manual/editing-tile-layers.md) * [Working with Objects](manual/objects.md) * [Custom Properties](manual/custom-properties.md) * [Using the Terrain Tool](manual/using-the-terrain-tool.md) * [Using Commands](manual/using-commands.md) * [Keyboard Shortcuts](manual/keyboard-shortcuts.md) ### Reference * [TMX Map Format](reference/tmx-map-format.md) * [TMX Changelog](reference/tmx-changelog.md) * [Libraries and Frameworks](reference/support-for-tmx-maps.md) tiled-1.0.3/docs/manual/000077500000000000000000000000001315121121300150075ustar00rootroot00000000000000tiled-1.0.3/docs/manual/custom-properties.md000066400000000000000000000124461315121121300210440ustar00rootroot00000000000000# Custom Properties One of the major strengths of Tiled is that it allows setting custom properties on all of its basic data structures. This way it is possible to include many forms of custom information, which can later be used by your game or by the framework you're using to integrate Tiled maps. Custom properties are displayed in the Properties view. This view is context-sensitive, usually displaying the properties of the last selected object. For tiles in a tileset or objects on an object layer, it also supports multi-selection. ![Properties View](images/properties/properties-dock.png) ## Adding Properties When you add a property (using the '+' button at the bottom of the Properties view), you are prompted for its name and its type. Currently Tiled supports the following basic property types: * **string** (any text, including multi-line text) * **float** (a floating point number) * **int** (a whole number) * **bool** (true or false) * **file** (a relative path referencing a file) * **color** (a 32-bit color value) ![Add Property Dialog](images/properties/add-property.png) The property type is used to choose a custom editor in the Properties view. Choosing a number or boolean type also avoids that the value will get quoted in JSON and Lua exports.
New in Tiled 1.0
## Tile Property Inheritance When custom properties are added to a tile, these properties will also be visible when an object instance of that tile is selected. This enables easy per-object overriding of certain default properties associated with a tile. This becomes especially useful when combined with [typed tiles](#typed-tiles). Inherited properties will be displayed in gray (disabled text color), whereas overridden properties will be displayed in black (usual text color). ## Predefining Properties ### General Setup Usually you only use a limited set of object types in your game, and each type of object has a fixed set of possible properties, with specific types and default values. To save you time, Tiled allows predefining these properties based on the "Type" field for objects. You can set this up using the Object Types Editor, available from the _View_ menu. ![Object Types Editor](images/properties/object-types-editor.png) By default, Tiled stores these object types in the user settings. However, since you'll often want to share them with other people in your project, you can export your object types or change the storage location of the object types file. A simple XML or JSON file with self-explanatory contents is used to store your object types. The color not only affects the rendering of the various shapes of objects, but is also the color of the label which will show up if you give your object a name. To make the predefined properties show up in the Properties view, all you need to do is to enter the name of the type in the built-in "Type" property. Usually this is what you're doing already anyway to tell your engine what kind of object it is dealing with.
New in Tiled 1.0
### Typed Tiles If you're using tile objects, you can set the type on the tile to avoid having to set it on each object instance. Setting the type on the tile makes the predefined properties visible when having the tile selected, allowing to override the values. It also makes those possibly overriden values visible when having a tile object instance selected, again allowing you to override them. An example use-case for this would be to define custom types like "NPC", "Enemy" or "Item" with properties like "name", "health" or "weight". You can then specify values for these on the tiles representing these entities. And when placing those tiles as objects, you can override those values if you need to.
## Future Extensions There are several types of custom properties I'd like to add: * **Enumerations**, where you can predefine all possible values and it forms a combo box ([#1211](https://github.com/bjorn/tiled/issues/1211)). * **Object references**, which would allow easily linking objects together and Tiled could display such connections ([#707](https://github.com/bjorn/tiled/issues/707)). * **Array properties**, which would be properties having a list of values ([#1493](https://github.com/bjorn/tiled/issues/1493)). * **Dictionary properties**, which would be properties that can contain any number of other properties as children ([#489](https://github.com/bjorn/tiled/issues/489)). It would also be nice to add support for **limiting property values**, like the length of string properties or a minimum/maximum on number values. Apart from predefining properties based on object type, I'd like to add support for **predefining the properties for each data type**. So defining which custom properties are valid for maps, tilesets, layers, etc. ([#1410](https://github.com/bjorn/tiled/issues/1410)) Finally, the predefined properties would work very well together with explicit **support for projects**. Then you could switch between different projects or get started on an existing project, without needing to configure Tiled to use the right object type definitions. If you like any of these plans, please help me getting around to it faster by [becoming a patron](https://www.patreon.com/bjorn). The more support I receive the more time I can afford to spend improving Tiled!
tiled-1.0.3/docs/manual/editing-tile-layers.md000066400000000000000000000100471315121121300212060ustar00rootroot00000000000000# Editing Tile Layers [Tile Layers](layers.md#tile-layers) are what makes Tiled a _tile map editor_. Although not as flexible as [Object Layers](layers.md#object-layers), they provide efficient data storage and good rendering performance as well as efficient content creation. Every new map gets one by default, though feel free to delete it when you're not going to use it. ## Stamp Brush Shortcut: `B` The primary tool for editing tile layers is the Stamp Brush. It can be used to paint single tiles as well as larger "stamps", which is where it gets its name from. Using the right mouse button, it can also quickly capture tile stamps from the currently active layer. A tile stamp is commonly created by selecting one or more tiles in the Tilesets view. The Stamp Brush has some extra features: * While holding `Shift`, click any two points to draw a line between them. * While holding `Ctrl+Shift`, click any two points two draw a circle or ellipse centered on the first point. * Activate the _Random Mode_ using the dice button on the tool bar to have the Stamp Brush paint with random tiles from the tile stamp. The probability of each tile depends on how often it occurred on the tile stamp, as well as the probability set on each tile in the _Tileset Editor_. * In combination with the _Tile Stamps_ view, it can also place randomly from a set of predefined tile stamps. This can be more useful than the _Random Mode_, which randomly places individual tiles. ## Terrain Brush Shortcut: `T` The Terrain Brush allows for efficient editing with a certain type of corner-based terrain transitions. Setting it up requires associating terrain information with your tiles, which is described in detail in [Using the Terrain Tool](using-the-terrain-tool.md). Similarly to the [Stamp Brush](#stamp-brush), you can draw lines by holding `Shift`. When holding `Ctrl`, the size of the editing area is reduced to one corner (this currently doesn't work well in combination with drawing lines).
New in Tiled 1.0
When holding `Alt`, the editing operations are also applied at a 180 degree rotation. This is especially useful when editing strategic maps where two sides need to have equal opportunities. The modifier works well in combination with either `Shift` for drawing lines or `Ctrl` for reducing the edited area. ## Bucket Fill Tool Shortcut: `F` The Bucket Fill Tool provides a quick way of filling empty areas or areas covered with the same tiles. The currently active tile stamp will be repeated in the filled area. It can also be used in combination with the _Random Mode_. When holding `Shift`, the tool fills the currently selected area regardless of its contents. This is useful for filling custom areas that have been selected previously using one or more [Selection Tools](#selection-tools). ## Eraser Shortcut: `E` A simple eraser tool. Left click erases single tiles and right click can be used to quickly erase rectangular areas. ## Selection Tools There are various tile selection tools that all work in similar fashion: * **Rectangular Select** allows selection of rectangular areas (shortcut: `R`) * **Magic Wand** allows selection of connected areas filled with the same tile (shortcut: `W`) * **Select Same Tile** allows selection of same-tiles across the entire layer (shortcut: `S`) By default, each of these tools replaces the currently selected area. The following modifiers can be used to change this behavior: * Holding `Shift` expands the current selection with the new area * Holding `Ctrl` subtracts the new area from the current selection * Holding `Ctrl` and `Shift` selects the intersection of the new area with the current selection ## Managing Tile Stamps It can often be useful to store the current tile stamp somewhere to use it again later. The following shortcuts work for this purpose: * `Ctrl + 1-9` - Store current tile stamp (similar to `Ctrl + C`) * `1-9` - Recall the stamp stored at this location (similar to `Ctrl + V`) Tile stamps can also be stored by name and extended with variations using the _Tile Stamps_ view. tiled-1.0.3/docs/manual/images/000077500000000000000000000000001315121121300162545ustar00rootroot00000000000000tiled-1.0.3/docs/manual/images/introduction/000077500000000000000000000000001315121121300207755ustar00rootroot00000000000000tiled-1.0.3/docs/manual/images/introduction/tiled-new-map-tileset-added.png000066400000000000000000004103451315121121300266630ustar00rootroot00000000000000PNG  IHDRi*sBIT|d IDATxw|u̶CBHB)R,gî;rzzgkCrbŊ4%Ivl&$!d!a$;;;N&?Q&M#B!B!1ꫯRI&tuMӚ,uEQܸ(m!B!B!D2W(h|NTeU16ZAJJrCB!B!ڜZi>oFOrze> ѿ,oBeNC:w$%fwΞFʻ5n?'&ig̻?N~*]'J!dޟB?G!<{$DžggT6CSWx:>)u4Gxy}D[YͱbH'_"=amB!Q"״wտ#zQUScB!DPH=r|z ;7>-h'?M碑پ>qnbwv5ZyΠ9k~e& 6ؾ.pj:t+!B?a6mZPvZ[ޖ6Ybb㯷/Mk7K!89&.Dx6Ag׹q`H:'^Nr˰{pO2%j%^4C'جz>Oc|n4z&>yYmr{{|0猆opSfr9;u-#iJ!TlFv C_ pf&W&Xch*!&7qA! ooH`cg2bd:@PS<9w7dTGk%5^{CJ46kg#[1>FƦcڍRFy`ѿ?fpưC콐QMU]09i_ !SiӦ5{ܿzd !BY+ì0OP]ԹUEiZ $o=51W_obo^@*ڟ׉[ltl>8-8-_;$g"#⳻1g7B!1 DVK=CmGBqhhE5dDCӼW¥(mOUlu: (^YZ[[:b`=2h'ZK5}bc?w8շo_4Mcǿ|deeX˛%/_Njjj%B!BH@,EQTA}?3<>O|֒ɴiӈ ,C4ϒ%Kp\ 0}+Wdٲez뭼+TWWsϡ*3f86UU:t(Vj_Io6G}Dii)s9dggꫯ' ܹsپ};?0PPP+?>8Rl޼{i\ѣGn:eee|G8pG^K0 \ 6Jqq1aÆqꩧq1>>;vxHNNK.!<<x3fЭ[7N'?3f ##cj+p3| sO=Z;&U[!B! Gݻ㏹+yGHMMeΜ9:ƍxmg\{̜9x Ç~zSQQt:رcy8yשwܹO*m۶pիWX 1b˖-/۲e III6Y722 &r}Ϛ5koذÇs3c VXڵk;  =ã>JTT_5!!! 2+V]ndddylVUUh"nnN} wL+B!Bʀ,\3g{WXIIIAQN:$vy{l޼I,_5k׮eᤦ( #F !! ULVb-N[ܰai'"";wҧOvލcΝӿ6nlbG9krXt)<7Y/$$ğ@ !;;?11={IÇJ~0(B߾}1x≬^8iXHJJ j\zM-Zȟh;1ђB!B!DW(^111dffrg&ZKtF/aÆ_i&zz111eO>ڵM6quבDUU֭#66}?b:t(FcC/3m4xs~///':::qw%11o/oN`ժUTWWӯ_?pfCr6LJhll6Ym-B!Bt#kȑ,[{:^m_4W4ArJuuQRRf3BfSMNN .dС߿?Xχ߿_wެY@JJ ҷo_N+lpqQVVŋ5jTn7nDסǪXlQTTʕ+[(׋NMM qqq v;k 6|V^VlcPB!BcQfڴi|ᇔc40`ݻw7oܤ w>}8p %%%̚5 >|x9묳xW- F?#F0wÎM7Ă O44f3{fΜ9MrߟUV1eʔx(Ȱa((( %%xLk(уN: Mrz!Əq&oNʇ~OBBcǎeҥu,  bӦMMylcPB!Bc2i$8'V\˙1cFWܹse]J[!B!'xL-[153ƍ3fLWtB!B!:CΜ9=\Pib₮%m{?ПwMM O>$FK.Kɾ>֎!B!X"S B!B!1O !B!B? Id !B!B?#@yyyW!B!B!a q!B!BqXFC!B!B2q!B!BqX]!B!B!:!;wb۱GeH9* !B!.Id !Ν;#++ y^Ǯ]$%B!@Bt NVVp8ʘf {TB!B\]k.yzlFUɫ#<>m1׋f˅`0`X'**^m66xBCyrZ\lbb TUQS!hKгJOf'QVg܅U@m]1 `PдPHL&GO\@1X~iO;^z7F9Z8f5s}1z񃨹tɩ0(vr=wK||׬&<<Çs7PQa'Ϸѥ1E4͛ǬY(((/ \pgy&_}ƍc̙ݻ72d-[ĉIGŲ,ULT *UD\)0^TEGQTl{Ji845Ӊm_(,Oap٩UV={iږcRSSa۪j2^9JYB!)A n#+ ^/i^BF>LbLbLDF]͂. /JRRBJKӷ7%5DSR-\[K9DVII ={fu,Ȫq}K`hxB&]XڻE!..L4l8^])((b0p@SO=EFFEEE'?sv;p3eLXX&AUvw1*cUUP>4iӛ~tc-w'1Bw(f|h `P1ٌ*J'5ƶl9:={w/KK閞_㤱~Rz@ѻꃃ΢)Ѕ9I͖}WGM9躎'oOk4 Ot4o՚5k:rx(--fp8zFBCC&..mFVVVVF9N_uQIHHH|vR6ݻ}.4;\L&'NdƍG~0~oX?JYB!)&ˣmѴ7$£n(J1 Mۅ~O@QB`<Կt 55}'%%ef=\_.{1(G?ңG6k֬bxݹƏ%_ƚ5#>y͙3ko;pDFF:\ve|w{dW{nǕ/Q]U‡ǒ6QBC U0F*[d ƒ˙[:I(h#2x5NqfzblO?_Ȩ0d#h4p8o ٻ$bf EkuM(6 oddJa6i ::> |>{ n?sN***$. u؇ji1c$au]fQUU'- Ygtx\Obvك(tޝ$\.6t]'::]vITTTcivS^^NMM?b***HII!))b6ᠺžUUU&4Mtxi|>JKK,zx<BCCXKJJP8}W$BsZm>tP"miXG4t>FCQ0((7D^YbUR9 h7b0V`6[b2N=޽X7Ɲ4>;"چB)T=ji `3x?6!>8dz|L;B.v񉤥eoɺ IINdu+W2j(~Pl8Y`&LgϞ=~//w}bcc=v!)[qU\\q]]@4RSSxCc fXm4fmq184If{؀)BSY+'SEx5];/bXv3a9`6EUQWz>-hȪ/[/*jX小Sdz|y`ShƖ6}3q.Ŭ?߆)m}{d_k}/Eu(Fs+f>j*]E ahhlp.!ӈ9n䂌6tJ -o9ٙgg_,3h4uVx{>Q|x^F#V? >; >4 '|¼yغu+˗/0p p lݺp%P]]MHHy4hP5I(߿$z6ѨBBO n@[F^u9x5Mzժ׬b t'|l۶>h4b>p"\ ǁ}~O^ruN]'{[n$w8͸1Stwp Fч!,c)nIDMhyMz=֜7Lk>}^={6;Ibb"z OXZ*l2^/GJJ13u:X* HIIaذaG8DFF%%%İabZIA]ױZ>''[GII ݺu x\?~i'""jL&St]*vP,@]!!!(BMM DEEaX - ^)yXl54 BtO-ԵF1:DxPp%OݮSv}&ΉTM6Z?G JUԁ"232KQ%i1/ b)8%]rvṟ^OOq;­Gq f?YQ.zM`RֹĄ&nȻ^Z|N&6"Knn %w?={vs 7˸`ELF^| ͞Kni$&$]=@tTF_n#.UMhT/ :'|:/>}:&pӿ"##={;7TVk@q{j!@[>6zdjDN0/#H_T}L4ATT]e+@ zR qyJΛr[EDZ}Rb\ZE;=}&N6lZ_8uhCj;:ÇpEA1tB,VB kb$̾$4_U(Mz,QX. s$i{f_`36iZ`b VX῝L='깹Auũ'x"]8Zb\.׮6g7o(^!̸qX,qѬ:شi>={2eTIKii)Ihhh .])++#)) ~UVV%&&WWW*]_~l26Y&B ZMd5~Ҟ727-z E]P`K?Z|cnEQ4?;4UYՄbcHu8UWW!Cz=\6/ٿ<~WbO~|}n!=rXqXm腷Lj톧j69z@%!^cI9=kZwAtt-y:K3>`гB/xu(dcScW܌ =v?EVXf5)ܵƌeUhFMM ,l!v7i)nxzf4T|z뭜q{֭PjjjHNNSO%$$7kXXn]c%א֤{政~ð^'Q^Rٗ]6^?6|?8)6= HOdL`' Jvw`԰c&KۗHShg͖JJ+j4t{驑<70hJ}/.:Zȩ|O)*ԟn-CD=m5T*zBxhEաIաpÿRoaV+ 1LPBQ Dx~5(BZ Q+L+i>IM|{0$]UUrssW\sg#Y6ũ999d_jocvS[ۼ=C[v;uuu瓐1cDe۶mSZZڡ~L\\\DhraXt?dq8l۶$v;l6O-}Gii)&ɿNC:::ڿ|Uո@Uhh/y'^x%Kt†,P0+SI}D17{m[Luu7il%jM]Ǎ?1ZR[WCLL,pV?A)*~FI=eYh>>?rh#fDl,gͽUs.nA0ks KlEw?Jk[b5eSmbBI 9:Mgθ<8ۓtx{./uEa;ox󅔖СyDGc s=t]g|ᇌ3O?4fϞ͊+>}:gqeee\%n`O- IDS%"U:¨Y\ Cn/XT@Uk9T P0q)^ K|f:vRe kzGL|FjRSSeeduٻn0/=U/ES*nN#I.c|"?{ ԟІ|a%hRaVdo[AGAÂ@UEډOi-ad0W#;X#I,SJO50*C l{ zlTTTSjXPb߽{wV\I Vd5|0zhn݊si@`DrCEDDPYYIjj*555G<E] '߿l6 `0{5$(Jjx]'8@YYǏ'!!%KIYYYYM3zjjΝ 0keg&X?wLTC97?$BtVGYYY?hd (t=0t~5+//'2jMEyN'xVeN]]aax1mJ#l}A1їh{Xl\&5$g;㖙_}s6O>011ј&jjkEƒ= V7tnUkp]wvyQQz`LL _|q7L#|뭷]a7r0rH>^{5 fiӦ42Lk@_CZ( FpÛ̺*Ӂ d2@y _?R\k:, =gmIka#3cF﹜9tgݥˠ7ӎ ::oA~Ayyٿ-λH~~>7x3?pc**Bf1+J@QNl# P@OYQ!* Ӷt:X,W5TTVPzheVwB+smE f3%]zfPcV$ʟ$NI<\}O'MIKKcƍX&SŪn1Ͷ;}?͆vSVVرc_ZZҥK?~1+j%::b4 ַ~ ۇn'""(ph'd2( l޼_qvm6RRR:u |bb{Sil\BDl7҈NywxkEi|V}ʈ(@iwx[JPR յtTs:´vpJcGlܼCTDq ,KuFMM/u s[ܜTUIL0 z*ƍ;lL?fsv,O?$''qF FEE<{O Bwu{ F;Sݡ] IFC]ɱ_A7c2).v39'z)_}0t/,K9ۘq@`>|!}{^A]]F޽{ۋʒh4b2p:x=^ƎM8 \t{ <ナsP {a5L/TO?|v-UYR=YU[WGZZ>a0pyxb?Ws!d]xPU]KbR2G]%=jfuM(j$GZ8(8d!s%+@OM61&]q|e,6Ņb]y5b`h|r8۟⅗Currr0~">BBBx޻.wz?^zj{7:w}Ǎc-OKLL/k2`0py&==g}oΝ3xxyG۷/>(zf?1a֬YtIO- 5^n SH sןsGBݕE;8LQ S u݃VƺDb|:kMub-@FI,/-KaU]"@2ē7] BCCMYY=ؽ{7 lڼ\F#>Ⱦ}|r;J%hO<YաS IJ[[CM @1))I0;ˬq|PuOW`\Чx?qt:m3\5.nOz6Yq2?yqyh^Ed6cp\$&&RVZNLt_NX6/y>'Ψ_hKz U 4౪%D&QMzrEkX  Xd6ftU}zr5`tÍq3Zc񺫹G *1x=nr(ʣOD52e W:3LbAlK.\Ș1c:u*+Vp뭷2m4~m\.n7n>,wu| dee':>p7s_g_a/a$9".)w~̧<|pUAx]^y!=ۆ^>+嬃IX-Kc朥WhIb(ر'q]gN'W\>džIKMg=|>*jrו0vxϾ:(r5V~YJb ⌊ w쳛L M*J,QzqVdx*>MEU}UMPb&9L94yw^pQQXYٌC4{q2|Y9j"rQu{D.NݛGgosy{nBCC$%kh~h<Њ#:jwaڴi\v{ ??qDEEڵkLlHPy<jjj]ӧZE(DGG|TUUQVVFYY;v򊊊"::zCEFFrE^VV_9CI꺑DFFm=Zsh2ks>{_CKK!DWjGСC' oK:{"EQR % (t@*yFt=Н]{ Ȇj}[|>/f`8S6Ӎ՟4`O-χ&$4}H{8u$&$ԗ;jٷ/aFp݀7xkw=}G)(t:HO ???}+\j [~:-0Xr:A3UxhAe]1)Q}Whs f5IsyQ24OAD)B\\II)L<Njip^mɥ@v(('1>).-%,,{9fJJ 'Ofɒ%p 6lٲx3i$}Q B),,$33z Naa!=o&MTTr k׮Ço^} H{ E)H>W_suR_x**2ZbTA[<Ɣ zg}GU3-> )J@)AbYۮ"o]˪u-+ʺT"H"$2ɔ!$ܟ뚋g&39<Gn#㻩(a'x'ޓ. IDATZk@Q>NMiFtTKmÇ ]wшnݎ{eedd#s1]LtR3b>yShNѨXXLNB ,{6_F ӭ[z?d2Dqq1"--w/6DcCySUBBBh߾=%%%dffӧٽ{7VHv-֭[QUZk69~8m:2UZW:56ě }VzEWdL ~B!*SC =5EkU}!UPP\Yh 4%=yuw^zj& pieI*ͭQZZJVI.ˍzQZ`"'7] b?̾?-8נ;)|>}"4Mc]\uU4 gj4W0ɧ~[涣SL6YgmIs(zzCF d)%,jY b*۽tx!Ϥbcضm F9w2p@n6>?,T QQQ:}O`YHP'zRT\w^5~g=JV6mǏofvm}uHMMEUUn7-[$))6mTٛ&r|\f8/ߗ 3mcc(-9GAQTt.+^\\UX)KdMh=!Y^19$=x\\gg \*ޟ3b1a2XDl&<<:<&}>T"\ }|:za6X,u.v)**k#|[-Ibyf<`/& ν+l63y[wpCF\Œskh<ꂏۏBe j-+^|]]pk**--eܹU 0aƟۏ>@ #ˊ_Hnݺ5j)ZtԉN:5uS*eX"*sx!냢(9Nl6Ojjjl6c5L ?iz2s.-.. i&;Qh/3I<_gF!zZS><  K)h_vT妸8lhl"v4eC34ll""V:]Ѵ#tON-NPRRBV4W/GؓMf ]?5ŨC/+ex8~6 oo7bZYv-to>t>bnR@@wZֹsg뮻nDFF @5j/łu9xD{j4]+°=1D4 U0\UvUUk5w8QhqMx+#^vsb$ 1< :6PA1P|oOS<--;*zl6{!((v1|ZA?85+c8Fzh(;t ???|]WX wŵ_0遇xݷґ^Y F-&ty8zMxɞW j3vUӪU+:wnӢE j}sy> q6-/m}|;Mp8umֺ$KKKq8߻<KJ^333Z ]L!L -{xח eZ4W\{fp87vWUUOz  "&&ݻwGm j+Kqq1qqq4k]+-++4xo]i(W\\L-?VU'O믿z}Ol({zBQ\\,|0 =I;{FIc !hU{?v=z^O]\횂eԞlaɒ\7f8996.l-ߒ7\*Kp8\]CZ Xyl+,idl6b41Ƿ_-ILU=[Mco廒˓ \VؙQ,ccon7`3İd3YМ,VҎߺ{zxzR>#++ E-[ٜ'OгGO0 a9%%% 2/\A^]?{BSS*NXTTD@@@{>s.$֮˹V -EQ-63ֹϯ*sl>bܢo($dbt4V%kvŮj'k zjq5H#88ѣGc6IOOW^|l޼N:=ꃧvf8u 6++p=X=b g,[DAAW;z|9'yp8+ၡv9ogz~3LRK!Dcu5U6?7'+iKjgꏽD%TUEU nrrr `zÊk_e%t'**N3բǏWzaV{yJ'f KD3SKb綣†I]?FpN`` 6M)yVvQ]ΤIXr%~)=\bW_}5dffҭ[7bbbh޼yj(O]!s_UU-k>g"??R"d2(XF^ɪ 4M 2lذzs}FNNDkf O<(_fi?ܔߐ#Ãl>جipoz]ĺX?B!~`ZF}mF%d2Ѧ{.['g b.g ב*_={6x~ˡdeUK25 `MQ~OCk)TX,V(`ݔ_ ͚5c̘1>}0}t}׳f:t@߾} @/zh^4y\.ޙO_~Nx:St*||h]Vrvp:B%hԳ=z).s}J59CT9ZVTUjp8Dgbرc^}}}+lt+1{!TUd2 _HXXP)|'mxP!Ӟu_H6*;djAUUZ~8psIn6:t@~&(( __|}}vׂׯ ._;&ŧ'x1z qyԚ3)YV OQhQc 5)N RQew!ĥ`0`HNN&99m/~u]Q}>c !B!4O/B&_vl6t:eu!B!,lp1ZlY tr1%B!B%,!Dhժ+Qb@V%B!B%,!DB!BڐbB!B!`ؽ{wSC!B!BjB!B!J˖-+Kd>}"QXXHNNNS7E4`j!B!.R]qAPU}jS7G4"͎;HOOdB!QH"KqA ۷/MјF#]veڵM!B!eBO!.Hnn.Mtb0m!B!.#KK8xp=zۯ2h;#{!B!Dc^Y , ((C6uShp7o :*ڄScl߼k'B!BץU&}]ۇ(XVksjP7n$%%Eln x>8~5ۗ-Yvv s2Yrc߬[0S6#=sB!~}]ڵkǠA)BLc_V[#kѼ+uּU1ӧOj*e-[$""Z$DZv-c߬֜e>׳\!B!.B??? Ċ+d2o3n8͛`;yyy|g`ާz|Ǝ³\!BXz56l___zyڵ+ з}ڵ+Z `ڴivm,^cǎSOq!+ 0 47ѳBKϛ4|֬YCHHaaa䐓W_}}G@@}͛7駟v p뭷e9N&Of֬Y,Yqayw;v,ݻwgϞ=|<tRjnF#|g(*yyy<j.NqYYY:tѣGc2X,5-[p8cӧ,2`vݻltN:/ۦM*V+&/ƍIJJ"22EQ߿?>Ljj*ѲB\Jʟj]M+O4]d".]Z;v0yd~z%B[֭ cǎdeeЭ[7rss9z([lcǎW{ѿڶm/Ff͚??dץ5jT999`Xe6 MZ qpiM/))x5ݻٵkLJkfP!<'k mv*BBBp\ނ8^o(G`04Y?L2PJN': $$I%BߏիW{n>|}}9u3fݛ_dJJJ1b_|1&Mj'&ƺ.vhamҦM/^nxb1˗\Aaa!+WJƍ,~ZZZ$G~~~[RRRX~=GA4N'+zopVH!.mH;r-f(_P/1U_p o/YՇm۶K/( .> ˗/oٲEѵkW|}}\PVXAZZZĪLhh(z?d޽,Zŋ-QBQ+nán7S>hт?={jVСChlE^+ !Oc_^Psy,X)S`6ر#cƌ x(..&>>QFĉ/pݴhт\i-[ҽ{wONHH߼ַnݚ3|2331tܙVZ|d2ѣG!.ݓd lشm=zٯ*ԻwoIOO'((W_}łiktЁÇڵ㪫>nc4ӟDtt4vb֬Y3{lz)|}}=z4۷oگw̞=oBkʸn-[ɓ'1 MKLdw}U($$^{r*s\ЫWJ7oޜ'V[nt7uB,ݻw'99ÇSTT]wUaXlcԩF^{5.]'/_Σ>J-Xnf͢gϞ3~x~g233ΦSby'8z(O>$,Z zG}ă>ȬYkjĂ J̙={^fB!]/z|WII DDDTخk5(qZdaB\ކ !DMr5kݫ{,5QQQpԩziڵk9r$~~~X, mؼy3{&** EQӧO'ׯPV4&&={C۵kɓ'm'L'xWP#F*Vnn.?b˖-Z[!YzE71UC &bbbO>DWPPcUUq\Ҷ,fϞ͜9snZĝ3>.=x?f '|C=tI.￧uoӟ$V !曜}еkצnwYU GB\jS#| n[?^II z _vsXzwQaigUm>xgɒ% DѣG'|>Cz-BLL s=>|7u;72bJKK)=MϧK.`61Fػ޽0|]fKRRR!B!DE3gΔbB W5ą2dH4MCUUTUm۶mV_^WwB!B4&Z(B!B!. B!B!*6f;Ν;7uB!B էOj5b6ٿ?Mݔ߭H˗݅B!DB&.FB!B!.Ǐ*i֬~~~DFFV{jYKxޓB!B!.~ǏߟQF(Jiw}ɓ'MfIw!B!۷6u3d)((o߾\.}Ue7E߾}nWyL%.9Rb0orRMhh({m!k?̪UHKKvAIJJjM6wIiиB SRRBvv6N}UU%;;*?&|)..`04uSDp\t MB!D-j]v3b?`2_Xp!yyy 2:NVRXzQ 9q\8z9f{d[ݻEQZDGG3j(ڴiS/ /֭wM Hf̘A>}ׯ9srۛeW^y֭[3tPVZh{=/%ė_K6~ǎ1LfL&~_UU A*l2j#77 uVa]Np\>|Xw^&Nhd|ZLdSNnM6\,88vqq^/&==￿.O]\d ,, ݻwCvp\̙3p8oYf;жm[ /{yᇉvdlق[n\LF{'%ė_K|//PVWDix-Z}j%//HoΦM(--EQ !999zr6RRRXb999:tZ%&$3oB~-u|!D\Bbq=0RDiJxx8dgg|rx5kQQQL6 ܹs^8N׿vyϹ馛(..歷bуT{=N F14oޜų>K~~>h͛;vlmHϦM9r$PkMrr2`0HLL䦛nd2+V?ֱV\Ɂx'0 ;XѣGB!DXX;vy^ك` 66V_߷Ç;w.?^3駟ַ  ''$Tetܙm۶qARRRjcCH ~B?׸FgsTғ1s:h_|?̋/Hvv6<n[oرc d2qi<ȑ#QȨQشiz^z0ߟm۶t:ٱctIg޽mڴO>L&Eяis`` ڵcݺu8NWN.%%%i&N'ٳ={;t耪\.ڷoOff~Mp^.~ݺu 2ٌ`wر_ՅfCS_K|/%ė o|7|QTTĮ]7oÇA~ //ҥK$<<f>dhӦMG\n7iii:6IY>}DV=G֮] zv;p8yzwT;+zzd=AU><<\Wp͆iY]N),,vӧU%%%V*{f <-[гgO}& йsgΝÇIOO'::ZorJ?("''ypBlB!i$BU_ҥKqDFF2zhٳ'׿ʢyDQ:vW\s=d"%%.] >e˖ꫯR\\LLL >`3O?UUy衇h֬W\q%%%C!dM}z.=IMM%>>UU+Uiv{bټ6u]ӴJOyb)..(%<233GQb5W;2|:Ď;4i.a``[nڵGO cĉ ~Gou }UUqJKKm?~|~jDH|/%ė__/^`tM7>>^:QQQ 8rP&뮻뮻kyrr2޽{Wvp8* +/hذa f#((j`SҦM/^nxb1˟\Aaa!+WgJԩlܸ˅i鉅G~~\PU^z_ЬY CRR;wѣ^m` ??͛7Wypzh֭[SO=|@~<ހ4ӧkQ\\Ldd~РA{_|QO|nuq9ֈ_K|/%Ŀo۶ͫȺǙ3gXfMc4IOm6z&tոFֽ[庐^} ;rB^*]߼ysJr-.馛*tu8L&l}<^<=}?kQFUUeذa 6>-B!DHLL+ԋ`oeʔ) j>StÇk?xtرgee^zS+^L`` 7pCLJM駟ܹsOMMA!B4;t:1Df6YlY !`̙Rl2֭[G6mz!B!BKOkdf/(J1b?뮻0LM^{Hnrnuq1ֈ_K|/%Ŀ[VV+>>>X,YfɄdxK!.E՞ŜNgcCq:\.yo !Bq֑#GPUUnT !ĥYRFˏB!VU],UUꫯF3s !B!BqB j**%ė_K|/8ݻΦ@_@dd$ s:+uQUQId !B!޽{ 88 4MvS\\QA뱵BQ}UNjd !H,!BKF֖-[ DQD/MӸ[T#+55UYBFs϶JQ3gΔYB!B{PTTDfZ^PP@`` kAoXN܂6!I !.تU$ė_K|/%E_QF0rZΗ27!Gzd !B!*vf3Zy~,: 5^SwIa{!.fM7nqqq|G:uk]N9r$7oom !j)g_K|/%ėwy /dXDTnȻ[c(]޸~c L "~Յ:e\KrrrIBBB]v1B!B!^aa!K,AUUZhѤmxF[`2e׳.u ]/nǮM!]kdoP:EQh׮]?ӱcGrjmJJ w}7> w}WfgϞr-O[n!44VmBZ#BK|/%ė_7e˖QTTĘ1cX,,o5y|>nM.x=DRZUo|3NLHz(eUbl>xVۃo&dȶ )vbFfbnb&AUx'qev cʰ6޳kH⩡+-u wNK]{d̦Mp\rUUѣ~~~:^NNoߞ={] >Jaa! :_֭[3w\\.)))3?Mj4B!B@II ˗/m۶dz`TUeر>VcȪ7vdC| ZxuL{vr5>ΙBm>ִ<&OoK`Xf|S%N a3oƗ{3p42с..7n)Q1^\J qds$QqӬ}F UUҥKXP֋k׮]$$$`0ر#wﮰmZZ:t`w֓k[l!$$Dze Fė_K|/%o:۶mc̙|GlܸGҷo_7oMmB8_WʒL&AR{oUŦ%.vdA:]1 leuƿ7gwRp1) я4~u"B UbAAד IDATA$$$p l6[o>f#""'OVå*Ƣ(Jv~rQRRunB!Bڵk9vЄ U&2Lʗ$|Mm=oFbmVrˆ}}[`{T fٟQx6'Ae H˱{=rRY6dBBBοq5?3 tڕ]vU&99m駟| mb`Z-L/M]AK|/%ė_70BÇiݺ5߱]#N嗲/oô59e67#ke{{볋|w0qM|39ʊ_WkA#.gȪOvk׮r (,,X111 ###3g4FB!5rHq24uϝ7跚(7#!&.1E T4i"k^?C+V'x߿ӧOyznB!BѣGS7ZXaYzdxO@f}"/t-ǙxŨEi.xCZ}mgu{=G!~.YBK{G֭_=5ė_;*3q3b;64X"jLF]ƒbbt5U7D  `Y5Q(""*6)?989νwu>zy˓Xa~Nu]L6/QҽBl<==5k֬ B!f8q Qfnn޽{X KP>Ͼ!;";;jjjVVVHOOŋ!V-oDg9>y RJx$f =$&e k9YD02ſ+É,"ji⭅DDDDDDT3 z ="2AAVDcZ?)]Z>>>QUD֘1c8j,<>PH(""""""""fYDToB>>>ahYΝڵk ==3gDIIC2gDEE =:ic'""""""Y;VZ'_pԩj׫W/L4A:/˱h"7xn^F]& >>A'.\ 6__'OƷ~*kkk 77GHHH&=^*b 2>|>Q]I޽&Mvadd> cǎ9̙UVa׮]s[\v aaaزe Ν;@rr2h"@V>>>8s !Hdv… {b6lXZZbѢEpww]bܹ׿Dl"&&bajjZxn^OǏcΜ9׾sNdffK.'akk3g" ?ʕ+#22hժVX[[[)h`}g}g0vEVff&RRR*iPTuv۶m[o ~!O?a֬YX~=\p~~~q?>? {a=z͛~L0_}U?O?vލ;w"77;v9P?Ohժ٣cӦM8x /R:vWu@~~>KKK*{dMd(__Y":Q^^^۷/,,, t|2K/ DGGkԮaկ_?J`DEEAVCTBueddL{888@ ++ [xj ^zRT3gsssi?}au2fcc/T*IDDDDDDԜ 6eggmܹsرξ˗/C"G5:=:uꄭ[i,^K.aÆ hѢJ QXXHKKH$ҙӐ不UsgVP(PRR.??ʪ_SB>>>aS Ν`9rYYY((( _bƌ077yG!<<\{uJBBk|\W(--ѣG%\,ʦ~mڴ ۧ:rH_ޟDDDDDDD-YXv-.\ `ƌ8p͛I&<شiΜ9ӧ7D`` j)SҥK:u*N> aڴiXd KKJᅬ̘1-5.]ZCWR׮]1b,\kԫg,{!..SNѧO?:ս?  >>n-|UgmGֹ6mqqcWWWڵKgoS:th?}>kkk{ꦮ%X|9/_^qm~~~W\YW~xުU*ߟF""""""N+Zhp!WQ5h`}g}g0~EQK`֭((()^x[BYYD`ԩq!aŊ5H5g}g}'"2 """"""""fAYfގXXXX0$"RAAz]cccP(qDDDDDTgggd2DFFcǎΆZFZZӱxbbw3g6 " z,ooFQ]وQxk!՛k4>>ODd8EDDDDDDDD'F>>Ͼ‰,""""""""j8EDNCDDs}>>o}""C!ԬYFoGSxգGbpttpoooX[[W?88prrjaR#6>2 g}g};;;C&!22;vDvv6j54 j5j5ŋC,#,,ֿ5>$.T~Wr m'OJnݺxL0\.7ةiř3g`ggaÆiT*?ARRb1t@$RRRpee4KB>>>aB'''cƌ޽;CT>@DDDDDDDl"m۶@YY 99vvvpttN@i4>n-9RSSѾ}{}`ll D~ը SSS^ iyr4 J%Jξ'LRF>>DDILd055\.GJJm***ɩꘙi,V"I{2IWeeeDJJzaMn^ē*211AaaqII'HGM*RʻlXZZB$io3|Zvv6P5h`}g}g0:%`kk8GСC$&&jҪHǎRj711ANNj޺IdX:wk׮EEEEΝO )) j(**y?Q Sm۶͛7&!J+ ^x\t D"A^`eeߥKܿ?:u_|Q_5]}EQQ:|m>}(L9r$.]HXYYW_L&r͎k4>>ODd߿?ﯷ}ҤIUn322uKg7sZXX`Μ9u65Qnnnzb1 !CTGGG~r%Q3 譅D2F>>DDYDDDDDDDD,p"M5g}g}'"2 """"""""fCCC8jͦ%""Bd}g}g0T95f̘5 {="""""" B"75}g}g}"",""""""""j8ED>>Ͼ‰,""""""""j8ED& >>f=UXXGBR+W &&GEDDDDDDDDAЉHm{} D )))AJJJ|ʕ+:U*\Ç#44׮]FOMMʼn'p!DDD ;;yzg}g} C"K,} v"99GσpYXXX틍B鉴4(x"z tΝU~DDDDDDDH@M$%%?@ii)lmm333( ;v 'OH$JBTT!ѽ{w$&&RDFF"++ R={DN@Vh߾=~TSR ߿|}!=z͛7ѭ[7@.k'D;uꄸ8>ODd"[nҥζH jR`ff}lbbHscX Z]AMӓJ "Reee:)++{222ζ'`kk>}=WP<611AqqqYYޭfdX$ ͑}"ָ{sx[a F>>DDA[ ₻w"33V~Vvp-͛7k211Ѯ 7n@ii)q-t\<|j(..֮EDDDDDDDMGȲ;~w_4Offf8~8~TgggD""**^ VVV8vN8[[[@Cō7paܾ}Æ ކH5NCDDs}>>o}""C!ԬYFoGll,|}}RQ* 5p3FaX!!!~PBebcc*>>wvvL&Cdd$:vljh4jjXYY!==/X,FXXX9sfc""AAAȪkŽ'k4>>ODd_!(,,X,\.ǐ!C5uEV6m ___x{{cĈzXD-3>>_ZED-]""""""2Tfff(--v R5*{`HD$Z/P(qDDDDDT''$$ ==666022Ү\TT|t {'&ޫ\#ۻETW|o6 @DDDDu Xlh[ZZK.x饗Q୅DToMug}g}CF”)S0m4̜96ls!QD5 U{)⭅{+5d!!HF5uU+YD[S]#}g}g}"Nd͟?ׯ_>Ͼ"DVPP4 `زe \]]C t h'.^[[[;wN-11ׯLMMaggWƁ0dNd LTBRa˖-hӦ |rt}ӧ_~ʕ+ɓ' =t"""""""n-|4*zXlpBDGG#s/bxvիٳ'LMMn LII+cو s)Sٳ'mxyya۶mPnQU,,,0w\899A$[nprr^? 1Zjezg}g} C]#2 +W/9y>@^^ޱիWΆ7֭[o;{ruֳ֭[>|۷oGddvo ,[ #޽;:ݻwŋ8|~r8rrss1x`ׯ_G Q&.\VZaȑ!CQQQz0wA^^.^AA*ϟJ1h 禤 >>̓r9&NXZjC,nnnHJJ j;v,݋?ϰ;L& L'>>DDA5*-) IDAT- <)Sۊw=:tk׮ҥKxxx 00CvLXXX\<622J룺;z(J%ab„ Sm6n5wpp@.]pѣGoTx8fx1Ο?wwwD"BPXɲW6z~R)\]]1|p~>}_|EWjQF>>DDMdyxx 99ǏRZF||΄t VVVʯrww+] ...ؽ{7J%s\.G||<pAwݽ{nBYY4 >}\x7nPTT$𨉈ݭغu+ZΝ;;LLLwssCAA }С8w\Y"֭Ö-[;;;̚5 ;v3k,lܸaaa:vHWaa!wzyy@opd>ޖH5g}g}'"2 "OOO͚5kvb̙ jOTOuBhQU!t!!Hb1j;ϯZHDMk4>>ODd8EDDDDDDDDo-f6.ZHDDDԼB"jixk!5{U~jahhQٴDDD9>>*'ƌATc|o6@DDDDDDT*`HDUDV YDDDD"kdQlj,"@DDDhGDD<>>'"2ZظrkahhA/v>>/dQKSխȢfYkd5/"Yl2(׆w}Wq;wk׮ѱ?ƸqRyTDDDDDDDDGcܸq~eggcpqqW֭[^Uv̙3Fի&MTq<(,,lP\\c޼yypQ(Z >>>>}:9^}g}g}"" *7@&O޽;@"`РAB M-lmm\aff $@RARaӦMpttDBBV^Ν;W^v|MqQ=t"""""""&bcD}>&FVe >Cxyy᧟~¬Y~z7o\.޽{i&㏸vq999X~=O`̟?9FRΝ;oD@"`ݺum۶aϞ=j%%%8v0`ٳ#""""""hvY/_^z%A`cc /))uhڵk={6$ Zn \xQ\W\Av0|pD"tU;M6 2 FFFxys2uTbXh9x d2F)[.h`}g}g0vka]Ç:WzEL&W_}-** {ddd.]_ZZZ-YYYhժ6;;;m{B*BTQ}OP*HHHg}<;V?$$gϞŧ~ H$H.D=:uꄭ[xH\B|b;wL&\r:+lV6j\RݻwСCq5DqeJQ>>ahv<=Bxx8J%4 P\\\988o߾عs' ?Fzzޱ @bb"\HNNFddd[&&&055EBBh?޽{}6ʠhp]\pA֞={p|G022BQQ5VȲMpL>o&QVVVs^Xp!&NuU8egg>}&O۷cj͟?_|fΜGy?EEEرcMɓ'>øqo 33D\\fΜ'jJKKz! >>&qkaHH޶={h\ax">C߿ؽ{7N*' >>NdQ ԬYFoGll,,,, {񱱱P(8"""""3d2Η1b1$ޗX,FXXX9sf# " (??nAUhh(ߛ(((H!UQ F>>DDYDDDDDDDD,TF6E """""5xE5 "zzg}g} CȚ?>_8y$-[֠?}4V\Y4hykPȚ>}:^~ `tܹ^2l߾'NĘ1c0}t8pзo_L6!^ѣG#..Q]gk"̚5 7oP(**/:w4 -[3gJIIkaʔ) ksSF>>Ͼ"*F?~XlpBDGGWx\JJ 뇶mݺuC^v+V_ٳs|Ŵipȑ:̞=Xf Э[78::ԩS=+%% 7od2\]]+ĉ>7Ռk4>>ODdYQ(Xr%|}}q̛7|}Wq1|۷oGdd 6?3n݊={ի{LL K_!!!pqq ӑo{%~G@vv6}̞=ǎŋ?(ر ::ݻwǡC{n\xϟ[\\b1v I,>Çq-ot}]sUhݺ5\\\XsQ&.\VZaȑ!CQQQzzxx`ӦM_1i$TTJJ 1o<A.cĉiiiz*ϟD''' >ΝO8^{ Řݫ2011fnnzjF5g}g}'"2 UWiiixLVTT34777!%%۷oᅬ۷ \)0|R 0c}^ʂ)@.kI$(Ju*:R+((k,_\\3Uk'v;;; 8PZ SSSlS() n"]t䄅 b…zkDBP\ĘD"ݫsZ]ޣG,X@oߓO|ǘ1Vʶ?ܼI%+++j5 k ǏǸq j48;;#55څѡCzj&00:u5cg}g}C f͚5z;bcc1s2OOOl۶ ={n2e VZwww֭[cΜ9:c~:֮]#Gh'F t]{\QQƎ~ [FLLL͛Xj( ;ؽ{7nݺZ_BCCm޽;ϟwwƍVs>bcc*/Q>>wvvL&266@b1j;C"ϯ]eii[Pܹ3Md]~۷oG^^,,,п|'zDXnl///a֬Yرc>;vYP\\VZw߭p" '"_|~aŊضm=z### :վn{{{|'믱qFt :WQؼy3$ V{ΧBT:WӧO7nŋѺukɓaC"~k5|0aXZZbz@g}g} C"& %%%X|y///WnU%>>pA TtE5\kQ,"ji"}j!xv{!<<k[ŭ[h4k=EMӓ5g}g}7>Pݭĉؼy3`ii ___ v~333 vʈD"O$"""""""o-f6.ZHDDDԼB"jixk!5{UZAT+|o6-Mg}g}'"j3fQوBBBQ\#W!UY+$$kd5#\#ZEDDDDDDDD'"""g}g}7>P8EDDDDDDDDȢfkd5.EDDDԼp,"jiFVc8p@a5iNdEGGwށL{iiix$&& 9: Ĝ9shj1cãGղ} ٖ<~XQh`}g}g06UTT?Gƾ}c?oojnY8{,r9y]tAqd-qI$(|x7(Ȉ!Itnذaz;hᴴ4>|W)СCbڵ /{{{tϱ~ NNNTlڴ _5~Wĉk?77۶m_cǎA*[nm۶!//ؼy3Zn gggtcԨQ8}4FܹsѵkWnJK.ZFݱm6 ظq#{HLLСC%$$sիWၛ7o"$$>itMjժǧ >}g}g666z`IRD"b/HZ׷ox)DDz+; 0w͛7ch۶vqux{{cȑ=z \_ꫯw(_ׯG~~>>^u7oތva޽HOONJ+жm[gL>ov#Ǐ/7 33vvvòe# ?31as|7x1a"99n`3sL,\w}3fLaQBHO?;wʕ+rJDEEU޽{C.](555kR)r9|||ϫnzz:]ٳgC"uŋu&L9d2ؒ/N>DDA+3gĴipilذ֭UJ`DEEAVCTjTʂ8?W?##tRR_]vUǏg> ӦMX\>_obѮŋ_~g}333,ZVk&NCaҥ9Nd=!H0j(\x۷Jt6l }>>>ôiӰdʯzSbӧU~Xz5JKKpBL8֭D+QFի¾} Rƍ5vޭsaΜ91c6n܈o077HB>>>a.]/t+vڥm֭:s۶m}|[̪oee+VT8ʶ?W^{Xppξ7VxŋcUr?C """"jD5k툍Cht666ƍѱcG,YFǘ1cFRBhQU!t!!Hb1RD5[x[ox?5mЦNBPPVXTu^}g}g}""b&er, DDB*((YDDDD""CQYk,D5f#QS[ uixg}g} ODd(p̙ j"qP=GUg}g}7[ KJQȅR4hrT8Z߅I& /.(SYBիT*!VyQt&6ۢc: p/) _Yrֹ:@Vj999 $lj,j % IDAT~8ո25T&3SѐoBD̄JrD2eh :B)ꊜWQ2:w =zƦŋh*7x:M]r}o)^4{߁A[OL)D"1$'#3# n#`7X<zSYڵgq}5H GkdDii lLRZ] *FSM 5lgr Fߠ2CjN:5q rܺu ze&FnݺA$ҽbΝ;>ϾgTz̫#ܸs.?߃,Yp}XZc2p  ]KkʬX,tQuF՛3>>/Fut"+** ;wDbb"d2tիWqqqJܹC3g999A۷oCR&M˜1cZ'B>>7 O&'2T*j%Zx v;tOHrEœ7oB, ʯ尵ELL `ll\ĕJjPw[#F8wpw1_ ?:ɚZ|Z29Z9 Brq:E%P#fffىkS'DVaa!{=,YFBaa!nܸ;;;0dȐf1/!!!Hdd$6n܈y߇1]۷#33ӦMzDDDDD-'|*5*#`"q H2`ITf(++WYְDtt4##g&ꖸ|QJym| @&Zչ õJ}[;Ȍd(-S"_Q =kG5kSHII^=nֳWe5d8[#+335j`oo#F@*" Ν?LgߏYff•+gѣGXb^u̞=OO?/M#Ghرcشi^{5}|?::(ZmTtɺ<j#G(>>L6DƎk&MtODGG3dJ*EZXt)}ᣏ><_׸~=z4:ӬY38oyصkAAA4o4w\̙CҥYt)&Mbܹ7ҸqcݻÇYbœGxIA-rlkذ!Q^=&L@ժUoHJJb>nB!"wJJF`:C- = ^#&/tJ111R~:)L3,,,2*^QJ777҈xjӕHNNDjݻGjjj y+Jm<]_W(ɑu6AfP_A`0hO;V,]@y`s&3ē0ٌ,Zͷ~Kr裏6lǎjժ[֯_w\pjqrrk׮q0`www6m}]lmm]rwwA@o|||q#{]vxyyVi߾Ck׎2eʠVҥ gΜ!!!www̔)S1c}({=S.U888@dd$.]HN}]<{4HKKKKY FVEѠXWFgG& H1X])M=/R6lH hذaŏY>գaÆ4lؐU*TRKffR.Abb")))TV 爴n^r\{sMV94bGhޢ6oT[s*T̼`/]zpkpppxI+ͤ---ׯ{&$$q1uTj֬cL֭[ѣG1 +?Hܹ-666ʟ=&&JŀҨStix~<\Xh4۸8*VhۗpEۧ}7bŊѾ}{/_3u}ⱽLAzxsB!BGfdi4Z *ST%=T'1wjJLnର')^=\rqPʊB=A*χ~l߫hVoinIRrwQD݊DI*T!uciiYGyp9!,^OY3g6r0i!+F}߿'ORf֭[ǁ6mvvv?#t:Dm^_zGxx<Lllk wYWWW*VH```ǯ^OOOپ};~~~:ŅRJw^:tVKʕ9x=wrrsxVP%_%_%_%_MϠ׃ j z:`*J WTVdr+ؿTK*UӧILLΎt,--IKK#99jժ=Uť8fLQ8a* F9{\h(5B233IHH0*^ewzV_x,-- $&&Nhh(aaaYŧK.7شir.wwwXz5z'F͚5?֭[DGG?oڴ);v ۧ,;~#,,Lv9 V6mb̘13EZ 8׳i&wc̙srJe*ppprmB!B<^o@՚ejf=-ZZ*JYXzyAjTILĽtR VVVOu׽Ѡ^ck OG+הmwEﮒ9@zZZ3WWWܨQmڴ___ڵkGvh߾XȋfdpBn޼Iff&ԫW^|ܹCҥK&NHgٳȪ.O03gmڴڵk0~x,X@^t/^#Gk믿X|rï4mڔQFhҤ ڵSWZ#F0k,033qxyy_*S/t¤I7oS5|4mڔI&?tR233>P3ٙ^z`|mfJKKKKe--4`l2;+ɓ'85 Ĺfff jZ*N"334|||ڑ~YymZdt4UzaYYYҪEKl8wSI!K<}ѣGJϞ=M0q!/^̪Ujxqmٲ:z/5kPJ|dB!_2e0777zXXXVpVٹs}ˏ899?P}Z|]|&beeE>}(U~j(IIIRR}y ?#Ǡg)3,ZJ+ҦES5iBZ}Š#s.^G?uK)^x\xg8CLmAAA/Fp ʔ)# _5j{険GKKKK^ 7w6Lrr _ɀ ={fҭ['kԨQǜ_ԩSPcJxN\"sfLLYvnPES V-':DFF* ޳g_=\4PNJRRVVVԭ[רQ !B!xzvŰ{Jh4X/ur~އULUqov3l!!B!ʳGVǎM0$!&g+88Xzd !B!#KYB!B!ȐBBBB$_%_%_%_%BSBB!B!(G(rGֳ%=B!%xU=Jhh(5mvȑ&B!B!0% _wһwo qnVƍs\_|aa)oRRRL=rUkwN0`7o|'0fbbbXt)SNq{ү_? "=$_%_%_%_%_!^ ZS/]T)t҅ɓ'SB4 3Оu2~xZbL3 ,^okkkS\p1c[oѷo_HMM/ߧe˖p9hݺ5#F 99|ZBRꒄB!B.dַo_>cj֬˗/pBn޼+|d…\~ j֬Ɉ#8s | k֬Az{?δiXf *~{IÆ ܜΞ='6liӦ 6,GJ2lweŜ9sZM0`VVVDGG3n8 ܹsj,YYfŋ%==ryRRRhҤ U*cǎ%..#FV1c...OʢEUP 7ol+++hҤ xxxӮ]; ɓ'4h"W%_%_%_%__|! "MsLf8q"˖->qppSNTZNǰaطo-[Ɔ#GиqcOZlVeݺu9syh0aׯw:tud,,,ڦNJ2eXr%̚5 駟pm֭[ɓ)Vrܮ];w.W_1tPJbb" I&/_ݪU+&L@NXQȅ :thݩPӦM#00[?T Y{|򸻻? !B9w ^r4oޜz(ύ`@_=QBT YGՕf͚P^=8}2&?Q666T\[nRx7عs'7:tӧYk-~~~F,ZsqOy޷o_7oNXX_}׏_Օΐ!CrXի#>>>T*(cooORy&˗ue]R1uT~gF2ۯe˖Z/Οo2Xx1o{6vXsd^x͛7J"""???zABB}aٲe̜9sxw(VRDѰj*BBBرc3g|nܸg2a˜0a?Zzz:XJE~_%fٙ>}p%Ǝkt#GҮ];|}}T:uի_Yvm۶8zżyL 0aժU`аaC ڵkzfJhnhh([lyf_#$$D%_%_%_%/S F }ZΝ;ܹsx{{jcsggg<<<سgc Y6mpAN>Zn͛Ƞ~liKKKKK~>e^BTկ_(vEFF+WyLZZt:e˗9y1~~~_ѲeKm۲fHJJ%JPJ/_NZZ)))X͛cffVnKKKr rWɢ_~lݺ(߿͛7$""'Or=9{,Ν3ٰaCn޼ɞ={hݺ D!B!^~*|+r,[[[L޽{yڵ+/&===u::t0zҿ&L@=ظq#FUV NGڵ~X]tN:3N:1d ƎKRR=z>Xb 2P  w}GϞ=*gQF|嗜:uӥK ]Ncۗ.]0w\KڵiҤ ԩSDŽWR4el|ɗ|ɗ|ɗ|ɗW#_!LXZ[UV)5:[LLVX۷纭SNtzҌz1AҴݻӽ{<޽{IMMÃ~bŊY3v[jܼygrڵk7[n%<< \\\xy|vE}y^Q$BV8ȷ-[gZf B! @͚59vRȺt...888ysٳ';v$-- p9*WgZfڵZ?777\\2j[[[4iB2eHKKc…RzuΟ?O~"))%Kž{kV S\9.^H`` ݻ3dȐ7n}v  !!! 0TV^M۶mV:FC*Uv 6Tޛ={VOQTDFF>U޽ :urDFF(/DFFO?DLL tE)?}e?Kٸq#o`0PR%c~eI,!DGKKKK䛞`VZѣG]6!c(_<xzzr|gרQFJtxzz*^{5߿ORRx{{Vtܽ{W93^^^RF F@jj0J@ݺuBVӬY3bccs}N8A5puuERѨQ#nܸAJJ .\ڵkcffֹՕp.\`ã`>|8AAA4k֌7иqcΞ=˽{ѣGiذ!̟?-Z[oŋINNV?[o1eشikfԩL46mژz_u#K!B!DpttÃ3gP\9n޼I@@c Anj5z>~W4lhVZ9͛ʱ%J0ڵ+cʕXYYѹsg^x:P!B!DTqqq|{ٳg_hٲ!)) ^Ͼ}pqqQ?VZ;vp DDDY8qdfݺuKYz쌥%-SHHOf|'h{*UHKKի8q '&MRӦMiӦh4lْ &вeKϟ,Ϗf ////jT^\]]M=#VVVmۖiӦo>eyb2e̙3hԨ*UzncTݺuٳ̞=ӧ_Ѷm[4iRhܸ1+V ((7nЭ[\gkL23fpQ XճgO_NʼyU9}[nh"ϟxy+^Ͻ{ʊtctZQF₻;UV:tHga*{ibv/L2335^إ ࣏>zر~yzXy:s ǏgͦJZjŪU(]=yz \]]0`sB!EóXW^#?׬YSIcǎynЃ炬ߍ7Vj&N3 帆\r-}'y{UrG^c9^/UÇ7zFy+tiJb֭lݺUy7ߤu֬X> :tǍݤI~wB 1?J> \xq.]Jښ>}<1A Yn &00Шa8{,~+Lf8p fff:f.^Hff&eʔsδmC{5ZWM, -!!Gn*ikkz탋Sh|ɗ|ɗ|ɗ|ɗ|QXw^'--fEСCmȑF.affc;qJY-B!m˖-?*Uf\FF[lQF9H)&Rh44M8vX^xCӧgffFٲeiܸQ3zM=z4111ʶ6mĠAׯ 44TɈ#x뭷ݻ7gΜ1ʌ/cǎth dPP۶mcʔ)k׎ݻw%K֭@-9r$d/ P/111t:ܹ36lPGdffdܹ3gVߺu=zpQ{^ttܙTnݺt:ӧOWޛ~)HHH`ԨQtڕ_?e˖… Zݝ~ѵkW̙lp}=zয়~`0pyx e͛7iѢ[lQذanݢK.]@zŨQ+73LݣA%_%_%_%_EaY&FtؑcҡCSnѣ~D\dFEǎٺu+gܸq9n0^իWٿ?kzZ͝;'&M2:n߾}|\f͚l0a^^^l޼ٳgo>c'M?3gdժU?~\پtR*UĦMh֬ѱDDDТEҰaC222 S^:u* 88WWW/_Nxx8?k׮%""Tekr)-[?իW111^iӦhѢ<Mrr26lִV\ɍ7~:׮]3? 00_q1{l޽KVx7hժ6l`РA/DEEȨQg˖-L>_~;vP|y8<7e˖СC@oN:Eݺu}6 ,[իWcggǏ?oB!B#ʝݻg?+~iH~"{ټy37oVf*=ё8INNV ٲ8Xoߎ7...8;;cBWvnݺ̙3Pn]iԨ"""BUBBBL[Iɗ|ɗ|ɗ|ɗ|/nݺJ#ɓEs ;璿f͚vZ*WeI~~~\OOOJ({}rJ0h &OL6mfA{n:|||d͚5Ot~'''N>Mff&**ϢWzz:/l۶o&Mh"vA۶mu6l[n@V͍`zd}7mDBBBH!B! JvWx)==gRrGNxdffrYlmmM="9s&c…zʖ-ɓ[RT 2#FGժU1bf"** 3337nBJb„ ̘1ի ,P?~< ,W^t:/ȑ#iӦL4K|ڵ@;z聹9FK{=FݻwG/E! A/_K2j(m̞==zjܹYo߾=ߟ6m0|t:ZjJXbԨQ+>}:seܹ+V sԭ[[ҠA xjnnNR^*#B%_%_%_%_(\DDDp޸eaoomk"Ro0zBCCٳ $D޶lRNMIIϏ-[䘽*Zf UT$''? !B)SsssjFVٹs}BAPPPѻkuej*ʔ)#E |ɗ|ɗ|ɗ|ɗW(_!L--bccYh111hZ^u&L`a !B!1di(r {i0&K B!YZ(L-""ZjS? 8P!B!RVB-[߫"11 ҧOٳ'f`0zh&_ЫW36m}]vHLLÅ~^SxsSh|ɗ|ɗ|ɗ|ɗy݃&Os}$&&\'8:u Nyr#y:q;2WR9f^emy:cs=gd1gzkT߿?:u"==SN1ydʖ-K 2Vrr2Çt|xxxGdd$*3L.]ß6nXo.]D25j2B!D!رc?=A)Sիܹ$Z-Zy!vd87UjޤLGyx̬G TʖoG}̙3ܾ}[)B888ЩS'VNcذa۷VZqi-Z_|AŊdɒF?Oei=L8O>&Mpeƍgۇ۷on:&OLb:u*eʔaʕdff2k,,X~;pAAAXXX}v͛ǂ 2e >>>L4$m>rӧYd 'OۛӧO3i$fϞѾ| 4͛㱵UbrݻlٲT*WNzؽ{w}9Bɒ%iѢ*%JбcGvءV$. hz=۷Ã+W؞KR8<`0P\9 a%e IDATyIzFD4jԈHz|ɗ|ɗ|ɗ|E3gLT֖˗/Hjj*bmm d}ooӦ XXXШQ#N>kFŅs]lmm !LW/ 4#KRjիS/+۷/:u"337n0uTRSSŋl޼8T*J+666̅ b0wٙ$Q;wrέ麣gFCff2&qƆGnlٲF/^۷oY*K,cn <͛MyYfi&.\HS2doZZ#7 d&B!Y|'&&'*ݿ$:t(wfΝԩSwyVK||S_////ZXZ#[lxxxЧOXj!!!888еkW*Tܾ[ҡCغu+? WU&MR͛4qo5j]zm?zi+}-"d_)_r.]ԩSv:X._ @۶m?t'OrZj\ 4 &&ݻw뉊bӦM&K0o)=zsΪz* @_t:\]]VK,!%%hEܵP!,ˑ#Gq]hfgg@]YBTTXXXpM իW1 D-`WˋWpu/EݕǃoGS+l\r̼ܵ;6.3 ½b V\JɉMҽ{wZ-WfS~]6}aƌܾ}WWW&MdTbь5 *W̸qX|9ӧOˋr3vX,X@=nݺ 0Z7l0O5nݚWU*cƌaΜ9t'''XlY(QYf3zhRRR}TV2m4)QcƌTw gҤI,ZEQX1h׮]4hq[\97oᅬ3:իWꫯHOǑ-[Rn]>3-[ᅬNx 6 WWW|}}9tݺue˖ < ÿ 1iT%_%_%_%_ Y,-fl޼[qww'00d~Gj)S6mкuk ')) +++|}}63[ZٶmnBL@@@_jmsrSˋuqFcP:v/z-[FZZKQ\xUڵmۚz/`T>N= e˖-/9ɗ|ɗ|ɗ|ɗ_L͍j4MZfΝFB ((+d9rjժaeeō73f  iӦ')d=[)de4!YB!)BփETfEQHH};HK'$_pB!^.NQTrW!B|BPz|ɗ|ɗ|ɗ|eixZ((8MB!E !<{dI!^=666#K!YBWc{d !B!$%%hꡈ";;;<==M=QI!KQ`!!!JKKKKK^N:h4+^.={)f&Wzbҥz8Qiv]ST.&pKH@FDĻڢѴrcݳfugҙFQ v(F. .Fȍ$׮;STJ vZ{6~|AAE];n+&Yf矟i+3^#kܸq,ZI&aXp\ڵ+ĉ9t)t:0&Lp8L(rq>CTUK(EQ8sٿv&MH,AAQ#O?k;?\|gڊ=dD5>s\.׀v; ,H(7n@ >,/1EQ IMMMH<%%x*?|{NG}ɓ'tR6oތ'++ ۍ媫jo}?{EQXt)~?jkk㥗^BUUnVN3wu_| ==?\V}]N'466j*<Ȯ]0Ldff]#YZꫯb////gh.-XBXVYZ(ףjeܹzJ(̙3' hKoىfcܹX,zqMOOg|A~?>gd]]w^ձchjj҃5Gb xf?)\s ;v`Gk.|>`bݫ9tP:tHF;v}ӦM`Μ9ر׋罹ӧmF# MZZz]'OrA϶6f̘A^^`PXB gq/////0v̝;ZMFffG+iiix.GIAAAAdQFVL,X@VVְۺ\.ژ5kրרdqE8q:O=\r%\.V+E?N8K?ש"'s,===OtP ##C#==yF쯫p8̓O>曀697n?0#ؾ}苾苾苾苾!}A3ERdy Kl6gw1e@*)):N=MGGLv2v1hO>˗S\\̻ѣGcο\uU{xf:;;ٶm̜9[np8孷ޒBΙ ////gh42q3mrgܹgJ .ji0,FkpYt)]]]|gڊ0ɮw  ™cv-kz)Y`HnPWWOǣ{6bZ_"K/$%##+Wןٌ,A68}}}}p+px VX)SxGp\h"|M^/&;3 &aXd UUU߿`0Hee%o,{³>ˑ#Gp:z$r.:f3^{-]v9ӟd2q5pUWsN~mgժUdffJee%+Wd˖-F-[kF(b\pX"ߣG /L8ΣV/}EAA+Wf]1nTn6&ugg'/$ r饗b ?M7Dkk+>(_~9v"Eii^lݺU/T\\LCCWNh^D?{o+_@ h/qAAAN)+Vɓ'|yxyhooO?p8؈2#k֭\x\qN8  ƍyWYjSNe8N}^xy>yQWɓtwwCyyw .#GPYY̙3'alʕ+ycY&[ouDFjg)eYLh}}}}- &N\@JJ mx ̜9:BdggS\\̞={-;PG|rF#iii\yv`l6iӦ磟UZZ. UUm ÄB!} _{{;6-ZZZ]QN233c0K@e裏KNF?>ADKp5"D_E_E_E_ǚpjd &r,r>w3gΤ={vZƍɓ'/$33s@Oiiix<|>n8&##_ ϟ`Ŋ,[W_}*~󟓑)S馛ix=pWrWsN~4 w?)vǏOOazxw(+wd|1"> g^HĉGT}  dr-LHgڂ  7@ZZGe#^̜9m۶a2`֬Yl߾}eL0zo￯se֭r-l60 8N(,,b0aXp!O>$ 8z(>:TU`0`0^WWWǔ)S0L2P(gl۶+Wٶm\p]]]B lyWXbB^^g楗^b޽s ⋘1A di Isk4苾苾苾_3W3a5eLb.S3 qE(#řsZ·;HowPIyYIzEU etOl=}*ԯ-/+鹾$CEU Q㡢ΆxǙ5kfłlֿG( [o;j IDATk   ޣPl0S؝9 ՎZpA`lÚ?*f@ Co(BEU w/$ʪ/xbaJظ*ڧ_o*jЃJP55n2>T*?;k< c!xx~?!@ I}v}}}}!G>^W;'|xܝLL&0A Pԉ%u/ce` f3&8>ꏵƼX^v*jX~yTlށЂL(fOE.U5+ u/s SY MPY ٰwi͟|Ia,3l 0H KAAAHԌ\lL0P89ـ#3O;ᡆVy(s(4 jb,sjm|m=/b[lQ[ d 4?xL۷o}}}?*(fP1/ʇcIfOÖ gLiT l<6*;[wwL`qDž"u56]mx]'1,ڒ)֗-6uwl|Z CEU smStDÿ[pϭSذ57rQga,xQUP(ċ/8n!C;w^JKKݡ o󫯾u]w] E_E_E_E_Ǭ~AA%cZc(¶mۆo]aP߃6`4[]GQ'1hl1-/5 L6z Ouci?*MzRҏ$C0Z\ln([oK KXF>AA@bm8&Q,v <t b’"ѢAwS7<+xvKenPv!HL۲'4gx|UQUCE%e%gXeڻw/~wh,iӸ dTAAAO6a4YHa5U{51˜^^L)lN9 ^3/m!kf'qЏ]w[c`tdcCǬ+ǃv0*T OW+YQ9L; '5yS&``ÖZ/)dzu [*1Uzςbl6c6X,1K #eAAA! !mْ Ж~zäȿ^dbƠ(N2֮Ά-stCÿ;$!ӄb.sH wi =;eUc!EEE̘1bΝKII 㢋.b,\E ڟdd   CrGa#`δ`hǢv8 ˶;\R^w?\sgWhY5X@1A(z ~MƘ] c״BP?LPWO=TTPzb<90V<&!it}}}1_ 䔀#*:Az~$RM9"M{qoTd=D9i?@oM cc @ j8H0kcUb]n-8 !<$;z`~іnD xje%tD"M;|V{l>$!QC{{;.K?Fnn.W^yeB}H KAAAHҢ}hO0u|*3T)t[UsKs3FldrR$s(kpt|{Q~̩`hSNqL?K*6z[wiYq܂=p>h&Q2Ǎ}[֖AUCt#~yχ,p |7477Azz:pUUx/+]Ck;ԧ/ڳyZhEtcϱxFQnr(2MP^VNe>֮Ne>},~8 tJ<$3).sEŦ)/+aÖZTE FpCS߉taCT[o3صT{& =,)Ss h0kdҽh\>#ժniw#:w}@az0jo͑VA@(3{\`j=KL&=۪5ZRj(U{w0\XDHC Ýq=c mTVUv4iz8~=]CzHt,@ &9aOoVUU k.5mu<0H K5"D_E_E_E_Ǣ~ _Wc:LYaύ0cL)ԖޘX ?s3x?ֿ}"}Cvn[{+`0ZPT?"0YR0YRs `NtLOY [+u&{րcӒ|HCt`f]잳z;9<$8w6le|(4X{$u= 9$2'G d   Q (fE"32`G@F PνmWKs'9Θ,=k*:{*:sj>e[E1Xz ߋׁ%%mzvSfn3317k4 5dO|8眴=Dt_N A< g,֕]j:Q{tyXjz͞0JH,AfLֈ}}}} f fk*Fwg3~wE{94|ʲ)3?GuC3Y@'j(ծ<]-6m8,3J;f [jEd,*RLMPLI{G8gg|By͢_PQUúٔpƢz^hyBݖ=0HF   j(@ȧ,߲8eH=ŴՀPЏՎQ|:RҼsNgjNg*zp͝P?;;cK֘xK ,)|^76g0pw6T8&+ɪ{\+.{>jw,j)|0ݴzLȊx=y3b2.eipﭓa8cXldxHv>%BҌ////cH~^zlF1 a>5j/h/|l4lf3^FV$PT=4>"m.x Rr/irY9Cȯ_ȜբePQU} TL1c3ca&!`2i=GeMeOsN'^>5ź<16ngk%`eQp*h"Y   BBQ !5pn~NL&LoƆ;q @Ax#Q BEgS JÀ<75[Tpr^s[ *f{*4oܲq=Avjg=Id=@a0|e% O,;";=&acQy>&/֕F1)dd 4cF苾苾苾Xwdxdsbt@ 7蛥jhh "%r|} :~ h ,[Վ{\;q [Q[^dXRҰ92@LO׿/̉򲒸cu'!0OזbgE(l*~UEU >}T=0H KAAAMdm`ҊC釶>ɓ.XCCš̲t=te?}qLӕZ`)ITt`*x%}cx#GǮR,)LĞ9= *~Ğggz t' %-_R۝]HC4#-ǎ!qI军1,Ҋi=]>R=|XpPȿ_~YIZ<},znˏ;Y4#|h:1<&RPQUCOxjpE yXTT}_]+z,*jNS=FYZ(BҌ////cQ{&~ aU--=(8s9';#q㤠 ߑ"=6ⵏw-'QpA`DxaMM[WL1* `Kɠ'hqB'[㎅՞dCq4b?^ÚNEU _7?GS*ONEOd=x]q=$acQQ%w>=mk55N5F AAA"jȤ<DŽ sNh&0!䥾T}ۢ29SA͍#Swʑj '.mmndeiksm9#/u/ceh1#x*̛gp8ݙu7Z[Y~yTl=;)fmg:5v]'+A}S'C2!s̎~, xj~O?eB tw$!ѱ.NȫJgC}gDǢnlޏ{ڥ;M^> 0JH Kyc4l߾}T苾苾苾uQcZk, IDAT[Dž?jdsfa;0[Nіn1tFV@R$*BG R lr:S^éAŌ5=E++nB/V~K)R*6}ާ0Ẋ<+fVTT4yɰ<$2?px0F 7~衇UalR]]=쭘_}3^}v}}}1>cZQ3w^~vY :NLb91yVc߶r)-L9`ЩfX'9?}~/H}Ec?b(׭۾6p3f1yx`Y~J\| wJOLCS9B+~wf[*4: JI?^o)| 'dRLONO}h.̦L<YI{Hf> aFu O|57b u_EtvUEU smStOn+9*N|\;> ??vTU%*t:innKF 3VkD苾苾苾)} BXE {iqf0j=J˅Ղժ늟t UCCsLV{fF:_~: Vgg7 1#/;cXg0R@7vG&lvfN͑llT{XRzW 2T>SҮ3]4OdC_FS@qk#e%]5]`iqk<$2SEU kngI=fMiZ(   Mu`P,(;BA'cjRYbN_xuZ;yッyッ?hmi߃̿?1~[SN+;7Ը;5 m8Ssb+3ȺҹTV寮l@F=X)#}=MA}5b^xmTx3Zh ǣڅn-az7Jg>9iIχM_TlXb*/+?a8c] yl~t͇D2AAA!QFlL FňA @LD0ޝz^//|x+꺑`MY!ѱXw<0*T<77vms<0HF I3&kD苾苾苾14>oW !5@(yC@P(.XAH@ә"YYv=Է}~ @jD ٌ.*{٬=[_Vܠ?Q=@jw? jhw,#|Ægcw@̜ s|fB1k1K+jgD}k4{8]a4,AAA!q3UNIq¨tuZ"{ExQx1"U}.n=Kk ?‰j)H[q)0,{)_M끐u{AXggEi:̇=f -_RƭZ]{nŖJLY!X\'*jWN|>p( Y $X!///?jeG_7u1[lI1_ w┄ b[2ؗ`Ut@I~ '}P(s혭Ӳ sǢ}st,׿bsd=0ZPw5@BF2wϑ>a>&AAA$  {:{\=.0Z:9#CLAΌh=p΢59!D,;bΟ8v.x Ï,RP%wPYnٰwkEӡCa 1)^QU3*"$a8c]d ^!M3Sygoa<3=F d 4cF苾苾苾X?ähų#%Wht-/n⽏sk@̌t=ue?}qLvT\CC3ݴcR?}11F 2"> GoOKKt@ SyEDoFd,&cLqyTT킐9u'!0*jt1N< {,}z=Wa8"TχDjd   CR 䔀#*:Az~$Rixiiғ#{uic [;'6&{{BXzGC=~ȐF2UٰV_.ZfTe>֮ũ0s8`b͇DY $}}}}Q$>O-#}r O%scw̥"֖Lha(Zv. ÑjɌ-4Tm0>@~yxNQH8c:=ըjT?s04)8fwɼ) hY@7\5!f,-&Q2ǍwdOAg7|7qk#kWi'em\ m_8L9 a$c `H{VLz_p< ,-AAAÔ  ߅㵗t33v'dhL?Tg߀QXV,;=293x}mݶ~݂ӷl"KLK0d`s`wdbʇs*_7{QߤYj;Et6j+ǵl}==4wx;=$;P^V†-l|eg峡zizty~CyXlRSjrYj:vge%l80C=D2AHX#BE_E_E_E+ ^W;FսB8c:vkTtŬҴ]]wN3R%꺂@[e[=Ҷ hfH룡YksxE~1 5ꏶR81 nQgbA7Re>]d}OV [ jmngRN>& syӊ!2AUz@1S~|kJE?wGw/?'yon;8Et}R]5琈Ea,AAAahT7ٌ%šذr)m)XmT=[*BoY@ = Z`hEkk{G$ǜAK⡘@ɤ̘P!=4~ߒ;Z7_J?U~F2'y_DBF=_?g;]50EBsr@ I}v}}}}=ݙb4& zom!6P`'̦xV |544&^j`Xgg\;!35N0{N<&W*t޼M|IaLVi:7Fhs;Mz+㡩gO͇M!;pʃ=sac=%JgSQU/0X$3'GYZ(   M#3sY䀠W[tt0oN`A/gͣ|OSsJ%Oۀ8$`4 1C iB|.tx; }/ZtiwL8I6q` ɖ< J5SSԩI*lAZTu7,Η=.pg_{ʑ/*lҗA1qn݉vW}J㸵[ 1ӎѾPTjfa&A/>RԐ9N~E험q4Y:WC1$lt㥼By>9YI?5i 3?XNWy6}9]OV?TTcQ͜Mjf}}}>拮NN%H%b؝&HEQv.}@,#@>Vw22՗fuyQzq~g'7^y_8ϻ0,Caܥz^?[HBKKI"FR.+4-\gZ:=w ۶!3x^c%EdL 5u:ڗs[,hkz>Xb~귦?Xn'xnSz Y%b(|1T7٬Ϋfưul"F   P<Q2 d4(bGu/=35R55_׽UdZ$B ^x݌p>1(lGbƌĉ\'T9'&)c8cϼ*0f@,AfϞ=J苾苾苾,ѷ67אI1PqeyZZؤ/ (YWUh`h mzH|Z1jkxƖ@B NOMT'(d<$~ / ~ϧ/-cONX(f%{nⱧ{Lo0c+4NLнU}iǠ<1e%,+!5[cvca$1XeZ`2ɜMAAA*.rLϢi) Dۉ_Zj_{iJ`2oߑ}Xe7ihLfVUUsOϻ!4Dy(ITY(@ܾZg8N2MҌ:y_')nh{{IcoGKDYp܈`5$~_~,#…淿-ϯwy%KL}yCE_E_E_EաjncPcUNI1t ǏS]BQl`DDMq(}( %9H2>%62~xǓ>\.'.+oI](N(uu>kGQqX,iQI qk[t()'\μ]Ep"\i~8ZZ5 hhD2fmoe}χ-hWmcQ} XYK>Īv %GWm1cXk =,{ӽU\ᢉ9 F2EcӉT?hTUs7500@]]d2LL&"oG۷O2AAA =H |[o'-C2w:8=~W-d4H'3B륎Cn`_?> E+~{a^Ϛ/K, ;iooqlis jҵ]h?cpW6T{\]ڗ/};>q}J3{lR3ǿwb~NhrKXtcpz R_c~ΜMYW]Ǟ=%ҥE_E_E_E_E]׳u~5hښpqxP^=c#iLe YBK- ,\r1LE]EdMKd/Yz&Ra2]_caRZ2ƽ[. +5=Wlweyݑ޺M<2)8sXtcP^Z̟3'gAAA_9;nyԒ7ͭlPVw@>|*]U e_ʌ*?*^V 桧 cΔlךtYݵ]MhuW~}P(By񷾮ּo5C 3zkǏ}jzKzk p7gkSƎA47lh7vgv: ?)3kr'ƼZk6cC~Vl"F   P9T7b({ 7<4JksJݡƦ@Qap$wXC7 ۈĽ%ZF v@ :>0 L+r2{0*Kjd:M-XXݻ2=womk>p[5>{%IMfsUD,ABh}}}}!oc"|YH _>a 6>uSW7:q2WuI}d$JC,^hX5hh=23@@7D W_*J@-=3cl*xj_Eq୫!&:vF7bsQXBus{m~s,m]S+/X/aC;Y pæK~|=(}b'Lg0f##s2'g 1AAAew{h_R}ŽH?ft2{re͵nM^}|ƪQ8(nX@~N IDATPD\M>caN*iѲϫ8k E5/ }!ql$M{r=ld1T3ɀUn,d͔~2ynݢs?{|ouKMQeĐyaQ?Csr6] A={3E_E_E_E_1&س gQTZ:2;10Ksy2  ELk #TrRLCm@i 4/ T̼(iP.Js&ciRŜ"eǢNsKhn׹weh$7= {,mƇm]ttoE5:1T@Esr6] Ac&?sNE_E_E_E_/ڵYs!3&gt9 uT"FJӿOM'N5Zԛ7ia|AnL^rͿ`ӔYD@SP'm,Y/>5ػ. yٱf(nzW#(Jb"ͦ_y_1{JcXޫnwxtlp]ǬCmd,;ؽ E?om౧{8>>3xeF}6跲ST۶f۴X_D9DXQRC%sr   T~ 2Z:E"6NKD,L2͆ lj$CDùeۭZP(B-,?ȁ}\s{mmdﯯͻܽF6Q*m&#xqXxx8\>Lxqzj۫}r1T3@s(7=7۶ۻ̱̱0TWtt z~Uf ԽUD'q1^{O`'~0p^b0!6:Vf2'gj.z}}}}?O"bwP^H'HSL!_eX 5 x\Zh04bh0+p')s7AǶĽ[.#A*ty;Z./߫a~fN&bd P5sF苾苾苾WTv?$ش$4@z4Td@Ur;e_׮Z^kD;=A!8xHm=1ZɬN'hmea`Z:IZ@2 %8J(2QtfDex3C6JߣtYM15ҺD_VlzM,(; h ­-ϔM;ޛgbuom5KM#\PL1AAA)yPLaw@K RNS\&(hqඒ{-4 Sd* 3˵QӍa ݃ptQ;ÉÝ[fdC FF}.&׺HtsŹ6(Z9i5oD~\6ԓ7͢~'2Ra&gP[?š`ec}f3Ǿ}{n2M'pf0:WND,AfNֈ}}}}џ˕#aU?E޺拰5#yqcEr'N}^7K,([0~6|^7uui[*J(e͋Zwl$Mp!opWh~1tQc0赘 MT1'T:ۇWݹ->fR14.&6vS*!uÆv^\ xl-ULԜ AAA$[q}INN%8r&FKo ڮNP5EӰ Sʀ)\Xx}qT5>Zfw*1/% EP($BHe,3`b~dzV87sdcቝBq,>Q20'C; S{/ Y\Od nǐwn99[((»X#BE_E_E_E)$XD,L"%"rl^k㢣V֮Zg{ͺ\_Xrm,lneۋb(e@3^ ca[.-$LfC1%pZ:n rfּߣa'+NbxhօymOݼv;SR Z_J\W0Űs%MQ zN; `99[HF   0%G/ravWןZcv ߽\ն1{$baTW֜0P쐊iDZρ}@ |R‘8>7Lit4ѣ8zO,u^sfΎgd2!Lgiit,,$o!ww#60HF Ug}}}}/ ~(;voa0֛w,G!=5۪׬plxLC7,|'ػ{W54򳣌L!MJgk|啁s2'L:W~vʱ 1T2'gAAA*XZTcT'vo} |$Q&HFIƣ(:j "Πii8|޴lz P*sDuC:Q2㾋9k;cM^ M}W2|/ |A}%c3 O CCf8' a#K5"D_E_E_E_社5+\ak5[H[ n"$<,]gM"6N26S3˦RqIFGx4|%#jhՏ "(yDF]~(Qx.Pp0K%   T4i"|$q};uuY)Вv lô77@*R@zPI f HPajdx/p?jߍ}.r]f%B////sN_u%"y$ Nw ͯj/55/_CFbPjYa9Ή&:1[E,"F   0%tD,IJ&&Ց["qTE|6 H >ҋRC.KǺZA%!?iuz55J/C0YlV+ .gם/di U3gkD苾苾苾%Tr@j.g*9 HM苎>:DBy:GDDlۇjw%Vw@O_{D,|Aa J-3b a#KAAA6_tҩD Ӄ^hsI>Z2]R+ Hi)p%K FZ ug_ɥx𹳅/X?(՘3BgWV^ c!1K^w> T͜!///?;n!zdtd\<1bd   ѷ 4ףڝC{I$&HOO^WGuB*:HI>uMEƦM]df< QYje|xb%di U3'kD苾苾苾Q}.lɉN2>PT'x9 o'-Eɦ2>kɤqyk;ӬG@q n_-qk72/!\CwQ \ 6M{\S Y   BEh$鸾d-(v.iZR%J^]uhnD8=5u1Q܁E9$e44eH zsn`2KJF&s14f_*~Bb}di U3gkD苾苾苾!$ba_z&ܫ?:ho5y?ކ6ˇgPTGT؉; ST؉xx(ĐpGQ~ibfiWtE0#Y   BE,&m ђ15e26ttkKHEh칥tԄ#񼬬\ PcPV}Yp1û$B,Af.׈}}}}џ+ev륖Pv/- PZMK݋C 46EIEqzjߊ|rK 'l<kas+kї u&g/x?-u Vw@ϾBbbd   Yݐ69=~3>T7$$͸A0R`jJ 1Ǝ5S\gz{`t4l^{WڝJߟKŲ.1͜30.7bd P5{칠WRE_E_E_E_?c-yAƽ/h3Amu6C=8XH Y   ”(sFAF<T"F*c{yvN턦8 l6e$K M&&XȼƺШREnEg}Ʀ@ !l#F   Pi~'N,"~vifjwBM-S!O3:L_ A o]3ѱ3 kUC%y]|^7͋O&,Ki]R2'/f 1A={3E_E_E_E_l[_vKr/OZ2< }bREՁ%)f~bWy(` w~ )>\~,6+3Y sûi>LmfnSOxO򩇞_U mƍ￿ٲeK[Ax7cV\Y?+v*///ANgr( }Egț0=T -۽CH%b8< K7!bC`=l2h$kI t?*$02wSSSc|<‰C uM7m,[k%>BidB(Y2#_z/un >`æh[F" ɌJ<"O+r<濣y8{,d4 M rwO輻zH P=sF苾苾苾_V;1?t ->1\~]Cu8ié[?c$(dhp4~7T,!F   05(;YףF?̻-p`6 3$q(ĐXݵ=JU$5.h?̄`)̺Ƣv{d\,Pm? ŽxJj 8xK4qI$F@M̀QG6E!%:k/Ԍc(6;*j.D}}}}}џel*? -"A"ffy>N$&"(^=fn/+.7?@#@#3^0,\][V8sCV_s?0Sİ_}N+h:Zذ9v?m>^|r1[Tݣ}~vZ;4YҶ EUXذ=.h# ֙aL,"Y   Ԥ"bwP^H'HSL!_/ ,F.'T'%%sEŤ%@7ty=z܍ ҆UsAJ/- w!y*E0Űǻ~3/ lR% Wcwōϱ$Ξ"fv96pͽO$HN(#꽭xY#Im6/qz\,Y =n(>qe+Qm*'a>yƆ,jjJ㩱sSf1AAA)QT^PdQ2!аBaF gA9azL&HNHIH S`Xh;~ e/] U& xh]Rnb8a/ΪAl["[ʆ+ܿcy]5'Y 񭻹s7px/ݲg"=|3 P|$E/>oUm%hbx4d}d2l6)6.>6'NaWMPsl F U3'kD苾苾苾1}OMEq01>DZKNM0zYI $%1v6Al#KN44M?,w֑,`XM`@g~$4.? o]W$?vtsϟPk+mt|.Z[ɳ/N+~,_Υ_h;X򈩵||>\LM"jx_ )()vsrY   B(.WvG6P<tl81@LƏo--:wk\<ĈaM޺%>yCK󎍤 2DCC8KC!a;Muc֮ZŴ|̆u.b8zQn腟b̰ IDATH'YCzWyNF#qClW6;ǹ?+8faW},hi~Ql^Arzrhl?&Alz(, F U3kD苾苾苾5֗-}U:ș-&hvb;Aq`STzFʶ5:ZG ڊ}GW=X-9'-Uٿ33zonо(p84ʱh4ӿ0w0`X YVjbG?xTᅴ?~ӏ_}8ea2_wr c42 j窣in"z>:vh,jSAq٪H;.g{wѲrl 9\sr6#KAAAt:$Ir/Kp軪;Eo=Eڵ6z M6/W_~K??wr~r'bp2(60x6}%}Nz#v3|a3oas#g", 6$ZZ7ҩPX_]~N>u kW/:B!/z4tZZ?iŐqjRF}|4MϾ22  J!AQUG -A4\[լmjb}}}9o,]Z`vo}'dfչH3Zcc_;)6?yEjM-7o7̻I7. [3X릌e2:U( rޭ;/2tƜ\G2hbYPdld<=2@(D:wv2S|MhϪĹךFHc}Z4t72 Ѵ46McGy^w fbY   Bسo)Q_HVH O3KlK˺uwc.,n~y7Zٵk==N{wѫ۵k?|ɁSCC*v70Roϼ~"o͋g?CwM]]r1>)2ghh225\ӝW$b$c8=51^3±(!з-# ?}ά#3}bcB~ɵ_]Q 68oUjoF™J"k7~LF+,!F U3kD苾苾苾=}23c"TI"v7' kWYM+۶ݗ0֭ìMq/edgSF۶E cxl-\ u2Ŭ{zɯt)(g.gPgbYw+j4Q)kK|xͺ*Pk*}sT?"gpN*zQwݎv6-?lfS%cQ*'w 8/ovu ' bxnS7dWxӆ)c9`_gbY.h^Ʊ7^DL#cE|xQ |pgf1AAAQhoсW:,+z&UIR`Ooqe0&RddkuvvJݷ-Xw.@7:;T6mTp}.G鞑)6YQx}kuCbڊ EL@gY [Y=y>q4 fTV67rѼ _jy`Qnrg29!SHBqT6%b; ##p4ZܼLqyt Z?-2Ѯ%qNo.BV20o 5LƃGZ"lRXɜ<߈%B////sD?ΐX֤$C&O*Sӓ`Qadճry$W[rB㜑dTM6#ܺm[i(ήgaPhez{ŦFNqc"ÀU9Ǻ3`$:A,tc]sXsv:sJ^cWFNֶ!Yf|4hNf4'Cӯ`,е?z"t-G8دYaݔjkqI<7qzOl`ò+d_m%.޿l"F   05n.{tL,+]^zͣ( UUmmI$faݮ/pq2H$ksq,Y#ǹpa20Vl6XtE 6eeV<"$DDlۇjw] Vw@Ͼ&V #rO:1.^&8H~hbM[8г/{ 4=C&3 }!Gh_?oWY\g^(ƛ6ϙT2tb5|ƹ:)>ddoQ: kO+~xK?a_\~~{W\?g>399(DUw{O}}}}w^aw/Z:I2!6>D21gݻ^ϒ*UȽ4wbKiE04UY@Ǎ7~5kVQ__C]] uuVnH8{kgC寿+u7^u7^+Ocmk*D2AAA踅Ə !GQ;é_c@JN%sX&rQS> (6}}}r>|#G:M{{GHqp~:;;W~@{{;`˶}}Qn,Xѣx6l6G8xpvN'SNc4%n ޽ڲ.>^@ήe]M1U'(d<$~ `p$2B~ScSSSuIb&1\{eYK*Dg5k?\ErC$cz;zݬxM0KBAAAb:'^/g"|hhD7H"rD,_:Ka=)R?%KVph?Neٔ((9҇꿏cٲX,k +zcyF(1j7Y $pv ̬(c5&Z38W`2\y[mUstd44H" }yLg,1?'od1bd   S>{D,̑3(o ϡ2ZD<ƛz/a8fVV# &Ae5&ܚau.cʚhV܁NO[-ЭƎ5Sj NaP(Rz*ɜ6v(8\>ΊCtab fݮl!5A9[#BE_E_E_E,Si-I/{3 IR>|2̤fV) jRXSjb0 ,#ޢ1t~!Md4 vh*e>ӜRjaY as"ҹBKB*Sn, 1;9M-/6ޯ}f AAA_9;[MKrHPV#j^MebO%yq9UB5 {1kCsٽ(NO nn@d͇ɲ Yݵ_rEםg4'm*o!G%q$baApcnᚏ\cv{d1&bd P5sF苾苾苾\?|* s>+BCC]|WNl|+@& (;2IȔ`.ӭDlf1AAA8K-P$5ɗ&7R1 c^f]^WܯC2FQw-,eL+a)㤳kgCoo]] c;gZmaN7wn`aj?`9޿z"7~P%Ź vSXTC?ibh_sl!5A_;P>1NGy%uɪϚƺK ccR0QuLȶo1"/=T :ެ0l` S6ʺ4e:Zc xs!7nzי={6mmmhhiq1nZndd 0|N/////6Ճ/:Z:qp_7s&fdc.F}ee+| tl]ȍd p7 @~èĐh=qȺFV:L,n>C)^tG ড~ŋj1Lob8uym3lY˔pXo <AAArc9ƟP8nX;4+\mK+ɼpܞ3P)\V`-21}h^BKDB=(J+5<#홴 (`->8+;ͬ/gX~bTLCwi~.J. fg}e{w)>랶 ////?(Т쌆CmxK/Ǘ*$j>O|}0Xy<9^ x%sj1Jp_76uޮw JßLv L0TոN  VRY6>O~)"/ycu˗SQQ|an@3 1Y~jJ/nZ5푔k~0Zc(N}n/ovr̪VY7~ yTQsE4 1{C\b0aʲu=«N1*pW/ -֮C)N0%   d6Z:q\(ۏCn'/q 2Mgdo&ch7T-o4bPChޝ<1Wi:oh4csì2f[ٯ1b'Zcx ~ ueff߻se}=4[7YY`-t1\.ZY0Vk̾XvrD,A)#BE_E_E_EWTAýF9*ՃoD1B$&I$E$f>`Ơ:3kVavhaf CgҎuu%g7?ژhm-1tw"DP~cB=(h.3{zz}vZepwotq.w1fMfv>M#>'SgFx>`oXH^JJ&3N&TUaܹƐn)[YWۖLNC6v6\},fm-c[L~X&g?5kV(;4f^y3>Zw 4xUڥo1|+몦zx_RaF|?6spi, (Qe1A6d}}}SU_PT1P@ 7}] V?LFNY>x[gn$5R12ZQ6)@L<ן0D>`iZꧭp8BWWwa̟fpX+8fںgf3Dl\~1AAAZ([ VZ,B,f>fL WT AK^P<);Ԭv=kPOYY xX봎BG<EiwYCMz'QP[st؍d4W%s sH硺:A1-+qw(1QSq}eekYƺ'9`: gƝ5kehPSSˣ~FYŢQB;RKżp%[$2L~ $̭-Nds%E 0bfiZٳfitٳj$55J M@ߖb4kq&7oEA˰D&ip= an-Į9>4{AAAxUG_'P +`e `fԳfM sI3l ӓ3X*+TWW[fR152C(PU,p81T-q{\Mڿ2M4Άcf_Z^^mB{ٿ kw6ٷV̫|jwMqmϾM|n6c̹~.~S[;^W0Z4[rk1~h_zXO떵nYk5l?yuW/L1jWzI떵,i^QM_VlXgr,A)#BE_E_E_E/ZxC(]U t4@qy1iT,8H~KHOƞql44[Y[ɻd  >}}[@BϘkjC!>,N& zԌ7ޠ8?3{XF.9w o~WmeSQ.hgy4V5M W,IUUgef$Zh7w>xZ/?.Q[ 5իl*0~Y̼Q,3|V ^uAAAr,w+dbar[ld|hNYLD&ȄgV !M~HL#z作 l1$7 6vM{TfkP[[̙S빯E4w%||Î,+3*',lm-!n"2^޶͖Qн28:W'YxV/Lw~E._j{Ƒeef_%IJ]e-i:50%°ٺu苾苾苾苾 h* "h:PVMȻvcdc7rxϥˤhnn0)LtDZ!uuuCdt 'φXhP4574Գ~}-`de_qdoo[_@]]]J,>h5P[eR`\.{6ԔygN1v%Ml{fy~mʗnO,UL^ { E;(^tmo^2v.H/q<_4{ z=466d4c8ʶ3a:v1fHƐn֯uo:x!ڋ'` Pt 3t$\fwd7nqc†T_@0&Ѽg͚L/x<Ln&<ʞ%QeYKx\wӠ7&# ~\Pc⥃%ݺlr~0 +V:i+ 1I#3ތ>tdj Vƕx6Ÿ\XkL8gJDn)4s7M-0J ߶-"E8k⿵z[UYTrCU2hfe>7ݹV\('D6WY}]xn/Kٵp81+o4ͬ`> >>_­|%mx6K׬t^\yXmWek[g3LΚkWmec%gl85]O立EKXM\to>Ɔ !ihfVs;ޝֵY { ,⎕`ƔwyrWR3y[f֌pU |T苕u-yLzSz?sYyKAAA0-~FX4L4܇_jF}}gu>`IgX7PZ8ň2ϙl \KF39ES`i|1`ft6WsPu)QBm\l̴z_sˮp͂S*&pS.#7_'_`]ᅷ-jŒaJGz.1ֵqo>]J$pŔHم_PV&azl8Cbe|?_B,A)#BE_E_E_ETԯXIM (nT׸hØ3sz(9d6osKcf5%g21 Dee~gr{@G u0par 5Fc@0aK̴0QZ *V喉懙2auZ溫,+~0V_y7KxO}2pBGbD*ӧzO3N*V+sA*7YYtMΧv+Vr+-fo6nc3߼ce6LW\nôYa#KAAAȍƗ@WXqJ# G9DXe:wL]7[}***9*~_elni$g"3k{G 7 <(^"Ԫ/԰b4b1~***9kƟ9eZef`ֵV,H)/4+oG?ypEQh 3(n`mu\wr|Z掆gp¤s() pbb(n7Yqvu4yiNif=6{eZ@Jyilv^EyS4~zʎCa Jhߗs 0a *+\~80 b(_]Ukq jJDsΥs*jpP&i3t FQ#4+('LpR_GthGQU|pY1L`)D5sůA>Uy\P7YYtT_;gD,A)#BE_E_E_Enkd9t(e/@p.sUXس:ҙXPb0̓h2n/s>Ck-`'w'~ 9X"F   Qi1Hsg:q a&FM.޽{%Y4v{a:3k8=Ő[n}}}}%S2sZE@K4Lg %Ǎ*YȀDO2@YIkLĐi]y(zoAa،`7c0_&0!] 8x )K//ş^BB~zeJ6ms~׮]bD  @z/χ(R-[ | eƍQ:gϦ24MC48vzG[N2AAA7opFAECQ̀h/_Muuԭj<^V6YBݴdy)9SO}{Tw6PcBL>YfC߿7x{L._D,"PAϥ[zP}a icĉa4K?Cww;G*ԾCD*GY 6ڙ-pO׏vM*.@ (z1ic*~0\.hllV b?ee`{XgYJbD!N_qp@w5eG8&??? (,,i%°(3苾苾苾Gsf϶_l}݄#1q(TC k*+ Es>Y|u,Ufv9ixuґ7~-k+cPH?}]'uy0 Áij˲eˬcE1=XvúOQh@ @EЎcPRRɓ'b[h4Jww7ӦMiAAAxqQ>El xRC2}9a7F}Ar*#̥p81dYRe l"n($(<fs?[aZrߞV:Ξ:gO3#4Qͅ_@_QytGAJPV굮rNCQN`TVVr饗4Y SG苾苾苾)R_BEQ!׍Y_N:̙33&|>oˁT&9*Lfi`Kre170iԮtF[$C^D㤮}JeW!az-,{61=Xvʞash4Gz8bhGC^A s~DwO| 9`RY   Bvbah| x &y0> Mj4(..)L= }'V2{i4b6~r 'DCa4 `„(~՜3L38}No@\2"jU8?1VBbaf=4%°9e{D苾苾苾B=-w҉B@~< %Dwx=yYt2_UJv%#q]]]F:-!o4pab@wl7ZX'k?8.6<Ϻ{n{nw_;fKYܚ(eֽ/<Y浸5 ]Ro*D2AAA(@{AQqi_ JPAAUo`g6e =$혟8ʴ{aF+({&X0X D e`3dk(1d_ \c!]if icݞye,  G?yy0ͩVSgYcW,d.Q0cPo.k}uҘKر}bG T!///Z A 5Z,B$CáCa<2SQYוI.LъαSb.O-BW8Ms!fv}ٳ̸5k6466e]td:L+$L,7Z8"υݸ:-+3+|ˍWÍn\(:k,2m9a,,AAA!+X봎BG9cN#v=tiUwK6/5M7e>N|o[e;R15}_(rÊ䲽t:L5)5<$/i},ٳhjK^?&de`ݸPaQwFh'd\t1/q]T, +3;$k1ߣLws%Uaefgbb @=zhB(|eC,Aͩ#BE_E_E_ETl-e0\tInN=;@¼ڱ}76ar A=&eeex<^/z( 4?#xbd   Y)ZxC(]a{?,:H49$vÞc& #*Y+kLC<>1 `$ԃUm-jiTq뺎ii"9S-4Z`2ZZNRTg{>(`ïBq9eMhFXQZdfi^;$2ҕN!`UyeZfJWjUq+s #4dYizKzd 0lN////YZT<'*6v>HUٲ.h):읜51VziDa4vmO1Sc7:=YJ gD ?]φ'j=un9]-tk;-S4nJ6>3#ꮿ$c,Ơ? ;)eS_[y3p0cA0HF   g/xPʪ>̙m9^~NC/ͼd']h/XYd3’td:zN($4q處Z$`B"ĞV UuˍW&ocPn6(yvl7k-*sر}w1A6b}}}SO_]21P=^¡ yfϡ444[FIFXzo\lt6)Og3T4kMv}JY_=Ʀ'(>xyx }9=bPؚoIٙ SKy~]]<Ɩ}Y0XܹnYFV?yœS3rYpfi!ۭL,e1t] 2K 42LN+;bB{0STN㈑%   dG{pfMzl+FFfXjR~̦vcvc{ׯwfv|ZaHTt6V2l|jeNQƧ6[ev>myHAO1Lo72g#/c Lrsatuu9O0K/4qalݺ#_I}}}}}"1X_'sgf$zDhjLi:mƍ+Dx'v54 *1IpH1$c7МF~#;,^s埿0P̝R %a:C5nG,ɦߚ5<44;>UUk5kBQ\:\dI5 8t0dg?Ȍ34 Mә8ѸvPU2wGA?i06|Zo S"] ye2 +{yȾ$Zw Ӽ2`̼2qgo#p-= Ɛ+K.W^!1 |sbd   ى/(P;v,n>)<~cp/ >y||xܶ_c/=q͚K9c@q\J'Z11$gev). UUr>ٳin>̡C'/y^) nw>sǓn>ι:;(, 0{lv{p1~|1]];طo?g"9p`+W~#GZ)..zc%gJ3L;qޭ2mZw^N MQQXpbGkV`IJ Ww14/c–|W{qYdAbr ;ڥK̫d;ؾkƬ,ׯ[9Ab ^z%\.\s͠#Kasj}}}}? [Mߣ>RM+g&SpoœK:uPNCwέjfrde i9lۡ0!] &g,5pM.:VܬR_4ηl;0صp:1AAAܨXIM (nTa@ԈFE E` |?Z_yXL2ϙxY( % _f| Rס0~/˖-34f߁zbH JqA***c.祢 1 LLV \dbbŞwߢ~ј‹/p<,۱[{f˹k0(@c KحЎ;FOwL, y1CAllݺUE_E_E_E_OƗ@Wnt+*_PGUXh mǝG8Ou:(X4 W>.1$ǀQb齽(ۈTUUQU5fTUay̝;{ػ [e޼*>vٿnۍcø*ucֱisUmBUU͛iͳ3bKcc\" p?=M$CpTu6=7H{K@/ʸz|ۭfƕYⲅe淋+ 桹}꒜b7nwWU+{3(A9J ;՗ga,AAA!gb,Jw5z@Oń$FB5MGxq3QǐZcvke* yh{۔\v۲vpڗ|4D1J29ïpJcMW*@,Aͩ#BE_E_E_ETbbcV7P`śikX40|@PDIRPo^EayS4~zJ֒Đ0K jx]]]ZS4ҙL9[d(^/>T3}B7nŗ|[UUuvƍX$:ҁۭ0$EUu g*`Lb@ xz({\f/_]6Į]sJlڴ|]ňAA(++:^>K( [lAƒtG[N2A>[nHWRE_E_E_E_G^ 4{AAAA>Hi PAX 0t>L__Ǐ7|=/    ÇgѢEu(+ʕ+=7)SF,Aƍ)//4lݺ`>苾苾苾 yg>:1! { EQ yW2^# 8Ji͛?Dmzj5[}}}}ѷKi [ncygG̰slڴ . ܺuAAx!F r*Y#2ghdIi   0lB~{:FCI~+DRB U뮜uzzzF^wi>~pxkfP ise|y||^ƷG}L{[)7 j?{&A5tt\p (Rw-Q0"yiژ#F )^E_E_E_E_?:Yz唌K"ZZBEhNw2&x9"r։D",^h4i/ʹw| c1"M#aܹϸAnL‘0mm0ECM< ޹?OKC8~{>Zǭ_Oy僯.Wşo>.?=Y   ° C+.DcQ45O@}R~X:Zi`iF4L-#0^z):,=Db#(QMCuYj?zAY)s'墯'>s%U;(,(whhj⟟{'N_o),̧ϲ8܅y寬o93KKu:<MNqADcQ;>q|N؉?qq|f7x:Sp+^>sQ%jQ9tT ;Cu4M}> 8}ܹso xGپ};|rnVˬ}Y~=Gay̝;7eGyMӸYh`4Wz>c%°ٺu苾苾苾苾B0(itob:>aK](<u,777g:;;ffٯwu\q#|2)swvM?Nl JqᢻkH%sێ祤ɓP54w!K/]BŜr潇x jl%43iIenŌyDg_1clt]a錟9kZLaF\qy׸;6mZʹgOO s}qM7\q]ԬzիWn:6l@,'o$Y   Љ4TNvMïN\j)Zq.\_4t::: (82Ee+-c̪߽bYvPL;~\~շFqݻg]|.~QQ>_WTVE8'x GtDx׿bqt{;oh`y|sjJtuI1]YT}6h[9rޝ7UMӝ [Yʦ NDg`030^~*"  ^0 eB/؝tMGIHtҤ!9= =H,RCE|7$ .. ^ǰYy^PPV\ڵk<:]SYfaƍ#Glߏ-[رc3fC;刏GLL z=`ǎ:t(+P¥K\nڱYD@h`|g|g|g|gX?|Z,%x,w 7.&d uqo꒒\z8vf3*++1p@ԠadVSWB$$$ %%^hDll,RSS81m 99'1eff"..w`0 ewq I^κ>??)FBBqeDGG ;wDRR͛^zH.OYn1fD@DDFrZvZ@w +(Bd PhB^CT`SPZ$6Ķ:p799vCk2˛YfYHkkQ^QR^R,~)0KRcw,#N**o 22ڐ<ȃxur={ރs}z5ռ [a25MHf-a}?p}X+cqk̀4ZF |/|Ƈ<`o>kf444 lGۓ$sob5Rl˂ IF# :3\}}S[so3>3>3>$5}drHH\fKg_!.'̒]+J[aPwމ0GPնbܔiLDt۳'7GjY-Hd5%CN<ӧ`p v't!!5j)e;1qxL4!w4N?ߣP(-%M?23LDqa# 2Hd _4!C\\~g[=,\TzTVVf$%%$<V4|2(PTh4uاNmДCNNN :tg}oM6ٞW# ˬ^K4 AR"nD>A "zݻw;seYvC{ӛd+m%{vmU"KTxǏcذaNۋ:<***PWWjG薠 _~a}/ڿO8CI@g$@ ެ$4%,MK f?[b޽۷/"""\&Ǡ߀A7WSªUxe0<9OyDsnXQИ)wR2XLgV1ۍs0~8=wv3{lz< &F3iZ,Yo,Y+-:6LXv-^~eM '|Ghhm/tDVv4ʺr^0JOO-#,, zo,(޽{1}t}3>3>3>^B2YT[I6:J>z2E}ªyZ#Fm1cɬ|Lůvs0)8w|t#F`„Q_a0n8cja04!Cߺh=A!8n./Ŀ韛&e'N؞we?2\ b….;Ι3g}zrMJGXqqqn슎=wFۼy3 ⓶T*bĈN-[,tVgƶmlwAkA,g\$V'.Oh4qǛoE{ӅB~b]$nb]+ 4? Ѿ-QՈiԵFV8]egΜi+jn|z|=*0sā#"=LDDDDDDX#=X#(X#e˖sK`"vg|g|g|g|F,""""""""X#YDDDDYD]Fu;jԨ@R^HKKT!??o׮]m㇅9(:=AKУGb+g:Ç9s|駘4iRpg|g|g|gn?((e Apz@uuuS ϟ?⪪0vX@wSPT8tt:]B;w2bDFFBP+DkdVP(T*P(lkdY[\wn5ճgOH :u,;Dֈ#-[ r_7zl L 0׮]Cii)z=zdu 00͐$ KLRf{^udgr7||XX`0PXXu`|g|g|g|g(Z|8O$",dAɌ[t{yObVERRR{DDDDDDDf_wy y?mӆOe8XdOXYDDDDտL&塨rDK^0n8¶jdޟѥh48q٬uJ—_~Yԡ|R#@^,b@DeuP`X Qx1JJJP\\ b ܺu CBBI,""""":  ###1f̘ȷ9Qw1}0mtosCR1yT?wO?de܁|Y]B$$$ %%HMMErr2RRRl{k׮y{H"r^#ğ0ajFi-",Sc#*8~QnrsEf (++[2N bFiyI,"""""ꪦO;v@;~;`ԩHMMk\ȺY{-9PJ)ǔqCq?]B]9p=IE~gl6ۖ5V4q*${X#(5JRl?|]#kʕ.-ZZck . %%a4ZG7njdm۶ {qQ_‚ |Ҷ?T*kdQIa{7"",:ذ(HHHYݫ0EDDDDD䞧z|ҥx'~,էOƋ/r^ydffBT?=$!8HА _7ݡ"PgT-[o((('ĉؾ};^~e>}'OΝ;qصko,_V?hkgŊtɓؼy3>Y+Wg}fc˱l2|uja{_UVaժUP*Xpuhh(0Eϝya4}.QGzDS2f_$JJJlϙ""""""`ᅬxą 駟FPP ;;?r9pyO=򦏭IIIȀVѣGũwϟٳCΟ?c޽4hFEZϗ5`ƍ sY[nťKP(0qD=waϞ=\.DŽ 0n8~{)))9s&BCCooDQ… QSS>eeeX,ׯ̙Ӂg3>OdM' e{ף ѣXDn4i3>3>3>3>0FRBBRte}9.\@hhW>}˗/cJ(bƌMII=ݻ7>FDDwRDâpY$&&"!!1119~zbɒ%x7ѣGcƍ_x`0.]? ,@LL v܉ 6`?>?gEXXǰa0vX466:X"L|ʌx_7ۡjjjp$"""".#,, FnܸrX¶uuuQQQNEDD8$$IÇq%X,VX߼(M:ǎöm۠R0ex"͛Q!CԩSӧq!L<co0bƏ^x555P(NqbbbpI"%%/uP( 5>Q 1ED^S(.rziٝwމ;aYXX~:,/opV3uTL:p/6_n~ܹؾ?fIDAT};^|E444 <<f͂Ng}"rDEE HOOǬYeC.cٳ'si&d2,\'Nw ̙3vg?0ED^S(Nñw4ʺr^o2m@Cpp0 ķDDD]5eM%"w^:c"gʕN˞x Ldff^;gk.##.׍=G~G#w@c"F555HOOg"YMOOرc[ܧ=zF]dBII 4 &k2iƍs}"zVTT(-$$z˜1c""ۚjQ_2Ġ0 +S N$I~\.$IR,"ZK#Z۾y.ԈngFd#tX۷F;www68wZmBYD5Wn~DDDDk* D\v }ݝtjHJJ tW`"{n۷o{BDDDuyzMu+111] v"" 80] """""nzK`"N-$"""""nF}}=_讐EFF"88qqqnWXXzg]NJwxLdQ?CVc!!?X,׿YFVV{_{Ń>u;sZ\\XuLdQRWWlHI#Q?m1uT?*pnzN,""""""Vz=d2'o$A.~\N }ȵrWc"nP~΅?)YDDDDDDpZaş-:}\CK񋋋ի00`~~5kzjd2@^^m _l6c5k rssqEa׮]1b~8ĕ3gT*Ν; CҥK.ץc̘1N=SPPV\ڵk<:0k,lܸ9998rӑ e;v̩刏GLL z=`ǎ:t(=wk\ SO0EDDDDDDNkw-tFV{gº:,_O<233qIXoZ}]0uTFo#GFq]w>#GB&aΝ8<,YL7|~)~_?!C^RtX\xžҘ1cPQQaKXEDD`mswdff`0 ewq I^κ>??))|#::UUUعs'rrr0o<$''cѢEN#<\zB[$""""""N:"×mٷi:hu$aȐ!t8{SS ?T*AVѫW/b ;;_~%$I`1zhHCFRĸqwEojT*<΍/ӦMZ% j5Mf|`0T*mYPP$Ih`pXwjkܹؼy3-[~ׯnj3i&XQQQ}zN[YDDDDDDxR%i}X ׯ .mk4QUU/_ƾ}PYY iavv6$I¨Q駟x"bbbIalֶܸ(~FGGC6Ӻ_Ml[CQF:JFZ}jkkVJJ ~mMSL򐓓={@!##Y[;OL-n%j,X[nG}łDBpjh4uƪUz„ ЫW/F 8jڶ$Ix7QUU`L2l;[GixG&LfjXd z-,Y xWl3LXv-^~eMw|'1|ږBWHd :5YDDDDDD6ГZcM(otR۲,deecmٳ'֮]rI&aҤI-!I0rHvAԩS1uT5iiiXt_}zǝr,\Сcj_.cÆ ˦L)S׶= H,+&im5:㨣8pAAAӧO7:cr-P|9NȩDDDDDD4"E=j8}46n܈̝;@/tmMge?S edX|uw<[YkdO'B""""""k"ȲיY-M'B""""""t:L& #R N6QQQ~Q`bJz{ZNȩDDDDDDԭiZ\pzR twȏL&~Gh ơC0vX?,0|o=^tBN-$"""""n-)) W^ř3gPUUt:hZ$%%Mll,}vwujn۞鄜ZHDDDDDD^k "kR&---=g:!Qg:aɓEDDDDDDDD?vJk%ZIENDB`tiled-1.0.3/docs/manual/images/introduction/tiled-new-map.png000066400000000000000000000565201315121121300241560ustar00rootroot00000000000000PNG  IHDRd^esBIT|d IDATxw|TU$$B &@P Pz@qq誼PP jŶ@] ) @K EI0 {eH)|?=gf}>īGȩzM2I\J܆.,~X4/ګF,mJYwq)3"RIcB&E2_ԀJ%䢢L&SYbge E(5efB_*; gALuZLy.~F׶?}}]{2W >w('pwnmP_ % (wˌ@V:YWq݇<!OycW_؝/{/_u Y |򯙋8qGI< h\N j&.iWJ'NGE ye|l e#:;>gO*ƜəMq;<jO_O~H (ۆ(2K젌.f5^CfhiwѧPLԢ_ޒ|quTP0wOo_zj iJ"}_C|s4# hGjW\voNtcgI7R!ÿѧG?Z553vq8, ~>{%Ԑ"[SJ^3s?{ImN炳rҘAzbi{Znl{oۓ9I ϔ)SJ􊫓.N6, cB+EqܰJt͜Q"X1Ίeh1|- pV>r=zƉtb'QSԷ&aϤHOq};LTލM%(I\qWeD֞6$!J7ss9Uo71k$FZ 1dFE5qqj~ ~^4t&MfbnxQ5d\0_M%#ҷPIHttw_3;̑24}L2(4&Il;LQ*?>d "c7ENha6M] 2 n"1oV⤛L.̎&r 8H6f|rUT+!!97Y4\#^志2u{{8e 6n$nBb_ :6\3"Nr&nq*O6pc׫+O;GO:jM%w:{d?U:^?_ݱB'|&wI ; dESژq$e֊(WnԜq4I h I8N&A~sKr>ᅩ9@ڑ\'0|` ]xhɅrg:OpW/GsBG})3$bH(WpOTW7} t{1bȑfi'^pknɘpwwzN(*#fJUw JJ]pH%mN;ML]rWBQ*Y!yvvvrRO!l$d!FHBB! Y!l/\q!D!=d!FHBB! Y!l$d!FHBB! Y!l$d!FHBB! Y!l$d!FHBB! Y!lD'|œ9s/ѣ̙3-[upBјTILLL뮂BȮٓ{2n8HJJ"==Ν;["&&%Bzr`` ")) 볳hZطo_2'33ȷ~'wB4(wC,(%{PPV_Fǭ,_TZhO>BЄAQ9>>̱c(**BP0i$ٶmNŋl߾cңG9|0yyyt:ƏOΝK-ߺuk/^̒%KP*deei&._Bk׮ФI 1DDD0d[o])-![1c0j(˲޽{R|8111ҬY3fΜ ~-{%77ON}|r:tAJ,grff&)))ѣ:???F#;wn}ȧLB˖-Kܱ5??e˖1i$_ϙ?eXԩS<Өj<7| /@HHq}Yٮ];z^lܸ^z?(j*Zh 0[72m4KQ(t wwykٝiii$&&ҧOFbcc- kٲe<䓴mNǴiXf oep=w\ٲe y7Xt)Zwh4|rVX̙3-;t /@vv6վ+>55,/^l棏>b֭L>a0`޽+VXumРA<7mڔZW{(uAPh)^:jK\7̙3X \tR&002KRRRҥK7,\r1c`ggG&M3f ǎE[yL8ooJWߊ{ŏ,ָf3NNNdeeYz#FshZ~vCw$$$`2HNN… RPՄO?QPP@RRW^eĉ( z=>/-u[IIIA AXڢF!$$mB{%NΙfcLOOZ+,,Jnd2ŋ1 Jfddh,f222pssr Tp! z~I^^Nb<%Ɗ͛79|0F),,zx࿽s^F`0o߾r mFQQ|;}mܸ̓ C'sNvMZZϬ\cZVёt-/sssח|rrrذa}ATFVزe lv]+?33'''4 V.k[y[P',uOYÆ cڵό? V^… t3'NY?lܸW_}{{{;vll&66֭[jBi2 ٳg}v"##1xyy1qDgU6mлwo^~eX`Arwk̘1/0j5ݺucV׬YÜ9sۗ?Rۗ5RСCO3gL8GŽWȑ#sέFt:T*U-%lѣG1bDDlũSW_PDVٵk{TyHnnn/#""l64ŋɉlvڅ-l=sRO ˗/b hҤ ]taر6}M5bFQb-l=uRO4| !! Q[$! `޾nj C]>3gΐYQpppUV^$dQ)uhB!*& Y!l$d!FHBB!,D$$$͛7;!ꔛxxxz]Eh4 2ܻq/2(m6N:ŋپ};cǎ(Ν[^hi yʕ 4SZy{{HAAGVVݻ7[E @FFgΜQ~G._\:0hРMŅYl "<w}o7^|E9tP7$$-Z0~x,X@=h޼9:u@q˗ *l6NIHH(>>ztbY@@\v cǎ燣c4h:t@V*=zÇJ"88"og V s4oVZaggG>}P((JڵkGJJJϷ4L8TC.~Rbdl6/Ҷm[/^Lxx8Oׯ$''c28p (u_GM?BBBh4dh )w`HOO'%%p˲ {&h.^l`0Xݻ7M6;vcV>ww*= BْwU*Vc .$l(Z-pgeݍޞq¡Cxyҥ z{&??.]U}qrr"--rBl6kUe8[S$j킂Xz5 .D1fN8aU_~YGy+1 ۘL&Zn͌3jtJ\Ewذa]c2tfgY3ϰ}vv܉dŅɓ'Ɔ HNNh4΄ GRѫW/N<5z!ڦbȑsVi t:*ª]1119rF'eGeĈwu DCVٵkefEF#V*a=ڒETT!!!JrI=!FR6|$&&ҿ˜_Q9u9S[# <3BY IDATU'65-Ec& Y ''' rbO4:jS% YTё .бcjO2 ƖԚ$ YTe˖s233;!ꔓjժ뒄,*.tZ!IBa#$! !,6BBe!*%!!`ݺuժGG]믿^ ^{5FWm!jmo&'O6mSNu֕>+oX$++/r}>66 Tct:|}}0a;vTBԷZOͳ=|fΜI۶m[?¶K0L6zlx뭷裏h4XHq2.lLL /_gϞenߤI L&7n`߾}3gK,BT=C.ۗ3uT|}}KlOdd$)))0a|||J;z(W^yٳBCC><<`;FQQ I& ͛7Y~=zzmUgvv67nʕ+3d_n<3ܹǏSPP@֭4innn?m6?>:HΞ=J"88{{{>M&;v_~h4ҽ{wƎ]1M< B߾}}:l+N:|dZjŜ9sxꩧڵ+Zcǎaggǘ1cػw/=^^^fx7r q1dbbb1 9s>}0mڴof͘8q"&+V;֬Yqpp`ذa9Wol2T*IIIgذaϏ>}Éf͚1sL\\\}E-äwС *IՕϲe˘4i|̟?{[>}.]0o<+SxQ>jbܹx{{sy"""ի}ʕ+SOY]Z,ׯ7o&99V?{1IIIaɒ%t:W\CϴiӆǏ3tPF#ϟgԩdeexbf3}[ne~ 445mڔ:lVW,^YΜ9P^ϥKJ-T*yqttI&>00rN___[ׯ3j(T*zZKOO'66QFT*qss[n>}xtQ[TTd=h :tVEPpI NΎ#FXȑ# :VK&M߿1M8rTPNr_'x3gry^z%JUd2C=d}„ {f^zѶm[L&z-ˊ=֬,;F۷/ff͚1rH݋lr&$$ .Gll,Z-[Z-uqz?$=BBBh4F!$$mIII!<<ܲR˻Y Tf{^o$FAX;;;[n)f0]NVT(8;;fYvg533b?lذHVr=b*Oifɓ'3rHRqt\]]-z5/Nj...VuT*,c.^~(zTV͛L&vJLL $>>=zӧk׮VN^o[P`0+^hh(k֬]{!s=Ww^NדOaa}{"wvvFP0wR#JNNNNYffpuu-7 6V ٙ)S:_S AAAٳ={0|닿logh+m(ሲ>e Y۷VZ₳37o޴*s 6mlߟ5k/еkWĉ$''\"ND裏o~ߟ7oraF#fׯSXXXۻѢE v܉h$''XֻҡC6oL~~>pkLmEݻh4}'-uޝh0ٳj}`` ;w呐Pn7n,J;ʖ-[Ȱ걚L&zŎ;`0m6zȢ{z=ׯ_`0`4KB_ڵk6m&=zpM8` ));wҿL&θEϞ=1LtޝsӥKJ;Cqyޣ.lY2k,6o֭[1xyyOZzB3ׯg8991|pnj)3}tnʛoIaa!ý1 ۘL&Zn͌3+-=z47n7@R1x`7onY?df31hZ F-Jݟl&66֭[Wx k׮iӆ7cY7n֭cT*ee IׯǏgΜ9eβ(((`ƌ8::ҩS'ΝKV0nyꫯ/Xg޽ 777@Yb-ס!Ѱ9ryܹU(##Ng mGeĈ>:|y,Yb5/-RڵײFrssU$""v{¶m/>>{{{1l۶-Z JaI=a[joiiilڴ4T*Z⩧`A,lݞ+g; A?'lK]iHB6 }!P j.IȢB\p;Vjʡ@lllЩiEZlI||~8|I}!!?|2G߯}pB klPkY|'?0Zjeѣ]3nܸ "۷ѱNŋsƍR-ZѣGU+uz&LZZ ӓ&OlСC֐䄓S)[;w.gϦm۶(JknJEϞ=kmvBٳ'{eܸqDzz:;w*ELL yyyt:&L@.][ NLXjꫤҼyR?tB&???ɓ'ӳgOΞ=g}K/U͛7ӫW/HQQ)))%׮];.\J1`Ϟ=\t0T*~)wfѵDE{raV| 6l`Y֣GƍСC1|dggj>|8-Z+bȑs[M/B"""B $! !1U<)^!;! !,6BB؈j!瓝J*ud2a2ppp@єYNڱ mVBBbggR,#!ld2a0*!XԴT+!aoo/ׄ6KPPTTTniǢTZiқ ΗFڱ-i4da*>Pv%g2FHBB! Y!l$d!FHBB! Y!lD_ILL$//7nw(Ffppp(q[Q}Ҏ+.۟$*HLL~w( y+Ul6O?q 5kV5r\yyy=ø' JU*ߟ;vHBҎmr])Daez v۟E0LZ^j,Ei |̘1R全.[m2d!lz\шhdʕ%\&j,ct6l ''srrذaCk֬`Ν*GGGR7ž={tBvllN-|G[O>|o=//J?''~ xWeܹ߿Jȑ#5kGeҥ$%%Ѷm[-۷[F}lA!`PPAAA!ЎY~=;w$55WWWBCC8q"ǎcժU\pVСC={6*b.[mCԩOrr2YYY山t ???Zm)Μ9SAWCtt4aaa~ Xn+V_~aƍ+O2n8ΝK~~~űvZeiӦvT-ʴ#T 1chdɒ%ر^{>ӧOiزe ˖-ѣDFFke{ȝ:ubh8K2k׮EV3|23rHQ@hh(qqqٳv/" GyƟGylC:uĮ]tou///.\KҥKfffZ5''Jѵxx@R[[AAT*iҤ Zmrrrh޼]՛B(,,/֭?|^M-$Ҏn݊` 66p222 믉w)V_$8::Jvh4L4{7x[muCNNN*s%^j9r'^OFFV/NYVnh,r -[DTmիsj޼9 UV__i&^z%\]]ygX~=͚5_3T! h\Ύ.]0p@;fYzj~{R{η999dff:j*&N\IdNzZ-[r!OnY'|b۸S݉]vjcё+W`2P(j7n$ #Fb ڷo`૯bذaߟ>}ѿvEjjeLvs zɇ~̙3qpp 11BAӦM9w]vEо}{Ο?_kϿ4h\z2۷*_v| i߾=vvv\r}YƉ?S~^u-je$ٴi899駟mh[sϱh"># [muv-N:~|||,˼P=7oR}8s ,W^L48τnݺ'RSS-dCGn}/^̻ŋiٲ%exv:ubȐ!L>OOO>r]p!}ӧO'??wwwpqq?իӢE jNZZzWWWg)g =dqnn.|qqq 7'r ˔; IDATc۵kjμyHHHLJ^{ Bmۈc…̙3@_#ϥ"#G4#@5 wѣ̜9h-[fW,22ҪUcbj]vѻwJa4ٹ2ҎkԩSyիWSa?;`O0RRd„ 69BT-g^v8eʔ2[4<$!zQ19XK_w' ~n5*{{{ Q!v۟!W?c}qOPՕ~L&.\c}}OvlOzUNRR7nEޥ$WWWňiǶ$!W@] C 6ɐBIBa#$! !,6BBIBa#$! !yUH^^^P_5kCb^'IBDׯ_}Ҡ_ReO?q C hؖ۟$*c=`0TRرCr vlOƐ@jNUn.YnUSOlIB|rf̘QBT?\шhdʕrO=QlIB1 6ci999lذX5V_HVuؾ}{-Ge}֬YΝ;_ZUNq#&%%Do$%%={S YڱW'c˗/cǎ P|DPPPla^o_;w+L8cǎj*.\VeС̞=JU#%[m R=.:k~UPK$te-om[n毼f+j+f)bZ)̵BMsJ2O>29}yϜKȑ#;vsN ׶zj Xv-$##:jZ`կزe 'Of޼yXz9{,k֬Z^ڵkKkp#EQ4QofQSSҥK/̪U8z(p Ϙ1?Trrrظqcm5i54uŁرc0l6h".]^M6qQ w_hXHMM̙32f^k233_cҤI˗/';;si&99f̘AZZ ݻ=z0j(&Luؿ?#FԩS2uTYb)))Oԋ_GʴiӘ>IZ=9ܮy?nW^ry}9sL:u* ٳ2|||HJJk׮|Wzjg,[캟 VO39//M63Dff&iii̝;^۷SXXHrr2F>:}zߟ9sOoxb?9wMՏ7^`0pw2|p8`/iiiݻ˗eS2:t\~> ..~BZ?!<իWӧOuFMM t֭^߻ロ;wdO?uh[^^^( :NGFFDFF6.={DFFbXn?CeŊٳClI_Lqq17Utԉ{7|ٳgIaa!:?N߾}qss#22FjG9yyy F2B9sss"22@nn.{\xbF}Zݽ}G 2V\IDD?9_׼+[<TZ?䈈ٰa.]`0зoydddd\\\1bCweРA;vӿ8y$aaa-R}Qf}l$&&WT-_gѢEtܙŋۧ7ջwobcc9s&Z}饗x뭷9s&V w!//HHHIII;7R;6l%%%i{fnyd(**r#Y.++snjCrr2tޝ_~N͛9{,/=/2dCu8jƍ^{Ccᡙ+++INNW^˫Ŷٳ[lEjj4Z7n3S&^|QłuHS /пNSh%~*%%0;԰m6:uԢI,O/U}z~vqsZ?jifl޼ }8; q s)-- i5n˂,<h4bocm9,޽a &Eĉmfn$2Bv@PP?#[HAӓ N>ڵk7of۶m$%%Bvv6̚5J2228q Z-h},//';;  {[-oVK3m46oތb!33j}$$$Đ!CHKKק_~sNf3{!!!͛7`fΜɚ5k),,d+L8Q*JLrr2 ,j2bĈz};ŋ4hpu*h4ܨi۵tBLL Wĉ?^S???ŋ)))/>>/;־tܙ`~:PTTd  m0!sxWd,_d eӦM̞=HvDuu}VtӶ>|8 .ngn^ã3#|||뮻8tBUUVT{*,KeCBB/~ټy3=QQQ #pVA+Ç'33LPPgΜ!=='x@{ߠ .\@.]pႽFm?ILL {ex{{k*2m6/_ۛ:~G[zMVVǏd2ܹs#뉌駟&//UV~c!h}->eqy PKL&:t$&&@ee=î]l6~ovǏsYL½KFF8y$OFQ W\UUeݺuL0)S~0`[lj*TUUYl6S\\ \ea0l?B![,6mĥKpqqK.oYfٲeDGGs9,Y^gԨQm*++ٰa3f`00zh.]Çׯ͎;8u$&&gL&`ҤI[7L8O>W_}jy'LvZ\d'8 AqƩshR<<7엟ϕ+WtR+Ev{С8d&lɝ%S(*o|z+|܈ gIUUK .REpS U_\̉X,5 EQt)p{2d[nuxY)ȢM8^X^UM\) c6tp{( ~!Y(r G4x*7arPSdf*7?^2]Ḧ/)ȢPTEFrid,=Usd8!vOQF|ј ŋygHOOťY)YT'}*>PXh "'iW(<8,]:>ku,rrrӨJpp0DEE5vvߴ05#Y꼑܆8)gg={oqVVZYZ 1=vSbwy۶mlذDΝh'$$9T.~hTUiYͭ|YvF\w=zg?ر{^{gpB:vH~~>/"111sQ ŋ8q4^|EBCCY~=o&o,De}|ܶb(hG>۾=zΝlrII 7\_Ϟ=۽IKKWUP)((ˋ/D:vzaNPݻw3l0BBBPUcǒIiih ҴG*wʯyc_NUq صc;#Fik5KЦ>Ҿ!_w}uVTUfپx{{Y^S]](f{֥K8u?RRRk琉ESβŕ+N~wv»h0^M`|œӭ{$]Ezиќ{jykeffr!y<==)((}7r%tRߟm:CS#7mFyȭϗa#cYz%ǎb;w38{_U!GOƌ+ߦri{ʢ9˪Uػw/TTTGyy9eeeFee%;vCmѼvټy3EEEl6N:( 6ݻwsIjjj￯O3ԛdnʠ F"_sCKTpYjT+`֭t:={6GfʕcO^nMH=WiZKJuɮ{VfWٹv/1 ɬ]_UdcG$3ΠkߛF LiWձ݂mݹͪBM d2Wʲ 13kNek7r?xό(<mہYAUl*҅ KW76;KꨁI8bծlZCs+rcqg[t.;1dUNn JpZYzqužÆ4RrzZwğ+$G"CiUQ]B;1w&!Qظ4@ 4[-c;<&Nh̨PI%<"]ZV,Vde^a€]>\2W9^#?!xsK6WR e-ئݾ(): =`JF HR5JI>Jpqs(zOQpQ.d'c^#)\ӮkA%]隯&nk4q.jՙN\ (ǮWSĢ3 ܖL/̍/ceo"1px1&'?nB2},'nTWQ+ňyM{V}@6ՇPvhJb;W;TSQ1 zg4Qg ?I1ӱ:ȍw3] D51L=1_ o@"'p࿻cMރ̮^uty8<#+ٗZ6 4t4ss{ ßM:.hڧP³ j 'bR(삙b# !*T*UgBCBzBB$! I B!B(4N]!KMA!HRB B!IA!BB$! I B!B($)!PHRB B!IA!BB$! I B!՞>S._ cXxquB!D Tv?͝;!CӧOӦMjmBqtR9s3x饗hڴ)jꋮ&iӦIRBjP餠VmqRTE͝;1cкub^~͛7#O<-Zd2}vN8A~~>Z#GҪU+F#;vԩS |A{1Xliii,ZZ+CBBR\BBB9r$~~~;w˗3k,bcc9uo6ܺu [[[~W.]믿_5vbȐ!<[꫒ GgϞ???|||ҥK8::Cxx8yyybccѣG߿?666XZZҽ{wΜ9S[a !}j $$$0w\eZ^^8;;3yd~WvIΝ>|8T6n`̬BJ%<==:uj===ygHKKcʕڵ@PPmڴ)J鰅RkG>>>$&&rQ &ׯOJJ hZt? @vv6XXX`iiɍ7w# !Z)0i$l֭[1xxxsϑŚ5kHOOGЬY3@~0L,]L0`www.^ȷ~/jݻwse^ujr2.]oԩS۷/fb͚5DEE{nV\ 111888vZN>h4̘1P}Y:D@@};%tW_ѼysRSSV>| GJJ 'NqFC>}6m̝;իWoo /~JFF%pA1cL0CѳgOYv- .iӦ/3}J|3wZd" WWWo^2-Z@жm[ JEiڴ)ʺyyydddp1뇵5tޝgмysxj+[ƍС[‚VQ!""}֭9sNٳg/u_Gˋ>}Rhݺu+ÇF߾}M)DDDFff&;v ;;&M(fܸqhZy8x]Z͛o#666>6xxxrФIpttdРA߿_j.] oFF6l`oo_b `eeW^nN DQҤI O{M}4zh>S;nٳg/^d21LE-NR e0HMMeƍ| :\m Lߟt:bXYYqppp(󤔜\l@,WWW]@BB111=ZCZZ,^իWj*ĉ177'!! dq433SYXhk׮dԩkwttTfrr2\|JEJJ J9 Q''"RSSښٳgcgg4ɉ"Ҕ]]]iٲ%_|E{{{{Ȝ9sXz5ǏՕ^{Ν;W,=<쳄Gxbbe?&M0|ٽ{7p{(ᄄ Z''bɤ q 4>LDbee^k)MP999JÕ+W<ڠ#GUn:yj5-[D׳2vʕ+W8p&hۧ޽;7n`ǎzF#4c999Nnn.C o%..r,ȱt9sш>nݺŶm0\|0?iذ!椤׭[7nܸAXXz4%ѣ;wxΆ=z4S~ի̞=^DHHX[[ӿIJJҥKLJ_?|Gܹɓ'W).]uV&NL֭۶m㡇*s]}BBBu֌5K.j?>_|!!!FIOO?&)) |||xꩧ7nӧO'%%V˓O>YΦEIF+V9:pwcݱ`֯_;#Gd̲֭eXx1L6F{ ѣ111L>\!!G@ӌ3*RZZ666Unc[?~_|øg}v>^xqѻwE"r[  iРA,/٩F#?|^^^{uQl¶mۊM%?qrr^׷^UIV~9s&/"M6n{]ߕTS0L;aÆ8w-iӦy|PoPTF:vQj*X~zUYf+0~xڷo]YkS';OjZ[|ɒ%bkkٳg&>>:uĀO<ɮ]ΦI&5 L&ۗ]K;ӓ7oҶm[`0Ë/F!::UVdח^z @3O?4mڴ //UVFaXXXÇ駟HIIՕ1cо}{K&%%NСC۷o;/86*=۷/J+dbƍ>|<׿Ev0 lڴ~ @Ν7n ,\D^y={v٫ٷoYYYhZƎO?Dbb": {Rg?Fnn.;wFVӬY3[ɲeJ^߿˗/8e˖ٳr QO[nݻWI III0aO&MD˖-`ѢEѱcGŅ7n;ЩS'<5 ^^y_Α#Gʊ8Z-&~??333ϟ?ȑ#7nWfYgvqfϞZf…|'̝;&M(|YΏ?̙3|W?ŋ wãf={< Yɉ=z}$jCtؑT]ܾo׮vvvҲeKZ->}cǎѹsg6lJW^DEEOŸdN]RaccSle/KIIiӦŎk2GGGs >R,0j(V^|r IDAT\^لiu~KjYx1Ҷm[e^ZZZehРpˋ!Ch|5LWT4n???Ξ=K޽7olGYGV3`oƂ Xx1xyy1sՠARRRhܸ16888Tdzbb"Śy*R˖u, \^y7nĉIII!$$~GGGybe]V<_:ޞ"T;::Ҽysx Y'piu~lݺUi-Jxx8F7orqn]Ntt4& ^իWu7o\jG^eT/|5vNiӦ撗ryye .(}^^^ z=$$$pt:hrrr0 [V͓O>Ihh(v$QT3fTj4ó:s1^ye gʔ)ղ8~8$??b̠AԩS‚_~ߗ &BFFwGPJTcKzz:4mZMDD7oޤYf>Q4),]8w^o$a#??͛7 ܾgUi=N/\<zQM>Qѱ-j!CQ  I zͥY) z}ÐQ]$)Ύ .ЪU+,,,:qDFFVBDB<==~:uckk<.DMP#BO| !$! I B!B($)!PHRB BQ #6 !DUstBᗨ !.*=ѬtʋU*UU6#~^UJ Z,t:jtK!D}b41 hJ[`eeUUVBQeB$! I B!B($)!PHRB B!IA!BB$! I B!g˖-dffÄ j".!uIcǎsAIBq(wZv-\vTz=#FDGGKǎyG0 %22NGÆ y'qvvŋlٲdի<3\~͛7#O<-Z!}Z@xx8:ݻ FEVV|:t 3335jZ_~cǒ;v,;v넄ЦMrss aȑq9/_άY!}:}||ET*QFܺuKY]vXXXRh۶-;w JI&tQYٳ8::ΎK.UWQUm5;;;gZeT* ڵ7nRTcm;88@jj* ̝;WGfffuE![Ֆ*c͚5/cffÇn3--YYYxzz2uZY!uBff&NNNǕym۶͛;w[n) n7%&&rQ &ׯ_B{Mk Ofǎddd2~Jtlܸ={BϞ=9r 4`㏬^wwwڷo40i$l֭[1xxxsaaaQXB*004cƌL[nE1rȺE!YssΑ@\\'Ne˖uBꤣ:uKKK:t`˖-\|JEyG$&&K,w^._s=|SO=O?י9s&Z0N:Eff&7fɘL&~gN:`חÇhgٲeL8ww24b?رc5_ܺu|&OLxx8ϟ'++޽{/*7hЀ(1 >>̙3uq"ٝ?ҥKu-[,v?{ieؽ{7V"-- sssƌȑ#1 Xݻwc0ѣ/k1m4,Xݻw/v,zUb,^7n`4ҥ f"..ɓ'Njj*m۶W_V9;v ##V˔)Sҥ p~/SN6l/Rð0>-йsg^}UU6l`dggӣGj5[f2zhFŁHOOޞ_///e~PP+jMFO#\x'''Əϒ%KزeKwI|TBz333|}}͛mۖpEڵ+&L **իWs lmm߿?DEE_bffF||<׿߿?=ݻ7˗/'22N;ӧOޞtV\Ʌ `СI ...xyyzjk} ֭[͛7n\n:ʊ_~/2i$HJJBR믿re^ujr24ƍG^xصk_}...k|wņ7`ԩۗ~Yffؽ{7+WƆuٳ'666KDDD0j( ֭[_O?˗Yt)vvvX`]v\p;;;N:^Gpԩ2IIIw孷ޢwDFF2}tDYVY 櫯y椦 ڵk9}4˗/G0c BCC>;͛#ŎEi.]J~1byyy\~]N/`0;_2}t|||4hNNNlٲEvZΝj233K fƌ2a:DϞ= gڵ,\M/$GevZfϞ7|$pBY`| >>>>̛7tfΜY+Me>*Xd2a0믿HLL}ʼ'OҡC͛'ܺu> zFʕ+lْ'NEDDS1zhv܉ZfŨT*jL&.]/&))FH>QRU*&Mӓ/?/\СCh4XZZ2tPNV>qqq!..N֭[7EV3tP4h@ӦMQqqq}iӆ#GÇ6Ԃ888رl4ifTa9 ⴱۛ^z) Wߟ:Dn̙3t:Ξ=9r^^^JE֭\UVsss<<<~gƍVښ{*tL6ƍ+Wž}믿,TpEnffƨQؿ2WNtڕX9}4/2Z<<< ^ ={4h͛7GVH&M,O`` ^LL ׮]S6Lԩ7or&LFɉ  j kDǏg,Z \\\ej5&L N<+]vd2B`` d2Ѯ];Ν;hĉ<\p"##ӓFɓ'1 4mHbb"ϟ'@RBN8qDWPj‚@ɓ'ox033 KKKeYGGGL&iii~I@ZZZةlܸ@"UԩSޅj5֘f0L@%$$ѣi999ŋYz5VbL8sss"""vypZV?!!!t::ӱȑ#PI)99U9)UV@~y:u*nnn$$$pB,Y`(rrOyW;w.L,!!!|G,^WWW^{5:w\,cEˬh9r$?_x뭷n}5舙W̛7V˵k?,P%)8^:wYYYL+8::Uﵼ}*Rhܸ1~~~={ViWTE٠ALKLL ɄWԩSoFCǎIHHwʺ;vcǎDEEh"6l$> bV{(!!HDEEMfpvvEOt:rssٶm~~~Jd2)W>}}>CJiU@@@aaaxNNR`͚5J:p>55*Dqa/L&+%v4wޝ7ncz=FHrssWvpww'77L:ĠAlёHW[GyZM˖-߿̦#݄r8d"::}U:3g`4ۛ\ ·~4eddpʕ2c8{,yyyT*ڴi^/R %//tBCCݻ7p&Y͛u<<3l޼9s`nnNv6Z+++FŚ5kښN:q29h vŋɡI&DHHX[[ӿŋdeeۯD`` <:6 bʕ?GGG}0V/ h4͇~Hzz:1IIIXXXSO=Ů]رc=|Gܹɓ'V:.]uV&NL֭۶m+Sr'Tpp0[fԨQ\tܲZZZb 077ݝ_@1a餤jy'KcQZ޽{={6* V̙3%##FC0atڕ^?w\qyػw9sdF`W֭=z% H͛79uToK-x+TkRT̙3c@TP6mڤ$!:uĐ!CP666L:]VK^xᇕ|||طoT쌹9 6ȵktӵkWgÆ ̚5|xꩧppp ::ZIT?^ ڠ 4͘1R+accS~pqҿ~zb^ǘ1cسgOj /qKaG歷*7yWoƗ_~ʕ+L/K5_-1/,,,_ʭ0 dggӠA #88Xկ N^^^{uQO>b 1c\.vKNN͛<q^Q_I+2͓&M*se*${\eDӨQ"uݝKVx=<kP>D+=,wQR+OB=U~n!D;Gcnn.daa^D%)T-/u4!w/Im;;;.\@V=%J뉌-U!I6lH||<6m*$;gg2qU~"~coo-7}IR/|YF !JW'7Q5!uNB$! I B!B(#q_KOOGכ[#л… }+==ڷo_ɤܿ_O q'I ⾥i׮]GVӮ];:q [T* c IDATz}]0 h4qrrp}HYK 8 G]_j-TIdeeUjC5kV1DGGAK5:thپ}{ E#DQ?A/jH%INN?>KR>'O>o<"""m?YYY;wڶw;zh]P# ^ _ɡp .^!Jr%r㏺^HHH`uF(|2/IAj .ݓwݸqޝGEq7t7b0(Fph"K5Eq3_M&<&1%D!|&>!$¨G j$hTwEb(`7}y8GnU}UnU%&RPP``̛7sq***"** ''F_xÇvÆ #""h~ߓDVVWp]z=̝;kkkRSSIOOGRMuu5̜9LbEEEo'ʕ+h4Ì3PT$''Bee%vvvL64#_}.\@1tP"""3//O>"qrrbҥMyff&_|( "## pMd2fԩ4Yƃ6=``ܹ+rGI/ 88'xZ}6dɒ%qa䂂Ƞٳg7{nf͚E޽QTTWWOGMM >?#F --^zsRSS_W:thqkO/9s&P7Bfȑj;y[ĉܼy˗ceeǙ4i|8p@7TQQA\\>, .kkk`͚5t:vMbb"?|崦oW>}ZW)Z`0,a }u#777.]DFF OOO~FA^dq6 ;v,LJ+++T*>>>I]]] ^M^^}7zh.װ0.]$MEV0pFl.~ckk G&--Uq>ȕ+Wpqq!44B!:[n1er9666L27aeF-mNRd4Az~9s T*Mdeeqei>JEYYY_ N<)=P-//WWWiz:qֳkF#vVd6ΒP?AJJJpvvnyii)*QW3FzPm̝ uBaaat:%%%c;v,O>$ϟg۶m_'''ɓ< MղuV@ZWRRBϞ=(,,+++N8Azz: .֖}JKKٻw/nnn]зoߦL:^OHHΝΝ;f@nn}󵵵H,_R?Nmm-'N{PըT*Z-NzBCC9zTYYINNNTՔS^^4hh4ꊯ/IIIRUUŗ_~c=\|-e9sLGs,eԏ!0h "##9rK/$u\xO?L??sL>s <}6YϨQHOOg͚53cƌ&elmmygپ};P?vV-YQQ5>>>Hwڵkcʔ)\x7n[r=lmm0aˋ{\\\x7Mwpp_СC߿R̙3qqqa$&&{P( $""l̇ꃷh)BnXref*--Nar?W^mpݻwӿ6ӕX;w6lg'N0K,&LoccåK:LBע騨hSkLL[ ޽BGǛ-/Iwަ^ t5diKi&sQ[[\.u6,I$R*ܽ{wwwJ9P(M t[NNN ѦT*P:H B&И( HDRA$") AH D$AA"  )X\*++)((0w(gϞMlBQ[E,Dnn.<,˂ ZU)gΜ@zɑ`.v(lkB2VVVV=K숖D]5 !M_Iy6??Qw=.v(Z h{{SuQ$b4c}G+*/Н>,F1v؁NCӱcǎ&k+SuQ$b4ݷoF4 kҟ+НٓBll,7o 55>d*))kՋowmq"x.U,IΕL~~~3|N8%wڿ?'N0w]^w&a n:&O@V3mڴVz133kk9UUUݻGRTT3QQQDFFpyz*?ŋcmmm۫ FXX˙G/oһwF~GvSO=EDDI?j(:433w}V\iXL3ES1yRXjիWpB ԍ 4ukkkZ]o%00ЬIAբ鈍Ãׯl22dϟ'((Rz-zETTbnmkGtwwܹs̘1gϞ5y]yGMINN&..aj.ɓU~ٳ h2oVV'??'''Oo2lݺ 6`eeEAA7ndƌ3m۶ѯ_? Ɵgbcc{Zfȑr|2׮]ȑ#DDD兕gϞ%99j;w.|,Zl?^x<=={.C i4͍#GfϞMTTN GGG/_N>}8w111|8;;… ٴiSS,8y$( (--&''Bee%vvvL6uu=IIIdeezj8x iiir~iRRR?>nnn޽=z0ydRSSIOOGRMuu5̜9L?7|ʕ+dFvvvl޼odMƹs())a,[ [[[.]Jpp0n䲲2֯_o8Vg`k -"..cͤIؾ};Q9///rt LKKӓ+Wy#6cY~=ӟHKKM:Mƚ5k6lPbժU{XYYI}`m_PZZJHHHK.1xg}Fhh(k׮EJXXzbbb;wn%h CuuuݝK.I={&g,YOhݻiR߿?.\ 44ٳgz*wmҤ(++CRRzѪt|v9tZׯMii)SNٳd6mԤˮ KP@QQިT*f̘͛ٸq}c wذa8pjRG\v VmoYVV(V={#ck5ŅRt:ք}v\]]uZTbk,ۿ8@zz:G.3h \BAAGn2Zi4oNKnc6B.3p@|IΟ?/%Μ9͛x,2\]]DOdd$[n%88Q4ԏT*y8wͶ2IOOg…ڒGLL}V)++.XWUU{.V~~4Jݻ8;;K#yGh49rĢיꢱYlR4hIII0b{.}_BXXׯ?70hm|in߾l???iBBBCT6;޽{jT*ZSN=pC%99oooJCݓp-.\ sHHH_z)~gٶm_ kEcؤ`kkˢE8x `0ɋ/8situuEP憽}2w^֬Y#'NСCR &sN~GM}cڵkh4% lBff&PB{H عs'@ǎkv;M8UV/֭C&Dff&k׮`ٲe,Xf[ZP5fJJJ(..n4ٙ\*g>}D```]eggKUt=z^zuXB07ub&YZ֕vz$%%QRR\.ӓ;n;E={;jk% 4}􋩸ߚ;vuQ$ ڲ#* Z-&{u{EqMBKw{vWJ?zWvھvK&b`!_ILL/Noˁ{{{iH`<.v(իSuG D$AA"  IAA  HDRA$") qͥ0={޾,uZ]IBboo?nPb޽,XUeHy ijzL]ERZsj.keeѣꫯĎhID]uQ\S^dfu{ER,F[aߕދ+X\ER,Fs;G}+Ҫ` ݹ.#b;v@ӡرcG~/`Ys]IA iۇFv8Fþ} )th͛7HMM>h2;@II 555*{n9Үu Ws%''L,??'Nt%/^-ӝɯ)lذf[ɓ'i0ZV6mJ(h4ܹsAeyUUUݻGRTT3QQQDFFpyz*?ŋcmmmw&xXXaaa,g&78|0999rz͜9sL~^___Mw% +W; uTLVZ%,\}u{M}Y[[d]| %VN#66_βegȐ!? JKKy뭷իQQQFYGjVG|DDD0|p}6&[IVoPL)<)XYY5g̞=&fee~qrrb?˗/c0:t(3gD&ugǏ///prr?beeEMM $-- \O?MJJ ϗnc .. lll8q"?8/^t:]ưaØ:u*11176o?^x<=={.C i4͍#GfϞMTTN GGG/_N>}8w111|8;;… ٴiSSaeee0|plllaذah¸|2{{{f͚%՛bd2cǎeܸqt:=ʅ w>(K,ܹs,]"l˜1cx"8;;3w\)qgPՄs֭[ǯʇ~ȢEh6c|7deeX.77%K0m4Ν;GII dٲeڲtRu#~vel^MbVUUnj3 ʕ+l߾իW7ۜu#F`ƌܻwM6СC}6dɒ%qaXti|j*  ''Q .xby& "##JfϞ-߿QRUU_Miii `0p%fΜ2RRRxQ(ڵk'JXXDGGܹs;,!={O>'""GyIE!INN>㭷B&œ9spwwݻlڴ{ gggN8kxWqrrP:i |M o>}:ۗW^y o.kooO@@@Ό e˖-t:yx7xyW3f ;wO>qES2斤$uVqF坜 A&V#//~#FЫW/d2aaaܾ}Fd9?&LBI2d^^^aoo߻@###L4x.]S2;wDT2qB **Lexb222Xb2s>Tm0t$LƫJ޽ٲe |׮]kTfȑuZaaa믿ЫW/ё"n3<+=x'xɤIFV7wpp`޼yj#mi8y$P_}U6nHll,+Vn2Kd-󉎎>i@УGF[[[(..&++˗/KU*eee4WV7mm.S9tZׯMii)SNٳd6m$ކ Jbƌl޼7w9qJ%<3?O>^z~u+www.^?@mm-ݓCiii/V76{eeeT*T*40VJKKtX[[quueȑfPMbk*\SCjʤQUUUM*uiK.3p@|IΟ?/%Μ9͛x,UIDAT2\]]DOdd$[n%88:Sʊ#Gƍ7PRR"GGGܹ޽{/z+UՔj$^KuLVSUUEMM4O޽{.ȸx}Q4 Guhl DRR)))1+++޽#}۷o7[Ϗ1c4*Q(--w(J233sGʜ9s@9|0RZܻwO/88ǏKJ999\]]رcL-M///СCDDDtXRBB:$$$SOu^ٶm_ Oo)YlReѢE\.]v F!I~?{)//'$$_~*6lEk,QQQDGGe) m;;;Zuu5Vb5jARSSYpɖuCRWXAppIqqqYd7j߰WOTr1鏎fΜ95ʕ+$%%bŊVc˜9sHNNkS+E\QQzX#sΖnk;ޫW/&dߎ>}t_;ňst ˁ ?`^].vKii)III d[h >k֬uXܹî]Ɔ[΢;E~#000={;jk՚5k&L`„ www[sn.> ,DWxjˎP(j&{]w&b⚂쮔Jez=W^2z,ݻ.pss_%11۾8-"ggg!ؽH Nׇ}N <,Q/}$ HDRA$") AH D$AA"  IAA;)t t5=F+)zA,`h VKmm-+++^Ahdjjm]IAVhtAz=:]nWRPTT* X0q/ HDRA$") AH DShR2kSnP:@5=LxrTVVRXXAunyER#ҖGae%nl '8K[H ٨T*ƍ'nm%ONNNH `$*eì zkxHnmş g[,SQQSO=^oc#+++BCC9rHIArdPӎG tWZ=Jsˁ͖)**h#+^\.][ F"ۢ5`0pQ{H `DhKt]{H `Dz8ml/Rh;R `ЋB[f{Bۉ XA!f{uϒ%KصkFYH ` `0Ӆf'o!/7B?S#}0h'= ^9cا:T+]>JMM_`0μy2dQDR#wFx.0 5rߟYJ8~ AG2w9Z G?g޼y,]B706:zn-AUicɛ+ ='M{wwm/NiBؤPQQݻyW9rСCu}|TTT`ooiz\\NNNܹsbjkk2e ƍؿ?=eeex{{fd2gΜ/޽{ /* tUO__M?QQ*`04CԎDYQ(1e׏'x=zpq>3}i?ٳ'ټ; >GGG Xj...pUxwdϞ=k֬1Pqjͮ@`oR());tPÇ^ZMNN|w̛7=իz'O2f<<<0 wÔ tU,}Ҷvv784TR\L&Fe bs5]=5cO¼`jkkKqqq9r Zm juESTT$% s?cXJJJ1-A,|/?/`@i:o?rE]lxGKض}txк1UҥKu>O?o=999M=zPXXȣ>h3>>>DFF6YgAAAeC{#^#FTBG8:`L8v~?QQcG8{$EJe 7S߶M=#cуqsh4ܾ}rpttDRQ]]PnLY~HHIIIjsz1cpI_N7n4Z1> `;FF჉!W+K_2{gs{?eˋ;g}Z6nHEE,_???͛GBBr tVoe +W4Z ]r6۞ܡt**%/GӚJIIgFl׶P*;vV#Z `LA<:Bsw!.4 ;xyEG_h.DR `:3>t&! Y@O[Z (JJm-qttD۵-J%ZGG6+ ?e0wlJs)hZv]Ŧ2\zg7 j~:mW$A0]E|x6US謁-"33t:0eY>?;]}t?kB!B!RWt㡭>SZ !B+פY]jM|[HU%B!#iU(x6I44m5(+6<>n?NUڥB!LJZy񉽨|[{}y-[G/B,!B+c*55|d{M*(ȏ[uxl\B!ĕNU}#']@9ˆo ż| U@ownnY!m͆`VmHxh5B!* T቏~p?3^'MDLH K!b%FLB!,x|h@]=D/齀oaXEw#c*B?gWCDF*5 t}YB!Wg@ ຾?r!F~im M#;aB QB!ğdoË'̒4*!BY{x쑟W=gKP''{h Xv=[޹nB!+6`5,3o#׸2/Wl67ϒ/ޅB!B!DYDkd8T !B!B!'@W(B!B!Čr KQ g-B!B!BI !B!BB!B!UAYB!B! ,!B!BqU@B!B!*Xu;B!B!wB!B!W d !B!BB!B!UAYB!B! ,!B!BqUHZ  xGhhhH|0/pLMǏgP^Gy}k#=׌|믿>>ã>i`/|K_d?466r}omZ&B!B\ضm((իְZt)g2n ׿ooȪF4Xdy)//'''\={dٳyMB!B!b$R%.2wy9*c233k07weppe˖ݷw^v   o||1Mc='> }Y, _Wg5nB!B1f{cc#{yG7oO=Ԍرcw}|fRU}sH]]vcXXz5_WַW_pzj>|6#'˛SCCC7hj{ !B!-~;7pCm^/Gȑ#mGZZZ"M0-]tDlGiiim8]O~ry^:::xGt:9^{K.( ~@ii)YYY=z*عs'0@~~~RZYYɧ>~ߛB!B!BB̤[ou6V u{{{n+0֭[/Xx̤ج5ܒ%K8{,Ǐ#??Ç";;;޸q#o6>5k`"Hcǎ]'|21÷{WWImp?_"{_s5tR3:ޱig}|XvȚn.B!B1fFֆ ؽ{7MMMN$I[icʕ+ٻw/mmmÇioov.]0b(]"222^`͚5cֱ:(sEŋ9pBTU_= +VzM6?   =zٽ{7޽{GH$B86뺎';;B__{κu8<7nB!BqJv~+Z,[i/ĉqE,Yioo' |rjkk\w/~ sdZ~=O?u:| _7 ?vT5>HKK8yyyX9jx7IKKKٶm[Җ'B!KD^>>?0T gjgjSEU4t݂CR4P(fCQY_'==};ݻwMee%x<6m4M4?b' 55zVXӧ)..<|'??2-=iiilٲUU4 `Do4Mc27*]ioo>\.Sӟۍi>tww=䐓3eĊD"|>DQ, )))v!5Oopp`RBvv6)))IYdB!vS!HY}=,jDC׺D=g 6h"T7| g'Ԇ{ص1Mh;uС1[|8y)..N }"v֭[q455Bqq17oo_,Mxgxinn_2wuz+ _==MMM;vիW{noߎ힓@\q444( FaaacN<9p:DQ*++g.\QTTDee%6+ӛo9})8800@?n|3fJh bhnnfZN41:;;IOOp΍$ C-Ap\3uxXp!EEE慑DJKK OsP({͛%%⊒o>*zzD"躎ihN جmdںH) B&RYDYXBBѩٵ=vsG/KTO&BQn&v;P`0GY,\76'*tx^BPROFnVZe^4m'/_GII ---dgׇ(|ncժU8Nl6!^ӧO/X]gOOfNUUB!3{,je…1cdҥpyVX'=P?`(qJ,=W__?';J:` iF(2*ݟLyF dB!.]D8HJjj*dgg9u3 4{) p8h4J__湍磬,2 RTT믿nf%f}v;6'}k%%3f ]'iC'$p]/ЇaQhY.2t)Kvs?2dg9x/_wVf7LyݓePRR2c ]|ʪUػw#GLIIɜthjjb͚5Hee%6li)FygO~bSO~^{ V͛Bu?믿?q35~"@7|ŋv^pd㳬磪*// gfoNEQ'''P(DWW#ihh*Z[[Ͷv<7:YYYI[X,jn#>LpL~ׄaΜ9Cwww\Vb[p kEUU2ZDqS~NssF V__ΝCQ'##688磽]ٳ&s0? ~ζ6),,$??6˓΁z{{zc4M#O{iDQ:::nD"aRSS'uOSx<Bq5k̎H1i:P/C{X@zNdaR?DRX3zq>_vsM7Nܦ sdOdzq:,Z<TUeŊ:ugR^^}]i pqjkkIOOr~IOOk[\f޽{ٴiS\ 7n`…lٲW^y楗^_?9  Kcc#wq Dغu+o6k׮MvVU .;UUz \UU A0`Xhf3;l%nU( ]پ};N0mP(#zj3se6?~MӦ@~Ν;y'yN `XX,f2Ο?LTF .7b2tH.8t<33Q Koo/㩧 |%3xe !4%̉dQ6T*>_Yvujd]3 %R?V_n<>Udgmٓtvv '}2q%( cVif?yreZjb&}06z:::Xp!/^TVVsQTT,ZSNN:M7݄_4;B/^-[I[M|<<3Pm={kk'O =Coo/fʕS^!x<8N|>Y*CUUIOO7;/@`vz=&??'OrtvMvv6p8i:Bgg'6lwA4ZZZpݬ[nJC&CUU HK؎v`Μ93@Ν;Yt)sΝZ?`fY{u]73̺zٳgD sFg,o"]]],\pD"//2+ F*{n"YYYvZ bd<577SXXȺu& :'DQ{=/bid<r-}---|k_c 易oansgJJ N-~e…l޼B|>d޼yI=7x닛5SUU::::̙3Ylg'+|twwLH$Bzz:~;#nՊiXVkx嗧4:p`|Ǥv=.!#Sg;>mw:zzzcAQm vq8SQQsHII1kͦy` 8<Ν|\2QrPi/j`KiiS0B!GgH__mmm߁@ϓ˵^;nq:u:::tR `Z$%%^ye``SNO__. 7 ;F ʅaf1>322ی2SBvFFo[op5H,!sbY2  bZ žXrFL:thm۶=fppL);^Ysg& f&F+''sΙ,UUёtҌ-##Q/0x׉}'HKKcޙ3gXlYwLA,#sɪٵkB̉1777vZ:;;~1P7"Y]wDׇ*س :FSFîjF4dtZj˘ns]׉F8"~Omm-`0ߘäpB"Ür러,^/͔z #c֧P(dEII g#3V^MKK p؜M(~MOOyqf}DMP=v0\Qs[n%[)GcǝFOa??D"|7_/K~cXر̞1cl6~qƄs!1:wu< q3ÿCUU~?|38,cgffr!3DOO090L PF;`t{nz{{)**cǎb V+\wuK `)ec9@ n'EadL5+ 0Eԣ(P^E!*dffh ˨UA+#̂slms?)EEE;v 7T>bOpP(Dgg']w݈wttk.mvEJt;deexȠ 9$)xa}/^dٲeSnÅ !n ]226 EQX`'N0g0,--P(ĩS(,,o7yyyι|0nlذ:4McӦMd{B޽;m5ۍvbӦMB1>( %d) F'6t}CKK:P-CI8I82l35q4RB\]vqqV\if>Y, 8uhիW3j%&mE!33GSS|>n7NBQRRRp\fkGZZYw)z#HPVVFWW]49 Rn;" o>sxYww7yyyf͍\PP O97III{D 駟& ,:>yHAAǎcݺutwwqF.\@YYYq10zxo8p jRSSu|JZZ9;1ZaZ9|cXϟcYd?PJVVuuulڴɼ-zΦt3zf mHxˆ`0ȥKشiӔjvzzzX,tvv&%FĊ}tEQ%A~O8&--ffv;uٌ `ֹsfHsZZ,_t3t!ej:ƂYNn7#*---ձe˖u%SUs9YϨf7 ߏD":DZZ˗/lŋxj|ר`…pP^^GtKJJ&<-..?_IOO駟63*~#|I}QַŢE|*qnݚнD?C ׳an94^駟`֭扳e߾}$#`tGl0RUUΞ=իGΝ;wm0CUUJKK9~8~ߜ0jia!3Y+WϓGOOϔ;F.X,3;g:ƉZOF%#вl|>~?9998p nFdIOOtpLOO b\CY̙f ٴsN?NzzpPh117"kcNuN>Mww7ԧeɲzj\HMMe?~\yh,;w4nƄ_FEE:>.tT\.e\+2j0r x,ц0| 4M#  qLw#3 (=gniӦ`hÎrh BY7f kC UE0ύN%]RMV]OGUC.d04T ~O3_էrH$BNN4`-[ÇEvv6gϞ˗Vy“F\s\si3b22~:;;lSP( e…q`0h2I$2QuuulݺMSS1زe ^_|Ojj*vu[oq5נ*hƍQUw}w@ uxy'v;˼ \{~|߈{=<;v'4eff_~k`.?ݡǎc۶msv`073tyf{=֬Yp"GQFV0M8Z}INQJKKٽ{77tB!6l ==5keqB555\t) a…quڊje~^$Ot]'Fd&##Xav9}9#GXlY5~FcϨ#i6 e֦2EY,>LQQѸOwy'Y(>'1J \v\\.󱱦;D|,ÃYlݺռߨ ]XB!Ҙ5֬Yc֝}"cT@q(I /@i26YXPQ L oh4ʏ~Ә6}[?t#k-'3 iѡZZE#Qhp8#I?s]BP(D(ˬ`۩fTVVŋqf3_n;nɘ;Ӊ(444IMM5;&.A0$-- g֐]ѣG!'''W$'g 4?w2S"LcXojj*@H$Bkk++W5c$Bun7mmmtttOV Y(Lm9r$V9dt`3Sa7cȊ5};w;.c`ZYhEqq/^<P%NRUuF=ŷ{ NX%//oDDdjc/r-$T2VVVϟT)Z*)y6Zhllŋx^3;tŚ5k03=aAvv6,^5J tttpQRSS\)((`ʊ+\NKK ۷o1TYV.^8j]L67g93/7bfxB!FF,EQ+C'  YCnN@W2XK<lV Շ:_0F #hQ ]BX,6DZBCr N@ 3g(--,l+7ϟ?`0himmmf!W˜=BC'1ipxZWN'dffS9LXf uuu466RYYɆ طo000`Sv3CzWzSSS)++r{ϟɓ'innGy;vO~۷O> صkǎ3%%%RUU5! 1N/&<9r3бi>hj9fn $Zj,qmfvڝNgܐ؟f!2Alw20r%vhF e<3+;]wEJJʌسX,lذ{N>MUUU™8>RXXh5SCcSuu5ճ|Isb};ŋo~íޚgFUVj)HMMnʨRRR(..`Ht '(z =7++;vl6^{-@i E"xlvB??IZ|odg))(24TLYRueG(D^ѡˁ,M@t4]?z9i H4: d?>x^~d }nn.v9y 'VobΤ8880Uٜ:uwQWVVƲezxEEEcֆ K0n0O ~8pZۘ5λH$Q.j7B1f`hᰓʰu;/~xju*Zc(a$ tt1C CAt& cNmƛo9{l8l6~fA7w%θ/F셡P>Z i1#G388h]-vlq5u͛4 6P[[k[x1 =zbn7p,Z;00@4%%%^5'yÇG?oQF4|M3PddqWXaΛ7^{mϞ=;ZO- ϙ3g2VXW*nt2:ql6rrr8q~Caۻw/Mkh(`fM&fvj宻[oVo΅ ̟۷o[o^ϲ1>G (;vBϟϡCؼyO߫3XgddPZZѣGIKKc޼ycb3t200@EEňӧO'eةh eE PTTDaaa\r[[ϟX灱AH$Byy9f0b>gB!bb.\`ڵttt>麎 %Z)n {((#jLU=u>rx CA~nB0 lGp8/,TXVc3bE MROOcْrE_+ IDATu\.vgrt]+؎ÃX/=Ǹ*MMMn|>@PU tהΜ9CFF/6;Fʬl444Eq|In>n3;*55`ѢE0d/Neectzq`Z wҥK2\}q4m5~fddp ,YB04_oSS>\#.iII po[w6 7}_TX,3`atb gD_22#߫hhhܹs,Y$PJl kNTkNf~|W4r :u'NPPP`WN#|):;;)((@4yQQь˖6\9m=''ӧOnt>Bsyhlzϟ7yx).b6%uhP:3gOjᔯΙIKK75O ۶/rQiV*MfTtttTUŊX,:Ͽ{,'t?a\򏕝M8&??h4jNGndH)P 3etFv?!1:F .YePUUE86kFksly&Ί+̩!R`ЬCUVVWP`ӦMqm!1>яr}}{_W#ž:u 6&Ó)ɱXlgD(8mG4 NUUTUUav٪[*B3B91Lq>^~etqC ͿNL* KNNΔO&233ٴi37U+VS\\Պx2'iii3n$fcw"hp`*0~^'kNuY/ƌiiif!?YLW_>b7t?UVQZZʼyf}"!~""%WXak]yl'ORXXHQQєg)q\twwbpc;5<8e-kΔ+dtXц 7:ю+QfffwoFFycF4$mr`rEuq.d|(6Yo9Ne!M~IYX86Lj%777,%v FF Q9љۂ Ccf o[ɀq` p8R3A ٻ;33Ifr'H ( ޠ]kխkݶ_kwV[Rh]"AhSQ :!\AgLBrG^#2s.{.C?d iAz饗+V[nc=-[7رc5|peddu/clq;wg?~\_~yuؓϴK[slɾ5 =ߕr|Y;vPRRƏڏ-~_[Ϊlַ\N_C-!!-_tu&] +Vm`pq^WWhƍرc5m4egg+!!AQQQjeYڳg9yTώg.w"""zh?+V;{r:JJJ5}Nwc&LЄ \\g*{`:l @[ -Pݻwv?N$i޼yC7n<dUVVv_NQ@[ -zwUrPssU8>;sd^Z ꪫ+@+z]egeu8(/Uڧ@ߗv>ۿ'ԡNR}V/]tE``:¯Oj߇N*m谳q 5'z[m[j9q0k6pNkd-ZH>)//O/z;>SYY-[zoذaͿUKztl>z.--ܹs/Zz'tRZJNSTWWkתDa@_*=c={+׫-]Tn[tQYFJJJM7ݤ/}KZ~JKKuڴi^\.Ν9s Ҩ5P ,R}}|M%''+--M555ѦMt]w)..N2d~4M=ZzQT[[@ {Wi7^z%-]TMMMzꩧdjϞ=$mذAW_}n&\.eddhڵ?Is222a=3W[r8(0tQB,V(Y]Z~h^]iӦ)>>^[nի@3gkN:Rqޫ\R7|+W "׫A1 }iK 7lؠ~3q@ K*--Mn[UUU:x-ZEEEi…ڱc~f:Ӱá+B~$iJJJRaa$i„ '|>6??_]v<"""y!o߮iӦ)33SahΜ9:xCXeiذs]cz Iyyy$?^UUUɓ'VG$رCǏWlllj!sѨQ-˥TmݺUՊUJJ@}i3.\sv====}MMn%%%ɲ,0 I oSCCLTMM*++777^WhڵkW=ۭ:r_ך5ktWk̙:?p>J6n9Y84ꫯ?eY ,KiӦwUNNvءŋK^-"=ܣW^yE?O%K"8?}ijdu$NIRBByU]]-0:IgJ:3466VCҽۣۓp&N'ȑ#կ~459g3{vvU-ЇƵ ~W_ݻu]w)::ZǏC=>sL=c>}5n8IWξߋŋuuiݺuzgu=t@ݗv;RRRIׯה)Sr}m޼Y~_ ڼys'O)ѣG;}Jb\\T__N[K;O?eY :|$,<+==]Hssu m}q1g%Kݢv4Miz O[СC/jԩR5ݫ' ,K:th@ߗjFV[_Wzj=u 7;N'?5n8-\Po|Zv֭['45tPqlaÆP+VPrrڞe˖^ɓ'rTPPÇL/8(vW^pڥ}r.\6lІ ¯͙3G<~EGGkѢE***ju̙33[>Q^=ijƍTJJn(nRk]PUU|P>h8|;ھ}ovW?wK h^ ω>]Z$PEEf͚I& vw|N X`DA,Al @[ -:P\\<p)((.p,I5k@kĈ`мۃi wA?Q'OpT(33sudYճThڸCyybccpB~e7PEEEa絚 v7tSSS^fϞ`0^W0ٳUWWɌ6,˺ R__ǏӒ()99_ۍkMMt:]ܬjy!>YHRmm>Lpѣ JOOﷶ#""~]VVѣGiRkvP 'ԠoLR0T0!ǣl-\P}ґm6͜9OCi֬Y[rJAvm}~xֶYK:V9RaR~Ǝ+ITNNn~%&&*22RǏW}}y P^^vڥѣGgi;vLUWW+))Ia(::KcmhTnBʽ}s @  ZL,K/Р7xCO<z!EFFIgzڴif̘ѣȺK}v]ve}>?s3Z>B%$e\.WeCQiii:v옚v[սx`0g}VKjkko}Ki駟֋/˗Q?-[/XzP111uӲer4d я~$Iҏ~#+..Neג%K4X7NzI{ァӧ?L˗+""Bo/[oe͛uNz)ZhQ})""BQQQQfffmg-k9"T'""B *--ըQ\.nP.K񪮮UJJJ8}Dߧ/Z}G]p8Yg e#eiݺuڰabcc5rH}2M3ܡ%KZYY}k_ar\ZpKK. 3f3gwӒ%K*11Q&MR رc}i2MS5kVsѣGk۶m7o^(رc۽N;m4KР={hѢE}B뼃ƌ;v(eY2MvCmtM7iΜ9S6mҵ^СCua9N%&&zjafffYX'OT||\.;^RX[[+uUUU)))I%MMMgZVRSSUVV&ϧÇKh;85550N,%׫NwkF֢E4w|zEMMnwƓdYZ~(ǫ!2y<J:s`RRR>.33Sǎ ./RVV9"04rHEEE)66Vi*..սTcc#uAvb7N僖eISRRRZzmu{u{mKg>@UU P||$ pBɓ'+0,{]jǏ /?=XbҙYZ'O֮]tM6-SZZotVQQQsw82M3~sss e)11Q˖-Ә1c: ;xڝx`FRm9eee)++ɭ²V}ذa/Gw gAIJJRBB;=_wEJJ~zx Z~LҪ͛tR|>m޼Y &hھ}N*á2wĸ8թ>9͘1C֭Sjj L6M=կ~5՘1ct:U__çxDsΕaںuk^z(--M:}jkk{_М8qBNǫdsT]խYzl/ZfxEFFjtjĈO~F7N_,˒׿uZnLСCu+""U!*,,Ԋ+oےK.D6mҒ%K9éYg#FИ1c޾h"^ZRRR4gȺ+kŊQ~~233Ν+4OhgR|VЈ#;q5XwP\\ &[UUUGy{ĉOGtڿrrr?lϞ=*((n?Y}Y\}- jÆ >}:mY8?[ƍm6k… JJJ#<ү\wu¯ZYN@ 0P8/ nviT?+N.&&&f@: ΁s=7]]b+...>An Dg+` Y,Al @[ -d` Y,Al @{6 IDAT[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[ -d` Y,Al @[p v{nY v@K `Y,Al @[p vkV@@$Y,hPRL2*}J.%ɪo)0Ne@ uuuz]?66V=nVEEEn:un<Oh+''GiJL }]SSgmatyF^{f̦\ eHr7]ދOq^W;v{~l۶MeK.Qxz`.yY555zBM2%窪*y^8qB_UXXӖiY9rO… k>_tTLINJ].Y͒L%9%I8EU*1Gm655iϞ=JJJG} &(..dYF-h=cO>7mڤO?#Fмyz|jݻWrK8{U[[H3FYYY6l kj}238B5ӲdR P H9̃P2hIeI=0\= vޭT***J{ĉӧcWfffLYYY;>/Xi;v7߬@ X䨱Q>OҙY'V-jؙ)˲/ kp"+ a2NybgvǔIj,K=%O`bξ}p8.^]]$%''kݚ4iz=U0DJNN޽{%)kY^3`P!1TnPI43;d8%#E`t'mǁL8ڵK'OVDDD&o[ [|NgxۦM]/+))I{QFFrԤرcR^^^4MV-f ]\fB ˒,4"3Q(VVJs$IcIrƑ#GTWWL!ө`0.vp8+4k.M4O<~xBUrfxo~/&&F'Nl>uEhKBSHOeiǎJOOWff'%ۭx2 3??e c0zY,@0d8rNYT5EVr'$K+2TԵ镕*--aOt:KBITT;@ >nϞ=*((RȔ!ϧJp%I ̔P}}| ^ǻ}% v-˲Kj\2**Jyyy***U{iY0Y,@晀ta8$C2䒩5YrůQЪ!)yz24WAkESSS[$w'Lm魂PÆ SSSN"""ԤnjiĈ*))t{_S^^dz2Mɐ\Lq&3$EJμcx4%ucT{V%jƍӮ]TWW8~n|>544袋.Sy.2 C.K:q"##{uU0Tmmm*sjn9ef IS,^C0K{팬{p@EEE,K111jjjRCC һ+11Qr-X@O? "lV堙%!¹dzB#L-XIFxvV߯?,Ҷ~俨(?Sۍ{8ַ!ĉM`P>O&LPLLLӟ|>*'N} B5w[Uէ"jwm}kܪԗng{.rݚ0a5n8yU/Po4|p%''kȐ!1ȑ#:uꔦN&%%ɓO(lA΅ kCOϖYl%'F~6jll˻̙3{箊ԩSzKݭۭ󧦦ꪫ҉'tA޽[͒̀QnnLҭi*//xVm_!Z|\u 7O{}bIe4{;ғY\@[_5Y,Al @[ -d` Y,Al !Š#\.7.sNsQss`weX%˥7|S[#ӧOv7l-::ZZoݍA5nܸm[ Кa,%0r-?.@OdZkZƵ@ode7;Bo! -d` YOO?ҾzgC6裏ݹƃ!T#BBQ+[nՖ-[t5h̙g? K4o8+ڹs[7f̘.7..Nqqq}G;ػw֬Ys_\.>SmܸQ={vxftwd۶m=zyd=3f͛7] #ZNN߯R 6Ld4}tݻ7>nA***G}(;vL~_Zp PQQvܩ;v}Q]~ڹs h֭Q UPP I:u6nܨǏ4M馛nTQQ'ۭ'OQ&MҜ9slYؖ-[4k,͚5+ބ t: /hԩrݒRmܸQ^W.k,IvoFeeeiѢEJHHtf/ \.]*++޽{URRW_}UW_}n:*(55Un'K<}?dzͲ,jΝ JMMUbbb۷Ozn&|>=ڷoƏߥݫ;CC?~鮻RFFJJJ?AǏPllfϞ#F驧RqqqxG}~͕կ~+T__SN֘1cdJKK5j(Iuw(**Jo?>+09|?oWjjl٢իWoWccy-X@]tt:UPPCiƌkp[ PyyyB+h۶m:}bbb/~QǏK/ry}ׯ_ru]*-- /J%&&jҥW:rjhhЪUt Yq_` Ew@Y)ShϞ=|;v/eYѣGK"##'Ntɓ't0 (;;;njnn$EEE)//OCn[999+%%EXM4m4y<9]~:yd׭H'OVZZ ̙3ua>}Zu+""Bqqq$KKKSii>cY>y~a]~Zj$i֬Yڻw%;c͘1Cz'tW… O!|g}V .Ԋ+5k/C=ǚ?Bnj,@HJJRVVvޭQFL7|9ig3O>$]{1c$p8xZ>_YYm7N<- СCzgIe-rx [վ}Z-tz=猹\.ڸq̙iӦu{}-4J: sՒcƌ5|@;wTbbL"~Jp*I***҈#4|&Ȼd_wyG^W'Nwv[~E颋.읐V|\\RRRT\\sp(;;;^h$~566xeee;ѣm?t;vƎ2=sJMM `뎞ֻj{iڲe'˲ eYVx.Lk׮UW];vhr\Qeex𹚛>633U{˖-[oђ%K4r=B@7nN:m۶iԩݝV~|>RRR$Iǎ[SWW;w4M?~\EEER+dz諭^ڻw֯_+2\]{=y^zKb-M2E;wTii,R ѣG%u)) Ӫtfױc$VQQ^z"-ߗS[lѮ]}Mw/^PP ϧH^z$)11Qo]vet:uW?J=e8˥I&LiiiݝV<,X+WJ:S?kƌ11BǏ#<'5nܸq|rmݺULTZZ,Xɓ'3 Cfo[y^effj>|-Z^zIr:;v[oU6mƍE)11Qsњ5kkeYZr@*k裏j;xhjnnq?x_tkƌoǏ+&&F/ʕ+??jjj_˗/o5㪼\/BxZVVN׭ުcdž_jv)0뮻[+K.1hfF!z4M|>>}U1x}n5I|8+t:tvgl2-[]F?!s_G}edd vw] Ћ/3gDJA UXX8蕛nipXnnݪ#GjŃ,0 h0}_Zxy`x/v:|r-222d?gB fd¢UYYtj P l!t]$ q ǏBMMM[r݊Z.2M3NlժU9ꨣ2C`Wլ]vWKf֬Y{?pMY IDAT>s;sm^YbXI'e˶6-&~޵ YuQc=F} _|}e2o޼$ITa7?7pC."! Rw,[Mn7[Y=NL,}ߕJ[~FXUU}+_tAh&M%K$I;444gɤIٙ{76mԩSS__$rꩧ>ǏGyd種Δ)S.Z2yQ. SCgF0dfb[v+_JM6='OΧ>~>:}{S.֖뮻.7pC7;<ϧ?~ sĉGC+35x=Qai!ew8qbfϞ /p?={v?[.W]uU~3ĉsy1UUUА}Ytin\}?=j5'pQNإǝqڻ} fqڻ{K !`߲;vaYvm?VJWWW^{J4oԔ$ɱ[n%IY&IRSS祗^JdʕOMMMf͚Q.-Z lΚs@_Yb-XM8eWL8e3# 23-]}}}>OWUne֬Y aÆ'?S.3zISN9%+ޞ]̙3$guV~T*哟dn477:'O__svl_7._,Z KQy\駟ems{,8|讹~;"7ai!0t[B`:}w@Q ٪U2mڴ;(,`L=طxzo( 3!3`PB0d[B`L=طxY@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!Y@!zիW3k׮3~,\pvիWg„ 9z(խޚ˿qsw93f},ݠ3K.a#>FTʱ[ouYi9a__߈$u3# #twwoKh___JRrƍJ/CxÆ Y;R__q slZ \a[.>v~G6uuuC:3q!#GyޯoG`ĺs衇r[OOO:::֖tuu7rjvtvv?>===Hɟ~קfewc{j@OOO3TpٳdɒuQ)7gִW^ɲe˲dɒL2eԔ>;+WҘ-[6SfdP殮=$OR)zhz{{;s<93ӓpSWW괶5k׮M\)2RUUUI6_twwgՕ8ju9GqD?Jbf:b9cWWB=>$ImmmVX1'Αd_S]]9s^H}}?/Ϝ9sޞtttTVssaÆ$iӦLgOB#68 3 yꩧ*3ikk9ёۯriӦȚ*o4tuueƍÚ7|ρϮʬY&?ӓK/4_}=ܴK_R.Ҽmomݖ.,?OS[[q~3{\r%9̗ۛQN6{p^46A\.9D uc#W?\}9ss]we9䓓$~sf98ڵk3k֬L>=I_W9ꨣ2gΜ{<۽ŋ3m/ SO%ټ{TJOO._~9]]]I˗'|~x?&555д1 (fmذ!sLnִ) >/~x-[N;-MMM9#C#sXpaxL6-3fƍp”֦1/bZZZ*/Zhimm믿^YNlf---[,̻V^s禺Z[[iӦ̘1#Օ嬫VVdIu7s vnq7n+Wn[pa_g?_r6QhYre:;;3uԬ_>7xc=\p9r饗n3kOkV i}vo/X455婧JSSSTVww./Ygp08$d x~znW9gttt!9#rmO<ummm}9pGpYjU%Hl^*k2h…CP~@ooo+TΑl5H?|gHα+?~|eӦMٸq?K &sc}c˷tuu /̕W^}k0\sMn}٣2ͤ:32ƺy;Y1[L7_pa~444r 7ܐ$$K,ĉrL6-4pzid___S__3fl|]7x.bM6-Ommm8ayG.\X3mڴdՙ:uj3u!rd׹3ӦMľO񧪪*?|ΝamX$3gK/Ter9Okkk]9ܹsGɶ Gz]10;jӦM0aBͱT*e񩫫l?`Æ :u6ǚ7o^&ټܣ>s=7rKsG;۹瞛kkF}V.USSקj?9x;r)sO-ZT2x H >lִgӦMYdIr 7 Sӓ)JYlYMV٧j \hL2%---Y`AؘSfݺuV0a„TWW駟δi*A\._ϤIR*F|m[,뮻R[[twwmo{۰s̚5+?|eVʕ+3{J,X 7ty綻`W\qE͍$nϟ PЇv~# l?rDx뭷f̙_;xYH1X 1cF=}MSSS~_də8qQ.3yJ;s!T_{{{N:}ݣ*r9MMMJMMͨľfƌ̰+Jygf͚gkrIN;-W]uU%^{9S$|{y7ߜʞ[s=\.裏Δ)S~lܸ1O?6m=Ɵd̐:csiUmp1lwCCCneҤIC>~ys˗2h` cyIi!P$VVxJ6v)$ɰ>yqGfUUU"?y@>CfjhhW\yYti|k_,CZOOO瓟dh>OdŊ93Gm{*dYZ^PڞF^R4+8S*r- edzhV^'xrٳsaeƍȩo}Xg+f57n\͛q 'oȊ+*_G>mn+˹so1GqD]:~\UW]mgqF8!MnW.ޞm;Y7nܰf 8>-T*mq߽UCC#k׮mݖN;-ٸqc.]oyHfɒ%;2ư7/MMM9sfeS^ȫ>zHaݺu< L9sdΜ9~k׮Vwy爏QWW̘1cv(hѢ1ɾa!kSa:8`Jc=B dPB dPB QTJWd(ˮ{Dy'!sI'eӦMc=1ߟr;#c=qB577g7nX`X`A:::z{_773gNߥ>=r򗿜kng_rǦf硇!=vN #Y=hG׋XCLI5k䦛nڵkgҥ7o^ns'Yg޼ 2eJvay{ߛe˖q3ȁ$sYgeѢEySOeYfMhѢ=IUUUeI&'|rw\.G͓O>:(gR.ouܹ9#А/åwO>d>NWWW'̡[o5o~s1Ǥ{"G۟ ~W_}u&N3}tntWfƌWkMŋꫯ>̚5+ٸqcg/\tE>}zn\uU袋O|"K.$'NLG?[֜tIbMF=d͙3(3L4Pf֭ڵksWnJGGG)Sl󸦦-"V___-[g}6'o|T|PҥK|\wu?~|8=iCk}.JL2%oy[ԩSswOϤI*{1S|g/=ƍ<ӧOσ>g޼y{djݲGVL:uill̙3s>2`ٲeyꩧ|$uuuYvm}Xcqc=6?peFpyɖ:[?vWUU-IϕvwwCIUUU>n7,Z(w^&M^{-8v[VX-)Jinnɓ6lؐ &6==={=>fʸq2{Ufk&N|_L/W3<37pCeI2o޼1]]]V]]w9䓳|\q7Yrcg#(vyGo}+o9C:q|W\ \~ַk6g}vjkku=a`_^}մ'TUUHoo_'`T?6M>=G{>{ۖ,Y%Klqĉ|=_|N?TUUe?k6k׮M\G $|MTWW/Ί+ UUU_d]}>'T~]vXO>ŋsתˊ+rꩧfӦMc=so 0oXZ@1Y=`FG־u`O1# fWIOOXް>---6mZz8{I1õ`O>}z^~477gƍc=Nmmmؘ7 r466Pxz{<9C3~ΘO< oB ќ9sjժ<Y~XgL566!s d0̙3go8>B(! BGK/μc=vbə0aBfΜ hllLMMM,^z)y;ߙ;ߟ;k֬ajkkK}}}7{=wA}Ѭ_~,! F#'|r7a'JR=|;OOOO;0.*J9r= Y0I6n}}})˕l{z=w5]~}L'd.ؕ94{Z Y0BǮN^ϡٓJ28}fd@Sfd>3@Fc)ھw`)3FYP ظ;ng/Ή'BεfÆ ل ԴBO'xb^{nq{SSSo5;7iҤtuu{ǍI& ! F$>XZOdth`Kъѷ;ժUrQG%#&|5v:ꨣ^8,-}Z  d8l>F;d ^Nhi!23xÌ7jrBK `S85FZ ^Nhi!287jG --Qؘ7.]]]c=v&===ill}뽞C0pMGt-'FQCCC~x===ާ&WΌ3'#V;ZNhi!s_c=׏p؉444dܹ;OSSSZ[[jժtvvS]]]Ə!?vWZZlgaNave9]YNªO? F%-3l/IENDB`tiled-1.0.3/docs/manual/images/properties/000077500000000000000000000000001315121121300204505ustar00rootroot00000000000000tiled-1.0.3/docs/manual/images/properties/add-property.png000066400000000000000000000200051315121121300235650ustar00rootroot00000000000000PNG  IHDRGvzƀsBITOtEXtSoftwareShutterc IDATxg`UEgιB!0iDʪX*uW_(+ˊҔ$j`zMy?!0O=sʔ<33 ܽ{W_}0̸')))f3xKZ&pA`0 j fBhX`Z@yVc{_dr4yٯm~.@ڬޘo9]? $o^|yw=3T6m5t5Wfu|85 a):tTS_O/OWk7?E1_}~%F>/;2Bm5* c)Zng|㻲OBbDcObm7$W􋜷6,W6 YB>%偕$}ɔq[Uq`[=F)<Ȇ #Y3m`zhݢI"5mm-HngQXƿ3qC#w'26jo?xDFl[oVXRG `f&D?Ҝή -EG~_5Z֦D{gmOS ogTS]Mo''y>($O5)~|u}+S&I9:Pf7ېrnz__t \޿ {`1jPHw."bzT,umT* iaM07ErzlR7bS?{+1tKخB'f&^u}MSu_§C=}ܱOL3y=Cw j]1rPbb̢þ}XY O:m7M_ryČklF0YdQul\(dp\I5&+P4m}0e{^YdwkJ`"DUZ\>[Nmݰ-(xމiٝwmxbrƚQ|Vtx[?ja5.ߏ֛Sy%~ }M:8ÿ'K۟u3ljOw8 1UAs&GiP4Pfwh}^z{C4^]2lgbZ|(d*+8g4EtD(G%!@NBƌ{߳aʃ(/m2Uywo9\ځ#K!tONhIeޤ<<2,jn2~.[ML/! īwX)!M}ܱ}~vEp Gȧ( 4Uft bf3{Fk #T.vn݉5j;>2 &Q D Lg[+8[G['m`6m3v5W݁tG꺺.s0?1]]x({Gd!@AXƒ=J}D\ӵD"Lvp򀤤Ӝ @ffK]n`Ϡ@^7#67pfoh5}\ !uQM \evG Ѣl@B$AЅ"Ȯ_4Ai߫of R@ȕr@ZǾC3P@E5˧#/z Cz߱1g$-N~!B*'ځ%h}͠{Ts]\=ӴxV}DOdjJ ]Ą_AGs$=Mi7 `D+kϒ~ssNɞ$¹j/?5ҕ{*ѫL"@K%6@WOqBQ%_e#4~ϷdklaOO!wX/Q I@K }.ѕ~7Zlm[7~W-|5TN @Ͽ~@2>4DG]X͉*Mʱ!$ON$mLH+>E&pEȨ}m+֬{r:v fW6v L#hSɴWUu1JeޟwH}'74<~ Q|bfncM3{{GݮGLM_M @]Ә_VN$ S%ٙ>XvAT'[YK02;\=M±iZ+޿V.YGOZ[c#{zˉK'z:IʒE2_4f=kMrIF:LsIV~í:8Ff{d3+Ôo  0nj!!q]$_gI^^^CM_$G*k^ ׯ/U~Œ IYdizɀR~wɊd\VP

8yȹ ڞ|}yt i>߽)y @ڢlc (pc<"=-; j3My_(P4LJJH$jM&ammmUUUXXD Ü}l?yҥK)bOʊUprr3gEQNuuu҂HLwK0U۳)BZ͹{yM_/(;s7o>w s|=ѧ t_߬m6b/^NHH a@wwŋr9RV766&''ݭVkiiiHHP(dWT[TTϯ0 2OG جW{" EQeNj$Ibz>0Zfaޒ&. Nm鐔.7%h$`O@نF!7e!3gΔdEdL EQJ3Bn9fsծ;i!dZ5o"[$RTTd2Bj:..?Ȇ}t SZZZQQj٧]޽ f!ӯ;wk}1CtJxf(27//jrJURR2yA|kKKKuuuHHk'NXVVvر0Ph2:::a> X ! ?y$07 'gggJUQQT*U*UyyiFDD@=<<BH[Yp2^H(dXޅswPWV% z6XP("""jkk[ZZnRҷUA̚5`0S\A̜9ut\nhhhLL {{f{yy6OBBBKKKYٙ0 ú%**3zyy͝;g۩+:=቗<(pyPVy8RRR6m4ԅ-KWT^xf߿_Tޘ8};Ond%`X0}sgH('S0y,,,:ujsrrBCC iiiwiWW` Òƌ:_Jx$n~ 0P&7x<^1く tttSN[ `dHP~0xqkf+ իo>STmN8a4f͚EanP8gWٗ?ḧ#+)Ӝ1__ߑzTWW׵kފrVsu-OZbxՐ xBhTdxZ\~0fT@4]+2ܾP(o0 SSSӳp떨g-pŒ&9^ Gkkwᾥ;vBe$e>sX5g k٣{w9boO ::]֨r9$5Qm Bh@J,nШ6}.ERw7)PmX[.;ރq,5Myk{MwNZmƪlkRsrW{o @h/ 9:)>ҕ~і~/wVn'?q˘lVMoe GkWznȯ26|'/Ѻ1 4(V8tWNRWi "s7Օgj[+Իƺ7\^jkuiW'rE%Hc#~)kAF!I1V>8Z+8)[g q$.|HnN&K9=IJ g;"2 iyX卤k +#ƢCb);[lMH zzjks~<}Koe`hF`SPt׷.3cS{+ݯ:F7 (m6ChW|kiho0]$V5TlǢޡ-)U^B<\kݎ7?{s$- 5"r uSH%1(jKhZ3-\#Rdӛsk R'mCG[ۡt=\C;s[vKDxI`M!9P&*8:*2}ȅ$cP dմkl_!/HI]xH~8 o?i$\`1 V5`0X `0X `Uc0j `Uc0R`{RIENDB`tiled-1.0.3/docs/manual/images/properties/object-types-editor.png000066400000000000000000000557141315121121300250660ustar00rootroot00000000000000PNG  IHDR^HsBITOtEXtSoftwareShutterc IDATxu@igf;VF0ATD.:9;O=ST,T\X`kf?hNKwfgg>yf˺<`U> Vf!O88PPc4] a0JM1U_Z!axR|0Y~͜mL$L*SgQ%+HoʤRN;| GQS|4z"Y'6dӎh5+xgiA#ﮍ[Z]L?iDJ[A>woT1dsSׁnq P4M6dIBg>۩&6Ǡxa1 w k:zބүE¡ǖ%k$i?H{"Xͫ_>1|(kP 0ö?mkh2#RHc} :aᗺ ssJMվ_ke"^}]8uMW)]Մ *MA$|D!kAti9_$Biy%mE+ Bt!VL !~S8A篩%5`p>wܵi.[K'Bߌ5 }}z:E; /I8ѿGW_26]ؖ]/}-Bc"_9eTyH|BIxBV<|an[9j̪[J!ri tD=-q1k*T>c3phU"+5ŵB_V96EbFxo9.u9r ݡ+Vr%_*Ӡa>]}\ E "5a؉Cgf*ޖ2Rh&/U?}bGRTFpĉ>ޭ[zG(O+o0e?{0bkN=A!ͭqף931a _k\!{isE3v=+z?,G@a,F;/ifrs'2Ҩtϫ㭨^Onoت\14u`νwa!BvTTXJo}z 3u #7e_ZM؆]%&dY}m8Bcbll]¸ʹec<$xqYr \m7^yB\SI3SUɬfJ mDܤԨ<*i!oWTO#^ÀKM-@8Be9tމxs Lv=ZNx{ l$őy.$-R2`ߥY'r j&'00̆#310L>1Od~kE:R 2Ns|]+aפGTϒ0Wn ~h)y 94׮C㳦"oPRh\|}زkF:Ys0De<UM'zHpʸyٖzh"7 Ȳ'1珛ID5)ߵ{XٕUeh~bndEOzRPG:2ض֌Kٕnb !31)Bh0lCLcoHPғ+IQazzpZy\8#i.4!հݘo!}>8[Af ?M=}&.5[aIW_|Ec"դ!l\DBˇʣP^ѰfɥRNOn+*F(O^q9(N.8 x?E(?M'g.?*'+B8" pTv7LhdG!*;3bT~vvpшB6*tpBټ>OҒS?c:7"@V:6/8pD&޺хJ_4b є^rm"h˭*b'fSy.S `!*;#2)$"jŻJd8K#3 E/:͛*vfEO}Q2IO( s0 G.?LRƳTΌ- g#2!;0B0-TG`R̼~3?[UާJ>S|%1K#~u,7R RCy4BD.Bt~v, њ?xڻ >vB:Y{d\~Nz'UT*O'GtartL}n٢}*o#y3/I_Ka٦w[nf1!O$#\g dBQ'iם7Ga {-Хm2 ~sC_z,FIT .Me>yꎞwŒINké-5BCCG#V'n,ȽCqP3P9TP_htAMeyQ,Bs(~,TfĦYIklm,bjEګgw>}=.B+nlܹHmJhxxdffvǭL-P?{FN[=#ӿgW_f2U/xҕɑC:Xo_BnDd7V[vq.ݦK$"6/5٭<񽖴 GFifPq_uңN}>T2Y]tv62tyiqN:OnT`Ը8|ǡo㷌'%E>4MS4U Q0@ͰF[Ey/zp°5#]8W[x^]>կc{޹MA0D"!T̘H#Z {2t!Pc0 ;gB!Cٕ}J螘:;֟<c@SSS B@ "D( "D(P@5H[r'p+_DZU.%Y~nؐU{òH'q\ Αd-?Lb_ȌKLJreB,!OGL?'b φf i6l]hMN!v&8ƣUQU#DBD(JiiX+sԔ?ʧ+< ?R]'^ B}u}Z<{4GbT(8s9 BU̹vǠ[q1unrWtPw|0$(G255š 5 "D(P B@:u 𑂂 B@ "D( "D(ocVuT xzzB+ZBPP)&&_׹wB/h߾}F(B5Lf5KZ-Bo̅ |9$##>D(T*R222j9 (Ǐ:~Kdܾg;e4;_O f ̭]wlW݁L^:Ά 5Vjoх40ںȄuѥdYix]ƥ O͟و ;L" 6,B'+SF  ʑwwkψ 2^>d2 $pK@=LHckq^/~хۖ2ϗ`<=s'2m;}F^՟j5Bal;B5sq3O%x/@eھNQSJH Ɣ[;rqh\k;Y*| ΧP.k;s[c&)`_0BUIqq颳^fz_?㖌6 _<7Y_/3;qY:At(eGuIҵu>6<tL=7]Ww#n!'v$OY4̺d|ʽrޢsk#1dϜT#'BT< O< ZqBxd|)6mұvCyeSKfz1rn-wdV3 6!ok\ѕ[(|T*\+3L{JkmP!u4@iQ !D)oQe Dzı}6vu!ѦTSsEv2o!4Ofv0D6&ܒ8.2B:>_HELt./$֖|*iJ o#0}BtLJd'*MH|cr]~ȤucO6{KIB4S{i":F=JPQuYgɜ تg -gG̃L1˸|`'eԲ\rBL8Kk13< Qy17RTeψ-Um>}0u;{;wK /t).Q` хyQl5N?0ki`TEp y0l(JPS8S,>8K)u/bc֐I 9`)j(\$a*8St}CTXHUS .V<0_[r, jtyxJ!m+q +2, h'!u48q&*k0]ڋ㙻7 MOc40<=~#j]_TY0E^}K(NPH4nn!aVgVUS!'e A @ Kv1oRҪAEaT~bmJ3TٚhP;_A F MwoRKi7izr(}%'hg1vvvum ߐ8[9]{*`v-8B>Fz쥝k5,}c; F5.n8t:v3[(HK=ZBd~x -ж]_Oޱ7qd,Z83Al.}ZcUYcH0괳gsPz8{;fR:u9uXz֍;nu}[r}Q2ǚL{Ìo|]VLhRJnԩSM6KG#eƥ#Wٮp>|Ⱦ3STP PA+&_2j[+0gURYU9M>pmG~Qh[#G #((vN)K(3_7%(N~O!pik|ڈC3yv& ߤionU`ߜ%";HkO \ToOyϒ۴22[3h?g]/Än3|cWΦy?o 𝁑6 lV  B΅JHHbO<??Z!7222|||^*aaap=H,--3xǬy5'*"bj @/jx`BZ j{ IDAT{p j@EDD@~dMQ𽂁<OhO Z6}}fjrh3#vͯ_asȬjשLJ׻M6^MRehuՐ:is/Qp >Sbjaea)tZ93i׺tQsFttVLSD i=4}߸ſ}jɸJwoS IE6OqJ|0՞h ]ƭ+aJ\WIgE6f}ֶU>g.`4eE8B^ \`^&L]WnjPSWAicJE/ϭ߷}+֝ ŨN)7׻uǁB$kJ`Tqkzg-3tiݦː;(Q/N6-| *Q9GgFo?+Ho-?Է&lB;PkO<. D~Ӯ(1BT~l[ʨM C&B!o]|1.*7"xb,a6ŭe Axxm'.iǗ[|"9{ ZMt>{r+B>_7}U-6 !0+up.Z5ƚ˵ɓlӨ3i/%Nes24[=>;R2ڋY0%2FQ\;*+&n9 ,l5)s4 ]RILȸ¸)Bo/|@3x&b!{Ol `P V37"~j~xdUK)m\>nԶocۖ ,\@ BWϕ.r"OScZ|(M"v1'b)j {EisU$ oOBLHMf y8["(eSo["ޓXP-UڍdiKgcĹBHvmPd|mԘsōtu/p0uBvsa\3yQư-m%Gs4$ViN {6r|಍FOa;mQʨc?|yJ*9/:U?c2(u&63xE1}Ø|>˾i?8[&.VNU<3[ B˸YYzy~q{Uz5cuGvvlAK(JdX<\cD4l=G v26[MQ b{63Zm,*>!N|ha(kW>4iVاh4|#\DNlƦF:}l/9KdZȎ_x5gxb}ZF3aGl=N}Emˆ(.|{#MUNˈe+gmց!i!hZsqwS1ZWDh&zEi(,{›;k]N%,BT}Y0v,ϠG*QYo<(yV;.BE&op^[C혻Qm9Oo SИ^q80]&&u opjfoR%FxdzcʿR-'6b7dcu+k޾$ aBQ3wdtz]J@HvfⰕCwa reEts楅j: ![UP3Mgs&Tj+B!UULIJ<cp +jf*B_=N0Y3浗U+Os4넒ZdJ2M{o|cE8_k Ep][l*Dlgs?f.o֟Z<m~laB8ck=8~pUMǂgeBK'h(B8\43!0dv?ۯ8M+/nN1n߷|.n2hz\812V Ưo\wBtǡNg6hk®v貮lӼbS'4T6DlLez#/(_ʭnvc{fѰI`Y:6m&m3y{륫ZM=ɛ|YXLS_Ž I+f V|@`}3?ר^`Dji"0_8=z1 XZRofELk=o KV0fl49 ~U [9tv" 7`iqwl+״w'3j _7c=j l, ԖךV{>Z|yqYO+{5 MXhu.m{/!פБp @9pmE v=1s侎W0.YΥ8wG,>Cr j+El%dAbi^VUa[[ۿmHv>ImSg} * )Ҁ& إ6n?tr c7[0-M!fˌںj.F ]]7, !wG㜟g7͑ D(P)J"Z1xk̵eu?mX[[?z'MaMhÄgjzӘ!9 }~yzSIf~3U0vs;Ϣ .}:yR>-4shu6uBν=uTlMW l[ g!(JJ׬z,#/oçB_z *&=y>ڿQB`5$,JHK z5/xu]ė#mv}@|0U.f XJ"tO,k4= U$;g_U?0f'&dI^(fr 4triNrG Rfq'_r\K?5_5 bb! ޤ'R*=&O*;|$+37Oj|qZVR68Bo08BWgKz<BC.B2c0ʎWRX92jxvEBWa8["+oED9˔Wvc;édtBr޽]tqn;;Y92QZzgEY"fKBl5(Mf 8ogIX8U`-5P>>>P/PM~#|ѐ͐7&_ѤB2,*ƷjeqB!FH$>rjꋖE,iRl 8ze:KM3fVLQ,+fѪ̲%d_S26AiSkKª8KePYjoU|Y`y ]F,yd^l^y9:FΠK@甭HM*E ck/˷V\c3|iP Zw4ek3YzM,/+\+aIg1{rUCUmrsLZn=VemAiRo1Y*Khi!b NnB !2oI.NbuX26܈݄]*c.">S&rrw5f_%7bJș]zгefSR k?qU:54Fu`{W:+8 b9Ao;"^G ˸8wƗz֯4gq,zqi}C:s3`B&C9ҍDƚC&;P@XANߥX2mpy~wW۵h:âïFUn!ljCBS{Q2h>e Ksic)BgJyY%7_g\۾G4<'x -۲蚫Īa9{Յ>(*Tҭ[ z+PWBEDD@e~dM6-Gq/TXX%ɬ)Z޽{B~~~Pz𡫫+O%44VAAA03 B@+߆B8|Jvߐ!/?pۆ W~Oõ%B(nK<;1B 11?F(k!P>i[[Q"[86{ZTol-o\hGg{U@X[S<}EF;ǯ۰DdjX{|h阞}t8m$u꤫!3unʿ_=΃ڌPS(cUܦ6_ ־wn +k[*3q02x" X/tq[/.+ OcDiqnE-4%Iq2t̤K`;GcC'9ObbK;u#20y#+>\*nM#.& ]S~c²):bl_N \ҥM^8mP^m: 3&#,̸8u=~{BOf\}`){st[]1~k-bO5o"`ʣ['`をi՛˛f:߸G䗎<sk' ǯ*YqE nYm 5qg R^{vi *nr ]QbзQŗ`|NTpPV 9_~,Pj䙝w01Lv֢Mћk۶d:Nhs6𴉛: KwN왱œLcR6S5!XB<mOFe?@|hsQ˨+8&ۺY@%;ʇD=m"r0H7anYW,Y5-r})pT˦,Baཥ \O`Kg` ,3WPڿpq G)<ֵ.@&{cD5nkŔ&[MB <0x"&(m$X Wqԙ* l5ʛc-c2SEG(L:6JȕFVxdGLǾ ?*_I\6 _2,6lj9F:n9 س>Of?'0b/.lNCZ! K"JU UhF+~Vߔw%Ui*RhZgŕyE$%wuܵoAk=h„.OЕyReHB.7DlLPhK6,+8G\5PIi0]v38KcPMyL4ĖqDp86PWL!D(BTD ˬmyB!s>ٵZiZ w.54!avTg($. :KM3D>O9FX GQ M'ImnT%~zdlYϛ ^'b)1lmfBXT3}Cr,r(;62bYf6Y*4r8NS:i_JW#iREVR!d[eI w-5 c+r&r*sEiRx˶jcą8s_xSr?+M˩C7/su!2lH9UrU4yҠ0aiŗ҅ glM9pPb4j_ #yQ-m80]&&u 4ͽϔnNֆ_]Įj`Ǿ?1Yc}#>s7c61posʟ{;jaj;*p bcikG4!mHPIDATh.gߗaaj_3q:+W^<Ј^vpuAK' @Wu떁 T%,,aKÎȚ6mZZ]|kh4B{;|; |oP;+r B) (yR "@q&#|D! ruu"|Ç8|B8BEG qtrPZ3i" B ͆;\|f4Mk4ZMWqX,W}E(vP/BdggkZl $ E |gtO@ Zhlll|Ki.,,WT`:9|oH$}p)a<z('ŸSl]1D\ۻȵgEL-{W!t'Ə?:gHoq !Z|c#מ&jbc[Guci3qRdBgoxww!/f*~b͎K*Yۂ=%T& "D(w(fFsiOW.ܰ80v6B*Ab]Ka+*"8lR+4B\.iG,uytmZv%o"-=dH]iu!?c)#ǵ:NwVr玝f H~d souaՄAæo_H#D3U*!dhb_Q*mX"f6.d'ex#]x&viV8K. Ζ R*ipPʂ;~Ԧk9Z`Ft2$?=3 K M?6ecG!oزq^xls͟PT1I Jl;ǎc}xӆ9!9z^e'b".!Zey(ƶu._{wUuq;k}aB!!(IX$J*DAH )6B VvVAkXpX(LlwŁ Yg;wy^9m:nS"f=VrɭcH,r|;LUc;)'woXēsxŝʙ^S 9Yh^\b9 hdst|ú*kP;w$.e-o{$DD>ߜq646T@w]t9ۊ7~daFVb;w&jo}c"{ cx5&ބFZ=t:kͰ<"jqW7ޞ'G1Z%ZLٟt_70ޯj:]VúO!3ǝ-C:J/Jm@ 1~YV`h΋MVWg89UM.)V9گ@qf ?2τovmPi鋢_z}3;r]G<B&vjQ7>| 6?C%9,-kAՉS `͵LJMMMOOyݻwGGGGqB>޳gi  !~].WARTTԪU+mλvNNNII >hU:ɓU @PD(" E*J/߬(̧fQ(\~uм1 JQ&:P@ݔ]f<:(Tff&GuPf5'Lg^WN(?e E0 W,1 (B 9.ٞ={(BKܴ"h BPD(Sa{~8S1&t5`]6u橯/UI>.Cxs(DQB3Fnn(, Br|73'0e=΋JfDQ*U$WjRl|hk~OlZ?\#koYWӄB&stԉwGo|{i 4kLr)rre`Z?O8 oOtw-|wxbp+S@I+>OA!9oa?㌓3B !%]SYN|rQ%Fyl˦$Nxn/bZuh*r1 mBٯ L}n5Szv?r&Kjk~4l]  $EyGu8-oωsy~!&o1׹hvRva_ Js*/aLF(<Kj}oGqL㻡Zޟrn׵ŏ;d6Wdk6ki/jT9bO"C{iv~t'T2OG!Z9A 6p_'4OƵG-~>4Əߘ9MD=ͫ9N[[̠;{YuB!bJi^@#n΄a=c~~鰛g$0P3ݳx~[Z̡{[2fH ֓"CTLqG@3Ę )I挻R@(.?)k(yc L&uq\\1Pgṳ^nʼ8zBi9Bpу"h*l^S!Ak3P/:nKP@(O_vr<hB}ٗt|N ۚ҅"l(抉<" @h.<%8=qZd;!?Ie ŹJSҴT^I178K4FN˞}Oʺj˹JfQMf vo,)ۿ0D^i7;D,q).yVCm6h zK fxV/n1!L3-oGX$ ~Nͷ X=/}Ex 3 [~/Kx"!^GǶ꫷"P`eTs lGL[!o1- s$9:TVikO\ƚξ頪i8k!<+~,YJfN,]B@!gnҫ k_ ٧yX^o/z7"/M=1szv/˿qm5xNvɿR4K|V>=-ۥ;מ M7~ahJ^t6:|Yl?)6i]4!дdggS-4B֭`aEQ+ )  _sݻ7д0  3 FjhrB}s! +,,x<jhrd2aaaNߟjhrB}N;R,11111: B8x;cQ"yN7GuPδ !EZPͥX~_ӓl޼hb*%%J46\@ BP Bԋy_9e=Z7#z?K4z!M2BsXI !4;Q_ IBGmݺd&rOIRsos$ h:gE-1B)[Q܊x@k?.l&Ayw\/Taaa;w6}cO[<.!\g;GT:fQI-Y=Bv馛.c~JNNt4+#OVI* Ԅ(Q=B"ۑ;B+KS_ݑQZS$dI*@h& M;K4 вS/(JRR,״AU}"%R2<҄&4IV>z!EQJJJk&22RQ@Dn(٬wɶv!*OBc. ^z!UPPtK>{]j[*iWGu !U}]Z}ZGtHVI^z!EQVBsy:K"?D(a Kض@ӈ>[%B_gn\lnw^^^}`@B/}t+LQ?ͫ#40`\|7mľ6ܺ~j}5yʴyMݡK#S$<4݄ ]u]_#Kd2&A^:tWq/WX}!oj"$B^k6޺SX'D%Nt5AIWbn#}w@\=*g]}'O+ Ջ)! j)WYwAGO܈/4y.g̫l% oȑ#&yKt9&:i)섆O][pwoy,TcH_\OV#KfAlSF_eVϩ|y؇JTOJwNf|]Y\+'^KBjs_z\@{x JKV|\Xb.dVԪcM9 |%TQ*CޞW+H$9TzS fEGhoN"g`hքll6iD:ʐe+D4ę*}4R2lŨ=#;%%a2pgU*p֏Ǒ|[G'k ׀3Lh5ePh%>z.1`$NI! קhb$_L d(P`icZ"O}jD;;Aŵ.j):v.d(;̎0UUWBH_4Yɴ3dMPhEcY3[j~[/A0-UY8O0%}w''(6LD|J'^~7wV[W&wNmA;U.nË_&4Rw^ϞJyRذ#CmW;zeAV>U ^"eV[Om}- }oigή3\b ,SsC^ct&¾ #Kd6M$ݚb7>[gI]zt 7׭o=tQm$v *]3wns6fVJYCʍS7 Tɗ9ԥ= :|q24o:$ZU{U牋Tg@:s`<U@@@@>J%^~kB_~PY|]ٳJvBH.C}P 8@@〯T6 T qqqR\9}EF3|h6mXzccӨ9-*tC?f;{[|fqnG૰pAcƏ=g Om7]+0~VZ/<PBCƢG7siiRȺT#HO*Ѽp;K\I|d_:-PGE F%m@ʀ 6,y17KmDOo{Kϋel)cк{?EF-u5ĕ#:auޣOo`[۱^U`(ӕѯyמܸseqn;qMJi#v!c^y`Cn/[fVpKXvԍ' BFkٔM= ֤:{Z\E <ӱz6]\4sBQ9]8Gڌ['!{t ?8"Dq gy w 5Xt;bo ͺ nPqڕ%S~h`W{?S;Vij{p0D<ۻ|=vCY.8n6ҋe^\mH3t'ߏk $r_X?:A/eɚ*-&_o_q+[Ƕ0Ƶ+KRTB[Y 6cQ[A>XϯdN=A~,їҌA E^)Hau,ڼ{|fPgkL_S% W1^5tIQlWm-y0|^;S Zvmp?kRƱ R]#-:@)j C! 8j; CI~ZJS.**ce˥^3ڡ9I y3"Νpan+B*hhhhBߌunΫDC W[mb|q+:SK J]. Q&u9o*А]ΙWڲe{؇J"n.d !DFתJhI<]v,vVfˆ6 rUiW䔼ִws|U@PRRB['zF'f͡IlmΡԔt[t:'.ƲUۆA̋\ʫ%듂aDZH433+))82je|kQm%cZzr?@3|r*Nշ&eHmNʈB4hCѳϋ+,jB 5C BR)t:d% _p9i(O-1 0W1$5Kkma#FR,4:XokΧU'oPHǍ8$).+1-O &gf*umͤVfe#e6?_#RNv=ɷtrfbRimpmjF4(.QϏNL/P1k_,|d?z|rvwa3Q礦SL%>CuwE?yM,Hy[Y)*o&.,JwuwtgȠ))N2@Ċ_naaQ2ӢN/3*jDNNN```-qqq^)u4)98_i[!0Dha-U'cYyq㺒ܸz8NP[q~~~P5&111WJdd$q Y)41V3ӊ/֎XBB@|кgyrn0KjS`TA~ڴ%Z 5W-p sPzem-ά;Уu/Yӌj]Aq *vk⮳7زmJ'>MMY}u.G,T1?ju\8{h#ßg-R`&$+$ hnnGǖ9uʈVL N]}NYRh眙U @b/ԵwjX]zEvn4d֢c…w6L@C_QG]{ sBxs33 rKSnIZt1}r5⎻/}%.z5yiGmw>+- ^EW%CPVeNқ$,55y/<^kG<|NT:SA5f©.j"%Mᒎڐx\#SyӰiCZY00$Z 8ha<1bz@ǘ+.fTʟ[`f%eLt`KY8( Mkfn|~b*}2-K?*$,x˺2[NY59L1x"&Ѫ|$_Kh8ϭ -|Qvs 5fӖj%:G+#;wEZ~B@ =+G1e`h(B6Ocdlac8BVTw͈D>PDR금eU+- @K"1uKLiĩV`J[Q[pBTq1dc{gQ.;/1֩j Yu#]Qa eX8iu* ,zނioK",=},R8ҼUpMP| +Q yiH)]z}0qJY+EJh櫖ôm;egVm%F ,Qʔd_&`jhKklaq O;DU B!]Gl̹RQ&],`K6B!t)]x=[[5̱?ˬ{y:h'Bǵ_8wڼW׏*  ezkô̄y`\hOl:N|ZĎ)c5oi+FU\<~]灍.XNe<®mo(BlP'kFYN~IU3ϙ6m8iXφ6X;XC Β&LJa>eX̶VN]:1!n:e%g6_Ulgva`}nz ]k(+Z7hՠ轵I'/n;G~w,]HHN D ڏ1bG8gSozbӼ\j>f/2W 68Kdd$W488/gbbbjYq!!!P5&QQQWʡCW488/ x4MkZZm0*݁ .b2)9 ;N[оS g߿YHmɚ?wn3b_Ro죉_-GJ'222222r*#777333;+KF 5|viլ͎WszyP{l:mӷ ,up[?dӨT*Zr+4*Ulލ ߈JZݾ=l2u&5ǭ}aé[ !"#qќS?eH}Ҵ>5ͫK SX"H6v[߮a̿w2jQxnղ}BuZWbGpϚ !k_pr|#> vVObO"J<3okpT tI EFŘֶ!cvfM'v^ـo܎CO/0"0de&θЯsmV v^zYdPl e`M>Z[9<˙i3|:\Qڿ*hR?{b!=՘nq4IsAۮEQߺ)kv֓1E-DOl[Tav6ɑ/SPyU& .Q,Uo%4*>m_}2tpSV?$ܐMZcs4/m$7 U!Hvz3ekVNY =]iS}7,1`iAKF3mIh*q4Mcyֈ &#^6P?h\YG >,3 WS\^2d^NVyBHs9i(cq|+b 0 iayQ [wbyxӰ {i7.r+N QԤw]ODHh]ڸgcuM[M% }QfFAb EQ*" 3oޚhrviiZMQ&Uи2`qe] NpdXͧ"U%dld^W5=EۑT²>yvy.ٴƅۋ ȦFLXU%\.MLL0Ur/^(t+KB*ͯڣGoJkZJw̘L& C_ X,|@8@@4*fA|@_)mhhh㳿E;t9{]9cS44clgќpOd@ qڤƲ_=%Xj:spWm_vV{_Q~Ǫ^kh _ESFL_uæǜٚMs.GUc{ #v\ъaȽJ]c:0c]8f=/¦A:q#3 C! Ázud!DGEO:{]h2{?aPN:t='^*fb ' ѩC^FBE#{w29l:mNmtuz͹%]BI>oL@@!ƒ{H˹\vm/-BR-Jz&]AY4m$ctnU[xz1S  T+;N dmk :)CWON>z\hp"BT~ g=8ryĚ=a"6נפܒӛwo[4΃!7r ϥ݇p2_eYɘz핒~Z4yEQ˅?ua2F' q?\% mcdžajsO>\[@nbfko5>yRkWbw~ygR% &(76 G ta`9 P2"T}4hx_!8tػ7q$$w"$~ 5m~1zI>tK2{q\,00$R)!k1!ʄղp$(\kęk"B&h)D 4cnv)d2_K>P|UTRXӑk4c@F?X Ƞ2=+bX7% YPG'tA!Zp"5:?CiBC_@\[3 LQo1*ӔY)BR_urb Y8Yb6f(Ѽ~DQ"D,0jeǑb?7>{Q[$[FNLi2qd:3Vl?|ĉ}Mg Ih?114.յ&33t֭ޗIL+N(,_BUHsO)K/Sʍk;.hP|UsfWv*ސ}ḁ̇̄]{rPqT*xq-[w0&zNܸw6$|aky/?XpNΏktgcu6mKA⪈QRl@!,O?Ҵ"XlQW@Ϲ##ʭI1rk5LWEsrG-6ǎO+RG>mq1-^MXyD<68AH'`/ƍ,| d}3b_:5t_)zbOoQ+Ö!KǏ7U C7$J{[Ϟvʦ lɽ}xKml!\pP-@ֽ8+Rny@-sXT7C׸~ԕ3Wg$v5ԫM-q+au,د Q=nD1zM音薹0Sݶ:<}[Oj;g17\*3u;s6Fwy .sXԍC"Ķo":w}J*]e%qMo0dan=ua+tAMLq/yϑ՗ЩNY#|թ4jXXuAtэ)Clg`CΙɣvq'n^DA`%220DNgt-U:5!ELp иj.g0{s`€G}s]D9fƅ@|DEEA_)zw#L$P444j\InH~6CpYOUH➭3|׬Dw2*b8sX6͛6 wQI;3?4$Գ9dȋZ7WЦ-:ٝL1wHА΃goT񣃋Fuk,En+K2$UQ?|TL|0ީĆo K P KFt*C^lmk'z_5B[63.*v$ v!߻~ZbY5qmڍ[Fzr~Mv)}ї}}y;50E^tNi_zAe4+?&jPgBX}p^mu<3"*ܑįvlܢnB̸VXs.S6#jǢ;7 nѾUg5Kbȹ/D2W8FMWw)4<>kĨDټAa?=Sikk?Ө5mڪېgYEyr` ng:9ɷIIѓ}ϹB~>&^\%r=bUL$,X[ncp7p?>Pem4nSBeLz3H-V,E|6c_"سww[-w1ihs{) uKZT(lK6) tߠ[ƫfQ7-iL=A!/b\MOZq։'/RÊoDϟ;cԊuչde]Cr2|̩EU! Bߴt‰%ֿP䙓%_-|;JsvQu-KmD}ѳS\~Ò/ tȩ(erx[yr}RYWu0GzӲiM6\Bټ]|ԒU` 2 l07N񳨌i.&}xW~0V{pU8hPO H k <Ǧ3[wr?]fEΥK?2._"\BX24!82X3^c)F a|6. Ls{\Vx8=|`!,ݭ5}膋Jϡ#k$tɓ-K*Fq 0#E vwoRĆ{7O\{ 7sp/>gKfhofvp}j5>^$xK׹CKײm-_Tu Zv"$!jGNZKH"\8UmQӒm(Iz*>{Z>alyoGv/l-Mre@Ȑ}j A;w udr }q[Gu;{3f9!\4͎ g$鞝t}!4!ҦLeD{*f])N[5*ӯlof ۠",Y9qpK*v۰ S֝qq[54;cK'%MLwēUhVvXٱ+(iڽny?m­NpeG~=HRGVS~Ea!H% u[VCK=?XNV.%l}ٌeġu8BgYڋlLU-.\_n9{u\)3F73|Ƭ]uϢŸصaEs>Ti~=z@|@`СC_o 8@@4*[fA|@_)mhhhs84~>g/=l*D42d0jۺu}|CY"+GMrXm7 ;p$|5z ԣ}KfyZ|/Go')M˦3/jߵ|)tvsט͐'ɑNx=J*ɭ;Oގכ6=_uYкk{(]Av47@uHYP3ku3Pɻ}1 T:|cmltRmp1O?uosŗ3EsKӣ)b6lfcKM@G^>hzL=huًl;fq~_<{O!vb١Cϙ˧b;ҊM3V:qwD>:qlno;y;Z1L{2)n<.~z_LX2Y,y3bv&$4U_' va#$.Wi_Cfjn٬ !iwY1o駠g57?C߃LROߎV C՝W.ɆP]13y6 F"}mg(Gfz4 B[q'>2wۺuE 9#)qnx9'گE3l=>~^Δ+BPwT8OP-eեG"o>,6Dv>G 1ΝI4Xuf1E^.x0Tg [o{d;V Ie-Mڼ:0b$kqK^#z!}̓G'+p[wf.9= ̼ jr?sPg\|4jfg&ʴj,;t"2IFg]ε k+w~VBRmƨgV⒄ ʢ{#Yigøέj .D_A(`hb[XukAd:eݳhu Oh Oۢ1\c1i߉šGi?OM]2/X ͅʮh~6ʧ}>RTq1BJ׸Mn8f0F(E|L%h-wy4`lKy2nL_Ѯ3k͝u=|ٜB/ߌGK 2ȉY%a!8z㴥W8Mj{zry _wn\֬9+gL)iTdkySx?U M\^G8ޖk|H׌/3 x Ii*ʍ r@8Đٳ'20,LJ cΥQV,HDv6Cjj?lgC"? nBK`)HsP" *Mep$Po(qyP)d"mBPKW6\g`[oNû^ocDↃZ쟵ow]rj8:jbHؔfӪw0[ߟIv>oEz'sk5l~[m=b)Us޸5|/%~o+*iF舶.l0alU;O.vmsUᒙ筳? k0ֽNٽ:շ(!7?8X^7:j?iH_Fkc++ ڭnXGa#i,ﳫӾۂ/*yv>mѯ2pVͷ2WM_hغ%u\kы5r/yϑ՗ЩNY#|'uU jM 0 U44Ky՘oh}888888>;ohk)6AR%d/jD!DS0'ի7oUMz}zzsLU!F˖a... ˪f}k(3->Ii@$G s(/ lk|x+^4>OULl[ߜ ]߫Ʋխ{ef(J. UHxڵcXkZ6@9˚L/PoRWvl,3UMFr 9ZJ0ќQAj)u;П$ɷ;kkJM.Ps's<(_XBJbͨ+OϩqXP~A3eT?yx:;0ZUVY^ lߞLO)Ri<8o*MϪr TH6榥0qMo.@3W?To_:!x8 7gQjnYִN~m_ۈB3cuz+ՊBLC#(ͷ3 hFUUUbX ^e]&6h1К8xgg}_:,qkJKXXr끉=nbiaF#lKəS{ nZq1_O\3)k=7jwVtӀ o#B*6QOK\+H@Z3?[w3v{ѡwnyȔ5Kg\#xӕFGx=o{U4_5-SXߍ'~\<_L&凵[= [s2uz'|`hg/5pTzAwx7}uow|5,sg[p GӅ.؏?={~4=ts/r kLO}Ĺ_rrՔo,k=-* mkv0SX5UUػ ~_e;{K!u"/Z)O5WeM"|&E"Խ;[9Y`D!>n~CoZ%8}!ĕWԚ~Epkx{U1CUi 8'krOJpU`ԕ/W6m΂d>kMR%hq],Y.[X]b|A x頕g(H*]-Zja Zzsp`͏k/?ٹ_]6w tA$Ef|dRkz,jh @!$RR7Ta2Ox2+GH=-ab'weO;zơ ,uq `U%Vǜe&yċ @Ush;ux r,ۿ $?ZVLىbg`+IČN_{ð7X5EiD4Qж8!w_OI\3k x*0SI֕ ~9a2=5qɄ͡Q|1~Tso޸K.&}Zbc:=bn)娻_PBqE&! s|b(P$ jeYs2y{޸j}$o2q/Y2 q lmsqZDBQTvv6A\%w-_D"X,c/UiZlin;JNNp&hH$DQGqǥ@ӴZ?|WM:ZEeee81z]g+MҠ)v6}F$R)-@+w}:gkӡ)ϲ*$!@sScǿ0t';q4WҚI8T*z}@38h\lh28z(GmSk_XA,UKlʲlgVKm- 2̓?-syu`hpK.yyyCP\%${Kl}GFS"$j?xǤcs' ˟^%\,{=WI 8-Jmz ZoGߠuUk~)@V22IbGU.Vt6d˩XjG]Z;)o&&qp^Ӎw!\$UU2>K\aCγO}%D!p<7Ez1L _?xõwUh pM6k1mڴ\|3m:ʜLGQhGT$*Bs}__ݏ$VQ!-Y s.]Q}!ҮMh{v'3t_C8=Rc58~Q*ja,m\-fnaOGڣf\idʁrDW2ǫ;G3>6y=A{v:5o!9yTc5,)Z_k߾E:C:~^06RSSe2^OLL||ܡMMd/1놋@$6̨>>?od a=;A(_N0Eǁ?LR8h4hPK :u<E.L{wAs{%,IAt$IBƁ?nM ʭMWj$)JpLM1<θYiZLhg\LL 4MT} Tyo'_?{d!~>Am;=9.i2vHnߚ91{k5Ĥ'1^$Bٳ7J(/tĔE3}0}Q^4JL"&.L~KoMutǿߞ4b66@ &00B(7_|+=x˟qirʪsfJ#{M0}k{4$㙱+J6_wgϟ٧}&ȷά^x`ؾϺO웗-YﰮouĄ`_))>f~>^\[{1ڣWVQ%u ď E..|&djue!2Đ=ۤ>m ߮kMa~0';{vs厬z%!F`D o+27 yj}=a>~]Ҭwʘ}GEwJƥnݒiYbXԄ?lt_Mt+ꚲmD'&EǙ}/-ڝyb-Cq!eoɧ^qŌsg|w_-soȶ#||_;&˥ؗԦ6wҟNm3+ Hxro;d3f>\#`qz׾zˆ/\hS?q\5e!-dmmܝ. }*zn;.!=o;oڽ{AMXiN?N_}ͺmp¢K<>Me;SWol˻9[kC_go7;wĔ:<~~cCi/9rIGz jr?Q^d\Ms.jޞcN}v$nȤ[ dof[WExsuNx!7?>8e(P=?>"=mfXd4yH=&HdN[-߼n@Wn]"L52?OÊϒFxu 6pfkH]w7b6c1wӿ&C#TdX6IŹѡv:qUe8WREV6- <:Z]38 Ź!C(5_uRw(E#ZB*FbO^ԉV4 Օ?ZF>]ʥc+#Hy&i{WͮIk659%xQT0wMoS-HVR{>t#dARO"{ѡOn{,5_kf$ Qa^]7ߦCc9n_k"G~Vbu7`kil MWH ~tp ['n[qf]37qΪ))Bb7svsTDĶ%k[jy$ P]mᨖ=L8K3 ]*5{8)/-(H*zku RWH\$yCmlv-}W{Fwkj8CSoVJ$E.Fea翱헷Ν`b|bb$ czgO;DSw_ ھ o&"j)! 5T7whBF "RR-o2bUs} g+qQ5 Tlm8yVn听-ʸfuh+)ߘ>/2ȩ3]'}hgҁY74LWF2p1t-8SܼeM\Hb%˦~n AR]{&vۺS2I3T!)-Տw_;9R?9:<্+>5au]W\#&KRr&ܗBq\;F]8c1]T%4 jx3tRm~xPpOxM &I)&}Spxs+L2L}*ʼ~%iOG8jw8nD9kWn]b4O?/4ιOqyϑEeg_t167fYj=Ks4N{ߏ3'8w渾!JܢKR1h[1fk/9n'Aumߞ,rpdwEn#-c]I&썩rl-ƵhWU |ٖܭ-/2p馷9bH5`-YS%!y(_&M"_۹'Sɣ~ǒe/}&#z#mFU k;wvNխ'6FvrRŜJJ:k9;;%I;}nQ݃wm-|eػ9ϛ;_k_-iOib|y=WkԆU[m[[3g[a#fLCp BjA@ \[pO , _e!͟g0g_^Nҭ> Hwqp@5Y95Z7]˱WZ;=[C!ZT2hYBzՕXVm!HnلhEu>-K[j9  _]O݈I_̭0OluI_?>8U "hZa4ow|s/6\pWkGpm~8fc,Bar-r!ԃ:{Bw'hڂQCjaְ.8qw)><[5&Bnn.4񓙙 }9 2qqq88{LNNV<ErőiIENDB`tiled-1.0.3/docs/manual/images/terraintool/000077500000000000000000000000001315121121300206165ustar00rootroot00000000000000tiled-1.0.3/docs/manual/images/terraintool/01-newmap.png000066400000000000000000000410741315121121300230370ustar00rootroot00000000000000PNG  IHDRm!PS pHYs  tIME 00T IDATxw\G <:GoR"` HS, %`LbĆ]QG,`0 HJ/v?V/@,#@?xU:N2eWN8QQQ4u۷o;vl̘1ӧOOJJ:}kN:ն&++3g 2I\\v:::MMM {ӧO9RLLɓ'Gp8`j(""EZZڰarss"$$|rEE?!$$dժU!mmmǵB:$$$T[^^]]gjjJ'w޵mhhhWH```N -[c{˞={:bllXTTD FMLL>|Ң*,,]^^ARL&999:ӧO **ZRR-#֭r ?xcc##G^|͛kk넄0Y?KO\paΜ9|{!TUUwϩrrr 4l0ii㏶<Ν;&MB%&& NP(ӧ[ZZJJJKJJ644pBIKKdV_:dh<3ByСC镕?BPWWxVV֠A\&MDt.z?ݻnnn&F*++۷o_KKKXXLPEE\EE!T[[rp?p5rΝ?>?&^{{"A8pbR͛7,׃F|S^xMMMdd$knn쏐H$?1~sss333Bz l۶MDDdŠ#KGpOII?~*bl2uT}}}ss󚚚첲2߾}"**J̆ <Зt7o޴M|!CO~b_PGN:5~x2|޽gς@ .~Dlmm>L&.]{h>"C+#@/vA;=HBBB|#@G#Οq0Ϗ_t@Gt@G@GtzۏO %'N #_J\ᦦ&?#_N>vBC---t:HYPUs5ҥDbա8Y9![ u,XXWWf~#'Ohwinn8Z66/oKHp1322z!?JINZf^ h^^w3ǷrExxEe'=p8l6;̼DDD466qŚ5222` Gy >>>jkkk*)GUV#4! DJqq X"fxxWmݶ3ǎ?-******BψC,k\CqItCHƦ?YTT*a\6ʕ+!W0A)**۷ BBnj),, cYFF2 TW7ݻd2yɱ11`ՐlmmP\\ppiہ8Xq wٳUU @G@Gt@GAP x8CS="Tj#])..̨zRRF&FBBB#='R\\2qSB@=ͭ71$S:A@G efd㨥 tty<<-*CLDY jjk4)v}C͆qM/B$+u|8vHJJ:4>>S9/_+7QSS^SS#7nޜ8qe?onhX֭d٪3fxtgswsW^3fezzz~~ŋ,YaÆv[N࿈HsssAAAHI㡡+tǖQ۶o/,,DۏXnիI+W ;cL"?Ɇ&OvpTЙgMLLja1f'''qtbji)//o7`UUU- X\vKDl|b~7ðٳg]V]]N{{{DFF8>dȐp##}͟?XWWWWW޽{Nvޭ.''7o<C$>yANNNGGgӦM\.H9N4h^^^`0TUU̙;"}Ȑ!NNN 255z-kkk999%%iӦ|S |qMuuàA^x %%%wwv8FGrrr O&8e2wK.۷75塻`ݸ~gfaʕ+{{Ο!4y$/O?~q0UHhsԦ쬗RS9npHhK3ǷQjʃ**,X_նDPyy [#+++??[0q̙d2֭[ٳg={pݻw3l^LMM~ѣGB޽svvvtt,..>bbbYtuu]paEEŮ]/tƌϞ=KOO/++={6Յ 9?BBB111%%%ϟ?p8/k~ETTСC8''.kV{RQW< PUUE,zy{)**ڰ$11tyyyʕ+e!BYdeB΋WVV& 0 ,,ͽ?x0#4Bh?///'n*;-r1bii)q|rrD8?3ٸqJUWWsqqIMM9sƹs礥HHGG{ٲ{ɒΝUSS0ٳϞ=߾}%!!dnnQXX9>22{Xg__"++KGI\ɉ<ݏ (r@"~ B^*O/+--WQQ!+'K,(+0D"M<"&&V^^Nc-111PCCC[,0f"Hqq1J%"455DBGv0ߍE+ 2+//%)++c\'Dxqq aT5440 +**VWWoF쭰J2 bB !:N:997ðfp];USS;pJ0ٳ<o=B|9Qj z0#!XΝs3ҏ?F "f`0\nIɇyyyDbg}@WWW]]cԄS<a*D" n%UUF~~>?۷ q傂B~zAA>qEEE!CQp|l]]GR_|qT_~%ϏH͛9%::!!!,,<((P]](cǎ]tYqq11|]߾xkkEEE\oT6>X[ZzڵGj;h͚ϳqqq"7c˗/ VSU%2 WTT~c >v8p 7vluuulL,%˘Y8w(fff!6P]lVyʕcƌQTPh[~qz""6_vB8¯L 4wǏ47jq̙ӏim󃑑{6EF}vݿ>PcH7ntiS)d&Sfؾ}Nc'Ndhhl{8p`?L::]_븆eee[8c?'gϥ:LWOׯm"X#ሟdfGbΝ;{)S===.Z:=!UUS !=xB<|0KYY=ۭ[G=ՍhL~ͿEK.ݾ}bg/'Ҥ>m3ob%aw߰a[ #=LI0>>=22$Ri(5塕ҧ[aG"'3AGz*U}@ e@=3)iii!D@Gz:T6J 2L4W6^ E*! ma&t@Gt@G@Gt@Gtt@G ':zJVN^VN!7we:}@{ 7FFCBBĉ&wuuLMdr=MaV?QEEEͅED:Ю3|c܉A߿?vxUĉ`BYYYt:]SS!vZRWu{u\Cӫ;:xPKK Nmnnvss704RVa0TFt)Xu(.NVN~hC#-m յ-m^̙:zJ*&VUU׸ ?ݿ@CBCjkk]3_K~-I__!dooG,嗎G^cl2h[n={7J>P¾ܶ7ٗ|7!OkG9Ceddܽ{wȑ`CqFF۶nCs_v7 2T.Y"))vo"#B_ؿ8UU5k~I ͣP(o\U[[X[GWIYE}F^~>B%BCc R\ܺr &k0Kڽ˛0qRUU… V#JKKy<Bhzz&ZZZB`BaQ!Bzzzz;w"rs[jw,]:E[GwÆ0ڵ H=ˋgrss=w YYભ۶>sFWW_wIKIϟ_TTdWTTTTT(((df>#R VҜMQס6)..8qRYYܰ~=hCPx<޺u?\.O[[CPUUEk=$H?c)SVFD.[U?co|UwPƍ^^& kHƦ?YTT*a\6o5A%ZZZ""!yyVyf̜YXX(...,"2"!̙3߻wԩSݼuw=?wŋؤ]_=1wpɓ'AA ^AIJJ )--bLӧO>}ZE_Gۦ 4,liFFϞ?0P]޼X2"E]MFFG۷D"1'*{u-ii^M111v*3gkkkŭVSSSL[.03fI@gA%]8'₃C454?Nގx JG|f~WU t@G@GA&@l6oH$D"QVKU Ƽ/1?gA&z<wx&MQQa<~2p87n\FVSSgX%p8GR\&KKKѣqP)z< OMIaj逎 nyV*++"ߓ$~dJ_>1ӧO ^|)HP}%#8O3ףG~?ۥ`^#,KVN۷mWYZY_xmzmmmo:~x"؝;wͻ֭0Onjq3勗|Q?]Zkud}}bKK ͛T*u(YYvuuC gϞuwwQWWo666ƍKOOgddhjjZ[['$$gcc#(,,,X¢; ĠxѢEE/_2wORe2|0aٳۍd-޵:bg7zll(TQFDDJQHHի333<==kjjBuuu^^^vvvO?R\\\p6ZNN_ p{ڶÇ>}zueee~̦__ߛ7o^|Bxzzȍo}}}EEEKx<Ç&'kY vbl+MbbcyAC-,)?WUS8irii&ȑ#܈(Ǐ=zرAAA—.]B%&&`tȑVN6 !4e={kZu[֬Yciiidd4k,~ԎXYY뛚[% %--2`"=((UUUu!!!eeeMJJٴiӄ VZfZ~!y)xCÑ/^ ҍ)3D `>lCϲe |}}1 ͍JIIqwwn}/^433ѹvѣGfHKKSRRj*??N?S' IDAT>)))''gǎD߿yŊrrr6^wsh7l np!!aÆ޿Dnliر׭c0~ZW/OMQb/[tҥ]q,=mii醆"FӥaW\IKK#~:t(;;[BBLEEEfffUgO̤nӑ^VVVEEE7n <~ȝ;w\EEEp G-_<--ݽn tŻ\GWTTdgg'߻3{6B69B57Ҫ?VVVdj ⣢!qJw)4X[[K,F ʗSPP@"<<<)bbb#Fؽ{CBCC-[6jԨ8aiiiƹ^ ۷o}ꕎ?vttԌ\SPPx L&ݑnxҺ~FZZځnd ~H$%%/Gqw}033a 144LLL0dffaԟPsεOfO<3"vr[Q1"&ܹhѢOBQBB!'//OV\9k֬}uְ-ZL&1;ebbRYYyŶ#aݻltEEŪ*b1}<bq8⿀yƍ[n577ڵb3\.766׮]nO111}AL<Q[[{%.beeeI$.7Ώ:0lΝ^yhhL˗ϟcooOʧZr,$66t0, .**j…Cu#ݢ#v ں޾m`]]ݑ#ǎ+--e2D I&fJ8.+Hɓ'Lc2L&!++UV&%%ao޼ihhrʨ(kk붻 200 %66dN2EWW͛$bEGG߿_LLkXϹ_K]"##cڴi&&&>>>ZZZqqq$ !k׮GXmVVVNNNAAA(ŋI1uŻ5o1Cm EG͝!4c'N+W#,(o:%֯_þgq~|_QE,1߾cSyDI‰N~jF;`dh?& \}_DPl۫p򄑡!?52pvvAxdE|}WG&ЕNy%VVVee1 8}%]ĠM(..njfF HLMMqtvY#}%~ BJK{;?/gNPtYK++M&tDwZikkۯbfADKtAGkt@Gp!l6oH$D"QTQQQ]aqؘʊwt}* !4`} ]=þQ?qb#,+/+'L{xؑ!}yu5:<4]Xy(m~/9:JaxjJ SKtODw[ϳVQ^Pe]A8>=--̀>oq_x<L'ƿy˗/)*g.Xcy{ɘ1c^~=z/_qc[:"S\rbh66?;wͻ֭0Onjq3勗|mO\Zudi+#"StJn6ԗ(+'_PP_|Ywww"F O7n\zz:?=##ESSښ۶b -X¢; }ChѢ耀E"˗/  {K2L ?L0A__x'>vB 07߾zQHHի333<== Luuu^^^Dxڟ~),,,%%峥vh991 … %Vs ;;Ç?}>>>DzAA͛7/_LP<=={—nYGghnnnՉe١azzF&111V/^o~A#c@.0qBb_E>|ȑ#Tۄ/=zرc%%%/]JLL$4ȑ#%BM2fϞ=V5kXZZ͚5Ñ8`eeojjnݺ׹Đ!CUTTTTT0 WWWUUՁ6))fӦM&LpppXjF%''~!e˖%&&b7ŋttt]vѶ䔔ڮϧϟOJJ!*777XBNN.886kx-.SuuuF9 /_RW#DEE#V6csT'O͚ի^OT*F;ɓ'3gh[f+z4ѾFӥaW\IKK#Bχ:t(;;[BBLEEEfffUgO̤ԋVVVEEE7n <~ȝ;w\TTϏyBBB˗/OKKsww~zgE>~wL:%,4al_P^Qai!.ad2qr555bQDDDAAyy~NI "vB؇FUUU H$~Xyy#v}СP}}e˖5+.N>iGyZZ5<}ot QQQQQQ۷ھzJGGXFGG;::~jƍ_1JGPd_`` qH[;tDBBBEE($,LQSSUWWp^uI$baa!1`Xyo] 333.so  Geff~CU:w\l6ɓϞ=NnKsDv bD wYhQLĻD!TYY(!!˓'FUUU+W5k־}\]]:kX#ƍkhhЀxQQѵ[>m?6| <111F]9ůcXT{zz޸q֭[ͻvbXČ)ˍmnn}k׼ۭX Spp0q!tMNNfX²$?GzK`sW^?<44̌x&Ϗ'\S-~zURRKLc`ggpB^:?=uF]p>;;{&SktVyBCC,"/'`w۵k,^!twnUN>^FFy󦡡ʕ+6"""((fkX&9e]]]GGǛ7oH$mjjjhh~11~b~MuiӦhiiőH$Ю]|||yiWuuu+++'''KKˠ PLLLyyyTTBhĤIg)VKK u ##N:egLPF}mQs-hjjDM1}ĉryÇ?S}YPp]mm/:^IIIׯi^2''ښb^FK[@_E-X4š3<~;v>u?.+,ufXJ <ҙ>VX[W?VhS FӁ==]G Fݻ]ZBT޷oo724^Is ^[߶xLVTPWwuaNcmm!BJb=}%]ĠM(..njfF H]YLMMqtv!m_pxo_EP)Էyywo g) .kiedvbzp`^saut\?aJJlNa޳~q,O/o{(/+733t£uuT!jʪ]/,}r @GBZSCCFFFCSSRR5u;oǏ"28qrXt iǏ*.. hsHK_MJ,fۏطo?B7nm_R ++%())}o̙aarVV'N8qDRM6oܑFt 1頞 6?0'M6dbbaL-#cÇk8?acL6NK{lhh@211&cXYY:ڢDqvVysNNNlN j(((joMMM&gw1o۷6o|psss7o={F~:TCC" /UUUuv?A5 7GEm !~))6@ a׼ys;`~{/(~^hm`.{B^TB«ᶶKGݗ_P]]}⥓ ."?~=+6&‚b5bi^~]^^/̘1!dn>DYYy۶mq8;9*(!!!#=]6-ZKQ bn5&Ou۶Ǐ?A0&'N`P\\2rg;IOOqUKEDDddd(555yiKKx)'#,!%%6C[8pL2%*j5;;{235۶YYY RTT4bxbbϏFgqV?CS[˖]v]JJ*$$gV{(.[RRRW^UQQٺ5!q}gϝ lmmwkAA^޳233I$Ntt4/w;Cqqwލ;tW:гG]g3{vI#::#:##:@ca<`L D&nz B )Q :|3\$33?Pr+eU.,D^FL` Δ q)..NMI8FnxӾ{֍b*UOM=\_SB!>S|zMTVFefd㨥WHHHGWR2[5سY.jlB<7 Y6u4~=5[^v̳s8VS[կZ[G1 l.^YӨLuU+k_ZCP$Ry<Q2+4 wяÂzzr5CUMFf[غ%*??xۤc㴴7jkv]}0 q =z`" as}uiiӔ)S t:ѣG)))GE׏5JCCŋeee6mRG611y'OW\-'; c`id2۷ņzc\5@kx<.-KTTkjjr8<Х<cg2x<ܹ~[H:rԙ3g9sL&GFn$8 j:~JXY}֭Dݢ;A8NvYYBH^AU eUT-**u5áb#p ee劋Kݶa͚wijjP(MaN{ð#{@8a.jt:BHQII@xtq\C$0h\.g{.]s$sGa3''uu5}H׿yƍ벲!UUp h?,ox<2?|ԪܖԵq^UUU;pr` ~3g0oH#NP8o^WGF8a9mڴC-&Lpę3=qQWW88p?+G q|xzz4~K}}M1 +,,zj۝t<+.HhcԖG~߾usIqQMӧNDYll!|ǣ"sۮ"ڞ7M |ԩ؝V˗211Yp!aa/.!.n;VUUp~q$%$/]\j .kldpRRRr⥵?2dHcc2sL'GGbsfC5eШc'yvp8zGNAB8ۣ'Nhh 2dkkKpA6p6կC]ܤeJ,bpsR5{oMv1Q8:y~Ox7IDAT_"vFNSUUB=[P }9o[UYщ XM^I}! 2@&S!x͡R(~5rzRtLI3TUQ !yBJK*QK- !5'@GQj3`} 㕗UAAk׮}g0\p8=e988ݽ{… ӦMKHH| oݺM!,, !saйs޽{:vo!#F477WTT9r[nE-Y!tʕ7oB-q`ֻ|||O҆neeój*gϞ544!8wt@!H$vxRǗݻwoРAZZZ|||E~葽HFFFuuuQQoaŊ YbrPUd2|htt9s,--KJJTjM 줏?~⅑/BjݝE@?ԠKBy lѣGƍ311WUU!***0/:ёd>z!aZ:;):pqGlɁ1k׮pC>~(//omm]VV6xC}w _Cogii=zR7}1@  44AףAq;8L6`~ @  44 @@  4ohPAA,ׂR`ezzPTTɘдڍ6lذaxReӧϐ \5G544ljjBb 44o%@i W.'JH@PBVΛ7TIYΝXxQq354e)Z.BL&ĉV֊C B#,G&&%!N<)!) HGQQh7bMLrssN  hffƦ&P`5k?.RUU=ᅮ\'Sݔ tutΝ;P_{:uJh޵!a߿c6Q!qq1-m-g؎?ڸq9sMgff&''/[Iꓒff۶Ahз)-+Eeghh]!B(h%K?RQQt`X,ТEyݨQ4 H!mm[pY,6Btxڳ>|ŋN_@ XM6bLB@$b}s9}LNΛ3gU~bk;j''||UUBRRR3fL?w.رnnnhAhhA?N">|8pD"4B>|| -#=|P Sh8) `^MX,fA~DQ555} ӧ': 7dtB|*Ѡ;&a?}$ V?x}·GXsÇ8~][իfΜU^^ѣǚ~'O\YYYXXZ|yqqqlllFF'͎LOOAnnnLL.B˗/nnnZZZO>s۷oCCC$,,i& cǎ-Aɮ hH"Ǝ+((˻z/_cxyyjhdhj:ܜoY99t:!tрm<4|I\\CSSӞ={8Nyy۷;<46Aʼjkk݀QlǍ_QQA"~(5o BUVVsPƤO<ǘqaۧ:e 1cܾ}UVVjkk޽!$,,?rH--Yftx:__߄--ֽ<P [*@+ص.1i I}jPSߣ{ ܾ)))# l6GRclby oa29ٯDEz$́=i>>>abb/?߄@ HHHNuIm,l6F/h5l:S45hY 44 ނE? bX?DbI@ :N9ºCir8H,(/x*뇱7"":z:C(,_Ԣԇ?U}@ HH75:ԠכY,VyyT1ʪjc Nm6C& = Wh4ZqqqB|yyho@G,Ͽ(""~:+~9~ Y]c =yL")?}xpShl@g QRNZ^8v]} ~ҒK"\\\GAz IK.+fΜU__~h)))cTjs:FCSSGW/,,<&vÇNd5c'{ 6fff~JJJϟodd܌YC``>B133vaÆm۶YXX,\!doo)S=:???**ԔBau\]]m:thٝ]/455]\\ZJ_TGGã ?y򤙙BߴiSlhhPPP8~#/^xM a;i_2 ...!!!b ccc ++i``@P&Mغ/%;993MLKK3f Bqqqٷo_=S{{M6M6mܸqcǎMKKj.]joooaaq_Ξ=kffdɒe˖=<O ޿_SSpVX1mڴ3f]|VRRR]]=44dr8 .p8/_ ͝;Kvvp8w166Ž666._L&KKKO8x p-::ztfFz((g~g.jgм7Os۷oCCCB<͍'''kjjJKKoڴB?~رcK.mܸ1''GGGgܹIII7oތILLD9|wa;rn֬Y999[l9uˋccc322<==mKxɍ7>}1}t''Ǐ?~LIIxtttBBB~~޽{aÆ%&&nڴ)00ɓ'+**>xAAA?*))=f̘_X,Vtt4L|߱cO@@@QQQ^^Hp8^jll4000/w:+~~~/////… #""e"..Gemmc 녅D@̛7!$ 0rt 3f ZZZ3g:ݱ%+++x,F__!\|O0e`лa hkk+(( <ٳǏc2 f[[[c1]&**br-_ɓ ݻ =))q̙YY>f0輼99Et8A/..vZXb8Z.۷]_wzr5HVV 655!Co5`ٍ4:Ǐf --nMN=_OEEEUUfx(+/G***q8WGÇ:u* B,_ήlÒAq}ii骪*E =zϟ? Pii-PLL_[[$HmZl[\\u}ulٜ l)Daa斛7]\&=|@UUq \VVf-,FTVV߽{o߾}eeo߮"GFFNSS311y-_Í7TTThkk)?͓^`1G(p8RF>}-SEEοvttrrr\϶ -ZhQ}}͛W\3III t݄:뎽}6,,L^^~͚5W:۷oswɵk?Hrttttt_&Hf} wf@ /PUUJBKIIGFFFb:5|i)**^t qwC`i޾k3hTYYu!$)))**ٵkwllܒ%~qqN")pw8ITTTiiAyyٹsjjjgϞE>s4yI'&ޒls\+) ???.^U0y⹼6ǧ=xI531އf}cCCY(:]|*l:ޡ!D%%6Q__7DYTTPVV+~A? 6b Mȣ@¦ qx"@ w@$ 'jPh@/ct:Nop8D~~~(R ^P uԦLJPHHD" ҠAwhuuEEC $UU)+aq I ߆`TTʲX,݀@ !F(Ƥ-6 *)%_RDGx8Od<8 !!$|,4+B}%  #. AA]@zTDDE??% Р_ NJO}xxg!@zLEE嗫AA^<{dmdn\vs -PfϞZ~皚OE}+110pMF??WLBD"gW2I:\f)hoRSjd5ˑVu-F(ڍ~n+W?kllbllBӃ͟`H[ ,?DIҥK%$N81|d*ǎ742RQ%kR֭_ύcmlFOobP 62 nÇ36^]]YF{z.ZkmmcllrB%%+V'O亨x*y񍍍UjÆwؾcYM}7opM>sڵhI ,nJR ]8H$}v'N=z̙3ZZ[n͜9 Mvuly3ztpldMbbݻ?C[Ggvٳ<<<~Klٺ? 7nڔ|/_0)HK{~#&H$n y3>!$--}e%oN1S^^{!qjꭄآ.Ǐ,# b mlGRQQak?Ok_PMMM':;;Ox=d˗/BD"p2DвK=K+,,D8(+p8uuuSRR-]]U d2uMDp7DED-[KP->w./\zJ2˻&0!u6%/, l4?zD"lA!"6oڤ2k, EkjF44t9y7"''zCFo`hR6BJJCN8~]=GVk` Dg}C}ý]*qet q_uUYYCpޱRVV)//o_|ARAQQMug؋7;DR/PRRzwNIY!$..c۷̟o`Iaㆍ'NnNnSD:t8UuuuЬǎ;vX~9s7 HEY!TUUER?=ܹx#G^2p8dLq2Db6:B=Vޗ733EXRn%ԟ1czDddbRҗ/_***hhh 32B(++C cY`m۲8NKKÇKJ޷ISFF]g͎ʺ~WXXXx}+)!C@ `v]UUĄL&Sl6[OWԜ ,HLUWWu( cӦMMML&gNNuuNsZ@@Lw>vjO:nׯ"))!,,{P}, Iqc $EyyБ#G+()[8rh1&!445%$N8uAQQh7bMLrssN  hffƦ&h<@2q7 7<0p@635[lٜ9s***q Bqj*BGϟ1CZZZ[[Ó65598_Ϟ!.^~ґ#Gt){#Mu5Bkbڭ[g̘O6{ iׂ 233CBj-[PCCƨ:Ka9 uub_{:uJh޵!a߿c6Q!qq1-m-g !ht: 6zHSS3//Ǚ!k+8TO3GnrY۔)GFqp|EcZ RQQ_EЊ=ztF,{1B@RSS[tAh 7}}]z!wǃGiY)B(;;GCSUw!v풥KχGD\H&=ۂ!>^^QQZ,p fYQQfOBJJCTn{ffe!ll;;!,"R+BZ_]'--J$**`0˹---555!)IocKK-C,].guֺz2wgO_ʺzaÊN> Yn܈xBɑ1VBBž={9x .6 !8쨵5Bh޿9Έ#-ܹdݩ rpVmA!fgt_^^^kkPddTQq1kn3f7{oqqѽ{wCmc0a566v s>}&'͙gt?WxRB5Ǔd>^O!)))h3@p]eee؃em:bvK3r<|Qg抋kiQ,Gz=rrr?tIg?},22!++۶m}皑# ?UUa:s<mlIOϰ\W[go?MB9?'-#K$ڱbIJJHJ_;ufii-ɀ| B՝;w.o/^sN?ż|WZjj1tͺ!G70lُζl٢YUU'IPՠ27nܸݱKDDR6VVVgΜIOOOLLu]{zz޾};..@ ̜9&q))ɳg]~۟4#N~B('͖[z)N_hџ8kk5+x<@ YJ 204RSט>}Fii[WFJZ! I)lM^&6)=wh0UE--X$WDggcc>y2r$Iq$>|SRR' ȈL&ˋa+W0aDRRR/--՚ P[[ې:]By-ByԨQ;w1s~7!B YӧO> FXX`N9sZvEQ( קwr7l3~x;;sa;wkiiAkjj1i~EIr_kkk{xi$''#OVUUŶ_x ZG~AHȺC*|[`kg{,_111n:|iiiGGG'$$ݻ<==׮]+))zſ7 p #ڵ7|ө䚢@NN&&&z{{ƆٳUV577{{{/XʪW QV: Z{ĉ7orut[G2mڴAk׮Y$''[ZZOR/\8 [mʔSNuqkU(g͜};|ٲ˖|ƌcffVVVu+V\xьm۶߿c{yya] Y3ִ4gg窪 ,ըw4YwyyyQ?Ncc#BZf"""X` BrrrСC+Wr}CT=s<" vddimmmQQф wdWW6 WT88oa\..//m a {챴,((PWW={sΝ+&&FtUU"x<~޼y^^^+Vi9l7kiif˖.ݹkׄ R7ԧ444tL파 n-O0ɓQQQ=ukЇ4HDBJvTܼ̈DM\\܋/&{ӧ ~lc {޽ŋuxUUJBKIIPuuuPP'LSxKs?>>>!>.v{v"&&&+++###PaaassvC+GFDD rW H$''e˖#ꢣ3>!dcmuQiii2&Hl9===%׽tÇa`/((hll0002d6fmmMh4Zg͛7h}M:Kj_|neЎKK:|;t\1?Ǒ#G njnn8BYYY/_fϞ=zvݼy]֮]65&}?jdĉCmF&&%pbcm؈-miiցSܦqpرNC6_t*Ym]]\/υd233N7o<2|i,Sljj7oW]AAaȐ!fffAXXǏoߎZd6H{=KII9s챣GxxxB :|A܈{%lll6L0pg IDAT!%%E[[{ɒ%666حzڴix<)))mF$ Xф6$$$l޼ǽswn_pї/T4ӦMyil|+W7tw TݻTvz`y+O!o"ߺϞ=gQQ<{ 4hcCxy- +e{Ѓ9utt쵎X?~L^^.2⒎67 J5iӦ]~POeeJJJ()wAno>~ $.!Ev Ixxx$ <'ޕ|z$u#N5 0D8%nIqw\V@ KRPzFb F[fth6РweIPP 44 M0q&+nR'HФ؜'duР~Q`LGkI5G}Kd2fkhPbxŸ}lEzz֛7oZDu?jh/=۷oGM7ÁoGZ ]]ߠe˗͛,4 96'==~Lppp]m79oFghT,Hkv.2)ݧu￷ ~,--UUU333˗/P(]]ݹs Dx;w-]zժU+W F7gy${CCcbb>}J-Z'Z #J 204RSט>}Fiii2իUttN/7ÇNd5c}>LswWQ%75;5Y\Rb>>yڰa#בNdr &H$%%%6MHH uqq  -55a///ٝ;w ߹s]KK B(??_SS3%%5w oI.+.*NJZ[[cNAttY~^1-{˗-- ?w6,l_lll?~}3>>2*4{iϟ!?100PWWuGHKKmD\\<:::!!!??޽oܼvZIIիW/>z?BoooU+WOߍjkk+++ ]uuu1cccٓZjXPPPss z3ֻЇ(VTTfefHII!?q͛\61G2y2BvZFFʉ'&OvurrBQ(//ȨǏٳ ?|4;ndm̘1fffeee[n]bE{322m۶~<[??Bw…زΫVJKKsvvJLL݀b^:xIo(6(hmbRҥKBQK!$,, `nnnhhsuu&rpppvvƖMz\'O|sB%%>1t_n!!!nWH4{ LciiYPPz왧Ν;njYOHX,@Zb=sds\ܻ4WCC]TT'S֢Zȴ N<Sl}HI$P\\d)*444vrrT*ҲoT{0'۽wŋ: PUUJBKIIPuuuPP'LSxKs?]}ꕑBY[[}EEEr_MMMpww X/@"HNNN˖-///GEG_g2\#"" y: ZZZ>ٹs7Ӕlٲ5++3f_PPؘ```0dP\\OXX5Qκٛ7oh:u*}}}|A=ȹsׯtG),,ۺu9Ln-++l6ڻӸ&o' " [ D HE"eSZ6R+Bl AhZ+(EҪQ*}*#J AeK$ 315jH&̙_9tRaaapp0bz|P>=_qQֳ_?s,8;;}?r8ޘqmO_fssXqsxcy!ma}|cP)M咇'222߸R U]]tR.{!rvյtR'*++%Ù6mԩS;w677oݺ!rJEv)buؿ sN`{.Nִ{&%sp 0xZIh4%^g@ot>?3so\|}98(Cm߯7m QT& jfj_4Wὶ0>_~B(0LΞkoAʤ5iʔ"]] t&oDHTQQ#=."tƆFc0SMwauk=.60up[q\&A 5 2HUYOPI A  d@ 2A @d2 |2L& R(DtX2HIↆHԢq3U@1yJ# !JO7/- Kį]rogϜ70dz/̷144̅ /Npܖ;2{'[[,ٖ@ }?\Gd0JipUeeرckjjzA@E˞7oޜ3gNM5pdR)ؤ֥B' m OOk5rA!!LcC_46RO>d2ն Gp4 AvƦ ôYfE9@AYG(^f9^d2߽E""" Զ-[& 5-FQVVhBK@pqKs&ewcccMM BH*,ZP޽9&|(nn7nL Ɵ~T B.'rW }XPe+Vĸ͞p⭓'Off(pܹM6̼[OaasURr:*jyic)~&Μ9UTTt۷"㍌?~9k,7^9@i00Yx))Y[OFwʢC.ZhffF> 4i>wB3BrUU666w|M| sssh{ 455Sl`=}8adcm=~~zu??_466"$U$^/ݽwQb2::û4eM(Җ|^UU'߿???JUyా~ {Фi۷ 6L1E K=BGoV|pz֓-// KLLH$* D<~,m1_{KT*ÇG8?~ҥK/5M6_r1aRkJwՕ+W ptRaaapp0BH$ĤX4!A`BZZZnnnO 5! p1S__}KMG01aYDdGGzFFo i877wڵsyUheeeIIIBp8 77PЮ]<==srrUAJ>;74~~˗G\uvt|u}VJJX,޶m۫mi[#Hа)ÇȗGVŭho]O2aǎ\YH5V b7$' x \O  d 8.|2L& S( Pth$bqCCI$jѸ7uܿcdprr98 TK*64ԟ*n^[wZWG׮c\^w뷳gNZYqoP2HjBuy :fDEy-w4dOZ/4X-56A!}`=@i6 èT_UVV;@akTA8y9s\S '" B!?wt '*+<=BaۣGӫZ"dopb{’=y__ ռ Gp4 AvƦ ôYfE9@YT{\ 3f?`0Ν;gaj^FFF˖-{arrPYY)uh@ J@A~{,K[[EGGo% ,"u欃޽jY}_p匲uSm17ٛ6[3\gΜU^QAd>XosΩ'N$JIZEc)))~~~Gq ƴ4nPmm-+++Sy1Д 2663fLBB·}?uRIII̊gN䓴sΑYΒ%U7{hr˽}v6 ϻcjqq޽_1+KYi˿Z[gffިU5q̙Gn߾!odd㨨Yf1z-FPNϗ_ڽ5[l3&M 9fU5kwEmmSukN<6ccg'dbc&!+X)LLLrss?޺!a߽ۤ>k绸 X,VPPP^^F۳gw``i\\g){ 7$aRi~~길Q@)F337|2B+uRDB$Ik iqM܇N~qss9\[[T=ׄY03"߿???JU1'19@3bikk/\ի䐺^z Ж[ꊿzzzAP(6۲V]?*bfffooH*miQSI{UYON-// KLLH$* D<~,m11ꮮݾ}צVUU8^Qq1/??,, !αb2C#/[,}۶˗/}ɡ!!w|z}LiS?nڴʕ+.b äR\.'CαrJAA.]*,, FDt ? pX<*Ν;ZZZvvv{f̘A;/0 ))ɯZnmll#tg̘ZMbbMMM cM| ^d֭[1͍NZ=|+##79]|nkkz*xj4$CCCP8{l[hh(Bh׮]999* {Equu%pP(?۹s 'mk={qΎ]\β#JII۶m{[öWH$bPhXxXhIZ\|CYt<z:D|>_*n̵ؐ;b1mmmaYYYw(χVа:d w4鴉.&g"""R7i`dЖ> YZZrh~\tƍAt>?3so\|}98(Cm@=HMQT3SF(k!W @dp< R7ZZZL)).՝LkibSAD^>>r\@mmmI#e?dѸ7g컥`0=]bX2H`8fg0X/L*AۖQjd2 A  d@ 2A @d2 A  d@ A  d@7:P" p #b/)BAQT:ow"b Ӑ5N D\tGsXkii=wܸk(cFu&/,A@i5rO/Ok[;6W.78FpTӻRs'vaEEoLcâѨ@zcg;as5 Srðolwp͉CW I LqS~+99ܹsFŒq`0h?x&8?OJvvvD?gE 1jjcfn+#1 ml[~슞y_kLY^ dxAqs8VB޺u3L&!f[=w PS__agW3ҥOM/l\Ɋ|5a3g8Y&pݨw:F,W j!!!SL7oީSD"ѣG,x G8 bdԫ/ {6lHϷs˖-8߾}ԩS~ɯWуBA~}$k{w=,?&LXުx++'!9^lh?UA@!jШԂ><))16&^:sLW6M䨏br QtDRGG}Wt2Í'N% ,"?NQQ*k!>5Xa]] U_-Fquu%؃@ɤҼcQ+d2Z G=5ק/|,xMA@Y ʸ.VOO737A DZ-+.L69ǀFRpN|#`!J8stcK} 4:3jcUUmyi4CCC.:Ç?;]b˜<@PMGt]/sa\P&5(PDVNuv7(hvov/0fDDddIDD uafzZUy>:yߪz{cZn(C ~jYMjz+ b_}abرcH.SPPP {7)~~ RPPP.KD$).)+++?>2ڧOO?/d_f#e36nܸA' eSV63߿dtk^=GRSd{u: &˲+W"|[_4Cd{ʔ,}0E_xWtS(`1,}1#ȸcǎ{w4{rՔ_rIÆ_=5i+|)>4u3f^P(k/yNsED'=uI_=W۶QA18| 8^}=A%{Ɗȷj[w|=T(JSSӺ~헿|6mox? yyy8f矋8~)SPA1"o 4{&EZΝ1c/n⦿'Oo?1O?qk^GTa@ s{キljnWnSUUUTC n}/q˖-d۸/Ǡ%#~"no="jM7>4qbiYYs$`YGkk;;;ZQcRKA1Hǒzb`.]7^1kr<%nsǎ?͟Oιit,4L25MW/ %XD4r{uׂ67//믿pGal-[V+73 ۿuMrgΜXW]5jP ~q a/h2M.whARP6;vRr??E:Gvg;ă((((. KK/X4KAAAA_ dic/)(((F3hK9=pl')7ͬ*/Hoκ3 })4(zs>7+'SP\G[oΗ+@ "'wܜ/z{j)K/t(qO(.uK#g}(*[)?rRQ ËTߑP;/E *R!XJ?C$LAA_X5 tF"v⦯op)q>\^^>2_c*uV^}GW8&GC#W^y󻺺u[~mX#eT `clg k7!=|{8wD0H8oNX6aBԩӶn%9O;Wׅ g̘^d[oWL_v5\{-vmny3?s;K;w-y&뮻ٳ?G* _f{WU{-̜9/C~{SU ?߽{g=zO;wUWwo{S'_{?z_z*Pcǎeee?oYjG/_`] M01}#cpc^pA|x'57/oڵ ϷwgQ?aiSU` /w߽gX+x_yu+9nw?N8ljGe&ܹswύ/IU{0'OSرs͚Us0Lw7v??6=7/)SkٿhXQQA<~x 28vpM07|[o[bD|c'OY p&Uon7o~_5M,++~|yCYiS'7& P S\:&gLvevءMl٢ou u`ѨhG/Y.y|_[U'O7ޟL=dPWZW^y뭷$IF?ߵkW|ffee9rxD"4 DPK`Zn;/XH~sygً<ٻw[%,Jp~\~٬ee_yNJ_<ڏ>(,]=kG?:}bg{˿N2new>۫3i`0o=|g8;桻D<".[{f)FnlmzmRj/!lXv4_4ԠR ).@h%Zn㝩&j#K1/I@ORK1#cX;/wF_RPb0ťmiwd@Tc𵌊b࣏>Bj\wuTt@孿xގCgo}y(ZiV`TEfN)E4`xP&0<ꖥՙ& * Zύ 5=لb OwM]SSxoNot/v)F.6⧞/!O2hFE삪؜Bv!}w(wFPT5鷵9tbvK0:(]ټ3qM0{OSXtxtٵ>xSwMus]S]װ߽|G<[k=w͟2CMA՝NJ#{NguM,&GnQ;(va"'9ˤH&FZ*rpü~6`?(waq\ kxs"JK;ɑu u rF@ks#~y(ӧ/ŰApVt0,Ȓ"KPWkwI1no(, 8vPҨ0k_t"KߜټS߸ɕq3CUUy^Ϊ5䬞ͻu?wɶ~a΀iw80j^C~QEYlD9x@T xj0"**)HAE0I/"Y Ő4QW^ygOVװPp/pLckG5es<>}ڳڥ3l|3υmhp?4E(^n\d: S߸bdnvP0Rk,"1ŻnݰmSSPuEA_,i;rf;cA%9aq:l,BD|VٚuCfD1g>BZzU]gْӦmG^< k PR.15NI^TSRW>) =< o_Ӥ_:[Vdb,apulu ;ᰙfk LFq`Xp=Sdk>sT7|Vt7kq/փ$c ~Ìzdo^Yw/{Ww }vӇYvTTiRPbX~ YVp+b kR$McecN}Ck7 "KBHOG)Ū{Jɫ=Xd,>4Phu'Q䚚E(n|:\S]BtыkL'kӧ_XɀF++ }I I dYEc>}mb$b}ma Čo"6y`cSYzU{~PX4Kn8|"5Ś%׿r@ߩQw;M R "oXXd GB]$f)sڀ rxA,عE^qgӇė]:aOD2bAa=;?`6 rI.*E~Yq,4(4w<׆mVSfTS/)TEVM&/eR$ptW8"_7[m[Nq} U2. o-v[VTeP:2/{\K;ĠPT CEHcHxȮ4<kFd@9|| ڜv`/+ ӺM;o!)ES{8CR$0.p\ͩkPǙ> fƿ{6Flќ=1R)ERHNS);ϬYz6e0(E:6*^U"9a#A/]PԂRdI,g3E?\+ZK*'؜䎟8qBwwg=}K66!&vHu47 \8ifٜ`x`ꬔ"C-gmY}5č]:CQ~xAn)ԙE)DEE97v'x6}fq |mn? -hz1bt_3K֖-[***ȶq`mu;XgVKfyiSe)'}}݁&kM$m7[%;<)`le˞`2.NOJ =03NCMk ێY\Uװخ"qgN.)Ș[Jzx;ˮDtz|(0ߤ0& Ȉ" ]vktu{Y"?W {!XL6 KcuG,c2;XXRv5}5mw=}}m4јqbrp#bFEû!1ia8 Ó3A:-ZS Wr/QjĬ=?vd R[t?i&u .uPxO*rMMSP:E::fDT4{g/$r7k1hgCU㭯o"毳6@gglTY<Γ' 1mId'Hq~$'c{l3|tIcQ1i\ENf6*|eϋ\SN"S]3l SQԮ\"ԄE JMrq r0@]/Ű <0p>5`9aJ}@n)\$#8ZmHCݼ`g93Zks\o.Oz0|pWAiف']^G.EDB9vW &V?,ުqE(^/HinRNV/*,Ř{~;s]p/ɀFT qf+)rf'Om`n!6O%v|cFv% 6AXp$*QEXg% a<=YZJ{ ^q}A|&"ʻy^װVESI(*\ )R D TE~+}KK6b /paB@꬀7gE4 * vzbOOq1q_ay!cYaLQD(2pf+g oH8pϣ 1>Xpi;^͞D"_$GG%6pL"G)@CNb jR+* ;I7Ix|$B78ŚU)) aA4Y ;%ʰf* 4m-vEX7= //Os.\M%{l 6!Mhm}>0Y$bbIU-l腺H `6eH$#E:lMĥV?]SMyCb_!#0z''*)ڱ_>:TK5SN; -y#{{oBl0+o IDATzMAO}hפ8')JBɟIkhPu[g50sfLCdÏHHQ<>bɲaH#XB~%J .E?t1l}3PU2fnN o}}ӎOEkiiӃ9ٳ9w̪8b+'uh[79xVWt˛B'ϑ_M%8rmm,( 鳤t[0lG5WPRd S )ctW bQ\TPj=//4uT}#K1@]J֭[7߆/XH~sygY6uݻvꭒ7?|} /my|ܭ}}i {;Q`TEfN)E4$2bo~^!6ъCaq9K[G\0<ꖥՙ& * Zybх7kfAmvbAܨt)2)nSV8#ѽځP"oɇ"MAy?%q^]PA.Tb>ˠA= bsEY8.?GE!_ନ((з9%֏7?5Șc_W*jNsŞnP`2y~\ \]'pTovcqt9gD{k,D&.\&`1a< gC []f4 9abI_EFO(wxB/IC5՞ͻH~PTwL(wdJZP0j7]v-q5ՃBq)B XhMܢwP$E*Y) I|^bIbFv1*}kfY&E21ZUab?}ɭް{uKg9 **"C"'Rd"@5o?HNZPJK;ɑu u rؠP \ce \" +Ȓ"~R +PIDŽ.b&41E)R`YpVQ7gw^D:.R7x61 Rdz0o00 o\}| u{WWyi~8kOP TL&FŐ_dgl,BT xG h<04~A+RH9BBTd an)p] W^y)a?xAY~PdZuI "lsOE)RʽS0񎍯qT՚kjDiw y(Q}PWq.@Ii@O%^'8o-$lj@I SAR 8&(Vb4Hbo`3=/~;_T*έ{Y+M`LU` sL)2E SkWS`#+* 5 EBH!(dq7mUʈ.J1 ]Pb8`bQq;TEb4C~mD)n?E7o7d,Y `(0Ξ 3&[Zy_da_…~@9rAM 8r͙osi4gQ|ˍkLT+ooFA.,' ێk,":?` ێ_"7X4 [N1S/1"obXlg6Ȣ$Gþ",N Yh'wg!v8cҖ`r-};an{pdu¼g%~9Y"h,i/5%9  67Sua9pBdJ\0,W"ȟ6m;ioTw bL_BgYWd#g/a'!#ଂ*'NX͗YFړRS|=~ŅțֳS@4gO<{V/*'~6_XtPP ߻Xzab[-rM9gӇ95g? jök2/=@iwX"A,+8r]T15)1UBU21#I/Iڍ#3zX09cY;#TUTH" |\VSJx£\+(ם8FFu'M3PU!HشlTEjA}hn|=?6:d{R Yd@#Iþa$$,"vITO%$:Lc|~k|/S&SCI611@C`b`bl|yޟf;?Tk>mub+!B0PԚWսG|x|JifP \4Kț-R:`@HЖSLdoLȥYϣFV;5Ly*)yaVYQ>Y.}v?(2E g?ϵa[3;"V,)ٓ7;ͭ7M1h/ŐBUd+nR&EGOw#"oqU y,’Aĥ(3]-z2$HqͮqO6beAU;H/9*?`:(>IK=8 2(W dE;&L".Zctb*n֑dxu(kWzD[ PdaUDPH؋)%{l_~! 4ٓR$hsX׳vogY9Y|INXG5dvHv~-Q :q5*AQd("ogj+M's)5"(BӧrǏ:6*".fl*.)6l;fqUd_`5K2]8HF%Uȑ+5 D{_%n-[***ȶq`muw# 6zkA)$GE3ᙊۢ%l0|z\v:1)8I|94cqf pl"U_ 8A J)8r+<č]:CQ~k%Pٚ?_TC(l9E"] MY\%E_Ef. Bƙ"MAzDXPhfgH֋R$E®ǘ=3{"f1"Bv5SJ_?ΫP+mfD IPQovK<3#KKKn3J#l˞`2b\SW޵ApÈ9Yv "(}+Y|֢We1\'TN5R͇&l=yѕuqej=ǧЧ$=%4{aHGPڀ"KR"5A}ǖF Kz<@4 /ҫzza cJ&+曚iT֡fxplq!1 v338 恙<8/K;S=w?R{B|+`/ڋs )ffJED͇\W҂\(<3*(-;p()9&bz ,&-7՝Ͽz(!EV/*#poLh/RS$TF/p r_aVRO'|'9{?+º?!zz/co7} =iW?Sݪ _kI})WfۓU$9u]Q63U5tKᮩVk&jFm *eIjHY[(rMmm>4ܕTMa8(QψyĬ5_xFUQTw_ c/V]"CA-K)H佸ǖ#I  BrtX 062c-Go۳gC(bpjL$ߘS N /#0&("I{83[ J k"GHv5YuO)g[I"zW ^ZsBYB^/ .2MSIq& "sA|EJ bE uSbѴ fO"/8 &_#̔p!Y,5E_UK]O @1 |I+jbt%^5#dX^iK_ C.>E"]M`%z3=|$B7Z7֮[ G!Ufb(u{}s jE{(2V7gK((#(QPE u/cšh0+w(JaͰU @h[, e-1b c|H2e#~~B}"Krle3E.E`xo{/y1"+0yFEj-ôO9J(V/*'CLL"5K׭{Z jL-=^PdH"="K1LPdI fay2HGԒFA1y -9>o5oB/Y7,'>_l]N4AEƠ-μUw1kQ5+`Jm{^Һd^6wplX(2R7lq^A] (EL/Q {qV WQarUE#G$a+lY I3ec8 _c\x Mk5[W1,Zf9H7;rK#~6%YwQyI/2go2caIxAod|9YTB⌕%`(NdUH5fQ_\BT{2[xZ뮩&ijl.d6=\Qw_A] H@T9a/.n#0z''*)ڱ_>:4@aIZ֘{Ԍ`$Z #I6N(h9Ԧk;_✤(Qp6 &&&aAmgKou˜dJ̙M[Ԃ%Z eV[%Y_So},~[xAl/ҡ ԽHq4z, aaRKsΦk4RUBcyuc1_c^1S}[j =S_olupf \[D- " %i>c,)̟"Ƒzmr=//*ptT}#PbSzcB@uu"HGݣu֍ ]9xmonrV5,˦n{NU2=1x1ς;dMUdᄜRD اzoz_7=Hxs*5`x("1-K3L *U\R)2U7`&7_kUF_S讙M(6n;zQ9J0Bd 6]u/§v <(Uas An'Yh&[=Eו;ïs=9tZɞn/d!K0HALL^CZPw͇ Jˈ|rfq=/r/ֳ/?Y۲`jy?RPE9R׏bJ'÷S7IXMoBAXuMcޖ%ۃ]0ca~T^$l`3U5t~B;z"殩le=;5F o΢G]KA {sbCAs &*P=IQqLlTʴnI1|qGM>?fƜY]EN>K4['/.'`( U z/Rd$~ VH (LhnS7TƹPkد%[o5Z3 {(2ܴ{\ݣ4R…ښ4YRdIQjn?)eۛ4?¸gK=h"u$*FSguê<1!U z/R6MCݡP ^Pz^o`ހHG]ڥ3YݞNHPw}Uvzj "u/R{lߡ?6翼?L&FŐ_dgl,BT xGb[O8?'MhMWڞI ^BOR"KjR$ KPw;OU E/d$~j J+3i!1R$@V#+op3PװPp/pLckG5d;ڇ=>,HnBJT >zU˰<dbz̑,Q=U3e1\E6hl ;y))Lly yj{zd]`&ByKrWqnZ dq7mUʈ.--V/*'FpT&*sS"ǐK?L,*n(rT ubȯ͂j?E7oO:o=;ɢ8zKK?B0'eC6CIk6GS"iG.9m|b?OcW5HPw7 $]P5AiKmS(\5Kra IDAT b1=+M&m'A ێUBAzE/Ű@xrf;cA%9aq:l,BD|V>;Qۆ6RT_M +Wd¯1" @ć3AE3l?}ChP_#^Po ,,i{OUu kfKrt:lO}x47G G!JфHScߑBgYWd#g/a'!#ଂ*ןבNugS}c$`E6I¯pyzv I"iE& ?fx#{\Se,ΠY̟SgrSXt ێkːھd@,fzvMZL)"#uSbX"A,+8r]T15)1UBU21#ӤpƓpp7?Hξ(>@IYY5TUTH" |r%.Δh/b&>%heIpv݉ohSe\BO[uO)`GLPlz]I?mAE=&/)XɀF˙-Ph5 P%a2ap$1IoP$3$f=Ux!& V\=Jvnl%ʅ%aY>88EL{'ox#̈aǚz["vU6Wɧʅ%b+w.J/S;\4yf:W7)  )Xd GB]$\h)&8>n&N"k-q]:ǧ$ۃV Pڰ rxA,ع8CF1c7>=>"ke42+H1FPYyTFۗB|sm 5Q[ݣq?롃ȪW"L GDfY`)6>ּ 9YY4-W^𘘶gNv5!pJ]EN-+Vu>~9c,"a}]U^>s'Cݩe 8wYҤЫMC<voCb QYĐO Őrb͑hg7fxMIUdEu}X#(,)7^sLL IaI.6R3M⍎Bo$u IbHmvыqb%KjiiӋ#Pݩhß)Z~EHn! oUd7>RL~)Ia?շONm^2&Ɏ_ dV§  ya/٧*dB<dWc5#{2>qr]m΂' :q5JUE}`~'R/9rD("z)>5RM(96ӭw1-3ɰ[Ù{JENU_u  6zkA)$GE3ᙊۢ%CRl"R 8A J)8r5J(Z=JFHʁ?prH{H~SN/\׮˛HM՜*[O*4,q|4jw!{/fN[sg`sOcX.>V$la_-C:%HY 4Uwc^o3IVŐoJyY;)>9CU-)|ԇ AAAOt u/ߘzT{(F рч 1p'BG~-1QQ1$yrfJDqZ6V{z4a _BA@K2CJ {cU$9]QBArsu/xcc#wh{RlTeca4)K1\P:`>:+*$G;gE4 * /vY&(" 0]P"]QAmq YBm 3Խ!Փ]'Uw4KÁ`x5{ns\3[$/03@D1M&c͈"& Y`tPTT?'"6M2^đ _(0Uw(5 `Vd)P(Úa@дYcaԮX@Ue-a-zEs)3+سG .Rq-$7n#ߐ"a#'̂NiwȡȒi@^V>HےFaLb$%3A_[TQy%F_cP5Iݨy yi0А"!^Xwxc਺ӤC;^f-gX^UT1:x87[r% o[W1,Zf9:C-ڪ} C݋ƩnEڨW/.gG! ȊH)J/PcYpM,4.kXYR PHfX.A`}{$HmCBϗ{_#0z'(ڱ_>:4,IqNR(8υX_? t0Ѡw,A{](h9Ԧ’\m'^Đ:v*+H4KÄV_oz2ݜhbӴbX"ݢP"l= t5!r4Q[f,pNuw`[n`9P"OIbrgι @̜4)K1-Ek>%[1@qז]eפ;3_}.n񷩊0ShPfǛPDb["Vg>0ˠA= bsEqߡTCQդi=;ݮ 3 ( Ejn4 9*J}ͭ>Mcx-@$?Hv^z M()'^q/V61lb.*gRuIA{N!pV\%xz@GϴO)Ɇ^_ðZ ȩ`['/.'`,F5Z(tU9k{liL11+6g1LPYƤ2DeeSwO1_Za$qᠶKayLjWkno( jOa%;u8z(d,E `{4d^ D[S{ (F &CU9*Ksy1F{S_{oRrJ6r%6g͙[¶xtP9w볪.\&[xgC $*~t+${"#75>s]*YA6, &λuL)eqV'Ԭ\\6iÙ@Xnbe O?R6<$ld˳S{4w İΘmEI}EX?{EuK6 IH d7 w/(`)(֪k_k&Z۪6iy}OZ,X fo3qvONf/9g绿wVfG1#Wd̲G2;Ft VP;1 ΃ JLeCќqL{?E`b}+ )]8B_?<ƊWpNM۷p˯! ihpXZỚ~bg˾]\\\u|?GV ^۫@ߴM t-Cf;L8O%@ Vɞ+Y2)EZ2^H9rbA_itQ=ֽ1Sb/v\jK )K?-g|&-eϸn^Lu^eC8L)3o+pfNN>#nV-7?qf&AgWp@OM^e{dϕV!h ^=}qr3!`/*:Ֆ_spֲjO`G[gqlh!p<"혚d=8ޭE#мd/Ǟh4Yj%GVn-jnx) Kj{Z9#Q< R8gɸ;W4Q*ZEaNA>R%HtSڥ{EΣ@z?hX2](xi˦ܜ_cgx'_qqYy&C#>BN͙w]͡`rֿ67z6t,?+S0Ce,Q¾Ajuu=ɝU~c/Z8'Z]xܵMMMI"r9 q)>us >Dry2cRl`BpEw DsC;KlѼ7mm.>oml@LOw1Fl*ޅmxgjxpU;l!L 4QWl6[mg;yխe飽UW}w_8..n|%VVF',tC V0٣'.#5Х"o{Mz4v:]HOg/r9kkk=w]]K.Ppmm.sM/EP<wSS{FNMݸtˎW>BRgj* n {_)jZvV&I!%طxe%_%8*!l| Λ9 rH\2{/)ӗ.&d9OW!AB2< |z`[I 7=,G{z gL ^׫3jeXL̿pI˗9r}_c71}[qЃ̊'|KbOOr9 q555]'+WՎ13z Bnm󛯱g9zYpKJ@ HBB0%(D꺯_s*޶Ѷo {E7~B4. p\vtMS/9βNwXU h^p!wV4_&yq_Sr]J4eMTNӪOٳCV9k$xg$?Y mhOΕnx5FlhhDtH ce軱J;Xc?gSS~H O-Y"oB8tGcuL'ܐZj/QaL l~6eйg#l1tVGx1V%TسP?@u޾kx]2HyeYrՒ$_E*7v Kk<c+f[r \L5#ÿi쌇_~RZP0 zjQN#)ugkBjk2v{<n%g[B4668.zBuu#nnfh(O"J|$7 - 7 !>f]Py.PM7/BSL&qL2PG| 64fDzE 2ڻd_GddFNV9?mRC~aU'5CŌ/ccC_MhF,e[ #+HdLC9K#˒)v:],K?&NpYM#;mY13jkGax.K4"l`Gofd.\L٥9Bع’:$mOr JlCt 2t/^L6Pc!꾹?-P~NRϾN|!\Z$o܁Oq+|VRd#8zҋK"2^ =?~!u"XQ#ɧ;4DG4|bi4/ #R^D)! [@mmmccJКSb)@T692Ys7 R EC=[cVc֙?[[\jl{vM<44֟LuuzL1r^l;0TQMI2PY?#Y/^zk_iϼ2*j`ȌQ{@^Tx  ^fiA MI")LUq7Rcbb{t<' #n$,%_-) Bl|̋~2hsW/#"D^s8sI޵}OuzTYZep(H#AdA8 n{U s]B{{;sَk/Ғaޞ }\KKnt:+=l$ n{y[xe3i]tB]+**$IJ¿.L$Y^Zp&;ֶbi`ª#H~Jsi{;9 ZyO:P@PBDeW&?R-?޵^s~B E=(_$HSa|4y]U#.bw-\87xw*+v#,I7YY2#Y.WLHEҬYqYf\7n׿"َÇ;v[YYAyy--8r\>*\EGv=.eey(uEs*hq%HMP45uݚY5A YFeuBoz 'cŅ8)??v GCZ^uM{n"cn8?CfD5J=GC^n"%!&ҫ-ĔCKv$4ItZh,=;葶C \Kc'>X[ʳڧ:ݜU (?tཐ:(u|B,_q:%كw̿cekKqro>skfc67uTؐVup{eqy) U}^sM=99|Lbܖ!܍l͒~!!2/W ZlYZJn)]RnykDҞDۧ>Pe#Qn_ ۳Vktm܁:>!οלzkVqBwwO%:x.^K^ ,EQgD6\}uߞ`?ȟ[n.7cN4pA!]Sy$g!k|c[T!n|70o\Ipkkl갆-6A*KĽ„ rssJJJ$ ;::zzziӦWw-\x"tqՋ#Hq=^'ℶt]EgFƲi7QfuAӊP \.,[K=DzF8m5RYvK z{L&iHZfoOdQ/BUqO/&dO͞&Ks=fXJeƣ Qqh/z~@DT{i/۳[> pT}i/6̋eY6\U--*ҚH%n c qoxIzi5'';'KDMU4Ut:C~oynrs!w;U!'q !".iRB9b"15p^L"tOş>!@>}oy1@%<̳naQ>rbfU%B54ihzpm^v yt,-8~C~oHQC^՞d PڲzXi8I7?w%QB)س4ŧ *#JpDU>Ou|H ]s}57 yşo˻56yw gT|qj7*{~/{MjW0wmSwt9Ŕy5?\D!f~_m^t mtPpCS=Qp=ܱpyeQ*ӝvL Eha@_13D ˖NO vG6 J9}Bɯ@nO"I/lՑkuf^L o_ޭݣ7?7MXxu9j`ɗ  Ϲ/_RotU?=]?L.?z{ JH3am ,\~.R/oڦIx$\o }:$ԽbPojjr=$--L72٬6渑UC lKі]d,Wu}>wM/| g [P ຯHXP5ߗh(Dmxz˛wygwg"8}JSNWU]#=NW5$ohzj'Xu+p׷&o gvO^ߴ;62tqǛP0>b x$ZN3)qה$W '"#`I!AF8{*U/DEE|pX4ƅ`{ϯT &5} @y !Lඃ#ȧu6Z)V=[]'+ $e:JfIB_cPƦrM")JJ[@]=NzA t]4lϞvv=J8Q{~˓xhşS@OsdK ( 1a] )V;,_8:)/Ӄ ?H|;/lsw>wUCvçjhzʾ<%ſ,^d^$dY6ϚUC͗u:ǤoQ/ $Y u%:D e?^|%<2UU>3gց-WUUŅ0N7N[^SH\ݛ.RmDm)ӷKnۗ_q:}7vX?@8? /;o|9;eEؖLw9Dl֯^8W>^E9Gm]++kQ$HiJ7XfR@ OX*++_`$  e Rt$!B% =]alEtP$LY/"?(ᑑ@p( ;oܹsg ߸~ӷ x >{@Q9˾Gi8՝Q\vM?=]W/_Rct! Ϲ˯]s˛w ^lO<kh{  EA$"B4"@}w{qogeB0;xZF܆^FѨ;xThxzY0@^wեK\mKtp}B=Ҁ͛7S"G\(^`t&:z&>*۳E"^A"sQp՗:tSΊo%)" Ǎx=^IX 4nLA5;f7ࠄkphaiI| ***h@@uN¼ j#Kj=}K"(toy E.r@Q v.gK]FWq"; H]yi$YmdIkh;vI+_榥!.\ ~rw>_-nQh#/"48JdV$BSS3͛;]&z71k1DS#Wr@ #/]߸A{A]`"LTA6 agЭ[ffM8d|diovyN`%j~[wc>VG:7 %L~)ÒK=_o]Kx|J+iYCSDf"Ǩt'~Yΐ/ HtiS].gYY9H獥-BqɈ $ĸI@oj$AQ޸*ا744^^^8ŋD%K[/Lz g?);P7#+I!S&}l9Df=^A&p.uojlP0a 5\!~/oڎl"I/e7 )wֺN׎X,( qi4,%4E@.g,7!IV|}\ m:W,DSS\766aHa'I&lY_?>,TFZ[[,I?i& $*8//[$e3x=}}.T`9h@Q$iSi&B0}sH!jm ķ-/khOY_ Rh]!N'|uD) Ay2ϘFJK32$67)>OLK IMЋzp>Q#s+Kaeucjic:V \?ҥKAUES܁ڵ.#ā]vr³ 0l~D(1DPE!4#m/o޹f9fW~O gd͍;/_w~oY􉏉~-KR-q)z^ߴM ~$WmY ED$'Y3337nDE ltT;#H V13jkGaxnH3Oɏ aLIc y" [, VGGǴiqwL_v~QPKHWq](o8Ui{qJHИ_vFՆ72j}kלIe'tSO8cul/332Ӌ"&uO\1磶?;'~>g<|1"55 MI D;Ē͎ec'@P)#n/hۘq4).EAWhU_4|"Vv Ƥ}"-((t!٧#K^6M38@);D}i>1 5@˗loD\ rac{AN.BN¼cb{ܟdoڎGHc]t?|1OY5e$Z D2ӔpM0I`f&a8W9?3@0k[]$hQϷoe{jn/lo{}u[ywK^F)m?6Z&-BqEƙgݲvAQ4A4zAP/qCw}{[I16{^`i7NL2>DW!IċyB+AwpN8~ii6<[׎?|yhﯿ T=7?]vi>1s@Ƈ~{{K\`6$%xh iP8cZod.-!_1s@?j-Ľ%.0E_^s i3Kb{q[:x E=$[y=[0IfWyM = ;BʉN\rE1"Ŗǥj=x IDATAE[񂨆Cp%Hm.YGG;$ՈV^F(L}9$LwKxš h8A,=]E (ZJĤ@;!@H%]xyo:,jL,{- F$ BO$Ly3nZv^ߴM aBH 2 lh*Imllun[r!ec"|[+ #7yC/H1W +*"wٖ9Q s )E!$dEG*im}Ab%ӗ !=Cf޿{a$E|;ȟvÃ:ޡ zB輂ćCJWrÕűW]MzA*|H}v ;AX 6/2"ߩ0MU!iWIMp#SO\ebCz: NdzAR0B :tǴB6!E@{r"qrKKsu]B+%.I nAe.g~CmoApfiE5s Ze_s8RF{.Μ&V} @8Jyo,@WA6=˒SXE ՋkI/~L$]LA]2GmfkP]2%e^ߴMy{LRo:H諮olE%b>5b-nt`Saψ 1ABvC ^0/= &:fB\ybrՂzָ:>K@PaYEPF#._TU48㣛r)l}ퟒE~PUªU?z dY`6tUM"{k6LeuC2 s^o>tA^\ MgW-P5UShHrTE[[[ftɮō0Pb A$_^&Zmc)8@kn<"tkx<͢hJ}=Q8y[J}cN4eH, ʫbC~,8kѥ%lG(fQia/ 5@^4_)")1 o SS !*|\BR{ ͎:k!PȪ`32' DHbܹHQX@%Ԏ]YE&ҵg fi<痗JHgde2ra_JaY "jH Orb/NHőaނ(%;oӳ^pץG8mi3=j}.$֭[O47~fcIjHQÁOC0;VfGnkk̴K=8GVLƅHtV=``e{q ޙto}^\${q֭{ 0{ Gk7Ex?qǟqRo>+Lҁab3d/dV x0Yd9xC?bbCe)el!IB+b@LID &9g 7* !^C=:^yOH_y]]wOPg!JB~{MD(81DZMS lϮ|NS0d{w=uu.6?6G8.nlI0T2KJ=kRGQBPB؊2 9υA='w%_RoE0~Pt%0td0VOv 0pwW˯$jj]E%z+@ߴMY2rý& M I]x^ c$q:ԓb2.Wq0ٔ\9&먲Y/2 $!!^\N.R7oLoxM3b; ˶Qrhjr_pG6.|]GKK*UW(#D=UUU.v=2T\U73>{;>bZɏQ! ;4ɻ4xֱ5CIIiEEEss 8v mr,RPQ*7'.EekVDЃ//y'A]E3֯3[."[å8' Rd_ױtW}̈́%.egEEpzRY5bnH@DL6p:`i(;!$Dz\kJa#XZ}}"n@+R}ÀBK˗Zr͚y^T̍Es1e\cvOpMqa[c70@X+]|m[,YVCؖj%#:e˗GQ|=:FGobd"rMO7%RfIаO5AqDz n#tdw#oBHp71dhïQ{ʊn/q1/q!W q7fb!j#*W9AI8ø/Y `J<\B۶" ,,YVCV}10ȋl:|=Ovuokkk].'eR@g@2A&ڒ6IS{%8W^2Zq)ȵ|u]WU0PG{dnݶi& N 6N79&̻{ߦj51]4DQ"5H򁊅 TfGj sIc)B__>aXWwۖ=LSwoڎ1mL'}ȍk}Kr̉x!=i*h}`Ka NU{R@QBdfCU#t+lB+%yḨ@gL >? .]a#"kھdY*0]Kq=>Ԃ"b`|Ym,6755Qq jM hÆ$~FH7$'@)ZDބp&Yr%8^ Kpfr˿gzݩ)i˵6͒ L~LNNɒA=dX!P 2<7J,^%߾ ?u* ;mqXE%[.ڶeOBЂt o?AB 7Y.k4F@G KCnROn4pZst%Yd[OgmA;bѣ[GC5444BtUNC'JՕXo1'UU CdLQ wmb{A嬪f¿&<1}x1@f/=[j3nf( 祽`*I/hKC2[3Awwwf-nȹM7kF"b}сb _i#Ha|A_= \Y%${n$#O%HiST]UEوkkk\.DU<=#E\cGG!NJ"h{M՗^M,GYHe?dpK@ M;B{QSh׮߿9]aZ{?ŋܿi˗_vwiiznnM+, 1nהt0a^l;0TQCgdY`(]jLؖ;iK#_%őr!Tc¶E^DI;iI|[.X9+R¸YgZM#hO,17,.a:z+ MVh!YC/زyuI3Zͳ+E9[uTCUL̜9⒱_ V8E`BmLDAl6KwwȈ]_9mmIm2t]?4R*N;@G'3>4ԟa)-nڴAefVwپv̴7"(˧6ݬE"L, Ԏ7XVM@T%״0/HaܼA44UoVA8D/uldY%8^.2O0Ĕ}00#}a(IA eOvuME"MU&:({OD[Ds"yjC沬_4{nr_~_oR$-z8a^2.DM17MU!QTIXMp(rk6 FX|Ovd7t(i: ƽy7Ԃ= ?&كc R(j%I5wd"z5 `\]nI /YdWMT%\gxAu=H4ƅGtż=!y\ 顠}KuZl͐E^4, J#jJ좠7aV&m4-O l R=`0v}wN^x"*V{oC6,:dY5MWU s2xA(,z)2ٞ]egA@TMG+EjF*  ¾>]D.eti'6A#BD*.͹964ze&q<8?CfDM'|n%ЁB~o7]t]C%#)'  }&z!ӝtߴMɀb\FW6=,,Y,TR!PSl&N<$jeC36'-uB{2}o:37[ɒ'Dmmqd*"=ݩBߴM=أAH[NjM~&צiKf|zҖo6*-3Q#!8gӖߴ-mXXQ8?8.))#Y BPH״r[l IDAT9ǙL&R$ߴ%|[o{y96ozWVT.ikk۶uˡCCTRR:deeϙ;QpM[+=>⋈說4,*,X'p֦%98}['s?6eddoҖt](< QMBmB;o]fmUuMfY!>w**O`M?-mw[ƺIUUiD%_jNs``繓HHǡ}zD.@δHʔuVMQQf=~t3͜13;kڤ;vwk_tA-_:aО}Ad"- 9oY2R`7r]t]ӡsP9!' wp?(LvbA0z}sᰦi 8ۛc,eTUQUE(eܹxzo88q pJ/F&XPlok( bo%Ƃc k,QDEbW (w;(sw쌢\}pbeYMZzml\ߵ^*3'Oma*Gp;5)~mXbI*ƽ^˜F{yĞ"3.%pX@ ջz1ƜFqZQ,1JW۶{<BpNNR8 ˱Dz,|nN^Osa7jQtRY#P06LyQ NPlyy EZsc1.PXf9%zCQ !a=}tvv.c QeT^||˖'Ot hX(/q}vzll VXѴiӕ+Wٳ ";;O>}پ}s ԰k9uUVٳDiHj߰p,nZ`CĿ@RRR~~`m;|%T!XP>@980ƘǶv (́h܌V"W-]IJFa,1|&Ⱥr6W&i ն0D3ɄEwj1}(:XB}͛'GEE 3׍;v˖- F?֭[nz 7n3g''K?bN+~ azj`х( o<ϖc(BQ4"^l nm%\6)4]*5.5*dYvv(8.P&Mcbbnݺ5k֬N:3& ((]UYXXX֬YV >|8c DLMDGT S(=dBsB8(Bܼ+h oĪUW#]v]!:u^z{!ei5kRD/iaeO<1KO8YK%l 4(P8uRsIQ<ʹiDL4%QK¸.ۚ銾'yzzNjW7ojJH,SY!аaCccc?? yÇՈQ۫qF EPP˲r\xM8Bo?p0Zrrn=xp۶[ߧO`%>3K@Q5=k֬߾],B'PeW(y0 :i&W^1\ߨJ&QF@ M 4m"3dlZXf&14Xmii)/b6EaK\an^ϫW;مΟ߼~zǕ @1 ݴ9Ծ]2-,,ܪ8XM9Ν,_.n[|ԈƄq_Wj^+Wʲѣ/ qai@ eay^GS{Opo;[UvLy#exPWuFE7|cǎ &(---ϟ?uT(B!QQQaaaK. /AԥK\w^au޼yӦMiT!%!aOm+V_DQB, Y[-\Xrz>([;:{柂 UuvlނM5 Ǹ)ƏZ񋼚[ d>>ݸ56#).h x (AVx._&&~,EK9.rhVBl3vvիW^L֭[nJ5GvPE֯4K4j0k ?i޽GGeV'͝#} lrE<h-ܑIy, @QCLڶQnZp5zy[X衿 nzn+ p77WoGxWAȺ/^o)?IQTrr+}DG>+ ?T'jlx;ר^{Ŕ))ݧe2!j~q!dcm\5MMMĸ"7"r3bmڴ[w^fdy^yV"?r(lyg1-IJ)ϝ hHVUcDDCUp޽.]߿ɓ>>O<+TPQG(H|}k-ϭQ>*rv~w4X_6k䘫̭R^^cEۉj47osǎ~N kRA1vuu>ύ1VYzI/tf \sܵ+K:L h4&..n6lX|H||/R gYʘ«"󗈈 #quQeQ{5'G)SѨ+W >|Ŋ;owqaLe.usDҩDDzD1Sɸl.y*JV(… 'N\`4_Rb&/a.ϼ (|3f̜9s֭ 766ֱ?%"z(d6/  L0!*js}LFQJ &"/!0c̿ުђZ>uL&>|-QiS'K_"w$6|A@HT۷jժ@QD"۷-QjbF,n8+“BBqȑ͛7?^acllO4BDzXkêhD`v(`aAa*XbĐګx_<hРUVrrff9+cEW[o? #G6_LXʾpB`fiPGA~g^l$aa<== ԒM ]ѢǹZ'ӦM̟sNss._G"XV,3-eo'H TTƣU.8wu2T`ٳ>%[u ef_uk׮ +ĕ,iAh211!L& P*)TJ T7d2ڵk}ݢŋ/[Tb<|!jğ^&K7l",kj*\Cz@U7nolxgϞϝm~q_S寁x,[c=bZ? w*U^2g׮^e{'9y[ӦOII-5 ԕ+w[Swo3g΀>|2Nzxѧ^6=R>礞mܨ勱rƍۮmiZ7.9(J{V]F#HJk>cƢEBL:gӧM}*[ȑ#ƍyѵ_iiډWS4o^t:445dH>}ilŋwJߨaK$Ld++XZv޸qRǎ u3gKv O` ]zؒۡSr6 #95םKeq$Ri֚OH$2 ?~1j4nhLШɤ Dܶ%jaM7OKOa0?_?μyF&U~^ٳgݺi7nH{A5mZX:u|lȟ?NAFmX&p)ӧLoiڴi\u;;;H$4MG ]PPvBXlHkv1R>lȐڱT*) |;6_p֮=rK~ҍ$7TYbhȐ?SvuI5ofͯ]z#FSR>|0eCEh ^(ϋy.]mkԉcG DqnڤcTjuv%<ۿICs=Z~j8^bŗae2cH*#TXeh5)WXHLLMO7j5j?>?/PTFrs߅wN~k׬6ᇑO>ΟѰfEyzppѾ}XBBĉ 7Җ-յM36edeuݺC/_+l_׾r}wg瞽{MM} ;w޸}|| RYzŋ绺vs3x9b͘Cz;{Doct4s#Gq^rEPKgg2n4-H>,HƎ fƌ8Oc wfC|jaaz̒>AWYIDATj:߾cGNk(ɓ{yzzo_,][޶픸&#CyG!씴}ݹZ3f|jUtBB+ZJd#G~-FXhٲnO+ߠ:uTUszn(0ҥ!!-ټČ!ի;ԩ}6ne)F+kgV+[r=۷E(==fRʕ͵J*oh/IsJޓ'i..ElBXR0UR)sο?9.ZbsrT*C C;9YiT1wrrޞo ç#Xۜ9k"3(Zn%K-4hӧOo߾\؜BU9T&Eqtt\n۞ *Mk/q lnnnnem0 0eٹ˗J0f̘1cdff2?O9WuvYsѢ7eME%[Vѣ>}B"##gΜY;8*Je1<{Qz ҷN/Dmb.{PxУǬ3EQU 68''?wpǚѶmkK6lEXKII~Tptb7Hؒ}YY9t5mۺ-Z?`贛^+aԨU=z EBR6O?kW۾qe'y !DR# u+R9w\e.T# ̍}SJmߺLGUcc)rKժCˇjۤks32rBC׵jUOۥ1H[ (ϟ?YY oבOuڕKU_Y^,B.Oz@;GRy; B'M,ucL,pF}Xr4Q%\n~ѩSԪҮ}'O5*%%E*֮]{_u޽맟f :5CC'~~^^^m߾ҥ'N211iݺ K?试+\y@\]jL>A6M>|iÆ?K;ujgK36lؒkթS=:zOYvܹ[۴EY&>;7~u?REdc5i7۷[Biٲ&O^RmbzϞͣc{b'&ndӦɓ&Uk0EAu""{/~8]AǸYVSSS۴mԢ… \ }:}? -xbQh?1nkx9Å|9Xk4eYc5¢Fkx49*Ξ]LƟ4kmm}vۏ7nZ DcsW_VҢ]۶K.]v]YJ鱗yr?deeٳ{p]v֓׺~ʷ ,#>)X>ݒY*)FD9oTezZ+O^ KR9,WADD[_AK=<]ojck>A#cYjx i+~S"﫞|ZAGN1"_]Gpp6@gmmS˯g|233WgWZhynb˿ P!$$XźrlBwojIJP@_w_j\9?JOzŸ_3 v=(4N !0McH[*B,BCGsLs4N'8T1/*jx[l?Tծn[^vF.|5x/H8yy cX!eBE19<9NJoP/>kə$(;6}!0s0Pt{2 iq Ec?عKXs'4jJ~Q"wHW*kyTl[bswW!+3DD7Rů\<&K.* WImW$@jEKxhT*0@Hem<ŀWoy?7kuO*JKDDdE r~^^rriii˗Ewx~R66h455uusqta={BKDDTV"ah1˲)))<٪m{k+k\Ҫ[ĿExA=ϓ'.%,Iʥr +kkZmJ&%""*a>ucX@0q׮]nӶ5jTT{bjiJRT*Eufn%ܨgЋ/Qq.o V( 122zre!/{XD0jFBӴ.ҶvL#Z"'2 @I$CMK_"""]hi+"B+H ZÏ~W 4CK$RCĿDDDo6"y@y0BHbΏh  EIwtIKDDv@ Bˆ4223g(ʐ˗;88f2 c E c&%""bmku  kiiٯ_Yfŋ3f̈lԨѺu rQ\3lذݻ_>66vرUV#G(={ڵkٲe-%Kť_( o+9[ ߴS(y_})Q{```۶mrQ;0i=z\.oժUPPΝ;וEӴWrr2M.\HLLݻ7] TLPT&#/]҉\" U۝:un޽{awzyy|}}wżWzzznܸ!teJ5wUVK0 J}BlXX8a„իW3%\(ĿDD .gJTr "//\sssd BTZ6mnܸѣG[[ۙ3gFFFc#~;a=K}{\`PKZ.CE "@YM6tgԩSb˖-ٳgX=` b Ohkk3|^GyW.t:1LL0})?, p8$zxx7ٰaC== f~ ;=S~4ӳJW^I!*..k>nǬZ w[X~=_b~fcʕs: UU;n4inNy릿 /pꩧ-[XvmRoiyL8ŋxbn_ט2e 6/SUU?TTTկ~+ž={Xhwy{0zʗz(i9WvvvJ . r6ѧt&\pvPG}AYYݻwc6җぉlذ|+x<*++ihhO?Mޮ*V|;oiwߍ3غu+P(&TVVĔ)S5k=z}zn@UUӟĜ9sx<2eGUUfΜI^^梨к9̙Ûoi__Ҍ X,?e̘1\.:::m>,f0f̘SI;dggi&|M̙èQhlld娪ʒ%K7or {gy-[|r /ŋ9;v,nJ91 Û{! }gժUlܸ1f>AP(hΦOo:.N;''"cˋ9~ ӏnX9q1ǹnۓݷo іJ9#GСC(9rdJOfЍњUU/?)h+++p>ݨJiSUhS-ﯯ7~Ӧs| ۏ?xN?t:ի|q]8z2BcOiğ߻>AAhhhHc*[9Us_SϹ&B 9Ӎo裏hkk#//뮻/$mF?|M믿NmmmJ|@]]GSNadffrDzf͚>8"b%N'M7fGFLF !4jmġC9s&lj'Ȇ!20`F]a0 &FP:~r}P|P NAѦl0qf!dȾ?QpϘ|6,V+#ZgNNgر(Bff&cƍnL&l6=>oaPCT@UWmR+VNAuh WC㟘h>wv}7 M>\(8ލ/f7ql:m:w}\}s49BGgg<@~~>͌1;n 7٬u!:9:P.0X.vs|`Ga2%_pe?mi8S"0Ly饗Xv-۷ownwiӦSZZjߺu+پ};z\ve  [tbڸ xg3f&h tTSRf$iZ5m6F W^E%h׶ݛMgp6-qvyZ |deequqn7o?'O . 38{P[ 8q8q>M~&==ټ{`[1؁\|`VLYQWTj#sɪChox,3#8=/r2o /\vL2%կ{]w>\v&NdDN:K|'ڋ橧‰/`[oWz\p%_QQg9眃6vW^yW_}mFFFgugu=\b{cfΜ ̙37d\s5o~w}?쌶sz3Wa6g1J{.6PF;6mL^eÛo /op/g*N;4֯_o{.kvک|v~ }9_r+}sK ̘> M^?n7f ܽ{7 ̙3{P{|f#2Q:ڻDU 62_ch9^ W^yիWi[\x(7-ٹN?tfH>_H׈#qoiiirʗزe W^u7\`}~8/+#<ob2:u*,_Z-˖ jYɓhkk#`پmmm(=6oJKk+Nu_:AӦe |l>vM"cRU,nFn|֑\[o%CQz|x晵byCXxB}EEE1ovVܹc=ڃTUbڴL48W߽̘1s9/~q.ӟYy mmmxnV\ɣ>M7-% gmΌIL>|EL3Qc註WC9 & 9/8ogh=i7єܣeZ gp0f뺽87͙Fӑ&o~F19` |9ORn{L& yؼiޝwVa>}:~am6On߶m[{rwۙ?>.Ҥ]Q{Ӧ.hmmer`ak϶w?Ё#sӗ*8+a%py(],it#[ʯ^o;ʂ ()zɊپ};p;v0~L6UEU>w}{ᇹ)3P|+׈I:h%krϥxrk5ZvWD 7[1n=IӿKy}ɓO[__~vnfN=4\.N<Ę1n[l{gηM[3˖o~N'_(-(O`A>oju?$;;y??}:tiӦQQQAfdiCCEEwu|>ywٲe /G{AQ8㌘XpwJC4;{7\OQaEE\.,QAaവqwKa'\n$l}in֨ޠ޸𢋍!T5)Ralt),`mUcPU)S&3B}Ngi)xc| dKTj? $'g$S 6Aax߷U_,XLR|Ȗ GL>LU0'Oy &M iS?͜ϯR79}:9#ٷ 1rdyHKK;, vhoop(D86JL&bXX,8222?r$b |nX,á_2a Ұ0r=j*/cZzB˅ fܸbf3V3V4L8, iiidff BǙL&Cj% Y" ga2Ǟ={;eYCFQiI&&a =ٌfR1L[lFQf30:q%LݡlOt'-  0̬__?c̚'=]BfVv:cǍC6AAa%ĉ6}:f(lb gTU0% AAhAAhAAMAAMAAMAA6AAA6AAA6AA4"«xYrOpޅFAS1dF5 9/q<7sIQ0oGU˜VET0۴Ô`9&mIDv `co @olQiVRha,t|ƱeJ#Ǘh(_[ɍMPk> # }=*~NX  ˓sD_{J^B){HAg[#Adab Pd*4OxAXlQ)Sx{(_[RJ0xa7$)j3P̻? axi1av@a?VM{>xX{c յܰ%,L,jPk8VȞ•Y@gKAS}1 QFt{k+9i? àll\nxH,al ,>[>F3R]J٢RVTly\WE3[4#͜wfI7gA𪓂 F 3qFɘ|6o]QaF()`030)ALffIGզ# IDAT;l#C!FZ~eͧdL>?z" gMy+*h14}-*3K^[ axi1a8qi0[l(QRK[>vt =5v@8[Ӻ=7ic!JC|$&VTlc( ˾1ߡ|m%KLd|NyIj XӺҲQ;1WVm|p ai1a7Gx :=dX8]nltybIKK %E9>wS{O蚙w5𶋆8 eןH'RfmE6C@م &/TQT\eZYvMQ4b8 ;"c*cp ai$X% h*@ ŌauY-6 ChsZH1t&ހ8nk^A0ג;7cscO qʟy(Ŋg#s#+,|*~ 7\:ahXr8.>d,+Uq؜p,+dYvP1]]:~^W84 |P(S^|.J2-@IҔ4H}&A6AF[ k2[1] &Ó!iLsGb:Y8Qݱ6Y4h0Bg,<Ph6މ2Y~7^1h=oG 3F5ʲb([!q1O6v(.ݘƑOb/`m (_@3dNVV|3 1_y<#;U[%}íC>];{ZFW8kdm{-c[٢R{RAO 7%;W``RZ,'B s׌4 J·]/u%=fIM4KPJ䖫\vlCaE4Log#i@f JDajy}ȇDVTlcӍ.b=pOԇA&Èx _[a%H8z_{pPPm]6 :[ cn:[4ڌ8Y4DiX~85*v5ChcY@\.c+8T[>Uo7!U Ƙ( M iadpDf9 @HPΰo[ qeN5QBL}GJ#t6`wEU׼ex-m]\wa>޶FFdwk3\n2v3v4ޖC}a;VƳ]XtU M>{T%j۴gy8H-l7IcQ()/)`9qed( ڲO}۸~$ʮ;`ov XCP+Ҡ_l\T &Èp8D8$mՂvz`\Lmf1͆bc`0Q= c8 7]]ʊYr8\:Xz\|*]KCę}·35"w K}~'+G ~J XYpk֙ND h-WgϺ ~vN5|XzjH{<džl֮5<5Ol,1hI5o(7G ՇA-|yc=68u' h1al[ Fe(in]Ɔ~]{QvVzѿ jqzF1,y8ӯ´5-}ț ZaΈ;4}ŧuL..LpbE@çud4O^ Ah=2b|\?b"sawr>6ξ?V6s602'߲V6jhlhj0ڱ5s+P0(l#1տ5wfB/fOcuE%(ř0i($m~F KFjP0-3nR`,#0HAhˋ_,JC,V;m!} uLAA&+~G3:N׼+&wpڼ {t5,hkP}1aظشoIsdxN~_F͜ˑ#3x÷]mmddĆoޖ8)dEs~|:]?>TO5"ɔKRlub=s0ۍ(vk6R_{aXQ% &2ƎQSXVla !}ygM|/b٢R^F/ }͇d`RI5ZѠwGׇh[}[A*;JOZ=͍ӝ--'K`٢GKDc@aӛQ_89ǜcN0Ktg_ao%}n]7cİ-=B3B&\UcR}u[Z&egՋbV(͊) :h[RP0vcʟ~ij>P떎Ppxjh8eeՋ iC02y\Cj9DJLu/1v::}vٻ2=1K>-:==MC*t'4L=jRR4R+=gEYʟh]zYD/]uޙ%x ízvGL~?5 >ivSzՠlPP2G ,ReMox)+aH &ÉPcfukO soC7UGƆf&g$d{tx#Ύ>ˎNc@ݗkwLK m؜XvGzKj q<1(8ܢlߵ|wlYC@냮!' H/mdtfz0F4%&PkY5TB^n*j774qCaH &5gguu}s(jOÖ Nm40}xsO1gƑ;a|oov;di$:^;w|G5Xsb)!`8qg(Jln\cֵI]3I;{YD70PCgL_43]w |-hS c' hT%-W/[O,QB1^0AhƄ nԶS b"iC7D[MM}m /_x[SI?r{7ŠŎY Hy3t'O5y ;\n aue'- -cXRm& / )ʊ +U3b6lģ7>m02m#&cYJ8csP~̓/&1\O+U\kxâbHENuR{Za,vub;LG$vWN%uUFcв;yYX]0P`dFnPq6(u' 14,-aI\We\&* K4Ah--!vp_{l: /csk Y3luFS~H'cd۳]ƶ#G:~|q=gݻ6So{VQax!} ?Lc)_hΪW|@%K.׭,˜hh}1jQC AKΊ[k5Z'2_ˇ4,WA]30&V>J8dhXr80; >m0LPAȃ[낲@o%h! t5L0+ F޽X\IǓNkka9ҙRXtG~ub;[:qz2Ʊ.L6vŅ,[8l\`g²(a t0:;j JĮxnD!p%Ef MC_0B7?K  &GC|Z=]\l**Ov1fFܸteങ O["Uw7tI7 F$:[_5$_0[l1v;NO^d!v;" :zq +gR;1eqo5H#y&^^x}bfc/7|ikY,[8'_>uX|֍5[Qێ 6Af8YL~m +a+^VN-p,$b0%ڮ{npE{z2RՐH)%c򍙏: s u6* 6W1 򍲘hTl\\=i^A1Y̶lQkgܦeQ;FqEF5}k b 0`3X|sbiŏxҍqa55\ZfRYMC7¢ǻ̚tRL޵T4@zzpڣ&̭Q< V6Kn9.̡ήQ!^1^NWFWÞ,4 F}IÊ?bJe-ROm4Y +Uct_0`gQ0AzBG35vCxՄQ]sֽUjjc&2G0kI|y̚tRs5(jx#,:Ht:&c!~3~։Xftg˕BYh4]yjOc"G7Yb?0@5 >4ߣݓeh CA7zЗ([TxjţF},Y٢RʮǓ/V5 CQ!I'd,x߿eAA٧VsޅFAS /:VGhIvQ0oGU˜VErKtOhoF4 !~Gdr^Fo᠟4ONd9^Hޱ7Py4/l,V߫HPޑih}׽m%5-^!Q>xkY>nlBJSk7]k+TàAqD'AnUf([gdNf̧3$'CN\scߣOIFs!D'Ɔf-;'RM1 {G:fm&Ԙ>^< VV}RU$, _{Ӏ5 >dEm ianHJW׶r5z\[ܳD!y#G:cD}kE~t~ 3d1Y%S1m23v6RgDǮkob=w4ʟĵ8f6CP Ka JP]J(hH}H&o\ &E ͜wfɠi(&o{R-I}F]v-7peJT%_7$A&ÈL-4J㰙pgD}ko ;49{I,=Z|5X>_OC7n1鯆DJݯٞI b2[m%>ltu8bG{R"S2&e gb.C(*tFWdIG5@ %SzFPY}p}٢R^[i5RАjYޫOSVTlѠ3>m086 ņj-5#mg|NCۦy:2ɌS=^wbh3%Tˢ|m%KLd|H Mq[3~VÐAMysQ񀷝@0LCŏЌPu?i7cŇHeł[@D6(U vjYWAo[)Dl4f,E@CO'\l#AGdWdl쓆TʢBwծ{eה ^! 2M P ]( isZH1tuܘj+:cXůXSDF]x BuG 0{"55uڍj;7cs5-rCgdt+Z2>jgm?Օ=` h(>d,+Uq؜|2r{"s;vDMMM}7'>6{Oի"rHOh`'scu) #dcYQef4ڭIbkIjo}`vƬ:{X" KE!ЏY~7^1hH06mK80dAhCGs-mJ <Cvd ێ4N8Zc5ԷI8_^ OD{_KOgt nnb'=5jBۣ(_%3<1FpVkbz* ;_  U[ UC.ƐylxhKYh|,fʟdO[y F # Nw%n!:l!{*fB s׌H4"'&:Α#Fl5=ѥV&0[o1n5}=o8j%H#!M-I>pI@cqrՉg.[4'qY^ׇcU8 Kn+U*e8hH,]3;`+_[Ie* ]C@.iel6|m _a|M^ A@A l@R-ڳU\L|O-,~LOi$ DdOj4󢼒Z;&ѷFckkUrU3-үkFHtYVU t?5 >a]Ԇ2\4ZKˊgxϥ{ccVrŅ,Y0WNt CUA_o 򅣣Ǯ{)FXQlmLy]wk2e gb[G,FdwkC@Chur4R]%mɗc! 6AQ0ɆoӞ A9&]͞˵ IDAT+st1pl DFWd$Z [TpdƳHǕ -WCJ,)WTl(|ّ,a0C2 zןn|x4#݈MC0F_0 &Èp8D8$mՂz`\ȚL>&>ΜcNHzna;b0]ѡBOH eb2mдrK!8%1 @áuƤhPG?2'&VcC}kj˭bptłn;2'{mg_t8^pHpX_ikZ{8(O16ig)_zY|ZAF3!P[' KuU{@ٵB-ny^5,t#jX=^+*IFY arq &m|-~D@aÌK'%͓O|GJcC3c ^a+ӭEthDz>@ߕ~)4ڱ5s+P0(l#1տ5wfBfOpw}蘲\ 6p`?YF%r9&%ԐJ}(4-_iX~K4t6dc1ٞHgL%zПЍ5} P/.dEŶ+_C|X A,^ҢG( Cn $'6]N GhƎ2>tqoաxj҈?'':_nqqO8;˚W--'; W8Q= ;hnkbHZ,[8E TuŗEfh((bhHP0 I5 >$PX.ƕ=NXh·4,Vv݅r)[Tj\K5|o p{WRU-ޤ92lH<'?/fNHDT}DK;EbǍ5D6;ە4>M7{ ^;?ʓ6sFQǺ%_׈D{hOY^AT#JtT{R9>q $n#m2 Sz#{fli]7U/1 rbljkJ>>ȈlOp`4N-Ed!tàY<:J>,89-% ax-klų[c ʇ4,R 6A>*ao+ALD!3~`DkkHh|2Ǔ0pn'.>dG2oZ"'ï#&pn4&֪7iG`+%E#+zf^ܬ6Zח^]YBIض4 &C((b\v,m?)1jwP0q1=ׇ @YiA3T1 N'5,IJ\pFdw+Sk\)Cb˲{Y N m0u"OdG УȀ)Nn0% [SSυ_0[ѐJZxۻjatI^6lt,V;fLWfv];8&&(kdpME-3}k4 љ=j&D5z% EY݌3 Z-]5 3M^eW^'SɇG *O|m%g8Ki]V K.ڧ|HUCoe1:)b 0fYC]  ?{u~NAg ($UIIVɢ%Ue9Q"2wݼJn{sWBɑɑ8~qJLIdQ f08e fHeך3g}6f6 $F<Ż߽<zj {dSu<£% 6AloFuԂ6_~?{x2 hۀpEW<nUl6iMd#W6rj;F#Cʿe t|p,lvf\q?ʶ֔ІMۙ6ԅ9u8686v?$a^ ~|CH}upLlX9YņqVkÙ݋W8,Ԇmw\q89)!!IRC-XB:W$I_53եˈk6ɋ/j MIvRmxhLZt!лXIh1TaJ[{K**F:(N{B*N7ű#=}ދ@F*Nu|D5mv!ѸV(qWw`xІq:-ƽ?Uӆ( =MY90׽׆E@Ita6dta!sRBB6 A5pXT5lhӇ@mA8E5=h:jsij &\=Gy)PÓ٦9V };Xi|$(X烰J2`Ԗ0^ Jb~c] *n\f_?"A8Űpy5*5y>wxԆ3zj{6{6u)B椄$mKFүH XFbiOv!0F<-G.^xu׼Zu1I $.x?8)5+a.b_)IxfwnM"-p]xދ J.TIgyb #w󷴡j1ॲcqg.AᾯpІ/|xm [iVym89x|5EPiépj㰐9)!!Ip,mAŒo+c3IjJ4uԆ{*u`DhlݢE = Kf^3yٺpqOa lS[պoi,Sm_8YZ{ Ϟ|@dB 2헗',dNjbUM[mNņjsRBB6 %qt#QuT-0pNұ,fļ3^I,8)yRTx%hR_+eCey5iZכ|br1:W/ *8bnUKe|/|x-Ox ‡ע]m~Zn%nzϺІe[چ3iV_Y6jC,hՍu8椄$mK L#?/yG8P˚$Ns"KoT-iF#cg>j[M85+Z#B`a>"o[4EW{ZZ+ڹ`tfg*\[D|粡ׯ7[ɍN#]l h-~!n=jK8n[zY*cpa hὸaT+?6Ͻ?g'% ۗ 1'ˬy/*p6z I XIHC ,?`竭б[oС5T&6\ǦBbf Sl裲}tE+,Ԇ <1`6ھKfЗo"i$ոT\h Ҙ0L>|Cg20v? DlUz!I@OEφP$vذs^TmX8꜔ u]<^p~a>;JHT|?x85>ҹr{TBl/xCEP UI4a,5fS*28 ͫ7~z)H2⿭2Up|ˍÛeÙɠfKǺWYb9y. mw ms1kgӆ8{NoNJHI$$f?Kb1%]Pei dvɊFioÇ@2п2?* ¹W;*.^/#iȂ+Aw%0u:(7`C8 1'-nEtK1:}R?,nG 哥ۯU1kf.KDK?f%g݆ ?sFsRBB6 %'L#'̚82/F$#MJ$JPJ;r߾TR r *x}U VmWM҆Vz.ZU4\U5H5aGOvgkLd$v^lm3& oڳ|Cgy1z䒯|7o9_{}`y3G=ogC@.[o2 /I:eeNJHH&!n$k.\;:6O-=bXU GH\RYR8*{Ok^T-<ֹ2[*m0i:tf)Ÿ9sp&rqdպ ,/^ֶ;-ݟR=y헇[7{]9IY`CYo ++7I G%$Fzŷcp,BaS#0 9ֵ~[}skTY}х3 9a](_4#(q6a!tbBa1Jqb?@lǸ׹Sx>y?_h7Z0w~<_>7Ma9)!!IR˼@ȗYaZfn=N+HeBt,xOs*\ *=qsSiTYޤS#͆@X_#\OUXyo*e]Yikf!(qǡVgr/cN&",uKH4| >->-:Uz߻ҹ{^y>|/;?ӷ ^7WI4 &!Th>p±1 Sn40 9%,S#0ss#5m"e¹S'7]dpp{, D P)ޭv~^.ʜT P4ָu?C2‡׆^hݟӷ; T?LYh\gݿ sÙI IYi$2tf/q̃ 6L# \4/L]t_Řs/>[ckʼnUҾq[Ϩ$lm(yn|g#v5l~ϻ?ulX9)!!I+o m ±M(%镶Y^]jZ٢lZNCc낉N5QZy~%Ik3m;j󡳭(ҫaİ͒Y5`qxhau*X7 %Z}1'z/cƅO_UmGX )zй2Jwꚪ. 5W!8pDZ0 xi!ZukV5 WOZe]JVsEׄm=em#+ڹ[gPl"6Dep,4e\R~-dM/[-bx.C% _W,xٛn:Q088Ħjj-Ɯ\+\6쾐c~=ˆc} ΁ I iX"88\se=X: ~Sّf_ߗ>t\xIi=* r}>&ų!Yȡs-~GPEEmͦ˄gsE|[i|<>8DTUjZpOIO߬y/q{1 aCĆұ IH,!T (_'lA$N=*7]$`L8űsfentláIzJv* ~eeES) NCY3骞(Oo׏?{QӬhy/ڮlXȜMBb)"_W(d4V1O*fo(coOmq\p@fuǷ܆j-T[6_}܆_ϲa!gs霎SWA\0|xrQ3 I$$5?[؂님6-(Q1 SXqb:Xc:EX:4o ']F&iC`CT,H9!ӣ8BL\C4*a !!IĒqyLn\ IDATo0EHa܆Rta:FrE8ljw}r>,1$$j@ƴIH ? [$2hz58;hYOa3عsh1{v37,m:Қ5 EJϩ]꜏C ۂk:]kYlK iXZ0~MGbb&76TL{r1iO]]x[*JC3q4ɂ1Ny۷Мn7H%(xduUK`;mIH,%NP5XÅ1Fark)*L S( Gم"Mq,iC ̭_`jj*q6fY޶p~UXıLR2X`0 yUb*J]sب%jtik1Ydѡޢ҂6 +^;brޗ0z"KTI6 (FD"-L 04_V!\ E>4aL(* iC D-Rtan۪H̪ Zʣq 1F,B4l5yqn R˼1I|u,E-h\)#>߸YS3dufhjl ,s TAS/~¤EIHHP v}u_p.kf D"C!w=ՄFE@tSmCXe1 1Oi=UXs:rhėNX@QJ[$ 2Q$̣BiR+.Yӱ4=-pޏǙv,rZ ] 7~A7>}y܋dL!X.d:ZUSPU'uuNj\qu+]dΚQ5M+8|k)3LƩYǏ-xNJHHORc#ҨL$N6e/Ƴ+k!L|NUvH7+YWʎ=n~UˊȈםq<1\ˮt].Bwq]pQQ?hSg*0WB{p÷Nzl`#1_Ŏ?{o"r/:!/!XEgSĆwnGVm&ҘSWkxy!, ηe_A8^?}~'|4y~z3eYȭO Sţe{d=k`cruk 7}l?K"Osi^{Q0tŢ>@pe;uй r\G0x p=6?GL]QP\TG<ᆰIڪ{jjW;VIjN$i8g.7XwmG-7^|O6NyR n ͗P r?4б,#\/@H7MeVVR gbÙ|ŕ]k}W?~z'}cNӴW.mon:&&W/\LdΝ0ҬĆ.w=V{nGJ>x6#Cj0}'#,RU5p5ԕț: =co h'P/_?~'h2qh =ObK.×}" >R# sZ}pضmS(6\C7%t3l~:^z~?;4!3b11&ts` ~o|k"s߶e6HpDmGeߵR&qIHe.ҹ2F z4;XHͅAnEY==lٲ^nVJ-[W;^vdɯjHl깎'^x4$ma`a1m?/Ncx7{3)-Odv|h D9a9$]X5Ru*|tǫm*ܲeKM[vZPV?(]J:f2eEw=6K&O{Lo̓3/loO^@w}큧OoʮE*̌@jEŏƐ9p]Ƨ47dBMGظEi>w|a bc۴5lWt)Eꅋp\#7pvϚ'xvAc9=\^ca;^bG~F@+j:6H¦TcEEZu;48Ad-0J&!!1Py'L L_x-\٣O^KՇabQ~zaٹYeAG%akni8xqn\~- `Ç+HgP*PAY6fZrheqXDa;߿!\,ys;D՛aE+eLۜ(j] ύjY [%M6 s/ .JՎ-ػlc4 -DzVm7|]`۾lAiһ[~^-m}I ׷cǎp{Ck50 vV~78IeѹTiQ=3ѶU-gt-ygҩ 3ojjzq )h>%UD1yA2j^ACΡ_hu4d<=T,s*h1X!"WE5b&>ƲX"Uk$}Z)T5 p"{!{~NR 6XkWjke Q3vY4mk7LqZ<*S+c$$$`9.Nak[C!pk.x s *tO)֖h^ൊ$wegѝm۪ qV'0"јh\_p|V@zca,G@jht~q:QvΡCDjetb/﫞WGTϣ*ܐu6a1+z h8'(.Su±qGܱ^ Mh'Y\; )>8<9W8Z˪MlKܠc[NL3t$aj:LǟXA 33Q) ḭsS< %4• 6~afƿ/a(z !"ZdMQ28`+hp, oԷJl$mg4jYVZī.޽QUMSk7ŏ+( 躷xUWra\s]8r0k֬֞+ٽ{"ُu~;޳j^j[[BXf0H1T-^EVC QeiYQ"9Nt @&1}ʷ?7]j^"Adž 4=/@)hKI9 u>U8@ࠒ2?Q+V Q1_] T[Uo"ۯov9WtBL]G^lO{ښK!Dqɋz*iavzP`X# v;زW+ mMHj(~/K.EQ8p`Mou9p`#gvilڤby477MT~-燐΋'uzkUU9q(W]u5pa,K _{{;I&뙙817 90k!l02|㑱v˽OD. udy xl_MYjaqu%'qppVS N%$8p,P4T=齧h(<υ+@U<cBz7,-J**[p\z$$$JkC(Sq b>,(w&BAG;s4J0>>mǩKwU8pys-ނ:00@}}q:;ߞ@?L.y;; "C^`~vYu--| Uv. c!EG5N243 Jq7 doE]WU㖼g*JT !faMB\aP Уʶ6m-c|k]&,[Pxے8˗yܹ{n2$Z2J$bb:;wRa^6n<.z{ˎb:]]={x;/|?#ψ~66fM YFd``?%%7D+DDZ{Z+yT6~󵯓2 HWWOH2X^ [ U4Ds.5B5Yt+3 ;Qb>b:}T{tڗ[=p]mxuIW5gdc6g$u!aOa lS[YhTlrr:$VyOlYްhmW}d>%n+[ojF+9 mQ@.i=m'QϞ~2ru+'3c-MyZw4ϾyiT% "F 7I$$2rcэ8G--O{ۢ+\,t,K1b prAqĬ}$SE۟I9ӱ!K ]NIX.ƺV!TM/ 'Z=pUL"RYU $9LUՙ(84db޶hy0Ӂ9ITՈUj[qFEp=l㲮,;w{ln"㺮WJ6pgsywI^?_rM[<ΚwclyK}FcڪɅa{+@6 sDE#U(iUH~Glf``?u1 RQVUS3! YZ#B`a"|3m?{.f(z\Ǧ>2Wk«8qmp@:lBU>8{WҌNYlhK}rKq V|$/{1+oO`Do׮Or#ϼ8Q8=|G︰vyjh[0/+[_$N6 L,zTDXV(E㻢Dm>YEzS)S%h !y[}}ek-~qx=j%}j[syOP$hkhxTN{XvSU[Kpq1R1XiFp:, UOۚ CeǯiHJ[fc\{^#Išoc*7!FX1'\aŅdpMT\c2o yk64{##E^XY&S޳'\ О]G{deIZ_Ͼy:Z #E3rWX7/:zD6d]|x9' hyfA٤UY^u],l۶Q%TGB8Nm YU.*G|5&PEk|7ˍHx mp^:RUsf\cF78pٳ'\,Nh [iLUH\]Ml.$8%QZh_AM=בͦϸ}%rE+G_&ҏMGIhZ, ؏?Y`tXm𽘮8k8S{Ǹ`Mw]Ԅi GN~Uj=5i.nWF_ᅁI޻t\ d;%x`o:ή7>V6yW'G.;~=?;_bmkW~d:E;Ϝvgy}\C۴P)_v{4{O}Ό_;Ϝ!siTmNY|cQ8 )+ߴ{6qf=޵Uq6 M>ܴf[ [l Fw)b֭[N+MKk~/p;oL_ZGL?1U~(D>+E0+c lDZ׎ {= ?x$Pkk#؎K$3/{zGG ~(GPY"oq>o]s^e{ղ.l}ɱ-͚/N"3*HS|sKY{N;28/aŴlGPDx d ^>xdgi fk;:MSƠϟ?v\^=~/O΋yr(epS{Ji1>pr~6:A7I$$6^R7T pPUDjܳsoN[y {]֝G>?E]ke[-[ms&+cƢhG3OLlhiiX,i9x Ǐ_=WXEETmQWrη8, 9IlEŨ[SXmlo1lY/̊zp < ^bUfx]DT\ò:z,{o'Ey٘mfPqq DAW4q hn51~1.Wk@M&?ܲhp₊ I\b0 0tWWꩮp_~MwuU駞3<Z_mȧ( )Bhykzʼn-LY+tԖk+[=pweִd\GG]=m*gwڜ| D=mCz-8gvv &mv\}r0[=G=w{>Iq/35߲{n|uEy ɦ6Z:۞}8FEڗ+hݍaes 9WO ɌWw1aT ">}:CKhzr|Ɔ|qD X0m7HAwAnO\;rl]W6;6e1y$e> sk'ÿ.eΈ0:/#l<siӦdN ^xт_#bzEh}а3 6`֦ 3wnmQǛR[[C}}--b^lb~e)چ|eZ)aܶҢAnOY;o_6swXcFד|㲟{*SD۠cN\=i㍭|qϯ:fΜO?M\O±^ad$GA#^kTQ5P e #{d:έeRQ12/͗]`}*[w-ϟ U&sk;`YӧODz,䓺<}`_3/<+ʼnt6oκo/E #N5f-/fu+Wr?eum/,'WD ewoF Ԫ1ad1JTCg]mqDD:inn|_lunO {$ e}`&uuu<̳TWW]T5hs퓫/^`M[x]#jX`%65i*'Nioxw)>esemY7z|Ce&vnlv_ʹ]DoqlܸEQ0 /"a܂T(B 9Eq:[3mC62nx>@B:~"y='x C0Bw0-:Zvk;iD[vH贶vjxLMz'~LliȰґ<1ӵ[4  G9mٲep xlذx<n"a/c41 VodШRiа@ je̝;:ƍG}}=` =#q\sb$y-$޶cWuGފZ<~H?r֑ / `sq?$H$"A8 #T IDAT $;[۴H !a'%3oy2oaN?O9BoQsg[_K]Ն\ଘu{l5b ڷ0obo̝;s쫭I~lx˛d7o>ߧ!0dʏ g'r}E߸p*Y8t6^LBy_/ʍ. 8u{WD"\ym +"^fݎ8N6pP`@˘-،Xpjp9s1~^\giwNĈ![;d-$Cjv"bumtlM:a„%7źqVX;X;,}4ث!lm&{Ι_8>4.3wuuug_ߠ:7n4I$SO=śo'jHٳgSPPaia`Ȩa'Pq$3[s=L/fذx{~T.䷿'+"ܵüُiC^ M/ؕv[+ZZonoz"[}}]:\oRRR)O'LwT}vNjy ζH-.[O})+yF^+Ѯ.h5M#`***3o6~ 3f _|1_}mmmzjƍ~5װ#FpiO#0w\~iJJJXbmmm3l0>h}+lu:]mm \BabۜlB3'T> }!Øf`A9ױxey,X0?ԗT;[1^V'<:k?!Ul7kNOΈJ,̣Ϗ/Yguf &YVsqpgH$Bgg .~_v:M7{:*sFbΜ9=M$BH$w9 J1dyz!jjj7n---lٲh4J 6}R'~vLCǴqIn}^!ŋSsCek4C@x {^W0:HqRbeU`ıǣYq[? d`[`~Y!9sl]]=/aKy̛77tbeF{> 8oh#M=vmNxeɫ\DUU4-:y*ƍGyy93f`ڵƁhO?#8w}C9kS~SO:_)++OfŊs]}̚5;:<_WꫯrGSZZJmm-w_'|jz9կrI'0uTjjj;\]f ӦMR<@V\W.nj[oEss3mmm|;ߡxZ,"F þ뒊MdY0]W.۹ ǁ8EXCj zx=+ zLʯOQQP(HCCryz&i_;8Ky94nhbBe$;gS&U#sN[,ܹ32E3E]dnPsܹcO?Ͳe8#ٰa~8&LSOe̘1G}3fj*Mƈ#5k)..fi1ZTTҥK3£nz;u]رcyg|ǔouV֬YC8k׿5<_~9+WYO G a&Yո턢v2B;ڂ g]ѻwoPkf_96F¸zW/{+5o{}Rn]6l[bݺu9XO2gv:wic: ᩿!:Ss7egKӠ7lg~_2|pB7|3uuu0/+WdĈsGryq嗧߿K҂ ෿-_='N$s7Ϧ:u*Gi:zh.B~p=psgipx ~Чy06l`ժUL<Çkm66nGuK.;v( DB 0膅Ītad'[z&+Y nώiZ3W˽ܑw[6Snm[Dj1RlQwOah6u\7wFW9Ńɹ3x63o^ӧJ`u-;~j _ÛW;>Æ|_?#//s'vqA"իQSN9%c{,ctAM4%K )//~eeeeYlܸ 4MקEN0yr:x<ÇGӴ>\;93ikkoO{WIUپ};---|_˲hjj'? '|2pK.Œ"aol'R/Y[>y֚Us-~o mC^:D'V@U 46hV{-Ӿ~*D''rّv*p1/cO,]Ն<~''_{K1#& 1!#Μ˸{_;:~KoW?L'i۱(FK#F[0+Bee%k֬c0 ֮]˘1c\O&b{3ѓurϟillsn[o&:rX,}X~= ԰{Zg$<*{7)INBBgx=Hgnˎ[8YV-5j9lb,p឴/$:jLGv:RنDp;\Zm|-mћeKc{;l<,>,^_845oyǠ ;3o[όbgݧ>P{yy9h4{kjnnka͚5iSPP!@#cǎN8I& ㇈6ATDzGz$:\w]y{}s2^7푚>}zz'<@ڐ++F0\DdH%!Dbşwv³^O]6?xm ۡ|3Y;<;5׮zfΜI'Ĉ#x7x3Œ{./eee\x~v }wbC?Co[a'z-^;{yv-M^6 ˿{%^Zs.`G _2mkzqG"HqڴiB;;#я~.~8ٛnBr rKhΕ NkYgYgce]e]{s.B.ѣGg M-{QBNW.L3 6t#Iw)w1}t,b„5\O#'=9~Oׯ"i=9EusD J> WraY:k;߅@ L[vpιgca23YēMX|3;?AWK4mN*xw[c;b τNR?/w}\]O |2е!2LS쮗*@m^PTd-}9`ِO;x_YA 4 0loIH>Пg;\~3Sר`0>Y#o-HX{*yg ia)!cXXMI= hr 6Afg.vl`]]=/H{Ixhn>naq}h}=gίФcjP~)B5!|mo-\acyy_{AU5>+$ }_y<흄Qt$+4 !9m0HxT![27$;FͼUWWϡڵkҢͻ SDslxs{/HeZ,u ͫmcʆ|B/7*+r?fÆP;i,0F /eJb!F9cA\yjߚ} xX0̙rL0 $d0҅XD]׉]]]޽o|ҀO7n$DBD"pƶP(D8& _ h׊=FqYJxT6ߛ xv,@UDd ^_.f~gܸ)TW%oc L8ٝgӧey=7W6I6q*+G1vXB0DuozNSD=U퐤 1tiar_ZZZhj'D8ik֭k[DF#覉P4.E ى;[̡e7[(--󽃽w[lEh|֯_ǔ)ܱ)s܈YRMGkP`LJm3φ}aOuQVV<0}XPIm?~ea? +_>0,Dm0h1 jEmqF'0:(uxj efm-Q./ P]sQބS}w.U$=aCvHS6U RDG [03e@u(ԤĜ1 @L~prpr,_0c}dbXphD*A£ρ6A IeLSٱ 52{0uL 75e4-5H9ح#2&}m1żnݒMZtHv ~F PSS' ն`g=ƎΫro6f!]p% X4^ð`[IҴzraiA(;,HletiDg[iC3f Ǐɼ2/NXO=SȆ),%RX @x(le}a:ưz>U+y}S5NdG][lO 8iH먨Pj(FHղa )#HOb5k)))쓰+i'sؼGl0f"w^Ya mkS^^>0;Zô`kU[bR ;`l$"6AތUcbp=bwVR mt!%֖S""[ Gtä } uͺ e{X}maO ˲~6,\nrZv3#k-S]ǗX$u]禼[C&M {Uӈ2ԭD۵Ck&Xh*uu̝[#[{4%1!Gg |je"Ͷr{u=z+!\ka :-׵!T-L pn۔a q{~݊G"?"W_M[[o?%\† a-[0rHoСCVD I(êjA S'ٕ@ |ul߾Y@@vb+]^s +[9~o;P[;7SmEw]3j-W&"+κ]/oퟷ jkk;w^~˂Fb&My-|mAI=bqpӂ2mmo&ypUWquQ[[1VG?˖-JN8|};p뭷l2#䪫⨣z7,?y(JzPUUSvos^;+qGD |]nABp*CԨ=IalmTX 2id&MEQ5CĖ{nZfI! ~~aQ ӢeHAo !}/i]O8`]ʝ,nZ=@:h Pk':RM:;xBG*@.Ä#z՛)/)hkiiaƌ444P]]_1e1}tN)//_|3q/^3g|W^yqƱk.^|E-H0vX.b'5%r 6#&=1 VodШQiа@ qEMM-}'2iRml|'皛eH fbP)ALt~*znHU^Mel5k߱c0a Zk'8dTJ TsnzzEQB\v\p \}?m۶f͛GeeeCg:_~9<EEE'?+HwM7Caw͔)Shjjbذa_QF+pI'2{l$Kq=W⭚D IDAT\mϟ^XXȜ9s3gNzW_ƍ4+Wr)pꩧfG7o̥^ʲe˨?D[lm1$lIo"E3= =-!?AZ Yňߠ-[&3_ʻ9­&}@ِzl5b 7qsDys{|!Wy5|m9j몪46&OzһVT,*+[ki&I$ E +V`۶m|_`fނ `ذap̛7sraQG|A^{3fpꩧRSS7{^x馛8S)//fɒ%|[⥗^%K0{lz-TU}k֬ᢋ.}o~ᮨx+;l!1/p#sĄ6x*@mմ sۯ}=P]=!kVdZ%L[CaUvx @Q(((6q*fϞ+֭[{=zt^!Qs'rw0eƌýޛ '\@$NcҤI-_='N$s7p'd,YM7/eY,YO<1q}v'`Ĉ釛~i楡7x!1l0K~T~5-߰`o"a/QK Bj,}k6קy' (sEoKQK> =eCv `/Z9mYeaz f;dz楯o._^>}zy|$~w>ڡ0y}]HQ9HP(VnO[8Çg|ߧ뮻>KYY?xwؽ{7?O7o^u=zt1bY7nd„ קE/Ν;Ϧ%Kp'dtnܸ13`,X[fw^6l@aa!ÇwQuW}śGa¤Bv%!I8BPR|n[ZU? |>7 4 0 Q@ŔKF0 ?^E8z-ܡ}&T[> |>HtɴMI 7%5%Zwc`$^-2e > s^3\ T:n:ɿ@"Zf/NIg[[l~ڳl,H\x!a2CH!Ah*o5[c74M à3A8b9WvvX8̷7ĊH$ T=W_u K._۹۸ 8q"icvZ9昼qs뭷rG3zhnV,3 r1pwrM7oַ1b'N*^f͚E8K/ݻwk{VWWs1pmq7cwyD[_ycB6A.6V*ն H@H"!9# &kzxh\v,sHO o`"kgh! vw# 7nhbBe$;"aR55 !P0vмys3lS6QC-s[ 0qvӢ-{}Ҳ6>URC,)XqzDO(ڇn(|dݺuA&MC=ԩS:_atI477s衇/fjO>d^}t(O>;8 ^u?f9yw]?p饗r衇F5kO}ncu z~k0!33 `elx\Op Dw[y8 y67oLIIA΄z铖ށaZգCE6ezʔ) կ~sᄏǶP[n[n%9,mrGOiӦePYYs=5\#9Dwn[ 66A膅Ī"\d'[zL Cdqw%a|pdn?lP/ (x6,;S!3C+?-;7s ,2'+رcٸq#jP:u:uu:7a&SN]FiСeeh! K2]ɪE=d2ʖAN$*h_*u{Jh!d{FIPAҡ|G'v0aDa "W2 \vh(p12{6$ZԆ.:-O \6pXNH@#mC`W;dHQPewzjXf7ng͚XBYn3@eqA߾i?>Ҳ(UUvw ee%6%%XvUUc1 2s nBIIaz.[1>i=i!PK}8-0L SŰ /QY-0p։i lR`L"a/)T@$-4d@(Jv͘L!Lbz6z`!1!m7ͽƒ)!d]tt4եP\cRwaYcZB⤓NBȇv0NҀ3Wau@CjJK=.Ʈ];R"l%ÔĚho"ljwu"hZs7A7UB@')7}i*MD +g0J:q`H]SB5`kEBQ(,`ƛ!Jbbdž\덺 Q[h4Dmm-444KT]JHN;-;9"PǙg~˲hhh  (شi5mb (XKTk.Ap3- źU+hkC{]-޼!R0`&M @ bTWŊ+Ҟ }=C18sÇ]wmD -L(Z3$;P zm$V,$"6d@Zjgaj 7q TSSˤIٷ/ZV `./"55has=m|mpq2ֈq-dHr=VLq{ #憏J`hӟ$Dp zzn"A  A0 ]fU Ale"  E0Sti۳c?ok#RP"6iktp'58gņlBQ*]P{N l[bYTdLR0- T1.AWW;IS5HRO`9dsAC0Mdx 4/^l{MP4)P#i0dH;n0XfʅGi`qLڧ^ ?8l]ʯ[9ByBuQm0 #=%&T(Z.`F2-bC@5vBŒs;Itu).J $MJϺb[9a$=È}%L#P6v-,%iYD+֜h,A Ivt*UI{[3'-JtъLa$u`d0hMwf R(@ѸohA_5-j*񸎪]qԔ4 G҉*EP5˂h"= `YaTpAq߷fGC=g3wh3ps;qF{n BmYSg;%fImE 3\bh$_cm!&ڧ{ mQ@P#F9[ûF,۵H$;iXC#(Z9Z,bk0tIaX 3r =۶;bXPP,¨VTUcW{H)fŗC2i4 JFkLdM )uw EQ dPDCqH0",,FfJa$ZQ4 -HxM ePQF+(agMґ{ /[oOFe?]H^D D KvazgwǔM{1#++Hv4a&XA|w!ğo6єpobno[j ˂ L4Rv8#GU44Ma\0D;h9vd9]h*PApA ]1T%θXr$nT9LEMg^YQhCTO(ԈS"}jj%;bA[OO_2Ap;7t0 M2+"řM~GS3ڮe ԖjE F0ЉҀ:4UY>CMvtOWi#6hž,o-* ] MiY(VTP70nd aL$01 uC *](kBD'ZA!İTTD )):*eڟiZ1dj 0$JVpL#Z]-(Ecô0q9!%""C7s\olp-`sFE >QjԄdu=.i0VJ;+2sK(/6!WoK^^}t{ۆ\BIe(JHzp#2 !B8V4QDj@E5Uuh0 0R^.Ӵ0- Q4f@(rn3fh5%H Q@*@'wbbI ؂}  C{Hܲen:PDeql-|G 9 Xؐ ӧ> 6z-, LB,bZF~(3&ð3 T0 4MTD3MJyM2ξtӛ <+ _pkf p9l~n./MAIJnψ]k9NQ[B]FJi=D5-[Oй&٣ r@kݞ9UUĚ&'؜~Oe{xP{& +^_G9;a"7?m"ڲq&޼Bys"MA#i5q~W` 7Wy\}gm BU6ps -`睯'ԼMS 7߽ Z.6& iPup5sMZp1nO[./Vqsy6Ao2MA\nm}E o-KϒU` @N6ZWلX_/X므l%MA\8ps5̶MMyŕSmil}E6AS 5?DW lMDCem&}6As#ܲ ]g6&+r \,|'MA\ ě7||E B._Ai6[5aO $D 2 E&AA&  hAA&  hAAD  hAAD  "AAD  "AAD  "AAm  "AAm  6AAm  6AAAD  6AAAD  6AAAD   MAAD   MAA$i^H 7 gY8s }# %$<*  MAA&  MAA&  hAA&  hAAD  hAAD  hAAD  $>Wyt$\pR58A  gI=rq*lC/& '{-<4Lx+I$HJ  ^󴙆AgW8ab  gN&]qea"AAh{hI=\4,˲(-ޥ։bYDCXeYh*\48pY|GiX2%Lr|AA>%& i@, >\8i_L8a]33mJ&MD ebhA+DDZi٢ʹLLEKwע* e%=`&dih3#2ĝ  N)?>FiI EImC+aБHRRrdUȗTM6 >o~c8~OERp4m<kW@F݃Z]#5>1YsY]I؞ԥb7&"[ ~=.%p7Q߯9| Vr/+v]=I8ݥܜl}~9_>DF^ܹsuQ{F-^g۶jjXqmX1Wu_I9!WYYYԵn32nժ #Yf$|Mr5mZP5005۶8lۖm=12/u%[۲$XLܵh3(H͛p4w$7j(;;[|_x<"cH+'uXX͛7e[`S$7,8|L%iim[`Pe<% %?߾w\7luV0* ) q.JCfmuݡO Ϯ9,5,J-yc e +*RƗm CəP($qRK$kx_Z`1H2FBᰂ2Ȳ,5 mwhd4+5m3ɱ D D D A`I{rW/΀ܡHnX5sJ4ףnk:F~IQUH$ub?šrdP$!@z:}^{Re  S"7j"3&m2xҨ_1Y齡?` ql!#'5̴6{ˣ`LƘ<:00ӧܹszȿ3m`Jhllŋ|EQ߿_d!TР_|Q֭өSŴw^"x,ŋڹsۧM6DPHhTٳG-cР2E"-[LON=fKKz)PK,IڵkڼyTXXիW-c/]KD庮֮]TIDAT?~b;Ԥ>HXLhT+VP__$izWӣNm߾=uߍ7U'NP,SUUy?lj`L޲n)L6D֮]+uu]RqqJ$ԱctyI~ڷo>씪6p}y;6CmyRiiIz˲4{u}>ܤݻQ4@yyyڰa6o~M.]eY[5񳳳եJ 2K.=zTk֬3kO̙3vY ,$yeQee1:y}vTQQ!IjnX\S{f2wT[W_}M߯'O^uڳgZ[[500]v˗ippP$E"ٶYUWW^zYX1z9D"1"0QmL7oۺU:ڶmlVyy~^_GI37L&jӼyG[|-% 7'K~wڽ\R===WEZɲjkkSO Rב]/T<>ȀLo U=}ٳi`~N6c2t8 2mCoQmiոh DZ/M'&&?KI[r ?*ˀLPW XDHܐ9uZBlb`}~ѧ\'W~xⳕD‡עrퟗ p[a-)Wqa"9ϒT hz )@%K3¶ &lDWErIa8@h @h @h ~Vmm-"01@ v~,ZԅIENDB`tiled-1.0.3/docs/manual/images/terraintool/05-editterraindialog-edit.png000066400000000000000000001767111315121121300262000ustar00rootroot00000000000000PNG  IHDRms pHYs  tIME 9+`x IDATxwxT3l$%Z(XzE,D1;l-{sQDEzA-޳}9YHysvv̜;;쳁`0 Q!QXF0 Sl"@ii) `0=Ja`0 Q`02 t`0 ȕW^yKxdz"##o>}/o=2LGckdddxȓO>YVV>&!>!EQ! .LKK[t׿e6۟硇?~==+Wnܸh^x nZZZzyQ#t8qԸnz:{Ji%K:6f49ӧAe5M:$M:p`ݺuׯ9ԣG?]wަe~7&$$ڵr|r}w]w}_G? (.[ |bq5dffJTXX|LByۇ~Z>߯ &zwy6m֭VZ:KfϞ={ ʲ|WgffX^^f͚/W^իW_|F?/--5kn߼yoI;zj=:..G`/_ k2NUN:qDPU3 999v!t9焷Gןv=??o="½믿\'w} . 4Ό3o߮*<$!!!??)33sذa'vlڴigy޽{hMvdpTVVʲ`4555j-/򒒒Ϙ1:s9g׮];"Wiv}ݿw?CN(}{XQ1NTG !K,4mYYYm/rȑvZ!+//_z5 2dȑ֭qz뭟~)BOIIME?cƍ֭9rdlllCCŋ !s;v z._ߺuŋ~ǏOMMݲeKgwEB etSGİ|<+yTUU*eeeokd] &&sssqqqz6Cxk8 ժjZ=Ok(++#|>0.hP]]1J$%%%` #^F78u4''sz \p8h տQBͻxhOۣ˥i?I93&MT]]bŊ@  \~L[k;L^<yDP__ŇSӴ6uݹ#;j2'iӦM4{vrqqqr>|xj ]v׮][UUՅbر&11q„ 呑C]reZ=8"I҈#t0-iߝ$4|ǎ=PSSӘ1cTUs;,WGw7 ;b`0`=o`8bZ8ٳg56m7n\ͣ/"111===##cǎؙ{n 9rdss}ۈVgX~}VVֈ#~kDnwt$k0\dɵ^\XXhE:u= eo\]CI˝}`0  `\`0 a~]`02 t`0 `0e0 t`0~e`0aW6`0(`0LG `:`0 Q`02 `:`0 Q`02 t`0 Q`02 t`0Se`0,˲,O˻88Nt`0[RR~/uu'奦I"# oLG q%%˯:11$>x{|,gP`kE$%'A 8>(iSeS9 ""ⴼGQid3otT[mȳ]>|kۿMMMl\\>},fq<9ih!F1W`\[StN~}~B\7=6^5i9jH]Ѫ۷pq555֯7nj=.g>۲!i  J.yDF|q4 !d#53 Zxzt >3EZcTĒmO1uz㸸:k1Kic6ʇEZ @8  7'`{`<$g0qQSxh㕃&`|l,Җpw/ynzLLLyyyjj*822rرyyy"ljHJK];Ue|!Bli⼹e= FwNF"5iɞzDBls~]7|MdɜneKߩf1;nV=dG~fDΪʪFJonn5jԱH)B۷{iߋk䓴 *8C !Ϙv! ؿ)U C>4|?pAAA||g̘未Ο?h4LOO=u7x#%%4lⒼO|dK] :nM&7EEԭ$S]P__7tw=]544DDD1b gub=UA p$n 6Rml/X`hERz뭷> (-Y%Ibu蚨[n ߴi}/?^ׯ_rfΜ9sw}wÆ ~{JJʸq~gNoy/^/O?}M7" Ǹ.`;SmqAX9(>?'73I-_Ss_}ըQ׿M4yȑ̟o我#{g; 'ٱcԩ29rپ}Ǐ7 nOSss X,ǖ-=GCO=vI0 _+*OuZ<x==syd0E:uqg~73ffz.B}P3ѧٻw/u|qg;c7l` GΛ:ujrrrիWO<.Z%I/@-XfM2eʔ)of[M)-Fnll'N3O 00AlQ@eg#d2Mp֭[OoΌǎ=_}kF#7vwq܀wW5oQs݊,T{-59ve4jkj+*QҞQEzCk8--h Ϸa[믯nH7̌;.}:T2HUЯ_?_ .h̘_~՜9ڄcvv{xxhfvnvʔ)۷o~g}뮓en|W\q̙] 4C?#<3`=裁@G.[q\E: F[>ٳ̑c)ޚ^OE~;Ɵx*lwBSަe92E9,#Eu:LFSScTTVNr޻w=HMK_d{cSraO0!Svd2:t`0WVUM8:xS1`עT;QI䪪ޢ(}L~ӃĄ=9k߯m۶/4.ljn^ ,߿ҥ3g^,)R}},'WWWke 鬮9s^D[ 2e4aai>R1J1J9J9Z9ЬV@yU}J/%E$Api@M0:CmnvDG;UN' ˩Wd2<9ygvA ֭+-=ĪGӴ`0( _K. .RUUk~7pCg'O۷wGPQxf7wz&Ƅ xϰX,II_| w8}…GFF\;XWLlN+w{#j 堬]v(*{yَa%#Z$+,.:tz͒ .`0Z(+]O׶sy7l1uYz_֭[>4͓'Oods޼r8<;gaU q{w_sN1vؿ/ .8pի###n^G͍[xqI/:[lٺu5k%K<ɓ'SQ;3Z=\wg]uX[SksM~[E0)GX䆏8.++WLtYYECCd3Ln4U4pqGyy`zGGۘ25M=hL1c9eNg9b(u,k&$I)X )&E%`h89FDGL+o!BX~7/dCh#rǼ+4 ;`5(J& hnb5Hm~fCւXSHKO;OJ/h`koG3{tk83(gdά*WHoƐ: 22'+n`ll!`S@S>S+8I&;p< 'JFހD T7%fP@7M7>kxA,FA|2sL"!^h ~o ?LJsn?oW?E[p޹n1ލ$4ZFrfe_zAw'+`:R%K1QF#N @XxC'9r\b , ) bsǓdC`B0bUC5M >TmѴX;BMth36-]{AXS4:͹L;F^Yr_ݘj+PBf~`wL0Nqnر"3UW|M*%z.%I` :p *0.\`Mă(У H@CklC$` ΞCwZȹ,}e=wϹf gK+]"@ܕy2E=Jл7'&ր 7E@v!,a/L-]2FIhw)Qep- T6CUJqHUq )Z|,qnla$#ASoj X!,XxM/V&zmw䴌Ĩo̙ιfvUAl[RR34TXn-SEN V=28uTW72 IDATQ!O! $I4 d`.jkc#Bѡ4U^WdbÌ#`Z$UC}a%^"Lx Y X90 BI"h <%.}#uY.[+{`G^k0[-(%?T0gDBc3{ut&XqBƍ<5M"/ A9тe/JKK V%8I? t !no5Ra;8$`M h$A$h x^ZFBt`;p:Mh2iX2t9F( .n5ӟV~tk@K9p Tl ̛9IYvES\w&:Vg]s˙AFmm Ʃmi'b:cC`#`EŚw MQe0ɔbB`+0Fz/)a R> w 2 GpT;\aDsJ[Qi,OlՆy3~O\Qiά1W7nK и-y#BZ6WTMëoK?\lG' `297&N*XS4L@+`I o} &WcsBFf%/># h!ջ^E'#Xqd( $5a$5HV!A2ZE] `%$cB" @%`UUUU_5tf}^8)AMS*cb`BZ룖Q%ChrĊ˩j~3@4O0wХolŲxOh灏M\ur00"a3p *n OyZMd;^ݨ-{RB="!q8&},QzuS[*4>&4MoϹ*68zsfYh pH^ ,jMAl| }Bj@Q.7zD|Bm G&BHWg#SݯKZ ic@ R.Dp'"^\[IW嵗5IJw:24kBo}mJ0`L=敻| ̿b2Wr/$5V{G%c0Y_PfB?v#/Ha wAGU`Q-IF:۟M˛ .~_%oz;I P&POǵ*8p)^Y#@ "Khy]Sr&ź>owy3hRDT llmhsn7~ɹe֯Mq;˨Z[pxDd3S.:,n QR"o>>1H,"*H0o#42^<~)0u\ zW O+|8'3SV}_LO2(-/ uT?ǟ&=n7Oyeg$E$=i㰧Kqh+#\X *S[SL}h_]h0i2bϒAgᠷ}D>46S"28oXk1TrW M@PM:`zUP7*@s_inQ+ \Ńnb|yVd#hc¦6%]O>9GK*n_lE(OO r#~ŭz/x19} ܣf:ZV@O%D֧WpKPH"JW4sڭvX7ο>;ah܄!fO@~[ݵ<4D( כ+]IB7{sҌ"rQ9ɆCcG"x$ ZjUh .ojR I +Dh7+zpϖ}[*ݷi~HU,ߝ=DK.{6`D iGHCp>2MkأA#c-x`M 6"Cd{O)ݼ#C,Jg Y ? ֔ʒuEU>w%7=L|&[TTLb>iBܧuq_5WDߎL$)X$_pj5WΝ9k,*&|>A~3pwZoË{9yZ tt=+nik Q$%T5E5%h0G$Z@|XUhܥ|DZ|A_oy4s\=eθ(ţb8/Ԗ7 ya]aY 8)ԯFK5 cl5 FZ-FU `Y4?yi×o|!RYhgx{īooNMvi|0>_4wӄ]0ybr!g3Ž,z~|S FDbedzͻ#^5z#P Hrޠl*Bmosܕy9Vst9ּ E>AĈ8;}5c HĐ]a>A0:aɊ_'KY;&(tҥS a#ntsō8Z2ꐖhػ_z,iz nW*aċ EkHd?YFEqyCFT_hoQ}tdwάD_=v5z:pgÁM.]܌ǛQ9Q(~#D9Bh[yNOUxABK.RZ.m2[@OW<_LK=-WN;j`ԑC9L^iK.ƧE4<-EǷZM;0r DCZ`% Rۺ@ZЀ.l$"snh^Q/(Z7bԐ;pum5Ѯ,&~g?`Mƞ+VV #1"gVvΓZ=ҳGQ7qmDOܝNO=2&J!eo~ v5J4Ef+WwQp;Ⱏve{.ë FQk&8-Dtme%%Bh%h9&Dwː0ul5%͚e4Ljot3S' S5 : [淊L r9G`,-/BW.-KJ ފ<μo.8*{h&wsa=f)iſ5/z6&8[_͎{ل`˫*m#G}Z5Սԑx–􂌌;Ҫ} }TؕI듩JWC5ߙ"9vUlb}/zw-?*=6wfI+#9[ʇ=ײi.U*\|^^:3uFQt.22W#ԁmsW6&[ +f^q3Nn@˾X{h6w$ 8c2(0 ZJ@ë*(uԿ~,yoW+z_??Pƞ{i-CԪX hdg7\>rЀڔob:_jv$=쎉b.3rWtI7ę 1V"^8q|ιucy/ـĄՀWrjxkl56~$DwadW_Hl̈@ 7$FZ U>4ͼ$Oҋ2᭫ 3uFѶHv~2.~}̹*]nM?hYGLJmf:7ڴOzNg{h*\qQp9,@xTY xDOKTh#HnhtVE<`hm'+rxM(BCB)45^-5/?;oĒS׵=9U6q}=,~ i"&adƦQ G0TYM^8l%%kWۮLP2 qvlvI4uYdE9wc9_$8^BXP''ILƄsPqݬE`K]9){5iZzͨeH@hkM9zš~)~ظkTģ(nƩ #az_Gq@0Bn -CB`aƵ $QN~dw6ZNwB0@0qtpk^Ν:S%eۋ^)7(dI4:$Ƨtm"n:+}hux<qc'@"AtWek 8`-πP&0a̠NYF$sۼg|).vO<(5/_Rs846RSha_}8uXh&<976j3w~s  {%洓 cq Gx;IUT n" sJ3 )MDaM9?ҘLÚ*D7"AZ1ZazC3#o0R޹e-}bQ8,<.tϼo^3J5eލ#4TzsJ]\L4j^.yX{qZuC ЂqHC,= U `8Q47hHh0sH H]OneVMǵVԄ#{|3GZ-GMO寧nK%E7\)VA&ෝl6K5xAu)XxQ0t[tZe~oZXi4a"C\e^Da{SQwLt,8W^ǁX=mℌfn3Ψŭ\o,,qtn:3G̨"a{ʳ=^&9>d;f~hj*ϩQ2.LdD ?h1LTv $$$zp }v)q@LB)z5WyQhJPے*Uik`2G~6~H&kcP0mrԕKK0HR7Mt,"?>HF{_r~y7 z>{xHjb崱ۙdԼ^YS_naΓrfe/]{Do芛qzuCO:i4#PBH (9Vz^nލ~!>&R1 GG('xA42.얖aC!oVC f* @龭w!mDMm5( Eq١vmBPhewĕzXh2f1AXj5 t[QVlY--OC9G@rR-As}ՠA 70s> ×X 2H{sfecNZ!G`>A :, ɨ6RcʦAeb{c@Q75 $5W 1ƚTJg !X{EQ-&x[сA_b`Uˍ"4Ք]|]hdIIݴ^}˲}HP;M`X$z3 ԑPYe0Y#j56B0pB*x8R98Ƥ|Y>f[ l2 >wS=kj7Mt,{G&{H܂}0VA0w-R _FZFlz'kŧkֹcB[@ ~$y8$+ǚ*4ZQV%k+?g .vE'ƛoc`0WUS]~ѴGuzs=RDV~ X&y)[Gt;c;yiz 1[wn{j⡫V]Y#0pAO݊͹* ;(L,{b{Lh֔ț(vp+>(}F.Lt3rWmkӸ&˹򏋉c) V3LGs2q}+5/-IiصdP-Pߜ$A5WBp>h$4~xghc"|6A:˦U0^װi z`}ݿ*z׳/@X1|ʹ˹iDrfyE/}n"gV4ٙdTm8U4wS3k=FzY]q3N9l4^lЎC79:]]WKJz-ks} ~=XF}cp`ktӮІ'ĚJqҰ+ \z6<5V܀Ĝ٣+uM6!#S$ 'lQwΜbNY4!uQv3oGW鼑Yٹm{uq.2JZ%}|3h#5gVq1qi,'G9 ,~{?=~8]g0$@bDU 'ws6s7u$T4 C>y4ъ;R@TLtoZb }Č{‡|]wLtQt˅{羺\z7lv\Leqt8tj1X-i]hUW=zԔ_SS~g+1gh?>C?4ůXUFM^:|›ס4iD/GRIuV/ wϛ9kʼF羶YdwLW@>uM7+4" ^|ϋG&ΨUs#T~wm3徺1wVLı7.u TLVEyG\%1 >u:yQUv]`?`ŭg1@x[q'ʽj'M?䮨˰okfH z* *>۠p+UEenb$BMM0hBēcD6Omygq,‚4!/Xx²|P;+m1\' 'IXJۆ@d '(5a枲,p+Rl]M)6G%1a-kY0JRLV>PֳXiXĝ(|ʲT}|qm-D͑bmYeGqԟs7 0`Yay((D2X`+9f&֭n-4lL77E6ЮciZ! N=Z'#7ELQVS^:V%02 g!~]Y {^EEd) }ɇ _UURt-@shoŭcmMjg zLXe>۠^-b/O1('Nk{y~̤p<gmY0XcM`x@AҞ񎶯47y{UnYyN17C] "wA]gzpyŎKooX\8 "XqqۿOGieqRI:' kWfPڇaorl+k^ER$̟.蓸 W8z `8E0B`v1ǛC2Nb񦡢4]O+(Fyo;BE -Ww~o E@} s׌p;'qtaPp,0@ (6zov㓇\,!>h%MJ._|?oA^Fw$@dQ&ʂۆSS7:GTwXğ( Kze^9 U}A?L꣤E;f8>`T ՇF4c5ybHQY&D" BD@S C4qz @-]YE/"[@8t%: Z!ѕ:ܫ^ mYpP,}ƇT0eѴ9M||qdqBJW0z̼Te,s!:{"D-=j+4M|84[1-= ?轸 W9dXZQxh,I" ovϧ]UT[XҢ㘂ю5􍣏DP%L_HqX8E$~eW>-u~!mRw/ =_îRFi=:}?>Y.Bv(˄֕Dz<[xƛl?g|vuѥȣA4}O8nm6sǪŸʰ<<;g/|V˗<6W-1˖p|F& >J "BadI }~6Go-/.EAv E8jRilmd&nżXpМ ڣz>3EmPш&fΗeEەGd]ʹs1`ĉ<̩S'egg=z=]"Hda DB{-aEUG?IrZf-%NKN|Z˘LD^UƦӗe9c=3.j^z `XL {*||oCNYaƒԺ6  `d;Asɧj~/uwd!wEZuO`A;=*v_k"Q 4F]rE,z+n!|8}uٳgʕ|'+itާ[hԔ[w|~-ʍPNFo4Eu.@J#D'ihiD,4^[+c3NC^OV8,$b6ƺ+vAj9]Ő/sDp㄁m_l ̹^ >I8_]:f)6+: Q~ߌWP~EՔ@jN,qʨk|`!\L=(@?eQ_gˢ6Ig&#^>K̽<=[isP曟x zGQ@ssŋo0ĉDu8r 7w?ƍ`yy-[9sDko7oz?~:''ʕ+_|V=p, N2@SmmgQN/Pj$0z( LhZrd*|1RKf[NueA7y 2& ȱ؝^OkS}Ñ}|oV)~臞|(N@vłYEݏ=N3USG{!nl׳pǻcÉ`V7je.U (@[5 qp}4Qo|KkmņN7m L1-m۾ͮѣrK20O?T {ッ*mꫯ+Ç_z9svؑ ꫯfϞ7qDP(aÆ?eee7nyꩧlRXX8`͚5C ysss̚5~:tw`3,];^, C (_a,iVTuIuG+>/nݱS4fQDY6EZ)P,oFkN6cҲ_Qƺ+vMi֠t\iCl1\_4`wDI, ^]c﹣Ĭ>t;k|&_^1e2fHiHNgQjOabBW[0{s[Q1GNEPsz{U;3b۠~`/A'O@:rg}_\.=_~ĉ5kȑ#VTT|gpy͘1qn5kq>عsgZZzhժU튢޽;==t#L{ .dfС ,Xrs&O&=ia#$a?aO(Nhl]]i}A GAW`X )A ީ]Drpv QP ibl4B8.ZMVf]l8q"33Q`yH![b?9{U56} gʙ,,Ҏakv|IM^c"1|SBEy+&N7ϲ3LV`ݍ,L۠~`/A)))":vP&Ѽ#uϬef֬YzI&-_|ժU=аa+"}rssqz.55M=$'fu#ޙer UY [>o{gch;Bڄ1uM-9iI`y!!#fpdAv2$3b`&&( 'f2S8B";}^>>[+ϢņaqimӍ"ȉ꣸ G8zTTT[o;64++KLVF[WW7yG} `4eʔ)S7|lϞ=dee^[[=#6nf9DUҹ0iũcirTDb~i3O}UU!`XE3DD"t $pzY9he^KY~E3yfT=m,6(/) z^ewuR6.,z0Q*4YFMZ#&/6?9GYgyf޼ynɩ_fMqqǏe׿_NQiӆ kO:ߵk;su}k׮}첳|𩧞jkkONZ[[[WWw攔a8ZN|Zd?_VVVSS|;#LvNj[蹑YM_\z?i1k ig ?8չ5EZ\6&Rg0v-P:Xϩ]3 E?t5pdĈx씗k?>hh1OAN "f @ {2GB920T]ñde, ,гDEDVYZmfE|Pqä3P^^[ehZfO>|n())7oz|r&L0iҤdCiΜ9>éÑ]{߇~=<Ó&M`t҂oqȐ!'O0L(~7zÇ/]^Z}￿gMJJz׷l2r9sr-Ϗ?_(Uȡ^GTONѐИcoccDdBb33 B$AB+ƌ?9?Ehꫯwv8-Zh"} 6Dw3g>rf֭+W}}}yԱpu?Q̰-,0iꋮA`.@y}!ZLYߺ}_m_mւ>uwՠҮ,ok~gNa( Q!,@BBXNcGF:" fiU^:F!sF>\Udy]sIb $DZ39wCOX Ka)MVOf/<^ Uuh8.XV?${cq[\Gq Y1Y~BlpeA щ꛸ 8]OT3FK\]0LH}tMa@t=g57y0&ADiYvPϐEVI '8zt Bެ(2GۡzƩ?JZM"N eѱΓ6 "1 KĸME8z^jivl*=CGnol:UL,'+*>YI2 IDATDQcf }NoxH~u[6Qh$8Qg}A G^ X"Y + aR^˲y쪐]:L p8,v3?uLJRA?0OM2z Y' ]-;gi_@ֆ;`+ ˙hj1[pe?y~,&n3-EXvl6_9dx5Ps[+]gj #"=R,RkZf{G]W7Bd2'tU L]˞P+]V|8"e)D#>+0H9V-7rS7;N={胸MVvFqZAo !>EQomPs7 o@rXy^X:EQ3,r<Ù(N={NQmnBH##nbetq~u,28"Ae4?s>,9qw6½j9ԱgxK-uuZXwE+ N y^xfYMܬCEOXc9Iξ۠~`/oA.{GZP?M"Q=EuD <.=Ҝ_q(^'N:VB @ͻ.HF PTP;"#[\^:9Rt aLjmEMd0nsqԯp 2SVKC[z#]ΛDIspR#gٹE>OL&Q=@W6[{y~$4'Dcnu&cնk\yaaQuuUaa>STTXUUoV]]EUUUwS5dcǛrNI\UUaM`Rc8ll0pXOSa7nk=$P/~=ZokJϩQ槪 ", )Nܗ:룈ɢWgq>ڐOdrb^DQn]Yfޫ.S~6 +*獇돞9k&n~Gwj (Rj4hdUUuD @3 Vd1 |Du*m7PMC;~o#2'$'۴[qzd t^MjR,B"wa"pb,_oU꫙nrH_[e.]Bdq῍s鮨ST 7us[Վg۠~@Fh 5:u*>FZ(T{zy `aQ{_Y#8^\S%]i;ƸW~vVX pM+NqF 7nܨ}UUU%K TH6ð3x8SBf|1AoA_u9 11 4}yb@pzAE2m,'Ka}R޾YE.=ފwqץOS܏-sFoT]!Xϯ9~i5^YI^QsWo}w Do3XG(n>JB#&5} _T;15LVEQY&H%39$!I Lrp?9E<_D횚&ZOLH/h@WtzAuaUږd Gl?a d䆗h7f}>{5}w&o2z祧S: -38#veԲߔe w9E+V=ksv,%?UvA G)dO[XXq8\ÊkiI x ,$KaǚBUKp>/6'ui\ݨ3= 9*Kb$'';“y``8˝ l"f^Ml_Ͱ}+[+Vƍ@ ߪ,HJ-E gޠ7b u_UȽR-[O׆$*ܬ4镸 o8h"JPJ4"6 b*Y0 oRh6R7DҰ Y{zaacSR|{@Wַv}p:8 `Đd$yFHPE!-1LL<;~;wt] c>ҴvXk]RA4_{bGgKb&Ee96zL6Ck e4xFv: ;릲Z:d=F_ͭyy I!D?Q7nGA6i_(i_h NJkW6 ]VKۓ*/pãᮝEVHUN6g]=RE@4zA G3X+B[ZIeee=X Xj=G <ؐb&Es2HsU=b?:Uk'5-53ߕnu$s9tѪpЗ4QI%Dxgr2'X說(WE#0f+cIHz9,mB(>g9`0﷿͛^O+'N0 O_x믿N/|'`8Dݪ 0,x|AF@0%ˆ^] _ġCkj:pI=y[ҪE~P͒థλ0/nP%Џ7zfNN81_lr41*4c?c567[#(ՙ38cƑGu@miqc jO J!͕iEqJV.Nsf_VwFѝ 8wՌI#vE)**x<-JLLOʊG1k֬oѢE<x7ofa^~^ziʕCΝGeeeذas=3ϬY VX\ZZs=P(aÆ?eee7ndYM֮][o{_~ 77v3Q5q9=Fd#$aPeahFspQÇ6o^aѽbpQ4)z~XH6e7Y( ( Dj`t)).X/SGMV͕೦O*YE.>|}v$ ξTupaKV -?|4i`t;+MҕS{"n3"L ,#QX;ꋒv/˻VO>Y\\\\\LO:q;v1bĉ}SN=rΝ;{9/<@\uU?O6nXVVK.z?<{>}u444|;wLKKCZji~;Y'O|}555f,0,Kdfn F}! "iaY/^_hDI~δ6M-!fPW;0ὟllMen63o=4GH偿asT޽B+G85;Wn4R[} p""}L1cƃ>h^Xnɓ'9;uԐ!CpwM7SN}7'L(J]]~KUo7zhzzJٿկKBׯ_OΞ5gr-H]G`/.: v-Pz?Xh^Id [9yi(BӒ=_˩ SZƣקvTosFG҈i{ QBSN:u*͔U&EM}wK[[[bbb~~>ݻw:p<[͛f݊;vWvvUW];v_*IR.555lXdHzP##"Z}D:BB$I ZY~zdgڰS-{~eC3<fKaByW1jv]iwmPOS4# zG+qO^RRrWL>}Ŋ^z[n壏>>}ɤƥyϿǏ̿-]o2dɓEZfǍ9rذapGQB$Y "Q#p %:jF™DZQr!$YO,NRbDhhD^[.$ff(i;ju$|P_fz v]tIԡ^z#mth 7⸴;_"L&@noV3gΜ9s"Zj2>]Ϝ9s̙p,ZhѢE?Cl6׫{)))k׮5~d}&B$>vМ@Ga)@Q**]aXF!~igY`sZɳuLͰk6S$E |y!CeQ OjJvHNT r_|wYOp4f`hL8F~]bK']BhlF7+̸vc)Ha.fe %Db\XDd~W+}yRsT0"_cwxAMj:A}YC7\=]ϔz=mITC=faPQ=.m Mj5Fac2^}dX< ,nO⨖oԩn4jA0p+'ph0/!!,I"K$HA%QE8Mx|QN5;4[[}B HsAc P8 qAtu6ވ|z dPL~{"2XLhaؾ3*|G߲4*}z}! oAi=iH+}ᚭ;>Liɴ(!0hwȪƙA1,zB.;?QȾdJE$'(ҟKq3& ֒""NNg.XR@0ۏ \lńl&10 e@QV$]suWyΏcIkkHO_ccwE7N.4N Bt ê1v K%3;,*K!01@!;ˢLtԦP=q0(-gpcSUVFYOq=_ HKg!J47É:P DB)IR0 jo@DB tb^Ydgq/^MJ%Z+I.0l  ˲p!'n ~ UߺQ\ѹE*zqmmyk@ +.;|8xEJw "4bWoc/` 0Hd( C +,xZH`y Y R S@$BdY Gݒ a6E!4QH dlvm^<(>޻\h}{Jް(ͼB;|#iO<)ǃt<Ȧu_D Od'!,'ow,.{g%LIfS5 )UbX*@YVA̮X{䚩Uϻ.+X|8E+*.uν*c5xT%ux˟ؼk&F TRU;m&aAml e)pf"(^oaQL!Bd,RXδ!=@{_͙l98.ars߮9ơ4-\L+j% +otO1s08g)~mؤǩoWdz[duvjb\\XTVr ˲2L.8/>Nj5ݲ0?T\HyE gN%lie&'CDh3$,/srÖCT X5EQdYX"I4C}T EIŐ$ۃ MƱ|âIMx 2Y_4nM4h;u3/ pYE0nE*_R#r&!8Gpȿ !$ W 6~y6E:FvLeӧG+JA['b}/(sVW2s|!,f$gK}hKNYa, OޮP˲{.!TMtMfn.Rβ+?^vȺa!z*1H5,ObPky`"C0swsFefyv3e55MZlhCR3ѵYBW {^EQ4pE }C{mޘe!qp=x5 7y'1y MoiS=S)ni_-SfI5Jw1ETx.uؼ$"~ٹ1Y͹C*QҒb'{C.AIP~%w^"l^zz#8^\SU^:|8N1ƽ򳅳K^ }+>\>w]f˰okfH4; ?s =9w?yw[FUuw<ؐA)B`v1 &7,&&`X8r5]B,"_YЬvAAi l(<=3E;;>3-ZMOhW꯫ŕ~rőTgQ~\?̪d{JCNմ|tBɶflkjBO?ߔVў;mϫmc\MaQ?rPQ2%483qR7X52\'3$a+ nDꮨ,YH5BI,ۖOV=b1 fѓ$@QcЏۨbHQY&D" 3(DNZJ#I EZel}1&Mu4mxAN=oQ<>3/#;b"(}IZ's3QVg*U27q7ffxlj'~vʭWۼÒ_}g~a#\v)^6A#IΤ~I-"aY '= ~W]9Հ٣t(K<^a_\[}a@vZ^:]KCJwEeyau22p mae9֜R8Bb($0O욝mΨG(N}m:=oi5iF]C}!a洸L ;eTKBWk{ZOj9QH _Gr}L"jiS.)>珼8Jv~V0,'Lݲ풶_zŻ~T_SLE"ʗ [}K_VzM.t7>U&l(srդ糌=.th9??۠ysH8Y!AGHJ5oY^cpV=R^z84;tT޺gd"5) dMس^0a)B!=h'QNDMBdp%ȢG>hp<_ vWn{j72X$,(a8nNLKx|~ 2%#/|`8\֍9F?ElXԯp9DY5U/w@]QY%/s}& ,meQ+ qw\.hI]\K-Ukkkˣ}T"*JKU\PdIHB>s39 }K};wΝ= ;%1ު$jNI<9^tMT8#;:G}xorӗͺl .WO ~5x=:"zpŃ z3#w]Ͼ?RI hk]IմaRrGl\f[5G(C v|܌W2ph T1)ǟwzFzC$\SJQd@#):WB.Ԃ}.I𺯒>%?~IJX ԯK!HPEMJf7Bi7}{평XL[w_9jr\..mͿh&ֆщ0ѧ^ktx'n^4GK.\%WNXf2reGʠ?\PD+/V%%:Fh:j}λ+ cS7=E7d9J{.G R a* =a_D{YS,4CtG[xM4@g -Op޵wC$6>,J*3=lmmuh&sG+p4}a۶@;?пts͋Ow9w촳⼫.hi\sG UUٱ hm>k| Փ:smI΢#h+zkC*k!UocfX)C*G3~ޚ'TSgc~^rr嗟WVz.Iɬ:x@MXb6[w>㴳5慢vI 꿎zE^hBڧ?+Ǯ\=n~AJ5N6Ϻvj] ~xH%}Emذlϟ2eÉ'&T%K<OUPhԨQ}Yqqy~䇘>3*%$EnbC4[ܭ[քX( f4EEE՞DUe\V9jMԏ1,/h?o?O<%}fÆ{ ƖV02'o_$:Ժigöwn G vd;b@#GГl GP}އbw~M$]OVfX,L"sw# 믻ǁޮUۣ}m &߼<9"ҒmiEh&ͣ%>JIXw^YQiH=`*0ѥW}vˏO reU/yx9~ "F2@Kϗh5AsHOu]l2I_|?'p禎$l :tOU#]EDE8+ǬTE޳]ٴks災`ם۶׿^Դ//.:JFOhWZ۝'YMp:]$ʰ`aQ٠Aabfh>O hѡnxhnǃh4ִm88|y,:ܡS%#-fSJXEiK,@&W%qRfWe8Ye]_jT/Nl+lʣˉܡaqA7P>lUT;`db9}A[U&|~ KNꩫ{OE5[0'u~HR|_ڿ8D{2G9A{s=s8u|˗ϟ?wߵJ/"篾nM.0$E-`sXz*=P =ߟGS]tԼ3 NxzukkW$PWWG믢v{;::[sЉ!gvHY=ǚ[[[]5 M8*QUP>z!@PQ>@.:i3oL-^iiz(*qiQ# -"<|";* 7 %{|fwgϙ!Bl">tfBhBT_Gη1=TMSEcف>M3g7`qR,%+Ƭw^n:|х YݷxSS|w]W^1yP**f]RmԳ(YJc_e`׍7^_5?'U[bϞ={p娫%RJkjj(2]+jn `jʸ sa1 ?ή`l wfsE6 Ŝ63T:lU@5ѴMh.kMY-2_RS;Yۼ@尛-ɼPQ.|j;=;whb_}<oʘ uiȂ,xכֿs=Ĕ*93oqDQ7h[#ơ @[tٱNJ 5NEn:a)շک=Y"a̢ezh>@gggyv7`n&`Jk }~k1x{?Ŋ/]?,P]]My;n^\}ԋjݘ_S Bwxbkm5m0cVMsdo\L SP4r2剭8s^LIQD)?-(ynȶf94W?|Hඛڥ dZ(ޤC-7]_^cnZ ķ(|?ܮܡb{_H0xgrTAĹko|#$̿fGDy[S6oI,f 'Tj"&G1?Y8sONڥ#h7,,Ywe]\9;`=t~ذa<B_"RoT.iO߼gףtz{ͫ7͹$Sz rŊ:f﨩IVF=뫫_Ju=#(癰sÓUn-p^/:) IDqR ޽h IDAT[{M OIok?M?}ӒAjߴm.N%Q5MG # =ó.7>krJFXUٟp^v[S֥ B@V&:\6QSO[+{MPDn5}GkNGWU5,ɯWeNlfDڧ?YrG89pkVPPPQ$/!F=T$Xe ǹnu(D~fu DafB8'WRR8 8|I{hq̞]B{|I}נis;v8UۢiqM7]KQ&.w{sG˷=<*hʪ"^8q|ߜi\vKMp@V>J`./KC3vU%fhL %,ޫ8~\6U.6y,H?{##2yP5E = o릊o8޹ΦOB9߯9c4n4'6*9G dO< 'g<+Wob~coF ![V>0]ک '|@͵i,˲,777YfڵVJ6ju:?OI~ Gx*Ϲ(r~n~\rz~endY56qw3 !8555v,MMq\v99[ww:thN0qMM{N+Yf n̘q6!}'<nIJ|[G6W,}@0C. 4 bD:&o=3%oR=^ݬ:7q3M7]qz@DQ x̘LD5MS#.(u"=9.#*ڇ?ci!1>Ϝ{*%x$:TU#V`" iw1=>aܴ3?^M~]D_0QޤC hNNIʨoofTi>O?dׯ4ԻnD"_mf TUhOF#.X֣mcESuO,8bq^ftuuȲ鴝yMMMp99.99 hhhJp؞=mȡ\CCa-/p+|͛7(// gb1t\S%nvd2_ʼb矯P?}Ӆx!!A5%^%ijfc!}:&;NѤ~H&i2_Z6%~b5JqTބ߅w@*J0! 9J5T-IC#5 m"RB'64ןzLomz͏;_7 '5zIГfi< ѣ=7|L|}匧'L_QQа9sƈyv\;-]f#Pe#*s2t@i02퐩\I#8IiKR/#n7z4EO_*yyGqC-K{WU')F,;(}\}K/DEYx~+ UTO[dez[s)OduXƮH#259n#)1Lvm)cv+zbEę6"Mu=u$e9B@naהlA- "2/dG)312QgзQ|v fϋ<H v#=BjjXd) Rִ )؜fuʇ?hr䌈ۥXDLW{[Pm1;cSE^L-_w=H.K*AfɐÉ nl.{K( ʉ,C}j*CӮ͋.\円=99N2,$b1Aiuǵi\C};xKqq,4BDV `ǧ=Inw&1=AFN KLUT)쓦1"(KQV4Lwh*,hP"hXSE6d}y7`OWea2RM^R ţ|n۩L?%WOh3aa 9DZÈjK_G "/{jV ɓ艍g$JĤJ&B V#gf8ۮ:i;w$fi4JNSx^V&zf&j|UDKS\Avs]ʪ*+r\t,KQYU9y9ibs&&TûGX(2 P۷\i#ZduZ9 "ƣ1댩ft1; VsTU +rw6eRF KfυiW8~ S K}M EѰL_R҃.K&։[ĥX n)l=t#XD}G!qno7^?BؿʼnۮaaIagtŸ톅%hSoGRfҞjn9aRk\3 o1њk&inkx ݃$mWVR4lt85~8Ai:8XQC5Tk-SyYpo0(Cm2)yѨjG-<29iB`9 h)f9+Gr# "4M&\=aQ3j)+͙P7p>U/yO)W]׸+u3 nxU4%*LOzMf:ΌH$4ͬYі-#NaھO,='٘K'4Z2DFHUt&hqP$pҟkx 䈞"[fezygK`}/A[Ъ5Lo}%y(BP)Awdd)Um&rL4Y?AC7c}T_u3B?KV!K Z9g:_ "XӶ(/9;)y h 5``@f^qrc>Ky>M˔*g\fLz3W쓩1[AN6mZ FK!꽤,"4M;wnEEiwƓfL#}wsgʂ\_q3eSVK~> Jl 3gAkl\a [mp-Ԩ{^p{*ݞʚKg4Qyw=\Zts{aE=Lٔh(~gaQ@DqMI<@xqEUx+Q]]M$`Ǭέ+KOc)IG6G-MVT1mTDyyjw%ˊj7MZ`g~?q;~F%AߢnQv@KʠxgE)R@R)KܭwϻT5V$㸶d ]ҋ-e'?efa5pi"8M`hM?ẩ.+Hܒ!u2{Zjic*Bt3 *B4UF,ݹs׶myo X̣GWQfױsĔT.}@MXщpRG?)J srrEٺuرky2jԨ"\ b4.>réSf --(շP[.}]Ch- Ϣ^D{:>zH5K'M߸&zY.Kt҄uJӚSg{%7pMgM{I? |2[^TS9fG 4Y/Hh"  )(--8q$$M-;GTBaPLsXxM,E:~̂)В$B@<.;w?nܸ<'2l&g=ւET+ջB`A4W4Y~,vCO9CPRճ[.]o\Vfcͥ3j{1t҄wry'߰@HGY||3@4Z`r,X/D.);gaQM)b3p9GNi55KkkWX󖖖|>Qh}ݴ`O2=8TUwt"<Eh@+ՏtZEp BD bw<q}(++ݽ'|څTEq1QJk $R}Y#lE$;o֤{ w޳xFô^o획4Έ9M*(XezfP}Y#, Eݟ,EԜ@{/ Z|E[wu jo'xaYS赍^Vz褋mwu{gaG <8!;cD%?#D^?t,Ic쮩$y)WZD&\r. M/EP1=fTR۳!ᛨ_)G4M, QMFp`/lV]c\v!cf6v*?ʲ^ɝ{֓O:e֣ ng/;(k%صk^ѥ71(=$":wc$7+Ji(cJz@uSFVW IDATL#zm_6.ֽPSeֽ@zs#{se G <:8hPC(=MJi9/ =8:G 4fsv4KkVpp|q`Vi_C-]Ás.:ՙ;|؈Q.Ӗϟ{ĸˮBgNSN)++4 EDE}w)z5\|EJRrsBI77~h2Ļy鷖o2oC(R c;IIB( Vuֽ@{׭ŌJRTcESmoz=Y0xԀ(G[P#E-`sXz(-PS㭮ݞj"S ,CQ>XDHث oAUAxUBt>8uuuT+ӵ|qT;xyNSFU0rdE / KHẄ2j)))s:m&X_kZTMD;vPi3CIϬs\VXg?vaۧ?{c+ƍEHRL?q8dY~<*JyROU̙3n"Bڅ4 Jŋg=U(O2e&馌D9:Ĥ/Z0?[t^@^hl^Oݿk6κ3+͒$O:y۩ByMmeM=FT7e$ګ᪛G  a)+$SBܴv+'Sջ̗^64ΑEz8 kp*b[cǎMNkdg.=fOx{~'JPIv7+1w"Rv %TT=|շ|"3,g0+ [n]S۟-Z<$.EWVoXfP>mY|x{|)-J-.z~u}B>}[^:, tR )ug~~+Wg#7 008$HP@4-5ׂB&Eңȣcqʪ"^8q>^wP"考ag)~PNVU9r'!#Дm:",q8j--t;=Z =sg^(!, FiC ŗ^bzj[Gŗ^v+ULiv%NK?}W`'2FJklY[IL>.ȑi'MuCxQHFi#\[b[S[Gbk眑4 0pT jagm;O8*3#Eem^kV?TX8,H@dX(Q&5xuԏ9X w?>|.@4stq?; {&r-ث_P֤!Ek6RlPͥϿMadٳi; VHo}-Mqzc."9J3G/睕4 00PeH!v|%ځ>bGRL&6k3m8~Ѵp"r= /v D|7pVi𼼄YbLNXig-}^dh>LA[`sY? +ŗ^DM3GHZqBTE!{#OCLŤQ'-@ɵ4x TR}-{|{-gee9EayVj[ﺵT%g&s\?,-WLG * Ihj!5M\8M_/Q#=vlo!$24$E w"зNܹs?ЧGGTU\eҶ];xd**BpZHS/v + _Q3u\b(MR6TJuPJL1.=,NR2!3uF@1}Kv~gKo7xƦ41k4 OqZGf),ONL3]] IʦJxdc )%TI;?>3딴0`fQU4xvq|x4՚yiK&NE;IW=vz8#Z_71BEθMU[N# @Dq/XXv?˗^ãMCEEEpÍlô vUD5ѵo7һ]صo~3h8ל= ].$ *r]󊾖=?TbR𡪪GX0fYC,s\OW^ @Exf3pPkmZT !EHZ6WYK~E]u|Ǘ62T_˞z,MG aBS'5MSU%8,G:i/牝P2%)m\} V5uGi?-"2Y)n"^ߡ4Zꋋ|y$$8L}晗ƍ-eȀ v Tobhz$DcMi/cx,3ϳfEqEQpiORET';x$IVSu.^,;HxlyN>a|D85n.+ " fǻ\&+&@ǗF~a 0`c 4>U9Tړ7MǣdϞ=̂7@ MA'"o*QYT9 hP=dcG8&ښm"P079g^}X9=/l dp܍8{g 9 BQy4UV^zl["N>T91-i*&-/.fˊMUE=Y˻$moygG 8z^1iNԶ)6NR:RO@Da;wFW-DTEOEx.I>e08r <,.AN5֯6?uHP$IP lQQ5.huuMYeY "% "zSxӎ>'zU2(Dx=a ` ",.nG t߶$+UEs,֮T|z^Ұ7LMRNM\Eթ?pE 7`++Ek,vgcc.T~o37~۾Ѳy%#e.^t8Y/龁Q(}  \lus߬<knn2ĕh=ERUm'p\[ GrӸ/AyopC4YDD"X@D0;vLV5+€ w8Lj3AcɚDlˎEEEb /B,3!3**hi8+tŕHc 4U'qjdՓ3pBeIpk*(P yԿ[!=UEhvE0xԀAL n(p-3͢&(!ommm7nLz? H4wP"ִ+ #Eq:TEu7^E".ZH$<@ b+ȎMoɱй~Af9dʔ bPek,Cxp~~P=Nmާ8 }Z&s4%Zj EػY,H`" T8܍J% F }ԀAiHvQe>Y%X)tZ8u| l'0R$Lꤖ9p" Qo~/x@-h!D*BЀgѫ`0Eq/d.a =dH~JJi G9TU1 ~曯̊˴O*͕ksf~҉b!7$ p]9rfbU[9_.zCaG 8 .!GhU@LV 62ۦ,YٕD;_vݬ,GftM"EnOT| iWG[s/ѿr>=`*c sೠcʭtr@D d/wlza/^/IzSޡC3 Aj}?ɬR퓪j8D0VBOxN_d9?0 ocWľ\ '?y=/€ Ni*.F+s.W5N]nȶH)[2$vOKt"4 `)RS҉~M4UU@T6N,^ҥZ0`vr;?9YDRiŀ,(K^<ɻL4B8ro =Loe'='(2VTMJj"ϩT1O9(QtKxTERT RDp7E)ٞiM[hҁ0`5Eq<Up8Mj G}'߼SN}`6RsfY8*Wkkk w)%8CG8BHr/g?kZ1P7Ed؋v57B??˧OIK4444lʪ euvdN]`h>ԊP<EsCx$Zd$GxqT}o-ֿe GxuFzO7(D~>Lno{%i-@P/aQͣ'4R MTSd9}:]`p^٤lY\0SȲ#RnQT_/wwm;Z##$L~SBX<`(9,AkQ̢ȁwN1eKǞk2ܛe^k,߯,_ySޮyFz[ef:>J~^-2s躻*+uK\>;xzPlLQBXJc1~7,Z(SS6(!Z GF^8^ S䗉D< ɱƙ2bشI淶6Na*>hN#r_5)ĉS_5U(USﴞ*on|D !=;[6}+l6Z&h<'(L.*(E.ڒڳx Vhmm9ߗ?wΡsM7{ņ$5x:be~g9vl}ul/ۓ>;5hC~[vvU@xh.TgU42D ecg^㳥;AM匤;b[;&X͎͛Z hq$;P.N2;cr#NzP<9. o<~ݍOj6T6(q{'Ϧ}vneRuu՟nĥ0lʹJX*FBJA;NYR!\F+;;솆hCzֽiaj*?(?ihl?%.mm}EW^-P(={P~9t]Dg PIiZ~P:4YiV=7L˝U1҂vdij3Ԃ1^z;ADXBFO<#O-%jܼh @=DH8B)D<#sCDsKJ{vct;=~$XQQ~ŋΰp AR47e)Q.jdY|eiypwo~ȟ;vvr%55g5/*s>wSv+^WWO'J0f4r$;PFeQ[s;V1Hiɴ?u[-;N{& \iOٵnۭ+ķ&hң(1h~mt<'kWd.͜9ܚ6<  _U2k%9Jlo)sZ) #=`g/}i}eY[Oll\5.gYuƈsRTnfHpn'/`e"8e9۵~ 3<+ TTx&O~r}d__s=-zj; W9|d-{wRUEE&C9:y,3j..H7RpxPs¤躢%c |(Bӌljg>_hrYGcvY0x3/Ɏs`p:Ckg}e5PnC8 oXmV"Z$*8wKr` e1E'j!MъFf,'јHăAGW^|J+D"D"X̙0r0.19ZbvuhccHіi]:}n⦽M8YEOoeYlNzu~T΢(O:$Q͟^lvss>-s،ba"RuW.%z׉ҨoRd +:u|X)#s 8ќ_j Xdݏtoj<=k;~!JǫoPfs7>xg9 QKr`,~j\-ߞq"Q; 7n R,vʴxbF;ZZvʩ e WP(cGx<D"vb1ߴ,D0DA^wZ Y_3u:\Rt"QP:=g^oY"Csa;[H" re<>7b @Ih-V~,D"[lpk0ر9N뜢_:;KBAJ$ьb1K;(RSM,tJv{n߾?i眳U馡Emm mm?O BVWWb1EaBctᅗƈb{9^sι(/beeUq׭L>_hXJǧTatGo|Uڇ.3UνI 9wwǯF67tȰ2>25TMDM\һ\BƧ\PwFik7k7D#Hw/(Qɇ(1{3DhFoFE4:'QHQDĹ95"ʘ˜*iv)!")%4{Kp+7bKPSe  &LE%uesYtٴ{{{Rݻwtvz> :;A.Wz5/8yrI{Λ7JJ`[SScx_$[*)gOWMMe=+V\JJLyHQG̀=R~_kE'M=Qq.TRX#f:Jd~=D=ȭ>%칻UDM-݉ޞDD{wߝ}#þK=+ݧ=w*4hM-+Xm}K)QBQeF[LQ&_DTc$bXbBijB"x}bK؍]R{%UUnLD@&B!_yyڈEAPH,Y9%' }%ppÇQII`ʔItB4EaMP9!<2J f.D [t{\tɔəl97I+'VVt:W`5_4wc2kۛo>cH%w.'Vķķ (dm˞v4R @ &)2BD|)$`:c ^^(#MVTk(&@ڳd)յuE7#7D.]*%"z˅^So_2Fmmn7HĢѨD'+]"TK ZTEDy,l,0եwf3->D i'-@D,L]gv:voJ9k@M y33ui\hheى$gS+JzP&{d3ǬBX,TK=*%̜݀Z!n2pn4h%Qmm:g8N,ׯ߸񵆆h4MUUW744DUUKȧ8ם?ZPB>$/)nC:RtQR/O ZenRʹ-e[.kzDx9Tٔxuϰ?~y 2ro_.QTU%}3G)t_^BrIt^CD7l}wFeG,Q1"n)Bp SI#"5ѥ(*1yxTT>a IaQ+AÖ-H8F-̊/{bJR2\22Ü"_-fv4u]#*n&%&)H%~G 62Jn; CDDiU<ԷwfD[WZECvG-Qc53Xe#'Ɔ2IuL"RԡgnܲT]cNr p.';9W~q "9/D U\.#V5-:g6esO((Ct ~"TqNs-Z"#o#Ys7jJeTUqy=xR5" 32$A)S~EUjt%?:%78Y%Ӧ U )B˲InFsTUW(3f {I[Fss"Kz"Q \!s,N@}tr)99zElmУ&yMп\V.7k?̘{ꊪ&]B7 ɃF6uiMʦo UU%q ΅e1ƪNTTqNėcJtJ(H9Ayy!;w2%7I=j>: ?@x}܆[H/Tt"'QA'/֬;}+MT uߞ3Zӆ.9sD/Zl w2aUuUә=Bxss2sVCn1MܢSјTUW5W"lk aKqquMT&y8\:9?002>SD 母Ƅ)G`*ځWLc_Ֆ vwS\⨍H \cfo#0rtf2o]yRT]ncd9OsDKP=f(Q|(q,.&GV}RKYߐ?&׉SCeQ(rQ(rQ(r9 Q(r9 Q(r9 (r9 (r9 @r9 @r9 @ G#t3OI _IO GQ( GQ( GQ(E;/?trcaq]U^RgrX=/wiʮg_ݎ8g⹜Џtƌ'[|9:<5S9!ճrcaZBp!D8Iex2̈́X+B ]{XKABΏc-xm3<.wOf9kFKDBPb og]-zݚ$ '\sL{Q䨑339-y>8Ke oQc1iGkoﱄ1F[W LqOD2&.1FDĈer@uG#.g }^cL1bD$!JB3P DF;LSr]{K;yRU?_q5xb\qp"r+̼ni \O^&5jW '{r9eq΅D-ruy&((2ZD$89*0 #Nx,sKuGwD'#MUUrK!jGku6eiQ6gU3*t;BȖ(QEQt]gYeiZ͟lY\UOuu]UUMrv-{ y~TQq89*QEB.Y_\\WSU c<SdQgb1~)`irckt69i=:TQp d(r9 (r9 (rGGE C)`L1,cLS)aژVG@q}?%O[QX1*Q(⃄ճ[Mm}ٹ*Uu4 s{{ - z&UU(|t})޼s5;>r*_]6X\lxkgŤ(@9SKͨ}ƍ+//4g(D8'۷ϲ !,ڻwomm1V]}zww| _Wnwf]vx޽{Κ5 9 'p˒%K^|/| /-ADvZg;,D"BYf=SB-[X9sL>6lxO0JyFիՕJlٲjժ.;GV]}wttd2{Gt?GD)RU˾{_4 2(\;߻}{DZrTyUp.8[2M?<ֽ̗Ͽ|0p8|-7ł}{[lف_h/Fϗ~:ܯ_=7.岧?o҅gTF?+W7~/rFMqN*@呣01Jò|#GB֞hU;zW.!G`\J}lncڹ|JM9荿] ϞQC "&Esxg ''UUerhdriEPE0 -T^6̉ cl_)K"G`(c̕S @ GQ@ GQ@;)@|r6;IENDB`tiled-1.0.3/docs/manual/images/terraintool/06-editterraindialog-done.png000066400000000000000000001656001315121121300261740ustar00rootroot00000000000000PNG  IHDRms pHYs  tIME : % IDATxwTߩ;;[awAA%ƒMyQb&*}1&%1& Rv ˲L[y8ð Y3s{;9± p8B0g 8+k׮455gp88ۣR 8:p8Qpr8u99O9w}^V%K ]JKKEyG?䓉wQg~RC뮝;wI)eoocc(iRJ.]ZXXoذa@_Nsynx 3~'W^=BSN9nݺuMMM_:{pr8_mmm`bR~'MuAJKKܹ30 cIl9$3JTrrrXbʕ<ȗ:=r8<G#2_}@ˬK.4iҦM@O=(7x_ k/OF{(#xg~_QQj]]9ߟ|ɔқoyp_>uTD_z饶a/ 'x֭[O,l%\z饗^zҥK 8s***Einn~Wꆼ'xs=կ~U_㏟}Y&CѲe?{#\Ƙ*֩_5MQ+~ Xu}i644xǧG+W<^;;;m6NPJeYsrr>@ `oqҥX96l`YV2UjȤI֯_SQQ1sLdI'f͚;裏59B?-[q 7dgg̙3n;w5şy۷o>}yF~i&6:T32F~x}>7}zNNNsss= ''gƌg^bϿ{SCN˲$Izw~_8p8‹~edS!Gu… [[[X,dQ\򘵪!5~]$5x6u2SiKᎆ{};jr8_ gq… /iӦ`0~\2Nzwv=b}gmmm'O?~ss;C|ڵAX~xRrLK٧Ə& ۳o喞#<Ҳw}w4?G/c|WB}ƌ7pC2?iLusÚ8\.W,{.9sׯYf޼yC6׿N<>c݌h<=ٳgnݺuh y+WN6?}]6opyHx{7YQQ_WW?iBjpw4Se(?52O:±;ypE87_p8pp8(p8\G9pp8?*ጆ3<pp8(p8\G9:p8(p8\G9:p8Qp8\G9:p8Qp#p8h0 0 JȄ;A ,up8H8}+>h?/oʔ?ϗ~ieS+m:p8F<߾}ƙg3yrAx/k4MTMR6C'9`:jvƴ:gt4/\tE]t?//((7o^jڿ/}}}o˗?-[|Q_Wf{r}Osx9ypX?t4㔿y c5mΜ#~/Xٳ[زKeyg..)+X2g}vg͞=~1lذ;NӴ`0eOOoo,okow\~ڵ# [w/X.RĿ4Dfdn-'Iشrw~srWTկ~Iwyy畖M-)-;kjjXGʓ>dE+?/ΗN8Os-ZSOu?яTU}Enx<'|'Ԕӧ>}XK.Uѡk> )qMGcNQ)QgIڴ?J)@[FsEnmm۷?WXG|K_n/2}7Y-?3>Gٟ|FiS*9G¡Dw.@ȌuuNek}ߌhtL_[38o{nY`ŗ|;Za~^~MߓxG~?P _xEvE e˖-3gL(N>}˖-,|钔;sLJUUڵk !V wq?kmL|?OR_կKʎ{g0='.iߡtFIQ9%n&Z+%)9cƆNǯ[ ߿p޹Ν{s9w^{ TVV^sU>5W_=+/ MPTu` jrܣ(}imͻvܱe#O J{]J%;c@{u{VSOJ~hj]tE999,0???YǼkkk=PUS[vWUUN:ExGoZr!Lpꩧyo4pAכZhB!x^7 H{'oذ3]l=sqG":뢋F(c֐pv+!OSBo=vGy+LO(3|kY1{? ؙܶl)hAټjU͓79|{#S6ͽiNJ;z{ji9䓒%`׮]S l*}%==iiޖݹrϯ彞 رc靝-w?h :_ɽwKЯL;J"; BESXh+r,WL4) {{D$ID"].p(|iw;ws Çv/J8/-'$zL K,aǫV8ŋϝ;wѢEGqDEEp dvt{ 0.ꪫȁ8S՝Jynoּ֕ڣKv]R+IdH{u6SaaaccckwwwoooaQ7yr{m𼼝)ȶ7m/}}eCAUU[[[(;322ZZZDQj޵k" =ysH!"T"D$DlѶ%\zxݎ_;ME'rMNaۣ,_7نsݬi]|'}郿|HsUig|3/J8/-ӦM۸qc͛7O6o޼9[7ndCF.]\-[̛7tΚ5kpWۖ,Y/_~UW ?LJ/|mMEmaW'b+V45E 3m; ', /|Eч~8vi[_2;o_T>z˒nZ~=W]y(_@gԙmǦG?}>kE3oS49Ϸ{V3G>7>;-[l۶g޼/#Ę?%7sy.+/oWz* /K~|i|+b1+3#z<@Iqq[[ۖ[i ۝CM۴is}CCvV 'OFZl56 ;U?nW5Mu}O<{>_}[禛nꪫN8a^瞻z衜˗Xdڵ֭{W{o',Z(u25y˭ ]p&z_{szܒH$ɒDK 4 F*~_{̟u5:4MUU3NSQs:p=+'n޽Ƚ=;[>N$IUq8/!@W=-t9Hx.7FI<﮼懁8̳p{t:6B+D@nn)uul:n̈1|oH $P&aخ ʒMeffhE| 8dIȃE}׽?|Ui~avyyy(KKK -˲,sk!Ph/(_?i$;'#Ù2J&u5۶>M^|\ ?rI L6-+3c]]]###3';pps$? P(Dl˲mUAJ$Ii8#E|>HdA]DJ{8}:;͟]ia۶,˪*Ž,I.S4]XX$,˟_ Ip8|t2ԸlnYeY4MQp8G4`nnkkkOp_2 ӭ/Ɩ$I(*tRAXEIEB(Ri*Sp8>7W9s,Y>(W},:40_7_ ;%C*p8 M;l/=yg+2'؟3HKO?a)S¡0QHlbVM&bč1(Q Ji"N?pr8up8pp8up8pp8(p8cg?ʟ3o9.r CS/|'\MrN`bb`6zPH Cآ(|XBT$7 * #͸Û QAM@ġ\TUJzq˥؄Ҿzg*b69om&lu[34HQ;k"xK?,8e_ ݣ49X=7F7 -SfAaESE4Q_Bj_5U"i`6!~3Q4gG9,b"%fz5t'l/+m#dDa@D29)k[V*3Tw*+K|j{Jq( UeYJ =M)y=l.z4ǣ@I<Ʉdٸ;:hxE}5L6_)*N/@ f$޸+9 I{eIМi@l ٫It؂x%")Z_\>Lm UMSn@$Ou}GuCwUWAX4Ca8]Uϟa1[_ ݣnQ/WwCvjN &;dWQ%2옢Zڞp@fD$JmJmJaFbnˈgof9=*JN/䅤S#B!WUw9!QI&M4XMW ΐ QjSbѠضaSjڱ=a-aĂfux2YC,)iB$U5%Q$FP*WRG59 t,)%KCdE j0AT$FG_4+NaU F,L0US|Z%~ŢveUM>Rj=NgxJS.Q ˌAKGEIt24RDu2Fa"͟m Z=5/E46OtؐG}Qr&OԸ;P7X@bn(a tk˪{>p8;o޼￟gD X˶:f[QdOE] 8</R%I$ɈN(mViEwBpM^$(qjOQS2JI(j4ᚌAGcEH<^ D6mˀ(20g Cl?ٹs'x"77@yyyyy9iŊ˗/olley޼y˖-p'.\p s=Gu4^{M.iO9S q]d`[;f.dG[><$])M,euRU`r M*{*Wf@AĬ"0C) .M5'L\qhf޶] !;(MKn讚bqf7!:IN Rolthqb4l*T`@DY 7aЙ-u5!9DGwtK&i;} &fŽ%EԌmӐ4h"(Ê"933of̘QTTdyٲe3fB/[|Iӛo/gddk>#>ʕ+|͌;SJSt! Ñ,1 m '4 fEaNHM '6 门L|P7ټPaN),{ S4G" G/aS'ˑ\B`x5zz/@bdwgI8-;o dfb ń$]d?UmOz:[\#9DG,"k="W./c"ږ@v+:HBW^yG322|;Ν|믿sI 322tI]w]GGGVV֋/xwL<ҥK_x" R G6@ۺ^ն Uhq#DmDl`Uxuf[ͫ)%ѝ7 -nL,@8vĶdEU6mmFLjU <Vvi bY]{+9W6jvDm#>*qvw(NbHDu%=,#RQ/Eǜ9NgPo`}Q{{6j^۹;wnegvQS8<陓Ks {V#pT4<]'9DGM+NQ@RV9.3qzʋ|h0r7>G b( S9k|>ߍ7x7W^y妛n2eʂ ~mڴ4MBH04 CUU~2:p8֖l:N 9H%$dN'T_WVϳq}Msϖjs)I<-+9!J ¶ )zm[rSL;-f"t;dCm$!IzE#T~3F40fhy|snl~_0Ҷ7|SfĽ-ؐ&=mUb/!Vnk\m1یȊ nfZPxdQ^vYaδinWajSkzPل)A!g {P$E9..# 5P4yXN v5|'z\ Nz.Ɯݜ)OIV!*bѩև?6y9.NoDňh8Ѻ!*(ÊCHNov̑,ko}롇ڴiӂ E=Co޼Nb@ktt$v,#41`#DIL O3[=b(+kڕ ]3:@5L28mtZ2~j TÑJux>IQ`8[^NVwoJn]GU߶ڦPE+wlmAU>!DDQљ6ArԬ+# |^;ބJªopWT=vFf`ڪ +h*vp'%IăjktؾyUo94yi3+T%QmJm; h(D Eyzp@{=RL45J9~C97ԾC̟RudzVˮJw;Řsu?!LDc#`F4Woӛh.EsAT@LYi9ЖmlbO(MLݛ;> B`gmnn>#UTTnYc=K?s{10wD"=8eԎvjTp+@SqV/&QÉY_WVW4rȴzȑ,>7UD4Ģ y=*d ^6ŁnkBU~QRf6cB"}W9-nIhyu /^5Kt[l#S*W͚લe "J>sf\vG@Uľl8)5YH*Jj,E"=w 5Y TZYcɕ$=¤4 8=`e3}k7z+=F01d^؂t9}sƷ_5ԉYE̘ E KONz;J'SͬSSb']-LX5]8^fUi7áiEc^Yb#-3%9DGM@yaVb$Vò{MA5lo gyh{(r!/N8_ vovڕPUuٲeɟnv(US.UAPj[0nXPě3Xfbu78nD7z/^t̑Mg~(VeDhP]6|]ΗIa ~BlS[89ˏIUH8yz<8ɀ8ZZ8 q!UEs&RBm2J~JƼRJ*SA,y\H1b \~֢cfyqr[irtJlA B@)M;uSbmF)%C,&(7n^sW.&( gbD-ڿ\R,PZ]Bӄ(nwx> WN;Ug7g"$u&leDeա`E_Դ="* 1-f!q0L0[V nlm(I lbgj? ~  FS58BQp9?š $T :QRU P+ I '!VEDXj]^$5#R'%ޱ`ތsN9fT&&Y]0>"@ ؜؄Ȣ('5&ў#>dIfXWa8ےz( T)?@p/,;`9\Svs&N{ئ0HÈT=ӣ:ܒB=@a:#Ih$gq˔xg`]|J1 QJ-lmbZeUS]+0=l*(2e9$9)mĀk'R݋:}qYw[sК$Ȋ.΄VIQ(<{oִ4M2/>Zz$1EIћ]'{*˲l3; dhnZ8ISUf)l&gbW#Rv[mYJ55DPMA4Ve&fUzz|)ʄ.DNXqd7gІW&f4t$bPRf2H%Dq<#Е>EE16֞xa ʶ6lIV8l Κvζ}oy$BZ,> lVRMj_i3bTϦԆJ!F;\RHIʟQj. ,SJfT^Pfg^ÝkGx(%dQ3TLRk(;D=IĶjbBo u[ؘ(6K؁2 5[}Ǒݜ!3ɺWN!&=,?mbxK ;9* ;E+Dwrl݂9%3i‫舂[GT19k<(pI;pIF0]sV̬\@M@ )`Dߪg]l 8-۩,v 3D71ʼRYs{Gۢd ׾sk/;xP,8 :%ý5inVӹcn΄j2r`dE*HQvbJp1SH:lÌ =O ;k@}!71n9|I,?ĭXGg^yc$*^CU+?~0 qk8gLu8LA}&>z3[c뤉/`^krsƔݜּ|aϛ/9D9;a#l+2}M{b'L]}̗$R`R'<5c8al7hVZ JC 0G?}Q`OzQ5-+p2@I8nJy_ IDATfZ9+M2/s9ŗb 5aSu'{ƞɻ^z7db&St= &Y^$MǑݜ Y1Qk ١p:;,~jP8:8>HI;i*@l s| 2ءA'_ęY!='h<• L XW*ۃYt+eV#6%Y,=ޚ2)T55 7iQQl[bܠwn([.5=_m&H{9<1A1ly<YUJ ɵ.o"{cnQ&EEY^=#~wvwGRԘU{vIn̈ H5vTb}eH+ӝ(}xe,1y CjaRRuHi41с:0%砝8Ͼg!,,_$+Cfhٞ膥@:KA[k.4Na&P PPۊy:5?P&e7ax.aBB42udviɘvd=x 1YXFܲjlq: !M؀#K]RkwL QI;(@m6KV&:$(끚^B)1H,2B,ha쏫w( ZM+ AĦn Pb'{X {y}vi1Q]ױo?)JA(nT2:*R4ARGvs&H{4@ TĤdt,&kѲ&<_8祽7s Rz?Q{{tuҠ 'ᙯisRS[C:[Dw8t0mSѐ =3I-m IH^nΛ8՚~ׯ$TJ~OΎ_M"/R ƈKZf\ bn=Q_^~j m(cqB7s7Tu}gU)T7tn+/t bjE"cnibR, O! /53@)2cN2 q+2dR,&9;Xfdx rRGL[]]m3 ry,>Æ`{܎SqY*}[ݒLuN[R.Ui(Heenqg~`b_yǶRu?(.q,%Ym U+3lyF{)&jB61bW]Vevk ,$Qni쿉ԼHF_vs&B{Μz,'o%%09@gN=vC݊(kvVɧ  bٔѠ١d= ĔtuChhnmSWgplGål%i'GzojIYedll1CpaXC,_&a20L0f71l#ZlyվtݥRu-ɘΣGOuu]os9q-FF1d(Gs}9C"RTD=ZXqFV`r$q<9 Y/ 2J۟mM,bJM(o3rB2cTMUT%9 D(U9{eo|,s*ApK5ťDBNr6穃 ;#t&ܩ'DUd[{\S T1j-tėے)=-[>ٲ{Lg{{ zYr2hsl'R%UD ˧WS@^X8 p 2QɹJhc[ܹ@LyWEr-L2d('2ڦ ,MX|RSeZa'ba^@UEpNTtgLx>#wzyM*X& 2.XpzN<"xa_[5Jny_RBDt802bGw/ɭu//"Z̽)>پPۮK#|a%#D ׼onFpT8Yɩk*sR(W7~ PS<~]nK@\߈F5eR]Ozam/!<"h,2NKQpc٣&RXLvAcF;2=񦧖f6^G՝c3Xi\m|i4 #6PM oPUQ$;;?΁=O*/[$Ei-djXK 6gw}뭷O?tcyJxĘKUh"/dH7+LьFgKeÐSp2Axmmw 4}[_SP?wn )HNXPD\,%qG8eTa\#u[K{i$^𬆅 椫8m ~!CC &*eQ1k bk1dP&{TO1U] N?fCCCee… |I>}ӧcJ\V281?/G;Y`'!<ONN__ȘrLc[zfK*ՌPfJ4ԖkuU-Ah EB)U.[:S^_`R5b3(8\LzD{yoR=ΎWuw'W,Yp20"tT$ۤBwW_"I@ӴޑСSaZ XnK jK/e4⊲^xaݏ=t֭*N͏&N "q IƵxh$~)@QOdŽBjWjJ1ٝϘ*En^eS T%lH2KD%V .U@}TujjJO5+O&ʑثmW9uM:|ң$?]P[A*T%DKű' 0}nyߠ1xTpƵн]nK>or\myR=&cK=t/_rqfo{ٙe)Ͻw}[oEYp=%Q:::.Ɗ)/\MrssoUV[?O7nO?xc=~ppf\ꪫ\y<߸vuٳ'77ꫯw|0`08mڴ~(.KJt#Ip("zCk7ldYig_^ɝ}p(jL8Dǣcv;6;=UYYV@+^@v'+r^<DY-pThjޢTK/<lywi޼B;Hn%p$49`K<6\[Qb"Gt]cu3$Y=I֔,w`T`ܹUs eojOsc@"c(&hr[2up%}895籼R@ pw4vf,յ/~իW_~?O6mT]]D 瞫_ZZZ ```ꫯyo|(~;a?/ //>?<.,G p{%UKv1GXyz\G~$c6j*U$=#@GT%mx: CR*M8tSӪ9ASA{x,H" WhΪR8zg]'r99ngwN}uY1eqcYTjx2!Ll8*9Q AY\ֲ>8.Ɖ]XnKG9|mji:0=7ttt;۷ozEuwwgϞ {'^~kyV\ `W^ys=gѣG~ pm=.Rk׮B3wٸqcNN=BH]]w{LoQK,y衇誯??ܚ˫S@xߠH|@{G(5,&2Q=EooH ?j,4w~A3I9<*E5|U;Nu,Q~\Cn@ &45]'/A 4ДةjOpԸy˙Rp=]PUmr|cKw )E$`"qLT󾠾Y]y*;7(5Qr[25p4O5џe5M{(Y\\lzȑ# LVQQN2-++[=zϗ66kMZ?p8.GyfΜy7/^8~JKKIȑ p8EɎ4Y !Gp<$@wRgIr<{iZB:?:V~Q K504Yrx D\P_P= ꐩDMe_|F[[[x_||sO(h"fxg٣O>ye˖|/iڎ;~FuӧO_t魷Lɡk*޾m6Y%Iikkc}.]:88__DG׿e&u4x작*6jg(:;I[YDjΨ DtU͔9cS&(E8Suf5676{tH8[0E`V՜nQ. ړ GhBSC& }qr 08D%:Pye(s(HQ+>dnP[:4[SK)]tњ5kw嗟r)_=#<y]xyyy,xɪUYf#[b͛g͚u7~^xI?\YYyW.YW_%ȲlΜ9fz}Q;[_>36m={U}>Nf.aFY#@KD45~Nns$:"0v2_$PTMǣ!U)U +__`qC˜;M;а*yNM6M4MQ1MS(jEATs$CAǧ4ШFtJNGW&ƌ/ȴgEǜ޺ƶpS /TMh팜" DZ .%Sį;+@ߓ^Zdef`pis~W^p-3Pcǎ=wywilP__nݺV2f̙3^H+Çǯ˒"b'xKNPCK_Fjԝ?m޷sgkأ'}5;ũѴGkgL&RZ:ʂaJU`$Dg%czgʣ2&/_+%RmԭRM&S~fS 9H8p)ը;4J[衦>5MW1=hOEM3O-0QdQג?R]r[2p4OgL 5ReO%SA G%~Rh^b;g0,C͌p('WQȏ?x4JBhj>KCooC MSJxMQEx}aR2mCS@& N8 xB,(.MS:`SqI@DBt:̬R1FR[P1`@=N)dUGbmQTfٟ[;{W|+ر zc(;`6k],w`)z,7R`sS3p]su_w&1;(Qg2NQcx YUD =8j^Ud, u4 2>dKCM>j $a,5Ϝ3C JU40VД$ٵQD(tId,D x0>j塉.%SG3^I{{zE>jɘ] 5 9BJ86?{'/(UAdN{Ȼ\?F2Qcn(2bȮB&0џ5F DUEI.` qm jʜ{)@nKQͬS|j,c웚5}*.,UwUJ`/8^dwGq,8NTT&ܖLe;FCVZ?j%!!0G M*JQ+8A(5}'Ir1DMt= awn5uxTIE=U㱐JpiO ̩U_O5R-4%PJN:$rWS`}uTMv ,WKSQS)/r[2Ep&L5sC1vZKEE`Q$a5+Iv˥D@8$rL{4cҋ9rdǦ*L&{K7%\/Rq4C(>:Ukg6֖ ǥɯaܹ}{;YX %Ӯ&b{;BƲ'Z;! (H\qInUۢ_nKbql=#W IDATVCoO24"ڜ:*u@)joH1Llc^mb1YGfTջ.~o#MFr`yxRjd:@KCɪ:>ʂHRMuULdNddTeL؉.%SGM.{el6]N}zKK,INg|Rp ǗW1MR=Ge,pmFccjzP=}#9!GH (UI<=U*%Ɠ1)yAdT2 y]R cjʽ#p!mT٩UgBAP|~FE O+C'ܖL{1u3 u{Ԅc!%],$Ǘ0'{èU~O\9C@3M]Mgyh?t>s#Ǧ{@S@%eZ[߭FحNhLĴ .:3S1o)Y\QSEP .r[2up4ݵkM+EZ테]2%'\w5WN'DNe?yq{6=!(Re]F>O k$= :Qj/_ag.橋ARjhoI.3;b NT5JZ=_&4O[FemXh1&= cYL|NDoc`:xE^@USI(ƣ"*ƿ=r"y@EAY }u?/UgLh-:8j%'Z4{^B6gOH9->l˩X̅P8hxMD~&*o2D;KR Θb$>oc#r=Mѹ?9dz5 a-`O< ]O(2Nta͗_<4rb=STѲ#\_ᓉ()Q2}P G_)S'M Nh-${ukmmaHommAXɖVSK,1p'XD>ẺDt(6ܯ|wӛY.cRYzeW1V ́ɋIa3>#6>?Qd2Ήr{%U=I##!;Ý>Jm^=I*rm~TS7Vr[Q M$jb-[+0ldKNvLQⲢjSD 6g=VG=:-;KLO UTS`^Ț1Db.؉.wT+*9@5)@55YhS`O"5*)`-5J LxÞ$)iKnfU^cKϧBMS>rYnK~],[l P_^UK2 %0^{09Dl8~O__xB*vɀ1* P z~OyWUےf2aȬIyjDMv^twL-%Iɟ J)ՔD,+qYMݱYX8.&--fڥձl" 1nc3ކ0ˤ"{ ʒ):} {En[0!&pW E M$;?@K R}U^ TDR %qMmu3|@%˽LގaPE$<',-k~wi3~mGYHsZ WolY-dDXvBxFx R- )6 `ρnAcR<}ސ,ܓ%#7/:ͣ4mM>QdTa;宲Uu) @ v#!`T$chenS@}_Hjbm}&^hwr*k%*p}O{$ے) 2g ӭY~}Gŵ$$`r$q<9 Y/ И2 ohL5uɘqxg2(I5C8> * prP56¨5vl U$ Nx^B 3388qƮORđ>@7thfbz[J?e̩*tN|#XW飪*^!6(W_HFmeNBqfxchnd*ep_GozF@t"mQ=H, VSeKF(0jF"h,2NKQp=\rrPT%[X2ipC&PQ@e7bA! ,qt9G=eͤ_P)BJ$%>ћ+/;/}_nK=Þ1=с3}TG\pd)XmE Y8j<-lj<'jvƒ:b8D![Žíұph8ܪC,K/TߙC ӕM&zT0yOuP0GӍtv_'ؙ74oh:86n5 /3O?=y^[ ͝5/c*D8Q+g.AiRZԎaC#ZT‹nG$fpЀM(9 D0a&g0rh|okч9g4 u/r[2upK껞hMAٝ\s͖-[8_җ>ϓ{}׿>g9 n$$jhƫ@Fb3bYڧ_y*J\)4INawEFnӋȲNھMrH?8!Ohz3c(KEe٥Ht 1VYSUDwj́xsU^tʙܰ #7R֤%ˆʷ]Mmܾq˚nsn~.r[2Epw=3zL֪)j)^F?7kUUUY8p'ܽxa4Q]ɻ/?跻Yg]ȃBh88shGS>ؒ/Z\_Uh741Gqdj /ɂuM/^! x<~?7EEE7tWUMv^=ܯz sƌwug aݺu+))ϟOqp8|?%%%.ŋ݄xଳzyMӶo`֭(Z (G p{%UKvN#g*GJ5P=|)#QzF л#* ]Xrg:f N=xmac駲܅α&fo-ǹ޲c v99_ m_|}To?xiӮeQeEd1PȔ0;oӋug5k(555`;|[n]zu}}}CCW_}7y睂 xg*BG}{Wok֭[|n3<7soYu|_W^~=q6l/7t/?N^ l7h/)/+`cj""v6'8'TԞ*rg_)p$}Y9#QkdO)N?݉×]|e/o W޹zaf UlF>h_kr@)p r[25qgd2u41X5IIROoFﯯgo]tE .|.\+lٲ7 G}?!t38cWp֯~^[^^+x=z_~nonnfWkͺdɒo58dɢ 9y%ؽ: $TyK@LMpqzapJ0%6cͫ8Hh*gZd uAet9SQr[otɝw/B__xW.[g=󊋋)~saDž,ADQ,*Js:p!W_}~3h^^^IagWpxaTyn^9Y> ,b!Tp|瀖@dVy8T%=$=$G 6cY=䋍&cPGB\8 6w{窫\iUW]xwqBmrQl+t͚5pg}&-J\c"M)1nx2_ K=ێαEjM3Nq@TMJU !G;yF "h P)8o.Ar"ت"J*Xv&Kd)׈G EFg(XMf-DUX262oii5fDPkI,aB!0G M*J!%8A(Gci$zEGD\( (֭S@?ȨTDճ]MFr-"~]ݻkWXwM%.IX鹄R%cd\~Q<Xz>!7EZ83WYiө=ѣȨR1ZqdJ٣Fh3J*y-D9 mNRƓy,.G m0$QaJ`(65TdYVFU 2g0bDXZYnK8j bPBs`K9ODHi MetZG r4U%nj/T'|V㛗D;p/ e{:GJ1PcBgBQ(QJu{r*,nPdz#ܴdBkp| s7D^ wޙgN3QWhN(i5EO(jgp<HwܓSaѱ71j֞%뮱TX*,Lqe&S7FMo!{E,9 '>яZ'Naٴ}6Hq wRg ȋvp ]e3RE"YVdeT)p8rNtBG-&~T* \k~f;䬔 {B葷pzPFoh{R'Ek9UP(E5B@%SG-4ZfK )>Ňm9 pwP4kCDtBpz"îh% E%\L,$8b胃O"rzL%_xOXSfɧ(ces/4"ΜST t4Ւt 8/=yspJ`偌$jAEo?ѣHWj[,&\1(GeiӒ%4#}s$AC뱲ӼDphsW+iUyN|y6B( PJ95)WaGuςGk7X\EAo,=@rCnnc V,\}JΟ) M^:PyrLkmNvB$Y#ؐyѕN>Cr(EP C(gira* Cp +ؽuN6]mzK)( jB yxl>|5 /Jy>w$9P"Qhy6һ jc oFW.9@_qqM -o/vsۊŕ$^2s+MI~y<ۭ9酪/|Ngz+Q%'h^{mȻy!!Gx6TAN(y~gb~T8O\φ~-Vȓe@U YPv^n p|T".%[,<(]3 D|5$x * F#^ThDpك*,):?PX}~]֮:xg[[.prY%_pE ږ[ d")/ܸD<%6սbq-8n+M,d5nJV4+-0B %\vnQrx?;9v-AS_ko<N^O.nә‚IܼbP@~49eesx F-AtnP םcZCի/GLTDGA5!pO1ֻY n8K掿9/>uR4J()h B4(# DDQ#Yy9 ƪ8'7'0oܵ<'2* $7@Te ꊣ[Uk}zApΨ9%]%SGS |Q0bێ,9Aikzz `eht<'&hsxT%>Vћ~HG:5Ow 9.u, K> oxG@C!srbN[PPPP7Q({ZOVK67 Ӎm1hibTܜL)cf+4J|'5Q8K>,>QI3#2b߽?]6M}.3eœDFzv T\^# Wt{(M7,hH`g[ :I,TE^k_zn)-YZˊv}!m+Δ)IVn.soDJzBS5MEWt"K}ۛN)Yqmrs Uk}wnk?GB~0O֗ɗ7Ovwwc7oF*ˆjwbH4{]v.((Rg{x^r򄃪xUE –trԞLy_sOFJ'ޗnqF!xp (؜]gԕs#I qFLgWON濿x yy[P9Ǭbɗ.YfOZO%0헹KϧT3M[bTm: X\dL$l)mG-,[1.w;̄y`hqMFt4+3j>{`xy[,rM9~&+$畄(bN, Ѝ;:</qn AѮn#"vuu/^a3=!n͎عy悂:]\@{=a׮{89:}:UsdL&$ $rB4dw",F}UX#EEPnE˾rYd׈:5F%8#06s|mfTz>S {d.`,'Ns#QaJ)YMV o wc܋a; \!QSsfxef1Frl %s2+`]ScU'N87Vy~RG-< gu.]Y+нv%)DT8u#sxyǡ%ђFK0rgV"*-I"Cjw'~ /bW?~R@e}wz87ɴlaَiٖB9Y@nwrP˨7T1$6LbSyI]Au[%_{zHXi]czBIr&\9*Tc""WV@ [PE&Lm],ơwc$$r*[[p\c<OR[;gwepHE (dWf.#M?>@0|c{_^.hշcѦFup\նwaSW2S!gx_Tr&}U[}o4uLƚV}ѝ / ~<3V,N-}\)(ڥgo];3ڤ.1TLDtз9,#iկ6criߩ죿ј {zz֬X&Lb|ooo* U,#c(T --H&<̴e0 I-/B8%Jf L ]#S %_lc݇cfL vsމ%68W.is;=dAH&v̩ '919KΨuMIcCG2H"(ǻR.` ۜpSO.`{/cb(ܑe~݂>g-ϴg?~>:}o3Sh~Ew -݋αqC ݥNX84#i9XurGy5fȂ$/Q=n#5fD$͖̘},]ͣ# G>יEtcs+I9xg{3``8quCcr]@/.ԫD];{Yxd\~cĿǞjj ;j% =ΐ[LA( g"RW7W-Yy2?\}n2FzBՃL )<#tt%p˨u^9Of[dĐ'9%lNJ_eW$IbX{ϲ6|ݹ\>fM'cZ}h<%JOI ?qlSf*:cq7}y#N+i$i㒄U6v޼CCCK,044H@app(]N' 2wqI044*%K2&gϽE%I{ccC4:i~ӜEȂvs[ MtL{EgyCC/n"-]ϧOj~d0ϹCd%ҏ8} n$+&Un;^(Uq=gؖaiE/y]ȌZNWTr jU cn X)hY<Γ߿tv=\ZL \B-$J,*ZݎS)7?U4_W}])ķyXܡH3>zFm!﮿=^a~F s#8 12LzHؒR Quw1$I$DbbŊB5x"1ʭpr@> BP<߿P8O;c$AQr_L|t =t(Ԥ(JDH 5@b>[i0_#CCsqORĄ{KD$V>V I#$KP$ns.m4_Wk3e(~XP?˹1Q?d5;1(UfH2s?9Ʀ^xzOcӂ:Ǿ7U;x|zCuNZȉ+qm||(B{{){_n{8#/>޵/Kwy!$!Arv*-)r*QR⨦)55yz8TYGE޳gw(QD<mii CX\lQ9FEQZZZh;P(BW_ryƾpɭӭsC,Kh,QR6SDF]kYmH| r?6I Jxw8!?ۍmVͶMJO69v̅k?E ԄHY&K^/Wi2եf VJfMe5gLrَ<}ʡ7̴r/޸4捼u(Mg.|K.k}ziڕa4䵫ZID'1^2sy/ {ipn$+5"pp8E"aR&F"fIZ |O4iЮX,J~XssĭHs,e)LTSQdIp()iIݙpb8%Ium+ Iý~CC 4ocV4a4<Ι/eU]%_83LqnCRH2%EWPT9I8%3 6$GLۄ!r$F,t#|ZD!3o\2F>uy>85<_W<"k{i\ιkڞxjdɅunjeSLӟosN (eǶ\Bw(Ȃ$IeIrD3,\$0jNQH,\GI%7EWqD!tZ'\.d#4T]'m026?8wd$ɤ)qu)+ΊbC|>ERC43ݜےehgʱM;@V_E)ٖ=_d9I2332).5Bv IDAT^05+ >˯My5,I--`Z '~o=im7*x}p Mu[{xYzUM .uz*2y+%q- YF1Z,(z(H]P%FzEgbᵳTْP8xLDQR&aPv>nGCJvLnlT5]eS|Uğ |#F:hܭL7{0 R@=P Rfӟ@OhUĠMdKZ-1Jr-T/9VC/jQ4z2\W^rT<@Dˉ(n &> nleᜎ""\ȗ0-EU_BPyI_|TRK;rtж5)kled̄adm#QBU70#=P+plH=6I3$FDjjxgh7m;mvIjy;bx"`iMOf?(MdxG.Ψnwo;< ޡB唱 R 98o ZQӶ%.q>P} f> tN.ڂ0b[ ӌwozHQ+qp~~;$ ͯ|O68R+j* 6섡(2^C£88 ok]f"t<=kWe5La6ioE5{^?qĚw=ݚk|< w)r ^_;@G'S5ju>Qñ \&h>޷RN)Wnį_%yOK?=^~fفMĹc˲׵JجY;#=aYMH2d\7}BdGwCCI *=$vᖦ=Lk4X =%xMȻ7XƟV,YrIUAVXjπS Rɉ9s>M$ߕy!=G@E"\!H32Ufqݺ8Q$:LbDyAA%FZS(51jWCVa$R^"Pa R1۾~4::N}wI+ ĕkOk.)9{{琈R*!9@jN;̦T_ >a-Hj*Y\DɹcED"x,ɕY(fDT- 7EzTf`$3ͯFHSX]^-2d#zUlKaHܫ'n WG^+Em0^ooY&jL ƢTKȽTYBVm* _{#ͤ>4*#w_7[vEܗw;^މWW TeJ/^zzQ+!s[SC nLHڼ́hW.c ]EE2A~ = 1ɣ%aQGFQyjp fqfPTL[r <^7_C9ٲnl^ԴS@V!+Ҫ/x`nVc:{-[[{{R߱[Do{KP)* M*M/-2>8dma_W_p=HJW_p? 4jT_0 Lv=sQ>tˏ;#\m KzڛH[tș9_yX*P* 7=cs!)m^{?,UR523lHUZ[FHwwwoo_46UzZ1?xPg\*pyVJ֙stvvBMhtAnLIf/=ͭ͋|򣗑Ү̨`wP? [ض]m`J7pr~w,]ܱt+E{c) 47mzsq+6~=k`{@חOG=x9l*> I TT| ,32-SaZé IT<]yeK-Y()܆] m"9PQ459/8O̕Hg#Kn WҋEa+X .>DPÏ^+WR~ w+{+= +O,uL^ܠ],*60 oMxqFޢP}Und6K p,ѕpҸԨ`GIQT- _=nvD9744 D:c1z)I!3WշWLdAڇ?=Go^۟F_^̿~M 8Cnf 38&xlۮ $%}|bdRzZas lYlO{UOG=xSpfȊYlY)0јXŢJKK]Gx; YL8Jo+~a02dؔѷ,s9lf@qϝ28e9)Mn";31Hme?mՉy9W $47:4 ^~U/8IMeYa깕E7E+Co2ș D \~?}kI5w-K ci\rw֜Lu/,ZkN>8soテu6Cڛ*ƒ<ST:gIC+ii/&%466͛ת(;FY,7f􏣤0 piy"'ܱm0T*cYv&cΝ3E R 瓙SѝgU^ uŽ NR}A9{SペTRh\E!dP2?rɵ[رoK tq^so8mEVf /:%t`6P< ;ڲ'n^{ RR)7^]8 z0pvlkpܬR55EYW H$E;;;njE$I(Jj,0Ί(MɣA" gEQP2c )S[MCQXkh{chK˷wX,ɘK^(`:NplӶ a1PJ7חeW(j.ݭ+>|݆˷|7%;|Z浹ϖy-8#h*&Pnm1JTJh׋GYxtԃcF&75 J`}  |l-̗e%GFQr]]]zFNuxFgNRSOY=Ѯ^2:_8e͚JsM^X\ʮٶet eg_z/~X+%K~ WRixuL,ڨ3L+=.Iˢ[r1 0@Jl7`qǒض]Ǩ'֫ `ߵvw%\,?]?C+;H5%J+4뚅&x]oR.uR2YY2(Ӎuww755 ʇ)Ώ2]!Ho E,J5B HP,:$\diTG+i6 rw8/Pot: :40tOxy9W=^QzDTek*2zcgK}y?Ex6u^A1p˵mwɫB$2^dn^{D]QQ!٣<2$'*1[SS7wґp^ڌs)MF;~)*HC}l2dWQ]BI*G] 4{}H?sՉE]:YRJ_Ibz৴8>3g1 `,LYȫ-'9$)QlS!0w\{=wm:wD]!5o|-qƒgz0{or( +T0:T) gԸ9w! \1ߒ[x(i.?z07uJIqϾ4сCC]j{ɚR "T]ܱ6nKnK_ DF)M2@kRRC"zp|',iL (~[‡W}-J=O/?窳/=c֒O&_7 ?IAdT a,_in$4mط[Ѵ~iŏ8{Dy;RMB20":iꚅOG=xxCS}Ibd2O|,-Uz&Kj;+\M̴2fAy/:?E2{S(ܺD|S8 &bjKBQ`H}c$_}#:I}[5J!cIP%*KtO ̑\e9FϋQBXܱm.Mo~aN\WUzý~eA+O{s]mTؼns^%: %fQfDCN6l3>.3Ʌ=p!Zf(-@lDպ(]gh(.ҳ-nJ) \%+*֜TH$LIh eN/Y `X>OIAO/~{oԩjؼxQQR\fj"2Gif`qқymYuUp6Y u RHgO/t߹,i.5E5"*mn>;nϥB2i>O]u] ĩ9n:ұs'2FBJ<_mar"r ɧz[BT# ֚×]0/_1 R|p|痯hG>`<TFmLejXQ9‚vAyȂ*E-,Y0Nrn5y[WP-hcGn)./˥R[k5UOl;S쎇@I!E[A}s'!K{ *ܮ]*;<'~{{ ڛD6Nyǵ,B>З2G?pf, K[?{N(8rvMH:qoڂYxtԃsN /(eǶ(Ti.yxxp,c$WAA IDATmqJ(\VT>(|ga626?X*5OݵN?ag;f9.0wD_}Ͳlm-+T=,[cC2cې8I6[?a;K\G`~<-|.jۻOZVv}a~[,IX?m-&2ST_,+525 PL"zqWOG=xT_ "-^F.4BR~ H48glEڥ=jA39]yT5&نR)6綝bwzdd*܈&FQV|# Tئiy)||iO`rţ6/(Vp`˯]Z6 y5fXPfMd+ZLK!ffh@hcBԌFtv j PKA;3[BhӶYb8 s(Bf> tfEm{E˯s+h@ '<|!ɶqP"*ȉL(^|Jbcr 5xeU=ΰD6ŬPA]p c(6垇A(~_(~83J)<oU,d|e;V6!+.[cBdkKYX/kT}֭uǣ(9 68sOgm_p<>8ͽIbiAEf]q A;Ef6iĐN̄BTQY"HKjȪc c3ߘƒgz0SpBuIT`rrEё9sL[\W=poqť"*GIQ# ?c3bIq4@cc*a+cmiS/3~滗\uswϑ/kY$FU=誖Pl#zU:S fbPEBZnC =,9w,3S`,yh&9Rx<+;BKV-2#()Ӫ *Mbor%fLQ̈́hE,khht/$;mzH'e}⟅ O9nÉs&M@MSI0I`2db`20оA f2PU_kX0Wӟ7[gJG=x$1'1 esLOXP> e5lhhM"ѢR!5QFPe&ugBQNG|հ \9Y ܋p8<<< VliTVwmP> pLO@R!QBhJxT Y 6Lʌ j|5է~N}{`߉}v~˯tQHSxQf3%Hc,U4̦LTVּM*[`Z]bzSD"7UaH)^^ǒ*9ڟI?.I*AQ1Mu~]UˤO}yZ =,! 2 lYFckָVǢQ2W J5*98jQRLm˗/#5dl ܆MwQPaRٽtYۼ܅ӫ۫s#gH>IA|߲nf+WH!31ѰLz+?j&ԴǞE_۴82 ۯ8dwRҙPxtԃI$V6 @V`˒ \@$bc55s,G"\dYtV]q#3U(pt4bp7cd&$Ɍ)SU>:eZ#4 =#4RB&L R+bHMǍlXLeYa깕B Ǵ2 LӫN\λsS6YvEm]S> G@&sxauۭ5'n#K5(5#+(9ȹ maR /WMڹarJʺaMryջLPʬ(إ_[jiypu^bVZc)5_{h.i( "͚{#XKBؘ[``ŧTWPP2L^#`,)+ O1ŲyEG!dq|>0W>i)8+W-B&$ܱ}7W&wƒ<2$'j1CKŢzzcl6'uX,:[g<=P,z(4Fp9B-;Y;6umΜ9ſSHȫZBAmMzMDeP$dDRg_L!$T ;UXҧv>0`$$"Hة*/.۱}wI z0{or( +@,6ѡ 6l_: |U~jnFT_ AIo,B0ݲɍYH"ꈂMɲ@I:: PR%Y"߉DJR*-")5zxZ O},NIDxy""OG=x(n65IM,FPW8]˙hpmL< BQJG Sgψf\wwwIeLa[`m$d[فq6p{;c޾b->xzʳp)"Qş(29r:_3s@U=dUXY(5 l}pS(DQ80CQ87-\tgo'а2|W+YtfϞ۱};H8"'ؾ,OG=x)xn̦ȌYXjkDzh4ƄbPhy#3_!([hBܖHpP8)'Hoo:> a,_6hn$4H$fS2FepNLbS5#k?u|*@6.YEV6JZ.Js"ZJ)/W}WI J;?M@mtSQ'HByTmQn瞞!ߕ\*^ UXްÉPM4pKUTm,т[Jf$)-ӛȧtDɍ2飡&gpR9 7LXJԀű 2UQ -,6dY4mt4a`ccȒ%K8c:1Yu;:߯g2I]& 2*`ПɤÚ9C+V7>>E$sԗ>")Sk-P؜:"v صD}d;_|^x'?Iuwy^~O7m9xnudKPxtԃ#SIN(ȱMKsB $"6 Iog oE%IUL&ͦeUU$tr~z׻)?up0w P({Z*5TfF$I,(ԃDNH,#h~5*zU}.OԱ/7-tm$d0ǂZ(x] mim?]5wmX|+^WO۵7O}r[kN>8Nj2t;aG(V[\FX)f6ɖ}[/H R 59Cӝl㫮*G?1kT_RHٝ4~]u3RxtԃY8tlP8ls[MPc/0ǹ Iq NrȔ$p/,V{]!(*[p1D뷰USCDn:X)@sl3qKfmHrd;*混:)3Ff6 Y-G1W|}w$)N >P.tVHcL*}N LKQfm';|ܖien]ii4T]'126?X}}QO)%x jۂiZ)۴qU14ScdScF&TkJRdӿ/pLgK}{%dͯLUئ57R{(:(r>(39o\ЪRsH-ٻޚAPuJIbs4bC%тLbOJ3a^Ǣe=Poe}QŌrR#+tvH ğI_,3;Ȧw}BsoO/'_d1't 2S^H. 54i).,;>.*82< ϻu;mIZ"2c:} =,a^\\R)Pr2˸kL.<'P+-8fwhiG0@t3%>/XyP͓ uCe3+%E:Rm / 4$6d7q;sr2}MkmRj K[~?|[ J Ȟq6dWng阆-xB2 IDAT'kNyt7pKA8+tb˜Z3GvIYŠ^ C(CUJ a|{p޹cp⭎6fHjϲvZE R` i2wCddq8+|C8 i~Q7&mg:m-ntVN(unrSf0ї6oq9:??uJ"T:GCk\Ra"pẑ" 0kj(!"wM:S:C;=&.*b !Xni!0Ce(t: t: : @G@GQ@GQ(tQ(t: (t: : @G@GQpA=ϛ_ea ;p?i#@GQ@GQ(Q(tڗ{ÚwMc<] #Ŵeo~oQ@j㺞:qΡ+&w:ogFCp8-lwsI9c 8s*R+B+۶¡4[+ǃaaa$?"|&?Q뺝A|Wʷl;BiB iiF"P(4$c&?ўE;;; )J4:;;#4͡k)ia۶}u=/v^4i7v(ڶmeYD{cG Hr,AT0ֶmk_|oYʐFzz433#)K~K|2KzG{KJnvvRZ pjHnqW˲&?`t"`b1t: : @GpX@ߵMto2 ae Jtзɦ3=Tw껶ݜ Ađpկ?Ղ&ߒo)>zi}`ԢXIG]}eo+Q[}Ǥķ04 H^ՠ6(p8 ׍_}խ|~UUUeee䔖nڴ.: *++y˗߿_vȑ^xaƍ?hiimƍ}Xk8Neeĉcܹs<|{uuwߝ7{W8qb^^ޢE;\[v -[R^p!~֭~]]]ii[ZZ+Vx{>`MM޽{JJJ>U:^b?vhAAAi4uvq𡜜l!ijvƍ/))kR:y^n'Ok*^\k' _Rws]]Rj۶6XZ:=;;{ʕW?qQ)ey׉D"'N(..k2gΜDbۗ.]>B3رӧOB_[[WPP...~-Z}-YdҤIBݻ?ÿx0@E`Qaa5O=zmmm{{}***jkk;XK/k͛H$X̲,0Ǝ-(//_Ѻzٳg}wWeQ!Uz([vRѤW^}eݺua"WVjSOyp=---SLyoD"QU駟q]7;;'WhvVOaË ,hllə5s{꫱HΚ5+/yt$FԆ{͸}lh-OHG^. XѤʍЙF: H&;mj<=Q@j2M0FЙ?7!dɜ_79[]XvzȒt:yΏ-9i˜ C*jmwޖ>)8!#3sjч>m)ieϘZT4( )R˜zꋔ6t#w0R4cHuQ(tQ(t: (ɒfb/|: α իIENDB`tiled-1.0.3/docs/manual/images/terraintool/07-drawing-cobblestone.png000066400000000000000000002730431315121121300255110ustar00rootroot00000000000000PNG  IHDRXf pHYs  tIME %.7 IDATxwx϶r{% =zG;(*(EQX~` `]zS{$F)7m 74 py̞9sj߾=   /,4o AA,$&&bY  h@@AACAAACAAACAAy`T* O˗ĉ{K3hР_^vu"`4EA^\Zn믿>Ȝ9sjԨ_rENiyBH2*<_~OєN5k?;ED!CPEQTvZj_?x7`TpS6T*EQ5k;wL&0͕ǹSAc6mZ)O\A^@׫WaÆ,R֯_V-['N4L#Fڵn ?3Mӛ7oҥŋwQ,X'Om۶߿_>xƌӧO/:...C [BٸqcFF;;***??(rڵk{Rvޝk988;wn͚5֭[[wY`yDQ?|wq?Y&..Ne{=;Ey(R|Y" /"ξ&yOOOooo"IRyݚݺu;sLڶm{͓'O}̙Ci6Y/_iW^'ݻ7,,!22%zzz&'']<==6lVXXxbQ?2;X+_zŋ?sOO͛77Cϟv(ʕ+ǎ+!2h y}۶m7nxdCAr PphԨܐo "4M6qܹCRw=* .]jI4A䋆@} !`YW*:رc >SAgfN2 A'\blk2!Ej[OcY$̯D fff@jjN&...)e\Æ oݺ]խ*biݽ{}uPV[W [gϞ=>>>W^MMM>&/:thzrssoݺn4q5ogΜiӦMy9իN:QQQǎxb{uҥ'bc) 9_q%,/ʜKo߾2AA Dc)  `0            cc  sO AlDAy  h"  /5  -  /(OEȑ#O~%ѳѯ~gu?3f|Ȱ?7L5Μ>قii?>R%OqBAC[eYYnY3gVwF.]f}]O?_\˲/Z &OXbE$Y'~dIgÇ{&?\2'MаQcO˗<߿#FΙuJj V ȋs4q܈ßB^CBB(62`a|'i= pcǎuEN$i'N͛?_1((yyypa'Gǻw>O 4M4:6  cQ*%4˲uq& %$$}75c^O E)`F޳f-Z֪]݉ F FO۷[n}-[n٪l~;9:'bKʟ3dBg-xw+?=mt~7m&/#G=fɸua֭=z4\$%5uȑԬUw.\=Ǎ?zձSի' RY_ڵk\I?U;wyrL||;w+<OWtJV333# yn-}[lg ۡcY>6LAA;a>YzACB_8Gbn^`au\ĉΝenxK۷eFݫיӧΜ>q#_k1̔7׬Yۿ_?GGxǎ"#@aaׯIc";v0k׮s пėc^8_qoFy&Lx{6jɒGUov1l޿ի`A /_Y~Cǎ*~rN>o yxx<611e]>t+:zɒAy1Z DDDԫ"/biN4ݷgP*NNN3?^^pMu9x!dÆCnٲEQ lִǒ @*}ЪU7B1coӦMjjjBB?Ӵi]:;vd2={CY2@S.\Xn}4GѣZfYham6M6%x{y |lZWyʪ3)|&z3++UV _]å;آ޳ݻt,)(($)99СÏٟG$bl !C ݲukZZ!ҥKO܊% <~SC߾}?1#;;{ֽr!Tp:3224hf͚.*Bǎۗ/\?gggBHDDD^~>+W6o"3gn6lojͼ72L:N Pnzgm?-__U4b;z %J<33)))~ <,boom:ԭWԫcbbSA@>>}Q{^1 azfcfcIIIupҍ5$]rױC'Xaa͂K5N6-::nkկocCB&NB aG+yl߾d2AA>U,W"%5%)dum'^9 ,L\I;{<|Ft mR AA|\IiwAU]HIIa׺oV AA|l<|Eӆ.: OR8:6ox4A gLFvA0WQau !XY{>z}aV*А%IGA4+M}a2g cOa3~B@A4+yJ+1! rA ZM], D ã!  O男kOA4* e aj׮hB, yGU~H]7o\҆#b ]P>mCFKAj@4En5ѷ:u:zLܼq}Ælaa"I.5 s?ҺMۀ 5;7yXjUN,'$xxzݹsG[^ ?9`0@^^O?-[_6k\n|)35oyXazG,/ب!@`0(۷ou*5lh۶䩓ӊ#F[߽{w͚!%%"8XA '&o߶u}+WC'\TKuu:uh K#̛?"ϩS|bAAAy7mtje5n59ź-DTV 6;)B )1nFFmc$Ii[^Q#_ZHHӺ 5Ԩ`Ppy9FĂ R@$Rz3{ KZ% Ι=Hd[i t]D"vj tEm۶_?wxkc?s̘N}:|СW=zdR*n0XHQNݹΑJ2r((/m=;dh@cΟ;?w\٥cǎG]vceoM՚.]?a1E7L)E~ٳg7h {iպ]}睈5k-Z >[s^ZVP̝;aƍ5k֬Yv믿t2ɬP(<=VZ5lp/O)StԹ5{mV_?_B4/AU_ 믿믖#?~wsC ;7e˖b{{;?~Vzȑ#wV*Ficbbh_jZT7o\/3R+8^> A־"F >=jHF%bIWU99IDz.BHbRҼ񅼣0,!RZZZ H;;gY)!  C);;uZ$APpбcSL.G>!EޑMӄSF#<7lټtb'OTvvvnnc> Qco81;+Ӳ٠Aȡ :M#bEli߾XjFe3;'yTK|X"@B>j,X0TPoo dgeAJBɻ+&/M6ᅪF_BuFmoo]zgVVfnR w 7˄H>2XBbyuԨd2+Vy81),YR~kVȑ#k"*(!f9%%5%%d4Z{}M{hI! Ku waÉ;Q"&{K彏aJ.FhܨQV;uP{~>:qFCiԸѣGwɓ'=a_ІK.D|ьuk嗻֬YS>`e)˖a7,~znWoTypᅵ"$d֭Gn{n7! R&ѷnݸo׮/cQ վ}{ym;tf-w/qr3v}m_1?Caͺa(JOKoݲuPP0˲O(*;+kWT*Uy:?4~4GA+.tbͤ N D, :t$IUa5$mڴ-mټRjjܩsnn݌af$>AA̰9Y"RV ;GܜZ5e].-*r5 f6Yh4jiШ5~>$) FR*(U   c9wDXKkZ?*E>Z@QJBEQގBӴ%bGA G뻛vmGu7쪱 O'Zh9 R%85D|hyb0  nze_MjZ^ʧ 5  ȣ 4װ;LXYۏ(J$IUy v # R=$(Y%χ|CiRCEa AAAfdYrϩky@ IDAT_3 !$ i1")wnJso4O;hjNc*bC:u AmڴB@g`Jd6 z`(uiXO7;4*t:0Z]Q7_铝 3O3gNdy$0..[rC^@DQGӥ >y/-nq'O@8D l(AV (:|~*|B/󛨏o+Yk+??0(("IDB!RA~~bbѿt؂u佩S]Ey ;{6''wurrYwqܹV[W|$վ}{ym;;y^vح]+ynVYkxqUת(VDRn@4H@soS7gRh"cM>S8=yIPQQF#γڢE;($I$"LuI$ѷc|s|e^@gΜjɒs<_nw&=lذ'bNNN>~ȑ#ॗ-yAիV[P ̈́{]CK*(]ÅBD$/VDBQH40,˪T*Vh8xȞ;Ɔ sV:e(ѐuKÂhKPiAS4qi@s@1>75o#[c|-+7uP(|ef޼i{{C󵱯M2y:th欏'TKIh e~3>,jkjEEl6ͼ rJq"E4-40B`YVn xlV4Y2۩yu|FZ9Y WpG}G}'R,?}4k(,oJv횷'Vfaa]_W_Z7m4彩ϝԩsN-(( ,ZUق,˴mŋ===eϨUVrUrrƎcxիV;8k 55sfN]ussdf̙zqVE)MCU?FK,jI+oo;eaCR>P(8h XŢ+aɛ|_`h `G3$gONVUCAjU$ZLF}G}G}?BZJ#2 @G!C?ccƌ{:tѣ#F< q?_ԨQ#N7if|&wX矖/_ۯ͚5IIIV^pg[mظqIpѼ~;ǧbCPsvh %>#(Z[6KTvua|e6U1U9\htl8J]R$Q $: vBfBJ؂_1W/]HN\FPPU$Yc0GVVW\]sAAA{ymض8;;ч7gh޼9M}0|l]nС*j͕̿ģ݃l2 ։Fj1w}8{>4p,G Ri Vh@[+!nZlN4r9BmU99BIL56-4k[PŌ W7עfOO./OT)qG]2$I&Yq)5kլ|dzO>SN}ypo0 h b 'DA09Ap Nig} ih̕SbP˻PuV^P$o*8Nl_.+go=<.? U%dL:u7mfIܶ}(;u7-_ݖJչs (??߸ظ6((WT1| BCCC4h %h*2X6K[>Ͱ ;Z̋1? J^ 9{7ھQ/!ٹ[-.oSeӬEK$IbYqX2/|ܸ7\]]FF9|G3gM~@|̺jժ޽{@n^^zT* ?E7jɒ5m4;;;%%q5yz޾}:嵱c_zٳbXfC*ȹ[h EU߇3gɛW o,00=."X :Zr/!s\ 1*>>ꣾ [+ ej{c&Ulѽm[,~xnݺ.Ƹq>nܸAM?ӟEqݺw΄ ͼ;qRJJӧ0LԩVnҤm[vM7rAE2wS!f>όFRJs^kW՞_@T ʌ#XT1ʞ;IUۻ5@3M[:$`U- ?S΋#Zk(B}G}G}я1S'M6th&No9}TjJJmZm*男OM4Zꦨ9cAP F0 j >ꣾ?Ǎ;rN_>Z0am4 YEET*a4f>ꣾ( ;رժz*4\b?DzJ SR^ĭZիb gQ Q {EQsuA/c>aPe̚!vPQQF#QԷ;H$ !TBN) @'Bs L䤤'"Ú5jsrݸ+=zL&lԖփ,L&B73J;8EXѤ?lЙ :*7Ls( w/Y>>ꣾAl]7{宜8&;Opf~^ٹclKQ/aX]k\ڗSj@pEsfCoUwUԣaV볁Hp+!]m6#v #t m j2wACPxuH@ @%Qh_qy.>d >>ꣾ[FCA!Hw͢'5[X%͢%d.T*3vR94Zsd-#j|"os (m liL`& :`mQH}Dِ_E0<0ZHr"u- _ vg(H<>>ۖ~g|#HXKPvp./q e C@;''iP׭h .sB8"(:?%7H$<В ޵Ӻkxdc=ZLҒ,U`褬`/mq:,GS1f^PQQF^=;wĩ+AJlÁPȺySw~գoxJhR$uX уSګ|,(ZJ_o5BpK 04hͽ.fܑXJ7,bR2{v3H$R̽ԤԔnV37ê] vq)-8 PY MKcVc6]zAO3(. QQmGZ A륩?f;u˸ꖵ%NiOlΝ˰CrKjW8 uR6;I$4 bZ5b߼ s{y9M[ppq%bukvC3|}{#`6$I0J9xJ,Z)%Rc (*5 Kt6_}cqmmV{]'} ҴʳGGxc={26hͱM #XkՍ$tp @y  ҍ5W6v%::}KRע IES&&=M f8YQ0u$IN@KT rIg6Ur-$kPQQFwċ~e*đ6m7nܧsf2 ǿ>H^e֫2 ~3\~P[[nɂ؄,r#2@ۚ_g]R@Q0 (Ec羲wÉ yoFK 0Y>l-,thpD"fDEj\j4*v&i,i:D,ShL,T6_>%I*m&%%'<<̙3DJX;ahXZ˂ E:3 Y4B'M:C\A֨K#G胤."WiwY442wM_T_u%Q EGN-Hb'rI&iՠ>>ꣾL"%??ѱڵ۳s[%O|KqU^٩,8,ozx"yJ &$-zV־'(k"9Z0 ʳDb@b̧w)zZ>;N}{S'eșʁx9~Ս۵@t~PS`5k`ciPٗ =@QP{G}G}Է}jl,/d2)JyO>9sz)b9@$,HE5b| #̻Ac3 8|Og.,qEG;nH;?7 PwwII{8PwuF(B^Lx; ?wV~5>y12*Q"Q$Q@MS ×aYр˸x>Y}XEzXDܬ&7g Ϩ[S>󕝰P%F*E)ZP7fT`VأXp B}G}G}ӯޮ҉6molpɭ[nz=F7Zw ,C/uKo7rv,-7ƕY)D4r3$er>z-jګո{.DpqoLY6g#h x? 2IWƾw,LD&K4Lm' NyMH@Uw~@C}0sn-F=`¿|ћS;-\ul/i|vW QQmGZw Z/C&%%}V|bi^"IDeSDEDQ^L@M 9&Y}&A()%JK9FhKQ= 4r>:[o+!ԍ|cB[FL2Ǵk׎afNssz5Ď' rV X&{(ei9?mߝ,gu*qտw}\U~[*^H?}M,(F=EX)z3pv,E%rnJ5|NTj@ew>>ꣾGg/|si]_~/s1c/^l9fև>[_ vUgn faф>Wamg8skܿ^fn<~j%H;yR]z7ӷ_]?GK8ibnzƿ쏹kll%ۮf+ЇC}%\tvk /b[00EN#Fd@`Ѧ/׹/uR}+׽{u ,Kk9i`>EDс(b^,ڛL&u~&U2L*=rJ "@ ] Z@K&9qiԎo0rDKurF}G}G}ѿP^}upLlLt# AψPVwzY.T:m-g=,,ȑ#b GGG1>˯^l^f7[wt8{Mkt-厦a>E7GU@#W{-xKQQG.gJHvU7:_kO'}1.zK#q2LDՊ /Ӫ9zBxħR KS Oæ[d6nT`QN\Ґ)N`5,J1ZhŤAc-X|_Q"kP̏vN^:Yg*"Wex:r}EއES[ Niw'G vQQQf`pK rO @)0]7s{:FwwOH4t(.0 <kV2x'pHhirJEVDBJ oAZb: o;O?k nŻ+p7Xz*`}/F_W8]}sX5pK"/0d1tAnE6 `(,`E|`(w,_DQQmP .Mɱ؂?ey<8Vh=pl=hXN큀曷[ MrV4ԁ{fz!)ю;m)B;7o7wnQ8 >ۆ~R"(= iֳ<,|#\4?4 ߟף}Ꞽ7 N&n;Xԁ ).Nz[wwe3̂% -xK"=O=XM64MS4-{x_g\{9c9N*809Ipl*DKk@sf#=%z<2򁹆[hxyF)}Hr׃DѨRi Vhr IDATU'Eb8o6PNC}G}G}U}EN>0bKCA*>Kɟ-wCڭyz׭g/{O'#ZjM6vQUkDr aBf2]L &OL(zlԺ㙦*b 'DA09Ap ) ih̕SbP˻PuV^ʢě 5nD#;ۣ>>ꣾmWoGf^u=¥m{ t\JJZHeQv ͜0<n)/\GN9ex R@ h*D;'VaG+4 yQ0gA #gP/s$Z?l6b/7xNy|3-Ra P(Fݽ&ہRځV\dkAgԙUTAb@4j )oh"ȳl֭ZS4%z>//_Wpsf\2i*؛,5 ?f MLfNQQQߦ|{]m߲zK Gj8 lÄBQTW^j{{{g''g''w2yFQ*EY0 SD@s e9jBF y醂l}~B\ZGu8BBg f>>ێ~ACG ɹ(˽޳sǨF(}Q,MFecd^xМu΢@!&G}G}ԷsTy>[6m(5>TGPT urv>wlԵO6 8:9'0(PWhIO2{+Ysq5dtfeDM"ofd2k1@QQQQ߆&ACG,pV,"I@pڴlO I&;OOUTG܋&`+encu}ZFy3!RA@0XVoC/خ!H1LrSEp e82>ۊ>F1i[_f\>?S֪ΜIh:=S4y9Ͱ%k`GPsA}G}G}G CP"lȯS]^^0ĥ?PIP$/^ĥ?B-vg(H<>>ۖ> Mt lX6 QgA0@tRV8ՀdVT fCcX(-: >>ꣾ诽l]4\OZU.ɂ*Ԝ;zU@H-ZfA$dH*A-IpZ,)l_b#73G (FTț E(HH>ێ>zy3wu…;̙5cgΞ޼uK$bwǚrJ̰ %д$p1f5fQХ?{U{nI %+H) VĂk[,Uk]7ײ,`u]Wш"􄒐f23N& 8y ͝s큭,S>S>|#HE9vT~͎E9xD"H$ń!e۷kw/2Ա .+;J*9;ceX32 3/AXX,Кt1Wle())?>Uׯuٜ9kte \β,BHQ_XXUYUP7dPP8۷wח+ر}[CvN? .[nC ???O,_YN ~c …-_}ceesE/\?뺗?'S>S>S~"hȰNÇ b`۶mmi9\VVz ;PFGv*6ڸ؏ћo C7_tszhUlhllt>gܾcǠJS)\t >P"Cjb ̓ A] <5%S~d[0cۈo rȉ2XF4a/\YiOO:Ldh8ಯ3 Փ1ֲ,1~%njlO~z~ L E2M]sb9>~2$Xj#1栜T1eo:MJ' ΢|ʧ|ʧTTTIf [| & V_ܳ7aeEQa<i=HS0xקw߱}-@VAdƘn < '`b->"^dRaeYXٱ}[x85T &n0u g 1` PAH b٘m"m x ())?>-(MEu S b[䦛>Æ?n6a̱,1pL11Kn^r+XT"5eL%A9s .Vx kM]veOO TT#`;.[m˲,bia99iYrc9YbP.#XD0UJ^${3P\1c@Anځ)d87u`())?Ju-G;Ң]ùf!t`%7Xj6@0oKy#8n囆@OOeh UOn"F3İIg1+c1+chaY']+0  rʧ|ʧ|O혩D(^Sb#˭L`WOC ZxwUXfrxgKg=E-=_[ʧ|ʧ|O<"H+ad.ݼͧTiTT%Dh@vrZDf hh0^;euB, :JcjOOl6>1կ,Y^Ʈ84h/ 28+MKV#`ш9bnS){3/]ѭO.S>S>w&_,]åE#GK~u$v;#HEu:LGpiM5,[ 6pAAX&Vm%偂Ըa !pA򁘱JOO1?4u~]G0)r oMHܢI)7C_枍.^X RavO())k|**$PR8eJpH ٛX.b*%V&Aq7JʃejE@))§J%GۍZ|؂GL5;d[c."+Mb1X!ƹ7LkYR));⿾EzR^GJX3)ɦ`^\`FX1Xh[JWBu/KS>S>'혩Dɑ#8w& mhav3p$X+f#i:%,1 yIerGL1[t Q>S>S~|RQQGl@l~Q"D,U1u]5C픭3X2ut|ʧ|ʧӮ*y4u,t%DXX)^%C 3T0- %m U^tYpYc));1TT=dt,Sܱi`-SWC HHDX^r"]^ce"ܘ|ʧ|ʧ$a**:4;.+Uè5eۮN2 /9 .iub/z`EwP{ϼ())?A>zG! "E eHUSkCh&rA 3Rg.S>S>' e|E#h7:ô*ҞZrrb,uǮAy~ w !&`È mD.Xڭs)))=>a%ѣ9sfr;{wYܩqӦA`ȭJշYEUxɍFn+.6OV.\FOO>>U CÖeBn~诖Ml `CtIBšq=ܙ[u:¹0?m?_sW8m(<'NA` ,*;&侧`A.;Tcp`Vk6~/|#'\Lv? 6|,z ?yc̖7@-Cʩ7p2L";*>zG]& Ϙ>nN(D?ƶl?Fcsd7FK־w׬41A ._eyHt`EtPC +Ȏsa@5x=e 'apRP˾ʧ?':Ldhׯuٜ9 lߎrff vG6zWw$ ׎n9@#楒jMDT!e`m`@^RLKqAV$xxIEП`|Pp#q`[%~77m`_p٤)OR2lx fYӄe:PFG{}*6ڸ6?7O.Qiw} 1U5`ngsn)WJ f *vsjPx!A+ȂotiKKWeXhOOOǧJ%blߎzj~dƶFvOoZ?¡i .m% b%PTW+h:T(`9T/ AΤ̧?'+q{-7a_ @ێރ պڐW (eYӳbBWBaZ,z=&nNp+ $B T'6C!FXFlKC [4EG|ʧ|ʧSQQ%,l\{W❄[e:N3/Ӽ6v$Ң+A@ gE] JCVBXN5""0 #ZxC=ĉ.^(~O o<{+l%;d*aXkC߁ &`ӄmL7á1 aaYP\D,ԕ 0{-l|**#."d,~(kkZ;@loW#>p߻Ǝz=upWviܳY؈ ˴-n`0/yN!{'=+XZc:+dw"_jW4"qca6_YVVcwZPPCy[e2W#JH i%QbaV~XLOn`1OOOf~vuTTT'"h6{P甒@N3妧c;piC%Oc)lC2`-eK ΁]CeX&81)Md|zy e IDATS~ri7LE$J| qƂmrr d6k~{4AYxeh^ /y `iJRikbה1T>q<'[eX%7 .5u;ϝIOO2>zG#7ġPl zy pD0UJ^${3P\1c@Anځ)d87u;Vʧ?'rRQ%$ BP8LӲ,g8alfYeYA<OZZ'a/åE`FˢXc ,cK:kP\dw\|zS~eh կ2 #˲$M0 #QaBc a܅j-f(6,fe,5fe -l:d4kS@P\D #ʧ?', SQ%deY].WJ/###++++++'''+++;;;33333355I%//Fv[Y؟6Ϊ~{-Z"X?ٔߋSQQ%9诿y"p竆t)|Zv<\C4Z! 8Nmz ιҘ8cS>S>'Ɔ{#TŶmB~_j>i>1&yæں];w<8=߿?7777'_^z:n3rq'L<4]^|֖-<gOu打:r&fon%%HåEW84h/ 28+MKV#`ш9bnS){3 r<7_HOO67z2GVp$JjN45ռ/t5ΚkpH9\[]]}{Gq~5kd„ Fxtc]wB_egAN66)0Wh;nw0 yۉ8UZZxׁienmg|A 5hbq2X10Ɯ/L@IY]An*#1)#>0ߛP8dYiei۶`.+ڠE4^v .s)S4 zša[na5G@m`)8+Oy_}N ,RH*\ J#^rn?' QvC|{6x9bq[+C (K[ ;4{3aZeYV9D\qe V4y |@q$O2e߾uu0a/tYv111S0ԾǝSrޮw7$v}vyWʲeewڸI:fٷ'Kۣ`J m] 韁X.vRR,X8XFS,KbDg_1(cȢ˧?'#GA@B,*cZʝP:5wy˱z₿rm޼YNt|)شmښZDQm۶yׯw[I$ L>_K>1q}v/E*6+ݹ93_Ow=eԢ7f\L_o%,PNG|+V;Nz͛xbSWO04]lp0TjG#Ѧr)/p]#8.(9;Po$rffSM]Ĺ2cm>1Ѷ$01s˒D[_u|zS~Ay° Ƅ,1eJݾw-r H㏩>8" {:u_>???==v_~̘1N\pŊ@ZjBq={{p۽rݻwҤIuuu%%GJB/}.=.?>Z3򾇟O_J`lC [H#]i^K``iNI* @L Ftc%Je/wŸ;{3dnqØvBFjJ =N1tB;fqmmڵ OOO׮]W[[:cwJ(w+o{s_/Z*&Ͽ' #TVV]nYf]RQK ,XaCmm-xv]vM>;7S^~]dM:nhA1e:)v;ٲ,bvq6bb8ٶ !:f_&6,426(ic"D,~!@bm[C]mW .+;{+l?=YG鎻kl۲-wOW6򻫯~_|@s;vyOtD];wj>d萌t8_]mݻ-BKWUUo߾mĉ麮5z*󵵵W:tXVVf^~q+OϟHA9Uزfǣl۾-''&jȐw.c7MffQ:].WGhBǏGKLd#2,bF, L] 5b"!aIx"]^ce"ܘ|ʧ|ʧ$aLtA, 0`>#]ssoN?g֬w&Mԩ))ǏӦ_ZzZZחʴm{ժU'ONOO?S/_WZ5lĽha&8( o+Nf1Ͽn%ȑ#zI&=C{R7+y?3yCmx졧;(S>P}X͑gr}=.xn{c久@}饇+,޹w ׾$Ct. "1hVi }Ns3HM'˔OO<=ڿ8Nb' BÆam|,2y5\sO}Xj9ɱm'4555oV1"'''O~<}Zye]F\.8)wXo`ƚ5װ#Gy 8';XwۭܠA+;vlshLOOo磎ua*y7fQxM@֝%).XI&ՐaX*Ӱ3\,'`^rʜΘ8;?iS~o򓍿:_S0ME,بXb1^G'N5`cơMͿ_(#W wߍ927/:U}ߕUmn3NpQ߯YHAƏ|Z\ڍ  W^~E+Pmڳ?}޼DK`ޞ,e}1%WZo3 `FdFW1%7H+Z.В P ^N&'C:Gq{SS $QJ|&o}!V0_<Ö,0XG\Y¹9 :m|3nIs~^TЈ`R OiΝY-\ "[M|ͩbJ^pR(;)\lpLZpL`P¹дk=r}Rdgcߞ`W7@li^2{*y .` o:.(`( +Oy/]{!{]ߜ <ϏY^y-ۮ ӞK6{!0m] Bomt/3_ڟpsک=l K9TF/Q߾yii%$ vf n+uf7UB?lcSf/9%m&ԗjKK1%k߻kVwBhb<$OsM @b(jqp.Ďm7P9^D`,IX)\1Բ)򓓿/kcv ojlA606u a~XdFXǼ}6OH?_d**+9[LLRI&"h2r 0 D/a+h5\IEП`|Pp#q`[%~77m#_p٤)?~b,'T4<2H9 ` QQEhڋ8C _Q3cE,PBcRQ^Kvs۟od Ձ&"l,8%&a:UA= 1AotiKKWeXhOOݩVL0#y #6B#,34w9i.`0 9^Z~ *5G0#3-tp2X AlPMuO3*MF`)jcMbG<Lʧv`4! 1 1 MME}-45: Qg9g@n};8s\ٴ3,J% Y ] 醥j(90[\NJ 1R@ b%/ -lT])򻏟:&ibT,/E s"X`ID'iIl F,L  |,*yԵ"Ye'r+8rlG`?ek:f~m`Y|>~3k(P5SH, Ȉg95xA4q<#_ϣ|ONm;s`mSNv) ൴0X.m0gDyKEy9OwȦE~]ZNq@NďO4"Ȱ0,(."iJӕK7Օ!!R5e:,_ -,{lRZo=̤|OV>|!1 765a9)E5s=d[FeMS ,/e1Pϱ/5A+#?jSQQ[~Ulm۶O8~RK =؈ ˴-n`0/yXIOn . S~)c &6%LKb^`qVboV~?)ЭϑnF$"Vf/0Z+..߾Sjj(2 7X*` %7jPUdޝ2k2⬼jO+(򓖯u.0 $ :<aA`J XE4xi}q*jOc>կ93͹$ l p:;}ל"9^`E[1 ub9 ңVka@,0tC Z)?i1/yr\xl@@,CK> $3 }&4 SbJ=χڷTTT%G[6X'I@Tya!`y"D&rbލ?<AXb9> YDO/cA|OZ> #KWaXD "f!-E<_ 720jكX9K=χڷJu!Gж̬l˲6'hƥL>Ąs+;L3XX:5 H)}'zn@k%ElC 끗<)_nf1d^BL XaN utg3/b[y\=n|toi կ.m[7X` pp3؉qgbl11R%ٛπ"y@6V2\poʑηH|,oˬ2|A(_ a6^AB 9к߽o-0Ց4M3 6ܲ7k7W8&>qI,n߶upҢˏkV0# V+ql@P8#@\| 5}gCqihG4g߿s)S_rŖ} Ż_ w9{16LY}B'[/Z~>G~w#:=?D"NDp  vl_V#` 1l\JV–k (.@ӕ}E9/>Lp }0)O1~Xnmb`섑?ٔX֬.`aF@Ă0P~_G>X3kv̱޶^m945_E5ܣ#Ldeyq_.lƴ߾mkK-;3j#v@h-V& |1C:V&b S &J:Oqv MKfV6t|FޜOwEl 7O K|^;^`42*S 9:O?0oqYV۶644|M7WUy͢E ]K7WScO>v ? b+ 8+@vrZDf hh'y)Mb9WSg8:.YtGzmCcZzJg mO۷ig+}0r6L=d*X`*۝g|nJ^&MɧS?A#dF$EQD@4A4eDQd1,I\8w&` E͝84,s_t)7?7+MKٛE8a05޾RfKW|a|7)׺6k3oŔf?kWs" \x@y[J3Nx{P fV4]9V֋r.h?D :"c,˲m>/>a۶!m;Yp IDATjX5 @n\cZ%eu`F8>͌:>ccqL.&KQgO JVC>/YqrdYeYY }BHܢI)7CŬ  Zb@AX* G<]@vnvw:є#s9yɎws}Y(wN;15#sH!#'yd@ ? &`;N;SFr@t3Qg^Mb}d&9\V /ضpFQL"Xm&6q ۿKN GTWsj˼ _x*BB;nOG'߉^q ?R:N}YKl;;nMЙ#zU /+:|EiXEO `wŅg_pA}SMӏ?a,\ŗ̹+f='z9ʊ#hSR8vRtf2j -1'3J'X#Vqtg%Ώ؄#j]mcO;}sXs ]v5ڻp"_kF̘݊i{EEH|BӘ]gyuA#!TGX '%K+y8fP+0mx] `b%r.MWv6.ٮ [v 6o8p;^^7MKQuI ⷝ?@c6Ɓ\g|6b&b3h Qf[Tt-p|w,fO̲_ws]wNzb$d﮹LxB+xG:]: "vڵkOqjY>G#G#XpY/[^g`XSP< #10/ %- 3a.x{Y/ZQ[٦wvp  Fh_v;6Fwvp`"|_S c; acDLM ra`%V{W_-'pcYVӴ'|kCK8[ӦMl޼y`Yn)Vnjj̼kXZSS'm媪dfdޟ7XZZ/?G9_}]_>|ؼ[=DY~PAA_;wE昫= ćy=kn{86q@cė"ǂ| i}Q1u#G6 a Djzc ҧO>uƌ%s#ɚgd0>TUK/g>?~ƁD~A~an??% S&O>NwyWnuСÇsh韯²SO?s닻W38=/zRy[o/\aCz7XX{?zy!t=D"^}9''g},f\><[oϳ,kÆ|e>4w _-_اO;n7ܲaÏy=u_angm~.z|Р=ve٭[rn[nY۶sss_{ÇUB"q<'X̫HFW#<@7JX$TK,+:+ġD/\5~LϘb*;7׿~}v"dIM)wW~6+}̷mx=so<ڮۗh;،bJs"BL *EW_GaN.:c|ٜK,y0O?lΥ 8 DZ{83e[Aځ3 ses;n JKKA8emۜf AOv)~89EQ8_aC{{@ 3+yyyu(Wd8C!qWWW_oΖem}쩩>]?pa_]RRVZ?_M2,A^r#srZ1$ RVt5"z=kLb{Ssch*>)tθހ^ z]^+ ;@}}}02 bfe(HXu`&3ݒ#}$K"k4;von34 Xhl3԰k,;^nl[dV"=f=GƏ9-%$6[N9}UW^q߽0YN,KEgH ^zP__ϲaAbp-rUUUA~~`ZjjuuuUqnkV:餩yyyeyFP0 3lgzrݚx.vʃyxT߻Ν53!$" @"Vi֥.ŵj6U[E+Zź\낖b\A-dֻLnnf&!Arg;~fs{ ex Y:iԨ<>8{/矿81FZi1~J{nqI7n~b(=Mi.Dͧ`XU `ēO%Ez$Dr! n(.{'_g,~&7eCL!0OVq a X`a\ڠ ?CIDI`@3>p 7\ Ϗ7yи1 σqhcA2xxI_>jh䔔pM8#NXahH<\V|PU4Ѣ5q*ś*5^_.>-`O Z=֭UN?b}z6)@J`؀g7>zPYkhzf?k&v7A5֠WD> nI>'8xS 1[Z A㸼ѣGHrHK%۠)K9 qw晿:r'bʹ?ulE97S=GYn['x҄'-_~g?c ?G=ӭ[o v/s+>-eOc]E %tk|5xqN +-9jwB@[}@Kg `ەG? t9O 84!RwA3ZBaݚ:7? ?,TO sm˦̷GsUM{go$GGpKoxؓ?ܟ?ܖ8Mx)AdYX3?O)er|{q=3'9>|3òa&#N|?g9[n}?~DzТ]s4S+o߮(ʈ#=k|ݒ?O`rM0[nθ  st5y{Hys{#ж+zw׬7Ly٩Ws_}&'!֘+=FIjaƿ~e_;S'U5~wIBT|9ꨪf+!G?p^1;>';pAcF컥7Gy nb Lg"v&:9<8+΅?kflW7,|CK~/|+vL|+,ۋ߉g9.I wKc]eolB!G _W,gHK;kv>/|ȟ/!b_|o[ʧMFЙgM@%nJo+[{JX{_u7 ELN]Krţ!IV$ CRʟש Z|y#7\S]ߧHF$IPA\EjpF9"4O2["^8`a =W + ]#sS!YBۉ ,N >GjWvhlo6uR2S<{>Ոxz^tHܼ;T݃M?(8qbK.WD{) n9.Oz7쪨?@K:n%QjW[h6*T\6 rR0Ԑvh&*`o9Z)VQd'S]bF쁑])ևDǥ'BpoC*''gm>]f͚5}N;˯6.}'4怼Rg$W +jʊr`tNoCdi/Fm^!hOEmD5P>|v//@RS|jbF4JhT+-z %X5%3D] 7.Nn=l$DI 9vXK}@4uyiC7p 7ܐ,1; V^|ԮD/HЈj,\Yc ձX$9!:V5;"S'!ݰ=x߸S:!|.ca񧜐1>󿌅qUS~1%4:Lp"ӸL)@l~OmM5wrvXW[KlݲS%;5DZT|N@8ɣ( Bj~D!b-/B-D58O]|l)h/E &s־GuM}AR7c=e-%޿8 W=A7{9^SݱoGg};x?|?XOBwOkV~իVjw>! X xHT~ qW]i/HM9[)'+rp5O['' _Iv▝Nl;_{qq>˗|uȑ,sK߷Fq綏Rϑ('w_.+)`Xյy.b2)Qς ~7wz3iI)C:r pUV CCS¢WS~ev8~7@uݻ8jѫVEۀ{aGI? G ?e_ <o\B4z$5$Yr֧f'z'U #.O=>/L( x>xOj;?а];6sAU59uh8* ۬2aں Xd7 3~W;Wh zVDhEZYVAeeОkiIkZFiF@a} 'ZӬ ^~ԯlFv@ս{{]ugO8XS#]{ssZ AcO4M삡jnĂ*> EL0of0,-nݻ wUTT׻8#gC1~H[н{FAjsܨK i;X4J73خh^\*(N7T>ַ:;w !涊U9AWQas0xC<\W 8zK]&C,' :KԪj"fg ~~ ৉:Q39ElɪBt1AFѫkt G lSnR2*GHvej3W];?SW . Y3o;;x]% lv+@S8!w(ӄ7ٖӘqALh*wo{?|`Г*>6ڧw`?0;~*.$+ IDATX1~tɨR{`GE{{S,vޏ>㏦:k^8d-ͭѬ\BtBL@i]+ݾ1u9fcћxC(;@4= D'LMy64#Z@4TŋNAdX4T ɒ= >>R8O>7Cӗfc.ȗ$FiVF(Vg_b:IWV05 lD(4/Jܟh4!?0h4ҮuutJp$N Vj*)Cw\' IpGe!;=hZWc?uR{#N ygm>;\JN87Wg6[S,Q` ߂Xe!㲒w-]qxdW%QR6.'8! +cо0ӄg m2I$@Dd`FYbx]+Ѿ1A&C#Ԋ)2 #?@o[í%._~YQm@b˄ U}/|iOҷ^3ˇFgY~rMBԕ0w>K3,0cy{Uќ|WKpqUP0|] jB|m4 &8}\h/aϡ>`<ov! "B$Æ4ʧN=j:(WQE%=\|kb5aK/BO@Th+u[+]⼅|K;直}zAmmY]﷎=2 *CۑE_l)'XF0UvsA{TŴ0^[s0q$/{<do+:\wӛ6TB]館U\/hWvhloz_&Y6z)V? }嗊CytM3C=ؖd LCu['@B4p9MwDEQq\5EУ ^;7\F Vf9ֿtv-֭Ue,\]Ҧغv0~W[npZAD&AE!)ik֠˥,p/N*X烑d Zһ'8+־111uc-[ `Ƒ,)s={tMm>Q#k7WDCUӣxӯd2B1!Ҟ907ydvzⷢt8FR> e|>wqq fc VJ/&Ɗ r`.e8Š]?06_Jh y@T ~ev8~7&&&[sއs;_ lܹrX5swFb*qJу~EC6Xg\Pj[Ɲ+Sb=d+Ҿ 'pÏ+W`/wMo驻g{@.i`mmp(Nx5݆f/w:LBȀV^]XP:6#ꗹ&$jLtJjRx9ɛjRh]3שz ]5J){:>c'}$<[н{ƂP0 l VlMÀdQ^DDt㋝sOp".ҖTWZZ:r # |G`}:^B j>8>\^]y`KdMW-;2% u-9EV;? pTIÕ>wC%t]yޞRUUU3^z( ^y㲲݅\[tMN3'׳gaaziMZۂ/Ip ECUj}zI>klaժU믿38 ҍ3Xu[=FS [C!$9/wgܾm{?DKy>I?/,,gsFAF5n N'*??_̓ǎ]t\ÂVT/wM?AJi@ki)BTŧI*5hujwj, UE-ZClś*5^_.>>#Ԓ%.̝}\za{ gy "D:M4M[bť^znX.OD1+#V߽dVZ5D,OzgYn=C3?S0p`@z,3jK/qgKͬhJ#^=Nc ]./L*EiGp f/:]rYפIp8lΝ;\X_ӻwn`0WTU9s qݻ狢OC&l_Nm/@/=Qm4MަGX,ii(xNΨ%I$)$K>cGkhS> Yo&S(LOCr1W{0XÌ/:\S'g pS':1wʧN髼kx=s+(uQUqVC(v !cv|`Ow*ocU5e$Iz^?Ӯ6sbݒo{w[|遀K.kYG`; M4 C4zCE1u!+I/<ǵ>AJvF7GE#Ĭ;y*@(p<" Hn3jג~hHIBt脕'uj>߹k T)jqvvP^/0$?-39z@䐶#-Ҝ .{Y`>w!maZ2PFN;>Q7W +' sS!YBۉ ,N >GjWv 21~`+c? SBl6`eo^4BW C6M8#V MC!0w;pz:fQZ/hRySg/c~rj7YOܧwjkkZG35otNK3~o1>{|PC9~SS<p8V,z'Nx-qǵ= DQ{y7ME\ne]&bEƱd 0TBwy >냙:&g/@ZNHD 1 n١%yɘ5PE3kXS(bh?uR%fBFG)uvK'Z{SNG~Rk7x1]UU Ø7oޢE}뮻NQ{fڵ0lRILp"c9XB֯l.gbbb Z 5V5C W+$Grj3W []u;7Oro (XV#H~ߥ k_6Fj(+@?^hn) L?]6?{owK)SO>6

S6o}S"tհKLY3ЁBQ[ƛu{e.n^ItjQǁ@vh2nRg]++_\*ULLV?uo*BpCBtI˄~Dx` !H2k x3?R[vӆ3 Pc9^n)R>;0~s^?5햁)33Z YƗ0?_QGEa׮_~SO=r +s>,':v7Vej3W]eSV S8&/M! bɡ :si鏾ygs5iҕ_YVny06^^nr<`{BM:xg_|Q4MìGf-^xȑ^|u(wURgmVNh{b IDAT2 lftWoWೌ 6S2xC(;@4= D'LMy64#hDCU$j*IaOdj;X+{Wʗ_S]t)I)Œ|(n0!dMť}})kk'L0a„<_/O(Ӫ&%"EF3(;~ev>Pĺa&^P>uxIv8xA;= `$b A/=훬zlL95; bFCղُ;5.'XgkwUT7fx=ZqI)v)%m)9ԓwd0KSuu^ )[Y~AAN}|L =jAHF-łk"yy`@6*d81(;~e|21@0'&'A]ݲ'+l+2xㅔV@iQVv^Iu5&1 (;s{7hh;b)s Ǟt=hgÞ_V2dS²)?rU~U4wlj81-o=XNvsy(Zb?Wa_T:_&&4 Cc!xKz%У4KdT`2xIrHO&vv]|~.~ѯtW ;^q=tWV`I)/TnSO -)hyVw?!|m[~AdJTGȷ[/'D'N%1% nsP/O%ysYĔQ-MDiC kDhќE1Tgȣ|~:ޱ#CX_OeTy%|oYg]vIRy˷wOWdyFPp?Wo#ÿ9gbJӡ3/[dMCAzljeSj51쉔VCWm{?iok:;[&7m{H[p$v L[D^}|$ HDle|ˮ C =۳Ā'L{WoCf3S؁ /)2 #?@o[í%._~YQm@b˄ U}/;/8##0&~;xAv>-L[zkE͝{ rw 5!"iD>.Mf~_!ڟg]/SǑЧO[;$`OMZ8_k_[XCa 9_=$J; pٴ#I G_x G1>wPxr膮 yc>xUu(ɊG(3h1Bm{̿2=*e ><صӺeG)E֬N>z3'Oyd LCuIV lk,S^DQrz4s%w֔BJrҜb~es1>wt>Q(hrBa8s"L;ЌωvW |0ܼwOpA󙘘:"aվƜ믻N4I5oonn]~۞>y'Ic5n:fA5Brl5@OөF;&{,񝕵=rDyѶ 0I20uJ^i8n`Agog"LLz?sRф[-[p•+VܱiB 1M5*7ͻCZ$dž absE+:;_3;._'*;dH쮉4ƒQ!zG2JR@S619%--Zt*DR[Wcx<~I'q'Iҷ~1cZ_vڤMua|7Iz}PQE%D)GQ0ևAtZR0$@!Dq9߬}d|h|l0AN.) :1tCKCTr`$d}7Eob#u@O z$Dg=|YA9{5Ӧ*g$Tl@eeJKGys7/oOk_b1ѕ+ "@IUc#$'oDǁNM &3>wLΨ=>{LW`R^ -!(^Sךy z)} Dk|3›zVJ}2:#t0u$$I,K9S^[n3|i.xpO@eV-<1gKUz2S+2(/Hj˯XN0=헝^^%=s}.LLG#XYY駟-_|~u_|,A@pxq\"RaB3 )^t@0qA8^6Z"^DI;r@^0vg?9Dp]IE J'8L7q&ZDt Bl }.(:8߯uv{ܸq^x9jժ)SXhQ `ST;cXEEisTUU֛Hx폼[D.$ݸMiKs YaYR J鴕οc;,D67EؾRO$2p"'J{޽~QMX)"o]Ӂ{СCL9lkys~}7NI9뺮d\|+=H BtN֣5OpfOcUDae6oE aw&H!B *?7}2ppЌg |p-~Ϝ9-[}+V_}մOܱc߿|p8ӯ_3gϙ3gǎ@O^/g555W]uՒ%K/_>eʔW^y .LD`H+dk+Vcf Tz@T|˛lGblآ%"Z"שߩp4TFh JoӫxԾz}3~~t dŕL߶ku-uz"'q="-W:xS.'U_'躾})S|Æ 6nxW~?|ĈӦM0aB]]]$pꫯ^ve}fϞM9;i$zrʔ)^xAX8զ9tv 5k=|xK%̇n[AywxMixG'78AjU)RznBN 3>HaFFN8^t-yrH܅~߃?d*))j(zףhYY]wE{g};S(_VV6a„;}[nѣGO2eҤIVoN:$ʟ0a5>| \wul S .8o5wg}\t&^ؑʧN*-^|]0Mre*^P~ʟ|$+bL|$鏾):\S'g pS'): @#kx=swʯ{O; O8g @]feIwʟx {Ǟߝ?0h4b-[eUTTX~5E mh6}zF~}y'u]7 mfgn۶ O/Sk׮o~`…,`:IsrLvu~~_u59{=ޫm R>uؼ7u#<L N6N6GPVfr/ IlU1aΟ;'(:ا)S3nuw47eӹ~9s\/x?o7xc555^ɓˋ/^lټynVI2nAA5G>}<@LLM !i}Jl+8poۉmvYr_x  n1jUi$^rDk֖F\r+#=4Ls>UWWf]׏/s⋗^zLrhwui&Iңfqekn X#G3IM494\>ݏ=Dh$g@8kt:A@f3>wAfbbIHUꚚ>ookiD EǚxhqW]i@ҡ Jxbὢ+WyέIA55@jARܲ ^bØ_{Wjeڛ ~YNV24g_wm GOĦu5+ ɒm2 5;y߈=Z_qyA%E/L( xG$g|4 H9`bb:Aoգ{Oo}̼A]0TЍXPqP5z(; CfdXZ>]?O}.S}v(,#Ԯ _q_K'N<>mb!ۼ;qCTz鑑,dO^ᥦVvmHPǛa.f|gNoc0S+1u+@ibQA )ɓ.< 5ʔ^3wbhjhܽKa!3>wR~{ņĎ&<xC(;@4= D'LMy6tP/:I&DCU}У;}cGQyDAM^'5՘xS̮6uC L;jn~ >8n0at;{lVУ@ G+صl ?C4MR:Gɺv&[ڪtTz$&':`=^yN/}'`\QK/[ur$ɺcÛo'Ɔ&_~ahj,j, QһCb\/q%дDDVb$,N?yg|d04 :DFp{u!zM'جrѿDTnE1`y0>3~uCi~uLLmW#'9 Fo7HS+k51жQ(sLZ?p װ &/`}c?G0>3~/-#yՙ:UYw1DIc2JGc!&fY~['&h&e$@b  M4{}O8o/;8ߧ[ԧ z}i;([2rFzi- Vz>л 24l+omƒ@};g|=ۡh!!N,M/ͰTEV@^SOz Kޚ0TF+&w*5؝4mbl]Δ?ial`unxrp X*µD}2T\_vH`*>`ɡl &P==[t"DWaƻ™X86Hbvrه": p 1U=91n 0_l3#YÀq ECtɩHRb E#ږ *JrJaQͬ$L)i!Ea&1͝5%A`h5]4%]LL#x?rT8J?j0m#/?`*} 01Uһ8@L)bPL=i0-Gyb${7@_ňm5ud-ö 86~X%"qz#\`Ϯwu8 aI$/ W1L[}jEODrQ?6  Py^Г1AT$od:3<ǻF@ہ'tղdR0T2TATuϩ6< E% 5 ( g|~>x'PV -Ķ,C- aCMXĒM FR Ko﷪$=2Xڬr%zpȡ]3ÂؾDуMMU|חٽlD,COEm!' F˜c1^U^^O.rt( 5 _*W2>3A&#ص"8!=AA G1pÃ%>** /R'RbЃîPd:#<'F?΍pz@ IDAT VC(}!^%GغD@f%)[V ض H3>3>3~'ɗ֮qH򁭁 hDеDD4{D_pK 2@G q^z)[[78-[`?#ׯcA7` B,ċKt ѯI6pVx8 "^rƦ3Cl[Omg]>Ιc1+uʝ}G>Ss3 "A4b6qҙ.XўUfC0.Z?,#6mL= *>7=mZ"B@'I{ZJ,Y ?;%XI[k~A^AP1yNib}HPx,XBE,O/[5\ S(}Pm=taq ]mhnYΐ=~#,y [WBE`ؕ}R=O13>3iğܧ%I `Qx hH\֮'g a,bK$*>@8 uܫ577ysNEE_2;)˕-Aq_ [&61՚?T!x ӊ3םXV%&x0֣+@X- .g(kF#cq\Cqo.z7BP{{; &<1Qy fISOjѹPX_*4SЙ}!ZԞl_O#O-[liW>s?gXa: LoQe VV.$*>h yB<?8ĐK,3t"h3Y /D7,*XttJ' 519 D?J~~̙3~_#߽{{gwM6=3oU~z'?|iӦ?ϝ^a:CK~jU+*lU%~e!i9gu] uϮU+gׁc׭Z^$Oݪ5Uh]?b3_V!2|%Żjx@?|fx}meJ nAhNݳ3>Z~k'R1%0lE`a+0 dMY mm ̹k= ,O#^}՟=ܾ}}K_ /L7&yon-//xॗ^ZzԩS{o~f0M|L׾B×]v-[g;!lݪo@kbz]H@bvD-rtiA,=HE{L[;Y_O^K$@Yq*W^jj<>Ce_H(Z9P<3֝@'oiʒ$z뭥{7ܲeڵkq#zh8/p8L ee'޿{se_bZ9_hJqcz+2d.@M`|g|gOqhk-n ]7;9՞@ CbAFTFZІ(XTy3+i#500裏ڵ+H<|ŋ Μ9Se˲^xc7 //b*b x`yYycc _}\5n1]c]b%TU5(K4c??kuV@9)7^$Fgz>9 Fa#ӾsS`kPr8GQ͈dYNR_:::0ƕO?E]O>c=(~ӟ>?c=|r߿xrf0 AX~˯znh! 5Z {<Vr'2]BL@<0UG57ߪ' -q?/V'Gj,]uaZjkWlDCqx3VQ7:= q;){'|rܛ+JWodF;::(?? &L֯cbҎOwM4Y^kʁhYAT=Ec+*~@?kuoZgJc$$۞‚0&t<*ki1h<_Q>.x,SPX1f:t{ aF/$7Gy(zb[&x,ҖtH|0rlmXz{U5%@fïzpȡ]3>g;`|? +@i Cb2TAT/0jڰ 1Q@CM0≮`:k=Tj޽մU$ihh9sV pbݸׯoݲnU-8 Ӷl5jy0-4@%=ǾKld|Z>u:m$\i?!. EPO.B~+1Ƌ"dG :^fC0,xΝw} Hd```Ɲ;wΞ=Dk֮qH򁭁 hDеDD4{D_~zAxx 7 x,mg'ZĪv4M(z-ymҢZ"3w$0بQԸ+W+_^vL8\  pl@*>C!|lX:T"s󛮾|!3̚>y?惣{Q([гxsDT[ʷmB ,C'ys/Qԓh0 thG|_J(˲m4-"TWW77ۮBt]A8?S?:x J@LKK/ (Dz?a|?%#i}@¢smZ"B@'I{ZJY 䖌2db:K<!q <EEI$aO#X/]T xǢ0pؚ 2T,G[bEnv^'9{`|Z̦3g0`u~-eo0F8i4Ky,)H^xm`#x [E`jpw "2A@<A8e7Î4_ `rh?=,]}qZ`,Z|ˌg JȾPkTGT$b>NŴ+5=^X0" 7񽻯mPc0R)_X)xwg:M=iYF1+W G3YǟxBc r@u fISOjѹPX_*4SЙ}t&3BB6~b$BgD;~6mE|'3Ȩ8 V0]PT|G<^0!ȐYXAR]m3b6K[[ORbɋHl3'@P,5]€?Ogr4tw/*>/x_:t00.|C%s?N3116J1@A^`i<[^5'PPS:H@H;9_b17.c|g|glO蓤G;(U5|SyAQJG K6ԸÈlh=Š)~g]^׮g|?{"-%t? -L*Ne P;/hX4t@[Ꝝj; 8zx$zxJ@"?{1>㟅пtb,&Ģ):>sDZ 11:"V_p=&yXW`=/8ѳ 1C~+!Ґ9խ!FOhg0?K="$a~v@x&nJ2.ez}G4 /OauNڇTG0+EjfF'QR[b#f499Ktj-?'!(L7uz~\/,awdF)c/6e&^ia ܟ`i1b[ ml˰-& _"r!jpq˹tA3~}vUg|?{ GPf\*a,e61#L&uW`Ie'L2,t(>ENpfAdPQR41j 1G2`s ϣ(Yc|?P ݡ2yJ4KQ_уcO_DG]VvחٽlD,COEm!' F˜c1^U^^O.rt( 5J\wvR|r9!A_sƅ}vB2s}A:d:^,^lEGlǖz@ VҲ@ (3>gr*#zs/SV`*>M7{zm{ϩ^T>uN9@fNweMAClPXh*_lD r[/zƒwx2b|J~ݚ uV0>=ĉ#/M7+̆`:]4|*Di1|PqQ('$i}@ыMO#&o[b!)IhSHRQCK?eR>8)Y([ݯ08;h*X'"H3K *F͖2:аeYM[ZZa8cF8ninycY a/j':̿! 톚ӊ'waɫ,ݺ(۠ ~SO2>g97V'ˠ^1,`QQVq|?!4q1" Ό1'TUuH24 ^o^n^aaa___WwEsr}_zATkfdTJw McVJ 8`b|g|g,5 Uf@uY±!+3l2LqO>yښwmo:%%~QkJ7\:퉗XKeS,k6~}{"Yr.K/`⚚O$|^;v q|OQ:! 54$}0m["9O!]ǒ * g3>g-_tQ53ß"T tD i%+*^+ Uôu^{QUW zpgD5,r{pVdWDm=uTm۶m$7nzYF[bSC2A+UV`7W @?AQǥmq+u9Y4oI9^qQunTXx8ǻsqXd @SSSEE5+V 1ȫ;o޽PͷZQ[{LһZnՊ)5ng p~qw}Z)@}@ݳn uuV8|WSjpnFnU5Zz׏_V!2|%Żjx@?|fx}meJ nAhNݳ3~+_; 7~𗦀r0m{d#LOO.<-|ҭMHaK}^VM;4pJO;}TOɕcƺ?:ГL2ytLt]=ia}fԹ3{}x(0ҹ+TD޲[7wg`Պ*B4$ K*nmi 8"~|" Ѥ;єyk1qyy ~9Bm۶B6o~ׯoڷ?'.:&!N燶LwJDqe^s/HR1,Xۤ V]?._U1E*T>uN[ޞ/㺦4x酗D2EmA: Ω^itO), ~edVL$S4|XnՋro^?g7&WNsKg8ZV+¿+^8+v7Ywa%_z}{kdFkYfܱ\מO)  rټV$ap\uޔv$5gAehF?X6L8)x{WM՛mNskEƨ)۲swk (1#8q:wǛ8)i!Ep_1͝5%AH/RC͋*ҭ--KCa"Ã?k =QfTt tPO#gcB NjLC^Ǎt񉱔 qA_ΨSs=܀wM{ĴHbce os@ǝ{F@\wy1=;\'Y.P(PlY#8cy5r`fYցhT7斖+\z<5n1M.P*OߪAQ@@PX@;n6Xf IDATVpO& ]"6o4Kwhص\SOpΘhw8닪ںVg:B\ЃEu DwЏ~=򉑤Nkҫc:m%#DzWT03>37w-O&K٪OhJQe_FAόG~@oG|yZw’)>,HӎfɟЬ-Z,ԒKx\B `CSs'ufL;ڬYfϚݷw߾x<ʹpɅr+ǻqCk-8!=AA G1pÃ%>** /9@ z04{ug|gqKUCdO&B;tX. >˧f!82'ϩ90ɤN;GF=Lɸ,`HY~Ws=W?>>zw}W\Nfjq-iq$26O]KD4MG勊 /2GOv1ߐ?My=S Ω^?OJit`:` D5<|!4Nu7t*|:S8rxp$eK+>ͯfBmqЕˮx?3>3=xO&6qBÛsӖg/&eW~N-Qv)4,5uB@Mu͉ӳ3V0$''4K~T+eoiQN?Y~Ģl;3B'z3>x'?z_h,ؐIU`0ТӱNyp0ض --%9sJb612ո᫵p-ö $zB9!Y!'p@wXFq>ʕ(|yv 2;;>d4-7Y ]7^Q C tK&uM7SFU˘ thveٶeeB[mWTT! @ soS$8>tF4-wlI4xyY `ZlO*&G0\-\`8cGCƱñbb:uk1eYew9ΝnNNPx<"+$I'du6<#fhԓlIʁB,y1mۤǝ@P,5]€JƟl=hq8Z&s1cd跬kΌs'F<8r0kU`oyS@AMY꠩@H;9_b17.c|g|glO!v[[^nu^ tj뎧& ]VHuSϩ^Hx'|PJZ aC꠨GԻJG4td35@b? VL3>3>_]|?6=ڙFSYGpB"ԎC Z"< ]z'N(1A"F(+E7b|g|M=Fi=W'5|jո /k'e//z/xAYpe @ \Is nFg|gqK/C$O&B{ ?o!O7op#wG8.y&Gmiӯ n޼yӑKythOqS+8Q  ֮؈!4.@Nov@ egb@Lg|g#MWUU5innjnn<<`:y&3RYiMb@ȭ0XZVC[w@Z& _"r!jpq˹tA3>3G]w%2I67yyp87w8I%/Y$777ڏ>Rmmm8v577xzy `Vę Ȃ V $[* 19Uӆg$9$&X}Ea|g|?`w27nn?ܸqUSS3uUUU̪`:5r'}fjԓX&, ,SL "b">ROK~9D@T|7G_'?Ojqf8]q X[[KQ,j PK= +iO@xA~!bP,x C㔭^+xl[T`$?{x>3>g `cmc6n8-H@dbweCM$Aw";1t.F'waɫ,ݺ(۠ ~SO2>3>͛gIOΓŭY>fܪ17nc|QD&3X}lbSQ*zJ1NDVJ 8`b|g|g,57fŰsMݔwPVg}ūZs3>3~_i*¾3qzGgy歷zbXqq7;e:^~'|]_.//_zE]>H,\'(--jٲe;v8'Xdk|B}w0f: .iZ>r;wTTTZ*7/DI&jWxse_bZQ qc֠@6/kMs$;S]]p? >跾={-R__oYK/tMǽ?s=wx_rggg]~ٲew~o?~o߮Ozx_~ǎgϾ뮻!M6=3oU~n??dV٩0 hljڼysWgm>0K_E 1?o!6o<[ (z&M2Dy~:Ej2dDϵQd|g|g,O\'X?655:n7] v_ ,9s?Ϟ=oE]yW\qŇ~W\qooٲ妛n{gϞZ|E{KInd2yϘ1\rΝյaÆzmzꎎfb:a4𩧞&租EE' `GǓH$ݒ(JOOٳ 77e tlCk߾O~->^qqqþ?x=] r5wD*x3oN}jW䚉~|UK{e:`QXP3>go;RX+pM'q.䔕ݻ}ݪ UUUl;~0}yގ˗?uh4 EEE[nm:Lg*v֭ۚ-˶m{p0qpo߽{Okk[OOo"$ /}Gz//^ٟ/{-KN@1A{ ^+h4$-C2W0>3>3~V'Gn>xc]Gʕ+Νlٲ+W ]vY7|orJQLM{={^f7xSOUTTp 555W_}G2/??x, .Z"+8 V +AMh E MRpueG?/C+FyǺ FG-<_:";Vvm6"Bq_/Ih믿믧>~GNR҆$utt:ubu?HupgG rBP;:,bK/9:sk:>)SsA<8ᲥW3!6mciĝ~g|g|m$Oiƍr22#̴jkkj t(uO0q .˲<~О=#P('-L2k~A^AP1yG@$<2 ;;_1.f:3W PZZzzY僃hGé[N4$ ,*>Q/غVXN骵+ə*BXҭ;)N-Ce|g|gOfhxܔQݦ#Fƍ3Bw5[FS)dy=X ~=FAص݃ iqiڏ01.:^çPq%+Gx/Bw1Ρ+2ug|g|-v{uZnwo-8na&)[#U( !`D) OCnҙ;ؚ;˘z6 hwCX*U?`O“ύP3?)<0Y#XT\ dq)'c{x1Dݏ4d[ORbɋH^NuM-^d|g|gO\m"SOO(1mq6ahVy0>3>3~' N!G? 33>gq IDATcşY#x^Y>o >$Z@Pc53 <18́ 1?LLL١#xat( 1*`i1h<_Q>.x,eDzDK.Ǵ,g|g|vx'!47_=_8=rN)X<_b<nM] w.c 8fC0<>||ؙ#ِ;BPZ*WRJK[{hTE"hC(@$\1& Byk3&lyfgױ4|:H2F :Z Mfc9+eԠzT@o'Kя~-~%)ŕew)]zU,\v(e9x!(1~m9W,=T;.F({AZ>/Zu5j4oc-t 8zH*@ :aIN=~15O@|7UG?я~{rU,0nPsն=v/cTM {o;b  l+s¥;+lFisO \#`"x*YR r CYN,!T0&'kZ܈4el=1A-Ҍ~wg*)^SvLO٧ຫWeKP!4{e3^6t53z=4%BAXX}m  PbYGNעFt~wg?9_]$'/{j2[r֤|ध_GShNi!T@Wcps.O:kZj,cboGXɠV -ωbG?я~z:\6xC;[df(rdxS/WUg?s=T< X6yR\.ӔHh0N4UڵnF$W"OxW*EX޹5D1f "/Fu5~wo|3Y`Ws{S/W=QoDs{wgS/W͚G 7+}}b̜gҝw}+ob3匠 8f5+&ՕIy5NeR^#Џ~.3O}&Wξ弅/~Tw\dB>T{E+nq4=7;R굟5nLG[[IA. +;^;Wc2lP_W6X!?_}e3Ja=4 ŕMl4bq[?8F N5ZGieC g [6ot.* nxzuDR~'cJ)6az^,*RyAE?p2]( GKozlŕwO-z]߻uv侬 .|iC.:K@seH`Dݣi\hV'm婩SS(}韞EioVhI`dP/G?Bi4V`ֻ'{r߅Kwξ}3#faMe7NGMt]εÉ;WT,鋾/0I4`)S򗿴,. f͚1cپ@[AnОDjwEѧDqr IB2Y^5xy+H~ <я~%=P *oJ4dKwڕߊ6̙>xm5"y>>Qm;G'm୷ZTT:[oFr.Yfͽ[UUe#nϷoEM)o\r umkkݶs]yb( A jyMy{~I5㇩i6r/F|`Bʁtk5 ~G=SM$p]Eos.ϵS@̙,ٖ&O+V.Ӈ2ݐ'N}}=n322"[JûwEqUy[[ C-+qdH];++ح;wV(󊎎 ?]@xP8> d,t9>_&+KhGN' я~U P63}0lM?˻pNgO+e3JI |]e3..\诫+FO4keggkyPD3?h}nNo{Sh=ٰq})x\K."=6!qD>T-H>x- ,T+$Z:EFGuWvg?*Q٥KiJjV<(ʬY~NS(k+ ={ےK/= H'xGD$(KPQAv]±~HT"Џ~.@il_ڒ< '%7 l3}0~ewqQ5b9ԗeN\UqJ ߻7PJMÈǏW[hhx'H>`=X(SSsE_oQ p)G?я~{f7!e3JD*W9 mR6Nwŕڷ`6MU5vhOX\ig'5>A\U^LKkkkkmmUS3eA: >|Wr :2`Q-=QD0J~$2P {Zqjr5_9\残}jo4 l{xR+[[ӟ L=bj+,OOeYpL-Cہ6{ +x69|`ht&< BQ8jV~w L=ikE.i?2kR>'-\iٌR]cb?N69g`|A9J_`ZZ~ѣÆnlۉI۬x8_3 1lҬ&-ik|(F80bO=@?я~fӁo9cjϙ>8y{](H';G) s 4.**.޷Ag'w2]Ηh=^U/VMZ# Џ~n)=.i}p-x3K],'̹ٷjH[~(n Zzu}5 fM_d}>hċEs#xJHI:RKXN“ƺy{d\^Su ̻JT4TD=b<رQdя~.5g=V}?sːE/~v,/`_V88aU&+ W,2hӓmmm=rIJi %PR\rLGӴ@} (S`eP;>TvāG? }vN :=P lKLc@~5u!`:3‚~(:s2  HLi8+; /Lز쬜/!,r բUp D_R@( y=X\(Cu(M3 G?:i/oڈ|ٌҊ60uX\i.Xbq̩z6\5௟=++]rneA, W9@uGo5 ew~=AF| +; VT@N1@ Li4M4~Ha9e$Tia1:sSg#پ TE M~@X G?JoODJ'=G0MC àUCM(UU8r(vOݒlh 'H7 p^Q(C8ջҔz >YЏ~nwr9x^EQ}^:lhjj$˲$xN* {‰5]s:F =nq{$I eFbs$d'p H>ћ*G{E8²ljy@JJeYx8b'N Rh-/rGof ڥŘ5-nD2XayРhiF?я~Ǐ^q#4%BAXX=J퇀xL`APS7&! ӨΚQjO*(ؗw٨eb&Z<'G?]0ͥS])Da؝-jiRk݌"H>9(ET:skb L6D_0_4jG?*?z=匠 85+&ՕIy= zg'0b-GXG?]w#=G`ջ` @!p26\C҇ta~?~D/1w2ەef_fb#AqYD_Pe?XT':zrC?я~ [`c߻yڴ3wT7cGEn9v 䁊vɐ\NN/_|ƝW_:Ň~_j/p Shڍ;=Ƽ'cGCʟ\ֱÍ~wK=)8deg,KqNL;aGAen>KlqEiv?K̿ ZL?ɟ@:E<& V/1ZES 0/NSVʟxG?9, #KJnnd9 Rs9M*چpL F!]( aX@FvGKwa" vI_p"JJeC%y)I5P{iKCI_A?я~i"KAW\,RhV'm婩SS(}韞t7+J4e8)(FMG?B? g\55D MhE91gUQ/>I-)TW+TQSwըǕG?я~wq( !@u{E] rtbEѧDqr IB2Y^5xy+H~ <я~%XFOhep8\WW~O^ܿ@~f5 CS򃼦DX^H^e?P4E9QN#>t5*,,я~#Nh`UUUqq\PXXXt2PSSEU+^}l0qУ1<0̂>HXNVSI&p~1fo =oG?]AI1GFwy0̓Ƃ_s5[4=շ9#̷nbS A#*p(@e1`Z mfwق~wA3 [u]f췷PJuMt0.?/„zk1szcԒzɟnG KaB,pB҂`kj& +v粃ތ~wF:O߶Gq5J$z |,lh я~=~"{83,uԜ rss--0Ģ[j{`hutId@kf @xݢ :2 MA?я~A=|-\ 5MquР`FMMm~}2'#xv`=FŠ~`%MX*.c;G$Xp"Ԭ0tG?DJR !>G)}>u(3㲷Y-p`gr.:swFM]cFĢjVG?wNG%I }0`@^^^j0rUWmڼi7^v7>#ڷMT3FꀓD.z IDATK]j`T d/ vE- ~wA1$^촴4Q{y<ߟ+I $ PFV"{HW=ޒ~y+c&MhJ9ԭKbcu7'E+G[Epr=z,qa2L+reL~aSsn=Вhn&Wהv]9,H. 8Qb(2 rG?я~_ښ=ғGDǽrᶶiiNbG.x X^0M D٧΀Bx:5 t;Zq +E?я~ŏ= ^kr\szc˟\ChUm},$H>T1!>Hs& u2T0P8kЏ~#NܹKQٿc?ZKfwPj9hbQ;PSO2+jV$я~#N4|͢G!,aWƊxIISVY0a\@5QMiE/ 80Џ~./biAzS6GС&tbT5Z\TtR(`Ġ%Nxo1༢ޝQp@ wOI5%ћ*G{E>eo߾2 BO?tǎ?X/uqJ)ȁ d97PSbɚ7"G[FihP4E4G?]//#h5͸nH$zy<Dze9DΉ9NAS"ëD_~ƈdΆ2=rJ5}KG 8>AzS#haaPJjkk-~R4rgYanM1B8A{ΚQjO*(y iQ&n2Hsя~%~#\XVQdI}?!SSR>ETGiJ`4Qtv'ayZTc7ON+~'+","S W#ͺE?я~ʏ^q_aB=UТ/X@֬TWë:&ZGsD.蝝w?/ÈX8G? E%{O!=sTkO1V^(?p Rj'a5$}HvPG?я3Aas=FmCnWq"~Ʌ㲆-~&u OBuя~n#>}n6팼U}dw}ؑA|Ѫw9yb{]2$,_q՗dyצ//Zv+G17iؑ'WupcgG?ROJrvY, GǠ~Uء >wҍ-7uYe+Jõ^^bEEQԪ_gIt`E05)6az^,*RyAE?p2ݰRG?я~aiA\RvK`p#yD_`LHnR6eJ>0b aEAN Zt5&2:G?]_3ADK"iPbU(C-U*KIiw:K[Jrя~L?ODA\bE 8 @m#,OM:@ 5ӔHĤYQ(I`dP$G1jG?я~9'RhJDM-̉?xInIBmP]z䥮FM=$GG?я~Ï {pGix +:VLTx<.>%rXNꗑl򂮩 -΋^Aя~./041Y7ZSը_dMC,re[V{4D98¤ 7j7{dЏ~.a1>_[h0 !iecQCZ oQ0` CHbA˶dC,D-X5ˢ,/~w'q{i|*; O|zLU 5*-psLPSsE_oQ p)G?я~q sŻڞ("ZA%?]ZYq!l(y>rFCSЏ~P;_q eh;#foaE?&M6ڎG@x=2tY8jV~w "HOrAW۬x8_3 1l3'ʘq'j5h>jK,jIfя~]~0qnj .=ϿAg'w2]Ηh=^U/VMZ# Џ~n# PFV"{HW=ޒ~y+c&MhJ9ԭKbcu7'E+G[EGhGv @xR4X7Ox +kJ$yW Ze1wn9~GK/mMA$4IH`OW@uj avZ[*K;@V~wJ#{Aw|r բUp D_R@( y=+&4u2T0P8kЏ~#\RҔpI 9AX>ьb( .Ģv@7 jWլH> G?G4|q`yʂ@l_vNhJ;/zYN 膁~wIKғ}`RD0bђlh 'H7 p^Q(C8ջҔz >YЏ~nw\pD]XFG#7=ʤ2PNX>DAS2y_L8$Mя~=~"&GPoc @ ћYBvi1dMƣV#FX44(Eя~A܃k';EMPjVc}A! #ra:J,)]Zh.я~.a#hGSm] ϹAzcqE" C)Q=,,}D`0lX1fo =oG?]b" .I]#㑶چ003ȇ'q_ @x`0Uax-G?я~9GpjIO#ǁ !Nс E8sli d 5uZsAioF?я~ďk #H<GZXТm([$ XFв- 7Q!,&52uͲ(ˋ0 G?]5aI^._4q<$SUBJ{K,S:6\yx[c#H> |,lh я~=~+#{\.,j1'VwPO@jVpg-@A^#yG{A܂+zoLj[Xij+@S% x>+`NG?]~=ғGg69 C ̉2f܉25u;ZY~wL1#KpEo|#Bu]LhFu5Zw0*2y{K{UxS碖GEŮG-Թ V=?˫19Q/t尮RխK(5jӴ~wtp׎ ';%)%,'IDcUpE"XhU?_´8 8z<ϰP=Q${Epr7Џ~.jqi[U5~VՁ >Ϸ-̫:[H Rh-/rGof ڥŘ5-nD2XayРhiF?я~Ǐ#a~?le pStДa`=*11"sրe9K_%я~1viիW_t~. O|]^#{WsyC??ۊg"#hGSm H>v2Y6J IBYA9/Wc!-~;MiyNC?я~w?nٲe? M4~Mbj|}K?tDFEawJծ=ÊW"OxW*EX޹5D1f "/Fu5~wy٬Ǝ7˯8A4a+3/X@֬TWë:&ZGsD.蝝w?/ÈX8G? _#gyfYOߞ:+baZ`A-L3v9ܵ+lUSH )5y> D(GQ=)&-~~o6>=+V1}{e/r N%~nރ'O8i^#x%jIH],D02 &r,5<uG?я~(=k 5t Xg6oY3gN^SCK/8~GQ9?׍KXQ2A;rN8`ק 8G?я~7;R ( MX_P5y]wI&c/{?U{ Dp*<";o+ !7tcү]n@" )  _7x_oO7<vAI\yMM쀁L,10!t4M$‹.:U=88߃>p{#NۿÿC-^uU?(j{5-w߽׏|OUo~߿|ֶq?ugeege+**_ r{啕?tG}5ƆګGuӲK$5y%%~+1B~ |饗6i̘K>0wܸ#F\re&MׯnnUW]qF̛;o̙1c.yo} /袋Fn_k~ӧW_VnZ+2/-v68ww9`@?}^]ȟc捿V|^zqy1 cǎߟ3k]>ςǞ~^޽,o^9rĈkׯG9ALѿr[6o^fQlJjʕW]ݧO#M<~b_-ߏ~ûf*$IHd] /-} _{50horq,@CM{+).PRXLO {}ݷ OVi+Fs ˁ$e qUW_cv}9jw"4q6ߎa|xdY7wM'_{{<%w|v?}ǪKKKTНwޙ&L{ijjx~1IDAT?g4cY64o˾/I"D",ⴴw 4)Y֑gͼ{P(O˖ϛ,! n07ysطoߜ|~c"x*ٸaøq4Ȳ,4dZq\q  Dzĉ7^b"bf}ӧcPB% Լ{z\2A;t 0 y,Z~M7tCʣ1σ0d@ǫ1\s5鱊̜y, UU;H)))@eYn[osɘ+a]vEc jmm k LKE~-~1o͟?7}߿u5V,_by}eg3< `C8ꫯ7.555;+c9mdvb?_zowW^uM,ɞ2yW^qСs544 0daO=?g,`Μ3 3d&Lʫ \[>WM8eye͞= DTg?qit?Ϸesr G̟%N@{W֯_?sX tD wBy_n׏Oz!Gҗ/kG˲˾ٻwv{IǿX/ҏ0˯~ rj{j\>?Zgck~},n/xoH혋Gx־%g?ŏ4&=Uni]„i>#+K'Mv;=' 9rXDK._pʿA+:6.,(|ŗ=!-j6$YXPt|Ao~DdGNl;ZDt[[[w/ ;;9tb& 9&EU+WGO7MB.&`N д{W<``\QN"η8iE1 r. --8~ܸ**_0|ɧAw 5O-y옝noo?߻ϑuN QBkS'Mxj "ӰG9sAa"U?@ɡx@Mu>!].5iO\5|#E9 'N4я?^qʯ -g񓏉/)(.UC$%gU×_{-saA΍D3V\rРA=v:N'V$t ?|(_Vv9ۚ)6~mDl{(DWT\髆 x0 J"9>;S~gԣ2eUnZ:|OY !~hDЫWzCcq{3:4 ȹ,={2r14-苄Z2ՁCi)YYA`ҵgaAߺʫhCU\// ֞CntA7 8Sob޽]Uӎ*/o?hh<ΎaXkB6ٴsϺ_Kɗ^!  w:K\AA`p:AA  Yi}2  q(" u'޽toO_]<伢⁦i`"  UUw[jMݾbu}w]xOWUAAA%?/%M Oy"H#  قE顃YCQqÇOt<#  لigSj}յX3Mt7<#  5egk5^ K AA\uDǍ߻O̬#Fͻ7mt\E/ܶ~ٱiӦ[V\2 7/czW--=uŕWRe{ɿC?>2nuӦ}issVZ?1>] %xn#W^|1c?~Jg-[_|˖-;iƽ{utMw7_ۻר&<7rx*D$RK]AyCPVς@KgWZ[Z`UC_-.>qd}E l)K+;a͝{gϽ3wn߾&=5GIdo<~ yyZ- ?F_O7МOLJ|o~^~>wuu+(,!~\0щ朖!B擧-4ݻufMnnF{=޵u㒓+B LLYYmhh[Ox}߾}ǐcgD"!&I===Mj1j.wbs\## 6?~!DbJJ Lp8Ch!644tttƾ@ ]6''GWjrƍs6#]̹qư[e8q  RvTT|-#ĉĤsȏL&̯~iHH׮kooߔKռ7ZZN\*,(蘛ti¢j>߾+^.YN Z_^vM{[+sp]</3+Wj9ܰƨ]'\\\q Fx>F{ޱ ?cSSBhllttt޶m۰aLLL rssg[}}}[oק}4GGFFn=B#m{yΛ2ihhjΫ&gO8̌8t{ekV}l`!3lm }B||}}=BԴk]*-- _ﯧ7{Ą\[кk.j9.S[D"O&ƪ񌟟khh˗LfaaattT* rGv\> IU^PP%Ik֬))))..Zjj1:K#GL& BewaP|ήԖln{>3$v2Ewuv`T(D"O+'N ݝ"(BD-[D"aݵ'Ojdԩn^_ԯP(i4"?<< ?11iI^xfB||eeeuuL&n^~a]̺N&(Ic.].,2e˖:u̙3bxdɒ%]vghyqqᅬ \:c aPhYX̌مɫVj)6&,/fi"N.OfiOǎfVU3>x@a ch!n߱syԔ՟|~ zx% 0nX/Pf&VGǻ ZBul0L>zwϠE|֦}5WWKuvvVpH@+Wzy-k܊--ˢt:gWT'َ>.ɦ˗Z'$w}J2L6ʕ+IIIx(+++00Gh0pK3c媕ˌDD}CBOOO|G^lUUU/^ں3B]]W.aGh0>o\FKb^Cؖ׏/cV2rDxpHG_5BxWs``-?](G zY]$ֶ <Tr8Xu\hANp ̛.㔞\>0nA0/ hwEӵ'jW D ZLŧ/̍̽{L,07`y.t>u1l4D+\8oE2^:QV;4 ƍ &̝jbj^_w7كBk~QUVְK>!$ DCV B*Juğ;} +a|J-#0oCz $t(WIENDB`tiled-1.0.3/docs/manual/images/terraintool/08-drawing-dirt.png000066400000000000000000003550311315121121300241530ustar00rootroot00000000000000PNG  IHDRXf pHYs  tIME &m/ IDATxwxUƟiےlzBzB轃"Mz)"El, , z!RB*)6|Ll* !$w \3gs= վ}{@AA^>>fyOOO///q$fnݺ9sCm۶uɓ'O<+h˗/-y/˲3f<{lVVK/4s̏?2m4VEtǎQ \E :thtqqر/\pԩFhѢgϞǭ_emCɕ"";<1qg͚Ue0KV!Zj>}̙3aaajӦ͍7l |2Mӯ򊟟!d޽͚5j/_.`J限vZlРAfrrrZmFFƢEDQ|BCCl`-A/^===#""6oihh(`\\!$''bccJR>R;v_~pvvv>+E4#8m4/N\r:l6B(Rǧ Vc]$ȷD>|z2,pqq.z 888ܾ};--&U¦ݽ{xۻSN NNN 6߮_9~&M؞5kRSSxMQԄ T*o֪UlٲL9VRAȣlSmҥf޳,^XT>1.AArYroYV[n>}uPT]WgooW&%%\^_ 2nݺ͚5ȸ}M&7|3nܸ߽͛{̙3mڴ).%%^zթSǎxbzzuҥgb W gW\J5kfiR۷/bAA:a6iAAlFAA#  DAA"  hAA4  H1;؁ف  R@zAAA PAA  "M  /(X#   j9λ3\=z5QVY3s ,sppONJ'U-y?'Ay>Fp5˰#ꄄ̞5dRzxE%9\|BWWWN6 X|yf%I j;@= Z)PΙSZCAhаg˗<߿ ǟ؆뫯cq hOg7tsI8na! aJ8axaذ ;vK.r$I׭.\O^7n„ѳWNW o+ڵk\q&s[j]^s޽20##óƲe˻v}e>,G" OZoѲgݧOfl6AP| ֻpѿD޽;8щ'>3燥KoߺRo/}9^Μ>u)\G>tÇ5kQ[ رCDqɹDر;?F6jutY|I3z̅n{.]^dwzXE#kDݍܼeV^  ||:v[/SpG%n\\\vCYk|DA^Au_EXSB{83JӬ޷W=mܺuz޺BB9ݷOU믏8~boo߿uBAشykV/L矓BA 6\^)ydfwW1+AS">BCB yꤡz+2%%=ACeLlsro% }pРnM4=< ݺu{۲Hx"H[YYDXutrܶm[ $I=(.uQToRF3eK/\|iƻZߐ4isεk׍18?s;{&m;;;9 Ezڱ}ݻ#F ;u^<7RmU>@ ,wF;u<""*: ZE /.'O?ӧoX@ ~M*Roo׮^v]wlٲ%K8{C IH@⋣GsčEHLKII~,]:`_½ݻO20 U_~[7ߛ1cU5jxyӣϫ}ْ$)J_?_??J%RVffW{{zx׺`A(m$5 i:==}ڵ;ǟ~?Gewz/>KTTѣGfRpsuG*:uB|2ʈ#.P_)چU24EcΟ;?gKGǎ=ZV\cc"jM.]Ο0z\sG-[]裏W_ݪu띻vOz5k.\ ?S^XVP̙3aF7kڴiӦڵ_}ҥfEPxzXjajxzN6s%7{ێ>>i^ oiڥqA믿jHcvTF#0f'TeN2f'ww.8zTau`َ  Hi۟s@@r%f"R 0 c3  _3IQ*=G IDATɑwGPE3ы7ܻu;׽QXР(izΎei*ĩS0ѦM#(Ib1e8h֥c=;wh juɣFDQܸ.'->f B~gΜJOK/Ha\\\hx+W.)J ۢeKa4F$h`@wBC((fF@ADQJ1ʟܼnb/-%>]]UNnR?t{P,yd^@Ѻe(^ty/뱲|`֨VD`UZu @VLElț?Au-@&B~@[uyO~AEI" /B}s#>Qgz{sceeesZn]T嵝( CffVcw(M XZvGGGZͲl M{v>Ǭޮ*VA$vpF@x"ltg3pv,Er?~Kri2dq rV" 7>>WFpohѲ}N(J(I$IHf9w]$I:읻O(̙_-^|9CBBޞСC9!!#F ^:7uVZo:::BY&i&6FZ9YWpG}G}ԯdInV#|Hk7$]歉o?if]_W_Z7m4ϟ;שS玝:^~#;;pVZ@DDgDEE,Ӷm/-{FZ귕gxw֦?hZ} fϚձS׮Y3{,u0Fpʳhz4PE3=h 5E_-.rŖ&] R}B8N!2`3]'o~ݲ}f8I(Μ,X9-7T`j5 I]1$VF}G}G*" 7xd޹s'>ްa}ƶFyf6n:e =z433o߾nj.t}RD6ܺYxLvA l[X5RYV-f^,FWTr7Bup txsM3S%lA}G}G_2W/]HH\+ (OԴ4 d#55U|mknйs砠={3i?}su3g6o䪾3v7|+ 2DRmټ7y=Ha,f3`h2[#X&}qipjY$J7SX OAZ-fJ>S)_uj8||zzZb/ LO%''zAQSRR\\s<=jxz&%%U ?$);;l(8.!!fO@}?ӧԩS{߾>\0UFb Q;$Q,F_gb3SYKZ$2$*;T7($oht/] vv@}G}G_ .z{xָx,[)cԩif͚Ym.bN͘蘘= ׭{e?R]޹s (__6OQ`\R9|ֆ _?Lë/A @kEW5?M4E3ŽVh@`JRk&Mvg(@0ܭ֞._􋤆w-^$eFMbj(Zqpuuk̚Ǭ[o>aaaVJNN~W #3nݺ*J~*8~/Wn&M5j[ݻwmCƎ]Ϟ='75kZm~}KH[Ahz|Ţ\#hSfM&l&KK)@0/257U*-쁈 4 oK\!F)_>>Wa}[}DA~ڞXI+9ztmŋǟ Y`.o7o7(0p rk7_ɧ uz'243iDf(`MW^ݸq۶@ڵ7jtՁsGeڽۻd#>ӂ)JJO`oW֖_>[T곳G04T({vR'I&7P4mmtBhV7mip=K9/J@ 8^cv*>>W >tyC )SߠAS۴mkoo_Xnبe>-ehΔ* IBдdɦ.w!!ͪNa- Yie8r@}G}G*SQQQ;w<| :Тesg:tLUjuH)U@Ӱn>^@s RV h6fgE3'oki"]3wlڽt1C-JĐP/G}G}ԯ"qGC<iݦM2Ţ( (JR 4FbX,TO,tvP1g6"F_7F!j*()P@!/K 4GpBQQQP>zPi8;+ku/ܕSp`4c=;wif}S0h5@gE)5 OpEsc6oPwۢaVҀHp;FUD5GlF*4\|饗 qdw#LLGp Q$朼@%QhoI>.^d >>~UѷP T;f֦㛮+fVR-? YrnE'**{gNҺ4`;=; ͰK`oGMPs@>>~G P ́-7nCQH(iK8Dz {''zMU4zH@} 0t̹nEY1Z IL75!&{Nۦ k'#=) ħװ g5 YbTv UG}G}ԯ"k/UP;U 6,`aB@S)i{@h'6gG/l`E}\9H(f5Rh]BlJVwI,FVA00Bk24 ?Xd1$I^V>>~U{} H !$2@T40KzH8X9;h&MhV'ÄM%\j9BMސƛsy=jL &7SR-Q  V8zpJ^ehQQQWS\pRf#Xͷ)$R܉OTbjIZ{]3MFmM̈́SpA`5FQ/I(QʓW]@+Ebl^E1_sN/]>>~Яcqmmf{]'MI} ҴʳGxcn=_ZeslgD&!miegwp Ky FNYc+lZrNd g-zH_nH"/o64P 'AxF,&#Ih#Bmon6dZLA.e Yh]|>>W} l.)0߿2gJ]ȬM67ӏg1Ȓ;Nx}b=ey|VZD˂T>V3ۥEwkVyKEQ08@* WL7O΃yGo7[9ޠHb6޺'wFQ5.*9K^zh {g_>7>>~ү>%T[ӝ9sHR%Omjd]8aP Ii_\(ErM}E)Txm+`ՠrik3w yz'  *{:6DIxcUgNHbnO`N|C$NcQQ,DFڵkgRF|S8>S"8 oT۸Ox&i.JML}Ͽ}[~+&-@&; Qu?Ml@l?5ą#XV@V':&vPktP9T[3nѯ /E'$$ 2d˖-~)|XSd!D#xQQ% D';E@'ݺz >yh7")͘OJ!00#;y8p >|Kм;i3_‰!n>L2.JR3 yNp)zv1 C MSiwFW^ "QHF .g5ʱJrKZN>éyr]w$'پc} #Gl>Ǭޮ*V)U$D@0*-'IH6F8;"%oI5M,NTj@+v>?>H) W>~c.Xۆu?|7+Vt3aj%H̭{R]x5J7WhI'{n[297ъ2LixۿIiN_NZ ޠk/$OLq#@gi.~8l)Tã:=9h͕S@~ H/nb&#stKkis;@`b@4E'gzCvF(FnKӜɁ72hõ_o_ix~OStPIJ}_@<~xe7 O*t^-|c7X̭u TNT 8Xz$, iΟX&A2-6\gl1e x[]+%@}Ωs )+MJ^Z} s, ~R0rJ{bF}G}G*_}%{)">xpXP .'!%qﰢ}CQ@MKS"!҆T#X{XV0Y`O@`iiN @R% &G4I"@qdbAnI5fVi X9Wu8 W>" ;^o߾{JcA U|F pT>sP9&!2)|\5߼--&Z!͂(atc?w;iVNTB%ΜQn׳Oĵ#bNU+ H# حm?zie0戼D(f" ϑ,F=j0*ZMVHq*J"FHaхtV9)hGQV? & //xYφcԅeM Nᴼ~=чdܶq%HxBbu,ӃGF%!-xS"DуEڴiC4EEK.;Gq,ǩT'O |i wHKOQ~bk@s棽Gz8|nAA/M|,D*7=X#L&ިOa5.! Xulrf{' IDATT -fJ!S)@sO[~@7W>꧿N,r*'߈. \*9 ?/'=[lEe[yzԭ{O'Շ#}ZR He,bۤ+wB"wفcȀSS6r'fQ (3g1NaZ$2$*;T7HeU9{~~IΑiGSFOq[88(A'nݚiAӲ( j҆;jw>u•{˵λvs hq[w'N?}NĞ]%$B+4 ZxQPj5`L@ u"{ۺTl?S<_)x~E̮v)@;e߱o}l"?r=uFr:&-I BuP(o6%e3^ZJiX ~q FIoVRiAeD*H.|!HfXW>_58A_#ت5[!H`Uݴ~^Lܕ+WYVӰ,h4ɓ'mkIR;%M@3M[$`UM[n՗D>v1;Q?~ F[+Fpю _l5@% jZ-IR S'|iwQ狌qL. ^rKy3e %H`P34-Yi˝*)czHjSX&CCfNP˩*5_x~ Jo߲vK~G #0 PV9YI)Jy0lf4N޶@fnt1C-JĐP/G֗8dxA|N#s5M;-fZ]A1xxx曈H9;A<05ZwQ;XV4GLR}\-y^Z9ň_}"PV?}Z2Ѕ[uׯ }bhLEkm۷gWD,FŨF祱w >J( 5$9-K57VF}/~%Ű}?m:{ۡڿkJe0'gsg^vٞaG' XS^J9:ݪ<f9G-ܣRfA0r9_LҀC4 l@D??iY?+$I-.wvCGw1X2J̻l-b AN@z) `C_~ҦB}/3=P/T]#H1fyEn/p )e8ħyfF^' xco64 lNqmVD,+UMFLy?{v@0 k cQpJ \ќŘ3j|]hU4ck^On ԯ,}O5GGA'eGC!r3INa1̪ĩZH<˲<ٵjtBZ N;9,& G +So5Gj8*nɒs+:ɐPW;sj']i܏ [xv5/~'@[]A#(#b1f phYJ"$y ,`5GE} G}/>/~eT ymᕒ;oMTQ4Mi$ 8;(m$%­ZE,DD`K `1(osJF_Yx:uɱRK<,! f^Z&$Ѫ(4G;ʥ?:7+U g9VwI,FVA00Bk>4 i$gJ ~/e~e`fV5cGwݳi˦ۑ-/_7_vy $#J`12s<>mii!!*յ֟VY+t]uuueֵuֻ-Q0%IRj[HHHȅd.8!B q+9sSg_~_xPQ}EUl բlƦOwƢ*!t0ǿaqSkE#KDbLGlCRJ )j=}2{^O2<|_nl?}s}/~K}_ਫ}PӵU9I'LP`i SIj@(^ r|APʜ^fc`f5Y ?|??^_'OMkhOܼ@gwI?Ko,˶m4ymf?'nAJJJ\smgױkf:}} +JBN߰6߶Զg]hazkxhlazOkذix6Td/᛿nذ>6]j[|/h?t'vZP~O\w"ꆇl}=]Ily {-tpªc9zݚX>7|>*Ԏ-myJ4b2f>o| ,`L-6"]^vg6 βj()e:V/#Ժ2I89 |Ų/ D38uDžo sH],Pjj ^Il@F__(xc pI^me]LD/ @bf Lo3=e?tF<S8Sx'f l7d %"$lop 6t~__7;')E^`3*lKw9ɎY2\ïg.킯hcԶM#>d$ =1f1<l2 v}u];W/=@5ӥkEas`0LZ_? i[ qv+`$ciAA y]DIN ߙ$;`f fL-9>;qIJMGLIQQ`:'8Sh+,1p`jz"J}~<=yCîw>-((0  y^Eg%I3gؘ {arÇn/3"s_P 拲ٕqHƆMDtЈGɘ0-6 d4ˣ,E JP}%*eY6'IR=1Fqu8ՓTOgDTOD) t~__YU9%Ks̍b$ɲ,I e (JVV_~o<x̯Ǒ̢HF2ƋRCDζQFAZYr (K2/6;6lU=`Ls(Eo1zA@z Dtfl<>fi/2LRSY`Q${C3zKiiy++o95<W__v (iJ466mUU={O޲aC=۶mf0-j% ȡaRP D 3=dg{ 7zS"C]\g3 I8SZ ^|)nf.aFc}}=?Wxt)uc\u`ʺ4MuM$I$O|oy.05Qb#}QAPıÒkM$'S '{R v}bFro(qU0$ĺY`q0AԬIJJ!~}={js9@)Mj]/ B$Iz}?BNE T+]LxQ H|I'T/S04MԢ>nx+E27Jj$"٦nY%DԠf B̔*]9K ԤFI~}={Jynn[g?m~޺6OeI$Y%IeKF`>Q$̤Z /)T&O3 /*W=Dt*/JDt%Q zd_FyQN0c(‚e$A/p!B2_O$G9^&ۚFx rv;I#1#/4}t}ъ<S6G_Z6[wo_g/BP(>${9r0r-C?fj4|͟>z7cO.jxԎ]fSt#"ʻ52Qe?h$䨤O!(fb6pq_$8Mg>1twZ8N.054 /y?3cc;" ~Ge. XoAx@֟JD@cDMKAxXxjQgcLJ_7^<}}=`ۗ\Ts..li3eo(ުaONzUó m; Zl/Jrd]s;" YE'!"\Є(v4 . ^ѦMݟn6c}kmtnmV__\Xpʼngf|po>3qDak86%?<smmmmmm+V˭s۶mN766嶵UVVUŋ.0n\͌x򯾾QXߐB Q J}< ķ)"68LuQ6G>):#WxWw|^yn;V3~wQZ17o ?6:,$?\Qȱޱc͊9}BŇm4<G]EF__xwCODoOex=y:UWafF2h^S45&%f4{ho<LP;=3?6ww۶ʪ+VcN@ee[:>vǎ#'vv̔oX̧fz8ۙlg}C<[b[\s4-+,4W謴i Wl: ޼GZkveEvI?W :4/ ÏL{p 睆ᆵt>7~iٖӕ+~澛=[`K]fj IDATŁ_́&P#i$E e3MYږ>;e*accMG~ UNlό?t[}wȭr ,#XI i39oW1f3#. puY7bÏ'h7W/GiV^sQ2pB(2PVg 'I^sS#K*BD2zK$ɓg'%D,(NLIFRT_p 32sjI*#CQNՕhl?iJ!;΋וϧQ*[ny !|gg'!\NN镥KhNN8xኊ Ib*1y9oXxW7i3\SW`,Rr Bij@EHK]/Y!#r FMm"Jhʟǭ.W/=wU\dO`;.?Abf _z>@'OWȕȑ )[ (^ds'Y:-{|Ӕwn4AxѢ*iwǤnmmsPUn}} 4 @@u |{feYY];o*566[83m /Rlϖ 0f4b:3rDZzGx|XM5呖>-i _ؽ7vޚڹ_0r vrluYR'wQi- Z! EQ&ǼϏ?_wj#W 1^8QC1,9-jSDϴaؠqquU F l_ŋut|[[[UU=mmmU~r?3c~O]^7^MDl `jqj$mfb3̢vyeQmc7E9E:故- =O6>ƫڽ]M%9mۻ_ѺǺzoZ^0< )./Rxy|Qn6GOM 3/8O'3zKV {tu3D :Hj3E -6%r6Yܗ1CK($١2+tgu2v==˗_/N8Ա#|FpY%Dpֈ00qYg;\V`r#ͽkVUgtXrU7l:V{mpMv4fѝ{j\>=ǜY d.| 㣖mnxeލٓ'ohxRS#菧lCOi$cN˝HDٯ.IJș/&rؠǧ?Sx{,8Jdܡdgd-"txZ]x>337S=y|8^f65TO&9T$>IQY|+!]2t]Tʅfrlgӱpu .]5oc ED~dK'ڿ~M5nrm'ɗڂ 3-,ӯǿ|ӕ+%#rNvLh|;uaVj&rŜy' hbfL!˟mRޑmT/8Enrn"Aޙw&'5L%5X&z#SzYiOR+-n Wҝ\qBdOl{M\kB('v ٌ7*߽?Uf.' puYݲ"BHKE:kd1-jLeϗϻzA۶cֹ틛u_0⌙`8Sz\/X":H|e>bT9NQ'2v髆]S]=;Y)]CO]UUSJ9ݧ"?3SW/Oy')ԊZ¶Ξ>jjԌ8)$kW5lX_Qjxi ncmOm}( 6v6.Ⱦ aC@־+7wnPYYа{Sq㦆yyy~+,<ʪU6}yŊVlmmssO=msf:kkGΝecE[ϟϪb l uÆ&ύ6P ?|@M;2O/~9W7<fw6[y0|l~]si>)Kd֖G[1׆\~M-=<ŗ`nfGZzܴ+\]^8?\]۾kf~OmnÙ}}=WT}=yBĭ^i/α$co?w K?ذ6l[7?oȮcڱ-O)_1TL|5^e̝Fk_ԬYB-%ET|LgJC;߶PqN"UW_,v)z7>0}a[[UVϽg}f3wkR{N6-_Lv5 A98 GVܳzY p\gL6\]s5uRfwfypuY;\3 Tu/,x}O#EIT ,<5W/=˽,~(<ϟfҴ}Yn(~=oOsǝw0!;t| S.жO]l>'az+0)~BO&HT\ 惈-8lJjGl6^/D$a!0s NKUjQ{{g_t9>2&13'Zd$􍘺7d_8ab}CqAV~Hb[o(^pkWU7 G%棕Y-'om}).9 N>}Ԡ;/B>|%+ArIa(pj0Bc6N@<J6<4_>BxY&Lf#97>tH2vd2Tg伖&_eT9c9^;/0d,ij/V>3oX.N qB(cz|(=AdqVꞧ't]K rʟr+\]> Wjoy9{1Fj>‘g_8Z$8w^'jˋ4tSfb?0>~}=e{)s `wv< dexlr m B>Pؒ%dҲsӋ#nOa$ciAA y]DIN ߙ$;`f fL-9>;&rjut[nu;(1g/>U%n\~"p넨/|ĔUs*ˊ3Q2-+܍ҰVڮc_^Y#ͽ#%˷puifޮ=ueՙ1F-1j艨Sx{)󌠓j# kDlp8py{n1vΡF^gD(e?'^)% 1#31ÉaZl$%3}T__-{w_*g%noyt;qA JORQE`r,$IՓQʠ'ƨ6Nղ#׆۹5k 7P& oyt{ 8ołPxܦM֬y-Pt`ڠ÷-";mTzIꉨyAR~}=e{ tpz%&,c6 i<SEȼyFłc~=lgFd>ZF' VKD`F̶cVY&eF8Y5s C. վ_wc,XA@4[^qo5keѝFR#jQI;:q!-˘[2!55ٟ=J7ɓ+F-C7=jvwں4dd lwusk">¢P((O޲aC=۶mf0-j% ȡaRP D Rl4KncvӦz^w;m۶VVVZգGOݶζrnt*nݶ@\w[/0nԡP~W2Yh۶mDPL,)DԂeMDtk+̢c jYd2ʬ:ݰ^xi0\]L tpt JOj:_zc{+=y:T>|Ee58i8ۖЎI̙#I,rhSb#|EI >qxɘ!m "8> w)T;y:4<66q;.]wLw?3S~|ka C R^,P =i$M$ l NGݡBD~MBPݛe۵Us"-}R /^1I#i @HhYZB36 LHz˟['O.аcCg?}򣟽zzYVE9K.է%Sx6 3{/|䝙?WDMpBh.$5@` dtJDBye^yCl / M˾[VV/+ .\3uwim@ݍE3^:5ԛO0a[P 7ɓ 01@_:˖`sf`>Q$̤Z /)T&O3 / gzNXIDxQkSZ"MκֶAagnvЭ,s憾g}fd_FyQN0c(‚e$A/p!B؊z|e"eQ#9N"-=SoŒ=/-+~H\{`^mTS; ?\@>`3 K2SGOљ_z>P}=y0#6be%gv&Q _w~{Nvv~~(3;f._$'2 =w8;)!]U ^$+^8rSM9pMs/w2kޤxvOڕ c=E_ _߉_V$'3R9Q(Gfcfz=y0#^{ ~c!; 2!'*+kJJJB$t`3m}<5@dy `pd H "G) \Z`ID$(JHN_U5wӦ[nq㦶緵༣Ӛ9LT9^s[56lό6+g%LI-z|X/Ȓejy8~P+7W/ϊ4wɾepev5w!O7-+r?^ymbt`I~V[l1OA-S/5^ӕiy^ol{????!_zk_Ŀ,XPi@eF2Ԛ//S d&pd;/ad2M=nƩ5u|]N?A\M6nqt)̹:3g~̢T;@8'|u0FcΆ".pf|?PE9ӯǿ<|OaL2{QAx$gggfeez^.c;#: Ne_M=n*e(Jήq{ᝓZt3kz5Cԑqڅ?33f'=P| RSv|8%4ATAtv%vHKofndu+ IDATO{7bcŶ}RNჀm3l=RΦc+ AT 1Fw5w\riy95~tÜu2zSfe3 ϽkyR{3_HGD29QM--)Jn9s_L VVU_wSVVVV6{|峟jkjgƷ{{ڻzUȲez2o!J\!bV6g.=5lXMљ H?ke |HQI B)D DCPĐZ`CGBqYֶMZ*+ݯ(N:0XQ9iȩ|w\XT/4ni;2Ke&֋^'֟JŹ*ٟ NF1Ae:h" Zximu7PS+/~6+õ [$5oӡ t4svX[; QYSiiUy䇫Kw%~ٟj581"l%ԎV|y錾Rb9zeNvnAJ͡lj|̊hh@S|CCCǎuլ9pqyy[7͌W^>ys_GJ:v2)ki^ ]tv;L7q2S1褕(D=TQ %9|U A$0:]~ڄmm޼O#Gڦ 63{#H H 0ވ(Ee2khS?'k;2 kVqRq[|%b~dO{Hp`nYww_}3gz^={siǹ|77sfNi[4ߍ4 +"` }~< LќX&5vuuITWW{n ] L%l3_v6kj>O~#|g']cQa7.'[(*ֆ_n LBOs`WBF[aFDt@RJ GTP ^On /Le 4 wy\ub@aZni J>.n^rv̘]w3uQAV%5(Hɟ-)*uD.ʦJW;=9b[3/5|vO瞃ckj R`umuݲn;5s#-=7Ք?b/V8#iU6$Qt3Pb3zƿT2M `ZeYV`2:7_DoWw. !HPWW944|Q`MMAvvumn!n ̹-s{K5o>;ys9jO?ӁO|uzbu4ȣ1#8<]AfF2h^S45&%fN,39(3S+ԎlO fN?ޜ]UUSySe;KESs>w;P/(nM+Lg;R-o(^OsK1LQфNX 8^R`P^ե;¢7*w oRK^wu/'IMc-+ܽzy1x9#]YD{CyNJ?1->?|] c&*ĶY^,8<)i,6L=;1FSŗ_S;w~ǥWWԹۿuwm ;:4F{kdQäݴYY겶Q7P~e,7~'~zz|w!ӯǿK*jmYeQ,,Ƙm3Y-:TLX. +suzzz_GFFWƣygז| Y@&?ɏ\VrۿzJh_ oȖ[_N$Xs6W-10?]Čz;$Q˫U A1܌&01%IAREh$WWΙ}F92DbB Tu:Dv 5l{2 N tS& o,nOl:\d2u^% )NCƒY,8%!^R#ͽ+!Yc&y{µd>'-gi/~?t#BR8Bj$_4=G֬+j/uGӭ (^d~ 28|L z<0 *"gNI*I`̜ AR}YT$Pي/4M9G9rR@bqj/J>3oXajjX'բ(Փi`Ye_ac Ny5uU{dUT{,jjQE(io߾x}@c\dOG󦉚ŏ47Ȟ/x8|ًx_I+9}wxU;L%7JQDWPqu][,*+(ڰeQ$ PT4$$!=7mʙf2nʥ}3{s9sϼ0Ż0b9 Yh@t,IKK=uuuC. @v%Iy>77õuz`mmÇsssEQd0kS/`V{&rp,(=#tC5MPvxyyyrrKn4 -Nl1{?'wVElZUU!(AEQ B N -VFb:Q'fI(-UfŅ0*dFj _棑|+W2z 9{lh~)nYÇ%{׋_Y ,I0)v BR( +q7-QXTQXT )E' y*E#Q|Z&fx$w?8ܦǟ;>?yl\ YzT/B,QH.&tD@aFc96/lsխk/lB%+~iV1ni)+vhϞ2bcc***v]QQ3`@Fў=UUUn;2_WWDzKJJjjjdw~iG HyUU%*Q 4j 0B>!DG 5UU%>TйΈ|K3 a! 1YU$y~X`i C7, @^' m)e9nڸ@wGEE744Hކ9oVVVljC >v4&&&**8*W tĈz =Hy/L^{]vgYpFfj/v?iic Ό a=NErkFp"`O MjUٴ wlSdOjmEg|X1CW:ozʸʣÔAyB˲ced$[EJ VO~biڶr{YEsZ3 2:cw5f/xi?p|OHH*+%E{wOtFc#F3XD+,qcS}I5M1j.=o1EQ^:e싺"zbࠁqpСٳg۷/99bXLⒺP1E,VkjjEEn3gpWWWs΁Ycccozhbbbh!vIzy>]y]߻YQe[ =o"d"cU<-(HD0qoj+u%KYUfJ_IJ.TKi1cFt5 hWYPuOǽ?' =@`B,!*""52 in„["/epwI@[vh2l]>it׻ S IFA'|/{jxa&.Ԝtzpf&Ua04~B8aY_J411e'>hҭy%KκKpݺ'X)(""|q#~5cH||i۷o4iRLLfmٲYx۾}u a_Y 2O 6rOY6==;Bal"Du c1˵}{EZ$$$@Y~`{hty#œF4>TRJQx_4isvm4T NoKuӸN~6/1GG23 t4X^1= ǜKNW)<`BF4EUT`AV0 x^0,rbbpc]Ǩw`fn׻O=llp|ǘ.$}WV/{w3 _A2op9RnN vE?1 b˱,G61 ȲZÇ{fʉ'>}uAmZXSSٳyٺpРA B<mO>ʪna/Р"pе;o{Xaa?ǥKnu=F޷Oe9n]oo* uu uu 8_$,CFT+^ZъmD`;IOU\!9P|=}/àG<Ϭk|:=?w@VYH_:چ2-ffɄa wM Xj)E ۇHO9{>|->FI)VNVtb\͕=bÉǡi, wۉ|$cvhndY ~|~ɓ&-^_'5$&&jlZxQQQ [6,11PӧN>u:ʿp}zׂFha3"Q?YiFrnq9j].'uYHio }ZZ発qW\Eyb Q+GւtQ{|zw=׼=>ͼhej h*0͝Jϊu6y= 5\Nl]:5Ԝ¢GX1a0$,X[uuK_Ko,fy=TɅKѿ)`D=ov a,fp,6nA v5z)IICjG|yСC{;sꄍo~̩c[g t9ǩ-w49qrnMʎA|h)NK34BDlR9T_f+JE&+F"Ado$&[OD`? \KEt_壩u@`ϯD 2J A&D|^`aX@|cGE$r'U0ତk9F)ZfF^oҘݵcǎo=3rhCSb46ME+'.."+[cxB3Kbh{Z%ؠnMgv5uOL"l߶m„e $|} Op̌I+^@ün.,̌۲\xl wb[[}⦛n8vdҔ1<-?0l¢rQWuz?!3䬑eeKDh֔/Akd"诘D_*i^mF aa {HT=`r moGĎe1M Ddv5781En"9h h B,b͌0q$і֥u%<\b;"M7(+Fii9i:rs2gʸ/5y^b<(_|!CTQ|ɅET ==sz?#qx[ 5x*U&'K\v;}䛌蹊oo/ԇ0%Ԥ׋36ɢ vWzdNP p:& 7#Qp3{ >Bmh De4uJ4[wxi[<6̘tnȘ(na>xo/^c=Ê>2}|BR8eDZQg A$$rrg/|(tX`>SHIV:VahrpVBCR&5DvETY_R:Un-~Bk=zdvk1R 1۟'^0:PnE!ێyɼhb9T˰&AiQh@/Q=(!u9hOuw9$ҥ>ٳu-;K5B 7whȝG(~JMIh1R' N`#~3gI<2yw;t M1vd̬8ռi]הӋHĝg5N1zo4ח#!B4[Zd&:H`EP`i@yey U+33&MʵXLǎio\ͼlZ83R)((0S.r9K/ Z"He(zB#bE BTu*M"( 4􅓤`I?>ǧ\o-26qު Q.?24mr'@}M9÷"7'gg[%d }/$$gE1'[Y.hlJ=͞#' X›Eu?q\2ٷ}AǬIS&n-,y4wm{wt<؜;!*ug LUl]c'=~Bg?$! ə!mݪ=[Ma14ױDV<-yXh2FHsb%Ow9jk91,p|ȧ[Pf( 7X/M󂋋KNa}_?We:1>+9a%sJn@,XPB+(4{M ˂As C,SXTYQ+Ѫ~#w~W?yl*%wQ1gC5F Wwtw0EVM tMQe{[L?~?!ӏz$$4m UUNh*.]fy&2 5xu cLb!kj|@uY< C,ors҉<B%&9@ycdF|Ў0(+f@0?wBRgOP`=zCsj&ɲ#h@zKIL-쩾E#ifDPh;%dB:q ~ d$Gmi6@8^geٍ ˖ݱr*e%%iii%%%҅;$sel[rUAdeeBSiv_#*`10nd$R K8OB9@a Ę.t0,>ǷpDa߇o׫$F[c w fʸi?T! "f +p8 >OUoh(Mx>C?wakF4W#=0&4DqmҺ )7U˾"˖ݱl*EZ:ԽD=RX8=~^^^AAA[p/v>~x_̦;oR7Xd JhDW'om4Hʅ§wU 9N;^z嵠`~{׋ޱcGA@ݳ\.j3j\gĮy36 1PzA,#{,aHbAq 8ẁܱEy[w, c{Fg4 SI>YY=?_~-[9 Kׁ/Mݥny^mW@80rc! D@`^hk {Nz l!`w;)p|Û(~Ϸ~`.E'>wvOC??p~ʫy_Տ}7_# bf1ciC?a( Ď6K RC_~'.0$dd2B(&:_~)9mL ^__BO ]`H1"H"˲,˚fMÍ hF+BQ70K^/W\Y*>]GrXs3,̬OM@oo6[YlBfb o{a0t|@Ka Bdd%F$Ҥ`:,#su? ;ħJw2c1覦?>5/>9~BB]?#vl=VV~'L(Jm jkZ!D}UL4U4qUyNpKMscl>ۆJ41!j | {Z%!"z6E0?Ȁ`?!٢^w_)7z9>YL rU_܋3+k{]+9௯YAtL4ҳX/eu ֶ,N`@q"%w3'Z0#,8¬}EP|yyyI)ac49]ahZ:V{hϷӧ -3ftLy )"FTJ80`>Ң!Ȋ AQ4x~% @ }U0 ʒ1:) wBfTUz\"IE?-K{#n |~|?!'kxlY?~R=~~nsϮ~.hswotTԙuv}sFy%#F o=gLrzpQ 暫7Ud8lm2_D3.=Št֠!ɊfygŅYdke D!c QM@аd i~Zrb퐞?ߔ̉X-ݯuǭS;}$U(=I){>H\^PeZ1+"DU@cZVYJ%T,ˀyB4 Ab2g #!($!&:B[fwf`Ĥ #<{gor:Ĥ=9HO#n'H&==u /c|5WGdgy77w~?⛞{vĜ6*QFXNW;񢢢3g/ YD0'_|i.liZws<kecp81GD",oby,"ځߙFÇKxE*Vʈ?o?xXߺ/68zX_v:8ʠغZGGjor١a$,z=EV%I,L EMbY߰ OVe< E,QT WU`_!,J*I*TU5uz$DAk~P%Ò90`~~;| ]+W.v?8\01zՋs_~Փxzޥl޼nd?0^w̸ ~|o\t;v?qgWv8̝ӯxwwM-9gҔkWx<ظ{ǏW/"##߹ S~85߃?z(xz3O<(\gVjf5j䈇|0))ZZ}v-MMIIy䑍%%%O zx;wSOW 22|N5L0Lƒ$|@vh%d|e. F֌ r՟|aˌ׭+NHmw,7nxk'O4ctj{=w۶oqǝ ty)ځ{W1Ϭ\ux׻{۶9nE\>u}tqJ^}54x{ソ>+0ExO$m6۳ϭ^|テ\.kk_ILL,--,{v5\=yw.e?jڀ8vq6y?hajĈaVW\~x ***3sɓ~m{8e9i(rt_^QUtvv=.>yd;TWf \kڼ8bq_l??`6JKˎ;V[[yGZ~¿Vzk++,,/>ӥK޵_JG?oDGtO"xƄtMV9Ld* &NMm5.q0:˸ lQzm Zhk3fDהMiMᣏLPKKllE{h{Ao oYq"-鱅 hD:y)3E,+<6u;5UdB<+yZ"AS34Llv9_yuǟ444`2u~j5ݺ訨55M_JiJrJuu^a anݍ&cܿlwmsd |V]x|>.™3gn-,5j 7Ԉ'NHJJzӳ'LիW?ÇKdÆ[.eN:q'PQYY\\l8\N(g>\zx*=1zM_ʫ\Զ¯n\??.?*}_׶+(V >&Aۯ?6F$'1WU",qVy @ӈʱQV7
!֓2YtktsC_~A: |v B@ym@9 Bp(A:o=AaI~hn3O۶mg >nj1 ӫoiC'>;OTU=g>Zו|?tgi~ʋf_d䔔 fͺ K4-9%eƌj`c+*=FU]'--ظXؙ,dÆ+W]C~>}覛ƛСC,^E~{ӭO 6*:z޽{zC3"޵ha3"Q?N4J{$wQr9eW=;*#MMaDWKO <ϧ;SxڴW_7HvCk~ljJxaVC ?/60nW>}㵵#Ea 8ek׮ݼeq㢣O1cUY=?n6IDQ;v? ;{f.t#xfdMLdNFf/Kyx{Fx<_|LKh<Xd0(M$ M[d K23W\{mU\RR}б 巿[l#3KqGj՛QQԠH4X* RKJ&& R􍬲K?bS`})w||>zX l8w6ۯul~|R|}Rwt_?oK;D=,ֱNvYkyg0!{UUMwm!;~ -aa_yg#x%Q믘+_7^s h+/ 7^WUSkx坍uOv++ox{~v[_~};?Ez|he澽@B?;#yۿӒiYYYSϟjd|-7駞2c?とk;#lXHG͍SZH *aiN @/=-/ga @h8Dx\91 X32J_>U[Mhkl2d1z`Ѣ Ƃ#JgOIzܾzRyhv^#*Qڷی;,׾[в#Bx$E/G"I[b#.b᰷Lo{9?X@hhSKLъe9QM 5O+éُjb'X` *B@"ɚʼnBzN- a]׆ыAZҸ̌`pz~Q |~"{wo9;v#`Qa~XکKΘyn=wa#vAo/pCš5Q>|d577O>c.]$Uڿ-k.EW7dXg/l4#5DIZ4k\9H g].{5-yJ}L㊋KEQxHIV@_XFD?|c1 utGf,AE3@ZZ_FCkhp\ Y;6}ʠ팙9֤AwcX-"nnCw&;:,# fUr &w]>#aE&;4UU1au!Dᎋ496<g`xGFnt&@M{ÚjLs?+sVJxxx3u}LE$7mdʕ=\pM7*dk8gRn|O- )_$q 17%A_霾"dFͷ5`X= Yd}]=/1B[vV2}Y5]zl9Jc'mVa^'${=sj`^IUTjB & *`0U @Ux^qhc@Xx$-DnpUU!UQuvwGXC]chYGzZQ׃t4{/gR~#>`?*wk\Wu)Ҵ^a,_|A笡E:$p}uk6B!`MF9Dn㒻%=Lr7׹N35&#znwZr j >\B)^/n4ظ*Fp}~ y^6sWoqӧ *9 <\)cRdYxޭDL-9R"̔ My\p6׉i*TgeC5U"ؒ-,+zrvbta:~?ڻ5?,\{X u̦s6d/I [SŹvCM} 􋅴](z~:L. .-?"&Jð6fZA; 2yr!ɸ*)O Ԍnz& 2&x@MCWEQb t}`o@K>|o eAvK&:)8byoisWOlu0G+޶mݭk>a2!Kaht;聞)~AMݩQP mmGj+!U%{:+.)(ኊ^]";; 1q-AOڧf$Z|6i|[dL IW'MH\늦d"_yY!)sE/Jnj@ҦM쪒Ewए—2j?9M.hINulRt<!^n: H {;:93"I扮ǁ@9yJq!0WS}@E__rݬ9 9d  I$92iE &H H08.gC38fpZUf ݀C ^V  SM2L0%IiF @_ot L_hП )">$zT3K> 8%4骋n|ǟ}Ĭ!٦V죢v"Tkϗ:7˦ 9 x&xnжq <aBU`pՈ/DY@$@Vbzڂ3l})]:MOK?bcw&bXqZ]zVVztS9 $ 3|DpΩsN v`Bp=OpbS0T-K2L8Cx1kF@ /J4up({'Zѩ~hkRs!Ґ ˄22CTU ‹ ǐKw Z%ql&YFe!K}H*v5kj9y nhI>jD/s+#UU =?k 90G\cꖖH$ٳgP'{ [As /e-3TcQ>d\;Z2kQlj8TL'yb̶i˓bҠ9&9~3/43g$N[nty:Q4_7x2G08D"@ۑx2FNju0LSSuILdJ5ڟ$ -,<LLaWRDv1ux2Ou]u]QLav+|"Ur@mm;e`~ⳔTЗ?$:}?L`C'4DPL_eu4s$Q_;DCW@dn,P#SC`ccc0`I(vhQkRкX$h ?`Yc?mUXTs*Û#8'pD]FD)ӬxysZ,w{yiƒ>S||8F LtƟb Gp0(i2/,;YR3I@M$ D e>d: Et:*珈BAPު͹cC1qx'9,uuN* cN=ߟ 嗷WL+\~|N 8(FV /.\SS0 =^`yr ٬z0-s3uUvpL'>ՕnX< HssHd9w;yKJ>Rf`8q0!Τl+¢͙=VwЦUK!8@KNi /HD6}1uf [ NTRjWrxށ5n?8Qh23LbGaX2P5p( m!"O[E^CC0G09t\XtZq9e/`zMvdZҮ5LZzV)v”Ξ]:>%M7n:Ab9c}58BZvܪ7zŚ9cR^KH/ Gϯ&iUQ.uv$Ɓ^=֟!bP2g {'DÃ65}?Y0{mO^|E.{/o5w{?+&$x^LȻ֛Uj e6-]uSВ̟= C+2᯵Ūf̘8%Iܵ+`Ϻ@؊~93D2)l4|^ s_қZ[z]6{+5?s^vx2;9CRN]Ig^Xff;Ԧ(.iJdr놮뙴B7oIe;$(' ?sbNoD%IISgG: A99[iDa)DV  8ʼ)yxӍEe$>uH쭔n"2|x!7*)eӘd?ir67+C ?.LcZ?<r+h(jk+)V)Ξ]R/8h[v2@Y3BDΩ?.Y\KDd?uY2ix Μ=/$qж0$ USRɾj&a誕HᑓĄBXdc_ŘOۧ`ט#)3?3X䟡XGo홗- Z@\.!koZ?̤$$Q)s8îZ矗  N3I^%⇙tKriN'Uӧ9jd+1+i 0#81`=ztƌ(g~晿z˷Ȍ(X!В))ArJhI^ FN @. G1԰5z)`Y@:5fs& ͈GB; ~md֜Ϟ%|$q!O7< m$)Odhar@ҍmm_Qk?ܻ T* 'hʙ[wlu]RRi4v7>eT&(Jei(Z,MEw;yݭ(Leݽݺ7 $72 s_K ?q<_@*@Mo=H&N|p_*@pq.J&:O1x~<wtvP/;vw<vp:8+(?Eb#.0P(m'M6#T=dkzkaw%MI ΀ AL&:8S)`X ldo(DaKF@gaI8|ECY U䒋X> vvuo%dGbRmMM5тnd/)>>pYJ&:HO1nG0LZ <߿i W\q9dx?UW\9gw|aW% [~'(9P*ؙUDl wU>\gM3}S%9^T3 ~Ε;] h5&Ag tҜz;LI20'#OJƥ}򆆉3˷d۳2gFgGlBOd.SM%@FtrtZ6h$dWi. )F_oZˏ?`  Si ?jB oLf 7]w,SI|]e%?Ʊ'_{5w 6jq5($۴iӘ dxA%ݺ~sgvL}+7:HGYwS&OWd!-_ ->QDt'PIY$zT֓xN3t-!Tgv^ /5'reWYTъBի#4f"SB"9kG*O3F>>)szz(-Z ^ ewI_|Պr$ ՕCAcw:EA|>)|X!}r p宑*el4\BnN[v1# pO?ްgNQ|Xg >;8СC+z'_o7;7W^Qyk;?r˗~kgÃ.=vf]x-[x晿_S}_8s>xer?f 1 ㈝;w;ȃ*¡/ƈ_r F4MskVZmۻ.p;vL2)>#h語@$E2Py]S8 =84SI!Q& J&ǀ5G]N=ua[#1gSz`֗r*oїud%%UIZz(~].w~Q"LZEK&UIE$>p\.#Vq?C,84 <ϑ% #zcmP(C?,!&:)UTx2Xn;᧍9 ~]:!zWtZᖭ/O1#L-uL&//L&u՗'_$Ć?dK\s -W]}[^\s7Ux7u߻+\ӴW_{iq~[R;*CO(AF4M0nƅ M^lU]ʌvt >Y_R\I*d%$Ȳ0n써_ LZ!҄2v:E2'*p,XKZO#!>Lndeu(4jeb!&nQ|N-iC_" ¿|,ˁ@zCj9MT ^t$馛nL&;w+,YdGKkkAg0Z3ad5wo~hE ҉L 95?A-* z%Z@7tCMeͫ7-c*15d];sj2 Ct 8@-ɗf3̎VPA+Q>"+%b r;tAԛ Y d 5Jޢ4j|)C}H>}Au:='[;w޽/[o6ׅQ̛7_;wl}'Qً̢Bg{]1aatGA>d"%;;csbY簻> Vv7)L3iESÇa 8m%Otfuݰq|gg a<ﰻ9#'λ7C~JJNT~eKKx4?S\7<xwTGlUU mG\qŕTLA#h&T*,tvX̨DQE!E6 7?;YFNӪ nk~4]i7G4]w)6 '`M*ߓٴj)l\`kZν(W;PSS3+íѦ@0X>sꪫlu"`' 19O<75nm7ܰrŃ-_Çp8?1 ?190n-wky~mrw2>&̎19|K.(re0u5kqx+nlM_ko=`kZE"&p? /"h 7>?0>V|_.++?@[{˛)Sf___ݬַߢ{-D\B듉<묳~Ys[ ?s˿E +SN]r[oҗԸz51 c~|G`(miJ~4Mr'I(r.ev8IAww2pvw'iWzV,j.??rL \hWvsO-aay} Çǝ8Kf)7 G]H(P у]S@w:'?C/Ⱥ֖ZJuu^-z1}"t_:/-FHɡ,cr^k9jV>jF z )zX=[r`}_ I:|Yp;*Ѵv#Cp@ECW ]5LwI޶ IDATSR^wR`#r;0tuD Zf%Eg-LXLjǫaںvX{^N[~?S=3Q n+,>ZZg```BpէH⊪+NAztvMID"SR 5e}0a)CMY1o5t?Tꮵ5g%K|DDf~R>c|OkU֌NIb,g?nB6I%?~&^w) F嗝S!] iMݩxj T=;RIm%^^dx?Oa0}J\q?i!IkF Z;~LNhƑ3QSŇ_=Q 3000!hGRkJ_TRqbL]'q%ޙwujPN_Me眙ղO BS#cW[ `= Od:j}Yjz`9eP~E? #J?zN>Dx|ݯnhZF֡$'tE5=էu;(- N*۲eQȰim|q5]A|43q'uJaj0P1hAr_sw%KG|RJ>[$fb41O{u6 ZS~/T<@pȲC'ގ,/CKsfDC#azyTSS91֟O0qn#n~l{wjSE9^)_(U!EćD!^J ,N!xneSIm~+|US,筯.@T/ܦ7ϭelODX*">;nB A8<NAPt/0U Ŭ2d( +X (x~r-pQ:/mOʲ}9Dw":(L4;Hel} , ]{yS.G?Ҩ"`w40|~f(1ndɉ"=`xouuSTTv#}zmC7dS]wb10i*(jkg.Z@r@'`'_1>4#8upN o 8S޺sI1;䚚jG?|ng]/4LhfA4eϑԴ [k HDDuS˭^p")"C>-VnF[kkkѨ( dKbN1C?77D"m{T֞:l-`_=Bkґ.H[~(LC/.0|Η A nꅺjy˞5>$v`D:ޤI<'v1?н0kk}@8 9Un`i:n+H?ْ.T)C-SϚ´Ж/>:cOltiv韙:?<%/Ϊl?p/|7.)]aK7g:CA {;3u?&3`Љ` ʨ*< `h)#qX~ ^h" uƲ@Gñ+IA$G&? ZMxkzo_'Yfb^%/>>%uC/_/.!'tF /i(ىʓ F(hHv*250oɬ %Z?"HU NNF[s j&1qˉb1ȸH:.#`3g'ު=Y6QJ 8.dl% `{tfK$Z5իf'/a0UnxC?"a *"Bz C7窽|XO{W^\}tFnǃe a'%?@Ug]/É~/@js.`誦m6imuն.me.NTRh]>ArsO% {DA]v틫ځX8@$ټu {?\OOwCCCwvN'-Fc7 g/X8}FϺg=c!gws.z$98[<^5L2{Ikg`0#3 ޞޟM40D:%%2/䴻 bY5Yk{W(9g`h[&Xv̘1qJkW4g`/gPd:rf_?l3~ƟpB ǎ#]]VwCc7FMzPwL:$[vEOVN7F^VrR=Yˎ @fC GIvE4ܼ\@dqayX_5?g?C  Ӷ_ߴiַ޿oa*a'1M%QVk݇bD c]?Ca[gydu`|9`0Dy}F˯ꌟ3~,?É ~NEaOoogG'q(E>|0MVMZCsog$yAKДe/Ho&O3{v~V]n)gڍM?OuCA|xQ- @SӖ8C/j'd# ۵+*Iq9oݺHCCpDKFr_k{K>_1~?420 AEQ$2/~߹K/tܹPYZN4f48 ]93L1 %hIuMA Jx~"㨀knn.5+dH$?ϗs0Нif1cۇ3~Ϻ^#<|+JoO5\=z ^l6[&Sq0t{5EH8ix# &5ƉdIx *@<fC8tݺuPHy洵WTThk E]0DlID744lJnQ7x!?'o♏ 4 m믿~&K$ݻoҤQWU= :H7]f)xahᦗg}J:){=$$cazSOb1b̥.m`{E"9 ZW 󓽆^Rg ?0>ر.λꪫn ~i ?4|ȑT*JNe3~>s~Μ9 {GMUUe aB، Ix핕|1r\h\eB۵n膚aq<5hCDdw2sj2 CtUQ@8nmFWlܞ={$I,Ab6 ?<}?g<_ K4ݷ@Ӫ 0UKMø?vgӪqMk#iUνgIkjj"+Wlv۷= UU;ji0Z.! а!%Whiy((' Er3zO_<4uhW8^cK>o/M`&yei?K_w`迟w9hZ5][?gcܳ' z0@${A;w$CDz뭏=Q~ӧO5M#;i|V3<`‚abF69{;`SgLrbmE7n\0U0{j 2t0LtG.f&to7f1QE ]%VP ;$GGue1o<Lu"+Vijк(j(M/9{_5? 53g_.t,:YE~W7|˜Nd2Ar:K>E~n4m?ӟ>j;묳Huȑݻw777W_}u]wYg~M7q^]kkkMFu]gK۷o?`ӦM@ ˖;4L:twA6 9.V-3T2iTa0݇bÍ]eo$>C`':}Gadv股? >밯,Cݻa$ghёVX_5ڍ3~??$ "q/._sַiZMM I-_pܹGݺu?>S_o|Gz뭮.gٲez͛76l7Q,pҤI[o뮻HD SNUUa0{+W,i߻e.$ਫdmnd'ab.9Nj˪Һ֖zZ'pVa'Ë/~7ヘ7?I's|,ꫯ*n喲u=۶m ^p]QQ`aB ?QUUQin/uwPh˛O?/.((4 7-C) 3;))yhwHwBp8P򅬮Oÿv~2Gʸ(q /|Ζ!аu8&2Hd(>3}F"3~?[gha{{zinp]n׷/Kvk[ii Q}l2T\Qu%)^ne4%eLI1Ԕq Ä 5i*R$t5"~E}{& c%֍C^j8qۇ3~> 300 5|E~s>O~s.‚eDQwI@@UUAvlݳgϙg1p7\60gȄ聞rhwv'/HhaEeٝwBpd=]ڥ3~Ɵ/9``` ?GpxpxI1VA&'9+>v @Q5hipPdݖ-BMk#zH$B[ZЙgr9v<7>D"V~C`ssJq%nQ`3~mq;6G!c#8Rݮ|+UٟtgfniطSr%dt:-N]28e[ehcΌajCr:/0?A82cTRϨ?g H1U À+طHz_7 ^6 e_rWHv'x2uUUUtLQB; U{TᆆP׿3Z;?gG 640NJ8<NAPt/0U ŬsU˓NpD'$c'$ʞifTh?)sPh#cZ$)±տ3j~d3~z:fK>[O^> Ox+ϛ])~*CWeXǸ0É(aM43dAה=GR*No%f,Ʈ moyZ7ܚK˞'r(J*?.ml\`h6@&>s<]eHPc[}޷fXOr[>jy)'i8~m/Zh;_Evo:xt'g5ưf` [zZ*FgfO-]7Ɍ],`?f-v/ Ril\Unw%mEh^|~HR{[}hV+S$ih}~h*d IDAT,U( nHm|P(hon^ظtMpèoб*C9ZeVAsKo֬d@ oqϑCGCb!ۿ/ Jw2~G;4X0^Pг'C2}Q`ϑD}TeȮ歰? CFB$`ITOЉhk)Xj&1*|GԼrex Q^λIxEcol\aՔCGFoviH,Jp2~/8 `h_ 29N}Ӡ%s0 Cu5 >6~i&_l% `{tfK$Z5իf'/a0UnxC?"a !RoU!`hh|[v#mA7 X\LmjP5 ǂx/X|ۿ'gĥ o d0̃/SV*0_m|KRQ6+%J({Uld=&MBp % ڰԙ.No%8QI^qz+n?8Qh23LbGaXH$mll C`h˖7Yy2jy yeG>?x]5]2L5'XƑ?:jׅ %onnD"kء.i7ljKw2~Qs3}43٫.ӳHsXm>hIxUϓpydWP&{``Bp<0M2 EIdk 9_*XV}̶%`w?sK6M-f7AZ?xi#JڞV\Gk9=V9zhT9WaA"/\00|FRQ:(i}PgD pCm jNxsz|s0 aӱ)G&v~|NOX ff?N 3j8SU(Vt;@&9HXqa1"2+CE`-@I2pxahP%9׬|PP8Z# ~~eW2|{F".xB'N3OL}55L.reզMxsVn#-ֵi!O~8DZƣǬ$:UM$ğ iziC>@qH,&8(@7fP5**?ȉ!^8("фA!DTib"RUV_0;́"g+`0,M·c=#?^#˦<˕W^NL(i᰿ދ.r[w=455׸`w1Dfv*@ @@SSl6W^`MS` ͫ[[C] LS.Q q@ cd<q V"JdYdr+ylR:?v^@, "D2aJKKѧoi4VS57)++իO@=zhEj 7SiK"I" 2&PRޞo p8P;vNy̙3.ti0  NNDkjjt_id$+Qd{53:JJf,_::vtęL0KKZ[[XcYBMUU՗^?² ˲PUUU57,S\\\\\ 5G"ӊ/tissS(4EQ}ϲL,8jG͛wKcϳ|A p: а}XQƟ=4qs S5w~L1aalr 5eϱ/#9̄ж 'd1)dc+æ#ZES‡\4gA23C9Sd?4>?x`kk~Kѣυ~s.`Ly 2,OQT*QUUSPdh֢Q DR*ưEsm,b@sl4r܊=-ԃ(b~pv͎;< mi 9LE]ЃW8F; ۅ.f޿y]zx<DX?9ciӊM+i =}}E4x=HPTUU4MEEMM"d_3p_x"_,s\D(ia68^~C }v3qs r9БgFФP NfXL6(EMuq\,ಢrJ*߄9ˈT,*dt6TQd1UU62j x ɸ`CL<%YArAL;Z.pakʡUjSvOԍ/^IJhE Sqsfl"K880x\s gzܧp'z~|LcŜW Ɂn7*(04iU/Ghp<x 9a}?˿ Zو92%!߈hsg ,bam4i&!1EˊY&XLV;iQ^OEDQ昝vڗ9cUQ K̡8ɤYY$."GeSEM6LqtOO5}qIJrƛmTXb'hX f 6ɊL4tbb@n[`KoAdT 6Gf2*%ɫUWqUI{"лVMU9XKt%[1DR\.?'ÎvL9ȅeYnjjv8Pߠ5(ǚ -vLcES`-5a͝EfVCp'@sX J 3!*4BpjaÆK.7p8P3DF7oBQ`KG PAIX2+@LD㑮x<&{GZhMý??C"mL8ajZ2pJ!3^F[i;s_#O^pB''Ͱ'[ jkkko}}={655n)mnO]z?}}a /{Q>޽{(}pѵi[ؽݚ7EQ=T*W~~}y?֪bb}2Ȼm7{-8{ @yȣ> j4UyoUد?׮jq-">'ߵIx }ŋAbwa ͝QO> 瞯|+tRԦ[ 7ܠɬ/,,UV}*..~6o êghO5-#D6pyEX>ܘ{ck tӺ8qZS5*92 9GŠ>4 ~VpOU=)KnOooog17b<PNiKHqb65ioƳ''g d=h4dEDx1H ZbIJ,?}X8@S[ r 9,Ipzzz~[riK/-YAe:a׿/>S]v/8+DN3(hlcB_zU.ͼv{ot R4! TCQQjbXLAAк3("=9we(* ,Kk #&U2x<aY6}zEQEA0<e}S4=>?>pؕauk |h''|cxU5:K8Z2p4zat _t9׬|PPn(F&"B<{9ܺu%\=C=3<W7zիW-Y"UVZ5Q~C[b" ݬ`7+}`I簒A@.)Px>H nD4#&cE玟UFk~xFF-Ы&fLnTT)~Jȑ~ڵ׽NVZ%m)OMq`sL$\ßMID SN4uDőh*Y`шkvP0-j>cY;rʕ+Wͻ }x7v~uBd4S@׿/{yC yE C@Y%n1+܍-be>1,/$í__鉅~ed-z)+)tb]> |ub''dl4 y1!@NbI1S)QRgP Ad1? 8DsA,MMMp8@|{j̈ܩ*,&f;81e83Y6F d*Bݲ{fbs+[1PJ,"M=V\MiE$x<@,s )Hfx`sdG_斓3!mƩ^?Pf''`˛9k1q`{;YPeU22(pR,A9+)--EnM.TdP,KwwwyYdSK+*ei,Hp\L<ga@f`sV%ap`PEӑɗs}՜p: ر3繾^@b< LǃÁ@ ;+㮮_f@N3M.kaHbt"3ٸhDwrn>/k`>nzG2=pc}:? >?'V;JT ðIfhZURPˬZD1)Ge2?'@l.83YOF{.1-s;W 4 RDUd%~~ѡ݂5"gGPVYdYVUAUQ\.j*bY8axh.9&P%95&14( xf ׸xY9!/w|dZ%j`7o.NP}!4x}<:NMQg4 ,ztGX]=>2N|x>ifEn^>̛`@C$-y }e G*:K7}oroXY=5 .Xp<ϝ̵eM|v78~N$\ß[˙ZRt^j&I#˧6ڔ `o'@fEIq*E3PB"D5" yh3qY\wjV}96BF@h2oBiS'xY3X\VV KOO9|P&37C/ɼE4árRj@J`-|R!Tݵ@o#/h@ /1*/A * "SIuU#6m灮}2i"Za헁Mޭ6 CuVW}}="LaryLpRPшgGRϖ^7 I 9?/8nk Gp&!Dp +t C@ml=^1*{qUyH>l,xRoWUTR]g(]xǴA"Rg!ng^E)z!כ-x|Y{Ywd\JlL׳CmӦ ر2OrL$'^"D&޺5D% _%ӭ`͉)Ǜ,44,)`)ޣ+Tp1}Z-zkk=ng߾1H+'I55n+(J"!L3ۅ Q(ؗI뇴q~"9h2 Cz-: f֭;jkk%\?r+#͟gw 7? >?Ix~%sAS MCfdS)ܩx,8P@XKRCs*qJyP\Uh²< s`Uל)J; u %OoE3KL<wUhdBDpE;I슇ʾ& {(@qG}!E6@yuõI?>[6MwOOI_͚i4B_]^8K@!Diw\,-k0@SfXB\AIdQHdd /ҴGoommM֯K$UMLD;00S\ٻ_Sjzʕ_vtt[w̥9^GqQ5__NmhHBnw!4#X[=FZkU]Cd@˔Onk50`Y)Q? j| 3 &>ހClSUU]UU gO%Oy  W^^ȳL5Y]4ji߳b5<<hi""D&-KO]/<-=xe[/b"2Pl`s6)@Nb0)&KoLJŀ8uh1:~ۇ(EZ /\04dԫdQ_WoWa~ 볱44lkU׬iv{L%Y㯽~~,X8aFX(݉>ׯ]7~p*F$q6t̘>*dt6TQd1UU62j PQHܥx <#]ٝ%WVC /\zjۛ#d HүO%O|Ixv"JD) R9je{p8,i={8 c刺X64USCe,,yGs&y4῎(/ا""(osNEQXcD @z2 e`i>>S?tаe '|O,y^j20bP<8 >} # "gA#H$Q"޾X,&p,"-!1a #] KF^_O ?9eBD"1C/Q=|(L裏w\˗/GQ+Xȑ#'l &rq+W.//+٬4C mY+V\ⳟS)dzo$1CWY $˧Kf;}`sXs,qݞjjԸڿ~}-44lw: BA<ׯ>^s˲o}%//7x,k uO[G}iP#|ޯ~xvPkş)uߗ/3ۋvP޻ׂc'w-~2Ձ=(3JKbgMӾx>C5xw}˗{ނ, ]?%Kd2Y__;7r-z{^F]t#<2{lxg~龾>n`[o|O>ptMw}70Hd޼y?~H$2s-[̘1cs9%1oiS[6ھ}TUݻw}7zWvlz^[(̮TS jG䕛@T쉒ߪ68+KixNVOy(}p:gϜYpwt6Z֐E`|S 1)^Vz? lKOD__2>g?`'!}̯v ՑR(xڛ} fb5o{Ç_GY{썍+W|/̾p ?OE{hկ~W]uUww>;۷?_N<_?ڵk۷aÆzjz;3Jۿ[AAO~z󵴴\y啯㍍/bUUU_̙˖-kjj[u]]v˖-,~TUu˖-#kX"SXFI%4L`ZN ' HR6;x(2x*zCyE@s)* 6&U#ι4g@(P\ivK &fhf]şLTEbWeZoH㓖q_m ğ"/g[o}zӖ? tuwE+駼?P[o}}C҅ڣ6[~Cg?3H(zz!p86o?'M7ݴ`a/Ϛ5kh\%Kp owя~T\\qwÇ,i<00`X/^ٟ^{-??{8ݸq#˲jժ>hsuM Fj@{[#?ak Pia&WLUў|k(~tʹK[ d=V\v]Y\3 P *35>8 =BQ8-ޯb65w*㣗c[ZBMMAThFNȧ/LTn#[3}ܩ?iD__O T4)//FN?M?/j#iG}~"EQ~_?|饗TUݷo~/~ӕ^6R˲,755۩TB1yyy`z꾾m۶I|ɛoy\ECD /xɱc==ݍ~߷o߾}Ǐ˲jm޴Ym_אg5UƫL:KWęP0NV)A%aIx[6wcKQ1>1,/X"FmW]uH_5#ff>KZ? =Nzy}U:K?X ı zniΚbrʝ;w677]λ`O2 lٲ+V8N[n?_W>,21u]oΟ?ƍ25p[lq\7pCUUժU?PJ~/Zh[l/ yx^ r-_җկӲJ IDAT@Vkxڴu־k텅<(ImmmK/Yz R BpȲDxT5iMJOSn=3f9@Nέ:YEz$yԻ9sTTM&ӈ*3J3!to ~ + P<U?ӆ?5_r}$T,t bZZ2sD|Yc$+//nit//:'ok؏sdrM\Vfy^yo}Eceooo\Da/:'msΝ7wn42?=x%:0p,YzM_Zp{ldi<|hK/b9Βϲ qQ3PlQofXD:7=B"K'__[q:ӯbp8a(L a^KCBYQyc ^Ng!DNN:e@MMM8+㮮<]qzӅ?ח̟S5w~L1a&"9ކ偲肋|ȳ3j2Mdi::/Ynx__įC9Sd?4>?˜Mz[bw޹yq]Y6V4)96uD(M6P \#oJF{$Yx[oUO /3 ' JjXe9},~u 68#k੉?ToF)r{O S gK vsgY$C-n֙ --]X LZ9'M$?rpA@3*s. *0iCiK]A`P ")9ܸMCPDm wclgjkksd4]fpg"D&}!IOr}}w tO\3⤻+w6<dz66EȹNp_UU{S5V@s^%Y$'f$Uqft20xf cxY9!/w|@Tqcӧ677,TNOi ڵLG=|.|N75=MH)=?˚,4O\3do ʄJD.(Yc93pee%lC͘>smukxf86PPR~hR0K_:"Y,$r$O3+tg$XPujEQaJ8K_#i)9>"'9㾾)?]}}9'*'8w J. ;LYNyGϘ>]U/ jFYlL.2[P;YhưPJi8D fVDw_m-I*tO\3x~vkKKjRz!(`&,"gP˖aw3cEQ%Lȷ3,sYffPr+v 1^1s~#q#9} !} SR?McֆQr%ki!wCTMO4 P.QNzwnk?$wo]# /?gS^?,Zq +>jʭ݉> 'm4'Hl$nB!|!)?m}_nAYQdIeYUUUEq\TeY8fL\;ibmebAgxQxR1ET $*F 'h>@4}Zmz·cΔYAuӦzC=z;1 &Yd?WXŸ*/g>Lu-a6T!DH䬔1a8AAYm p‚|b1d2 Z2)bR*8xT*D) Ƃ].Z} ]M^Q̩hjYmgkw?ӈ?E_r}$T .+Ca #tC2H"D\ 04@)s+@ԅn0<ӭR*nWRqfO*rBlcGo]WfA>^5 mӝY'9}} >'Sro<`q@/Dn[eb5}=!D੕Wv"QK< K88hNL H>ޜ*hxh*n9fOs6լR[fe5tٞGaGoʊGp5'9㾾z{ŸKه#H!)AӐ}!T %wj ^PhTeY.r4Mm='q7WW̓*?!g[Of`FnPpAtoA ll$)G5H7iغA/)yOEO'D__2R|"D`W6qEcĤie0hJvcT" 炿{iS=Iϐ /}3wƓ# ņx㮯o(XߎxBW$(FctO%v? Q"oWzrvMC!S#HUY1V^2DSG5>h*ZeTEү2-G#مJ5ȰR[=lidUwCV5}xDn38L(XψrՎxkO~}}%K?{̚EnϘ!B4'yQ =Jb,4vf؆PEA@bb ӌ HLbOk 'GI| Xo7d E4DFT @f0, 7sb |UfAUɘJLDzTUf1 Y?5t|2a!'s,РVZA3WRn:-=h<|hKߑ mRe1WfUi@ń(10IJ~ +'gy5 ?W^\ 'Z5w~L1aa3moG@YtEoxX'n'g*p8¬FALp< z)"@sZ~%J[` 6&iUIANZD1)GeqL9N3"Av|O >:x%J/kV|̏(S%>A)GX 6:4cBíڤ%G;)jȡD%_Q*ftIR|޺5tCNJ?9Q>_Ιu cC06+77A"gL<*7I TQd1UU62j x ɸ`CL<%Y"|O>@M@[E4#"JQ(`ȣ W|O >bf_8P,bH/O&0pO0Ekʕ+NJ-+.xָfڽvZ[i_)x=x޺5])޺5`&n Pwy?NV|֭Ad٧|wC*mV{ C7PV}_l/n @y^ 'vPg> $̟)ZrqAlŵs?\8l(L<_r_s5?{oGyzZdmrk &YLX8C3dc $o&L&'3gd&$ 0Fƀ1 %,kiٲ}muwOTԒKsNuuէ >{{|[[}1d25>11obU9wH͉}}}{ߺ[eWMM{%q9cz4???UUU.R>:L&H m;='{+*(V:/G+CK QFX)!@ypDXNPxI*٘Vf22J(7|#W%iWkGeq}Os7 TVV?ܵk믿L&KJJ//~;}}{o&lٲ?E{[nq[[[#ȷ}k]]]W~0o<HwcǎT*r|;p=:thhh|;G{`y׾k <1ko~3<<9yx<#̋1ҩ)-sY I/ǯ) +\h?5ՠF re хPx 9|#wO/(X]]А[DƟ/<ݛs{uݚ+WKmmm7|ٶmgy8?O<w}G/涶9rG?O~rA0_^>zC-YcW/W_}Gҗ'6mаw޽{S[o;300 `߸b7Gvni6k^0 mjfMKg5F޵6~s,#ȿj{/IoGGWGo@}۷{dCCC̾znao/Y䳟lAA!䮻; wy'_'N۷_W,YBY~U{Xf>P(iӦt:~v…Hdƍm۶}-**k_ZwwcJooݺuNkXX  /+tz[Ni7{Y|O~_WEQO<_jttR:66V[[ gihhxgn2u{{{wm:^|yv??;r %%%GEQRp`N18Y,YAI~|([e !=5!HaQ GUŦ?(dS:㢐_C2Α,_|'xgv]ںu__q{9 AOѱc9s~nZD3.{cy"3&&'R.8 6`j)*-F{I('mKӊ^[[$L^i%ZಓcN<A>*oιuϯ#Gٳzauu˿򕯤R)?mw`e˖q U^^~~[VV699gϞϱ~w}렮V@sxdĶq&&Ok?x#o'݃Ct1nZ8zًpbXJJ'캓PD E hb!*8.r3Q|#w%/Yg>xܻmܸqҥ7nO~r~OW_ݸq(fM/|_|G,Yr7o޼_q.uֽ+ǝO~뮻4MpF ৏m;wÔX,͋cyyQ]u]fYQURd2^O)/r0aͫ- eI2"5kuT[uG>j~z˿"07'{4Q9)O=Ԝ#(KzOC=C͊q>}ss dhO}Sԧ}UUo|ߘs*%븇BN͛ wt]wdd޾Sp~,?ṁ`Qܶ#p- (.řFU.9\ls!4N#ȿ*}WoKPG_qs&zN{ C8hʕ`@OOωox,ˏ+(*,ZI"S#fz (/kQB9E-F0dÄ )&(H#ȿ|H`u`o֧aaա\[ouӃ6~bv}9ו BZ#^qK>㒑9y~FsB?ЯAVPY-[Cs{]rkLe=UJfs n}B@DԐ|#j*]Y7. 7d}/?WJ5||g3*E5Ç,crKLtNw]Ͷe GU؟߲4ܺЧ{~wT}3F #O$NBEkkj3bKC1C38oe,#X&2h@G>'3O s F>? 5bN/ >nAr痔@UUM9q]d~qTcFLv̲2GH[F{0-EPXDwܭLSK"|#oDW7;x,B3(:並,]w=6>>>::zXÇ,YF>Ľy9HEȫ!H[FFk+&2aSKZȓD0{`B>|uey${̭sƼN_k2}-]Aql˲m1VSS'ca<4<Ϯ\{S@4 Cjvkߠ7V"@w4^^vFeU@D`6|_|P~ѧ71*y;<y۶^eRJ !<)!glxx/Է\P(H|0MX)sO%p `!^t1@.|_#3W$"+w?P2 ^`kjڅE #Z?7>"˼5ẖrdb0+Bm`|_| s%/xJ~3‚7u7-3nt19x:sW$mj6%Haʋ|eG>UQtÕPf*~z>ղ3X_g;^X cNhL48(vD̶D%%ܳ\^Z]8u>K K}Br'y L$ۦƋ.;Cyfͬ%L-5ʘ 2|_Y%]>/ހiL4]gl"-;p lX_]۲3-; w5]ƻMRo R -6mU-#m2LllK-+I08 ,xQVPD/yeU KJG>Z#^q;ӛw꩖իiyN y^ p\ G^] ``oheήX>޺{Z^jrlCÿQp ަ^l~AWn^W@Ijb0ǀ)M^1MN l=P cP}A>|i@oJoǛCJ cZ[$7706]=pq;@0>zEw澃?~:yKgyd#g> irSGsbNHɛcvD>ߴy[#^Y-/^T:o}[׸3;4JwR'fo_\eyZA?HKf`BxQV",ئg&| 4_nd&M=#E#$mF }+|#"Fs_ -;]=o3 7IߤҎ{qKmVS,lyKlC-O>EC1Edio? x_󳦖Lg&TpkZ[ /EU`D$|*[J1=`JTcFj2G>8E mLxG;^`5-Wxw"CK%X2uhyuh{>k4q-gyd2#(Z5'_alV۩skJrNٙQ1A  G>"' fS72橴DÝ ' ޳ԫ}; b۽im|!*QkgQ3y#*s Ph{guE $.b^xB]p gY(#ȿM?z{,E(ۿ`Llu*9w_SH!+hb^5̭;Ӹn 8wζw ]i6PAVA4TevX> rB8eLR4<삼EG>/nhxځZxǛC3<͡Z 6/;Ngt|})ATe, ]`˳Xۗ}ckW"vXj1ٺYV+M?غ{=7n6{2~G-{t]Uizb֮^  G>6ooz6o;|ghڼ}ΛYzO+=ȵɎ;֮^ 7?}vݲHv\ 7u-%%^}z2hJW[ܱw>DhizddzG8{^`[wdq<㱖;, ,tLvɋuYR T`EʙĜ駟 Ph8﹯o'U|d: Y}{H))gSϳgAtб6Wg( RxKXiG>/^hx>𳞇o߻v=^Zo]wJ߆2"z({֯)&.^wn/?ғ|&K)Wh8(9ʇ$52JR$(OV *ЙVf22J(7|#kGsGAqz]=޷ wVF^x5^s?;0wp`+JRn-酉[NۿӺO\ MNߘ~ 198ax֖GѩiOtoO_IflZPC#;N'@%v%2̅ξ򼜉P_^kK[2+G>o^DGp^l,Mǽe"pG=}n+ )yP|c˓Omh%pk47&7A8[qq6_-) ̝Q]%H.+\\.[Qe4|C E_uk'h*J*Ԉj#[wxsW{^`Eqsx**/,6NSϼϼq/޸]؍o=xɾAf&̆ ;YuCU^GY^GSX6p.I+3I/,ʖhbL RX#@#G~@[K.^h7r@ww Z~Ιޫjٕ4 7]-tlkA`m듿hh[h Ebt|АKHâ-zzG?_x(1q{\M\כNW7p[b2mbbjχ#855ѣt6axddɌm}ty]˲.]Z\\|n*9mj1RTs[OPO081bW5^HIV.;9c#G~yFП`LN x}乀yz֯)޾2.0c wUrS's~Ȝs}E2;Cia{s! u$v?awLNNqĉn馉 VVrήoprr‡Osϭ8APxgVz,c!QNP(ؼJj(OTGP)3]~܂|#&̖^@/o] 5:u cyb{b잛c.ǶXawOWO/쬮.eVd}ּ({y'¼$S-vmaXw Lza$h~x_X6I\;7cׂr̞#8>>o~]VZ?GVXQQQ4J&`*ڷ^Xo)u37|YO'9#!xIleUCO. rD*YG|#_A7pԵX7mc׶Bc}[v&u ggY}cy.7w6Z]8JyPW808}K37s Sn]M<d[ +++e%HN:%IkkoJ}rг!~Ё%8S4udgx˾#G~@pvP۴k^ GRn˄sb/?啎T=t?U%ap;ٽ#[c}cu6]y01q01/jAJvPt<Z%%JK痛]=Zjq^/zCuEHϳ$VoG7_V^4U\s ī1Ƕu!5m1yQVEYp mr@$O2_&1AP!QVmjG>/MlaJegxc}X\{hٙ8?Һ[#bYWx^WAegA3Crb o5gyb F;}K_Xb(//^d=טl{P(h,\]bFLwzneve\mhegˬ洼=rԺg ̘˜ʜuE.-gY5BccU>u_[ .|w}&3O ٙq"@eTCPP7tb@3#Uٶ #G~@[q/4x|eg2Nv{[ IHݾxc}ܶtL ^~Yf-iy膻xɪl^`%] *Њo^^G~RٟFf$p4̷23& @3XlSK5:G>[r.#ʶOxӁ w.ΖrVk{cwU(ᙹ{ -;>2jX9gWuMS{ߘ+d2ҖLKb!9s,[ e[˖0@>|1mx߾o] Zv&̤e1[_M)7|c)SO_Sܲ3U^7-ec}!T+61-T<2{9y\#99sW {[FFVMxOpk#O234ŝpxy{10p.q5"ȭz$wd]6UEH +G([>&M/D rR+pES Q̪whKVf+yp-F|#H wx[ׯ)n,`Ý vbbByJy5?L@otgᖝU+˳l߮#!Y16PAV_2G0H1͋Ԟ#hY&zj : ZFzƠ#k蛌f|#?(ZP]p^IS к'[:xǘ9񭯴{>"i{"׿/)rTSSnlzEf}(|)Z$)*䖹s ^Ug G>8E {o=!#|c}-eg lӲ32ۘr'U#{9-;-/(֪-Dɽgyd>#VKGGGGk?|%K25d"%Z4SYeA $ t9YI-B>|=A?oo'w!߸nImE Jބ_=u/.kxӮ$Ahb~yvAq(K.8}ԩSNZrR49_7P/1B-q¤35 >iڻ'M- ôXY>veZfr2̱r9G> /8nx?6zsߟ-^p7 /w~޵,{X;6}u?? pGsmDZ-˶m۶ b(:lE| ?%65^p;Gcf3+)LmJŽebAUdG>_?ǘBі)A$I԰zuˮ_~}~~(,K nU-#m2$M-52:ؖn[Waq"0;;Qb!EDYE>|2 }0yIj8婪( tbsWW3ͫ("IQ^ Y#Ry4u;5pE@E3 mB}fjG>>(Tp:b&TWyUc 9٩Awt]'XFznK#G~| Q EX1 ^1zQVi̢mql(K(Ff3R4YLrfnܷbG>0:B]ɡ gM-=?L24^2(JBIHBa?&T(E烓]tҟX4|#?P|zQ((3_ aڅ9?9L5%y'ʋ̨˘VG> #8GUf8I],ZŘ "&HᲹβPG>ABU~2^G,v1e\RcJEL|y"0 ʵbG>Q(TPD,Xmzrھ?[& 5m޶{Uo֝~gͲ2^)l;}HuS״߼9?jscHw=vb_@>|-%%RBgbTY+VЎB<>O?pbs_0OtAs:J9RT`~BO>ڟ!s^6Wg( RxKXiG>14B$4CK QFX)@n GO'+e(џFQ+3j%Z4sG>֎rtQ(tg9 TblWi+\웬-ˉiOZ[Z+#GW G0E6o6ecP9s,6?5zR nMKg /gwyZ1XG>Q(eW`V _ -L1S#PCRT!8A尗, d.0KcV92ҎkSG>`Q(Tpj8:wŲUJuIRXI xxdeQT=D4@CffJ¢" G>^a* s,L&R)V-Z5QlfضU 9 IDATSKQAmy>5KB>lĈ]]Vz"'YFZE|#PxUUUZQJJJ ~VG (y<3+=1ݐ('(l^R%5V'S^*ek=R>0;M?nA>|bAR,uiF0ΔKnݺC4KS}S4^Ba3+WZJO˒Ifyeڠ73`볎 G>GPW#wz#1˴L gy(ذc/z-uNɑBRrA\Lx#t*a.@6a\M G>^(%և%B3vH YPH7 [\ ;GlA0S@E x\)Bl1V&&LѷM0!<DA G>(ǁ ί|,+c2B tLDMyF x^yAUQVCЦF3aW?IjLD!tHU B&9b|#?8|zQfeEsddxxrr;26:FWRR򾙿3r 1 "fVQ(+"Xy^"pα2/wAmSC>|F(TPt~9(7M zOdIضՕXX u.9~ hΌ{G* 4|" ={D-a39j#t5ۖ|#>sQK #(AB7D·~{MEAW=#F4ī3/:󭌣V2ҎeR/V,Ԓ@W3|#?X|pp`F $Yc… /^\^^swyGDB36bxe?ZF2݃i)Z,‚ z]/n'fZ|#B] !( HTXX8  E"Ⲳ2YEQ o3y3dipme9XD&9lj)SKq`y231f̱VG>qE7Rd>gcʶm َ֯4;Ƚpxd7G+7E/"To>nBHLm&D92U6a/YQ-J8^A>|#y#B]J%G\{mh}ᅉႂyX+l *1(Df18njo2^^pڋ G>>FSh8V~oS+g7="3mLrXUI r-rl!\+,偣CE>|BsZ5hѢm^NE~s]SK.,"T_xitƚ3(̱rdb0+B95|#BC>3%w7-? 1'`Ih3y)IئfjSHhX|#Ca PRɉ _S]}^+K`g`:%65^pʋpm53VlfuIM-5ʘ 2|#?(|BD]V^VPQQr˗_|+VPVVP>kմyTm=rʌZFګ;0mzdu-ݶt$D`60+EY+B)\AU)/)Q#G~p8PW#(u-=zC&''''';v*n^W@Ijb0ǘb+۩3*!Tpl3S#G>qE#h6s0y[UJvI()%uW UrS7PNHɛbvD>|cPK #h;m۶m3ƪ PY9iy%Gs,‹J 3:I(, ISHшge2aтrߊ!G>0 u%yJEQdYHDe-[Vp8,IR(:///YSKuA*5 󄗌"ʪRPR"@PX ?%J?% #5bi#G~8P\5L!@z%5V@v5fiUSd3ה,*/3.c^A>|f?(TPs/frbT#B]b}sL̇9+x 8[PU~rI)k%.3dL9{#G~P(*( ,6=ecm_~쟎]U6o۽c 7e_fY6`ܾ ێ$ko^9бvU p[z1p/ G>?GjCJpt:ˀ|JQ9:|駟vN{I2Hcn^'R)G J̏SqqY ypX^I $Hp,/aG#G>߲0 pPrIj,1dF9GUcI*GP]Y5<%pķ2-LR4B IQPlSU^J 46t,YX~KH;Mf#G>GPQ0Bë]0hyj<^F`V+]%IRCR`e& 0ET-A )A r|#k{ QQ>fy{a(slHG$ئ2ʋ3csNX HJ+yQ6XR8&J VG>>A.R>&`sϭ8APxgVz,c!QNP(ؼJj(OTG&X$lq |#? A* ` r-}JO'Ǒ $L*u]ET E9"r #G>Q(U r#p- (.řFU.9\lŠKA>|QK AOqsmmSw'!-F0N.!f.G(mt,u$8A|#;0 u)pmC!x^eUU!&LrO*eQm eIئ|#Ge*8q.s95A* e%Z CW3ϋ@9VN>^;# mjG> #맀̸wJ@s*!(>{ §[Uٶ #G~@[q#B]J%G03=#F4ī338oe,#X&2hŲM- t5#G>f* Dߘ+d2ҖLKb!zw>1+a|#B#x{99sW =C VMdæ27Ƒ'3>ak|# ^*8 Ff_By@7{7r!W6eiU*0̨%Z/ G><D.is~%z=5TIQ-#=cPbqܜDdY|#?(|,(B F'^df-їI*1AΗEBn{*eos ^Ug G>8> 25d"%ZDMFDr5qgPB/ 0B95|#BC oZx~7ώ,z{F%q^fJڔ )/9m#G>PC(ԥTX^;)ɶ,P^k2f3knI*SK`2f*|# 80PQ`z Wm=rʌZFګ;0mzdu-ݶt$D`60P!{(+yB("嗋<*%%|#^  Dp󪼲JHRcC%9Ƭc^1MN l=P cP}A>|C/  t0c6"АWJRcW@BpvjfJ\ )yZNG>| uAς80XF^Uyczj10 ʪ4xV&-(|#? |P_󳦖Lg&TpkZ[ /EU`D$|*[J1=`JTcFj2G>@qEJjj9jTʾ2d3ה,*/3.cJX!G>_*( R\USLG;+bX&Ivhc6"^8B!G>/?sQK5Te^Yb$*?Ɣ5RlD`kŐ|#P.Xڏ}:7vUM,jڼm3 ;ΚeeR􃭻ws**Ho;^;:i y)sԲ@U5'~{lk|# p[KJ(Dߩ^ (Wġy|~o'ľ羾aT d1u"r 8}? B\`U除 J^V~<|#? -y P %G0=1@CFisQ5V b8A;,Q pʌZFF@>|A Y`/Xf(ەh0:&krbӯ֖k G>o#B L6ecP9s,6?5zR nMKg /gwyZ1XG>Q(eW`V _ -L1S#PCRT!8A尗, d.0KcV92ҎkSG>`Q(Tpj8:wŲUJuIRXI xxdeQT=D4@CffJ¢" G>^a* @Y^A^;2:麌oeF{mF̘Ü#V+< ca^9 !RwƢDD>|cPK #skl#D<˘nH 6/+ʓ)/Ѳ E|`w0 y~܂|#p?EG #AKS$q$/ `q]EABQ@Ept\3>|#?| uykHg)\KB9B Kxqli: a0 e.ҦF|#ca+9*CDSc\fq] .sqdK$J}dd&t]F 8Ne#G~@E14B]J=4ܴyghPDYeh1mj4)}%J~ABaoHDY"d#!G>Q @܅\Npl6BY"#txӭΈh|#?87pE@~)!;3R,\A0| Ϟ="gfFj-G>}PRg Č`ψ/ jl q4̷2[H;I3ZlSK]G>` #7fld7,+3eRXA^zݪO4J G>GP{y9HEȫ`=C-waQ\kf, wAT $R,J1&6Qȍ1Fc4X7Es5hT@-*vDTEQ)q);;s\A~><3g9gv89#ص왢RJ\V1+3hZ Έ(5@}G}G}mohǻ՟%.HJZtNpE2_WTmF%p i1Z[&"G}G}mGAF#%FRDJ%eBVJ 9Ah<}$q4T [_F}G}G}mo yU#F+n}$-- <}cPԧ2j2, @CW@ >>k> ZVF.+u5&9<#P/kf+ZPer:XG1h>>k <~X7cy[hEhxTW)W,PK ~\!r@\&8\>Q(( QQD?J;U5'QA 0P ]IxF&ATeK2%qv@I9\>;YeH.МJ.+) uuQQQ_[f\if*X̙3xGGA+`7(04;(sGPᓴhEUuH^;])W^G}G}}nϊ GSYE߉{'nf]2 }UԖ8zb($Ř+˟Sk8|$􁼼QQGo5!Z>#kO[Pti"9|谓W W@(ʟ˹F#4֯BMǰ}J%MݫH$bC>pRRb>Aw-Od--# B`|]=c ?/)R=4jJD\*}CKU-Z`Y`˗-۱cH"yzzo#-hMj\V~IEUСchF^)y'O.+g@(HN;]HS} }SPYrتHQYZ_׽655}X_ww˗5xa04a5ЖAEVȪ&z1tJC+z";X;4 M+D}G}G}?UPǍ@ ظqcDdի?15XXE3x+H )=hQAM*ާF'+1(r4wi B<4wVC>>ׯ ;ST*}nxhhX[~k˵+` B^1nA#Re\(ۙTň5* BZ.^= r:{G}G}zDk(hy Ȉ&RеW;5??m_e& -8yrp@14F|QeC:5\qd,5>>ꣾ6KL&&:;_uurᰰ5}5dHPyE4:ɓ>w?hԁ&&&H V;M6܄*c B @A<.S?ŋ< EAj>p^CQI$2V&2zn@ѵ/.r̓>HO?{ȡ>M.??W^r9~_O&ry`*cIDAT|#G*r}}SVY{=X<.|쨑.\XRO@P[lE3 cfjb2''Gn[$Amʕ_P(jM@+ ߽{* k?59uƌ2(HD"ֿ]v-*,ӧo耀{n?_keemcc;`@FVُB4v%46?>~BC{߮^C}3@sgOoۚFĭ[&M"2bS'׭]aχ^cjjz@)=w_fyΞN_jCí .Amaop^vǠV6%*1GoڴI&}<~|tL̊}O:uQU{O333x |y\V5:5ݪW0CON>֡C-[LƎ3וOZ;_ުy\qd.]%xx<HO믾=_WW;tfnnnnn~>tHРAͭ))\>- ^h:tR4ɛ"g[% -0er dM&1PtUkX#"y~;| 1!+W`>}jOƏgݒF̞f͚lOOOx~5accc2d>DGG';;ѣG} oyQD "?aaal d!JJJz{{}3sC~[٪rښR#8w߭ldT:xofË`#ۻzό,M :uKAZL5'ҊsgOuhm,’>y[n*DdEEjYyytt*R#J`;t0buuP^^njjk%Kzy{?䓯M yYM#fCUac+KK++ FF|!&,Y2{NԮYZZ:99Dk䐤1c?x/ӆ_ONj`SqB@@0J ͔=Z!p h? 3@^&gϜzM#mHN $ $.B/W.\s###07`#j8Ao2CD'DaΞ=ҹsZKABɗH{ǐA]fw""& ‚7o=w@Y/s8$njާo?__ ܹS!ӭiI?eep@Z׮],,,Ć./^hb{GGR4bvx%(iJv\ H5,NNN(!HAIÆ-\0>.~ԩzzzl$H _@݅]}왭qcظqD"! wQо}{3S3.rUxꓼ_Dm[,]T*577`p??ߧOFG<.'K.7j9sqttAxt4t_?R~׮-/-- ҤI8.`S*)v/WbVh5#vyٕ+Wjᐜ@ A%0P o͛׹KTjiiX/Q} yQ'Fxy{ =kkkAu۶3gR%g̜SW)zUGW׼{9[|ivyݪv6߯_{hpphppM>^}}%Kw3/i4n4ݕKe{(jՄnܽ#k]hvO H+yU}]xWXh `゗/6vtpܶuFCR}Kƅ ꫎;Z]]uP%R`3Ҷ` µKJQ J#^ a!j.4sՉNAVajuԔzM{ $ eSJwH6˫?pv\&5T(˛}5+AZ:֬]n ޔj<}EiF_>;YX)H99|ӣ"8jAb_NшQۃ."]@aswv=S-.$ID.F`dԡc[#ZՉaAZl~^kC zbKS{>~jlh`bbjbbWg7Ͽstpٍm ? HVx="Zk1ʼ~3<~޿;v&$Zi{ԅkz5-~K{2qU )wl?m^\eQP(r>"XZYUVVDAP(Ν;3tXkGV_^Qd.?gFK AACO}իWwQS)S <8$$$77XVVtj1̚UPPpY;wQ;}QsOȺo [n+#G jkkߝى0̱52rU-Ν;G=iӦٳ-\bO#? Ainbĉ4;wn̙3f̳gtر޵kbccg͚u}'H>ÄvŋǏommʍY!fffB㋊.U(:;;GG?~M#FE}2aBDddw[hQjjj=Hh( ѭGYd2H$F7n8p^ޡa X7n.XУGO&L\?˻].]cbb L3w*͖-[{6ئԣgMP3'NUr::::::<t|vpʥohhUWAAaÆYYYilOJJӛ>}:߿?$''$9c H4hРA%&&j웗l`zzzNNθqEk N:5&&ߜ:tȞ=.[lLLFƅM'm۶_~?x]/Ɔ%"G=mꗷo%%n^zMrr2F=pu6z T.A*vZewH#++T;ڵ+]77 Ϝ9VQQrKi߾}\\\lliӦ_^,Tj465US;|P||\\||zzzi1Rw׻w/ժP(rrJ ˝3{@ 044;g]S¶ |ҥW:hHHA'L8qO,ʕ+G7p:v1qNjlMq5zʅ  ZEYYj.T44hPCBB.^8wѣGÇ'%MR(5?QQs̙=_~ׯ_tOR- wϾu];͉AO5뿃Q# |rMگ_Z@AA嫽F;O>ͮ4MdEEjdh.x[ ֮fnzע˅  MH$*--UJ$6|,TKKK}! AfbϜ9sƍEW^^^={tuumL6hi֯IHXaF\^ZZdIɓJ&`qqŋF.\…5aש+wCc xqJqIQתͩb I6>տ23njj\ܺ%~tsm_?I2Ťמ0q|v mfai5J=*Ai;l߾!""BT:88888ײe͛Ծ}{OJJ:|ܹskegd\t)22]]d󃂂oT̙;gO'L9Ugi?Mߧ־6zyWBAסh!kWg򦈌muS,mDszh88j7+=9((Z.Ay0|*"\kh?+qʕ!Cmۺ˅  H>~FPZ"~ 3\ H(T1tEa_պFAA A&l-WbCC~Śa # Ҳx{LKM ]==\Ay iZsgOP_aI͈pa4 tttu^ltm[<66u8N{֦5:jX+L  !:$&qEӴR.o\s w  uVE=a5  ehAAiS`  AAA- *IENDB`tiled-1.0.3/docs/manual/introduction.md000066400000000000000000000074261315121121300200630ustar00rootroot00000000000000# Introduction ## About Tiled **Tiled is a 2D level editor that helps you develop the content of your game. Its primary feature is to edit tile maps of various forms, but it also supports free image placement as well as powerful ways to annotate your level with extra information used by the game. Tiled focuses on general flexibility while trying to stay intuitive.** In terms of tile maps, it supports straight rectangular tile layers, but also projected isometric, staggered isometric and staggered hexagonal layers. A tileset can be either a single image containing many tiles, or it can be a collection of individual images. In order to support certain depth faking techniques, tiles and layers can be offset by a custom distance and their rendering order can be configured. The primary tool for editing tile layers is a stamp brush that allows efficient painting and copying of tile areas. It also supports drawing lines and circles. In addition, there are several selection tools and a tool that does [automatic terrain transitions](using-the-terrain-tool.md). Finally, it can apply changes based on [pattern-matching](https://github.com/bjorn/tiled/wiki/Automapping) to automate parts of your work. Tiled also supports object layers, which traditionally were only for annotating your map with information but more recently they can also be used to place images. You can add rectangle, ellipse, polygon, polyline and tile objects. Object placement is not limited to the tile grid and objects can also be scaled or rotated. Object layers offer a lot of flexibility to add almost any information to your level that your game needs. Other things worth mentioning are the support for adding custom map or tileset formats through plugins, the tile stamp memory, tile animation support and the tile collision editor. ## Getting Started ### Creating a New Map When launching Tiled for the first time, we are greeted with the following default window layout: ![Tiled Window](images/introduction/tiled-window.png) There is a large gray area in the middle because no map is open yet. The first thing we'll do is to start a new map with _File -> New..._ (`Ctrl+N`). The following dialog will pop up: ![New Map](images/introduction/tiled-new-map.png) Here, we choose the initial map size, tile size, orientation, tile layer format and tile render order (only supported for _Orthogonal_ maps). All of these things can be changed later as needed, so it's not important to get it all right the first time. After pressing _OK_, we'll see the tile grid and an initial tile layer will be added to the map. However, before we can start using any tiles we need to add a tileset. Choose _Map -> New Tileset..._ to open the New Tileset dialog: ![New Tileset](images/introduction/tiled-new-tileset.png) Click the _Browse..._ button and select the `tmw_desert_spacing.png` tileset from the examples shipping with Tiled (or use one of your own if you wish). This example tileset uses a tile size of 32x32. It also has a one pixel _margin_ around the tiles and a one pixel _spacing_ in between the tiles (this is pretty rare actually, usually you should leave these values on 0). After pressing _OK_, Tiled should look as follows: ![Tileset Added](images/introduction/tiled-new-map-tileset-added.png) We're ready to select some tiles and [start painting](editing-tile-layers.md)! But first, let's have a quick look at the [various layer types](layers.md) supported by Tiled. *Most of the manual still needs to be written. Fortunately, there is a very nice [Tiled Map Editor Tutorial Series](http://www.gamefromscratch.com/post/2015/10/14/Tiled-Map-Editor-Tutorial-Series.aspx) on GamesFromScratch.com. In addition, the support for Tiled in various [engines and frameworks](../reference/support-for-tmx-maps.md) often comes with some usage information.* tiled-1.0.3/docs/manual/keyboard-shortcuts.md000066400000000000000000000074511315121121300211740ustar00rootroot00000000000000# Keyboard Shortcuts Try out these keyboard shortcuts to help save you time. On Mac, replace `Ctrl` with the `Command` key. ## General * `Right Click on Tile` - Captures the tile under the mouse (drag to capture larger areas). * `Ctrl + MouseWheel` - Zoom in/out on tileset and map * `Ctrl + Plus/Minus` - Zoom in/out on map * `Ctrl + 0` - Reset zoom on map * `Ctrl + Object Move` - Toggles "Snap to Grid" temporarily * `Ctrl + Object Resize` - Keep aspect ratio * `Alt + Object Resize` - Toggles "Snap to Grid" temporarily * `Middle Click` or `Space Bar` - Hold to pan the map view * `F5` - Run the [first custom command](using-commands.md) * `Ctrl + X` - Cut (tiles, objects or properties) * `Ctrl + C` - Copy (tiles, objects or properties) * `Ctrl + V` - Paste (tiles, objects or properties) * `Del` - Delete (tiles or objects) * `H` - Toggle highlighting of the current layer * `A` - Invokes [Automapping](https://github.com/bjorn/tiled/wiki/Automapping) * `Alt + C` - Copy current position of mouse cursor to clipboard (in tile coordinates) * `Ctrl + D` - Duplicate selected objects (since Tiled 1.0, before it was Delete) * `Ctrl + Shift + D` - Duplicate active layer * `F2` - Rename (if applicable in context) * `Tab` - Hide docks and tool bars (since Tiled 1.0) * `Ctrl + PgUp` - Select previous layer (above current layer) * `Ctrl + PgDown` - Select next layer (below current layer) * `Ctrl + Shift + Up` - Move current layer up * `Ctrl + Shift + Down` - Move current layer down * `Ctrl + Shift + H` - Show/Hide all other layers (only active layer visible / all layers visible) * `Ctrl + Tab` - Switch to left document * `Ctrl + Shift + Tab` - Switch to right document * `Alt + Left` - Switch to left document * `Alt + Right` - Switch to right document * `Ctrl + G` - Toggle displaying of the tile grid * `Ctrl + W` - Close current document * `Ctrl + Shift + W` - Close all documents * `Ctrl + E` - Export current document * `Ctrl + Shift + E` - Export current document to another file * `Ctrl + R` - Reload current document * `Ctrl + T` - Force-reload all tilesets used by the current map (mainly useful when not using the automatic reloading) ## When a tile layer is selected * `B` - Activate Stamp Brush tool * `T` - Activate [Terrain Brush](using-the-terrain-tool.md) tool * `F` - Activate Bucket Fill tool * `E` - Activate Eraser tool * `R` - Activate Rectangular Select tool * `W` - Activate Magic Wand tool * `S` - Activate Select Same Tile tool * `Ctrl + 1-9` - Store current tile selection (similar to `Ctrl + C`) * `1-9` recall the previous selection (similar to `Ctrl + V`) ## When an object layer is selected * `S` - Activate Select Objects tool * `PgUp` - Raise selected objects (with Manual object drawing order) * `PgDown` - Lower selected objects (with Manual object drawing order) * `Home` - Move selected objects to Top (with Manual object drawing order) * `End` - Move selected objects to Bottom (with Manual object drawing order) * `O` - Activate Edit Polygons tool (was `E` until Tiled 1.0) * `R` - Activate Insert Rectangle tool * `C` - Activate Insert Ellipse tool * `P` - Activate Insert Polygon tool * `L` - Activate Insert Polyline tool * `Enter` - Finish creating object * `Escape` - Cancel creating object * `T` - Activate Insert Tile tool * `E` - Activate Insert Text tool (since Tiled 1.0) ## When using the brush tool * `Shift + Click` - Line Tool, auto place tiles between two cells * `Ctrl + Shift + Click` - Circle Tool, auto place tiles around a radius * `X` - Flip selection horizontally * `Y` - Flip selection vertically * `Z` - Rotate selection clockwise * `Shift + Z` - Rotate selection counterclockwise ## When using the Rectangular Select tool * `Ctrl + A` - Select the whole layer * `Ctrl + Shift + A` - Select nothing ## In the properties dialog * `Del` or `Backspace` - Deletes a property tiled-1.0.3/docs/manual/layers.md000066400000000000000000000123771315121121300166420ustar00rootroot00000000000000# Working with Layers A Tiled map supports various sorts of content, and this content is organized into various different layers. The most common layers are the [Tile Layer](#tile-layers) and the [Object Layer](#object-layers). There is also an [Image Layer](#image-layers) for including simple foreground or background graphics. The order of the layers determines the rendering order of your content. Layers can be hidden or made only partially visible. Layers also have an offset, which can be used to position them independently of each other, for example to fake depth. You use [Group Layers](#group-layers) to organize the layers into a hierarchy. This makes it more comfortable to work with a large amount of layers. ## Tile Layers Tile layers provide an efficient way of storing a large area filled with tile data. The data is a simple array of tile references and as such no additional information can be stored for each location. The only extra information stored are a few flags, that allow tile graphics to be flipped vertically, horizontally or anti-diagonally (to support rotation in 90-degree increments). The information needed to render each tile layer is stored with the map, which specifies the position and rendering order of the tiles based on the orientation and various other properties. Despite only being able to refer to tiles, tile layers can also be useful for defining various bits of non-graphical information in your level. Collision information can often be conveyed using a special tileset, and any kind of object that does not need custom properties and is always aligned to the grid can also be placed on a tile layer. ## Object Layers Object layers are useful because they can store many kinds of information that would not fit in a tile layer. Objects can be freely positioned, resized and rotated. They can also have individual custom properties. There are many kinds of objects: * **Rectangle** - for marking custom rectangular areas * **Ellipse** - for marking custom ellipse or circular areas * **Polygon** - for when a rectangle or ellipse doesn't cut it (often a collision area) * **Polyline** - can be a path to follow or a wall to collide with * **Tile** - for freely placing, scaling and rotating your tile graphics * **Text** - for custom text or notes (since Tiled 1.0) All objects can be named, in which case their name will show up in a label above them (by default only for selected objects). Objects can also be given a _type_, which is useful since it can be used to customize the color of their label and the available [custom properties](custom-properties.md#predefining-properties) for this object type. For tile objects, the type can be [inherited from their tile](custom-properties.md#tile-property-inheritance). For most map types, objects are positioned in plain pixels. The only exception to this are isometric maps (not isometric staggered). For isometric maps, it was deemed useful to store their positions in a projected coordinate space. For this, the isometric tiles are assumed to represent projected squares with both sides equal to the _tile height_. If you're using a different coordinate space for objects in your isometric game, you'll need to convert these coordinates accordingly. The object width and height is also mostly stored in pixels. For isometric maps, all shape objects (rectangle, ellipse, polygon and polyline) are projected into the same coordinate space described above. This is based on the assumption that these objects are generally used to mark areas on the map. ## Image Layers Image layers provide a way to quickly include a single image as foreground or background of your map. They are currently not so useful, because if you instead add the image as a Tileset and place it as a Tile Object, you gain the ability to freely scale and rotate the image. The only advantage of using an image layer is that it avoids selecting / dragging the image while using the Select Objects tool, which is mainly due to the lack of layer locking ([#734](https://github.com/bjorn/tiled/issues/734)).

New in Tiled 1.0
## Group Layers Group layers work like folders and can be used for organizing the layers into a hierarchy. This is mainly useful when your map contains a large amount of layers. The visibility, opacity and offset of a group layer affects all child layers. Layers can be easily dragged in and out of groups with the mouse. The Raise Layer / Lower Layer actions also allow moving layers in and out of groups.
## Future Extensions There are many ways in which the layers can be made more powerful: * Ability to lock layers ([#734](https://github.com/bjorn/tiled/issues/734)) or even individual objects ([#828](https://github.com/bjorn/tiled/issues/828)). * Moving certain map-global properties to the Tile Layer ([#149](https://github.com/bjorn/tiled/issues/149)). It would be useful if one map could accommodate layers of different tile sizes and maybe even of different orientation. * "Infinite" tile layers that grow automatically ([#260](https://github.com/bjorn/tiled/issues/260)). If you like any of these plans, please help me getting around to it faster by [becoming a patron](https://www.patreon.com/bjorn). The more support I receive the more time I can afford to spend improving Tiled!
tiled-1.0.3/docs/manual/objects.md000066400000000000000000000207121315121121300167640ustar00rootroot00000000000000# Working with Objects Using objects you can add a great deal of information to your map for use in your game. They can replace tedious alternatives like hardcoding coordinates (like spawn points) in your source code or maintaining additional data files for storing gameplay elements. With the addition of _tile objects_, they also became useful for graphical purposes and can in some cases replace tile layers entirely, as demonstrated by the "Sticker Knight" example shipping with Tiled. To start using objects, add an [Object Layer](layers.md#object-layers) to your map. ## Placement Tools Each type of object has its own placement tool. ### Insert Rectangle Shortcut: `R` The rectangle was the first type of object supported by Tiled, which is why objects are rectangles by default in the [TMX map format](../reference/tmx-map-format.md). They are useful for marking rectangular areas and assigning custom properties to them. They are also often used for specifying collision boxes. Place a rectangle by clicking-and-dragging in any direction. Holding `Shift` makes it square and holding `Ctrl` snaps its size to the tile size. If the rectangle is empty (width and height are both 0), it is rendered as a small square around its position. This is mainly to keep it visible and selectable. Empty rectangles can be used for placing point objects, at least as long as no explicit support for point objects is available ([#1325](https://github.com/bjorn/tiled/issues/1325)). ### Insert Ellipse Shortcut: `C` Ellipses work the same way as [rectangles](#insert-rectangle), except that they are rendered as an ellipse. Useful for when your area or collision shape needs to represent a circle or ellipse. ### Insert Polygon Shortcut: `P` Polygons are the most flexible way of defining the shape of an area. They are most commonly used for defining collision shapes. When placing a polygon, the first click determines the location of the object as well as the location of the first point of the polygon. Subsequent clicks are used to add additional points to the polygon. Right click or press `Enter` to finish creating the polygon. Polygons needs to have at least three points. You can press `Escape` to cancel the creation of the polygon. When you want to change a polygon after it has been placed, you need to use the [Edit Polygons](#edit-polygons) tool. ### Insert Polyline Shortcut: `L` Polylines work very similar to [polygons](#insert-polygon), except that they are rendered as a line and require only two points. While they can represent collision walls, they are also often used to represent paths to be followed. Despite its name, the [Edit Polygons](#edit-polygons) tool is also used to edit polylines. ### Insert Tile Shortcut: `T` Tiles can be inserted as objects to have full flexibility in placing, scaling and rotating the tile image on your map. Like all objects, tile objects can also have custom properties associated with them. This makes them useful for placement of recognizable interactive objects that need special information, like a chest with defined contents or an NPC with defined script. To place a tile object, first select the tile you want to place in the Tilesets view. Then use the Left mouse button on the map to start placing the object, move to position it based on the preview and release to finish placing the object.
New in Tiled 1.0
To change the tile used by existing tile objects, select all the objects you want to change using the [Select Objects](#select-objects) tool and then right-click on a tile in the Tilesets view, and choose _Replace Tile of Selected Objects_.
New in Tiled 1.0
### Insert Text Shortcut: `X` Text objects can be used to add arbitrary multi-line text to your maps. You can configure various font properties and the wrapping / clipping area, making them useful for both quick notes as well as text used in the game. ## Select Objects Shortcut: `S` When you're not inserting new objects, you're generally using the Select Objects tool. It packs a lot of functionality, which is outlined below. ### Selecting and Deselecting You can select objects by clicking them or by dragging a rectangular lasso, selecting any object that intersect with its area. By holding `Shift` or `Ctrl` while clicking, you can add/remove single objects to/from the selection. When pressing and dragging on an object, this object is selected and moved. When this prevents you from starting a rectangular selection, you can hold `Shift` to force the selection rectangle.
New in Tiled 1.0
By default you interact with the top-most object. When you need to select an object below another object, first select the higher object and then hold `Alt` while clicking at the same location to select lower objects. You can also hold `Alt` while opening the context menu to get a list of all objects at the clicked location, so you may directly select the desired object. ### Moving You can simply drag any single object, or drag already selected objects by dragging any one of them. Hold `Ctrl` to toggle snapping to the tile grid. Hold `Alt` to force a move operation on the currently selected objects, regardless of where you click on the map. This is useful when the selected objects are small or covered by other objects. The selected objects can also be moved with the arrow keys. By default this moves the objects pixel by pixel. Hold `Shift` while using the arrow keys to move the objects by distance of one tile. ### Resizing You can use the resize handles to resize one or more selected objects. Hold `Ctrl` to keep the aspect ratio of the object and/or `Shift` to place the resize origin in the center. Note that you can only change width and height independently when resizing a single object. When having multiple objects selected, the aspect ratio is constant because there would be no way to make that work for rotated objects without full support for transformations. ### Rotating To rotate, click any selected object to change the resize handles into rotation handles. Before rotating, you can drag the rotation origin to another position if necessary. Hold `Shift` to rotate in 15-degree increments. Click any selected object again to go back to resize mode. You can also rotate the selected objects in 90-degree steps by pressing `Z` or `Shift + Z`. ### Changing Stacking Order If the active [Object Layer](layers.md#object-layer) has its Drawing Order property set to Manual (the default is Top Down), you can control the stacking order of the selected objects within their object layer using the following keys: * `PgUp` - Raise selected objects * `PgDown` - Lower selected objects * `Home` - Move selected objects to Top * `End` - Move selected objects to Bottom You can also find these actions in the context menu. When you have multiple Object Layers, the context menu also contains actions to move the selected objects to another layer. ### Flipping Objects You can flip the selected objects horizontally by pressing `X` or vertically by pressing `Y`. For tile objects, this also flips their images. ## Edit Polygons Shortcut: `E` Polygons and polylines have their own editing needs and as such are covered by a separate tool, which allows selecting and moving around their nodes. You can select and move the nodes of multiple polygons at the same time. Nodes can be deleted by selecting them and choosing "Delete Nodes" from the context menu. Careful with the `Delete` key, because that will delete the entire polygon ([#1555](https://github.com/bjorn/tiled/issues/1555)). When you have selected multiple consecutive nodes of the same polygon, you can join them together by choosing "Join Nodes" from the context menu. You can also split the segments in between the nodes by choosing "Split Segments", which is currently the only way to extend an existing polygon.
## Future Extensions Here are some ideas about improvements that could be made to the above tools: * For the [Insert Tile](#insert-tile) tool, show the preview already before pressing the left mouse button ([#537](https://github.com/bjorn/tiled/issues/537)) * Many improvements could be made to the support for editing polygons and polylines, like allowing to rotate and scale the selected nodes ([#1487](https://github.com/bjorn/tiled/issues/1487)). If you like any of these plans, please help me getting around to it faster by [becoming a patron](https://www.patreon.com/bjorn). The more support I receive the more time I can afford to spend improving Tiled!
tiled-1.0.3/docs/manual/using-commands.md000066400000000000000000000051551315121121300202630ustar00rootroot00000000000000# Using Commands The Command Button allows you to create and run shell commands (other programs) from Tiled. You may setup as many commands as you like. This is useful if you edit maps for multiple games and you want to set up a command for each game. Or you could setup multiple commands for the same game that load different checkpoints or configurations. ## The Command Button It is located on the main toolbar to the right of the redo button. Clicking on it will run the default command (the first command in the command list). Clicking the arrow next to it will bring down a menu that allows you to run any command you have set up, as well as an option to open the Edit Commands dialog. You can press F5 as a shortcut to clicking the button to run the default command. ## Editing Commands The 'Edit Commands' dialog contains a list of commands. Each command has several properties: * **Name**: The name of the command as it will be shown in the drop down list, so you can easily identify it. * **Command**: The actual shell command to execute. This usually starts with an executable program followed by arguments. You can use the following variables: + `%mapfile` is replaced with the current maps full path. + `%mappath` is replaced with the full folder path in which the map is located. (since Tiled 0.18) + `%objecttype` is replaced with the type of the currently selected object, if any. (since Tiled 0.12) + `%objectid` is replaced with the ID of the currently selected object, if any. (since Tiled 0.17) + `%layername` is replaced with the name of the currently selected layer. (since Tiled 0.17) * **Enabled**: A quick way to disable commands and remove them from the drop down list. + The default command is the first enabled command. You can also change whether or not it should save the current map before running commands. Note that if the program or any of its arguments contain spaces, these parts need to be quoted. ## Example Commands Launching a custom game called "mygame" with a -loadmap parameter and the mapfile: mygame -loadmap %mapfile On Mac, remember that Apps are folders, so you need to run the actual executable from within the `Contents/MacOS` folder: /Applications/TextEdit.app/Contents/MacOS/TextEdit %mapfile Or use `open` (and note the quotes since one of the arguments contains spaces): open -a "/Applications/CoronaSDK/Corona Simulator.app" /Users/user/Desktop/project/main.lua Some systems also have a command to open files in the appropriate program: * OSX: `open %mapfile` * GNOME systems like Ubuntu: `gnome-open %mapfile` * FreeDesktop.org standard: `xdg-open %mapfile` tiled-1.0.3/docs/manual/using-the-terrain-tool.md000066400000000000000000000133611315121121300216550ustar00rootroot00000000000000# Using the Terrain Tool Starting with Tiled 0.9.0, a new tool was added specifically to make editing tile maps easier when using terrain transitions. There are of course multiple ways to do transitions between tiles. The Terrain tool in Tiled supports transition tiles that have a well-defined terrain type at each of their 4 corners, which seems to be the most common method. To demonstrate how to use this tool I will describe the steps necessary to reproduce the `desert.tmx` example map, which now also includes terrain information in its tileset. ## Create a New Map and Add a Tileset ## First of all create a new orthogonal map with a tile size of 32x32 pixels. ![Create Map Dialog](images/terraintool/01-newmap.png) Then, add the `tmw_desert_spacing.png` example tileset. This tileset uses a margin and spacing of 1 pixel (which is only to test if this functionality works, not because I'd recommend doing that). ![Add Tileset Dialog](images/terraintool/02-newtileset.png) This tileset has 4 different terrain types. Traditionally editing a map with these tiles meant that you had to carefully connect the right transitions to avoid broken edges. Now we will define the terrain information for this tileset, which the Terrain tool will use to automatically place the right transitions. ## Define the Terrain Information ## Click the small "Edit Terrain Information" button. ![Edit Terrain Information button](images/terraintool/03-editterrainbutton.png) This dialog displays the list of terrain types in the tileset and allows you to mark corners of the tiles in your tileset as belonging to a certain terrain type. To start with, add each of the 4 terrain types. The fastest way is by right-clicking on a tile representing a certain terrain and choosing "Add Terrain Type". This automatically sets the tile as the image representing the terrain. ![Edit Terrain Dialog](images/terraintool/04-editterraindialog-add.png) Give each of the terrains an appropriate name. Once you're done, select the sand terrain and mark all corners in the tileset with this type of terrain. When you're done it should look like this: ![Mark Sand Terrain](images/terraintool/05-editterraindialog-edit.png) If you make a mistake, just use Undo (or press `Ctrl+Z`). Or if you notice a mistake later, either use the eraser to clear a terrain type from a corner or select the correct terrain type and paint over it. Do the same for each of the other terrain types. Eventually you'll have marked all tiles apart from the special objects. ![Done Marking Terrain](images/terraintool/06-editterraindialog-done.png) Now close the dialog so we can start trying out the Terrain tool. ## Editing with the Terrain Tool ## Switch from the Tilesets to the Terrains window. You should see the 4 terrain types represented in a list. Click on the sand terrain and start painting. You may immediately notice that nothing special is happening. This is because there are no other tiles on the map yet so the terrain tool doesn't really know how to help (because we have no transitions to "nothing" in our tileset). Assuming we're out to create a desert map, it's better to start by filling your entire map with sand. Just switch back to the Tilesets window for a moment, select the sand tile and then use the Fill tool. Let's switch back to the Terrains window and draw some cobblestones. Now you can see the tool in action! ![Drawing Cobblestone](images/terraintool/07-drawing-cobblestone.png) Try holding `Control` (`Command` on a Mac) while drawing. This reduces the modified area to just the closest corner to the mouse, allowing for precision work. Finally, see what happens when you try drawing some dirt on the cobblestone. Because there are no transitions from dirt directly to cobblestone, the Terrain tool first inserts transitions to sand and from there to cobblestone. Neat! ![Drawing Dirt](images/terraintool/08-drawing-dirt.png) ## Final Words ## Now you should have a pretty good idea about how to use this tool in your own project. A few things to keep in mind: * Currently the tool requires all terrain types to be part of the same tileset. You can have multiple tilesets with terrain in your map, but the tool can't perform automatic transitions from a terrain from one tileset to a terrain in another tileset. This usually means you may have to combine several tiles into one image. * Since defining the terrain information can be somewhat laboursome, you'll want to use the external tilesets feature of Tiled to share not only the image but also the terrain information among several maps. Note however, that it is not possible to edit the terrain information while the tileset is external. To work around this problem just temporarily import the tileset and then export it again. * The Terrain tool works fine with isometric maps as well (though not with the new "staggered" isometric maps). However, the Edit Terrain Information dialog is currently not able to render the overlay correctly for isometric tiles. When defining terrain for isometric tiles, imagine the top-left corner applies to the top of your isometric tile, the top-right corner applies to the right corner of your tile, etc. Check out the `isometric_grass_and_water.tmx` example when in doubt. * The tool will handle any number of terrain types and each corner of a tile can have a different type of terrain. Still, there are other ways of dealing with transitions that this tool can't handle. Also, it is not able to edit multiple layers at the same time. For a more flexible, but also more complicated way of automatic tile placement, check out [[Automapping]]. * I'm maintaining a [collection of tilesets](http://opengameart.org/content/terrain-transitions) that contain transitions that are compatible with this tool on [OpenGameArt.org](http://opengameart.org/). tiled-1.0.3/docs/map.dtd000066400000000000000000000063361315121121300150140ustar00rootroot00000000000000 tiled-1.0.3/docs/map.xsd000066400000000000000000000377411315121121300150430ustar00rootroot00000000000000 tiled-1.0.3/docs/reference/000077500000000000000000000000001315121121300154705ustar00rootroot00000000000000tiled-1.0.3/docs/reference/CC-BY-SA.png000066400000000000000000000117331315121121300173010ustar00rootroot00000000000000PNG  IHDRXc pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-gAMA|Q cHRMz%u0`:o_FIDATxZKl!2"v}JtuyJ,iSe-vԤ  rH([ڡ1&h0WjZmRpFP$J[awA;;wCq1 Ț !aq:X˲8,ˁcYyeY0 a0 0@':tHW]uD ! 0.qFbR:3Af0_XSdkNu]ځ~@8x]d2T*¬CQ;w>24˪ƀh,0XڦNs1{o, clQx uǖU^[TVFwSSSRvv삪i4j&Mjᕘ\1x^d2Pi‰ 6Ȳ ˅޾e)u 55/ӛ7WX-8 +#pid2IAd  ;b1xˊ b,s]L޾y^Z[kS 6Xw588$k>ӗ6eL5= %fz n0xy@%/ ȦK?sx0Uw2kWSo!SDA#>55kW &’JO$YHm{5?e?~%@PTl)LRpBm( ~?|>|>ut䭤%0M7). x]utR6>Znc0`Tp$( |>(PP~^8]%IB"@*2v6`%+T\,y,$5<'޾M5(k*dz䇗럜DwW0z{Π ::NZ`Rng r9Zgm>$Iu~џ%_L: 9x9bV?x8Ǐ70mK+Y˝};\.~?e<~?rp"tb_IqZ[in^~`\u-b||6D"6mrge2yuX\u Ķ5ݼ{}e,CEA( %J1뭟ۣwGaDdigi"Pq^xG/B<͡XCQ-XTYq ]4_S6+if> ߄0ꥭ },~g7s+(eW|,zv<6VhRnb\<Nthqv1j|of]+l QE<^GFtq@:"d^dɫ|Z($NJ.#(_"i2v/Ezz{hw(noȝ|!_ n2== Ӥ@ع!w2c#]0NigxDž G+>2醪M^_ i}Y~Vϰ߯DSg`4H|@nGv$s?Md{yo, ,VR\5- _JrW\]~^o =kr*FϮ~bn3*b֭۶3҅mp#~'Sx| ##k @\kӰг{lɮ]سwm߆\Z}U(qƚM1x)? C0@ B E|IENDB`tiled-1.0.3/docs/reference/support-for-tmx-maps.md000066400000000000000000000370741315121121300220710ustar00rootroot00000000000000# Libraries and Frameworks There are many libraries available for reading and/or writing maps stored in the [TMX map format](../reference/tmx-map-format.md) as well as many development frameworks that include support for TMX maps. This list is divided into two sections: - [Support by Language](#support-by-language) - [Support by Framework](#support-by-framework) First list is for developers who plan on implementing their own renderer. Second list is for developers already using (or considering) a particular game engine / graphics library who would rather pass on having to write their own tilemap renderer. *For updates to this page please open a pull request or issue [on github](https://github.com/bjorn/tiled/issues), thanks!* ## Support by Language These libraries typically include only a TMX parser, but no rendering support. They can be used universally and should not require a specific game engine or graphics library. ### C * [TMX](https://github.com/baylej/tmx/) - XML and JSON map loader with Allegro5 and SDL2 examples (BSD). ### C++ * [C++/Boost](http://www.catnapgames.com/blog/2011/10/10/simple-tmx-tilemap-parser.html) by Tomas Andrle (limited functionality, single cpp file) * [C++/TinyXML based tmx-parser](https://github.com/andrewrk/tmxparser) (BSD) - [Original version](http://code.google.com/p/tmx-parser/) by KonoM is discontinued. * C++/Qt based libtiled, used by Tiled itself and included at [src/libtiled](https://github.com/bjorn/tiled/tree/master/src/libtiled) (BSD) * [C++11x/TinyXml2 libtmx-parser](https://github.com/halsafar/libtmx-parser) by halsafar. (zlib/tinyxml2) * [C++11/TinyXml2 libtmx](https://github.com/jube/libtmx) by jube, for reading only (ISC licence). See [documentation](http://jube.github.io/libtmx/index.html). * [TMXParser](https://github.com/solar-storm-studios/TMXParser) General *.tmx tileset data loader. Intended to be used with TSXParser for external tileset loading. (No internal tileset support) * [TSXParser](https://github.com/solar-storm-studios/TSXParser) General *.tsx tileset data loader. Intended to be used with TMXParser. * [TMXLoader](https://bitbucket.org/martingrant/tmxloader) based on [RapidXml](http://rapidxml.sourceforge.net/). Limited functionality (check the [website](http://www.midnightpacific.com/portfolio/tmxloader-for-tiled-map-editor/) for details). * [tmxlite](https://github.com/fallahn/tmxlite) C++14 map parser with compressed map support but no external linking required. Includes examples for SFML and SDL2 rendering. Currently has full tmx support up to 0.16. (Zlib/libpng) ### C#/.NET ### * [MonoGame.Extended](https://github.com/craftworkgames/MonoGame.Extended) has a Tiled map loader and renderer that works with MonoGame on all platforms that support portable class libraries. * [XNA map loader](https://github.com/zachmu/tiled-xna) by Kevin Gadd, extended by Stephen Belanger and Zach Musgrave (has dependency on XNA but supposedly can be turned into a standalone parser easily) * [TiledSharp](https://github.com/marshallward/TiledSharp): Yet another C# TMX importer library, with Tiled 0.11 support. TiledSharp is a generic parser which can be used in any framework, but it cannot be used to render the maps. Available via NuGet. * [NTiled](https://github.com/patriksvensson/ntiled): Generic parser for 0.9.1 tiled maps. Available via NuGet. * [TmxCSharp](https://github.com/gwicksted/TmxCSharp): Useful for multi-layer orthographic tile engines. No framework dependencies, used with a custom OpenTK tile engine soon to be open source, tested with Tiled 0.8.1 (multiple output formats). MIT license. * [tmx-mapper-pcl](https://github.com/aalmik/tmx-mapper-pcl): PCL library for parsing Tiled map TMX files. This library could be used with MonoGame and Windows Runtime Universal apps. ### D * [tiledMap.d](https://gist.github.com/gdm85/9896961) simple single-layer and single-tileset example to load a map and its tileset in [D language](http://dlang.org/). It also contains basic rendering logic using [DSFML](https://github.com/Jebbs/DSFML/) ### Go * [github.com/salviati/go-tmx/tmx](https://github.com/salviati/go-tmx) ### Haskell * [htiled](http://hackage.haskell.org/package/htiled) by [Christian Rødli Amble](https://github.com/chrra). ### Java * A library for loading TMX files is included with Tiled at [util/java/libtiled-java](https://github.com/bjorn/tiled/tree/master/util/java/libtiled-java). * Android-Specific: - [AndroidTMXLoader](https://github.com/davidmi/Android-TMX-Loader) loads TMX data into an object and renders to an Android Bitmap (limited functionality) - [libtiled-java port](http://chiselapp.com/user/devnewton/repository/libtiled-android/index) is a port of the libtiled-java to be used on Android phones. ### PHP * [PHP TMX Viewer](https://github.com/sebbu2/php-tmx-viewer) by sebbu : render the map as an image (allow some modifications as well) ### Pike * [TMX parser](https://gitlab.com/tmx-parser/tmx-parser): a simple loader for TMX maps (CSV format only). ### Processing * [linux-man/ptmx](https://github.com/linux-man/ptmx): Add Tiled maps to your Processing sketch. ### Python * [pytmxlib](http://pytmxlib.readthedocs.org/en/latest/): library for programmatic manipulation of TMX maps * [python-tmx](http://python-tmx.nongnu.org): a simple library for reading and writing TMX files. ### Ruby * [tmx gem](https://github.com/shawn42/tmx) by erisdiscord ### Vala * [librpg](https://github.com/JumpLink/librpg) A library to load and handle spritesets (own format) and orthogonal TMX maps. ## Support by Framework Following entries are integrated solutions for specific game engines. They are typically of little to no use if you're not using said game engine. ### AndEngine * [AndEngine](http://www.andengine.org/) by Nicolas Gramlich supports [rendering TMX maps](http://www.andengine.org/blog/2010/07/andengine-tiledmaps-in-the-tmx-format/) ### Allegro * [allegro_tiled](https://github.com/dradtke/allegro_tiled) integrates Tiled support with [Allegro 5](http://alleg.sourceforge.net/). ### cocos2d * [cocos2d (Python)](http://python.cocos2d.org/) supports loading [Tiled maps](http://python.cocos2d.org/doc/programming_guide/tiled_map.html) through its `cocos.tiles` module. * [cocos2d-x (C++)](http://www.cocos2d-x.org/) supports loading TMX maps through the [CCTMXTiledMap](http://www.cocos2d-x.org/reference/native-cpp/V2.1.4/da/d68/classcocos2d_1_1_c_c_t_m_x_tiled_map.html) class. * [cocos2d-objc (Objective-C, Swift)](http://www.cocos2d-objc.org/) (previously known as: cocos2d-iphone, cocos2d-swift, cocos2d-spritebuilder) supports loading TMX maps through [CCTiledMap](http://cocos2d.spritebuilder.com/docs/api/Classes/CCTiledMap.html) * [TilemapKit](http://tilemapkit.com) is a tilemapping framework for Cocos2D. It supports all TMX tilemap types, including staggered iso and all hex variations. No longer in development. ### Construct 2 - Scirra * [Construct 2](http://www.scirra.com), since the Beta Release 149, officially supports TMX maps, and importing it by simple dragging the file inside the editor. [Official Note](https://www.scirra.com/construct2/releases/r149) ### Corona SDK * [PonyTiled](https://github.com/ponywolf/ponytiled) is a simple Tiled Map Loader for Corona SDK ([forum announcement](http://discourse.mapeditor.org/t/new-lua-coronasdk-framework-ponytiled/1826)) * [Dusk Engine](https://github.com/GymbylCoding/Dusk-Engine) is a fully featured Tiled map game engine for Corona SDK ### Flixel * Lithander demonstrated his [Flash TMX parser combined with Flixel rendering](http://blog.pixelpracht.net/?p=59) ### Game Maker * [Tiled2GM Converter](http://gmc.yoyogames.com/index.php?showtopic=539494) by Dmi7ry ### Godot * [Tiled Map Importer](https://godotengine.org/asset-library/asset/25) imports each map as Godot scene which can be instanced or inherited ([forum announcement](http://discourse.mapeditor.org/t/importer-plugin-for-godot-engine/1833/1)) ### Haxe * [HaxePunk](https://github.com/HaxePunk/tiled) Tiled Loader for HaxePunk * [HaxeFlixel](https://github.com/HaxeFlixel/flixel-addons/tree/dev/flixel/addons/editors/tiled) * [OpenFL](https://github.com/Kasoki/openfl-tiled) "openfl-tiled" is a library, which gives OpenFL developers the ability to use the Tiled Map Editor. * [OpenFL + Tiled + Flixel](https://github.com/kasoki/openfl-tiled-flixel) Experimental glue to use "openfl-tiled" with HaxeFlixel ### HTML5 (multiple engines) * [Canvas Engine](http://canvasengine.net) A framework to create video games in HTML5 Canvas * [chesterGL](https://github.com/funkaster/ChesterGL) A simple WebGL/canvas game library * [KineticJs-Ext](https://github.com/Wappworks/kineticjs-ext) A multi-canvas based game rendering library * [melonJS](http://www.melonjs.org) A lightweight HTML5 game engine * [Platypus Engine](https://github.com/PBS-KIDS/Platypus/) A robust orthogonal tile game engine with game entity library. * [sprite.js](https://github.com/batiste/sprite.js) A game framework for image sprites. * [TMXjs](https://github.com/cdmckay/tmxjs) A JavaScript, jQuery and RequireJS-based TMX (Tile Map XML) parser and renderer. * [chem-tmx](https://github.com/andrewrk/chem-tmx) Plugin for [chem](https://github.com/andrewrk/chem/) game engine. * [GameJs](http://gamejs.org) JavaScript library for game programming; a thin wrapper to draw on HTML5 canvas and other useful modules for game development * [Crafty](http://craftyjs.com) JavaScript HTML5 Game Engine; supports loading Tiled maps through an external component [TiledMapBuilder](https://github.com/Kibo/TiledMapBuilder). * [Phaser](http://www.phaser.io) A fast, free and fun open source framework supporting both JavaScript and TypeScript ([Tiled tutorial](http://www.gamedevacademy.org/html5-phaser-tutorial-top-down-games-with-tiled/)) * [linux-man/p5.tiledmap](https://github.com/linux-man/p5.tiledmap) adds Tiled maps to [p5.js](http://p5js.org/). ### indielib-crossplatform * [indielib cross-platform](http://www.indielib.com) supports loading TMX maps through the [C++/TinyXML based tmx-parser](http://code.google.com/p/tmx-parser/) by KonoM (BSD) ### LibGDX * [libgdx](http://libgdx.badlogicgames.com/), a Java-based Android/desktop/HTML5 game library, [provides](https://github.com/libgdx/libgdx/wiki/Tile-maps) a packer, loader and renderer for TMX maps ### LITIengine * [LITIengine](https://litiengine.com) is a 2D Java Game Engine that supports loading, saving and rendering maps in the .tmx format. ### LÖVE * [Simple Tiled Implementation](https://github.com/Karai17/Simple-Tiled-Implementation) Lua loader for the LÖVE (Love2d) game framework. ### MOAI SDK * [Hanappe](https://github.com/makotok/Hanappe) Framework for MOAI SDK. * [Rapanui](https://github.com/ymobe/rapanui) Framework for MOAI SDK. ### Monkey X * [bit.tiled](https://github.com/bitJericho/bit.tiled) Loads TMX file as objects. Aims to be fully compatible with native TMX files. * [Diddy](https://code.google.com/p/diddy/) is an extensive framework for Monkey X that contains a module for loading and rendering TMX files. Supports orthogonal and isometric maps as both CSV and Base64 (uncompressed). ### Node.js * [node-tmx-parser](https://github.com/andrewrk/node-tmx-parser) - loads the TMX file into a JavaScript object ### Orx Portable Game Engine * [TMX to ORX Converter](http://orx-project.org/wiki/tutorials/community/sausage/tmx_to_orx) Tutorial and converter download for Orx. ### Pygame * [Pygame map loader](http://www.pygame.org/project/1158/) by dr0id * [PyTMX](https://github.com/bitcraft/PyTMX) by Leif Theden (bitcraft) * [tmx.py](https://bitbucket.org/r1chardj0n3s/pygame-tutorial/src/a383dd24790d/tmx.py) by Richard Jones, from his [2012 PyCon 'Introduction to Game Development' talk](http://pyvideo.org/video/615/introduction-to-game-development). * [TMX](https://github.com/renfredxh/tmx), a fork of tmx.py and a port to Python3. A demo called pylletTown can be found [here](https://github.com/renfredxh/pylletTown). ### Pyglet * [JSON map loader/renderer for pyglet](https://github.com/reidrac/pyglet-tiled-json-map) by Juan J. Martínez (reidrac) * [PyTMX](https://github.com/bitcraft/PyTMX) by Leif Theden (bitcraft) ### PySDL2 * [PyTMX](https://github.com/bitcraft/PyTMX) by Leif Theden (bitcraft) ### SDL * [C++/TinyXML/SDL based loader](http://usefulgamedev.weebly.com/c-tiled-map-loader.html) example by Rohin Knight (limited functionality) ### SFML * [STP](https://github.com/edoren/STP) (SFML TMX Parser) by edoren * [C++/SFML Tiled map loader](http://trederia.blogspot.co.uk/2013/05/tiled-map-loader-for-sfml.html) by fallahn. (Zlib/libpng) * [C++/SfTileEngine](https://github.com/Tresky/sf_tile_engine) by Tresky (currently limited functionality) ### Slick2D * [Slick2D](http://slick.ninjacave.com) supports loading TMX maps through [TiledMap](http://slick.ninjacave.com/javadoc/org/newdawn/slick/tiled/TiledMap.html). ### Sprite Kit Framework * [SKTilemap](https://github.com/TomLinthwaite/SKTilemap) is built from the ground up in Swift. It's up to date, full of features and easy to integrate into any Sprite Kit project. Supports iOS and OSX. * [SKTiled](https://github.com/mfessenden/SKTiled) - A Swift framework for working with Tiled assets in SpriteKit. * [TilemapKit](http://tilemapkit.com) is a tilemapping framework for Sprite Kit. It supports all TMX tilemap types, including staggered iso and all hex variations. No longer in development. * [JSTileMap](https://github.com/slycrel/JSTileMap) is a lightweight SpriteKit implementation of the TMX format supporting iOS 7 and OS X 10.9 and above. ### TERRA Engine (Delphi/Pascal) * [TERRA Engine](http://pascalgameengine.com/) supports loading and rendering of TMX maps. ### Unity 3D * [Orthello Pro](http://www.wyrmtale.com/products/unity3d-components/orthello-pro) (2D framework) offers [Tiled map support](http://www.wyrmtale.com/orthello-pro/tilemaps). * [Tiled Tilemaps](http://karnakgames.com/wp/unity-tiled-tilemaps/) library by Karnak Games adds support for Orthogonal TMX maps to Unity, with automatic collision detection. * [Tiled To Unity](https://www.assetstore.unity3d.com/#/content/17260/) is a 3D pipeline for Tiled maps. It uses prefabs as tiles, and can place decorations dynamically on tiles. Supports multiple layers (including object layers). * [Tiled2Unity](http://www.seanba.com/introtiled2unity.html) exports TMX files to Unity with support for (non-simple) collisions. * [UniTMX](https://bitbucket.org/PolCPP/unitmx/overview) imports TMX files into a mesh. * [X-UniTMX](https://bitbucket.org/Chaoseiro/x-unitmx) supports almost all Tiled 0.10 features. Imports TMX/XML files into Sprite Objects or Meshes. ### Unreal Engine 4 * [Paper2D](https://forums.unrealengine.com/showthread.php?3539-Project-Paper2D) provides built-in support for tile maps and tile sets, importing JSON exported from Tiled. ### Urho3D * [Urho3D](http://urho3d.github.io/) natively supports loading Tiled maps as part of the [Urho2D](http://urho3d.github.io/documentation/1.4/_urho2_d.html) sublibrary ([Documentation](http://urho3d.github.io/documentation/1.4/class_urho3_d_1_1_tile_map2_d.html), [HTML5 example](http://urho3d.github.io/samples/36_Urho2DTileMap.html)). ### XNA * [FlatRedBall Engine TMXGlue tool](http://www.flatredball.com/frb/docs/index.php?title=Kain%27s_Tavern#Tiled_Map_Editor.2C_TMX.2C_Glue_and_you.) by Domenic Datti loads TMX maps into the FlatRedBall engine, complete with node networks, pathfinding, and shapecollection support via object layers. * [TiledMax](http://tiledmax.xpod.be/) by Aimee Bailey, a .NET library for parsing TMX maps without dependencies on Windows or XNA * [XTiled](https://bitbucket.org/vinull/xtiled) by Michael C. Neel and Dylan Wolf, XNA library for loading and rendering TMX maps * [XNA map loader](https://github.com/zachmu/tiled-xna) by Kevin Gadd, extended by Stephen Belanger and Zach Musgrave tiled-1.0.3/docs/reference/tmx-changelog.md000066400000000000000000000157601315121121300205600ustar00rootroot00000000000000source: reference/tmx-changelog.md --- # TMX Changelog # Below are described the changes/additions that were made to the [TMX format](tmx-map-format.md) for recent versions of Tiled. ## Tiled 0.17 ## * Added `color` and `file` as possible values for the [`property.type`](tmx-map-format.md#property) attribute. * Added support for editing multi-line string properties, which are written out differently. ## Tiled 0.16 ## * The [`property`](tmx-map-format.md#property) element gained a `type` attribute, storing the type of the value. Currently supported types are `string` (the default), `int`, `float` and `bool`. ## Tiled 0.15 ## * The `offsetx` and `offsety` attributes are now also used for [`imagelayer`](tmx-map-format.md#imagelayer) elements, replacing the `x` and `y` attributes previously used. This change was made for consistency with the other layer types. * The tiles in an image collection tileset are no longer guaranteed to be consecutive, because removing tiles from the collection will no longer change the IDs of other tiles. * The pure XML and Gzip-compressed tile layer data formats were deprecated, since they didn't have any advantage over other formats. Remaining formats are CSV, base64 and Zlib-compressed layer data. * Added `columns` attribute to the [`tileset`](tmx-map-format.md#tileset) element, which specifies the number of tile columns in the tileset. For image collection tilesets it is editable and is used when displaying the tileset. * The `backgroundcolor` attribute of the [`map`](tmx-map-format.md#map) element will now take the format `#AARRGGBB` when its alpha value differs from 255. Previously the alpha value was silently discarded. ## Tiled 0.14 ## * Added optional `offsetx` and `offsety` attributes to the `layer` and `objectgroup` elements. These specify an offset in pixels that is to be applied when rendering the layer. The default values are 0. ## Tiled 0.13 ## * Added an optional `tilecount` attribute to the `tileset` element, which is written by Tiled to help parsers determine the amount of memory to allocate for tile data. ## Tiled 0.12 ## * Previously tile objects never had `width` and `height` properties, though the format technically allowed this. Now these properties are used to store the size the image should be rendered at. The default values for these attributes are the dimensions of the tile image. ## Tiled 0.11 ## * Added `hexagonal` to the supported values for the `orientation` attribute on the `map` element. This also adds `staggerindex` (`even` or `odd`) and `staggeraxis` (`x` or `y`) and `hexsidelength` (integer value) attributes to the `map` element, in order to support the many variations of staggered hexagonal. The new `staggerindex` and `staggeraxis` attributes are also supported when using the `staggered` map orientation. * Added an `id` attribute to the `object` element, which stores a map-unique ID of the object. * Added a `nextobjectid` attribute to the `map` element, which stores the next available ID for new objects. This number is stored to prevent reuse of the same ID after objects have been removed. ## Tiled 0.10 ## * Tile objects can now be horizontally or vertically flipped. This is stored in the `gid` attribute using the same mechanism as for regular tiles. The image is expected to be flipped without affecting its position, same way as flipped tiles. * Objects can be rotated freely. The rotation is stored in degrees as a `rotation` attribute, with positive rotation going clockwise. * The render order of the tiles on tile layers can be configured in a number of ways through a new `renderorder` property on the `map` element. Valid values are `right-down` (the default), `right-up`, `left-down` and `left-up`. In all cases, the map is drawn row-by-row. This is only supported for orthogonal maps at the moment. * The render order of objects on object layers can be configured to be either sorted by their y-coordinate (previous behavior and still the default) or simply the order of appearance in the map file. The latter enables manual control over the drawing order with actions that "Raise" and "Lower" selected objects. It is controlled by the `draworder` property on the `objectgroup` element, which can be either `topdown` (default) or `index`. * Tiles can have an `objectgroup` child element, which can contain objects that define the collision shape to use for that tile. This information can be edited in the new Tile Collision Editor. * Tiles can have a single looping animation associated with them using an `animation` child element. Each frame of the animation refers to a local tile ID from this tileset and defines the frame duration in milliseconds. Example: ```xml ... ``` ## Tiled 0.9 ## * Per-object visibility flag is saved (defaults to 1): ```xml ``` * Terrain information was added to tileset definitions (this is generally not very relevant for games): ```xml ... ... ``` * There is preliminary support for a "staggered" (isometric) projection (new value for the `orientation` attribute of the `map` element). * A basic image layer type was added: ```xml ``` * Added ellipse object shape. Same parameters as rectangular objects, but marked as ellipse with a child element: ```xml ``` * Added map property for specifying the background color: ```xml ``` * Added initial (non-GUI) support for individual and/or embedded tile images (since there is no way to set this up in Tiled Qt but only in Tiled Java or with [pytmxlib](https://github.com/encukou/pytmxlib), this is not very important to support at the moment): ```xml ... ... ``` ## Tiled 0.8 ## * Tilesets can now have custom properties (using the `properties` child element, just like everything else). * Tilesets now support defining a drawing offset in pixels, which is to be used when drawing any tiles from that tileset. Example: ```xml ... ``` * Support for tile rotation in 90-degree increments was added by using the third most significant bit in the global tile id. This new bit means "anti-diagonal flip", which swaps the x and y axis when rendering a tile. tiled-1.0.3/docs/reference/tmx-map-format.md000066400000000000000000000433411315121121300206700ustar00rootroot00000000000000source: reference/tmx-map-format.md --- # TMX Map Format # The TMX (Tile Map XML) map format used by [Tiled](http://www.mapeditor.org) is a flexible way to describe a tile based map. It can describe maps with any tile size, any amount of layers, any number of tile sets and it allows custom properties to be set on most elements. Beside tile layers, it can also contain groups of objects that can be placed freely. Note that there are many [libraries and frameworks](support-for-tmx-maps.md) available that can work with TMX maps. In this document we'll go through each element found in this map format. The elements are mentioned in the headers and the list of attributes of the elements are listed right below, followed by a short explanation. Attributes or elements that are deprecated or unsupported by the current version of Tiled are formatted in italics. Have a look at the [changelog](tmx-changelog.md) when you're interested in what changed between Tiled versions. *A DTD-file (Document Type Definition) is served at . This file is not up-to-date but might be useful for XML-namespacing anyway.* ## <map> ## * version: The TMX format version, generally 1.0. * orientation: Map orientation. Tiled supports "orthogonal", "isometric", "staggered" (since 0.9) and "hexagonal" (since 0.11). * renderorder: The order in which tiles on tile layers are rendered. Valid values are `right-down` (the default), `right-up`, `left-down` and `left-up`. In all cases, the map is drawn row-by-row. (since 0.10, but only supported for orthogonal maps at the moment) * width: The map width in tiles. * height: The map height in tiles. * tilewidth: The width of a tile. * tileheight: The height of a tile. * hexsidelength: Only for hexagonal maps. Determines the width or height (depending on the staggered axis) of the tile's edge, in pixels. * staggeraxis: For staggered and hexagonal maps, determines which axis ("x" or "y") is staggered. (since 0.11) * staggerindex: For staggered and hexagonal maps, determines whether the "even" or "odd" indexes along the staggered axis are shifted. (since 0.11) * backgroundcolor: The background color of the map. (since 0.9, optional, may include alpha value since 0.15 in the form `#AARRGGBB`) * nextobjectid: Stores the next available ID for new objects. This number is stored to prevent reuse of the same ID after objects have been removed. (since 0.11) The `tilewidth` and `tileheight` properties determine the general grid size of the map. The individual tiles may have different sizes. Larger tiles will extend at the top and right (anchored to the bottom left). A map contains three different kinds of layers. Tile layers were once the only type, and are simply called `layer`, object layers have the `objectgroup` tag and image layers use the `imagelayer` tag. The order in which these layers appear is the order in which the layers are rendered by Tiled. Can contain: [properties](#properties), [tileset](#tileset), [layer](#layer), [objectgroup](#objectgroup), [imagelayer](#imagelayer) ## <tileset> ## * firstgid: The first global tile ID of this tileset (this global ID maps to the first tile in this tileset). * source: If this tileset is stored in an external TSX (Tile Set XML) file, this attribute refers to that file. That TSX file has the same structure as the `` element described here. (There is the firstgid attribute missing and this source attribute is also not there. These two attributes are kept in the TMX map, since they are map specific.) * name: The name of this tileset. * tilewidth: The (maximum) width of the tiles in this tileset. * tileheight: The (maximum) height of the tiles in this tileset. * spacing: The spacing in pixels between the tiles in this tileset (applies to the tileset image). * margin: The margin around the tiles in this tileset (applies to the tileset image). * tilecount: The number of tiles in this tileset (since 0.13) * columns: The number of tile columns in the tileset. For image collection tilesets it is editable and is used when displaying the tileset. (since 0.15) If there are multiple `` elements, they are in ascending order of their `firstgid` attribute. The first tileset always has a `firstgid` value of 1. Since Tiled 0.15, image collection tilesets do not necessarily number their tiles consecutively since gaps can occur when removing tiles. Can contain: [tileoffset](#tileoffset) (since 0.8), [properties](#properties) (since 0.8), [image](#image), [terraintypes](#terraintypes) (since 0.9), [tile](#tile) ### <tileoffset>#### * x: Horizontal offset in pixels * y: Vertical offset in pixels (positive is down) This element is used to specify an offset in pixels, to be applied when drawing a tile from the related tileset. When not present, no offset is applied. ### <image> #### * format: Used for embedded images, in combination with a `data` child element. Valid values are file extensions like `png`, `gif`, `jpg`, `bmp`, etc. (since 0.9) * id: Used by some versions of Tiled Java. Deprecated and unsupported by Tiled Qt. * source: The reference to the tileset image file (Tiled supports most common image formats). * trans: Defines a specific color that is treated as transparent (example value: "#FF00FF" for magenta). Up until Tiled 0.12, this value is written out without a `#` but this is planned to change. * width: The image width in pixels (optional, used for tile index correction when the image changes) * height: The image height in pixels (optional) Note that it is not currently possible to use Tiled to create maps with embedded image data, even though the TMX format supports this. It is possible to create such maps using `libtiled` (Qt/C++) or [tmxlib](https://pypi.python.org/pypi/tmxlib) (Python). Can contain: [data](#data) (since 0.9) ### <terraintypes> ### This element defines an array of terrain types, which can be referenced from the `terrain` attribute of the `tile` element. Can contain: [terrain](#terrain) #### <terrain> #### * name: The name of the terrain type. * tile: The local tile-id of the tile that represents the terrain visually. Can contain: [properties](#properties) ### <tile> ### * id: The local tile ID within its tileset. * terrain: Defines the terrain type of each corner of the tile, given as comma-separated indexes in the terrain types array in the order top-left, top-right, bottom-left, bottom-right. Leaving out a value means that corner has no terrain. (optional) (since 0.9) * probability: A percentage indicating the probability that this tile is chosen when it competes with others while editing with the terrain tool. (optional) (since 0.9) Can contain: [properties](#properties), [image](#image) (since 0.9), [objectgroup](#objectgroup) (since 0.10), [animation](#animation) (since 0.10) #### <animation> #### Contains a list of animation frames. As of Tiled 0.10, each tile can have exactly one animation associated with it. In the future, there could be support for multiple named animations on a tile. Can contain: [frame](#frame) ##### <frame> ##### * tileid: The local ID of a tile within the parent [tileset](#tileset). * duration: How long (in milliseconds) this frame should be displayed before advancing to the next frame. ## <layer> ## All `` tags shall occur before the first `` tag so that parsers may rely on having the tilesets before needing to resolve tiles. * name: The name of the layer. * x: The x coordinate of the layer in tiles. Defaults to 0 and can no longer be changed in Tiled Qt. * y: The y coordinate of the layer in tiles. Defaults to 0 and can no longer be changed in Tiled Qt. * width: The width of the layer in tiles. Traditionally required, but as of Tiled Qt always the same as the map width. * height: The height of the layer in tiles. Traditionally required, but as of Tiled Qt always the same as the map height. * opacity: The opacity of the layer as a value from 0 to 1. Defaults to 1. * visible: Whether the layer is shown (1) or hidden (0). Defaults to 1. * offsetx: Rendering offset for this layer in pixels. Defaults to 0. (since 0.14) * offsety: Rendering offset for this layer in pixels. Defaults to 0. (since 0.14) Can contain: [properties](#properties), [data](#data) ### <data> ### * encoding: The encoding used to encode the tile layer data. When used, it can be "base64" and "csv" at the moment. * compression: The compression used to compress the tile layer data. Tiled Qt supports "gzip" and "zlib". When no encoding or compression is given, the tiles are stored as individual XML `tile` elements. Next to that, the easiest format to parse is the "csv" (comma separated values) format. The base64-encoded and optionally compressed layer data is somewhat more complicated to parse. First you need to base64-decode it, then you may need to decompress it. Now you have an array of bytes, which should be interpreted as an array of unsigned 32-bit integers using little-endian byte ordering. Whatever format you choose for your layer data, you will always end up with so called "global tile IDs" (gids). They are global, since they may refer to a tile from any of the tilesets used by the map. In order to find out from which tileset the tile is you need to find the tileset with the highest `firstgid` that is still lower or equal than the gid. The tilesets are always stored with increasing `firstgid`s. Can contain: [tile](#tile_1) #### Tile flipping #### When you use the tile flipping feature added in Tiled Qt 0.7, the highest two bits of the gid store the flipped state. Bit 32 is used for storing whether the tile is horizontally flipped and bit 31 is used for the vertically flipped tiles. And since Tiled Qt 0.8, bit 30 means whether the tile is flipped (anti) diagonally, enabling tile rotation. These bits have to be read and cleared before you can find out which tileset a tile belongs to. When rendering a tile, the order of operation matters. The diagonal flip (x/y axis swap) is done first, followed by the horizontal and vertical flips. The following C++ pseudo-code should make it all clear: ```c++ // Bits on the far end of the 32-bit global tile ID are used for tile flags const unsigned FLIPPED_HORIZONTALLY_FLAG = 0x80000000; const unsigned FLIPPED_VERTICALLY_FLAG = 0x40000000; const unsigned FLIPPED_DIAGONALLY_FLAG = 0x20000000; ... // Extract the contents of the element string tile_data = ... unsigned char *data = decompress(base64_decode(tile_data)); unsigned tile_index = 0; // Here you should check that the data has the right size // (map_width * map_height * 4) for (int y = 0; y < map_height; ++y) { for (int x = 0; x < map_width; ++x) { unsigned global_tile_id = data[tile_index] | data[tile_index + 1] << 8 | data[tile_index + 2] << 16 | data[tile_index + 3] << 24; tile_index += 4; // Read out the flags bool flipped_horizontally = (global_tile_id & FLIPPED_HORIZONTALLY_FLAG); bool flipped_vertically = (global_tile_id & FLIPPED_VERTICALLY_FLAG); bool flipped_diagonally = (global_tile_id & FLIPPED_DIAGONALLY_FLAG); // Clear the flags global_tile_id &= ~(FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG); // Resolve the tile for (int i = tileset_count - 1; i >= 0; --i) { Tileset *tileset = tilesets[i]; if (tileset->first_gid() <= global_tile_id) { tiles[y][x] = tileset->tileAt(global_tile_id - tileset->first_gid()); break; } } } } ``` (Since the above code was put together on this wiki page and can't be directly tested, please make sure to report any errors you encounter when basing your parsing code on it, thanks.) ### <tile> ### * gid: The global tile ID. Not to be confused with the `tile` element inside a `tileset`, this element defines the value of a single tile on a tile layer. This is however the most inefficient way of storing the tile layer data, and should generally be avoided. ## <objectgroup> ## * name: The name of the object group. * color: The color used to display the objects in this group. * x: The x coordinate of the object group in tiles. Defaults to 0 and can no longer be changed in Tiled Qt. * y: The y coordinate of the object group in tiles. Defaults to 0 and can no longer be changed in Tiled Qt. * width: The width of the object group in tiles. Meaningless. * height: The height of the object group in tiles. Meaningless. * opacity: The opacity of the layer as a value from 0 to 1. Defaults to 1. * visible: Whether the layer is shown (1) or hidden (0). Defaults to 1. * offsetx: Rendering offset for this object group in pixels. Defaults to 0. (since 0.14) * offsety: Rendering offset for this object group in pixels. Defaults to 0. (since 0.14) * draworder: Whether the objects are drawn according to the order of appearance ("index") or sorted by their y-coordinate ("topdown"). Defaults to "topdown". The object group is in fact a map layer, and is hence called "object layer" in Tiled Qt. Can contain: [properties](#properties), [object](#object) ### <object> ### * id: Unique ID of the object. Each object that is placed on a map gets a unique id. Even if an object was deleted, no object gets the same ID. Can not be changed in Tiled Qt. (since Tiled 0.11) * name: The name of the object. An arbitrary string. * type: The type of the object. An arbitrary string. * x: The x coordinate of the object in pixels. * y: The y coordinate of the object in pixels. * width: The width of the object in pixels (defaults to 0). * height: The height of the object in pixels (defaults to 0). * rotation: The rotation of the object in degrees clockwise (defaults to 0). (since 0.10) * gid: An reference to a tile (optional). * visible: Whether the object is shown (1) or hidden (0). Defaults to 1. (since 0.9) While tile layers are very suitable for anything repetitive aligned to the tile grid, sometimes you want to annotate your map with other information, not necessarily aligned to the grid. Hence the objects have their coordinates and size in pixels, but you can still easily align that to the grid when you want to. You generally use objects to add custom information to your tile map, such as spawn points, warps, exits, etc. When the object has a `gid` set, then it is represented by the image of the tile with that global ID. The image alignment currently depends on the map orientation. In orthogonal orientation it's aligned to the bottom-left while in isometric it's aligned to the bottom-center. Can contain: [properties](#properties), [ellipse](#ellipse) (since 0.9), [polygon](#polygon), [polyline](#polyline), image ### <ellipse> ### Used to mark an object as an ellipse. The existing `x`, `y`, `width` and `height` attributes are used to determine the size of the ellipse. ### <polygon> ### * points: A list of x,y coordinates in pixels. Each `polygon` object is made up of a space-delimited list of x,y coordinates. The origin for these coordinates is the location of the parent `object`. By default, the first point is created as 0,0 denoting that the point will originate exactly where the `object` is placed. ### <polyline> ### * points: A list of x,y coordinates in pixels. A `polyline` follows the same placement definition as a `polygon` object. ## <imagelayer> ## * name: The name of the image layer. * offsetx: Rendering offset of the image layer in pixels. Defaults to 0. (since 0.15) * offsety: Rendering offset of the image layer in pixels. Defaults to 0. (since 0.15) * x: The x position of the image layer in pixels. (deprecated since 0.15) * y: The y position of the image layer in pixels. (deprecated since 0.15) * width: The width of the image layer in tiles. Meaningless. * height: The height of the image layer in tiles. Meaningless. * opacity: The opacity of the layer as a value from 0 to 1. Defaults to 1. * visible: Whether the layer is shown (1) or hidden (0). Defaults to 1. A layer consisting of a single image. Can contain: [properties](#properties), [image](#image) ## <properties> ## Can contain: [property](#property) Wraps any number of custom properties. Can be used as a child of the `map`, `tileset`, `tile` (when part of a `tileset`), `layer`, `objectgroup`, `object` and `imagelayer` elements. ### <property> ### * name: The name of the property. * type: The type of the property. Can be `string` (default), `int`, `float`, `bool`, `color` or `file` (since 0.16, with `color` and `file` added in 0.17). * value: The value of the property. Boolean properties have a value of either "true" or "false". Color properties are stored in the format `#AARRGGBB`. File properties are stored as paths relative from the location of the map file. When a string property contains newlines, the current version of Tiled will write out the value as characters contained inside the `property` element rather than as the `value` attribute. It is possible that a future version of the TMX format will switch to always saving property values inside the element rather than as an attribute. --- ![Creative Commons License](CC-BY-SA.png) The **TMX Map Format** by is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-sa/3.0/). tiled-1.0.3/examples/000077500000000000000000000000001315121121300144205ustar00rootroot00000000000000tiled-1.0.3/examples/buch-outdoor.png000066400000000000000000001413101315121121300175400ustar00rootroot00000000000000PNG  IHDR g pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-AiTXtXML:com.adobe.xmp Adobe Photoshop CC (Windows) 2015-09-16T18:37:56+02:00 2016-01-03T12:59+01:00 2016-01-03T12:59+01:00 image/png xmp.iid:baec68a3-9882-3242-8da5-4ea1264a2494 xmp.did:cdadb370-baea-f34f-bd81-7a253bba4422 xmp.did:cdadb370-baea-f34f-bd81-7a253bba4422 created xmp.iid:cdadb370-baea-f34f-bd81-7a253bba4422 2015-09-16T18:37:56+02:00 Adobe Photoshop CC (Windows) saved xmp.iid:d4af998d-4bdd-5c44-9a49-f490c25438fa 2015-09-16T22:54:58+02:00 Adobe Photoshop CC (Windows) / saved xmp.iid:73240714-ac59-6a40-9dda-7e1f8b6bcbdf 2016-01-03T12:59+01:00 Adobe Photoshop CC (Windows) / converted from application/vnd.adobe.photoshop to image/png derived converted from application/vnd.adobe.photoshop to image/png saved xmp.iid:baec68a3-9882-3242-8da5-4ea1264a2494 2016-01-03T12:59+01:00 Adobe Photoshop CC (Windows) / xmp.iid:73240714-ac59-6a40-9dda-7e1f8b6bcbdf xmp.did:cdadb370-baea-f34f-bd81-7a253bba4422 xmp.did:cdadb370-baea-f34f-bd81-7a253bba4422 3 sRGB IEC61966-2.1 xmp.did:cdadb370-baea-f34f-bd81-7a253bba4422 1 720000/10000 720000/10000 2 1 384 192 |H cHRMz%u0`:o_FvIDATx{p/kIl`[T$,!K+g)Hm9^[NS:)N]ݭ98+ T1xs/( %v˲Gd ,_I;owsRis{DEV}r(qےM(kF)ϾL#E9Ϫ+TT"TnAE*RD++@{bɪHEίj *t~[uuN-H*߯n -7A@퉙뷍O\U;0_TO{?-^eOAPTEN|6z^ /,ewMAH{stU^/+4%5i ^k"^k˨>&Ua=Y53ᶜWJK^R޼7{1rmϙ Q~eD7~)m&l1j|Qe%O>?._?]~(ft7YXDZNS OkkjT׆N| ROVcj_9ΌBu{4ĹMYGbR?znBLk?Fe:#=ìn{BRPߚ_N$9GKv5{t8_X_oy ϙ?R}/A{Qy40˲~u¬5&ӑ=ICx-}0YtQ[_&'NWeOV;_5Ow;(<(ƏcQ՚O!Q{9JqYGї1x5)l F1G4 ZiLxԱ}a?2vtmhʊ^Zg E`ռi-Xt~ՖΏ_+l"`:YnS&+e?j[]^+W~΃kz^TC}E)An!{uY޿qOƠdMm;BS?|;=!Y:$}|mS?4 hi ~!}{k o |pU29 _*A%\dj W"G.)QYY(tq*#R2qQr Q<ܖQQnxt^$l K|7n \F0ތ=dX? ZsROiIUK>* ."BѼBho<ɧ՚NH#icsXڧbox+_GNVfC3m W=QDҢ$da>_Uo@ 'Y:Z칗/}Kc+*'7SDe'/ک\WJɪ@?! 'a_! Υ9g9/tS=َH{5A9~7i-ET'jʕxG$U@P@< A$FU)ymSZ9b*4ݼ?FPa Hޱ{;}CUԫH+.DV]B-򯌟}_>:;;aϓ]Os;%뀨H09qʂ h8QsQUV_>1~f(|h@.Z}ь8}.T,u D +=tr'͂A+_u"8"X4~f\$j㓫s\-h \-H{EtÝE`2I]y9UWt%( 3 ,U$?'HN8D^X?9ŝb[XsMXm EWxyQ#,K81`ߛ7sPr pA ׾*PE{qTFf ? k|W?FL|ߺ>Ջ4`*l@KZ-Z"dIɘ]>85>QN:z08ϢIP9os 28gţ%hHtM($C!$o`˪<2k]gwt#Iʟd_2lhx"= Ϙk]9pC6~MnEM2|UV }?gƚ8eE$9M⏏AlG':^XŨ&َȳt' _ܚ|@݂G}@Aa1qp`_kE7 VsP7Gޘk@mάA'u ב|zGx%M'f Rj* 3T]tu̟3*o.'#H#R*?_+EO.ɇ?-+#7gW}QAp"(ʟ?${ ћS@ u#H`DG+JMkrdqƉU9IԷ?RuTBW0,05xq }^!^6{D1 O`:i'=T -a_'_t6) Q~x\ 73o]*d'A!O *YsvAm?a,8{)*d9 D幟D\g~&ϟį<41 }G0UȪZ( 9é\@a' wa8OV!;T.DeRB L 0+o(V>RM H"]'dIsχJȘ<3O э?{A A (!b@w^xJrܣ?BP; +]D ~=>Wd8cG \x/ +y6.D(W7=c\!\œ;2~{N^n5=|Y^XBTuE3ּxÞs]}D&R 7:0Vɫ0ao!*[({۞+kH(2~ /W}2tMDw_4WOU!Zo{& )kg疐48Ոd /]g|_A%t386nQj:}R!j<MϧF'fWOɞ K饝}V (hO&cxbm ]]эHiqN$j T ~R/(:4ʥ% ?Q?ڌ2tǏԣ,{pϟ ; "|!\ v{y 7n$i|~_ 4[әRF$EU'W:n*2 bd#O.LU㧭TraǏﺼ?:|׾}! ^4gY²ɮFLx=/n{a)}e"̾dOd/g :˙ (sG/dWm zrWaOT_E =mf ۏK|rtfMC T3DrraTyQTW8Է: (Jk WB[zv-PE`lD\^S?l\r\vⓟR.jСlⵦ05//yyDO7iOey]" YU{Qf+L+H,'7:)Dr3\p^-+V]D5~Y8dWgOF5~0>'8/dJϥp&t[CFbεM]^m)b.׳@{#\n@?(񣺯}=݂n|0A9kß 2ɻ'FWu+ȰT)#5kϷp(+':}ģT@\"~Ex͂!WTj_kys Oޡ"1* OXilY=YJ=?_Rro&DVW~8?We-|TOtBJ ڳS޹n/|P2ޓlB2S(llT=?QvJ:$gOmry|Di@Yx2haUsܣgAuRR w_m?G}lұ?QD# t(DX|b` %(Yz8d3WrGg"8@ICatdXJՁZ\&:!Gj&cHCP9{yCJHX Gp>ĺMYL ޮuΆ^S ֤u Υs#5aIVF 6htJSL{?~F>beLn[gO4QVkbռ,}?:}TfL?Sj;~ !}$w?l藓{U/ TMLįrK&3?qB'Ҵܽ8~:XʂBB2;NhݞEP>;2Ǡdåx^S%`p'dW4cOԣb-f:#潶74*'?ZPJA#M~\L: KJ)s3t;WygNLn dE'9-7B\1P|scH +}7!<9,s|lBA!0D׈5~$ό &q2frc U?R bdɵi<]&Oj2ۓ-\ @J`>D O׺,+QpSd4'ežTd[ӝbTW^dnГ7dc:dGs:@fR 9#vtO@ʱi2OMU۫w>e=MP3Y@ĆZe`~5 ^thҋt* Y!iH^Y&nJo;&ItU YWU<k˔-i* p.򅁨 ߆G,< ^Los$h15~H8r׹d2X~U$/}s$l:jmMrzH1/Pn~E?,xM݌)l ϳy8}?ׯU !xi_fnR?w ;*HA**HPF>k<~r' 2~962AR?D?x?,ǾygPE-D9+,wR9GX [.g&;f)銌6}lfкG}=HVA˲F&~gi=+ΤM~ {Q{a! ]ؾJr Y`M2~2f^"cM)~k^f{0,v 'N{ zQɆsQOV,Vk[8Xn㧔?щxۗ~*Т,WOUB+{Tk.AXO R< C<2(Va\Q@.ЬPc|?,4x>!TjҴh.xE~R6@yO.) r!*X:1Q)Rr?rK -gIs4Y.`y~lB~5^#MĆQ% jڨ>__Č],3H.fReBPved Eǐ! ?aFepEgOrwՈdWcvS7 !CF!"YItA!:gNBm bK2T޾\Kﮦ? c!o9Q6:֨Bװh~lp,a7K:_=N1SAӹ*ë } N y:ǖ{Ž̲$ 1~:KT~'jy`q0gt+H9UrZS@@q UbuY4dp$ #1_:t1Jj/C@6^]^x1WS30y5rM  r qi!jgy?@4!ӯlG'JPA(7C +^X C)~rQ}{.OxKy`M9(N]:yulC |nB%*[)kn2n8$p12 4 @ ?a i+Jy!א_"3Wv݊hR~p*Z?+4BPoJZ)U{XGG}@\* ܶ~{wt雍'~s3Ί@T^4.66p@G:0Jʥx`qA|kIxR# a>R~#)ܟ\󁏿[Z޿dyeTŤ8{%<2/еTpb(g!;o:u݌O>!O9eeY?z.>:\~]2-Ƚ @'cR8=&n%4Oi䍺b,ߏI# *LO|_2q-&N.+Lw/Z/G^ {jjz_vOl`sp3Zaw;V.zJ]"G.+LG@߽j]BߏA>C$IIG?|e\}ьH)6n=׺ >@ JՍO^yћћr|? gw7oSmߞ['юL㪎OCk?yá:P \@ː[Mޖurv{AS9Cqţ;*wf}JYTS܎+/wCJl\䯈!o}!|QW=p%>)Cp;fk9xI1Or*h!//MǴt tJ䔹=]]kQ]{ ozf=+@D^)Q:<\ 'C0d7nes12M#ArSؤw:m5~(-I9mmIwuO?P~Wt,x@@"b8-Rݗ\d>T^ux6\I5R~bsrk&*v9+AuaICTߞzQV͛FN\ay)J]Dtku"ɪ,6~vtwѭ_N.O/D{bƱipM>n^1}SmQNV2:_NC_]3J/pr$!o/s,3/~-գiL 3?BdUOg}>0~un$o.> BDj\4'D4#‹*9B״PAT$EQ??9˵YϯRG+yttbxnAb``{^rk5Za]FM!K{&QDaΡyHeD-AUN[)0{UTM4П>,*P!R}g9|T2~JATuL7ĀScYE-T"ȅ*F|JT"`RGfԺlgOu)F$v?T&+-,ZH\we-[ ӯj[ "HEcY s>|t|ꑯw_mq QE*RG菇W>")|@뿵xP"7ٛ7GZﯹP+т@߯rKύ@"a@K  Df(0Jmy9=pк~*F"A_Sf^u𤒶*|p<|=ޅ]?~-, 9Y[}׻F4-3ܹe ߳0|tߦe_?rVܾruݗ @~Aw_mLVB'c@bDu# Y@>30C.A7]*'VW"ûvh =7| )l |׆76utTp5ߒ]@" ƞՈ^XYMMV9:>VK(䢔nfTT7Lk"C73W#@"f;+8np|Ø4Za*":^7vfsUIӢ6q>:.<̎doR*,]87zNEK/)N'+mzҩA$$ZoǶ6?4 jL4 zY97Tu1,dԷz\l &ojhQ“ZUM#ժwWg6I al5CwS*>y(#? l#pUmKʿo C1%" ܞ;bX\zx`)ҥd3NdaFǬ{,OpS; ٹb"S`u `4ıhZ0dJ L\f4a2m>&j޴>L9[ XϙRزA!GvnT' By3ܲXJ ,(VUdb0z 76mG6LN[>ffGߠՒAMT&K:|'fJ!7_ec1|tc=R|.3"`pQMVayw^^&sif`ݻA;#<}m˃Khc[>KRΆo%eMfIǓe)`~ݹZGu,<0F :!yKѽ4rhr$K e U-6 /Yğх `,PSD3pRҜY! 7eγh(}iؾˡe㠂w*{A?~bsw_m1H.fh'k)~!^ J$=QSQ"> ŜŘ<M#k`+trϚM(8ݠ n HSּ>d&)WvޘIr'nF|W = 6Iv?3?$ OD܅?d/܂?G~/?27+&[hzwz7mUSN{I7)Mት5ôLfpLВA  METOO|avnl^y0ca;ֳRϳJiUO(egs"xj4݈5Ҕdu(į~nʔ|"d'yɏ>Uyp؅ "s_q<#doKzTZQ?v9v` ^6 'Y[𒵞ן`KE}mmQySJshKDqӢ5~G&b0Z\nIokk9i ;J5 ͮ<;=`D [6k÷'u9uoڭvh o-rIfFfz_3?dd1E$?=1"0rrntݨ[Ѐwa7n )+lRso _] qT_GppXQ [6n0nx?>j*nehZ4LLVgBZ`m \'YT3$I~PyEbUs,AJ_,."*GEc3dQx(Էi?fع1c7zm: rT0 d>TC=?7ޠse"*LL>~;V᣻pm_j&˲7 "\?)s,%rs, ^l!k裋s+7ًϐu j( *l/V.kWOUaH:Hqą*CᩓL UoM?n ZG,ނKqf\ g>!J7iy9>Zj(vl(j=yWv(1[}X߸|ȉp?7vo[d`0];ً?$OkWm3S[PoG3hk@"X=W1L~~Y /vu52M5o)#DbR cs8=1 87:-BMb*߻/yM#c@ P+]Np&[RB=mx$0YBԠXz-ǏxBt^051eGVގMV~ۗ( 4 /2h-ޓuãc1)~me6XƠ5¸rw(a@ 8q:7?E [WMvtt{8r5D$emD;̳Es8mM+A,ނFox ? AVh&=2 d:m= W]%ܾY͏ZEa^pV xH&``-=dZg._y#dPlH{l#–WRu X56z`>;d: 7v GОoM.hqg %|3\6ȩ$B{f1DR o=چ29/"5xҙBl{ :l#жVz1mFb3yDH㊵OT(Sxbm]vM(/rDR'ݪcmH5W!+O|* hݚpqȑ$vg_m<*:s|@ܲ1'@ǥ1Πޚ| jM],`,Odzg '21Ոm) 8i[8~P>*!q2ӽo–&a\ђ/+~.D mٞ;'S[ƺdɪ$(ro{۶zsǍYON>hH5~Nʟ$+wlp 7c.WgY |ƙ[Lϐ~Tp='pҬ~A TQ>p+lY⎈Nbu#`7hmm,bEp܌"D<2޲& |rI9AOVtQML Rܛ3z:57i>g)JMV F OtR̼ 94v~h4)Sؾ5KHe QRdL$~Wvވ<]?~ rqXA5'@ j?eGT'z9,vB[Al\_MG sY)RDUsQpk ǶtFBe`ѳy)B?/]" yr[(W2CǐץT޿efbNo8kVSPg ηP?~XHzPO܊@Tu*W%F] R(AU!Dч7WOU!n@g;:TI$#@J;SF' }oȅWҜ\510g%1Es<ׅSFR&hFW7gHG+rj<;>^rjk׺ ɴ1Ѻ䌠i&qhX,WglO̶WF0A<`R5 Gany.1$ dƥ]KBò!N颙^w}Lypg?&hhrIlJuK¶3ABnmT12 <]C.;>vXW!S ޣG;{HV.!ׄTyya-p\ ̱)&oTb񖜼וC=ЫdzwSH LziAEM.⺃/SUos~Oz-A^7+pLUK5e]?e8 o?//o]כ(ɮ%Tߨ^Q/1Z9w[0|BkLwQep]֩j٫*\_()LPDvT=g!nRD,2r&j': ^V 4-v%24 ̟3RE@e r~ћlEqnԪ^ ‹/< J?-m{ag>+ ?gc/Æpƃf5)B0y5.+ZXU&{x*nij47/X%o)dWғx`hBw9/"'-u "\iMs`|w2HVWvM._E# _9ϭ T/_tJpSAy!Wnb,hӦ4a!(EYP:AM c|?ϙNUŐ;n*(yY69;,:n#/؇OZ dBuRp))X4ARC"7*؇ORL4'q8H>(GwH'[Br#D)KJH Ɔ@]&23(V) 2 /WR݀d%cϟ!2+:4,C0;~8/&rwZw5j0)`u&_wg;:M{* Uv3XG\?V1eGdlt:H7o&LeFLjHW *_j_yUb*b7tKptnt 6 9tF.\@D=iP=W;&tig8&t, PߤltD $5gtCjA@0r}vx4CP6$KHR`5)ŌI)XfSA/dW910PkbP:P@T*kMt<SdX@gp~k`P@:Y1N?0zN:!tnt,3@WmQ˦!D9* چB@BAMǬ#&{)׿,bY0D'3<1Qnyt@=pJ4سYݞ ,/\mFV@pEŶg.s[Ѐ߿^ !+lH@EֶʟO*+&=|KIjI19CVYِu8rNMZ}Ά꺼SAs~Ÿ*cKtMvs}vXxvLGfto"A& }ьӍ2 'Gq-oMMVܾ7>7:f쳕H4mύ1~*YB}(j֢m& Tţx pdұMQ@`i }_HxaFj1O<ׄd^< LV #1 ޲m*Ќv6-0u?)URyntLLö>e6`I`r^\'`IsPЮU/vEךVHg4>LI`r\g7"  ShȽl]R \@(l9iN9M{b7Y˩kjPczB"d|it0̸GpA1NĠiR ނ=(&^G2D!"3qdj3pvS=۟ _{Do_C&&C"*MV f#hY+ '^&2(TkO#_B`> ;^cvU{b-HvY 54vtTǑbq`nՑ)z?7U{%!ϛf # srlaԤaМy2V}OS&xh r{A(ooڎgZNMVhBV}է"BǡM{\̊`+Q2i-RԠTb&֍lG'{Uji+A]Z}l]Q@?~taT63 p9|;70|?, yUP[6Uvh2`M!A c ?C"v,frƻBWM/Վ ׊K,"d{f4\ʛ7lX7b0=S*kÖ߽KI R 7ůRM+ ^R[d!CC5R+-wղ|Nr r1)DBC@459N&y+yHl I%o-s!PLOUA*J`0/{BA߸e#fOpWl|bdͯ7^;T^ԡW2Ehv 5a0F %ejRs]֑me))3^k/al7.|am,.J>0Jɓλ8=xi' >\ sd`dqF֯Cpݭ_1pWsnmwܚpq ?v  xy?D\Z8霅wd<3zǖk[B ksMF~? >0JI_)7ܼ}=^qyX5o+93vh Wjwu8UO:֗U|mslˍ5ךB!a|N)/ך'5i=1#L!e+?Ww~}E}ws,M+Ц!S "EJN ˓?L?R c:bN"W>\ В*2x0ʝ/τ)|VyIES>fxV,)1[ ;! XYSwJߨ;#TMmtJ} Gp֕ Lw݂4dR$PSl:L7W?RJ+%'ls9[͕?l?bKf0NnZM{^#U1ê9"2TLɈךl^U@s GʆG`Ics0 >@\?ﱌ@h]traH򮝎mx%Fj;ou7P 'f,?N]qϭ@:T0M kO~2*Rj{@u15aVy/~z*(H?R*%JFm.Ў[yH*H'a08]v!< yTN1hmFo!J# Â\懆 tuzxm4כN q@5!];=y8WFzՊXlJ6 !X0 F?R2XtÉc0A۬^/Gk2 ^54ǠO$ķ7 + ZrWaY gxdAќ~w\8%7&$g;:X7Q-SlnȨI̘}Qi$SU\RQ{\sX_\3\ E08yrJϫ= yu wR~>@i0gn(K~<$V(EJ}P'N[x囟" h= Dh,?g$+Ҹ)D@рW?R8 z~dg0XpxA4V+gef80g$ybE,ނdhO̘x ? `tH!+ Z({6:^ȮUMHvCm#.Ų/w(K ^T ᔠ^g4scU2) \, 9r["+~ļn!;\ 6nF@=|! \CǀB1Vs`ò`rhM+-\.<ʟ+'-*-E'jTK 7XA ed$]kQ /:c,FOn4hk8 tQt~rH$Ae̼ (+ P?w| ;TOVU"LLR;G.;|is1`ٰٗPBn?plicgDtY&l~Ȫ3irRh18i/M݃WVI窀ZXs{Qd\zJ/zP\@!Pk˧0N~ w_]pа?LP%;|l>r=1o4?,K :~HڹEOD* +D,sY08rԆ0h8Oʇq)`$ࠓS.+A (l?zF*>WF A]{(KKnoPYs~2J俅-TCXhq=bȿ2 ! ؇_:? B_^w_4cs#fcCè[Р$Ob{0MQ`$F0~Ha QҲ eux sfp?F"K)oŰ@]*T! \wW`E_x1Bȳ(mDJ?9ΖEvW,Zl^  6ѴhL( ozﺯ2~eW[#Ʃ[%cM;ɞ=ݤXA$ :#O!a Uب&ߨ TV\(IV ?(jlj*%ݴC|#覔YE?4` OD 6=C"a-]hyeB~ǟͷO|^v#{XnlX 5 z];$xYQF?-{2CԠ@!&P(Ş< Cvj93gPH摠J#}ьzl hSUQzJ4\ms%gUR,Kz3u$>6Me9u#Yճ6}BN֮4I~7߶yI\ycY# ɕ7*a#.Tunt ." x3oMg7gm6' 4$](ㇳ? 'fDOé`X>B@&瓜ֶ}J\ Cx0!7ᖕ"a%QVAO$GV/  >Ȣ ep˗' 7/;cmxP\O+_!qϣgw ύ}ьqntLV[H׷jB@:0>zU>Bq(apm¶8UHe+uQ;SxRqۗ!^kne%X5@X>ȡ4v_ߤ} Ei?Oe,ނ;xD4|w :ӗ5q}̾t :nnhPsvl߅3~PLw_4c4\;~8ԠscX\KlɮF³A1áMC̘w^$N\.«%@"LU}<=+\< yռi􂲃x{<ԤaMBIs%X{x vt"՘Ɵ|3' f벖g[it:+;oޣG<|蝢kjZ*iRbM6&ucxmYRWsiibQ*rP}zτgO=q m&VUex?{ =FK)gfe֎7~BKgϝҚ)QB%TwU ]؍ךˆk]& V#8bĺc-p̵SVsD OOK7rʹ:lRg8&xJqm~ۑyU-z*(|w&mpȳm[=)"!t*m(ETQI[BZ<@UI*&3|ᖕ0RIuIsqA2}pSAb0ɮFQv^ hVܾ.]/2uT]2SkkcQc[-yQ@추5kٗ.6`K^l2gOQˮz?3= klYմoE$M,EG&+rpkqP}>L:l;{hJ3<Uf[W',Gğ0V:DEKwC|}wJ zX/ڡXTQ꿿枬:s|5[157"ZPN ?,=cK2ޣGVU@LMs8ϕ7-#yZʍ臐3%~.wOko@,ނF2!۱/BcԈFa.9m /҈tL S sfs{>ƕRXcBxۙNLOxY< m2qv%T.|T">3~\9ϳ.Uz1wuY۳n\Yy:Ѕ dOd??>tjJ5fUƒ߀߿#iٍ ՈdE)h, n0~7V6t(Urعe3B@畑/"8,#0h{Pd G*pP&w/{go`pmkM3:ċ߭0L\G mC/ar>~Ѡe})J;'Ms1Cm$oϷq 6Ne5t!. 6)wK>:<27p%UY0 $4\jWZF"zh5m{+=zDAhByE9HprO_v8?2wj" ?5`k&OZ%:|5//}y5"_6r\eHy(+5Nhi O) Vv 'NWhd(臠PanZzv$#IuJ[O1K rNGp˝X ə44R0{bAǽ۲ю 'uCx:?g=$ @NG! -73hZT(fy'3mrv2GZ^OPSW]s9 V-sS*O,M y~~L^qpdu[pS1Z) !Pocg߳yH?˽h02:Y3yԠ#4!LCJk CX,P5.4U^HB>&^>\>ˍA9u>G--i]Hsy|^|USDL ȓI/l(R&y4 S#pܭʖGW6c?&IAsSAR!%KŹ|eg?~ BRix FAVа#5V]sHEjPٌݿ>y@L2j64#hOv;Gy|Ŷu.uct)䅧@yi*-zzWқ2biFʥF5ep1RNj}O`2hE@י6Z j"LxT, F eE]zFeA0zXG3tնZә?Yp*& 4npwVPDiYNl:ǜp׻93ޅ߽TlȭC U·Ǧ9|3өA V >ѩ^U &V*b*(ܘx)|Ǻ}ݘcA[V.~VOQ,FfIENDB`tiled-1.0.3/examples/desert.tmx000066400000000000000000000013161315121121300164410ustar00rootroot00000000000000 eJztmNkKwjAQRaN9cAPrAq5Yq3Xf6v9/nSM2VIbQJjEZR+nDwQZScrwztoORECLySBcIgZ7nc2y4KfyWDLx+Jb9nViNgDEwY+KioAXUgQN4+zpoCMwPmQAtoAx2CLFbA2oDEo9+hwG8DnIDtF/2K8ks086Tw2zH0uyMv7HcRr/6/EvvhnsPrsrxwX7rwU/0ODig/eV3mh3N1ld8eraWPaX6+64s9McesfrqcHfg1MpoifxcVEWjukyw+9AtFPl/I71pER3Of6j4bv7HI54s+MChhqLlPdZ/P3qMmFuo5h5NnTOhjM5tReN2yT51n5/v7J3F0vi46fk+ne7aX0i9l6If7mpufTX3f5wsqv9TAD2fJLT9VrTn7UeZnM5tR+v0LMQOHXwFnxe2/warGFRWf8QDjOLfP tiled-1.0.3/examples/desert.tsx000066400000000000000000000042241315121121300164500ustar00rootroot00000000000000 tiled-1.0.3/examples/hexagonal-mini.tmx000066400000000000000000000014761315121121300200620ustar00rootroot00000000000000 eJyl1FEKhDAMBNBSt6jVaL3/Za2QwDAkVdiPQda2zyTonimlU1N6Ws+lkZ6l56AUXcPY2qlniv5uL5Z5BdyDvFXXMoX3Rp44axl6nqFejj3LLK6xgmf3Zg06Qs+O+qiaDOZOVgXPs7jfCme8Hkce1+fNlGdlM3myDTzc580fz1htW2Baj15/R/J72wLvcVZN5HnzGnmVPJ5hNH+0dt33j4ex91TARUs+WjNZz/fewKvJfy+/1naR+dX7OfdEnUYefyOeZZ7Vht/b5HjefxJbO1iTE7YWuEpg5hfPzi8D782x3Mg7DV4= tiled-1.0.3/examples/hexmini.png000066400000000000000000000132301315121121300165660ustar00rootroot00000000000000PNG  IHDRjHE` pHYs  tIME '3D7IDATx}lg?󶳯kvM@ڐB["R݉CtHT=N!z:@wSÝګ4ΛNw:3;3z&Y{7Iyog<۶ٴ!xyKWԄ}w~ŸB{ߝAE\"UE1SϮ\:Q-__']?oKOmusB+QL|(1MJ [ןý½{5g (Po2@ cL@xU0 Ԋ20ț:P"n1p)`'ȤtJZ\@QeJz [)QȚ| pW-=W07y\񚝯_pC?.z@VIC ܎VIc~!0/j% P""f-u}s{D5T,l:ADJtxBE+srƑX(2Ԗd2P[i`?{fk]wh7{&GIaF P{mTϳ@4 ' ,ʮ?h~6JzԜ(Uሂ@goXBPfn"O (  ~uLh g@Psgs% _`f*[w^5UW7cvam_?s 5Drá0WP" Dž 7cfz=5"ҮPX,`F7L$5v2GLfj, TQ w]X~~zvsn3OW'~;sƏ*i5 F1n?SUlvA8ee˅%ƒ nNnxstb^wT(%B6eI:QCVP̚:%v2Ԗd-R[zp0]pu~Cm/?&CmIf'Gfvy7wh?Q shVfHߖfk*slfnðW~͂kmwuUuvHj"+ eP%%̲(Z iTwN#ؙK͟G_\{>WM%_r۞x걋|C Q@&Y>PQ3'9TUiafpԣ%S*dV*ŜmY@GO^AB5eEs&r@jx/:p9 p!&v"jyf_} mjn_si3;|Kr-62)s8`Nonk-ú뮻j>_b˰q>sWsO}?(L6u,@6u,O?ęɖ@u]M7T裏6  [p9כuU%Ԝ{ۚ{nEמtta,9I{LbC\8K ^־׾;f411ѰzV!7t^Lr\W wܳSXz.Jh >gy?l;_Vw ?É|3"*qgNuddsJ2o߾=[o3::at 9VfMb(sN= V=HB@d$yu鶭 kG80lMaGIQ٦&Zloݖ 4ˎ7S,  9zP[ F?oȏ?P^0uፎ兔,MVLBqBh2IMSO.Ϝ rJ%e>uujk)F4V?siB{hds viM̚H!kMNB?l?Gfv}^]k9iLnؕ2S'{`'K3-JKtڣ ^I4̬}v]ӧ> ʌ;% bjBqS*c0DzJ#U*_=44L@J(]mXKYA"LQH5!l׹:rI),1c1vDPc'+@8]dpn(n{;mGg՟qJLD-< KU1lzxM5sч?a>پ}xxp4MdgʴJHbXF0ĩ.QJ(muUi(a.Ma7zw&rQt\2bmn[ڡv!9o>].y=Q{n@BI (WHhQP Pv²- QPQ gڱcG3hʄ SHOiDAJqi"n|]mPbTDc䙥8y)@5JFb(dkXX!fd(v4 gC ``tm j E숅)h%L$W KT̼])!U%eD";8^033&q||׶=wVʗ/\%eD~AgXZX4pwjܤAt$Geab aEQ|Uoεzk9J7 b66($)+6^&b"h[(M)jtto&耚a=zt9̞RUP~䂉&{=!{yxl- "ajX(tBgiy5!ŵ+l 6@'"hA8א%Y oHKTUĬPQ^!йrffc.gґng<ij۫PLmXW M8jS :sUط=_JK/J⫢Rֿ J6Sb T&, H-#I2bh[d͍riѨ k~jvgr `r=!rk y%\`ۖy " 9nΨ 9:,0*ghV ìi&6bnq vBfy~:qb/$"\pH* f{ZUXPWoR=yU^YJ EA@Jl[r;/nF9o4p` 𽟜~\y5ˈF<%#a; Ȼ'6."K"+jN,Ϟx}[{׷C=bO+/ѯ S${8$Y r{ԜmC9tjr|)cK{Eϧ)dB\KٞsJwN~K >uo~r陦LtY߱e.jc`/rrqIbk Oe.`fYwѻ5G~Y@=oG JT nh\[}*?G{hǾgzo}B먯Tiu P\ P%pr؃8 SHNsOgg9|4 \4)-Q7Y9V"is4&Wqif|4̩7֙9}jv&Wu vB rTLa9N_xRu۶mt: /pδmܡw3uKޅP[n,ia}4T@y}¾졭Wb:ɭJ3K5 _ۏr&E"b(rcJe=C,`}UC@:ݰxA9**ϡ-hV 3yڮi'(墉a[z{-{]k9ה'3Y8w\)s{7͇onik6PkCiT_QcE```~jTTvf;;;z tBzE|'T )(# ^E\Gܴ}'nARE"UQljoeoC8[ީۻMUx5h=`|h4njegRdڙCTxٙhX8t 襪6+֔mMP jT}mN`3O>:FB]öߦz }lAnW۶9Qn>\c1erG~Ƹw ۛZ=цꁭ>6ϦfF6PmZmZ ZY+MkԋO$jzުհϦ5)ʣ׼~Ϧ5Wy<-8oM_ ?T@7[ygw`_,?6+/ ?狦r)MIENDB`tiled-1.0.3/examples/isometric_grass_and_water.png000066400000000000000000003145741315121121300223650ustar00rootroot00000000000000PNG  IHDRB¼sRGBbKGD pHYs  tIME#Yw IDATxy$Gy&DDfVfeU}TsfF3ͩ˒8Vl~j, ??~x>keɲ`d. GH33=S]]ufUVҠ[ꨈx'x7x^E{^E{^E{^E1ۑsƑsڋ3sÎܝc/Ϟvg. #ws^,>=`g.8g<_##?09|.{/mwO ʂ:Aۢ?Qy6I/O˘U щ}}H ?+ׂRYl~n;sbSx&JCmԠNPgqOaV}uw=[(wʌ f|*n3ץ폄aä?5o+!1vߎfiN;Z K5}{ iL+ ̰m?ry@kflEŏߗߕ^ 4]Wٙn 8v<"G@v|oߟ[2hس۷_j|sw\?MR9h+Fӧxa,~/lB=ҿ./cܙHt끭k<g‘t%:mexM B:1_C%Z1~˅ dZO[2&YI V֢k`~-<\(ϲ'%bgD1rmO$Xri%Hwn#$G?}5~GϺZES aAZUuà#wRGΥ^@(7ݷ9*㟾 >%ˍ_Zkɡ"#e>TR'𝽮@zΟt2Y 3-qG%핿E 5\M$fܶmUWwnv4J2q΂}\q$Mߕq;2}_]fٗc=ůƦ`{Ƕ nc|Vj0QkҺv\X1c>WaQ<:ny t'w7{j.U›&2]['O]w?m`H?{y,i8r0MƮPn{-qvd|q]xlduNKѫO Fɞv=ad_0.8]e6h܋2q×鲌P<6hdT.m7NΑJ $>.~f'1J|\tE[L)xXZQnU<ƕz;Nm5{`34͋-:BzC\N.V/~s >WR@և>W[_+HX6db&l@vUGWV ;=r׿Zr=]:bV]]oM.ǜz_{[Gw~yPC  Oͅ7Є1 \H w$߿KG$;~Aqm}:ᑬs;Uܧڭ|{?ZDAVb9]V:W?5;@)ƎO+-5_>yn&R{E{&zOr=J>[)ch4Bs,4z9Ys?r ?4~tO}bC~Dt=n@?up EWY OnݶcYveh'OzῼK Ax076>yk磁ِTJg8G'H<?ٶsysq!ҲW-4󷞜;6epVP]{ꢩ1vsp^ȡqrz+~jJ J4vݍ)+$ZfRLRdW}q iz=p&&7oIN2OP/to3ɐ`t{/j\zgһkr{iY<(~D 4^G#w__3ͳT}fㆡm0<|\qk*5G0_{d??&P.-/R̩ڡn-qG漝U>e%5jѳ;SOܫMu]߰ 䊱m/N qWĘI3H9{n|oιb~\ gVR¡6=lA۳򚣏L o)ع.cƯ ,? -f8fè>؏(L7&C;rOa~ ,TK:tдMze$aOsfzT^ӃZƌ%uMeUr/dzcC ֛KG{f_VHN47l`3p.l8k3?8SGOo)-RWNG]7nN5_78@d6o]:haNءVn95NOzV[>3/KbP\}.mxCwIyjǑ*&:j9*Q(8$AmY]}d.(mLݦdW͉dJ#A;`gܛ<s%N gxn}}h[}'1'\<8ۿ@8ў."[)L˒-Ǻo{"vd}ih&װi?mLd~UF{rπsy iEP߰.h-1]`#ȊIg07o c/J%` P$EpA\5pXaKᦓOȨo38(1fg?ǜvp ||}UR$#ww>$Gp~H&..1$w%x"Vs'˫JS;#![YfNsc䶻r&YFG4]1b`VtAWQis/4J=:㴔FgWMQ Z2:\s|(QP;8E;j7X) 9>fUjdҲ$:xs'00?Dz&|[zz#g.y\,JP>s9+SqM{0Q1h7$@?.`SJcqxwigS#z|qAL@p21fVG䙊s'ŧ!;\Soϵ?s'9p7&#"9<;fj+aᵚ|<Ňl+knV(ܫ0nf\C]KF-X` ZG@ 6uStX*E]o:*5B92QJd4y(![nDM܎hũ A)ƿ\\-91Ռ0vcJ emzk4& 8priN^[;%Yc1,Bh)A>8w$B)+Ua9q;_qv+첕q<ϐՍ:}_]ԼgH ;ɍ1FQlgנu^ӫ֢?ܨktĶiLI\_|_D d|BGsc={E6HnߙMV7Ef;gB˧Rkh%Ia'Ay#!"iw,Av-T`g^(d]=7:J}4ptߓŹR~o78ڮi`4QF(>RfRbcpew)cz]N$ɱW*ڇIsm)$VLW6J4 lEL@]^ 9'2}jlo^}ċ؅Q]fM[ҸKQ):." ÐbB #kQR/iOL-hEFW~qNi#C +bݟY,_t[ؾx>dS;W0Mzx>٦40*"s; .[~ϛ훘1^д˅//r70&6Vyg1Uum{V4A n3B3)@ XX㙮ZdFP}޼]yb{T7RA'Cյ\u{ uYU]Iޭ_sC:p>(N307 R*uZ( h|)&BINw36vR/N#;ߏ| 2d~J &k@AEq!C\F[M&* {\#պxUa]!8*WԎOD,"D3(turEx;a!tSڬښ@qGOS6 9j':ZGjh6 ue{D`)@ ç^& %X%I2Rc :AtkΆ!7>2pj:h8w|Ԟg5u|g+ג6n_^f]G]O[ʫߔz\vM8ɯձ R.W(K^;~ObbxQs0 Bj`X <  W::dٔӡE8}n1Uj!oeæxI઩6_]75IJ fgc<-UsNv;"bR'FGp0H 9i  lCJDG2/1J/i2K]tY%7w8T8:ظ5`1l٢|Wq8>G` a|#XAѬ2y V׏FFRt4pt~S xxʇrq$*kSٍ?yv)B$2)?JkF>5Dr+X,zK}C}hG>xuQGm -^_ӵ8Y# Dz!2R(/ 0¯SmE :x<$A`IiJFf-%,M}z=ommuIm5s=ei#}_^K=uZΗqR}҅Jm׎eGFNڪ %~&7n$}Gw\t~K+plqEKbj])J3Э\Ug]i8ded" H@$S')x0ff ̢[ $S:Y%_]hArz{<0fr{Nɳa0Ukufmܢr}q1w]q WD>Ua!ڊ:XI:J{.bTeV=G 梭 ]uuZ KQf=W!W` CՍPX=V ()̄=iR6m/{cJLe6B~E }u·kMyC$ٵxLVB3ObS&^:4@PftevcSOȟ{iH hE29IS++Z (d I̜ ʢbX]pmRBBfuk ɩ+6ˎv18u'|̀n_N]T9Ƴ+g>;=ȩuU+$ :FֶN#$te,o>[Z pJ: Ar40\ )"0R`H:D|.NME\F"8\e6l}HԌ3JVC&Gt-ӗ dG TO0O%-|G+А09C4͢B b"x265";%w}GoM$򬞍jul@YyUοW1:$ bөԹ%9vSany5:@aHCcUlU ̆>d1BZOd) Y$ND1PW1Bt ytԦ$w-e|$fVU[jnB Ǣ;+krd)J򲰹U~T|Z^"C/ۖbn8:eH aX n`CPZZ_H$ p+mj] 45`dAtvC> ]HqMKʝ#7+ OߣZuqte*/jux}-`1 C6f(<&9.08#gt">8D:p  ! d/R3>Ln.Y#{--d{&w=)CI}w}jf8ș#Ù~}4HDz;o:s*k,[0;:N#lm,Xb2g"1d &ldS^@LMGz:3T"&@EAR:rY]+ꨬHdAaw% ErH!5lYm &jYxҶyOέVm{} P\I@v}9H810X` ЦiGPP i- LJAS>?B.A@*PK:/DmZt(6R$R4VoJضiI ԓDѲI}ضڢ4qR{_3 Ș舆T5@"=k = & AJJp!vQxk{i6A SctRֳNH,F6TY!ҰBrW:q>@βD$0BF y@C̑Ȅ0$ARo:@b Rh8 `|HC(7B&&XK(A;kI)LΫqMr`[@=[K d݆.]ŁupW9aEv*76+تS@ #t[ .D@Pjx$pFLBbguf lu TP0$PR"oSd@ $)|" 0;䴾DJ1YuȀnTcX*Xc!KZ8'A$l!he#Z҈mQ8]upA)b(UtqT2&0%H)!QX U@J X^@iDp%tf"2^diQf#hVyM|mp4<"I&&} ?1;nm….l t>M3V*d!pD8c=̐Y%0 m衄IL˃k;XJk^d&.$EĀP_06Y.RBlI;~GŮvWx\#kҜ`&`=UHc,d{`0o~Uʆ)ߑ* !-?ݨZt 5D*M k1Q4ۖH1cb#XE U#H Gq!ˢp˫:ah 8`"LMyBXQC2^5=l4Dr0K6( ۢ-W˸QQǭ&ɆRY8#|mͥ?y<B՟~з~fkݰhAC32UE!3@Z0u"Nز@\!0PY?@׉c:D$yCSX9t5B S8Am^bAO3tx&Bו6Ȩ"@ӑTL42}0)D2jTAwۯ-p&A5%X'1,wSFL2-( U{6!QeSe&$ΑTpi@z}a#n'`6TM1\ Q0c硂N|Y$bn/4 w}[~bot.42,b;c FiCJcaݛ3q$#VD2TJ+>$E>r,*HlڂV"! zkHL/* =dh" T{(0O%@yv" a\ia8: k}{6(/Wdluz](~8ŚފN}| *JE&Ő$a1"pBF^CA F{@<'ap4"IfFAa2XC*%U59[Z[c;lv/!Xs]QO4vx.s6T68i3CI@X:(ܾh6`5 aHH b;a@Gqm*zѲgzbT&^VgnIܢ p٠0RZM h2d 3[lpFq ep /0>aıu @.E@bH|W !88Ghu(aS8BjbðN(!juQH0E:mTyNXia;a$^B)*J!>w'{y8OGJI )8jYW@VHKF$ xCg@uMRF_W4l@He),GqXC:k i x &4B2T[vIdvcYDP k;׷rBz*v 6j_bܴV,&i`)V}^,`, ̢P3 1!ҐHx1Y!N! @G$%aJP=F[ M]@{%BpjZۦf|ss#{0лE)JYm%ӵe\aMl`W9ACqX(nKq$ ɰTv y deSU˕K׏ȆP>稕% X Mj!sM xL!CUXX(((I((ZϤ >5.gbgL42ѻۍ(kTsR/!P='5 A6zzO"Pa@ni!(/*a[0INKj-d&11`'ju3r~$*I Whh$)FƀB 1)VPP,!""dF,f9࿪@@1R$.eg2ϦŬ͈#}B HB"T  :" 8_I: u 6d)! Z+$ i1ub- p 2 ї!cN!Ӡ4 $PB(VkV@narD-,ͯy ;v'G4AeIu$lL^bA< 59FFJeͺ=L, b@1)P]r5."96KB٨GshUK|LZe!DBYDP.RS` })P)8a@PTz!D PvJ "(n-3WWhw%$M`(`qdK1B\) ru9 ) P>#yCLĴ8icF)>pdFw Y%Ғ@O,"-M! D:F=&=Vt[K |@6B9C"H}Qj,@S0Ț r4w2ɁL! e6 CѐjuBDP Tc NaLBV*Zz[&0Dp äh6$ "402EP9`錎Μ@{hKy_ի]UE ̀Yc,ݓ>S$& MZYMq`@tO `32Pj86%ylU8߉ <+)Ȓui wQu{`&2)UGeyK zH+, 2!GرW0ɱNЉR,-3o1*fsS$FYjPB.{D>\b5LU1uaA(3I֢fN ӊKRoiI" ~u|j7Jȋ0:ZC:C$uTb!Eևou,-ZB)Q`c`e#T 92Vd<ð`<%'}C$GT>h ǡPr~^ r,Ok{aNg!k|d "BBaC'fOQ74(eG%&і#!r(H1*{ĎezDA;GuDQPҏBl[u.4F$yR-Y xIa%{uNI+R1Egn}|㨦?VxM!ί9 B?5Ȓi(=Cm'%Ŕ2ngeÈhOR Ն"~mH q N{ $1bL ؘ3UhMLDAcPJ8ZuF'#XM%\BfW`T9/\ E+-g8S_(]8PDXoϦ5W$'|V7,.{u 3YDE0,,-8(%7dܴDaFIet%P[M-"?|J}G9 1ce=B0l%'|E$))lnnUSrHD@P^D@AקI}zѨYp$P+80SS5JRk{C60A L<uK%*zYv8tP)} mCm\1U0ؚ#(TGQH)e5dbRS9o#} hÜVF{^It4%r*,T%aa,0j٥80Q A%iߡ >'\)1X0 a&$a(pFR|6ڐu=zYFⴅ+ 4CInF_w!\P,el`mTr&)_lA:')*vyw b (~ Ȝ%B 2 < %X>Py!?t'@5P%AC G RTa;>EMoN #饟[+ҧ(M % _2%͜v?DmpMB7T>~QhT:D;gǎ рHۖv cew JUKkt3Gԁ R8q9i*l+cDހ$">+e\A)Q%ZrR~yL?ql5ҢGzJhaE. $ K.8"eY_2̟HVW(3rh)>%k;~+IUR5VeNBg#Od$!b73吪*1Wܺ=ËG'뽀>Mo}vSDU-E#Pz }VnZgsօF6-K 0)F*tZ2I#%#$/i (M -G*[^S $&W4 Z5Z Y]&e PvH\P6cMڸ˾8x- +q .{>1KfJtGrE(N&Sd/n *VsL +i$"K&vJRRH 2:d)aOó!3q`ZW, Y ˀ΂ Тr*D"(*SmԔB"?R%ƸKe02K@ﴢܴtV5~z z.'Ӳ@izajhYܜ`M`Saib|G屹!e4W4vX\"SE}*'ސXCaXhg;Fw{n 0ce`GwcKl –BUldzAMqݑMyf^q\#e7/>\@=-rHs\Nj֠xCëPMA.T Q#r ! -gg)P.*, o=84ī !׊BYh0Ȁzii;yM"i{\Dɷ:>wUWݱm-m/d<);s oYenjz:vdbY!HZ/cczD>IGg1. IDAT?R'gHPl1EGВa`(x{ {}69)B\O2X$9#JʙTj8Ah*5}ok. B C}o3u]KQ!jDXШJ_(VB@Ҽ8h;2b1dn` ґ+AhKXXIA/2 *v/!wxPR!9abQAP`M1mqpʹa {~ޣ/)X1I 8')ΈSx,4uTjA9O; 9] +dWX]0<")/pK9b Af(C({8c`-ŞA>b µ7Z(!0Z㧿A&gwN:?$XA#ad\&}o%;GA\NJ:K9 zk9wk(Afȅڐh(X4ICPy8 TPd|,w, ޺j?]+1S7CcёA$f 1~$I|h+D9]>g e MIkO[04&4^5?)XX .>Z)9i/|39b((&heo{KٿV 鸴.]A]24.w\g^j(3TI3i\Tfu3v,uSͩ22 b@XM%堀ٔȒsHZYEbՁ"R(J <Y?!/9UgSfoW-~0t*ogjLkhc\`7!Uƣ vt#CrOز%f<7,,B( V=XSbK9md+o;$Y{҇Zӵ~ݍ֜g22j]oi& ?wTsI`L1P$,u "$]3m-nn(=Ǿufv:ήeX_qג(%Ԍ ٦C Q+Xd -0_dHjC -hq%ޱ K&Kj,N)J9x/@:E9 2(=9Ъ,Ь%9̢#UEBFQ jѱ@ }TQ(OG}IDzq;%0+J0 {{\'ao)xK C+, M!גs(]थV-8և9@3Tc/R_w`b/+T]2ߊFԠru$ztSA\AkA j{v 9kK!K3Yr1Z ďa#`2bra1hH*4S#O]/}I=]Q?$oyI, !$P$}Ң;鐒/i IU1,l bO*{$Rю8t-Tn򷿴uO_f}_E( P7MhD~Ւ~I#Hɘ*hmG<̩WYbC˜5 i6q%OD9X |J vQ:w<i}7pջG-R[Ԋ -Yʑ]b&,҃!C2P䓖'iXCq4?(G[h%b0&epR%D "PGO^[e=ǧG3C߿$8bl)T$Ɔ%v@<3hg$7ڐTH,JKblЉ,VaP \ARԒfAb S7ikxJ|~񷦈B/}Dc'%H/ z9eXcЗ2%$:sqNU/$*+"OlL-STV\ѱ -\GfG<W8n?W5{BS8\)'!Aϐ'aۢ"@\8>2Y/(%0\#1L{[YQYJR|) `I;V/} \7Y&ʭ=ث2A"^d1O$qbP5:+ѩE 9 Do 6\2=+)3pGJ>9X[rqj*@FRKɝ`,JN2k )u_K$^川il'jzB?}XKVW ]$[118 QeBF5b(T;`[!FRfHDZk^uBV#}T9p{|+q[CA")$@;KqÓҘ$hZԒG!0<*h3 Z5s|ߤ{-g;o]awʸ2A*i8|Uac3" 5V9r&z+[3[!vX&xW.}Srpl{c%6|/)c%>SLWYzp4a2uE4PXpx۪\2c+o]Q/w*>ssqQ}R:l-Џ@i7%P3fBV\Jqi+y$o|C\e|PBBf>b}՗:o[>N>[]gS)|@ qdqLsJ}N[oMAiǖ]ius [BAF)z&cSmIG}_}c.\GB^#I ! }Y_[K$I[[_Aʙ%=)_$t%ԐЫBIxN@PHqNI)~B9^wbHGO\jCRge*H0D VHmG[TnY~_|/tI)_hjGBHFiͧV,@ _,x׻'!cBVk;K!J+ `gDb$7@=s/0te# }+3MZ%E$0JR6`h~ '+G%U 4 ORF5͞GX2c?.3o[ݾ7lգޞ5qh 89#`1(ҩC3'dե8 )H ,heӕcr\c׾@"%+tFԟ#PcHR<57~ݭ+;!E5%ő ؘO޶6g5hmnO_<ӾG˦+8ۊSd87~L? ?ww0oEEV뿰UpeMVG+vT/bGW/y3~T?>]=v|#;fmfmfmfmfmfmfmfmfmfmfmfmfmfmfmfmfmfm.0n6kv|y{[oķ'o~_Kj"@d=C>ԏ^)?Pw{xc߻֣i9-_[;n e[fbQ CBߑo~7>4/ESAUy`yݔ{0.=wޗU~כ;&wO/q眺h}~t..U- S5ofOe6Y]E~⌾5١y3, f3̾l%ZuV}W\.vK:8Z+W"ه@[m{ CԅR;ͣ#2nOs|_ `;]}C]=ySݾRfr']g]uI~k /?iϺnyDc=4P&8ct{vBhSqs"eϹLj],;|)|jyڴnZ6v?ۼhmD6u'N }~~Jӏڈ77)5PG+/ikt7Us.gs@L~"s'GZ)7zѯVw=.~ٽBnl=Wf Kvⰼv}pvA]߿]VoR(r'ܢ~-hJ{yu#)0rz.!ؘ=JW}iq?x3m30?yh<7JaWҲgYX/헭D1W]9`ϑgwos.<L'ه' Gx ;?7Z&IB.T/ԬYRjg 13'}f?-O}=:^PB~*yfceQ8=vM͹>0y"s1CI[A/ߟ]חDZWlɛ>:ꥅyw߿c we_'9rp;)/H7;^7V-3^0^G&^QQ(ί#!n%qWN;=[]$1QN4 '}{v9H)Uf6+ĭw4N]cF^OϿ5ꩌ oV>-&/y*?lo% 1?l5d\0BqH?Wꁓ@E%EE=sT<[%GKŞg149*};n@1FJJVUrJ^tv5*_9QRӳ=p?sF 4*;<`~I'q/:ks gŕ{.* F>%mW+\4W: f]vh{c麟kk0]ܻ?1ܒ$_2;z??^ciDne/ɻ ^xp*7s~'g}-4Hᜁ0,';^bv؛pC{M5^ 5 T]<ߎB!knǶb鳝pQ]/hOapw'37^^7zxa]EyЍ D;ns➬xlTX5cXH2{H.D/f@hm_}@7:ߑ237qQXw}~{*ap׏y->ș?F:9a"fGueK SJxTz+)TMJ&ͫ\[MustqoC}>xJ:Hzx1djxy8EyJ. k ݆<ٓckefa-{an}_{ǵzRcBE183O?h?&j#ScVՁUa6j!|ķa(ZGWgnv/F=0*҉}hj<U,2{~`0(8@zh$kdN<2Y{Eu)<)7hJI)/wğ&_O⣟O^/" (&8NDsB({$ћo=@Q-Z=_6$I"/)*j'ӌ0&Z/©KKO] x^@beGy/+5Y66{F'KMW--kJR1>wC,fB)?r53qޭ%! fi59(k xW~?gR{b?6U_*aĂD}T9Wqm|O<9&;巟k.g# ș}N4ˑz^p{$0T =2DLLFyo4E MⰦjmGWVV7׽t=X]akտYog݃%KOfgz[ٷ3h$0 yØ]vYـm`mm0y Fi,#! f4tOwYVթ:uy2sB@qi|w>}>?'僅{ܹV{G[\{Ys;W$mxq87;sIV{}H aRPldf^b\^şgW]v/=K{~[;xn) 測}|/Fн$o]zr@P@ATkwI=ýR#Q0Z/$rsN·j~? iν3J7S>.mri:;o@˾]l UUSj*rK$$AqyA- 'ÌqZ,t۞wޢyr" !_klr<5Qݑ+Oz]Zgt~g\xɲKV?V}Nݾgxk[?3/;BmSU߫$x3 `oZ WZ-t8ǯ]ô r1l fGPWș wZGX{5V`1O=]uCE߹o؞3| y>:J??1}t~@w%ݾ]BzҼڲ:EAf zM184DƎ Jz-A4bR7E<7?ΣHNӉU#pS\7n=G/yߗQvf}s`?}x~tUݩ_Օ oC#ėnj/4$nIJI%$@1V0ցagb[qGIml[7үxas6;Qz3/`cs-̧9r1܁w|RD 8A=B'g4Gc*mlGS? Oi[?wz}#O쫮_ iVMb珫f6\7?|Fo)j'wj~:ľyGckyyXBȍ;5wb<6$0;v#6?h}w5O\1wszUjR i`a˖v'ݞY~_ nԟV_:ȷi8`]c6[ڧ= FTWU}W*㶌_^xA]]35Tݐd*8m}dbپ0V6}J0dd;|-Q*^_'nϧ4? ݛWݭξ龸iyg4C2X,=zE\Hqk9:r_VZEmdCq`8˖.ՎouA]9‰⤶޶DmC 8  c~$ 0ȈQd~^{\k5g_trR,Wo啖|c>oOܾg?t{#6.\~ݽQtԂ+6"5PɁ14=5Q1Q9G\G)Y4` IttΗ'a`,sjqKI[u kzz Nxe囗\i xG;Gw|fqn#T|}$get+4Ϩ}wn 3̙- d!ڏl޿z[ 1DWkP^V kgǘeMuK/ɶ{U]>}j?mՙ'>O{+7>~ pN?\@TZ`kB\ޑm _*c*$]4'-F[*\p%q%PPR5v*996уI3x I"ԱOXHVqj{\;x PePEѶ!ڰ"&=QࠡlŊs uaZM<}?g>q#_M_O@c~O_zfn-i+owCެMvk"+ʨ\i/}mo7c}K:!JvN X[OZp[xz/ ԯF>|#ܟUCIV/Z=9=% ~o5V[1Yo 'o᡻)`l›-|g[yE\xTntX-FojeֹPZ?e1 )Y}Z zIA+b5 F3^PqѤ''J%=m_w|++r<[ng6:C[9GW8 Ia 4 CU"!ԡI#d'[Qg0 Цb-1T仚EpUw%AƝm{r7w~.+ߚO<f^}޲|_oOSz{u?Oܨtkl/iW!-[!mҼʵխlYPwqKK@FH*6 ) E5v#!66,_5x;|gC)r2ROJy'Zwk קvWO(\Gr+p73_ܮ$fR]ɽ;ʦ lT2k㓊ՀL'eMڬ ISenV\c*,EK@*{ FʁNf o,D zd|ݚ='/}-A,ij /Q%EXHUV0}AX$V2/ Lw`A0PEU%Ñ@[K8 TShILd>2BxTrDNc(FAPJfwQ ?XKD.7"|ݒsv7vd1wWtvVi.2iFit!Yiǂdrg4S,(ٺe]`-._z#z]I]B>R@TH0VpGq-4`ǀW!$IhIJR5}F(+C5"ȴG}\c4=j?_xφ+gZ3ӣc3 `g{׮`ch}b+H"r[WzTV{uPMVa桳 ^x٘RdE#PTy : IDATyǟ.;ŸCy@C,ԂWHtG$A@k/]]ֻѫB»Sk4$"f GtU7ڷ()ξz>|a4v[SGw욓HsJCd AAө% U]MB xMs>r@llT| )i5BY  6B 㔦>RX!jzKSYҮSYQ&Fh  佚0\,,b"mzM61wS<D{HV +F.UI?kese:_@iTInH6;ԖTsr YgJ#YWcKR5z1_vTz՚ !YpV)'gyM^]z=!zW,B!nC&fu5g^ -\U;X ByƬ.>Hɺh-ohQRt,flgk-ZʬilZ1htxl2̤[Xvj 5̋ _YB)i+2 OƨRL,iJ9@JY&ԍ4v 2dQأZ/k]~R{F(F(T,g$EI"!hdP}ȴrRRQ5gEE"#j2~t#g~S1x +56;#F'HU @1 fFg3) Gb|dz˃w7ʟ՚n#G+\!UehJީ@" ̰iy$[X+ U3ms9{~O"KXxQW\'Lmd4RtF R Yka N%Rjch@Ւj/G~ 1T3F%( sRS`P3MZ yk};;hM4rZL}\fda0d/S(G" CkAD5TR-Q Xь+9H;PNah;̆3sF*tcvCvb3A#WW>=A6,&az5,iH'CsL ̒(`~Zo.(isnVX^SbvJj@1t^z>1(~JIҰؒf)3G,58J9"55dx` 6%Nl\ST#pV13ai:sI<>-# 9z>?UޛwT?5JHJEMS$q&F0LwMlu}NiF0548ilQȌe>T&-])[0Mxd?2 N,KDŖ MIZatNXn;}EVv%0xuBa4ّB"Я$ƧZ]?>s&èCd]ZvkԴ Iy"'xdO w " Q@hp;e,)PT ^r±( {T(_vꡏg^K沑 A\XtY(-zjOwD}L%q' ST Q0(r] "=rc + 9c0EO-Ր騼/AYY`Go"u" OIVh"lk=g^ǵ>ٛWyS KT(!5㝂Pя#jB'N eb5ܛg4u`aݤ]||8Aw) JO|'PNhZ' UH"%I qlYL*zDK/OG 6 _'?7BKdkq׼0zN:gÚ4X!ѮČ, [C %eqE2=QKOl(yl ͥEfv-Q౵8K,3`X^ Bf%=L9[ߔڽf???٬Ϋ^ W bШZ-gxWLPXK83NAS'R!vrrˣ҂;5^ñ䇤wK.>st3OQ _\nR 'Y:(g5 RG9#%J`گnC{Yuֿ_m\W|!e(ƒʫ)S陶dRrU ڄ,8k8 pfka`<]մ|A6 P}3N%SWRFS\Z-V8epVfJ#@;^ԑJ9LMHSY&&vqF#lHҬ=Nzd_5dӊT ER~p^WIzQt`m+3!NYk-Z<^h$zW=d-$O!`i<0e_լu<6mK䥊k[GE6*kƪeqKyţpG5R&^HT|8x$}F Ls*!ŁwiY8ItxD2蔊ܠ|͡фd2$ˎ3#"<`sXS3wcq&d9ޕ4DFKYM>A)?xhdj TZVS*H}0o~{iyٮS@x[_k] a#EXXH:#AkYaH=nWP0,r `_Kk(N@! 6r4ĶGD">suO !%P߈vkeV!wOm5˲~7A:ڲ-I0%'Sڲ~9bvYc*cQ׆,|#Y[E[V?mFJgH|%%jl&qRӮD5m{f?;+TG g qj4qNIyqgOVx8oFB>&'X@c,JÚLmɒ:A+i@fpkN nM`=јK+N&#P3ˎѬEp2FѠkC(S`/>r?hu}C^O5 Y1=C56#:t5*wQOY`7jV a0 P +jA Ğa %hV:֣g$6K?7yu߳{6:/]m.UDi02`-f,hu=DhJ`i ac|(3G҇u#kLb z:4.K/X'Ӄ6D 4pSSS'sܧ? >uvrxui;EU# =uΊ(A$~FGzܛq$ Cjkk퓜$O2]Th4&,R @ (5BB4|S1 x'٬-.⢒gO=/ sXkR!"P݄ 2BI? Sx-Emʳvd£8VL嬯z\OyB{QeŪF C#2ȁ|} YkvrJg"CJZSnHYЯC, \š@h1(iM_BxQ~ĤgL,P,ݴZ6P!5R*%T"KA“|Ks~eXxh1ӄB3*CNgM0jAXނxdR G( Au$ZIRk1(+q|(JH2H%POգonItU:oA*P狝p"i\sG,I[m m`R\A%r@hA)wD"?){ϴ߳7ӡ@u-X5.,L(E/i'z 8乧7h=pcGrtiw4#BJ (-Jg]6M޸}wDe9ߑTfTϩ(H!!ԑ9,I^b(8 AEjy,GkEDzrȬ9GJ dZ<ya<ԇ*i^5;@0_] EgE%2D;Ya"U7PҋsJO<*IREԗv *3-O5h#Ɖ7~l*Wάά>0UVفXGr@(iԴrV@S!*$S:qIJԓ+EuբsǨUX?j}ε8ۊ/tҥNvo(M$#)h ݒ΢dgM&4:T[" i,0VVgNHXA$&(wx8BMo\.-|COUӕ}QK+$B q:T/ gQiUs4-j͹6%%$$yF$J+{$On g M9ZOv/|<2agUJhNȸrX'%Owy^Tzw hl .O-ȞI<\4K (ֿK:NBq^\f4Tܣwʂ %HeIL&=y#G[O#ԌF8>;5{8k"h&.?S >$? 1 Ku=2XxF9wPKtĒzHJSc2>rA RjVHYvw ꞿ |[n1ʀTWIUH:G:PK1Gv1.EHG!UT9RW IDAT8eQ))YAR[KYwJ❣lO~L{CΡ̝:*49Z^ЍO ~K7~vD)eЕD=h7bFTh,鋆r/j(>߼ [BjYR$z* dŰ25(p֑'F_qFJP/RFC'id c}IG.HxgٓF}}?@ q[c:H7(eGw!u+{SI"]-Bޤ¦1Z9pĶؘ !‘!PTZm, 2*cF%M3,4.Zֻ}vxF/1qD8oٻ,&~ߕ}ި;}hnĝJg-Ri>K ]ZT1C ߲yTRPmӻ>W'{bk?ReZ*,Dٳk}VzBxqz> Gog}N?Ԟ>tpR&bnBlKx *9Y~Wf6}I}| |Lu]|t=kx>x蛄x.ULbHu&eLqqsօ|^b\RGw IJIx[, U.Zt҆ks4f wn,}Y>ITNiC^e@K_|.y9Z{O?9^Uyt¢?uϽTᗊƟZeq߫/Ȩ[ؖr|N*#OX!91GuxFs*lsx"?yjoؖK:k?;?{kgdzkx>8fwLV-Y'oH'*_JJ+4ʮAP_WՆ+*T-0zJRn򻚄O32Vcެ Ԅb%wO#j^]wݿәY7'oZ[½E7ްq Y0U4_x-lF䳮vbd6P"$K1&^{ |x{%;>9`[b͋k=)Ƀ.zS;??tmzޔޞ_͉*5;y})8"^Թ L>a$ /~4`1]y#dD?xfrU÷F'q/tGey?-o˖:xȟРċ~Өv]p.*-gyܶZGiŋ=EZnψ5Yڨy^)n ڢ`z.qjA+SH$"Nd鷛@tSeMsV&ߜPAaa͟T Yxy۝3`'vy7[3`E+ZbvaX50k֢𥜊:zBWwuQM9#k^\x>n];8[Jm@H (=uwi-<;2&|43[aKO*ES9<80gqD>{%zVOՐ_Q}7Kd&k\K[=+0>BC4C)I)T&$tHd=KcrYjYX>@RNAp>(kߚ N:o:9u[M\}hd+bO>j]棸u\пfYj!&\eQBRwu'/4YG'NŇGb?w}G @}+y r6$'=z4sZ;?4|UsfIt}Ï۫ΰA2?(R8iSQěh߱#ח3/SrUp`M VՏo}A/v^0Qb *: "^w% uo%#kz)AO2^*q4biams^_Ӈѝ>8w#,ca2'.1/FpLs4UJ+Yg"ovdLJW_Tཫad'O~ߟ~&x+_2Jb6*4=W)k;sw_K̳[/KIY˷_~̛W՛~:[}N=nO{>}>a نd QSJ߱G&ڼ;yͣ{+J3ՔgG_`AMKz%A>ƫDZ6-t2V+Q!e3@3Tjɜ'ݥ2~M`!ZQ_Uϖ-{wBrKnޏJ,HPAp9}ڷpeK+(]$?׏4E #C9Ta$v'FH_?O^:e_Z`ӧ^Vo@|MmRB3axgW_K)s);n9sw!d,cڹWs %v?LD|:Ou_о@ʹ 63%J,o17X[O1oBa]4'<{tZP$UKNLL%Wocsd8'Fl9 ߷#t)yl FmAf|8Jon]H{c?]܏{6OS[͕M>FLJYj^^xm*m7^oT>91 =]:<ڊ#?^4ZWv_/?r&tĩ׿`${Zw?@m5.a-327&nU&T\Ȳet+wC{?kf_03gJSϖZN@e3M&j>GufTsf3M?v/MsJJ)2wx)J JwҜ>t3W_]Wâľ$@L?ɿzZr!0"9+>\2 =2ԕ)ıƖ[&[)[b5Ns b3E+VG#߾}J>f8 zt Z*[j3^zov4E69;oӲji,x9 L\Zbbb T>/zg#3ةd; ݾxzZ}RoR { S8 $HrJWGޱ?9uƎ|y6'Ί%!(}d!ݽ ( 1q|{^V Ij_A}`L?JQ/316pG BC0[ۜ>|G+lEg i]~ڟi%ЀւN$N'fo%k]V[]V{1 @"b똩U(Xlu3K$ǦjeWZ_꟒^r{})J9n8k9669f)fnTw??TID lnDi"im;om@_Mߞ19:j̗|eLw>~&Gz_&9t rK.Yg8H@J9u9qE)(eշn>4Br-zܝdk.*l*ZSutmaɾ̯Y#F\DTgTo3=?;XaY@ ft,G((R6<`tI?&pxsɝ# I+%bkQth>V#Hݔ^7%(R]3,("?rl|`;sWJ rn_;PQT&xd{4ȍw0|!R+F6$ h^&W_VeCc5?n#@P>_y;g4?gge=?Vfi.>M_Fɗ֍x\6/r$%Rpd@z6lLI.B(ќ9|;{25%?GW~_/~ș^4n8J%UktoOcuv!$GӤ8!LIƽw1 A8*!" Jk2HR"B( { J >#w\g=n SLM%H$4em5eGF6#%CP6,!I-F*Tݰ^gZd΁PJNNUMҮKuz?3W_wGR[^eq :ZnZH5)$KesQHTv MJ9*qlCV1\AWpl͵7H)|P{s?vWse˹e~V>SrdFl_Z< p:;OqS qH%H͙Go~h -?ΤV#%gy^˽OyI) ?pnTLuHIU€s0Zs`^Pi iLwzsћGw>=x.6wOq,$stmFf=H)AIr,cWQ~(8eΛXS5 DKRP3Vac[Jn3Qml }7VmIg63y QBl>fB.Cs#>>!FB| Mi}E[{-50ꕆ6sQ^ԶIH{[|U1,jp#>1owK.TēC.# $I DXb$)]Bcd RH8gB*6MoNnKfw+<~Wb0!w,&c(Hfy=]EIgl &aQNUz E%^ho5Iu4G Q96F;Ph> !RƜRIj,/Ϫ(G73W@iǑ]SGnYWH*NQQk%릜IҜhƄaG-+=JJȬ#NsSҚ#Hg*!9r}2sy|r{k · ʓRuT,tx) E?Ƚ#PF8/HLp-Չdt{Z gg"^HͦIqtYFӋl|QoRWzo!ByLP+/H'$%'P.BFtlT "K;gP?J'Eɓ:{֢!Z0*KDg˸"VjUbZ&&0h5[F!|z0IuPTby2&|{Vܖ}o[$||[GFyUkqVL'Ț9c*]tLW5^jN iɱD8eWѦ ړ6%;t_(l~x@Q;wCTA6YPJ0:᝻264﹧t>Z `_/KIc#4) <uJub]+#2S"!ԌD!r(fNI3J[P8!H:iu&(!B2{kR*eyRؖԷzJ-mݵJZim6X.)zpv S!73@KYo2Yv 3`U@.9 _XZu }ŖgH@PO)8 Am{Y(w=ތ[t٘ydFDžvӰRfmÉ;z&W \@0:N`HF!0.dk˳%fR\>_!HyJLp;؄s3[Z+9 Fg&:~5uz:cbFǷ.xV2UAѳLcL64ŽZ:K1I4e7Y>Gl)` dN(Dh@ *xZ\G)cN4:>4fvӾx!+\r6tN*{e8QG :'vR4"Q%z ab$OYF7S *o꬘ .SQz~㐛AVTHLQ#٤?]VG<j3rtqriҀlQ_u{=^(;ӭLJ IDATd.bYP`.Җ]\C-" Ң3Gִh6 Q mY9b`cOY=0(r'ы)A3# PMNnS&:DžY;_Re1i+Ghk6&w=TAFY:ck,.kI&rbF饫JS8C=0M=KvT"*^-m;=ܳvo8{*?!g"CIAuyc*5WEHtB=%48([R\AXYpźjyHYdyOH3h$ĖwrrP.nL$7 q#jmNجHJ=>tmy=;g AUb sC:=$֓XOQƒQJu@[V*.*8]ӠˬQ/򐳎uX ox#=9Ye!axY{Kub[رY#fJܳ F&ח$w v)7!/f8IrKOAf;`ω#iZJҵʨ!_u !} XwSL&(!#Ҝz"R0Go?s1Y-*' YQħ`ZB-'p>%w}|߳mODE0`KntY$I]vN:#OѪD}Hvzdj8IqSTI}K}z6us&C_le,C*GdKO7IPiD^: {g1ĽZ[h (9"d(@D>Q ŢP!M6d!p6/'RܖLg^#ZIǝ:87ΥY*!yG/( ~La-qt3OIz9Ĺy~C`r}(pKFHmZR:7pMZYMIq͠_\)\ݭR#=~3=V^ $ 9) -D[zmK͌s҆ 7 !FT$RB 6I=ǧ~\Ki}Y'T6mÆ;AUd1H! .w~SňܤڬҸO2[fyzQB4h-+ӔtL$ooηo`pԘqОށ̅Aw bR\%9AB!]ԸxPr ȓݳ$Z,L (m8wZPD{l̦c.H26%vj4UBڔ %87WnL兿ybmMZ{)ynAEzO= y.ILN*uw,wX TPll6c#os!$2(EFʢ|J)e g-靹[~[M 7~D"4lE倰/l[{xS͝XuiYdgrZk}\K,,[cǶl+q !! !.tMr d悘p}\rQBn01!ĶlYJ5WSgZ8J؉ȡISZ{{{.)FH}MmSepWlgIхWJН,c5&(Gyו>&IH87NӳhJGT71v1sͽEuM.p=);gzIPN*sO3.fIM# "Z; %'YVl `G)v-:ks-%$:DI Aѩ<D1ТiNJfAڌ!Z,-k7J"TU KU^q6qIF1(% Zd! t6n1=g]yz\s|p{Aml6xJ)$Ҡcð4$A9g(n{]1kW ==@\tWUcإv kCwO#1 ^S{Lt1|8~1m&ؼUUBl0BLw/smB(Ct{Bv&ʬ5n@V]ǬVN:ŦqίJb1Zct3:@Ylvۇk:ڮ\DuNtW7ƚij}__BkZ~i Fw! 1@ِ<&WTD!4 Ak4 )IV|$M$rB]@<=ea=i&XہܶC\Oeܣ2ꪥ4 ]ʗ4ۚ Cf*$U$a_ִK'הۭ3$>>9⯔YD-X7O 4JBE@(<+I)AvR5Wt;LPd( ;a %#wR^GSp=\/hj]=7y䈗;"Y"U5M iXȸͅ*mz0L"Y;T¾GB'-XkN;Yr|VJN݋O?Ț_=krRxpw@h{|ct >wA4%T9|k B Ʋ& ģ 0%1Vܙyٹo)(d)QU_Eu"Gج b ar]ms9$lRrJɱQYTM_4H$$ |c5fuR(AI{Gy!-TmfJ= I Jha6Q:]ӤR{kbBTʻX3( :Ce?I#;H] IM{G.4-4yq|GN.U%.ud{6zUs©#b(Ip$n - m5K',p߁Y,Ju(Foj,=sb[+ ? XsPr3Ccz" $DW\+Ԉl~2s^˩E\]c Id\*ѡ5X򮃣cNbG'^]]\h,y~x# tv;vMM&Xu)Ҭ.`H 2QB ւWHr\+qxac'SKetJw1CcPN]>Mi| ^Hu,n'[̺n @GQc[|Zs߈/d`ra IʼH)%VaH;AĚva:Z= -tWfyME[matEGoy \,}'%r>": ,~Z).2]\u:.ǵ:zD pt X뎢3 8d5tR=#/(힜(;܇|d%;Vf| Gu\q\%_ bK(ix#WNExkhrv]g_Ooq;Q&uA⵲NpiOә{K 4iurDHyؑ^LW,=dw ^^fWĐ' f gYcVw}WE]l4VF@J iEO|c7~G^=$tnv=!O2Mҹk O4kܚd5i#HQBR*"#9o}?pg''AqaD'1Ѻ8@P)UFƆu<␙,-%?B*#%ZQ>4~@i<%XR2>Ru:NqNat#j8kLB'~1qjS+ۥ:9#R>+PJ SޙMwy:/㲠 MfB+Ȁ%-u|%7MWCr'$j3ѱZʰW<3C.М;؞d (=Tsqˎ#yK64_l+;H|_,UgD ݎ^eVb0#M{]Nj}N|CÃXsD*y)0Iza[T4 {{F*1]7z%< "y+_Tpb{VSw*Aw *W-yti颪oy3x$5*Ĵ3_myc|ϵtRU' 8*jk 3UZ&$* 10ImbH_b3Z%lus % #a1'|R,p9pLiDQ~G^-g}bRoQދz}\/9$>*/ 帇1ݧt zPP;Q^| (T)z E{[ ǘKU#Ra!{ 7-Z0IyZ/, d ~7#tNuUE> >^q=}ރQ:xyN޼xr?- !`uȐdq 6񏞙N139Tv\ ǤyK_~)?oJ(A$􏊯հ렓kA$.Fo]M =E^͘Gk\tx&4V= $}E ޢU j EX9Mz-_=`(;Op]Jӱ-w/8ԅ]kPٟ5sgA7^O׏{fX^ 6(C9/@+f}٬'o͟CЄ0q$蚁Tlyg 7rs=e Ifxqc`} :'yR2{Yu~W']@/{V+Fuʮc!xb 7~kNOxPWr2mv!Ҵ^fD?8( (WC=}}g~ĵ&ءΆ /lvC)>~l=ȣ'|+US7:lckG;_B)Jз効ܯereEg RQyJȝǟippTʾޒWμ,/+2y Ϧ麼W6`䗗np*f8s*vn:-~9g;6x;^׵mfWrZn޷UZ05uyUUƓSI_Z^MwXq?ц#rL6zElQU=I_d>xK۟:^dQȍ =Gگf{-sсi[pr*ٸmP=PZ$I]OGE݃XK ৏ί4.oqL<!%yݤw!^},;o0sx<5Wo<3ku]Jwmo"z.Թ9ȿޗb fe~?i4`b IDAToۜH|rwm+{H^ӱaG;oxG^M?xB^?]7OϥfҤaQ7~Am_o rr}~0 hf3|_lCB|]O/c:Qɪ W;'TF'nZU{-奣 ;8MovnE07k⃭.UW>Im/ 4nyhu7io1*j zdΏYhיVgr#_5Zoi}ӳXthfH_~O]Vy9#2"8p}j[/sl@(m{!"q.ň{t:ġJL,w+R͎}+}y.(.,1  -w [.<9{XSn- UvCaNǞNx`4}@A;?%kDnʪ4=8=o, `b^SAoNY69;8;oJB!veW5 O^vg׵p(OkX+addAFYcP߇-x@אyoU sڵ%e7y}6[z{fZ 'mn5: >k qKI.%Uvl̊ѹWgZ,\y)@HSD<P7][$h=!(&lNyt3uV[4d pv[*oUΝ蠝 vm_JZڵMq3g21|팝 {Iz)/6O/v_¤Ge1L/H(C_'V{}ۉRjөDrv'Ҳi]c=<⍬}+?7'Zn #s޻O'$B&qBdy]~)<+kf/;.*pTol\mƌ uI Wj%[7q6|e@]x҃^[汩`|v%Nk2'qF_g VB毭xFwѮ I]_V[պݚr|rcbx3ɕ: #gkѡ~w5]H @n#!73mWF0S[\{(TK8-*skVtv %*xI94o ̹iWeUKVe^"͟'\dP)z~#z79b(2 B4z8E Nh-e3 M3]-SպwgdG 5sK2QZ/(C.2p`q.g3 qgO>鈜ztEĂv3:g1u/k-s׬B iaS2#pJ+2",b aW>8׮eF^ln?oONM{͈4#U$ ^>ZX*ɸ;lϵDAra0 e&`.  D Kp:̕9ЎjΠ>,!/qSlLW"7rJ~|za,7Y]/p_",%!8dxlm{"*-4FknƲC/q'$߇܊T9wfGLvnk.s޻AMS+:w~onU!OA4ٷiѶ+kH}7nr16  xB0v [)<ԥ3 sfj:^oIKfkwz皫!Vl>gñJSV۪+:ֳz+_Ngj5bj2\OFԆb<0$ı&I5鈿vC.&78ebaPe$ũ tD>O~Y1)zJ21 čhBhiCiģPQχz_59s<|i0^ϞcObUeVW;]x)Bњ6=50cKrawo{-wN>! _}*2m f[|ޔQχ7L# CYcGGgK֯gV\C\44d:я[щy%zx{8=8G+AkefCC)Po;VӠg-՚2NdOW~^%d8sL|1)I!Bg˗Wvx[8@%eȐws~߾qh岡=SHn_(aD$$nV Q7f! z-A+ eiu:eME휡^CyBR@**J;^O^5V8:v\72V͗ϨWSbvѩZ8ʚm!PA * SC*|Ga+IKIӾxT,C#q#b,}MvKUsSS'?x 6A-:j&+>=ewɳmAT5k yt\=DJNFB^MTJ\ϵ^Dlۣ?}$%d")v]r(jw] G>̶X:b`L2*8x ~Yc2FXC:o C2c=lx.oxtp-OmV)=qNa&F)hcEK#zOwJj2WҾLx_^uj-=XOzl{n3W&g+'Nm?NறטwQ^vn+|H; ,=1+c= v~|#bcKٛci)\$a0Z#]@i $I B*2#ލ4G?556xy欑y;-S?9p;;7fNiB,5FB)h CפS̆+(i : 0fk1Ų@YW7Pº&N4/] s%߷MO_^|ǮWr/cqDB`!҆v$D1_ "ɻK""T4B`Aa%kīf)-2Jzգ^ (YM-f18 f xz춁Ge'"Cٲճq߼x,CP8^V=+ M|BrWJ]p?/,n.ĸAqCѠq0ȗ=gmrU%|sQ-WH>-~'np͖]VBFVUeϜLػG9&;7/ږS'ȣ18eIcss[WL-ߙpp<ֶ5ze.Mʑ1}zrU~xiiN3P 'W"(1e|o+2P6uP{ÕmMGfEesguK>tIʨj-SJɕy`Q1hd)>QWPh˒|aii܊b)"q*6I$(lhC$ؒ!@6C%hl!P$Hj0Nu )PRjMx4F5BZ2jюcQZVr^ZyRSwHՖ+2goLӤ&]a5ƅּTJnn3f5Vw~pr{Cy % @I8*Eںl`(d RdbL C1EVI?y??GrfS vRs_Gfj[ϴ"R5_1}6=||*_PuTMk@y>P \%zSڳl6uuuI!1 Elxq[-{˦:\zLYJ4 rKdIIu29$`$Iu⸎%CS^:nw7VLA P''g^nECEqhJIiZS Q|H@D=Pq |E> [T&v;趡ގ纐WD֐I=Ri۞p'l>p,[ݸ8NU-IS0))qm JC&ZxxF1%UO74i#\L$}hiCDSX]FA45ӨWfo[e͡My}4Í'|C1'GvϽb%(L12HtBFZV3R(LLE'_cD}N^dR. "~N`R$̜<#R5RJcӝi8hdֲXWlAiDfbgZ#Eym-_8>5#v)˚RpIR* y0Q*8^unB (wxͪ\ʙhJth[:Wqi068eñ9) vT$hDmi1X$R)y CcQyö _05sF3;c@UxnQRH dx@rv!]ЃzxFTiyma<- a"z*X  $ŗu%F m)9\B1`%- lnO|ax,?ZK/i|!Yj1%ŭhi(MXL-J'E`%h,#Ehxy2ҡR5`ޭi) 5D%TP$Qu`5Zƨ(ChA% G;Yefo,{dJfc1fd X$:Ƥ]VՐĒ #F02a! *x,!V̜I$P^$vs.?˭Ke{|JO#o]hYiK 2 EvnS!U1Ҙ3K) LSnjI`yV3aI@̶] 3gd ϯP_YȸC!HEHdW(bH1qB63cR`AIܩhTPc'm;[3e&#P&QRe5#5%M5, h XbqYOFCa_KX)(̶[hmH)PBƚ8Ğ`#Cia&kYʲ;`RsIrc_,>V5+K5I1[F4h1) @w2E 2"`uaǣ!;gܠK{(YN"6,Q ni Za7NhCqa&dޠ@xlOHTe)-Cb6)5=z_X)ʡ-{ ~V!ԩ!UmG;!qG7<۷/YhbZ>uHaz1%N RAsՐݨټ'Ԃ|!)Mqfɥ!XmAKų1Dmb[D& IDATnM ;Kٟ0ꕢmĪZMZXkȱ 쳴OHm@y SW$]66PsQ⡄G:uP('G}e_u`8)9;N@ G;4%vR!;@ Jb!RsN CcQahCM)7I>i'TО1h)ȦbeK&E`YN\O C+%M-C aHXY%c2؊"_S,!X 9RZ6EtPV3 d ư&EXJ:;t*m(D6ԿYJ}Lέ&MetLjs78ZP -J ĄS00xXmiC^8hQ43g6,ϡ&l+8_k39:`I#D% mi fԥ&!v%>~ːg`ףϳ~yzq:n_Q<^:(zc5,C$P`Cu1p9nXd"v/#p(d"r0I$'=})utClHdZJVvO2^ihy XiZ%IþdRX>k ˖J@Jփ2&X;JUKx^f2gVp=Dx%,oBH8kB*/Ƽ::5&+Ԕ?:Ig]D#@ zG' 9AC*xITU2b# Rr*=\ T%Y"ϧX64*asjGC9Β4^PF%Ħ l\JkcSߒ㺃rb5zL*PyEX$8b&I!08Y&.qmQLg9#p$Z3- זH*{)YB )>jL1)#zXFxH`P#j?PHL}?Y1S]]oAҸ?&qyz(bz1(]ыD;tŠ4 6B$W?߻Kg֯WR]3ۂcLHʞ%B)Js=E0g1 U)":f.ٵpҎ4]axr@|!M^c48DahɱlYKf)wK^ۯ {v'uS/8P2e,An8iwX4J +I7Xňh_르PH|Ofvi˜~yR FJ!ȣrDQ*q0?Wإq&,BwOI ԴyBis[P}LCHQ?BT!d(~X&M(3iKcO*cv8ċ D֙]IВ)CiF=N8LU]43qNk11H(ۃ0\P=GXJ 5X9]aRţ=~MiX#K[ziw )g=R\ B @kXD+SAݡޛ+#Tܓu;l;T=(i8oWHCl)e_%"m֌hfVRF*ג8X +yF"M{A JI,ÄĹ&srƐ8E`>X#wN3J j\#/@'q"d}r ;LVF;i/He7BwzAiSʵ.@bB* x#Q(!qm Xe@y^O+ʨԂՊfZR>Fe !an.儩ZHh siIx͗ά\ѧ(Yd1,(ؕ*V!! C ϣ iS(08\\ !:L#=Ow1ygi;n+}0y0Hǡ8g4"rk}_I grv XM3PGB!w]>#@7ƶEoʵ&ma_P،AhaL^P~|N``9ꌡ(^fmF@ϣiÔ,yWRbeWfR\91@)Ɍ%Zޗaixu3 :W#E:I2vgA*V}Zg_5*Y b-/8ZVA-J*b-7*%UxiC70 &Iϰ4Hۖ|K]yXџXO_i|Akj#5 "acۋߐҥK!n6k0X,G(>0xRkÕ_ ˑ<5zp8@aQ>GJ,FFHg *ҝ5(|O\.j;7E$Ȓ,zsw8R <()1Xg6#REDCL_)hEbe1w0RPBqfRaa|qq|%a)A B |@8"ϛg}mpJLo:/V,XRK8&4O1sǔS,Ce{@e,d,L^1M{Ck@1GsM<'/9.)L'h Ԣ k쏑E"G/Lvr^| *o(!٘ɨg28o9c*̞ͯRI-X$)Z֩G`bG4; Vc]Q+$k7u)(r P*@xRww~T73Ĭt{ϭu{'vƐ @AXNVq*gc`zT:΋>JGUPehk͌Sg8)զa=cH "[k^p䫿YjR^}R1§ЎFXXFY*ZI ֖X[s9\!΋1H;(_,v 7 P(B>RBmz[]*8RcLA%h!6K C! ק ֥a̮Qq) Z/%,hF*EW^Ɍ!_z$%AE)JF8g?F^0wHA!TqPE]!}dC0@]mg6QL*IjNNTF,Y-K- t4bTOcTQc|Z~龥}\xe#qνt *?&1F0i+!a%*n\[+C.Μ.N@0 JFJiλh{?7V Kfy/?%hPwujՊYFLR c1ڊR_>-.|or9P>ʏp&=0RݹO8oxޫ`!H ߜ9;/:Eb@žm"xqK ơEBBjB*a02=TU7pFRBuҿ.a%BB=GTC%"|e0¡bApIH$ȱ@A+n*P3BK_8avE<ɉ9Y0!J6UW4%X> +4&.G*y EN>B*#ԷE桑GEK2I;FZFXTD`LY$͔y3F:GzeHN1w.=r7}#J!dž`t֏dyy#7;4ŀL_IObQELAH5(kϻ& >S,S{ NI )L}a4nq 1\/1P)Q |LYGڵPR|4>˨ "a7?|iv< $/zoR_R@<պWwv BqϪ745YL}{l0 ?,rćw.=75o\=WRb:L0r':8[!]!Tyi|VzZG;Oq^TRȥ2vmx=dñ/n5z~yO4rR! ?8T棌cg龳/,Upz9M z[ls!}%Rzܗ=|;G_n>,}_|څН8%e`/JnF 3b 'VC4)Eaoҳve?W8T"a΅}Ko,A!&e cS,BCP>U~cRI%[3J_w/gSؿ~E4bfخ,͹  $dn>۹PJ'J`bMiv RB2Jrg\} %bxE1;0&![ ǿ`ޫ3Aו Xtm:T>Jy+as͹r,5NTQ*wtkF&Qh$9.RA|3(.t5Os9q\0KoS*݇atvXHu9l5N~7u<ӵֹCD! |ꥈ8ӟJ wϷ@8QR{#%v(+ Fݧo8~d Gԁ`!RGo}A>;(:TQC@sbaۨ/tʦ&09k♚ :  B,F' DyFgS nla #{<;(4gЯ[tvܹpѸ3=^pPAl4yFla #8ppP%Ҡhvyk"Fw? B.槳sk [8S<{ߖƵ-la [-la [-la [-la [-la [-la [³[;ܚ-lq~[` [-4 l` dY }[6:!5oT c0dɞǟ TJVc 'NJ+suycR' IDAT@ +~A]kw>{'N뻱^O^eB[x#۲ ϳw! q4F(eL(Ko/|vϘ7uYAeq]o#d@|+Qu ؃ښAzUR2ゲ;/91_O}9B'߱]pww|HSFW +w9˴'F~PyZ˹؃P1v5x۟ңUNNgO wtN~qj@U-'Y.9wWԥ7n >Ū/ .>{78xb{ti/8g{is_?2w}LPG/,[ov>O.k2ݞc'M`-ۧĕ9m6׫IAcJ,?׼m}nrGOtcyr>uCZt}Q=Ғnjp>3&]g7o-0g7~5H~KqwgJa۔աmyi ڕp gDݮ\vyᑣ7^\"LgM F~=~tqI;VWŖ<3:&ج.HzMͦ}Y~MndfWkM~RjS@ѩes`]FnϳU/97Noqi3Di$??2$ϿW#ə|fC*yt68-FCzsNLn+V(7׳P^ӷWbW}qu8}ݏw+w=;}v y;\SC_>XhZX_cldycV2Fթ_$4:"XG[5%u~$<;Z{N͙9l8tEo.X]xQ-/\-OWO8F{#d.dɄ}֗ =`G_{\s{7sCU[m誰.9}ƅã8ZfUW\V۝َ7-H5;:]lXͯ|ծq5?dGIu+@\wf}PҬu$ UT,k?33n4Tr;74J|mʑo͞jhӏDC-sr3֑m^GU6S_t&/&@=q-0q^xx?FtRz2'K8"dpί2ئX`ۖVbkfĂg?zdVZ1.=uVmn;2JͦE]i:2VN3N-g?7N_++.=UV5k km$f& ~G>rhU.8]f2xdye,f&'j|m$Ҩ`UrÕF+m&:'N羯 Wt[4x{?us̢;P׿5B5=vJW :8.&60@q0 bk ;<,1oK6W4ˏϑ[r^s8?m>z켫1>F6Sپ?{pu3@Ym-3HK 2*O=yz{#'C>pn˺Q/$u\7-~Uuoe]{ҿ+_7``GfZ?1wp]ҪkT~$4EiiH*G%ە$ 9JCZ*d XCrtp$1ǥGx+gw\*ĈPuAzK`b~ղ2~S.su2$9۽wM/Vln^U7ZV#oً%/xSɦ8lvl^scy\ddDij_-)Xn|Ϥ;8qy /ىf3P7ӁO컶 :2QJE-1)u%N/TNNMoW~HT6n] _ܙ$$)NJq 8ȳ^v#yZD_Ļ?>Ry *7{6ox3੽Y\gѿ-v~tZTs` N:5ܠ4RAw=e5ъ3>eʍe&EZz嚤ΑXCϗmC2TKt"@ )L ˊN,G V# EC3*McV3 ڋ # bG)tQlYYIf4BV[鶡q 9}vv.__/|:jU3Y1Zwq`&u zh慪f$ǒ0w7z=0gh&t&M|u% B';ߓve?zžQ_>rpk?27μԉ,ƯC?˶wݧw9'ຫ\N.SyyRGfp6)Ajwtmfw2qQj wPkY I FЌ*ra\a(/*r^&AK9F޽Vb'Hۗ>|\ɧB(|[e~.ۡ2ر+[a,QI+g0&ǮTBpq L`]Gh%/(c8BGA& J<_e"?{ 7j45[}9m6iK5UDڣ#5VJ]!x 2UрZ.;LKcֻ 9$cx{j?{omUy~gsI%Kd 񄌍 !(TTH:IЫ:鮕Tzi(hRɲ˩D*IURUJCIHA `cl˒-ӽ3?}W1pkiIz7|odSlxpYOj_kf}sg ͋ .FL\Str,9r}Itv!; SZAiKJ"mr u2(㬗ᇔo_ڴq[_=/{nl$G|T=j^j~"d7'$Eט:uxV?xMK|.}wK;-Lsu:ͣ+}0 浪M) EEMq[wG-p 8J[yKRa)%)QQs#sGNmltXgN^92Uc 4K V!I;kJh̖bc%Ҏ%Y`Ԗ8j,04E(ԛb]CZ~LOK}X^/玞ߟ)JH)%;wHԐJP"J#FXP~Bs܇t<16_('4k 'T?mX5m?fզR1.>:۱~HԢ837,_̝?wx+y>S츅q}qݴy ٖlY [yP{Nv{Q?v+g')! ↥ށu%E==(!dA]'6y͡$!14'J/ f VAo@ f%q@$IVflN c ӄd/pӉ_oJf%Լzb%<5 pd~,8=+E{M6 ϵmNLLֹR,+-Sh+jM{}^뷬Xa+=~Yѓrȉ;dtv @* DBDQB]T 籮,Tpe.z[O\$l}b¹lK(CK\2[[ZG[# [gu~kP~t(_lSc|0oayX-ʒ² &v,-\#ԝ>yO֓U)Hޔ8]B-h3syH(l$Cw)M9ɑPޙ;zm{u،U.`2`n>=Rv!='#^+Bo6< Y^! *>n92!E@4A*}ey!Q]Hm,oo,{[_qdv#q',Vc'm8F)Q[l\ŤJ@55""֚B;tlQ4\fcQD;Ҵ$ Pq4 ؉& XՓdG6IUG"q x#DeZ*jۛy{nݵW,R6&gܭRB yTY rRl!D HD=x%$޲Mxm͔;Zt%sqQSD\דx ;I\?e揝?tΝOe{nauwEz5/@*5LT8,q;+s/rmx_Lc p"Ձ"D > St7pN`l?n!rLhF- iv6Cz]f},9\`B;쟟e;+i7b W@?îV2"!mEޘe -zݫ\'ݸ(o[1*N0*ݜ@tFR |uf|.%"$XL^L1e3dSئN*+I,d!*rM[RK9`猪 $#x\6W[3{=\( {OJfܡAo8YGh o@!J *Z 5aiLo"eV2AO= IsG')"bf.ecHbJ=>䅧H@KUeS#v]:|j?"~jˉYJtbX9gD mlHU+[PiraꊭN_>ᆣcdclmb !,hM΂> fX[x :Kx\7ucJ.DH98K!T AҬb2* kIޘ]tU 87_Exq աif(shCy vJCȰb³iVjā4gIkӸ0dBRHD]1H*,+?TA B NpQ%/htx[7f޼7ljY{& [QU 2jfMjXe1(  7)q:n"{H4UW 눨AM#$ k ЁB VN{bP( TZ[>}iKy:g_jM͟qtNAmuU0eXi |+VmO>(MW0t}FJ| HGv.H{Ll%zFIIH\,hQMP$v[(=JRi#58rr~lKb}k~k_=}q:6 C.ZA)VC\JpDZ`Ī3-7)^Z'> ͽdk4F9Y`cm7Y !n(AM@T*Nn  6ksڥ~@S7ԝ6 m 46'oRdR 7g!gk3NNfI*BꝫlS@QgdsSuϴ\5cFQξlex" .%@\˩zXcM8 0*fQN5ɪ$;[d]ю}tIDXI$ӳ~UI-\1%¸?"w'>s_?}{}˽7;&C)ـ@!`jGK  SIhKRa:+-tw4BdSg}G1z, 6a@YXaM U5T伭lsPpC@1QL7>qB-|%>c,VZ:yB3do4HDHGg⺡ T]{RpdV8` _ :"ˏ-]"ٓ3Uwjo}wA@SU~@1῝ K\UHu\ B "ݝ>Y%&yNVZR ѳo}[_^M6V~1= * PHdPTzۥpIL6K0̎HNHZ NQgT2mYtv$sa"HYr<Ҥ*:= ZcYoIZF \I~|:|o6C G0hQDfT DQ%Ut=/4JzEI-,>ըh1 O[G @PfeGU Jaǿyow]r8'VPR3a*9zVh`y4Fwl?i}"*qII@U0sUm{P !>$eA! D28S־uϽ<7WWߩM}9{P⠔Rr*`';xn~PUer(VB*2.*[]]ٶ㘕^YzYlF;(7_j;Y_^M֗>9o0:*U&TJ]ϒȽt8<yI5^1DBL,="r #a IM{%q! X#-'V`][O.z]8 \-f\l9Z $mC4k1M+)8llu,ZHGGY%[Tg_f1T:F[g5o]yB;zT+â8Nji_iVB΂T0SJCf,j06#/Amѕ \:ĶB cPCQ&Rj=}u- +a֘3/sƣû,5PVCA OJ1TB[S%H%jV_~+B;o~5RA*K%gX{g\~ܑi)) **ߚ)o)j Yy!/ה:LaBd209JiEi2#JGaJ\D+`cyH;<\j eN+L(dM=Q {AcYH TAmiT@9O.w?7j/NG*NSb%4D,J. hje$؁z],0aÖ揽KB=ٰN%ĉV?C(AkM)4=Y4dTv{p?lSBWA@j AnbU_"Q5_dgw=гZ䢐T-LC W"1.=AQ~im",iK`ә?=wdqi)AoYMyys' okaoֲ Y]& eN,w8]%c84ꝟY>7!n-Hhrᘙڒ} RSvl:@(!?w}ɝ0&g^]GJcs}{]߻WEz"%D~#{"RO'l+{ǎ#9o,K;%e]S߷ܽqy\)qZEC@lf%K%#-+N` g?uޣۓEgH^zн:qM7w|/,uLQe*UIa׬eJYa" je-+qKsGO. N)ƕ;S`MqHuY~P6a_$@jdֽ{/4]:W;f7J7@-[mhl72}|j9qZ|$ƲE](Omֿ]W^5/jQbO !N<+0a1BB7F 5z4g_TAxZlQ fTF[Ȫ\v@v](b=c̷fҷԻoATzӿ5ѓqZju ;_/?[_ ݬr|Q9P0\wlQ SB l">ԁ!ձe9JCFUw{"RVB AZ_ 4X^ !̋3Hٿx7bw@SJ< ڹd5b0ou#( ݴ=:%]2~Cs%֔g_yڈR[;8 e6T|/|O ĕ?Y(D{+5SBլYz!V#T=Ew N )ز'eׄPKG7/:k !/~#aFaFaFaFaFaFaFaFaFaFaFaFaFaFa^Tx'wiKPaEpRC] [4߬]Ow{Zn{ơ?o=b{#p]:?5G~uO]CqUJ=r5ɫg nF/d7o{lK+njʱmJH adoD9 i/n3yO|EfQ4ʉ9t{^nc#޶c++e[}ö-v^WxbVLܑޞCÎVǾ `1șqB נ(o ?y7hg^U_qļR.4&0wRs˨ cANq% xָ[Kq^g]]q1]ZOh U{rlfdj2&.6UWx.e&~.7]wߦkgk>=јƛRyER"5xT9w|E2g7虬վz(4𔼎i%160P%RUD#?wtɋ*M .=ut&PCx,uaxR~]nC-9:~M .[y.բ0{K-z6 ZU]}cy%:~' O%}ØK`MCp.Mm~lxA~G\ =/^ua}X6bյXR2AC4߻ZK6\27ݳsmZx`˫05G%d߬8~p_c5s4mtl}ݿy-^ͯA^0ûSr-wVv7*5o{|29|m{_¨ěo_]u+dž ̌}5XIRNZatFl Aנ q256OgD)~1 U۬+GIgaι;t R{7uDR1L^ҽD;E0lA{)%E*+W* ގ A]R'~/5;F{ KwoK޷13aHԐ0HN\^ $eyP-bJ.*%**)%=*fI,4i ,6}.rq{b%ݧЃoGy'&=q9c RJeޖER*Q؞?q摅SgeGgf7~ѩ4o!%Q,NR:`gJF(C[ʾCZIDTK-UHe2&̃wX frΖ8p8p Z*NړpC3ڪmNGرۜݰļlp6 6'ī+fK9+SNyc}83_z˷yп֫u/>-Nӛ>9)O>*tZ{T*y ނ)4Y<q[NF'˅g˺ۅGNE-KxXx1yT_S\w#f1 4&p^$?3 q:Uy B* rpT/Bjd:-,yHu>Vg~6}/=}u;d&rrHW7Mӱv`Zu'/hnc-]ދf ۫.n=wƗJ5)g?ſݟZCn3Ʉ#"/)b˘Hh ^zcfaE"8ØOȅf^CcMb&wjSəAM~ÏStؽOMɯZ^ec6Л:yAm+L98~ ʺً&qv7HZ91ۑvnS_ S@@HR-ǃ) -fچ~mCG$bNıFK*r(`W"`,hM+vL~eovz"g]"輳F:c*XT2l`@J R*HwPR4U`#҈!p!Rq\4eq15xW\8uJvMGygt W;\z/<1L?>w 8sl-|EZsEWK9=Dwcż 93%g9}%c=Q 걦TYУlY .[OVxX2"𤉦/P=EQ04+`'p s/לYىoMbg'c@{˵pVg( c.N]u75ן^a!`0B59KCj=[!%R& pΏ 1|U0H !DE:k Bbz?-kSW הVqNZc.}!,PռBQf{MTc6\<o ZRJ'E\p|F&$kQi<x>Zҋ5q|v<Ɔa\b)#8>1Ccΰ3i}B[EA~f䐊Ly oN52QB M%Z%JFE__i'K?=8N IɅYh 'uszdfkA ~\3 =Gς@I&ii, :JkNCX<,#2MK&ZPpG@.s FSKXi{OIv6r\С/䑣_ah19pZaWrWͷ 6lAB! ]d$+ 8_Mr`CJT_tԘYm蹏tlJw) t{h‡*%{| .~H|r UBW%B]E)T]E~9=/~bgyK +6\S>w(pz[Pvlݲ01.Ҩ YIyuj[1=YN"Nh}$+ΐ參"dJ]A$;4DTȟx!jy0 2v:QdXsH_ou+Pa$ fS[cpO>YǡFřb2z_6"m&ey]:m`,2b{VAlFS-D-P'+vIfͷoov^N:~EE鵸6qBVJ ?T*$E@ZR*J5Zc>y)L<*\ENBL9LBp!D> !kJPi&U*9HW=&U ![Ri]eHj f?qɻv{'MYTF JȐs/to"eN2cHtSi .Q{,=%)"c2Dcnx2&s@U]Hm]hi^d j;Ә9FBkC&P*ڭZW*ɠJz^b}A!!$]kiLF;XIKe$WZ :QZ .ڭϽ/:'3WqMEy@:A +#kCqy>T+v+TjB :x Sf"ֆ/FEPzK;*ΎlIDAT|Olz %{OʱWT\Gɀl|բsC!/P Àx^/!!E|ŤFȰp`?/KGT!#"n[7:a$A[F_s;BJT>J"cJ>, A*T/:._P}$ai۸)YRtw/GwEM٬SsV}7[X2'k;,(%HU+Kot4'~X sCޏ(Rv/ϕ?'7ᤐDVQqgvͫUMJ*`;o8Rà1EqE;{ mpe9*g@W$rdnz582޺&QUeFC^ YŖ#{8U]ei8ⴁNQd+}`&=H\ 2)w[~&T`u#gvf;"3@W;'ϠSTUh@RRZ{ḽ4-V(+]3a1<4A[OgV݀AtlYKT-$.<ڨE_6b g nK*B 4W0G&زXκYs,/,v XTh 9" 97^VPzL,?ehqqc]J(> yۧI3/IdL Q E2)p$/Hfư(\,מ7ͿcM-Q3w}JPB%Rı" yYsU;0 * [7' 8$n*M=,^[ D-̖1MhgYWn>էO{z )*.@a%U 1wԐW!'eU}(1Aݑ[0>?wATn=TH WFe/]^S{O-WU\JpdG>;;ȃ #ǚr8/9pH ]TTw.7(EYZg=M>$WU f',[ppqAhRnPAOMm' RLiaKu5Epg"9͋y"@(AGz;}`O$[B˷䓼 Ce'V܊KZV|q Lo7 eD*^] ::siBAoF˥L,QT(zm3pΰvci[(pJ`|k/<Ã0GJr`z{ Q{@Pt#G0wdC*U5qC`PBo*'HϿ]7>9bi (]QP,xDu! [SHBQRd=݄a͹].>P߭v$u! >]7|k? T!& %mFJao~;흚ɇ\J]6ZgZx<1ڄ8r-v w F6ǫ S1QsXƹ7ۺNpZsUE S{:d:oQzÛ|{[Uv;%*=J{%UbzYFx]J^PJ;d6Wnֶw+2/%JJX6%H6,5%eM1U?~kʿ8sG"'mhMv޷߱QZ7',;)B1TjMw^5ޥrC,#AKZTn۳_Z=N]JHy1kpkO; *Hka[QT*U{r(޶,o?wtpFJ^DȈw"huh_kfL[BFşo+/g?7)WOc1lO;j[|E2#<#tL@1+L޷w͛A>u.{@o%eY 6zؼ\ϕ%{l.ChЋ>9tD!?O+~7pܒRpزVW[5# 5 " P~w B[?? r9ʊ=!iliڳ=_RزXYz˟py?h]o驒vi劸Xwɕ KVygR82t!+fw jdװ*V nYI{ )Bʰ˷'/:使T2φ,g]8>3pAhkw ij%g(IИ4<+00H2"p@EJ܋0e[EɇG~NG;Y?>6?#@cU*uA]ugBqƖH>T)2kK,J!ء*]2P_Ά"Wibr,)e{B`l؃ `qk3MSFuO}h~:i_}ο'd{zIFU! nH yۻcZ ︼'|?ę%P-wa={t԰JZkv_ŁU|,.|k8%W C[ڡP@=;W-M!ڙ2˖mON%O/IU TvX'^T@)$B)*/( BŁЈF0symn;@]rx$0r6 1$IHz,TtƓ_~G濟5(D>Wef]3Dp%઎ \ek ToXSKHy5 Bl]/F8dfe8O4p7[d{SbYcWF%oko d_-e$מ{'j -* >|@'1R%X[. .Wޕ'W.(+[Qٲ7mw.8҇W+eD Uw(/-!D۳ P] ~TBѥO}􇖬-~kw'AD@WHuc?c?c?c?c?ǏP1mIENDB`tiled-1.0.3/examples/isometric_grass_and_water.tmx000066400000000000000000000041721315121121300223770ustar00rootroot00000000000000 eJx1lttywjAMROVgyqVtAoFC/v9L68xoh5PFPGhIYktrrVYyS0QszZ7Nvpvd0n7y24L1Q7MhrTSreN/le821HZ7lv9qYa6sdE0cYs/kX7PXYwtfaevYp7WDrd+SnHByjYr/npP1zZ4/elcuM71rjeckdc5KNHX75fMwc9s2uzb6AsYstJzwrv5/Tz89SLIZy8v203llV8xl7yMU+462/v81OqA114/UhrzUxRqwprnh6ZGzp2PNQfPqRu/X9hnMV8F/xLg1L42erDf2oaa2RI2qPtbgbhmw2H69nMUxx/gVccXdC3AW/o/HV60vW59Lhu8arDxmfGIPFUV1qbLVQEIs4PlOeHQxqVjmzr5mLYsmf+5Qj5yM1r3Ne4p1D5VcMh3qWZibLx2fYkBhPYOv81I9wbrGd45zFU7zrndpwDjkHXXfej9zHc3EG+D3AWcCZMJif7hTnVxr6i9edtoBDz8N7kxqbY6sN9gJnsnqIOqCme7Un76579sIV8dccHvHqZefH76BP9wjzkVapM2rL+5/8cR6QS9eh8p2AT12y5oO9+7yh5hzLZypnHX29/pzB9PE7bOg8Mza5KvGu4R7mp/89zqvr7x+TnxEn tiled-1.0.3/examples/isometric_staggered_grass_and_water.tmx000066400000000000000000000052361315121121300244260ustar00rootroot00000000000000 eJytl21zozAMhE0ghCOlpJAp+f+/9OIZ7fCwNaHt3QcNAduSdvXmPFJKj6csT7k+ZQ55i28PrF+ecgqpntLgvY73JtZq/Nb5LO+xlqULO7Ix2fkKe1237Gst+z6GXGz9DnzC4DYa7HdM2j8V9uhdWPKeM6ROW3/JHTFJ3gv88ncXGPLzT0hrPJXw8HsfZ9yXynSMERf5pP2Ukq+K+YQ90lkHL208B/BGH8UdfZIeiXzTmvSKp09w1Nu+nBMfoZ/nyF1+n4Nv+SL+G7wrh5fQ0yA+j7Cjc8xp6SRHzD3G4h66esR0NLvMM88rcj/E/ipt43pLa50OaZsHS9imvrPFQxhu8LXF98zBNa195QNxFpbB9IhP5kKV1pqmHfF1SWv/WiIOwqPvwn9La2547Lu07YPMUWFhf2zjO7nSPtljPVZmh/mstYxlDh1XxF/7hfuStn2PuVzDjvLZ8yx/+wy9A/iVP+wnFc76PKDvrCu939JaF3r25ov3qwrPGrqG0KGZcodOzhzxr3PMI+Lw2mSOKfZ3068c6MH/3eLN2ijFfkRclD/SPaW1NhTrm8WFPPlsYvyZGzNwqb+9gcsu1sg3+5Xzx34lWzN0NNApHRfsVz8mllP6is3npuq9xn6f//KnA49eJ6U7DfujzzDPV/Zk1ajPSuIo2dy79zivp4hVW7DxE/Gcpz9d2vb73whzxOMmTHs4zvZ8JV4Dytf8VK2UzmWM6nV7XHquMV5Zt2a7epifzzWQe9K0o1+547NBdb6EDfFUslGl9Q71iiOPO2e15uQrrrRWikmDNYnqWvr9jl8S9tDB1nTn0AzRXFddsxe/slEZt/zOGcK70Bz4eX8o1bjrEu7BbFP/A3Y0A3jXe4WB3LZm1/+/Ca96vd73ckpxXyB92vJXEvnSpS22PSxzgYculTHod184e9QP+V9TMeHd3eNBnaPZPeKKNVXCoH2aj7RxhGM0nZ5LLqpb9a0x7de5x+SavmJyrqSLM+RyoJ9YJsThuiP8X+x3aPWdvTzmveo9rXdll1c9UzV1hEd3HvVZ3pmPRPVytP+73O7VwHdwHIl6fGlNfelf9KrHDwU77Hu/saEer9rkf8T/YUNxLNVna3v0/S8kYST7 tiled-1.0.3/examples/orthogonal-outside.tmx000066400000000000000000000324261315121121300210070ustar00rootroot00000000000000 eJyNWE1vVVUU3Y0KQeXL4kBL7QAiEkcopQOIkjgysXagYeLIpE0HGucEtY5U6giw1Bj8AdiWxhZ+ANLS4nv+AJKW1+TVH9DklWfSR+LeeWt51j3eWxmsnPvuPR9rr7P3Pvu8hpkd7DFb8dYb24Pf89bFtOOio8/xquNreZ/jdccxx0nH53j+SN7F81nHOfz+BGs1vP0C706i/1kZ+6asMWRdrvMY+4q3bzmedTwj/FfAO/i2HVcc10s4f+t4QzidcEw6vnd8lz0HfrAu3wOO8xj3seO44AT6cY0GONPWTx1jjp8cvzjO4Fsbfan/luP3XXgrJ+4XtWnjeQX9VzBmErgsdud8lXdwCb94G5w3HE+g+R5ZcwDPDx114U3dY569wkW5UZ8J8I6+AfalPbT7MvhS03nMMV3CNzT+A5zHMt70obvezjrWwfue47HwynUhH3JivwG01E1Be0cs8eW3mOd9x2lwXHVsOx7AP8bgI/PCZ5+PmwHvHceSaK76UZO2cGyg1X2mT/eKrtOwUX2Le/RcicbB4zfHyz6239sPs3VijtB6E33XRPPr0CbXmpwaAvrEPPyBvsDvOn4IbQ+4jkHnDaxfE52POl6zFIe0n1oH12Vw37Hq2HzH8W5o6DgE9FrRn+l7uk8rVvSZi6LvDdF4GaBPU2edS32kDjub1vWrMt6Mq8gJkc/OwQbypq9T54jrKcfVkrl+Fq5ctwn9/hTOZefIgPC+7VhEW9tFb+bwyL2Rw3le5DHGeVuY6xrma0DPJtpYL+Ip/JT+TM7uT9/k649jji3MEWMO+5gF2Py4hLOel8y/A1bMKdRbeW8K99BkzlIOmMVe37GuL2u+y/PYCNbbAkfGwCo0vyX9cq0nwbcsXnP/e97xAjADzutoQ6def3+kJ2lMnCmZL/wl/C7y87bsTXDuOB5Bt//jpbgiflBlQwe6am4bE40Dw6J1PscW9inmiJhlvvzVcaAn7fnT8JyC/ZG77u/SX3Nx8CPnQNRxl6xY05XZPYN5HoBv+F+VL49kccF9on9GG757q2J84KXMD0bBrw/+EHt7yro5umqOh7IW1330FHtNvkvQdg72co8GKtajnn2ib+QJ1p7T2XMgzlDPI//mv+C8Db5NWVO/MeangB/Bt4Y9CnuXs7FVIEfWofy9d5cxPF8mRKtNaDQLvxiy5O/xvgMteQ5si7Y1PLdkf8owjvW+hIan7L85gnXJRLd/wQ+ZD+jPjOU1K9ao1JLfeWatgfdtvGcNsBtnzjcu+/+VdWMubNA6i3lNx9MWahl7qvUHa1RqS79pWjord9C/hedFjLsKaByQ72KJLax1437GmqZX+OV2Mz+FP9y0dI52wKuFd3y/CH3Zh1qz1f7x7n62X/USHm3ggqU7pdYyeZ57EedTxI3W1XXw25T1a+DFs4vn/Bz4d7BHm5bOOe4XvzdLeBBRO0YdwzszeYevjFvymYg1xiv1qFvKtx1o17QUi1EXMHYOgfsR8G9Z8hXWiZyrjvFVnFl/kfOxjDdrmeAZeeuapTOce8x6gHquAVEv6jnL51VozH6shdbAn3VnrBvxdtCS7/LdeUv/NUQNxntlG7ypK/dxHWuw/tbzlTVIrMlaKu4Zeu4egm30I+a/WbTL+KaaHoeWh8GX+sZ/I1HnDlixFr9nqY5dtFQztjK+vMurbsH7hqU7J/X+GxyXMGcNWJI9oy9csOJ/PKEr/0cJe96Dvjdl/3g/2ZZ1uH9/Wbe2GnR8AC7Rb8dSPOV2jaIfc7ae6ew7akX/nQRP+kC8j/OO98vgvA95Yj/q2v2SK7Sm5fx5rC2gT/R/YsXacRT7EeMXLMVdcNa4rYrByMd6B676j44+3QFn1U7jTLkzz6nGw/I93m9Yyot5HcdzhPkrELkrYjD8mnGZc2a9pnUO+Q5mPEO/fivG21Grtktty+8eqjM58b873tk+s25c6t0+cNdS/cAYv1Oxfhn6pR20oh+dzvoOZ/b+A6OnAUo= eJzVl9lNw0AURZ8ltgr4YquAjliaYPl8DdAChCVABRB2KkBhpwK2sKQC4FgiShQ8tseMx/aVjmRLY+fO3JnnFxGRGZiVamkBFos2EaOBQGQw6N6PFmcltcbwOx50vU+neKYztsb1OmzAZq4uo9XxbjO2wfUBHMJRjt5c6RyacAlXcF2oGzu9wCu0YCohpwcPftJqFdZ+r9uGMf1nvWjtwX7P/UiEN5vzUiZRW5Qao9QarUHRftKI2qLUGKXWaCOjZ9/zprYoNUapNdrM+Hsu5m0jaotSY5Rao62M73Ax70d4gme4yOgjSb01tH/eu/947xd8izvfS7Ds6F2+VZP8e5oVx+8rY0/D90dN385QPnuapN7DZnxvT1O2HiCNqtYD2GaXt3aot9tQh62K9CJn+DyFEziuiOd7fN7BLdyUxDN5C7kL+Yf74I8+8fkB7/AGQ+zdYU/7t21YI/IWchfyD/dBoibwO1nwmSNvIXch/3AfxCopE18ibyF3If9wH8TKNhOfMq2nTSZ5yXSeTOvZn0nU83Mw78Bb1P/tUKbzlHY9k87jD20Li3Y= tiled-1.0.3/examples/perspective_walls.png000066400000000000000000000071641315121121300206710ustar00rootroot00000000000000PNG  IHDR\rfsRGBbKGDC pHYs  tIMEnp IDATxQ8 EmUĚk5kb>:b &[uTEUfǕ6;,G1bkߏ@JǣFbYK!֋~m Dј)*~P'E~P'E~P'.C!Z"mq?7 S'֜鼘sF/9QMR]+T1Ƭ {} E@ws|"@?p @9("@?p  ?4,%"@$~ IB?~'$ OHW#߷KWSϾmj̷̷*O룦bq> P@s=v|r}X<h8Z4py%C9Oj `S2@>i -}R@;D@i)y/MuF q<"m;,~>L;c!p TXc|rmp@g%Jg8_û#@{RK$@H -Km@; @-@}H @9c8:D[&Zod F49  " PbI$@?ĚH @=E@:"!E ;B&@@9H "e!@iI$@^Hk"#{^mxKvϬ&[kU\Ϭ6|\37?)}1F]l"isX>?y47~m"h}0G%[9󠩰2Oڻ>-!ʫzz$/$}ǯ~! #?~ I@_Hȏ_BG~>W$/$}ǯ~! #?~ I@0M]oQγrߒ+NǾ*˂2cI- UB! @ _H~/$_$CB0 %ZMs8:o= /$~@$ B! @ _H~/$_ I@$ B! @oC{U^m8*l1 I8s '}U۩ Ba;_jtwx]ט82*qi}w`L~BOm! '~_H - xrS$[23!k0'}a[!{O=U_b⦮g}`q"˲{}0 !.ڏzd&i0 J )u (z N@`G  1Fs!|.-͓ iw~`xx%^E~GO`1dlЙ8X2ηwre1_='*i ð@xmL@o/z @x @ 60sX@m{cX% ðj> 4V[ pCP{lx総 HqmR{n=\_Z[?{*z5xnOW' ^F뺮Mx|PKV@؛)6S0!x 6*L @(;y  @ @5ċ=@C~   ]v *Wh/w7rDO6Ub xvyx6r1-  j\e@C@[\+k;鷡|^ {Q~=r,,g]8akc0Vz垀a'DOn_r`@Ø n=2AN{s kz A@waaPn47S,i}!lCR_}ąTIENDB`tiled-1.0.3/examples/perspective_walls.tmx000066400000000000000000000015121315121121300207040ustar00rootroot00000000000000 eJztlOkKgCAQhLfb7vd/24SUBqMMNevHfDB4LczusihCCCHkTzRay4XaDP7rxf1882ZpzBqTp/Wo4c7ulRy96LUKRx3EFYF5+GpESpA9V845pT/Oxijn+luIw36k8vf1Rpk1xPepx9vczV+O3GL6n4JJ9vkSOf8/Qwb/r+vHP8ZVzFwTQshf2AA5owLB eJztzgEJAAAIA7CD/Tsb4yJbgiUA8MO0AwAAhy0rhAAE eJztzjENAAAIA7Al+PeMgz0cPK2CJgBwN98BAACqBS0QAAQ= tiled-1.0.3/examples/perspective_walls.tsx000066400000000000000000000007341315121121300207170ustar00rootroot00000000000000 tiled-1.0.3/examples/sewer_automap/000077500000000000000000000000001315121121300172735ustar00rootroot00000000000000tiled-1.0.3/examples/sewer_automap/rule_001.tmx000066400000000000000000000020651315121121300213570ustar00rootroot00000000000000 eJxjYMAPPHHQ+AAAJfgA3A== eJxjYMAPPKG0F5T2JqAeBAAmbADf eJxjYMAPeKG0DJRWIqAeBAAMkABM tiled-1.0.3/examples/sewer_automap/rule_002.tmx000066400000000000000000000016451315121121300213630ustar00rootroot00000000000000 eJxjYCAMfLDQPnjkiTGPWLUA1AACYQ== eJxjYCAMvKG0FxLfC0neC00dIeBFgloAz9QCVQ== eJxjYCAMtND4yjjUSRFhFgwoEqkOADFsAIk= tiled-1.0.3/examples/sewer_automap/rule_003.tmx000066400000000000000000000021451315121121300213600ustar00rootroot00000000000000 eJxjYCAMfLDQPnjkydVPDgAAZj8DRQ== eJxjYCAMPAmIYZPHphadpgYAAL88Abc= eJxjYCAMmLCI8SCxuQjoF0Lj8xFhJ7EAABfQADk= eJxjYCAesBKQ5yXBLGoBAAmIABM= tiled-1.0.3/examples/sewer_automap/rule_004.tmx000066400000000000000000000020341315121121300213560ustar00rootroot00000000000000 eJxjYMAPfKAYnU0rOVwAAJk3BME= eJxjYMAPPKEYnU2pHLodhAAAb/8D/w== eJxjYMAPePHI8aHxeYiUIwcAABkoAEI= eJxjYMAPOND47ATU0woAAAgwABA= tiled-1.0.3/examples/sewer_automap/rule_005.tmx000066400000000000000000000021251315121121300213600ustar00rootroot00000000000000 eJxjYCAP+BDgk6LHBwcbnxy19ZAKAMzFByE= eJxjYCAPeBLgD6QeYsyj1BwAd2cCSQ== eJxjYCAPiKHxRYjQw43G5yRCjzAaX5AIPfQAAE2oAGM= eJxjYBgcgAVKs5GghwdK81HZLcQAABQQACU= tiled-1.0.3/examples/sewer_automap/rule_006.tmx000066400000000000000000000025431315121121300213650ustar00rootroot00000000000000 eJxjYMAPfKAYnU2JHC4AAAEbA5E= eJxjYKAMeKLRyOKeWNj4AABbzAG3 eJxjYCAfeBLgkwoAKZwAkw== eJxjYKAM8KLRlAAAB9wAGw== eJxjYCAMeNFoWgEACrQAGw== eJxjYCAM5KG0AhFqKQEAGSQAQA== tiled-1.0.3/examples/sewer_automap/rule_007.tmx000066400000000000000000000023351315121121300213650ustar00rootroot00000000000000 eJxjYMAPfKAYnU1Ijp5mAgDb0wTB eJxjYKAMeKPRtNaHDQAAdfQBLQ== eJxjYMAPvKEYnc2AxsbGx2cmLj4++3ABAGBjA4U= eJxjYCAMPNFodHFcfELmEeITax4A5OQCSQ== eJxjYKAMSEJpaRL1aUJpbQrtBwEAMlQAiQ== tiled-1.0.3/examples/sewer_automap/rule_008.tmx000066400000000000000000000023761315121121300213730ustar00rootroot00000000000000 eJxjYCAMfKAYGwAAD7AAmQ== eJxjYMAEPljEcAEADVAATQ== eJxjYCAMWICYF4ccAAHoABI= tiled-1.0.3/examples/sewer_automap/rule_009.tmx000066400000000000000000000021541315121121300213660ustar00rootroot00000000000000 eJxjYMAEPlCMDQAAD6AAmQ== eJxjYMAESkCshUUcBAAH2ABN tiled-1.0.3/examples/sewer_automap/rules.txt000066400000000000000000000107421315121121300211720ustar00rootroot00000000000000# rules.txt # Copyright 2011, Stefan Beller # # This file is part of the sewers example for automapping for Tiled. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the Free # Software Foundation; either version 2 of the License, or (at your option) # any later version. # # This program 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 General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . # lines starting with # or // are comments # all other lines will be parsed and treated as filenames. # Feel free to comment out certain rules, to see if and how they are working. # So have fun experimenting with this bunch of rules :) # First apply only one tile rules to fill the regions # # We mark the place, where rules are defined, with the RuleRegion layer. # So whereever there are tiles at the ruleRegion layer, it will be used as a rule. # In the RuleSet layer we can define, which combination of tiles must occur # to trigger the specific rule. # The layers Rule_Ground, Rule_Over and Rule_Over2 define the output of the rules. # # Which tiles should I use in the regions layer? # Actually there can be any tiles, but it should be the same tiles for one rule. # So use whatever you want, maybe a colorful tile so you can see easily that these # tiles are used for defining the rule region. # # In the very first rulefile used for Automapping it might be useful to define # some map properties: # "DeleteTiles" = "true", "false" - This property determines if all tiles in the # whole region where Automapping takes place # are deleted. # That is useful, when not all layers are covered # at all places. (Check the Over and Over2 layer!) # "AutoMappingRadius" = 0,1,2... - This property determines which regions are # automatically remapped at live Automapping. # When you draw directly into the map, # not the whole map is remapped, but only a little # place around. Here you can specify how many # tiles at least should be remapped. ./rule_001.tmx # Setup the right transition tiles at the border of light blue stone tiles # # Basically it is the same as the first rule, we are just using bigger rules. # Whenever there is a light blue tile beside a grey tile, one of these rules # will apply. ./rule_002.tmx # Now put straight walls # # Note: Compare the regions and the set layer! # Not at all places where a rule is defined, there is a tile in the input_set layer. # This means that there can be any tiles except those used by the rule. # So there are no black tiles allowed, when there are no tiles in the input_set # layer. ./rule_003.tmx # Now we add inner corners for walls # # (No new features introduced) ./rule_004.tmx # Now we add the corners for walls # # (No new features introduced) ./rule_005.tmx # Correct the error we got in the two previous rulefiles (overwrite it once more) # # Here we can see the use of input_set and input_NotSet # With the input_NotSet we can define which tiles must not be used at certain places # Important sideeffect: the empty regions in ruleSet can be anything now, including # black tiles as used here! # # So when you use both input_Set and input_NotSet, you need to specify exactly what # is allowed at which places. ./rule_006.tmx # Setup the corner stones for light blue stone tiles # # Hey, there are multiple layers called input_NotSet! # Yes, when you need to specify multiple allowed or disallowed tiles per # position, you can use multiple layers of input_Set and input_NotSet ./rule_007.tmx # Setup objects now # The objects '1' will be placed. They will be placed based on the # Over layer, which was created by previous rules. # The placement of objects is done in south-east corners. ./rule_008.tmx # Setup another object. # This object is based on input from the Ground layer. # It will put objects to borderstones which are near an end of that borderline. # ./rule_009.tmx tiled-1.0.3/examples/sewer_automap/rules_sewers.png000066400000000000000000000004721315121121300225260ustar00rootroot00000000000000PNG  IHDRH0<sRGBbKGD pHYs  tIME/#tEXtCommentCreated with GIMPWIDATh 0DёpInBq]¤ʐKAnKyS'$mg=yz= @d @ @`,ە1h->qB$&1ILb|$&1ILbHLb(N eeIENDB`tiled-1.0.3/examples/sewer_automap/sewers.tmx000066400000000000000000000014271315121121300213410ustar00rootroot00000000000000 eJztlUEOwCAIBLH+/8/eDSBQ1jTNHuZiDKOGxSEigxDyCWYRtPsx6HBH74hyn2r9zT2T7uj+jPemW+sfrRai16K1ut1ebtEZ8+aFdxaU27qj5a7O1FOfRd1v86XlZc+T9RZVt3aG6FrX/0UIIVkWa5oFDA== tiled-1.0.3/examples/sewer_tileset.png000066400000000000000000000533511315121121300200130ustar00rootroot00000000000000PNG  IHDRgbKGD pHYs  tIME  4@ IDATx[q&Ed99} 93$EYz)JbY$w5 7 0h iWKQpȕ4953"WLpN5:zzN*"3##ˠ˗/Yw7?< xn@sz>|<7= xn@܀|<7=G0~}—'aӾS7q_@0D9#<BcD0" a3u7vBNr ;`vu/u"{ n۾vQ}y)fH^0fٴ[ն,QDβ (%9S]OG7b+tgp_R}# !p+挈YUlm;GUBHJ&eSaXdgYE$  sȲ̲2k(f>}(Ff9 TQ%JITc3|{#D0s˲R޼xE$V\Žle)uwk7';͚~H>c菟8eu~X|_??|q'ox:8wF߀Vw9B6_aLyN= p>gaB ~pTWD͋NWðdV?S;_*1w", iRLY(9VE)ʒ$hFD.Uy\^qs 1y޻q{o<wHnD.eZ)5Y6#Jy+yUi5/H:\ev;;WbL5w㯫|{2ʼ2`Cpn֔|YMSe\>,˪m@zg(;oF;sbwXHy""F0텐3{cښ`3O0 > }:#7*l:1熤t`s*Y@ Xbc6M1dry>gٷ4|)B&RU9׹o}ƭ@7ndOϞsi_|0' S۶;Q.ϋmBpy|r>id|}c{o_\:d0IJ(,[5cnxCp}Ϫ2 mQd݁">0t]_U{CVQL}}),(QUm1<޽lv7f)jǁnնY0,~|:#'rY/*Dn;"#""sNU@L{v"2&Vfd0{Gnsps!_]cղl֋g:wy@<96syw>Gqbs"mW#vDn^gW.qu41R{ݢ(wnV[[4~ZL&[nl_Lc>Vs@S7fYi&"zq (ƺ(򔺦y@y<2MwyQc8|{(te1BpmwyKUM6^t:_,ny< b}>jޱij%! w6 |!.S1fn:u[߹|/-Nx8G/tC$݁,'ʈ/WdYQSۻ}߭VI>,K_TCYVxMU\Um9Gw\/ yM RJ¦2e>F/2^g6%s7lwǵdV!fjާ}EC ES1Uu fwq hsӔsL`Vbj0v Q8m+]wP 떪vq =i<`)s<>%$0St]}PMiH^!{3M*"c!"\MIј6|(fQ7\sXU] H!t3z<۷|(vm۵O0'{*Ӷ_|iϹelzpqw D`R"<~ksΠ !m)YCYȽwmb r9E@1v!87Dpq Hu;¹uV`fa6穪fuòh6͉19$*0|px'Di!=ZރOߜN>@a1D"6f޹"0tyd2޾}cL}dYp 5bqeYєTι$ceEӴ"q6v.Lj.h`C&]3xG9 cwEADž(8+i4E6:b`pV[7 G]0\׀lKaGyz#9[%aM#T 3\.hND16]wQ (fy=^tg:wy|,>|Bybr|8D0b݁T{չuFRU*eMTM`D9Um}Osf9NI7Xaw.yr߳`֟^gBdXz{8YBvJCLd1;f9@7]AJٹ504)ufN9wUTcm$3Qf"cZ1DѸ 0y5KQ{)8ib0,NBL)u]\?Pj)adS!3|r qvc<!q5/{aKe9my|rʬDv}I$@DfzULBw,-˒6m1 ̕LD]\rڲ D9?wy&2"L&`L2m;0O$"uΕTg 26mߋ;wluk@f(7;ŹuFLfJa&f9bNIDR'llt*/PY^Qs3q.;׹㛦_=wjǹR[Й]D5^YzO&lV}TI!W5hTMDLXU3&BY3 T"Cm.tMtJD5@]3x@=GѶysLC`2f}4Kf0M#"†j$:LUU["f]3xU#f "}٥4}A$XaJE6b EB`esY{s躣IsdFY$kMᓿ$YUͦ)-gݶ2![.HPJ2cv")<,_?_/<*ﺡm?ilX=z*gCui26c qbdH,bLL2mk,lm%H)Cv̺acYnL(f1)y}D\u6}|&*c>,tI2dټjәemȲN5ER\?*ER,U%%23f 7MMa"cv}f!@ckp{_{c\uЫ_]<;;xmk'\~?=MY:h RHȹE,+fv!xU2KDL8 Ȳ67JeFf!7aHu,2%1ZQFfK}DRF Oi1 fq1%Y@# #,OvXwcYWuuA8ʲ(2"Ld(ˌ4c{su]_yJɹB`UKIz]}YD_Z=E 5 261sgf*cy"r9G$D6m]瓵A۸HD6q܅Yw2f㟊 dD1q-7'a]}5f郶q4 їa<6բbL'3Qs{w'?_3bk_ GU(A14L,clo 7.p }RϜT$3O㳱':6Fh~?\^oz"ڿ[G?zk2!~- s9oxUˋ21[,x^:q,? 4aCpRR|_UrVNZ1mDb"h7uҩ'33;C֢׺oxa`o r{5313#fJdU`{fN)oZFd]!3#i-L1@zU!Z^ZMqRRUYJ`޻!`p"c:y)&C$0іcL5D4@T7.l]#H(}.i<@k]7¼)//,\\n\3O)&Qv{6M2 92Lj*D,˲< F7R* 2  Ar31QұgދyƺY= ;lL`֏ #vqg}0!*T))Li9Q8fL;+ ff^:`J0pșy6i pDIm]zk6hXS&"9wRdsZ`JTRL;"6qclp%KwP- ,x!:s89L혉r^̘3UzƦ˜؁64<~z2_Ώ vb'!2(U +P31;R3fj͈:1O:>^˘d6掎.WWc< s䅩rץfEAD؇L j 0B9bZ=%!< }0)sc &D6g 36NP:6p,D3֥NǼ,߀#^$bJDFDc2 Q3191Y{/XUydcspƄ-=NTs0i!l|I* D@LDS%ϺoxaԔwvg S3 wqHf .9}qspy0m3EATy׋10UޙI&0 Κg}>І˜h>YU SAP˱C  @3 q2I!8%*h0SfDs0^TkQh扼' V]^{l/8z=b_,G"ͩN>$5SI!&IkWzќݔi˱#Z5Itc֌P'M'b^^ZS^9˜3(1S"(N%ΛFscT1Ù\9ǪJo N+Baq ZE9$~ęŔ ΂cA,slfDw0^ `|s^Tc"s3 3:"xhC0vߋPl4V$0d;%!g(&3rϽHm "}0#Ib@gll 9cfysĹZjѱlhP]%Q03]^#/`#/%Cgd4d!s4 v*w "rcfn1LD$HjV9P1-" yfGdC7t76QqCyaY{ߊJ D옐g@C@|1cRæ8PR%fgfc5!@::3G&&j6Sk}xOIhgfF4>x lh0DR !$$-π(%Ĵ9LRySZ&QfDC f>"/0S8RUcڏwD @Z$9v إ4ံ“<95l>IFӟ"ǫV)&f>ΚSJk+yn_ (NWNi`f1!Hd=Lkg6DiUF7 }o2B&Y`"-&瓘ڻwl;uC(+`uR0ALg.k^^aMxGά"7lon:r}?$սXDRfdly 53km[Qe&%%s; D`&"jm>dSfȟeͧϨ׺94Jf_۶n\:Ãa[L>x$ 񅽽|n:ԝ9GGK aն0ԷoNASXm&1%;O$LAy<U|gct>< fY^嗾J 3)·_zj5۞ 0V eYwpLRtp/\-~nhӫ/̾k00E m=Xbf\)fEygbmzI&K; zm ;>0d|2Fޓ&>=ú<[^ItE+s'?^ws|[T+pMgbml-d^|o|ܒt\z޽{Ⱦτ3| ˂'9&by1 ! '`=a%ظt,ҢFNs?>&FY^뒇X,?fՏKҲ7߼qƥKN(T~Z=|9(/l' P$)*I(4AEyspLu]ּ.%bqi7nΧ(0cc8=ժ~zy,γ [5Kusi0 >|뭷~ڶ}6٬at38Uu兩*NUK FF?J1.y|c/|9WmwY>5 XlT.yR-]>dYUk6 GTc)%Uiŧp.s>Ÿ!0@0R03Y^O!dWiGÃM}v3Z/lp:0skήYT3z pL̼wkEk+) a|UU Sev4 7y|J,;N׭rzrԼ"*bf;҃cHFTec{w޻̃cʲ,.ʲ`b(yEyg'6W_bg?;s uQ,ݽ,F{ 5oz2/O~nd”wJ)iMŒw`v# o"ius ׯ_4PU~>EIW_Dʕ+V}vgVzـm Iay][u('h3#κ|y&ITo/eYey: 9vw.Of1e?_/|*0:w{fyaky*4zS5?7[7o8\eʃbb80@K|[zɄx׿ |L#~/۶~7ߜJQs=Xޏ/Y{pfm`823f23kx KB~"o~s\>涗7|Υ=&}ֈYDe9MB8ߍݻp-@7jkBDcrϱ0ֺVHLc1J$/C ieY0W_}ã(WСwG~vIMI;'𧺏O-?ğe9qVKiyX_ꗖܷ8?~g2,2]huԵ]6M۶}w}}[o|82gojGLHNѽ\S'7I N<c [eYtz \PQva 8̶fGCWb-qޣ?i兕 "p" @sy pzi!C8dTLNgEͻ+rG>#80#0 qq+"] L C/2,/, ̶+0Ph؎"ˡ@᪊UcKNi /#8CL\3eY6:k$HCXZVΆ0 BY6i9]:GFp@;d1.ITr68(gǼPE}?"7݀U^xX2=rJfKN"]-c JՖĘ̳"J|n޼_yEe2g3}4Mc':=<D?ꃂtz!pxrcX>#f " )|oɲMqOvlmTl1jA{ҦA,/l\te15Fp+t8񟗧/0e3ͦR}Z,G*U`:9>j7Lڮ%<ПG;OD?c(b D[.7n}t6o߾똀Rzrlcb2K`lvDTuU 2m4M~a .0 UըtT%Ghh&([V-ZtG6#mI$ޱ@vTlzVձ0.PQ]5PH]76`IuVSޯ|7gSSN~srbE!~9Nk~o)"/{z`RU@ZPt6Xwl481z]UZj͹Z)2jY6VKw?sMӬV/]}rqV,K6t:þ%E S0t@WM08WI庚 ȉ\o7zVyajz0l' :V:212)Kiw: 1ĸ@0 nݺuG^r~ ;oիWGޕ+W޹qr:4MTnPbE LXbߧ| Y兵mwس!* o-wDhԗ=ZU1I{if>d%GWb#ʁ*w٩κUՂWPһ_DB؝;Ɖ)m7f(lڇy7}5N`J [qBapVƲM,˗^><) ".rUg"KHRJ; }1˦zfya h'61!G;59 y~rþ~Nc?ϲl$)1]GG[9tXE;Krob70;l;vY3{{~8bZ Q1wvG^$I$ə(1sSw1&ՔH"8=%3$¦:fcOFd!DN,@{:~~*Uݞ7 id1scġ BQߏ}]N9:`W}ww߯px!d~ګj:ۚ:ͮ0=%uS"CȅPˇ0 'z>y𡯪0VU㈤<-?-εү?; |q~ڵ_ۿۿ{^jy4VEQdYgl[U Y9βO__.h-t;_V)ţ53kl6cM8n_Z/}LRz, XJQ;'=QO xhZyӐeQMD·h2X$Ɲc?_~Z+|耙wMd/_?|gW/‹۷u]FJόm[UUiwgko}3+٤^V퍛7o<=f?W6e9&3KQD"iqP3|Q8vah9dL9s#"63Y"?Ej;G_~ /ϯ^|g]<!+_~]ׇ݋1-cf\1뺾}M</J9bu+/bu0!c䔀DNyX{<,&>~tʟ:wb/`!jP wS&ˀ |˰zZ.1r\.qem֫zڶ}"?_sUG)]15u\.?Z.KPM=q?,VFДstbrR'gmmN.ϽO}_ <7+po(S v\L&bqXU|6[m[]\R)%!{fn;5<ϧiN/Ms*cr"T3R#P5߬EleBUTͲofլHۣu~?>ϿOWnmUlrRV 5mjۈQgaAC繈[(ʲرU-y (x?+K۫ OsUU>WUWC?DJ&awٹu22 B3- @Q-hM1Gp(XW)h=p gBfCC+jyQN&}4?¤:+W+O߻ܱ nmm-ˮb1%ry&^-Iթ\ŭ[Cc=k ⸏)gNs4̇e{cuw=U}qǎ$pIHexC#a$f bx?%C@ü h`$386}9wٷa.WUWe.~gUo/2˲ZkLBeYVB`QB(B !A  EVXRB*uRŸJiP* `=܅* ŨBH)93LYfF#3imhbȵQF2)!eYwT{?fVZy^ ;p%JmJ)cZmbp\ <$uIA꤄?v;TK ]+ڦ7T9RRXD)dBIϣ Pˢ1bm98MjۖawMZQpaFHyNJS =M3O,$R֚SYum'RREQhcR%uA+줔Yf}&1}J9o vE[MAl:/ urŸB N:.}Ddy!гfbbŬw1F@As3q9罏1B:w]}! p)NP=MRQO`/N&bf3}eYh! |1HL$APr1H{Dn]63Z;?_1BxA5;QR@4b,2kh/etenxCC^b D#N扌sC- ;HuXNNS=m niN DUEMc$ cohK*ˈĄ!$4x爈B &e%@vc;C/s=Egm$3{ڶ۾}pduuR>:@9iAjQ8 (G 8!.6Z@R[[Dl)dd4aqmv~CĮ* :bm40Rضv{sgt~ 7:)H𑃞DØ *Fb}~ {`K-.󒙜M9Rd٤,u@;8 3{g{1B}Qr"ĝ;t=P:5\uR1:!R0i#6XE]x< ۨt ѝ[Rb/e2CR*Q;D1 0sR1@o{Zho$(9d&uƝLF(꤄?|t:ʉ(24xX2f7AN)o]쥂g>^iJq6 #N떤JL$0Fnc"+Nqߡ:-^t 1DuR>:4 H1D ,ӼTZ.u}5'8Rw.>~L,|ȑ8ˣq *oNS+<!щh{t"@jBv.ZB @eL&`k=Nל֑eɕ*2:uݤkjZ=B#b!2@Y;pBdpJYVLvxf8~%Ie|1JpW31QecqޑAb#[ۏnÛp?3H)$qrƊBTXU F#(%Ku}O1DB{ Z{7JN(K63J-w#1$EuLQ  XM*]ltzN>l(H!Fd"n|TDlQLKHP{)# %bZ!#)3-ʳ';V(ʡ}on2NʳUq' i̺.j=_sBfF3px P* @DԱAJ΁"% RD Hk wMeEKml8ܺ5m5:a`Z ry}߫@d ,dCۦ84D .kp/:ɫF{imOYಐh/t63ܼUuewy6@DHLL8ݙy6]5s#LTJܼ= ,RUV"|h\>r# o&z:PLf %'&=(Ijs۞\F0ٯn ɤ4`dՔw( $#h|1wcf A dq:DxVژ<3.k]oBN}Ԁ ZT1' znmR=~0T/D, }LIYz +ݼd|ljB x@2ZP! GwN;EQdyKvY:m>ŧ_/ݧ UMf, Ц.AVh۞dX/5F Rvoq݄FT/e\sdLpgO_Ͽث^IDATi"2y\d{< 2 y!xh<\%օVZckmܮ(T2K-pw:`vWl3bv`w`J0̧͈ݸ7CG! Qhm]HQJBιgyٳ 3677!PK%4y2CD)eY6M1Ʈ׷6/B^f*XAr2,m.W..pd7K`*#o*Ue)X%\ۂރČ^$>5:DxJ<3!x"JF}'4->0 1%\*b"b)T$R?"J,\3{s>8(j(Q(BhH,2efR0tn_Rd'Gݯ J.v'Gvˊ *Sd,!͞dBDιb"2B40NB FqhOޘ*Vjkk 1*>BHcV VeID12TP׃wN`eb0n'/U'594wάa !]Fm1D)EX2R \rT)W__=Dxʒhk+)=,;)RtR֚)+R=(aKż<w;yx|R_rn-wV{2A c&BTN 5ATp1y)6C: q?} z,yY.PGB)|t}'M*b`0~{ک~So= =>, wu *aZ)"q:Vwhw9y|R_#M`rHpS5tgOc/? yש/_n&MQSQҖO|=~~< nRTqQI./44ꟜHĮA#=2~`=jpn8_8N&x4׮5M@oM۶u6yt/|emm- D8ї孭dmy~,X{`|b_B1+n`8I~@7?^?0ٟ]z1RZ8y1I9!ݠ(<S0{}0bu}џ~}ec}p{/=}Im;SXs a"?)/۹#A38n쁓EٹjDֹ QupPx( > 7~w~[[ׯ^?)/"\zb.LTb6lQ:(?),;= JZmL'н2b}ng̬LFDV㚦e6 RB/ vu J i0td?cMb L^#_R.c3Å,  erG#徛ֽ6MxHuBEQOWo_yʭ[wNmc{NZ{d7! :?JX;M/ͮ|{dbtVV¹ܰ6H](F"͢ǣ LKi C% hm&}g)Lc*)b0W1vtK\̥_{}2_oV= nʈ]f] <:\oRf Q$bf)δzs!7ooJOd|g!RcZ|ⓟgH2^C7E; }ā)`o_sQ3EAp_L[}fF[#TïeYi{z='&dT6 ЙAw}h|Y)1 "ʙḁ2-C9&>$fӾ^ןi3b w]Xl ϬkiCD|!˜Xb ⭭ c2#ʪJ:޷m;.~G`aMm1̀U]5,/ ò@fe zYd` &-f,+}ޒ(TB JsD$ֹt!R @Bc%>@'ъ]4B:Acf%5dFhLE]11!Dl#EDl/D `}xmvu5dIy)˲ k]^bpJ)7n6:/|._B@ᓟY]gJ'+`@cLADcU8)& 97u{B:g΢GD<7kE<3++ob nx0>?Ȳ,<7gb$Άh  H1Fʪg -3&(Ȋ"BZTXJTϝ>sgSD"*mߛM߭UCkFyQɍ)[ ):kJ졇h̀g Kޖ߼2+{~2:kj37k7_Y)<sqXa9,@]{0>6XDT )<cׯ0T[/^>ٹay;^x=q/M+WdY6 \v,Qk\,~qTEn<@RK`0c^1ǣqy^=R^~0߹:K_nݴho޼)ܼz x!]q ;1]~0>f;Jꤖ~Q,[s*[o+SO=eL?NYK}y晕7oDȏ>z8,'&Їj7]F lmm}{{~?9?vq(V_gou]u×W_1;w͛ L&.I3z.q&ZiCjo`Gc~[lm;o@۶ =[]UcloBumW֭1xN'ι7H̭7hexry'N9>$΃ ![Ο?wwTr.X\8\~Od)8ۯ.~|WVV~2`P9綶+|ǩ*3_|j9&9wڵk׮S 333I3glm4tSlݽGY{ $ܢ(S%p`lj`ZI z/E-fG/ln93/*ɔ %㜙YXqq>\iie`M2"+Wc/?UUљ!|᩟RbjPZDN8m{=qa)g+V<{F/.#d[B)5TUe֚vw9/}K/RӪͭsgם67V>u[)SՃ}e] fpvf(666-.g;fvvyO\Jq~8b8\Ҿ(ze2x7.iXD.>?IxPt777_וj~~1˴snGu˗/?/"]}j2vƘ3DOVh.vS[?b$/T/_}G~(jmc? ;.\PEQ Ku=H_DC+jv uWZ "˥sj= xT-nlXc̀LwROZm:0cdveI!w0\!&K&3KlBpipյpavTJ3ַ̅y`ҿW߼ۿ߀p.7uk9aA׿ a&;6ڨ;w밴}@LUIENDB`tiled-1.0.3/examples/sewers.tmx000066400000000000000000000020631315121121300164630ustar00rootroot00000000000000 eJzt19kKwjAQBdDim0sFqwguL3Vf/sP//ySnkIFhSGrSdEnxPhyQxqJ32kySPMuyJTkZC5KLa2dyNEo1Lsds3wkl/4f+7V/0/f+Y40Je5GpUn2+J5NiQCdmO/HlMyYzMI3JwLUJx7drIsSIFWUfk4FrY3GvGuHb8vr4jcmhNcnAtpIflmmar3VA5nqaWMUKeQ1d9dyht59iRPTmMPEdpua8Put/Frh88P5q84zFkv/NZP2TOlOaH7Hc+64fMmdL8cPVbV9+tcn5MzpTmR0gv12uDbQ4MNT8AIA73Uq3v3hqLe2ldTx4D21k1tf2ubw59Vk1tX+KbQ59VXfuSlMn9SJHV70tS5jqrYu8BAAAAAAAAAABd+wIHfQq1 eJzt1jsKgDAQQEELtVKvYuGvEDvvfya3MBeQQAzMwCPdsum2af5lL71AJv7xL7X+Y46WtzXayq7z2RGd0f2+V6a5bdRFfaZ5pQzRGE2lFwEAoArpDk7Veg+nOzjlHgYAAAAAIIcHvboDlQ== tiled-1.0.3/examples/sticker-knight/000077500000000000000000000000001315121121300173465ustar00rootroot00000000000000tiled-1.0.3/examples/sticker-knight/README.md000066400000000000000000000005221315121121300206240ustar00rootroot00000000000000Sticker Knight platformer example --------------------------------- This example is by @ponywolf and released to the public domain. You can find it at http://opengameart.org/content/sticker-knight-platformer. It's a great example of using the flexible image collection tilesets with tiles on object layers, for both the map and the UI. tiled-1.0.3/examples/sticker-knight/map/000077500000000000000000000000001315121121300201235ustar00rootroot00000000000000tiled-1.0.3/examples/sticker-knight/map/alter.png000066400000000000000000000130531315121121300217420ustar00rootroot00000000000000PNG  IHDR;hw pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F VIDATx]l[9NEnz'M7ibHMB+P5 @I0mw mHh*"]LB DK31 8N)9n&sbR%ǧ9>wsDk B) P@B( P@B B $ H$ H( !P@B( P@B B $ H$:lc6666XU4 {кoffwrr򲟿Wu"ų_@ӶvUKRe7Doh6 H׍mۻVXiYHS.ǎ8>=c已IFGǢ(ORdžQZ-"M?ZsF ZxguZlr_tRO.6U Y)OԺg4736`!ڀOCh ?'d&#lRun12%ofH:T@; ڶY5bώdl;I·&`fzc'LXZ[#Βm窀[A>vB$ H$ H( !P@B( P@B B $ H$ H( !P@B(  H$@+jÈ[m/=jNMO[-U__=XSӲeYB䐇#gll_>0c/U:s32KKy̕Z'o , )DqgGt;xÂ<H$?}NH)~aè$p76rm!xCS?~y)ʮظ0/.Sn .\Zma8GK8.<"bH q*ȡ>޳^z|ē?Ǟ=K=nyHk:)"c{07*P(dervv6nۻw/i_ett ! H( P@B B $ H$ H( !P@B( P@B |W#).ёOjxV#TE,c-xWB7G,OjN!P@B( P@B B $-#<􎅧 XTk^" U+U`)$?V.x0n4CUqS`f.!qZX,0N S)՘94mASp"m^! pR0\}/՞`>ʦ)0S,{Ry6ɏ4EHOdF .$W{_+L19b⽯799y)w,+jXS4@oaZ>?oFz/t܍SӠM2g|X ( C3d2_h_؉Ϙ7A)t2^?|&_u- ͬK#IbFh$z?|.'`ڶݎe5bLӬȟE6P@ekZg˵X4{\SkIhYV2;4lثGHl/3MFDC UqvѸEMU.H*w,}-P<`0ؤ]x8&"`TPBuGᒗm>1D N*١fWzN&{6\e5QhE 41-1Okݷޡ 1p8 +4(j-jW@dj.#)ZAh=Dff6:AP(dyL @w8o=t` rz 6:z`s#lT˔y ovVWKxp>ă(Yl3<) H,`Yh k>I$79 W@ڲ<)q@zJD*8I{6Ċ4Ӳ~WF@ 7>Xi978 CnZ׎I΀6_΁Φ+N;GZX hnm}\Wρ[" 3x tk)0_9_5VWokJ [c@ih] 920}ty͜^2-G FÏk c'z(`p')$/nC XUA|7!8=٨ԊnRkPolK{RR FQElQRFݝٙ7KLC2;G}ƋݱRa!e#|߰}{J`w3EV?}m@qRi X|^'  X4ؔ2 L d L/ix'2 S@ dO\z@I L^"b^IENDB`tiled-1.0.3/examples/sticker-knight/map/backgroundArch.png000066400000000000000000000014351315121121300235510ustar00rootroot00000000000000PNG  IHDRsIDATxmA8ARܐ\8xR%PBJ\%طH!`DZFo>XO3oǫ7M[\,o;Ow>n+w՗RarP11yIە$>ЮքrkWec $ʉQ bTx=ƪ!QjUaRa#PLn]O!;8RC8C8C0!!p!p!!p!p!p!pٕ͓3ެѕŲzt+=-RtxZ8Nj'5?|yu9# +ı#֮.dw:oEx58b۳F c 0=z$s8  qLFv iqdHJQ|l@V5>~쪩It`$K*qT0l/p]˭a!ydyxfȺm}~7,4Pzfjm[_ﶯ⃮fpvWx4ɭv[ó^:k`lrz@ .a}L[ o}Xz>uk5a)z>N^ %Yz>TN^ ^[mf@^[֏7^ τq[ `k} &m}{Oyc^[m}f^[kf085O8z>Ȕ?%'m=5@hʟ0K>}S} ^[O>m=5@[} >zj} 4zj {} 6zj zm=5@lnzjhRL8zjhd kSF[N+rH[O>aV[\ʯnzjhU_ޮB'5ȰkI>b'5H@s&RzR[7ᐚ}DF[Oj`Y֏#0zR δ#5#í^[OjaV[Ojm=Gf &m=Gpf*m=GlfnzRzRhI7;ap$5zI'֓C[O2ģ֓C[O2k֓C[ORm f_[OgO} Ij$o/I;$5s_*}m=Ij$֓f_[O}m=Ij$֓df_[OR֓df_[O}m=I&h$v?oAW[O}m=In74kI2x'*ݨ}m=I&h$gX֓df_[O }m=IoW$C7zLkI2x'd_pH2p'Ä';$77r$cm9M-tEXtSoftwareby.blooddy.crypto.image.PNG24EncoderIENDB`tiled-1.0.3/examples/sticker-knight/map/backgroundTower.png000066400000000000000000000027371315121121300240020ustar00rootroot00000000000000PNG  IHDRLߎmIDATxM0۠#T;UOtF`F`*T Nb'_T50X̴ΊYm.*Zo:@@@@MQ=Ͷ2BSEpbA@@@@@@@$ t`Ry@@ 8iGcy @A P( @A P( @A P( @A PiY8&m_z4 *}/o8VbWk<o!uoޢ @vOWDPsC_?>+DSs#.UM|i:OmEڝTc!1%7mGRAPO+c2#Ƚ@m=@Y-"sO$!,X R]pZAz.KDhXb %tl(S:x!屄5ѾY#@@ @ @ 4` 9 = 9(7Mt7[!Qqs/sy\<Һ /NIy{$8תJ'AƲ>.x:@@@@@@@@@@@@@rgGʉ ^js T^H]̙~xpAOE s Ο wy :SCc?.?Q&>2@@@@@@@8G;%Ake6 ! yָL1@Ɏ[֛\D9 A!p.frA4M« HAst-?=pp~}4 ]a@ǩRf G #HJ           ٔ7}'Ɏ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @  B`!0@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@AZnնs۵w-tEXtSoftwareby.blooddy.crypto.image.PNG24EncoderIENDB`tiled-1.0.3/examples/sticker-knight/map/backgroundTree.png000066400000000000000000000021611315121121300235700ustar00rootroot00000000000000PNG  IHDRm3IDATxq@tgeJ@ @ )%P%JH )X &ؒn{kޱ'_]Oaqerf6vv{k7Aփ  hnͮ+;z i=^__; f ݶCm{^]jL_0۩$q}/vA аğ|Lnwvm]qw 0a?\xwK.9: аğZ\WvK{D2XF%c0;<勏3@;&4*Ys{:i/ sCcڕrɅ$XF%bΓ5\r|($U.m//ݴɾhX&.7L;y"@Lk'8'Y_./&T,cq \fT e+Ynr9Z,rl (Jj?4VmvR-aﳚ/ݶ.X%,$Ydd8+^tw~]X2RYCj-@=HP?ZꇟA;9Ӄ(*^3T9AAV[>$$ Z AwՄ?$$kXO$&_i4_̵+U$~X5AhHvrg| P%\>$,@jBcsI?.SMP!l''QٸVQvIZvI+ ҒOҒOҒO|YXQZfHOXaG.-vɅ",|1 .\^",|1fTrI. $~'\҅0 @V*a@ RǷI@ _ k'@VM/UH@ Bdh4hf@ 4 h̀h@ 4hf@ 4 h4@̀h@ 4hf@3h4@mT7-tEXtSoftwareby.blooddy.crypto.image.PNG24EncoderIENDB`tiled-1.0.3/examples/sticker-knight/map/blobBlue.png000066400000000000000000000570171315121121300223710ustar00rootroot00000000000000PNG  IHDR`@4r pHYs.#.#x?v OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-@eiTXtXML:com.adobe.xmp Adobe Photoshop CC 2015.5 (Macintosh) 2016-11-10T07:51:11-07:00 2016-11-10T07:51:38-07:00 2016-11-10T07:51:38-07:00 image/png xmp.iid:c9faa26e-3cd2-4101-8aad-f60de76799ba adobe:docid:photoshop:9476d200-e7e3-1179-95fc-c4d575c47509 xmp.did:eac43e72-3193-4e76-a9b4-4b16d44d044d created xmp.iid:eac43e72-3193-4e76-a9b4-4b16d44d044d 2016-11-10T07:51:11-07:00 Adobe Photoshop CC 2015.5 (Macintosh) saved xmp.iid:ca125513-cf1d-4845-b29d-a85c8c135700 2016-11-10T07:51:38-07:00 Adobe Photoshop CC 2015.5 (Macintosh) / converted from application/vnd.adobe.photoshop to image/png derived converted from application/vnd.adobe.photoshop to image/png saved xmp.iid:c9faa26e-3cd2-4101-8aad-f60de76799ba 2016-11-10T07:51:38-07:00 Adobe Photoshop CC 2015.5 (Macintosh) / xmp.iid:ca125513-cf1d-4845-b29d-a85c8c135700 xmp.did:eac43e72-3193-4e76-a9b4-4b16d44d044d xmp.did:eac43e72-3193-4e76-a9b4-4b16d44d044d uuid:E0EF0446F9A5E611ADBF8EE6BAAF5053 3 sRGB IEC61966-2.1 1 3000000/10000 3000000/10000 2 1 96 64 a cHRMz%u0`:o_FIDATxypS?Ŗw,16[@ ey)YJ fL$<M(H:nBSK &ifլ" lKKҵdKWόޟ~:9{BfL G3o& d`!^vCz해y^HoJ}0ې.m uG> 47b&TN8~dR10][zc"~k֬z'> &3gb2MAp'iyD>$ w]F=m|P B$,T>x& TV h~ | -z’F߁ Ƹw @zoF AmmӦt^^wa%g?DXW?C5L%pTW&|<;pY'FR(/nkgh$2{V-CO{i1c)+el$v/CK'pTQ}N|ȓFH"uʱ(EGϣ|7~/ZBl8fہ\ KqTk~ KǻNADb N k8װxWZ57~$ܥDWpYi7z|>_: MvyK*--~1bYREClƸ.c;-f '1\(,uXʊ.p758 :Q걹.h$B/ZkB[BHru)2m.VP^] hΕ-K{rͣnL$u_m qY{= /k ++*-DQruUPDìu;wG2id-%wk$<,0ovv <Ix4ב7*#z_L]Ubaw +6߲#b/VH״ H۬xCR,Sywk=[qYhȱN~V\VdHR$~|lKp-G(_|FWZęqZlh/6HΪJT,␙mqA>F=;2돌zn3 M\)~=!^1n p[J 8˺t{oml0\(rGVB"MZ@tt4rW߈ѬfRD@96\ٻ3 H[BZqXzJcB+n5)+6i/*<JuaN! 7>^Ut< *49hs-|/W]űg#~8ͯRY\E|2#WG>dズT9GeE9\b& g`o!SF O SF`kʥ{[U$*59KDvu|3h eCCZI+2iZf!f.fp` 6+a#f36S3_G&&^;\5c +7廿ZÅ곂I+֒KI[¬u;R1x!t>AGX0'RE86s3VS|b@p[- ן\߳F&asqkB͚+/|C[N,IQjRHQjTV+- ʓFpmiJ 6i  mKorx 3`%Uި.A?8ynkAUAJX<DfB5* G*&]3dLdsP[8T0rj"F xlib@ Q$Pͽ#v  qT%1}e cpY`,K`Y_!2\nlO 1ef4/m'f;fb,u[\@@93fDd+[ٽA{.!7xkF0 &b/6TVdx9z"ؤ d3.;,=|}wvaHNs'ubR#)Ռ6`QNj?S=V@d')"1Y3zSf&g.KwZ,z{Y_?s7T Ԥ9Zsy pY("F%R4sDb_w0H ۂJx'vl\V3Vֺ\ZNO*J`7EhsZɭ)dH:n{{?n;aZ^`OY"c_ق÷q;;;q-Tkiҁ=ǀc,wnlÓ0w\]X@[𩁋˕ŎL? {t.'z|43|>yaYL\h f9s@f!oc88+h׍˳4@_PNGޛL;omMBIZ2 TS Bv < E}@6V)cC"L3$op-$?3dSPO+,O)܍Zd T2%nMKJ- ;'׋EMBcvw(⒄Bޮ,psi ]KY32߻5~ ͧ5ylQc;SNn>|Iw*ǐ<`8рhrZJNl WEj򨥯ď^ϱ`Z|ERHk幮>?.81} R1ouTV~"iwCшVT| H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-94iTXtXML:com.adobe.xmp Adobe Photoshop CC 2015.5 (Macintosh) 2016-11-08T15:10:40-07:00 2016-11-10T07:52:24-07:00 2016-11-10T07:52:24-07:00 uuid:E0EF0446F9A5E611ADBF8EE6BAAF5053 3 sRGB IEC61966-2.1 image/png xmp.iid:316eba18-d41a-4c70-9aed-11ec47d6b68b xmp.did:316eba18-d41a-4c70-9aed-11ec47d6b68b xmp.did:316eba18-d41a-4c70-9aed-11ec47d6b68b created xmp.iid:316eba18-d41a-4c70-9aed-11ec47d6b68b 2016-11-08T15:10:40-07:00 Adobe Photoshop CC 2015.5 (Macintosh) 1 3000000/10000 3000000/10000 2 1 96 64 4 cHRMz%u0`:o_F4IDATx{pTu?ߏӝ4`hA0AD;" j-djZŚuwǚ]*awpG]"dqAdm${}NCrR}9O$@Aod(~\Ʉ$b [ (V[+Ǣצv~ kG@pzؗ;{a /%PJ{s>ٷoGa%X,To& Ize;wnl}{*VQ8_;wAh!5/:Ȳ".|)+qЌjah0}4oߞ );;Bf)/q00n/kQ Ξ9, >GJK`wLϾ-@rؓ:_UrIt!#9ZΝ;Ǵiu>MS?HbukAŨ>_zk B/_vC٧S 44#v!4g cb:4npuA9 8LEr}+?&x:AO س9DpQvztsˎrF[ŲGzk B= v4sGڈ6v(wq7!Py1h=| ɳ+Dci \]Ԅ^P,?fY;k|0ޅyDYԩ-ˌ:ˌnDh+_zUWo .|K,SMfw9':Wh=|*6TV ~SGk6en d}Cvžè7H!@+= k xQ` l,V"Džpzzq=V@T/p~._?\eƺfrtkH`)"R@;{ڝ?f"=XGLOYEH"Bt]YP.бr:I7`0|N^ ޞʨ'i->;ǵ?f"pO!d,#z*9D^ r`4 MrB úKᯚ^9aúfMG(Î8g@eԓf9 [?$!7yqs.U;ypMkw BHϏadҟZ><|VRAkIEFJ^I_v?-O*9!9?۟۟a[|+(?*QPh{-Aۼ߾H>,)ۛ4ޕ2lų3"WF紃/W.vʽd6/7E f f7?{)UѓX֮ tR0^Hy]n hVrf9̌v 4/)#ݷ(i磛0M :2۳ JMZS_` H}CNr֯lׇkBRTx@/2k AN/P(cuFM4?aVRi"|kj8 X3'5Muf[v!yej@AE0 _NkvP&?_a,Wm[?Z4Q.MZyw@3nR]#.'BtfHQeVVK-Zɵ#4w 5 S4ntc튳%_Ϧhyۺ(+7PϘ![ #R fxiss 3`2Nв$M]nX9k@PmhM BK(4QR+ȶ?)ZkPϘ4}SD9ԉ':$ υ+ͨ23K0I/zì)ufy_\6OnJ*RvhxioB&tITI_&19I zÃʈ4MŲxy஥H$`^$B'ȼh6sh-KH_c{n5BE83FÖ2aCϐuJʫ$EKD>FسI; Ր|>gPefвe~S 7x]Kz~xYfe$K\.VReydLIC<)$8F;CMN VC6(N!\]ښN  :.|i}GL0K;]A˖d6BeԦ^wSBCyDc|[H~yq#TU̞ T@+[PIf-E C IdP%]vtt#8ˏmߠD@<źit.M>DHU ލ0/>6ՙ\+h}==+U* T$jiI)Et^ X&YMͲAn**+6aG\[]5xZJ7`øz? 3'#x7 R]+ׅN4Uu}E܍aKP3ئBg$v!n܉tj H!m7hx2cHSNxmuu/LnւF$| C@]G7ݷo!}\*e睨NCrCd15pý_'IכTҖG?ulԀX%»A7֮HXt븮+>SѶDC7.9hs3ko~=  BV4‡r( ؞[adY)ދQH#٭#>!RCo{wݼCqn\> P4 l?l4!m+J;,bRߟZc , j[~B )W:+2Om ϫ xˁJ+c? 2C/\KԀ\p/@SaYT.'мk?/"L\?Co v+4{ >"òz)sh}dVm$c@CDhYw p[pj0ɉS_/ WM~"|wีad6<#EOqBOUW*vFk)!> 3'+.|&hiFpID'p Hݷ"l!}G SnQgOsjGjiY?~|?Zw>9C. yH씢tN\U=$ydG.YŽ;C#`k:xZP;v5r*ykGEErA 1ɴ o{d=0^l8l=2O,?y l8X< ~]?: _IENDB`tiled-1.0.3/examples/sticker-knight/map/blue.png000066400000000000000000000434641315121121300215730ustar00rootroot00000000000000PNG  IHDR@@% pHYs.#.#x?v OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-;iTXtXML:com.adobe.xmp Adobe Photoshop CC 2015.5 (Macintosh) 2016-11-08T09:51:04-07:00 2016-11-10T07:57:29-07:00 2016-11-10T07:57:29-07:00 image/png 3 sRGB IEC61966-2.1 xmp.iid:9baa11cd-2148-44bb-8683-bd8f6d263266 adobe:docid:photoshop:691876dd-e7e4-1179-95fc-c4d575c47509 xmp.did:edadc86d-a4ce-4c33-95d9-ddb3625585ac created xmp.iid:edadc86d-a4ce-4c33-95d9-ddb3625585ac 2016-11-08T09:51:04-07:00 Adobe Photoshop CC 2015.5 (Macintosh) saved xmp.iid:f9f10874-a23e-4b6a-a58c-1f0164d87eab 2016-11-10T07:55:17-07:00 Adobe Photoshop CC 2015.5 (Macintosh) / saved xmp.iid:9baa11cd-2148-44bb-8683-bd8f6d263266 2016-11-10T07:57:29-07:00 Adobe Photoshop CC 2015.5 (Macintosh) / 1 3000000/10000 3000000/10000 2 1 64 64  cHRMz%u0`:o_FWIDATx1 00\SA:hVO\8}xtcIENDB`tiled-1.0.3/examples/sticker-knight/map/bombStroked.png000066400000000000000000000124471315121121300231140ustar00rootroot00000000000000PNG  IHDR`l pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F RIDATxkZ "nbbc:7c!@zrΡ`С=CX{ŠoބYfW;3v֞m,5_7D*AH @"HR$ @ H wypL<1MBjۏL<\ !v T>B K4 {}|lۏF| cuVeYw(n;p- q,0ъ%3tᣬ^چ%x0˲L܋BH! 2KA]ku:)`\eu:)w} g9T'X$NGT% 6%8bںz.7~J`sZ yH+#VH+ ?aOBkzW~ZCiEhZig!+CmG] O,I`z7)u? NvDl\?uaC7g, oR`||0 6i;pY0*+S!Ƕ݂r<@ш2;I4vP p8ڴl޾IB1|0L-;e0R·Zm i1|z>/ գ#2!a(Bhzz;' 21`yL( ~w`L(tBN35  a/cx&/ (P`@ Q5 E&muOR}BAԂޥfm}} nV  Kמ9CZQ'^u]wiGٵ-d5)iǻ!iQ a/heN$[`0[2nQO/p׈8sjB" ?Lg d*tE"XOFE,pgV8_ۍE\BVkBg@Ҋ'Sp:`9Vgfw7[8u+9"h 3O7lWpw.ag(?_A\VC̕æOn!K ͒P~ZQ&"hёhL |maf@n3}2/0%NpX $b.B[LGFVtf t8]*: <9OXΗlX|h7i 2+n%.aCPgspT[.Wae: ;?S̊1;,ՙҔ8w%ՆRU%4 avx8LJl捥|W$jdg2+?_</>:oI׈X< ?5<$/y2E-V4O'vcQ {5K@ϛ }A'~5ާ 6bw^y;" m` nY΀0`*dQlh99j0BVRjFe Ӭaq ;3/haruΐYrXa&8 2C=.,W؈D3a? G 8:NXwȥfIK{J=qim^bfdh}Bd#1k`XߚRq,7nɈrC~"@ 2oC582GmIR[9簘[,K~գ/l uOg.KG|maq=u mp xfLwq5r@ b`c7 ^בx^憼Rx!kbt98Vgc He/: zI)<z^PxGj5GFv*Y0,0hiU.B*aRM@u} B+Dǘþ`Dfqb&DGD q}G58 Kڦi~}77MsoTͿiYui#nk "{qzW}sU8~2J$) EH @"HR$! tݞСIENDB`tiled-1.0.3/examples/sticker-knight/map/castleWall.png000066400000000000000000000054541315121121300227340ustar00rootroot00000000000000PNG  IHDR@@% pHYs.#.#x?v OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FWIDATx1 00M|SA:hvM\8}ǭ_CIENDB`tiled-1.0.3/examples/sticker-knight/map/cloud.png000066400000000000000000000105261315121121300217430ustar00rootroot00000000000000PNG  IHDR pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxQJ`e!8@C B \EIfx}-R]H3Vx>Tڥ4os]t,Ct,\u uڦ4rY}Ywp??˺eMi&8RRop@(+a [;}Yݬp>/sl u_7nLzm_7 >\χWz#ԗCWxK:4~J>:Cw1B@m }6CAC@(? i0a>r@Qrrte1}Ǿ?L<@~ 1nUArou e3 A!@_{,@Dn,ڍBKaVmJ37 ">t].K $";? ÝV.|u;/6E B@)o+ @@@0ti!+=pKi.8hb .|4Ј}ݸ/k P FA @z r@) hmS kB@H9_ tp熀x/ W@mJP&_wrC10\w e+mL.v)ͻ\޴}tp ȇDt,۾nڡxߥ4o ]R}8x{siQ.ഋ~7t g ~;^h๕/>er=s4mT4ae SW`ζ6Ź)|kD =m_֧إ4|sjG쇺:SE>!7O$ |1o [?~8C+إ4woix d!M}vd׍{$8H`(h4\9Y/<\.V9@\N]\pp 8dps/r8v h\N  @^, Y@Y/<| 84{K@$pI@)ז=ئ4sӯz1rYpSئ4|(t`o+8 < i1 KijvQ@4~+69_Y'^ ۔fx"t Ch ,i!+C_!l38efP/ye>E4s߯_!{0٧~[B.i`Om_&z ar+C0Q8[t\}nakrY_^m6s7 pzuaL/{IENDB`tiled-1.0.3/examples/sticker-knight/map/column1.png000066400000000000000000000147551315121121300222230ustar00rootroot00000000000000PNG  IHDRfk pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxOLwǿvHX1"C*>deԖ [X%U{ .UmfOlR)jUhaEn^mIGtPăc=xf21g<+!>{84J?X%$;9Uİpkr) pr<\- _S\=n>6(2~[{amZ; >M%YN@8Z/ 4l71,vH+2YN8L<#?C5(VJJan{vroK#$̫_)s, -;đGl|>woIr@q@o6.s[y*2yw;R/2{Q視 %v L$, JeOs'`S"Lln-=2x+Yyk2m.v!*stMja*z9G3#.v!*Tq>rn}P`SV;Y"?Gy ],ϳ+S;c:u`Yk ?V S5dP &OM Nߤ]FtF!׶@u:aa 6K]~gWЉՈƵ57яh/p|ZRxּ-(J\4ݺX_#)90$ CؑHoV@ G<?6?MV}4er^;SQ iSMQ[$?aHAzêW"x KJRk3&[1b'N9 ,bKs &޺O1z$~3G`}F}2%GN.k<0y[si1m:Ǐ4ݽ$_g(EecEߨpJ•uؽUP"Ko뭟+^~,w1}]%VAz9ۍ%a:@ $D@"H $D@"HBUn|1Ƶc$%q1P CP `ya 5\ga.Cx낾,< ;iD8.˿?{[ g{1=G[A[4 1tߡ$ËGDs#IL4^9@"H $D@"H $D@"H $DV3H+2Y9ro`R C,'p1nty%yL{2X|x96˨#Ԭfn7c`iGk2SHJPMԒ1Vd{x{XQ1NhRq$ J%ɏ--wO/=@pA/R 2G!ps3P >58ԖgTקkk_^X]b[Ë,tW}pkbX!4y=M G ~oxɟߡ~^ 0|_@lNO'n艜k CԌCh|{V;kX0}#"_}=8?_FB\Eק{IBVIBV*eug]}|Uk8t>A#Kż; @g/"*1(jjjbX2N#\;}  D@"H GgӝdCѺx6OyɤC: eMR @]@̻2sVb-aWAHz2{Ѽ8ZْWK;B 4 {c7gMӈ-սY?} 4k}ݥ ݜ|gZ=úT-vs.s3@1zgCg뾏hZ~Ҋ˦i 3,`WMm=JuӊZmpr^Qt+0_/`o2@fɮ"0kj No˦ڬ"x hzx;Ysk'4 ` 1OSآ_~}@c?l.@5V ! ;X0;lP `Oz;Le㦑p0( mT/`(NH J#H<]M1@OE7[jܴ.Nœet[̲*$$)IENDB`tiled-1.0.3/examples/sticker-knight/map/column2.png000066400000000000000000000146441315121121300222210ustar00rootroot00000000000000PNG  IHDRfk pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx]hWxRLw-q=8ȴqbӔ.풰ИĐ@]&laRn&-q ʛ )IAq1B ی74kgx43ќ?h,sϹ{677Q=&U t>2sC` .k0ev2(A=8)JܳRA<dDKJyq%# Pr,Ia5/=5 J6Sc_Ki]%FyΗ*uD[KjW MU'V*2[Б._hҫ|hGfbD&ӵU" xUW22ްؼ>՞f|@Љ<@sK| nN &Pl^ox =s&أ\7 rycz(c ؐlgUxG,]Lgh2#wR +LCy 躭7TΟ;zpȡBZ4g0oHKˌ4SgYC#o<PxQgtq#`J˨T<8:qHV @=,quL&I?7ԡP𴴞@m:?p p7M<׎aḩiIrć[.řk-k܎qcJfށ I$iU$^ ƍeo?Xyش\ 8}\G6r2O^ .cc{mR#hqy5"BXْQ?֌ϏN`;}憴\j.FaCZow-=Wtbu] x)'qk[IQY~guD3Qd0-t)?\1.rm~{Sٵ Zǿ7z^P{1w n4b}W(tj(D?Ҫ `Uߐrj|z];}D<Ghwp <,e4`b D@"H $D@"H $zؔ!H]?&_IlH"]?U Jޱt?]?_M%O #v<ւ^*jsG'㥜乌ĭ:@$2t WS< y/Xy:Ưux RNy +u^u6b`HыǯqȏN>`m8D@"H $D@"H $D@"HlL $x19w hT6լIr6~i#Q|mz̬Q1-rG'z>+ܻ~yrSїdzM=hZNêvҾO>C^ZV?K8Pu/ llhΘ ,gk90;ΌǼ8y﵂[^ՠ*xFH%p(Fks^$n}V;: ݙ {z!aDr^?q!'tx}5뽊˿êof tn1:ѽKr\;:wbr AqkA/^ ZO;xD;N~C/ۚAWv'>3n"K9i}Lι:rҿQI@Pņ$B\9w;;N\“<"0y@;]P>+f~a"G ݎ Njy݉!xL@ʕebrJ֎ϕE4lfR WQCaFzjM)EI?JL.Y08 &1uT[ jAZl Hnb.0ؽj~T H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F IDATxO G4Ď`ZsIa!#%}J"Y!H% %DjH%hc*;"eER z<wX:&)s|PP4*^r<",KJgY ֎;=~.e,?忡^JΥr% ߉Np 6@ vvv>e'QW\ -.XzX@{m܄b7y B bl|ǡX,BT?aWSNxP*\YT*+`\v2J%PĮ> bseX>H@TSyRT5;*`~ B[iu| pggSb4@<;;@o#:Q;7g'J3<;+ԥ vrZ]xw޷|Z\X`c+='9|Л`WV焼 z|lp yNy ÓT|Z#UeNx2ʲayVd3ܫ]<_gHiF_{˿B7kZ'$  r,wxׄĕۿT`ڽdF3Sʿ %Yͻ()Χf vgQ63p/3ۂ/츾r芝:pnܼ86 lnn: gZhplN!g # Lp}] O/Po"Pl ЬÝP2x&d |]$3&܋/A C͒׭+8IIf`i䉯C1O-^/6yڼȑ uc\Nz?m@ξTp<`R3fU9M8@d$p5F]ȦxzAY\.|5jpj~ҋxvF] "+f0v @ |r+͆_Vz/!ԗAJqnXMøV0g#5{~6S'gz82'5ۂpFf.kIfL@d!N4m#>JA  *o9a_{@P7/8s Hoѱ̮4u,NNAqbi:Yj!ѹ^җΝ6AK@أg- 8'hzV]fwҗ`v`eWL7h/ϻ=Y#m@)RݚqA B_ ҆MDެg za]  ª@xe> Ͽ!Ha%WC p V!{|UT퇇!(baX$#vk_0fs U@g8w7/p-4R 4ajHm{2@h Ftf gv޸Q 4mpZC~t@ >@ LPj'AaXU0қk8DzX]غsb2:!̝9z gma>B/p|'l1A!Z9?<=iԦ[pN{d˲0UI0~H!i'֫9Yx@\ B ><p{| 0LC7 Ԃ3nױ2DTWE( .R)e҅.'"51Ub_{@ϊ#>K.8+?+= e?@Z)N%@H $v;_Uߋn @H $@H $@>-"EB9/N7>-WJ$M;DZ0[[[P,)Z<677^y@z@z@H/H/H+$dSIENDB`tiled-1.0.3/examples/sticker-knight/map/doorGreenStroke.png000066400000000000000000000170211315121121300237460ustar00rootroot00000000000000PNG  IHDR;hw pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F=|s((j^Bq)8Rl8o8nmy `P8V*U*&J/^  ;88d__}0/@^ߺֿnWTJqW_7xP;q?Dz-bP8 1~Ayr |1Z3-tn-/48NZ^t: \ŢiݲՉJ4mooCɓcs= [jjzROʩm>4 H1A2]+~z H@:6msm<88r9\ :yn.FP棒ƻA.%`T_.ٹFc7?o VcG++ƍzRqaMJ֮{e24atcJ\8+ZDIW kP+L&TN C d25AXZ L@v]ke]eMT*]2VqNĮZFԒf2V*Øe)1ыj 1V|D#4؇;Lf?x`Y%5@If!>.+rKkB|S5=ph@>AYՅPkmY{ bV'eV$%di`u:NH=ybxR,ٮ^|Z]kc I8ptcQ1+>&5d֮2jbdG t?MAȕu jy1 .xMIpM],+&,%\8nM|<;h*6>bwGed=^dn`5VSE~ 2SWV9c:@}.Guj:ҙ;ϛ3wf 9&e'sG3&q-ª8. BM?,YbY/S2^pXinT,N%s!a!tAYexe~P4Z'zzg[&N/@$4V OT=#We*@3^+>?햭I pjfvniûՊLs=d94 iJ P[5Kjn.2R%&1bлx ]!p#~,D{; J<\7EBk\kljY&Ɉ)M"Fiy9/iB+@Q |suauu!e. NnU籆TTCgTp8Nk T~ #Vz.D`+?"}5 %vu'#9D+@\QѴ>lR_>߄UFpfnU ZI>Q+*JI3~U~3CUk4B=[LdDVLwRUf(Mi&49nxjzZjXbepT"Ռc>1Z YG=Z  TnVwSȠtZ djqψQzHt Ɓ@~ğ5dhM ǁjkØX(n,@WUVk6 @3qtO*"{ uwΩUWHnb\aeaE\d+>0c0?0}T⺰ouVx VX/.I~xoƃ+"jNEUw_;TzEjS1LU!@H !@DZBHM7?0 L?@UpLB ,ky^`QmЬ"UHem(~nXC4pJHbd[܏MCH &^  bKhd͘@];1iHu,~>LLb,H ,~n'(@h vz$0O[u $@mࣕv8>\ %q.\HM:nHuxn$@]}?<#@׭|#| dB, T=t7g@( p({@hhczpfȒ ]LGs@:@H Tt t $~$^NO@X;SRE.6@4 `WkڒS~kkZ1pbW3&_~4Uj`B},D.~ cˆ=#l*WvM@LN3oW7azJp:{Nx[wQ&ÆΈ{|v ?2FTmƱ" 0˯xS؏эE%Ym<ÆwsaVK7@@Xcx~N@yJ@ qx,[~G$Zk3W [I% }ΔhyF vh+}~(Д qm+$lѫ:* O*fwL`c sn$@ $! `s l!7˶dSuM8ÿx*m=mO[_$dCQ6Z+(̢>OvZ  w<$COPM a 3^z=g_o]~)ݱOv:߷eS47>n7S8J+(VPX] fR4|n$b'[‰C!?bWb <؄cȋYz@K@He@RJ $@H l0g2IL mQ {1co1$@H $@H $``2zYKߋ!.ׯEݦ$抚rN) H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxkS4Mdb$66E}Cƅt}Eƌ yP؍o CFfc7n],̢ܛ[8W{ |M9s?zWV;_K4!?ǟ1?$IVeY^xIG^_GO3Iz)/Yey[IjeY~)--d;a%jzLyjZM 'xڹE o`Bl{$MPWZhjX^_'y,w$@I&n\.CTR__5=|mxݲaeG^Rr 0<2hca]x+WcöXVIVWWaX2c8LgN|.7 D0t^%Fa_xI7Y {kzp>vpkz"(\M6Kix3b+N+_5$DQ7];x7v^v> Cxór|.T* JjN#x=HYlmA$ƅ-(IҷNZ<c0/„x :4c8,d`:sRsn!l@WGNpꅁ5J#l @I&{-ds9 <@cl,L6WXq$Vbo. >p[̉puu\/ Vag%aooimoo+]3\-N5O- o[VurC@ob?kk\huŤ)eYO+ *AQIPzJR9@INz2spkJ4r,/[v1ᰋz cĄ+ )=߄t 71+S3~}l+LeTjS`#(fEx7veٹH45Ym{VW*y>Սf|4:PD ^2~:UcF!KwwfI*'eYw?ȋѼk]/ _! aX C&1D t^=͕fzG{,UW/Im@+MRyaW2(:8!W/f8,-߽kϦmخ Bar5zz: ͕E nooj]U*%u ͕←U)W Pg<]rZ&{`i&tCowolAg1O@.d^\ :<2by^59Y pSVPku5HtB9 A/Y͂ %kxie,p,#faWtXju7;nLg7UnUVpk~T89@8L:K3a%.u炰~Ol}_z 榺՚fdVGl1@ l檇V-\ s`ps[yzU7>H&#zky&WWW]_;֓;ᎅn/+3U)F0NJpSlOݱ25ya:3z:)?RZAb7l 8@J=m^!Һ͆j8@7y9NNtbMpb"fZv/8hZ| yaqX x/d7<Ֆqm%Z]l _G`g-VZ(4l fs{pi&k2iLd˞ ؋gE/R_o]/ᛣݗ|_Q(نV;sX *?|#?ǏįǸ}k}?ouweŸ/SõSĽAhn?LB#@}VԻ.@Ob\ $@HM' ΋M92 3Ky.L .ˣ=JE.M-;k@h PoŪrTSDp;%VI -l}P"n{:$V!6@+}@G+Y5!?O t wٙ&1@CB cc.:H]@ NH n$G #;k!GH@ X`4@ZVI@h [0@+'XZR1MHV6O'u$ ]G]E t G? ̽7D@H $DHVz%@1qtMjī }Wes6Wu9U] ZA^Vhvc&lZ0pU6zs%sSݦIx<\Ce G;- $AX*H4 7' ( . )r1Q'N | 4{}^MP7lrtjfvNstZ7,dWvr)Ksc*  Ƙ.%DPL@NbRĭY<}/^ku%sIxz: 7 M-_&uk"B5$ٮCkf jHup Z|Ki9 N?[=xҘA@hEpxz'?쬅j0`*R$|:B- gtd jndo] ~A %P``vY:S_fOÅ0쬅ɝx1&<,'1Dql2:%DpcO#A'.Vs8;{p-8p5  ƞ07}$)Y 5 [gh W\7-L5˞`t.uq"恸`bTWPu@+6*ؘ6=#`}7w׏7egWϊfV@5o<+7?v:@DWZLSB4xhńu^TgT}t+ E ꃋx"%N؝ÉR$LRWz W HL9_20Kr@*Ӗދ@H $@H $@H $@H $p,\R%z.t#^ rSa<»8r5E/$""^XVjvw ΠvIENDB`tiled-1.0.3/examples/sticker-knight/map/doorStroked.png000066400000000000000000000163461315121121300231420ustar00rootroot00000000000000PNG  IHDR;hw pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxKrpflgƌY֐!D]B| ac2" !$Dw\6 x%9,C Ճ<D{&߶zz|a]LǪV};Bwg^DZR+=EQC/JR\}.x||핢(^ro@*Qz,Ce+ /1(urrVU\dY(/nirn;Vʲ|XgRԋ뼾eσ-DudyyydtlL;;I$md~ayMŢ#(<ŻwdMKDC~~)Ftˮ{䦦~0(#ZɳAIﵑ&H4J7}'F.7٤y'$rnL촆|P!䇞ߟLL%٠D"(y6(Y:koI'NRR-޶o)KnzVAw +Yi=ph L6Kvww |Vo|` $ٟI/r6|VnI:ɖYmxiuo~atzNBks% IL 5ۥ{m8ҫ*,BY\ PQ_K4KW>;;MONNҮX*zƇ1͘075e:dEuM~$1הiE~D2v2LkFy?~fDŽf ˔ؘZL /@z,1CjThLNKRR=|>>T٢҃0y Ս+"$;W[;i!O[?On\k=/*\ ]1eYz&V;Ţq=};/@>{MbP:k3 u zSp1!kAߠӋyrw8"88@KbTwͲ_~,ۉ|_Bŷ5>:awGq3 9:~uCە~K!WBw\(@6c~W]At:4 .y6(!c4l'\N`)!ZjL?99Lg_\BZ+ɈsIuRh{y~`Y0;E@y heasb*b&<1 h+_~̵~jf[[D1ZdŤN]`.^fmf]F Ьz_ϯ[Kh4"@WLX4h Ξ6ڼ)N0cTm D"@]p&A6&ⶊY]~D lFBbk "@0w5k,!@( .$" DiczJL6#@h V'Ε"@!@ dc"Ng6 @u"@/)  tζWm]W^ \6Z˺K.+^ZLmE./> c8tg0tم{Ù]o b3eOzL_wmwMDa A"(r)tbi6}盧l%7;[v%+oxi[6=%LF=;\eU!zS13yrwtn  C DWbg%Ps%tF.,E› U`CnL\Lg$ҟXܬ|zI{V):ߗP@_;êDk~%^2[ D"@[W4@, 4 D6?G}\͞a²d`ܘx̅Tܹ Ƞ^=}[kV%1óRXS<')gv%cCMZganc ěl0xl@' @ D+6uY@rQ4;W[ ڙeSA= ۍk-dm1H GFQ9@7f]~DB޺1O@+țd-5GSm[pA/&Æ Cj4Ҝ`t| DZzSTDCB@=yz]0Dho۽rǕKڃ 4HX@X=KwЉTZ+, hų;AMoǑ"NrP )!sDdgE3!zS12F#@ijce.IlѮ73Krnh{Z5\:C)Nu B7+9%EI/ߓޜLDQȖ Po2a`l<ɉD5oI:@zh#Mmwm(^xK۽]xXsxXqo?-cX=j gSJї8YVlINy~S#d~ }W.ն^{ޥ:δِY H7xb/4p(vd ^8tÉZHq&%Moz `K_XܬδE\ n  Ɉg`E|h~D xGdΆW]CsbIXNڟIMj|V4`vZizǀu`h 6, ]嫉hĬ8L-ȁHu׃}W=id(FiT33qtģu[?_#T/d FcKxS|zھ(kx704"Sv U ]B*?n -.8<{ .}/KfCt-`J$<WY)dIYכBx =%c^6z Т>Ȧ$7[wثi\L> H3~Ԍ[x]KU w|UC.7RZB(9-ϕAS7yޘ ++|II>M.Ihwg>\NF[`*b̅43L81qy =YMwˬ!j =>, $ȓxzLc[ 2~% l8h D"@h=7٤" &bD"@ D"@ Dzq&lHt@F`;%~/p. !=+߫#mJW2:68:::—   "@|!@|!@// *Om-m(IENDB`tiled-1.0.3/examples/sticker-knight/map/earthWall.png000066400000000000000000000054541315121121300225640ustar00rootroot00000000000000PNG  IHDR@@% pHYs.#.#x?v OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FWIDATx1 00tbSA:hNW\8}U; UIENDB`tiled-1.0.3/examples/sticker-knight/map/earthWall2.png000066400000000000000000000434641315121121300226510ustar00rootroot00000000000000PNG  IHDR@@% pHYs.#.#x?v OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-;iTXtXML:com.adobe.xmp Adobe Photoshop CC 2015.5 (Macintosh) 2016-11-08T09:51:04-07:00 2016-11-10T17:41:07-07:00 2016-11-10T17:41:07-07:00 image/png 3 sRGB IEC61966-2.1 xmp.iid:9c88b811-6096-4948-b8f2-cb2f0374f6d9 adobe:docid:photoshop:9ab1a96f-e830-1179-95fc-c4d575c47509 xmp.did:3647270d-dfeb-40ea-bf8b-f3eae8f3368a created xmp.iid:3647270d-dfeb-40ea-bf8b-f3eae8f3368a 2016-11-08T09:51:04-07:00 Adobe Photoshop CC 2015.5 (Macintosh) saved xmp.iid:1cb9ba7a-697d-4afb-b863-6b16be92822c 2016-11-10T17:40:40-07:00 Adobe Photoshop CC 2015.5 (Macintosh) / saved xmp.iid:9c88b811-6096-4948-b8f2-cb2f0374f6d9 2016-11-10T17:41:07-07:00 Adobe Photoshop CC 2015.5 (Macintosh) / 1 3000000/10000 3000000/10000 2 1 64 64 r cHRMz%u0`:o_FWIDATx1 00SA:hNW\8}c1TqIENDB`tiled-1.0.3/examples/sticker-knight/map/exit.png000066400000000000000000000100761315121121300216060ustar00rootroot00000000000000PNG  IHDR;hw pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FiIDATx]RVױ[rqWP@Vv@t JWPF^@,Ȗp/8:tu$?&3d '#TfuyÏ  @ @ @A*^Ֆo>~Hj"1=IKt qy{Ge YW{V Pҁ3ذAғt%OIW0j;Ti*2ݦݻwj*>ĕ?axA^%}']$!MTUyU*Rh3$)2'ceYj*V_]HZěNX$Qմeo=I_axJ/ #l6L66@sOpr6ͳ6n\mk`XkL\m k0Z;HRܜ-xΓRpos̻֋-I3auۙo9o!q @ @ @A  @ @ @A  @ @ @A  @ @ @A  @ @ @A @~ @ @ @A  @ @ @A   @ @ @A/Ӈd b}RIENDB`tiled-1.0.3/examples/sticker-knight/map/flare.png000066400000000000000000000160321315121121300217240ustar00rootroot00000000000000PNG  IHDRRl pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FEIDATx=lI]FJٙ"M+ BN#tPB!Q"HWDAAAA"E}3A"d YGIh-&8ci?S+lle566`cc Q0ьdd5Ub6ŬzzHTx%Uڌdmasc1 >%nMQ0FA? n4:p:j(xpz7UFLc1ßI`UFDO`*j>;Ycv`hFb(iUMq =.=xYO>%P|.d'?b6)ܦE4-. @AӘHp-a UxŷZB!H`әҧ> @#aYTJ4Jbsl4HNp!kvAKج&)<:fu$JM?ˌs,J@#&y:n|lx(`|*A("Qbh4I|0}}rFύ8z&;P%=踫z?Q⮉ÇFK> J= )%?[:-;),A497Z>OA<7JYv:=@XLxʭJp%fRW )-|&T3&{P(Y*%`V?Q);Fd:2bۧ˝ kqHcS@7 tV4*Z? O=fYNs hBvq[<`Q<:A@#P5'Ja_I$_PYi%TkKz۔(.0Z^*o{,8z@E(1_@9LO V @!}X&: E;d st*1gft(*Qr-r=rh:=Qr((} Qbp]FZ73Zl50Z-c*)a]b>Qr-O?%۷7A;u n;{*? T7 ̐QV?mЧ'8I,?v_Lz[zBp<]O;ry[ږ>ɡy۷@`M la1B,?%^2UoQ$ZǭĆvPo+#s[ dF7 :wl`X)lZN@mVĀv\H (J[D E 64 ~vf,6N@j8ez>7.]`/#$vНe=ANjDW/u90Fex!2?&/Ϝ=X)JFWex(`]JϣN@\,CZ%%(Ebf ȥ]lP vg\Ǝvbtl_eFI=`<@E*/ T izcr+u䪹rHy׽k[wG[{n~ߨV.}6>ZpƱA?F닟6ޏz5SWdpln ߨ@ȠgW`ʧk9?@h5:?/zQA:q;ؾ$˿][Qnw{tg]Jj3JKp+x`g4"n}h^oi vԋ(H|A7!b43zm/|(DFDb1>°5)VPK{ŏD֢b1!<|ᣏ=A5^v.ՈG}0 r\2Bȭp帘x"Mq$o9>$ zp$̆8 r:|}'.%?Y;IU_%.wO$A,f1|(yf``pTrICn4:>woP?ZFZx"u2nu JB DzTKd鏒?]d0@m";?H7j;ɟn?8 kX u#n3W:>᫐<8X[[jxu_ V.}nFmc_Z+>txG0_$Kx%W03dzE5@C-dhgndNwd?~t(-|W HښΎno +lQ 7Q?x;v d Sd~zr5$Cbz8,6)Q $3vߣ 6ƬNal3r*J%j > l!€;}$20 "-E@:e*^}B:%J+Ų"W[TΛhPWP$UoI.Hs-@v+un>YWgEW~ m $`#Хlw@q P2E^d=rݖ't@r PU!D5ڛY3N3$@b 97ߣ;v=zQ {b W1J,ƕנpgk@,&/%׌JI,?%'Z+`99c:ر^br(*rڅ)˯g.[oՈ*#@A |@KZJL>V: @#:A8Ō?!Z u *:s>V U,+kϚr6ޏopp]>VhDY _]@ S؈~ Y >'<tz: z`Iwӂ, s| IӓWPJ6\ñi}͟OA4ʈ}:6,\-X9ff缱O >Ai*Je7wr Ϭ|bw 5F0J, ul8Aw7}.dCpoM/lw!i osަ;HZإ;@D,x;^R` -faD峎~ŸVp4Qfm<<QNZ[8l԰;R:V)׃c6gp̖M_(ђxf[ΧID8O{6es*Н=jd> gPg2<] "gNdW(GH*U]Lm2 '0IO|DEs|QdD I( VY6Z^/i v+ C247 {g)c4 @Nhty tx#j]gyCLJVX̐˦Xf=P4 &ʤ2L8:vؾ,{oqrvtBb%1ll ?|dIENDB`tiled-1.0.3/examples/sticker-knight/map/gemBlueStroked.png000066400000000000000000000101651315121121300235500ustar00rootroot00000000000000PNG  IHDR@@iq pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx1k@ |Iݢ!q1x0Kh%C)Τ- x)<9cz8ތNK8;n6H~)H-"@JvrYNZ۲y,xqοG`X mOt+˲L-۶,gh,: RAyW[|-t<h4MSpQ[y7lib&J98Si4w]Ӈ4!Si8}t: P˲ΎK%[xoaX^y.e RIoL(m?d{'{tu z'_wW~)Puy,[,KWg{; {;Wf Z*pοෟA1(wR0X;O-\f9&@`,ߠ%)NP0e^߹o_,k\\.˲7+Ö:7K7Ľ+F&7`EY3LAQQꞦ0r^i.TU bģ ݯNHP%>ժvtB컚Nۯ(Mu`LAh4rKĶwR4cg﷥0f5ZUb,Zul(`d4M}\1(P@e iǒn5DEC-R=<ˁ3f`pDi| *E,D"; Đ9$UFtKDpp°` AJ$,2)\, ;#Յ~8_t :OR({O $SE?XzW6zAjaD c.Q 1&\b6JxD-B3AL;i œû_f*R(&LP]~Ҍ@*T3ηn"A϶)¥%58G6^9P2<4 H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx[{tՙ4<8vlzFeIؖm9_*.K[ ![@7l7-.g e)&.4 ن< bS7[43o~&)9wu7oa!L 8((>1JaI6b1&/ F$,H"!ߍF EqQ$ c|/YOBɢ  AeY~C@@+)>oFGGAv!($IZ(ht"H$I/s'bK$YF$Ib(8!" &-v&A4e$I_$P(;w###%I I^C3L"x'F<[Qe* 6XQs5|}NDc%4h1J] \xՁfUjo5ᕎzlb,Oc||< g!Ų,OFBTKߎҕYViw2 Ui4W5? ߅wv,zV4̂_;0817o9l*µJ5>'~Հ> Wr|llzZJiEh-ݍyRр\Y҆:';1`5al|-JE&# !Vrʖ`||@71ۄ[,`9*i'Uv0q^:\XTepk(۱T!N[Q#N*Zp~%P:Ɏzx ]*zx 4_j֡Pu6.66£upZ+{nbBBȽ \ȲP8A,Yb<@|y! '~Y,XlogR{Ge,ˌ( 3>>Ό3^I$dYplÎ2 fz :h4<.f>ou5SV(X-ԌЬ$ImvrrsPZYÇgRD"}p80~8BȗS|#WVך*7 7LgRaˀ /ՠY1=~kFBa޽ ;^/f&~$eY~.ն~?n݊5 zkTi*9q6=|ヤZPJŘ~B*%,3g EAK18gi*5J5v7Tb ikfFa[ >RnT<n7μ^&I$IxY>y/łs$I׉Ȥz _K~`Z*ݷk t4T,>ZjPYd@!}ECo+ǵSqsf;汧E:y ۗN@<zIL8F)ϥ>y(T*Q]dS킛G߅.K1K: u7.xס:(CpY/EG~Aoߞ5K~;_3/F$^7JFA=Mwu8[uslEQppT 4R J1<S+Ö +X/b&OB<(2E@,keYޝA={T8|c#1Ќ֕ Kv~0gI uCrSjT{nrvL)].IF<~? H$D"& ijF188B%8@lO5Vݟku I~'UVh4oA^܂ "}AE"Քg@JS8r$tF[{;V+/) co,XTᑺyx݈v4\nEb';m6"[BOo/3 _B!3?dD"F*l!ecY\g3 uMB‽AoUvbk*89z4H:}eT/> F# jrU ӧȴd2;7mBVRkŝ%H Vb㭮F||*A~/uԣDZ{,OPJ$Ib|L0le$Şd(܂TԠGوp=`m9n.5cRW$ !(Wi#vp 4>H|jK$|: 0sJ0D@)e|x<6>WW%\,DQl%`!+(_ÔAQ~ ap H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F $IDATx\]hYKw]Kg4LwM]BD,ŨDyQy^ R(vl} yi'OKR"S"\\,:;O~s9x)t(((*((*(((*((*(((*((*(((*((*(((*((*((<#,ۮk7cwۮi \a9iba2Pfm(EvG/. ڴl{1 аl߆X2 _O3Ge=?狼Yd<[Il~ Ku4m/ZJ̈́np|}ITKW0CrIeW%r~ε"˶)bLZ=%X'"Ť$u !,9|qץ wGuD|3AН7pr s6c,987IĐ_+YLCBʋ:SQ?3 4%ND>R8R9Z sܿ0y^bcLe!h`eۍ@$^NPd& cH]ӉSB]I $bH" [ΧW1+1]bZuGskr@-@\k%ܴt^G=DK07sseMH>F뛶qfFi|-mRߞUZ1V|dau3JbSWbrd -IL14!k$6=9q|=rsdW..g5r# ?%". pΔk&@;ݲX[c->F˖Z{)t獸Us[c~w"t1-:mX9/U֌j}*.|=!r&: "(#O:O+Hx@{͌RwB# ͌zsFsem9rpr,^"</Rqs105Ii Lj9v<&)CKՓ4*OP&%щg "U0-g@]HjN!;)I'Thi9q[֢c5Euȃ٢3/$w__tR^mHkT7HcqMZ _}cʞ ;oo?22u9e H?ݸ'lZ!d:Z~su?-=[FtMG}<yX 1g_-#[n5^=rz˳ ܛtKc U18o~tgѾ@t1v16 Oua*8cκ+?Gp 14w}m.~ @aN zFj!j~2Ʈ ;Tⲥ5Si/w(-ߙ~z c.c_7J=#CcyzCэ{bnدRޛŌҺvihL;bWkvi_lU@4ľX !y2fF_;Xcr,PF\áBO!oc?BD>C*|S>uiQ1}W蛶qx|*d |u2 ݸ %^M3S EsZWbZHjAT.x PSdKy)CV*~p/9&Ǐ_k@22PfKyZYdKyX&{"ԧ}Q#'8>]&#XMƘ A'ܜSg]x-ukB-~![.1slx\/ʢa}6L:? cg$Yw?w(BpfBq;D԰9FӡFGVxfϑLaF$1IYZ7mG h|$~^߅G)ȱG=G`x4͌"ݓb֘ȅ$Th;D{dnGddstN!"' !lGNvQ1Ow&|Ow}Нz s0|aYwq@~iѯ0 їލ$9]wcwV70S7CUXTC>?v]쬻Ʌ'Cx1<<_yDBCDNcO<~3!cws]hzOrѢ ߗ煝uZ[/ϊw`Nj~r^=+V7'o~ /_䒬%X{)CF/* H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxZkG}RIGՒҌ.~IVƒ` Q.bK؄$@t1,9| }\B.>/ C2[V{G$qUW}?{_}00xQ7%0040400404004040040400404004040II;˧z\O]OJ79=Q-T^6<)˧Htgj(R-Y*S6PzOFg"iDlX_@=E O^QI酸j_4]djǪ'孄uT-OZ3nz5RkGƙ)FV|">& A'BJSDHȒwU㒚` "aFڎkAz6ܭADOi5AO]zή4j&LRTT.4}8(pE" 0w'8l2_@AT"!M^_ܸ͜c#;$w^nu! 2?15Q\4nh>娷XRhN4j1}i7άѺ\G+prƛk ĝý(5`[Q9y}%A37dXP'i6{T\g˱!oǧ+[yqsck\XAsA\ lNÓ&,KzFDXťE3j Kq2W=D1\ĵ p>1f&޻h?|- !fSU0JYCc|e!f*Hm Oڌ'0Ϣu!+V\:'wᰵvk96rh~)x 9=.׷Nϭ+1o['*-83#tNF5p@pFdBm O>7K`C"jߺG{.Wέd[0ϳ= Mm!;w.卵 g b=2c -s2 !Hۗ; Crb!P,2/XҶ V'ya1wpa?5Q|ɗ 6gz$[d Pxca{<(!w,`9D̝I1\ ߶dzMjڭZuL;Gv&­#4=&K61\wȳxZ= d<\?^=eBsw3JGԞU'=tԏ#j)x?xv]LW33FjlӢHغ}xv8MsxrGRS}]8lG@{ii:9ǘy \Zgz;۽}䥇'26,Td"]:+%a\Õ #r7{8ˉkIÕ d1uvq*r|pT* 䳑B__Dyu*U\Y<)`x?{ ~;8;HTv+3|x]R M2ݵ ~I#EhK-F\IENDB`tiled-1.0.3/examples/sticker-knight/map/grey.png000066400000000000000000000434631315121121300216110ustar00rootroot00000000000000PNG  IHDR@@% pHYs.#.#x?v OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-;iTXtXML:com.adobe.xmp Adobe Photoshop CC 2015.5 (Macintosh) 2016-11-08T09:51:04-07:00 2016-11-10T07:56:22-07:00 2016-11-10T07:56:22-07:00 image/png 3 sRGB IEC61966-2.1 xmp.iid:941746f6-9f7a-42e9-b40d-b336cb21fa60 adobe:docid:photoshop:3de0bd8a-e7e4-1179-95fc-c4d575c47509 xmp.did:edadc86d-a4ce-4c33-95d9-ddb3625585ac created xmp.iid:edadc86d-a4ce-4c33-95d9-ddb3625585ac 2016-11-08T09:51:04-07:00 Adobe Photoshop CC 2015.5 (Macintosh) saved xmp.iid:f9f10874-a23e-4b6a-a58c-1f0164d87eab 2016-11-10T07:55:17-07:00 Adobe Photoshop CC 2015.5 (Macintosh) / saved xmp.iid:941746f6-9f7a-42e9-b40d-b336cb21fa60 2016-11-10T07:56:22-07:00 Adobe Photoshop CC 2015.5 (Macintosh) / 1 3000000/10000 3000000/10000 2 1 64 64 F' cHRMz%u0`:o_FVIDATx1 00mN i4&.{q2lIENDB`tiled-1.0.3/examples/sticker-knight/map/hero.png000066400000000000000000000221521315121121300215700ustar00rootroot00000000000000PNG  IHDRĒd pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx]Pg GbGa!C(zS9+T\9׍lk.ғ3[+WMNgl [}7oBBaZy}}bYJAQ ,f(P . NHrD2`YVO @˲Ӭ:|̲lE@2,Md<XX4'eH]d8ITQχ 4M#77f3fmgXEQi$9}}!hhh@C}=z Ru5$>.0TP.4Mn㉲2 KoZ v?˲'-Glh?}^D^4M듲.i$%{ו@&onn7H/U_q~+%4@/:4M~(+.>OZB4?<o >J6e+M1LJNL#<|5 Xή.)G!Hbtvuid Q+/7 i+`q`%@gj#, ϻ<<,.N ⿈sD ھE f:]sۂ4Kfե 3;|[KR]F >/^A/ !EHo$&c>}NAǏ*n[I +hrL+a_ n^fTvQZ,6&'_+KbI')KN'T,AlFnnn¯&@^-Gl>7_!crI"C\!),44En^7Jo <n>XISR0 3]ρa搛 kMԥo H6xIC~.8$u7O !]-5'O-s-z{15^KН&"ɞ頠l6)LѤ&p'+m0aNTq-,#gH1]naY+ PtC/ v{$̡t{ˈ~hJ$+_pEJpBy1Ѹo?:Nc <T[QD<:fm|30CTo?'иo|@τO")6mLIoՐo~Kr{8EXGdPp_ p!`'#C?Чao@? 86wUݱ,W*Ŏi x6:!a059I 9ira氥mmmRR)G^ܿO 0i:$;W S^? ^7P: r[Hhv%i \p JBN!,VY/V$yg{l6cci)a4|섣4M 6`*(D^ym115dXZlTE5-I,{FNѣi]]! Tnח$d+FGB&%E^RP2.]+(T"AB@n 4=~;xm9i C|hܳG8e g"&8.l65'ABψ}vi:]6V4yGvGj,:eM~^^LO+ΟCoOR<I6Q"OU=0-GlQrHVaSJQ `/SIO>'+иa%U/94rHF/_#nb3<T jXRN?}WcJ\Ƒ̩v);?8h8Bþ4;j/47J )N[gCeV쨭u;w`uNY,yw:Uݣe'~0s١əOQ5@&[gWP7v~ /_jӛ7+w::/?FFFp 8(8kM&J\FRmGm]\޳`9lPHW sex] FG0r?H vvnSZOKhRxIa[DZYUp[vyѾbAIH+RVǕR/Ѽ޼KJd7=g R 'qlDN #$7nRuhs%@U;'>肰Ҕx]Ef!$F iZ4.6D_x}/899_Q믌|sgbC"D˨7Z%p($|)~HϪ"(7;pMfa㭓'q]H-Db+f8sY/zEN_TӧQ~v;W[(҅ lX _kM&|"RTIB m]%Bޚ5F՗n7{r'G {Sʾ汨uM^ҦFG `ZSL%UdD @ԇ]:s7o~vzo;Iܾ^| bCr'c:BckBX fJ Ѯ~sS[m 233ʑEʹLz%5ǃ ONb ˲hj &V ܝZ͛Qx>< "33&S4YԫUW]x|  1D`L/ {|b&*Ej;3:cDg1A (Qycb޺Z`5jPE Z`k'X#8'0^y ߻~L,wzL|xO|;]磣X_VIիBTd1f9 ,5Qx!m+ksL &c[ͼ}>ncCBDXEjh |V:osNK0_"{}k{kC/CN &@4 H}(vu _G1!Qd?wo5~ϱ~`XC0M,[HY1DJ'F HލX! VzNp^@" a`7.uEA?.]*T4Tᇹ3H6 bJ<@M|Po' \{?jxP)ȑ}fx${,nk̞?#nD\/E"(>E--ڝϫNx&7Ƽ:cG]DWXE]jܺa%=o  (9+C|N*}%%xqܝ^Eʯ730@Bd"K +?@_҈Ƹw9-눷lJ@9gsւ$~C FF>×nwH `e,Z(rƌ|-C bvQ 5S|>6pf0;"tE*,b7Mi0i|@uo\PG//eS{*xѤqͭB7շX`D*P'Dx&܂v'&|Se-Gl14{V ~(YXIjaܭ3,V8!ظRp] c|ʔS5QCqyxXU&ڊƎdgDK-?W =h+[CZካLOI+'9Y(F\VqGSCh +eIE4+SA┈žULPӌ* )k%X9J-`jҋ+iKeeb) uE R]iRƖ &aciT{٘`"ΠCǀ˥yL Y Z抹 ƒCP7U_;$14[.⭓'N& TU?;B C@'$ GɊ^L)H99YF`ߙa1T/EQΘ(˲l7$:jrdsGέDҍ55g8ATX  m0gd@N2JIm#!=KYU0(gh" P$7E!xvU B\#X~plR 5ecg30ZGP pGU#gZ ~rM)HL :m(m0s 4EV@ksj+4E 9z8fAeV!BD|dj-\vr*MNޝYԡ 3 ]DHSx!r8!_CLj Ԥ7]+AKo;nsx}1g~V+Ҝ۷oal5)Mz!?YK0!Qg 3٬i Z8!q@faԤǏT`z1*xLMz0ső0 NҜ,ז|S fUMMM%Rlhmmgb|Atu\H TP,إD߃P_/(;nP`Kep(0z8|>aOQ['HI秔877f3*lR \˜YkjܿV@bYR \[R_*&>D+xj;Q3BF<E]MIm-AOK)JAZ 膊w ==h:֠(jPs2EA4+x|2|a:e'y?Kzd (^W3r \\V6D ;˲jRpo~~2J`*( mL e.㉲2l6PeY'@v!CTPKU H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx윽N@y7 B;@acv\b_x01`wZZ:|S @lsَ/y5qXUuShb~r.;  D6_zJWGZ< ,\\wM\7֮h儭$QȂ̙NQ iUM$ڐe0]t:ӧ6.Uj3m2Kk?@DrxX( Аe3,~ ӧckXw/}Nϫ9 @$ H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxixU@6m)%ik.i&mtIl:(Ό/02Tq,:XE˪,iKEC0J&ؙ~-ntuu%s\.9sf2. ^~LRzy@,N|gXӘ2u*&l(<.`hQX\)Sbʕ }oj7XŞɓQ]]~Ν;q!Fmm-ު\uu5vލ#GyL8 g\.x{ p1 p>ʍ @P@8Cl\VXvng[ZZ0o<(T*bH2jb1 [s݈o&4 KI TJܠAL&XU FшիW)!E#燸n#̣wV, F XI$'bGn:>/bN:8]jAgԂ3){I\q":.k֬{jA: 6g|QlF,3$"Q.X,Ɗ07j;߈_w ؞iH !`d;B0=O庎x< y555H1V$B$&,ˬ8SfEӂR Z46$oy62p_ !CP^YO?W}L6EcF2sxʳ)9iHWJ.  A{XȐCJ˄!,i yxOh{Q/B{_MTܧfu&ƪ0)Sa: sux 2Ì3JhpXp{庚|E)]QJf}yL Q!ɰњÌC&,7$"AJ&T"42$Ȥ2h <⻒saFӂ3 6%+WV0,b؊ w= F%Fw')7bI=6 pDLǍ&|$Tx'MBc#0||0⢱ޜ,3֙R`KWٳQ/BWp!L37hbo2+|[bd5EbD՘2u*֮]l߶ ۷mÎ;}6[wq Db=]ehtvo妣"FqT4n& ѣ1N D:˳qĄlFEc/x<穫 ­S`Q(x}Xמ)((U8@_8VbBM^:,*9"9s&a`e*L&-N -`_ALz.n a!~xgz) @Z#˚,`GKLx+7qvS_DV L2q{80S{jPt---hjj$?~/"2rr/@Dx8YMMMطoA> ˗/ǁ{9sPRqL,ϟ#k׭CNT$,B[Yb1^.l?7bڵ~kXf Λ> ~DFnúkSO!^7._Yr)-MիW㥗^}g}{yXa4PJxژs|b  IL,,VÜo[{Ln@Rx{g~=f}5̞tde˗>|ͼԂ?J-hrZ.ĞAhHn>,>+Qw&7 ?2sK)G˳Vn0X%gW_0*Q548=d"Bn ( XbH“Ad-d2dzb{5!(AĘADDaWz W^ATU LӒ1\q"1ZpG  1#FqC#@XT4>OIePdkGMh=7#!c2:3{6ު;ґ#H*>I׋ 2 9d $=] Of|Q [lqŮ]믟nhDe3 34QV(Q^QWƴ;@}&nA!PEaڌذajjjP[[{xg.lٲDg ;߈qJ1/'|U8v~{]@nlޝ`)4%s*1H Gl\ssQV^gi+*`+(@Rr2"%a&Kjg90U )-Λ׻gjc rݸo|pC"^!9i, :Rb TǪ"IUE#DШh+1Ja0G)|Y8Y}V N A!F|K.ǯ~{cObtXDHeXaLbSs]&5 *c`V J- TGcZB֘t(e4:::pg hěoΫ!1n_߼zc2nƢ*л5\NӌmF=Gi؞mign>Ä&F&ߖPg@vlQעs@GGJe>X_{; B,bCfvN9h-̊3gpWGM8;;V}@Vdc_AJRC f͚uB(Kag.rرc1,8/R=N3:ʬh -γs"{ԂXX ۶o}[X=c QJNBܞ00Ø=gZ c"(DozGKLXjHV!T&<製GFInNJJ_GB&1s~>g0('dTcA&eo(‡6#6[Xj*;BB0g\}ŀ͗R9y5cLE)d%A@%Mz0eTD!@$d#,IQO-Ix\T#ƍȐ0$t:mO&lknnt0L95m!29aAGa̙H,FDD8d R)2io_IJ!H P__OA9gW#AXO*'`ƍxǤo%߆$(ZD%$)6q:ddgƛoKyf|Gӳ0z萷=}4狞rU*1aJǎCUu5֮[?ŋ%Kòϣ Oԩ񮮮ۛVjp PJ0Bx _3Xµr=TF)~|([)Y.pR=c앟 7_J_ ,Ji5. .CH ()vJj' ]!r#!$QJ_Q +%1:c!<ƓE` ?sLHGGRO]?WBۄɄG 1kkkRjsݳx c=I\n`WJ)(-O)B"B{ 1koo(\{{Nclc5B>JtMROygt=%.dl+IENDB`tiled-1.0.3/examples/sticker-knight/map/keyYellowStroked.png000066400000000000000000000073421315121121300241570ustar00rootroot00000000000000PNG  IHDR`@4r pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F IDATx1O@ +HH,*d2 P [Y`4ЁCX*̕o{:[s>_ ħ_";{w{KDF D $@7(p_ c1qp90 T?ݢrOZh1;0EѮV|_=PأhF|N@  G0jG:meYBٶ( s> AeYlh(iD  ei_*۶יF+.{>1ζ:wkBv긳mLp]W AmYVJvݧ}=0Ǝ:y^;:[OEIwU !euB'u!k^A}XEﶢlXm%j_ ݚeuX#\ h4pcx(DF}M Ẋ֪0nxޭe1Pjp]MYY@~ة'{lN{4D9xEOt("sbD˲^,ie)k˄I2@bdm_xVARE(^[ԕm+'F&\D x"&~l6Ѳ,t' ~>>N 0#ؓXfdJ./ގa *lOiN[fϾ}y9St]7se/[uxLO'XT?g.ٱ dUI{8jbIГq =lS?V!g|DpVvGyҶgiëC 9;K%_$+**%ehލs>P+ Ep06TI9W|-TG+1q=AͰ p+0u E $@H \KMR}IENDB`tiled-1.0.3/examples/sticker-knight/map/platform1.png000066400000000000000000000145261315121121300225460ustar00rootroot00000000000000PNG  IHDR@Llx pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxml׹gfk1^bGm $BUWDm*]K6JT)XH66"RܛBC.S/k]v̜ݵ {~_yy<936ʕ N"p;]Oogyp87 ,,1ox^Hr/tFۺ >F o6remŜ>;?1ڥ?g V@ۤ/'z ś}ƫRXۇƺ~.hDFkW[g#(]\J ~.($,\ "P꜃6f/d~V?n?JÊE++r:Ёs]qסּP"%ֳP' bڜƍ}޼u=&H0qt &~``ιq0y(Ѽ<~s.ج `r`2/ }lVLK''!pΥ|+!.WC΃)t ^-G4ur5Dҍݻס2~12EduӈlvX۲ekf>z&1[c h[5VS!MsO**N23 fexg1$a͉{T>|4"Ylte-Q/l'xa;, -VS5Ƥj3taCؾQ_D(([vlU`29DRتIq0ڦs7hj9!$TہF-gsjwS=ptEKFac.mVDR<6 'Ū gC6+˩m2߶GFM%oZ-+_O!2Kf'/0DB2La[[Q_Z'aAup/}%PP_Kqp _Ps*s>?J'"~T;>+c}CCcsA?(ZVy1k-=2673 eMij׳ 65Q_eʊW.xl?D"͘M@Y1+*6&eF|-Kc[`x2>Q4i޶qTď$n۹s'ϋL]\J0ݥ\ kW{!2OR_' Δb3`1kz/<:!$lInML7zkSpVisW^UʲLWcPlߨ_UDNzd2|Ƕ=q&׎w5S@dC?"b .^vN+l&k^CѼ*%FH4~.}v}Ƿ9&@$~BaR`B?Wk)<$'US[X\奚6ҰFkgD`v5S ,B?ߵ5,gMoSJRB_ţ[hU_XT{\=~౦bn\2C/#7ә 5Db15nM`U`yЈQήz._o˧fg3/N:^͌Ҫ ;elXRNn],mb 3[.`= kdљݰL&]2eb=TVqnf>ֲ mo=+iěWHzĪjh$`8Dk "dڢ-l18iCML $粘OpU:5~=+FϮz`7 Fd|aRg mCÝU霵t!{or m<ۺ{ Yo0 ]GVl?<o!z-NwʪQ3BM56pP45PKig*)r\O2 8#vUb+S@?ױn6U)tNo-@ҪȨv0ۥ5ljF`B?1clB. v"PY^&bp{)nDF"m.*Z:(]J'˜L=*Z_1f̙&1VUV-65Q $s hu$A_U/5e<-8~FDH"xI%Ĥj10]o*0 R8%%l}LO?37k|1{L7;Բfb"ضௗBY=%@Ic65kJ3HW!2MBlvco=ޝ2h^ci3wD|z%g&|1|(/%xEoi$xⳅX^JP325x&^>jw9mܯ$@gc Y :Oī w(-мş8vS;0I{3{$sئMC27v (RhoIDŽ r!Y4$->#&<όVU2䢼Z6^{wl|kt^%܁ F6a7`S8kS~B SqUpn%=ZT C J*u k>Z[jpch~@O@/f`U~ 0%l0yÀ;psOyser(_r lVD޶S V*Mxy1;#Փ&"cE!@s-poAs-cXELB*흔ջ~":t`X^oYG\v{v^c8Й&45hO]l BB*ñ? !M0_0JBDGE 3`?a|bs 8 bv:%ZV!B) !3mƺ6G 03BϧxB_01.ث t^.0{cr[~}1vHU՟3b@򒒒ꅸ(`UQcw=ұ XEj@U՞?TB(RU;9%h:UUU43(Dq/Z΂bY?BҌ(b !16 1-: "n5EbM,f@UVbpFEZ, 2O Sm5#1Ɗ~3a cl*>2+bl6KAy<~'-K,x[X,1@S暚EBUۺ2.-- F%TDQM/q+np8np8np8np8np8nN+jSIENDB`tiled-1.0.3/examples/sticker-knight/map/platform2.png000066400000000000000000000141321315121121300225400ustar00rootroot00000000000000PNG  IHDR@Llx pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F IDATxly?wGLőd[t)Zj^\ 83PgÖ?V)XRaƆbthS )4]onPD˪V 2m,ER%DW|v,y,XT[L}N^xPȺ$QF~&Zou8.LBHB 6꘸8@b8LCͮv(rf8JJ]CWaf)͘"6B}>o^zDiS)1٩+imxʙz}b8^d>Cy蔓 }3וO?>Sxg@_錿oI'=>w3$;qtN~9k`!"c{KPh|.Bso (zD+8zu;YwLQgqdR~F?`4+ZWvx1ցz|\ ty#s e?@C]4T%Xcs4ko &/ = #R69`keNnp)UA P2eZ6H2|2.h|wRydOľu] oVipɬ5bh:_=ѵC}NTYWP!ә$fb5rY&04^c%đ '4f]˷߿Z^B2)ưQ5gSD.wSV9_^HF]qu RLWHNU5LVٮ5A29Gcci:ߛf&.f3`pb8l6Ym1(o[m_w翟ڰʻɟR\o0B?k]ʣ{ q_#rݑ/dC-;6~y?f玭ߤ 3%9bt4 с ܝͬĖ߾ޫw Ⳛrg(ytn+qN #͝xja'kx_H2ǽ }bMLju[a%'p{e{CᥧE{c$Qf!eU &~{&?,1`dqi3yR:f.&XkVRoϮf_ch:/=[58"[ ϘTBU$nLeBwgBF#|Oi4wGH ivI|+uݍU8:0I٫v/9Woϐ^IYI'-rA&03T&`;N: ƵKqzjݹz|27gLs ^/s*Ky-Q,Rl39cLܘJY'w/p8gjsib7ѹkй{=s.~BFq5Aȃ?? dZm7JHTМl9,|1*kǹ|@YW!3urCS󇔲2>?סlHTU̼Wۍ?3+'}ֿac()]r qC+|3F`Or䍈~Jx#siiz<V֯t>K}+N;r2ovҠJ _,qs:%mh 0#  Tuh DRߓn狑9K!!o-6ff)]Pt(U rF~X#myS2?WKlMJyux/2Շ`.oR܊rad.QApC];6/W|B_g6yOd@W,|{ {E6b?KO;8趜7g\݊"R3M5 #PWmEI+[< F|Q<Ox h\]t` .w-{w)}@ ۍ 0+̿;k̀#ӀO_s^ߤm,&~;a߷BxUTRELo+l]0*6kUokW+@te~QbѨx@66fH;YHbPmb `LEm2l0x\TmP#{Gb𰵏dˮ8 ɜm>-85+He&ֲGm&*3B Y,Y7 -l <sR:-l<000000000000000000000È]sG'IENDB`tiled-1.0.3/examples/sticker-knight/map/platform3.png000066400000000000000000000103601315121121300225400ustar00rootroot00000000000000PNG  IHDR@Llx pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx_lSU?w-(Ȗ& MMD$HQG|EC%ϛ}1>(<}BEqM %3K8eeeݺׇv&Mڻ>ަݹ{~_ [V+M 'l{bAG6JL¶8pUm~as8J5/}B'e<9.0P񼯖Ah¶_~O0Gl.K15:o$R`=Z> dOE9hEXd~;Tg@&agMTf2e,q#^U !g_wK-QYi<ǙH2 t*>Pܜ3h<ѿXuFXmpE*L$2@FQ kTuUy2ؼ:Zu?*۳XNVlb>'Q^1–pTNvNof= ޽WdR]X 3FK;Ǎ1mP\N)[յ=[qӽ(tyq'7e=|ls?FCi O8px hHI]` !`E`gvnQi 6WOy աF?)VDak |Hw(GئFqe>]LpSuf`q`z~CE#hPV+,BpY\lF=Nkf\쀅Gm 0b]J?ʺz%y7fѥ+ ԹݢjxM@ pW&Q-WZRs~Z-C ۞6_ [&`+`R՘ Y \U?F'a-,SiJi9WN?ھBj{JEd - I A bA@ 1 A bA@ 1 A bA@Vkf%s{IENDB`tiled-1.0.3/examples/sticker-knight/map/platform4.png000066400000000000000000000103671315121121300225500ustar00rootroot00000000000000PNG  IHDR@Llx pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F"IDATx]L[e-u J'6`m%Ƅ8o4[/W D`I\2RF)Ja^=ݡ RK~}F7)Wa> t8~QD cHN%bW] hhcg#KODJMu>{Ra2=+@ \H4ŝ]GgSxVi3,.gա믪̃u< ̜#w7dsRDS}C4Op\#+hm{g .l=Si6<.d~;mZ>=DSarˋ^P|Xzb]/F&cc]ݎ|GN24s(趦G+9es/XzKL`$Ûy}6Pipg6|C[{Q(t7.wa5P]>Sm,@ Ph^_a<$f om b, F& bC_1s"pAׇ3S8 \4dKtxDG8k=o21 A 4PiXzsQQpnG 8iw9"T3:4U@24TFQU#@HMRfܘYU* `4鏰YZ#:=aGfu!Lc u=O&Q`ڌU&w; XàVb7h,lw @+u*aGbj4MkB9e``0`>q2ߊ;W_2„b5V1m}B6-ꁽom (!?R˘MHi]sEB%i;H{hRd^,so d㧕s^,I5h1d2iZ=P,i 9+{+$p i64Rk5yg-a.5%Z-)3@,bY[lkA0[:tzҠnL]:;1%[[oݸZoT[pݹ㴑OV.A bA@ 1 A bA@ 1 A bA@ -B0IENDB`tiled-1.0.3/examples/sticker-knight/map/platformBase1.png000066400000000000000000000173761315121121300233470ustar00rootroot00000000000000PNG  IHDR` pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F)IDATxlǿkcmb_\{ "B9 :DIO5:W#AIT:Hti IITh M9) jHS#H@ X6j?=^{1xgl#Y؛̾}_\iY`2~_})2U>˕-0d)&D_ہH'YgȾ' AR[K`IW^9"c`ÍmB=p.%}Lm,,&΃ېO"vlHMA̻S.(|u`{/sSv%bJWZ @E1A~tX)6R;ri3, ĴS+Ѷ (n4T}e; Eu=)mÂ/ #ЭFq⳻n \}lCڸN{X8:\`$,Ӕ--X!/[. ]7tk_nU#1) ]i,64l}gj@c7{EYpӨbMQC^>)[=7cţi,-$* ~f z+e_BGŅB穪#Y}*]*}~f] $-عJt(z27XeeCN --x&"}w{UW%[jgη$<`sTtxEќOYTsҤuZ̊bT99Vm[1۫,wŷ2֒}k\$rؿjiˆ06 e l輽Jo*P,rq~>a-J1g(J?Ŋ+&zE@7-zqnccދ#x&+"Uac!%^ɠ۞ a(r,Kb̏ӯˁq[@gw/!<>[OBEQbv?nkpπjR%!kY/{tXS',?Cs/GIzRȂ*';-Q7E'p:>,\]9=绳Tek"X"y ()j!;?W,t:r[1HVڽ|l.*'N@}{T\eA] ,౹l<ˁ=팳5YrX釿0V<ʼnszxđ2x۷"-rþ+‡`{gĢÂ7R\Z:sMx|ɤ=Na5aT/'Â.{5Z3)CSnܻ:_Ya Z’m ,?ɉFS/9UVdwqX0>Zb,  m*d#Û5YbpC`uIaJq9:eE%MrGimXn/nU'kIYK7ǕM%Jx,'$'(p(6KwĄj/p3|uפٞ~hX0Y&fnxbWèŊ#8}ު*?5h~:_Pw:Dxqm[Rx|*:˰cBo^.fIfYyMi-is*[m-c,pW)7J'DQ,*Iakϊ9Q\(WAOuIˑlNr;RF!/:(*9O•h+]RVzω[(w+9JD+U (n|$6˘9X16^YTW/`"IOŜz*[=H fEȾÖ~9MŎ璝('Q,ӯeVk@KZ[ep. @e9 ;ԵOpa؁~|cݐS-3 8u˕7`.*%w"pSi;{MZ+?~U%ۊW>utĉئp,"-L{uRq+妶Ev$>8!hqqvrYt7_9{_)䬫ĬCQ+ onl`}eW3KJ1?&; |\DP8JȌby)'D`$tMՋ#8t'9YHC] -Gغ_k՜\[8-IF ~IeDpH5ӫVΪA{%S$̎JdwrŲcJm?L}O3uߕ"vS͋=.חpXO$VmLYt~8ZM,C^]QU$e}'O>ǶN& Җtpio3v1Bg@nr 7ı`6Z&h5< >99"P7o9G;;NZHclu@8(VOuLxq16 xgoeK ||(HX4?:}Gؾ_ xGgq(h{o=E]ٹ& V<}CO&W(o1ee+|>MuW:1iV%v>n>9if>wI4ۻPndxb_q\/3`)"v~g>C\L(^CmjfGn'"WZVʙ!?H;OD[=3u[t}s}Ԕ/#,6G:qb?Q߱ DyPvLJVO~g?[,[(ۖ[2'A5f+dm(O5NT٩zf*pFv+̴uFO`#]FlEOфg~ź-d L@Lv,ADu.f+J:eźW =0%y$ab2vpP$S 9d A@-ਗ਼ij$   H    H   {6>ALA_٤?"9D-ӂdn}j{3Ps ^eNj6c'G|K/wqkDQuhڜCѸjw;J]%.ټpHHKO7~/ٸC3U97 zTzO _ TMse+ٳ9`Uf^i+pҎqPFTMNGfW]9:e;I劯h(-pee/x).oxԄi{܄6Wf7Xf R?-MB}L c0M`cP&n#<&Ob~7=w@EJ`L"c* 3z\}u.+Vw`mwJb@ٱ Nԃ yLDz 3 7hq>|< 63 1 q>],ox9P0#14Yn9?S"Շt%` _8i r} 68_s@KgurE$--+=h v&Aܸccœ&r Ю@);ʩ?f f.'  H    H    H    H    H    H  " D(4e!IENDB`tiled-1.0.3/examples/sticker-knight/map/platformBase2.png000066400000000000000000000173611315121121300233420ustar00rootroot00000000000000PNG  IHDR` pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx{lTW~ǿ1wg1yBH 9]mWM#%lJ%tS"U,J!۰mUZ*[6lb%%]d <ƃ1mff;q眹3w<3}$ˌѝs~< C5 (_\z՘ݷZp?<>AVuY?\E&!2g-D,XIyPG°-$C_)\Ԛx?F<19CCFN>ˈUtZb?wq<#"ٜUhy7gcwm`vBE]yO];BdCo = ߑsmRUb.5-h0;;ݮpg9:.].(O^ {'8vGs>s`9W3O <;r` \>y ucBa fd{8/ǿх>sgP3V3f6 b |50[PPR#NjW s;+ʁ@AN'Ѝ4]|luv``pP9-| l}-;~x^DNdgP}'%Ӫ#1Wd啙&&;{[Ŝ3gk/ NaV۰v>=\P4mo~8o{U!-m_aǷm>s%ߊRIR6+|E`+)ꯐla{3/\ Ƴ6t ,ز4gxY>kLkM K$@ýYF·pv4dс{zz~;vtM$sh\M/-M px8=Ѧ" MF::H6Ӏ=uph U\ pʟ:cE-*M9-2Z0;~7xՑ0G#&Pg%mil>Yo815iԑ0mó"lնPBׄ`4ךH"A-ԙ8vX7~Tr m$JM5 D Vyq>Ye|E@?ݍ ^K_7wTD.ޥ5"D3>9m*^U׿A<Ԓ]RfgK6 IZ\_l2S;8w')c0-{6z6kjEv,[IbA0 ~5p9* l@ I5&qu "Aa*hSuz3^`{P(tDSg#6 ~G9!M@+P0u%|oKD]q`ԗȼd=ћ0,q`ɜ#':~{cKD#g#хm3 `# e?c6ЏVKKgVT3o%#s3n ULX0|2z7X?[&0'M>#QL5 ~T6vGWEN#SdtK2Q0zZkYY]6)XJ0ܱs?sLEԲ^R>z"Zk2+xXE3?x&O`a{3\Vqlo ^̨ Y5Th˵rqF"`*Ef3*iY-̂L&šm6\֜z]u%/ 3gY9I׮_hrNe;wW&$1EKptq`W),PqRkxXŴ 6.rjU@o$82Do"CQ6pr!>_'a"O-GPG\r?cmY"^M&so-P6vc^!~m0`!Elg",s\Ewr#`vv4WF.Nh"p`Uzg9l ~Nٱ8M1Gp)*к8-uvMdɦLٰUX3;?.)DZkC/lhKmTz߻7~@1egw=dXw6w6r9vnTLK#^kV ~~r}+4$5~>,󋄊q hXиke/k veJ>[|~ˮBu)-,M6[e?sLbgmulWR@)ZC*o(Qb?|^.*7֋_ߢU;WI) L@LnA_z<"oao;WkA&q7zlij "GϧK@0_ģ:I<p/"ʝWODpaBxCI\Ԯ#b@ A<8:E49{6FxtaF8+ %[{FK/08FBq*wH"o2WcC E/>  RN\ΎnrX;_,G o(}m/-ߡXW&!XC10gg%E?4.UUUk׆XS+漽@>UjSQM"3[\qܝZ9*8EG.cqFo8ahoS@gE2>lUA=> },,]˓WpiFU߸|G[o`$}QXr1"sܭ5v-,{~گ(lvNhN3`[7ܶcQ1O*RmBs@ck}+/];lzk8'U\ʹiK _FY] 6ZR ~h?ݴMDVqo_n lX ǣs7K9SmYm|p*c+x+\tcr]vZSUٙKa%#Wz=Lۺn {Ey7 t_clkvK1[~ū'U2@$z(sVF$D9&-{ Q @r7WO8K3J0e kI鮮"#~0G H%Q^]UAA@ A$AA@ A$AA#>LDpY7Ӕ,ԢR=K_wGp +o(_Zʙ{QmwԒ%~ͨ6.zabЗX/K+س 1@{2Zj,`'z ;d 9+ τ' /~߂Kć:mxy4&.= M IM*ld{3uK]~SxI `s g?ᲈT:gp7Meuzt]*X۷R"@߫R Jl$] >3A$3xnڢ~>"p<+̽ pL[S`D}+RrH!x'(~'lQ_ k엡NY|0F@JWsmx$uP,2aC~ob6wj ssp/] @jVyxtvpl0o۝J>oWH&& *t;0AA@ A$AA@ A$AA@ A$AA@ A$AA@ A$AA@Ĝq_kzIENDB`tiled-1.0.3/examples/sticker-knight/map/platformBase3.png000066400000000000000000000135651315121121300233450ustar00rootroot00000000000000PNG  IHDR` pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F IDATx]l\ݬݵ-NIma%cQBpT<)AUEV/%KTH!}AU*5!Ї jը rEr$NIkd'[K~xwowO⻑w3sqGS0Q&!],.iR>3~7CW˿lrN?Wlս)\hֻK>w}HOXs"p 뗛3Ɂa:":A 7sUW!]?h [_soHOShQwFfci҉<4}2F0d,mk Rwl7݇m;ʳ%@\cuAutdp ܆hj>u48#d"Gt"o.XT3~loDFI4%W&;@g+D!>t;Φ`pvn* O| v~UFkGMU <^ؗ[coSu~mѹv#(b{GC#N 3m}c6.N>=N@3`p6tY|g]չi|grC5HMY}/~hek+zu [XL編$Uf2h\k\?s[/3cj)Xb58jN_WDϏDҌ$f/$:pYZT:E= sNֈg}=+G@ai=S1л2Z\Ț  lNK$r-1QzS3ǂ!YHH}޿u_Q FVw"3>jG޸w#M(+b6Bc޸œ$~LGPwn<;QӀ|(^ǘ}a}:G()n1A|2׆I;.F$P GMGj> (Ǟ}xۀ  H0r5D?+sDJ'g #G#>Ml`.!'wDzJPV*Y'{zLx>#cE ,,jj/+ M~%Ods1SKGDz1x6Lw_]-V.~TiVl֒b2i%Wy0|x*^=$cdK1)Gx[ħK~\|>h]N~eǀ`;NKD{_H͘@ #6I cQdv̤4>Ds}P |'.վ΄.j܀[H˜¹vCy{wx7>YfafF e7>z l촮~[N7*8^r92=X41N4>~p[?̘Ϟhh,h&vs&MO)@1~.AP/M :}[cJq4yi /ˍr;˔IWS0X wS0Mt7BskegwoS|w/.?|^u_OCR6h[ٶ`^sSىelwƵq;*`DF s7:wm#>^><;\~(P׺=,C D*Nڭش^`p껻c}g%\Lx~nn ]u=T@u&n|%ŵNC:ev=s'؎S!1r` /WN#7s/O"zZ6+s+7Ќֺ%(Nj|t|6//@^e,y4>uB(u:OG̙f(z,kqh6SlHGʹ/!qق_"^ң#b]w.iAAX&^8}Cu݋^a `,8~͍[age=UZW: 0Vhn]KS SAD ' "jbLEHd DT$=|##u8ɾÒCP w#xv񒉌;,р T6GcgI4 KՎ_ҟ"FDh@DvC`n 9vhIIDa:C@Td9{Y 'f3WJY~m6;/0W[n/NV~;% W[dG Qhscg+T2GC#l2lW3事҃:N]/j~r <}YÞ;;؜&؝Dzr3Ԓ-4 dsvbNc;5=o珼y.s4Oo|wm]7*SqO;pXĠ8-˜ Mm޽NБ?|iɫ6Y䠆ރz/3ف&NG=[eif#xx?O"6؟0)l/*(6_l[ 5 0`#6ȯwx*pW?gufO*%|3 Yo+tƯUbIܦ* 7Hjs^}e`2&U`ZECUz%hȤLO:HK=2R*.!%$ K%7쐪R%(װ;G-}(!@HQ9DbŌBշ)t`5Qh6`Nͺ{>)+4uK,9v5mP'1Sra ۀ   "    "    "    "    "    " UyJrIENDB`tiled-1.0.3/examples/sticker-knight/map/platformBase4.png000066400000000000000000000135431315121121300233420ustar00rootroot00000000000000PNG  IHDR` pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F IDATx_lS?v&vb'XĤ^Ta TT[/ֽhZMھ*/Z :UkN KQh KB䏓8gqŸPE}{gc ~v`?%;zv/q=?p.5i?17o)4?9l=8< ~i'aO ?) gx8v~퀮 0grra26F<Y\r˸7V6Nj]ZQZH>C0F3ZQ# ʹ=Cks>5ϴ9%ZpN 6͝hg6oh?gLIj'a3oph,;iٸ _Eē1׿Hõt룗\k@2l$ >>ȐuY֚hYk7qk>R_#r~LfTzΈ>ێ{?h;j-dRsX֚gVM[R18|l~0ڝݗU7yBcUuM\nh>\/ߦpfs&=G)Hg\c\8-GxX3*wU_VxR}p~!?{pͱr{'!=0GkW?$#D#6ARUb&L$c4AMGS쿘դ- ό6gm]iae;F?ZԋzeAUf>Xjw|j.*kSі2gBP#d&-= ~w@ ~ۦ׹lّ5j.M9}+.NMD>z[϶O-,Ϯws/;ً͓sSϐ\T-pʝX"C}BXDcSY+,t\9 x}lJl%mw;I$4V5Q^`-;>8{)17GZp7Cobwg/9=EY`'Wt_"L𤷅YxKl%h>JNE=ϗv1@O3M4jܯnݡ@tʶWr֮@ h֣R-UM9k)3o,J?D5]d.!TΓē2o UӢycY%wS>zx2F-UvaTGu2Ш1lmm!wPֈu!W]/R\ךm Թg"6)aQRPjwm.UTHF A=L1:!0V'.J?ϡchPdSOJ4 DpC3nZh@P ͡q}рj<2r "AP48|L /3' Ķ"+͊-  EL2Tbk6y:j@"(1w ,֢%'sֿ1]A *Bu,V1Ϳrk* Mu}UڄGHy_CSߍ;d#x2`|O_(ԝN%ޡ7y'|D/'m;3+בe@ [𝮏^ZVnF x2ƿZ/M U$ o vx2m^6Eo0g=[{EwZ.l:-mxXjg6B,ysmZY6ރ8eyKNj+ԡLƨ|lj5A{i` 98 3gq. )N@PpxI߀al ؟v-鶟^6)4:Nhq5M;y!SL*޴ 1ߧtyDst(9K"PB .O9Ar Al[3g&!7؁)1OC~όnz}51{FWGI *<Ο/<`@E< v?m;[-r}X'@ /Ut"0#JF$w@g-mKP 40<#`A}w:b1`rQ%@J t}2ighZvmsss&:    "    "    "    "    "   BN|jIIENDB`tiled-1.0.3/examples/sticker-knight/map/platformBlock1.png000066400000000000000000000103101315121121300235040ustar00rootroot00000000000000PNG  IHDR`zzI pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx?LWǿ+[K "U6lш)ϒI&+Bu!YQTSj.D`giNȑ\81 k}?2' )%FqQÔ8Aq.iǦ _ ֹUOgq.Wo }&@bBC((2ہD*++HK.!gbeD2m֡I'`fuu]:{o7yo ]#a7. >cDhކPB PB PB PB PBeVvM<2/R pHkgX#Q*SϰF튱68aVRc=?jɇ.|X2҂歧)C`gчĤ 3gv+A\jq|-.*-]FZ2V=CA`sAz+i<3Q*h | O /Xְ>-^wU?eD#m?7tQ7-욮;pY$ O ɴkg~+)@7Ryׯ9T/-<31atZpɴþbi2iʪlw]*-X +-P.`@} NK[  ] >{[L~^=-FC>Eՙ$YW]#@*+/kBcև}^[0C +5 lf@)bջ& @(9Xػ$IE ۭ|Azk,Hea: attH`DG ))7{q ! H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx=LgaIk 2(RSSl,L,eA4K*UTX%,tSR˲#!4G}q3ɗ? {~s} Àd*%[T,ժ@Zd*5`L` lLbERZTd*u _ 'CX@FT!Rjj/[ @a}:¤hD]5RlZlԀ[ |G,&kWYr{D% @( @( @( @( @J`P4Xkb֦/jb9Pj`JBE3 ,@ײ1 _͇o{؝C [O۸;)"v:X)6Geaܿ|gp #ꪁzbBF~:#9OU3Kal=mcৣ"6cX vwJן2nTUgJ G:21ࢥ{k ¤[cC\obw 71·Z/vv5 pQFs 7 K܄dVU&%tu՝i!7 Awҳ8TkdAiFes2HcKdo \o8˫~D|rȎA8k;ʊOx1O!)83oQ:, kE3P>1 eEGDGݪh220$]ltPz{cJd0ABz3I\|H_يGdbQ3؃8#~ 'C~B@x ( @( @( @( ( TsKc.qvøVo\Y~?)r&e p(F t?vGu{_l+xIv/|z\eYmu¤>Hf3GeoFQ6׽ ? 07 5-"xYdf`_ >7!{GNb?91l}[wN3 ?31o_BY]=80X\ZiNWWqPw0 IFLcfQ'md2@ #'@]5Ȉ}"k@ <퓲չ0AY-{/͇w\42;P4k=And!ROy$7SLS~|#_3[X& YK^ 0 qί,~2Z@sVvN(fϬzcsG>2 HRΑ> ;+VnZ/?o^%IENDB`tiled-1.0.3/examples/sticker-knight/map/platformBlock3.png000066400000000000000000000103231315121121300235120ustar00rootroot00000000000000PNG  IHDR`zzI pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx읽kgǿkP_Rd.ZbE^vrF/Щ[S)dTbZ\E"J])\{p'Ū-%u}'Y,=/zu$ r 2eH^xft0\piispq G6K9+%\CH +qX?pgիYWƜr/V` 1k^~ f4?3Za"ȅNHxSsWJ4f @ PB PB PB PB \^D-O8DGptU@.)@1jXÙ`ra%)&AKjE 0 ^H2LK.݁ [B.!T t/(IHz1A-ne JCp ˥[.npZ ; toV6ۂkv!T(16 )rq ~l@ +wv ^5M&G$!ۂU@Jv )@ i%X ܎ (@80w6aB*-LZi bFsên#qkinݟ; \Lu8-LAIB.zCս-^U}*`eH ˰*S=װ<$5K*$!UO9DDpי=}pv zxz.jf#pƫ0 0P @fmvZ:\4>\X 'S 0!܎N`ې!$18-Α_[Pd VLk,7"+ zٍ1}mc&@j(je^(`  @( @( @( v+܎ ]'[֫ 8- v 8M3)ƊtHPQ+oϜ,:Te4﨑ڪUeZ u pAE5 (Iofpjޛ-B͂n@8!%J7*5Lpi\W!58W(I \S2+.؍z0cs[=6D5͍p_0 '<\ /q,& Vq?k6%gwG>+ W(<ph E>|~{~YMk6/h7z=3#IENDB`tiled-1.0.3/examples/sticker-knight/map/platformBlock4.png000066400000000000000000000075341315121121300235250ustar00rootroot00000000000000PNG  IHDR`zzI pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx읱j1 ꤈w$9ÜmaL`b0-S>BLy8Lt R?'ne;#H$2ѕuLshFp8b1Hi0 0@@@@@(;\#1lDY0%b"8jB*ÃVuV3f >lDr1HOKI/2}ۚrҙol;;)ϘM[Y|5ݛPf4(@p-mWLCǔoZB{S&Q2k%J&l. !@ҽ YFPN TT M͡<sڇ։G S?ESƀ%c:ɵSJuDF =p&@ (ANBg`5\iw)G{[:yCg@l;> 29̭<6*A_<;݂ zF$0jSF7@@@@S1*,Rm_;Vr]fg?4jxT0p_{'|l]ɂf &}}?.xPwiPK][Fԏroӗ>EALX1< $3}~~~o ks"clgn`Atʥ1^=ko*=Edv:IENDB`tiled-1.0.3/examples/sticker-knight/map/platformConnector1.png000066400000000000000000000065201315121121300244140ustar00rootroot00000000000000PNG  IHDR`@4r pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F{IDATx1k1pA@Q{Os 3[nZ1b-sc΢pk/'%<#3<#3<#3<#3<#3<#3<#pW.3xُ!(cjZDVq/"xr H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FuIDATx?k@@BmYj@/Jdtx=tNc0dn] .lY~cZkV&螔E !R?zĀPy4qdm> Λjld A4c/˓C++ssZ$I!}Kyx[_va6jRJeE{ mv@Rz: `+:.: `#t޾{mUelu/7UZl@<9Ԥ9 0|"wL!䛝AX) |ԉprn$ah*!ضJi<@@`1)'D6ZnJa@](kQyV)}gsޓDwyɪx"*?q{8="'" !%ѷDR7YL:kiEFDNmjtu{b/d@(A;b||.=ۯ|Kr Ϟ}dG @@@@@@ܔdIENDB`tiled-1.0.3/examples/sticker-knight/map/platformConnector3.png000066400000000000000000000065161315121121300244230ustar00rootroot00000000000000PNG  IHDR`@4r pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FyIDATxۿj[1p@q.nnq͔/2d[ 2z,h@,]KTܩص hZ13OYx;_DzTuc!PQXg 6˝7o"0tc-;^=6@hHlQDc#l pxy[@,J+~,$F@b$F@b$F@b$F@b$F@b$F@blڝZ͚xګE6Kxe:7lF;y~6x"r$Ua@䆈N#k t2͡m|m#TF{=8>@ ŵڝHpxykK6c i%D&ӤGE& >~zgϣoRp>EX>zaޝV$ ?Z97U",ę97b)3_ȷ.ϰ]]dPjѰd4?pG圫JhۏgiQ0WUnCDO1ldA@@@@@$B~ ;S3IENDB`tiled-1.0.3/examples/sticker-knight/map/platformConnector4.png000066400000000000000000000065271315121121300244260ustar00rootroot00000000000000PNG  IHDR`@4r pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx?k@pAS!6 MQ%.$!nŋKCOP9//Pڭ/vTvd#x{gbf+I\{RKt/Xѓ@oJM`*t836x]m&ܪ#HI `Y_\Fq>Zn#$p-+o0LVmD{YZ }&0..&"I)~1od!DӾ`RS>Ȥ6`9R|q@'|:)/.h5- sЁ5 ZD:hQB0mRx;)} `Yg nM޵)C/7Xc[ĥV!-m{ч|̍;QiBxDdwȗR6BxRw.CE]N*n]57tUJJWfZV PT{bO줺#qQ_m۩oIflI)wEM[TYO      A~ tkIENDB`tiled-1.0.3/examples/sticker-knight/map/pushBlock1.png000066400000000000000000000173271315121121300226560ustar00rootroot00000000000000PNG  IHDR``w8 pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxygu=ҮVdɲeLR E(BJ# G%P&$@UPI@)`/lYmIZ3=}weɒV+ivH*iW>Xz%M/BXϑXٽvY~@"c B I+hXLˢǟS,As4.bAxactk%[EgٰmTF!I\k5 :Ptv`s_B †O3_"4 GUڑ)L1?̗0[gby?8cݏr^kSV*{ưh(*T1 9%S'Ma,A4_z/5jVÔ =6e>#_ۉ|4c'6?Ae(B}̣%)~R6}Fܢv@!-[ځmC&j~kO -5B BgAE;GNr~c-yFڢib}nrѯUR|[ ] ?$9-ڟ1p#f~9Ñt_ۉ7REI5Z;êUo~tDT[俱QξcQvm~ts` SHnRUnΩ| ~ha?1PYaPi1TM)nQ(3}g}*>rk҂dGi v}-G !zHe[u0c'@T>'.ߐ -W+~AkLmZF u e/ENy4nZ%b߶Q}zX>R PDWt6IsBK\=7iֶKnY!nXCВ؍J9-ǫ =ܘM5WtKayPJ\!ݣ u'Bv#)z4@|]i(>%#![5ځq۩~1J%@ r E ٗc$]{nҼz"]$CE(Wi/q ?9LL%\)[0I*Gh6_AioK4P|hprIɳ웆NFЍNL/ɸ_xMfC<'3%Hl# A}^?QS HhNhha Ur7.Gg]LgrL(.wgF#!Y Q;vJ,- .k,y6.KK!ǫ)j''f;'??+^wF|ohT\"5)Ah_Laxv0nux:8LjX)‘BH 22CLIA6!,O :${RӜSԆ_[4ߤG˟Ж ~oh5C:/ZMe(_F"I=8>]U(yfIU68jL( t YW+{=!hՒ**Ulh>2udd,cUˡ_~hZ=4oFӓ ,ֵKNTR?NuDV[(^FQi=sN5m P80NsL}K\uޫ5s5h)u|1}g?&0l|Xqf`K9ttD'nPL\Βrar}7kj/[#.C:T l<6d)[B!X|6% bu˂&xFM?R H [z$YG0%fN_xɆ=#@֍Iڎ<3횵9E.ΚrZඥK!kL&s_wSfhϚ'2k v,w >xC+_5XeHk_ݪ%ޕГL-&-5\ulh {',N;U'ŨL=J_f%^5E!U'oݢyb /]isW :pt;`̥_5UY4%nUbbbbbbbbbbbbbb̎w8ɢ,s$<'wS$Ts dZχ=Wɦ% *JBΉ3@A/8LԣG&SR]!7-$a%mBc13c;g= ,~[zvCo4t ȸ#X&I+4+s+7fa=Zpr\sCmÓ!&CRJx$$ HZ&"o+[š,H h8TnLBoFoL5,ֶK>~'4Xga/T}Sc]cVWv 0)hځ'G,#oi(߂'aHJhBjciFF,+LaJDP (,0SЙHqqoE|J_ 98ixEgra{BIʭ=3R@ey脡; wa4$ E ZBR ^ȔBrI?eEC͇cӆIY0 ш2ԛS$-kj'G by[B 6u Z™kfF'(4,rs}i-<{'8Rp3^ȹU@i8^ᰱ]єggzγkť5vB Zo^@+qpX=`S˒"\60 9Riw%kr,i NoH!zt㕀䣷t`hZ‰jTӰ:iwe/HYPh.,I)Ve5"l4$=ci'F=] H^ƏZ&8ʞyy@it'%+zѽ^`:X!v\r6zsצ/I|(>㍐ )YcSBPlNT"pن$Xk2GJ(btF2|Z~8P#nM:I緗0T ksD4Q/Ro ZdГVljw“ɠ-)X݅VdJ?<(^qI'޽5Q/;YcjKR ,/_wytp,Q`,!թFL&3-ٰ۵,6$FǗ% Ôg 焵ߨ5&ɜ,qun`jMd׶ j L\j‚ElN-wN];nDIENDB`tiled-1.0.3/examples/sticker-knight/map/pushBlock2.png000066400000000000000000000156761315121121300226640ustar00rootroot00000000000000PNG  IHDR``w8 pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxeǛqd0NwWUkt웢PFEQY–CH5@eHB>" :,~TﳜyΣ羣羣g]!ZѺL+ZwiR(յR{xT0ǵFiMT7&q(I̒K+Vje3kzG꧂ь`2hmlMEdGKכ%̒|D+ծw"hC aޘT!Ҙh?4nrN+dylChzLC&bəy AdIB AhvܝH0i,t&bF^K!(`biET7x=ݘ=Nr>Xr^W| +9yȣxoX!NL$I5½ch^kS/7p-OAC07ހ0M1cʃ{F! IedY.Иi`Yx %UBc{nU8lÐ,ǻV EX1x|yKꍜ ⯺FlϮCob܏s;Yc[#X'/#oLsԡ-!_9t>k^;wAoF faUٴb A?FzsfQ[CA=_u0e`^5@#HGw8x=ނדQHo "O^S1th^r SFc!u m/l (&DSĪt5=ض/YTF`;#(ĪϣT&cuoCYނ:7|R~6-oO|fl9IR/h'$C26)#C%QOx= Vv_8V=X#'^}h&0ɀ^XN#%cF1i#<+oXxí?J=-=?T-oT# p #4Y{#l8fעPruΐ gQX=~2_݁RsZePh&Sg`O.\\/aʛ;f*.m{%sp Z5Bz;D$Vsė0^Cꓹj'dT4j/.W޼ [ZLSPyPa4S~~VΑ1r')CRsȆd)#X\`j(:KlO{N3J<b$1~}~`4#H6f&T6.i}ھxFO%_(!7zCxq)sv"缂iB8Mpn98Ovq]˘"KዷI˅.琺}@Jֈ6L•d4Y46u7ݍ6):yAъ^ނ$$4ȺƖa(W:@ :KvI=a 铱"dJE; RyzCǩ-?%hx{'#Ī.i5d,Rb&z?㐌B梷[q RxK?3tQ#D]N3˰(1Lܭ؃'ׂ!FGa1BoW&JE-5sIՃhƯ:0vhHN2bzВwƿ qPd)=J(- mU%VǽbΗCbUad4Dm@Ϩ?L!v]1^9_\]iMzAZG>6o*V݁bA481">,' pOp/O>1?gB#RzЊHg6Z,#h1 %^JK)HhS(jW:ylQAtV:Ɇ6ńbV",nToA͆XՈ;ހjSa1Ņ,aX*: *=թKJHH(  ]P*N^D:9NTѬnL3ꟹNUuVZ.ң7$o %׿D/!8]K[*D{›-MQ|f~fobs ᵇn+Js ):lTKג0† V}ocKD2̯ ^ڄ!(֒>=9xN5h 0Q#8"їp*;R}ؿ`{t *w:sZ o.C(2 mZ6_ZpnE;$#ٛ؃1wlGMp-oRĶRބS,\^V̺:ң.2fYz{pw\ s7Ż7v^74'ҞEG/.OJ2fA2'`7IM :j wxo;K_@/(9FRW'u1HNWjݒ H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxoy|\D-bK$GRj[gq14I\h{P_Ћ"E/m8v'[eD(-^ Iț̑(ZH$}λG|_͹,U+Ki%Q ֱY@ - cyFk]X\\^a09cW> dOtbֿ]x7_7m@$:]+*RXis<+ ը-,aav$IP:!XG;8c :V}o_4LS<3?̬L~˒6y# Үr- osr =N4wh \Y<0y&WHh_*yZpN33a ݅1 ixvM|;WqCOA%m FzREAA/u}zqt_^}%ctkKO l2L1cS fw3WB} yWA%QaKiUh >V,7I!%0ҊT?QJYjs; F3ius8i%:1)LTBR F>ݩ~7luRm[; B1=@m.MI A5mГ[5CS,6 @A%\,@MtB1=`vRmƭc~"դ4Rq2n}jiOc4Xn}<ED5)V-,`KlF >{ǶYA40B>N-q~&xAiKi6? Ps-EODT`3T#V%kG1þQ^qZԤR%!eӛ)86ZkZLod ӕIV•Gg(r^ oӌH!0 -_rVq2Mq&~1݅} PtȌHgCm(Ն Rva9\Vpm2I{z>Rcq&'Ybvg^ƍ|q{t=zv;*V>9BM%\`ۆ2 (¤cy.ӃRn.۩2% f5%Y/PVlo?p;(Bd%\"ď`In# 7C9\nN!=d`XnHTo {GVn ~іjn'H!YlUHc ká}#Cϓ4:ՁV)^p*p_c\]+בBPn.&{rs(˭GʌNU6/386|]۳]]a$7J_jɕu;R̴Q$:!R .)(f9>3I/a ;>՘zv4_!RH=|w A|!Z坹G#/QT),3C'OMcK2 Q1ù]ʏ"6R}$22M-Q(97{{)XEtS1%QpR}4, y2SN&10~$:a\/OL Y놈T6Bwߖ= ;|9EG:t!C@:t!C@:tuxѭ{h|\%LZ0>籥-v 7k_7HT #]..ez:{џXϞ¦Tg>gyd<7CaKeԻHY $.0Fv},\r[||wK 7aD³=,^Wgyn^'f퀬'znB>ScГCbankk\3A75Z(#T2\]H9,cK!yy'ͩO⛮:dt끽rC]D*z`d\蠗fҠԩGUBQߢV+T\:e=A" JB=;oVgȌ<1[B hXҢUh& N8}5~3KQD'lJu9)'ťw(7e1jLԢ RHn !eԺrU`!Fr?\m{W !߭T4WGyO9\F餭mK Ht^~Jy7u~l>ʬDZ=!pR8a%,^:5u6Fs|1Fr{S[ʬjH#'>Hwл-fMkz iO*dW~/{Z¿Pm4="}l3gn!Uܖʍ6& ZUiE:gg ~'EYZb $Zm0Qg ZEI#xG֪5H)~Њbzx,K$&p(!j fZ%eg4{(6(C#ް6XUHq,3H$T-cGx>DAJ)ʍհQj1`F5m>bZ{$RI>n{$, ϱPĮ'xNSNs/hu{Cu[3s?`u\ni g|eC=$4/)f+SJ tiled-1.0.3/examples/sticker-knight/map/sandbox2.tmx000066400000000000000000000453301315121121300224020ustar00rootroot00000000000000 tiled-1.0.3/examples/sticker-knight/map/shadow.png000066400000000000000000000425101315121121300221200ustar00rootroot00000000000000PNG  IHDR@@% pHYs.#.#x?v OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-:>iTXtXML:com.adobe.xmp Adobe Photoshop CC 2015.5 (Macintosh) 2016-11-08T09:51:04-07:00 2016-11-10T07:55:17-07:00 2016-11-10T07:55:17-07:00 image/png 3 sRGB IEC61966-2.1 xmp.iid:f9f10874-a23e-4b6a-a58c-1f0164d87eab adobe:docid:photoshop:17a3edeb-e7e4-1179-95fc-c4d575c47509 xmp.did:edadc86d-a4ce-4c33-95d9-ddb3625585ac created xmp.iid:edadc86d-a4ce-4c33-95d9-ddb3625585ac 2016-11-08T09:51:04-07:00 Adobe Photoshop CC 2015.5 (Macintosh) saved xmp.iid:f9f10874-a23e-4b6a-a58c-1f0164d87eab 2016-11-10T07:55:17-07:00 Adobe Photoshop CC 2015.5 (Macintosh) / 1 3000000/10000 3000000/10000 2 1 64 64 y cHRMz%u0`:o_F)IDATx  Omn0@2 'IENDB`tiled-1.0.3/examples/sticker-knight/map/shieldStroked.png000066400000000000000000000121421315121121300234350ustar00rootroot00000000000000PNG  IHDR]]qj pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F IDATxkW֮%Wj:#)MK#Qp{ Q z)8ЋJ CR>tQٛ1zOӃֳ+i۟Z+>߼yV`Z!@,@,@,@L$^^B)ݧ)o(uVeJiVnM{藗aJ~?!oJBHo3ЄW?&7Яe>xB.(e7ЯҔW4Bv3~lwJv&scaBzЧɻ$N)n;DD( 4Meժ5 h6} *mUNEYX*LC!v?bFEKV7 a9Q:lK(J ̂w,ܽ0GbeB{|d7(X]Pm*t&eamE *]o'1xɘ~qk,@RjGۅ  DJSZ5 ~bMmw/'C°B_.h zj\ŖNR/*'wS)13Y"l#hn F(ǡ_^^Et\eF0'3ݻ1T cϠ$C%ip@ Aܘ?.W(tBȎ3I~IM 'w4E"Bȅ/xQ ~-tTZ6k9Ut/՛>@+=ոz\XZTnGGG#M?C??C A 7K7QU;3zNʊp㏙̜n,imw:o#T,T<+Ƨ u%EBgn 3fv8   fM;V b/ۜ=C!8XVA?s7wAu (b >=tѝ縜ʴ@ڎ#*m^oMXكrHF2R6tl"VQgŸyGPt$/ꂊ%fo9*,1N@cTIYߣjX:{R #%Jۅ>6XVU3Ov9ϥy۞Yx]9\הAmE`[Ih4[Ѝ,bu6t'χB8 _mY[yqmZ J-m(e'1ƾX n͛%'#cOU&Bo?tQY1Q<~ܦtpo ZOzՍԈDOV uCgpo{tt3c:`x@7#-z1iz=tVQmBӟ=D._?5//_~᝼xR[,Łs|݉2ǽn#e#q:NE4 9q:^wFV驈 /?=gsgqey 'r/?DshIaK)[q`;xIxχBmϩ&F‹^庱͢4kr-'@@z^]YDYwH)k_N݉z=X1ܬH O7k, %fi*ױ/u ڨ n^ q@:ZpȢb] ObpG(]Q ^@yQ >I/O;ѡ3v2v7+~~~WYH !dg",-o";t\*d.8ڟv.C;?CǕ*+LFqt/96;%Wܜ^n),xzrHtK1~?{ ^bDΑG~.Ent䞟#YTEӵq8XHpBȅ'yit:3f@p3 ɘvӗaxZ~3brt9x0#V#/zxTJx罘tܽPQ tێ[ Bb$)`L agb\{u' !;Һ #y^> "{nkTFVg={ފo @,@,@\FH(IENDB`tiled-1.0.3/examples/sticker-knight/map/sign.png000066400000000000000000000123301315121121300215700ustar00rootroot00000000000000PNG  IHDRcb pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F IDATx_l[Wǿ^u(N$v?SV&)C 4E6P)HIQiC !x2fa566uھ؉8ssswRJ^( H$ H( !P@B( P@B B $ H$ H( !P@B( ,j(3ߧ(7g-˻0nVTu':S01v-eB9m Hl\@`g0tpKa)$r6 ]T u]:>N_BO&f ;J$t{<#AB ha >lSPп$M׋-$LP@P {)HJH( B Ĩl9u~NB`$@¾}T5 4W`M7cK`('4T"TCش֏/Aq8L&mdU׭i TU! !Ѯ%,ʏCk7_w{<#G, R3#6%-z{M^Cui~S׻-Df(n V@ i0JZR"uVH}H'R\'{In~?L>U}VVeq+eWi&F,B>. "a 0B&E#appM+Ç_p8@tAu[>tޑk,zu .i }xekؔ| zHHm.aqq}4Modq+$pz>1|өz$˯iZO͊OQ״N:z#sGDO+Qx$j[G ^;a˩/4OM+&]@UI8}f߉T,a-R- |` DáPP4=4fkHyÍ|37k)&ܝK7{1. czs,n}XAbƧ1}ICpp/nt Aui Xwc)<I|,Τ1t&?EOX raɫSGm{z m-`:\Ay.'wI<5uGr,"WZtAZ`,dNE^y1ؕrKXZN쪯=|'Ӷi5$, /H羊Bj"QNa翣}1T,N=xpeLi[C{ާ>RpGRjPui9, bݬ1|1̍0S@|%p$eiĢQR@H*,+DŽPM 4mnYVH)r[P>H9lj0-(LB;a%bCKF'tӚaѥr.5@l: XgfרɡZoT:ܮAUgOߔ*2| xH7 l[NB 7p;%UGnl}w5:`XpN4 lvBLF,c>v_Rd?xasO 5luշ8Lgt@a)poRmW%uKIC׏6J>˯L&%ɷkM#╔ݮVn ե}p@r2>oyyvFjbSTl)?nf-Rpٶ6)Z+oIdpw/WQ G$ %0S@R-8`֥<~+KS-H&U<<_JF-[EL$wKF+2{3> Dܾ}JI)G} H*If XC~{#o# $ H( !P@B( P@B 1UB$ H$ H( !P@B( P@lbSN5ȭ[~~(iL(@aփ h| uqIENDB`tiled-1.0.3/examples/sticker-knight/map/skeleton.png000066400000000000000000000631711315121121300224650ustar00rootroot00000000000000PNG  IHDR" pHYs.#.#x?v OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-;iTXtXML:com.adobe.xmp Adobe Photoshop CC 2015.5 (Macintosh) 2016-11-11T08:58:25-07:00 2016-11-11T08:58:25-07:00 2016-11-11T08:58:25-07:00 xmp.iid:a6b9dd89-a978-4108-a32a-10975ba5e246 adobe:docid:photoshop:13015530-e8b6-1179-904a-d28adfbcb124 xmp.did:65c47d9f-c305-41c2-92dc-65c39c98d7d1 created xmp.iid:65c47d9f-c305-41c2-92dc-65c39c98d7d1 2016-11-11T08:58:25-07:00 Adobe Photoshop CC 2015.5 (Macintosh) saved xmp.iid:a6b9dd89-a978-4108-a32a-10975ba5e246 2016-11-11T08:58:25-07:00 Adobe Photoshop CC 2015.5 (Macintosh) / uuid:E0EF0446F9A5E611ADBF8EE6BAAF5053 3 sRGB IEC61966-2.1 image/png 1 3000000/10000 3000000/10000 2 1 133 160 K,9" cHRMz%u0`:o_F IDATx]Lm a@ZWf wl銒UEJEJ.kKFM6RZQJ[ONGk]HDk$ Hox@Mi1p`_6G/yE | @r\0 A?'%RE <'x {)R$?!biMNH](*./'44)P J]q %PqV]egM" 7OHdb6;B,ˢ ^|ttWUU۷c=JDNgR(ZvVvz;v ꔒD3>WR^/E_309(2¤ˇ);8L12BfݳGWDkR?*P]OP*yR.](w=')q?b@ QB!x^0Z;Qe/pnt SQ{ X$2~@ qjB5sV@[{;张r7RH| e)!L E YS/D t: YT5!-Ɂ*T )w1*#Qb` v=MՈ؝"aA\Xb =jI"E|`fn%bl]r6O 7HR. !ߕȤ" .kH`P)Ah x{Ė"Ed\)MH"6GG&H .+^3>+ /p˴) ^֦Uh"Z_o_ؐ!ͭ>KoOIB\1y@LKo㣫}a^qD|t5%)RH[X#փMR1@xgs1SSHpOTz: g1hJz N"vhd?bJmjVw೑4\e5swc_ò,ľjdjH@_ wH~7΄;RF 卟`hNd0Fr3i`rh~a 壝t4hp]=xP{@#x-E8!$c4'!YB(,7xt*[Gǀ:,f%IqVo2b g[x7eDmWj(Y^>@sx?0#hQ/,I@hN²,i)_ui }@Kl$tT>V-^;-U=ZjW@.R+b-oAlYmҩ Xnnӧ&&)H!v444೯K %5>j`6)kIG!cTBiliǹwc*%)$v!J{έfLRR "Dx ϟIR;{, .ˏX~;Xɓ8y/ HHRTbd䚚 F'?_UB c}վO>u%-yYi(Ԅ(eg0]U pm2-`4):?2,(.WtL7/g04hҥj$_MMMj!8l0`9'Eq9wV|ܗoׁpvODjٲZeڊcuuRϣy8cjBv` KkVMDj thR jKRaw'![vzpgl;2,E] :^\/WFԿ# e鎧T\< mSu~7Cl Hwߖg;6EtE' ![ަE Pdx8&yR"{l0V &*wCiI Nv]jGu R@CH\WgQLYICKu&]>0ĺ);_uS+ùatm۷&G0;`vM$m-A[[)")`o[{;ZZZVJ.ŴQ)Iǽ,\3!\-uH&\CAmG[R1:l>OWFm]]hFFAţ^/ZZ[bUd(UeLTĿ804 DlER  9:8JiZ"R}2jS}t` ^\}IE87!ZZ[C\$ʂ嘘 ԞXgĀ]C 6BQnڊm;h|4!wSq$6U_oVG  xB1!XτbHøb XVZL[y|BF }cWP]Z~uBWU2e vGyB Mp~%ULSt+f%!`t!%W̑z)_GiwF"D-)Dch*"E}}=&0e{K$f]"qʗqeð8f>T^ 5{tс BTAiRRX!7IX&䨲Mv=G4A%3gG΁WXݶ}qE[FRDLPHkoR@3)!юl&]>x Q˘pt_ rtI`9 gfH̔\˃ݑB.0I0\1^"Rh0EP;\0ŹP&\w0u= FH8 ߨug`~q'gheyYQQ=8%D(#@Q3r0us(!dMHt:C$}Ϙߜ]?8(N]7"ɦҁ-d %;z?Q>/)%\ƈVq@U!X| K ҃Ԉ˭PJ I2Y'z?֒H"cl}MAt[c+;ᡧCt*$ "D#b;&pSQCkbd ~7F7o#]9wl$OKB=^ JbRH RZRC03n~Iߜ܂g_EIp Y,G I)A6 Llr)Q1D1Z&. >SV!J俿Ú6"3_DIy-T* .mv .H-،0Zańa,L}9J<IQ%I%.=XK ,ό-;IdǕfF&22UK~))^PcL3%_f]6 7vfؒ]\Ƅ)΅;Ȫ\7?EQ>^Q/ntPH񜜔 )JW[K%ǡt/IF2GUH)e`1mŀfnECO' ). [zKф{1]UQ&%Iaʎ"xYaT !QS$9C H !\0qPB(!F, &e;o"SPAE0)JX`t ]>3?a.ùUȹ^AH.)jCDF&|pnlʂæ,-d3 ,k -5k2֔ wr. c1m& n ߍrp 3#S Hr|K$4T/5n_ax.X5m~=.jXQD( )+K!D""b)a R'FLY(D>HXDψ&["@a<)&j7WI N7#c# }3xͰ,WS q(Ȫjt G_MwE>> V|cGFŽV*W%4SKHR54E铤%ZLW32S "KtQ[~HdKN ]To; ?r ]EO2l$ N1>IK[eGC]!;7ej.(ڍXëXVh`Bf3N'B &ϖ{waSx9w+|gQ ՔBdju4ryϛc0R^axJ2د"ixAqcQgE]` ڰqjPz:~Dh)?$QO}P.nN7&mQUgz7hko"E !ş!w}LaVg,\x SSM3:ꎺ:1)!b)]|&]>\qd)/v={{3095X"% >IO$)FE@\.x!5,&) H$!=bK)HwfyuB"o8> ^,Gmm-V+]CY1C!F `lƁ?4 HLHsH)աv'$H$rnN]`JoN$X|:FM-\Na1/DرcZ@ݓ/ˑx7&!3@rǜ&0A2>xχ([<./%i1؄xjL"~<1_ U?G$QRb738 +"J[Ԗ Rb{J1&}lUjPXX(Ep;QMy tvveٸuWD{n1Wo5x,7`Kd<0]WzKutT@(u߃DM!F+AcOՑgp}s ~Jö5JD`ɓػga˧h;l60-F4& 6Ci8A9 ϞLx2m:d 'F˂ĀIP[uxўy!ȡ U |:I& ?dLYd ~ 1! .m|cDkLB5v>AFSQpOh/]EE FNIfz|mQxZMT4!~7zn_=6’BT7z^VB F.KCUɹwTKTDM6o C$D"P_},W%]Q Xx9<Z%،c]}dAHL3VMi/Hzt hoTu beOoi(xZ>[#ȒlzD ˡI3t upvƮU˘P. nN`lƁ FFڨi@dMK#$z477^}c=LY9DFJU7փ Z }Fκ'r IȆ 0BsNGGYWFlpq|TU%A3UUVGh5qM(@_} dUU8|\СCk#ȯců_Q\ ^=ڃ2y*RIl<~GyW 7t]]p:p] }c=ð(!8L1͹11s{El$]\f?{N])( {pq.X$@YV0Z}c=pơvFW/((B466,ˢ v;HvV LY*%Dg,am ͖ljJ>j:OE߯;v, vpvnnAZJQdA:ij3"lƱcVXXZ/F|-dQ𺆅 ~%jOPUUx^,K5L6Rh6p`tdd闃:0[8\X*hTR<8QG~[~=/$o'. E>K9AӐ;؛U…<, #!VKR0bw@P+~/I=/ȋBu>5I!:2< M꾥"E )R"E )R*J| (LmH"rR|d0ZbH~%1P@b)VM;#KiuШkV>~JEf/ 1r`J.|)Ra܊ `EAE[{;j巟O^5+g khhPHS> }KEVpC|Fp>(ePd(Ũ.N׍Xb}T@4ùCrRՅ8}Z.%;)9J]VcERh\gFui zpeeO;vO.IUi]53Z;QeGX;7nӧoퟺ M_қ[)C8\~&]>^/~T/[\ H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx읱K#Y?/0r\`ibm$p` ۉ;V--E`sa6N75fd2oL}k6&DD/klh4+@р`۶z-h7I~D ܜXJ Wv[wbaAwdk{G^,,x^y"fӈF`t&#/_ťlՃ] ~ťh0lծb/P߰m~T,+ch&T H)߭Y0$@H觟,P=:wxGx xGǾA R-ݧa)D]DI~@ZNN뷒?;b oAs~q}t;3/`B"O~ЇxCsmp~eҦK!k|. 'ul֫niAݖ5lz8Ah6?h: ({)Vnj52qV"@:YfCI0bCڶ-JE,˲R08DIe_ı)o1D3qD@럅((q5J0Y1gkDqG)6ʥ7裸G:Vn{s.oic)jqt&vcsW{z:n"iXTV)>BHR9GS$8μ_w!3y6-A 8(2Fԫl}3=l!@X#WmR."5I&kv{&nL 'kwMmtyCTěiJ^jz0c[ Hh>L8& 8 H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx۱kTIug~V 1*xJ x `!R^qե R8K -RXsE2/7ͼ6Y|_μyHkN @(v?qOSbP(6ͳ )b~>36;wB} sbcwr,@FDq|v/ig=_\ݻltd>d% 1'׻dTK|zpxx ;@鲱g  o2~uWb'3~t,0?xR=bKv%.C9\b W'׻IDV%~ RXpu\b wlݯt\L+/~L,@F,/By]"I!~%H ?dy>CEb, H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx{ip\וw}Ko W"pH $@P H=lٖ=#O 73[̿x ?XwQr-Ⱬ}Ĵ1 :`E!bY]3|̲ nG@]xʞ/Fic5ZO"7k1D$|"{|' QR7n3AJp@౔T@@|(700fZl): y "Z[IkM@uBkŊu'L&S`"NDUrCGeiwV8N4en LŎ5he2*WG|ߏaf8CJm-S! R:N"R2^SDY7>oDR"?XV[5:##Tc,⪪ꑑ˩TҤf0x>HTDl (rcKk 0o#b-0"b)0q#\>WT61AVR)1W,gv@YĘ=dUU<*=acL Rd2<੅vmwv]7\YYpQ7&Eq&7f!@NRqfNMʶ*.&&&~ʲ^]r1O1ƚ4$qw@p8L&lr˒B> ^FDD: 1ї-˪o.񋀥T\DD0L L(tRDd$2J Zædk↑|-1hv ƒ<>dQ]S˗.5 zZ^P3i2eYLb~2>|ʲÈ,r?Z~ǩdT*2QJm-xޖX,"g@(,` FIteJt8ßo=MTD;W&8 U01?f2ƌDcSvٳM+ҥKŋHKysqo,5X2>%`Nƻヒ=/Pw:ӭl5ɠQJ9mJ^Q؈, m7ЏU`GxW9P( T ļybmhZVMHRK3lYO<yܚٕܽs'֭[M6u}+`$ wRLM9HJ(x^d``˗7aX~=,KA)/~i Q3=ai7WTT̙A"3 @b#Bn8\?0QW6CWw7x&ׇћ7]QtesJ0L[q+L: f< yj3ط?XB>t\םWhRJH,maCacpQ8 #'@r<K_O*a "A) k֬AWW7|_"Dk%):fL<1yO*Ķm011Kӻ Jcm:(d Ѷ1f M}la.jDw}FV돖 "Nٱ˗/3}Ūի|7(J%f1wG" S!"uݪkyV,_'NL[7n˲+*Z1&Ry&yޡK➡!qx~{hllBώ21\D*DĚIϳ/˭ؾ};6k No^lloNXH@(DY~ubӦMX~} &u<0SCMm >&y&Sxm;^xT6hY%ٕ5;:нu+L-J<ح'N&9Vªeh mCzܶeK,ylޭP(*"J ADl|TVVޞ3F"8y}C0CgJ8ca;IOTa:?~|uhmmի^AƜ:#D(tww$z{L& =JI,ŠPEE:P(4硶v N:|>"TN鳲3 H0so.^܌={|æNlݲ \nyZc̡q˲J71sg:{EGGA(¶mQ]] ]b\v6*I)y73G H]pQAc"Rc.=1t}BB4$"T >=iu6,kl6f+R!f(HEKK˜sr94]==`"HXWFDX)`Phknn͛db"amK <,= `uؘn> Ȟ_~ϟWxW+/@cop?"D$/_o#UY}I1p$')_SSGɯ {4sWUܽ55580<|( 5-ukTJDpnx{12²Oc8 PNG Ġo6lقuJJ013Ck|>V܉7޸Td: E %&+q^б|r*eۋ~c\r>sqt۬yHkCww7RڥKo:G~%> OR˲\yKI2"fEsaT*x B)KATq|ѷQJuӫ6mڄNfF.åKqTDسg^yo믯kf4G1cys&,k;;woy(MJ& >3"] 3>'Oަ|Zѱqc>Duׇ>,|,DMf\UUtaH"Hg|G2 R$1 ;S)T1&Q~XeDY7nb[g>.Nj -wt:xxmǙ9TsBcɒ%صk`래@_^465+"hŭwv!GDg15ؾ}gbbtz=c B0D$<`ض2TT"8:z{{4nZ}uu>b>QBWZ.Xxg8q%urJTTDK/}Ǐţ~曨F@O| B1=3h 3oIg2:>Q,]t|rC2l˲DQg`pfZHRƓONE&} @`֌   硵؎3QWE EF3fh%+x 3D==XP(ڵke3}lJyu.jwN9Am̽P̣m`!ܪ{&\:޹|95y }\3+`-L'xstn rscrJt/x#ǰ?~AA*qvb}j g}-yȶmljo O?%8{ ,˚!MDXf oێ\&pmɃ(%@u MMMOkeY_ (S.vJ냁@5scv#* - +ގAy TUUŚRmP計4>40s.E[k+97"ɠw'zzzq RLcljh6#a`^,YDt&AOO/v m y/pJY8rfQeY)J0Q(pQ`;{DpuBBƍma,K̟PJ6 'D2036`lZ#\dZzݻ} tww^"=F''L殮igv9v蜙֝<n}+RJ=,"ug#c"Z'ñX _3<.mdV+$l?ye'IS5|2Nڹ_\b)͌+VWxPND.R2]9 sӳp ϲ`)m#,456P;[Ū]7xW^MX6DiRJ  SOaY ؞5uRp]@`Vq]PD/?8oDDED,+F7 bhh%P"B>Dž p] L.,^{^0(Ik!V[flݺu z/^D!+DtJDtRb1\"1';s>F&3~*5,mO̬Y|M+E52y+ )@>Mduz, DߚƓ*͞ݔ \˜U~,NM^Z뽃y!s"EE3\s33R "7|٤}#fb 5ʹoAWg gɄlIENDB`tiled-1.0.3/examples/sticker-knight/map/wallDecor1.png000066400000000000000000000124331315121121300226310ustar00rootroot00000000000000PNG  IHDR`zzI pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F FIDATx]l1dѪͰ U0M_QH Ej`NRTAr>i J!MC1&TJ-04 qZ `5Zicsg=kgg׻/w홹ssΜsF1 OI I ID ?VeUB@\8dtǫ9b+9"iBA<2tb( , ^dvB*X}>wQ;4"ΧF~o*2`[XaB}yF Nt "$@ u o7N‰$k"RVf/|`%G*anwX)`'I< XꐷSN3jZ$@w[o~ ( eL I ^D1n! t=*X$|Q58IoŠ1غ)*w.+>fiT5XLۥH=&@z#Km{'ߘt_޹MQUӐ$\!%Ę·P̫5tTմF)Vj2K۰,7xm'h>I X!]{v`wmoC`UW'V[S[Mma4ֻoAԮ5WnfL`FpiߔOGƥdJ6j%MzT~;CLTM;D=YƑK GWaϬ 4 7TOZuQ4;1tIմ /$Ʈݬ.*i#01UӰ`8 %yc79^]R .ؠ2- Vܩ |bϷVn77-/V8;q(pm- ,2 ہvQrTb]ef-K2$$$1s?@m'#, \7E?}987{h!^~?n*װCzDWgπĈ)| 1G> X?ꕘ%\i'*Tiڱg&3t]KifwL;ba E@Q^QZB3o?ĝ ߔZ".rI6&sE [Yֺ<(EoW5-ȃ9CIܚ$dv:p)"@rх`쩚95zyb^%txxeڋg Zu|BcX~cn6\8(% vQdb)eSe3Zy][':(.~u|l[9o @g$ɝ8!A1]^`k?#>l >>[Z ~.|ip; OմxLIdWqBHAUMbֹwyɗ]>Ǜ]IuBwR¯|(T->#*[V.RxtwTmA LoNkhGsI78VNp[ɟ,ciN)sb9b s?֓ߐ:_,,4@axzy.p,BT%k`3t]Rjad$H/39t ~'zyx"톔0! f#轭0fڃÊ= *N\!@L׾#w1^ ?Ē·?:JY1]T5_i[/ ̣ H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F QIDATx]l%Yw5.se>D) "RSD5jK /i0CK<Ъ%hCU)ncHmdmmU.,чY_/^̽Ϝs3L&B«@@A@A@&/=O/&DX'_!2 Ft}9b{ "&D@ 8VYCF^`DףЀŖm!IV4xYQ3q?T+vS#(&7&_>i]H`84S&`e,i$}3JeБ:0p ;3{McSNVU&ǀIFi 62CSQQU *ALGuk~5za)r\p#bh۰2)uZe+F;0Gk,j(\,Da+ӄ`f_+G77UBK/%L>:SEߞ38\he=mz>a}tty@#Y`K!l[) P|TU>&n`6c$csfO@u-zajnDvJ|d,ѹ$צRI2 $X..DdaeaSm^jq~:^v-w#+>ClzƿVu;`c~YxQ59v~':&o&߀:pac0]sҥRN7p.dPU(((((((((((((((O p6`$n_#g(T;F♼O Q0iXVꈧf[8y6aPȈ&D#UQWB3V4'3ǿhx2C'ɔ >\ +v']9xζndAQ3CcYK4G?0wKW%Z< ۰li"/r8)>2i56S*[u sfeP즰k)X1  g+v1NkW@A YwIENDB`tiled-1.0.3/examples/sticker-knight/map/wallDecor3.png000066400000000000000000000103511315121121300226300ustar00rootroot00000000000000PNG  IHDRcb pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxOrfnp "qNOr;' -FY10R U?,38h&ύ[TA74 Q"+)qpdR Q  хSǧKjM=0r,RxbXM$H LGu=o$5Mdkp0&ݑ؅|d^.1@@@@@@@@@@@@@@@@@@8.0zovN щè[2'U+tu)g}Npbwr<ᄂKI}ϿXؕLtWMik?pǾW=[>guIvo1\RˏoU2<9cIW|yFʒ.}u:){ӑQm;^Qlco1;n0:Erk[ǚ9m=ֱVoHC;>Ѿ4},$P-\{5;/Ӻ5U"দ_K($}o>}pw _1^aſ˳*j1_RMMcgUgZ$\8CqY"&_`ZDּ8|ԏm6(v+e%3ǃ"tc˒do\B篭W3 S|b()ށiJ't<06"3{( (?! IENDB`tiled-1.0.3/examples/sticker-knight/map/window1.png000066400000000000000000000021561315121121300222250ustar00rootroot00000000000000PNG  IHDRA@EIDATx훿ASޙK9 E%`46`!WyXX b ZX{"bc!r`%.yٗ7ɚM|$;y3lRi{+JA5Ƽ#Aϭzi{(_[9S33asȶXc1ǰns]2|NѽkjBB^?nnTq6<0n؍*~j% U~~\P0z?[.X&X=ggg 5O]x;[co >ʌox<whY ;4%=WyW9cgy_^%rŰ?w_W Jܬ$!>0:,i{2:ȭuẋyxH~vXpR={.SlS$\rH|+Y*A_w~}5VOҡc]iSXHy J=6 ` qCAzhZr=ZbטQCXG^uCB0( FB|\L3K OJjR5!tCODJc̸ @~ZRƦoXɘqBp'yS-ڹr( w;L7A:-ȩ*T$S 6ķ$=^|Q!jͤg <ɸT!!5G1$N6X.ÕTgtb%IY_r){3J=}/A/c$}]/)E7ޏdBuxXA!x~*</P+nBP A!(BP A!(BP A!( De ~aLkBeS=&4]1aZD!(pc|s@8u!LЍ\{?Oѹl-tEXtSoftwareby.blooddy.crypto.image.PNG24EncoderIENDB`tiled-1.0.3/examples/sticker-knight/map/window2.png000066400000000000000000000021651315121121300222260ustar00rootroot00000000000000PNG  IHDR@@iqIDATxAkQ = ۆy5R[$AK-FEPP $PxAbыS_/P[O 0yli'0lvgv 322rT*B۶fo׌18+vh>cccGGG ̆B;0tco+ : 1XsuLTFVnc5|^a ;psDчˋTi SQ(y0Ϙ5xڀ;@vj+#|Oߴ"\Bt[4}H^2Rko:Af!Ew#=;9B8'Jq oqNB_X6<{&tn”EBԭI qqA 1x<9pp?}fsp((A}mr$N]J$+F]iBH$}PO 4C0bO5 ;_%pW'Zub3ȟ4-rpAi@L/7[L` WZw"iH15Lih(WcKwqnM?jw<|q5K-"'|(DžBT? 0*LYYiR:oFK7>o{.Qw&`+յ JXJ_%Jǭn57k9,tw?$[1#/>s)J}^ً6y  @ ?$=B Tt 7/<1Qyf1Zzk(S]1'ugR;uQKLI.4Rp(n//eSw}{P @(P @(P @(R{z[Wegtz0+gHt-`59)ƍ^?<5r-tEXtSoftwareby.blooddy.crypto.image.PNG24EncoderIENDB`tiled-1.0.3/examples/sticker-knight/map/window3.png000066400000000000000000000013511315121121300222230ustar00rootroot00000000000000PNG  IHDR8;.IwIDATxq0 ٠O8#0BG#tF`Fe,# #ĝGH=J]?]׽}vkͫ1xl\,vi0{3 kA !́ 'P=ZZ-AoP9 &jƝGm9~vy?_Uf1N+.vњ=|j!౜cxBnK\ED2t9@Je+:B.eTFB0J(*rʩ@rkn OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F(IDATx_/z|>ƦqpAsVrAi'Z5EB PzT7\T J? X␢iL4%9`H.}>Z3߽{nm}?3f̚53}>_:e˖-[i~3w'Zol[=c`3we.'~oɿnd{ޞw׏Q˳h7>x~Wؾ߶xCն}}NmguKu}{Fng[]_x\M^6/۾!hn;X?nwn|6YW=V֭e=>,WXOקTپUϿ8~cuH={~wiXholOw{^ {Fݷ=t껷uƏjߠq3}&oتcX:͌K|7le긝ʿ;_C#3zٳzЍ73e7^=C ||?Xi\}\l.'csaD/f眉.[lhojWl˖-[}9c^D>O :k}ngtZsuNp0ߓ߫gAaǮs{\Pmu8}Y@^V; N%uKvo<tIlRN ܃u tRܷ v.oW61&oru.sucL*23goge_XSI׬?`_ փv]/w%|NzRŶdnlru[߽n`=鵫3m#G}~& @ȬNF|g0Iڶxu}uq&[_#8I]qt]̸wb8&L)PƕZngcU]XՅcowcw%p;#8Sq~ouw ,v@`;(Ƚ ;O+4/%nbv5>81=@*LDX~˖-[1mZ>&XlٲeCȜ?(M9m\R:c$2r\BI\@ zjE];ΙL &Jcu"DML` 6$qNb3ISJeTYZ1FvCn⦛D&&Aes2`Y왭 ,ÕM0@u[t}c1v/qǰaj"ctP^gRǽ1*8dzm w׫ r݁"980@j[dP4w;{F;Qq9u6w R2~7u[=c Qu'/tcVN^}s1D@YqFǂ8Xa ()(JdEò 0E3gWXFA{{8Ka bqq˻`pƌ XAU~A:Oieٲe>۷0 V,[lٲq8SJNd\0W,,nrǴ%#ڿcaAШN>eL4@T 8ícAn"Hiټ@*˂,˨@w|rzQVR3 J(V4L *+M˰ E,6:q w8 fvXvr lau+˶:T6 d T@dSEwǾPWAu`}x+ $&Yf6K)s4{R hV!ݻF{Ěba plWI}1V2d,c}7r߈s22x89)'c{BJ߸.@-w c0Qn쨎EeXA1(T`1Ձ $RIho2pK,s)r5.AM4Fk>-9e˖}&ot{ڶ.hlL-[lًCi:M.ぱ(V9DGcaa92t*p$h0‚",؂AaTut] j56"Ⱦ:4c CXdepɆu=f" ^ %F4P&NjD@(8IX2ŶB[e˖-[6m +g1 r.I,GɜM+g;@̈c}ց $0 a4,`4Ye0Mb(WJ @Q Jq Qy\k aȂ[2%/ca׀`~s3C)ĽC?1)n$YfUX7 ' pxSjI):0 `XR܆9qt%~DB/sXˉOIXӁԳaDwc6X"z(% @"xaq`u8y+ZGcXI˜u Q|,`6Ql*u@Fe˖}V}$,][lٲeƀ]yGɶuN9]8L;1v\ò  P11ȄvT7lNs٤,K*T)݄e򉌍*#]&!;c,QU=cn}&}v({#Z#uu' $+;XI;^$A2KGcn7;XRVM@pMcd6Y@`eor+6PN صl(u(c@c"A6z`kS@xm tΟtנHI}gg.=L{}tIo}YIt@oڈ%Lj[$3Scñ)1xSc]~3VfȨ/#c=K/Tel}Nk:b!N2X$&Ț(+*褮8P>R39ŶI,rfe˖}oOmI|Ķ&˖-[Ŝhvs9:8~xyImUuX n0vw.UZX@EU uԲn2?ыmθs*xY5%?ޛGqZ+vU;ԩLޱ ˉS[iM͕#ee2I>{]{#(Pìceo$(0}+sN#L0:w%!qR B\%:Tmɀ¤javF9h{=sࢴo.)(8/n1V!u:M9Z1,Qlj+7^:Lq&x e,Q0)d;du+кj}YQ;6|~G1;= aX9̏)ȤcC 5$O$ZNXH$Iq1DX]]]<;ulBald(Nke˖-loiK>r[e˖-[686NK9^tU[vGݱ̴22$5,04mBXe) X*r%5DM(+Pf`hvwZJ+ fv$}|G5z$3N6\@(u;I&lR܍ TM!@aMw1.$ R:خeVf!`&Sd ;'u .?۞-ӒE'ED][]Fv Ye=N18k[`ٹ3pc\a,3*FַdQgϫ$4a}{XD}w~u2oo&qi®Kתoע P¾?Lt$gYn-&mW;iGv~@'ܦAVJc&OD=wj_*,L|ԗC \|F1útw JV39.1ɱ֞ ˱g2=kv4yDQW; ˂Ǹdvv&I (SSA$܎Fl@,0v'O2CS Je 3MW)vڍS3%I0u;)PeyyסlWo2eIz9+Ipoۆ,'#pW~gbRmݷRN "!Ys+R6 `nz5Wn뉒ܙ}@6&U@g56uKP_u ucqqav `dI $1peV1@t1Jǘ* 8e˖o_䓱0YlٲeӖ2{TґcY @* ep5C_A&9Dǎ4|0tU4ݵwf IfmʛMcd"Y1`SeʼUI1? nu̻Lσ,P,_u]Jrd@6SjNQ~|VԥdXY&\qmYIta잫>#1nrdnՄȔ(撺MMлs`#LzGdyX[eϧF/=>$#H1FsV6fTRU(I2Zmjw3P'bR3*UpK@N4& x8ıcc_b(1@GS:㓲g#kI;D5Ug~nq61#%Nb&,9k㖻c,N7a%ht5cIv,؝ e˖}H۷}I|&˖-[l1CG+˩_u1k3U2& HЫ@+ 2aƂ/Iu(fYɌNxoWR\P}wK0fimc?zw(1 "@ Xg@Lm6u*挺Νk,u(KŲU&(vl|wTLkrH33>D`Ԉ(vDZFtP$#?I" _}W?:U=:ɳ}G'ѽ= 9HǿmՍYž0𗎋S~sȨg+q<*PH'2nP;DmW̊ }ƛZTDɻvc_ ?He q*'R\1K &$R?N}ULpD2KcIn5G@%#N<9ֲe˖Op]MlٲeRq9N  BPu2J3h/πNFD,NA0s0PQ2\̟W'asەfڇU@$alHem} ,RO?>ohv`݇; an[ɴ>5ϲ$AFYMX,|Z8a由['QM㎹#(9bW7`Ս.ŏFc+> KSgJF1PG1}ɲe^=O߾,0Ylٲe4qOcAf^9x. uԱSNg1+ N` >I'MiA%,[ 9KdҨNñg29l$;tV+c!aO}J e}!j?bQ %2,6oWdy)fQ@ˤ@`HPd4;&%u$rXFƿZF߻ +p8 dt8\)At[ÕE &0u \$ahF[7*atߌ:od7{ZE'% g{1Eul ~3j7&r8eP%_4 L4xiUc(&qIal$ QXn|iM*^-x ;9?'+yd#qϧcrn,F|\pŚ2v)lrI<+YdVF_v(.3@əxKe˖D%-ɲe˖-r29[jP %DJXq2qY\,9  5XƜ$v9ai;6pu(i.X*ئNua0=? >XN w r@–1XH(DQ+=zLÿӎWLiv4wF3|z>mR 72_1`?NIc&6I_H:9O*sb@XBt[C@=  ?rG 4@,idj\;>g~\s'K`/D``P|H$c XiDG2v> eQu6rO7&,"N"/m8NflgǽhȤmL$Lr^@'?1[*Iǖ|[.pe:_vkz@I"C]]BDF VefdG]mPIܰb(q n.)Joz-[[IXuغ˖-[lȱcsGI9l,*Ge?(:)C&ޢ}\Αwe$!NXX 1ດqW*SKIƗ10v 3³a$Sf`pDr'|PbytvY-lO&9 gYubЈvi 'SdEw:I{`:+XBTֳ:̽+ nB8 g, Ρ@nL;uet 7Rl#L1N ,VPR05#ݏ/[vtן320id~O%ρJ0{3x+%ɒ352l&#(þJ®w+e ? {ԍ1\c2VezRNrޙ߭}n?ws*_rgFl>\F.*b [䂑 Vŀ\I9ium\k@Hı*qcU#[ e˖.[8-ɲe˖-{pbX"q"N).厣MI h8 $бu`Y.qu+\2jرk ^00 n ^}͂*~_d~vaM2A%SDɴtٛ5027I Ts@(}Qv3S lgt4~c(Iڍt{1Rֱ5t)Pr2LI[IyƸmsٱ\8CejP6 tR8@ǩ0싪aF ( \9gTyնY>7ouIoe56vq&>ΎG$/@`5q/r^X2-8> .Շa[m/X+! ٘]K[Mq8,X;V&;b6xJBK`Rv.WRѶɸc+ؖZOj\d:IҞĺle˖-s%y,[l2X3΀,Ʋrڰ,r9M&l(rA}N/Ww LUAPf|AuCϭ(} f2 \F#|kRKYQ( l~IVQ;u,4oK' N5|cɦ`92{i9޼;Ee0;6vjYvP*ANݲ5t啬Ml}KAwM 2+NS8Fb]ۈՅ G}VeU@=)0'Q@lQ `w5 (P J!_&URFAlt_.0&3$Uߕ_NnTM0+ l ߍ|\+Ͳ1zs/*`*Q2g8C0u{0:߃>(Kd,9TIEq:٘\=ұ෢؃*),!7aۓ|\Oʦˎ1daIg] %wTlblNcIq,[ebVOl_Mlٲe uAA$*[[i90`}0u'*d=+e˸9@:@dZQeX3F;fz锻.iH xςXOT@i+s{OEVwn9`ϑ{IUܷWVu2OMI QչLyWGdxN;ل>c)H!s;{xd]+P +ʭ8HwN؎,bPCIc*൰G%'_·1vP@lӮTW,'깺8[OR7c8b8x.ET;~[Ͼ&q|LA j 5mcT՟$X$c1gÎj|'ϩMֈ JaT8t<5r{X#`_ O:0&^پJrJX ;>0.Y yLP)Yҙ ,&Lկb#lb1YluoOe>N[e˖-[FŁD T Țq0?[uNb:l9Ov‚*18 :]ʀFKjIܸoct݊iDpw~3[#3 2 $[/.ea=TۻI%e˲2if+I7.=x!>n-1mxuRIM 1Pb.ayیO&.+E'2t |;%R۔16U ́8ZNϛtR4s-8PD= @2㞯h\HΒ9 ]G\?rAT0X4*&|;nL Dd<1%V'4R_4 @ю б XAg$#ѿaɻ>ۯJc~cSI2`f/Q1ܮ(,R'rIFl?\4JuhqY`Flj lzXr['%-e˖]gKgw}˖-[9VqA'9,̱c~9u.C 8qRTeFstYPAeA-Fvxl4'Y@OC c1q9gc!邯$ea=*_ͻKϵo%oeԐǬMJIM( 6Qq]-[%`V&V ϡˮ=,evұ^X>P!E1a8'tE00Y$l$tΉbn5$;ǿ (Z. aCH@$6U acA6~_W˲}d$( 9vAV'}l6Rzw2 8vY ;$wk] <2Ӌgn|wy踓6D&Kڰaylk*:@gtK(Ɖ+ X3uv0!A$ P1r]9_g h~%=ظR}W{_u%X<8N'y + ;щ>suo1ıcQ}ݸ"DO9: 9w121q'X8&n<:Q|'& YJj'i'$akڮFs˄ Fx(G܃ȹcbbQעk h6Z1H`28NuyET|;]vF˖-$K'.-le˖-MCRTsq:zHe0Lc3k?ͰjSqCq *8`I>l/U.ceO=ؤ ad4'?2T HAOeVW6`F}@v< xrΣ2a:¤mg΄b Liv{\ݪ^$O aM9l2ߎiA[M:feV u0p;`O;cHݳD*gHL!5{ pHW )O%o#,+9Wr_DI(׷d,:v{,`o? ol(yjƀ<펡g&#qwغKЪ;0F-:_ivGo*&3|'+_yTg0V(H<;`B݌zll_DHRc.Ꮁ2$!pٲeΎԞےY諬&Xlٲext P` )Jɺ?39`^+<`B­N`˪AzV&Qr7.$~ h8lG =n fr8.ej)Y:kI=; :BU Lgm"mݦ]Rt:Ty6Ȣ2 5T_eAt$Ii #i7VVQֳ b;n/>DGP1Trl!OWllX>dq:y&-aDĽ_5!~W6(%`N;)FOM^^(Fe '7 KXC}Qˀ N6Ucg5fO ǞHYaLHې+5vIgާQISq{:vUsݱ0cayuNFO)sN.52Čg L B[dńv>;%:*9SGdžv_,W1z6-.[l=ݞdGV,[lٲǬng 6OIFu,F} `QW`JQC:4;HtL`a0ǀe#ͳb@t .`eN*$^v+XJm,uL:3sO*d(+Ɠy* 8=rY ԱLt, g `|gDycݤn]+:֕̓tkٺμdbW}wL+sﳞ ALbKdp{$l5l4Ϣk3$ƕ) 66֨c t2nN}Ww8&qL3:>acv/r'c@8nM#w4|$Fd~OuNIXN?W;}_@41D3!#O0a&qf}1>n=-:h2M@*.+vDVN-[ǘOhLYMlٲeu"Sg1QˤveX8m}ìTY(X3XXm:-N C7ncY=p, 130( ;`IqFMȄ!wvꔑ$-@ uZUSg"aq/l>wJNۻF6޼uoەGzewտ{= k;B9#)٠Ee$?Ga?<w2o"08= #ef {NI$̻wbam$x,pMo8o^NP݄*B'|&"c@SYH7J' ,Kpl30?Ntט->'+7I`Tj3SpgVRhx(ccΔ#X  .PX/_ivl&H@b"*Z]X\fQNF%1K;)+?L,߸]eγ3;\&Ougwݚc6d}顛LOgN]3*Mӭgcu^N<'`yu@ܢK M`&`I}M!Way\gOFXK8fv:I,\؏ػA9yqsc%L荎I ip*&B&s,2 Cy ՜yt5vg] t@ƒ|)'?:ߎbuȒ\GВܿ%c7k,&0G'2],Ʊ8 a9Iٌ0(cnXv2xwmXG] &˖-qӒY,[lgn̡q43,&-ɤG5J`4Ie.R2pJ㋁e`QݎF|T`Ve00V;j^|rY:}tr2m)Cm&̲䜣f:ҌNd|v)jB!CLUiΞ 0#$vƗ^d$l r}u &SjR; 6A;#!N܄/dv`5Y&G y6s> ࢫOM:yL0:ϮkMuRnՒB ɹ{a1;}k S2aƤ́Nn$eauY'} q'c55s2C<_ (dd^e~1[]cy>bd;6+Ko+{4ۜgKadKaqlńb>,kG1v8gR)ƞy*ފNQ)rƒ},[L}˗$β[e˖-[6t1QQ9n%AǍ]K#-+:\%yÂ! d*FI `}R~r28yuaE[?ovʹ1PzO75j,[\Ԁ4ݱ4f dWC`&PͳcUVa5?RO\uWo#<嘬rB(K"mo=-e2)6.d m'] 8l!XHj=NǽdʍJtE̢el4. "XGR <䘒IԸYmKu6&Rw8cn餋C.; J$@=Vc#%1WG-Nnbb&?LGB~0y+dq6L)n;d@5 n_ƂʳLJS3ξFc|Dr%&a2:^'`iZ ԰c+qdu$iblno%qއTOVYlٲOܮppd QK2M9ΤpĻn)MMjX]FK!ZXe֔z /c%QU7+5UYWmNQλAbҘLRi7y`*qbEs$8#V,mSMv1`0p,؇tLu=nIG mf1nRHdW]s*3N;ܻP7;zvr8^wl"_Wf[0vg@"j"GZ70L ;r.IqH$z7vߝmJSL0=G͎4(@# P֥_SרcP8 Iam@; grCR };'u$A-Wia:gv嗫:{eLj +JR%zť:s@~QB{LʖH0֨XG*v:+L-mߞےY6C&XlٲOA*jI'0GΉ-si iI=: Ucp;'[+ws̩!3Mn;)̦R63N%LS"zu*YǵG&ܘ&ăriʌԇ( eo$oP (#(Xa<+7K 8+F7Y2&tل<b5l%< d[+XJEI [ Sdd~x<naez_eUQ#HN`āRC뷬ooԙKwϿ;$cvU񝧀v3r?l7$[I TCIir|% Ycm? TXVb3c ʶd]n\0icCϞ{tba ,VGYrq`&M@bqaq"w~.66뱱1˨:b.XKPVG7;g\X>ixN-moiKZW,[l٧kaURN0*Jq%0ÜgYdm $`\sɵ2`Ki#&:gYx<nc|@b3ycN{('Aa'!p] dMN` ĠFkon2IC10&ڞ"޵1?A0ns3@ctvXJ=V!ώM`#6'la˸wQ`y%ޕNt<Hpwe;c3Je\۱krcm]UYQJU a@w).%]n[rZq0Pc:{~)(}?XG)@ GcHKjҚݙօ`؏JVD_vҍ{]ǎ}ȄU! ~[ر:_+KI['Ln>W)=W[pD-L*GIײH@+NF+$qN&\`1ePj]`TL`Jv˖-$q]яV,[l٧k|(￝6rUc1Gr9w!KK8P%,2PT#<`:(pՙh@ vaJeSJ+z_"92j溬90f?PeX;NBdrȗIF.׻:g%;JI1lL@6!Rc}5d{HA$x,&=fe;G'S'91>L?Ifs}00@Q%{Gu` EõUpѾ9OՒc9Z~#a_JyY`v 0K< B'nJK1H:J,Q> ,(uRv#c@B²?3Fi+%eؽ8˶ޓ;)m6pP64Ql*ans[ү6_YW#(Ե2]#*S˨J~&)%]P9bכ0_fМe*) &~]Jzl;I3nbPIvl߻7T[]f`,X`sdMƹM%q6Ih>8:q5bQIX&dD겢W@&ݱTˈgJ̜o'S!jvMWMm/a'&w'#+BZXlt߫量 n&C]U%ͣTxl6zRKro 0 a=gƪm*0 ;OAkR&d]:3c#c)L=#vsqhXYϾٻ{2Ob ZH(tXtB\ŀ-WJ'&9qXS6ղsse{ wD&|1,[ھKg٥&˖-[ C;gi2GI( f@,uBwPVDs(sSFETf` tE eVRq#ר=8v&X`` 9<ڢ첡qЉ "'u*(,4Lk"ިvy~-{&;0H7|v9 LGa:2ֳIl'r4L&/q_?H+9!V\@ L̲$Kt]3=>̘KcA}90I$tcWv9T&oaѐXGS0%LCUF]M}?;^:0&|<v~\j`+1uI }T1u`|%u%/&\Vq&rR,xhi NfX=Nzٹ c}fXu8lƝ-[qmn[vqZMlٲeu"Μ>la;sy];S3g^Qޱ`Gxtj090@WN`2; @ueƐJP[{'ǪgNb^QgunÕX7=_*({*BF>n:(i6Mr,N4Lus,lt2r=8WY&YTI\FЅbrVs1,sƨoD׿Yp\jT|;9W\W҂ l[)Wx񧒀TWRIMܻGo(LK}~&珒NtMl;%zT*9¨8b=`%0DqYv.Ď5dNJcJ[%).f7v˖-{Ͷ$q-ɲe˖}%ځ5 U9 Pѱ(Oz.Ӄ*c4l΃Q&eirN B &z͝2+߱~a"s3;U2a%.˂o4lBM2W{Կlokw1fɌD"`Y5Ye:?s0H]J>jMιIT E]e+J>Q;BI8>ߴ&zfBk ? ŀV> NϪsQ'R&nb}`C}^σI0Ey褈f9qpʏu?~1 Xa@C1;82@q[TI|Կa'8FCp;o5Hɵq~N2&qjە 8U?&0_O̟KY2>@?c?g@*PE>l0@&Sc+N12HR1!w 0zKw3R([L@,.bLxzٲe~[8^dٲe>S%phu&AˁVC`u[9nyG8ZV[f8c)qN>"M+@YI$x 䡂FxYL>v) w ;6`Nw- zz 2;Vy`Il1: D2J满Nꟺ1Z'JjJ:1(9gcXjU t/O1 /uK Lu`dr, !J>'c@Lɲem{=-pɲ0YlٲF 8o d<\tぞGǹ iFP;ԫv9M Ξ}YcsM$8`Ixm` Ij5ɤn^D4Nc?‰r%ǥvZ^B҃~7) ''ab& cʸ+Dw0QFNzj@#s13#=>A-q!g} ϡ*v3'$w 옍ިry\ܧNr'sU$a~$ 0G̎(ub58kk#(Y:Ef2Zz&Q,',# Q} AuX}LtuD`muW=NvR Iuu8:ܤ5E&N_{ `6I4:&dI]zLW#;n7NwKƺd3?_Yh:P#^{ճ>2Q9;$ 6읭^ؕ~3;i-Hޅ);3V`cTR`F}&Cgd)xacj1Ȧꛏ5~ar9^>AKY=m Gt(tl)]wٲem_8޻-ɲe˖}3UE!Ae}UYjǪQ'%T,a65eAc7 N&VYj߷#v=l ㄓspZB|OپdT#9o)# )Tfc88X=Dyz^^TqNs6:^q@ȂJo}>' )SV*ۗj:(%Ůlp`l#rIu 3WH終0v&r9DPN%X:^z0.է$BOQ H8YL\L2$,)8vI*uqH0aRV$5Bp^\e>v[e&XlٲoN3S ]98l$^[@$ٶET(GUO2ǛBcXIoaT]`" `gSx`1 $E@c5a;Zc͝d)ƩIbx7%Ѣ] I|FLETYuewCc%)uL I`}ˣx-|Y)gH[`yd @PV@)Jo=D\20c`ɵ_0(v B?Re#w̽K?ut1U(ؗc-ae^]%&8m.1ɻ:`!4Vw]Kasv  ՍOp;96sDhˮM b׆]?3{VB/ dDRp]Ž[T(+G32:^fb4j?^<(d]lKR,/iqD8{q4UF1@cݪ8gɂg˖-{){+/֒edٲe>I9{ W T04=sԔ眕ʽ)xccc160ixQP d|." ۈoҍ?ACf@~b+AO@.¾xd_DE1?. RP;*օ*ƨ7c8axQq$OEUc$l=q:H\LU,[x.OmI,&˖-[s:Ya`(Q$xХp;5N8:XI9ݎt*ߝ(D{}XF<8 L=b~].mGfjl̺)P8zVRt(zw˲Ne兞OV:7@"EճLz\U˸kQ\8DO։]F1πh9O46[Sx_S8Rɧt}fjMzyʟ9V]{mIy{&ַ;r99-&7(;}wu/~Sl$3J1s$cqb@vGǏN"elFW1721__1VR|9gct|#ɻ?$O)Ibb<7z#*C'lQDųUQ1*U?g'<YTL5Y5.5A1f܁JRII`ٲe'=ݞd0Ylٲb]t?ke(C' @w "E'EߎĝcRa`wz3" đ/`=*Hw&Uw6H4hs26:q͐ nQ38Rͱ^8&uSf 4Wcns@,\d cFXKdhv]&c?QlBбdIvb#g?FJ&aϲS(6EduJI$}dl۷18[2s<]ohܽz?$RCYB18RiS38J[b6P`T~w`jtCcIi[3+rPGp|6x 68oKbR +uDgэLm4:q D h$@WIxL*;`0_)񝐭p< Sr,^T;ݮ,>~5KuܨU u,& qH/u `p6(lL2)NݐDmuhi02Juy]=lrjlR~;\ z%p&= ˮfȲTg&nZNLV/&k61XorpnUer6U﮻wo'TK&|ٛ󯀙\kȽ@RϖbIh}Pkd FZR7\m{-.V^qͱ?6jl 2 O6i9O(ޕW;_ݦ8ay:ɝD(޴l51ױ$W %eaq8,'.@#E%Fјc(&K0NSfѸb֌RCX*TX"ahю EZ;i`lKؒYlL-[ZJU8ROB@)ى:glDPX=u ȣẗG^ZMo'on$6>T%Uṕ|nSI(fuc+zxcmcw+Ò pQNG%:$:c鍲8 ))?y.xHLz唝t2bH ā\ۯeqEգXLP }*(il.gvٲeϿKgk0YlٲWhݠ~DS!HǡG(^2\ P8SԳq>\N"wꂭR+:b%x| mvIZNWGMe/uy׽s WMͲTyT$7jN;Ʉ^^}DQB,Z,#'PB719&6_uD:gXe0M>vYJ&/}@b`/)noc;PG|_`$ 푱D18 v_YԵt׼m=(0 uen2u]jtKP(%V׳Wj{]M&_u|30M'436eHjuV2`!&a7IǷ#.1PwS'Uҩc>᱈q9/dm_K4a~X6%[:^rŊ’0 *8D%?ؘaRԬjɘbƘxŘYa=.Ap,[v˖,[lGd#qx{H4€% UEF QNh HF@G=:ŀfv d+gsa@lqL``e!C:ѮPT01Hr3M[funYe:&+mN 1ќ#XL&dد}euMHmRP $jy\8 P;l` Q_K_=%ԍJ1%̜LqYvy9h I8bp  ڨvǖ3T[+ k'1wϙAظCDIWgD1u cqI\Vz;f& wxO8`F-~ttwJGeq`*)|FS6s5bM&TI}{wpCy9F^7f9>ō&~5p4~ 5ZsRT={s${̼;֔DJYޫ.Pn7뀖 1*_4s;g>n,Xܘu݁HnW#vF.]Ǯ9X>kr2mZ:lP&[;9w *!E@l,371Xc%Q1I՘&5!sI>a`ũFB\W J۸@5w dٲehi: r]}˖-[,cp 1tgŤy:F]@,hp1]2g9KoUGZю1NU'~XauetKL/F2Tvwo\_Qqۣa,i{);{׏qXf׎L##IСU2}sA$*XgwsQ8xW8ɠ~L@r1@*D.H~9u/m8߾o\XbmׁMTͽg%:L}o|/8 j0&Qٰ< _gy2up49==:ͩ.6S7Œj,v,ccwvFVcaE3~aϚA_J*fI_2M:ndb_=wxј'w~~+F.b',jv%%Sσ%@xi1^\Mq = V4NVv`DXl - e]28яYP{FJ`f#ffqKLHWo+ V :|9pDofd^?):p/6a'gWd ($S&,]v+Cf!ܞg6ulXYa}e;nߘWQ%l?%i@sWb$` %%r% !Fa3{ZǖI5F '5oɥc9&]MPR7}in4'1~ǻsDp;cdҍSI7~eOR8v\ ; +r̿Bp F+N1d ws[U e(]`DMȑX*H{KB_Rq._xmDDRFcsg K++5X6K*ĺ]⢋[YeVgK}&˖-[J!HC8}MFۺu0F!ErfR0j$ ,1uSф2gXH*CH6 tA Fb'UFއa&~4XR}gG޳&&3TO!DgfJ3@1HPhg4i3rg/3:ʝ*N+; dCXؾ{%֡2;p̼rW_'dNFc1'E}LJ3MQ!iG\q8{^ԛlo==|83=S˜e꽖1^ocdؒo6tlΎ)L}ofqF-^F;nd]!)c'~b=񦕳b.8X.Y"+dq0J8&v|\VažXj}]\ Uq1)&V̴xKrq-Vs`45+0ȡ7K1S/wOV>>`ٲe^u E}Xu3]L0 5G4d;s2Cu"IL;Ge{t*N#9 sGq.#1`Nc-Q}FiJW 2ue)Ia6j*X2Xke>X2lbx,uHTUj.;.L'(],1Qp,sփ39`PYҌ@}سU҆.M.b$]Z׷g[`uUHþyV{cӒ"Jz'$[rg # E7د5ԲhMwEbrnޕ}osA@G^vl'}ƾA <uRP߉q  :0}yTF 7}W˕>UxX,d MG:߉ɐ1-pIhƻL-Θc{a' ,4+̧u,QBmʧM[\DѿR j1 [ʧΡce4%Lwuf 18` f\N-إ%Y-tlߞ{-{&˖-[lfPT!:P ;ZD'oN@w6Yd ̮H펝֯Q>zIhF:&UD r0;\r$#(qZHa,% StuAN'QL1ہI0l≮&.F} EPQw0H5 P}{: O:#ANL|g$Yn_w?c2lO2w JM oarx`7WM+h+P8cE2ݝcu;x>~6܂?c5aa9ZaN7s_[9*Wn@&G&CIv"ӍYȴ\f1mD76NKsw`p/r 8I0{&`n|wVJ3ךX%f:16g:*$TRQ<=Sq"u9`%dtebdi|,-`HJ:c5Q1V75xYS%S0Ylٲdn6\QI($=OFRNvQf4o՜ÛS)Lg4,`c8Xcf]Fx?4]yd,}k*{? 1e̔c S4fMLe$e?˸aFbboQ3418(zlTtQIH2QL @CD_'5Ş 5EMY5[8>>`ٲe>|$8r>Թ"ʼsb\ɬ s˜bWrӯTδ3Vf1C0xȂL[Q2:`+m E*Pfo7Oy3hk@'T8)A c``,Nc :`uY]8PHmJ6gX}=0SXAb^o9잿dO=0^MglR o?Ppw:Y=$`?qUlӫ;v!L:ՙ@zQF7ص: Nn sK†{|қ\}w 8DPzo_/c6w[qS 0ߦٮ.3d)ڐAշj66@OfӍݲoǼq ;8wL>'p׆N}{197s>ƒgMii*WiN>ǝOg)ct*L&PP5e*f0o;*̒hx\c׮xQX3cW+kY&>-[8>M[e˖- %c ItCer:5(i:0swAK@ u9*;ݹ]ۏz]R߷q{wjGwF gd?P&*;UXRlY1rބQsL%^|Gd j#z;a_aտ]y?;QxI:Lur6yU$鳗?'=׿jt Y &J#}p- ` [»i ZZnvPsO)' ܡ) @^kܶMe ܃r1.+nDRb DفRT.ǐjBٷ9Ygm~,Q)f9Y:VFxIXK P un[:u?|n|0áZƣĶpMHh˜R:J_|-a~wZ:9 Jq5<,;f A$Ndgb]y&Sir_"GX<ʲ+fZ\KƂ-poOmI,$mL-[#16NeppϘC>Ls280wkv':aT\+?qpY9,4LaȊd&0%"5L#,{KKt*0l7:QR8l[oz*U73%o€] Tm3UB+]+k;*d}&`X/Jݗ-w4\w3Ϟz9Rϐ>Bbra* uAT2fw|n{ۦՙؔavN$_9˅Ƥz&Sn9JIݫvs _K`+Q#&zXa߳}Fdbw q[Ս7̸׍9)!~}sbưQ$ʱz۾",qlN&%AbIeT۠OڲtՍ]ߎ3ƒ 2t p?cQQqo8E:`iMY#q5,j$ձt LCqpQPaqò:Ϛ0ȎlUBa9^پ߶,dmL-[, 2N "ձbiu*9@2D8#Y*ɚĉ CJp` z4$Esy4ˣčҘa3i! $|$ij,K0Djc}L?bGe Ov63_2(pYRܨ>fwLo<*ҟeYw lcFځEvŻվ2>OeX9cqT>eChه[ȵ¶i#^`On;i7ooh-Z6ߒNPIw8}kXΔDvWuWcI'1%tt%/C?q%JP38y_+#I˥0.#b$s<ưc2q;cuxٌS~ٲŞ[˖v[=|ٲe>3c A0G+ypts`<3c)aC$l0 S, t΄ 'Bu q $jsw윓@U$bRr)g@&hL8 n*04Y`; *N: /*xֆ7r@$gusq4 n2:&SdڽQϐc_LB$C'qV.y ]3}{Ymۜݝn3jT> cǑPM(_:@X9$c[T@@Jt&2;=+"e6y[{bݨdlxMl\O&8v8PՙrʯB2 =19TZ30Ylٲ2:!a`htFGB9-9 ^;"ݵ:N6qL0':@&|F_ap.I5d;` U(d&qz4N5JǼȎp1C0Ywn)mU\zc]X3#>@U.)Ǩ밝2ln:3)srl#GIrmN5ֵcja/gN;xoϧBMndYJmL %;͜/`+A +K_/8} 8̀ QGG=8eXҕs@v8A(t5{䀾l^vTmM>'zz*\2*t=ML(u: R6arDelٚ s  cS D"ٸ5Œv$ĻTulׇu.oCIR(Lw5οf~r/|\81`dr8Q&tyxH0s1,oXlTLͱ๩xfs6CQ&a ,\c cQ_?f%S}ۗ$βdٲe.4 N<'dG'3ڨuND&V'2pr8&CY`"jE0tLPR]9FZus:5۶Iy E Xk2*2U8xdOkHe W@$[adL=,Ru ]/uLGE.ewy 4ޒC6.[ȱy\v pv5Y \0IWHo{:W_+ E N6gҬaݞs'om{쭰r~#(1+VQfZ{\<(A}GtohTߌ]~;}']0:x_čEt<ƭc^'G}#a Vw2Bu@>9꤫p;g 8З\RZX$AűO2,$fpM37@_d:y 3 X,o46X1W8H3v'5.˖FOϬ߯&Xlٲ1pl"i!HNf'v3#l. uve7 ̡6ס֫ZF]`[-qq-,#ޞowQ(ySף;Y 1ƒ$k^cV,E VR34֙d#>#C%]N1As@Řѱ_ XQ=c!azr㌩6e2geqWq<1Dv<{2N?c \cV`;gWߏݻ Q Q6x@ur5]4R *xnT$\ԽD6u-x~eo &eǂ>LXk8UiWL';^w3L_웋q(}vfټ@p\έK%ɼ0rƶn<Qz$_G @RQH-:N!fK002nU H>1I@*Iu`c@Q27eLb8T'=@.V^T;VYdUr3.i:i[FdAyvDrŖY|I,{Vg_%>C[e˖-;i 2ƨڕ3Б6xNIZpIP HJɠӉ X#Z)h$5 j ,3:Ld&XL&E0WsuYFXP %eutJ֎v>|~*0ƛlRlWgಷjB*a'bCܧv+8,XbQӨ,+PB ́IY) 6|+f⎿e lG߇I ʯ##?vL٘ǧJ>fd\& nglW 1iZN\L7&iqa]+J2A7ڮ|N 9SutzfR+I[Lv%g YI_w2:*?G qxc,Vҝ$KwZvٲkߖ$βdٲe&Q8vE9Us:$quW8 ̡S! b0pI=ZP7aVt80}XvSY5,Ge8VLQAF7r ldd7:Hecwx6$52%5C,3Q雤ٵT树$vB[mg (N'Qtu{ 8NR(ɛ{h3zW|]"d8ؤi5%:18:nVcq \`IpX֧5BXW:fNrGUԹ1pQecbb= P(xw<2#bߑrp,Ƅ}q7زIm'w,}g 77"ױzS֙dƨ:XTI]1W-;15Yt .EՕ;Q 0!AխcmS4X_ܾ68U/cѤuoB7L;ߥ ,0\|l62D: .A՘ǻu[ޗC2)@$-D@q|յ{z^uFL0QA$ $H<7혾;#svU.b4axLvwA_2!Vψg%%ꛉ ~SЇdե͜ߪ;X |]ſh%_B@(i-6 ˈvv Lj&]yM}x{+se)Xlٲ vl昌_J+SH*akGrj;GeIco#JC-u+lW7a@&iDc) 49E[e8.`24 @;֡B]2%趻~0u0cE<Aqe N,o|q)QX9G!h,x~q6Fٯw? IA &k %@dy'P8&v 78: \=b Q A``ɄI*+^{nFIGXa {tpe^Z.1Pl%>שּׂ3H X} Ty,FA $ͬPvU’v1?2.IIuqFbe5byA'Lɱ8 D ;%KD::|GظG|yٲk$q-+˖-[vx7@N'xLSt@*qܐNqM sdٶ.[Y }յί4jlzd2{ݝol UhM5L.cMz82v`M]Z~UfT*21w 3U9i['T;vw.8p dR75ߕo~.;Zy=K*z'3;m{l[/7x?L!_fu %MXI4 Nf@s9cK&[X!dk: !&XtXcIud:sׇCc2:+,xC~>ս׽ƿ tr;Jemn|osl"w\:J2Kj[q&Iؗr2%cH|bV=K!sE<%QX170Og2;̿gS\3@$[I^197զ@gzU ,`JIlb#Ń; $l\9W;nwV$Dem_8˖x5e˖]k2q܁9$! Q 3k& s#Z]}[K#|YM"t M&s (_V6I#* H҄v{щѠl ֟τz/R@a`i7waye'47}sbljj\Fۀ o٘I0ZS6>5gdp; 8 N4طH7PLbqrK(ێ>8g~;Q}]%+0TY&À-#rј]82 #I02b7a!K*]({qqU%e,[?ʩrVj>Y!?m{˖=< -[Kl ݭCgDQau:0/iJRF9j_%w2a瀎j2Ӳ6/T.;yS`pM$vbfTZ^eI9k LZN3DD!tqߺh5tֳ:0h̪Xui|VM'b{V O, 'R6aT-ps`َ@JfVVa-PoXC)P_1F`;wK32F@Z$flwS$ FcKQ /zw}=Cu`DJSg#{_o]0g7֞︓C. dw`wu}(9Aކc'Եc;Sݍ&@_12a"ۮ|L+c'DfN&2t 2XȾ{c@L^ đJu*Y;ٜt חn_ƌI՘VV m*K9iiV:i4sKȂ@cJu0\bR1qdY9ޯ4hlb `lٲe'Kq`%]su>npV?_!]De!tL&LVt0#[$Yܕ$iP' 8 pwx.%k\S`I0 Tc7^P; q,3 pIgasxr@9,lb]N<>RP@8 %'ŤaXH@˗g11VOw|^2͕3T=#gFn^Q|n7#a/H{Ie%$f;wϔ?b!9wǫ {tN6ч$`NqFȪ_\s@X " j#xz%ÓY^{X+c<~)d{IoƤd̅%:YQS});\nH݁G ˦+;;u'2@IRώ<#@(Y[rXda֓PuThQU[s8 1ұeMPŘ1Y0(p`T無D;T cTdwl6˖\l2?]Mlٲe20i`$Wjp@' ޮ}^EA*㪜Jt㛀BF2&`Oq\ɾ Ƃg*Єhi/c]:e((. a&'F:gjY#m{LeY.|3}e5kKl0yjs''F.^qhOw}v:wck;2$jqT!;DFaԤL ˢDrw&in{i&w W8 ۧ˖o;<K^ovMU`X[a;0 vYISD3#٬χeѼQ8 Y7whk$(![HwwDsFP`8Μ,&XXG&N2jb>x9;]{m7XoGw).CQIIbI}LI2XY1>XX4bl,9BY۱8efAcvIjfYbAxtfIeiIxٲO֓lٲe/dGȮrWaJ7ӝ@W8c ¤h~ lŽ(<9vfB,eA`%$?n`fR $1 \֛m{BkfIHwĘV:l};= |Lj !Xı}ޝ^lwпzt8&YIXTwփJ8&3/˨3SgB3zJ٤ @?D[؏UT8JI.9s0S(֑3|x3t"C@ d2At1煎Gsdx3}+CL#'ߡcgh+(`C7Fy !K0L)ul!cQ}q '88 n2L68O+ 2=;!߯DZj;z؍~c0QL'u[,  Q˰9WQxNW  \S.^ q!*fɍur*I/[ےYldٲeN ղܪrHMp SHs#ڙ(geTGG`W7;sr_tl*p.3MmTP S.XRԾ#] $@QPW3$fe.CǦRO}ݵM]~.y?d`4q~˦el8EXOwϤ3#Ϩ @Q@(zz߭GX1~SGx[r"`d'΁XLMX԰gs8%ߧl{<\-u\g Py+Fdlb3y" Ep ˘TX7vƠۅߗT["Q, ؂19ֳYy:Rl)xX|Eืg8gKD⿲6PcyaC-̦# *wAQL Ao @NFv4W?Kbr5 $1 KXJ6'aba ]kf"D:~&(c{IҋdY2.|=-pɲe&˖-[6a!Ǒ>P9J  ;/&_T*#:m ,D鵲߬ :A2 9LSTN/ ƹs?+_it;lb>o _,hDbQ:$>8 ]BP$bw,f%`9Zcp x*~-'{MbUkŘͤp0$3JrL1s+bdY;m-z~V,[lٜ)fj5 W)#9v:Kv:fth܎҄uנ@4gM48G2p@(:a1c& R7OQHA5)r$M-4q zV}@?QYc{ 7!p΃QثdhDɞp%WJlAIu@muBJ GY@1:Dxo,u8}cT3S`?r*u{$$׸ޝn϶q &ݻ=|mQaYޘm{8>޻|s_=|ݓy+ڇ"q8@k3LSݘ(AӍK9Tp9klld%@#}dP>u-stL. H۠$^-`I`"cFo@% MdXbۆ4>%ұ*h<^X^%xX?scdDjbp0X; m+%:0 ;c>e۷钸ղe-ɲe˖uNQ^%K% Ṕ@cqtꚺmM>9 %h; TL:l:0%&~Pb2b- ՀMI.Y`N9qq%3smdPlNB 䥆@=[Mu&/d@,ͤe/p{W1j_@ƶq ZvFIONAgsU(pDPO8I&wf\be $@r:@Jf|S=U;0t Q$>ca1w4.s -K2oKNcu8_B\).έOͩ,,$βemL-[sď*ku% c0z];VNRۖ~K:}֒91éȚ"83&Q`4P8$c.aA!2RQFNФەEkh&%Ĥb@7yd;ʬ(H*ae;ynk@wHv||ұ~8?UTD%㽑aeKR>l &nܗN]ӳcm%ɶ3IŻy;?x Fe;+X)R&ˌ外UYYK`L:Mc>]ٮ;Í 0ˁJ h Y˖$βe,[lY:2`b(Q'Hg *quo|=l&Nhe5QTb&=W'TIk[Iώْ: U[EHߨl'y}dQL0U/5'ujdocP%0 y.fkRoQ$es8I`υcٷ (`b'MU.8TwWP0@ :ٻuµNVf\'~}]<t|&=ݻQCبaa~尿-cqb*Qϣ;W&Nr4u}:8f?~cXb$|a =2u Y*{@d}jJqk+6^XLRWW)J&ܷIjW 'N}wP]vI?# pBNn8 }TJa?ƚx+;T,-\sYɧ.TciD!:ЉcQqC'gɪxqX,̘H8c*n汎$v'hilniZlٲY6Z 2IYFn%(}LD':XGvXF:) L(wjҡU H(;)uNھ@xXV"I "lێ]}JA)Y\9fcq28,M6`28R'lT9n*IW&s9j& }dt-YFڝe?Iz{DNYNX#G6U`_s(Pdzzg·ݛo,PplHWMq$Mt羅O%yVP paA m[TZ MԳ&?{`"f;a5oʼnR3 76JurwZffƌN1gqFtrFl,drp̮wpQ}'3g!s{7+0`7; |S0OxÙ c8( {T?e )]Y׏gT..X9dTu{TsL8KXDõs+SVxn,1jcc1 ̲i-Ie.0Ylٲ:݀\v'%'͍\ s03>8RQlvKK`YUZk\qA& Tf' %n"e=*Y%}bF3qs}:b}(8`Z41f}߃ ( 6wQo&et,]) kzeY޶N cI;x׈˗T&b$\z/u>2r~=t2FM;طdZFOuHEswckڗA  ``96撲d<&_`^&z>}8mtlUcb>ڣ}mIs ~ _79 jrl8unl,u7V|N@VI2ϳȵ*嗍-SKd;Ac: S*V~qUj)&Q0;OҜ< :vbz6" ,ɉ]dGa]#ف=3ϲj6JTߝ&/J5GG.So\ ˹`K6b(IeaMITNfYp~5HA4Ciw׀܉=7Į*4p,'ye 2;yc]Nttxeɔ<'4dlgTA"lNjISϻSn[8 nUE<20@;N{_ST1>SGǺWWþ{ާm_lJkooSDŽkĶ>0I}z19l22qcmPl㸑,D1(FzQw2#u_l"_ɎD8>^b:80~=KD?(Dq'3}Y=;&ZsXJb=NW1B`B8cSq.v%8$L-gb,N,Kߪ^q}1~#ՋL>u۷R eXq5e˖A6D]L1H:dn}!z@ mWTYU4,:;c  .(UF@.sf6Ё> Zv+jr3ܭ2Yƽˬez`Yo.1PJ0SlSt]f (NPOv50&RwN9F\_W=1`x]5*F7a}IuۦʼhDL?{ SZr{1pgJ(\bu\A2tLmS 9 (SvN#ymNbGSg46 G=C3uo\^Jސ~lZJP +orwk{gδi@y'e9u ĵ cAΩ@S+ XlHqg#$L$*v.^֧7T1H8ƓzYl^(tsx2KhD雎ٛ%^6NeK>}۷}I,[lL-[ B  (Gϐ`ǽ.Q^&b`9CGe3(gg(' \uLkPEqSUviMGG[׹mJWZ>l9p1a 뇬b˲R=JZ]oTHke :1,SE!βg`X0ZI,i08CfR7[]k)P&0⎸eP/?:'?;Ƈ> T25;~ey@E=#/Dq}#x^YS# T b 2]<3ؽC  o߇XԻm{V'A) Nc}Q Dk>O qBm qcpc1տ(R$Lc"7fUcnܩ+ 5mG&Ʈ|{$bX"F| &?zSK6~n#0ٜ.&&i c1?1Q&&2*1=LSenHK1ٹuI,,fc2et,>NRO5X/U߫_ےYC,[lY0t ^@P ^X3N}NT9ZH:GXR5^tY~V52\lAXpu$ue]>]*K 3%R<0vMϔG~.5b&Zߝ\g*I0ɛ:Ipľy |-ga熙lR\`A#C :t >IIY5&ӭ ޝÀ\7!A;H.vu  <2$IʌHuەXyb-Ql+x$eWQ/H$Ucaurpw@>b(UWxO-Jq:}5%=o0j(vcMWg®x5^O?fY=<< Gع2vJ\#i-a u9aC$U1 CKqr8ʿNvT"lL(R(ilL8V1G,#k 3c19+.ّŎ@,ƍBbVl[[۾=%l0Yl22ve`\I_Fq1 c&qשW;sR'iVMtYH鮁bs&V]V$, 1\W2{YEVA{>)pdфTFsр@uQ}Ձ:iD>.r HI2C QpNvt=[oowj÷A^r4d6'-2ӌrѰzYMx;bZޓiyc)K  z;pC+ǎeR05~F^+kS;8 eau'~~'j_<d ܘcDY%g6xަL-9Gqmu\-ʽ$`Kol?~:d vlզ1}8ߞmCzSYB'N]Ș8ϻ+qVG-ǎ3tR6LX%9O%y8m0#eXUcN ⌌yDZk3خU|& z@%`zYl|\}:%˖} [e˖-|"CERYW:/=vR9hD9u(9s,ccm /E-_{1F,XĂ=W(PI]VRL>GQZk@۶=Dʩo뛊UKT&TG[M9VĻ:YOTi#cIzYQLg 7'_nt<~ %05翕7ɮɁQjO'SMX}K~lGY#NXw@N&/#&!`ꤜ>U p&O*@c igB±yޚwL2)D&ؿؐW[@JI٠(ٰ26ww[hv8ŜӁ)dI.8CVv'Y'׽{wVl &Tr\i/|ǡԦΌ}|98dD> lVj8bNc?.t.=R*IX3$q?LJk9J',%ũ7թ#h{$Ӱoem=˖-[68EfG$sɄ :N#Ǹyȉ,s:H$̹C6u <+R)Y#TJLp_pyK@fԳ5l_v<Hb4^:\ h2]pOe!KGi;S $U(֖HFko|]֓;v}Z4Yӣ %}ecq v%0f$qS^Cذ8d6f$NHpRId̀|sѸ ܾ ]'뒀Fjy Q)x? TNsK5)eruiّw1nWW3{簏 9+ұ1ƍþS|@dcZ>'@$ˌ !c#{x0|L8U[&ȱtW:D[Ϙ:ȑ2ID(R(=a4Yg'R00;<]}((@SI=Fw}ޘ@Ca%3~;4ks fXMa-A%ȱFIwqq'*lBsg1[3"ekY%˖}p[e˖-#Csw9ldԟTZjweŨP$0' LUՅwue&s>u]!. Z s1 K 4 "8¶:G{hc5ǘFX U ]-Ȱs7 PYSTpDjXVIkuLݘ J*g\eRW zqMh0 C|WQgݖK`nbۅN` I @nTFaHPp"Ew;e(qH3t{o7ɍAWŬH-ut_M w,1 ;鶍'NVW98槣)3"S py~3 {מp68 {x |{8Wg1I3uvpÍp;p}lb?mc)F&יD21n-yFNHC;S8lR]R N4cSu 0*NQ7,>`NO%ca 01\$װnw`E;Љc!7Kt=iBh-;8bl%l+0Yl23xL !㵌6FxFwm;:R:Ag6|`zpt 2`@^$5sHe2 䰠[+% T0NTRϥE c`}v#ӱf6߯Ac{ݬ>.w#,>.=d2J$;TҌdb6/2^ѣ^'PӉ~{Zs'sy:, a}{)9`J21M"uwMܦg|$M L&8w\9^jЍT'@1|10Fdr(9cWE[;11lAH]D 1&W+:ׁ*iL#uM&idufdsbۨD8:`cC%'%itd5`pҾ 47N30ƔXDpKVR&tVN%r9/TۺsإI\%ɭ?ng1pƖ=p *xmn*l٫z.W,[lA%[ǘGb mHRˍ"`?vR mdT1G1(9vΑdGZXH)00dJYQ(⺾ tL&IPԪk9w)o=nd@Wa뱾`n+\(㊺&h\}HFe]& ZL@ꞁ}W@IsYo  xM D72{uF酄4<q'Akg'Ld7Di9z<&?*C=KL @0FЍcIQy|7 +׊Q;pY_me[mcϟw uyMdx0nC8?DWu`[Tn @ ƪjQb ٦NNVN>}+5&;K6p@}.||1912O`QKLaq'TQˌ$V]u1GpXVwl,3nd"H"esƘ:&Pbl\Oby$+^kɲedٲe2qTĵ(-IHdr ԧ% j\(Dv6QJ'epœK0RNF9]Zq (}bw0H1eQ.k 㻠]( d̦۶h/βMDR= ^eǺYx[qAqkLI1Q^2PP)*[Y'#8I6L1O<%k67ݵB!@׮v!x(Hl>wS}'kDjmN+ bF'WXy?IM=ln8q%  Sg 姂Xdu蝢@N Dn qYI$dÖ#`.΀g#nƤ[ql>M,N%42,@j\8K}w߭ Lҷ2D3D9N*#hk2 ֟e_vr ˝|5,KU#E3 ƵƱ`c"a,{oOmI,[JmL-[I wCA)td#4̓KXI h6*F9, t1 b' IBaǘwm6PMNn&iv"QG,k 38 T.d28.u2I5dLp}d$;8nt8 ~rQ09/c>8 T03EɃlavûzYC9Bi=q)*+xTttOldsVzR0AmI"7Ri?v Ʉuc|߱߃س&TDͷ$h7=R~@&}CoЩM8$D8":VcXobbr =<NrG]7lNoy;qVnRw-ctDJ?u㋺Sry`qYT0ӛm}|ӏıX?}&\2 K7Th)#;iV$ƺoX2&֫⊍;$S^:%˖b[e˖}3[^!QK%s1:d>s*$:f8R21'O9ʹf=Nz0PA(\BhT ",c;a? ~N/:op& }d֘Ns R}Y@{C ϭcu^v3g&FڢXmPm\D-+v[0ԤxP֩Sۊfv:ЈFfh QylIb_(>KM $r5 {O<1*~E^; znr&ۦFR$%g{ { +?aOe ه΂1סL c❃e$e3xj>tlEɋ2 idKo||w>x-?)__ ޡ}f|R1+jL"IW#G>9cԭ1t ŝ5%8"+ GS15',]<2eP b ˜R8i'/ޗĹkzٲn)]l'm)2'S{ < % *ӥuQ?U9k*@9Ӗ.m.wG6mWY@*RhKhUu{ xՌ2Ì3EB#Vr}dTٝ+k%3~{I$ 3 Hj,` o V&RږQsa-PЎd*h,M+)Vhj&pⳛ\2je=𝖁z%6od7mWNN¶{Xd& eRIȰH:F[0{j7w?F„,41w|wKoQ |dha}<<@@=M/jǜntgH.⳩ޏM8q3e;y7VLO9R'>?k :/XQz-(1ڄmZ/`u~\'TPKQ2:+sqbUr/1`\@$*6U\uLWΕMVL)Wp[$U|>+87_67Z8˖}<&˖- Zu+7(9)zZOK鄎P4!cIޯX]Vu ʞq 83`dk76`- ^mlOe?; Pl;NiR26+zD|̎T,I#ٝ*$KSAgR1!}YWV4…-BPDay>W2*#F'p15 mР=h]v!d72,3n(V &]o'ӵ;ug!sQi"Hc3dswGߘ}FčػY );6=݇=#Ǧ P 5&tri"a{ᘖXؗ,qq3PFgBhbѤ^T? I;L[I2i^`⤃=u}`l1`,`/bqMdT s1M`,iɖ_'O) 7cGn8Q`bXw* d1?eI,[q,[3P̮|G6V9N pׁ>#(c :[ a#:}*EY|L*9_'r4]Ѕk & XhΌ 6urlrCA u7LL\cu;197dpfr/XF+@<Ί>hU(]rӒn %MCeP [{u/<H9Pα9M14uJƁݱ=P,;G`,[6;^B럝lps%Ѣ ~FƵnb RQ|%9أ\=]ٷ 23`_ɱ1)T07'=tD8&wÀ#l܁[O⣡?Xg|N-?;)Z*dHϲ(_I&oa\2`*&$֡^Xa2S*,{cɅw1I#Cc\~Hcɘn?~r/Kd]ciV/[= -[[|VY6d'i>Ž%l$L,~礝5r0j]@<۞ȽNJXp:2Y7dsߘya@u'&lCn2i?瀒>$&{e$߁Bo}Q[IDdPR]N7 ⻿>W=&EqtgcG|>+vԷJEul]N^|'o$@v|FlͽPj>މFɜu6QFm^TPB$yԸwI(&?iƍG}(vIII~ ԯXZ,눌X$C0Q5,$5QrFb)V} YxI 8b AVWaL˨㪺T.eY\dFP MzH%d9r:Y-dٲe-ɲe>y]/;34(J7N $QprƘS5\5hFg'.J*i?XNFˉ:n220iԏfco=*}gzo~#r,ˬj?3` nތicXer261Ml }p t8}q1uμfFi7wiKDD%#4>˸Wlb|>H䶮N kcOfG- }֔lzױz'8p@XOR``clTxSIE⟺'Ɛ4Q% d@@9!ZcRxc{@ ۖ,W43C,oiZ{ٲe֓lٲOޔ,mED*Yn$^bP Pwt:Ku_,,漍ht#G'N׬N߶8\砻s$G t4(Sg11Y f=1g9u֐,`%(pUrLiGhcII@^+jrv ((2:y Qe*"}mt­;~qrdwK* :;1tH[$2IX6=ܳv?5t4Aau+gyMA`]gc?SP 㳑1[.plp%i0wOJ ]wbLNOw)u[O?f/ ?vScVP0Fro?Dc43PM ,IAߪTqܣ4G`1Q?m50Og@&|!2|#e\X7T1J$K]뒔[rO &\c]Қ;Ud]I@%Iv%uԘ7fqy%w_x(|,ߖ$βe-ɲe>9K{. n` eײ/9u VQHvsggEqv=#ZsؕIf I",HYpRȦ(v2a5hY^ j2JTFﯢU"UW̲:]o^egh4ynZPȌ]->ʌz@7Qg_oWe 6#5H ;If :jvG+#?#f |F67i'|Mc]=Gpwys#L3ýK.y3w,df\(Uc;AЊ(&tI19ˢ<U|qCJ]'"(꺄:u*:۝1fu8F:vv*6J=W_E,[,[3\$He@#;BfuhhE`YcO݆NV-'b2V:JlJ&Tҹu `>IE2rT$ \2f.uj~6N3su9P#9/׭2:p .+Nei+g}Sl: lL<;we@6UlWk#2$a4gYJpyoZߑ?m;>!ËjOQYjX"xuCoHf Fm 8 c8Bw]Dž#6kӉuslLT}S #Q]DM۶7w&NH=>ɣ3`K|d`xꈱΙ,/(fT+:bߊYuDr$1<_&ߚkX[udde@AN&vchgq.9b,0,@&]Dx cMMLUڝ7Yb2LKSˌIe$9cb"ISmcDf1XȲWe#1%l'|&Xl٧lZZ zQǡwL9P6&qj;29XMx;L%v(ɦkYݚWBe㢱/5%Dc]25#_'ۨk164:;tc\W)FsDe O|\j¶|}~z$~G+Ըw`2 N{9( <R &G%F1*9[}vIim@"z2;.7r*6{xjԆ"ޝʾ;0ڗIҳ8?Q7c\㨤%Se˖n[e˖}8xD=VFխXJ; R!;W+PJsacN:PLcסC ; V:{:~Jf$+&{݃NGxR,xW@lFf6Q^)U URzȾ2k5`mY*8٣xlo@&%t"ÂhU:>N0m ?;ۑdO ,&F$p5cOzۦ#ؒ4A`=cbQY5u2$d#=ztfhޖT֩c?T 9C 0v/:in&$-#r[-Ub2(U:s:0w4˾SAXΌR|<ߖS It)zv>)`t:s`g\?7vh=u|6)K$XBtq_E9Ge;zǨr#Pucb7Ru0&%&}$sP.eq?w31L$.Ί1JVfr=/g`w|:ocur8#s,T dN`I,[,[75Seh  ^2fp&@`™'R3~礡QsN ݕG ϪLN7w$ R!,RA'1f ('wM,`AyNpCc$ӫ v7]it D}DXYL.X XJc8]qϧkԼwfZU}rFjzut|;#`:]{ ퟚƇtqe%$=My?6/kmGP+)8ӱV._mGP<8׌ &d7[5;}u2V2^9āuUM{4uca%cǹ}`bt-3*dBTJUϱ$8Rvm}u1qR,TDETN*1=~$Nnſp;FX(c=Jd;Š̒ߺ%J/ 69s1zw0iTD1ʲ@7˖}&˖-,EtRW2 UKϋ!STvD1 rcA)^@tȸSYY р c4i5jbЧ'|"s=X &*Ȣ"e@P7qNINgjە:za4_*`F]#f ZXgAYϓQeǶܱ\6=!qq<˵Rh'Q Pes`J#2,pNƞ$4Im?l5mH\* G.Q6a 8𼖽ξԭ?03)"ݮ6˖9y1=^!G//Eumxű07Rh^'mG; LNp<Ց>n}c e,Q1űېoc`Y+I|$,|9Nfnb+Ɨ{ 9XJIq:6YФbK&q8|l(?4t8Lci])X,bi0f7GXD>GPyw7LN]tisٲeӾlٲWo`Y twlpdd5u9Vow~lr=W9THP嘤M**E!kc3,-# 6X%:*&_fаVu:I0Աc&8cxpwo1nRO?c2չRۧ\<%lgf `lٲWkvB@ m/ovnʐȜ2:(O+t*Rv IXu|*XKRD":,cGT9/}.IgLC1{IKxRLݱұƺ]o $M 8p&Q#A7ΈDަ5Vm|O*/7A'I#HXJ A0Iz>FMHаm;`ӢfA+@ s(i5 Z;Јc.y|HJQ2~]řkXVz ʈ}#wrAr. 4Q U$tTҩwNWS`%.#\PH1|\M3̣o(c?m<[A<{`a 3WaMscTn(|F8` g)⳱?8ĨCTFƏA)xCɔgSueχ1Pu-e; s%s0is>q=bg圂'>+&$(n0'\߰.`Ub0b,61OzYit\c<헂>Ky9odS%lm_lG3`Il7APu0Z GCE;@ d{pbGwABH0]K08 +.%vXOÀ Xd4`HGXp^MoA#T u%@'FYQ&׊]q4֘Q8鶫LƑEd-9? f&p*#,+xStq/vđ7JILrǼ򏷁m>v-G(0( T{`+h@% |T=j}H}7~x>"@Vَ!}7}K;/!sl=R~HA15^ dRʺ(ywήc?xk=nιc}HR!9? p~e7e&, kI_s`kgqh*q%*@# @r/tX :NW7ێq2 S`)5#qJŒv,L]S fv\4=A|Jߎ %~},[,[죰T&tV FQkŨ &St.d:xH:M'J*I} ;̵_a]D́.-c.IzD7 zWݚ]:q :U+]@- hYy3b?g=Uu-;$WC&X[H&g,𨨛ϫ^?jk43!eu;y@&8a`Йqz!w{z&XN5wlO{} cgWyL5E,QuCO?kyI26trJb]ʘ/֥Dd̫aMcmR9"y!L@ &wLuŃtr#+9ƬcawyNTIv `Fj=~G?c@kWE`%%tꙹ V'[7ax JjYL$G{fcbYqqCp3N'Nb.80+L rj:~p0۾$q-[]mٲe^Uy`#8aNIyζmPk99΁:A2k`c5zϰ}$Li&s\w~Xy^UYHٟeH!0QٳYITa2|:Y(πL>I`b.`3Ǟ&{La]܊c pRb0Cuݤv`Ռ%rN\|;oKYIgXD̲/V2eQM;?}Gr{lYQF%$̳Co\ )Mrt3VU\c1yd+}Թ2z) O (g 'uNc|?O$u-[ӱ0Yl٫QiEe}A:8`E 0]c?25:R^AGkud<݄>HHI"0(+Fת@z t9I Jϱ 4sF{.}SNYf5:~1rx޵-:L|}4x"A `^;TRmgy9oJ17> G:F$<: 1&ģӁBЁ>d )5va9= d7϶&a]W/()pL:O?|s:Ǯ%e |ݦ[? pTwso#c>ccR}t֍oE8[|f `NlX1Y]咱]x8?XY2Fǂ>;}{` PpYFX\YKf~T,'9Z10vG' bȶ@u0h'1Ύ{DNDGdf:vgRQuʎ%i2~oKgٲe$.lٲeD ҁ[].$uc0Jt:>u":pc5N'<(IjFt qNW7PA ^.HEѺ^a6Yp,$,H(1~ # ֱ@ ^A#lsw׶A`ǻ{7Y{4YZ' dfn UEڬ\̄\(@cM cvY;~Q/-fj^LG(fsi:fIJuDv&Gdg\>:(+N06daP׭Vwȳ0+Zj|w0>Ͽ=tތNԭn3qCd(a/d_9qҊq Z 1|d|y5xz0@o︺@&蛢Hte8 }tҳ%S]{RTΌߨ$mra &%3ĒjMffj=9T+ld>wҝM\`=9׸9dLKW,#W265"Y;@M=ݞdٲe||`ٲeԠ pČDiB$˝\@Ӟ>&Xok4o|dÂK0&ccݕcsIzݽĞO׾Nؤb!a7+,zIװ{k܆31 \-a_Ih:I#Ƥ*OR'0AD:GN&FI5 CeQX`m`]w"2}W z\ⲏ*SE=cSҖt.دط&ѷ9;Ip0߅I(Ge[VK%F'p^ЏVWWQp+e%cCƤo"`/JƘqTl7tƲXl-0,<.&KCVguqn?u亮H;XNۇ? aSa }d1.Ie˖%&˖-dp L!1T Z;Fk9:qӓG4ԉ=ގMgRul"&b>&<_vD{z(s]'>iq3/:YDICN)L}Qfs^7nR`%PQy'+}ϰ~uf7I]P6^g X{bTBax6;M1E2t )&y_? }"&,M%$*fK#hsN~%ę17&<ƹ1ce1Vc I06bpl'&guLw/K3vD  p$tr5IWg*Odsb, HjI,[,0Yl5&Nm`F%?j:֯3ndelS>.`2:KG,.I.9LIOF.a(v]܎{T\CYyʩ$TdaRTnv}|lٲXMlٲb؁7p?AdRnPӊ#4վāIdfA9n MDe8Vda %JnA`Y.uʂ LZVĄ~`W tur25X?UQ`jN&u"xoP%tHͲ&9G`תΓ鵏Ko_˽A909eWO,[A7q~l~Tc3Ac`GI0˨cZ%N7a&>NXk"ujYLԱ(P̤(Tʦgu+6us8l'.~?\#"9e˖}N&˖-)&24NFA-l]cJǧE3 YLCK*M*\8u:V{9t}@p}zݘ@2SJwVL0ꐝe17s28"Q\iv]f93@XNHNPɄ4ŦO#\Ku Z4Qcs{]RZ%i9&\NM^0FGiF~Ո0xl& t=el+k;OC-@Q` ˠD0WI˻sH'xCǏI~my}۾g*/egg][/S>֯ݾ__o~o?2f`_'m{onAl=_RLь䘆ݟo?{鶟y>?w}i?OCۏ?k;7~olW~ʱ }w}em?_߱eQ??_K/7win??{oG?~ž;l r_??Svo|g_K$q8.%5.XMnG_?oOK?8c*l?Gl?/o_;d؈?Oo?3~8vYcğWs3U,$nMKb7yh0w]%yVXK-[vdL-[1`-A+pIZFgL 2:Ve΂JkH0:ԡY ?n?۶mۯ~׶wlsV_͔QF3*0WkJ}}%`gT~?;WpfTP,wnΟ~_nCOMаl ~7_0C7Ǜoe~g7}??}G~ho[g>Q#d}?_Cۿ/7+Ue?~w}{7N'~Ƿ?'W7_dsll;_Y\Yݾg㬪unbCVC@"LԀpl;N Mmc$&鎱MILȀ1QH}A|TskuZ{s- ؋ 3޽#ԶnKH$Ճ” N猁!бs747.| -{Pvwi'ٳœo<-Mm*A5C`hU5xJP u=U>`[uܝ~AFl;q(qo>Q̸ 'N5K_ |jj.оy{V\bả0ع|=,,up1ꏀҸѪ FM`80~sԶZ7ß7Ÿ7۱?m4yd ma5v͸L8vo͇s9p0~h8}b~7w95S.wY1GÃcgN&*.3kmJGp 3I2xT_{އ}i&4,}v;(?urk尵mM O%ɳOݧ>;nڊl z ..'1L~2\Ե47>K&NuJ ɦ"qኯ\w+mp4/CUÔ Oe):vv‡Kx9n9rܱ0mac>M6¼; [[P;@b?}|v(Ƀ=P꯾Wvt\Bb8MCC )Ri<Q;|b/rX5up%S3vl\/=J~y[.e;}m#=a;3iꈕhbjD 蔛g!pY{;@. "DO@0 "DD%ډË́k_ ]\\"}-)Hɏêhb &I48z`vEEMH& d#G 6w]%$_< Yle;M;w1bQ&H2JB:zP5?|FOy/tvI[ ~=,{F}ԫUå7}Nk7ٰ3`ڬعIXuqHqQ?=o^/ss^5E{7~jj oss^ o{g \C٣z@ É=;w_x{^Yg_1ξbYY17 ߄}gb|M #}- n8Hع~|C%ĉcם-Z+[Ot nK9c,G%Kaqئ1f0ᅹ`% Wv; 6Z@Jyd8ajњ2hPԅꏀ n8] ˛sY#Ht{;w>k'-C 6oլ{X#3o8x]4o.L"v0̼\jm O 4ۮ4>p$4s? DZq¤Qp 3i `sM/^[)?sKM}oHf1hU|B'Qg]15uwϦ taμﶰh%I]:ƣ"E1|d\KC< 8r|zrO.!㼎~# }z]ƕ%:# Wm0\:ɑ#Xr V?zCi`gATg?a\Ye+tbfWcO=QmDJ> #ۗ.7صT-C5i srIVUri}W0q?(DAP!BW!B>5pشt"j~ՙ Dϭy{RoN.ۦےsG*w\_ f2$5)  7z\M9Z$PU)~r n8u8? ,qEM?lY_O/|%KQ;z{ t溜]KY F=<S9VU:s4|/K{+~>ڳo\&KM>ݏ.8Ŏۏ &L;o}4f\{fA>oՃ~iJ.I;;. ,^լO sK.qH*F˝gNLmz@Ӻ#Sw΂מ)!WviQn;?~?}ԝJaGk*οY"On]_U]ʒKzo"y^j~ifY\Nqu>ydת$. WvYU䦔5F9pun7ȸco1GTnbC,I.󓱵Dؐ~#Y~kVSWT }r&KoH$H8+D{U@,z*v0nN?'w}3&g"`8,R-<$SL=ѐgQE^gy6=Y$x'[SzoG֦H!n'i%eV\.qW[/ƭo;!h}V%<UrI!r?)~Ё!lJܦ2V5rRB]^Z'.;@"%s>U &qnnu5/^ƍs> `#G odH-|?̄Cه_(Nx7wll`O/x <Ёp? c3^yvm$%<עxMSWG9vyvhZ!4vtFS#H1HøQc7_ }J r8//kp{IE^`s{hK*ṟ;~ۈ48~HqֿMPqU [_WYUM(&%{ L. k[ye'D@0 "^, ^9!0]Ybacky4: p >kM^h _&Zw\߻<٤,FM%I^Wp?il1$*(;X7c"],HZwٮT1SO>. ۴Kp3ah/Nr%LKoHO+6ȘLZWc8[?l Ǿp_}*.$$staG_ Y?y)ŗ J7$V4\ϲ_kop7.Z+Vj#  n8O;٫aGx_U>$}ֈ&x^]_e_M`Ka}/שtK8a(m0=}s,)Úmik6xE^c!%߸Fa1Lf{8I5KCՃy^s;>VmcSS[jϑ_85Kn憍);ѡuC`:58~/w;XG=}ݰJK,$?~>sdkG;`H9f3FNPZ 3f0S V%V)YP=ƞaS09jp8W']p_Uxv"aQM̺Rx{~7f)@=cjٽk.kES $vuK$u(|N";ڮV8uJDurI!*`"D5y9IQĥ"/ ^]>VI9j%VB<][#DR=".N* ICkqV-Lpi%OzP+ q-JgL,êKH&RiN]@U1r!v:v.7@A"|Q&YGة猅nKrd @H Jd!#`X}-ljjU=-U P'/ }'+z쇍'`7M%Y]'J0f%7/|БyU!pa#k%Mj~q/4jjçO\zפ>9".a7?o9E H zN9K˾Q՚DVia Vx'DI5~ho?s {u 3o᥊G|++B ;E}Es>a V9xBLƿo<}zxlۊa^?$`Rxk۩yGwy8}D?!4qN=li,:]Łtŋ%ž06/}$L߅KfC~țhK!B2!B5|U98K4Bex{"m3a-tjα tQT*pm%W8l"q︮lrI ɄV-DQKNVȃRJ&^ݶ8yH&$#G 3U;> *0)xHP2zyKy.xдjcŷyPc`si !rlm 3ֹ]@,鶶n+\+5uCo^GՑ@,qQ$O~c/TW{6XmO!lr|NP-/~eٿW*!jd ׋[n>>DpA}b%dᑨI.I‡,XgV.Zcpmjڕ@k?&,Ie;+w-6 F'T?Γ!$sm;jj@A8R|Gs ؚrG7>r7AD %.3pߗfeMM??~%s#G uX0ӐmlmfnݰVhZ?'8GX`l*tYJ.Uȹ%y<<ŸC)SMp#L>T PoIb{$$du(*+{0GMv&s#pg7>ckT#ߟMP5Ս'B$r%2n-ğbSޞk./|:K"$D}I"D\T@ K%)A$o[S-\]Izk1qrutYp̀AV _3f Kkt+\IHLZK,ᯋafю7_ >4M6U JgZBލ(`ws-48Aԡ VL|㑢-{GAsmo 枅%$QjE:&_ܜ@*,pߗf;-.uHT,U0Xۓ绸Z>LOڨqϽ-ӯQ1R,XU/qh.L=/2pl_#`N]?qo7n6[Ν3F'/.#pqG_zxnKҊ %i:k!,c%sY*(pV\K]i\UUK!Ba!BT<G 2yEO}H)D5lly"'|斓<]mg-%[Z®6οj:s&L?irkm{'GaIYT{qzVڶ!0¨,qm]/חڑlo|i'F.U seW.ZV%$VZmU֤qڶKM6";wCkf?DF''~>ꏀs=iM޶^f\{W͛cnhonia[\޶^μ|W۶o Fy:v߂cmZwᥜ.]Ϊ*g s FyY$z{v8vѦu~89g6?xB-u*;wk5aH_)>2M^PrI2-Y+G(X6Kj:f9|i5Id6qkA7s8I@sajް=,_Es"nȸbakCsSǁVNXlcTBUM8ą[?L&,gs/[Hš<(bbϞ3q򣧜 bDXfO(v2F!+~e3Hmj#_,&upQq瞑.bt)\ba0ZIZ*jtH 6KTХwxnWz!K!B!BYXTE\0m)IIGc`km6_ >h\<~2.DkG<&˨q#iC\n"q/홇ó-NLV&c_4 7/iFص?M oe0tzxxX/ǜT/EljjW]3Ǒ㎅7R@;;ؗ\USFhnxCd= /.#&F=@:o{+`kycpsmaz-pq·;'u7c)V~ewC^ms=#ƺ_8&Dd?9и/^nXlX$rkx2h!@nƵgÉ*z"{d;:Xp 3LNꏀ /3= ܷy]H!cqDK̸LHg{|;}D8I쳠cnx}q옣$?-o 'L Ϝ\Jxi 8}5l\V yoIMm>o/N9LWZ7Ã΃{HgNȕ`E܋ru;w s?-o.+Qª4N4J%G#eՠLIKE۶!DBOih1"f|whf8%2p*-f wHVFNK5B1~YR4bڻ 6~\U.!B DyEO>|Xʒ!\JIen`bټ\)--O ']#pۣΎG;]Nu7nHhxq |{v# I&`W,V+;igW}T͆憍PU(p?DqA9 UIˁ0Gt^ijIF/,WӪ"H{.xLnmm/!x,iuC`h]*dV-yeSe,/~*D/u"`_g!<_}z'՗8i%w9ڹ>>x\ұs7s}v(Vɗ*jjcJge_t GJ /U7#K6//<~ׂn{vŷvNT p_1]1ڳL˭\Wŗ隟4sbq5{K&DpMXUl\{l'Č(;S$ nUS{mSEkOzotܝRѮW|~0aIJlӱs7n}!Ӿ'nT$@6|@ MFӚf~{ K> K۵fL,I*~ HHbw֖ #NX|9p b(X&Cҧ?_Æ@2B{{MMб}=%2vU\@9 %\ba,9.IƣY  8nE1d7wO4S>g䙧eMa"U揼v{FF% ܥZ},Z/l"ӹ*5,}ݸ-xLniT&Ib̉"tϠE):۶Ã+,^ u^ɳV eEk`}/88F53$1ăM~Ǩ6o6$608ISnX  "yoy4?z;;|) wJ:>+3D m ͉ʸ/ZD5s 88n6hi,88u)σj؎;چ!HL/ 3ɥk)LD)͂X NɄNr- rkXwiTf*PKBQErǚeB^\#\բBOh I#p UVHXŢ c_uIhZJ.r5 E>>^mŚZq}cx;g,J$>GAU"D@0 "Dai5G8v/67PxCî& S07%V=N6DZ$6\4~<6QӲ*d!磋ᇫUɱX%*Il޴~~SOJ`M6pLZL\ nz S4$eM(LRq_iOs#dP۠z7dӤqxV9n[IEm W[0({E~Qo [z bR9}pVjdQ++'ȟӧ/b"7_¢UH_}Ң[Z*$ǎ9ʹ.W2=7k2mEKW}u1 MQN*O}byM+y_j>5AB@hTdkkg"Yb!IX0jC=4kDQ住8},t7Dyww罽u A˵dX7qK,qL*k}s#Ec)׈ 'zq-P9Κ5印m[ePr;0w#bp%|IakbXdSCQ)2F9mę)"2e9@,~񛖗@Zl''At WR1ɼHÍr L`e;M宻ϦV7nL4Tq 'F6)ejes8Y)+Zθre<*Sdd01*ɾp V(Yg6g`v&ғo޴E,{h>d9ǚmL,;y)הqeVƬ[.ݸ os3e)Ʉ+e]lwCǪ+l _,qg ˗!H$xN]kҞ?)%N!SI!%HiC'1]^TDSJ2H̢Xt9ږF(#x:es Ԧ'nZNE* JULvG~aKKA $RK])9*Io\jR/QMLxBHn`Ɩ#LM}͘C-cãYKbԯ$JLyj ( * pYwaϜ[^tV3 #eHlgڷMM@G+ r`!dZa h:vVr~x޶%63.Ӟ VvDA~ҥ̺k Ko`@.˖۶/߬lJhDla]ڸmcI0Z@/|HDAdKsܗdI^!pZ<ĵԖKפ챢/%Kv$@"Qp =N2nOшv}]c}j:rXӸ{ysCu>H2~|E#b[`E|[Rq,J ֗ӊ8|G$D@UFq?^1X)E]UXux] 1pU5łY1`b~ྯ> 7p9_Jʖh[>qׯYv0ؾ%3SbuA_WPQ waT1]j}= RKZ$,qBѯ"LB)dQ.g `26iē,D PPH>pdm6<>!o7n(~yKR!W&8kB\I{HGp`7)98x vp[8r03;{yg2l q)dH,49;}S~VRt brX8圱W%W4|AsAz\Kmӯ|yȓ󲄾t{R~|$hqSSq_rHX,rXv -R,䋾"X/kC1r-͛SQk;N B _DXQ5XIR1ӹc_&%Vg]$>HJ +[zC7ikeۈѤ{:vv*=^|ኯ\= 2\ދaſI Y_0z{Kr2(iW֧X4_oh\!G^ nYn\ >[J.lGUJrAn@m߾]|GQ}!Ҳ-0Ts ;q6x]\RNq!XB"ddmGRV(\[ܻ'E0L!B3$DRs:tHH YѤi^SK$ˉNdB"h Fhگ_YLhB_7z`uJj< F!zHM1$K;\^ˀK7NuE|sao黻kG R*8&P% 0+i&zi&Z-GI .25-s6q9c?\ xU, N6KHMb~bLubw\IE dD#t"w':yWؗV{>sI"Kݨ4>p$ӲmWT1O9eŇ? ;{m{nĪDQ2>)K7ʎՃ[/JDwJH~J9(ΩEpJSDDUeh8\©p3[Rd) Ǎ"! il)QT Ұ#&׎5ƞ1κt8:-55rŃnkcBm=[l|NiA4 / Q\u09{r&"D9(o!B蓠 Øcr}ŃD7WQZ0K*tlMi/IҤCHP/nM*Qw\O=["J6%V V8as:5<^s;-иj^~RӲ u'O=N;w\υn IRJv]-MR1F5u0g}Ϧ|d 6cՃǛK:vٷ=ݧ\Bq}*떽g_1`zQQR52C(,핗 }W9H{[zN,ܵ`8?߫Xcf #L#`}/dos=hiyc2gEVmIq쓾FWLAÛ]O}LLlR׼$wnL2<&<:'&L#i}]t=|i#è~(4^]^p YAaڬôY6'^MoI7,+oyǾ+ak6X4vk.sΥٛf͇<ڜ҇yYJ,xte hR>3JQ4}Ō %!UØ'ˮ^ddKfLd1 ;¼,ESw;n%1q] Üu˥8?/ude &]TJtyW#iY]%˸UiڻnA+PTM%΀$D6$D сr1M58&t$ <8|:3]#`K_mvLd?g]<f>WmL%R%&H  ɪT$I5P\L}}.ˀYAA0#G c;URZ]+zx9X ֭gR<%{.8jp\YbÿUSBR+YjDpfîNWg.FTr G4uĆ7" :#alNDŽ'Ä':{{D!C{A9<½$ o̳7KMj0/]IG{;D9saѦuj=8[6[Si"b=3YOw]{P,_ꦤs4]Z\.mk\BYF?԰1Euvu,`ԓ`S,%ubGR8P,!UìT<%`BK8R"Tx ^^j ,qڹ6P$dU)=ipE{Uh &m!H˵"!j\-w4 5"*-H|G/Q}"aZE 190tW!cU|${T*/ril-z F3'[h 0wyqVp &[籿 ALؐT13;wCKf>IYOVd-o +CV,86\z(!٧R7mlMPyTY1hEK׋ -k)a#kUAWi4 \|ㇽ~o0|Sa>?кnFR 3N9g47f>UDrCcŏw[xKC NфShGńS+=};| Bcsq(\԰d-\!3z EfED#I$ȩ#rEt/-x%ij%pLq9m 7muV AU@(^/J$rE&&$v\!3VI⣟ΦV՝VT}<'*Kz;w}_ -Mmu 5o}r0ThZM`{vۻ_>}=}Ҕ[N4ʹ~/~7}A"Q sEמNkf3bO$h䲌^J&27o.ܷXs\aGշ]GM`=Q=|d~27*mKN̟$>*nmg_yI,&.܄K)NjmXfX}7Y @czȴ]:l/%$~sBXlḮ}i6\rG{{o͂5K w!lii7W6|d\Ws,kkÐo¢,P\C%Lsc7_G&g^̈́Oz;MkGKٵilasZY&Tde8^3ty 31N/=]J2pT]p56Lە0d $mqv9$W*UqJ|ˑWG.)N/ 0bI!S!"D_GzK\vt9=͋x"%x"PH҇.҉~+OKO鸝~)/g]:$1*f"TNE){;Re;I*n];:TzPyZ+*TdSS+O;Mj"n+&Wlm0Ǧ>%ӥy3+kD]dPQ*Ur+}e}O9$@oz]'"Ip ڄË́͛[?-o,?|ȕxM9%;~FB4F9J.y_Bǻ DIH| kjä N)q5i* z'N:N\mݲKNey). {\Ҵڞ~FpɍkusCjwo{:vvd)}'a+;4RU+?ԪVb4y.K>c{أƍ 8mU`Sc{'-]^[.C"rX5h*RE]y盒B$<*DQU9Jɮj=K3[ÇҶ1,ay)h#Y";NG&09ށ\"DA$D^8ōE1~^i>g# 5$[gƳ𒿥EbCkԤDJ&Ivg=nĪRJ>i uǪIL_b9V w</?dЩI_^3~}˾F8K|BI&y_G5ߺD~`x;Ze;iL{QHϯ;r@GϢ]`{ϱYKG0ڳJ츸V~k1GB !X%"e8O"sy3yw>YHy[YWoK3tNmK0)2'5jSb)'s?~cu50j((ڵ~Gc([t]J6뎞r"uqTVrpJ4dJ=c4=c44&5ϪRi!S uaR #/@"Y$,7xܺxθU& D!B &!B0;dn%Hrrtȩkh*,߭ |!tA\@KOǕp?= mRH!TTJ,qTk5 lhiެ*GQ*OΈʑ%=ul&K?qމP1%}l:vp 3LgH.KB싑حľ3o8V.ZSֳ2{1m,/٥/;w+z1"!9v]ǡ-6gh痳+<Ecѓ&8떭wӺeY @MΊ (~nnxL44lbzoS@:}ݰha/g&r8w瓩NʋMM=-񱕡BiTF'(aF"*WyxGOL#' 8[Zjin-.ɡVcq. D]#Ξu˥+zW]IH&H,1b!k#Ui$Yǽr m{UQ[J 'DBI!r bq97!7X[UG죶/eͨH8TFDmY#%_?~;Lj&_=?CkGG*!EKP3!I%N<$bB.Hr*&/^z[| *Q2MV@CJZLYp3bR.G2OQCwXcb9d´S)Y3qÁAd{6k4~h?m4 l&\_QvbI%=7}B}>fp.tܝ*'Kpc< 節v=nB߰-Xh iz7q#߇dLJا'^aG2'k*,iD`ܣEsÛ'+Ns^sxMjjg'M>>ʒqݰݿzlxnhs” N+Qq)猃`ߧ򵾈yiN A8F G/a@tҗ;?,X%ɑvˍ+9"Hm_ ϘZ8jphinU%L$␦r"]#^ sBZ/%tb[0")m];:ѻ%kz"pˏlxk"}mcI./ÖҪ^8_lvÂW{AaCs;׻ ᝦVxk;%{+F*GGWĥjB )Z%odQ I$ǾYMX=h ̺$5p- U)b7aC[%njccG& R߆c=cKfXpbw +wO⨫?fp.g} ΅[C`7~1?p}~{#SnaG/m^ Iф _3l0#o4Gp=^-4bSÛKU_MRK![ڠt| m۠ !K$UQH?۶ v@ri0LDAß>oJ8;+] <cf߬2 u'EMM䏟5-Nc+tPDZHyO^Α8r@u LDN~`Lq2uEÝ𧻓e &1%brL( $9ךj V:׀t[Aw? _5]Th{h8n|=_e#I,#ɲ}Zȵ$lv9`NB 9R m#0%$D6DFU!Ɔrj xҀ5䶓:HK_[^)V.ɒq_ ߻^{hÆzux] \aKk"`b{+2}wKV5nW;%=I8`\P䙇/^|l9|?vZ%}?]3+XpUh[۶mQ ݾS`@״^͆e#:ހE_<0pɍV׫n~)B beg$WUI4}m4 oK}kLGTJ +ؽ/b_ lP4ŔfGiu2!qhZ߂oW}pM%q/*Z76.ap/ FPkoMYD#GWw7Qh jq*VsR.O|HhN1gzsÛ,|vv$&Ri ;wss^Ol&L>=#B:юwH}idڬ;9/ǣiFs.-CI &ܲÑ%FgO]P҃ u\p vWm0R ǏJ(P\^,)pׅi%x~JqY\ {kG Ourz{C ]^cLj?g~lyycHۋ{͛a}/7\v0y$M_T$bEk'l3=rVI󸐎(A3#CU:$)$z$gK3-\x*Ήu^79W? d`W.r\p𧦫9圱䏟zTD!\YpQ2NE 1PSh\v耦UqxE-B"x}uvu_ 4<%<7m)YYCr1(J}swfxݪ-+EeÇ ]ӥdڦ]Xn-I,\q,%pθ 2&PJ,đ@. "D_E RTBדdi4ؓYR[YxMu.X9+q-b".xW१_;ŋhrԨpyKO¶%Z_Wĕ,Th&Y-r80exmil_i O;w<=w1HfheTymjj-VkzR=N}(*g~10rD_R>.x&S]~A@?Gc}dsߦT.Akok<>0qѓ]Y2JZ[/QsS +6rڣ_I R5KUKhdLh{gJBHr," "KӪ p-?U9+,4˫Q%늸7aL ^\+*<$ݣKKW(s)k4g𖖭pW*f>n⩳. K֤`8J#tc 5bnrXbQ6a:}r%U(*@ :HKwR"DpB nͧӤGRd7 *b^4 i`[J4pcS(M/= ǿO=мFZ&*"J|۲Ƒ 0[j^2*a y.`Ie&is*%]]@mc6@ (JYϘ6ss8r2YT5Yع޿QFd!wa>z@x!bJ~\}ȓP꼢?-oL)$73=RYucAG Uñ~mݤ}sncÑS|֍C.7 7mʂ|} ֔8)qQ;8R{] :dKHB6jj%6>~}(F֪c.f~bK<@KSjMR;8Eqߟx̻7(&XrT-JdqIJ9oLm)#RX'~&V;X\"p*.ߓ(%kSEN𢬐7j܈\TJKN4"vt}_}e+2YLBKJ'׹^W~к?bHwPv t+n!F֪o/<5miKl<{ Y ބOKsK|SoQV@R/}7s s !Yp/ 2F3uGj1Rydr}F<2,gX@d!C0is!UrD|L4vC$v88ƲEJTd]: +`UFK.\#q:ahq&N*Ƅici8w D…[߼\u5޺UH>vٟ}i7ęY=N!s93_݌HÍ˴bRaOن+#0fL07vz"rX5ݿY%K\gt#Y)KOo7nby~a3[HT|hQ1TP"CΎcZ.eo%\-Fg_EEklȜcuَqDX8@ez--͛[%!bhH˱p:Z7 8Yy"Y󼯆BH4儼b5Тמž,= #띳4C Uz1>;>'M9SJ4EJdOHĥn1Yf/;s?.oD%8OJL(`̇ #װ!IW4+DӮ-NVTzR ~U3]WRxNz0K_"̿??p/Cu3y%&4κtH@шtz=Y#dQN}j䵂Sw ^W\#`b G(Ise!B!B]U.©Pf0%mD(̧!XdrCdsrtW\(R{4AcOCPWµ_Fr%SS"l1 lfU*GMoPW m?cG?}Upa"7,4ǍX$AqTB#\TYH&G7$j7>hi)˵ײiѴ^qKb_^shklw/`Rzˊ.kJ_Na,TH}M(67~Tx2~ 46~+b1^ZMu.]+KB>ceDYk)Rhm}~)rn\g,o8v0Lv22rc3cDT>U5l;f\RS;خvCxE4l8t SQ{.5T hnxÙI96VZȭGq(D"ip~Xr`b4?>LVS'rɊSǩD7hM0Y7Dqw_8~)pЭryE8nr]γ\7[ZSV*G*P].7/ÑD崂Gky7I][W5x_0: Z 0\BC=!Gu4 H)!B;$D`:_c#k_"P)cce][UK2*%4趬X,\bI2K*I'iK$@!$H~bUbmesQXJ9j\O.,ʍXBFΎO_'D syL[[[_aIҞ$ieFӔp|NǰݿopyI$A*40Ist;jr`X=пs+27'gzcᅹwsmBT 4Q0< 3ؓR[fywv`1&;e߸-*'gq,"aǩZDTE[X ؝'ISϤ- |EHKn!K4r,QY3,lYK0$Y&s/6Di!hgAW$5E1H$ L(I->\k (B7"Z^\eAUP1UN>E&k%r$rx>Ţ9 Ř}#w-L11\up* H EQu]O.!BgI!؁ɠE4K7:MEyOPqq:8N#ⵤ8j︮X=@㼫>X2,XR"p9F]ڒs ]okk#GcAd8j/=+**Hzk;uF"yW =qM#M!1 d r%I8gG,E*IĈr.\EfrIX Ǩ/Ɇ'N>yVQYAWҁH9tu7ly'(N6dܴ3NpLm&,qs\)$N.Vljjä\, ˖W16U0Y$vt,j<'N剓+%ist(fTN8U>{,kJ>Ho/b ɥUM|g$|&Ƈ9l/LQ)hq$ކ֞L;JI>cH}.+MPAPjkCS5II[UFp;uI!T ":Җ66 K`*}NJ&pr:DK}(@_چ\J7~$uTgzׯb(*OxTI\]K~_v$ᙇlb_K1fдjeN$* WTNl & HP/ >V#5k΄Lj3'±cvlr?9J8L+'?ɰrص#e!©q]t8I M@Tv*&gL41-l}ࠁ0b1Y:<\{RLT8b1P=hz&}{ s ߩ=5u=%sCS ;w+69Y!*(*-_ 햓ѢNH6wSFyYiaT$LtW^_pUbHryOBkq4†+5\lϯ6-;*T8 (.68b'(p{ZHr.#bKR3S&axZ=e)Mg@)psē49@U‚X>Ao,V*%iJ*2g"p˅"D&!B(bI,,kȉFNyy qնf\n`/QH D?k/SÁJM6@ư@%d#}!d Y_ 7զЧ(T$#6'ZY^p?떭N Oz8mZؗ/ЬaJH,|*XhSYcܴ&kD߾eS卦giaݰJ͸L6:vU>umjjp̦n}ձsoq@ȼ7kepmΫ4N9^@J'X%G\YGŮ?,1*Qσ8.{5us~hǰN^Xpu/aczpu`ʅS, WI.^Gpb u<`I3o{Ĝs9[y5(DyҲsZ.QN -TXD2jV%i8 0Ͷ3<;-?uvu &'O= S) hɴ+E;gŏ,1iXD#p55o #`>5j84xE${tIyS& -sŊ/i4!_Tz<;$ Fpin'KBQ9!BRKxa҇D}>eR4qI~5s|(1%LIi%g}b-YL,[fRWQF@ 1z!pfL4–vbE#RG|@/ x %ENM`\"}fôrRT Te>{_ qb|,dLO~2|KYWL^ s3nLCb*gU s-./A")pq̉p(;hq͙05ϗK!GUٟE$*<;H1iO>%_RyG}{g(XD1FV/s>9LNƆ7S|dm\!0} K.r"m+G "~{o͂AM8US/8M9ojcCg $vA\<\Bt6qJ.AՔLZ7DTٵil19DYj`X}hݸILC6K|--[UBH;1.wq*;UWp1)e8u'%n.sfw)EPUP'g?|GR?b|mp*!BQN'J!JsՍ4N8#h}C$Ji1;SdkR8B,YHw˭<epy.I5j8CۍQ͞\JI]xm?\P;jO;-0|,w=/Y@' 4 fDO8q0rf 7mWYUqQLP8f^h'/c8 GY^?^Uqf tYg_1չSPChǾrv8կl2Ʊc3/϶EkJnraH|o sOv.{¤Qp}YEk+h3?6)۽r+7G~#c_O&rmqŕ9= i شwAW0y]4 wpǶ]|`c,*9磘a#W!noי#Zxa#kٷ=bRkOMW-{>. _RP(]y%$u  N%Nv9U"KMM%TLSd-|)O -ͭ) U8>=.0G7{5,Y+kr]oTI$b.٫sZ0bW|M**Y…GQ. (`@kcCA(S,r,q9I %("!B48OXNx&m=Pµ۠p}+,~2k^IP@~p}!d ޵fW;3saբ$O=^\hb*TUJ8 ,]~~c/rua^~aukUpij9SjU @ 9޴jc DfWIHz* jSS+;@s⑓MR粟vB!U`.jjp*S>4,q8vp옣3qL"g WY$^rR;O[͛dWw6DoXFu4wn鞍?}/d *&oYOUD4Rc2ߑr6b<>y!')ja[vpvzο@KS Yރ'N>%A@cK^1\x|_+ڱ鷡z@[Wg9K`kkJ>>jNʳ kgx惴?jGiALg@4(sо0HY>; ryF6 LwݣKS?V0.>c"^W1ؼi @7x/gĚ-z:M RJ9etY _$ ז)YHb[_." הٻ UČ8mA8(у#$qH "!Bv5 [AYHqI]Tg:H&e_MNӜ @H6{]иj#<"8iӯ>WB6%,* ize?,LWwRi)[?iҽf+qJ壥ʹu,@<^vddsT1rUy("_dI~B攃e%NTBߘ@^ %R6oy^yoȩ?"3wyZ?"?~؍Db2}qtkAj㧍Lvb[6xбc7O[㧟 ǎ= wZkgG금/r [up->׳nu֧q 떿S.;ޕ#`9 N@ H$tnR|!w߾J|'ZkKֱo&J(85 ͛ I1U2|mqW6 ;g75\%$,9ZI_#nA.3GYlCËkU 5萪hVa׮k\!'#:+N}CtD,lu$D@0 "?XTM(DI "AS-mH],Tr96 gP+a⁵kEA+qQ'qגnLq/13QiLi8ΕH&p"co9\>[>(=K( ߂ o:ǾՃc2m=d/H1|d|-|*ǥP},t>KrO% Nc cW>+EgW^5(rZɴBËk${)xW%ݟ#r/ZS,.B"ph6.f'YOgt,A5ۍ;0. (DB".bmT[$NYES (C"āt )пTqS7[WR.qԞ] d9dY`iC47'=\b&N|QX!YtyzrRPJo8rd]\&ph;~b `{ڱs7_« _w-P_|}U\Bѱs7<`5K"`ezϜ/gH_{,9*t'ɲM0pr^E({JmhN#8 <&ұ݆"DcpB80#\pנ :8[m{x;Z'$yiJ.ga'H(.{M$:yq$̹,Oli ?RQBKWNHR&C2Yr , [σVadC;D`PןyC|L6;.$u#w>:b %UM;KbBb",{X5hi܇7rrUfꀌpxL1KB ճ.eLEA,QQ,c0#CKC"(]h?:vt_,}⏹mpX@Xp5 ?mi/#=JX.&ukbN-_FnVZ©JU>XHWoVK9paz5tӼduCR8U w}N{xi ®%xgSjM\yjH4 DN̈́>WܨYh **TAENKJ,nIIiPϺ!B`"oQ mѬlv$IUEڏ’UFYߔ"P צ6l1͏-J ^\ ߹EKu1j$X.$*Ѱ*W[~b&limo <):z#aC3LY@ o8!WsJDUZǙ5OwByO<ϱ}xf?6QIͅ>?~]O;^+ڜCgLnMzJTBd!ܧb?Ӳ/__rw96@!9~mrǞ|TC}7[2&ئlӧ?}bұs74ED4o6+}N[|F喦6q$udoƆ1/"\?us/5)!Zb3 GqI?s}koiq(w+AvqŦc %Fǔl [[om&44 /%Tcc.R:V#r͗ykGGQ%IܳڲS"kK֥4ww~ʾ}_}fWб/sZz N.n{+.ƥx;ij--[l* %p0)ysnI1ESަߵjA 肪€==$ GBR m mKp!B@0  _b%iP =m )yT$ͳl&`4B!Dp|o\ݪTở!kKU Wd J+ CJv(!5 X9kD.|yj#xd'ͤ}."H$Ӱ 5э/kA\к!P(̋RBƛ:>+{a6 /(;v_a/bz>Es+g/}޶~_.mw=Kiy#w}yåkqd".\sE&#Wyuk) WÝvH_D&sM7cnX?1EbHDбs7<7Ek~v縹 x仿;@#mm|I'?~-+r݇WdڦVx_Q0) 8 Jp;OMV/Y,n©H[+g_?z%Ky=3Ilim6~"QU5yͫŏ,V=^K֙ 8uܗJkG,Ժ:{E~esIn}LJ6&aY*ZԔ5n:.a4"UQA)[`GJL._"ͧ"yt70q&tP  BՈ# ϗ֧>R4~0]i]qa’];+)ķӻP4*ʄQRDq:‘P\)JBG!B3ƲXɲx:]?kJ&:%Ii͏t gR5(/5_J8%pɜYOvvuI.^S, sbUcs+UYCAq BW|(-Qz]X%t8K5NIb)C\&mC.I$1(j3 #6QqJ>%I%W杝;VKcN{rQs\!BD:̐5^^t\SecyL {Kė\" 7^6qƎ!ov,w%$Dz Jl,o%!!/qE+Iix,x/+.0qϧ_qlfv HE|p Fc$&9#QЉ5(@b 0t:$oQ[U%b P:OP h]nO#4pq^ b+i>~3m"yYx,_QiՔ}6, .D6uWqČbf|U4rN,dz9/a:|DhߤB0y, Ѝܹ%%P˿hc#IsTη4Ǥk8xD (/\xUH}5 _ *GK஛Ra crҺ9Ij#Z[R֞i‡K+f0FYsppwbBT0=(Q74J2bɓ,Gmx'!B`"QdFH#!hn|mòod66HQ !iGZF" J  $\B.%.e X%_ʈ5Xn9.&*]G(( Dn$Ґ5ѧFV"-%R5K(G9 QC<3rdWnH8n("{LG>j[R jϼT"]t8P_4$R}& "DYLLc1n< &zB; d܆twt\( h_y⡌}L/YĦ=rCBrS$N)WYAk#dp߹=p깴Ū^],0Zl}4/y= ]t>(E皞_Y $KNYUBSNҢFōfεۣx |B?BTlq4%kPAJ(Go|"MO!BX"LB8B"[h5x=ήD*WcčDZfu ^%f ilxG W$`H-rR5/RWxZFi;RLrxIr d06Jt~K, SI}5G6xTaqv+$s6k$sCSx8mkv8m]R]A< PUe&YEZIL2#uH$B g/EP/ "D! $-Q:Jq (rJ}K>s'y ]d*}oKS7q5vYeIh4"%钬s,z'j _%|~<-Bh`0VH^ C$H @2`Sm$@pT]?-]dC 4DE,+3Y$״R ֎Ksg뾁]8Qy>izW'/BH/,C}!B콐l"aq@lI<Ss,D[u D+\6t<&P %pmaKۓK-i:.6ؖ,mh[T>Ks}%vU9ŒeB፣1}꛴?8YMJ<c5*}ɌUJ8 k\Uࠉ8KםkXD@3rd n8m[\;p)FoiҲE.}J8`\=/HSi"pZ}%鳭/B4XsN?o!BYbI.S+wõXB;1q9D DŽoAOqYNj*)lQT)_qF4`"DWIP`RDH<$"Hv~J9⊫ {{DA<'(QߚGHah{)֪;̕hQV)d<9Nٚh&X>^VO_Pac@ܺ)p @ $toLEQzv`T}MkxJϸs?yo7cRv!u =*p>9BF!$}~qr|H6!Bطo9pŦb9{![1Nsq+JLo,椏jGJ׆Zs49QҔH7}UL8op,H$SK ZFȠE1łcXULhF:8W=/5KxTgTEXUK6> &Q [tŝ%ϗ={J-X H 7$d9NfҮW: "D/$D,gÑ24]SALpVnd@W֡ mIB[G򪔤64,dXV5+%^I GKWSX}[K$>@%`@Hr.p;\2.Uv`*4Oް75K6!@)>.Џȶ~pN K O.cq3b^Bi&|1^efSYu|pA{߅uhpP- "D?49@;;6gjc;J17J'>.,' 9^/wl)Q !aXSZ}qR.Œ-` \ mPE&~l)NL(ghэZDZG$R$k$|Oo{|, ZDžO- ŮrO%s>]k@AUa@zd3`ҽ~gY,k%we92f[C'_J젟:I,Y#"DqAwHJ%5U QIH(TIJ<||<}`ܲD*tj u]$3b U,DK#=G slֶXƬ/9yX DqUp!ɺH# Id!H G,ZjG(@>sxYm{@WrE E.tea$8u+1˥R{)K+ x'Wف1뜤Թ 7'qtzN2;!B KcB[Vt@ϥ4΋9~ܱ X#V=:.51;3_d> nPR\Y=qʉR1D-Oh;\{S斬v$0UQU%N֯*JgĞ=".Q3II,0X}S $x>m<8~BrH)!B8p"LBu)HЂs)b%XJ'`ădn.YPi`IJϝrl{ήƇBk0I699Xgj,8*P$'1pU%Wz5@]vj$[K~*w=K!x4 A\ϑH&r \$ |&TTF=G|L$+xJ" 6!B_(a?9KFϑ4 b%42cvT%ġGwGa Eo:))J$ -AJ&QHz8y&W`4j)oS*_q"C(dI,QV9$U;ɴOL%-ڒjlvE5vv|JK&]M:KؙtYճVͩϮmq)u r@ՀIgW'tvug~F->B-rh;R[6i_p0>V?!BQ2 D#4U*N-x4 %$˻T wi0Z_jSlI)*N8%/yK$KB'ޫ4I"Tń&R%)$/" Thr+rT#sNRA1.1Y_d~Y$k_K.\%x?EHJ)L=, ׽zFg$V8k(-s~rzđK6N Eс%D!B@J&ZFq7MO.cpҧIϡG9Pq:^vG+X 1\P襡(I.*)kf듃ؔOrk[O"XfFrIOߵV{em qDLq8#Υ˵%,#+P 8Jioe$ n<d9PJd^zUg+8CR$9"ǑW\,+2*"@ %^. :>pHIR?qbdW#YӸj4uL3S}׾lx':R%d[Γ\%x$ym8Iw['QD[_/)$1xQ%"pP/QTk~!5PQڇRS#Ğ׻NHm!]\poYPGIa\ ]7=g`_#I];|J%"qd"D!7p Qc}gWQuN\IFS2U085Z!weJ 1ļz"'1X }cf$l7"U^FFNzN\T͝)Y[/L*S8 SE8lQ4,DE()R OǤek$|_aN*0C ΝuMҴOfViN{NkGko@A%w_UHdOB1=ɶJT8.XS lqy DѬn(AEC]4UO!B&!Bg!:0:r.BEcrۏ\q$ZS.̟DK8fԖӕܺ!qC" H>\JLKj_8>dဈ.C%7P4XPS @€dSt\{p~9~.E j5xǮi+J'Ӟu[ *7G(({&Cpv4xn$t"/ "D!,?;@;J]eoSrt3y6֧c| 8n51$y.;o,H8)p.[usꁔXPMZo2KDR$R)վ**-V2fI ࿜+^V#ft9E>הO뒥*y,@%ϋۡpai\_l4PKZ#3iNcM+g#\ei}~[?k\ϪMDhTЋ!B^7T4OkLWDB` *D2q<ˏr8g2Sˏ$;2t*)yrD``.%bF"n KmI؂DZ%n).D[y 7p&lpF69'a{.O# q۪m٦qJt:Qs* 'm<``P@UHJ]{Jk:i=Ez%mkؚYITRDp<]GjSD "ā`">CROv5BH2_Q\`d 4`hK*%@n24c%ĞLTԥrb%"p 4ZՠREVIeyĕSMS!`2;GqXǑ]+?x9HE5 %Xq8iLakj]:C%L1 ԒՎ<_Sn}iZ󎢨H{:ɉT (P{HH'U*sDpP"IV5$BI$mF"mSJ,zBq`G E+L$^O"p9I6|q2"11"I2Ct[ҲtmzTUuci{?/IGݍ5YԖj%‚d6Z$Rie/@ϗ`RD{p9duU8涞7Ol%ZZ""F4C2J_G/q}d>Kr\fޕ%;WVtCAFD$D!B[!1#fonS,N['WI|ak9.18,rk?|*/ RcrDwۭVRAU6'hJ*$Rh(V+? 1I…`EZ>*gZK%T˱I_ӽNфSxVД~Ij,KmoHw.GcOHB,JqOg7!RD2`IHVmte<4,z+j\b~WxAUK-rx&ntqtKx^F#HBm~(Y)b+*U*"I2 Zv`/.5wLq2j=qZ褏3T#$Pd BU걙($&j$ ap[EuBT]q'S$$ϻ*yI*H:%.u @0 b ܑL/C1 &IU1Lph{9hj-!p%Rjudٿq/%t^\WrIFD҄&ǾK&q$EEKecG'Ȝ̧hB#ܥZ=rR&p,DrUJX;pj i=X;c#HI ,R $P@BN%eĎ+Η(hEcv;6 ȱNP/ "D_dOUMx/YUaCUJI1TGCRYꇆ!`TgTJyEJ9U,GAԵ8_J(ڶ$<+x˛f:݂H>ru\zMX "2Zc):*&9ݥdePE<þqIz!| ; Q^=&5U/ QU}m(`P"|Yոլw B%\? nO?i!B&!B#A҈d;ǵC?s $gL"I-3=cJ]J:|]lt`N喷Ob+%E\J8Š˂'} 4R-z])^SZ/Ug7=#Ԥ}l'[8$TQN 7J3!B"> r ĢmDc)D "0ce$!H|rYL.f| %"]S%bI> 9`↯ -H"RP\E?R.YAsV2-*%xyW*BK[ ӤMK"|G4٥:.Y.Y=&`@O;+ή|dBt|B"`jw#Y$%-3%X*t+DF!!!UND"pmIr8J,YrlG?&pv8D`߲4AN%H F $qCI'}g CU DJ %MR]۰-D%hkV1CR+ O H4~k-r͗g8^ l{w;p)ZaJKG}ɕ ?NvKrBDUؖQٵb~I,Tf(+("D-"pt? +M,In_s,|qcAI9n"#qa/Y+:D[/x/,*0Ӈ@MP5.GE\HQ7^vdéJ[L$XI= P҇Q R1 48(KUQ8 y(U@yЀWϪӹB'.NVP$ Q8K=3lkT]ĥ!I8%p۳lK"PŠ!Bx&!Bc)z<@"B6$ڞmfGS+7RDAyO`=Yw;5cs`%ו\H *-%\bj0"?KX, @'֤[|Lj,"' TItw%Rv>U M8^ jRUVPSb5G2R[Y-H2V <;n@, "D!<j!G+ sısRfFP[8N+# ֛!v9?rj* Tm7K{xBGI>,)GnۺMySH)0 rRP+\hv)>x ->#>뽌c黵.0VYesV8t=D *&(O4;R-]vR&ӫ UЕR9Ǐnő=0H/DU* PID<;TT2ݢ$xd]#Kyjg+!BIHvpDjKCD8 ^>Yϳ`\u4r5j /7 vܠzHRR gmGA{%pID‘J\ 2.r%!侻NB"pkg* @wcE;K^/4sf-l)mp+z R0ф#dŌI+n ,1^+HpmYΫeTőM_w e];$w\PNzrJ=:cHbxR>'R+!P{JH>lg$+L3Gn;}f"D+$D}<85PN#P mǢPb2tY[@N%NJ#V;ڮ#Hۡ69\MB80"LB+h #gGіS#'۞,)P=n==aP2@'G۠5҉ԟ,v8\JNDCEqUW$.%&HehVYK qI4N|TB0P*a$$ \$#Xf9OeLd.gõÁ"aHBSʥWqR5dZJrU3OAUE"Ɉh?Ϭ;?N}_X$D!B;a!Ð85&ruܸ-1\,ƹxn \ڵ] 뒊 TƵa8`,S/c!Dv~bO1Wap[&ࠊȘ‘M`|.o%؏+0? %#tS;IH%OH!2/DU%Vj(qcSUH(`')p8( b#}%pN-6y!B"LBB"\PUmG69%ܾXۤXJ|6O"p>m\ڲCnypdTm˚[ 4s]fI-6+8Y`Bd-c\Ik98TEqDRRȁD"^"~Ln\d a JXK?g$܍>v "$J$*yo$D|{F^ӳKXyD}{9@0/<`!gNnmF9/gil'nМ^hdj=O"p!Oyi؇Fk_4̅Ӥb ߱g}]ŰOqd-)P̐#d=|jGMFkƑ yTu0;e5OaUpI.D+=UBTU=O? ZC82‘?$l"`">.Um:&` &r`J2OiΣ=gj| nj ]I&ǭ/ߙMP4&`B$,8òZ蒴*҉J/hrl8I[#\JAQ&$IJIZ$7Zp@imc>˝O{ $I3!'"SГ~S9[&xUd,"DL 3.G神6S p515Y azcˠu{ iߥW3)xBP(;%r ,5RE*yG9#A fEsc"`Zތƚ4OSd3G&,s7cp2+ ,b¬PCqkmHRak盂rPc8*TKR;3OXŤUtl %J%JlttI`|P44.(,&9NńSC/E KMD!OB64"JmO"sKJ﹬r,v9tR|KDbu-hԒ$XĎ&uX&rXT"׮*(@d<)Jt 0 6)ϤrhjdN,tZeMVuY)-R1kC,f/s及~Q2<^78jI$D5\V,מ'sѪw:VcŽ<Ȃ[EqyA2ƻ)K ~\reDr g:g/*I>a;YAC"^s,&p}'N@ M,/9Vr$E +' ͣC1 W_:s2nOXTĖ,N$" &syD*Ԓ%Tg!pZktvĩJ=7(έK )6'Kqpzv/{'۞>#4ήNz.pI|jS2S҇hdQ1 &!B&!B &ඹڤFˡ9&dTR˖1(d@,vA2xh7'uijT'.4%$p)6:YUJ$LK,tsa>Ӭѥk 88Վ)KEST6sbsC-q 'NKN{YgdA%FIϔPppb7/MB"LBg9e,qy|FPK_bLkmaKڏ.Cm0'_dLFUI|,r*`eTJ $Pőd>~$IIWcLayrQ.V.0F,6b!P"T`M ڲ89>nW+Ǥ0bY|A" rJ'b"Ud[8.[drIrqUZ9*q֋+D}/g4A4P:_Z5<- Ïd>=gr9ۊ82U8KJZp4my^;![AbqQOiQX~Ü:t[Z]3ې 8b% pxHT ڎ徥9 'kF٦8mZf-T%L.]nU4H(.} ldê|[p.ܓM6^~@U/_`@ՀYbӽNU*Q19 |I VL$FFH,>v7.ŕ!B&!BW"xYAUI<Se-1bH|% 4Jn(aE`4.!j$4<>5GPq%IB%vxY3XV@H&Pd*E]0 kI4qj% QYXOޱ:y^r=P TX鏸@7֫I̖[ JcPE;&0cP (ϦBmoR;D&qe4 gH?rĂv$<25dx[&DbKɄFKVkI9;^'o%@*jЀ$DJR?.#pUDЄUq%xHPuZ䒨V:U/UZ-E8O)]->Pb %t8C reʩP) /Q<{|IpM!VWJ[EYb߽F,6>k \!ˈ߱1BT@V|b.Lj"V zo5_y UdM$KO:alWca 9:%b-_"=!XI!V@T-,B,j4؏?q/P*lgvvqpڹiU*2# AIj'!`JrZ@JqwZ٫2һ~ZڗnNPū'&KMu_Uⳃ } LH Nhۖl펤"+E f㲰I!)p.>&pd=2 +h$9M ]JyD(7Jߓiل&0Y )ٳHY*GiM$1$LҰJf5˹V$0Wi`)]`x,k .5CSPqyE!zR=0KD'bˈh 7s,8H`eEGH,.B"D}?$D>jiDLmj0*pv:Itץ%bIɀ!_iLI&DZʖ幤R)DZpV(Xт#VɝF(֡IR0qU\Iwr&Z\% kU0zq`x0@DK\`^OW EW`JM̹(#_A'cba׃q+]{07[TҺyυTJ}RH+X~(YV)>9f쓿){8KqYE>MEc"$il#u9cC8PO8*B]t/#{X)/7LT@%4 3r,Aq28&.V0**8S*g].kF6/'YvK%\~ +/D(vayTj!غح^J8?V7T8K(Tv]qU$?|՚|ᖵ`\B"D/$D.D*[*‘=0II4Uimײ&x`4d x46IHh2@IN.%(~`J2Xj#.T)$4w8V;KA 3ЦJhBJIFy۷c*SK:j NI*R%RqL VA10V-oc Ie9Gm7O,SA/)ʒs)a"V1(>.O $`=Eo׵vO,!d܀TA#7MQm]$2H@i.5?HcΗhC{h$l kHUDi+\bUR˹\"HA C|qDq$UKv\ S졸!U(TUM b)%:w iӒU5.c^&(pπnHWED$"(DU 'ܱqh jC#EBlk64uJZm68K_-V>!B7#LBAI%C(Dp&TńJ'g!Pˆ4B?Kv9>j>>qo EI&%GLM~4 gip MtIeJJ8m۪U8C&,AI'ZeK!G)B%ֳJR ((Ug\`1};gئ\}>S_R 9Ͽ&/$̹{tU+D~[ВNCD$ >s4aJ^m 8`;b[EqbR%)p. ވXbG+X\S@KDa)0 U,VK˂Od&I98"!b7NKRDLI+II0FBbR 1SU*޽\IrbIAqdI)米ҽ\i/Zp6:egC%tY_!B"LBB"HJ q6I#pΛHb!Wh* ?#U9)pDѢbkIYHޭRmOGj㤎DM$ Y82 $I&WHVb XWj gܥɝd:g'hFVl Z,l#) y3{N\ip8q,zJ9@nՔy^*}&"ր!D5hUކ!Css)D"G.ŹXQ>C\ޢbM#|G%Mdj/󢏕8Wpʱ:VBNZҶ\=Uf X縊g8r*w%+\RMJ$<':_{,RaLR*TATW.,UؙF(CPBtKq{^JgcvOg/)߇Ny=g0.\`5ھU(6<]GD#E "ľ`"^rb0Q*h9 NڲYeDްW$LhіIҁdCj}3&1&%&V_R:~|S}*\ \2Hi[lI ,I0 )>Ю &/W8 1+雨33gCc\/"a/?SKYs$؜lX8p?j*l;O9%I^.* Ju]q?.,[ή={kOq׽ltv)$#xyN[* H);dL ^5A!}md!B&!B Id@ETFh[u69bD8eyn0 "]6ϵNT#Oa]zsJ't-dMHdK8VhZ`-Kz%.G RGLrW"}sI$K -$_"оhTXL E𾗹{@ cTYw#z#O`DהrS̠ v^;gɱ[|B,ewkEcPѾwќe9bͫ+vKcÌǁw ?tK(͟aҖ>2$RrU=I9͟\8fKY^[?8 }l#=I>b)@g7> WXYI>SkR)~RMޏrr88 w~Bӹt)Q(IBTU^HޑV8Dń>%HV9AUJhH '8$Ee~wq[!!I`MHgעl#HߓiVH^d eyJ 6xnP-YpөZ ƭGό0dhP&p:gp)te ItV2R!MֹN$^\jQGI0F"H8\%cpM.SJRa,P$Թ-q2;p8Ξƙa`5ђ]?7_2 |~3Yx|>.՘("^"޽W!BTly;".qC8EZ0IX.9㸪ljTh5#&"4QKlo"Ƕ)qD>'X U*--x"BqG*0HᬜE RK$7%%ZFՔqH89k;B |k6*N[̈́9Ւd:1Q4u:ɽ`bIISΩ4$H0@'$ RU>q*( )|ι5WF*'d\Y'PUIl2V9 %`@՛y-ӼMWYQBSͧ߇D( "T"D/7^f{8D>(Cfw$Incӈ$A9XUrĜCqDC@T'J<1 @=vVb /qzۥ,ES@J[K9d\` dkq>Tޟݲ\aΪs7 f= Q"@$e"-J$[$%j VۖܭnIaZha7E9Dm)TlۊInse78@ @wq/[dbMԹxK+7:DXh4Rcݷ2 v3?^.&fx*$H89l e}]"Eb A0 n j bB@qn(dz{1'ͱ̴- 2cDk 2Y/yA"AEM0`cR @[RM|Nʱڴ)Ԃ՚5 b[L D,5Ft$ ,$S9!Dkq\ t2ǚ9@:fS냕pɪeϹlzoyt!\rD:)>o5͢~'2T*J"瑝:/ $̱I;I%K35MI~ۗWmDw$f=Cnrl)r-WDk|n[X}sTUU:I!X|/}rl=HYs~H6妓%3`ˉ[5w{;W :/7u=9#l%{!m}3L~#ZhUDȁ #l;Yپ[mwALXj,u]_=lX{z-KJ&eЈK-nؠkI# to%г hV5 fS , DX@5 bJaˈ% [I* _Uj~I2% ,^~O-8#ތ"S .x<7'#qZ?ԢK~iHPf*zPrBKʏ X/p䳁29=Z+ȷs/aɟ7`/,fȰ7U&J1t:l\` V:Mb 9Z>+`ǫs?K*-&VmtXCݱbӒbq~°5I=,1%ZD!1m-Koص[6:؟.[2o̹c"'YlD}yf56>{IzӚ{#LUCQֳ%7V?>ԂXh)˃ 7hMF@=KPa:#u@bmx%cmq  65o&ݭ *Ձg,uuQډ&q:Kd,iP/T֒k$\M05KdIjQ,`o6{ 5lɇHK GĒ]]hF1@P$W'1[/20~NĞo#>+@ ~#p7ߍq-dw {k rr]"r2;k5XXQacSi+DNg&3ʫ Y[YTLzFPv\n+fV){9#G.vkCkmDt^$$ Iw,%Xd+_KD629.O>=,Ʊr瞅<ɤ*yz۽ȎD=mg~0ne;leA˘[ROl$T2/hu6E8ӖzH6~8`e9^m᥁C/#}Xj,pX[YX$$0d&Z@8cM7XVIֵdOJYH \^ӄ+Ò-cj(,Is$BVPrg RtUKt?ǫԩhEB̺NehE'm|U XcB+n'v|yM86⍣'wl_Nlcqb2=Bu3n ?-[x zĖ&Am6e)b5Va~M2k/MIIhԑ|eu`'RG/Zh¬sj~NMX8]F~sE0R#X$%/`}B*)j'Y-:zY+x}ΔOz;w v6nSSP3 .`\ eb9ۨO,܇Wg?#>5ΒAj!$R#xr|8p}ZxQV&LHZIZWSP׾[$Kp,LT/kŒZbfXĢZ;RZ6֧UZ;}Uq--8ƛ't.Tc3IfYuGJ8BԣmI̳sgVsm9mVb)_|i!@8pu|JGoOlsIqV&X1%آn:<U<--&V~T2Λ|sHFM0b'XyZ61m 6))6dҒǶq lJ K-vZZ lDW[dþB v`FUa<{?GoihB+g6:)0T8AXB$I pNXC@ GE#x"htp XTZv]7OȺmu 2tbci=LB Җ,$ˬNZV匸A6S&'gkr~cda ]fyݚx$*J s]ʁ%[jIT&:1$Z^0NZ諐O/$:o&21\yԍ@<~{H@ߠ@?]7=5x|BUݷ5bjM1H 1 n_Ō]ȩ`zLpbN$qSVיXX}I4j[c叼<Y9@mhSSm]@eσ,Y^R1}5#GmF~O)$$,rDi~wxݲ2$B ?%";5B*黃HQ/I)Ya_ΞcFB3NV6FJa$Dup[\f>-?@r &9v0XbY`T(AcHHaD븏=Q#iXV6?#zKH%9pqV*0 S8UiILri`2VeW1G$tC-%RtR!հ@iYam+= ,ҥg$ms-wV ' m.'0nẽl䜫$^qPoC!߉^RL&m;DZTC+0*X&H@S6 uA. .`+C&z}HTKZ˗(E "R.gv8l0LiS(X$0﵋D8R'a: %'l|$ L-^A?#X ɏulu@(sښ) OzJܠENiWΒA2[,<;ɦ!M$|0e,%-tP٤aOo?~Hv9OTJ @J^g6T;w *$67NR:۰~3j! ġe"Q>- a Eo˔Jj;@b"&9ʠq'פkX}`_\62,rDbH,!5a9~eK%AT PDdVSZ:d2&&v U*UD:c&B˽R @Y(:طfȴxcf%fX=YK`}hca2~'6Z-TcHz~9YdԾ$3,|t%wfq^*{n;KJ@m.=i4pC]{cc[IBq,&S۫,Eu\VpzD{, nIrsz 󘜃Ei!0j $%M(Q?Tjc0k!z^,el8(L)貮dod,^r4фߗVl˖=0{Ĝ}ncyrAExS٩"]'FJ IJGobm!ÈH`*":,T!a`O$Lˁ V…G@%$ P&0"J͆S:ZXyXZRF@)-rD%{L.QA+8ҤY*)Y-ـ 5 `KT~l]Ѥ7O"wT;ɠZRu4fOeJs\:-Ʉegq*ޱw$xK*}@ po`K\mnǶwԸK,vsFd%8צ]R'uX]Wń-cߜ̠yDV @5Lų<0@@fTM*HKƲ.ksK/T5i%X2VίT#l>[&<`N]I1&hb GPFRו]ɺli_,B&'OhڶHZ7jj'&0r S,6>YaĘ@ p1@X4]Mq)6-O < +;F QD6ճTK֔{A`:5)t_KF1fcw$0<7+,>Dך%ZDvU. -,قۡIJLbʖkobzKh٬̕ےmZ~Z+\ɯKZo/978fw՛Zb-}S@}Epqߨ6W&&"`E;Qzd\=oE>~*Nst. j^lxKb)2OXVa h[G8\h)jy R-{>M`t9*:O/t2^]OIdL*%Jc:;{}|yt_GRJ{Ҟ~^&]/c&=п}="#m/UKtܗz[fCZ1@ & @!" a}”HJ ԔQ&!8Xj!(gǁ%ӃIdҪRkYx6;l,gt⭷XPe5N e6&$,%x3F2o\8Ä]M0,sDS lb%wjI%HzZfɼ5e{=PF LXq?Ia"JkR)Ԝ v&Dy|6]/bj`l;vMkKEgXvƞ2*ppRIz\t;SFH%l%9 K"lyge #r8izM8MkOg9hL5)K._pv8yɫ;BIJ))%^q<}׻O|X]MliPeTIp['\b\,$D٠!mS4AǒլrNa-{f$(r+A4_ZZ۠ rN7 zj $‚+V`N}MtЏ CSI{ 5y9?Ż ֋@ XLd 0lviRz<-w<+ܐh%&+8f;>8j d{ER̩ D[h3@?mw*mx N}8gt5nЪ!ţab.㩘4Y4ĕ^O[RK2+~sY^ڿ”MZr(x`9љty%G7VX>`Y9,_ZR(l]+'ڥ4ık4!)mu=mޗ}_ug9xOM4M)LJbRsy6IN/k&̆ƲaevUJ۟E(%6>@r!&9Uêgg #MZ`Pj۟#63l*#kuX8Pa$&H,.,pZe,Af.gu?E&d3ym ,hضǺt0Fk9g,!gX+z's,C lYҰtYl g-x:M;:9uo''`8p^l @ 9ŧ_`!FVdv97`d71u5~w=W~D~Emf{2#=AEf67LYʛ%XIL%6ImVMn-l;&ux7EJZs6V;V=MiT&ф\)I%La9;kwX"gD4y9KgQ[ltvK0w~_hc=߭[h?SzMM Yja}AnS_Y@ ps@8LD)6ij{uwϦA*:hI@tcO" фX7݂k<@b,- `MX+ț=dc%K1Q [#DQ# 5BIp;{I|f 6d[PAQewJ*>1RjbAQtt r_oUUTw;H&Eo 7.cM'c/=*b5D8)V 酨-5 7)Qg--d޾ED眐ȡ9^ I%8䛰oϸgvͰ%zjĔ/^,p}OtBfiMz]ƾ#sN0۳&0ne;lg^(c359<8”G D #$\I pbXdeN!zx4Hhb-ZH+ޱ(C/{ }gl5/(k!0F6`;KI V@Ă#X$ޒl 嫺0 :3ǠݚMWmD@{ٙ3_`JǒzKf#Yʮ K~䛛sp}'U}pzjy9s BJKg%,RZ  a/={l-@9 #c,x/YJ%"m:3˾ Xh~:,kr*N>v;(XaM0 k+פ?t׷桬~ϝwϳ/u D;ɦCF)lk #`K-%Bsg6)dgcSH"9-cLS=)]M=[B$c@G(Gvnz lŽ%ls (\S)k$0i,{ zoayVGH*`u5jo)ф`S7ь~/b#K^< 5 et%Eʈ$K% u &kpEY{[^Q%8uQH AZȩ&-9xL4|/EI*}+ cd;+~sf3 (:LRu^ L^RT A(yX3xЉ ڹCǦOyQ$V^a'jfXS r:S[RD #Xyy䚪^N@Ojzy+'MQ.iU0q<{m#L/3BK M@Y~/ &~g69mvbc,S@74&,u6u SCLsG˚D_aDVGTRt[d{UDbH1k5˛FJa,S$V=x30JR:ς$@JK:`bJ%,`dISkFcħY"=mhHzjb(~` j'IZRlI2{4>Ыk8|rnͺ E[!0+Oņ9"{~.%6]8)@ &0B~NnrݧǒB؄YtGiAT*#efLۤj$}fi9婁,ZxV b%ڶF'׸;ki}}c> U1rwkxcZ,YQeo""lq4pr$'z;$ccݗu=Dԝ]μ}T9ƭy8II;%lVA8##ΑG@lL-m~4!ۯbC I pb0SdH>#0{]}2;$Ŵ 1D@ܯ[#qhDβA ^ۃCD+`@dF"|QN/*=ܪ3UOdzI-^v{e,X 2+^";a{A?%ǒdҒ J4295r-y+GYX't.dqƊ`Be,_]JƲi%YMo`?v=}2eӴMwZN/$!^T8p}/w)Mpq/- "x&e=~ֶi۩-UR5NygNd6fo3w/zRMn]g$|Z @C2 BN:`Y_@!& ϊFL1$ ykD.&R_9OhtA$0&q$R'd/D`Z$!;PVV;=J`yV# ˼lyȒ#]Tبf/m0#KV6qh!LնR[+D$\ KĘv ٔԜ}38cZ&K<^xmR&pxc.E^49V} F`N3 mr'bkXALsSi ]oöltXG1ֵH%"۰,tgd%*dG0Ъ^ۭ8,b-J?̏T3e/^[ҮRXJ%:@/N׎&Ւ|wq揕"$$aR-Nyߑ~a1XVqZNJ K2'+%g:h Kv1zyfm>k<MK76@TkB䖺\s65ⶑ}"u@4K}/0Nl 3ƭZ[8\R#k k959Ka0e+MՓUK\F֟ ǙfY *K~XsW++R FqLZKv]Iu4j-sZmwZms< 2ɩeB)j$lÄ&r٥Ҟ$ҥ~Vrá|ɩBİH#ާ.$~^ qI p`$BAeKmP:J^UtoHۆճH#}>X6dЖD".úU0p6Z8$ ,ZI*KrN8Yc,Tڃ4n5c65묯^;]Z's[ZXILԮ#嘸'R^JȱYgt,DrfR]p36 h3}:c3{b(]Z߿ @F T& u.o}T cU1lKđjd3OϿgҢ04l9'i;17,e]h[Z]7)n X.k%qgq+aslp~y(h2&%8M%O # b)s&Zdy|ޢ4^b0KovJe1v^d]}EԈ&Ham:l K~>p=;@ p@HzێFA+fycXJ(# G|Nog]MJ,2Ue܇#ʄ]N pc@H02G,$ @G<yo:ОI4"躖 *rZ=-є(b&0#XmR)%V$aV9< l>m/ŠwfTIC|tY nbڎN&5Iu׮Ro +GS\f*au>Z$SN"c!@K֟S1G&~agbr;H%N7-;n1}/j9LN4WE FMϼՏ5LeG1N,q#,Jzߵ|E3DiY4&L9ٳͩY}VMjc+ۇΩjՎ3%bnbձZh%]V#I,ݣzy)'OM@ҦthssxgqP=)&Ugmѳ#jh%V_< $le֯@ pI pCU C)r?-˽Sü#G*- , 2V7 ֘ډE4Q% .ltjo&ƭR?09Q$lZg<9R\b% ZLՒZV26[*hbʕ܆&k'ѐ$=.z# X7z4,{ݠ *趖5TI +IL;BGR[ugVqp=Unn1NZH@ ܎)]XA]۵[eVI.(<Ѡɨ*NqgK܈ VN7;\abcM>j<9kҜ5)5g$:Qu5S,r ^y:fDTD,l% ~oI-ֻ {y\#)Tit.gu0}!t]ٵ(}.Ўf30RF&VA0 *,1UKde 1Ѣ 2KNLp{`̳XA_7΂,y'IkQz躅'hSO dso j g/pEut{+ NnY;Ȭcʩk$̞ldOsS:mqk.[$+ݪ&$VVgILZw3· \, @VFa2pƜbtﻵLi#m]NIHbHɔ;yj#6R%ARj멑]BPe\%ERV#Dd;le;lẽRS?XܔPa[%-"5KI>-BS:AÈ/l8$X2`1c{ #G%-x"^(K~X"؞V8ad? : Z6Z6~ 9dv̲Ʊf vk-!#f<XV \5b4InZ3M3^< , &u K TROL2I.dq WU,l'Lsv.+ԧP~ht!q3Z ?N^ 6>.%hʻZ.tܱ,*aS%g1y-Kf_%-,CD}Ę^CWb0+bS8D{aNH#Edg6s2ND&%}ϞɢfR>䞞N1X8eGjiS'Lp{m@ p~I p,"I+)oz$`G׫Ųdֺ Zhv1>,54,ezݎG*aZeXH#ZiDNʶ|RsMFjmMr = ^Q*ԛz- k,!$HЎ+3oaY!^PZ)x$ګc%'Ly͝х砢mwt]ؤ)6Yi/~ZgQrZL]svΧEuk'IzRoeLZxv;K*#HpZO,)K&9y0' 37Av|P\rv':ǃZRH%V)`6;\bee}H$T&!&Pg ayqYM A֏7HNiX@ͲaߖS%ae/T:>U2#he?yEr R3a V4=[2p.s\{Fv%R% LxV8kT.%ӡa4gɻZ5LzIddwOl%fEK. NwRKB y> mc2@ǹ997zsbh)/W&ݦ&0Hknp=+Yxy1jLږM&`KYIڷ9&X"XwEkVJMudwӬ&ImlKPuYk}ZM'9gpf3ȦHJIql2ʦ$SaEt=]$MއE$h`,E6"ضLXJLPa8ZⵉdnoQjkLZJIlY0в殩|dT5ak,uD&,پVľ_[AsGD Q*H*$Zk;21,Mb*oIZXbTkRvYRhL:}) )_Ĭ%x1i.'ZSs.dz6M“;/WuBdFHE)*4GXԈ&-8V^}N I)C`Rn;|fW!e̗;d|}::iPmpp]9"SˆBTi!0um{S>-JXۨNz_N{={ad'wS;Z]_ͱNF)`#XmlR"ؾF1ELLaD6t=MHpkFDaZB.AYj&#X5h!N+'Q"egRrXi #}M̞mN=PvT?pƆ Tcp:-x $fr޶,î|ot$e.YUs~)u37F?Xd .L~'Kq2Rc ɅHZd J.1nTZt0~*![-CpY~[&X%7XZyu< KBXS[֦ڋV8h+kH%fdM&akPH&p"FGRwj,tVF50uԷ{ wLj:Zbc5Xq:4>G}LAdz zPjVzԮL,@ӳYjӪ)x%Ujy̲D D,N,_LN7,nIdJ=z$I&MrTg]%>ҒfNDMh%-$V]ٗ$jOօ{.t\t$=UK 9z4kjղkr k痝E+-y T( EPeoH'ݴ {%,GqCDIH9TFy9Y_N* RXkr4)D:pPm%K '֤ͱ;X麼( MyyAFf;lg*&6AphZ=$fSۮF. ;@@4KZʙr M ZbNZP%!)D+2r O<选 4`[4hsD"a0Z*'>"M@ FV͔i~k SU / \gm;lTv,/I4PLB.F1KĵBp$D*lNzZ'pa~|\=arh#`7-;/8ej^ch/a Sf1:1wj8,39,FeP'εndm'#,`//$a94-*"BrUNz&y [c%=? K\{$/dD;;gфB4"| ghR&x-}S8gt}3ե~"= 9罚ɮJBL3+۰\"w2T$i!6H¶Cj;zgGLop""l%HZ)چGPQR(AV,k1ُǟ1]d6EBaN )RdC"#`@e< ?߾WKz,XzʁD1ԄwYp:hfD+ t A[۟9f09~zIɱv8^^V3+_IYG/P'jMXO&O}j0+$A,0']{';M'ܨ-LCrx.g|eF83A:75bI6e`<5\n$ \$7b)ziiuw`4b)mנ}^oZN(mUM4)>s[OOAu,uS3gMqlYF [Gr!d^$#+=N-s?gWX Z=|jV"lvqym]@I.,K 8 `xTI:MLGױy4Da@*lP"zeڶw,嗈E#52 a $'۶rM) 'z{5%z%H&:Xd34di]6BP%|"1<V*J":^p'lrR&udy 9hk@hֹxק5$3S\3A,@'QoxA[/8NPQu&Ȝ.qƄIJ.eXN\~'nlyvќI<_+X0HَHul_H`帮GZ$~"#0˜RXFԟHdH KKtR)~3!^WD6 SaEZu-nעFR @ &!&!KAc"nbJ,kR뇧F &o[d[﬌c&{# k۫}_vH!ha핲yKnXfp^&{9^e/*xAu}X^Ս {dI:Y`2$0uLk:D[~U-Mg'yG%KҭhϝgE(tKlq65|?Nu)%_@ 79VV\-8%Қ& ̱/9 _GnCsqoi‰#~&MRRCp H)UpWX:6iC"rF[|Biʱqh݂'%Usa2OZvߥ}E )d]_Nt[Z 'LAFpmW"H$Ar SQ0iA a܂s~WCٵ981HJɭM܁H@N"x=v@I mLZV3wm-R?FIw>ӟl?d |y%,1l٠!FZ03L&LLF`j%˞akɏr]W\e{iR8iNpx$0| k|@ \nޅ]1#>0-ga97XunBn$7(V?j* =bZNG=x(cE}Ikw+`έVu\n⑥tYkB" G)߱֠fKE95F㾲H". 'խ}G=XvO();!EPPIdȦWMycY` bu¬wtj,{@ 5NA &XlvX&X(5Ucغ0QD IJQγYpJ,fE{-¾k6%7]kZTKY;HBHYX B{E~cdc8Zcug3?W.3=ēDh$$ך%Ɇ`܂ P"gq"39֤Gpa.MA@ @ ƤEH2G|'&4+` Lgj!PUٲ/-/pHι(D2%?o2[MS3Ԁ IQ:SZƆg7y*}r.LEp DIR(a<-`mkHoahhZ˾IS)֮.{Bd1gt;vNi 30E°BpD4QɤB}dB$8oP@l `CG$9B4)D!Yija߽>jV2;0 fQ0QZ*O 'hSֵXg/6&%?vgA#`J!K}î5̲`K<v?ʩTxɍD2o⦎\eMx'/Ź(%WaƬ\vOs:( LߎbI 1j.9orZ|49Iq&4ǥ}L]LEiNVsd#湋MXY tkpyru{=VI%5)ea~UvDz>NWf$}5O&I2m}=p D$0]Ӿ G&eLҲ/M<T^פl|?3nG4]X=) (vɧaMVWϲ680IV&-`coo@쏯am4R)AGluߪD@pPe6p= -M2>UuTb!F<@&>#(xlI-#y?q' )"D/޲޺5b*&^_qh)hR5Mluf[^2fa*e)I4ϊHr,-}=yv1" ^Xd?Q8_i@ 8S}+GQ]n>FO0,s,Ũղ̡IźOelyϳq~Bc=Ubz"7r)5/ @(hQy5+jU&RqB"\~;oLUv %1?>80#0ۜת|-p^{2\pPHq+~*gno^,y߉K<% JfuQ_;I JAt9S5zDXP֎WTD y npn۰ܲAODa>(gsI%k2N>˲V))D$ -bdh1dfMs$:@W__z>bJ 0BZ;aEe&'VE&0V\JrH-H&9ً5J2/ G*9H6=.p/ySi;Zֲ|mH`L?ۊ9 - }Fб'@d:65ة ,J~) p8#OJpGw9~O&n '?uN9"s]N,I+$b=ZXZ 8y't9Xa16v8[^Ît{ۡR,a5%-jKI$J#xd' 2'w0޲ѤM`D$u]S:zX66"y9 փ8\{DZ@5-!'Y^;8[f{LP/v!hKWf736lub6Gxl(l H!aEi!|pV;=eIJo'w!rmj[s(vC4 pTb/SfLҹǩY`{H4H*]Eq-y13]?-^NKʩqO*J%w)kވ8N^w h,;QwfS=^z⫧Ď}D7Qҥrɦ0{19i'M+,ۚD!"f$6;@) kYDLk):G+xZ`=⋵^p p@ UO+GVvrGdItt7ZS0W3)udKߗ$("%&gH ]AnWzS3iR5$+H {I %$:2Y6\y%OFLhLƤ`-QcON$>KЏw7@ pqFyw.5fZ(U7ƴgǩL$,\C*SS #d_ěg'MMR | *eҖE8r6IB3&"XĒ%0'DP)hB,˫9O%/ǡ)<,sPńZԯy)h2Id &;PBZJ(O@b^F5vT+)urϖ&t+]/8)*'ø#ou|PH@ #`S2}>!90RI@``R ~2۪'2\gbTp$`$@I1pwdͳ` V{5 :F) &e=OJ9ZhŁpOOvui^$ښƶk6bib>#h̕`%!V4 8{Ʈ\4Bj^yJ7$%IƒeDjX^[<ϧLM>q@ 88D Q[? ܰs#LtGiyي ZIP2a플'=5fػEf<0Iͦn$ A2IYʗ0t_ٵk[bgDv8)- O9Ͼ[8*ReoꩻI )%Ls>S+ҥ^6fRty-Ee}M}ׄQ!H aB$8`?JYD&{0KM>a$lxzLk!KP YCWo*lKM]UN쩣L.A"#ENQ#z:&-`-]+P+iMt"c4i JNmVzq崴њ`>,)ĒV;:s|i 4xWO-vpٔt [vC9ړxߪPE r&7.=6ՊNB?griDZ v9V8eP5a|Jfe'7aY]5-Ng{`jIMu $W[F:ryIwJФ/=-+DM'%83e/ I#L]*v"=9V/ 9v8ۉ"I,C+f5='B5&u0+ $lL ,V?tKlrLI 'u4)#0;-IX#&[$*zTIPDS"cln Oʍ;aYy_XWبzZl t:0bdeKemnT$Y!LYKf0OX9NTpւzPrG%`6ngjfhv}{rB4tDkUIck$&H9?EΊHtLBpNyr@ ܌qIMn 0_U'tlu=NPzeNؾI:i-Y\l&̓-z,c{D&_FG'ZWה1Vrr|b7@5NdB(anrj9C8 'VMN9r JǔDTNmZmsw*IَIp-#Dqi~", 3HHpqI.:eE2/~@Vkd@  \H[_(Bw_~0 ѕx-b3qίIrA5Eʬ6 !}r+MJ!-/!9۟~/%;!7f)Htg-(B#]<8l &y\LFABі9NH$HXYtqj#OE$LO {,ʻ =iRq&:|WwoB5f8&KCΰsMw6Ah2Sez{l[TPcZ/m@Y0EA˂GuO kT8a]VJZ&O6}`[ HI$`hG hG"el[o]KkA-,3}4 nx/ ]GϾ;VaE5As-хɍZba|g /*qYdI+La_N2mD'Ϊ;ٌF8ӞLa Ec'c.ubgG2)dEC,rrhvBhɍ1R/2H-ײt-lTW0S{e5NkͅyЇ-˩8ZKkY`=GK7AD'\ROχBYL}wFho&2uT:DdgsF8#t?9(mzɦHM!MIwhQD]߳ *R;3J@  V)u4p=D¾}ir a}jERF"ABTMp$upրFOUʼnܗeSS5670'j$$۾69AmS'H'el|g?O<_2m<5'L"Xɼ8$WDCT潗%UzU>$}6b;rZkbqoK\X? ;%@ .X&/7i~p,Qz ijO,ФѶj3oḠL!Lٵurb ̶Xg9#_K"`.L[ۗӓ,$$đqt[lORfƱJv%J,߲Xe^fZ-Ъ#H($`}T.ۗN\ŚM-ec#goTPbIYvBB)&Ë́jhؖV2dO5#Ԉ$@  8cME,f>W>V5VctS0hу+P$8 c,Sa5E&X$VGH+Ē9LV_K4fW0ՖV2?1h^y05'0咖#j ]:p];wT-jMɥCG2qʜ>X3RjuH^|Z}{q!A( Ma<9e~2UZTh'Ms}$9%˼=Ma %dҲ VV"5&`5ФH$z[^Ze߇G[&j[96}K)g됧:}O~7ʶӾo}^-0V!AR `Rbu:LM%A0 \CUDb} S4a-Noc)R#X$falh41҉| Ip$\뙭Jڭ_.O ~hE1{mI X=KAƺh {4)EU0сDk`[B,`\|rI[c&,?hq/[3jVY}Nj&GB"87ᔧEW ey&/ I@^{ouL!IoMucƘd1ÝX>\O5g3! 8zw$6n<%ܳUFeo5(CIwtV,Ng׵`~x6xQJZ ?9O,[z۪%"SUC(¶]6IVo0 TiG[[ޓGQ*vGq&ۖ=fd>j˚8[Z1di@,tZT,a}꾯,bDbիPY-o64\\X K~wJ(MVbɱ2]K  ^>K4Ͳ1UL>Ԃzk &Z8Ym3^/I5DZK #k#%x"j{:e.%ܢ yLS%bN/7ӝf)"&:9U<X8ߊSG5^ž%7Dyo "YM\Bºa󡓊:>ǭIz&,}ZYygLzI\VjU4>WLfp-Ob'0 iDe]T$JRE<;xOq'艺峐O`m{B۽Iyv}^] p2N`"JJϔQX} ALW@=,@ nvK8>jX/,oY?Wljd$;.eh3r5=6ˬ/6{9(/ߣU~KΛFitXnB(9FDdGъ&E-,Oψgr1^W)II:lChp-9}wQ-amTH)#]A}X蟫(v9[2ÞOt~]O䒲Nؾi-‡'HͮF/r7#S+ojT ~Zmy (-C>#h,Xrmr5rC$SY &q1s3'k7&NZ8Xl4YUDS2o.Bݝ6ObH-ןkj}`ǥZYIw椼Sjh d'(0 &j&Y.x¼w?{7XY )#L-!쮯meksP&Nt;Sag0_Y~## E&)J$,ϩ~>qogtOʲ.b6}Q h[ pŮ =#jಥZ⩝0ERHJ(ao0T3-j$ASa%ze)c匈RHX_힂dRHPdw.:Jr Jk`%vd) BL5DֺhSS,Id_p/fÈ VAE _ ,Y?<%4ꋌ8Xb(0/Yk6c/̓SzJ9_X$'8@ "F1{d-A7k̕tf.!$Y #!Iȴ'МtQ{VBˋ2`Mc'P td-r9@  cꬄ7>F21&^TUUYhiX!~*G0tlrB& Yyi9Ǽ`^t$_B ` %*'IgJ:dˆ%LF2D.\vO^.v5SфM*)fmOhRI'ֶUΩsw8q-0ne;RixI(~)آ”W׫oƖEФkn}"'I)w p;"&[H@mKMMiI^.^O5уFTA Y&zH:H%ǐH<0nOw,緣e-ĐrC:a%'ȔHp5ád®E*B%ɾWD/=əq z ozVMڸ?$X*+ljBw$\d.ۅA tcn @:pc J.?m 7 鎧/ZVc*Ay!>Y]tvo[JmflZi4&`YJIA 1!*$eԵu:˛j\WCH]Fa% &٤UIJ)T?au d7g[ kB4\Dd]3ɰ_= idob^.miI -䍚 J"Ijj)׳eMf gq Z> cUNX[V,LM0kd" LݚR c:ba'#6[,qd:`+U3B*a:}1ebZ>z-{CK5fC$G.OMTiQ1i!:XYplrؾKp;v$JJLLgJbG&xb%΅&DOq@ vnPlpPUXp?>'YN6ұ3)$qyrΣeճiT4I&9 ,$-WpBX$(' c{Iާੑx9: L@(-:)u3bN-1gcYݰmN =5 %~Ml`҄UM>,5V(k߳hIn{vQ7ٵUMvJ'YάwIA!ЬJdx"HҰʱMT)aDFtZl3`Vi%o#mZʑlRgSy=U 46p[St_,˰5= R#H2$Y3k@|h67F+e=S9밬`/t$;,JeZj&v[!+= 2+,(,!eHh &XP&%&p*:se*#vT:4M%_RUxxfhC򟧓$[1%g̚ӟ+0{(@`x@n=p!Z'aƸUNd13:y<bg5geNK^)KTD k0dY>[cN|͙ݍo2/F{e5M69l.+\2ޖi ՈuvgV*`=M,.AhJ&ZE^Dc%Z5Dog!h !EmD+Zeۜo|aAVrdO}hQ_ @@)ܪ@GD2=\ʉ&XV˩G̦> 6ŲƱ9>j5 )hD־կWAr|pU-pXb%%–"dksj2uZXY]Ku5:KJje,pfX 3=& {CrBxs$"2[جNdӅVRطDX̼ @ X6&%'[Һs;7~Zn>\*8$1~&# -qٖǖpG吘:d-[e2A!f-I_b Fm&X8乕zeڜV#al 'KV0,o:~ēclr8b{Q')zvy4yD['uvU=}k`""b)x&5ގԎd@ p+"oDV۪|DMH0Z%e ,p{$(XqУ`h}7 B1a_ʘ% ڨ2,XX+lzz:_ xj ^%фc5[- Vt}΃oo|q[vݨUڭ?Bu&r&,ՅDIJLii_sۙg%2ǴM:7ɸ'0`?^ۥ0WuS,%lTLJ=odҺ~#LkYr &( #h JZ)*G`8z;MFTo4pBZۖuˌygq2yk;l6}˘ۉIyކqYMkHpƕ "g òф\gc1OnEUH*uK_hsԱ`RՖFe ` iDblJ%UOHdMA:-dϭdj_..xH![`xl׫fkKd}UeAav;ɯd f%N$᳕?AvB*jnx:8Һl)^z]Vkcɷ%K< #ĒpG@ "X7$nu_2>&srAWq4֜qLJ\}r4z.;H-LbYQ,YZ>fSjiBa\?L4D/5T%d%sAcm$2]GaF&iזYXKY!0 }u[K= N'6lߏXs1w?褔D.0(6ed%q> jKDB HD߭DfI&}"X$eRt=FFb:8($ ~}Y1`+$EnWQ*/[&|j$̗M,BG>(#MK_p¶9' 6 -֠ei}`DtO5N:aMBKd޹\)kzjkW7iuO @tP;EX{CtA9}@X+h> p)4ԵW,Vsh9,/erVh@w{u M@ ]3A%k%}VH#6Gt]gPHlb:o )Kᑈ4 EKH<%%;rM&A[ ';^D Xx ]J(~n-O~5besV[$68dbYk}"I PSUbF#erO@V z, =dݖ5oA@Mjg׏]~E9?)iaޗ8IM,v'J18a y \<]j2*~MZB4J ,{ID $mX3U|zv-ٵϧ 5CL䑜ݤ "ÒS$rf䰘 cx̅X$V^=yHzB_ 硣epB*au:M,q^2?]$G)ˮ;`Yq&{Yfd]u,K)Ա,x{Ślb,S}ljøInn͞DRN hJyެ|#\0 S!a:IDGۜi+nw$p)9HARX\b폵کZkڮFH.2mVoA=kAV()D$ [lcUZ,t48aY%%H&9并9 d]^SarHD rX?;zZ<"JZ/I2iu쇘Og8OjVCecӚVJzU );J$e.Iyj%@ kl$s)EicUe/Td䅥vBs‰oTJ S6j;!n%:w7eUl%l`2uPЪI #hV9u8{)py~~rM:ώwοqM4DJ(e_ڣˆeTOEuQ*i!e$`=["I!<;LʶVqPRluʳx&HE,HQKP'l~d`< .A$ 0@QNiQ/i%\x4qX%gSڬXgy?xPSCMRQI6K<$V$q^"Ma$bZTXmZ oIkR-ffZNV, Z1[KMDlS5~n/$'/ -.'Gv @ 8-p eH0hnGŐ19#qsP fFJƲ0Nu `sFhӒrB"x:EyIML"!H )3 #hZ¬s<:+-}-ecμ&ֵ{2l۞;E_Ხ[!eIQ5)˺ls{EM(ٝ;jm$$Xfþ~$^)jЪ#LijQP˚P-" 6iYXv8 AAope}L<#h5 MB-p {wLm?cdfSmIRL !"fX9z]gd^Sot_'Jj*uO%`сi`xtzV.C%+ }}znSZUY.Of^IX5%$@ \8.s_qecG+Mtp[Ր &{.:^fKYI3ε ߈xJpSmI`ֽ$j*'3M>wb|jVO"&emv:Ko/Fg0kj2"G+X'KѺ>Пxo,7[O02<*]Kx?#LuRAlG2I2ݮRI-dK}lM@lDz`}֯.%@oEϺR/A2&:$~tX`35j8]N!EoAn HFM4mTOp;M@kG G,S=-^bUCdҪHHZ*}a7yD$Xު'0f`M$C8!#yNnJѻR>;=y_rJ,4%7~ 3S2cT @ y/1EhO/kkp#2YP8a3L#MFq&%/_T]} :`]7vx9M]ɦۜ)%"ڢ0b|. dwNl&?5DL,ēL2/$cZL\)4Qa5x?01*&MyoQSǶ{ǢAΦ?;+bS7KcT5,J$4L4amQ+a ng$p5;V'Q4٤U+ݐsנ83N ,8V汁͠=0xAA v4Ao&>kg :")ĪbcmK%BILhcM`>SV5Ey)jN#SvJLPhĵer%B< V 5'pG_U '1SSNMN )N'OZ@ w978 XAb֣U*O,Y%{M $b5)umy"{Ҝ쑪61sb MI)5/qXpLP%y9Lr%2#)O:I$<# ߆B$)DC$#sn"E@r S񬓘B ZSF$uz.N-<̔J5R'2 >&aoSH%2ӑAL)?CPׄźOn p#VKƦV?HKhiS3j0g?+VSY1nQ ˫7HkU,tmNQ$oDzRu.5bX'0ٖަœH޵;&Kұ_nSN@ c;˅ c?k%yqy<0.Sڿy.pJU$7hhEaoMM!HްHV}6#QN'IF.ax)e-tEZa&*XuUGFe}AZcnQ r, 0b$~$-V6(TNjx Ed7?3LBȚJ.)-&,Q+сRb+,FzL}z 2Qii$df]ƖEdppƒ3SJ,N4#$mojR:\pNV@ EN$!3"numVX3ѓ$M6BP%w]r57T sku,U&.<۝B4Q2<] *ZHcHPDg}R84fJ2i-&z S4H$^[N"XEy)Q,Me6\ϔ6l^$mv7eDd0-O""""&鄩xJ%L)8 H>A"(Z!mvcc Tjx64|kЄ fcWZH:J%cxvDh+m Ʉx/Ol?R; T#%}?G0Qgv8sޓQZ'Clh;}=~<+R?>'#zzir&}`fdܟ\OE+v@J)^8@ ܢ C|r#c$ 8/g)Z:*(vc xm7 Ņz1=L6v'4I`o' $-|UM͙C:qqsv'H A#z&x 'wmL!v;#RS-Ys_YGF>߱dTwpVNIyZU,xJ 5Cmbc#`@KM}/۰6-M aV~C&Y;aՔF nkv9bgv `bE4IZKr=A,$hH!`2%\Lh¬r‰E`DLkTYݙ~gR^XgZkn,9UM6h.*qO:$𮓞9AH͈:k`\2!ipɁ x@ p.ŘyySCVo_OҪKuDgX@w_XXǶ$&3K K2Zo&KVBeWV1đB6a*'m~2?% "܆F}m?Z SA" "H_;buSޭlIQ.I`S~Jݝ}U?S89˘INuv,ojG!^FO餦N⩕IvCLa@JL˪#`զZ[5 &Ǧ2!1sʈ.t V4Y펳"Y b$ =[u :zHzVײ_nYvm|JE~h 4RsfhIV290z# .gT=Nq`iL@ 8z|8"v鐷Y&gyo6YTO1}7彘IjWQÚ*eNPBW˫e;B F'%:e QI-Y T.LDJZ,sCnL|=U!M AGp*D눖:L-PEYĔl#nW=߀Meoe3B()D-K_fס #*j #JU҃)x5lpC]"~ Aj-3OX}8m&}7l۳~K`¬sJ1%`BhRorn:,N Il.ː8ˆ$!S)mV [^k2#"J ɟPs,uC7yC{ -!Ԕ0jH-y̎(6}>[ kdZ}SP\{:9v~3ɝ)W"G䎻+t]'}|3y?-g&><Ե8@ -lU2^[$Ik|q[Bid2NٓLAd^iIM>b̈=;S4|hQxbh"RŒJ2wF2:XAe},1,[~C[Z zfS#hBHZkReu,RK+BGhl]O{+S?Ѥ!o \Rf$A CG2 [6YکY;@VDLi "Fg[|h+iF@a{~z{kL6hbm/%h1Z$(Xn"0K@zἍ3I-Hg9#(@뷾 F@i8#1ecrF- >5KڟIl/NOMc"-ĩ*$K/r\)C |q-eGƭ\˳gYyϑ?^%z+/yyםնb<>?> /?$='<<\r&7.kz6Ɉr1q0 4l1ղߜwzT=1 sDƄ"}5ee3KfQ9mMy6<@!hR^c M&AK̎Kձls&d%j$x#H:)k" #hIC\'uG@lwvU( {mߐu$o>6$aA$"VJRHKҟڿC#?َ0lp,ݖֳѰJՃ +ro04/!Զ9{}A{ nJ aߝ3NR :XwKIKDy%1=8na|zIjz]Furj$V&[Y+i$طN$+ ?Km;D1rV'א,Œn \{W' <)Kׇr}&O_{J>#""G卿|<ϳɜ3\vM\">+E>yyϽO/ [L1pI6\[O>'G<7vi0S㟴^[&WZbs1=ž/LӇb`kǨMhS,H%/ JqW?7>*G,+h!#X}1Tmjj7kzk6Fü=M*)V9Z5 Rwo&}+FJ&5 #k$L/A0 ܪ@2EDjj&S8adks92b=bm d0҈'L-Vi]w фVq V8ZxM"\5$=Ɓv&oud68>Ţ1|街+@s[pV& k,pa'"d;<02Q&C/_xG^(<igO<. >/yCs:A* \n\ן=9x[*yMJ%׮]]~~M}Q/oO]% @FK^kT{qtP7pH~Cd ٥=n=kH)5ɶN{C_yF0av'c9g &c&[I'~R^wjc]5&g#";[>B xSYޡX9~3)۫mS&1TIe_!#ip"@ibH"l=# 6"'pi)2OIJ['<֯cH&9K,Y660b"OK6 Z&mר67Xgw>lˆn,U1l4t r&'pi]oKdugH.ٶΤHGnbd; ai4+&i$x4ۿg%Zdtp3|MW-Fp]O/_t$py1Q|qyӲC? ﹻq__;)__*>lw}Uk~;d܎q@ pKM 8ƹpu&)6QX>g7qrVŚ_ah4DQ<-VNc&nok M'$HRKw^_<_ ԇ?#L~k.;<rm{ ?u\]w%{u]{EDuUuW3?Ny޸P@ eNdrE`}r808X| R+Pb΂ֱiX Lo(XfH,,[^8DDLbI)r"U ֽV7zR&Oĺk,rIR:[omM~Ow9d0Dd;lil\Ke_K%bYߴ}S=aK(n'tq Hr̶ ˆ#L[_k'=7YLv8~)~x%ou(}>BтBwM<j¶uk eYR`wKs8yc D_r-˜J1h/klG-gFbA J-8j!ͯR2 ^b'Er $s/+ݥϤL_,v~{}%W"?][OwC/~@2!KǞ|%ݦSooXM.9%н'|M\@ ܲ`qF1O\`U{sc!Ǫ$OJ n?ah6_O޹RwqΝ,Oh+u"E5&QIcf8YV}(zX:H R#YJ.фY_[R vo,S"Z=TJ7n#IY9mMH&V# D9,J#6P ['#X A. IE@;gxuYX^T"!,6,gmBng8?](%h).#X),oX0'Δ/ZSa[gzmi]~tk`CsmsDUh,z[V8vb$3D?Xb$yv8X6Atd*^+g|cMq<~ y~ۗ۽\y=Yy{> ?|śd8]ɗ}[~Ϸջ 95-'Av-A69iѱE*OsEdaO8 ֩Hn2 a{Ng$r,%HU+D$0rIMDK_r z{$Y[Ӧ}?Xh҈V)Aeqfym<+{Rbu}x[P+߷ޔR&9/\]j]/~',ҥޜX&HA gOm`[. B7`t`* ~F2"hf*& FpضH!Q} Y5[f"-5V6Z(NK-/= 0،LK=3h"3^i-[8H&i% YC|-g%E B buk4:VJ}x#g8-b)$I%lӱD`-PK<\I)ozWwow^(pg<}}٫ ?yū_vT9ga7/0 ǓÒ+2#{[  ouER1yi*&f!+2(`OʿWJ>;#}\Y'/7~rqA@ ń"t+,+o7(&Ęs Xi>MjiR5mB6q,NRϏg8MU繱C܌!Mɲ˝LY$-#1&'!W!h~Ϗٔy?&o8R' s΁,K&],'zHgb\a`CEf5l.)]8S:ܯ]$.]M[o%W+rNl|aug⾜SM2)K޿ԵfYPk7%kB @H&h{Vut[>~JSDm[z$HD`,w,z~slzswnG$̏S˧xq3]J8BrwA\RA H2\ oznAqˮ4Q#Wj&c(O04w!mх'l }68//;g?+V^ȋ_"y["=|ݿ#yg@"cgy>9_Em]vM)|;~'~kפ켧A$WJ5_#^7?X>Ol@ (AX:<>@vv?ZV>1Ts9&ߊyx+ *"g'Q?| ]|N5!/'5(1/j"|G.GHe524v2jFKC_vV-v+2T$u {, {GayYWmvpic,ﵺRO]/8V#`)x jֳIBB:ZֵB, M7Ĕ6[ %8gđ"2p tyL<%W*sI%H?9d:.E-//yĪK%]%Fi!al .i\Z'kO:e'/ެj1CK-Hk}r#;FYC0y'O?-?v{̍i7k u_ַU6 zGG ՒFY>gkONs}٢v~s?'?I{t2N¹zsswx]ݙmfNrk2,o{[?,__h{7?7ddk:&SJI&>;Z)cDBhB,ÜX2Ow̉&-VuqoӋxE~F*0+FF >ǂY:Xl[y;!}_b"28O|BwOOȧ>Iyɋ_,{~<ϑGSמ'}3uțx/oMy;~V6W7D!yʣ^^/"yɣ^^~#@w JU>!CW?w[\"WT;۾?so6j %-**-}BU9 nFZ(V*,q,,qCGt2eP>zЦ{ ȳ9BLv-tek8z&XvεLb{Q 6mditW,qJY+K0Q?G2qV\ycQ>?;~3ƯG_'xB~X|m7{_@ ׆k"|׼Q뿬7?ss{;UI^q#{_"_p 9w<.k˧|ɏo?Ay-r*??+(z׻?/{oSM )B@{qD[.-X$B 07K2#Kb~+$iGz:KiP%<>w$HXD&)e(<p R.[QI}9lݛy~GV*)ĒQZm7(r\_S'AE%&;% &%tR#EMm {#`ud)2$x,R㧮[d{u & 66Z|]v4(b gY}@uB<9a"dUPPD+hu zMJ 2rٲS;Vn]^JSw s}NR(V%AS8L51DE\y/bHu['!HgJ&~U@j'A̓]ji̒F\DTbﻦc3dN~h5!#﫛J &l}.!d;nOVe—7<?o~Wy|˷~-_,<y$oxK_r?)o|GGqK^ʿ- h|N~?&Ϲ6~G~D{WsW$%y,U,_)}塻/YpM5>^9w//}+?"/yGH?p}w&{xS|wHn:H@d|G90KIdZG9(Ny,:OkxY/ʼn֕e9Qj&sATˤ[{vY#S򞕢^Gjj Pرu]O %-ΏIMVIux &=.#U׽OMk)ɞxbוAEu}{`ӓwQ"a$ۗkg &N*߱"TK2`7?!|q\BIihG*M]s4dpzu5#5|Z^H!Dן gԀeDɻ80ZLۚq2Y}޻Y]$a D kZ@$m׼XdI φ.d8AȶRu{x~z+x]\7zX2U߃|_̳'(TTLBU'qغք6$CVHȜԞ&ITXy.|ʵoI?y<ɯʃ>$o}Ww- /eJ>%~resE~WU~7SKD|j}ygx\@ 6ML/V2ai]0>6sZ蒕-edqRF|bЉ٤,sljɧvgCOm&%/55$-tI#g=!̂0dB 䳏%!y\B) 'B&Xw( J`rE*F>)K~{k$]9zᘻ]_(*'ŪjC~V In!A _[~o6h׶5:LqBdadM| n5$pICGj*LDF~˿3+m>اG2ɍ|3R(X2m(R6z`g:$]aA!H#|`?e&B.&u9 zg@)u,)=@.䜩u 1D&jLit?N:W<~:H@HΦu[ݯ}`m%Y\daAKXrrɢ$I7752`=yy~ú$;o]rզ6`CU_5>wT=$oxuy{+?] >>ox|]'>d csOf`yCɟKXQɧ~ɋ27ȃ+َW'odfn=p>/W!{mo{+v9)%y+'%.z nKV }jWGݏUS,R.]LeNݪgZkgOd?3#19x=7.-dZF4J"D,(I@G';,U҄I&-/빕&QsuQ"Ep H:YRI'&!D(Gj^Ib|{H9b<#Ed;ܝõ9By֓v̢} @ъ#LPhˆ*H锲KDM>AbJ۔D.NAಡhur+ߵ‰.'.cvj9γ֕l@M6-useXQJ-bqs8F,]W,mq{][+/p(&xjp@NVHZr t56M O(X8U%0Rdm&xrNI=FϮi< U}v=*e#/yN7cONxs;W+쉜s'|Rosk׮ɽ+)_oWc?+"/}bxvGD+/{Ow<uI^Wz㟒<[ZU/zW>2ʝw)#~-o|k@Å _x!%a"VMY[e8MqlgZhN^$uSJ&ZѤ;#tJ'\REE&e:wY=Q"(IaCz2]>ab[֯cYߑ,)eH\I꒼9/??)q.9v?:cJU#_o,ws >]W/ A2927T(ZǁG s̼!9 )y3ac5iÞL ߍABi>TU|wc;j@E4`}gM2Y,c̡ (gZYyR"KVs۩uRd-I>*z7ʺRIS^2ȫ7vJ콤d >̒h7:sГs_s;b MXI$S36JZѤ|b5a?֏@P-A.6ThOk疕eF*&l}!`_+ KI&Z D4$j‰B}Qՙ)fAʒY^cgdF*9^w$RCP=DCB'Olmv{6o:n:„jjsyzԍpI%c|NT+~߿+{k?,?? (/ey׻~M_&e~g䵯||yݒs=mNCeo %0lI^yߐߐo\}K<_#_Fygߑ}?5d2r%;ou\z-Lf''grIRaVVz!7B]UKFoO %%`l]YКPHSEJPo!IMm98j˭g^F3>V0aZd uDo$O$,%] {g)kl>~Pn;X gmd?ucO)Z_JZTG4IFډnGbIm?/_P+7<nO,6vzXVYg|CeHzPeѧ:zzRC2JV~v xn29ԟ?xu<;wue]YޅvLݲ૛ f ˹MBTJZKxRoaRSqytНr7SfN񙴏eK>kYx}`g5ɤH3'}''ۏɞE$W&ZpՅJ^;g|Z#~zDXesv%|Angަ܇|o Lg7y6a7[R'q;y |{v2]o?KgmftoҪU'Ut*Z ϲ^bۺL: SYE֣ `۟Ֆ׶WU˾|g%n~r˶c#lm -^'AVn:ų)Zsm_+UEp#[W p&hTo&ɬd</s|yx3Mʾ|WGwO^_ o˗~7 {ׯO?Mghl[yyϗ׿M[a__?gkz}n } $O_jV/ymuߑ͕0CaI:Ă5{;S.A ?Kd-NnˋZY-s%G"0cq?I^b?mqW-<\zE.?-o/V>ʓO>ٜzgo*ye]w%<{{ۿUϗcodvˆ* O,3@x%y5@п\U9a׀{f>0ԜARG?d T[,qXG'5pYS vjAٜ8`_R"wuGG~O>FPyKꤋw]c(|ы~isS_D]辗ȕWggSF^ @."c`u,1}MM9q-)űubǵju˔X};XkAdP$Gן4+V9V.dǞDy1v`2A)UzhJD.#㸷ѤRmv,ۜ%b]>YFQdzk]k}:OvY]\ţֻ^HOgMλcDRnsVI)+;KK}^ys^ /ay/܍|F>ۿ]qwM@c!^눱*WL_`⃹].'#f CV,q$}ެ0eX(QLO. q|2RQGIɱ(fiB$`8@[hbI)GM&a%sg-Տ;)R %v:xPŶFD#j=)4QNigS[B'$}˦0\8ͱDj MDF)5óa'tb)Zn5D9p%j5&tr! ۭ)eBΝ.`&X$`S.@>":(u|2Oty F,  ,$g[GQ')Di!wh]oa(LﯹJ O-kX7t_9r5[cy SM,P_qMewL eqd\cg\|g^|rs|[\|D?M~,SaʣLDD~J%?(?C?$v_icIf|}H>OI꒼/;;noߘssYdSQՑPI"V?xOx7IjmRL#hT+az=aɂ\, 9dz Hw]U8QDv%S&*x'ᄆHKƚ" øK>r{nAq;S.@G)CXV҆ޏbb}S6GNv=LOqn:bj!0TRBUw)A"T*Hb۲L0=aJ4iD_גJJ~?Oo/_ȿ_?gvܱ+wl=M@>O>YN:=7c_}}M>ˮOۯn(kj%%?Pzܹwݟ, &pRʑLz8"XM6`]$)u/Y w*Q\GMYMc&vJD$nswq19 elg+fc\$paʈDV$B6AkT$v69vgSඞ a=2 ڪI.P0H@2 *: DV]_E D\oL^ۭA=aA; , bOj׾v?yH#XV<zu7pnT/! ,驩H$)KH'$a/‰wGrL햹؎[yf̤_n}L~g~F{q;ۿλ:9duyկ7d'>.|#{.y'~'۾[?y6'~1^8yU_JuSOUU@ ,d2^mLL1M^~Ϲ0@h%xfSyLl k *`yMJDڣ{?+g'h5hR""hKi&dsx3:%LM,F; Nixʸ0fDH˻|S U޷Ndw=W|3a62aB.)yj$Xewk[F z:H(a9zG,\$p !Lq$DݖFMk4r #XJ'CB<" cZ۴0h[GZXd+8P¯!nOF&YB.-| \QvA"0MGl.3 f^8m%K? &˴tQAr ) N$d#Of<'?\nlqdi3Z哓$/iƳןJ)7_KuE_裯ds8/Wlg+^|W}O/?'W(EAoC},Wr΋vkˌP' @ p&/ i5/un$wdNly%bJ>Jƛ)c6S!TH$ =g >_t{$<|[naYm[M4JeNYfV<>KJY]I)ώƻ-:龰-WVKRk(c]O$}YzYD.IQh04.JanEk$cuNoKg?={V_%v_.^>Oss|sF.)w!r֯'\q{Gw}g~J>//ɷw]*\G~ʦwYGD$uI>.c@6\/zї˫xͅ sl+'?*;?'@ p#Rt'4smjūYV+bm>Z"y?hiUE^L4jI=9$߄iN&"q}a$eYB&)yމV3D9I LL)ɨR &p;aR)ϗ֩K%JڽTa`ov;c4gܤ iokň%×m],{"hS\.u',vؾXβa. `p&d FVH'[Yx$*&1 P$!E2щ{:S(:^=~\#9S]#t&,Ae {l"Xv4׬-!Xv=}7ZuMEĵ́#X=vJcY%-RK"Payl^~ z K$aHeݾ?1Q'e|ru?(ߒ;^%җ\?W8>,W7WqO|cK_2y+^){{]z|7f[=x|˟Dd~D=}M n y+/}+K S<}b)̻>+a9 4Ә5ߌ.pm,VC95֠IeMK&=xN9uqE;kULLIm"搌..g8ue{e=|9H,QdK&d ]EZhrOtM4M>n[$R}ݬ]k?޷0&2Ydo&vv˷T,<ΆK,$kX (hHl[F4-efc˄ .3f}_j0rETMf5[}0隈$)hbe3̉ kJ$.!dh`[v/l`e%e3D/U@|W%=U)7L-ږ)۪P)%f[|HjS͢8`cjITd$+4h">U K&سxlqDn)KY/?~}Hr Erv{l&v+=7A~#䓟C0^AWh V7g(6ot/ @ pXeLVm*}g>Yu#ue>df%x t^bR&Xbys#J>QK]hM&)-AYL,MN+5$h .{$}'[Ri}=S*aD%I9~l~Z,Ыݖu<쟝1O-s{.$MmR-6ønS0oYoTL,0(eBL7 LDDr 8S5a*0r e>&X"gӔ,0G:lC6Bdzȩ_<$↩X69Kx+D2{y͂Kՙ{@_F,]XX߭>iH,+V}MDOV*db~+?ddɹtS>W(3#A&,-1;?G?*яJJ/{Kn{u[syK_!)%o|>瞒gx&.%yGm/JwU>'dÅ @VZrm,z Y'߯軹_M0r8WΑ  2S%j,@:)M2_]) I'#fˑM'rhe%E `\B4A;}nԋLDL;fl3%D8^ەe$Фj6zH2k7B6AEyśSʻB:͞_/ø( VRW%E)I*9k<[K(֣b S$_RmJlz˄ nZr 5]fYhkP,BʚjUCCPBe>-y?{/Q݋{fnwwݜvWZZ@$lg`lcd@ $sZIsމcnϭ>szfnXtuuUuUt~})_#AKWJW( @kYUWЬ1z)78 ~˟#G?7BT2`4JfǶى)4QA;˟ b 3nX=Ě5k֬YـP~~񙢱K:fA1XC뮪[xluM R ^b[9;- ֣bcYKQ SZ[ټ&9 @h1px.f18\i`ƖVVlBU'~ƽs1{ؐđU21\ǍOBVr2Q}:YzF.@S ѱ&9֦Y 7H"#t?'CGhTlc/9^v#'PHhc71a3Q%T2GTDGPX"8@=V;\~R`Gq8I$([ $e.ЂET8&c C:e3 b.,ND*UL,Y0w%a.c ORعsg%;xNjMye+1mh#G+hiry%M)`m zثŕXf͚5kSf 2IbEd2k*P6l f(BVft18LNxTFTFPY?~M9G:DŽJ?Ae6xgNrB e.?\JT KĩyL͉pL&X^fg"+W3NT˒ph;!*&t72 M8R"8!Nj9cuL%2 EW7W5k,ڄJ}Pj@2h9.X$ IM(8|fr8 I9uz`j: -Kh{I]k}r~#חBT ~yRr8*mI1T9tr}9R 66 2iGD!]QT{CXc4:z T8cѢEX`6P6u8qF|8|h'M^~]G̭/q>h~y[ _) '֬Yf͚eV&? zƮ.k YLr qX~6V7v E6Q`dBr3jU,R4$`*{C}T6z _"Jd *I.n=GJI٫۬yT:4*{~Ɲ_AAXw;,%uR (R9?%4{| dIt 8ʖ?kǂYI86м2@DU y8@H=`-ۉB† $q]N"򒶫!N& W@I8gPHntSb1$pl&sJ XLxՏM9q9]ߎq@ TB*H8@E{F uN8XeU^b_}d|T#QrFNM^R8o$koo܃}NL,2}dY|+_{ܝ/kmJMIK9`; ^~sg8'G3:402T޷n 00 :F͚5k֬Y6si!5zluڔMd?ń t: #hʠ_h^`"7S39>NHs82[:Rd*2F&5"ׁK[>С3]%j oDM 4r}b>FF1<476A8"FL#rpR+ Q7` '8@I>Şܻ%tfX?Md,$Ƞ]z Ct8 e2X6LM; 2XDUp&pR3yXnM"rL'/@%q$$XWJ%)kx?$~{׭s]žs*V)pepR8:&9JȀn LƆжɟTK8cOU~=lYԈ U82$p@rPr%: M3ǡΊ) pl*ql%: Kp " ( km~[*Id1maoDpIx1=0LHK&|G{G~;&]j#<}( pS)?DtvvjF`[kǞy>pչ>+'l`^wS8{s>p(0 fB6UAhU>@,ҩߏBrD2q볡ȹR[*c2-(&ۉ|M$5$>͞)7*{3~|8Bc#/妴L%:8yD%C?9+ Ǖ̂KKf&&(cсEd>B):P+WNK 2D0:&r;ZgF 4qXFKpZNBG5US9&&a  2QRdc6g?0$b.װ`!PJ#jv5UH&Lu6AݻwgFXv-.k{_e혵 Eu5m )ypjOYf͚ispS2 $#GRb$#qD. b1$> <,bse5KxLD.GKtPnCZb,T\*Fz?&/ '#E8XHNr J.[tLF)7UuSvrRv"Kи6茓dk,n 1Pfն*͚nkSe&@[ -ITd IY&Ө D8PT90 PYUIL>849VQpIM t2,'bN*qN3u^)eR'X˲3v' ǀcq)q*!Kp27(rVCUDx$ ,>]ueRp(KU"P.8 YpU0`2\Ess Ru !P*p=w#tvvsESSBiup/M|3w.Pdqeg͚5k֬Yfi%*$j9&pIzJc=)> W (H_^DuCEO'",&|"PdЉb9I2O j(jƕč{t2W1p@ Ґ"鄖c0ʒ&> #C-$׬Rwձ@(hAW$"5+Vjܟܧ "b_s 7^J"!AJQkU$Pyy/4| drT-\?F/rx4Ni6fAA$Ƭ%2Ѱh;Nq]!XvR1e-J# 0 wń(^a:'C'gKF{!':$5v>n "B # {hBJ?/AUFX3HPˑ)t\W'jbhk5kSm`bmBjeqr:pG'eC&j1T$9]Qqp@9j"b67UIO1!Dp۲ iL/@D&T"$ 9iqt(@7.Mt#^HRƕrx9dd< ߯4DU9I cKSK@U'#ꗘcɽ&(zg%`TG?>A?Wji7'(JhjjgEOہ4!f .7}w}6m@KScȞRXf͚5kS,vjaU dBv1iWbS$xtrͱaՙSťad\LTh:I%FOd@]6p J℟qr:$pC(#R*;&M8ZE4|NXЉńIt<,c=>~TE*'SJcqJHj28}ʲ<2$20EIbq8b'<jkQY6X2GUFq9q7L1$-3Β0y)HT>Iˬu•i N!N:%#rtsKP-[αt);c'\u^4rx9d#%B' 2 p'66Q DǪ8w ["$` QlB.'3Ո2&=icSdAkk:::>%qkSO<,[Gcˏʣ[0Zd  9w[/(>ާ2ɫ|x~}׎5k֬Y6f`m|n6ER\ 霘]OgoS%c(Qy" @qA(ڤqbxdo0wVW(:8}eucT*mBf͚5k֦L|X(RuΙRAE8P)ɱo؟ϕiĶ"LJ DʩؓzseYi . 8~o'$bX$ibd}"[D$65в&:HxĄ\bF~nS6 IʀPB'W"@`"?:Q@QUZtiIDwqq(twkf/IԘ Mq4uJ؈N #Nhmmìnٳ @fϞ=iچGx,YO|m< +cv|E/QKbVo\+b7 ~~9<2lv,@gF!" _H/#{!`4'00`Ql 9p@C5*? 8ؿoŢ]]s:\Fs"f͚5k&yo-HqJKU5I%e0GVOT>ePD'EYBEd$d4aKh+3%z]媝&.9p28*Ic1 ,pDyIFDQi~Sb"9Dp$ORV]i^~ pަ,N>g:ۭW jPEd á EWƱ2XNf&&TN2rdy}z1Y= &* *67uRWF+ Å<2j'D@89nj@PJ!ش I81d"S8Q]4Sp 2E8'K'UDǃKx~ &N$LSR`0p8$ w8S\©&xj|vx:1ܳؿo/) ?ŭbg?==|q{G Z3 K9K1`fvX h6ZZJ>Bۺu+nu1u>N@Pixy=`R֊zzf{XBSdK@&e$tBHx8%eɑ*aZ=DSŁB(JtL&ql( 8.X{=Xr$ńpѼ;d_b8"?u4N:q[7ݧLNXbw Q/8\ 2 J2i>-eD':0l4A:r=zx8yG&pQ9:gL\QK0щJ A]t : q*Og2D6 bN:D4Y֒)1c,,Y AX4bAkJ?{#pބwFnjV-YNEE#8)b?]8nʅ;t^ۼYht}BH|ع_TŰ3QoPT~ZSnTzu]޳{ܹs!JH],Z;yם޽}f<~s [vk֬Yfm2 )Z&@M U(Y:XGlA`P1֯9.@8@*'Юȱk."*@#!KIpm$)cI5{=.=HG8ƒ{,030G:Vl|-P$SH wGrlrZ(CepB/cNx^e_x|dB/T*`e֎KLMRUqwN+[.嵀kǢYI3("sTur': eII¬b\%x8@& N8=][Lf~Wpp7:&F2DMT:I^j1O%щҘ9Nոrd<8iT+A&,nRKm\[PG,!9<r%.TAimw! Sk0* {}`t2ݻ?0N; _Bab&Z xBn8FDDyUF}Ѕq1\ @L"!{~*U@0:̎nqe. M8)C6Iiދ29J-l&bm:Xc1 E2<2A(XD.Q##21)TBG'yáVU %q4iGRFP NkȠ-pcZ/epFǗ_RǜRq ڒ; M:EԂwUҿJEP}[_Vӧ*ZSCVpь*2Y ZcF+OT,b8nZݻ/^~%_pBXL2 r,_<J%]]]g6xN+ Z1B̘Ӆ8^-JݷX1s52Zj1j/XKX @\4c /lun| 0ryG%r@{Gi z.ΎV[0-p cp)?',o;1ttO"6=GًК5k֬Yk/!i2^& $it wX{Alrty!*L\xB3C'\QrmwDNYIB{1w% -Lh, !81XSPY3pAkBc47ȑ} HpDv%z-"Yl# %5U0<]R),=GHߋB~-J;w:\tvu~ak"4![;/N83fyu8E b}8:|b3vçoK;ďc45aQ2,)Ut;:JVeϏo`ќ=3Xr2tpqX9Bذ>nDž9 pg^֬YfqRA¯@&|7I.+#Q ]Wa|rL/W}Rˊ46+ǎxPm9ǐ\-Ѯ2pA%SM )*1a'SR P`IHq1pԁGT׬q$LSS3O5&y1eU 1$1wA!I(NKIʱ2`,}KBP븕غ{|,*ﳠ,3A(%%`DCw8I;61֬M+Z-Nچc $< .vdb&9aS 4TjIIp#r~ 8*:c90xBQ`rj(\%gT:d@Tel"_-C&NDX(D2p'cP:\ sIx|@Ad!KHsF6+QHIe,SK܊)1Q۹阡[,sNN455GFFq;o=>aUsu1f߷Cڊ?k5*-=ۋ _a$?c p¥''z _p4eq6J:2t3á^98uljx}W{3:93Xy@ XZWw zꓶK pҬYlkfTFgTsq@*'pU n ?凼 OTE9^dǜ*K3AyS݄UzQcI<DaM$ 崜΁LJN1Y?hZy˃K4OZS)2iRy2KZ:>hD|CU8R`~|p@Wr1:qu%x iYiȸJKyb1θpɉ8n _6]]hmkA:6r^w܉z b… !022+W?>t/U߁Ec #!FP򊕴~pIhhkx}عs'n݊|{/o߆f,XKW^ȗreKy}V>®֢z*euP{:It]ͳg=ZSm-% W_O=7܀N;}yx\z f͚5k֬M9E>'H";)3iLⱸ>ЂL4@]0$q26U&r!]`ōbXLT@=Uo ,M۔WZ*L89JKAQ%I&Cc($L(:YnhFHzp$&%t[Ir(#o !)RT7 l %tb M@l%d)9Meq&IWz,t0}Ytp<ψRy2Z&QD8 duMT$tb!獓pBN9P^I{ T&IXK4z$i|W$NZ)LTyUc[a.}=X:#\6%g8 ZB۰  P(+fQ(+pUc%'ahmkE)\.ooI,(#MMMxM~_{ q],Y K.I6`Ř`f́'ICml^|9ٽ eu122o?=yyΣwo;Y})_= f#~#-_ؐx'OcӦM8p ߏ^ p;|X(bŊ8餓pʆ XjVZVjظϾv8l/bk֬Yf>N:I ̠)08h@\;}Y q10TkRĠd| qhTN*M EmC7.Im{I esdWuݚ{1&׶ LB'v`cZG.R<{LZϱ0-3"/SA2=Ib:) 'p 9Ou ˕at7 00359>QBa1=t^<###(Hef)/Fka^B,ZL ) p>>pQ;/|Gu0|nt3̖+x>P(W^ƫl[{FFG" 5/5c0s,8!ܳO៿o^xO~>:@&aݛ؎}4p~Kي|pZG$.7ַ}RN M&e:0}!t>) m2V۲0*+>s};GGcGfE/"_*kR)4epcN.pb*h^Xe@Éz-%t1~[J G'1 H6Uf&bq@U>Lpy>~S3# n сUL* I06мIpcP-b- 0'dsM_ N&NttF&[Ke*Zͦǩ~kI:*g\s~(Z$ihF&dp j21haUoƪu+R7ƶyqo~T*3g|^| B/g t&A94W7 οX(X,}{?~wK/FSSS]m=/>*ɓhr ![͘ӅxŢ8p7]vA8b[M]Xйk{cŌqk pW^Z棛Uޏ ^.}ӛ|7nDkkkO{Zf͚5k 2 .vΔ$cp&\Go\li#P-NcFU,K #ydNx%&Scw8!NLdsLKT%zH(U BIk9` e2$~$X8y;LpT ':eK0d1HiR8r$7&r9aI8@**U߹28F05kTLM1āGLdvq 8ICA:'m'i1e9E1VIPr>:k`N$Kt +FR8`&Ph#mql q` J0O2ljGKp D!U "0!O %g'Ƙ;x\1@Β\r83kG®]w>l۶ {Oϟwx˛ߌYfa9pqr)5k֬Y@@ecgjTA"Q\ G*ԩ1'sұFZ%\[.eq$r~Ą$@AT:(aH/~p'͉cJG#^I@%qz7eG #~,ܖ^2L%!$d6*F(8IT@zۡP85kSm`bmŒc$<@DHBU=5 (qi(8m9M4:.L7@dsh^PJS 1^WI 4BPOrq꼩IZrFN1ǡp\&?:TE||W5ndQ;S"M֢(A&X`.E(oC0 u2ɗr !_U{ۙ솋1{^OMeر6m¦W^<۶aӦMegq/;;aéaicdxxZpwu;n-xu(JHg2Xb֮]˗N a5յc0ПC^[6üEsO_܌Y-=8xYuS(z3Ei'#¡ڑ{p'FFh"|{nsIT@1:0j;ښ5k֬YkYci6F4)1 9c=N$#f epLX)'@&5+syer*}386F$:6H%6pb%p82 5DWx1м~?uztPU pBf- A'*frLYJ(CNS1<߹OZ5kǒY 5pI健`TBkGC@GW@"?M@!1p\Vc1}=E%*ifR/ql@#ILV3qA$r;1+x~a"ÍMQE C *a[181^S7Q'n7sE~'?ol@*9p=SO={@KKsytE90kV7fϙ,[+WƩ M>w=hmmŖ-CGm[Q,>G䡣6l 's>^pOb-_<~Nc+3!WhǧwhقDرcZڛќnڞeƒY' ʔ%_fZ49=W=[x%\p> /LTn~тdk֬YfN5QS>FJZgqF+#iƹX"79O~TN(#KTXMT ZUl&8~@/$q(+6{Q7f܋2|c%|q@8)z&tαsLJ!I&*$<$=A%aSR 6G6G>QM( DW=F.'oA&֎Ek 1CJL 1+wW5 qt5Ld]Zm'qb2Z[ېeQ, plMMM-_þ{gn_9spX~=ZvA ֧wG ;)>-Tfq#V[a\Ν;p˯~\v.9/њn%uZI#ppCelr|DVّݽOv5k֬YVMʱQS6>wq]\qwGP9umLtH`/JR9rYR<  4AUs2ʩD?*1ym2Pfpb"G"aL*D/@dBGKsu|2$m }(9r9)79y\gmm40%)pDuXNf&jcMA"yNTeɀSNwn⎧4dQ`GF6aP"z'3Q@8@ . 3GJ⨘A8SpI#btm5IpSiGƜ!4n^ˡ: X6̩ cv0|)l?>oi\ [oŦ_FRܹq򆍘=w.:::ՅV~lETv'B uSfG022!=];wn+p֙g> ]Ƹ}'c'c0?Mxމ/;øz +7"rqq 2>|c>kϚ痰c` q;vlE!WDg{'.r{d22<Yf͚ͭ,QGM5`)F^HDzE##RH'MD40-lBϡ:e䈓nOj*PAՌ%rzR9T<$I\@x;,%t?'#&8dIiI-L:9@c2h$J^IcW!3IR9T@8I`$ lq@ $vLį,Zf6IIp (I(I? r1:(}sl'::z)?. | D.W̥Y\bm$tj/FT%s!p¥Ǎ+M6$rZI2c䉮q5npRa޳ O> UJ/W]O}9kQן1XI>ӱqR;a$1QY2 %y\#: AcIrmf/|p%q@fI^ٷ0Lef FQG0PK<4y_Rp %s' 8D~A"*@3Na{ƥrBk+0FaXc QIʣǕEs֬MY 8H@)#C@W>|dbt*G'ȓ SZN mZ:Ґ|zIpb:!ndy;L3tAF*iZ?ǮR$N m<]'Qdv/D'q fȉXV.M'h,cOӀ\uH$7G7k:׹F0V8#w^LSJ K/C!"J gs.̙3MMMp] (1}rR~_0"R.]/}Kxe!%|?W؉Z+wAO|+|*i5XԱ^Y9I0Gp p;0T֬YַrJ@_vv5k֬Y eL _'H)@ XGT4>ցX((1)Ir\.1hʎȉd;љD%]JG8LQLk֦ӗ'u ʧْ>//yW9G <"/qr=a>9Xlq, L&I%t鮓~e;{K.W/Xyq'yPE^WKZ+DHZD'W\E${ʀ7!UMBm^ϲA!gq?ÿ$d꓎|6!JxNw>:Vl8?l߸ x(/JhkoljO|SkR ?[meiV;$wE(=z(z{{qcΝذa:::suWР)0?10ڇ_ujG0*߾m)J" N׾3g ,kɤݣcu.3Q=r?9G;m9EXk֬Yf֝tA]h#&b%rʑcX81-kcR$v<@2D$@`K,Ǭcr \7'قȐ EH16 \z#v w@c5;'?C@I'C뺕IWI$.N$ ̑br~yZGg}}B}9$c䏟wuCВ "qrs3]?Gǔ[N񙔓ry4P؇+ÚFXkC~&> ?!GBf> %r[:"%r(h$2D@zXɠp[e-K~x7yrpK2Q JB'gd"(;z!+R E>QH#]T'r;tcPgB0U\8'I.}96x40L9@"I= (-8Ɗ:޵:S{,Cp[?z9λlvU {_2R bŸ{>twX0IBkiiםޣ^|ES'نC-D~ލUV7`,`ü3pw#6EjMY=߾{vb8G/ eXn!eۡ֬YfZn_v1w0:V& /乶qm]Cu2{ :Q[!$g`xuy)G*[Dкe2ȓNЉdg'}2H$t?fT"dGM(I{j5dIA&KQu -р5k#<;je13<Č%:q q)L$`28* SM!qC-5-jaM=y2[@?;sՇ/śHG}K~V/}qI'P(XpI>fϙ .--طwo>_ׯ`Y+=::l;u7z4v'u>!AV6u>ftc~"܅zMpyŲ @gO]GmZf͚5k sݦrzvʤ2qh)cRe`|<jL)JVY%u_f/rIϰN D-~Xqѹ1OKuL@&icuxlbN6QI{3d$ yY4*Hdq#&4/=޴Yă;I/2HN[Q/@9|Z|e62xiUPY 1VY:G~㎍CpƙO85Ȍ#2F 2"G(2!)i!9bBˉUY6f&2NGNS1 IdXB'a d&þΕHOd T6ۦ,\8I<cXSn3a1q$'2Q@(NJm'Sj28YJdIXiO^@kK _!\N4?a֬=chhguvܔ5g'#;dd2}-b7'{?O8t| ǽ)1%B RN 4+'dAbڅmݎCCsK8/?ixV*ǚ5k֬Yk 'ʯ5y<bMNj0Q0e1Ԕ$8cߌ]A 2qTtL<R$d꘶: AcVa~I.,&彜Yp,¬w[8Vx_!JBЈ 6ρdɜF.Qn}2kr.TD*'\r˲9>~ux'We Ѕ2R}IPЇSP "MBPJS>CTO{|,DX‘~0]' A!Z+秌&2;I?8Q*P,da<̛7z:ٍlv=9 /P 2I7Exѭ(LG0Zż3kbݷ?>^ W~'NzZ%xda ׇ\;=F{Iͳ:^CW^Ess39Xm*BWO;^}tiYf͚5kRҷ q*qg'qRk[(?P_߈j%FX?VC&}H@,dxJ&6HpCE@@8ȤZ>l2?qXEگkɣX8IA&|, Of* h_JiN4v-$$ e* j[m$N/EMU}ycl% ~SnJo;W[?B SN6"A8J'ˁSXpke ?4/w\=Gꗿ@LOWiڶJ´3L%n!x$lZ.y_W;F2A2xTMF~+wx.y_u0,Sv% ŭ'T'@'Gq ~cHuiD1)a\9 t7FJ@*с^ "y֬a'pQ@U GZjy̧d똱Dm f_mmtM?s8pMMM83~K.Ȉę20::N|w>.O\.( ۯ} 2f/e?_{k8?Ięjwx\zܖJh}?CI7,H˗X}޴Jە`$RPŠ-+߆o></-a+ѽp&75k֬Yй`e!S!AC:H Ac9`b!5HD軋cIPƜ̱Lc@AáqPp$霪2e9 c ^'0;*xn)H z+ WSIJ'L}_%]vr7l]Gy$&ty|Oy#I#kadh6 ba;(.*/fv!䕪117~l+AQpoY:BRIiVp7ZnWuZldIYކKO~߹~"dwi#K9pe ǁ)JԸ2YHSP E¡%V ڔlX3HRyHi:IaѕIi2I=l%F7 ?)CuQ=,WN(zȓ4CiG'jDWg4Ib%\>z,vxsO6bU l$yQƓWĞkCNYTƁ3^&7"x'sxd* klƵC20;sVDJiED`IHh,2 V]ǬJy g_uN:c]챏=8/d2XwIG>T*|>?=bzdBA&yuHRO~!?ٳ}Ns0 wB497o=\n} :cn|ʾL -8FO'w=|--zɱa~{SYf͚5kh^;>񜒱rEVBXd b'$ί)2TNSIp~(uG8 pe0aэ^ Ch_d,;>z5ϰg'o'>Y8b8-7|x%?vdG(pRW7J%8Z8~韰l2TnJKv|䊣ȕ(z49WR>e%gςr4l~<Zڛa8A88pgCEDFk+Mxx';AA{:E)x#} x;6㹃O¥o0𥉉< g,<w?|;8spWh4q޻fގ֬YfZgV&G41IҘ`:_@Z*OdM: 7G~`829!D+C+4VĆd e~9~] D~OFerm " %$d/ e @WMhܿүfUqWk.P0 '# Wo<脎'@@)ӼPBW%*ջ!n:.q帠3-RnXlBpHLjh8)y.?GUX.f&֌  \DΫ*;UiUIF‡0Mܪ|܄@p$M)#Ia8f9ʹ\~$2(2x_ɣb'sO 1 <ҺqZR7>rh9&uA!*)WvLF8X:N*.5K5UQrʅ gUBT߼՚Rݜ~1I|ZkUFCUϠ>6WgY|_3< tr|ӟGKK oQ.P(}###u~8z(!8p_W~c{f jw䕐+"[̢iS9W5VzAKG .\z/@)!vmKE CƷW8&(Y'^ b0ߋG܇9hIoQ068axw^="7x] 45`b͚5k֬5ܽK9y_ceh;\!oWcvű$j7hς YEdV"G%cjMc.}r& T*4Q` Q1*}Jb*`I]rJ%uWIIJT@*:Ҙi*| Og|IHS}9-4]<~P4 8­¡FdV>~.n"427r^9=8eBLYNmkm`bfS1P1iӉ|X}p*$|j=%C>PkGDFE%Z0n`Fd4p DZI$1)3>g Q9:XCA-QEżޒMdTcTE/*ID'w^ X<3s.ԢxFL*[=W/J< Pn 2L[cy|{0}ͯYl‡RR)477aҥȤ1B<=zl^VQ}qۻ{v3<_?Rь}nvR-e#Wa0 ܚYo> /ZU'#"Cр7T ݄0yT`3ɑL4RC_Ւ?\g&Pe)r9aZw9n L8бp1Mzms*C%s}g#YLI(tUςC$ռ|g"B( >veyUR++e/6f& At8ttN*< Idve>ѵ ЉCRy!U:Bf,p|q>SNU~nHT!QMƥ4+pja*$ǘK+ G.?Y$15"k k5禋#6|u&iEM:/-/EPspp_ױyR.rU83Os]wގ];wu]rʩ/@K$=oO<8.\`Vw7mJ'wC_ތYe ә9s&[\?q[ނS6nTp+f-"[V~/|8ͧbE mddv1杆ms#4ցuxz#7)8,^3ކ0:mF^/Ev,,Ls*{9lw6}>yo-uלN=8<} f͚5k&OPă:y 49@M'8j1.mQV^ b0_^!e&4JD"1XNR2I[T\c0Qs%J%0e1qq%D1\6~QN2PI"*vI.q(I/29j0.HpzBjIL$i8P*/2F,dXS?X`O>:T~rű%*F[Єӱ˓h2L  n?FR=HOa0 nmj\FJdV8znlhکkS,dMʐ85 P0 +#LR%yTT,&kSSOe. 1K(tp~(ru;s83~[pϽq,_W^68 4=$!څ_+n|~u ~k-DGGJZZZqF̛7^ !0kLu8r0|q<ҷnCX)OÛ/o+Y7?|~aۅR#6wE wW_M? Z:lw3(zH@+ :AP ?7A*pഴi 74P YV=h0.X=G{oַp٥MrR 0f͚5k&oN 4NgoJI qHl]8]l06ϐm1),*3!ؤz$Y褐xW̓J4*±[Be B$1KvBT(%t&TJGy}W5 DmEOw9lrz4"K;TCFeqe A%2\t"G(D,͡l&8ne*6f& '[# z\. RQB8%a3 GT@[4{1u'Փb./ pZIrL,G8&0c1s4)*CӴ$%щ~8ǀm6փ`"'GBp5 EÁ²e` èJ595`Dj[Nw}qu^ )&5zLsqS(zZrt.,F9x50!lr|SƗׇ;o5V>==( 釫~~>|O>$nv\yk\ '/x# "W>:f_~] wbhh3uzGPL2@ f:MftFG-V7:;#A8n ͫFqg! O+iBDfvzi߰zF#X?w#;$_?_z gqzݎf͚5k&t6c%*Xs'},5.Ac6r9'CLc8B`Ϣn4N9m0TQUEeU'BApYpR8r>n,CK}kKTLB8\|(PP$@$*vNI4QHK }zDCW]'k,v2$d' c! xޒTǾ)bA!8D%#pyL21gdX365D4i:L S>,m"*t''#DT29_j!Uq'\y͡kƩ'(4 @7ӤZԩ >Ǎ/$/LXK(؄8‰& 4' s &<~ ,  ^ r/:X㾫K*'!I-)[uD/7ha㼫R2ZvmG:ƙ看N\?vO@xA˖]XӽvcOSl<iq;x7/Yך5k֬YydDiQdigٵޔ:4HĀZ8 ']\BB ,#oGXKNqTŜnb,TŲ˧PӎR@'`S@ &q98 %w3 WŜ~bˬ%wykP8āK8JLXK8{Doiu @$_O:qv0 N YMB6xvqXC*b0Rt,')D-[6 0f`QL%k ͫQSyxDڨ1P*SiѲT&Ɠj C*]5P\ZUTGp~ XLt4~|:"k NȃIs }*55L)X81] mL V-Ӎ n\ðpץ:~?DZq42)xɋS.^m߾z+ p%a֬Yr3'_7J"Z[[/F6z*Ty~O>$##x{pu ओ6 sOG-܂kVy̺׼!&~c Ù9 dXUw^{ク{K/add|\Br\RJ0|5Zko0R,ErAl})' W6saFs7u.Aw4['ו\){ߎѲJ]s U8=(xֿykgo(r<}QK9zW!0olZf͚5k mLNUcrA& ӣƛ 6ן`(a| pD 8a&3-SSmvu[6kˀPTnWOkx4G8\l{=T g||T&:6e,ӉNBV f{D^L=N* ejBٚd.(q/wl,J^J2wI$rbhX@t: z QO TYHkFF!; (^D8PƓ8 / oLt(2U8c1ڑ JNZL%Zt$4P`:Q*'D' qΠJFf+Cձt. G6Y&Ԥ9'F>S@I*(.B y5sϝ(-; ڵ10aNARݐc)Q@$[z]c?x :;po>;5\L&iJcEk½nW@hoD8Nעrsp{^޴ RWen-7u-ݎm1l:Mnsenp4{R~c0׏sơ}ȕR ^a0[glUQ -k9w-hN1*e&Mnn p =wϾ"hx~)ߊ3+W%]0u.B__nk-\; `͚5k֬YxojK;lerLxcӱa؂õj!I{ ̠M ld&jr,Aq.Pqq S٢z<1,^Lf1QP.^Jzq%FYJ8P̈BNjc#Tcc]hNmT3y,c#\@FB&rƁ A9VëSBI^"FBxuJT\ e Q˕IpmPr2IJXLkFFlB F8p`@%t[p*S 9/WV1hH$LN''edn}k|䘢ut`80SWI{ ;VW Nܑ| =@q*Z>?  3uiGQ'aGQ!8.cOd%r C?Q/~z:1gq;y%̜9gufϞiyxe&( ho'ԔN8.>CxG}64`xxr >l̞n477'J%n<-[6㑇8!`ql ;$<3xMoz8m_ 0Z`njj5^~f尩͛/0<< 'U ڛf0}1w-Üyito(ѮS0<׶ BY.D (n~Gxvj%1R`aR({oh7}/ZR-߱{N+ЙBk H Wpތ/VF!GT2f~rXwxoۋ[u3.[(uy5g{^xYر?(." LϢhlŶ{ [-\55j*s߾}xGqM7{E+I 8)]-30y6u-k9ZҭcTe1/(% ߮1XGџE3q՚wcVKvo9G/{Ri7B/`{l> i7Vcmz,ZhN5]n98Ю{Л; TDˆ+YT~Q/T=bu:,\RYV\Swa8yjU!f̘ׅ[Gؚ5k֬Y4W1xC%$&s LɸQƽ7x&Єʛp1#m~B"GP _5Rq 4Lțq@3iʩPPKd\RLC&!D'w=ru i>Mt:Mܱ&`]}oű2<~Udqc]'% exëP%8x\dqj$kd6U~X\BYK8v`?jbmL3 隸c9NЄZ8*OA#AڧJ92]Ln Munb]$'QyNFяpD3utfN8Cf 1 \hƖ'ʾq;,pQMN9FVY0l*a),ĜBhW#cTAp:1(2ަ91 2y|q'@* <<3Gkk+VY attdZck{n㙧W*a?ڊ~o?r577anttv"Jahhrxp=`ÆS>淠 |w}?;o<$zq\z[KU?O477u'bμؿo?{ܹ+V (z dQ(֝;1gfCoNd\`~b,\U3WcŬ5hM!_ʡ/58 0}>E+`QR,K{`}7cne"jBIM#/Ca~"?{=u9s̩8[ZZpo~kx' qpX̟]3f NcG^O>G_>|ӟwd.Xx1uux'148&;$,\nR8eiؿxuV%D`Y+_|)lJ}p敧]V%yw?n tuuA`u:>fy Q( &8b 0}!ZSmxb~",\ӊbGfl{ yG"6!夐v3H={ߎ?gbٌUhN7!< )qwB ȿJ~܁?3^P@JX}C!O>+3wYc͚5k֬{1D/QŔ8| pjI:8] Cư8C@I*Q0Ӫ:,,:E:r>@+QL"H; "e)8p .uH=kBHnU cI8Ft,9*wpbTbb ]Z-HJ^Q(PYQ%/VNCl'cZ *l'*Y. R9k&,kq%j"nh}QpInQQU@ՃCEIQ%Α t@081s۪}ԍ5 tL'jg&e`lj B:>ŵ%%$Q_ QUnB.@&DU+7 U7QD,с/ED955jD~X+V94kN_N<B+W5#8M&_b-A<_qE"0L:SO>~عs':::`"\u۱Ӱ`I .Rn }8 p=wF6_q|3yf!0.ýW\aݸ_}tڨ3y݃kO/K/Tٽh1K9F \񷢩)QY۶m??%:6dWǬF&T"G hIaVKRN*N瞊=qSMxfcAN%@2TSŶװrl}; ypQmޏ7riyfLG!0m>RNRO`TO BPhyqa-dp \ѽQ\>bBaHPV$Erٔ$QEбsM( ޤ-"p* k[8e 0(LRTV\pnZH鼁XLJ^^vd2J͛7cpht-BnxgC܋B7 hmm5d8>|_޽{Ԅ-_ bdx\|Q "?Qb|.baHӸ۱yuK_ bѢ%p<,=̝JXa1{YpɅמwKo>q20t0R. 8g+%ckLP(a > (2+OpTFPg qw9Sa\ ViIr C !c-J0b"#徛N\剰88'Ans`>Tn$TTR>umXD8AT(ڛNik1x!G4U& [Д"zZѫ^>\1\O<$2 f%IL!;wJExpI'%*oMJxR翈K"ϡPP3xl6Npy8rīmFss*FFq㪫FkK "~X,֭[[,1{\X ^{qVn\vL^b@ԛskɘ߱c>K_6o )3g5?1u>J~1`C`(?hA\)t,˯o1깚rȸMpa)GfCW[q/(aӑ籭U4-q?!j+R<=|lsi26d͚5k֬M׉S)~0%)%BLY$7*+̃mjP}=Q[U,EG#u1-(@(0HKR9a* hilqbR.Zr*b/ &KȠgF.GVɢFF (a~1,pJtc*j5EҪE)75Of/eH[^yV1qryQ撤8B莓"csO':]֬c6rd&Krȑ+dlcUJ.?(T9::ZEy@,]GKf*cI瘠M@YE8 r>yR22V8pl ;ci"mD$I8m6UKЌ-e;uhyU*N$0rH0  V 2QYZ@GEEKfS{0x2+BO,Ybq34{ƃ!V\oZPHdJaݸ_}}̙HT*\lٲO<(|<8~q?{JE|CC=gy ~~\tun|tuܹ mpT`">_ʡohq?rvu [lA 457aüqʷxSC~=`Vlf @)("失s q{ʑq׶[0ZDD1}w[MA$N9_؜D1|Izl(ɑےWbI:i,dG)>n?džbDX>c#'r>1S*v0{8ʑr&q6qwn+nRKYFt@N&0Љti%2pDCy K',]$;'`ڵ(4777݄GqxDeV,0g<\t3Oadd>0.2̘9%CB _A?npɧ`֬n#1Uੳl,Ht̘uL]H|:\k%B?~|[9%ӂC#r`~IV f{QJG{hɠ͸MX?w#w,ĝ[[tN #!Ut^)dm[,dZzUȽ|з6cwq9Cǩk,|g"B&L&:]ߨ$& yHq'2hDWfgރ%wWSxW~e0q {lFkL@8"XNdKr W5ku %28B*? L"I' "r8|jyMMU' Pa~y,硓h H2v?R6tK:q[+a$d8'& xuj SI9hqGFA<홎ٹ%/ǜc/pt 6cAr;ppt7<[h;]pgG9i7p\4.e\~nxH) bwcR^2e-{D%idS3<8h"G $: eX19?ke`bO@ǩNƵW*X\<u ber赔H*'uib&e}r*f$&WxӁ{~7fΛsf3;Qa1cZEBqsEG yvƖTe bc$aĴ|*C$Hﺺ-ZFE,\KT27rɦ:ѥ)et@ q %U$Gp*0J8`P@Ё1b(9N$`#I[Flb 2Q V8f];d@I8c%RRaN*zES=ʛR>֣Зk9rPSְ `&WcNJ^yUdYbJ%J j8.R(J UC\EX†:104\T׸57(uYn*t8P,j}mbbhpv\R42@x L&LS޽{#5sZ_#!5}Xn۶mEw4eЖnÕ߅S杁|)y Ha@EK:̼GÅA4[f hCЬYf͚4=l_pIKQzt@I?lT.aZuxͩr (BuAW\*ƒ_BC+ <";s3Վ&#dYK[ ^< (= ^l}vJ^)jB& *&eSIS  .6f&bc!Ip9@PfL8 AXM´$U>IDY+2ܖA$4/V9% Pv9\ DV9N ,%:Uyt,֙tղ ^Rf`\̬Bj5B0,"t58fL!N>$f/ 43AA4gj֤?n:b?oZ GA*b…371N8Q(1{^MMJ|>8uM .<sC ݳ }##XpfΜZ{- _"~b{}VxY==1@PUf`Xt:{cC]|񃃃Kw}H7eЖi5k sNF4ZL*% {QsN]J1P4SlꚰQjۏ/~ї+ţcqR9xcbmOa],XݬnE@ ȏ^)^~e_f͚5k֬Mn+BQvdўNY(K ȸ>9T,>R*f\X_8|)WB/oMXq tvwX6]B Ia漙9o&V\u ?U:pI 2љDLQIȟ\q\bm"LŚNdqLfy_ۉ$#W#W/?ab˥ǚIdn܎8BˑLdtt 0Mf&&2U*UorSx lPV Iq1*"K&a@'ms(9V0|!ALhB:b uŭ- p>P450|$ Lي.cݣ7QRR*]^s ~⮻B{[֟z*κ"dGF'Mxq!o6>AssB|Awtt _}twvB cWz5\Çs6,Zf͂_eoPّ39䴋͋%II ,Q9Pイ_[~-ɲ)Se[DA"e.\.6b"NPgΠOMu8 |>U맟 ozw>kS.7qw Gww7Ї > leϗҋ 2aX(7;tbwigDY$П.n Aͭ2QDқ/?I[;˻{zy{#c-ocVƨ~G~WIm?daXn<0E5`ҳaZU>Xf;00I $Hp@1}Wh4'V9Aٞuk/Sy<>]~.2'z{}Cb %t)J2 twy+{oKM U w<4ZǾnL,Q(B seArT[ot:M\fjbn\0 E/}gς-jԝZ˼|] )uLa1Yg>cW~,#/ !:eFa`Е+nb|, ;^2]~i1~Xv:zo& T幆5~D&Y8qoM% $H {3C.Aa٨u;~ &&W: aAK%ңT[\/Hnmy o?H:^C[ 'Lˠkk{^|X]d_ӜnB%d(]]_C"Q3IHh /"H NSADJZH'A7Mt=겶;\ԶFYD%t A:Q ".Aj'm@Js|LEG#uT8PƨW8/u ‰o#Ȣ9 *B,S4 .1Sr/5˖~҇u_yȀ ›"~dqϱUΰ4)z b~CW_gSSS=zӲ V["t)%S\tDEדJ'% \/Çݏ|#JR5QI"A~E,#I-it|#'ƿ T& aj~GH_qĿa?Y_6HEWo%h*DI8L/i}N؋Mќ䕽TP?A N PZ_JѺ~ 4 m+@b vṂX]PjV$~5/299a{EV4}6 L]6R3<<:<;rl., N.|ğo<#}7ry]Cn$ =9 s]z4 ^z%fffBudcR/Ss-734<Y̙3OH1~RI_zQx $hbnD][b_',G[.牐\O.9]qmdI-~b"Gr%y+na% E\JE@6`6O? eQ蠻 -^B}LrڲNˎ;dj5}tvvfR),"ΐr?ğ1p]x?@R[cZt}q].{0-zcʻzosYͷl5m??G%8{v\*l2[a6m;ZuS_g &L !4oK7K+XF-  n5&MGs|L -z$E]G[yC 3!vMlQWir)%kS0g8>Ccw 3{ |<D&_ĉT(CvU-]6+DK̋2;^&lc&VXiBLټ:uP5WU^| _,׋FC2s3`vuu=a!Je~={yQ.]otvu308@V:SS\0׾>~~?JWWRiC=)o_S4=*###3b\uCuǵ)ۭvC{oͭYwllo-S;^ˮԝZ`2\}Ol-n'k]9D"LQwj=^rVCΟvm$s1R[ µehtmxz]&:<5*6u8TM@A"[UcX]Gw#> H u{{>;VU$l^$L]D%HX-x:Q$<!HB%DYĭde#YTN$IPJMAP*y~2JZIv8AJ%JiU$aAؠ֩|MDG6Ǒq*4I&:bJ%1 tv<ܳ07;éObFêqR;N>rcƆKف4Ɩm×Kggr\.Q#S]^EXW}^z%4zo஭XdCT2SIlצ*ғÈA^ϝ0 r} U/F6KF۹0[ qvX"K{&*ƋBȱ5߸UB[sOԓdS $Hp-iBDqGX<8z|u3LD뿈XW!UO=/~ý?Ș-A^s+|ZQqJt$y~D]_VB*IH& A%m͋R)iBG?Y.L$\e+͋SO]6(eWj{+E?DgR+2SM,rJ W#8TUKH&m?)G?kGOQI#a/?ra$LVB2ѯK%,j":ГJqb'b ZDXu 6aaΌQZ(S(CϽG:\.ҩ45ATbr| ~Ԓ' Q.ٷ???:u}1Ν=ˑ'`tt^^7p=pM7}TE.ǎ;0MI*Vu>,+ee #MRq=YԩS|\1Gn_ERuӆ0\d2!! "r<\REb=?eX.-53;*^gǎ0Qٹc껛ŝLVFyyEk3CL~]%"P0. + 9&gq+y#ڍaPO} $H \N9%z}s֗d"u5(mP֧SpHm}ltyj%i#_wӃ7\>\$H 7{w|?6T#sMT S')K+ A&8~jdS.ѵ׵%gTU2HT9Mq$G.Z_U+WQlk~aOPyf]wsO(";CTJ;$ja?\q^vA+U,Q]Rj5r.K–oGxQ%|,DZB[JDMG`vRvuJ1mTvV=ɜV6ɣ"nJ<9O? eq5qV*0}}F0i^jaknzkڵjB_??~rEJ]džJ-߶SoxKwo/ŮN;wz=al?Swjnko}ݽ]l8uNʴVD͍O2\u$Iec?Wz.FA.U??# ;x`!jRfH  `d3q- H/&^k C =m}+f0$] A lN`ؘG>6*qh%v-(G IyOIeNį`d٣[QH2F ܨH'a$f=ҬWDPԾF)$T/Ҝ\TjWMNв }Pfy*oFrqQmq&DgS1i)EU2Y:œ/u*%+!)n]j?GU1iD(ĵQ_~-Y#U'ׇACU.a5O)f:,np<$gqCȰf iً+/L ` ({H1>fkF a .] t.e% $HZ٢gi\>16>zZI>feY#e eaAJ%:+lOzWg}}7] A+6;FU:Œ0K*O C񫖨U¬y$<!`FxG5Ho&'HդnL-XTN66/Z $K QqEe!B"rU$(hWQ1Q%~ZOVPyN̠{O/T҉On=a}lUF -4m 2>"XM3*|J>tOq >Y5V ndGjc63׍pZ۶9vRizzBզh;V11>ylx."x i.3SSˮ;0@XZ12:mۤim=:{M,H$5J[">|0aD +s /1'WGԑDw9+u;h3!0zb}y^|%nЦޱG/$ $H%~wI"V'_rE]`tr5}C>l\WŮ0Wmwޖ $bYw?~S]r$QeM2Z )A2 %A;H& @!hSotDuAU%Nt uyE\`U PWJQ˄QGLB5ny F}Npghr2GVI#* ?/pL4>`)( xթ*&A ROG~t\TՆҮzڞn0,W- ;nB&mHv Dvj[d(I$j* 1+MHI x[v&ˆVa];:]*m0;v܉t WߠJRb&=tDFkRyT+ <{SS>u*`be,zv;BJs'=*3-?O oW|鏾XFG+ z~ rV?l]A$CB0J*4IoSo# &rA] $"'JyKu˃H&VjhSe(ە+ E O t5+6lj1 sE~U%g "'G>UX_ET%*~lwc ě4Rzd,ݙ{^ݭ1ܹC_c>tmb Á۸T9xgɘ ׵9{w2 ۄ][0J%Μ=f$hN A 8N\ADʍbD̓qz~$ U2 %w@->ܜr Wf?wGi $H.zaQUNYï *kN6?ȊǿNBJBIH& $a墖"Q#j*$j+ErnR: %M]Ytzڵ "U$AV:2W\G7##*$rA DxD4u yj;}#D{UZaC}>Fl=N}y*]AL%TPBz OOK*&AU_aX&F$.!$׏y a2??G& |lۉu}ZWH0 :;;LLL~?\)0 9ϳk<.}E !8~8Aϖr$52/Ks~riX>@om!0]l LS_k1@Н2,nmcbdd g#h(,>ۻPtRˌN3FSLu1h,HL7Cݭ^!p=0StHi~ 0<*b(;s 1A $# ^\g۾r"ɺDbt3:]>Nx߶[T_\XvO #x_'_R/[ :%t=M9%#!!$X-$nLNTRHnGgvмD Ŀ,FG@ѕ/NBPPJt$:U1#h(1_7~B'Kj,Ű3 J.iO䈣{tS6EG2YQlNrEV#<.,{B[R*xB@X-RC"26m[ⴽaaM[ݨĮ_\N*׋tڤg .G{!t޵%P]3;5)uBn>@Xܳ /נ\T?$mQq%ܸCxifV+K\(vvbZ)g`` 'RRuZUGr,jJ&έH+^f2iR3XҝH)Iiw$i.`u᎝j9} ETI hmK"J鷕{<- R::Vi-W&ؙ~1/̥^t¨Swa]T.[rx2gΝC}u9˔xF#<DgWD ꔙ(Н]sbٸk$aGXkC.b6B[ϡ?7pN^xW:LTFJbt7Ac,8sNǻVzIHa^BVAܛ0ƙctt4, $H  7lvOr'64jG#۷ܓf٪]wjq7]]ɩ Aj C?jν8BQDgMlsNtT;:$DqLSyaP!|(_ZG$ёHTLt$YH: U%AJ'cp%dUI#.T VryaABYaPmnTF ) yO, CX#<$b ^w|DAFfIj'bٟ +rՑS $Xa^ie-x^3C@3qO8q N?0/fjbad P`z#&-C$NDž=/qi5+8a0l ēГ|ݔ}ܓ|Ja/oxL[#OS-د;/er냇"~K_T*a&zoO eaН+ӍǕ~?sICe<'ݥiXHpt)%)#`qUͮ0(%&KiwAv=᎝3YcgA2ŽLUǨ:%&qk`" 3׸;6(d$`Z};1.T*qil,`nN9 $H Ak_ĻD͟ڞ?%1PP'PDMӥBkNzH $X[lۿ7sȲ:eXN RiZdˣGtV9ATo|ˎd/EAF$Xsrq5\EJQhGDG6i;nP%Q7MyOaCWF{\.;O66tA j՞%jA#nD9KTv=~RIad}l'Glq'AE֩L'yb/Dh^&׿L*sR+%\'UcxIo}Б#ˆqNIgl<)HSi *.7ཹAhNٴM0qˇ#RϞGJLs]zd,1>>zufGץuE4 8%?8RL:ͭC۲|SA%de!}Aԝi!008jzc32{!7P0S}rfSސcTmwga[޵1&+eaHvRF[eޞaޞ!k6?X)\GveDlݹ%ڙ3g8hTtџ\y$Ԝ*0AӕƊKH6ٗ>mt8C&;! h[KO8a:DhO1 @^`:)67g6YkP0F )W*LLLD-A $cMrl?l1ڋ5ʡ$4VֱrW\{)4sIl޷݃e%L'H`}]ڷon7TR:__.JD0H V蹎Ge CѵZި #Qj%e:[v$}D)YHlsԲi:ʪ ھ8!(+Ro\&I#ǨU9ݜS;Q:De-X4Ls[8p[a6Ŏ#gșꢆ-aE0,_T4z:3]7Fs*H3Խ&!F2t@)P[s0lij RY,dnaZfM.n $H UEL32"Kf6%6VR\AM]+2#}mSYͯ8JN w[/VZёET"j}Ӝk+v<'hem H&t"2MDTFyi&og}Q^1 P8Y#!D(ҜS% S9 Q0\u*% 5f}U$ExБ?I#eAD0Š\gS]vU$iEsƿ<7?~K4ѕ#4:rvм(t9uHsIECǾ6'JV~"s,=]u'@J ӤcM-r8$BX݁|I{^/{.]=Ks΅Xu޺-` CTUHr+<tLuVlY351md,?Dž3n][?CYAA\.OB͆yAg~l^sGc65f^&ʯ~1 ]1:ILџ"mNiV)zs =N= bOzd +'4 v}ϰ0:05$9 $H ĭ^mB}>qt_?̾L\M8J{vDGoj)a~x/}:K l!KO$H`Bp"?j>T5tuv9:]T($j' LS%tj&*E]HTmoˆ"2:8)-)D4!a}׍Ǖ o?IO l%Y׸D4ie[u,qZ-:.$h}B>\5}0U_*NjLP(k֕ВHOMrbXǭ]V@Z]Z1r 2\tɓ'R.*)s]JH!0}Dd1Y2 azl>`_ RdU 3h6Nn9LNN"`e#sg0 b\?glHNLt3 o}G.|Yp׍8JEu+LW&0pRmm1 3^x}A2J+3gLљ,`6H+"e,e$9DUY*| A \}+ڼMɞT_|VN_KKaq!ӖM7.'}U5f;۞ HX9 $X -Zb'!jD+S2 #L`5LceAmH%:J\Ŕ*YʄD͋)D)$b:+UЏ"̯^Ptuۏo7:bIM2+,3&GULKtn~o !DY*e "'YDREJػܞozd_)m'+;7h[:ŪXH㶾u鈬[*4b2 Մy0MNVr *SpN ATb%LsJab_}*<en۵932B V\?N }3KGy#HϢ#o?^bI}ZÁ!npόKG@u1JvZ1YؓN,#*Ns"&9dUs+85 ΃(jg F0IFΟO $H 5-RqJy&)) ||;4 5$z;R%VbU+ VW8h*laT*\ $H!5Y #ݍ 'd ‰΂' A&~Ue$ҜUw% j_k@TRM#\q!$"~]VIs^8k?mSUj+ZOM74ߪ\ΏA|,]&q4 "ˏ=$NT@ݢnT\>OTRnzOh4*DK{+(뺢!o+[&y{1)wI1HgΜ<d5Oy4`WΠ%jН <q]@,ZGstwп .!F3癛;c)klFAB1Pq+`b&3 $%DZ?d{EۜH~.OOQw 8{0݆JDa2Yg:@1AO7bȘR}3#|}۫a{uRFjE߫U$`9koBHλmG0kdZx00\:d)8sө'_%HVRVj.q!{SwjrTRu#/?mutm\C,v`4,=sݦĪIJ)udk/| Ӥh١*+OJ] z0;˓2-=HZqAxΡu@GLxpcGq,w{Xffv%:v!̝eKaxMaLWX/0P"mc%%],i#@PqJy:RjW3 \H)7@AV*"}ū2Hfs<۩xFƠwK7{o;3E`7H.3ʢ! 0RBKy/2}iљ떊\RlXXi",[2{qZna.ss{qL5UKF=۫Su*?y,nǘN]o"c^#RsEo\ϯ!ZQ>W_f~7눡 Akf ]yʳ2aDyKyf6H& $JL69"A˃~J>"~d5NnGC':H*qHډ*rp#x Q0,%LiF_=ZOFR1ia䲠G}΋X?Q#L9ߏ: %ݾ^ yXv,WQcQX$8+5ؾGG;j[IyPa{"QQb'Ln\ ia]s&$茈CTw-u&/! % L^h}4O1cFY˼,؞&8RЗn\:st.>JϣP,bR2koǵ%ܶ+ұcLMM10\20@>]dKqG:[ctn}͍5?,gIsUv۵dס;wnzbR uο8ʋ9'N0]J:V[&H .]\s:/Õ.xN1.gZ.XYY׼?骿/QdŔݰTIo 䲐 A ܺ~^P/i¯FBQ!y::Z^-k/Ac5 \E8QEG>ⷰQI!qOTJbIX@-NDGBi։_$H$hMT5 yMgV.ȒUuO R.VGYTҜf͢%o]C7u[WK`?yCHyQpA"G%O|aǼ1 h|I5q;-#W ͺ&Jh{![쎖<~8`]]kN6i|!y3e}kPq}F4KD}(eCzʖx:.+ 9CTnWI4ͥk\J(}[<7x4 cr%eV|^yi@K( Ŷ1IgNfyڈQUj7xwMsj89:ӝN0bt tٵuG1Ӂ)L$J3Gq 7LL+a&#k%sFpvj _yӏ7MRC}8)M5F@վ︇׼ ޖ|}w.//>>d20QVmI)1f!ͅ?{ gNP;^ϖl%R8)5JLȘ[?9]_t9>;gTJ$H᷌BW~EUU?()d(Jt:'Ac; Dg}\\HH.q%jC I%AmoOjֿRkE`RV%)wC_7A6:a_A$eLStP-pi ahI퐄ˆ>AuUmşBI\n WF* N- XZŕbZ(q""+#tBk#!~ GV[{֜`yX`ށO8|a?lA(W,}G]bOmtR¥ZCMEbOyJ5%8yayH;@ʳ8}Se2;x}Eʋ٩1Q9Dſq?k~_z|BOqb5A 6"rqBR*"Dݨ7j?ˆ"AD\@{$C ,!ݲ0E B:?:əDJ*#˪ % BJ& ɲgHsYYDJ/RDۺ-V6rY?K}26 -+ǯ\b|IQDg)$hU M"m z?c1.B,ui6tKVuS/lVD$@ < ,Ӥ<=VU  o|.Z-6G$<5'g=1f ImM0$80e-w^?aM_Ẩl娹($n].Y41ct&\&$H"nA7*9+٤9?Ԏ_qH'QKpl>J¬jVxo'2IPqy4\$ *Js;FG.Y j9Eg.SsQIilc0$J&Nt ԯ^̮\]MNC"$:K;V9+LU%q%q )#e,,$VRrE/#46D,OUDשZNAq]0rk`JqnxrZGy>۶7۶9y%J q-NWo 6~H NQ@z޲_*ڝ/f6yveLa l?a06uksHIoK YXXË-̔ 본!V`&q&Z5H7V6RÇk:ɓ*McǑx.\vXPBr*Fb6ϼB._?\qݰL0G~ǵLSwjKܹ7؛:>}ɑd@6Qĭ209jc#ߠT{מ(:FuR.=./IFt R.m$H` .1/Q8AV8AD  ~ݲ8%!$l^DDtT-9@57ađte\l{4J%A%au#Q7K}2e%A$ f]b?񫟬%\"?A!'\$_a0UANq)V6"%.n|.B3ԹZ˚UX [h> ķe4Kty\Ine^aȺ##xJ׷9˥ m}obR(`.7 ]{+23/ `vv#ܵ_z{{WcSSoD!n0juYTJ;!$#cs'~II5kʤ e5oG/ e I$Z5NHFU]'b:m9),/>OqM3jNm侷ޕK,=9v)<\u\2| $A ??OP-'rm߹QKz3k1Ylɋe6kvxxo"k宏=#1믫Ҝ#-[_UI(-?!ZJ5<7!$HځJ(A#~5fk#!$h :OV5DETEjJE^ѶD@t&6i$SE@i? S=Fyn,S.)Y$8%:F}ZFK]K#r;H$꾉w Ns !K2QI "$b*4J6iyH%W0ք%|@i-u;1%kz;m]#qe5{^\׽ʵطU9w߾K.۶);v} u]oζm(qͷ\3V95Bme+~7w=tG[yZmSk7GgdYRTd [yO|O5iӕKxC0[0R_<3_qj3qtoG헯>ulTu8 'aafCqŗ/RVɍ"AE+DžHt &M QFӺ>L'I($ưQ #Aueu;*QDRTJy]m i.Slji];a&6)pHt"PU&C0aef%n[!^? KUI2U=m(Ǩdʲ5T;8/J(Rp5B%+܆),\`a/:#Sy zɷ6u td@RJ,CG_+m&/D?kR<=7206RTP0h(8?siΏa۫?Vi N N Lå7?@ʮ*I0Lfӌ.ɧ m +]` "[u,YfBQFyv4*zq [_{g;VUR+-NqcY.)%/EΟ?D__~׻Ї>Ğ={¯Ko\]sT S *v&dkԪ6ulm JIz #(NDm7IBIN$JDB#Fxɦ "JH-.Yb(ı S J4-\BPW?2QGަA "HADlӯbEu$ߚqCJRٱcg2(ki 6JIzqQ-s9yغe b۫3Q??eJ͝Ɠ)3mU<ґb{n^xc=e;5IRY Ueg׭U&y&H)*SLueciEUt_Δ^f023W[b ٜ%tGg~g9Ri lzI&B!.Jvc~&(yIſ|'bw[7}E' u&oQaii{uJ Azx0t< ga䏟rfi&ܱO7M?^>/ח\~Ÿ[c j] !YVOJ2_ $X[V5,HADm?/"GWGvsEl^,hO rJ\G%C&QD*Ŀ,aDG&Izc`jًl@!:38Stu̢KT~,:XqK|H[)""S$b0 =3ʪʆlSŮ,SǹRT9z(??ϩӧȧg:]SwBu%/P/ຈSGOۏғx9`SJ~OhN67( 돯hN.O!5c-*]g:c%XGneg]Tb1٩i4==xɰ 'kST eX 2ݝu( .1W^[ϻg3VԨgX w[ qf};׿owaRd. -<5klɶx1A^b2)LrVL70Jb<ސGO.+{ ']n!%fG/F5~'E9`B!b;1,Y1R.;'Yz{"u~7?NJ!nهxppx2aj`Yo{k{->%/Pc][0U$4V } &WRo3N}nQU%$<oU, Z uJoc}iSƆ`:"B4 xq2mRrf&+9H)l=rl>Xq6M]w#Z2;;jV&ғ,LvEgg'/0:xbZB/\:]tf8=d{mݼ<}geq>ɃyTjWey+dwo{-aUT/10X[!:2]˾_|m"jy^rCխ F*9lr< XYCOߊttmտu݇;b}gx'1A Ē OG>sD޴C}Psq$U79;w`Q>//ѡҳBO,aH)ҖR}L Y]]_!½u?kx8ma6bG:>k~:Hgyg׿J0udےQskK9#; RbM|VNfxHO?!:Wk%tj!4 q>?X$WT#_ݴ>6Mk ~RAsԱ@h[c$+l7$ѱno6#|z8r4/?OAacc?+'Xa$0VE!Fa&;^͌w oK&1U[Iwk^2H繡vnq^0 JAJ[ AcQn] μ=@:&!|47v_=0mb]y6F'N099I fۉzhE,\7IB@ơRLm rIe6|aܰIY0xZ$PA޼g)*t6MtB|!E׿uRwbFB@fGs"W^m!<V aev gz3[B5Svz"wۨ>M܅QF.\@{00(X.]uwթPwK9SLU'8;{ij=v<ęJȰbd,>pᷧ *<e "َ\X?$Xv %C9S"irSA Zߵ Bui_u$跮8A]XFN%ae㸜|dZT_JW0ё6&A?-S,0$B_ -ߞzq% 8"46Vy %q{?q%GhPqъJ-|V3`JEvlOj;w qoj۞mF`jTK%LXniq`G=[^~4Zen:|c`!p 5F֌) Ξ\Ld[ hAbHobtS/p\_O)~Wmn? ?.paBtN^tfU08e*dHwbSa68{Ԝ2bvoDV69h@ yHTҼrn|dbT4LW}u#8}Vtn:/%rjp"H,ܹ2ہtD`Lf_>=Set_~s< nm˅e7!b'9<MB>ij2*#.P-U) ɘ AuǑ \DY k4dVJ2QIr!AH& ~$?o{\DBm.QNJcPT5ߨzKRJu&iuN$ NAP+$HF&QI }7:<Ҝn'(1**"q☫3}NP0j"]]RoeU@G ?_w :z2ˊHO@]Ɇٴ\0=RJ櫳-חl>`YkqlY|ѱ8uꦧ7|B0;=$|pt;v8I&eo<ñm.^S/S)]~J)/]O-.`t]f!=#ۉHZyQ/'z."'x0:ʶ/t.N9ۢ#\eu%!,wv~ϳo{5fW I&چ^u+a|Pֻ88uq.d&B09EOBÖBnbğKCXnX咚) uQ, J;O`僚'HSwx 2u5OJEʪ][:JJˎd6,r:r~zUfW$XļTMKY4NtpcZ\NP-S jy jwdӜnI 0 O395ə%1H䖁–ŗ0W[gG.y՗S3'^ }'r-Ij'qt܆B Q~K0{:"x)?b4 p?bK?23i>鸸y7/hFuX(#98~q3[tWI/06 3yg;s^yGH]"\$f=o"fE҉He$]wBUX,}Uߒ4j"՗OkqÕHϥd#,1ΙٗqI01/]l]{YM_/۳ֱarlyjs;#gkZsۏ.vy.&o1SO_5 -[-\:IGY'L3-E D,.kSU"JjKt!:{:IeTˆ$_RҮZJFPU k% ub 7,`:osP՞L!ph"4*m*OQ='sh4aǛ~,$P w*0Lv3/֓[ &R6FDN`<4|$0{=9DG_#L!z8jx 5ܩrxe!! yF@ d i1c{CwoHe~ɯO1gtzji = wSG* H+͝uHŵoe'_f#Ԏ=FO0-LP;w#H$%?DMEqx7\aܾ^g tpk5jT'L.`O-#'e;B+0w"}Or'~][:O^>^FJc#n\js(45ZOLeXcb$dpL5Nr[qy:"YdFKPD{C<l%|z /aV>]Bprc(J<կ2c'o_R.z.|;_M7SM'?>הJ%/קߏûx3kr/㜚>ΥQj3uWe)tezk7L*Rwkm'Oڅ+]* aѓ맘d6ԋ.b}Rە.3 ` (Ol\A9ve`ݭ{/oN>SIU[l &U2 S+,bή]j I;q/ǟ>;Jj=P;NeK7ˏt<䳗 0?'OP.-K&2UL Q$L;v7z\(JpZqc??3gx;ffv/| ؏X`?笾@CiU T+Ul`m|dbbǞ;_z\3Q#] "5M^Cw 7lm$㥋<>gNБeO2=GݭQsk~L Tp! =p\+9dy 巓2ҍggs|g+CP/o{a*v O0ם:ss8s4{e2ǘw B,ox*g1 X"kHÙgqKkV6l-Cx3)b\q<Ƨsxx$];ޱkw` mo./bXۺv{^cƨ=uKPa!_{7Ca d-o!fǙᔦtM34Hg[+#j"2foK 3,m3tǃX"RAw0 /#+sx "Eo KI\Rv5l=*o{=oưxCmv!޳@6-2t+@LO~'3NvBעI'+@O>Wu93{ï?? ˤDʍ]ɺtOs4Q}M$S/ݞ&G8InIJ $HpWi\v9* $4 AutauIeq2~G$Fm' #u}ԩ%DۨArF- >kX#U4ёQ¬T?j&QD([8*m򖩕"7:',@O),L^AJɲ\L>/3j_k.ו3Tfs+V6Xk]F4W&P?OAk8h{Ê'  5؏gw6-ځ\oK FY *Z:a000n<,Kw_駞dY..q%m\drq[׿}7( 0VqC/2]8hc,*ٟ _җpmkyH໏~JHh}{ugZL*Gv%TZs@`[oǙ,qn;:w7D4g_0  k&YȚY'kocKmjN$)Aݭ3:7t0LqtOzd,La5H@խ0^<R9u6 <ЋD Nv=4-,3D.XmJA7_Z-C[tH7R"mlYMkû޷3(%SO=拧zTYϽ;TȋL|'/ A+l^ 2HJQ:]n#5Q@⁙3`W rɅxNcW\)|ׇrk( V]riEd8: rcq(nMlML4|3GN =꧞?e/Ү%x[?FX  X?ijhs){~D_>Qfd,_=wzZ~moRFl˚0{"s2!]ٕ9 2L1Aи/?|߀iɉ A5Ñ/?䪴SQI(AD |sZG6ёQ_j_I`DѩD#몄 rz"GbS'Q˩m鳢PT7h:/x,RIdzҥؓg`k?7#VʤokX(a,5,Z fJ'NP+մV9:[|8%aQ{?HQGP-hzjJQUJPAjD&0ri qꯩǡz }]fHh %yzJ8d2 Jͧo[AʶL5PaԩSu#eOnMm0Q6;[]x1.. ??DLS+Kd2p+iGrti̜2Lrd=C2Y9V kh/V6:[% OF[`I" T-WJUD"w{;1?7Wj7c?G㍯+WWDnDty"ޣOa;u N}Y@",}fKc'"BzrvKmT;EGO=x{Ce367SӣL~ϨF ?_&o13jNq3I1^JsI&=ُ97ٯo C{03ߡ>?K20{cv\<'jǿ -pzmJ%NM[kd?tȉ/9/?xvK?M졇7!D?tU]f@;t7`<#C@FʼvչLHKv ^͉}Hۥ5{I?r~/aOkЍM:%A9q#Wp"u3,! 櫗m3F8Qn{m4AkzΓ? KJmdG"veUˆ ] ҉ ;/&Ζ&*)+$uUIBLU iGDrB-pʃFX#!Do/ѓ\Q7%mW;G*e5&XY$dQ xKi< |Oimqtj&qgtTL^|M$oi]+9ݒ3gժA%D&d_G):e]p\OzWD`e-}'f3q~#zuDU9Eg Fr%]ټ 끧ۜ6(r!{a,FP@G8K u%j툶._?E!YfG#o3nA+96=0虺< &|pICMN{N =үiH?r8/\skXn ^O~NJJ+Q_xm'̹+B{$B˺zؽy/3N˹]]]]x!}1bfmY:A*&XtE;0mUhFuXL Q3Bkd?J)uT E[x?>WM۽m]PBrwՠ<Gt1A9ɤD-G@9ˋByRlI i@*2 $MZr0}ܰsmeo#^, Q%9yb oC$DZWn@=m6( k6CO(Ź4Ħ(=R(I+igs4g\kXF~t W q.>TT3)ơ&p3Ai3pOʼnGH yWJu!ʧB \MW6J.܀ R1rN Z8 'n8FqG9iA7n?kZx'Vgz^ݍᖼ2`N͢CHx cQ{>ZߧkF쪌gߓm_.W++9pDे_ʏ]QOQbh`_gȡ&{plt?+{>hSa-8" Z6NGpor($) f DɴHE,ư ")ci3l !UAը μj1o>.+OOs <($ɧhRh?M=MI6LR?S$,\nis0Q.\3 T$ +N_wrrsx=,TԕoM=Ao{(MNf3B ct$?N"XrJ8(g+`MӰb#NB$!V!F#z͑8$`H8^YS󖋟'xg'boYEQ銵41Ƙ#@XxmZ#-Jr)(ήu`ZLo3H=\!u$ȢJDFuH*HIo[ *Id$ds=[C5}aJoטΡ*=H >uv`qۈzs cj?}=$L =HE_5%N%쥖(~=&H`(<sYE%ÖmO͹=(n_Z" 7FgAڠP3Q3? ~=tm ^É?Nz#cV/Y,q5-RqVw~?`Ur%yLՒ\*&*dZd*R1lPw''>2:n(>[i%ٔKқY{';pr)zpV IwS&Ǧb@qc\J^/3gIJm8PEUNk °̈޾vm]TVn~$xk߫\>zbf(фFKx?Q#Rr 3TT"FPUS8vHQMxuahɚww51hRĬ0zm~¯?x򾈊Pmhc+cfv\K3&_O}}*'n~=b+7$Mi '*7c''rvCA߸/÷hF*(aR;oByM;ŭ!}>]n"VmA5|4 2afkU,}["\x4B4lG^Bg+zG^1I#Fd{&T6ƾMgmPz. d*b9HWFab;Vұ꫿g~ ';RGdXV%Poޥ~'zG+XI+GR(jR-(Kc,ܷPt[Lз7i!-Nvbzu*.6x,Q)$xxPŭKE:'1V?̪zu$ogT3Y) E 탿i9h%n~j1 -ZclX-m֝AD~Ld.U~`ldX甯_0k_z1‰~ݿ>8X6.߄<6.I"&Z7s_TGaPm[bL[pF.| &0Ige& 'sL˝ RIIrYI2g}Oom' @' rKXt4|Ņ"pSLuO;?o>!jZvMJA=<ˣIeV-diE3\t$}?5\ qlBQ㒊ǘ>oaOVl[`|llxbT?j)|` VOm,OAmUQ\n(+ln_3)Vbi!_F )Q+Bo GJJ<xJa' lh 7'g~*UN9E(Ruj}c(wWaK=cC܄L&vS,I7_j&=k8@EMFFW3:n}"܃COawt!CxRu W"/?Ao"+c LԆīi^GPӗpk`9ID/ 2aQ1'y‰D_-?<]W C~ܵ6&g=ѝfH3AxkH+B$L Ar`Qy <!Umy)KxiSKGܿg#]H1S3TpprytM"ԃ]ئ4&%`BO?G$Ѫr/{i;09 btD mo>b{H6{T)YP{td[oVaduCLTrkUZ`Kzڣ-\8**'f=\"O'.J*n =g1l#GJZ*F|fƛc B7q6->"(F1Nطu?<㠩Tr%`|[}o}2Iscdix NT IɧXɴ.8r\-2K[h?TQrdGfl$A˱HXzCe9s xK?)Ҳ5wWqe YۼI>>g剑 g6( *I'۱?sl t`$gynn~# å^Wvۛ3ewddc;\9| 4 ]H?"\rC3+ )%nB>0}}}(8'3qin4UJH{ιLܳ>l.~ih|4EZ[1li3teU0;R 08m)J\ 6Ǧw'*_"a'>+4oV\GStL@EstoN <&Ii" ctc8F^@/Jq.1a6&0wKBBD*Uܳ*9Eq؝b˷!}"cr2ѫ(?=}vOtd Rwdzw& IlQ29 oA6d#=[ð9xgM8.ITUXE d68i&gر_h4J4!Llw<UQ>Bvm-l|o3]0_Wx鋆ؾsY5Xa#DR.]ڟ՗9ԘP=fp Ck%Y}F{r>#b%=4cW?QlY$(\Iٍ_; jA׃_Ck;֑|4+B!ja@z4PJ˘.𸈭DbG#vo,T}X {ģ0a:m6BS}.M ݀DV]6 i >UcVk' c_6 Erd!Ao\sGbv7\Xxb-?y u"޼o F]G V1 `'W8"P +l_ E`(=fT4<^*aedUs$ݽݛ16yoITTAx}+KlwabT ,0}&5T6`WM~ǰ`ȥ,2p,8ϧx2sʴGF\bXq"0}C+O@M])UaI|xei$Oٳd.mRH:ȑ,ݱ͢'߹ iA#/B @2m`rÑ}^ aX(䨨+ڿ!i+}M"72LfiSs pTԵpɢ\P5 D,!B4eu秼88dȜ垪\BQp\TUU7W3e,-f.Wd~7vrƖ'l5H$cJơ MB@NKvz)TU;;!i G- m=[:ll_˖ hFIbC[l?RJTnid|d´>\݁$3f̠,aF&YqOilnljQ^[k{ui"ZIs.0<~عE+'FLVUf~=Nw Ļ)-x/P6 5Taz]/oA*J3jo#-ߥ38rȘ6 s88ʓ1|ɡoWx̮n'q9>ҁHFԃ0@Ǣw0Sxɀֿ\^P%o>!Ԥ⪴-6Eՙ"SKb)UH#F|kkd"VL'rh vU\7PW)QUh'xo> %hy}r%FaGNqHJAp^MYIxm+{_ fF[8I܊7ce[κi ϚEYu^(qwu{P˶'`̿|5*"TKNM$3τ]2+)^7.ނ4IFTI-K}f.K_oPX%\lFʖfxe*%,pRv8K Ko&\:n.e4 YH)u3Cg "j=ws'.= gOe1%5S+o# R%k3yP &z8N[]י7w.@h48n]׏E,噧L:ӧNj;{%A6ճ0񢛰mپ`+scOxca\\|wﴸ42%ᨠKfJc&"dj$Zt-߃՗@t-uA~4/tLo6-;x#\ϊ$Btv3hkU>[.( wOf=pC&m”bIY5͘ 9ҡ\4,s#s|;ـmr*C͔ũŧG>eI&dFg9mlRH%}a_o̮]NdLFrT7~Նx/\S1u9Sm/0k~+<e˳$Tl-NtŐ\!ñɄL\2hlj%#B2UI L%sAeQQeOCq*Kxưc?;o(hƢE)--~\._uMi'_Vjʰ9/pV|kw\v}套^bMYo?1"+t0EXzv@Q5+.Gwa+OӁ,=,@4ͫ/Ħm#TUa lXxb3!)7p %ex&LW'm Q+ FG\G4窃vF۰lU(sc;-hTjqnbN~ Km{B[ϸ:Kqk6ટo H1بu( I8-Ax8Gs's 7p%WвdID2MU/VUJOc5w@6qSa'Y+`FD Gҳ] =܏iBPj ~*X/{]wM;Pgw#^Zy܄b!rtn-3. ' }zϕlX%Be06D/VT19ضve"8B:ڞ1v"Y3UxN]>y@cuSٽӮ a EIh}!ږR:lm+{N8n}[RKp 8DJmO;C]m?x ;u5y|LZvD&g "|BA=B&LGahǯ:NfL+>vM[Ub;:?f;zѫ0.WSdF+&"DVt?}sϛ=hQbDx$z;Z!cc;6 =37I&'߹gW ))sLN(&'Id52e$2#I.]$T2\{\rLjI-[sR;}g6ĴMzc0Dr%7?>liǶmLIJ,6m]ؿo[n%b{)%555;EUQ`׮]ttv"r1w\l&fϚŘ1c|\.TU=l x7??/KgJfR9͊͢&{&БnzؐFkI (8%IsAtٕCݟ4 \8XIWHR λlt]Vc__H$o|kf؝ FSQ[FWkOt>x&a?9j'#bpd W]EkK FQUMӆ+eaYRJt]'8(@y̛H$fM|aۇop]A4raq.'{X@8t<[MPYAT(]B T) 3$Z vZ}Ul'H[UV[BSqMD:]юAhp3nd@ -/79}_)QK< ;o26a#Vn3gmP#ƥn~%=o!/bU !t?R柱wBϦ7h#TbUT. Ƕ@:UÌ!S}0d(D9`R= oE !WzP c BQF 3BZV'׏Eqrq}φ4X-pB]b!8q5)Lg1n;D%0{h!;lP⍽4ݷ.<>Bvl"Dh`Y՘ .eL_8 Qbㄫ C~a[ց+)*'c79eSZ d(ٔSrYC*b"`rp} Q2S*g8K9ldD7C"M2l*'THYdB%xQUC\x\h}^~%|)oߎEC [*x5r >BtŒ]0O [a3)h5kxJrNZppbƒ|7L:Ռb0X2HWR)tL2p*I`J&2J)&+RS[{ #`E\u5;͛7ϱmf0/”)S;p'*Gg0N\F>.|>#U.h俹'kynCР֜aUk֬!*]q& Ru=[^yP_g}.sGQ,'J޽Uqu7RZRWR <ؾm "`LtNss37GԢEun7qҋ9kD5mmXŶmۘ1#t$u"m 0unhz&ԩSg>ֆ˫S)ëA~mNAw)z,ةf_^$S./qdRat` )IDhHikf07#t5gۨeӌpɤkX>u yz`֭8MԸDh*_K襷N8hkẋ@I`̬„ž#N0 QskGF`X ;u..ĪMĞ_p#|$R#"8KMp.\2'6ۈׯ\LbJ%3]8 ܇[YovЧ!:2f 6킄u.ƑVZI5u#o=J[A h}a3WJdeqK 7P cqǠ$[o_MӣGr\!mplŎ7^U\n5<vӔRj'Uű,:7˶'~Oĺ;ELƝ{J>{n^u ^z%,ai~\/_x+njnjӁWqŽIO:ƐCkZ#IKX G;!PUUUqݴ\|\v\pÚ=/.gcZV>b$!C+$JǖU$}p"mO.HRIBi !U%Mdttu;]OWu܅ QU%b&^tW^u_xܹ_|3gk}Ie _SnHڍGmxqPQW.9;ݎ wintUŵxՔU~-qp %`0i,FIpҋPU4Y+uv8skM# 1id6oڀ磦כ8?lN`63v,D( Xf,b\x.*z].0 ֬][0ٷHo3:c:3Nϻ75WeZ-̫; G8G\\HĻQ>f\W6RP.[K 9o'_7Oj(fT.–6Hfm@Sx'2Q}\Y_9S_% >Gfl513N0* ؽ-Q(\V`tn.L U{=>ع-z:p?}D!`:bh$؝=Hw9fOb2ubdu(F]ɶ[]лD_ڌk{~d%֞.J>v:jiYj:FlBN8em!Ts?^VG˿ uto1(iWɀLj+MQ혦IWw#3Ϣ[T@qyb!%=Lՙ7 f7PFwoN~ú?;Gq}RsJ:ֿwC XظOIװauC7b<^P=:Z?z݂=M k$DbD>xk[uJhS ]Gf~;U*\8**U4FXϠ>?=밨J(F1b#%M<'hlvuEIHk#P1I}69X#dLEL %eq uo٠\HjҗdM<2|H}[drвd%segs߽{7?\˛BPG:8aloK2UG@b&maKG:ncz*k*(-C4TEEUz;BuhƖӾ3Vɸss8~؂y1 ~?_Kx<";nM7`Yo~;_PŴ3&`!˃MuġAbX%sls!FvM|8!ӊ"ZΑT9");yLS]uݔ%E:VlP!eH$0OJa$H$XyXi&r>1"a'g>^H$9{6_4;z[|_EJIOw7iH${m&aB!#YȻc wIXA`՟$_()+ɻm ;v{!nxn!UGG.vl(*K!h4#qPUcJc:Ɛ:OmɭIZ&ݥ̩:Uh>g=@ %׸9G 9z`%Bw#8~d{Kql$NR(3>6W0v6">ضbQ1$Q3*dmD+|m$x.sIdEgM=\R^ƒV9ʈPREP [-:1ŸT2ayf7x]&S]FٝVٳm Ig"n.A V½-Q=/!jB~X bRB DVlۤc:T_])@CH۠ѷ=pl*޴'$P`TA[LJJ*)]I$'d~cFu{@Jv(J-4_ ;;`0ql;ԉD(j|_$jߔ*bQg*_mCYC!^Q-Gs @PzHs[i~}Fh)i1R<IuZv.+(Z( ￲ UQ29VJR*dH#GIE>p'{>ml &.iX8Q&TmlG6$\j%GHD>p$P$gs5lc\/9y?z~@ Q KF *̩Q%U"+(L$6A{JZ םV)SN铬ksX>= g(7lɚg<|o;8 c~_~CjsD7R3mjFxdW3II-V7v|R-c$^'j^ȘIĝC-[Ϥw]͚gKΑ [d{GGՅc&'L20 FEm]mmm47 |\+NAS"J_E((t$pD$AӖfx=[zPߛt[*,#Y\zۅnM|¡>ZR! hhb"2a9`%KN̢t)b~)%NZC[Q7581iļhql܊JH@zmc [PZMUwҴw/=nW-ymjɎʫwCAo/_h3Omy]vEz9gK2 kaSjVqy WP18B:ji-hmduV)R" ITyyboEEaeiCGm%PۀJG0q!zRDS ȳXMKɧoAU|dy`2ƐpCX-}wni9>I5eϏKLtVK(aMx5l*pSd: f%yt;V"}+!jXqD -hBAUc}gуU8(Bq,2-TMp+-RuˇP$Bh1w CQu56=dF+4H[3[ H$xʫC9bƝw5=)%ۍ.η i R,Ɖ8^J#>1aI",̥[wJ[7$8 SVx5P7VAjL-əcѼ4b=CfA-ZKQbpOMolfaƒuL>0 "LHG(H &æUMyl0H6#v*$L9,tҗen ɴfSqjF09 "\l&d\A+@vS:dS/I-ϥN3{Hbw\Υ7]8[֭{#{X *O̭QLD-IA%GBJIpa¥%[o]sAȖt>)Yv-۶oŗ^Kw͙gh3yDn?ߦ0RLc80G6$]$]$2<rmN0m"_$SfO$P=B x7c4cs-g̽/}A3!T,–MH(JWGHnj}fS#G*^bZPz\%ΝF۞2Zwƾ7yPyӱsT,ܰ4i]84773yJU5j4}}}ڵ hYZPxnh44j*uuBtuvۋN"O>U>B!o57%Rzc=~v%4p+|^/_N8[ĵoe\Ĭa}phG[;JQ5vvovl<ؒ) h-bWVEťUy2kem0j"wށ=HT`8 fE+q 1c`Uy+>;ne_}!mؿ b6\)"C,$p%G cx H6݊>aN4"CUyrZ|,鍁 p ״: +1ts),;Uzl%ƍ}u+_xϝݟ C,`uI3Oعf/ò*{"i)T(@ nHڦ$ 8vZ1 cBU,۶ TQe00MsPFI+ =pw#~|(QA<'O0aFǏʻm]]?O뮻X봄8֟~  tŻOSC:6@"zD^*}XJ.CSh/Omy==;QWy&qD 茷ma3jYx\Dew!|HVBploBw:Pրĭ(PSSSڬuWǩI4,?e7]ZYFoobG"VX&L4YD:[q$p(奐R;{~w''GMfNICeU(Ҵ0=jk9!bF8 7$ȸ猉o^jH0F&"JzK)ӬÈJtǤSfd"hURJP{bpysLIDAQNhy8H._tmdFN@lZNyM iMb-ly>t_ i.-c}oydP?Kбi%.T}8&ނIbdSb=o6.$BQM,3<4m7!6آ˿j<\RLfch: L H_7'rUWN޺=jBk[@ gUsz##Nz?Ĝ3gb8h76{vo؃7Ջ3i#q'5ΙVGTm(I%% E>$8K}$=2I& 27Lb|QLNf |dIM#n?'68#T2hYd;pLlǦ732g"y#^>?DNjW|t*EEr'l7OW9kmt`mþɍ?V :.~yfߦv K?r{66}ά,ٔM~g8g~tY`p%+\N1B*O]]9l]w,h..u6!ʩ*^LT,?s<ٸbUT5̴q۴%X_$B&[c,sڒ39scQ%)]i_0ƒ!Xޘ,ƑԽ,:V̂sM|t(۴7~*`555{|scŊtFyaǓĭ8g=?,v-$ƥyWʓ(](u|u1]Bŭy[KRVִ fEP-W^yDr Z?}ڄG6Rրغ'fblmý`sz ^:苛pBW^:ă.(K 9>j`M˞]ߊn>pb^Ĭ@!YbZgL 1a']wqat{JbIwtzi/~sƏ?c_0 $4<LulI.|68@I>ȄMr6(x@HQnU\J1P(RAqʄ憻/gqaD|ʑVDU_Ff̜5 (83#DEUB e޽ń{qJJJ3f,۷m !)ucߟWקr_%[Pg~>;];KJJսr?^&uq+ G: 4HZuNMn2Ѿ-fliqߺgF*7q芷u +L\ s(n"\2G+"#_Y_Ev@H gs{!bQز &͂:h-MH݂e~NmBu_x# 7m_Mn#WE-NijԕpΚs9PL9ihח/1;!M!v!}-ߏO#4M4?sP7B@h*/$̠zZ9רi8;h]S6q&v"Vװq]LV{XO'B4٧; Uw%K% 8-({:1c BU׫(|hG ҶpIٺ}"G"IsE|R*^R>fX:ًf(-/uVQ.s4>|ڇo~_;hr3m G] 7k4y٤ׂus5s9gDԿ}o+8{1Alh)_3| I.l) lK܌r8C(bQ?sdsr gn(4M#HER.T2P^VDbv0Y5 ?ʠ.tPoı/DWu*Utl}痿_n^x"_A_ &^N)*`{IW304B]X&tƖ'lYM^|rVrw53+PIaco za9 )n -NM( Ig 'W [qZ#RWWW HB\H! }\=w}?>Il6,ض|! BAqةK07l'xt}hVd8J|JJ>y#H:}Hk"6 g7dN@QkfF29`#%r'"<:B-nrw$J>r`n sWzsWB:q#ܞdJ%'ܛM89e $v"Loԏۂ4ˆ淐}@"x}^:1[ -P H/eCOe-/mP] %K݅q;ڱxJ+px+q#>DscF¬78cAt#܃TtbkjFu_5f29 *H7LA-q+)?8 N-cmeC$)II#1ׯU~v?$;zPҒȾ߼69վZ4'=[HXϠ쥵%\+2(qo<؈S2JGʁRߝ̬e6)<,s- uPliO9XD1`{R+IWi֯Z,'\$*d$ |pI6%CE䔋Kn]:b;brt9wLZp_e%[ V0IG084MIگq ̉D*ѹTeAe0^_|ᮻ/<>ֵĖ6.}!_u :c8H$Olz=X(BPo`A9T{PP[Q6wbcJL;o%5Edh%RHn7ச6/ qSk\xߛ>LZ@y15)d4Z0/܎WTsnz~G+V"4 -5%88=1bolGF5AΔ 84ʖtEU4&'9\,HO,v45 $npd62t#zIlSr+-\'w㽿*Hwtd[ M$2\X%ufuYdd*dS%HJ"~MWK߲u+_ٱs'.Ö j9 13y^l6mubG` ./j5v`E`Qy4\/W@!8ʋ3(r 0וRI0-c@rӝR^YVdQ#.[Z\ऽF@Ww[ɞMz === z@J88ey^iUՎc۔0v8vPԤGSc#e*ʰg5G%%Hx0e}_?g&ahng>JKx?nsЍs9(y*KFT8uu=_7=qint͔,9RwRu3ٻ)9~~id# J2wQedx9D& p@ػy)dW0q͛FK1'oB2T{_x_4-D~K;ډ5Mp! [ZQ|.A@z>7 Jq3cpMFZ­}y3$b8/|CWhw\ $UuĻ4nT^IJ\ @ (_r=H#F+ҷ-]5ڋ>~g1/= yh[HRGTMS3LT~w^J#(4 lx'X8{^yXGG1M밍x:eR9emkӸXä+no9g7_%H1m=ųTNܢdEY5]G igG= jD-s,&ϙX|(F1NT+ .,"aB`KвC%m QR IlL)$-tR IRdpt2~cRFTII=3Atp$[P&&q$*%"yR,)*Q%:I fZPn\I6Gb u9lrmG-ЉdM$[(q+>ξt&N?gƗe6mٌ-aR) ^v0)Jj Mw鴷swӟٳgXﺚ}A3!@'ÉtKl9V9qW g9;gd#P_MMa„ N2EQ(---(8| M⏟KiU~ZX@Z~Mn0_ΤIc}ͦWh f~՟ a':=@[)%bTp1m{uVʄ'bP]Բy L@S4fmlYO̊Zis?tlV5A(CP0Pq`Voj$Q<baw` : x]Xm}D1@=`;Ȅ>e,%`ބ E8NW/E) m^/Bу87VkzN(^xN(eMuW@IIb><H5[s d@\Ȅ{XI(`JUۮ@8bA6=ܩ7\ֽاlގ] cv 4'3vK?c[\ }EXJ,FCl\aS?ÊPCJ:3#=dʙ)0 g*aRJt_O-XG @)Ҷ޹?ĜDmƩ47տWx ޷A؉LӔc !T̬~;U(-Zœ#+:_3b`Չ5K(Հ.ڟL׫՟3sSEwC$,-Bwϳ( Ko?5/űdt˛l #8>s;fbQLfA˖&@dR=) @Gz ɴg.k0gf'};)%1#:8?/|,կk R;_gK켊'JX';mJ U~#Ά~2nܸacڢI>6:-Ofok;9!lF;n* ko˒K v~oىeYn8'>1e@H Plh HAiiia֑T uغ???x6,D$4 ''k}$RUN+PKie&PK|z^z ,賯aoV#mp:Wj >}.Jݱ'T Do'=(.m.Jx5*Fk;c"eB~}]otJ?2f!<VG'e$jR4F8y'w#zH|ɱI㊊ /m|&Qq*zB߾"Puअر@ъmϠJ^rVlPf+&|g(K"+m;y:# s5j|o[6b_ZE _$xk?nA P H<2ᒑZd;~T;h8*A&1cK^[olܴh$& !0L˗ko}SNUUzzzяY_,~z@09s'?K~6eJ2泼T8gQ#ɄD ("`rTڳXؤ \?IM>3\ )2'M>\$\'MN>5lj*EC/aߛ'zzMqkY*NU1̓ݒ$Yᱭ2SPX\n5̞5;c?k,OwWx68@I:TRȦ& R*\)rʁPvAiZJ x<֬Y]wž}p\2 ގmۼ q~uTW?yBJI,qds |s3+WoKw]Pq![LZu'1Iq߳jj8O=}^nA&B"Xx<^t1sP: IJ,HvEQp۶!ꁺY'EQ8NAGJq JIz" Q*q|>os0g<̼3Ѿ ^5eJzcXvRfcoaY7|j2͜1w}6%zhM+WU5cRBkdq;]N9y*Tػ7_eha#X(BX:z8z q+ʶ4w& T̮lL9hjz=2!UC(RHV!{v䖇lr.6Ub cPaI܋P52JiY9l4%j<7_>kr%G-&BS#aubnCO +\q>p)O0,oE!p<>`*s&j݉ sWg6Q;! ?q.CU{?4(|PJ(%PM;Q1(/6Evڗ^ޤ[29lH/hrμϸ8F  h4i FՒkX|ȩ6%-lޅRZ^ fo]fkj'Pc>cuſ.bGUDJtf,d5ӽm=[iBBQ1c}Z ]^cH'/b'dh.+>s)O}wClV9鿥o ɴI_?sy6o&܎{\RI.%T?ZZ-X t%)8es8lI.@I.$Qr+>*%x[pbD&RHdHƗey~wl2졔b>lH'3K$kᖶǴA_髇5~Dg^1Z4l䛼)ZdUCĒܷ[3x\XC#~3f̘g1no:s0!ʰgJζʠ28I?lUa¬SJ?}kx0aqƙXg}_^x׿Μs 0CQz4ț7-**g>KeU5]#.lܰgyΎ{Yj gso\ǟI}92D ynwo7-aL0+H$2A P\.oƣy &2oB u`FeYtc6UUt))-GNs~Sڵs9㔖bGwIhs4mqd[uO~a[6B9৞PRV#۶v;f,?я ڶq"=pkn*tG;:z=v˝ je|>@_WHZ#ս6mWFiؼa֭<̝;7c:qǰwsӠFg `|9)[j%ٔT2CJ {ꫯ.88>$1|:'N#@W]X8Ng[7c{ n!?ψŢ{ K/ˍ6nƏr@J<_c=twu՗+P˲Ţ< 4W_K8<n۶՗1 .***M>'%v0 P?z43#;0FMkb[c3{&MiӧrԪ:of@2~x3a„kAwKWWWT*zn/O3iex?@+s9y?lݶPD3]jz=S*g1j%2ܪlEeTɘ~qB= $$g;rL,İ vuoc[&vl#nőAw<cW2MziİH'JL=YឰB'l~0qclk_ҫRSBG)?WTZX/Ao yV E(Y$a"[Cڒs97 ֛#yU  Bŷܐdy)2Ԛ~X"QߺH8F%9 &J ZSI?BObۊ G6Jt1N_W$ZqxϚDVȔꈦ":2/Y@gَ {ǹqߙEc)EjKd$Mq88'n-[,[.Slb뽠c˼p86u`v3# TR!64/p]=O'_HʫqR @!t?} Vd!4?LÅC>T} g,f{G7cô??X~e %$nʼn!ukT2O倔z0Xx͇QVHz7gڽH{+ڦQ۟{Srp2«KGnEXԏR])a3_`ţH6dpy ok|K1˼Xi4}`]woAjݧ3b>̾2_i2{ cHO#Z̬փ4|g_s&>msI1RIrI>;|d˷1/nP' W/XM6;:L.ר fk6I3\V7%\;og]uI>2iL()F.q;+ $PxX5NnxA{)n݊8yǹG$2q!6~Gy ֡iJGrJM{UGPn*޶;{;5_?>Ϳ/n&>?GSfX dnx$5oM _wuc-7򪷣r?];ħ>gCh}έ-۶l+瞦˶_K2<<_VFiuDQhkO۷nG8BH];-7݅iZe֬&tn#5?#al±l~g?^%\=O6~|!nv6oLww7hxbxv#ԇ_݃;p!}Iq i`HMj8}$ 嘘i1b(5@H+#-ډdv46lF IOnSc#^5i!އoᙨT%dfYBuJ$ 4&\G|o#13ʲT+~մcm}-?II== ux\v'akcQ -YFjW Cw?J\‰anG' ]{ .ɤTIJ]c79Ͻ%HY_x?KP}_!Ѫ]sP VScʽ26y / 'Qq=?}&H#FiEEG>PA"#za[ ']lT^Z `v1­@(ebtKbW(^1HEMvOդV>InUZϽnLL]c5NsM7Ӄ0|\6Wr|yGROrbkCRn RVsLmq7|3>u%xBAԘ*ΑQHQHR\KxV $3V ZǶm +V$jA9 ̝˖-QRdLrXAŇAqR\w,Z|~@|ߤqZ6-l.nƎɼFHrxMW^˅מnL&{<أ446 300m>~gömZm?ϏHgyݍ0jI0slm}K  w'tMg-DQRv?CWNM %>?/?Y!fpM$5pj#!:"$84BC'хAH/&@Ȩ nmp=6v l@oV]oc{Ge3c(9m4Qs;9t8C>^m{w^I(y/s^װwbulsV?eKq5m]< * >؂M}oǿr0UMJDyӯbw޴]L`$JϪF _?|i bIXNZ]AT55 8׬ƹlH=+#>Hl_Ϻ%);>slB5压#^!kDhIXH)α ߋ^QKS7lbGh~oA4<e؄R>DH#$nGqlN"$ڶʑ/LpU_yd%BC},Ǣ}C݄R}|p򬰎2`jw~i?Z`E㙜xb98$*&P\K"D|lm9XIfRl-w].g;քB&Rd;ɨ)JI&bHE $> w6UFHMck#"bKNlxn"d8rI#UG)FjgSDRD>)`HrS=G2q,Jf-mGuR'i:'xQPϜO;xh)uo܌r疛A8rxUwF1IQ 4]z)_WKgsٓ.d6Q 5H1{<4V~@g0d0I~g`e #%.@Y&.HGZ;Ij!?M÷YU>{{?u)(C]}./GnC10 }C.AP4ҹKzjA dY5N| b <+}@ L0KbZiRC.U\FfIrlԨ9e5t=qD[ޤ"5PFEa!5p;'qM嗡UcvBF5@l /C㾽IŒ.XS9}pR6UFS39Ze@'3ZZ p+XT}!k^Rftr@xUW Xd8V/)F*)؞(#LEB)|kr\P2'maqKe6IRrI'O dL6glM.Px1˝bV91ZG09F1ձ\8*,\{|D|_hr *&%eS)V<2DWn\6'=S4wy'=]]7.̮81'&\1WNW1l)n0~L2Kuv~ϧ! WO"sCGHbK.jkrNDmh `M`0H(4M<ذmT*5 1k,_ga>L_K^8Ϡvf5opo+!!_ 3eN2> (+/Wӟ4guO?[[Q8TVVrх2qF6l؀f:ͮ]ep;Em]=\t1-Fu̝70H%^>0i>0wy,?dnƎ;mq˹(03K=,PKLjbwGwW~-_p$3838.vŮ]hkkVA*"e[nt (UZS =.J#a4a̓0c:`Jć4*RH9sX`[ma˹ꪫ'>ܹsL{c /wp' VzfnfHtkny&eT]z1#[H5!v8#Ġ@'/&v$oAG"&vXXqP}CCXHm ~?7\)]4@NZF *`Mxe-r&WqHbto5+w28߅90xMϢ"ssn@8DI+ʱQ$U/Ĩ%wv~(!F0:e\JGkXmkGhy~躎 UPvλ)#wN*檾>Y`N:~BKܞ(G +XZ VM feՅ+eaEJz֒ꈠUqK[;jvycNoӁ],=sɧZR(nvň&jA 2K+@O8y$'"D Ae٦U8R ۛIy˜| *%>@.A#0R(~BamrɽT9NJYS1+fSl"Hrs=ME'I uɪ_xy֯_4 Â.Hq⎱U:_~TƐ޸CO4K6 /uqUW󨪯dwxy#`&%҅%nGeJM!OKI2_bǩQ^QI'}b>0kl~?$裏b&?я3{z >O߹Ρc"5* Lj;;y֧xgEJp\+V`6(]|+_oT!"RYYg6 miLx Uhfńʨ‹.q2w,iyOfh>>K4I 6/m\kϡiVA]&.ߪ^:;;Y~=۶ne߾}ܵd2ah]wJ'kZa;6l RHK0FoV=vZyK@18%:оR˸+Bb =hmme6K.e…\8Kqw2PާM'7杘{ An}G+Ϋ!F?y^H4 K`~{8Bːu.dP>O܀P5˛B|hUJb]C̖}va?Ilq.9u93ĝ Pf#>#W7 t>N9FLh?]`[h*j/$+I~DZ V7Pw7U5B>@n6v2Zrg,`;Kː0i-RjH!N߾/ko_OM75A`eRusGWGWIf'\A'i%geÙ{vzmS/:,e$\}VzځC u\>j os8fәlW @~y0e}V#**/@)TD$|љqZ15UJ)BJ>(V0N`g$=G!PQ¹xjA36sd}AAU_!ձdX٬<:*W^3҃]pl_uFE Ov\$pMW}8UGT ÷}Féqmbp&R!wnbxNR{;IG.C[|zu3J=)+,4?.8Ti`qɼٻH+8 k(98eܭ,4Jt/{Nʩ ˩h;6s604U.拨 SN)E:4{)=xp|-TϨfsɵV%)f*BI)V9Smj{KJt4גO0f!d#o'JI,&dM2t /##^< `r!WŤX|(Dn W_{1;:'WV+V(~';^>y.1m}Ѵϼ4 1߿[ Zrb*I%.>pB1 ^,vG[VIIk:9 aӿo9'sNV/qr&dIv;nF &xzmz{{RjJ!eb2||aP _`}$t!%3T̵jѝ`?묳md*e$G-Z[[$S.o$mO+$d_=nqpGFqeW &هHM#\:Lmmmuᩭ^6UYK/OW?J$7BV .[D٥glILfS" tEg2߷FX ]{ NC%JuSJ!GHQskѪB(ж"h~i7ÿxRʴABP]sbPPہT+8Rq\LӍJu3L5Χ/=BJ4]quʹcdX˛_h拄psHǑ( XH% TZJ};}:TTWx/6vFALl2ULT$PR|tڷ̱1 [Ha %6NQj|n>"e[H&rɡ )dy/N\2I JLڹB>id&'JkVr,v_ BǩP-:ّ{M=S0 &/"7nD9C*3CAʞh˓ru4~b8 )a3%IN v<|,ir} Ys+8ʫΨ\IY%LŒNRjZm'R.=@ -Z{%KNid?q! ~|#p]^wݱ;E`h1 @:s_!'K@! goNAO0H! !z1 t ٻ^s.fYH)K4p(*Ai "PѴ;җS3} mߚrx^`}%W-Ǥ?ڗ 3t /<'@.\CG.ɪ B[?8ڽDb/> %DiJ!z}C5Ȫ*mfe;n]R*)숫^HM!| glԩPK io"-掍q>7K"0)ƔK&kШ9mut<3bbtߧORvfnۂpՕꖝ r|nEHW\9΄ExenM"->7_#'FhaL|WaX RMvi$Ԏ΃\f90KTbcZÔp suSDt}iO4"PS.xLe!zӊA3MK\68luS e'NN'i~z]dSĎi ^nEhMXxg47L!S6Wk Bڃ\Į7v+(&#S.ud%|3]|Yk6$M*ɨ &*K`)d[dT2p ,J>"Rjbj%)DLɗfJ&G!r'd착,j}RĒ,E;$䓾/N!x*&/-˞,?snbnqظq#.% $C 9:IC$5{!e+B b*"i\4`mӊuk5\.ymH4|XM>吒&銐K-Drɶ)tٲ;Tt,c9gH)%>{[|sp/}|8A۹'h*:6OD7 N=gٴe8Ûoc˻ "ߑ5/߾@?zB1B|_۱Iq8̺71sA}By~xtV6Q;9I&o9h|Gu"8!]_ý4oءKڏMJ98i>U1z+8#~5!x.Qö 8FbYFk1[*A!|~HvBv9kShwANs6ֆd эBdTJ1"I(YW\#C2nG$9v3K*N|d\KB7R1>eN=&G)F#dP4%c% `XL d7Z5vj%H0wt}NtGP=SPf@0~mTឝyEgtӡ/mPRE+*9{v(vl tgWѹ$c;q%Ya 2)Rwx8a0 l޲wٲy3|k__-  <ud]UGQ]W j __ D$lEYua&IcO+OgX$ۉ4:(zI!WD(ۄ:$ Sr.1Ʒy*U7V=I' \¼~~A+lnÎG=zu8f{)wL t`"n~#f{IJ|ge-OC}/M -*R-{.fARXa.BA Rp6Z &LSPY.WLCW 7mat>zF8r$)`Y$A;"sBӁaIO;gΝԞsΔ~pex JH>bG82A7G$6';,%N6$T_WD?K(QL)"'c)$(+:#A̔o?1Ɨ ’$iӫhݾi$a;%g.`1s~B|FIVN<( Y&^ӫ^RHG/j02N0tD]%UCθJ;B865@3| l_Ojdlh~@Sqv*-PQV08xh$ O7lB Uqټkiuǭ߃OJ DZ"[$({#dw fs"?_ːCUHE cb&un`W4X8_2NqIrgZ]lr)"R2)F>M'7rđlӡ.Le9$B%$RhK)f[3Uk}.>y&&XhRyLtcWKCoCrjq.rbeM6'_h놴lDS;rv9a 6*{ tҖڀ!@ilϞ1BP^@8߳Lƙ0s<2 q+C3cLض@?J&7 AWWtMӰ=4q[6S8 e\[  14<77$z*ꫯ>Kw79n. |1f۱giVԕ[:/k9t䄷ř. ЌĴtϽV2KZHӂf.h"X$T 1< po/?eJ~^߂zsBjTV?CnD<q .DL4 cv`j! ]{1է>=+IDϏ "~TB=8Ik*UM(Cэ:VFUVrI)#Iһ{]Iɐfԃp 7u\;i~b5ATN$jZrEMK6LdA'8ֻt'/U^Mv8U!+W@E ՋNA5𾭘(ʱi<\` =<rʛiDZ@п}=ɡ>!5RRC kehFmIcņp!1j&4{)e NWQ|HdD蒾wq-gFxͺPQgo:< b7H*j'_xTIJɧ"R$RH$7+t;(8@4DH*s5dĂLxyuk.8e+C_s=;l47جZ-ï@ ^pc{k;X/6YvA.l趉ZЛvFK$ Fk?'6'tM Or$ل $B';USCttDQHmt-_d2ɚ5k羀iأJ)رc;qw";-{:#%P[Hv:vty3^)A8:qs--lg!&@t]ઙ$Ӈ^iʶQJ,*FN̝-؝=D/pUKlgl~TuR*3!s:LWՄRbG{(:Tc  CG(F !\QR)TDiͤsٵs]8[PBb&qR'Xu#raeW CͪЂt<3{7o㡟aE9UTAFX!FH Jۺ%76S5$p`e/.@kl\oʚ5 sһ>˲|3Jnَc yD9}kf`DmĊc+:毤|W{%'<6"{"#ɍ[QbI$7|Q1)F"U4)fwSDRjzRYLl1B&qVXcVtn Ç > R`"-6wl0@!_kST#[Qh.^pBeuN$rX%`$,8 F,EWRޮC---8S*ݏX\vQ;%3i9^Ԍ q3em$" GhA1B11$aH'?&1{F{zQCG_{]f}uӑ{7@"olCt aP!pT,t>U)FR/xC Exsv.a|$cI#Hl!h t6 'Fl! 'gWk0w;fԡf(L#>$_X։3q߅G!+f8w%piN{\ RDk@ aj n܋o_UGjdgcu7`; jB6,>Ll+s1*jx {;0#ԯ~2FIp,f/M0ұ˰)z6P /7w & +CjLѳU Ƞ{;u#~>2\ge[!a҃]t=k_{;1t@hGh$:vkN ѽh4\A/͸skīϏWہ{-谨 >2j}J9|e)o^ӻD\3g&hswOF! Î,H!HNwđ|]{+.Y5} GV5ʚ'pϑ.ŵɬϓmyQ,%B.##d;ULrnx(@)lI!\|\=?yetӀ䟧*N%6:| RX{}SnNFcX! 갮6J Ri7?i]/xΝdh~»l W4u'_!YhLm`MB oƸoa[ѵ sίcT5- %/Mj+>f&N:V`݇J?漿 Ccƣh> U{6[~&Z (3M!FYꖟ ]ovq͘Rkbp)F%gQs桇p zȶW1)AHRt<3d+?.SIgCRJE"dk/f-lfЙR:hиi|92ti#)ǡ/ԍ44qzӹx NoMu|)h4_!dH$'d+K{ Sk.Ud*)xTLN\x"S=/Q%WQ$;N!MhyUIrI$7r09lk)bO)%ZIDzeR 4Mҩ A͔RԮ>قkVۼ2MsUf[)M^,ٲW0?l:}+. Ma0l)z4,s'+*1:y$ŔC2dl<R$bKkC3„(GoKKIy{{7xi4D!to}[\q%)44',7l%&Ri@/˿SN9 %rxϱ^NN+FὋ -=xp46P-2QqåȕKƙ>8"N8} HTSf7}81vB7\q0$E7w!:zI_<>/]EzW/1fUL sO/NNTٍ%T m/N# t B Ez{1w}o#pљ.!b_Os53䙼{>De9W}-]Qfa78-Q޼}bmn~ ѽ5Њh\|Xo1S̼Sz׿mH/3$+p43lC]t}f>,ZRQ"m{PfǶ_v?cY (,<; Bf0|ʹv2Jw21ڡ fTv9zYBhZ7Cz;3`ct<+:Bj\A0 *6Wp\K7a6 j\+Q>H2v="ijOA lbZi\R $%N.Y$7,7N1|כIBēP1iot2F.I$ӟV%%5 !$i.XsM!+\rI)"EYdώkS$fRR?#}\/ .S4RԑPzLr!SF}G\)tkmK)ɧlK)FPɽFNs-ۜt ҩX Ɍ!tDw;HA?p͜HlziT~O“rƑyW4fNf8[AsPAvϟ?ܛ̰op!)f36Nj)\2i*!IRc^zo+NEE?Owb1J)|믿',˚6QD4v=XPŋ~a6oa|Tjy?~J<#0A[hKȖm19 ;G0ɴR,[nj ru53,}ٙ<'ImqgQhU!(,3'UrB 3SA$V2FY_pD յvJe#@ͪa:96hiTrZ,gH|-8:_fԊFCCe({lE)]U- PʡoZ-@yKZ-8 7-Bh>T܎-MGW2oPjcEtzv/H}Y͇WnpLtplJIhw*&ʸ f,j.GҽkӁ2_=XJ2.6fW;it'rHQl{u'W~ xjbk 3 Bbēy(F 9|69s2J#b0{LĽ{,lKL*'Ct=IyD)5f{OVR*s ϐBI%R"wG09 Q\RLw*IɗNxTÕ^Bo1}>G_B i؃QQD؏~e)Dye6NF6¯_ڀX]DYK㬹MyM!"7݃d.ysqPBx9F~sj8|2jR-Dzc-ӗ#Śqasek)giF3aX(*#cqEWijeiHv_`E=mO$8>3^W!rRqMWQE3:8ɶ/IYP $R'=&RxG9m8KB#w0:B"Ϳٸ4<D:9O3?CUç^}`=ҥz8fIJ$RE6C\8JCM(dR]g- g.#s>l\|UH%_v:੘&G렠JInx18f[;'W%5E YHQ(ds榕{[?pFҊ`^V@Mb EvqS%sc qXL2ĎRlH\2I15\ŒlT|yދϿEXM,\556}{mƃC`aZvx<uo 4ʷ"q)!wi0A6P7!r=$׬Cœ$zoBsL#A4j8k71O`Ԅ048{ #ImjG(f\~ n).We\*Fi!4I^F 1T,N'AG3sq޻8~T4cz;~H:GD=;a*+Mx }?h? N*NcƊPw O q7$ݶ'6J@:m0| 6Qt*f/W ر±AˑJKIzMϢEө9ћvOw?31V}|avB:C D0=F%W3#U)8ә{(#}Q-8NK\QSY3Wο>&/f2i@!ôThp xḁR]9smZ*&$H4)D*=w*rt,TKra| O8JLǺMj(p@pkXdYڶ]2<$JIbɄ/F^ O<eщb*%B &lmròO{ȣ2N'76_'x&_ZٍS,lrbR8QbYZɤmvp U !t (Κqd4fUy*@1ɢ&G(dS6'*-N=dV.-erC)]}/pvlxp{ѡ.6͙ ~G1>H} ݏX0SA Q @$ HKp#s5YXqdG/ыF F#H' 9D=(!A§Dz }UWKQKB";j&&SUNg߃> L!A!zC.C]\g#՞v][p;MM}BDhWԕ\/r31h J'xIF *-$*Heeĺzi{1XM  #1ᖓq|Ս}7U7q{>R}4]1#0҃ٱovNt':=E}#w[!5+cݿ㵧vIR<w<@X&St3aE\)z\N:h Dzi`5bޕYln{'' j|a"Ŝͼoo7^9(UpΕcO6&g ͘@01S&݃ă҉4#> vI9H>ۜl2I.Y$hR,Pm2iAnRòQtMнդe[c䐌Rdlndeg ŬRL2r/.'s1Hn|'_(C.i$S#|NE9PLÐ)D('kO~kr\mRCSmP|A0D)g~QRBHm5 uÿF) :cZ9Beee%$pF'3$\2I!\+R%㿋S:%W$0tl,۞^a^O{߸o{Z]y߾/||`oy0{3RY3뭹g!pRq`9}l:V`4\>*N:BUF,e;ڱ:p;:@YHԉ_AO97"|AE,''ѱEQkw!Br*9Z5ʹȆSpz$:vUø)o\ŭ߽kcj:KɎuLKDOϚK'Ӵmocҹ^q"d$J冕bSLI>M8%!GlBc*$5 YE1A$K8BNSJE.yxs"eA6iz81L2L./,R*٤zIss/7>wVR(nnCxnd 5PSYd>cgf̙lݽHۇdaC`pFb\:%̫F@\N'^K7F ʎfœ]27.DLl!IeN#)cخ7ӭBumWzpq_?eP%l81ބƄ&vD< #VD=DXw<ذ}`u.=d.$be k/Bo!rݘ{;Z:tw\A9{7Pgb->PU5v&=XU$߉Ou~ ί$"|[qL|E8qnG:̽mn;u`lOjv÷dTbÖōS;+Gt@ŇyU^Wi\qc)ehV$ Ѝ#^51͠᫙A?!ѵ-tFㅬr gS*1бTJcSHQ$7 %;Nn#TJ.FSY[vñ)%t]!P!r8$p¢oJHphCQB,؇yJi] [ǺS)gqB%ĎBV9L:bѓ[2ߕRH'RhTRt5_g)(*dC=#'7/3FQ7 }/y q % m܅q[jנqو V (gTĿjZm5K 8#1w=?D]vOl Q 'ʲ#1D* $Ğ|;e#ں0R-CH fl 8K)Wrdv \lӃ3RNa/ KSO=O> .q׬ѹ.fƥzH6vmffߏl+˹@N2Fh_ـ9KדŊR($(gTUD $ZuZ, 8!T*ѽ~g *R&JlL{1&{B,|Սrp!f#Vv=+Bԝv*r~~S]]=i3ɤ* B̞3s>Rq6oc.x8J& K!v݇!/s=xp i2tLdN% n'$;~n3qT5BtKAN!c $6FMT*QJM"dM2B qƇhۜ\ɴ84mzls5c"H!F"D##XEW[pچzU LVh+?u=oxa- B }.hƳeH>K2 IsQ߅tk g!N_ Awͤ+BU|UT2EWp:{)(ᄴTYU9i>闑U[UJaw#zS-H J2mQW(WAqy)T*O>96+'|p8Lss3Ї>4;t'/oyls+ mݯu5lQހūsJ 6-`~'pqzAzo,%dNtPVB }A BVcukE MLw# |3HmC,[ )wlZL;KtWCٸo;NϦs%GR!o))EqGs)054F,)Xk0xi)ݚ'3ٖX\5Q&aƉ"8MۮNK?Ͼ]?cw7 ?&;\$ 1/&C5Cv/cG 5`E1ϦٺMEmqu iS][G<+^p\>7["!F-[ؿw82M3+EyeD0H"r7ׂ>MXsa dj{-8Stc(;DNHń|~Ɠ[3a˘;X0q]apKGd|PJeT|hՕxH޼I]WnXrȖkFhN2%܊+8pYƎPP^~Ĭzו4 e,{5۶o;v1Ь3Uwv Sd# 辣\2zYsM|7(dha.8Ry5^; \Dz`'f=\9`RH_̅ŒoۊN:NQ }7/ Qz!hvVmiH'|ؠV:Bd)oYe<3?3]xas̼=)#H45N0Il|fG0q/l@*9rI@"ONLX!7Bk.D"i72q$ژZ 0fmNb;RLr لkrre+;/;,N=䞓h{(T`zHv7 'dqWsME.EN1"_cTx~>7R{\MkۉeZ,>Kb&lwxJ#~%;IoZ7UTaeͥ6$r=pI',:cG0pt)G_咠Ip|GѾ~jj 1 ۲yWF)O$ck!%LbMwAFlkgJQ5Hf !JV#_ȲqF&H2uBj%EuY*#dM Y&KJN;zOx $)J %K7h'^]JnUɵwn>ds ('7rd"EyEygioH#Vԅ!#nT='luأ*ҿ|SW:TsRsnѸWrN{@I_!˳\ub+ڧ@_ $1L%Hؠ9˗//iwy:&MM fII$Sddϵx݉8čRTLߑ`e i;M~~~v-,:upM49vL=xkl^}3 KdRHqŘ {=f̠]wc6wWF8Ţ<ܳttt`YO9"Q$D3WgptOViRCt4Xi}Z-/' Xru~uW͍O`! R^QA(gS[_O{[TT*I"gxx!֯C0g?ٳ^{βfE®-[R8puue̟Й1D'k7B : j;{ mzu NG-e7\Ԛ(*s9n"fg/;,P\%PMMU05~0~}MX=-QUo;v!;ZIm큟x: nDVeUŠGSªf5gG~Ie3B8$ʱ>J 釤QTdŠ@[?4P P]oWbu`ڷX4W5瞢ms|$i-pV_t)QB&}}lzM.y^zͭXq|cSPrqI#7Z䦙F泦p\nsle=27u5N C6V3Q6J%d+lRJI\|$ň!$(dSʹp#%"Cv|dw8NjH2bV:s+ϗs}Mnln&4(98%NJRzo+jnfΜ9l۹m)h*C9nދ{]WڼcC}"4>aJîvɝOIz]bh vNSXpv(4tܠt? FUVXQ p_`d=39td@n{A-p,[-'u 1IHx] dhhx ?ꚚMr/cW7#}QP4T}~Rk!"xEh(t@ 3YMwXf[6UIoޅ2- &Q \r=mDo{U};5 jx\"@e ЛqȚ&c$%΅C2F뮻 ijj{jEmW28?WZ#^~{CUlx=/%z QRRZZUW2ƣ${[ zFY 9J29rBKzmF٦"=ҋ,+^y)Mɔ$di!Ul޼|w=ϫQI:o WI% 04=NVθb^z )#Rj`zv9%ٟ''/HM<)T/_|!UK{ҰըbGyD m|2h=Q$)^ Ns&\{B&"S)x-F! BdN?M$F"#97~%%FmLK[hZV .dٲel޼m~:5~2f*I6u >qc:K:4׍OgtIRHsgj|iY3S6xUF L.B( 0o޼mN|$>'vS2%"ցsL _{Ib\J比ƕCKضf{nLZ٤kS(]>Vj,v:i1;H]cq뮻G{A~gEܹ64]gxxopg{ E 6zKD8G.96i׿9O= SNK. .t*eD 45d\~۷z}l—%~s]_Gv`%/>4?Rd\v\pŔWJcyH$\KW_ŗ\y{xq1>b(\ nWǩĦgyx!TlGv?-8FZ_A@6c +NJa01p,0_W?իK_?_?| U/Nb˳(!IK~B TeT+ e"i'GI/уL{?x8K@Ykp}^!=Ρ&/}he9'_F{` \bGGHV01-IqzIl!u( e\ Fqzap588w5D)O__*8hjIu;_~]v$!+YG[L s~3aˤF:"zv ;[IMI'Pf:gP]Γg,_ɛISw />=Tr͋Y$"Dnbp o}'ı?G/O.9#N&| "[n)J0}:ʰW<}K1Amt~ਊ'tb931/ 6N&dbM(S{" ?JUG90jm McGD]ˬ8˶lkDz1"J6Ѿk3~tmrZ䪔䦓m>tm*\x(@>ŒcLR9)k 2$@q##Frg7>B(d{-CGGv_} .¢*/[ƟB;No|bJb8hdN-'[;`^=|: #aA4n\\If5/;UdYu c\~ziM2IIPM$LedK8 %Pl1=RX$PRF_Rc!DvQw>oiٳ۶Tf/g_*pii^ޕsHޘN5{#F)O Xr Vuџx+=aPVVUokĢ1HͲ,,"HG>IV:;־*}}|?.҂i̬mG<6[=4.̜L" M8$ s_*'/[νwIIoPWWXO^Lߗ0Hnyi+YYh*k2PM(WL$fFI1tE7}C;yi͋|k_s\I3cQ#ϜEL."{K4Sjn934 d#gTG ФHjH]6aGV"]wk[>tGVf᪹~+;, QUIW6ZQF!X] *GhZqRpW`ZD('t%`ڨT  Pw?dkamC-Dܾ8M)\pEDjE4H4Zj&G!3QYǜf+ЦgYtT'JD0*#=؍"yr7T ' 2Q{7PBsNF/(#=ԍ9Gc#[_ŒS098<9<2"O/N|]vMt,{Q|9 hH x/TTzc8^o$F [Es5& Gx>DR'_CkI vTLX$_|l2̞MO2rQ0~*^p6:JRM|tծ%N<I`bS;^Y%I9 ]@ga{!x/0L7H֗A*N V.+&Y'H2υ%y'НBgrOMhUO)L2%d>%Hǰm5W3}766O>]z)O>!u r饗rEMv륿m`¬+Lq0#:"Dgs A/w ?ۯ!`dxx)i̴SN[o-?4|Uњ;|I("9T2.3g}}<[VsÕ!κv%=+&RDz>?ܦ8~%s+}oeC$=2V҇?.) -K2^[e/^O>oMh*$>{r}>,g3r!5zLv,fJg^B,e$u{wj [x/~SZ j;#0JYomf=?=Bz^HX$sRVMɢ ~4 ^r}yD~{vW/.F3vw&.X8#X{Z?.&ӗQaʠ\US IZ[qlgClu;Z$H>nx4df!#{ d')Hm#4ڳAUhێ5OϚ;֖BX e"Qu4]iD9Nw" ?z\nLd޽,XW<tL4a+ M׼ 1XHṬlKr 'ٟd+D2uy?vꔚ\ uU5BSq1FJn2j(J)t/B8ӱ)dx7"'&bI>H{)fϞ#&G! 䪎|/6i)+^6$tJ*Jn|I C!G|% %#Iz{30GwյEW>+Wf7 !(CKX hR1 \6d`e`LIWTB{L$, k,E!xfw\;-ce%([zh5 Bd[l{lJ) &|vL6S*}|ϜM(N;7V(=\b)n2oݭY8{|\s5\r%?{&q_ çtvfs^ %Qbī)ZVd~}õrl˟,gɒ-+'H9,ܜN *vv<4( UhW`zڳ1 == ]ŶvV"~Ԗ9" o?^̏h8_c T ox[I,zz{qG>Ӄ8x`?ߏ/ _rEmXvb~|^q<Øab|ÿD2l69F)".d#>O xߌW~`rC(%oYּ\MmwŘ ʪd'Ӌu9^xOK(J?PBEkw .q=n=8a G ufI/CAQrHI\w%K'ٓ#ɟ4 |~)P5Vbŋqji}^ @ͰV,s4818# fo\ #f9X1\MoCQ|u/FlZT p)Ca>Gq$6_OFW;X4utho99a}ƹvČk˛^~12_EkpKy@qBO#x5u #FV2(sDe7!d-&v>~J<0>1 3݆ נuŭں'BV7uSF19{"L\"#y7z@m'(0D+ 01J}D$H%22x&SPi@%~>e[ K[~ ])к]w{q87,=AAFBО Lx(8@ƼK ?#Fp"@2ö #E Vy"{c(<ÈhoSiՒL3O' &1"Yȶ& WV)5 puYDFLlmI`*{3y+瓑'N#N<8U k$\Ԅ iyyλ7EY?/وw=p]wFR /2?LfOo݊v]\ctY`r|w1 ,_#HR( 3"R+oy}?Co}+`ҽ id&rB=@ B?Kا1-,n]7k/KBotzpߺ ˖#\-K0!ĊL?޹m߆ׯ|#fET.s.]u[o#GG&şbx[G<Uw] &()eَ*bRuWUL+9a6}䝰V.C?%8G'P̓9Gn򶛑V]sO.`0Ngzfx?\ ɾUH.Gx!xV:3eM F, d"?ַbӦMS3'OyyӁ1@$~Qc.`'Fp[ $ W')vLRwmq쒃;W*bGu jH%~l"ēX|l3h0,[};4|g_* '?.JrjPU)|M m=/=mޮbsW~s`rV6.΅&So<# NT3o`U卷ǎn>/_Ú8{ qL&q㢋.F01X|+A^Þ{i7_/"Q<eu)qk=l8^;,¦E5wð  |k_/}:&f d_1h~p;oB̈JpťApݲ7oD,a!p;g9=JG,@1t?,ӓ4uRt鷾=_mz̮vV,e `X,m-Hv3h[`tJu/,Qa˛/źV[_5].d t;t;^wLV8^_*ُMvrXtѵV S0asl_p2Xq^ o0p{ؒğlL`S&gC[&vt1ل'{9A8|ijyԟU!QՈ921oI,fp@:">DdL$"/CJ)e=W⺛ $\tE+sN _~{ $ OR dO.=iz (P O8@>n,[MqɖD=֦ZZy6~^x-LA*T%$0A:ނc˿?ۃXa9 [hG<]<̻zy-hB`YXd>IBl faYY/aw~\.}R|S4#ْ@4;,481Fq䠧Յt Bl0ӻ7&ɓؽ{76^rr՗/3}Q_h1omvq]Xݹ)u_{]jΜKb޽k:ƌtEyyb #xyئMUKn@܌jpRae7b0{ ֭[/p݂e]=5+otoz-?5ҳ{"#gL@rE0s0}꽡`u߉ {18@)^/^Қ}f1 k-ZgbPvӱ@:Jb ثIZ>eo6jy)4m+!btuu5p#O`0`̹ޅ$@w[=nԟ}*p0]{Oc~\uejhh,8{ Hb}3XRg {\@Om(^)sasōQ]Z~)BP1N oxv:8TT4WlIDTGT ?/~L“QT$N&,Ppde672rIc'؂C@]fuF4Q-,?q9O#ojT+_h^<38|0>=x[) )ɑ(h̖QGru>Y4agbLOOlo /RXK#(sS@6+q^cXfr[Vbc{fZ `atxBIP&b X(`s?g;v,pB>?~(xqy({c`H \fށI{?<^۹[6o>/nLL {K)Rv\uX^3PuНZ-écp.m݆^~T+6.]pYE$,Y{0拁4{$SF('/ y`+$DM}a<0 4`l?s~L86nڲVRu^GXwiIŋ2pkh2&ԅѹ$>>\ fpAbXL2Mܜ!;(@%y;Ԥ5k-:ȕuvxd Sc_ݏB&0$\C$YAV72OJM*u L&⿤ Iu[%0́xix;U-tyDE:e,]4Aҋb}%'4dB$ eq|⯗/LDTRQy&P>c17(:8yVolټ7|3; }q/[ܔa>{o$GJm >/^{jw5^gYMj;3F_NnF׋O6 R/K![i$cLBg \O^c}gNRRʰ]՟7L"p8)UODL;d{% DǏ_ Q$|R^zm߁ R0=5ˊazz5L À8x~ M, o3ØLK!y@~S(ւ͋3'd^:WBt&C '@\ $@GC} Ȯ0w:B=pC܌T>2;3%7 ?$"Kѿ02|U+1`IueFP:W ֢0Z:avI&sz1 #P r/nlڵkI]NtB+zԡ*>cݥtekhh5LL[= ?S>/'JeY$4"*e'Q,sT %e/ķ %=+e.LêOmvmww7>DH" K'SE-q ˑYDQ?Xv52OQ)e#bj?UI+2.J6C[O+2L2,$$ N2]8zlXڵk+>Y؎o]j5x3I<}{k;PV%%wLOS-3k-w9=P-0t$, NgN~p罷;UK*SrplIxP"*G͸44--->CC0Msϱm,ZK, n dba4TZ4Œ(܍:2@@3a G- &2i$8P* &ɖd+2~jA@)tn;aa<7e1==7kn]\*B)#vox };뿎hyq7X,i S*Iļ,e >@*٦Qy/Ǒ7 _ xVS1WVȡtj/0p\c_m;RQ㜀͐L# ⴗ?g{Ch])|s:<Ʉ'DhzL"K69"$uj~N|\LY85ӨK| Hm?F "Ǜ)ϫ*՟w&ؕq[FcS"1D$}QVF>87 & "Q_W $D=D R' SRiVGYNf">8T81T68QВhC)( |/? s=֭( cXv~F"OP|5YåmF _>nc&'pw}(rv<cCRENA6^'Ҹj!ȖErh"HLUF&|R+@BN e@>fESD)|=2*\q&,_ th`";N`qpۑ%m _Y Z8 mmmͅ,+cB͛C-A44fz%`>WF F ~F;1#ǎ!|%ciLj}ikID>~S†o_2|A9[/旕Lj02iNk|> u~z'>aL ͍meGGPD"|Zr%￈G<gb i+^j . Lesr|ӟ?}sSy|rDФI[L{>u({Mb544  GG+} a %2bTb2nmmuЬITN\V>zltel\"SɈ!2,S) R)EZ\&E*I冣JNUJ$6Af''rQJPmOH#YT,]?؏/~> O8_s?~-1C lx/]a=Kc0 PdNxy…YK.oo+4G"YR8w>DfSQ V-l{rLPٙI\KxDi*aH)$$(sAs_+BE[֋kۉ4:Z1rj vc;|DBjTե r4Wk )@% #k鮬\Ri,]2xM 2FPҙ1{zzi&tw/d Mh4L-Ȗ$cgpha\xwu*ٳZP=$0s.J4c Dt.ٸׯ?G/cZHҕ7c80.fc+Wٟ/oۆCR`)۶q LLL,HŹ "JK.MoxP[{D~5ˈa"?(\ŷ>=3=7{ƜWw<ړer5bf6BF 3)2" .S/b#Oջ |5<%T.NI̊%@)E0 fj u$*;7,]DE@?U~GeÓAd~?qnAGOA Q-j1P"*ɬvnp ʌGb#K#[&I/RGQx NB6` 6~X,pߵk |??BwwwΫiϸIpjK/R:38WJ I90 nh#J7B!S:1Kd8bg#'&=OX9d6aJ$2˜:$cZYګ2))^'Ђ V98CSaVB,Cn*o'KjaȂ!\2GXXb8M%,R6$9?{yDtttDrlM;c?$þ>[nYpԘ9 @*՟9+A*F)q= -h?W*1@kk+nFp  5CT8H5O_---N^q_'ߗ-d~%v;$0 <մƁ# v.r'mi(>DV7~RZOXrV8a2Q74xN#A= N˄e" I.9R=ϚKDI{f} %*bX䷟/44q1qa3ՅX8x4~qׇtOXi cx_G:ނDekO7n.r>aE_S |ELdtehȑݛ{Z![ SeݏNO [n +V444f>pr) !7h+$q:e~H@ Wf}oS)ۢ!dD AKxV=!CKQ_.?yQomXM.8{HShMt@1g(f|y9^Kx(wG8n 9'şlqNC̖ !6#O rS9~/Sm[7F.i|OᷔB\"AԐFD 'x~2"9?A\ĬX瘒zmfFUATV4:U2AJ+W1h_M09PaDW|tN<:P5#zZ"Y:a|帍FaEq?b:(u4z`ˬqɎیENH(9*2U?E2 O|0|BrPHuOb,WPU %3whҨE=;R0A./ƿa\vF1]Q31ӣob.JY ']쀺ݍ~ L"52XȻ'rW$hY:s=_=9f[,fѕ햐( =w"\sǕXn)Z;BcJ&՟ DjPD<-ZDR^F>o|U- JRiqP4#^#XGL?|O(s|3WlfC92!!LdyǕAU.& +"SQSDHdUϰB_ Ȉ&2C$҈ ) IcZ2BJ‰;ȕI}gXsj\~ͥ_"/_@.CK"GQ\&J.C]]qu |xy L%)o6"k|h;_-wV8Ȉ#|{AyRI1EL'|&~:^GXN I&c4ޔvbI !%`c(:"yaI8aԆ;yt2-FPЖ@J S̠h(ſ~?wހ{Jh l܇ZHw2cA +>5^x"LiLf7ǫﺠ @/SLJ!oh`Ȑ0ia똃c9,,E ?# yzB̌#fAm("x ;|X}jtw `44.̛P052xᾗ068^@Hey)$aixE0I3Pl.aeDT's 1A% fE'ԖQ)ȔHTNˆ$|dۃH$%&н:"OLbf0i$H$IBQ@xICW4$2 |(!H[6Jn li-Z?8mܳv0{p|0Ж^==~ %ߋW) )!LW?i^Cb++ψ$!~l?ձKΊl8$p0b3D%AeqD2>jLd喝H*!bҷ ,(u4hvwTL/Y#e^0'd#J7ivyaf]T3%>7.+-A"[&/0c&$bf;]@>מލ:\vF,]D9 N_CG} 68vRN?]nߴVL4TCxO#3;{<Չ2.Vb`fIqBcf~, -p+m o7{}l1B{+p']W_D.l "՚B2axqi8`#3$mGpؙ~^TktߑI|Nf3b“C B9zJ O2Ҩ4G(Q⩔kfu"09Tw *rĜJ'H.lxd;Z,"v}UJDEF!<%8Xh#QmWݨ)A\JTd $S#GOtt- vZ?cٽI+e; lͫM1gy&6o^Gb&puސ{ xv¡`?˱]翇㣒\Nד>DTR2#(*Np"" EسJ'ILT<y* !"E v\,%ChdLoO--W4aw&ڐj=ݗqls8 D| u@ vI, a F><9/>#P5xӰVԦ\Ӧ'B_|&_N1bqĸ:1- {21 Kq[PIlXe5VmZekՆty2GAlO7֡!7!3c;N.b@J Ov(:El{h^zh;y6^._n$ qb|h{9ïlj=C:3X%੘D#^",ٷ[W8[5grQ8?8(4$⩸ \GLX:ŗ0 Crгz>|SZlU/}l5(bAaBRLMcjdCuVr_h]jI]}J#<фW:6?xB N>;V=W>'{\T15]NUķΩ^'^,ӭQvb7DGD$TPDhUDy4̭{gk DM'[QYD!4mn:5NSQ|D%U~\zZy`N`j{k\OǏǟ?!(f^pl |e/<!_X!#nxQ|cݣ90 C+ba!OQL &(R wq~~ 7on_/=*w>*e3ZF$xilu0b^ACJrpiye%%ALjDow1cxot^dBK4444444444@KtkA|d@U/b0gCʽ/$BN7]&+ &2p y ;F%/bF%(<@f@H%* t"#륏ZEP2 R1i*O2mt Oh~}#ĒJ9 DE|8H[=^3aKkbXuQDa %~1˜0Kq94ϑR䧱-rdD9$LDE: "Ȏ˯S;GD9+("(IY~l K/nÏ~ceTJc7J6  "($E<ں1\~ͥ5mu6(~٭[w>:tG뺰bq0b e1֦%3%24u1"4T>K,’%KnZ\~q 7`3FNkm 2gJ,)i0O 22IDrLoP8,t, D(d 42{Dn;$PV0= j̠ZɃ_>MT8`Mޖ:F&iYzo`M7O4#XGEB>Ēid׿H4?RS~ `I|r^$よ#Q&b8Ȃ)E<"WJ!mOж IMy"kA/˾(%˖S-C bV,t}#XPMˆ'<#h?1 "njuhGTE%ⲊM;d(j%~hD Ewu2oBQդ`-ev%=㽸4d#42vڅ#G 2 N>4}+V%Kf_W\q-[6 ;܅oᔜrÈ`"4de+*u'cUuγbeԞ2h8r$rIȠ!RI?1 ?PdfuPOCCCCCCCCCCCC,F5fC|!̀0CtW3 h_F: TJ?˴NO/CtT!*2ZoI%QI&FU)򑩕iC40Lb XD!x7cAIkA #*dz1MT%ڛUשu2tFMê+Ϳe  y4sNQ~X"TmV#LHoT!ĀiHR Jy^؃Ģ[ڷ}<'w[m^֑IV:դ+A$'/&kxLef0#B!BC,Ia.bCL. k'逞j̰Ʌ}0"HtRɛ?L9_X)zߎȿ⠊Z.?s#Hme2 +ǯkǜlDV˗^KTV^ % |KPβ8J2$meqe1oNń_翸 l@TRSTiT¯Ys*ĀK4꼎[1kR (GuNhV\Ys{ LE^L*ĀC2>U._ogcu,KK9 & QTKĴWEk*ϳ'$mX}CPProSU-YҺ9MŊԵl"Ԕ#ԐM%yudY?ND6G$*.mn':2'5ZU_D|/OJILM"DI+J (M4hEBIqWBQ)̅jIXڰu2Fl"ngߨ -Yg$?vEJ=;>6ll,Z׽C_{ ۟ܥ'y4·ĎcdE^켋r}22IDT- #PD!(ԄIBmkB?e׃\V~\e$.#UO~[")k10{|HyH ͨ^D$EbLULdm D5~}bL2SF"6V!J2D6(KOGj&]s&A$jQR-ed,aM.9 `0EDLde㧭Jnd'*;"% 郿˶EQ"~Ts~B8"#(>Qp HonH c "7Þ=D^TZnTuHD~{UHp kC!r8fS W-kԕVB2B4IEHLX}YwU+4T^EYI82J9ZB6K2f{|dຫQJ"ۣLjL`WO_ v jKaHfD2s}:фXxj=[?!RnnONfjF^̧r|T'&M09BTKTD1(难aKkDD>L§b'eMD2l9ChRѐ?)l׆+dŝ[p׍6[Ұbnkg 83ۏb=8D]']v6V4"$mM{䝡ZBIczS@. DdD `ȅq%4ӈrIұ׽|V5fXg>!MCFiH!ř)?oHDV+-lu@'@j%-rju^J&*R '&'j%:Q-rqy֯qR% Qj[M!d:jAqՋ'ՠ׉^M{0RIPA:A trA4d "ۧ憨P}SL e xR'E@ZF= "x%c{ K0b5V]KV/F[W+:{;L%BbXX(b1xJB쒃t٩&'q>zB`)iy528DIDQ LIQk9XE`uhqUQ1P 0c‹ay"TD,O!J|>}Obk#UiOR '|:>MZDMF. S9 y\&RLÀK)NоQ0FaLttsqbVvTuaY&F&aLZ0  0 8%eQigKO aӈjLMLDbRgu#FP<Ϗ_``: UHMPDI`rbST섌ȜZ`|>jן$9Ȅ/$gc$0ddz:R])5HQ59'X|c\ +e敪#HZ)kNmo3J" {\MꯧpO R2Nff"4xhS=<$h"#?dٶ0^>W+}JQ2-ԭ6\2})&eNunrn&"i$HD$:sHO*)')1H,q.4dD.'bZl#ʗ'e8 rI7Bf#Q'QC$˲P\m$66p"KLè'Ȉ%. Ndw+K;RŒIBQ%"E,_PdV4ZEQ1 뼊$|a-, 1b[##!?_ilqQ\2uOaLDsb\*G.R:"'[#~әS`[='Ɛ-McSlB@fRovZ'Njʧ[iFɤ:BtHd %*K0"dԮDAじ25hy~'X_}2BmrxF9_zzFMEZ"H)d"UE܄nyBHYitAj%1U0H&*҇F“MDbIMl;j{SF()fr5Q'>aDE2 %Q%Aу!J30*׮ R/$"$QDP" 驎dq 0V/(|$a=#AdvKp{,HRzp~"DW0 :98R+:V$ aeu2VO`SU_3 OxB.I'nt{_m}N N?T.|yV_W)awI_;@(i\"S.Qi.!$q]:ōWz≿NlRN)iȬsTT:KDWq usĨαĄʤ L0}+2᫝8U aΗK>ǫȔFDxLY:1_:s`2O"4J$*(WRXD7op"JSO_J^]F&rߙmN:g|(9"'H"2B:'d“FtdHؐ4b#ZVǢEO3J*ul[PV6`ι֪_^}W0 %~D0UbHi=k1 (p6K ?z՘9¬r·q 4LTDu9Qcvl_[p1]KʱØ}8=Jvם;i ,|~ ŮN!nƹ2|U/| xb]T/9;O(QOkKxG J'HeQѤ 'uǑEOd4s-{4,877詑X5P!#K фO|5j٪YF$ DF"ETJe1L$Xz8bZM89w`*_D!wTn4EH*[J&NT}OTD Q:uyJ&T&1wOVP-,r1BԈ 葺 vDx+H'TQϼ}"PY9Q/E _xQnOSvaUEp0(\_C vʆƢ%"QKCCCCCCCCCCCCCC|̨ Dwfz\*s3.sI-A)*{렲10dJSp\ %I"l.]*@*|D/' Ske @-D$H MS8!!SA$|RG1sײK]P42 IE4J&G1C?Ld662~]fb⯗RDehs"DBJDFPYHT72,YE9*jYy'uAu^ǂV@SI¬kD{(])/^n#Ǔ}d< i9m4PITU]cr44Wφ\< j~`ǜľoM$ 0"/䪶8q b [ʠ`;U)Z8'hظbq7ti&J]6!Z!nEBO:4.'Ȉ#2d4/"T$FU*==EH ہ'D.3t"M4LDReJ0+j%"+W_ĨVUMX;UK<˜N enu@N"Gd5<".ZD`8yBBl;OHFUIdȎ#'(M &5y5N$9qTUk`"vT>*F^r_'#򗥑uDؙ;ʎJFĨ҆H0$D6u|DtEE+8J#u[! T.藪X9 ?&lBj~M 5r;pidrĦ畬qgQĂi'-LnR.su?e#-#X+,F̈1vkå(c yù!<+fUۄ@wk6ti4t`sQ{"iٻN O>spr-%r-9de˳j ס6W R:e.\ ,_X&;g?:ZDܻhܿhQ/X"*bErOEKJkFFe׺l7sODr"k=Dbho#_lGQD^B!ΓMO?_2 y_&TI">1VY݌D,!#eDQAd0ه&$қD̈́W-odUidT7"7jz~HR(N'n(;F2:%J$"ED[qY=Sb(ԝZ$=}Tud[ȶdRD҉6SH,ĕ`8T%%vu#Is1Q% M#rjhhhhhF881,$BiXHYi,=!n&Y;#1L'Pt ajDL-сmp٢+~G_{vA\@) 9{2z~̶z(2 Hn G&cq;mW mmoZ}"%$l[](eY+m [(_sB e$1t <` [ϫjqS0v *RUs"anY,ZieDA8"HTed!F^(I'|Z\0->O,Ή0UzL/4v%wS$& |{lqd$!HJ=romw\jS!pgebENXB(>Q'~Av26DllQJXx 8"C^# LLTlZ"y򐩜*bֵaH&$Kw^RD.L aTKlF̈́'DQ.IB`{=FF׫Jv`%ȃ∪'FE¯QJ0Keui]GIN.SiujۂJmqe1MIlDIO$vDkUC (j1<$H=ʬnd%eW- kSe(knث d"vII"g.]tP@lQü!cޅ&hhh~9;m$ ^ߤ=хD^gy' b"kOٓc0e1c77 oLN(q3c.l^M+o2, N&j'cȎ2M.%W5Rc`eLƱ{ePrxLt7tE@.98g( .%oD{@̘g2ÙBb[}'`G:Ij9&b@a,7F)0ց$Z7Zmw  gp'?kgtϙ'-/eH["xCexxz!i$#Y*R4fx0xB]cQb)ɃxOћû.{VӅ).뫧_ .9EPF%+9 JnW]P9l׆*<8Gp ET,]Y?^x.w4r͉j;ɟr~5i2$bI;p&;C&~Z# + ,ˈ'' )AV)Nl"Gˈ$uNDd4g"[B)|d"n)Y)ҨTMTmjeeN|ƼxiXu<_5V8;d,>92X2iwV x"RDU>?qW^JΡ!L_/QG}PjnBIDL. ].7HD$GRM6MN%S9i*GN"*U8a8o!vdDAR5FU+DU Th;QQ%ؚt.ua` g#0 /фGdj&( rX'?" 􇎙i8A^s=l |pOy9|a#kwW-8>yc &|a/zfɍz(61UC/a0˒>{qZ ={aC?ݘr%\`n,o_ 2di\L8(;O-ǖ$1hs\ ^~gYW޾=l0 ˰x]ME[z9]z Qfn$74to>.@rNi+i[Dn x Zm=#aGm\Φ4]BE,"fR) ,cmEXҺ</e+DG̊cೠL4>ްMǁqta LFVPFq)/:`"fV Ȗb b;tR4Z«_@<~7Eb2?\iL'R7y"456 Q8RC)GDWVs`fz,,bqdqk16fy'Wc#XӹCSLtՅq3 ZRwDL|H$񿫔Ld &>D$DQ0TĩFU{Tw~?JJDPI"w<kdQ_޽'D >W"-smf9Nm#T6;B PH !2B,1&[(4&Vd'>~b*%qLrT7|͚'TG|qR;QdF%A`#,{H%2>mbIP\ΕJT>/Jdd9z|v *tLU;.6Lթi۞p{-B:DYXʏGmjڤ7OrsV/;Lџ¦ 1oGj60͌:aX&kCLf^ Ɯe1< ~\j~x%!O_Xa`1% r9\ˈ5\xc0YVl^zĂ& l^t#x9g38=ōwo89A]Hw"},2`x,?[~~~`~ӆ rM~$x+rC/:p$=51Ƣtö*%eXנTaEtVu1U n}WG/Wʢўt=Sɞދx{Hb:? ǵ1]&CJD*$"_Q-S4 R7/t & HJSTGׅ/#q}Io>E`O,QIcFKT!YgIe#*:I8:yW.2WUڎQؗ"#XAD ;Skw#*'>:@G\{,%O@QLڪ0.W&‡6L,M]A윏/˜'Jl"n&*aځz:fRs`]STA@lZ>6}Qd9t| b0; {Q8 A~ρ9"51Ɛ)M7LvE"޷m\Kcxq1Μ c%l1 eQrpu.HK F)KZVPā&k׽8?ױfevJdApwv.&pKp'-=0ۗ9̮ĆQx>(vT(yl1UYWtxx_6Ƴ +S!n>y!oL (r vQLFљs?$#L v =ՉŁ=|w{':Ov#al|'_Vc1D&K9L&k/ <G(-:0&$wox2lqf0[Ž3/q[O>t?}e (jŃ: 0 ^IstJ+J5׻ˍq+cbҗ-2ڭȍڇ8Cn %a%o-N{={Rۓ5G7OI)8b3}DɰSi&ZbmȔ*cEuݗpl"Ƽ.Ll129\0!rfLHĀdnXv3:&U_Xy!PFFge@ \'ڎ"J)'0TJ 2x2<#k;,/kw1Ϩ׀euq> [eZ{&?Yxj%Rq_ٴA82,} O<4** ɘͱ8sgm_!ƯWd%cv;KD=C-tTQ\J-̲J:QJA#*!FHF 1g' @#eʖ0%>oQDܦ"0RM$)42kDEl`eiH&M2K2?W`p]:X~RZmcV-q2qLAwp`Jvcy} bbm&ڴml$  SjHv|<jQFk7Zyb+/+.J'w>}X~V>4or>K@E fbx{;@{.1sN2 m\eat  f'dk[@4]W|DcAaKZV~`!{g3F}+fQ:74E8Gb%`ZgNѾ,)P e4S3]C~7/BD~ȍãGR?\+n 8ELjp|e0b&.C"zQܼ|B !F-\ƃnY^<Y1l;Ȕ̉p˪;c8rj,~~>di0#Htci* W=I2Pe/NkYcatqH::;Aj_y<ˑr#7 hѾug!s#LkvdG85}[O>1p\1L@'D-y X8CܱXҺ^rKe@a dOQMp}0  Ry6&rc5ٓ="Cq2,+qg0 &ޱװe 6^^7Ok !1>RVUzo_ۭ("iܷx%֕IT9ā^]:oVח@RŽc@%̩u2%mGz>>hV+[&ȜbS,z)PC{.dMeq/b!5AJV}AkFVyD~޴n:Įz 5^3CLf.$)r# 1߀;0'v!}hWA L[9ԆC0tK3Σg#0m-0>cpjf,n~6bIˎp!KQw@HFk0[nv *6EjU'"PF1](QP[ q15A-KSU1_\,|#7oY2k|uyv6~ o]3v QHZߺҷc"D|yWҧ%adjWqh¯'u.Q2 %uJ'к^rL{xWnS\V$MZIYD\/#7J*Q#^8rmULK}|K1Fx ^o#j&*u\FE4Q%HJd&,\e1F&lp"d8zQDv&6@.=xשӉ8A [W;ZOU>|,aȑ&"yL_gʼ-e'X&hsj/^TG;$5*A19 FT0-k-aTDeDe]~%RW'3fEϡ(u+ PVD*D<GuڮXR ގï`&5[ O{Y$wb'E# 7k#֑@.CK<χqdU3AmĒ6tߺVg NFW`<;gdGDցPE2{X-0S&t 3 !8`0Bm:sG\ #ia{.E^׍lFbIhEg~ǵ*C ay-8-Š_֛)0Prk9:qCA?^V5ϖwb A d̳.{&,UH-8tdͳ#SF;6\\B t o]Sq=qLs9^~; !9AGyf%nDy-(H੘ĀeĪ1VNQot L]E62>f\l85Es2<%ӞToK*.[qdDLR &"E:@xU/f٘}87_K2F_o-tOP.eH6muTm+#Dib ?(P{DT$w+eNT߬Ԗ Kf#HIKdj$ GE,ƹ M0')*$2rHу'Pu6 uB+" ME񷉖86>2xY˜} vHn1yUӐ3 "$ٲ0+ʻ:A"$$a65am(k3uGר;| .g !$R3/T֫D(2awClS#琎}]ua6UE&a6R#Cȗr偑NϿ V_x">e!H^~XԦ;9 Ek.!q<|~Xf\W߷K{Xn3rČ X0@b Qg2yfH `bX+ZP2q#_!#Av oehz)Z6.²] %PL'dqg2Y7;=CZb6ep۰#WL6~~ǘ.y ^٪xuEL,g3 =wo)@}?FNSFmY"wb-Evau&WG+c'!!S{yn i` fk ~a KZAKCEry;ߵ%S ҶБCvhx2LD,-;fzU8%Hc0G_-su+ u*0+ 0k}?p)W*I&ZR4UY2B&,H*xQĴ2\3hPH³e%FGFHooTDT$'cltF[R*%aϥ7^{;Wh—c~uh+ x3$ $} c:fJ(̈dk$DS6­x'9""&͎rύU~_mݭ?rϛZ,x1>KFZWp뚻ҩ ]=s JD[t o+ )g[TTtJ#b .0v$8yF, 2 I;K%-)8qWMo^XWpN((JNSɚ8Ƀ8>}gy5zo_R0Xk`%@K.&a3U!d,v))_ ]71 R0EjMV u(C){{S'jbmG&rـ[WU`W6#fݗ 2-y6B=)W^nǮBbi;r:|JNՒ1>vs 3̤׭@z]7XA4uEA /xj1&AVbѝ@ܢ7G[.40+g59CHՈZ֠Mk6gޑ3&p2$b釷x JkE5K=2mO»&K۱cWkM}XkZZpPrxphl_ Ħ6xqPHXrSr`'s-Pv2U5q"s b{.Cۖ%9W0a ' esVbkc!aۤN@P+iГC2 G)gُ1AV KV*HH@TIUkI29"DT7!S2W4iDMY|d/6 QDj"j&4LmQP^xW/+5fRU(knY٬g|qW,'4$D _x: M'DJxho#ۦJ O* %x Vmx@<AF(YOY ]kJ lb8@:S|O?TkK_ ˻(Nl9d6_oHvcKGqj**r((vr93rG56QI脷Q(Jr,Bg$kBJ-b9G{O;>ś/:eKgg?WZhoF(Տ[W߉rv[?ݗ# ۵u%i] )!hZnxJ'vId_⫷ 0JИc0cR툥 fx,ǰiI/la+:pMV{W_xO'%Iعnl-ݛ0lI<}l캢&6QîW=2HAەKCWx@V-88/S#G~7F-lG-$ nޮtcկ݀,JCY`00NA{ ,mq50RfhAeX+p_^=Q| / mJ[O`!@.Fׁ:b-y ;01ӗ^$0綵c=ޗQ\̢ZȬʈ"'5RN$@X` loW% @̈e)MpaalX; dQ_CeH2VNdJ%n),q*e(W)H2_I:=z2n(M85÷F܏W8kiUeq>2-OQn>֟1 FĥN^FՍZ<"BLd #v=a; ZdDfjTDSf#+HVDU)B.Q,0^DL-PdiP% )/*/BY>*n3 L4q1@-VX6.O{q'й͎O∪"=H)&j9vH.DL ^/WQT#2Rۨ|2()E "Irf$=v,\[ͦ=ιR;O%?A.){ntn š`xMjh4}sH׽ tz':=r444441X8zhk6Q@ pm8'<wFga;[_eXZEϛףޑpxb%Ti&e'$*a &Z _mZL"NdS^EnS|0"#h,|V#5D~)*i}ceI%2 O^iHM>(0r'OBQnjpRApDwsE?3^jO_߸'de߈{{HťFY[N:<J[S*2P|NP-EBjH!~|pEڠFd#M_t{ZuڑQRì> Bp rSA'k-1WsnWX{n|WB;B q+7<[װk^z#rvVWðH4ϡxw<=_(1#kHY1l<"}S#` w`Z`)?kXVR`v)1d[ܒٿK>p9<&;#iᵑѝEK/ >GXގV{P2޾eԿo11<;n^~;5jyku9[58_?y N~er ^>,Zr_O\XOZZ6SX-'ʶ$s)Kڱ#[@bG0 jK`\"^ÞwyJ,~e^N V՞Ē{68E4bc8RXq޹Fk 4k :[ҙi ~5 ʟf*ڌԪ.Тv"֛F?pDi\o^%q9#3-ps%L<#iTxEeehٸnAf!֝_؂ӧ3]_}Vsz I-6K0w"Hv@0IQLgo`e޵ŔQs+\LLJl|BJ| Ha&(`zJnoֳ(@BO`r- 4bQ7|o=4L,[O{u'mP*j\Z*4͚#T_{_sAuGȑ# 6P)֬Yիٽ{wʶdx_g :L)EO^u#ui)Ӟrk_MQM}P.7 騩a-G@% ]}@%R9%XbGJ2m-)s3Jb.Y}뤋;3ƋYIø)l ƿa%H-߂|3 mvl[+V09EbZJg[xxRpϱ;9,-)<2mU_u:1#d{5Dzl[{{ֹjW mɑ|YҦǂbj,}u֬Zr)<??2XdV#vC4%fwy1G? EoN[\_ٍ5VY"oΑOݏ$ 4AK|Nު;PRuzJS޶){Z_: xo/7oӴV3'*,Br0Z-9dWqj4CZ*\En}|>Hm&ETjF,DR'jN1n 'Jr+nܪ|޶^yD\V18D4"fXHP&  D1ӃDSi8`I!"_e$ b:ˊÉc" 4 id!r3Q pq(Z2>&8i5t A&(EfS}9+^^s7\Vi sFYA `^pITA% 4D9umDz Zv=Ǻ޼{|e1RNP7rwwN 36:K.eɒ%ڵ^rn喆߼o#>8D;x-,*>Mhn~蝼lN* B:8U!divJ:]FQ T)BRل$K,E7f(}kBC%c! "L3 n9~$P>07ww\sz[Iod^je7g8e(#R:K߲֋+@J*dɡ禍()ʓ(W1R5Ò7n'׌3U2*8KWLyYU[ihyccm1Z,ݠ vvrd^PPk tI!pʴ_{/< %ZƠ۰N0 Pq*zn< np뿐뺵L?>HpWf/3벲Y忼3gгWic7n]B.-;XC<5#ezrDl2ڽ6vtWϽHz_7nأXwucsj^:Wb/\lǐəmaґ隝<;*(8gDܘbpƻDk}ʉ7$I0Ha! 5`LXRiKI0-J.'pooUMp_o#ŕ5S=j]4I=JVkЕ#8H|P&ٹHOU^ʱ>O2g!V+шL#r.?\QF( $i0#@XJ%Qeޜɾ H$ L6cO׼լ_G|6o58mt:UW_]r5)榆}wQ,t2] =& E&'n=y=u.O&;pb<#YmTeq\"XSXS(`4Hб{Xվ(&R9}9h(ǦзKByc_s fTKOiuI&Xb%vz>]$YGBo)AJ|J}ki{{IÔqG 3ȣOa}-ۊڅ޾E .tWҼoɑO=u~t]vID5\04znل0tN| +Q A6ӲgpevlB>0헮CC EԒf hޱΗA'VK;Dz_ޅ)c/Gn}':2L1q!:]KYrtOSKY杔ߍ5{vH=l#le[vzL-'1kl}N2ZavRR-ijhc{Ηo`6mGnC'& D0I\`\ !^&A'QeESNd҈ADzS  ݨH΂NZ`gLʨ`NCI-撠EIm-$*_=āDS;-0d0A.9iROvm r5msI-x-$ndo4, =@AQ}Qw(Y0$  J^%j`Sk v@K[~G_ & >6P~Nj `OؾL,RtBTiiBKs3A#mRtmy7$/|f``4I75qMk+[3lͥ Q0`z gleqF5P_wҕ_kpcyznڈ^,r$Bt|Iz)wsƓ_(t^̎F\p|&+G Ny^Z.yEӦnre*Kab˜Pf全%MYۗ" 6m K|s -k[I)Vr$MzY{WL0;s r%B~,h)nKzy+Miݱ yױ[B)Ie+s)6emZw/c/O-ghA@̋&ySf2жG\ZD"|~S3pRIRzlIO(-# S7X?xB1/ώc4$Q@(Aߧ}M9sVdR5UdZTI=v l} w8_$<׈RۺfT$t| Pa1A9]+ #~ްըJNM 5Q( L|{Yǧ |4u)MaʄF^_c5'pAlj0szjJ>Ւ3Q LKH@PWZOtG=ǽY<ʍpY-Kϊ.V80h(5X=X^,M29$W{[yV&u_y1 B~@(%9:ǎM4]PG?9:0N)-mgk.MZDc-2&yMeWW,[ƻ^p/J&1`=Ygh7 ihUēndMEӴW#tg{qI1Պ2Qa`.HWrJoDEJMVj'3-fW$K,^KatcyU*`{k&JyZԪJa{rz~_&NmNɳ{ 4BA~(z7 '7Ѭ=yK/J))([NRL%e(ЛS,{yh)K)hR4:Xِ L#uh<ܒ}RMt:fK+Wn]IHch9ow]L˚tl=Y .i~,Y5,~RU`bipRYD +DnL}xI&@ )(Ox C3k^^qDx6߮fbqS  k9@IX64-Ud%q C$¬($._pOjIDIaT,ͤ[Iwc|b4* [.(tq[a3ZMH_O}>#*-|L0o=@ITzH%,ILnK&gȢXE۵@"q`avQ*r!Y8pI%X EID<I4>7 8vpl!X}5?>ȭ_ Óc*u,N`;ӿnMO_}ѵ(G_pRy@z ~DT;]G*cq{[+y}8Ny܈N=+;evzKolvʨյ]:t, =0j52u*i!h4RB^@?n>r>U<_ $ " Gj-$x|$`TY 1b? ~ Mw 1(5']73Tm>KI8mQ(@IԾwQ(sH`r, %l)3  uLkɩK#q7E>$p(I=J3dFa :Mf!p嚛 FW׸s5n}L)~ dRi\9[/JT ڼ3" iQ$HhH;wp_T]jh/-I}c#frv:_kw\}z )̂lDkr'GCEX 먤h{ M5,80d.=zgT|kj/R^-%a8IpON¿&8p$nUN0-NBTK$  ߯8ppXKNƢE)GBͳK|?d6(EIܓ/aH=H @$\FoJQH69,A'! K| h HH}|R9`[Sk׽f.}Ņ?÷?V\Avs/^~d?\ŶX('D9aV$Ƚ ߗZsGԪ=`Mlްs%3O")1!r~Njt^v^2t.݅ŏcqƆ'b^d@IyRJ pw 6C7"mh)Gd@bvCmb X6ٔM&mb).Z .hVqg}n.4cU]CtZbg2zl%|Rk4 93=|t Z=.'Xb%4Rcש0@}wj؀^|t&ة?FgLsa/NC/+X#TA(Q{qu YD $D{Am}㒽c 3,#xbDbKHkQH~1ĶݨTTp^$J]DjB Z^({ D3vLsbqs+ MdNTnRE[@(y$,f. SE>V/bKs|R Lh9U(3D橂J`kIDGQ (QŒPPJbi0ӈD9>8%('W~J0!pIK1YIjJ8>wo}1`Ix>'Ƙs/[/ OrJL[ oW^E*ZPO(͔*8 z۠Tw>BiZliҀ눅J `}$ 4*'&ȉBܷ\Z=db`}#/ uMLi2T\ :3TP/txhP2>ݚn'k*bd¶{X*'jl%%0VK9',KF8O% *S 0rr9q 80H8UNCf< (>"q$ e= la) b142*DÃX0u;WΏ2O4,W&/H:wkCe#ʉȺ۵@&a紞H=WՎw oN0|\@'< Z{W+oSCs^Ⱥuc߲ۛ;)z}֠!Oc[.M3x_ zx EֶYd aTqbhR1-(XJQi 3sAjLڲY`4J) L-6fq;͝OC'qƎy-ݨ9'K,),;(>q;43|mjlN \@Xk$Xbk|DGc=6&BTu=qqpXϔr^W*W4-4Z):<9"(+zr4~Sc3BKfGJHʛz &Q`0ܧ@%aA#F)Sr IBM 1דÉJ ctzЅۗ-h Di%ExitN6l%_0$'o!6^A:my |jsvPx]V\_>#q Sa1c0h (zQ8(pH-ɝ\rvX09 *W˂DIĝ#\N:4*~)Gj^iq`py|Q@z< Swګz Mx4Zqd\ XأΦXu?m| {XZ5DyɩF eQ!4٨ Rϑ]Eֹ#Q8 IdZeb.%1YuuC?Sc%B8)|z;>P5 o}.`@8vXcehhLczh_"mMwVkZ 4Io~ oѬ{NCgiJБ#LNNy?$a3fҕ‘v(M/EknK,KgQ~g8,L  |]Nhn ]@eH7%عd~ƅ^bdkNzc)/oʹit0QgϘbC829*f,H밢u\QAa9QAB~q"3G9BF<6zp(#k˛WV|J=`\}_4B EQI~L7#[uOdm_HUdjK 29`<ήKIOh3G&J0oI@!I]+ ,%aƒ0$```y$rʍ;.?LNb*hRK&X~P2'\~Eĕ[&ziGcM*aHKX8@aISf. ޣ?{|#F=Kz~=׾J4Mce#Tqhj9qTc|izmFAQG^;$7*o^$Kv pl6Ǟ={d8"l4)!,)plP.y_ώ;dm/͝M̌\|AgXo3F_d5)D]7fHo9c˻K8vwgL8ل9MMP ='E ݨ0eq& a0b 3Dk@dr¿HL's'i(Zf%c+ G18H8OHvńR+oNm'<X44 ] GS)-N14MV?=iv (Q`ȣZNg.fO즋ٷoO<$c&R6fS'=%O-::Ôϲ]\ҒEI?-%>1ɠSO=]wL\ g~r҃@H`Bwr$mn@hô+B~&nxī;*yH@χ@0V-h0؋!+-ZdVC i=K=7;iK,~j:rzv ٻs]L*w(rHD^ /zZgA<Ă\I>naeOPqZ4q_9 ]iJYCEҡ#IlȐbR4ܫK͕;H;+S;6_kp!<(:FC8~v.y O <ۨ,NT?R(MÑ6CXEJORߎ , &ܣ(8#?-;Jl2^adIT'J)t͘'ͷ9z\s_B$g- h^\ >@$aF!wbϯ%"@"aF$77/ X MqQ(.c JKYMX$*VD7O34۵+.Ctvu!(1$䟊GX"4Nĉ/a87X89:IDIDml6Tmڽѭأfq`"uYv5M a ~@&eQ.  ‚癞X,.EOIvr W"N m6 àL~OMn]ЄvRFPCADOy9(uZΕXA=8E#O"S(g4 Y:&Zgrs?C eоXb%h:!4O;1i&ۯ%ȵzp d0\mRiZdL{$ %(,z_0s,,ʘǟZMƯ)=EϩG*IkT ykL 6;cG$%5Xtb1b-Nn%cpJ)L`Ct=7s I8-x yjIvd RIpl0Gpa0:sӌQJ1Qcƞl}z 4(0$d8Ty!5D->A%4WU26)}? ] l IFYA@Fky%QQڗc d-NjAGG{C-/7[ZL'\ǧb+MS-"e4JG:;DF wrť9<&%B7J>oK,s4 w|Ͽ(!h};ޛTJX"Gt.ϵn?1C%tKz;(Sz:N;d<?Z.gQv[Ʋ3H%i6[hKwr"-xvT= nsjfjptJwLaKl߲rkv=pIxۏɇVX1Eڼ}C㔜"J)FL'r3HGU` h$s~_.O"‘6'V&Y\!Ai_?U\?O#̑J*O0ZlęW1QL.+x#%'(9 _p0҄s*ЋKMAVXK$qjMh`ZAΜitNjJds$u{~,,Ւ Jc- @$pd1Y$9xlG>;A@HSr*t;,^9`ښ%6`0cMq"܋H9brl,ĕ\&gVό:Ǻ DEXF{ԕ ڎ:OH$;5%\f=L%z (pINX!S~'z~GkID %gTyNkM[#8QRM;wS>҂i.|go77x[ߺ[:7aF(FA%Q0T`Z8֒Z29>$JdoMf);y8W2ZM8>ȡÇQmЖcmw0j=SbTQzRK3 Xb}'y$_@Юk_mCu$_?NlD?0,Md4AQV `WGSMZoqtm4OX|o~3[l}{hnajdzm=nlzVZ2,MV)Ѕ`s6rm8)% ˘k;qi4*KLc 3$άfp.Q gQ*Z{/P G?7ȚzsNA{SV ]l[K{]a 'lo}"?3]缾Hi)Xڼr|Fbh&ȣ'^$cZ8RU1&J(p\COgGntaDž SI@<@-ƂnJb6aPeOgcjIb- 28rˤD9?22:>[Y  qYi0$UBdtgㄤ jel|H5$8?O0-J6' VѴzVK&'*O *7'Q+d'Wnb9劓<:8lmgy[oktwK3L> 4iiW3|$# (6fSK;xY{ ? #VV yhM](-_iԫ,g&1֐0긬K\ђ᱙"=?7osY.}.~}.=ϗW{[yMW1uL _t𫽭W2-%9nh^{@v USx(5JFoeW%'\65k8c<1 1.#ݍyc^(S`<̏?C^}>2鍗y\R (AyCL_p]*ڍI6Hcz_b7jK@&z>@,,v̀Klm `\O ǚQWp kkr~\Ж9dyc3Rѕ[]PO*&-hOC_rop;K$jae-60x0-[B*E)ҖNX2T8+ 0 aښd8B_Ӳ*i I#1LNԾ0D*-m4H#;V&o{,Y4Ӈعb/9g ,($eHP{ lNN03Z%,D:'||0I-YD84r11B)`R )2Kn>DIoŕIe". iT^'J' :bp4Q8H9M i d-Q$$2q',T gQ($]+OT9AI8( 9H-J,+l0kU}>w%=5'.>x6VZU:~; ;F&;njZwTZ\,mg}6Ŵ+i55><+zxגv, Z MizSEo~x mH8Uռgg<@Țhg\LOXqE(&$)Y#GJOWh)bnBdpf_}:DJOsY߹[Jg}.MӽU-o~e" f|]S,Qv߂H7͓WIzO܆,zd=Qq];gw֥ڢa'sgGf߼-I ;Yb/@HIRx࿰4L3MK߀޾eofÎ;q7?Mcbz7Ն܁ҋԉ־ })Zrl+Jβ\b%Vo컰Ȥk kBsDMd-U`qSh-8i4FU=\&e(O-# Ƀ%4Lmq`)uAKtkuw0xŔ^z|4$ <2MF&KN`6֯g NiYP@F@&Aw$lʓCCS);%U?>Gaʚ`я׾5:L58|ĉ2==] VnZ/'"j_TV/∓ E6K!De 6EEDI:!spДR\q%44ս'|sS33uusIKnS'?RUi-`ƕ?]boώ򗫺5|ϔr~"mΓ RyV >vbiG<Wv6qd)GojKAx %9åmz߿!I_gQI6WSzz޻rg${269:>xqMjڬf5I)d6ӴSOUN`  $rv12mkp/ F&t{Qi%r[c6|ŏG7_6Ѝ J󸋰03zLh=&LjI42uĞxBgeQ6q`AHNyjk!8:(G4Nx;7J&J&,%'',yf3u6c(%|{y;^Y`bV 4y8p~;|%m?()a v_نU9~`;|7O߷'M= -3 HQ8520x?' JF]JhSGV5\٭ͬ߱!Vg{oۤ[Z9Φ4Nh`PV5wC#::6% s.fc~78 YwIϠ&4&g[^r KޙL$LYcbS.ZRm w$vl3?e/b<Z*Kfմ\+=@JT9O2A0SV̆KH܉,QVw3xl/܉G)#cޤ! "݌0)!S;1Ldp2WwL=>$^2lJ\}ZdgR 7+kyGN2^Ldq (I-֒`9[F*Yi[LNӇ, ֳiF.29|0S$$-fkt^Q)b ciwoعM/;GjKGIKlvQ_;\f``ZݔaMڤ(ĉqVǢ49hf0Z~ dIrZ$EbMuSPw|[M[4Q|G85To_JG'%vIN2lyxe†SI8z`G"`U&dt[!K#7em6Y2K- f~oǞ!Л:hdw(Ǟ,J&Oa\+ w k3b(HYA>3rw{„r0vL,s-e09dS}&:2U> ̭  J̻/nҙf4BȐG'|S3itDw0$aLfG.EaK Pj\RXӜ(T*{n֯[*.R}rCY޲U,NxM4M,ԅ╃#mLka6ft]g\prY9#< ıAAcJjDYhi:;LΠŁBc( D1%siQuų̫cQKB=E#ЈDD98dqŽSiR! 5:p`xXv-݌M[]pd~{vmX+54v I2)\ڝ-CO'_N0=>㸱y8X $JB'pW8֙{ujҀ^g sImWd);e XGlt T@ַfL; 1[TzC'GFqk(]ɱcxXjUԞc%Lj N)ˊ5UA ӄTi'Y[W5rK}RFcW;ҡ;GWG? Zskab#3rҳ?E3î%7O%v6pY;aS}ls:lk)dtO+Hz7WN>8:\Z7u˛V10sSrN>ֵ`YjoܤT49WLdv\}b?(d=K^r,gO} @O#  =ӊ޶sE$J1ܑ8C> ɤ[đq'-c]<Lřk85~ &rDM+,1~h"[E*l/ ;Kn٠''=y\i=[!5?$mת6;*-m&JXSE6m/} GH#t,|C8 (&/o0H3\{<6|`SY3h1,i~2+C !pa\4M;Lx6o}'?ocW#Xo ֟>y~' s,\dc :QL2,D/}h$r%trʚmXmMCG4M}%gV |9[gC/=m0g3W#, H|+_ov#X+rPyvD})\PϝೃXD 3n"rLl. L.#*`(g' vRINǝ]=lR^+Wkj|upss3фbx\0> 2/t/a+\(A1-'Iߵ>ʓ>9D>Q ;#Z {'?- 2 3i[OڦcIuX3,rqv_{mI\__SO455+R&,KD.dv@&X11X0!`ґY,1ML-> ev𤀶oN:n輽Yk5Oܼ{(i4ȚJJKJt1;߸;?MKb-md(9E\D\НeeZLa|׼|=? =?e˚ }i|v!1(iYJr"-S.rJqUWq]w1a18skz`z?v-NkvLǙ,+uRdؾ}˖-gzz3XѺzm$J' ;T?K$12۶mc˖K^{Q,y(5(pdD ]3*8޶^a0ep<01 ʝ.hTg޳{GYJ$ff$ KDI`r,J'|k2ʏII#y#GHDI'~yAɜZI`5֡hvqZ"Zx[ꛯ&nmFgg'SE}Nc*6rxt _+w)&&s_T*=246mbӦM1브M܃{9?sa>'*0'g(q nGT\ǁNC}GQֆ]{{;?`|;ߡnSO;Y2(I; Å2ytݦbMZ2 8e%y}oFZ8 r`/1`;&&xk_˻nlCtMKy l.ir:K/}{SpG6ϋ dgLtnIotZrߤ4E'z`#"mdYٶcG)Ƀws:6'sÏ؉HsM9k*Vr-upyk ki~/(2gm4b R9v#ә4Yh xxhaowp-I .4x2mm:EWQd 32f].У1ĕJCS1mcy-=eت^;GG_7fp`YCbc u3-k-8NLbCƝ@8gLV' cX'rLN-!T"EIOn)Å!$.?\&:W<=Ht'Y3Wavz)o$p7Zke$ YL)%lK.aŊ-om[\|}1R A&'r6iZdN.V߯.t&JLp]˖qWJJIKK W_}5?r&~?Yϭi:2J'R0zRILk4MlK%v۹[J'oT4J&h-pA\q/\6ԌlYO3@a RG*0f8 d.^jNI@a-`- :VQ7LŒ+H$v-,D:^z$CIT8 JiIb% u\h%$=P$,SXI*;eV)WWҍ\}\QkK a xt ׁ#`[(YO@ 3E|;aǎ\r%ؾݻw/:D7tu{|ëDe-7un?-,UHXJj2,$nГ5sXNS/Ɔ|gg'G8r(?8wv4:͟we.%9no.lP;npYRBdY6dM1M04-\ve|Cs[E=066^U ϲcvq~{<_7!0 Vt$=,_fy/S,B9g27hH,hY3cYLlעiSw>Nr݋60Jt>4LC?O t5~V/cdk5ٻ{:f rL~!ǎ1:۴ф4Ydjk3OHnv !7\խcj0mq0jR_!R4L@ rϔbt3i2XղƖVlB XպrM=љLYcL;<>z/CVcYdYjr_m;9D|XI$ 뜰ڷr'},/g1%rbEf/I]oH@y1۔#I*%xv ,垁SϦu!IZަ4-f3 a (Љ˷\ WV3X!2Cc8Ò%K9Tcm۷s]w*Óй5$2$P\"D"9Y9b vBZZ[/NsvF<"rl& %-r4cNg6߉qΛƪrmۦ6qoCJΪ( M| ZI)*Ƕ,6mĥ^Z8Vf떭wQvK9ֵdx1o O|hRt%s*u%#Xd` Ha HH"q%ᲣMd4Z# av(@I=ɚ(fqubU9UJNWNZ2<5rq'k1Qc0F)P\q%?/N \2>1R!˙J`$f7_pF[()x1>я}/[;ԧسgϢ8<;<[.9IX2r4.āꁄ{r:QuXXBx[tڲ}>t:]b_NLR+JEV\Мt96èR3%~<魺MyWFW#$_ϳz*dy7GxpZ`P(w333UMNNw>>|麘Bp^SGzTBye21.tF&6?ӕ!g88k5 Ly$ik:cQtu ;7Uul2k:ҡu5ۺGh:H|@KgU0P|N0Rf:ȀZbϯ5M͇+/l Xߤ i`C{ 3N-LWw\ءkL-k(P幉Gq,oYCg7\۲LFϱs7{f}NR_({ytn His 42[Aoby ࣈT6i{AY-6rF -*L*p4<3*[^'ׇha/YTQL]Ϣ "#a wW\~lo|ONԾ%#k$b{ơXxi\l/9͡rRUW]ETb8pa0_WEIl&R8\4Kc/И(Sr (ϟwߥ\p\mshrԼmLd7 n;H*ⱙ&*57nd֭>&( \w:s<0ȜCP!U:T1@K%޵S0(# .iwL;w-{hQ,"@|d9b< o7"~jԓɉf" nGI?Q*33> (%qK.Pvʕ]eo7f*2IAq'?7Mx M4 o!ɚeG Rg2<7.=8?aZ[[7tߧ甞O殯c?yfZ8 vXXLj8&ZdJNOX'XF5 :fКic8^!S~L]yL'NL,mҶ\zLK[3|-'SE~:Ux١=: .wLr%\Ғai21Sqh ײhmO*x໏U fݏ`0=ia1yĔt] !]Fm#Мk2Ce;ۋ}Q(طoRJM-=L t!QG"]իW^^,g4aV ґMv^wP<3r04#?L#4NXq)=}V5i2[bRlŒ=(m4]Vad ywfgl}ҁRYRFK]EoӒSy~OF~ Ii)xò/6Xۤ(Ō|q<6Rsڪ>'(%SwJqtf?c!4nִniHu.Ft{hMi%{Ɵ`x[ZXiMGX߶ل$?NoK)J Gz,k:;;ήB,]ʉǙ,3eӚܻ@hGL&,T%&/aY۶mcMztuusկ|fƊ#l];zx; .;:q\W9^[MCCp<W ]_VX .bu9t34qMEBaoP'H\ץK/48\wGq&c*ƞp-g+Yfl7 >L%GG:v!c,ڟdLN$a8\ƭ:>|\\ *k;"Fr/.Oppy2:qeEF2)@?=[yvC6HgӼ/ɦ6fN~[سg|;^k]V-&,RWlZf?`/r9Y믻mt'Gcw=cտQ3a)Qr~c|ҐRRaȂ1z"e?К eiJ73S8w}^Vm^U }]~-oa|LlL?S,˳fIJ'=3n,` 44+r&pGR.^/h'pq_Mdr6Hӡ3!Xj)à,%3Ϙn>pdE8x5B4t$kFo+ӊ32qXbE]Ir7.9dy<gez{ɥ|^v'AJWmLL@&giTiz؏4-ܸ4Z:gr(څog7=(ab _G^J$kKDC(3dJ!7(uQʇ'b;*&mXb/drc܅U/P24g&E4E1ĝlNe`L,׊dvKw{IyNyij0W<<(IГ[B{ڋsi9ID3b.>c4XwU[F*Y)W^Lّ'A(9( {bȵ^Kooos0 ͛~FGF*gښ%VwiA%8e}OvK#^[)^WG8=lڲ{RJ;#LL`hI9{V". 8˗/窫y)ZZZя~Z9ʆ-sܠ[4t4*"#XxlF`ZN٤DNNW^#R9qD`r I0cL&%S$?u5`GID̻`8988FXK?J Bʓ/T?Iw_} SЖexGyB39@;o)yBvS^ڞck.Egv7u}:QS| QG)kJsmk-eG emeVz"Ay8AKD3f?+ZW3mM'#7-ށ*Eǹu߷/k#U+o3}V_CKգu@i#Îݤ ώ>rOghdwވ4uZH'ͭ:D:G󔟻iIKW\uI{޶_>f ۓ*4i*m:Y{t'%%t/1x`eR|Ů6]%7'kύ?F#3KSbQ(\`)5+ˑ| G9LYc<=3б2ֺM0%z2r}bg!r$|+|jhBG*7PMK|[IXJq``ysc wvbg)Z#5aG¬"q @% iD& h)f aG$XN7\:8APIxz+Z;۸Wp/SjSu?ȗpT*B ZrQA{34)riupxgR\}:غu+y{f~? #Sx̗`!@ kIPǯSx_vkDCiQm^*G)hɴ*]+'!V.m辦i>qqz!yt&$l+[~2U䖎YhB0b;`"lȦ%1Ԁ W[PV뮻 *L?*VɊ Y!qdqYK.ᡙ?ȳ.cblp:›[j648#{66sb܆ 9Ι4bQ񢺏h[ 2FumB}23z;Xڴ~hyǵ)glpkж\VS4hJe[ɞR Ud6_ٿ%a1I,ӕ4)ׅة Y="V l%Jy q1t)yϴB \/ǦۊGOH^Nk` ,C ShB=YȺUhJc5u wxAQx0nĖ,\Q.Cҥ .B+Va&ty}MK+* & >$.4r4^%^b3QX,rv:K__/^x_/d8̊5M$Yp &pp[¶m7DJV. Yl`ښbҚ3SW g~FUHdpll}Cyk+NƘ.O2Q=ݧ " }/^a*+Ds7N}apc. ;YI{I-Fp$]$TRUOl-EIDI;.%u* ;Ѳ^fsZ&q"(K~%s2mrɗlU /n=ay~attQF$_=f_$]1!:X' ~F[38.O}SHںφ|#_8SeԈz c. Tr*R9QuK| irt'qR\eq(!|Oѧy;m C__ys'q5]ۖޙGynno:)][c2,t`ws[7.'OL"Ҳضu+GD_*rGtn>~:%*? sx_=&4iu6cv6q]R' >$ y^~-\CXyO8~܋/Y{zvJk[Wj[GL'(%~<: k9f{g0YSy#oՄ`3{XqÄN_2[ ZR56-$o*g^TUmhtȣ cq&LYk'B̥ͤbtVrjJ܍uYR5Ɩ83X+HxQgkj~,*C*9&t|sN+:,=Q<;(rV_}In٥8rq@wE}2X8̾',OH1T8ʺm,m^EF%7y d9{}9ʇi[ Xb%Ya'9,aG1mu,LN: Iea;.tL-EI*ٍ oÃ'$٤QjpnU0VVwLѡ+Cw֋V;O3if2oi5ӽX"@q|(mj*n馺מJx+nc3:D_ $Znג{Zif`ƚ)\vexNJMٶ}g`07ђnW(nIpF)1eM"Ns\x.<|y\JM H3>/p G:Z5s<- .\su₩i\s5|+_*>ٹCJؚ?w鳛(* g5 Ag3 Ryia0ɀKj1DmtauZ8# [0Yy w5I-(&8p1QGS)`+laVZy ;B,Ȉh)OWƦoyK77񍌏[o;d߾}Vrt1'b[f9{hRˡ 7xz8Q$o:QND-pI~e;/V|ow 3{\{7}/<><Ŋ[)jW(׵ס)N9XY14ӁW3U*c&R8 v46><ſLa-[otimTсO62δ5|R^RyS(%gS+Ʈm@k%k043q:O,L-S ;,ǟc4Ak [pt4ur˸ҝqJU.m. G9&KEe(>u'o(b[{rm?Yĝ<,x0 g:oYŶit&u62`Aq]bym:o\frENI)Xb[ ={g,Rţ6[Z4:̈́ŤaPKq`i'PJ3Y߾G٧񬞷i ݙe~CSϑw(:y#3{ZSm [oZsFW,̺ؔ1zVf$XbSiw׋g[9Sg6irOh"ӄ Є7m+DSkEGA,{$)AGt{\ 2%n2"f/ 1liGޓqRgu4M.2tc- HSK7bjDe+$g0Xc\uucmz?O= IZ I02\}vΡ2A0Z`mWU\nw*xKwñ:2n29R)F/< *vmt]gͬ\n]5MnK_0T8Ǝm(%mP>h!Jq*|@v*28q Jqג jGaRI%Ͽ%S8~5$cRil!a0 $׉D1P }`R8ƕ9At]2:{;f;::*`q=o>ҦK4lhV-QlY#hȗ$7oy/25=Y|yCu:!>??[>ToMDIEL%Q,&Ì*Ai(0hIW$n`UfCܒne8Q9;绫~kqKòH|+9t0Ї35^Ĕ++5qԹ5⫣Ӽk=%POgK6Kڲ̸jHڮk|o"G0L=^W.?>g?U b1$PϿ?S̷U*~kW+? =z;Ç~!硙2/i˱5biJohm)cpTc\{5uy|;3R윮rI.Zv}M848f4OώA{l7.fN>\(癶-`8阚IZd6ߺ=W T+kQrKخT*`e3?a&L[S)M{oo!Pv if>;[ikjDTXмuÛt\hMә; t$l ON|lEJ/hxY qNC^}=mC._f$ !2j [bSId\Lds.4bƞq!t`_BYH7r6J,;W[umdr3a  Z!yjcAA! 4ώD*AњnrƘA}e9I!t3Du(Ip?DƵU)t獿CSRUbu /䡇b4Ή1[V6}4$hRQ)D5KLY[na׮]u8===\t|uGYҼ ]L'RiV*F] 7tTn]-b,]GPt F-mjFXN0ێ*@(CJIkk+o~ӛ; ;XrǏc,ɓKK&0qO*oH$ ,c,}āBjSRX@E %s/L'R&7,3:"n.wt|p@H1&kc-n k\pyld kf>tvt׾׽痿>&&&+~]6 cSWfp7H^uRlYhoQLH6oo=>ַ0t}tw׭ ˪ k\=`(pG ;&D$ XUFTt=HNwxTW%tl*Td%>w}+ze5|w]۷~75MП2ؖKWL]k; 䎩"]*2B44-3XI8)ҔV-3%>xd [*\U~~mAp` _k汹`iB#cfȗg*iSS{;<}O|B7LّKӟ23bob_A.z~6''rVe{T i7M-aDT۵XѺec(0Qk$sUEoz!LKPuZBC5,mCSOa)OwvJz>SBKe$SIf)Jn5C)r" Xa؊s%9q "SZWqҩӑ9BGl/\KzK{ V4 b93.-7-y33Ip.Z$3 ]x,#@ C3>,E&O]tn ˵vxnq .eT%˴:}Kr+?4˛Кk%vBOkLqWroQVD|Xb%1*9`k;8d{8IݓgsNsݝ"H(# Idcc1<lc H2ҝtNm;Uٞٙ B'{鮪֧>}E&Gg0g*)5oռB2޷Bc)ɶnv }B4%y&)}ԇrKM%)ܾiG f̧Hd7{*%Lzg,:ƧBy-s u^9=G~>csi[Da @ڵkill,)ax/Z̮;83zuKU)7$״̺(Flv֬YST)%q5Ws,dSKWfn%L4Ua@LG0t 7د;uk_*)OĹI2B:`Md$9% #[6GQxnƓL~2l%:Eb3qL@A"]P_l+?K/awǙl>V*%lR2 eܽ SC'3DS=dl ,)t̫yyi5KXyf?۞I g,Z=E+>mcUUUxM2hr8}%T-dž t J 0nss3Xz57 `k2(GTaaPUUŽz|AV\YRgZ,o mb6&) TEM3IL#GQzd?"aIYI((GKE;-Hc@5:*}UIJ,B82 AO2n7Ao |sP}뇰c zĶ_~i&#( \BӐ!"JV\Yf*l%{>2G܂U5*BBԒ/pfĔ\w667Рѧ/MzjmPFG!+p%Mg:)+S 4HY$S@#JZ~v.by92MF2ly|ķS_ÎzMMCz\R\"CNl{K߶{7v^uWs@&y'A`jQU3gV|,]J,b85HJ\%rt+MQqN9R.Ɍ3Xtiu lr`85Dz_.{ikG*@QU?ѓQR֖d2M7|; s.։ix5o?U.[ILYN riFO#ma7x_b d/0r3ߒRbKGFH;d tQr)h vV>'sbSyL&g3~Z~ 0yN!0I>} Ld2B,&Se2w%6pL K&?/6dA(x4/^ ֣{sZYr+6.}f;KSx‡?Ik>y{UvApY֮]gy;?0ׯ׿~rRxZ~r1oPP]U'!1Ws4U2PHb({Db 7q^/w~;֯gعݻvWRۓR2{lVY5\üs K:xgeE:r,2vz' q UjN;(]=/?Os˼i5O:),~za}!6N9u = T=1l֊il:4Eë`뢦zvq*dY#ke.WS~3Wkug ok/,qUCzxI .+ _!yK}6=)AXVS )h ~-_|*SJ8`RvCrƇ.=kN 9=Q5*\2|$0kQ^>#=-D2^w7U7<2sI2Ne_+{_sJާVq^wN1B(޴y|{VJ_5~-@J9*9<(訚Z65`2wy?QϹ__z{ 6|~|5kL*SRâ9HdNPʙ$H-|fRA.n`T$n$RDФ&/b(Ra8>}9u !Tb}7w.} -^?jA)u!:Ŀ{F2$t)VH ?* ^8 P_GH??hmmg gKhcyJ_Re,/a$xO+f,%1466r-p 71 dI0bJx˴_<8*Cvm[B@q&mŗE((ԇhYִ'Oe(9շ3"4O\ #q p_Ѻ'-;c9X'wk8^dagӸ(e{MtIVjLT qUʔ 6Y񪤛qZK?RJsTx^QWy' Hһ0,y>-QaB@Qf"tZdF6ٻ;![Q Eels\',ͳM2BQ57;Hž~ɜZ,x90dr*Z9rr O M&bmi[)GϕnL#$[ocmZv3?QBaDo`f/ A&B8B:L&BJD:BZ &lˊ+WTLm.LtR̝^\Ne&SwHjab ,^< ms˭o`ǎ,-%n se\#Ί+6@ Ȧױgn}IE[XY̧[Jg \ɩ*8hlS*)45ɤo&b'q"l.4\fN犅+(:)v~@*Ťs -Xj&)&_vP9rd"Pyd$|6xP$ ! sK"ȂstU_6P88EαS;TtS4X`>ϰzjַ/~{ j MCQ=w }=<=?>ߥekRDyptΡBJl~[¼Ea~2;9Eg (3*/[nH̓ZR:K3^ZY.Q^5%o6Gߐ }s)IHt<ztI.(\S"k+f)^20,_;&W#~3(whe KEx> b[~z"^*6y&epIيSct!QD~32I A_dk2Vʎp/E<#1[DkD CkNz]7/HZ&--?oƴ<dS7nC0\s _Pj#+/ldk2f:)P0\_L!Ba`bɘMeq]#{~ŎLpRW3K`$%KI׸c-Lh)t/= Dܝr1;ns|H!Da! 4)v$( K% c&FLg3/ %koo]esKӴeyf/P__@Ss3WŽ?3lݺ!4Mc޽<*,&iOhRP*a TIdgN?"m3K{wy'ǎ߈4z5WH %%Մy?J\MӢRS5Eᧃ1L AU冪 >E!)%AU#q!bXH$7|'y{/l˔Dy[)օ`Ib4g|_KM]ͫ*%ӜY~hVw^f^b` ѡ\5dlxgct:"`'Rt^uo4 ʣ0(voO1d\V %>5%dLN/P_)zep''PTlMoGZevM8DMz`Mqt z^yQxHlBUlX¢'E@e0*^YϩǾ2%EB.^l)]؆́xpJѼJQToC]MQ3"IBş鈤/!iP髦W@KԌ}Ѽ¿'Xnx-a"=g**g{=GkY\{&2WXR}L 0m ȕqHRv>a,^ 6g^MXus$sj7wDžTbI˴暒q8MOa=μEJ2/F4U&ƀ'@)7 Yz<#!F~-ɣ]T( 5YOɀMEXpIShR%(\d20r>%_X*r$E(XB9$$dvܟ'w)P 7i峗9H)Jڥ (Rg/s$QcTQnANϿnDFF'i&vPw~;/g%n[x1_W]g֭躞 i&l¾}\f^oOk 澄E97HiT=Be΃Zy)_8g)8R6=q9_`s> "yyہ> ?#^dIpJ΀pVJ?*0`Zj$ASMlRRѸT:_V*ɛf;˜@A+"9?jԅy:sٗ϶l>VS8WCFÇIq)VV? ߬+P|!C#/__/1j/;.E4EAA &LjT%PA5ob;Y#e*)3I$9xT>ώ|9Ͳ-&GѓOՉ\ .12qIlsz}amYUdK]gcCV2뒨R㨮|峙pbTR۽y${ŖQcp8̦MڶMCC#Xe[R0dUL}LR,Gm["  |Ŋ)ݖLXv-Ӧ}yR 0b2^**13`T*Ypy7۶83zr,.7$_6GHAsڷs^c ه!t̛7solouRVD︍B7)2k+mte6vEfA$MnfX>7̗q {;wdl&ge]"mt>H!DI $7WיH=u86BL#QS( rM S(lɇZ8 !b8y{O'su}clذ.FQ}-ɊMKB ̱w'wS f>K&$E siǧ? X" dcI/u\eY_QSI$abFSBĒ<IbSxeGQt!( WWixsٓ0bQ6___QYUJ2{3DɾVI+\ԇT;=[_0K1˃]؀\Qi^1YΌħʅSKoS? $*{V0{P(=rĖo+@ VRT\2eU$Dd(j=ώ|><F yWILŲMf[6#!>W(\'yC{\0)`$yeJBNi)lSnF%ߺLܠqr;yM8rīzi7TDAgaG>B29jJ^PV_]#b& r¨Jw 6Q)s۶#c3o|ΝtǺIr$P IOi2m4n󮆖e0s,,^EntRU 6 !E!jDHI(7n*`c AeTI˘49rߕ]UQD/m"=SVQ[[K]]86~)%e˖ֆi'{w= rIsI8kv̻@S=Yv'=nM&.qwM2W2IJ .)HɗqK~~@RUW=wG?D&q?Hr7j$q2YJܒ:$lϹȧ|YL܀R#n)B y^=w _!xjJϘ9>ȉM^VGQX3S82M"@5y݆hSJ4+.$_W$b4¢ ?3 [SGJN:lR_+ME*P'HIUwc=W6K*<>e(&},mYÉ1:ļESlX |mu,;H`F #le{(*Ǐy#=۱bٍ=܅tz*ox/uw#-/VP4/ґRFoTI마~yGܳm<ǻR0d 0! [7\X % gw&OW_Cc9̂a"OԈd#OrUGiHq*cEϰ{ w%r j' ƌQ*|UvB!?&E_[)nuO()뙐"gxJ2n{F{mj$5ȓc^b5xo9ћF4l!x8:Z`Jm&>DŽZ+:*&V/{ݰu|?{ P>­4&@-=QUEu_4BJT&1E&:N ) :)|&rA!0C8n[ryhb6_wr˔??!O=ߏA*>tE }M=|={橧|M2ktp#s?'OH`{_HԉdMͽ(s&%I$Nt\MPe(>6 p`'ü߅_e˖O||#D"|/l{+*W/F-quUɄ4o D* ^R(A2A[[ϢŋK ]ύMPmGDJJ9i~Rf"e&y/\kYn!tC_ K&9$[~Rx5jR'G茜'~P 0˅TKX)_OV~;A7R7(U7]̖EGAE`MV{,jU d z k/f쁓(*6QBTAk@F?Xڅ=܃obMnix g~ݒWΙh*Be:xt[fm5,jXviN457Wo'"=Y~Sf2`8<5YѼ漺۸#GW|D/ +EͰqYҸÉ!,EUC͑Da^@4Qjul;Gc3KWM0Bd4d(.+~!2SFhy]=/r;](y氅1& -g9gW/[,": G.l:EQh (SI>Dq(.I40`|N9A%H [w|n 0"nc͚5-ˢ%Ky<!^9P1Kiy.RBAUe JqWJoO#!FS#TjzgۦOJCUTf̑I&X<Dv 7ͯ2d)ȗi>ݤVU?i)*$ ֮[GssKIJ,Ywz~cX:}nZm6nccU@meeoؽV8&,+|%`xd"PI|;Daw핵2<dŘG23b@ɏN+?#G·<g"|1˕)(@]mBR7 K=bTVVN9W5>ۋ'6ׄ*pWWyGSAEagBg[4hò7;?뮻t}_K|qtq@b Q1&l2YYgϓ{PH=p(& $r9KK81$ռTkIgn ÿ od;nGw ôޓg᛹\8ThGCH&%b ile{eڣF̌r,KTQ᭦W4=],mo<1Nm99 BtVXIpM~1[c$vԾ'A U@ke.i* R YLND/?=]db #NfE6zvL8 zjS[,5JBeף/N9+ !DS=/9REV<~>\o6j.n\o45zxqRsv^`uƩ 0FRfhA*U|a3;˵oRZI#N*qp`vi&,/"f ˶ |lzw*~ 6$ec l=l"ӫfFұCԆɱCgEU45$Sgt+n?N'F]/rJJ+_2~=[9=ͳinhWQ4Cm;<sDi`(6FEL|~9L1,"ruǺ艝eQòlxe{'5mUrȱC02``=[RS}-Q%9q\?G񠩚v@a?W P<_WQdp2 Rr+O3i.}Tm:a{Tbv ۶[ Bn,Wr*2gFO0n!U,DJ%̜Zb6ݱ.lۦ;BPWWϪU9t BNcE`lUUFliXz5e0w\͟ϙ' $h6e˩&hFQ@JB 7f̚5ssskP.޽diF&+K4(2)e8Ј=j#'>Rxp I䟟LLl&ap ?J 8)\Iw"ƑB*%OI!Fb7XGr PLvBLƿ&f,g$qLV"/`K/|x8бchO6l(7~yܸ$EQ>'O~ agF= 8uF_ؙ m) ~q_ > Th*sc?bH8\@Q81|c[hZ"rdq+0mmUܿ _m/N@gGYPŰ?e߷g"ryv:*g<=Sç0,ߜ0L$fk$1-,FSTE%e'x4 `AOmWV,5JLb AM>ߑ0s[.9g-,ȦljqhY_=Z"r1 `g 9GRC=%5tRVґH5X@($'Ŋ%d}RJ̮q3st-Er% OjEQ׿=}ېRrr(Og> ɱ@O˩I0Ԏ11ÇdC扟>'84x}&99>$ף$ա^<|S %I)6o*'bLG2Ʋ{ ;{^1] (ڶr[?H);X`Mq HQhhX *@ҩyH4]PcȀLrch,O+eLI䗣!x}f ه4/d,Y+/D,4ʈ>4f1QP1qK'Э0{f͚uQxCtdEIaBU<Nҟ4MOƺkKL:z}pǗDLp6v& 0qi.D7>N>GUTFQs)%~Gy Hb̙0 3w.7l[/F#SvAvE{W^k̀K$d,\RphLb2@$xLep߳ŎYG&)U6XrV\b+&w^(L~8|Y̹ 1:^,|>},?L߅!`B&8}!I:r&a)&$OT#|ftt pw] B)P@B\HFmAh@C/̢E~>}Īr՝hʷ>=b#cRA%7ťr7c7 29%1hdB~87*AkJ,a2Hw6an^ܺ)9g5qg]dž 6/FSUƣdž6Ն>;LaY&V>K`#fUȤءX {6S:zLJQ9ﭱw=v*Sﴗ6f!dE/FG/P.TH| k ZUcYVWdߜc1̀!1%$%WaJ V"/[^0'u4$N)OO# So_G}'Z ҙfQl3T S? /G TB(/[ ëvf[huߋc1@'fq@ID*--x}P!<g9(^e[B8Г/ӧ3nEU|%I3A* H Ouַ7wb-F..zGish\2|DW60H[̙ǙY3BT$'1ʱ $WiT,l[Ut61#瞅02H)M,N!A z&oO$M܈fz8CIg̙ `Q‘iߞ~4+ ɮޭf}A2` f\oHq'fw{8y6cgFOr&r2o#l?pj0 (O(^6ۻ9wnpIb׳9#]rdp?5:V7͗JYI:|o'A-4.%X$ ' v ^Wbk,Łj4C|{}4YjL|oJ"ߴқX ?*w2s^+[^f `#rl #!F0f:e{eL T4V ȪD"j "Kzw=b`X](k^6PTp<.8>7K:`#S£U`FHeNHaYF_,7i 94͸cDdD b 0ci!IeXCAEA RoWKmf6Q=><+ϿTx(l$v^*6J . k,F3/c`:LC#vP=(Hi:8/rHZ[HKp|0B y+ՃD9>[XtN9ɘ6 ̧6U_Dڂd?{Ͼ;oq=F45 ;{2 h~bj6Ng_ 'Eo^45XdlG,kKŒ&\HH[^@8߻1GRD?㶹gs /KKVM{VsG'O}{c{O4`LvS VaK3Tki>#Y#٧2#mǫzXc ]O0Kgq$8|[K( ʑHbz4a6 æ1~c?w]ʤH5e&{^ aŐS =wb('GaЭ$G:0N!-đ-9<2z[羱`$#e&ruovtB6\s0zbЁ4h> FSƮiL!%jȋHH^+gq#6οŬRA`z5ϟ][iMtz. $!D9%-Wb >R dnӻ !m6v\u3B۳}۲vvoeA|JHd劲m,ȥspZb-qP).ܻr}d˧M!aFL\UD1CxIQـPm.,qXD9M荟#aIR _ךbsҋ/rb0 {])\AG",ۤ7~!55yS H!npUWql˦3z(D"19)FtGʲ,V,[FEX[[k׭c]D#њfag)Rb } &I*{\J%IRٵsb,Xџ%i%,&5GM0h!|U|Xϱl+ 2ɼܠL]ʰdsT΅L 7Hpe70t [*G.+LgN? P}l dwt I⸿əlN1T$Q3?nKřLBPZ-J/uSd29$g}2Fo={e~_&^7TW՚JC׃WQrIO Rtwwo|ZONccy5XVW3}S)$=I>Dq'E2>ɵUjCu 6f&o~?@|`FL{6́єX7Wh.DU DZM3f|J4k}ov \.D<)r2l<@sՋnU[)zb]݆Y8RQI N d\6&t*;ҋ=;i һsrߵkW|2(ǎM4(vfګ)WO$[: )NS4>TWX\JefP!Q~ZIYle{E{t_VS᭦b6Qc}QcQyZ–&1M9p( si߹=WcߕS^ /$|=N'~ Vq.Dtit@'6G41Bi9R@!mGSu$s5v)M%UQa:Gje+mo]o xlqs=[It!mmܽ硅4ݵ؆4my)}A,sBN!jFB hAHoKnˈIw,zk߄nr 38lB+άm+Vi33↙w҉$s!NA-Aq6s;騜Y?hR3%QiyÃz%{__ü9RfHαC{Kv#-_O+ٟ`>~}G2I#;@ZOk/~6[_~yG4v`;z_`B6ZC+iu>fD'qtiڼtY-£i$D"%LXJRysk; R~-fh*1>S}KnIӭ !<3ggY? `$1ꌞdova ޵t}e;##:>ګ:Ȝz?XyU]Jhv-3RgF0ĩ_pǼ ԧb493Hqhh|m޸dOK,[-edIB  RH[ $vRai<Ĵ %OKlI|7̻նrѡz` )qJs}|r"?,U村9?,&DytC\40( L SVakaV1lԐipE%ca0o<_ /%,=T 0ΨR]y=t@Ƃ ijj*9F~Ō35kTV:߶mc6m{.HsNV5Z^~3m3H!PU;օa̞5 6\q!6]['Od&nˀsRV e7QP5y˲hkkcٲe5bŬZy{w!Gd$YS̀G4Փknzײ7cIw>$)e=bMxB0>W 8R,N12+%)&]f8)F) &@$YA 8%$#P&qWN(ׯ硇bƍL6m<O<='2cqw1`*)fIL}QܭE9OYQdKuh` 0B(='[>toɃɿkbbYWAWeIl$׉ڂJMū(|Ӷ#\sS*_+>i8+`RFVl'O>eh,(xUoi&tv$I;_S=Tޡ #c,i( ɌuCe[Opvryi.)-|* ^cSU$*UT LdX0IPRJ5wl)؆\5F$();) [GSXxK8q@jq&-e諦ތUNi<] i$z`8!S=\{`G >u9Ɩg[0g>їp@ eJL)^3l_A x92pkA"2%{wd%4߽xTaSđyţ:fjvw`#fF987+v&5:F,fx#sp`/OUs|f#4i} P\Lӝ8ݽÇi(Ta2^xOsєJ<~3JBs^XB;J8o\v|?1=^tO4#NYTn(1T=ۘY9兄Cnk rRbz~4xT^| !˛Vgg&v=L}KZo)9>-")$~ ԠiqB28FRة J/b00i {ɄL&IbݙBژtϣxN5Fun>uW^OAfzlZ@!ָ!%^U7~[x^n)ozzzf̜Ŧ͛ ttS[SGCc#7^Ŝsصk');Iwa$rI6JdV'iv,J u\jE/@ |!J:~mVf}X2&5FQ464\\VײhbmX', $q7\` QUdEd.I>I! K#n˗)7.?w16KX%CIV^y+L.Lc%@R2cDi70Jr((q+Ć9 >)tn2ٜk^*+z/3l;q#>oOTVUwl~3૬"XSL[kP҄䯙.%@SUݻaF|lڴ9sL)G8③N7(&=vez % nD%_MkO;PE$9s?BVt]|N/|U(1pqJ  b JSώ剟'n(k_f10!E]2L?|nrQiNO WeiMaby/e9:Ir(1=]7-&s ヲMGS@A9u3oq4?g"'ӷ۶8ަx[U5V7^+?F^RG_#j$)ɳ:Ka#XCgOEq7̵oW5;- i= h *u>œJGPeAJ_A` %!e$e+2Df>j(bČI;`:_cm $@XHim[c9h^u.HHe|N[i{(o( {Ique`7B1oU[ D xhz_x*&B̀ܿ]?56-/#yz^l/OwM}4I ! ͮX ݰhm!@'OzUv%Ҭ!ѻ;a@ݍQi 'yzN4 )MRVۑR"tʥ-42F؆R~ĝߒ"9>KaK i U}%*uV{{O^5Hr$g+jD7ɛaS{peq[{` ca]50yy`,Av;UغŰ2ώ~[K}#Hѝ94ۋxk^;T(tw-Sf1aYڒm!MGz]W49-yTӛmϧIk;hk1tthN7A?E_f~b?\2w;aQ˴Vk #Lo}Ws[{H?`Cu=c}sx5޲"ێBh{ :ߋXIJ_7θD оĭ(nxB|MaPfm#HK`75 J rrh[RoGժ6)؅P[`y,.KtΘ0\G y;G¶sʓTazDV`f SjQ_DBL&S;\K^ǥeKLq/xwԑnF $HI(7uYFiTիιgO1!mrLEUI H)[nR,رchF<c;zo|k̝;%Kp,\uֱo>Lˤ3za6Lli3CA(d 4\d8Ʀ&}'z訜RHZٜ11Mod2ʕ+Y`w'~_n6eoUTGst23L%͓=d%RF6'Jh3rƊ1l&g1qW(Di:N)V)3z 09sLfŤnø?KIӝ^Mbr:%0d"0I W(RQd2`D2:}A `)Ťlǁg2'~=[<Çя~wmN:`M-K~PH} |8JMC FAMh[U\U`c# =^[ar=L^|/!^Bc MH)?kʖ#ml$( ZM9^@\H3mxT=p:z,o\Cw!}px|HlwՉ#1M=!F ^dYVͳh{ "aUַ=Q=[_s?F5 5r26 [޼ s$Et9*߆Gn"ư#RxkHΦ1 >0T$GrX4laSXDմc%i51*Ws0A?;=n{/FbϾνK޾ Oi ao]Wp/89aO%WuHXI簤2 Ψ+5:8QG#7q-ϰٸtxeV aX+he@V!MP<*߇H$q~q2nZtOthSRR~-.Ei"m'Iƴ vlcAҜ:Bͯ'4EUhUh?vd~~zaj+-UrR@kT9Dwօ'N=nu[/z13}̨A"[Bkipg;n'ƶq19;f]L]U+[i}r}kvʢsϣrE VLGQꮟMd{ÃUpxh/ ɑITiوO;WaER# /}Wn?-Ha /j+*@-C%Eϳj3yS:<޺ ^ȖNFww2K&A'n5p3|"7dM;|ߵnƅSe0чeY455nZ4o1MӧxvڅN*}9tKXBGumg;֕ǹ `>=9r(`xxCrAy̙3vTYO`zΦþ^B6gg0Mٳg.Ykk/~A(f050`bKU܀EAS4Fa"sWdɒKW]Yx .fǎ#0!oՋh5 0DJfM̀ÿl= A>I?TCP|Lb!ωLav[&b/dMSIW&aA dRL|u#w"VB@Og1[) ?u2:cpfR%Y|y=Gy/}6<:}P 몂MlTM]C|FBIi=BPUx) #KTi*[6#uTH F6mmΡCx1 ,(~/o:sG1O~r澸ǃJ&L$v&e`EB&kŒrV>|cV{Ii|>>OqIK(JY QX Uq0׭]'>)l o~g$N0"dllY`25MѨlw`khwZ`TD/FH--7`m4[Ҁ\燔mgcGjTr7*ڤV:g>'~g_!TUc89Me@E'i%ut_ r."06YC>V݂4SHs𘩮UH=FoSu˟^z G>sl0sj0jk~X*< %äR)nZ[[/ٻ,ٸ*| 8>rEmB/zU9lᄅwb ;ʩS9|{a׮p :;; Bn艟ezl+rJK5e\yDq3(~;ӦMdy4K-T2i+ǮWl2,'栤YXJᜯdN6XEJ<΄H^t }/۫ϴ37~\ CJ+t\UG&l滪9qUEe¹@2q2/R' D^G, ˀ<3^Lkge.bpͼ@3qe— (?p˰C1(9WIqF.;>}QO}}sL@4˴8y4+]F P~ee%/'$fQze—ef͜Y|ӏҗ"M\8%ae_(\Y&|n^dJ,');aQ#Ξ $z1֍ܾ>:gQ-d4E# ռ'n0,Yh :r_%ƜEDaFOc jzIq.YIbfԵy3iF܌qtI+hԼxf849SՈ~t+"!olHt<3LavG98veV|NUTfsN̰5^U]W xE҆@-sM)/:E)fbv~~!ta^Coa/.I|Ma<~&4ôUNCAT/LE[xAgA])Wb&IB %il= ;*:޵[P *@hV-" ބ#e hMKV"@sZ^QFPK6L!mn̕񑦍Z5ü`ILipl3*<}[F$-jN}KAS mg֒821Bw镳90Dhamo]IUӱFsIBs)؁>J܊=ƊԬFĖsOab J:޽&n(@pf C@?H[Q9eie>맍ޤY{ 0N h z?uFvnqڑmob{ :I;iYKP?F 芞q교ƛp<960 Vx^=FHPFS5^~wT1kͮwQlCUFH؁~Ԁa85ٸ#d'L޶ͳ ˽$Oz4-.yCG_pJdf%1l= ):GO7M)\7Cï~yBx5\VqauYL&]t+)\8Ф3zCCCٟk׬)nY6T !DIqwg"U5{@0<bÇIGG)1I,¶mt]GJISS3/aժUb5pK< ӫfgn^`d#!0w6l(}| D2G>S (9k׮SP۶ ~?ʢE;<9D79p*8 Qpk$պ?t1f [Z9 WQ°tfTSBR?2h 5 la~RVܙ$jnWs訚) N%a*y-X^';6FN8%?J< @L>}Q4҈3gUr$w8[JTle+elF̯PP4?5DH!i{` 7v$>sUa^=଺ <Ҵz:-o\"mA_w?˃L}b-΅gV#L]84ScCPFOi-M::hJzuW"ߖfchDvA(RJ6͢ SG:vr6|n[Hݵ3{/W4\δu(y/aȂ/m4ߵ5 zVϭ;cK';1U{ar*ej5`HI %IISP;902%R*޺_}D ѻg~[+xh 9Nff"t͂Knt|6a0םRGXg~qn̟C0vu[VM6} Y|>AΞ= mTWװv:BPtu$b !eVP$CIL)%wy'^]Riڵx'?7w˧韩HW%$fM7_c6ljb(5NoUP'zI&\},\0 ̙˼yQT2MCU5Wv>6귦Y/V9˶\\˦9^ŤX0La"Ibqr7dsf Sf6yuX`r1:Il v&pM(2qT䇛(͋enBw+&S_N`dl@$ɰɀSg%b \R=݆R^<ȇ%( aw3IQxVȆ!UaԶٟ0`:;<{c=3|g_921 [FzpҹvG01COS&,X;]UzEer2HB` xE8)F8~ sؒܠdrs!'QqnzB;wG'awq?if !BlwSx10enwTfq%)fB7!԰k@՘Wʎ]W3f>f$ÃH.7KY Waa2T<;[iwy&Pİue⟵J{I":@%HH{݉K m[(X$jDle+[Vx^ǧ4@R`"-6HKnFZ^R&a&y. 7EQUl} Itf|RT%݉. t MsXؔ^ȴ\LW9ee 6Ϣre+˜c PoO53&׿GIf}w,t@9*Z6:T|IX1zc#De9/KT.oaoDK[ŒfY =q9 G鮅4߹)!QTv&UZKzRHn^%4[H)P--#ɑ9Tl%<H>)MDʢri3+[$uN6`$8a82Pe%mV%~͑i+ y+ZPdm>{Sl@I66PH>i!޻EHŏtujOzm{' M6fWm H.k'6210lL{Z*K߇lshx|MɖӆhcS΢n\S(-Uw"vRy|v$'c/CgQMS=#DR$ 暒Q}QVZΖ-[SbS)jl38 a0`?.t[bÔ ױaF,&a&;K:+JxO3{l_І(ZJa,ZT*EozfRd2d"G`2q?ez0mS<1G)A95Kv[غ(iy+}v6n~ٹ%b' VA"KA!ҙ(N!I@0/eX`rPI s@A %7x%qT.YHܝiw!qKOk/B`Ls4.\= S瞽{?S؁oxkCEr¥ ܬF~f7ThjThbBFl%ЅDEʣ1'-|iv QO2Q̽f|jFmA<׾5_%dNLU4{VsJ|4SBbYN!PH [s|aC3y̛HA*U9'~S;Jgnz!bmH$>=w=p.~&<,SFא?l-==R K Ҧ_CSE[vb6Dʤj#1N CLHAsej $^Q@kS3/ o9ɴiӸbjR!E,{S ,֒k.%I6]v,Ӥ7q5,$PY@L7I漻^N|k9)b)W3صL)K̾z 09O+u$aO 3QX"{SrM!G>$.s@}m52yb*O7iNȥMYb}׮]|CbAW2c^nYMxa7?m- UWa\͇jf5m:V|Rpְ&JBp{-^UC׿dI"ț>z7VXг*l%ݼ R8n֒bى,'ty(%*:IUR?%p8tM p_{`iDc<'1RZ޲MHK8 !zgA>!ꮛMŊ씅IҋM_<޾laͯEiiʴ L+XVU9uWNYTiv,4V:st.*W|"<~g-ZJyS-ՅTfo`_I͆(@U3hsCX֌HC^ׁ)datT3kZތ4-Z_氤LB><~Z߼a')ߟ4m|Ma]Bx~#"ep\u0m i{` ޳6 Q}E²XD티Sfm98w]‡G0;iLZx*nţef2)^^q?\q%U)z&da[GqIOR(FL?G*bժU,_|9y$/n݊J͛aSn_kݔɱ9>|a㌙hN>$TgEay²1E-mضMMM _! mK|o{zjeY455fZ|~¶鉟Ŗe|>뮼+W2tExH)=5VBQd1L&RJlH[{4O$j"LJTECgJKc0k"f0Ťn&+jqS`$y_lK<:R R(]X1q_spbI:Wy+Iw~g^jI |bi䳘mhPTqJÇwFdEϿlA/z{Y>uoXÖm/*W4Us3L`R-Ѐ},йIK1wמ E)0S(L+J,ab( X|o ̙3_(UUUG>BKKK-_9XbĻD7s{xM^+۫rşG "aƦ6eX:sj2~{zsd =sT\e) 3a;r+~ |* -Ib܉LFQa(Q[ +Եc$W߆]i))7 ըle+[V?pM`F 9c´ Nn+Bx1C [[:3~.J}˨X/-mO m<_W}i]&8%))8)%g;*i~mU seq. H윏%xZaa' *կjU_7j;leuް->ִoĊUmk5OS{ MZyIЪܷlI syD"<7.atN-[P<QMX)P 0t4ݵ} A+EL X)6͚R=[iyP}E{6_'@d0,Qȯ>{B䋽w$#kSy/V$׬(b윔,naȤHf1J<gڵ!ؽ{7i&̙CoFu6o>Fu,jX6[Wq6"46oڄ2n&F9=ͼ939NLD4.\xQVTU%::JoO/~}a;n=Unn43rrhQF+9*9'ݵ-kk{ߓ$ɲgH(i4H9̡F֭po6uBP ι[P,ޣbƍxxgqt֣c.&10.ٱ˖-إRoz3~9WmɎƼ$PQnQa<zpI![Տ!'=!t*B:M/5ZC9`0͗QBx&$1 xv{P~{u?z,B_SI;RJqۯEw弫x &G\'[A$vT[ll` ^.dY[_3=YBO>}_}J5u+Oضm[lտp,u'F"v !,ɋ,~_{:"k8Q:S=z}X׿ y;J(8#TJ[Dtxmkaw|>iL?% Ԃ * s #p[A k289$&YŶ%;L#2000000Å _  +~f?L%rn݈buKXplE`u9XsW }rIT%A(0p|fؽ,}6,\E[6oڙ]);@ XX*:M W?YGq _AɝQ{,Šw^Zp:>_l6m&A˰g/ߙr io=e!dX+W!;j>㌣ln+.nߌ7m(Ig;մȵcJks_v*K7A}\LPV$$2[7eUJ,Փ`!ꫮBX=Q!Ee#EmzٹH |ɤXѩIQITiu#/%z]Nݫܦ}ߏO?,V~\R̡X~X1ГLh;P7ʌ!m2C<xtslgpSOAH2`FJ8y4~wwy']R9:T+CkLDAZTBT\"?dR"'TxJ %b:cՆA"9{>Έ)?D49=mq % 'ۇkqx Nw}wlifP+;y*,Æ82*sŠ5=r "keq:ލp .یliH"gQ^by*l؎< ߯a{b/ջ4*!,߀`(8J?wk}?|{)AoceL#2000000G^ngBI8 սj{@2bWs}p][݃;W% \q>:`eqlhPV oqX%?qqj%,ClRŤ* qıp;7R/ƍc>yQ:u |W\y%Pw4y.nV'> SB(n 8cW\1o8zzzp/ϐ0R=ei%J(Ng=ΕW\%A!cxop&''#c}ظiSHZm۰uV< \d\-3cvs8.8j7?>yla܈O'OćQT-v݃xS_5N8^gx@>{j~?;6cw`(CQc@R` ^zԩq3^!eK2`2H>'j"͕8x{7~7n\k+G@WE, $zID:'bdȤ1MQ'[D[5DÓ5M|\PLPnIǿ[Vc ;5/AX{8Y3dXTU>gZ9l߆3S(sӟĕ+Dž;Qt%Ǣ6\u=7byq9@0!(xcxqb((З[.MӐ:E,"*^I S%$ *OWvd _.p=_MsͶʣ^  XV\a)5 fS]<`̌-$VAߵk٧ύfˆ꣨edh p| 8jkuup1x :.ھw\{0Z;ոDZa 6o<+ظq#֮]gQ8Y> J&ˆm %VgölpZ! XXIx2LёCTytq[JDWN\s C0i #rN$NDE&UmzĤJC@i_R [R1Q?\"WH:%[:1hKcV!^%_TjO~?/ށu`I:LHe C-LxF<3?=y7{NiH̾jh-N=44D4CyvF'0&RIOgo-KoǤqi<zPlju\s':#G{\vuurMc㎷aO <(źލs`~PVq笴=-[.{vdf|Ï `>7 YC\ƏOɓ'z(,¥\˗49SXV\ :8Cͯ`ҝyظq#ڳwOsN4(slq,joJ(<,hpX7O$*Q-!BT:bUGQWIŐL`2K1]LS#lsTDhy-sttHD4ѭktI?0UҴ~! __):gz4c/M|R1I.<|$`E㮏:2qX`yWmEoKd D^G>|ӟNd-/Y9VbԤZjr^G2 :ls wP|-%ѳbk& JB( K0\:ppLLoPw|ޅ"ᄶQ;iלZM@(8ERU%UgNƱ#S,bPS EO>JsgXĂMqS{pd n\z   Vc0"&sa,mp{h=rgh3*g1X=Cz!?ʞqx y4&ErAS1h#*'94D.F9-zOD/y'I`S>{lق \{رs'r pM7㘨M"owaxmcؾ}{Z[o PJq|nrfsR-[+ws72/}KpiJK.֯'ixE 'CWK.}]7߂QTp6 _{ݣq^N' %6ACD̫R8r6Ҩtd0Z[.ILf:+TB8hHRTۨ媱֩,ot'r D&=S0>blr<21E,sׯ7MPټ Wr]Or +yr03)usd-=|vk( +v O)2}K{:k#3#QsUK{h8z> n|NK%NMG^"224} )qۊz.m=#Z*2%A N?W: 9ο˲cߎ|'DZBG8CnΨEu1[^{{όsV\[nyV:1xشy3~)}܃GZs}\{͵{0NUcmzIT 8Xv-.Y+0Rmx.M5;ay#@drID $b>q(ؑJۆMND"G"SUQ+1DC0č(MQdl&+$m.Yeo#Ib~6K㤐4"*LHj>ܞUbO/ޘ. m᪮g^pqM .*d@qZC5\QcLOueRu#'%^ul i|̬&GV,QNdhFC*IR07<$R\^lCc5MNXD)eL'i_`R]FKm^i:|UE>b >Pp#ejsԆ8êxƷaP]r݀o<{j7KC/p1+,,(ї}V]"2k/\#|7O7p#qh\зٜBj>* z;kU#( p7{ DZFxŹ.ܬUYdҲ?@;&XtG3w48ѐ؇gERIIc<)űny`qx0\9 /fs}. 稰0 ] cs>8R­}u=A>m/%x}`\ tdo\":Qk$EW1IE.mr䒨l7|U>Kz o^x#eovNwwn[.r 7cGT+zF B`;>OXD7R ۃsdY:tŮ.pq|q)8ppA(U^7(^x|C\.qnOw7FGGj(&D(@,³<}C<ê\j}fosWa\лѦ =F(uE-HUO"R.tj$Qr3%3—qd|* DE*eU$E9H:Q dX"BdMjZiwPsj& b6Ģ 122lgpq1r0?_p5gE|j"na: LTZh"8bL* :k$MEh"JHS͑8GDUu'@O.cR?7%ݚ|.qg󼩗,A4W|aҝ-ϟ~ sdnX{^`%=:"޸8 VA WNaԜ$ *^9ꕞ=PL%(z6_ ɁU'`f3N^*Ǚ0nLgpٹ-%6EqT:¹~k$;pPBay7&988Ԅ3DN;#ԊfOc/=,H&̚oAg)`dM :GgN1ᘁ*:ݘ.P)DM9 kgaqD'!/5n@Y#@PL2L*TLM|QzL|?zG1V%z߻|߈&X,"`rrw} p]Y5|6^5S۶ux,fxWHdLbHux_iY<#===, jw[CgF&|@ AVW5YHnXgLĪIH #࡝M΃=ND.JEy#P%>Ю%-V0IqH!:k QDVQ#ĥ> d!%2D${EU>H&HTCHcy&dxS$YĿ+i Gx<ф(hvuJC ^[@-6BM8s ^ oݮ[Xk ~PD.S )YeD;& xq$ 7 .|2Q>VF&3'F~EWwk _gZ:noijKc`Htmg}e-jJTNNc ?V:-qt/c0K/C<r"I'7i%m2}D4$bG&wITy,xdŒ4dT$I*%IyUۨH&*"\Qd^LWO$ȿ<_o $+=}=(ƐΡf8^[ē:*&L`%q G$:L,Q1LuEi$UG$nE&taFD-=^VGЋŷ>=iW%"%6nOMc^7f:f|53x(8p;Z+ Xͫa+ Fj'1^?2_fSĘÓQ *,b7P-b!k味 (](8(:=(dV:m3+bϠnم[~4a *=4/P'q6h8YL$qr],߄܎[A좸ޔP2ŦmO~K0[e1Ii[ڠ,eI1E)v 1܊#!g4U!Y+`m.,bE8砄MSۊbXǨEcS󥨛X/r O5*ZחZڿrQbZŵmyiۓ)k'" R 4Y. Aa<KcO6ovgzo~@$yE׷V_v*y2}lT6|rҬש%fj.vQfnnS/3eu8VAt"6l4;16u VX1,PPPj"נ kpԱ9(Na^]. 'P+O΍{5z+2w;2xm#:ʣa @-Av5 ]EhjN.ѷIs[Ay>{GB cK)AOve3<;:(8%HT1!D@e'JK9T,E;d3-Fy,_WVW3xۄ4"IKb>|TkUsIF$*bj;$ $D(i|];%P}쮚_ I}G GT~XV2 !CwH&Q!"bđFe1]FV(!%TҌc00 S ׉'b\QIP4Kɿ>*$H䇷zG/YOi-^zO= @\^̥c /.𪬍]ccc8|0֬Y%`MbR(I&I692C$s*B6F@QQ~rA%ATX487]3eB][_އ3_}kZ/='(YmϠl b{[|ּq7yM>/r[wԗPe1\> w>xo7ɂU,;`:ƍ]Z :x XNE'*ǝG=Z  <*؂MN&(r`(K0\Eh!osDɴM\HVOq9^, )MSElt9,\VǩڀLyWpPtzpӪTPJseuqT\V8s1QIg\kQ?#>틊t}C3p_ug <(LWܫ?}by, fr(\_ʙL h:2qk~ϒz v&TTRF4([K:\pDL 'ڛC(;x1h,cwZ5^7iDb/%IxcMD8RUXӎ5XD*jY^'őMt$"D>#g\"3FsZI(oDHI"b6'T" ?:FUdg)T QD&$)pH )`Ʒ)H!db>Geڏl#Bd_~ @R?Ii$M:`mr;QD | -H'#G 6R6ؒsLPT޽U6 ?LDE.mnT$Cjo[tQ?ʁn+ rw}|ÕoOGqQj|>_Cͫk/\;.\[!t\B75x#x/G_ͬ\Tqs@~ .߄r kysBU7qa^Bd}KGEݏ1w u75'`z{`?|׾Z#K(F.hVHwY87W~X6vc򻟂{90J&6,b`:h~?ؚl1hq>-X|Ɓnyn03WXñ,ͯD. f୿8G$A*b~zPwچ?~CO; `yf[ɇ*'Ç- BDkp(y*ny)7ˋ: .$Qyfuj 2$2DB WUg(uV9!:li.Im21!"YD:\4MTbzX>mYKubZ'5 ҉%Nڼ#5xlk>\ &QZF3$I$-Id≸/]yr~~\2[TDI*GV&*1}LTGT1D\UH2tYS{1I$rP5QL4EWoW: 7s*Xu@[39/Eb8H3Lw2aQ::BGe% NԁY!Z"hZ+y;)NQedj <'|w)yU!Xa9j\u(vg}b[݈n}';ϵ^ s1N=A\j\r7BPr'0NG!8((:]+ /p3oNcPB(_^<,Xa3X9 1[𘇕kПı8S969 >`u}98{`7j/=<^VRdlGn.d6]g`nuG A1"(å@W5=`Y ,KgC3Iß *?/z('R˲Y\2_Rd0NV`G.Gg7>l8@_Fʚ" ջ DUT2v,]e: hp.< dg!*qlQƸsn$3:LuYZ]E q(/8I[%SZ$LTPYư|QDMcj M+Ȗ9:5mGL4maʟD KrI%-k#!đځ<(MF%bs)h}#BD8JfJ4Q),nT"DLW)RT*'D0`&3:G,"J]U$+%衲QL*u^:FaD$l}"ȁtvJ(/IuGGGۂKZOoYd|fZ "evj9h;͌H0P;I iW%e0؃` kڔ'O} TUP \kdh`^b2iR\||/XDg%^?~ yxe%ܶ-o=!-:c8Q:(j#3E)( auغB G_huyLmzPlUqMos `GQ=w,@?fZs'VCP #, .ӍE+W'}Bf(^_ZpL|q|Oݍ}2 l؊KW\ w+Ӎ| ϞzLY5: XO:d)%6 6A7t9X[`hc`Y>K{b"k v7hg -m dfv29&\rVI;-%n\WNUa#PN!#*!77G=L6ӎW/  t@Z#Y dБGt&<*G܇ND&tj,52G~oŒYe5$U#/vHmO!{.OIbn̴MH&iBHDI&r ΪE YhDm#);b/[wRtvrcZ[c>y(&kӓNoaݦ5g^<~wތ/#MP4 zdlGvnbO/}ku0a|wWX'`{Y:lhj%~p7^(.d/BNoY6xn\;Nj~մg 0˳\q$S;"X%X'xjn˳DIF1[GvCp,VW#c夾 C*e7gvWyZo5UlLyU. v*X`f9@(rAfE@s]`m8hR' ;3qo`ȟ3TX$G%`1wQfjv|3V*O<ӛH1:q|<*[e=R^8L"MR/iUݖcrl)?mU.Z|VY z-+t88i;3qi|;^ d(\fvVh&LrqTw{nP6 E+21}囨%dU=o@29Z%|`X&ܟӸdha` _{+?m0CGn뮙 9O6}x֟-p ~a8 ˺Vѣsk(?pVmCfp3Pe7v# !vÛg8;8TaA. ~~ǝ(Np`s5W* krlQoۅ)˷澈C3X^\ /8:|AmF*ph ,DMqn :0UGon @0~ Oؙ$NWDZ6^-4 x%O<ԑ7`Dzj!FN H땅w_Oˮ`aRy-ϒEk!DA>J+r,.P*q6a!c吷 `)ߝ>1_v6qe/iB^֥f:&{V*&NLMb :;sl;4[ęuƵi>?&yUv \&^ţR'q7%1J5f7"$}+ DBL"TMTYD$iI>:%~)v2D7suqFl#*n9-GBB;XR$S~E#BI)qxnz}4i5IĿQY kSye񿊘"*9]UnKMAjI[wY;S9T7J[$-O[zIrVU˝խ#$ZrLNU'bۚ5}v^SpC x۶ Bʼnhº몲iw2IzIRKE'=$4H\:&Z4LDd?ÀsS+Jæ6UjZQ߿?^#c( S֍Rw;gaJW . Ǟ`eZdlDa1gpz7t5[(6`}b9(^6q:G?m;gmG"U#A@=]x#` FM\j%?ܶzmR{'_gQ\5زd{@l>rp`t/&kNG}p=bO;DH1X81?'gM')sW>x63W8Q? Bmp ; K )=lQ3:_5ctՐ$!ۜ,s+O"k AAp0.6LbULr>rď1U692dq!p"Fd"ID4Q)YZ-$=$RY%5l#㶴&Hkn5qH.IuA$zɊ' e  bHt=G}~wx`<6oތ-[sdm9/ l'*~F^\d\G\P c< W݁ܦkJ29P<Հj' 4J :g1v2w\XNC7X6ېn#N5M1I*,ᢩ%$*'}i3j(ŋ\DB4DQ4NS=9h];'qDe'It %o$2G$oe)ndr*MwE+,EI*pg<Exl˞~ie,Q9iAe#M#:YDW4iC0!TD8u.LdR[V3i$I4*2ND̯͉eJ'&b"M(RGm9pze8уDZlTrp8^h@|><0pы#FsL2.C!I'M49Ht"wdE $rjk]MU=OEZGCձ4Mdƃ<裰, #-ΐvᦛnBV×E<쳰mߺ%@ o &q q =܃O<-0ddijug_x>>__b_s [S1A]87X z;qQ?^p9 w=#s>o#WHtT6*$Ҿzh>V+I%J\ه7 pA:jg{uGx+#/3FvUWδ}3r߅t=2kv;˸01\Qgaܰ,K`yCɹ B EX} 3ب -לߙ1*o5Gq#zٶfVH'2ѣiuqGY}e#qMy\gmR@r"bI8M_/UJ&IvUh%X,qt%r2' Jڍ|=h*I %N$Dg#-r,2墹Fp&eh2j 8gbD2mD&Z3t69:k$2I8$I\}a[1 RWUM G̫R1Q&N}- FDLQL|"]4*8QEiHUpp.=0J]Yo/UCI.újr b%m8xS0ayI@' ThZL툷IvHvjZaM>:R ic՗is62rVQ/V6}f'/81ZOp ~hC'?tǰ I?˿OPkp)Ò%`*+ŝxz_7ٍħ>)/y=f ɃfpY@(8xG>NVR8+LYtrpgf|7hy'J:lm*P V2a AmC~`2~-\# 3T]G#8v(>wA1Mu|~݅ˀ:Y^\m[p}12q &>3X-dbp] ݧkzY"ԡѿoxK%)>$H#ۑTj+%ǘ4!iWgz\˙>V‰T c3hfEGId≸,[D8咸"$kfimqt}.(05O;E!Nh~X$"D=\ '|A$Fe? KYa$IDίZ'_E4Hdk1]Ϋ+C" L[%*Bz liQ]xgp{ޔ^]~9OZ jx5=3RCP[9q4Ϛ6xqL vS-uT *=WSӑІ̜Wt&J躢ӜKH8xMOMG՝m }C});>@_72,[:EҘ 'ժ ]-C}vt8v\>{?qX~~ju`|,uذe[936Ӄ(Ųc'+ ژgl"!`k`3P>iLY;;5GAiy Jqc.Ԏ !"^V(gg<` W@2/Exۓ+g!qgz\Qv&O0pPX*oDo!վ"lqlWb WUi$4٬Lםq&GLtJ_U呭ot G^"c,h\gmt"; ^%ӝLyäS&rItD2$R>-iL2IrIq"TuRه!tQD&~$Vm-SLH#}TD&~Dg>DV0ϑ?%8U$hE|M*X4zsC@ lE%`, ֭C.<|t10ƔPR0Q |.@D XėujDLt4G蜨mi_t\('Qn?UVa韙&+@w ciq{ƀjD0guQ?N< wxp4qAuڋ>>~ly9o|˿˱uZsJ0-4&b3yA vxgNs3ubYcPccdE"f`='CG=̽:<0sgF0~u9EOό -<[˘n㍭Nm:6 #>h'*{t % k);:N1\4Sh]dy8/"(457j,[ac_qY$4SاR̴}KL@I:ёPH%iڰNMG&HDDe;t"KlѥGtkځ8oDZ^~&j~I'Z/C&L?'*J;|ATO+TMt*IiDZb&gwˠC$YDi"1$N=$.]n]b"IDE8d])Q]1X1c9k[qb,G6lBGK5d#Y[ LT8CP-ܒjgV$Rz4U RГhH>Nci.Z{)%Iq=hTq^rM} Y0h[<+fdgÿb\#>o}7݋{ =}X8v;P7,|[})PB\?#c[}8x`l9z &XZ\C3ba|=l`p0sCY < ۞3tg@9&qAIt?GmWˣQ 3Xv<;͊ ~7F?)DyMx-.K}'^&;m<?M߽X4YWK7bh\bǛg{]x' /`MҵxMd```p 0y+eJ61& s(K Gf6xx}2.g F5`!Œ>75SV1sN$8bz*zڲKI LXRd@uP}|)*}UoMR[ORĐ #q8*h,VE#pUJqmFuY$M^|^\|t񺪬sMTLBBbT&DBʴH""oIJTۨeUCVb|2Cw>M K8vd{Bdu@qQMBK~yP4ٵcp!o8Ǩ;O>Gv>,bid[ 1fAMP'@}c`Q~i뚷y-}-l[4HRV)YQ-QF&iDr.``:ŎKÕ5JI1X"5 y,[G|)}PR-"ʖEUL"[x8G$-Jd2IzIǛտ&7r(mLXF&$:HLlGʄCeJ\%!hC?K#!$G0MX GyP)GtFgV$ c00 &3J@*M$b>Nv93:n =@uuY^'ͺ8J{Au+ 6.Mg">`[! 8NbV\+q2~ey/% NO0ؖIݓ?R0J"WVx #8"ME]0)&m X%jMrEB INl`{ F*Nq ks,&4T8:L% [o rT2vuH/ءXqm`~WqcR3^;t!O)|8G ⁉ =Vo=ն<ظv $$R/u%IU"1XHbtf;!bZB+< "S>mu:t!Ȭ9%rll a F(n&=򅂲__ß8ꮇ| &r````pvڰpP4jɞ93(%ppE] rB%O]9rv>T %o>EΜvn+@/d0&jgR f3Hו0'-.jq)Oy"Eca*N<`gQ(pV\ VADO?ЋKb(Xٌu 1Srb^eO#_tR:7[Y+mҩO#aӤR"4d&wlfoZ%1e(4 f 'V93J$R-QOd%G>i>AE QNd5 rYXH""DđKhʇOZr EqDT1 ~D2E<)-j"Idz$Т29j&i ?TvHDё@t*rJIe&6 $̓$AAD˯*W$j'XHXIT)/*">u8J*#.0BD1MT0q,(_B^OWo|W5V+5E6,-|L j`,wܑjǿ$*e0:L02ee!Ȫd%J)-$nyb;=Ѷ}Jmksur\[/Rض{fgTρPJca,+/O,X,¶DƸ rΐ(8] *>ݧ~ÉE8.í 0a:,8\xl>XճfLgW±2WƟmE  k=\v \:`</S~ñFsSX2vrΪ5Z9Xa| n8WGfzE;@E3s߆Űc!3QX$mLc"MVqFDТӨX4>$LhŎ#Kj<~|U SN}2zIlDFPJ:CF<-$8KMq $"D$Di}N2kҴ/$"ITQL&NDf&D_v05&ITRo~w?ZLf q&2DGh"ETu*):;4ه9)T4* b_gˈ[n7_6!rxz8ǎ󼔃!K.+_U`E*8kqOxf"M(ޱV;X(Yx2aT, bC+)|^q|Ug%rM^ pC%Wa {Gx}<{Q8A= Xs:_WuEKvbG@,aVRbU3sT^ g)׽ ͨߑf@Õ+vsf`pa&$80Đhp~/nlLpu !ODV7t"WT*/*&,\eΝĨLo<GWԛ*A,@@A@[(I˾$}j܎ƟuUSFv92D^/ir>* k%["7-sA.`>lVa,hR( K)ްĉ![1T?!KڵQYuV5_9][eţ̈́ b,r`*Ő*@tD8҉\,^GL-K"U9QFdbH۪\@$iOD2t`L&i,Y1]!"Q* [U7^+Ťlww7~~ ?8J/puw0s~ښ ">~b U\p7V/ypՓ1AGH,Q)DV9o}{ifAoHz=NqAQKV#q]X%Zis73 ; svPBP,ssa⋝?/, ]]]S13n````0;;EM.Vtƚ7" Q ~ 60BA2!{ `5˶)բ,Bj^u1Q@, Pܾs fh3<3$cD *6:IyVYZ\|T68 Lbo{cOb$Dg҈h6~)ϨU+#eC$TM:*{@O.э%!`!I.{CE6#"D#bitz,MPnC0e}K"I[V7I("DE$il"sDTۉyueyTv92DGGvQYȿ `! $*bH\Yb~n"\n9e6"đv)*MFG&NM tTFɣ<Ƕ[R+//Gp'DZܱ)A6u'I|{E|DPHn~=> h >NڐXqq۷CTVAZ֥j{ӊ]kr/=cky)w\W9A{Ǒ*mtwl/X_hcmNY 300000hXpPJW2 ;^7   X_趁: I  FV9gﴏ}J7cyתNw1zyXCa3`vOG*bI~9_T2F_$ZknEo)dhyҫ) IïA `0ܤ:8cuPb5knÊ<C)1DwbPop$U^M 3'H@3DM j/]Eb/ *#\P/!P+8pW4܌ fS)ۋѦZq=|&qJ|XX9pȱl\b.tFeg,z2(yÀXݳ]B&c}z7Okx"S?x;ޡ>nKM, $2DG.%Q>M*b ʎ$yVJ4}$NUާ%MQ2ey~X| XO<;sdlUK8)nGset300000KГEwPa%܇cepp/ ?zPC0u&'lYy#Vvrv7c+h@~ nZzۇ#╛< .(uP3X,) \T*ÆX߻G&bKexK`18{pS@~;.X%`<l^D~\F-AӬY$<#IbU_ 6ɊEERIK<$)B>M4QɰeyJTs+ZDt1_-QM<Ǐ!qD+בKdu_u#bJDT0QMt'MC8I9wt$2T BBiKHy vCQ"D6:HDYD&3P)EN\Lt1- DEB1{IQq$N}DN˛FD&}H 2y$xʣS3 #b4:z$Y2m"mh{l߄L6W]uP*w'9Bf"*:W1V`0a'_mnUzc %I""rIDy30x6 d.'R9E~m0 D#U&*G61$!W.LdBʪG\d%$(ĩ,oT&|:U]<ӪȒj*O?&G rӃDNe+pWT|w`?p9}肶ˡKcH-;vX~}r~r dPs~H&a"^fuQ9D [;jDIPѩ$ͺ%R}rބ^ub{ο -1_V(s%Y1000000HBrv9;/7`N+g ?8+jEۈS}p;1cr WTk귎 3nI &rzܾtA> U9HDZH"[:9n U\>^z}@ټ(%c5Np ````````````````0g0Bc qf3LTIU&oޜ`Ӵ^-G <\Y2XxUN=G.[5_XQu "i"$=Ьb->kR~Z?K;P"~'AqO^&'.\qGV84Eʘ %9JHrEQ$>g&YۨH!bJEQ!`p`& I2 D&|Ȅ(L"ёLdy^B>*HNeg"noN´R,*r6;2Ɂ P]=8/|+8t>Ύ?L'u|nx|[֋]yI}W@-[8es~!}P 5DÉTLDuPXA@LDTe= /p?J .?f =9T&jy!.j02A`ac,e!Ap"5JK*1+8DSlz"J"nF9ᴺk/|KhGs<DܧMQ;G,[;"G#2DNt %5ld j@Gl%N; $IQD6+#NF>T.Źǰ6>$!Y!߶ei  PX<"KĴ *DU_F*b&g`TyDN"#2)e8"5.DeʿU۴p RLFN&.g bU΃_};-J)~W~===?#OLceZ`7@:gu@ >qb`]\wbۅ.:Y]s"DY-NuJ68"u:o8ֲu0VXn|M)kF|c9/7>O?__;|3@````````````````0 C.g!a9sL:VY&j7ȿ#AI:|Q:D[)rWT3SVri!Dr&J|"E^"˲z老4`nF!O俪l"|]f$V yU$)d𙇺7owݴ֭L})xޅukoWaß#~yy/.-d1y@ `O RcxO4~~˖-K]}å-{t~jIo\'[QUW{; P &+7,Mkk6vBɠ8uI8bjB(+WY10000000000000X0泍^"iƭk^&I%D_:K kLS8iQw%KlQz41/_G,QdTAjӨwd"tăK;M2O:-ZpĿI8qe5UL@Ͽ-#QHQY)k#CdI}|PE8hQ~ߤj(D68OD4&5*oR.KN"D:qHuDTOT%N;)`a&Y}DNS)6*(Z"Irmd&Y$R6Q)۶>j>]g# BsX?%;|=mn}C{Q|g'5[`eƆ)kaw`⳧'\ń}=oGPhqݯ=1b&0RSV#$XFqWB%&yu&a~L寿lL;I ݍ;wLR {yP9q9k```````````````pK2 c)CJD& $REH@* AOT!ZP"Zh~QwW-;7#CE^HM>TNDgI#HFoj$ZjR[""qD$K8{jl}#_3vI"*Uvme7Us" Pb5*:񾐗Ē\D҇JDeg#)Clp`&1PB#e%yDUDѐS&3U8QN:)J(3|YSP"@FGx_n~V4^ğ~cwriڵ'?}? d;]qKo?kl8$d s>n7&K\X=5+. \uUm?|2 iI%̡#6:2+; D!H[UXf^j[ۮ0/sy77³[c8c$/,E ^ssᢋ.-odd +T?6Z,*ο:KIdTG*EcjjZ$Wt18呄)K,,av5]bhX$,Ă8HQ)lҲo0%IڈLZJU#rG&DioLk[#TrUH#M& $~O/A8#7YByDHy$ZשrMYɧRQIDND.,<I Gt$r*h{T/j? NDn+nMIi**kѽ z}M)^y >W{?3mO&;vt|_ƙ,NK[+~BR(MB呈p uk8ʌ ;V 3^[_tt^xe|l.I{e{`j$WΫ>bGP:$ zAL\~(%0 kH96'D<Bqsd2guWs|GJǰeflܸ1N~'GZwgP~Bə-;&ڤ4 ѳLLtjYCeZo:KUlr"b.ŖspJ=| dđDrJD%ʾdC)U*!Z~d%lpXd8R^:nQTHg?W=?ZmDN:?%"u +"DE2Ir*_yd,'H dL#p %2 E.3n}EL.$z`jLEtdvqdzDT,Q1fuV9: 1=ceЛC>K?n򹶏opp__'?I{}8t*2~T*zl WYb}Ɗn"OJZE8\18XԼolݺwmxߍl6uz/3 r|UꀅŒLv8q%:9Ė΅T^\pqewݖZjEXt) _~;6>!6a OWx=CqAM7jBl6G8xw0O7x 4h4N ps. zPB,KRPJ:N$\jSo:@D,Qʑϱ|q⮩|$XD.# [ZlRYDҢ:Qf.Gb"'YD͍"ĥg%LbTL $i TKnzFLSY騶˪% $Lʯ#QD3 %"DG20*?@]Jw c؉}Q~X,tt-׭[7< Oލ{b߾}]nl,EEB>&5s \0CoO6\x!v؁\=w ! >_R^8t}$H$Zק fndrI>Qz$rE:3zdh,_#ɠSNwJ=cr| ;[)l`jN;7qsj8=F.z{{Q9g-7d { @`QO?mLq밲{uŊz.,ң%Sݚgy~,P.̪HeV۬%=DBj1i-.kDLK.i4$Kt⸵MbFrIAOq~tc;AwOwmvZaxG‹/bطoN8߲4} 1dYY7m–͛}v\q~3W_k.1 [&w\V#"ieTlRu+--׭pt/+<Rp^+xHnbs^`Fl BA]Vk_:xpnc [/^92`uux=Oqt }ZeЄs8.XM3jmY'GP^%}رc,K^s렛EPA`،׃.W%x{@ ʼnc~-عJ=Ѕ!``Bwl,#MMO-P.Ux pU92Ӈ`iT1;9i<$Z04ֺ %(S(N?k]\*E,Ԣ`c$F2^I ƕ*ũЪ%jqۺ4hT$ d,r%tYD\I#*kƘXv_hpgQđKKT08 DBq`۲tJv$Sx~mD(#IEQ'zH~H'b$tJ3; VVD.JW)'*գPGe?2iDGD)y:8X]g#nhbQ AO$^8=Q/~]Xvp>î]k.u<O3Gչ)c6 xTeqNSpU[V`hM?n]ޡt+de@A6e8?$}pާ~ -219R1r| G_>OK'](7JV-(+@M.rqr }<)%v?I&iU/EDG.I4qdoQ!=XD"UNrG-T|i)63Q5=s"y$j qy&\g5p@%IytPDQwTЩ4X0@&7oUۺH\63;:06)ަpۦmRn4e޶6 Il㘙wǬv5g%]}gFGGG၏M *;"^NZ[ fWxٽJo<~i*H TTA]C3ȚaoO|r?=rN' fϞٳ{r--- lIP0NVw?ƨ)H/TU U8W̨IR Ĵ(PqQP*3<ի8=c$3FPU5)mi8NБ,h:B3[@!Chp t{>qx .ƏZ6Zim>McQGqI'3uO\jar(B&L#V\RB}?jQcINd?c-¦eԿd-8B&x8.D,BNxgYdIY$0Xp%>(IY'N?>n5,/I GB À V O?+uQi F$4bcf|7U/b@aP{*QQDQ)(mF֌0qB;q򿳾u5L;x6EEQDEwPIy&28]qԙSTG"h]!@7tZ1 FO1Fw[_ӷH#(}C&53s=`C6 d1)fO5bq4cs*Xl[WZ;<;]xsOPLj&~K=,\`AU\.QJ9~^/D*S4* f͛Y2P|Czyr*>f*S xr TfjW$hYo/?W:3ҡ?P?FU;V\ɢŋh?t='k_nH۝ߥϓ4iYjE%w7B` OݙEjI8vd^ ϐ]vfƨ ָq3#Nq7O<'@mMMot4Cñ~ kS1\Ҙ֯oC&9{kϴU>2a?|֮]r9_n_b愢j0rzӖ_ XfC;~+1" =Ui֍~x۹};]+u?3'"g`^QDQaukغxs"Lm/c 'O=Ȏ"("('k6wrH:9 QUKdx!r$~/ipv>JIdTQ?\z~[K67t绰-kr'~闝WMCc>%18o|N2]Ɗ&w\*MX-s Z: o2 tg\$s>ptSO7 IjxWh k^ڵ;K'1𢒉Zy! t>sr+-"I:w\1|#IO(ưqt>p)l|[B9&1(.v{ k_}u|kFgS};+~:^??gx_|P@EN%Q:wvӹ{W.\/_N<'dHGG'/,1xW̜(9`#%#%N>5tXVcvxvNK$W0A:r|[C[li}ggTC:A|F|'tc9}54Mc\s0&.\K.ڧ!ā=RJlǢM`;65 iϛi:Oģkp3vh1&ok*-[^9]DtખTj~qqB%^{&Q˶=Q!oM N*gx?yE7=c䄭pb?z/P~zk]G-r~B= 08-plouNFgGN҉bI(` x8*PRiZ%7rPI2^pܲ z@՞Ǜ/4Or+bIܠ.'~j&x [Ȑ53H;O_ѧ/fHeyVn}l^ J" pߺD[ k@Ujc~2wPZ!oeK*DهάH.6NC:AbD" M_ϟm֮#.2#B v&$6"vԝQf |V1-m[.j/",B$6X;z 8]m$H_`L|V,`yql\g\7b"("(\!CW DZ`A8£8섃'NG"qrY2=vM=QF=cc ]E`Ԥru?*J5wriq>uYbRS/S-QӂЉx'~8㄂%N~V7BqpU**~p;ߪe8xM}A)aJ%G7{И7ݲЈ&D2=ؽ x[~IX ĝz:K[7=rFS? S9Q?yu;mKm(cS.]F@ 5wzW .xCx%ǻLiPwxT .:[@s=g}qtq=4ֶ8]mH"1κ H#m-$>`a㩑[g]d¬L:pl=.{ 6 {>w?L"([E]ęg7ymNWWv* R)jjj9b38{5o`JҿaH"5tgԟȿ Ng SضKгԞ鉌" %V1u|Gxzml_Iw;r1("(gòMrfBWop)x?ڇQ 0b:=OògW7Ɩ} (\nx<]N vj{Œ?a.ǝ{y_ g4oi^ՇMܓOLp}J0eF CKA9 Pz )&*H9A9}#MzzW A$Ay~wz\}z$A0@lrxpi;$.ˆn kST5qӋVJTDj?{tMNj~ HHRu#R1;uh ,T$(T|5=0Փer^E&iAA`:/>~â_g%K҇C|Ah42׀O9w~ֿ6/ܶ ;c9ađVQ[͠v8'[б >~6\K|aB:iPs?Mr+<|scڴikoԃ'ɷO@~HeT#> 0e=蟞a룊R=',d1̠ႫMG׳7c܀k#ˆE69Q z,x-'L:1xvl^N,"L"("!cә [댟1K?u>36lHק8#}tl|sh쮂;vC&mҕ$ge{Jϟ…;L0a51\{!__-Uq%~I cj  ^Wh8^ {~4QN* ?^ l)( JoPeZvQ4O w{+vwmu(5tqqlǮ.`5U)ě/TQTu)T;?P~D5i(0H N^ *CU> QUKdx!r$~/i,pnJId.秠QEN}_kMs' #[y3m˛ٺl'*$F#UiL#X"qDzdql]8Cgs7;7cW' صYy޸*QZ!pJ`vOmS/{e_Nw+B7q@בf}/QABB+dq="j 0 2J#EZvMn݌O>~E\|nUbŠHDĽ>Mg!ۣӾʟ3&űSrbE!9"?[R(!^q,Dcrs;kv-#"("(Rd t;{p;8c;m[ioߎeYl6[ՋFK3#GH$SW`㧦ⷝje7ARua*i.%s;i>㧎ح['xZc;cn[E -maĊp 4 a,d{*Fղ7Z׏$98k^ܲS9]m-t:_W>PSމ514v^Y dҐj :s¯qq߾NЎ,1zauT"n@h̤kɌovE;'s"yMLf\("(bH#:mdLo?˰э|2y椽Zy&^[ŋh"vA&P(P(RfmmLN8X MH&tqcraqra1|=n#npE1{h]4{0lǦ=V;a=4 n6k֬immeE؎ hnnF7U-9b'N '2e̞͸q=Yz=a@ᒾr^CJzS4 qmmJݣx_,k (9~QRUo ~TDU/ w?ě/oF0`֨H`)DDSN(vۖJ hDMR=OuA$~(Ag*1@*,a8e*JJI2%Ս|w|w_^oE[TUCZ?DWQ;@$hzvdm_zdOU1Vìq;oR-E`J*&{,RTE2sL=\~ӟNjH`K8H o&O>4X Cי:u*r vs!@HIǃyŏ] nWR1H ޾v9çsEǑL%뫽W^}ŋv:re H$eZl%;o7w,eec:B 00diӦ`\ H$bpN &4q;֖RIu(j TPxMR3 X { qYxia}AIPi7M+Q틼iAPIL8yՄ^rvwЍjzQʳ|?v8n19j۸f{}x5ZTa&Q NDI~pdY)yUew%jI Qe?x. 5o'H$H=C^iUx$l~:<~ԫ7߯b*Q2{Ž4F]))xo[i%i&d*>'S'ظiw}7Fi8 {lnho#ղۿMa"r˞we-ZܛOcm]Ih # B>W%gIMO~$@:YFΎj{"+ ddhtp,gzW]̻>{7#f RJ۲,,>R-b =kv_GXQDEQDEQD+di˶Sq|)SjIP^|{'~LbK#A 0 3 EqpZBG1`dLNF[[tKI&xgckX%5y5k1RԸFm͚ŶIPcɘmb,]s&Ngyihllm%b9qpb/ZG:t;c4r5rБs؋;mΝ;yYp!K.q qH"#FOG7#Չ#)+ВuŗwQџHZѱ,3W@K۶ItO>O??aÆ`|{ᛞⅻ_-ڟ_90E_IZL: I68%%B_eXfBIPZRR5?ۜ dY} ;lvv2൲qӽ>}v/p(.P \)e≟;9f ( PG:ߧZ^V8r2܈2zxU$(+S>߼0+> 7K?FT+/;YrjD%`ˁ&aa:}۫jM M*Q4 %"OJc ^?\OU8 *}[QT+)o[͂Y3f _زy3*,a4gSS8131FOa)Nꗨij{Sq+[qWն Fj #Uuh:?][G?!SNx4I7$0;م&I֑-d2XY\nIY8N>4D]wılaǺ]*)*quWKTrj&*@N%^ZQjM+^Pu,sBC,sԴ0ՒPjeQUEv|q1K7rEkw-p\7% .%qvyai!~Pwy?5 `J',"E0)^#S*QQ}YW"%eOzIPDRTW7n@)5VQDol)Y ӯRPjBqӊ>ZxX8V=ajo6W$ o~m[ h/Ǵƶ ;w᯾D"Q>=g\s gضm;чOːAaYl@&gGa Xm-~3nxܚW) 4ظuS0ȼo ηoc=uR5mlkŻFא`;6]M_<'=e{geĸ k]фk-m`KkyH$("("ʭ:t@Kv:ӒE =6+@:F0slұ}a9]2޴)N:Nc_v9$NSL2:9[`1!1;a0-QIBP ZRV@(Y)ȞeގAc y$ G&9.I\r$/i81/"O>$'MK.xG.X[c3r0vݝtz4d=ۆizu(y7v[neҥ,\;3V8X Br~Q?m$DQ=]{‡ g:zd ڰ##rzQd!2`4h$83iںs m+ȭ| J*B:6?q'MK/Nc޼y{DA`Q31a\';7DrKR3 z7,&O8Ḗ8‡ S0)~VH_ $Q!j ?!)XqR2I<{9ru3w?[kENU%Uś)D#L6 uY 񪖄T Tkӿ3V;AH]NU))UtTdw-s\g>J tU+/~R$HRK1X6H@]N$M*1=NCLk߫O.N.F參SN9/\}5_t=~FhN-IfCчMjێuu:ma_c-86OE6iUˆcnXBEw}^|qU^S=[=tMGRK;^k9|iְGţ>=˽Kww7z$͖̉|~d 'SBASEWEAJu$iMPkh=/LLi.ج%N"ggs _^Ȼn>oM[m*;ؠJ#V2xNwL2حn#>ʝw#שI8hژ9#FNB1C:vڱ@ImBm#|Fl\bS#bIZgɭx@%H95)w?~{9r) 6l7ma|ws/a+{r ء/K-|k 긎d%*L"+rIv'jg%^kFQ  EM*6 R>ٽLx @1R!DN2=e7{w-r4x xϰNT# QA { D%X+J^DI?J)A*dV7hMt _U|a69qTͧIҮ"FFy~V]PЉ7_9~`Vj~b.*1$graWn*(<%MFd=ٶc;eќzщU^q啬߰_X,i ƸY`\׎V;Č0.eɼ| fV+Zq]ɯxDE|AxY@Fu+k:ڲwD2Yz[r=IEߢ"("( ۻЖov>7TgBd .=Z`9Omzn־Rz 7RH}^Ә4[iϵkq+G"фN\KTd;ZAIBBo75c2%pɁ}_x' M{d?<ôohh444j]l˨Ul޷`BLGXwXx9kFNP3b$\_W<䓼+`|4+u nkWZEM{ᔋO@zf;筷SO65qDmăIa2DƁ=D:f@i# Ym!#>XD{b-+Q¶-n?yhB?xrf6p# Y2]zb{_\-|Y)U/{@ }PS2MDī\Z$a JM؂8$~J?)j$u{PsY3zU!wGEպU#q0eO˻ *erTLTdwmtHLm<*]VJeR"0"o?0{5= T$L$DDfV:^?UFWk\R|0W4 ~J0RiS-RMH֠@6v4t4Q_ݯow;xz*~:n\e%jaK:Ʋ t{:(o݌69̪[|3lذu \V;$52݇@nsВ 57!07I~"%6v&q՛U7prtIL3<5qu[s,*[6ўoGǣgF0n9eZznOl|AJ[:Lń)Z I37پ|>Ocǜy;WEhB0 ęŊ7ؕ6wnp>p佟=`˱jJ~r=}vTd0&x:%9 㕮|o+ԦhAJ/\k 9 c1[8"#`:m!ȖMªhJ' _M'_0Q#1G]Eǁɷ*>HcQDEQD1d9'?DsvgaC]uc3p3H.ۑ6Y+C.=bZx}Kdn@")GOHE0C=42X^lUsѬ1۱.B-]za#gZۢahYEeQ8-ڽ)%fИFS)ʡ -L,`8b챻鐹:6d1v.ٰap?8Xѱ]M50tSYѢv(<tI7rȱA0M~\}4y7/7ÖoCuЙ(;kfɇ.qo͛6a;6Fl\Nt}EB}6,hcf 1O1,͛7_'z~qQ-8㧓s+z6H^(޻Œ n?%/\7^T ?\U,.^W=x/ yo]]NTtV8,O x?Qxo&{z'8 TT/TÛ!!^?{54%{=킁5˩Ui*A ?Kj-rHJ?$Fts[PJ"mpԴ}G|,^R\ߗ/hH5Җi=?|*^p׭?!v1b23tH:se]G!MEͧQM9X޵tbKx%/|Ŷ; wBߡcЕ_"(b=rVBW?P cvȷQ 4L5(~ ʣt;ꂍxi37Ԋtod ]~U:]YӺ\ &)Nx?+I':qbLb|? 7k3:2.`I: a֟ \ f\Rkmll6Y3vP7ۯk/o~ݛHjǢ m+iDJIg.I32j/~ ~G64&'c|xT=QGΑo q1 3DtK gF\Zd?eY/,\q÷I'qT=e[)}3,֒ӓ/;.? ]׫ިg}x7M,"1pjO؄9BeO" NWaвdߟougj8B[ټr[ﺥ(߇MW"d@K\LU3 S.4 %A%S\}$WUùsЌS\Þ(ǴM:rm%ϏG+UR8|-|?7.E;4[cg" 9n2V Ø{2FMGftQ^p?;Bt#ih,\|C<.>Y_8dM֊}_}/p)Rr8:էZKTuZ4_;3YqciG:<Z;ѽuY޼7w-Җyi۳V.]Y۶][ؕNgרJ%Eq{̼y`w;]BI(^)'=jj 6Klp4!EwV1\.U %5ϛB*پ8LBO)$,H._w~ )j' ~:nz"Q-VPJJ-w砏MN{UKT?EorU*,aDP;ȼ*%Ait|)8RUwbVtԢߴߏvUVTo{{e%p٧4/5o̜\}n`-D Yz dKQ$gewbq~DYݤm3<9mٺӞk!ӆ>֨k1vdHgT͸IC%zm]y}sdn8xԑ%^#gβ ]?v&:heXo|<88b MhB 9#+eF51 [r$I[G\{-7l_"T֩O+呛wJLlǦ5ӌe]M=}r5ڵk_e4HN_@!1pl'C$Mcw9 VcBHa-z{VVX>)j>TeFӘn9~}OrIR:& @mD{ϠITuo TbtN=s%n]+$rwl4K)i ,TJo\ L~F>To^?@D J7J^DI @T? K*7oNʩ%~˪%A72A &~@{i /V(yUhv6MwT$W2q+ux}v7}m? OV9~*#U o8h0ʣRq ʑJ#/o}۱)$3U QqT~lڴ7-vkt~6'y /݅t \wcK#7=Ŧ[Je\yzFpIQDEC=1}šȵY Sw.8`t"F#5^djlXW\H.ր v1>a&~o_H 4Z(mhB%qu5mV2v7S3\{Y| R:8 }Ȉi1^ f41aC7p$`.Бk/I;촃9\%Kbk72)1 wdnjW 1c%spzMw7 2Yp_/}%KОmw4n/ںڪڱ};߸:n?Hc ϥ+dۇ=ʱLɓ" *;^]iom_"[6o_jJ9?&- n.ʩ`S(2 xUKzf}U+LDJ V.ZsʹvYh'geq(X`YP7H`X*ylb+!!ȰHFG3"5dS(X+LJSjᓰqF*бǵu85:b/n {ز,F}z Zd.%DΑhSQGluTDAT$, '&L7Z2j }*&¦@ ?P[r*q)x+x z]N^Aj&a`GXqXЪS )WQ.磈QN>п1C64Sj5Rvlɟ{ U0eds|^{i,ǿH)11 sZV}!x|@ek|⪫xs2FL'z|#֧9;bK)s$c:W O1BtV)1Mx#dи3gL=o?U|3g|93[vbUm6qǝwJ0 N5 .FēB6oEaAGb>+uI~_b&7CZ3bͼK}OɤtR=N鳹TMA%A8AH|GJS] v-ؙNGم@ބ|R ISJfN h,B%MoW{0mhnu ljU7kX$Wh-4%3*=[Xy*S=a.\➛f&nQ(N\ĝMj&|MFV8~x,t\55RLm=`Re#PL{?UXR0$h]jTLY}Iʩ{},x-\ Q}>T ވ{zp8*Ge~VQ?Urj&~HwyB^]!@Kw3;^X=Az:,FlR&Iÿδ]9'&6+$ >- Вu׼J磿GM>pWVu^|y- dhjJNQ"(a9V N* H$c!BJ @"6;+L{2(3Mh,U-2@Sr8v? 2۰ 8.!h=}FۖyI=aaXj^u(8 MdccP[5 1q8 j+~(&H4%a;`KR_G?2I$8ӧo0|uk T'oʗ3'\|4xpU}x[lk# X"bG%s*톎/k^'~jD?^\M#s[{_A'yc4'~Pɩ*x_yܫiav=_ֿ$$:rm)Nʼn_UC/gxi]? ' yЩt>wdW3֕ 6brq~@;!d!0'>'Ӂ0Xa@wy&jnk_uW`L$K"(cQ ɐ7:ji>tEg"P륿.tZ-ACr1=1ؔ.t; Mӊߗ޶w:g.tZhaю)8t4y$f`K{cB.8ه0֯[g?"\$_89! SB Hk=o:D;3|>&4ϙK.ڳՆ=`2{6i϶N?d }L 6kG!ArT/t}YrP?}8rCo&X,VU]o>jq_. `i^DP*&*p~w#Ǒ9;K.HbE`Urr-8Ƒ)9HàNbEvқ@MI0q4ӯmΰo72~\/sN|IX~O;B uعd^_tPXQk%JǰZHp N!t<~WBc'?aҤI(s zR;[0("("(ޞzxL3'tt`y%Ps8#(AL3IH3v mrT8x1 fMڶMI1&Mb* 1i=JG|V2f6: = G:H)l ˲q"W_;G- en#V2X!4~9T;:5װ7uk\?q3S!h_{L.DUfK9db, c yI2&m >>zLO=-o|ޜgs2YGz$5ԟ)%{D)EűL?JXճW1k.es[ټ~iAI Acn7oxӂB%n`b9&+S?Hqؑ^'g6X[tC2Q|&8 f+gAQp7G&nr<3mV;_ck&}LY;R?c*:jJ; حg҅J^EqrO&^=*._ Jz2Qley '޴ Rˉb"L*(V4u7ݝgyNy%7 e0HΦoaZn&jD=Z(@R.@mrTDMWӊU!J\e:L\RP*"By~Az=)ݴ Oׅj(HJluzlRޱq';WGCSCxԩ|_dmX B1Ԟ>0#&<º1"ֳ9 F$Ҥ睁6~f C{v[ }DEQDEQDE1=acɺ046Uۧd&m˱AVA~¨q&j9ҵ!8Au=6xœC: # =@`[ǂD#I#M]1 Oo#SȔpL3,?> "cZ"ndN:N=tc=_(B`JւE픅ZmIiZsRrQ}ۙ'_(ӟ)Sp޹VTƄc9x_+nr,:seSisT4Pd*j5 [ 8sHGGąR\ # n H)YY帡NS: o+%~Њ\` )Q݈ #/:o"*S=mgYսnx掗z;J˞gM}x~ D69QDEQDEQDwB覑itndcZLm%sOmvіkMs-d ]fNLǢ`籥Ea;Ԏ!d]C7޹&j[BA{ Mh04t]$$1=! SIiFGB&m8o)%~t]8}@'~`$0tMiZ,gH`eK-ٴ J0x]cvRgV &×r;[X)`J%E ebYA~ݎÒd\wu̘1ٳ*S8NVXQq&8Өx=w}7_WI$u|ӐC҈c#[!R+*'둶5H D1`n]svN28F1@K7.`q&,{fr5:L- U܃,qL ?G[)Dkdi*dbY+]Atuvfc8v9lCGWZI\㧷,]-pboylK\lj{?wrZ_~r q(!`I߹]q!IHU'%Zb=Ї -o~d6=]P}j& ht-wZm wK"LffR?ReʆrB ~Rk~w!5J&G'.}9t訶3nZgQwlM{YκG Lcz-suzG]O8ʷR7ԧhϴ"{%FٗJ_qqFbZ6c!1؝(l\-bcge9hZ_ ˆu,Zsӛt>[t,C 1xා]a?d0"$("("(^ԦjI%ҘvumRHcB'5:Ԏ/t 446FY ohϵRsdW7X-7c3.`h1OٵGDc')DdXD#c |b;LkE}Zt0ґ:zW%5mp @\ʂZson["tX^iHǹ>A&X~RZ6ʭ: ;/l-x$ؚdel++s81}0{*, iLvx[iF/?FYyO}bv.НM0=rkŋs͵גJFqw UDq]8k^}[OA6h'M>尢z )%񛰚7:6FgRwG% Z%Ndw5m6Zn馪lɅ&8#x%teTNj«d$yjrZ8XtXU/bZ], ]NM'.6ih?%HHmXId൷4\+XY#_xLH0{whB 4m`h9Sl)>A2{UJմp3&?a۰tk[9l$)ݨ*%|~yLf} &M?ٷlR(xItM ݱ?uU~I,(>(e/_`RM#@ p~Q޼A+I  BM&*Tn<?XUVҽ˫j[T `$HĻ|u_k+g߈K+wNءS)]*dv>+y+G\r69:4a޴T,u&=q$phUo(k֮[nn_2i zXsNbm]Iabcmue"R,ssR p)';2) ?UPe?~kEEQDEQDE۲1-vCۯn;!mdhBcXj2CP/D=42fBtc9&۬Mj um&kF˾B4gwH甩g#+^ȷy fHƓ~uَ3ݷ'ϡ'̯ZkBjy:9d[I!Xg9[++KbzEnSrs[[@{ƍw4w]laSOr2Vȳm- xOm$kU HB, _?)_}Ee|\^o͛[N_FG__u^Yww7_Zv"fh$:(ں!jGK [a=+qp(YC];סz yv2/ICg  0R:tݘ|vU 5Cb^ a|{T)S>iq>%y1RpNDB%A 7ͅHt; ؈GJZm,Y+CK>nwa spL@2!YB7t{Ycj՛$n@MRRہQАa5 hB{ 6lh)A®v/1vdt19plG{F($w)?a1{On6`c:liscI%kwcU3 $CwL\җ (67~7*I=M{P) * ?%Oo]aJ&@O$4*TCTu r~WV8QI;?PD#޴m7doV-XGTZ2+x꧷m Qwg@X:~y*i?e0v)^55ͯr\=L*﹢kMa:Boѿi*>_Wظq#=,涕.~l'u`;-YHz8m$4;KgOcƎWX[{OIB5vh~i3,("("(nu+Qh6V_6l(ڛv[ڵD='Wڧұ߰64h g[? +4њkm%H V堈6O JŤ+ٯڔ.3-;Gq]tQ9?O/_c U1)XyV$3aؑ_~T"Al O(RB!%6ֲ'׽e$c4|.:ۯ{+`yX1b"y_ ^t ~.\zÌa{!B3;y~S4g}A#9G݁t=D>+b]v̛?TUԜg0yx6ˮ>}A@EpB%ϊ f'EE4w; -ƶ, y+K.&K ws{44U_'o9bwG>š5ɯzq$SX楤< 3c})]OW%oKLʷoiӦU O-!^I\EQDEQDEDt:y~8 =A\KИNmXM$ci8Њ2o\6I=)b5d̮! viMp̋ԾJoXl܂#K?<=j-0m-I{,0~$5*=s02sf/I;2lDSE嶶뮣KPs%ħ kNp[vL0aqI#ctDGM8QXȴ4'ӎìՐ\R 0b. &l!7fIX>Djb7n'lݶ2LWҾm?ͩXY)\7Qj9(K4M+N w Z=tYּB'̛OY>[{H<Viwc\{ek1CN=,r&r`rfq\8$y%x>8`p?IMڦyO]T]QOcu,B}iBq4#e0kEE˶JlswZS' lxitʈ()*|RJ܈A u;Z-0^:nFE,Q}Ǽ Q?{\M7x;/PU]d#}^ɾhd{ GDEQDEQD5ZZH&(iˠ3Qz>iw\~j5kVi:s=}HO݃$đN%\Mszg`r]{RJ,WQpb %v8{_wERqsztm o¨&,O a@{Vo6"prghL&0?] Cs6k~cVHxLg%_mǰV.c[cSNqrS-A&بX=j$cRJ 腢\u%' )ZiTTu*IjI.&*}?L'ZM1F~&yA9r?p%h^;AV5҈:r$~%ժ*$Av8~4fܸ*2DCT x59OU,%W~4~I%Ϡ^ůFR{<#PG$7#Do5M }~ݷvFMCgW|Nb1֯_}ߏ־m{(t?Oˆr8;aG?!xukVXrߵ1HZ$L"("(b>z1LeZ(9.vemvc= =9zGrlF19t+61 Uc&vVIQJ%iu`(+,رٟNi Bpd:Y~!>>QńcH&uua|J.w[n# jظ9{*m]it1q:G/t2u+Řq_qұ'ٶx7[={6XRsɖU[޾nQvTKiD WD_7JSCӴ^DӴuw6`GVV,ô n>.v(إ1|O>LIt"ڹ8W|w$'jgO:til[4͡`һmbl ݼk'$Ca~VMyJCtct0e[=iWĝn^ &^E]%'B^$W:޼~T  PZ-*7H$膡{?S-nTU^ RP ة7W] WN"Aj Fa_Y,UB%jeG߇ S. S3&p`@ m*x?'Jvh!IePjK9厃 |4Q JPK$dI;wi~pء֎𒷚cf&M{.GRk;h4=Cd? h*(/$"*EQD>U$R:8=}Fc Dpwp˹k|GY3fO l3 ~ɛ9LH:#hPU9O? >(q$ .VKZ8ѾEKxT۫aJqj KJn&֬][vT]yDrm}֨`((V6t #Tfu3Ϡ` @1گ{g7?[ccdž!ф9"FyZ8R 򷿱hѢ9y4n &/\cwqM(XOUB񪓸U2iZ4Bwq;=-t}%cQ03-.;AJ[7ǣ&4wƘz6߾eہT >SK47nӯ +5 8PO钮,4綳yq1MUU/7&685%ڎ>8TvlhU ׃wJ">g}絿qAU[pRRt{#dN.qj`͍ZW$ B.A '@%jzj&~*!aj!M -Β %_UhTxRIo S: v;Ulq?oi@!A" x+#UbUA% -=}I?o+)F}CnwGKƿ]o9r$4i]]]ޚd*WC9s,nUxÏJq?d1"(TGS{3ֽa N=!QDEQ JۑcQ,9+ET ]vr88H#)YdmGF+_d2u]Yۈ_c0a{( J8&LxWy1ML2 *&Gܝz{Nkmmog׮]^D<1=FL H=x6913g,imng?9ݕSL3ySg/3?Q@SV?֢)\Dx 1a9^ſ~%(e{%<7%KΏxGo{̮$=\BлvqUWUU۹T.w%yVu8yvgw6I`&H(Q,-ҽd׶d%HbH",9N؉'uwSݧl@ϳ;tWWPWoϢw֮>hALҰ1o̮fKi .eڋw \VTR?!΄O-RK 0W{v ?}퇹u_j@Ul!M:Rɓ'q `U֢.2rB\Ŀ`z(/W[w}FsrRPh//-kkV-tDpI-.SYin.d5A۷x^xbW]R^խ4 u 'xƣ" ]ҵʡ얩ف+YCBn-->S%p5 tdC4isnݜi| X7I ?&Q.R<)&^얨[t9Fk,gݷ,)f-R҄R *ol-5=&! 9x݊)JU8>yʹYh$.N2I (Dm7ǒ>,RC*p=wSPn>rª!5 I\\*%O|pYR^IF6(a8@.jfzIxY1!8$bxLpA0&6ׄˇOL4x]°Iy-rI. ~\ñE\2U=oXa7uCsdG>‰'?N__Ӽ{W uM O׫m94%DHRUi/vMr3[Q e`ҟ+0JscfKt&޽{y'y;`x{.޽930zNìu7meZ|azr ;]! Itm:~#kWRS8|ڜTXPBO!EƟ#L0J};K>DT~% [лeviW7~iS`/[|-mX^/ Ev WmEǭV;ON66s[^*]N !2&`Y2{j |_ ڢ֐ڦI.SӴT_I͔4a/ P`I9ʛwppZvjLN%Vj%&k6e.d]ARŸ3P6*T8ǰvI:ߦs3Ydn-2xJ xʛԕ|/?_??czzkW_V@w㒈nnyɒE{4 n6TujaM6% [ȲMlu#g?} U4MJTyw85ek]S 4KX99y`}z x-g\`o]3I!rx^ w8X}n: rQ\d7Nr[nFN(v95uX+iݷ{4P,5med_O{:dmfAJ2vbƝ橓{#ٮS ZjZj9^i7aYcǎ+_ 2bۻXm*^X N8xӾ:m͌aVD`BNŹn)'fAYP%dZj "Ҋ>6ZJپ禝Eٴp<ǁr [x@#þP&7R,cΝdpˊ ͔R7@.k]xg$7p²%K S0ϡTnNUݕ77wS(4^e ޑe`4lWǦpqwBIn-'V5x^${4飣@e2lK&ҥ?~KL\ᡕFJm2g>I0N5d2~ 5KcT\ K>ltmv $)X.sa5RԽ0Fw3V>?<s/o;nO|mxKO}/,j+.MԂFZ^]y]>zTqʌ\Jk*Q(8ں_ӟd_2ҹlK=Yf5.!8_atz6ғo iѓ4Kx#zgpβqhk#k49;eWҙgpGOQ=+6ň"R0ZF d7܈̀՗A&o8kO{.V {9v<կC3H $ ;Vj?Fv5+794=ŭ_;ZjZjA]úm͚?r?84/Ka#QC)5+4k;7i@r'eT7lϸEK)㸰jz*%&ܮwepf'9~N0:!(9=c)v۪Zsmf-9Cq o݆kא/fj1E̜[mTE-mjGk͏yYrWw%bq:<72VU^22Cʵ{Ns=n`< NBb O:t%=6A՚W}?B{.f\"Alě88| _';BsO~S-ۮy"oXL$ae$K)wY\4e~z7Qέ0|4䳠/㮷?kW8^]C5zTQ]CG  ^r| Y_I]y>K`NĶlbH61N]$ tR'v¬aS=A# /SDo)`Ҫ 4DTO~e1$QPJ{ }# bJ]S_ʆG)?)Ѥx焘RIbÎxTp:tbR11%QIfH$ =Zd |$KJLO{\"CeZ)`8#%Ck;iwd0'҉Q0 Y;Gwe٪~K$u_z(#Izd/|ǹS &*˺uޏ;xG\}6XW}"HWAWK.I\ ׮oH!Mpl0JkvUl;V19{_u'^E0UNJ-E)Z\^'\.s*MmqGWUY>@G.x~Ui>Zё5"TrA+vlo;Rܩd@y}G-alN/W=6eg%Wl^y+ouXHu/kvЏ21 mf-}]-=74SO=E!kcu-'zD]--}#"<NiMGU]kY߳!#tĆu6,gxxѴVp}Eޱ'_W9z G1T:Cͫa ²/ڄ԰߉:]K_$Vmq6Sxn}2xeF415:@0x\VIQkrf[zHLD){_f~\}/Z:)^B&5nQf ^e[b24ڨFIc1GhT3>L0@);uzڜ:T^O %l4 AU0NcJcRLrZA"Q&)\&4*-HZ1-$q %ϭl*&L˂IaR6 '&Ep\nR8i/RII5cL5 ,D$jekX$N/΂P Iz`CLxmLpH|_)1uA찋F!TI݋Y&)Э=c|Gߊ^݋F;Q6K.GRȄFe/o뷮ս{`ϣR'颚FXYsL=)*œeelہ%nKZLLsl0ֱOMŌa}fUt>2mLwS{Ѯɲ{#r^ =ԷG!JNBn۝d6̤ O{lΫ׽ˮi 4=?4r_~cc\˵+nb2gSrvYCOaގ[v,y0s+7#CyGw)Wm^VĪca$NaԜ6%^e} s$'rq3 ӷH\2ZL4oͣxt6; }B26H:h>jj aknG%cpjk:#zuV&0=F<\vR#.sY2Rԏ1|l'lgC_b ?_mJ?iAI;vK"AڜCײ.~>|^>ýf{ݎB]H@AJӏ^e%%6 &iRXesӧQZ1ص@{rc%{Z6Qz[\-!-a/}Ge;u_?ڙL!ہ=J?ķ?B{v6G󕕪zo_2R"UtWIfԎFMzGL(UpmK)NN{tumB xYs+Z ,-payص]o0;ߏPgo"y?G2YX8d%LvE+Q'<]@K-Ex4NȗŦס5/ 3)渦t-`'MPUG`7(ݬAQ.Rp4mV!%/͡_n-E>nظc๮7;I@=24Ͻ_SZ&'>}&[Lt(: ӸJ֝,M#pvs%D|7Y'>;`m_qs(k2P* \IɯϳvK29w|䍬ں"HK{G ]\g3v϶ys[ZV83u[!+XMg˘CiEgֽ!-8Bd Bdϩyպ7i4{s{f jSL?F?L=Y7f9+싟K/}N=甑mYjGǝ8r+ؙwrn:_SXd|mg92vU ke5H!M.B>a5I>~h/nIrvV~^? fyJfm+Lem~_ DK՘~P)jv㍞DI uMIFMtb  lM?s c_3z{Zy"!~L1\Kpײ{# ˾w} יN={ ؽ~U y2:H2 q(D&o{-,5~ws"`y te}3#4z6s v3x<1Neȋ9!=[~?CH˨27v+\"5PzȽ?D9ǑV;lԒ[ކ]4~%Â_So& ZjoÛ}xG=hD2_#_mRK- &],[ٟrSO>fYͰ%!8\uyf+s.h_u#J nݡy<> 4n+.9hF=oF6+_ۨ;]n.6MWo]EgwGϞ=O'aR1)շS(;c2ՕuS`8#>  /R1A5VeZ-KZ_6@$. o7\n$lRD+ ۠pTdZLL59.A$\O;ԡSಠI+$Aͽb<WS*Mb[Γ X5og}L(@&&ՑT5a$ }7&j ^fI9DnKL,iױsK )^ecA]%Z~5Ljvnz'jy_=ozSsQU;7&>)>OrwӉ7E:;;y՝w˿lܸ1>wroIm u(=t ҢfKz}ܽnU1(PvWvak-~y#gx톷p<¡}& i:n ZQ;駿JeZP\7p ),jJVn^u'+:V88U+M讙>i0oAG%гkzW̺k>dldgx o An Xd`Cn_3 )c4ѽ`KǫӵiJδ\77~wU13ڱ3w̺kC?{(;UX,ZpxDGpf)͗7KC]f&$x PgSgv*Q{A^ZZj  H:sruGGGya.Z\URSK&Ic%=M)68)\K9xu5髚,iQΜM^L}8y$k֬XtuF<`iO77^bg`tte9앛WK,*/~V΁XM--^{}5\cg'bo5+]Rȵ;T*&L{&e2qI^&YXF~7%~ 1h UU}@tnusKd_%ab|I?_#l[WGQZj$ad>pI='cudo -ȹzNi#7CL'we $S6 .HL0S \\KZFLimMuG‰H€KdHDk48&(%:FIQu7;aTL()dbJ^V+ *ԗS7 P(Qq[= RS`ǭNSf:#迎;gV: *NtIyX*D!G,\S}7^1:=ǫ~&"ce)1V]û?|wu;:b6;ˆ-\r ??Z3Z\s5'om;7e'?Fd"gsIJBdBH(QJo>owߧkハ'g DR<ݹ^nXyJOKprUˋ(զZv ˹_biJG` o4W@+mY4p3o.= 4v:%7ȱÜ  eCdrthA;}O񰈝9{w,m'{Yivkd6H;J~ƫN3Yg2濅7yϒzйpICvbuM2a"*^wv3bΗ;/iܣ6{jRbm {Pp8e}?"~'" i1.%BJm{r@)yץϳ5CJFҒ{+5JJ#cET^4`YU*dUܜP^bU-Y3Zc'^OC~49np ,+>?==EՊ熕ҹ'G#}̋g#^>rG}Ie[:&MqtcyxNp}P$ LTKb6ڟhL" ;ߢXPβ`bBpT+< y_VL{~-ҞMkNh"cnP'eJ{H2RA Z1),,i2 OPIz$)]MoFS* &&%&˶JOAű0zP0{9rIPA$X6.U&\BDD& J ap@yٔ'a :.QJt89-N$V2H(Ӡ.c.I\ϐ\"x6Ax1xei.LTy p)f:j6eN( /3AA#F9QC*HM CƺM@?Jdih1*m f:1.57uLYV oʼn.ڦT* @ ўZRVC5H5Ѯ7W~MX3в\ROO'>,ˢAn]7[a-9(>OyO_/?`ʕ-b)RGjQ]v~])$f:* n{HYݽ)Ǩ%8'À,+COJXs77 J'1>/ZY+l݂^$/ߟ< ndrTijjj!f7߂ZV_wS9ɽxèxӣ>Տճc-AZ~BF:)Ͱhχry)q5)N|A7woAbڥӾ& O~]i#!sېL{QG~̝?RP_;lVH\80˗/O5wm^E,!vAG W_ѭ|eذu]@k*V~"$T>^J_1zJFJА/עz;أǩUkضܩ9Dl^8͹EMxT}o]ײ\RͿM!eqw\EqK űL$̝2􍽜X=~˿dժUu>H3Oe:S}ͽpPR-p-s|>;GVfyӦwsōŁ=LU';˵+o7R;q(pIcz]K-=@N;s ЊƛoڷȞ7nygċn&|^"Z70 e>9pVvZ{g>{wl_+ԼJb;N7QCG>ƺ \]9JKzMiy TGo'-=%C{j6ՕB" U H2CW*6cM(Jݷ$Lߺ|S(X\K I@IFg B.Z)<͆u?6SÂ+(#pj?ӫ(L|- 8um3 %Q0HC&6Ldn(X HdT3Z .lb5)`[ $L$9,B&e`~ua:@5D5mLG5֦Q&&哨:_XҨJA1'QIp_mwfIL\kv7\խP %,n3LSqᆵ~Br:AUlWpz/M+08͊%ٔ AKpV; 6]h% $n$#.JLCS }R=xʥ6#[(wgk v}gZDoR$Uͤ8rׯdz*M㖤;al@cufYxSs@L<}6OVY)n-dzfL-9?ߐXY;BX8Q,F:]əϿay?OB1:$JEyjStysSgG VvLm\=ŹӸڙ{h&k(jxE;S]9}ˠ"] ^Hͥ 5)|h)3 0Ux'ZН'4&^28ok*Ԫ9ޕbjj2q%̠bzfxH3p@ ɿ| bu:;saR <׽ .=ۄ8y>Bk$YADETu+1{oZi4'oO_w^`C{F1Q哔hV{J^T_!nWA;:@iW)mL:@H{ _Nšd]WϱhomHDh4=Zj7&_odww5\1mi#&Xxǫqxl?RH:2Z;#g:@V,3Гozd5[JO`~_BDI##]+=iY"^-=ͯEQ/Ur{W +3^ɒjrF|9#4k_%z>?Τ*XE ;އѥ bežuXkwzblE& ϣF>\{5ۡVNOujML.C<'ɓ', )`EƢӒ ;%|%棒>+yeR`[Wj`Y֫?ZśXxl!ǣ8ٳn)rBg|GOP?7si oE/B.v;qؿ?%Ȭ 䕑p`t'O0\:Deģ+#b!\ɲ tgU h2dd|J+]TE =\{~W d2GDH"'* iJ"G+t|1 frJ01+C 4r-d-_S\9 ^$I:QDC'A!8|0e\}u rf 7xA3)\S / %2QJ'Ig)`V&$Ƥ$>*T$J$.mNZ%1eJ+n?jGLNI4 ;3MϹ$qEZQM`&Sqau%׮K$^`[ >VKϳ0@FfcUM%eнbEI$tāz7"^b;W= N!X ?Ϸ>}?a~$V2i7͢*<\.Y.3+y<Im)h! @%a C&qÐJ̅Uڪ~-u )eu #SnPH41i3@%&b\7G cu@@ihy[q= K <|Pa͙L&/L|gCFp`P%&\W+$x -ս\IP$K rϮ'-u71r<4~M""q%Kg5st},D",aTNOM֌Օ#;ڍڊ ;Wqrݻ]vW*6lM/CGSiM N&ۅhytzYյ[y圷%Pc[žL$ک⍝Afp{`gqϟvɬ߉\vY}~:U!lv=ʦk$tJ.Qlw}8|~jshJ=]'5|N][Ջ3+9xoߣ/L0Vt/Ǿ.-"נ*T8agnB}~/"=}BRK-(wViΜSf,XxQT]Ò?x 0Iͅ*x`I)ۉoMT"` Y Y t$t4}@2]r(hO*[bIAVwW˰h &+tZٳH@+.4qRHNOk?g tz Qdv,kp٩Sw+xӝQ4- zO.ttt䜚x0%I&$<Vh~&S/ 6RTRl)+̈́hu|ε'bV&xۅKLYt7!\\J:NS ~<1Y48 ]HAp٨T9t8aՒ$in H\IjOOX81ĕ iJwDdcaqÔf:@Qyxva&Lťi< 1}6}.3sT U#Ā z,`Vpz3|9zE8-NՑk9mJ%C(iP }߫H|%K:xc6Yq5+6,d-DIRv$8lG%ge)n꣸W9g2o3jCӸڣԌYSY''>0*;,{z +O| {eK/&ܼ!LIv3Lb4̺ xH)7EvoA')$cQ 9`czie?w4V [h{jjȮ{}V'?jz #2YrV\oz-emOh^IY%;rkRwn\-x՚=2|ǚܳCoIgR0VB&:}x_LBb k]bR{Nrk߈=G@,[ N5ֆAL!붭Ik@`c.{G2=6'!!RvwaY&/9=<+_MPrǶ`& *TBm.{Z[9O]> arٖ8Ux>˔VMנ%`RV%|S0M1:1kecUj/c´li[E%vk&kǓ'D-"(.ܙA刑LNNrAnz52N;f5y|c|DD*^K~jR11e<5A-*h]X7p>MIzIIpl1YDӿ̤ĩ(ԏ; 'sghK4}0$& gR'GRd-0iA%:‰I$&X6G&BB:}#AX G&zqLyLۛ0TbHLSD #qISz-j,Qrq:*?X%w*Wyt廩j|O¯'ߑ!CGFR^i͢RUU ћ"HvE^[2oo9_*dxmy\LJIZ[=8nϿHUvYȮJrYٓ^v;-^5.ĴqliV@1M~pNK)&RDґJopP+`Y^\BsN즸|],`"79s(Yٟs8'ӓk*Z{U=,} +0v W n^/nxHshHst>Ⴢ_y7 rxi3yE2$_{iwFA7#Vl|x.Fjq>:3]@ڠӴV_4d\GRsy4Y9-cB"n` B,89a,+ >Fdy}!C,d0U}-;}05x,  ?t[4LW$zd:Mvֽ@ (.n7rl 7H D<Ξ=KgV"r]xS/WA<|L$c#aSլގD6 #{98":ҊU`(2DJ!=4%m v1n(<+4^(TRGXݵWI-]FBYݍ$޴#64K_[1s$WhD>ǁ1!iMv5 $B́ ueK)u"szIB[,Fª%;QIxb b 7̋ĈS(1É'>NĔ '*=N+HT*aHXL`B B!6a^>Ϧϋjiy64Ŵ?3/3|Y~'R5Dž_S0R>7CˆA#TMR՘:I1ŸÈk0$9!B|B2\MtڛȀX X#'6K,+ONTɻw??}_/01?pmc$HDm% ,zޖVpxv88w}.b'93u lvI>;rvo|ENY(m`MzLD')?]kY X3Ԏ!Ȭچݳ+UQ"W`MzujYΆ?bvm<w\O${|)5_{~6Y*hZFu&qzxGx#;ʽvQP~?@9Zz]RKBvRJ熆3ݳ).@!4?z^R@>R *TB͘m|~4ձc5p%:tX_.GO zIrVjh`MAK4؝5me-;s挟Ʋ"2QI!w腖T&#std"̵5LAg@zS22})]ܺFKڌUxq)&jXnٟv&922 АHd\ajr2;SPIulTo}%qrmlJӺ{G_FeUkٶ.Gy#^ ),6nOoZH~ W0_CJ`eo?pɬفշyWhEu#:"W'Ǧޭ)y7wi?ߓ;_URqy:៿Y_j.tx~~Eszw2V*ZLԾ u (;~kݐ+B 5mX[n28pej%x,^V`ĉhE)Y^&gH&Kmcc*|NwQ/J}5b͖Q$ -j|jסI}I$\&ޟq[i}j ;т"QL]ިmFLtßMe/Lp€G8V-R0Zr-s˘R$cTJL $QpLJ&p*`*+0m "B8qxLpIT:0Y_W MUL3F^"膗:owہy]<2^h3T%jj-ˌ 2B0>> xygc-jImaKY+Gŭ}J3^O?>?{;z}.'9^#}]Bddnzbf_i1{Zeam ^xGrbM-d}pD z?[Ng_c V1==MGGGW{Gc+z+ u,oշ-3V=Ϛp92މ~WhNUn7*ʛ\!a0h0ci{ J;nB$&m˞?pl8(m˛7:ג(}7JwVit@*^oTSξravT8M . nn̿4V?k^Hi$qRpRDaA#p""-HxYTQ]@ ~Ls"m.:u|0\s]7ѯm}я²D|L,btt.DM4UiVbm̑V9=u/I޳gX^\&U85u "gܷ}^JgGF i; /{uoLo箘`bI)${QzL>)(^2ېnd +Ld^Cvly BR49J~3@d,ׯWޖ`hC5hfP3EQڗ 7l|1_>93_|9FpfAO7hjH :{xb{mh)?U[C._f98|:D'9N-]j-%qJ CwiMKH3Et[)ٙeZM&6Q 1SKn czsi]R ㄯcT2$8YW2 %ૌԡ!z*f)$@%m^2 q I]d8c!BHJc?H.DI%NRU9?GA 7A -KB'( ĤL" ֙h1I*̽dHV, / 7SH D}ngM̀dqI0UNsk"Mq}L"Fo19! Q5QaՕsdq$qy Q'؁C+zW܋QDU\yya7?켯$bRA*,ce9n9KZd}k1U}|aڍoaCf:sݳ틔6ϝ~[672P\Iəuh4e?ӧ3O~ +;V7X Z9 vSc!N [3tz.CdT\{Mȫ_@WK{߉NNG{=r [ҦNDifPIR>2*I-VTǔk?KU,Uygu lg]%YDt!`jj S\5LJ8LP}>jbqLbKcI\<Ɯ6'n;2}I^:Rℿ'N9Pdn3] =X2w},fUOfXn}/o2 ~TJ I)MTzzʛ,ԖRݎR<V1 .n' JuV>YS輄rI\}qH8M+x]5B%QPHx8BִJuI)QJ5PJ53-].,acIvz+iLI6iR1|;7QщKLLIpDlzzZULD}usRyX \^\i : EVYށО&<~:Y^DX](vvgmk qJK'#Ӊ;*#(4RHuodnlasde^{].4)$ϟyr]h9<}eu8W 0Y+%,uobUZJgtQ-Ɗcə)q={8>q)$RfZQ@yhVYFX6{^i4v&kn[E:2h+-ۚsꇊ5J;j1 *co|7_􏥿 *VWrNU`)V."ߍ}k $K߇bXf(eD 2ƞ~JB`i5 Xix-9֚fRRKا .xl\O"lUN-г*ɉ]J̓;wXbk5IhL룕LŠT$鵏o"09FI!o=!_ J~Sۘ/d0XbRKkM|S /7&kixf7')\D C#I $Q" k.bFL$L&yKTML*'rf AFfQNbڙU敂C!RHvl/;ױsmy_W>=TbR21$I!;QXɔL c*#u)"MG'Gp"\)r,w xdr:AUi|(G_ͪOǨ@,Tiڮ5 6=iԮTf0YSL^I-3OPj3RsmeQ*<iv{]g);C؍ꖩv~6VDM+ogMŠ2V3Uh\QE*heVi6u[U&}zYZ"[!pTr6,t Lm΁WpǠ# {h\K,ojS$RkRhYdn}ZyZ)NN#7܄9COe'("}8 d![hLtJ)C[99ӏ}+چ~[irR0_ ()̈́PI4Cc R$(wRi"ON$c!aq'g} iB"RRdl1m=m)!pI+SjJT6a%08V.iā*& qjH?GLIxJ ,INcS^&N$DbD-K.ʼd*Mߓ %A$ D wRGը ;bڙQJ-]Z8C< X.rRK`* KmZ\ƒ3 Ԩ H9+<d")Kh,d vˣ=psBs6l䭠vy?Vgn4i+ȲV\%g b6\fx32FSvK mѵ+N(6<:ԡ)Ͼ*^%MF@(f:PvQUKչm[R-PS628=f,萟h?, U8:}+5VMB@g/נ¯-ؼf[2Oj&=WI\7ji&F]Ein27^?竩K'";My_"[RK ˲fS+< Л]Y B0` ܋ W-`x}Et/Cjb{q)U}s %T9zvA"bAxyX$bBf8aP( 2IZ7:,of*=7A`,#beU6JSٰITND)-+#=:HT`Ib)l/.'zIhTޔҦUaIzIp]U8a5Lx?KW~NO5wt?G%9xvd|*c-wF:ps5& '>gR1sZu(#0^oKO+%L0G(DkĄUi5%8EZihUI::K,uCij^`aюD~8K/TiӕSL'ͥϖS&)NN qj^4w|C(\zn@ɋj,*DƮٕ}LcKH}rT5bB0+,gu] lXVug`OjH/ҫArsc|Pc'Vn*jADfFS$f}Դ3=H-$o lJ ~#ENN"}Rk #_}$IQ0jTϩ/mG"bFA }$kLe.]N( H!SxOD"Z_ߪ\sz*z9!U'!uLg-ga:dRϴj$.' ԗE1- #m#quF)D);Rd$U1A&"jJxQiu—\`"4a$jVzщ>SsZ(35ZXxi9PV+qq_:Sข|Nj\~#W\i$QZ5&a$a;a% 'ё%0airL=SD+(A#1fju ڇF4Y8vt In@@4;y˖{["|;ɓ?ԉiў+ͦ9l }xg<Oc<:Qb0kssGWuӒHsY$Vhp. lV 9iߤDWKT=z|@ MZқ :z"7a澘4$Í}FР]#DZWwP$1Y<_g\\۝=d5ɾ^~asJ' o,2ؖ=o%Z^gPLmͤfbŭOUM^IOA@HLj"Ove&% ~ijn$RD) 1 'qVvN\Rr&QZ!yaC&_f|Džq;=:yKq.4xnO|! )D`sYקnCrd2it*!SJ0SJ?y=VԽӬឺp"9-scΌH<KaKDFe7f*@)'/h?Cէ@` HȎ#Ԓ5Wl=6sR^g |`J%ar_Ip &C5/fRK-yG&XvnyJ88a+*f՜=Uo&ؐN+.kc!pS*Kpw;D;|!%}cu@>(&;ND# G ̤fbRW+ }CِG;Bs)iZ$*%qKڸmH,<"V8h&ssirj'yۅ(HäLbZ64?}x}pycLm,LL a8:)-N0,U&`}aK6oՒp RJ[6xn5ɫ)4e<Wc:C8.t_ˇ2U8V.{G_7O~yCJ˳(`{f$:%M3lTu1֡~MJzL o  PjSR4x)V Kb"P=37]0/\i,<:}{= C.9J-5xNTj\M3q HRKmzhjo+5k`l#Î(I~}eo-ҟҷ1 Uq*=8'v#2 C bRz[jз2 7 C&g JTL HO4E)č; OM|Xd2z]čh{]oFFhdA$XBD"mMMuRS阖IAc)`bVijapVu:UE$Pn`*Z-`L^T W @z%qhl/|^_~kʇ^\&˂/~B 75kV/ƿ8+Ar:B/`G<`Jk5h]IJQII>;39Q?EG<> 2YXp?6s/]^O;Ue[݈;QMRK-Ԗ}ZjڥbZpkHzIO?cqNyGxj‡z#GY ]z%mNB\q# +nWx?A-Dv-GJyS$!Mg“ϫ9mLL͏i#=;l2lS=q3YB&KTXd< ΏZZ_1 mӍ3^Wh즖ZjZj]&m,N-Rk5eAU4x$_ZLq\-SJSL륁LNZYv 1ZQe<=yxO[bJ\$]w$-Z{& ,.1om pp]&U:7N񤱁LЅR$màIM%Iڜ8# xS ךSQ : (yh5jo>icSXӵ!,i)qX5P̪o3H4=FuZ m+vDFXǜrI"#\]qKJ)1oi)fkKYl?;$^^msnhkضDzet9J),+d枡tAjZj]6fIur:W(1WEM!;:Zj]z?il,oUqNkn8qNGG˹#GI2I-v545Du lƖ\&?Ox(=ܑwl]J!.{43J<o2ǔxTC},M>L%Ij¾iQ9^& >\j)YؤB^& D$ a8# F1(aEpQxuȥa)`¢K "&$ZI$k)mPGxq49&#XUJ`TO.ꐉr\м罳yMӕK3)RtA)vp0X~(FGN $Q1 ;2FU6pp$мOmtMwgl pzyq J NE˥x/2hj*~~+qnKɤ<|ӟ7em Bb׮]x㍱u:}jrKZjZj]6VUy)6/H 3P= C!ytu kdn|ک7Bjv6k06?&56GN (u m /SD^,uVT]/\뻷gqܓ{?_vTé]zV-׃uuH K2>NH jEõ _(vS@w~IrQxMJ%~s&As}*%VeaأrH$,tIĤx[R0e[R`$ H=NL\AeA 3i')M{T}X$ QIrj]}$oWZjg&lZܶ I+Mw=XޫٸZq`z[&kegɕҝGe^S:LeN * ;RSh+ ͞u6"p4h>IE*J+x%Cr "B&BecTWz1\Ϳ/4?} gٳg,ZjZj/?Шq%7JVJݑ oIs*[G/.1czئc4'OnĈDi mM5X.cppijg:hWXs7p:4їpfKk26vG5| ř{H*.3Sh BB8z<@vY^ƴn246qz]lӀOp*T\ v;&cAކ׬) H}<,)>:2x.hϟ֯\Y&'SۨA5ȁ+년T>RLu.6#⋣SR}%gpvYӵ7oy}oKyd7Jn-Z)]Rp{Q LTH" 4H*Keʠr]vZ{;p|äX\^O`IJ@J1ݐHp @ILs:'JI{0#a%(kvq,LZXT9̜U]&`$ .'l>)qզB\壂ۇiJj($d BΠ^Eeݤ5tU5 L\ h2:3f%= \M$ B't:rf[ff_`QnV<14>ᚄ7pв<;fa7E"J %-NڄLIJafa yR~y#޹ϭt^fzU^xUdWw8#eƞ:+<6oĶ[[^O(.)Ձy5f|s|ѵ2:Uғىٜ5^0VHa;߿W5]4/Ypֺe+]@y>p vN#sL&>;>etdRd]غN$:.U#GYo]4w?Mά^gN_\MA;Dn?MNzST m4Nd$)r4jV$"',ItIL.wMR-1Y}gc (=2GЋutmٳ H0>ҎIj lbZN]ELIL/3_T-<TJ՗SބN*'atIۘ ĥ 1)ĥ 5?'YRͤn" H#qI;t:r@+ EnӃ @-+e4׾U2z]Y{dϟUTx=vm}/׭ ^ke{X8ҙyvQ+7)(dlǾVpDMB&vq9QI:}Y$E 1}mN)]r,J& $MGwá9J{ 2mٸܘj}rVUBͫ^qv89 V֚'g|L, Tm2efvG57;gR^$vY&x1@_Gd֪xCBӔGpvS028<OZpkZbڥA2L3RL VW]|5Wi_~fU[jKC\jo@/,c]N ÛƛXM>w@:{ ' pZA&q@G6i̥1M TC5;v^ J4Qrי&أ!mQ1V`[scT9Zϩ!!#F(5_հm+ 0ҮjIxyLO& , aE>$11miעS9jBLI$I.DdoN4:y B yW21XՁ;6 v ./3YfRG8t~:ח&*l4JCWVOnyɴ-6gKOx.as O48A$A0\NcVF i k#WwCϽ9 O0mPys`t OoY{}lc:XiAqڼWI&-G?Q?Ny#$Y[3QTOO✛|l );c6mjNr"}!/NGyW0lteU9MT:V0 9B$5`\t1ș{B$`<m3o]kBWPgdLL+Opwj]<r=rujq&sgIQU-Cagl~7_lMi?^3m!T rPZl/n"/QjLTYݹr\vD3͉ø JqlSt@tz/S}%tH;Yh7 v"L-Was66mMԧI؋1ʼnZr`iLft?0cev]+/K}q/ l 2 @S:dKe\fT7i*=.$1'lxOsskI>XM"֩'A@D^R}s'2q*%IHǔR'rI6!&pSqu& ,I=8u$MӮI0#ԜHpTJ : a*gR919+B` #nƫNOhk _Rx3|o.4g'Нiߥ9Ag!45UkMd\\trª%I8LuY,H?6i`M{zm1 Q6TL#2犏H|75K9.wGg沱E>ַ}?͡QJvwK,Z\w]ꫯUO ھ'qWL'WThԼLKcpVk7j^z}#/rd ٮp"s'3Mۿ 0U-Q͔:/ 7_jZj] "N ]bj]BZ_of@|!S$K}'وN\E &aD KuUSfۙ- ǥDjh 1Jef&]8;8yؤJ\gp:%Mc2T\JLl߃  :dX $(8u80tNc{)rHʘDkHTO)eO|NrkAwJu)d}e_*cYxuWX@+2/ivX0U2ta8ht4 $6Y1ȹi*]VvdY ou"ϯ  : ^s8pgs46 D&-DSp1 #h:"BJ[FT0$}K_wɷ~@SĶQ0>%a9}3^FHQرÉUN c=)bIU>o-`I6# R'iy}~<[)bc&#`AWeiY%z9[ [Mrp$^M|Uw^>klNh-Mܝ]d)w%|03S$ :dE.߼d%_W|猢R]C{/MeBbh[$GTpl8ϰؘ?&>"Z\b(ypFל%Һ*Hd\̨l m_OρmAÕ#E[\[LЊBꭕδ_*?k:vn+JLOOOoƱ_O\w 6V׮7{g&vLo'rWdOҺzDO7VgQ:ƾ .\!*(\ưXMrc.nk¾זB+x;^kK2gUD S~)ץ^|p-\Ј ٠A~9}ha'GH!(ЭnVflׁPtu3<' luPH?0fcl~aaѧi,$61r=:- 68dP"VU7_ *1L29zk9 ꃮ㖠-C!A& 7ҹ[⻄_o풥xCъ[<=?(^.n{/sn;[1؋稿5dyd[օשeMܙ/r}*%[H +5$esq:/6oU:9zXe@B m|E1o^I4J^oGOl96$}?QҊ,5c+MΑlD3߱[ $o@^tTf}L\M5(EW&$D֩mLI/"ZnɂF!XVXDa۳.4KE%͟mcy/sw]#[]S9x(?a/(m? g-\>/\>ž\lnc3,J2K@gym0b뿚t 1'O .\Nw4|x%f78w gfO;\Xn УC#sxdj_ԱJ&)D{-t͈px}? r iFh zʶ%(l hCvGPi/hթ6 _k~'?O} G7 ޸_aъ[cvFz!Yŋ=.ٺa0#O Q{)t1[:կjE滂/|CK\qm)bOC;.PSYuݛm[5g A<]DGL@DT~_@+z 9.J&Dqv]D?o֠$O\Xis+a1j%BB$)H&i0JgYuYd)cvβ[w5`s)g6u@lN8ߏ4gϷYd3mD@AN,kL(\FCf]m%Y^4wb~D dB^1 UH0ʞ}\X:˙Yda]20G&ZMh\V:ᢖ#)wP &bLfi?khB`eDHݷd.7kˣT!Qz/kǣzGyCwDVk}/}5ν~ԝ͸C{kFo|ƧLmx%-7 !~~b zhЉg 98Ocw%r\YB0YrOnL!F&zGY?u,7*&BZ MZA Z w|]pbIJ.M5yQH!yǸt33]Jx2_pqKY&OJ<%H=iu^NoZ Z|78;A 0P]l&H<_B NITĜwy58LD)sͼk걄b%"c鰅^<LA/QINRUbFI1 '6hĦ\bSCR8 )nd)YgKel跽FYpIȳR7:tPĄ?1A$%E-Rb*ؖlnGyY6(XbK@$eu $} n*3}up#)"J"a=Vz"9mbK~ϵb*E1!Sjta1)G?&f%f\9k]E$D=7|Q;>0 V˔e8͋$Ů 1I?,'o\}W?̶T)y%ޝ7_'V1cq$_.׹g`#牗82S/P TckKUB K Ө pŖN#^?Ca0 X)nrvk˗L?wA&w~TuN doS$>SG=v;9!D)k_g@bǟ:@\_v_༡=Xd$.NY hH!QRݦuܡƾNs,,s U66mN:as*j?`*Dq\ML($ I֪`^bS&l"y@m0~69E& ts^^,A&z51d#6U}m9?KfcXB!7)RQig97ɕ '{C&i96ɳɃLtZ$Clo\H-MuJGIdMC"%-D}SН9;Td"n#.\v1O'hŭ-I"^ /1OSig]:Nr#O4KOR딎>m(="|լ0đ;.\pql~B A+j!͸A#jF-V*7WИZ \N#wڰg4Ƈ~u8 <~}ͣ+F=_7Qsp  hu޸ _|緑1ޟd?App-uاv)&&EULz" >vyWw0Mph7Jl#yx()\һ=^:j?hS }9Ld)-cncI}vqALĦ>b{5u7km]΀C)d [}w*tmw'E Ζ"@iS~ބѴR2چd#ǖA#@'}m^CwZ*z檌VT~.M̄Pɚ;`}Q[mr@&ŀь|83"oxQ&J[R ?D +r̃T!SW(PTD+O~|QFuKn,E8{ {b8ą .nC~-/|¸bsZB3Xtumd\ݫ͌$?O KǙ^Gsb!Pp|A&`Iɇ7~EwS,Ek!j㺗5j߿Mq+H'Qͺv*SdL|0(6QG46 c)+g 0Э 4Y*&:H4=NϹ J1>'>Lol0H xbu^Z_g.ץ ,r2f*(zy]iĄ5UL%X؂1`ckwHlpbzI>UU"I.)*oUbۤCex-$1,bbi&c4'3?MbT{]8:\b&jj'9 %:_,VVM$m,h8ŒjەKt$0a~J'f=涬U$+l` ^:a.gyY޶`ɠ696{Ŋv4~cgŶ52UI] 9At'M Ȳ;FYc]~TT'd :_%/`X4+SQ1݁ IozwpvF#ԡs4̾|}?%f|pzm^ݏ0 m*T??G\]SiC+[+, Fx< (ym(PK#0i'S`w )4D6P"=Tc+ċWoS)e« r0bCHi]J^@ܨ_U׮rc 7שOcɡiFQ&*SLU-1Z`2Eů0Y&*"CdvZs-_}ą9bx]?> xdaR {U- ܼ=Vx )NϿE+l.>s ?\b름(z`9 mKRD8Nua xxf Ɔ:.b#"쨇0 9벩7<g94bH>SN8$@Mrb桱#7_">U~?NZU^Cj7#{ᱣS/Iv`;&z4"t{C,גWx# rfXcw>ss4>x°s>r}QR%L1ޟ|)Tpp-v`>fh{*&6ՋS,U}zV6#(RtӾL 똚. *)Tz0ju#jդ%F%'RxDqQ&IrDtT\}NR.)FJ^9ӊ$k@VhA&Ÿ́L$VGCl!zm>T5lѽ=h k5 +[̀iBd;Z3t*XW@۲Վo0p"V1Ox׮jrr ]g40w-!Kwe^yW݁D/ݤuBb}gaJNPKNR<U! j&pEXIe|UG^=@xly.!lBW&sQ;$ɉU/\p\H0.*0o)$wMCJABl~>w3֛FG|WrୋHQ04 +橱 +K>Zp\١֡J hF NϾR?)%*|G>FЃȱT]lY㤟M5f՚F 6 U-YFB>ΐ*H$#N{RJRg[+)QyǞ惪ﵢxk@ |cM${Yޗ^>O }d/goc\J&|ɨ'Q r%.\h-ףѽGR:0^hr!>GIWa+iSd*Y%-9'}BP+U#v9C0qy:Ig{~jS}EHC=4kZ~^lF$lpH0d~DDNMXCR [NL`H %nJtEFt& I:zU#Y).(Y768#Gg.ͲI˃Fz̎a YM,ĄVڶ(dbKHdD+-ZQ]!Vre5|g,b-b;/|K2< ƘL&+IV"bE)đB&&l,mKL7Vq./SVe${Y׻=̹UF#vg*Q0L8pHBwzbk$2`1]*@[!HъZ|׸.Zqx;ɿ|oh#WR Aϔ -AmasWL :!u\%OU>)֬U6TA:"=8y ү+N^gV%dmNGEp׌JI0̭$~IɘKgo#mޟ$X1>TF!(#g#ʣɽ !dCrgJ=(P(^#cwsh.B"ig*Z7—O|kKq..c?7Y _D~ @nxzpcìīO7bw]XB>/R~r%$^qN=*Y~&ޛ%6~!@&6$kOel]:HB"6`6-<(\+1k?8Ȝ^.1uDMqJ!6{~d>Iad>ARX$K>nOдIæX+جslS'I˘u`,gyR7?l9l`j[]:ue E<,ѕK F)b3\gӥd@75!}Uhixw/ ~7}_ Qͤcs+D)+7Ϲ ;teƚ>J![t89;~13eiNӡ21`B&zbl+o׬y6/<ߘGNϤWc;m %۰XC?5x6w΅mBQ6} ;A?z 9s[o"tK6GIoì79(y9w.#«g(or/*r>xAA՗hNv_7.+{Fc;+qI)wo*WK0x*{CQmB#L^&Z0[WШ&jB<3##E';bZJt @!F}:ֹB)&SvOpu2styvѻ>K;۪bcoΛ7_箩{TU(tv.!{\seQBTFYKbp]ӝ3lrcҫRL5$;Ӌ&)XbHq&XR!qmˌ=Ld-*&ҭzml)'V]@ IʯZHuOz=%۵y&KmD/W,ӯm{lP8 ,,,D/cEKLu :vGu#B' 2]̋`ZULt`LNJ^HE4z{^Bp|^=jMo|Ird~2"ָ -ǿHE1V J^r:T,!]D:Q1M&hME=!֓b3I@$ݵc%G,yb%[@fݺEN& o4.\lz@>*DqBcXExgfh; RHTKkwo5~gz7_J*Y۠N>In7q `29 OOXnÂCl{3 b8:-8 {v\bT)[+Q O¥DUR ^U;(TK2nݽ}02͕; 6ލ#=uao*K[5.qj-^MVn ǵK?]-\p1~%bTRiuSB:Gf_y:|5;Q] ǴI?GYw`T/YݖU I:OW1)@ 근X^m=wպj(:cIߤI?nD1-rMM͍M$'>=$RɃO\vj<{,E,Ĵ1mӺh`H,v@Vّa1밁$EPЉW[TL!hT.ŹX{b-AQ}D5@/WddHP{CHWdd)Y0Y8ۡwP ;Y7ΙľFPF:/'%n/G',ӊ6b!$Qk/Cn֮3syw@!Q;E0lLB @Ũ47ժ'::CԝP0H4y fĎLVOJ: (…Y[ jp U[(|!;tH@JtGq]_7+o`cܨ^wzsgȞ۔J6Jcq&+47k@Hi@Q q)S+u܉rT@՗ۀ aG&?s/+.߁K!?U܀ V@,*6jfQ-x AͯV@HA;6GbYC%^"W/ܻgBx%WpfmN|3s0W/}${Fs}\Xe!vD.Kͅ+]S߃V}E; V-黛ٲ`p~gxn_l-Oz֢P&uϤ$M%6SD X S6?v,΁":Mw$XyV &I^WP:/mtl8&&ީ/Mv \@$LdlJHtE}zZ:[R!Yh-ߡZ&'*S5jʮvFs֛Pg`KӄAJ2ll̤6ȨTD)Cп(H~nޛ…5_wev:R\ƞ;)\d %^BG]lx[pb|~7Nż|{&C)VPm|kN;5D%|y>"m912@`R)ꯀSЪ8x"<LnC4:ƏcߞMKp,6[ťD*S}Oqh3C{O#lgd?uO~3m-8Ƀb#>#]b\u:܉/bob?JI#6=r-L⁦gOT)IVl} z &ɚ}IKw'f"ix\Jl(HIgY Z-0m,IG<&nh" : bHV)[,w+`iI 'Y%&ePl벽w1>R7_1ol` iţ6UQl%  .&X+dg/7\bIV$@K!$% @I#Xl.pi7jWYj.lڅ䕙,OwG1Z×ADl&&Zt@ޖ'7KF`Um{1ia/Qm- ~_3!ݫ=- %O}.^,4oڲPIXJ'֧"*g^=YT-NV1vdž|fs껈ڴ؁cNFwT{Nqi}r2* M{DDc{RX=?*I*08!.pyQьw%$^jш خvm b0YK@mF౽z :+W_OY⑽O5BH¨iD fS,;=JB nŦEC13 ߃^ӮQRkϻS ӌQwgP1t`bad%ESV|b? XbH[ UV4gcCSѭz+ Z-CJ>(kN_>TM7oy3Lh$ 0R%1YV7ls bb& {5H% F DP2TxwLtm^w”X'2zBo؄Kb$^Z:D:$υ F?Lăw)uh%>O>>f̻z vN䝲69Iݟbkq1[Bd?y[7{3i&ʢM/eE{6]MnΪ=2Ƀ.-(M KOcNR`WKr0OHd_ ,< h6@ ^.$X.R)T/}~잟"&b~wYJc>US7R!I>{O7oJ-_ V1?#(x)Vz5xb "{ŷD&`Rظp-4m4i '68%Ʀzd' FW!1Q Lb'%5}Na>=oX#XC#4[2Irg-7HBIt$W^ߧq^:BH\B)V|*<#QZ5:vIiRWV$6F!% &W9+4,;2Z f2ne .jﰝ:^\b#{~%9#&I_!PQ _\le]b88)(WҼ"+6q,=LATdRlN ]nO!ۼ~硩@ח==HuEZO˄N2 }9߄H:KC_ԭnlzJ$B礀JJ\7"E7TO":mp|o֑U6K$ Zq95F5iO7ÃJ:IL[ iEMĴITFY '6Œ'Tu%\$6$O$KJ-}oN-[8e׫=$2 ;C=B&7#(6'QJQ WС_#ܷN dw`8G1 5լoغ4:_q7Ed8Fj9 g&JyY]qbS~0RN...$֘ S*WPM߳ŀqsA\xcx+?~vy`vqFm<`WZw祓(˶ٙ9mr C=}6C?Q3q>XSNF{/[\N2׻i,Yg[9oa{Lcd4~G&EIփ4t+~ i^b$'? @pI&Hb΃&y%M:d'BI?Ւ dd)dY)؀Ϻz\SkĪH tPwRda^+.ĦBbS%*?oT0IMeNiceb}&}"fwMCHtlemkZOKIQ}de7A$z ܊zId%+A)bc{5'ߣw_'erIӣOi#!Ml%y9RIL> (Ou$|*QHKku+F4t1>R1 Ug =[ղ\pb2'dbJ`XёNJnMɮY藹i8y.}v=(i8%7ݾsq'ѝm.6/}xbS_"΁nǸp ǰk$4XlKU8!P+VP]`ڥK,T ܣ E+ޙg85:~r4B؂gï;J [Q%;$-8G?o((zb8S)ʝU[ar߮80z7Ĺų,5+[w#c8ffxwM]Ƞ0\"`{l>ݖ .Yj&Y%픸G$^4G}zHjIm^MȲgcMI䩘en.1d:)Ī}'I YUOT{3B%y$RbR1R1!&dbl~9ds&}bPW'KY䘟eL A-s2?F Lb%1(]Fͦ8 *&y%k, (s!3a͚j1}aoJ+lDT-ѓcFOm 21mruڔK9&FR 8ʭ[e1gdWE B2۫A&.6CBHγfTI؜ [Jx@),BJ9fc3 åiAu nZGjBM'HbfD[d:e㻟fvxgMzvW)WDxM|f -{;.餴mz/;|ъFxbcfTߩQh6ͨY.*ުU[o[>DσY8<~)x`LDI 9IֱNgW<ϲYK耈ncγf\q|L<^YPZ~-%"bjӗItz:vJ&_2ޫlr۵186( *g*Y)6>]$K%Ŝb}&kʱR1?g!EQrYV;6h)_qĜ׵(DmA}zUST$+)I=yɂGLŜ^^ӔɄ/pzaj߼l)6}j+/  ǎQ+6@}T6=i%ihK$:zLL:4Nj+ggQ2z3s=\SCIC l.Z-rK\ؤc=c$/ P1ѡZry܌s> UĄKy4&1-&JNrvwN.ӌk&ɈX޸2O?±$KLLZ9 ڊ򉺴_J-3P1)55}o9+AVW_{Ǿ=ș &*޶gM±Cbb~.e9\Ŧ|GOxex&HgfDĠ-ь2LV˨ g_V9`专HE;S7n3 C\8X)P;=^~[yP0 bm6¸q\lUva FXK2StgYTKrL}*mZU.g |8մɃpIu*j؎>/&}5pc;I"$^ϥ-K[,*ӱ:ܱ|_ 1s֪dY%Y2gi2$,OS'qev4):" Kl۵^a8L8ĦpbՓUq-g'$Y6:6LiyUD|'GԚuZmQJVUޙ+W;7!`rN 6'DҸ<}CXVԢxw\{d$d&i?q,WeĔ?mK0^ &p(zBJX Zjoq` 瘂FpOؔ.1Rf Xrj.\᾽oV4Cʛ?%$A^jJ*c v\kCB0ߜKځw@Mb<|&6q?g+jXKuK}!)E/?/{7e)x-qprm0#I:^@bUҌI%곔(bh n{" N,ە"JM U. *4%0^ U7~rkV{1ɯǧTl?)噻g%&|co]*MS;qƱI͂h+'[B( u7}SC6ۜu:"+׈FPkGF6'sm׎'`~;lm+&'7OHD!oW~lN2a# w'ۂQ? yDP ւ/<( Ym0-^Qetw $4(&In{M Rϴas=چ!oUc-!]MGfu.>\aKo:O%[NqDks|#>t4S]£?5}ܹk惾<%+d(x6ߴ69JH~6P5¬;5ʯ\_O>{ hZkJ(P)+^;%W%^ɿ7Q߭!2(GN2?/&ߺ]fJ&)PbK,g]JcwMscMUƄm^@x{N#"i>\o>{~(ITN؍]@MDW>I˛^6>t@*nEYJbFW|҉^_޶pB;!nG@t0K%kNL$@AYЉM$k=6E/u*Fթ(M~xaVOObWb=)8p0n}t$*TbNofOȀs cO< X^ZOf4Bxg%c[:#=`yl$R`o z%H^'^үe*؟ JvGd: .cԚU%EG9 peAMkn y3~JTn-P V[^(k:.MH!+v%,_d_"xJD[x¼.Ut@6*\O~u"!ÈRYZ}aw6>b3Rjk?bϘ3d,I?◿s&|/oX+<I*P2Y}Q1=4xyj:_%&z[7/"Џ?1 ewFA-/yhu[XeVԢFO _ľ\k{Q&JӉ(G8> >\[teA3j2׸峼qebSJMɻ?~[|^HM,1(flRA((ԋ)J%2Ce4ˠ+@s,y$` K˱r8\رGTNUL)TbC'&d߇Va-Y6"g S>IXE X'<Q2f|nfۀRv{[ςDemHL5a=t%4˘$6D/W/A&0YKnXtP-*$y&@oYL % N).E]V}^߮%7nZXZ@ފ[[<ӁKK3rC\uE5T_:teSX&'"q!X)a ._NsU|}X?)u8Im1QLu>.P1usLhפt }͞m.d%B(|?2bV2\$J ,r:\"|[eA 9}Dz YYr [bAyp;; $qNzx(ijs4D~<{?W j*?̿hiJ)YڙMox2?0Ǧe~|F.,S —IU%TaAMQm-se"'oƛ7^D%Vz?<[9: L$O<{!LNITLRD ekOYt~\7y@%aFlb[^W:2)яZKks:,a{]=x$1Ѫ: R#[~ 1aS$ly%:a :1Fϊ,<ɂGXr&knt.ء/SD$}N*(&10A,Uۼt~v<68e@=i␦%MFipuJ<5%Y`}}'$mM/=O☘qVD@#&V8][n0u"d:&Nfew)f&A< <(#fPvFefU;צTIZ BAShG={=7b7~5ŋg#lXy{x#ͨa4&{Gp|^q&C&x ? mxk= |' ^.VUe8bA>pGx\_J Yj-М۱X\Z>G٫t~_ܬ_niDR)U𽀻vCcā=G%xqJqPZgQ<|wSNf\0JYi7|VW:|Q#`|oPkvC%}AVjH)/qEQBד)Olb=p ("P7oمSLVv1{(AJٷOT Z-\k?~?^k}K _xpszAޯ.[4oF-|$%aPPK*N u((5J%F1dKzwMW%R6l IMץ_+M5s~ne%鴼2RIe ]QF1ؙ*4ypN[9ҕjH4(Au}&O}D1!,@DW#1<NSVYgv=5F @S0aDɲDZkAPDaB&6Em[od`}CМ'R1.S ܬ_cfhoƾV4B"!TrM &Gf"zRd^A B $X JYMoguADoGA30Sw x~"Uj+H!eݞfmhk‘2yFBt`@ł8$ıZeiq1x=9~拌/}~c6#xz'8<~lche0ͰAUc{Q3\YHUOl3w(LTLH+yS@QXR Fc=y/G'a!]ũ Yi&炘8Z?vH2M7JNMʟd0L̦qjF*?|[{I_§O.ZQ;0-Sg+8H!B!( cyu;xwx kZ .xZ+3}_o] (CEY"rn j,5]z@RXϳ\Ɨ~b 'VBs gx%OxCՋ:4@TB{޷!A„򳾸GN(7ֶgbmd \˳#y*%%Nډ .w t~ JAT$I:8*߁It#A "cO{RS+)'t>bGthĦ:$6Dˬ\oݎ1HFi^GVYiSc`b#EU ב ҟViRD<'$-(TѴɉPHUbg?ػ;`({v "avrSNB?|SWNَmJrnMu7({cޖ\M>C, SoP.Y)k]u~ϝgYFc Г\G!;! %{~w]OֶI! /061OD!Bƫj"jUw$n>(&vz72Vr+C+LM@8i+,.L8Q(1Rc8r>iluy<M.:zXxl*wX+>+'Ǧaϸpv9[:N3•%(mic!OpkWB&m2 VIxbLUv0ߘCM%p*[ ϯoOx=#6x"- Ý6Ǟ}<1a=pJ[#9rBk*Rˀ,]tr]`Ɨ|djSS{Cck`˿ԤVBSce15$W|bwpFFrfȿ&qZNK=eH@7p bq3K~f/̭LiO@!90@;N#&W&^HT9c9|mnD ǧRI,yeX8.D6! jeӆ/}\C3|Oq߮hF}=6+#RFx>޻)~C?=D8_{n~߀ )~l[`SkM"8 V84>%fM$[z@$ENޱЏ 8R"UE`}M(N`fOpY}8ےƓI'Ɯ_gAt+BkYNWY@ 1+g"uFK hf}@iiU IOeM5S٤(42(\bʫ;KG=Bҭw"wٶ?KR$71bu 3OlT?X%Ȁ@ryJd2xn6`t>\k^G]oXrj;o{L2gFW~wXR=YƀFL_NϖX$vD}54lL< LN28Va%0) FI~H.▂xxLS) adxj#N \(p@EiƿF\_=xc`Ҏ8BɿX;/_;C7ѥ~ϧ_FOA`b=y҈4F5C1{3 QR0e#/nCXxYM|{m[It5=y $I!XbYݖ^;,xۦa,xT*1a,~bcӲ kvbmԣVUM$%lr!&6u 6_dY]$Y6^f{ؘp#n24b'k~H:o-9@[Yspc*QxlIE 3ED_fnC$&t[ӳ)4s a=Ly$yIj6|󎹭=Q=wH!$qC!#V"2hn=ܘجlLuX֝mNd&&ςL՝WA#)"ѡs, [\. L  IKr\|bJ$IJ2 [|fC>#xUޱo_nqvEH-3QZq^ΦOZl&JJLܶQ2z=O+KWN1(Zk,wߑ,@e?@d(Q0UP69٤Ș3Ї .y>~쟾@~`hxo2&rXIT, `۸ATr]btlϲ4$STh+p… [-0QDHicGBИs;m W&+E٫PM .\n(vvťEL9v3æ1}J @Y@IZքLm}cObLtf5b2 d )$W}I^[ʹAsؚyP3fC$INfyt1/ `]"IiiZ_I?I1fKll>cEsʚei}2f9^9Fo&}@~9Yu)˂V"97Hz!BWfc[O^vR:jKJL5!$`F}chCǎ2ߘMtɗK&$9_W1VwA.WAfv@\D?6OE9Ĺ3\\>RyMˀ{Gst&+oG_2o+zuIzkrY21PD/%;:h ,f{br9_C#J6`ZĒ,4$s3TG\… .\p… .t1<=JnJb<~pڒ̝9]i.ͩZkOz斳\F [H|fS.1/׾It%<ٌ,]T,ɂNlpV8{="&@o2_e~"2p_(J~\ ^gU+3^d<'{Agh9?K\<=68xRx Fn y]>'J.+F 3=Om$]H[,$C@bZJ%0)Y #,%˦&&.Gg.WD9eM"j1UK[j.rJl6? *IpIx?D+(  yj߇xkU.CKJ/ԂQ_ g{{ߡ'}IM 5m Ll myp1NC=%,%ȕ[k')~Oc,Y%Z{~ɷgW_MҢZPZĶ+Gy \ôKI5zԮ-R (;4؃Czӻn095Tܼ].q… .\p… [2Z!Wʼnmo$ԇ>f+QYq}bjh73!84~V2&䑽Op߮>`c9"?ڿ-ڞ(Z\C$]NH m+-} V θF\^ T[!PZQ4q&DeWnA3lpv#M\_J@Њ*7j/O2QA^5,L$Kw(;1I!D<P"ӁH:f* Z$:8ic$zd[zmtn6BBkbXqu Hs*J>|Uk%^8Xҁ&y.GJ6p+Dqc*L^28 ]A-!Y+/{zmzwଞW ,LP0Rm`|8Β_W)s`08.,Ib\W|v=ᱣx8pH?%y{r@0IݟͪSR1-q((JqIX b;[ LfSDĦHb[ (2S1Fte,[4:e~~$n{$iYs<}W}hb%&YDIڠ6.26ۓOHb:(;";̇=q}ul}"V֞Xe@`d+dw1%̫O4RI5)h+,W 6̰s76 2)Ws;P"Z:z=Wr0s7wl]… .\p… .=bல|tC+_IE1(_y+KbLyrݚR)<3>ėVXy;1(N߇sw*(AArk ^R<!2]8̓{g~w9xwŤ[_\7 vÛ<@i2߿md`ֶZ+|wX"^Nߍ^s|ۭa>NpI>^a$Э`b^DL3jRkU; QIjgNVTD/stn>!VGP뤲@*2ǧNp}\X8Ƿ.RSY:6sf ZKl:&/l d*zY}ArKhd&4bKht5}zQw'p ЌBbRWNY-QnŢTbMu*d)uu3i{U MOqot*&zsCfח>,ш\^:UU/3[Jk+i-Qr!)Ȁ`41wd?3{=OZQg\6BC|WsZ⡙0YB&LR*1w36{]Nl,ߧP\ |p盖7&dOͳ4,p6Kg8ѡ,e<{]m۳;d&2B <5rz9ۼ" 6ZPwys-QɃLlu:ډj+'b }DŽLt t TDEWlۑСBE$}/gf^Bce֬b"|{qm/W.Q… .\p… .n9b/ I!)XԺ%i+$HVzYbףu9Ȥp(C!}u !Fw! ~ PU[ě:%\ QըCUmc2]]ǜ-V11U9M$U/ɚO厂HzBtHE$p#M=\{#%Wpj$gOqz,73 4k*u׫WrJ1Ufzh}c86y3QֻUbj {F{#{/ҪriKUdA &8bG.6&`'lHYIrE,nLey] ZACڕ\|.\p… .\pqTT e{`1RҜI@Q ac%5lSU*d#κ*l&rx9:]Vݝ.1 :ՔL>U$JIE-V DE*E"!wO0WnQ-BP%Urj-f7Xi.wlrFQmFnF&"BjaZk++稅UJlo./33v?cd,5f>Oo+[Ko}afhOlp?qWmss@ :t$0J֑(t&kz^n=`<I9dA%E|]EmtXæ8b~)HRTY}dQ.R9g(Y86+%EA,굈F|ZT>1K'gZd؎U?Ze=V'I_#2bI ))Q !џxydElۚYgZ%c/b36ȑcg_DȘ86AcN+s@\$4FF8rs{f… .\p… .%"7N@8Vl!DXߍ}=諃6Dcv9)jTLUՓn_xZB1RfA I3j˗>KEt :&)>X>{:I|R T[KqOxx^_m-4 ?KdD0G, |]$VδL oɄ)tsK9T*1(}yЉny6T9YtMrLY tC%Hvɞqidr",]nd&q9Bg3^mK{l Ƙ%!^ I@y`1˲dYlu޶N9c;;wfwUΜ93{JvWG$1)D忩'›'O3ܯ_ ۪D-JeB$lj)JI{, +xpI[!8\b/\k省FO/H\t>ȽPq$ek+ Qv\SU}Vm:ѳW>ճyWLfŬ5tk[.2T`{.XxMcV'x\+)}CeqJ1FHJcHsN!(58$LcQ(TG'q*%ya0^?7dTAZJʱT4E*ͯnV Ҝ5N-#Cx_tYɊJ%R^@kE `(#ǨQZMˉ~]\+!BT,wgu!3=(!*+2rFBPbѺl{QIK(+WeqK~oEGbIWXt2c KLH"$H"$H"$xZnΡ)iM*uv>ٝр)zS4S{$&_88Hv+*NHHD4(u\q 0IK*&c<<WC4Y$D)"%41K$4տVVF׾ճOPq9{vhj;GcG q|o׸x\4q;R.K[V ;oKw}pѢǞ6H])Xp r&ru|u4x$X!pZA#(Eeլm*A&QmA*IH" qMO qV9a4aeನmGb`+A%a8ؤMTLž~JMeJP[oHqMlZ Q*&QOYK(bbT%(%q} nn)֐:F:`."r֒Â,]v3m;j%E@ f飡1ძ쟇R2)$H"$H"$H"$vGkO-+wu_,4s %I_/ `G~Ia8CSCb]¾pG(ꚑ<*D˼ ^֍K°A5 ic %S).6 "y;W֏A!&9d68%"PFk+M!4pC? aE7u'* ixw]Wh=œ캉V%{ T-٪?UL|{!V$LK9 5 .ώf8]Xn W9\Ic`KǽܹWdQ4ͬy-9<)wihuF#- {hvng־sNQoqÊaɮj݃;]7EMK(5_%lʇH&&u\+83C+g 72'nZ+0Q`I:ITŧVJ%e=aƔa8`@.@}6d"0wL*'||۩. +q$$`3-q}F\R4[̓a sY -3q4'KLEm*NT8Hx.bֈ-X0 YZfdxfRI"$H"$H"$HiuRppG%mp{_v}ǽ;){LЁ]9Od)Bcx:@)Fba|sB]8脇ww0f/A&'<86edYhT8B,?N8F3Z~KHV{v<m`(1{[]r`n"6̹u+t#$X;L\ ѓO~ֿ sv-TQ(6;lw RHv lgV\XIT4{Iy:n'l{V?p骖Y# !I$ n/büMKiᢥW6rO_el{.`ZK4jS! H >徵?Li%>tR4VE [+p2/ qPHNQjIϫfND刳^ oˢ`0TR B7.8 H\/&*0j*'U4+8ڴUv Tw=ඎqP h?Ѹ1 Z`-W&DNTŭViR xV32)߯a@#2jfl?%La$vXΧR%ff̙ۇz8τ*'4L0\H6B* 4P1FcUR5f)DmS)$c8&JIl+'<^q4"+졮!OU1$H"$H"$H"#KklF+@V) J#`|eexxJO5Gh$*33܃ 5WC8N[ t{uvm8.S TI*Y䄭o pI2 &QeoQkC{pZ\:(>Á_*o69u8>)5`Efeqs^Kܱ'̪¦cSbN<._,Z#z-]7UK8*~}bXćLU5,<JۮXR GP$A°IMp~H2U$Q*9y"L9qmoˣ"t \? JYU=$ ( HJ%֯T9f3R:Q9Vbz@Дn&J;gspBxE"Vqafi8zr`þ9Vi#M!rS +v*o\=$ʢ&>N$&Wvc`~16%(66twWM ?/nhʳz^Zf :0A)Ʒj1 t]3eN0 ǃF )B@IGp1 1p=UWI;㤰4Rض 'cЍEۨϳo8NRUJ"$H"$H"$8q~c?:}1EiJWȱ? H\5=Ð]APjj܂?|*qxIi61f.D82`⧝Ll}γzDP$Q,yێ܏q+%Ayp([P&qWY09VIX4i#`gǸ1 Wek+R@]!xɁ>0 VgO:dSQ*miY``2($t+ Aer:tjS2{EN7gnW1VFD9V<>&)ΔdJ3HJg¯WN =~t oF^]upNQ*a2XVf}jvxGm֜>8kctdFRI"$H"$H"$8F17%Yn@hKI x$_ (3cJ TK_A7" QߌKIM!jO뜔K*&^LV.BDZU,%i뫙&0[Y8ʎJKCDiECs^ČLJ`4/9;VrːF'g8ʦќyߑG̶=?egf]iFqҫh=D!: Yаf((8+ 4I& xp:ƅ68>"o݆"NeǫV,qq咠: eJ&Q68apǩ󪔮Z%Q0I{%03 ,Xn'&dQ&xcE*V)  kuV<<&ta[[LH*:QJe?V9 6)#M-.fSs5`)Xn3mt6zY̪Sv|wq|ע1f/5Hfe1&K12'8ĩ $U=&iIvI- %IH:jJnԾ-_\^qk8 "Q67OY6 o7j{ǮbWny^NkU1mp|&i#yRb6K3PU.{X³ ͇I !=L/UcjeV,^ƒA$["TIBF%"n{uDLJ52 n0\V:c,bq2V})iJ46e/ P ?/@MCcQ\נo oıSR^S4Z`KDMWIJ:I!l?hY N-6CTSմ^>!)Ͳ{O3\d4@42%§o9ŒLZ23iOKE(iS4OmϷ$@kRtȜFk({okjۓH"9+2cFK$IHnW_1iZabTnt }w[_ o{K&B]$ڶԞ^ޡqp5f`VDl[~$7n S 76V*񧣖W8E85K9a-oN2efbqmV[ǪYB$[yj4Ьh9'A"*pGpâ%\9[6jt8+%zQ68Qyǩ+өD+3eP \Uan2R$iL52R\0dab:rH?,)['QӘAo4u&oXĒ*&Q'x섐S@f-o-j3Q[3Q!r$LL]`L+W`hDUV9v9Z )t"SW1G*e/i6j 6ilyʐ5R*ci\MN^pYBh:ۗ%I JnB}n(åz걆TcsU7'k=t2TH4c^BV\Y뙑U,gg,W!k0j ٠Ѥdt0#3y Ɨgv?G):A!C)̦nSm }Q(-RHS<)A -50 T8iM`J)1SɹD3)g;<'qr?WAGd ZBsӵ.7^XpG{Gr_?`?H!)s5q\xM.)Ĉ&D6%惚TXFk .Y%8krI <֮y0w|OWgHƩdlVYj$8E (amNdEPH)Q6=NVԙdS2ͽwW} +ǎ'aʦPp".'zc8=l{i#}TMx &8$NI|=euhJ%0$I)tGmmlkT~ GbJxyH# Dӗ]!+p>mZI%%n5pGJ2($ TЩ,GyVzpFYDpJRMZ!$Z{ޤffǤoX,tl;Mi8 dteyg Fiuԅ$!49}&6?t w֮F\rmN#uЛbRVZ=Jh3Tʕ ADܣR)B"ԛ lw6g?әmCRd̺*Qr `ᾶ?>z˗=ScRxَ&53g*&JaP%礷)k:sS:zѕ֒HC=I.$NH<.WM{p%|Fr:k.t nIɆ/d2Zwj^7I$ud|'{J&g.\,yy9-RaZ?)x\c;557_"aS)+%adE'xua(`h۵ZqÒ,[*I: \nHvoyga錕o\pi˵wiYc~ Fp 4<_$ئt\0ǀ 6W,N\%~wIq*&#Q0K" F[7 / 'jQy&q#L ItԲ T- S> .-Q8U#v7a W; NwJ-Qy%q`Zj&IB&)”MQx#Ҡh`ܳyoyݻa:MpRAC#p0)ÚwkE2Pg6p⫘[??.t<17 ` Jӆ!0<ϋrA%NpPQ#G[J堢ɤܣX&5Lk2oak,Wbw/5d+%sdd2ET(%CAi\@HES( 9J:  1=i_UJ"bɲCHi=j{v`Y\PrKԙ4ǻ"og:=[urŲk;vo4vhJ`Vf0O)_ړ!Jnb֘j]~ Pimݛ] GXECT}眫le#q\B1j.[:'EeЇ Cj9 H *E'O|+͡2ŕ˯%cԝҿMf_KBT aܜEw؎!0232詾f5H)9 HT )pVRITM#_cUPk.t;̈́l\كNïuBp/ Hyz +$$ds>[ŖÞ%/R`Y͇V VJޮC ebR2 ^LpIhY7]=wMPI6m *ьZXn ,lZ̒e9"SLrdic= Lh=1Ϸ ZLk 7Zo-tc32LV+l6CK YD- GX$ѐЯkL'6#jJ">uj.A &I$DI$qP ;m%}9=^M&>y+b FsИ>_2RTxg>S+/\AsXΩt M (ZD-/GeA[z[9=O>;nӘnbiˊ?l܌ZULN0@}~rX5s)Dqt,Hp?G '޸K;J{%Bz}8h@`DA#y(Ӎj $QMq*%QJ-IiRG?69q6:J߃!tG 6dSKt%($&.gyxYӅ+9JN%vjZp:JQ6e$T+Iڶ[\_nUD->9?AIKjR1 A&AU(X4֝IqW&KTeNH MzX SM,lZis66z#. y~xVkHIHl4/gyjSM¨Hbw,8%^"BA$LR L >lևwEOEyDύFwc吉9'1k5hwije3e XrT Y@t"5kƦQFgR7xT\ 'Bh/@H}6IAFj<Y>sr(9'ro]Hsׁ;(8y0H:Θs0q\sӾ(eFf6+O'kb+OiA"^xM̬X,vrJ}_LSi#EK#*T+OUNb4zv1Ed;I9$H"$H"$OÃ;$?%RB}X8Gsə Ĕ眦YLqvIC.j/|zA&I$Q)ۅDqMSj@ނV ;] t-epZ>4Ovk^~H8Ye q*A LRIŸ &5RQEN\[H)Q*N o)¢ee}X490˱Q;Ie}̘960_A$q$%u-3d5%q&CIDФsP702<N{~&Z{gڼ]8vC`i]l⬅糠i1rNrIdʅs]ģ]sxRmX)RSTK"17n>MfJ֜RZfN߸3nbG# xZy*i5G W4f"Is:p7iIaԏBMIn6$H"$NVI$q">o5) e‚9~ᝒ3ajM4--U,]]j.ިxdp~u;  t$*)}Hʯ)BKoayޟ5d\Fǡ{SI14fi(ǽTGJI%|4 L /%}љH3)` Љ=*0l +DMGˑBYڄpHM$ 'lw5v6qV:aZ$ܦV2M%>dnxyJ>'}d͂y8@#lQLLQ&lE MJYLi~y', yZ9\R7@:HHhl2AM-#G%&LY̜yRUW9|>JIq@ %3}/Nb̵tg;xk3>)$Hbz:Og̘@B d8*#R1F 2moDfSG!"LyTlq4AG{o!aCtܺg:zsm;vO=1((ZtX)88[؜ZBs]otBk{V; __۬])Zںr"au͈t=LH2Qvl,X-WKиz9Sc>q7J7{08iAR~%hSžpZI؟_}@ɣQd:5.(La5A?8UaBCLsÈ5yDcGW9n&|6㗆P& "4&!<(I߀N-Q .UIu֏HӅzQ (mUqz%Ep4jWdU>?V>o~>M"nW^I$6ʞ'n~0+.Q7a[(0ZZE)\,UM@I'LV+g*f7Sf-Nn|Iky[IeS]$칋!tIbpIyTDj`5\tb0ܩ_ak0RJ[̝Mˌ!Ri뤃LЂk0{NorHb _HqhVCZ#ޛ I$qC#`; Lc_c84Oޫ؃ܜ RИj>/Uțј"{0*@+MmY:u@Zq+絮kR84=P8@>d}A"efK[ɖ# ,{+4 h;QW: ZۨXƘ2[?mSS" B'qQI-$(#N]N(ۯ|޷DDaYU ڨA{X$'&/ApIRNKj ΋?JA%n+=B*2]DYJpHX$ Љ.Nr_OrD89Z2a5uuUV 5yG)*τL?u o[˷R{>@L< Kb!`9%={N?+VFU5Npt`t|L2QK4y=46fo5mG-.Z2cs{ih̢n$ /D'bW/V9y@@DyV*1۷] 5i#Üy TQk-+_fvX&lr*ԄNp^pg4p\!cMo#3n¶7 J۫0zD)T+`eDD_I7qyPDA%Q׭U)~_!I:a-N8mt+2 I n-q .J{t}$UETge9=Uuz؊%M=tu_ɿVfR Ǥ5`xkf"uˌ֬ۋa:h5OXBET.Zu La֬f'OX!PJI=0 Q3ZΔXIJ"ZiRgq+pC4¾'D$܂C7 caJu+==XDM 21Lrws=m:?CstZ B~o<՛?l!2c0a۟c꯭kdƠw{if+B&~Tkub4Tu&`[1@+w@)1NO։єR{:S܆*:!('z~omYSfd ڿL,%ڿO STG^eft޺bMm4#[~0:ny#SWk߹;v3֯<@ؑ\}t}1ܼ=-D s?cM$@Y.}ܮ^t@ j>ՓCMj4}ooYmHGu<ꀵ5xg:5*ٝa>rjvIUwp%s+>:=['g_p6%3Ѭkj.}; j&^gBķ Z儭nῸSZA RI$l=*ms:(3#k0U D_ϩ$ZT7|($*mXOOVlRn*$^yȊEYWP 6U5 ;ZEbj3Os3<=^! Y`p^Qtqn)W-;▊pm,ml̳r>2"+#9Jr̙Ks}M=_ږ̞G:S:y %ih̲l~̔$jrV\wo'>)7aH:(vG0ӵ=Υ =?ycCt``׬",?3Zw{j*!D/m_}??%EaHFu1ڿU!oy؃=TlH3wO,=qS7gGy Ƭڏt(}? R 2)J#~i3#[1kHнh[QGcuWk4}νh3;Y&P?Hu&=~!hHOf3ptL2]SSFwh&wq#XY8$v_.a4) q6QkZ >HǷ[='OfhO~:n݊ǥt8.wgK;E-%s9oeW3eN}va; q{f*w"Uݺ柡"&Npp<=+kN8 F G45 S>h6Hמ!X`I 7].(iU>v'z Ns$8?Y >$8I*W',q7,r|]*qj:ȣ/;%xx`D.uJ mr0hpRs,fl4ʆƟ_ɶ&NI5哸'q&E0E}^&ߞ)Q;>^^MĻQ:5!qJ+lOTwgܶj/c JrMbe >؃طLHQ,jd$qeW!,A{ʊuC8$\QPŸL`~D_11ǗOm4,;LˌT@d"",;ߪ3ie2̜y=*$eǦE3dz9Dz̜5⥇D5\fdfif4ā|0nݧD'Sݾ{# V%D2#?=HIYUu>l-#3Qz~$V_sf==}|JxǶOmLIFk,w\ּd`tG7} gDjv=#u1|+rk)a~g1k[p#RZ8"mdb4=?П"V8#E:nێ*˧[^iR ?A㹭nTG^*8~15<+_>5zH [.ɮG@ lWlG( 3e+- wmH̔;jGqVm皀b0z'ka)Edxs;?~gvJfLz!)9^֭S?-nGQ$eYobi# {hZm):nFnw?FsVbM q?=?ۉk+ZZ˘dwpĚ <'%>D߯w ɬf^9|/m$~'[%V(}B0JH.ܨw9E/%8y:n{ܓ}U!Lf2U*2|棯s]<+C}|gL@Ai8\`W)HnW)J7L%)Ò|`1VIA|&CDžg͒|oX|ܛwYrK씪WE\ 񊍯c(w2պaB;nGwcwaD5 o3%6k3ДhghUT?ۢ?+JcM3 Rfm%;S0J#n瓸pk`~O nJ?/9?j%IdH$aD&}ǡoI`W.x9q"Z_(@v'#)ZtA8$JMe((@$_l~MfI$?K`K8D**qUSri$Aji⠐= ?1 a@-#Hц+A)QKJ0q^a(J oH1`GV _JI5WHRL &;">mGӶTN넡 ]^Y$!"SՄpXy{Px3VGnXL.x bƬAfGqI:AmSL̞Ks0}!/XɁJ"x!MVZDzBw6ϓ='Ѷb`Rw_|v(كr5)hh!:oێ;R8,Ln ѐf:Fb)xѭj "m2m RRl~ atl5J(m_ތ5G6ȔAvPo-@.?z!0 je>Eǭ[P>Ů#"mޱ6B9˨[{?դM-`b% <_mȔ[u): 'mF3FL>9J8v2xu.f:PJ}t|k+F}u('qd<߾a + ӝ8C 6zahEIyYT:LﯞpF-:nF;- uaF 8Ҥw{cTRH֥qm__(.ݲΜRcd[_z'ka&/>G˷K^`&vަGޒ1 mH)74ڿ{ _KIl#L"/׳pAnp?vO*" A ]R<]R,^yce`.8 C_x;W~'Ŷ!rѦz͂ٚFxϫ}L6kVzjtBт\j/tl.ܠCVrrʑN ct?b*%t죃݇=cs`%_A\g nɗ~锗vK@~X6ZkEx`3jS8خEYlfnXRf3C? ֡m dr΅TIī+V`]#5;2&歷D ǚ)e ޣ)zG= ܯ# , />G0 m>ikHV}I&L>'j*I^K*%i_դ*Ia>ݛ8ІW%~&:MN8: &Q*'PYd:j&qH8Q8a@_ClwV;}[ ƒ"8JNxY8@J⧋muj^T^S5a#J$D?M'^'j?U;ǯD}B|L8LL`t5KՀ*ǩ698j eE4m\_\($iJ3t+CN)ю3C(2i.ْg_&8XBb ifh $Rw"&o|6ϹD!gk{nCbNrz) +Q<|;_N \[3t! il;.9Sޛ>V931DğiOk[z [,_$\u^Ivfhs;.{jWmc+ɆU%tk\?3\Z) W^ xѹ iȀr5ӝȴY}4SJ6Q+y&:}S/\\!qJ.yiJ0_x͂yG l{4MS o8`Fwr~Òy (1A+"nΡkc+Rl\%xŵa|%:G#EaJ]?z^l .|6k,:wcxge>dN_\w"-CmlKLm͎| m .ڨEX(b$)֋6h~}ٞž6~y˧R|&_hr{Ӽ&wJ,3综j56 ɞVQvR R)|Ź;惓A W޳7z|4U0L!(#loL*]%p-*1IҒƦQf O8d>eHgJAJ"*Œfͬo\Ǻ6zS$o&$q [(H94o[u.8<@~og%2QI <@[=t{.NqJ\"Bg[)p}n 򥒏]f,cJ;DuxRuBMzN#=ࣗ&(W } V¨O]1W/Wx{> ȔI~m_ۂ5TVH"d,cH=Lv{WdO\G}˳*޳%mhl'=S2B Sv]Xy3qD be \-pFbvSD4_нp\M: o܃K\ 2Xo/\,-m_}x 2^V onCL -St. ~b)V.Ҽ5.h,^{kPWO ғ!6IvW/Zâԡ\Sﰙ;J¤Nܜ3y _x,aھ;du5^si.ܠx],Wb8y*?p gҁ`rc/|乒sd?+^eo)^Uşvy)>) x_{k 5sr`N#@=VSp<ϟ|O%N<hոM*(e;*Lp:&s\ĐRL>yaHaY唵v:QS(#VR ׍Dzeӈ8Dd*ˣwPIxkX($BR~3 MN O%So GDUv&> GjLW· UUt8'X %A{B)ȵ(8ʪϧVXG`XʕUϡi햨\6e*3oA7\Lt(ICCdJhub;k2sV?F$X6cmrJ jwWI$QImhץG$5\ҒK()&Ã]I?pm!3 >pIj9y.MQ4k̻BM2i6_l0xYkWHRj~xQ$p۟$`0yi&/=V%7aEngt{FHB$Ql-ho9$e+7t%$"?6o9t6Sc E%sƹfPokJ~8pq241g((IMWWHWS~K&%=?}O7%dwG)tz+8tP wPrCt}1)Q֯<=\K ~}ʲg.|%CIKCW63x!!WNStn a J/&M 3Ѷx߫]nQ+k'ADj2RIR.{<^T/ wWOz׬~ y%tP2ҜZ_9w>N~R Hdχc7Q4_K7nJ뗻\}a;z<5`>c;`\)x˕rXDZϕH<]{ΞH˛)(KWg_ Xm#2ϼD+<RtJh irzp6+yՊߨ(6oR{ D7h7秏w>67|6h+Y!2"nj<8R@;fҳb&o~|AɆFsgx0Yk4_{/er ͪŚa[rW\ ^}a}-5% c7HV|{}o=2\ZaS8E'3*JKT+⠓%M֚IЉII&"Q:FL]U_^M?'_$h+Q" !&)H%$NݤuV8Q邖9q9m&qܻ/8tLmi>TRR':' B ;^MX$ʊ&8?Ξ&< ?URIN(G)nAMP$WSyZ{AD/7rENyϟq +Z~1!pE&l!ZQ\[#<%+UO3o^7cV=+5'@ (%hh1{nR\w:cY)1S6+puM-ie$DNHv\j^5}XNh%q[d'#]V6z&*`#~{!SuPRfX<:{o>noT =D.s;`^R.6yZ#nޢ˛hHWUdCb eK%/Ɣ=\Zb&aڿ~d&){BKHJs 47npBFPOuʌ3\G;(JskVy[ߴ\ [89ḑZ{@O'w4yzceBF]uiԋ 8g>_}(iI}F7HYbҀU?m/1t.*ڿ0<0%ǏiD粂7e &g6mȔ$?sA .W(=щͼ./&V[2P)z$Qpjs)&)Z|M6354tqȔA~ m_}m] 矮Z^J G3@+[:1ӠA֧>,%繌&NEDžy^xQ+kq62)qFKݹB09L^y3Dg7uל.cR[(YyɴA+Kۗ:?`|6V!-w>CN [t~w;`!MMiC~aQ%s/ukGrll\SlSlA֙8#%:,RlZmN[9ˁK6*N[Za}Arz0M!eïx*Si5c]Ƿ8Y\AcC_|ܞ~m7{ZtZ`i8:8m+j 3ZoiHkJ<[rEem}{(=΂PEs5ky`upo z7)X ΄>ds->n}ͿSﰹc6G<ǥ> w+]4{3&X`"ͺe .YO TkS/άy^LKfJ@i ߅kJ.mpz`"Y+{%k\{ y<-ٗ _'ye6;C܍'xՂ}[BO}(oÜ&OnV6f@ɶ\XV%$:?^Gj 0IP".,zb?0n#& ƷQ+%jeU~ce]ooϳUP@@O!D,0 !r'+A$SQ1f_OG"Gj'ak4Q6:`$ӵ IyR9|n8 $QHX$ DQ+Qa$<IR&n$*HRk^>XlMj@`HhWkj b% 'h(50U֕lz*%aDGyde:j#mz|d2lIf8lcyΚ=pT 5$;|a0/ ̚%'A9i8NQA*e1{Nu'2c|~I" Qr6 _Fc1)$Mc8c}?.C򖵊sfiܱ{ҰQs WJQ6vھ'PD }I-M3 ~St~1 @ϯ$d/)rug8 J.,i0sjBTΦ6JN>|crjk$%-Q%_c6J4y Jਉ2+&a|%m Rt޺mQZ4O0XTsY ۗw,l6-MT]2)O- 7ټ*!;՗֭>֍ٜpx{,`4E  upk.P\{)fhyAݟE:ˎ^93<8G%{Ѣ9s4څ6KsI?Bi>Ff^BY|qG(w \C[8dX6ͣ{zZ3-WHJg@k;%%} 7Ix_%$7%0 JcRy ^/8g 7;5A5 g,Y d {ay?~xz]HT@><ʦ%ؤ,S3ض_ %^T&97L< w/Oxh)߃Sfr2Il<\'N٤nǠO-)EQ Hp(jƩӄs+$Gb2q+A*TS; B&t>DAL1YLU\E #akV`c$Y|$jV J1ğ Oq ru*a{g~/*M|S{6|$j;ݧA"ʏrb|L-V>jcx`A<IcIxwOdvu y{d_k+lŁ*'$jxYnO:a8vy\Lb ^C=0.\FCh#8%JRڳ Ic*Io1發<)plE3ui5zA,j^Qr@iAmZq t}o;NE3a\ДL]`PВ¾:o݊՛E ~byig wɅ%$[)ahpL329p_pb+ Lnަ=)NϟҒ o\YפT )x:gwg2Zoݐ9Smɧ^$9s dKQMC5As#ϕJٱTɊ9KwA?މ0Lek傢3yl#wھX *j$_lh:QھǺ. #趪ҐJpiع?¡A3zMc]{C]޵PqeTr2ophrgKZ"ȹ#QUphe+:q ɜ& %+mW >z$8`6:^.J,ěl΄͹n:c]}axIy oA%.8]w\e6:Giô}a<%]9nmBxv9W׷ۜBSҒb0zd xUE 4+^LiJ)g{v8w J+z ƭ纰|f2ax&Iݘ *\9m3\Gz)$YH9:ؽqfذaiF}%K&ø:y6QhYgɁl֫7jr]r9%iӛNE*<\9 W H'OwT/_c*VAKml&)ƿG#qTLEH&\%*)ք~/K0p\Lķq;~ Bi)28$ ĩK8jÙj#Dª'1%lS  =ߙQޒ"^T5jY/ LEQ$rlLγRKTR%)WT~ԾG2ï S?TR #QPII-IIԲ9ثMA$\ь{`VJx a$ꯦsm Bv >"b;X,ʕ5wTG$xʠyYdUJ.c344fOd"4b^,HLITyN$8I!t%_y!%-'o]opZAXO@y xEm`)f6n2Ǯaۗ__fk.ЌVAs4ze4öI}b0yKrFr ~!xٸJSR*eN b8P%gi\)QvdY(p%%-f(v@{V8 fS䩗dLxzQwjBX (kEe3@gX)>{}h$R[Z^QaҦ' msI\9-8x41Er;C(bH8xRfP'R&$axĐF,P2U%A oG/ =8hyQJ0]M'TR)ϸ}>k(Ydza$WuNT* ӲQzIܲj` ᫔a`gpYx<խojQ/ ބ?izuM퍼s)2J7qi?N$wJv6.:+bΘ9(eT7eTJ2cCHC>:"ͅ8. Ri:̜@!߈8A6JK/;l$DI;p,V9L{HTX.vȘu]lҒ>/Ҥ$|q^/Y,M򶞴ި76=Ԏ2Y"x&`Ċi.l' M>rMd0 {7oSMKуx#-|ϡsSю )4|}q5̩w_hѻm\?s8)V{0aqUw[u.`۠qi<[rպEm\^[53c7HnSq0& d-"i(~]n>+$ i;% b;O3IS^ws/UK,X:>xC࡝&M=9l_d8"Ӏ7e'wBU4}9-P[xJgx ]>{ٓCwd ?f*]l 例+H^0`+2mbӜ>OK%s![T~5 \['=;!C" \{yjV@_\)C-Ρ@ẋUBב>( ,/o?bn W(,Ι(=g` ͇^~dM,4.~dMV&AҺ; y˧L/Is9ͮEF Fݤ|fc}AzFxYjmam96ghʄBN#R/ǯH KXؼޡ8p:H_ !mB&5ܘb,>e77 g/ܷ_c9pWtТgӐ@%N sԸKX;UKq|D㩓xVBL*)G>ǔ*KyB" H yhj`$w_a$8A'Ƙ82Ѯs!TPDa+i|{!bl4>*J@<Y$qIa'P n^%(dRAe8f0}xtA8^ӆ D͋N8R68 +DDYDIi$JdpI Z OWXx?*4 cKt-[ѪOnÊUBu J5IcSHۏ"KN|Gd2kB LR+VaϮ3Q*y!$HD`Y捫]5%^|zɎwwy͙daBߏ1 Đ. 0:R!¯IL#].EJ6lXiK&{fs :ߒVk] O'm=P)XDSt[}!NݎEG ݻ]rA-Z!!ḾjEs>{w5@)9G5*|I {{=Ns,ny8Ч'N]K|}ED~66R޲ZUJŠ%AD/&1Bmq<r &R|$8ń :`q&Ӎ($la BH" "ڗZOFR5 /[V`p(骘āQJ&a8\'>< C$cIM2I0&RF&<V(U?b86 BQV8a$lR['d'|ܦj3ՊeX>ǫCr o7*(Qͫ%hlʡk8ϗiWvD)Icc뽝ɤ}9½۬IT6ӄbq͗xmJ8c-6?^5zS]*Ŧc_6y|/Y0KO)?WyV Wg]٥F ۿ6xtࢍk/tʳX o~MKbA=J˯qϏoSzNKWy; _k;S`ȩ}K` rjV/R\r>Ze%en'o1>:g\R(yv`L,뽦tQkOMdrovy.oTV/ kj,lpͻ_68m)϶ebv(jMAiZ ARx5ڑIZf erBvG{fXK 2* QWR WG)K2$ Dch]nSx@P$n̒,{%wп6D;߿ **&a$qPI*'6g:Q B %ta#>'*}p:dwa߉~tc瞞<ơL"Wɶ$,KM^{^{]k[Z- R(Q$5䐓89Oto:z:u 8xnw~P( P߯(yS@Y$Eh 9y D!?xJȿ{2|,] R˝j?y[r[#+8TJ  ]j:Mj((y?zH_٘K1Ue$˘bq%浓nO{Az$DwjS%yZ#ߓ0]vgs `ݷA'j G$'?~I)\uk*CJl-{\4pͪ+k9mfrkPxle֤5_XʞȘVN}#!x|Vik͍OM(zC O@XwUkئTZQ8P;DF7P|OB @T{l0Rx Wq @g!*@\}HgOK/?ggS-Kk1TLlkWRjW=C=ק{\2뛬kG2\3RI+}WJgIѶ"5" #y؊%v<*%I\*`s ž1mgpGDɳ㺖]f:WZq%Cݲ1N\0UN\DWXŊ 7\ Q&BZ٨&6U%I:)nJFM6)cGM,1;Xv~<8_3|T;(+עtӶI]3͍G'Q,P*PZNd},R#BIJ$iBli-dTDU(%Z^Մ$J|i?IIѷxml[bϝ6G#̖}c޷jݟ'\]}p_{ LBkAT?@|zMs8EkB: CO| )`@#&ZiXJ!W6$ |B6C!B~(RjD~P_ ?[F1\7%롄j9UqiuRE.v>k]K+uK%ѓ8;nPTJ+O"Se߿JKÁ@q=-OGn9Q.NP'DNclRzspCHD,5aOS0lDH>/h4De>]0[&~{P4Rn؍< }Ѯdb uK7f85NچP~MbIX2um)lrmWg$JyK9*~bHFJ1 ^b1).5;XE"[դJN&)Bn9x&۪'.B -ml"H^Q\s".U[&dqҵieWE%yj$xKY,q'&.5|4oDzxxlud17 4A#SO>6RlE( |ՏVy &C=EޙtoNFkM5`#mNNm*v# xVRo 57ғ1_E@Ymt:kmq7]90'VmnFC:ֹ cb SgQ͕bI6YF'HxB 8< + Jj#t?r'LS3H%.rIn2bIfƓ~LHbrZK[Hm}d"A9UIHTG,ޓ 97L$#AG\qDle;l2z:i{UNHRD 1Ӱ/Lu K8@+(wbfe͛g$PscI2mZOݫw]BGuw阢ͼ+9yYsFDk#IqDi;4?I*A'qߍ$_/= IL9|vI.)hBb#)enPSh>#ؤPgK_teURbYXmͻfHukj{mY(d8Ot25\fb/q @z)K(R4ɳqdٿ+=:+خE0&#tⲢN*+"y:HI#OaV3L"Jf+_Lr( lٵ^GpcL<Sd]N=m{"Ӄ0[p JEQV&Eբemc*רC&.c3+_[϶^wiju@ø8jUff<\OD/ZaLKT R)ՖJsI_d)h@#_\iXnfv]Sm&VqӞ6u(v|F$QJjoyNsӚ/wc1+flL;p͏ux^E9ul^ZY++l&]Bҩ p p 6+AiMYHc qZ jeMS3>ѕ&e9oV|uMSA ?q__\4Ͼ.mB楘iZ?]HZIȩ=Xc8NQN xfy5; w R, l Wΐ|O%h0+K9hw42*#߰C &G,1&2lgeM:'au)g=meB >k*'zGIo\vGl{ײI:qsIL[UĶɋgǷӷI#&,wlb0hKxl lF׸yWPկd8ץ^"lx߼m_{mj2e2uPNɰpHb7q\69vh-;^\ Gf{3L&v$" c8vHSQ >z;(й&_tqR/Zk*_}L=IBW5/6 SdkȥB{sPbhY9kόI4qZJDfmڽ!z9Yx:KTB]ZXoqVg=0@*!.Ց<sTAq&m5δ}l L@)%.5.K3v\PQp0(bP.lR},V㘍%Nz%m{T2qF\`DcPdcK&ONI(q]?#ˋHJ!fiGu_hDvśYa˛0IH)K+MYyzĒA𐆹&*S˻ZDiI_i-{'~7Rs<7߶epG:捥x󜫟d'[j*,ա{ˣkZ_H'j<ԕ^IZh TsZhn,G?|?z;4@5ו4*<\G$ΚRo_o+u.r) _ZhJA܁1whDIA 4@Zľ@L0l7: ^"2o`1tҙ B)S/ϿI̮ia9k$Io?y<[ S A|k,? !Q䅯y N/}Pr~jO YF^D9Һ8|fY{{mX&{0ܞX(!Ife%]<{D%ֺ2yYT(1qlM|wI+Ll2mycM2BGÌg9)]ypq-fMc󿰃dk3'lˆk[޺'G2F<1I#};ǕnRb'q[S䑜FFr.+QlpO[Ĵ)V ) +f u]\Duɣ/H(i[\/%I!Yh^sjMxf{()w IeASU.7[*TEkF@>zuӴ F |.ݒr)a5{QPTD`z;r N|RbK聏n)iE"Kt@:m洹22I*;Y#g)jIF&1hq:/K}\6'fquX)4-KFӱϳXp&JlVR1Fl;3M"qŷR*1:ctG,,"UN18+$76HqƎ\2RW-).;էTbDgkd_+\0; $ <6 +R21wەp߈={/15BoLݾ\76,zvK !*)Z]cP*fvV!vGgTj1=ҕ=J4QI"\̩842,@\zS3l.F?u͆j4E-Ybb{hf,\i@),SRs_zSۊ"~vjǗG?Uʘ "Ux&k׫M4mя8 /i&^,Xޢ5;8͐}kK%*W|88`F/$k<+K TWbfj 'rTCc/H/Hi7b=Qm ήr1QJ`ޯ&cR4ې$Y[8z ?ȒS3e_X{a9[ْo~GO% [S+m )!?~s<}rˊCrW:}T$?eD_D:F)At})}BU::,$k$&eNÏ>$> uL%/¿f& -;^b>r輌I$1K0I6/CUKL(FH'RJ7ڛЦ&^dh(_FZcNdܕNzUh J_\DDb >( pⲱ )毹=\2J%xl=~~HqhfO(G[E<\P;7U{0ߎg^ (e^4_zsHDTtý{I`f/SA'g[ړUnگKV5*~Aw_xsT.|ȯ"g[! i<%:IB[YC|}cK!,76IpaT}=ԥbG.INT_]LFΛؖ8溽@mT߇-a_x۲1l-#AG$1sME9eAqOLMTK%6)ĥrGɳD'lyL L+Ebq)ythbCҊn45TJ(Gc_N޶w!2 kBJɽ KLIR-GĴe&(FQ-#Kr6-EiMR=S$#tט>Ba䥙4m{]ffv&MxDW3ː%%ytb\uckR*%x :Hh˴[]2ࣙ󇷷}{=C;"V{uy:1n@J& E]?^<Ưc# g+O VC ֚p" Z+BYfo o-F#^a8Q_0Imb%^Ft3_|+扳.(ήeWS7|}ᑵ9.}Cޛn; +0S+B >5wOrfwct"((K}Xsf`o~VS/ij%Jޯj`أ}1] ~wD'3?ـ!MGk~t ?z`UO.6$To?=u+m~:Ն10h }2?Oxug'IzfHT;ݠy Ǯ낕zxT%U.{&O J58 ~dOCqV,Y9S3BȐ/iTSA|tޤL1c;seϯUHO #JmR|exDķOF\O.)̺bU% %nush2 ړCw#C{聱HvZ8U-P%X9}e̥&jL7^>y_սY;̮K$?H!6"#vZc2`{Xus_F!>zM.qq]&f|H$}Ncg &[<5qĶ1i[" M/" >X *䩌H~I &3,OƍqyH .{;(j&&y$[ 3mqs)h@RN/Ɲr78X.׼dk,I 5~yۆ]wMdx3Id $j=b-R*KPXL(% ØrIyBRiȄF:*/Bhʕ&S,/!화@${+ &Ndou?R2:$zx>o/`BpLze: OqnT;W?={Tw 4&_;%8KB${?̧~YuZTɥS/?pH; I]Jm ?r}7‰˒*u)UC̮\ nܛJn';VǏyHtiqѻSu>uYHkE6Ȉ%#䅛7y%MPQ[%I4I%qJ鳘)dldJJQ:! RBJ6YDfcTFU*8mklIMXfoږ"҈m3Jz[O0٬`\RKLE&rK!lDEqOFU2D2LdNƍX`qαM6x,uYFwar46TR41eiXXIS$[n$ #)Ÿ27d蓩ef͝6p{AiAڠZdӟM+ZT*M0v8c@Tj#FRDWf%*'C^vv+{&\O]>.sn,>qSjCI&QPQ sӆZ4k_w_,^4xܻwy%.6KtT@ ୥7xWбH4c >x$^=1AegvQ51_ϥYVڋv+#!м˗B)C(ڌJ Y7w@p݌`z7c?q1Z4gA ˚ >p` 68Oys0]PFLfXj-R>u'J|'yX@(? xMAh"Jj!/ռoJuN/34ϞҼjEC݀wު8_iW%O*?DݡRP^BQֲT/>"|ɥ%B?~߻g@ȶ5e ?aV/J|!E*+@j\OǓJ;uF _d+{!'@;!]B.1'CʐD'<}q;uN/ V11o kvc<×UgOſ, ZqS:U1n/}JK`>"0J &@j?74%%?IxJ|f>Uac*dD<5܂k,*ΣD[dg֏Sm#60S(b g\H$}{s:k[HۊW$d"%;TI1qqYJTƾ/j[u7 yv9yDa$汊Klv6\69#y9fEߎ84n\8&Q$ϪE&8F%ض8yaY}\I޶^eW5}]F!ig"gqPm<"{+]2@ -rzeSN1Y$Ķ̜k-(+-P\NABV٪LB}2 oDQ}.=|4'WJx}|mı?*J&Y}fi'a*d`YV"d:HWgu$}2E\b[HU.s,ke)!uB!E9z4GK츞X2yݾl(.3mc/OLHQZ4%O\ݍ&Z$Rlbc9dgG,ɶ<wYGLU<҈Kd= &y88[؜ȖG%yeG8ɳ#$l&HUVQ6Ǖm3H|ɘJžH⭙ HVʕf5 [`R4Tfwc ZӤJSVu:f!${_X]U[`«_ gOۯ:RC: ?Ooj]J}!9Vp~ +9_AfKsH߉mxX\la(BrwrqU7Kocu֊X{YJJA릯қ`dN*(.~g.}bO4TכV V1?#&"c@V#=g`-{`_/_~+QZъwBA ${yR afJ3_xUJ'\_J)`*}zDܶ.k /qqD'4;;r^n7.ƕWT?OIJ;iQkc=!ѫ+xYb<d̔fM+nBfo=wpr .cH+i9A<~,zS9<}.5/xrXa SUVH$CNbFhtlU3]_E]MTD`*Q-2%ÜvLJ}a%v/k~jMk>]kn^1;}Cb:UYZ_<Sh(f˼n8?֣bQ\^9VIcʄS{{>)D9!7B>L,O9 qxQ=(yύ0_MB˙Po.׏o=xF% MP"8v7Ỿ1&rV;?];A#Yd &Ba=Y@1e%ٯ[+H@Fi҉%JntHL3sTP$,bnH%qB2):n_Ŵ!$v<~.HwM",Brρaf/r{N< c=DA2x[Ή+ǹP?G;i:հљwpl&[ $*1>ٕS[=C'i^FS>Ʊ):ᱹ!kOE3L`&틤*}'x-4@G(Jt! }5sy+{w<齐Uшn86w,o+dt՜ݵ84&zWT\P@YҡYk/^X&owbbŋo ^|+z4ٰpRj$$hd{0Zǧ"vjΚ g")~7=B(O,N쿁Ph|w=n_ I;>{ÂRHށOk,gSն*c EmAglu(H&.uIQֈ%Rsl3=J˸F(M5Q[[W󁙚I$ldKOt S2IHFa7k)l?&G69xɖ  *&krbwC!Wd m%lKĥbl`^B@"7y_ХRD6I$.,^bLF!2u4G<\8l&Bɻkg_7;MAi?§?$ydC0"䕭icZ: J8ޚAI 6JKuX2pOҤ\nck Z#д 0ZhԶq!`nj}b&ڠm*V{;Xl^aG&@)(Q k(HtGEk37plF.7._ <{0_K-Bi#dLi h4hRPN-tNu'AѩQ?3 DLyΞ-rP&&{5֓uʇi,7MDBvuI -z}s BG،`Q k~, IBGi_WRc|~^oϬ69ފI8IP 肠H6QK0h$yZĔ4յC6,ܞ$,3Ǩtڒq| 8a~ʝxWNYQ|:mD&E("a: !EMF!ē8W%O$S2ɬqR5 %Qa4\Mu@ D10Z몋3UD%B G"ɛIUM42Rm3 YČk\,b9y%H-v>J<'l& Ķ#IT!q$s^GpN\4v;AȳI+0Wu-ES/dpQ4"䩝ڃ EaeگX-a&i$H)Y@-ڡ| V4Fo|R'QP" J⎀<7pc uAyA%)"Y"5)$ @kCvA:Yeф2" !'n"JA"ovfU)ZQc'-EeJ\vs형Dfë6 p ] 8HPrsp$(4]~_ke#Cbz/\C55 ~z'y7N.DeF~qFbfbb[nEӂ)#m$Wɶ=F,'#d\*&}mq>u-g;,#%w5Id4K0q\ss\DN6ѣRd3u 2īL>q+TGdyVw1 Zs9N=L)IA;4.SgXUʜLoRI%uO<tEB|@-_$^8Zj,Z+7!o{?ؽڃ;(MmtJ`.KGɫZbXd˅ʙS*qsݚhe*AxED9:,>GyK߾2 B#d%a'qjٵ6E\đl^%cDp[dBz0Ld\rh\RD 7cÕN~;O0Ž!Pl+'&-1ULLxfn ZE.%\jlgmu5U 7^S*o=Nz~W|ר3OyVirNVKFTJֲeÈj-([-O.ndfKTm)MɄ.TjjV%oZ &33\t`Nj@ (:I{A!ZB0BɈ+E:,ZIH6hzdk mx*$,758گX=vaYH 5'V1Ίo#oѻuou?աYHuQ,%)$39 +4I# $ei dsHlvhVv--[%j Do#w0!CxS"J.o<A-Hc"wiG21>u ? mq}$p2URVKڕgNC@zNoGuXn/vIK+O|̦كl9 7?tψ$ao1s'if.,olMD Y٘yV:&lRGqlBk"2(ylaؗyd+,ɳϱjQ\;~V}Xb1,mbIy9M^Ķ9XhLHmdH%OPb7$\đ0WC)dR5q=5f\3XT6NrXw˹dKhBˎcq;!cB*8%z>89J;)j$IN DiITjS.7SmR1QZwE,rX:V):-* 1Ѫ0R̔f=dDAjX2BdA;ʫxX*ĭ Jr;()ʈR̔f)eʺB ȤVWA2}d |qxһbItV~mɶbJ <2/ǵ@Jt졡Bk#%ɫ$y@H{>T)g'K* %&dŠI60Uͳ# i7͔J\δQA sF# ArXiğ3l9UO0$n##u5ic@"6Qĥ`"lKdTBP 㘊'E8y\29 E q #׸-W}S0oCJ$HN}ݍR|2jgB^|0|k$J$溹]O~BF\bVOYR¶\X4+B HX1is٬N#ENfȠooYp@ e׽L\Da:$$v;mbdۋp\xQ8RgUgSR;m}cK2UɘM(-/gqe/A6[Ď׶2ǴS)qPJ'6qNJKENItB5JVk=\!l.rzmǸyvnss=^seKd^ڀp[adN蚂"D=VܤRm\ SdӺ蔢6r L g;ZY=R#?8)a6,$؞;F ff r_zlսmwf#Sz,lTRmGlsU N+n&AHpbu^]xD+VbͱC5pSM2 fCe& & - W_NxqY虇iuwa95^Y&ޞȱ$6a(*R.1Ko^~d-"P@SZ0hųvf#wHAuDZ25L}u$ & &>0z\oお/F5!d:t^=b**%d$#9_dbHlM$1I&Gӈ&RH\4fs})Y.϶)F&u;>m#RHQ\3&*'SdsbșLx&bIpB"2TQ\q,tN{RIi9H( VHɋSd3\+kW\*7<2jWIBG^~W^$Q"BL4 IU!k>?sgb~L.~RP=w\~j> f6ۤ"泭V2ZZT0LM5iDYyєK-0hcZ bYDQxa%h|!iD4yHd8tҵ< ,I2\ I ' *&q%$tgWEm(N &ۄ=.r|cF%Hjgh#w0󱿈3r=I<9Bs^T:lڼ0H˱56G!"+n޺N^yMNv 3,/NQ; O0&ؤa9yV8yi,|\ %y$`v ҈kV2I^.u2LNs_a6Ig1dl˝"2zMlk"hvZUjQq=U.Q o-q$YM4m@GC')Oq ?}ìP&]j&E&y$aĒɆ'l1\8.҈MUHʈIqqN>. S>q]P2v}+(ZDΤwZLAi.d 2 JzŵPIkg2TEH,;(qڋϣȄQ.Γ`j̠`[lrReڗǖ=ģ{/"*#’!։XbJLEI.B5u[\vCRk1Ph?~g~=#}OqS=[7G.1׳YiE#0{$p&ua'<2TGL1r<dɀz [ĵR#&&#A%OdK4%DmE67,܎guc[6, Q9:JEWZ㨔àb$J!tR!US'5\_ %f#A},gBx87ơ##)ؤW mT{aRi.JŎ^ U/k3]5AJ -2g=/U AEH6u/JsS72N@P  (R~·IZgLe2IJEܤ^՝$eJm9E5Q`,|EN$#\]a߿GPkvAdU-Yy08P _;4~5@6(58M;lzb:=i>鲢Zk"Bkl&!Zm i)p7AńQ"训$ f7[âcB8}ԍ^dȸDb/5]ӎ'#8u$Lb|ñ(Q4?o#k $JJ2ZL i|4 3t.ʲfJl_i5Ի1#hǼ%eu5:3{ 3H"l:CFHs4JkHd-r=0N"zV9e,R9q&S ł&#qtl3k},o3-0H2j:iGHSr %eN]9FI03I)blLⲷt]5ˮMLٿG.1%f]lg@]咄@(t =:RRIlFl.11*eeHL$SG)g" #gG,ul,n˒g[f h_"M0I"f,϶ۿQcPD$q7Rۖ=)d8bZ/q\u< !.0 3j=2U-у/@  %(I&ya6-IuNrfgy>L9&;F\b6Z}#&IHdftj6V03O}g1put)}#zp(j8)a-S ʾP=h:OփUW`n T %l*%B\%[Q,q\0%@W"˙eNn +,ˆK5?Ld-IyV(1m"ɨ%^;]aeUFa'i82HjMTIOĜqDl[lH0 Q#t2҈M&1$&ϥbRRz$Ud$AL'aYlydke2St;OjQjJL҈V&1L7EaL\i"m.`m5&Mu܄'&k%m<3Ԩ$R'HY$M1|?̝iFJ+h-(Wt%RrMRjI. YLE"r{>&$L\6׋&.[ IoLbL2fMTJL"Ied|}j&{7f|[$C]uG&)R#)Re[- #y8vێ'ϞǴ)\J*O0fJ#0aE\iO\ 'yD3|;HHe3Rq)b3XaVy)J#y,ٶ`mR}s|IPLl 25wl_lyXg%Of ;̰lyX,̵n6NM)={0 Xݮ"GFOyB7I2 ge"I*FgG&Z/['$Md4OЧ(-˷pBiֶKHE &[q?&0e#"Epn8\<"IEN/o[sY@:1+ok%6$/"0HbJkiM\UYOhMjYY!$&T1UKI%$#X)LG"#)Pmr&ȳı< ,Nvb.*!9fKifVE66m"/ MQ+p۱jft<5e[$1#@)0NobmQ&aYeFNR)g6BcWk 0AӔɖǼa4Q3k Z 6߬T~ptUJȠB'EgءB1m#8Q-`"Dz/ABxxxxxxxxxxxxx G@ZP}J e=Պv<͸_ڊ1u9Hzd$F=Ⱦt"9gYd뙊lRX_XoQ:q}LZDq)䭏MXDu5}mGH" R$k8{dk\a %5&YӅ"Q$3MRKcF^O0٩ΌE<#yV5y<2IJ)"BLZZO8Jöڱ'(&*OddjdD4@*q wkIdOzkY]Z$fc(r@*2-%5}h K\nTDr.-r&0AIDLmIBR9 ©[л$PDIqry:ҐjES*h[N2λTnҨODŽ ϖ&|+;_'Y'}#7: S],J\o# )Qv¿PtL(M ֚8[uG7ީ|ȗk>ϭ:V}`-6γ}*`tz &\\5`K uԮ"MHQj}.N$(îqF$n|ٝBwCv:ZQ]tIī,~'^TE!q y9'ܲ(\9˕W_^1M$OV6E$<,&]aj267ICy䡼c!mf|8b(M}q%eNf㊳Q%aJ%y5&i$Z`ayclt4c[a;BM("" z0H"yfg/ k%MqD'| CWxӬh%ȻKsXp^{seHHXl+5Q@Ry!wdEJ#}l1EwϹ2AXu8o-gyyH!f8<}=37)^,]~)mhV c2!(nw{퍸K'8|ˍ,v^DLy릏rt>mM>(ur; 9x)ǽ|xxl'xx\Pܵ~aeמ=ïqm {@|g}A/ڔ""mobH 8@[`] &;69bI5NQH|;G,uWsT"SׇYV2o=y$;ڍ,pKFqTFU.6!#O'o[؄;jq%¹<{ n{Lfx}ey+vVIn Jedun w{Vѝ4ϞspjϜ6~VAjVt6^_ Xn^ImNn{O]~BW <2占-@%$H/BƓgŕe>OR ʾ<<]*}[kTyxx[6 Jܴ]M0ƺF9||㪃x~a[ޫ^ ͢lTĥ\KFQ2b@٤W$q69&fKdk5RY7.PQZvHaLߌ0vSUs0T&qv#>LH"+[dĐ<<50uapw0ɂ'l1\$<]&."s gTG*<ĥLbhzo+Y#˗cRp˼~8#V;ˍmL`Ep^|; PŇ~j8{Yg9}9y\b邆m #$E6=k6DQH&yrE&h /aoA&OB6ZkdP4NDi:ir5#\G4} %w(sJLq*&Z?ABJ K|rq!Ui7{RF/A^A/]z+4OyvDs>ބ2.YDZFH|8gd2,}M INZ=G3RH~E^/V0ĭu<\~\5>-N,EtAȐڻ=߉;OB-]Wiy\WZ.U@Xz͋h`oG"^ps p>z(하/*ۋ"xqβlDtLF'x>I$mr![hK=N"ll$U0c_a1y4F nO<%S;NB*&Z5'"(}/7}>HR`GLt' c:Ҷyγsv'K.QDg4l_tzIF'-ήU-a?IxmTJ,ĂQo:*> oЌ:QM?q *B40@%[I^tV!ƶCGQ1$6$#d&6E.1?t<߹Ml"T)1dǾg,tJ-s^#|9Bt'baOle3KeSڔl$rYذrH0nN3ʫ."ZC`tbIAegcf"3N^\  I4W01A{uZ?[ɧ*&:BP~G'۷͇k#S,9!tL=(pq^_x%"|HxٖInzKį}T,רq@7V|CuC< ^*w|CX&z!ܞ6^ ŋ$o>bcVKI Q6WYJ=͠`4BNQ]^jм=`; Z~`yWQw(ړL<X"v8'oߢk4Db.+{Wf_$CF ITL}v߼z&G GDw2\båV2*dd"ˆM0mpƵKE@ɳ%~p"j "Y[DnqYsljnE򖇥g-)Bۡ^$WULnC0c=r{kЛYj]iY69W0ec*!ĒQ,׊%z55J41dvChW7du621ÑYd9\IZ.a(a0Z]8IVC%QtEQg3Z҈W{>}&d\+Pஏ*k(~}u$!:| ",95cK!GQg^9{]k(U ㎿-N`dmVn7;ٺs|),ǵȡ}{ǵ[pз{Wdm{J.1 9{E.qMe"?kcٟ>. v7i-qdQb5*>I&MIMR_Ś˰2^TL\L"9ZK?oERF\y!t|}Qh/Orh-֮i7z=<@ %;|O|p Ξ^ycS:+P"fVK$F$6:m"؉I_$s"r\A%R}3<l{ox娇lRtpYQ:?+ ѕFѶ q8rOۊz.I2|tB$PNFGwgD",6V1QcHl5^5yO;=jЯJ"EЫ2rIȶ61$Q*&KxzYfZ.QH#yiDɁ7䩂H\ԑj0 Ny V\ZDPp0nzx ȝș ㏣(!@ KBu˦f |JfOE 9ͺ_>b9 ^jrs/ҹJ0mެW$8?=Űݥ>V?ݖ+%y=v3cGFE|7/QdP?Rd7+D߶dw7}}u=(U}^&q!O"J17+z"' 4^X0gXذu]bR\$<'8 &$OV:׎ﲽw\D<"(yyx-:bOcH&%l%N:IlEɋoƳ #y{@nB1 Rn#hnaz9&WI&~ #{dd!$o/j{!pSG(xq\j& ìr\L>ĞY.'?+z)&JbΜxgCj&Z#A4.vUdi&}n*M??.Msӫ !IR KҐՈT4S/_t`VJC?6V#3:,/v(9 -)%)!xkY \iN7ADچjŨ&7G@ CJԆGvMT;_zDjzgcPw̯>/su?|X*뼑}lK]_]k%fzeaiGdAhեQWm<'MW):/ێ.˿E"׬泱tD;?릢ɠJw ^˞Z9N7vd7mc*ylk~{>fTRSd58gc!MD7mN6vKGlJ%No"I(6.In+c΁TK0R|1Y-FJIQ\%@e6+~Y$@䒴T1Áx6y$E$FFqy$X|YGEJ.NIVղsF* $Qj(a7uUZ6"=g2"KNqyvBA$KLf}4ĶqIQ2*/R:lb6Ά ;,ru1ƛD8'Akd%U0QתFUd0 L[[u((O!܎xQX]$yqكt|M VU-LG\⫬|#Ady~$u.k-OZ j^<Ɓﻃ=L kW&ϟ~d5X蟐[W8qx/3!eP?~ ]D$_ʾ=HVhP:?$Nf>Vwe%y ulJfFKboq領 !қtS\+3'[7ƷVf _ AδJ3uohUy`[Y~>B|G1QxaJ&6D1xh涑,IuM Sg>I4j%&)ŕ0r0LRD $ Ky !@;͙2K "AgiKl,,G녋pbMpsS9$OewQ,rB싼?APd:_}.Iꝑ>VQ@}E.uṆ$+-,}4~۴ϯnHRRk)q7ܯ=A %B~5g~YYBog8O<~R(Z9ygeՋ)1dC /oD*YOo%\ҾT. [W.rXC)0`Ӝh]^=$?"r4:Hv \Wgë`F<<6Nvs7$g%" 煋њTz${|s?;̕H:DtiBEȑ,ϳ~wc2k6<%h}M$3Ⱦ_25?0GJI`b]SXRd3V(*W}[&JY8UӋO^QkmϷQ"N;ntY[ <{I*<*_@i{och/]zs ,U؀g޶Qd5J=_tMzol3?Ln Yʛ vM9hd4,́|yt${S{AiO[˞`2zxLf۲8kҾ@HWviIv!W:ɟ}橥&E(P턳K"))o- D(WZgid |\(sX~t'O=N"-՗/q=F+[,~HB;Y|r8ӾXG Րx NHu3r_~Vyz7Y}"v=%S?e)uz34/_@CV_ȉ~I&W9D$7YI"%O>F;O/J4Hp4xOo$FCOWkؑƊ>,cG6o bَW+GZ`'c?Ƶȃvfh>]j%C/ G=oc: r{A:L,衟"1qgg9f?PTV31z_Yac5q I6ɖpg=9yj#쿈dƱI)]&rKTkj#&$Fkln S9 zv@-o?8blyD [$3kaĕ<[cwL.QdUcڶ76&da&&3tkyTH>yDjIFʹ(Xmr{s3UњGI7Eaz;;"eK7ԅ*Ҧ ٿz:v4fAFpu}_u~1&݈7! 9!S8Y~,TR|3iQ:6g3)QB t)s$md8!DF+ϟyK0 4b%z<'Q &~ET;=2/NDI՗.?ZVfUT;ƥ/$QA|7YyRu(4O.r<>?r9"qCx_'NK!A 4޸‰&+j+Z#$ww2_2`hZ-B K_>΅ϿL܌ S$m<¹_W/VCA=1=dGJ1Ft5`c7j]v}?'kK21Iã9watM.%``?\AXٸ*A1@2qٶ_ѵoNcd.C9GȋC6bI\}V!q)'Ǣu\&Todp9E dЫ헒NC G %~dLĥV=JXѱ=V`ac땏xb+ 'Ndΰ0ɂBY gT3l +lݵ+̱I$&i$OV&J\x䪕#k9JP4'`;RBJHAWL4&:NiA+n"Cn$pt/w f*+X,; =j( ieV:ð?1Z;뽡\\%ddxxxx\cP bz/ѻ\C<hսǵ1XS48OE:Q]3eA"qrs}1%R4Zy~|Xá+qSYz\J2yc)Q yN0_TC ,=yk-i!_~A+%P !&?H1!DJhi_n"?{'=r$u>]wsL0c &G88~l8L #q6>9O~5){rX}5J,}#3 h<,>FWY=px'g ]KvK0\$Zʹx9]-=<.\'@˟~I+Pчe2Nd_s>BX(x&P C5N7 yCDqN kZ .akLFsPsy/=_# | #Q?ׅOE}PDϾcW?n0N.F푄@zoƟhforXmsxA's-9V_MVmfؠ ӶTI YJlR s>iu-O7 7G3LҠ,en@d=Mu$x.hvf6-qLe$bicAӶN|!'quđ54B8]ӸS/]oMמ(^MٺuJT"y <n"!;?ܳ Bd7w $}:ay̾ԕ4I7 L̺g:Kt.ǜk9G ݬa'zJnŒGy<.~!@MJv?}?T(pof.S;1JP%͒×8Gw32JF<Å=LFpďk< uǭ2E.c B]+\zfOD0ьTcb rϵ}۴>yŒ$;sf VpY:}jE&aQliIu}6a|dٲHǛ%i}&Pb*؆u{,Kڟ헂:$0h )u!a<~l!ge}$EP6(ǫS5EAB_a[j;ѕ u8NE5?6 53j.GIL&g63iQL4lS;1wX4e JJwI=eo5baKǂq{%o֟Dz)pO>_貾^ȯm %!B>L-ueɿ{+HjE5ZP?3&O\)hɲG+hW;4g?м/cg p sf+ѶM</r#Qe%6ϙ.F/cgʳ\h_!ܼ8<Ǝ&mb{pZ\8&fou<߫8Ѝyʚ,[y$: nԭmխ쎍tلbENXxMԼv8:%m>6UI`ZE%Jb$]ʅ\I#Ɍn!3kY;R;  M$PѸJ'6 ,M4Sdf_OZL҆%uH7cuGޒYAI[dxx< IS4qJքNf\2_Xb~7slp!6$Yҡղg#C Bg;B@S}!'&ᓡf6lbn&*ܽFZ#9]Et}yVܫnZ%ՙ~u(9,r$UO ~Y.HJ`c~.*h\Kl2,?x' SYl3S\GǑ .oZh^O_o)$3o2EEW:ۛ]͙͓~."dN]Lv 9z<=+BK&FphC׺l҂Wx"|gfԽ7H~EID/xuuqOeӪBL4Q u+*Em}W;[]WM$W>$i`2{]$,z1P @}-.ʂ P }YF8SrZNO }ᯞDKɆ?ȂEPpgouynAHu=h ȢCS x.m%AytCq/W9P?A@Ɇ,|!TRM.SmX ]. Zi.\GR)Ȋʧ.߲_2քo/j\|#Zw'7\ߏ?ɛvcXeoKwI~%KRR?3?Enj#~O+o 7R2Ѻ{$2 ]I(g>|73C=4N2e_豭KR?vCOQ:Ql#;J8yLi?S fiԹ.ҙiQc6 NH|&gkimU11U/D;@Ol̶+jiTEU´TtkhtXJ,s4fϓV8aImXrl@sj&I'M+N~ұ;},$&H 6TK@I<]*I7UIfpb;X2∩tG2 9SM4+UwmeMiuP{ AȢ3Q}2AWW?yУ #Q릂>W޼åD+ͥ?~(*'#ѻpEJ\C=ѥh|AٲfN7i\yqs[]*S0Rqí;R$ ǥq~SRX?0.1n%xlzq; f=_>ڛyd5l{`,{٫~{Ϊ(E˖CF\W۸96ɲ/ZiNڴ !Xmp+\gN[n@4j]"v85Ew]J>1,bTJ$Ax|6״}tTƉ$X4bMfub*Ò;AC6[Si@8mB#$l_&Ma*tR-K*̹PI*qM85O.IKS-TopJMtT$YӘaYd'1UON*(3[. Y84@%MB-ɲ7Gq5e Zf[u83#hSM&Cd_ KmA!7>t§BQuGٻw HKҒIBHvcse#Aj$Zk N-TԄ&gI[dbn&4 Lm$/DJeݧrY Qm46calQ ,5wɟ7nTWѻD5p \ܲuR-]RF1O#Rplx/%+.\ܟgJ ~ ]a࿾/|C(~tY4ݰE2tn4͏q3O4δI#t_^㇧ywѫcߥA&vzb^Č\gNҖ'i^6u}/u4:mh|W3d n l ҋ>i(д@M$ $E}q 8گiRTյDbĠ ؆ن[M7I(mX8b(,tTuRA^MGJ&Ig<.O*$1UPf=Mnl&fs\r~6;MĶ 9T Mte3u2,plBeM%xd>'MI%mB# m,rl 'Iݍ9E=h+icOcg 2J!T^ ݸto{ug:ߡ:VQx$?ȱ7Jw*Ibܖzv0aw~n-1]ʼnJQ:jd52Da'rހ]5kի 7z?NYf QɒhXκ$ai`#Kn(%Z s?#@7*.T#h{KA/X3ᒩ=*.i^W#E^A`A(z=xI"C#a| N\\:S="Pg@ӷt.\'7sw s9A"CO\W6.7B; <\3@>6|)\G'i57xD ^EBB0E{h?r$=໶\'g%+_ %+qrS=όɵ_H4U&Pv[]~PǓ. Ɨ8P?9BC:ܾ[c7I/a*{~.{ώQ?;Fy[r emK]m4C8C_:AsNɻwx>g\_эy@ FH݇=_yKv.*-H/H4.W@Ven֯0-lҺrVjl`@%3ԛ%^[X F,pU.]:K$i-bvo/cKLya}Ծnmk9/x&ؔǡT$Y$˚w:Fl8s9bS$ZTu : '.cB:N{ThJ~"M\_rd$O"6K8,# H*iV8wsw'$mXX+,s0G`G9fޡ0S6zGiwR.oI*6$ `#99n5–,X)RN@萧_~Ƃ˂Mhuͅ ʼnK.:.{sqӦZ2d'*r'd2 K%D]z&16kVc%䔂I-4.p1(žub&:lh=';$K[!b9 Cwɖ [C*'g#siGN]fnH >KEF᳣WrT{{(W@ABOǑ%ǖB:\aOE}XPp,+C/  /.9/KsP+Zp2PT!:E#V .^RT7H*t?Zz&Dk;u[\Mtm$t M_?U {8'm9TI0$pv%tzO-ucRoOLG/p8^3lD*f{ʑQ^hY`_+_yv4z{tO? \vѵ҈&V,W9(W헼ZKGk{\'o/<|֗Gor竾 gUgGb9B}ͧ.Lb/k+QD}t+stu?ئ b>lINJ(4"9/.)8S͇Ӓ۠N3NXay#A:3QN9h%PԢMGE }kP̴6(Y !Q9p K6[d-bwA4 MޯD.t@=ΛRɁX9uMM.gQG2K<,f\D4,(8@rvz/%h~l4pmp2|-_x˶1m#?+J|T_XNJ_fm붖x]"gJҜ:thAtU+$/arNNc3$l+^:un^LB%ݨ)jI:ĉq>wx\ ic1_Ȥc8s$(1mtfk>Kcoڝe]B$ro,1-mln A'i;[{ߓò$Ӝ= pMx*ҍj69ɺ 9ެ,(bScg1dysNb~ q;UT*0J{8HAq?‰P=K՟6(uFYS䖨lŞx0H&}t#9>- L&ղ<&d0K<̂KqQXk(i& EPЖ\0tp }Ryd5Ts`QK%:$s#jn ( TK6ϮTzV|籠fA rߍB%R3#~>R9##YW3o}v˥<@(x1k6ݕ08{>{BsvrxDy[%2sUx.ٕM1sF|{xaoXWuL4UC8Usz>c9%Dz5l5nwruH2R]=TFb*H%eHV'3 pŜ& c"F?^~ZT(I .IKwET˩MGJiHҀqdngr\@"& I t KCM60ED)s\F\ǝ,# I'i6{.sB%6$nB!9PH68%|rsduD,btkw3#jZ*I%IXfcK%rI'd6V9i8ĦN 8rǜmi-KBJoJ!ǠvMD)͞?LUFíMH6:%6jL)$^דPڒEb24˥şݐr .Y%iʛ,NKC l[bF= &=J'E22Wy[BJB~oMac8b ZEvOk3GXyd)AuwF&(l=徹Gy|O o E)b/+X鬅ƛ!׸ 4_/-&}{w#pvLS-xC@ݒ7q-.pk2K݇~,RTmuM=]{,Yݪ[@)ΙtawoF뚗Wys5EK3HD^JtA#%S缝[%?xÿT> 5ʒ_ (NȄtJ(8ѧma 炀zZ/zb\G''k.\5ݗoOSy8OβŴzPoaU>rf3,x{.A7GL{D}ǵ6O_;+],ܵf'Zx3nLleYIڳ[+:ܴ :I{6\vИ DN%Ūg3qS`H/n1a8l߳ zi%i7a6$T>I+cNoFIV.9`đsx1Ngzts %!ٵoTHڡ'ͳ[$9.kXeNV96# wd))l:f]i;O43cfEؾ`4%6XВ Lli 'im3ΦёL$cT31dEYKp=ʖ3't??fNQ~0'w̷JDЎh-SXFDMɓhtaZ-Wh?8QcI."Y"$LAxanrt ! 4ksޱ P6u[^m h ӶA ybq%ܲMRro~/ +m!4YE#e%%@[S@E }n@(KK (-ּD\ՏC^󱮠J) yG㟚<6(GjwnWҦrŔ0`Um[LBJt\Wˇ3nmɾN`|aZ2 !{47Z9N)j"'w➢ZT#1FGS1$= dՓfckӐi mH1^u;b>;Yש|Z@X}$;|RĴ1%UM:tc.ylEg$ollj#mͲǶL6n`MrIVYۀpGorI J$ivW]3E%64I3wJ $]6/sIX$,Em{6);lZVOl vA8a)j&? n נõ\SjvRY^%j)4بu$A 䆝ЍOy̸g>!ͳO{[}!٦&)@MpbD1ҀzsyzX#*/+8[dM"),"0?5+YW[Go; LOW2M4î-K}H??i.=)#.YԞ+!DkҋnIȤs<ەL5ɀKH_KEfF7<3۶x}vp= M M 9,Nj&I$ 4:mnis3Ĭc.J&6$tb\p خ$\b>]$IpfƦ":I' $L7v <8ɺHh5,@ᬾ%4TIɂRrf]:;ꤍ-3M $TI4fc.Cjf>#+x3x^'5Slvm"l$ʄL:uf\Y4Ė*+ffM2o%OfH O$miv3YFHř\(s3= ldC;f``~t<'*o*^ժNriDKC)gYKw |[nj4Qg 2q61f3Cg/>3B?>K?4??F P:7-LJ8RP"[}:RWmZ,Qƣ}%eӋxk\xRHe/EPKliT-;@ m{q25"\YP֚ KVm~S>~.#DOD|ubǭ|s1mvBvc6Vݖ5AR Lk[%fפm=Ze4Z=s=T.f'Imi;;۪T1Im}jIB@>@Y_gX5*&YIJI (\VgL6lb7oIMEqSchdکxڂ;0R6i{iQ1:9&Db7GҀ4i'Ԙa(6$.Y}&6p$ .I~N]ә9Ҡrb IԱA&fYJ'ɲZi֚[n '5wmh &5Oi">P㺅Ll s'8[R6H4^`T=nJL: &6%4:}dۥ Ӧ)36NF &6clFm Ǚ(^\!QgvPi-|Btj;̈́K}^deNa 54 %z'7 Zv5Bh]9Z/GAHD&mf-OxNx[PWN\s,8KyM'#>d.E[- h%1G( $\]`u@mZЌ7g~5Xw#0;.gtIKf`ـ&I($i3!zYNܟfVGvHkMrXN?ϛV2J\ǝR+qz `)Æg&PbDlH"L[,6n+3[@$W0Y&+f tfcIi+~I,vqlv/A6E>ՑؔLlH!x=LmBCT灋|:ukf#KOW=?_{L$Yv4IHR6ĴN%T)A#Y&ekpL omF@Nӡ]uPiwJEbojYS"{Fa/imU!\TsB`.C˫^(Ҭh˓eW,z ٸdE7/2ήkA[/ ҉weqxt2렁~;?$jbguv%\:!g%qb=PqA>V量H~*_AC$Dok"d<_uu P #}o $ħYH2lDJ->tIk0Ӿ.ϣF^SCMttmy?tK`ikxzn'<'_]?Lܟ^zM􎂬~`\DeKmۋ5v$en=NZq2c_Lk̴IrXnājګ&S( yA $6%cqŒ)s66Œ4t]6 *c_db4$14uֳP:LXޮ,2=>ETLrZiC$˘%2݄M-$k8C%&,bZ$H%OANpdMB 6Ĵñ+ 2%_E)DZMHB'^|<# #vGHJydQt„?-huP vl{9%5ج|X63 )^YIs25!,_#iIZY_Qa#:6$mҘl'4SO4Tٍ8S1|7͑ZeWsFQ+Ah V,_)D߲fND .UEnڋ߲`)~ p PCM;etc|:.3B哈beE&: p7Pg3F*C'ҡ] i<2ь.}K5PC3Dm4[.jFU#`{6T$<6!P:n00h @ZqP[7|AIMgfw,D9j[*q:bq3hF[5o) kGsZA9*[]u6Ah̭ΤlVfٮ%e2U]eguit=}g(ڨJ'o_Ծdt;:?qЅ (Ifcc,-L"VΦxb"{'NSlk-eL@QsAgfcǖXTBвqʸ;ijpmx6*H'14bMu$zI'$ A M,bB&id_ 'I<@;&K>:d#mHIrXZ=]nmq&ljreL+{Lr6iL+nWh tl.o$>>X^^9`+_W4zpxi%MI8ĄEJ&$bd%f;%vCpL|ҕKaIÖ'tlJM $GZ}>ݠ U.:%LEB$[nT pULҪ3^ +_%x:4Ve4K_$o^ l%qkeX*EhL ,o)$e֩vpddB (Z {6>BF=jɭr濉59B񯢚iT DձRzm1ԅgq'NpXf)I[gJxu[#Kǩ?UtcdSe j& ?x<8?yCWޘ+BMFzd@ ZmԨf2mȯ c EYYǜP '\Ќ6voс{/W;T|Ϧ?Zx.5j ;4l(D;~i<MxvDEWל\+;ֺr )ӵCVAqx'+4{rqmjqb>Ϝn=3ח*MEk[oֺn`I('q3v$=3WǙr B1+ tE4M98; ڟdџp h?.GZ@:$|Borr]ߢcAOP#A[yawxO#7VPHyN gtskYQ(\dS3w#"Ey5ƀqŧF۷/^ﲩm+uZԁyW-~vIxvBSs@y`~ M_ ypTqWXh1Pr(aэT/\ʻơ5Pva,|c(]qJsOܺ]a> |z(y,_kKs۞W76˗+֝|LtiggZՈʦtns'^I/O˙XV+LOnIoǿUxmtQ^MS)'w;8bS51g\T)ğq9(b[rU>y=OF©x\rؔplub$ ~؎L6=|6;x\Z}ig "6NЇM$94ɲcD!fk3EaI$ :#Dl|TLKƛئR11/֣iZ6?Dsܾa{`{.hJ8?yzDeͿP4h\ wu ĄOlYPI ?d'~؜:$rɡG8yPypj6^C-et8Llmؖܛ $;Bd3R)F21aHE@kAQ\-k*tvD[vvM΂ՅƘ)ʛ_wU}& j|JIeV/h2ZIXZ0>ֿ"m;80O=!3w ܀v'=9]DPa8"YG E5r,xTqP_3gn;w:647Z*?*$x_#<1%~r WQWN]V_%@ `[Uw/ѾRUb*R:OSUf)+ tҙX>H:Tn'^ E3g}~H/lBH F/\F.r ?ϥSWS2[.&t^L}];=lL! ,$Jwwtٶy''T2$bn6O},foRlPrlq'ÑN/:0N )ʚic~MtVp8&$bNV6YmcuD,S IIMĴI֗HI[@% Lxq6;2$K!)pi |#<xf .T>'4T-ٶo0)ZVNqڳcob[ޤ%t<6{)t[vupo.|Rd)ȨA){>Þ;$6ch iIK D񧧛ps!_ ttAyVOW8RƛѰzt=3gWonAR:zI[pһm6ӻm{7Sp<֯ytmNm.dbʉPѬf V.}o=\{pNI6u%[8}V6l[φM=qk|"ǟYpIR%¬iN>Y %4t$mMhܷ8[nlmb$I*&]&aS%ifx:a&d!b I14dk9`LaSIB"Y%ۆOlG IB+6nL:!6$=M$gMfcğ9$F= y#5Giҵ`RvT^]}H3kMd.I2qJ*ə ?AS5|,>"#:%K9I_󍳊+jQZqۧL:9`I#26hےpZ6|b edvtn̚uLjZlk$- fNEט|9ݤ15%*[^ nTMBh=JW-s'(-zK]uX!ݑ'i)}5gx/EngSe 5Qq+\L йCμz+^b[NpӶrq?E#(YeA[6Jn#O3W[yLe"cW^"-u"˛(p~R_ lDGHRrW#rMDDLLьE;mF "ll^%jm=;nx|*~? =(Gjp2+Cn XUPj:0m[<;E 5. "u':6Ura, ꜝ7~%ϯBVS=;eћJ4&+RY_:yv_GP7]GR^@cA}aw˧2v|qctRjkuazvm5/8ʑy&\75}-wg}!/6^+<}ﳜyG2nmٲ^N,3TIS>zlr:7pmXd IIUI؆utII@i*'LĴI%b$~N%abeUcTOL4%nb2iIS>' ,qX{W@FĴ*fY`!,.:i I\ $w36Iccy Y'1LRmt+f򎗜ROx=lIrT$ގrLRŤ}]$ i5a8&O?I%e9g3O+&4Gd{ϮwEdRT01mrs:`k|$a9 zh &$i$ %7V 2֖y'5O$Z8xPgfD &W(lBaSB>K#Hv#FW&R* J-{fFr뎰o/&/pe"6>.>6gt(4ta-L<;!|XWȁuG(cvPH!f1 bC+ԃڲ4& NB?+[\F|ƚlŮ} .1f17x;}֗6wE:V߃0Wzl}4j֝vk ~jejDp`r_,0xvB3F05˧`q3gw J*u d/jp8(Y'.a[2*[9jnjq=BHΏnc˚/Y6<9뎰FP9?~pM8@@qƞe19;\Ȇ&nz3}ʭ|CBMAPlٿ}qy{n6mH\yFRX)27>Qӗ8Y.'Ӝl.ߑ' Vk!j_ B=WfסCwnzzfWbuw.֌M'8YcZl8Ѿ&fw7/]a8zL{$Y}JI*dHn>Q.a%i3HJTN}v &w o)hn\bZ9ؔK:$grp_2!Mq$M$V7Yv8汶"߳+4 !ӝfc:1mmYiS*1KL55 4(!iJ&6 ĦHb۬/lr-<CrJfL:yڷJfB"Ip$ݦ R]S2.Ô io$zԂI4pFc} ٶmQkF߻;WcW^'[HlL,ȴ@<<9F jhVPw>:sz$Չ %2;׮b҅hY%vlgW^|d>cO~Nɲye ܘqRy$٠4$^-J'漺&Eq@"IńN4,Ւr7tY$$= -m|^)çC{$hm~͠;%hq+?JFpv):\J/Ћ@Zp] 0AK&olV9:~l6 ~>v{#rwtn|u\ ٓuIcٞ{tkc%amB&"x<%gR$ $,$bb{QvzNwYwJ&Y %2R:3lqN`IL2V .Xpv<\|(P U,M$i[<2["my$lq2sdiM|1[U$aN6F:R:zL.sd-lOAlj%imڴب][N~M$/i+ ؆$&LzD%$,:i(ިUnزܾ՛\0O&IU,E{CR[LlԹY04N 04,!4*tV{X JwZlq!4d!N N`i.}xn?y&DH"l\v~ LՒ醓\%K  &+Gb"Ũ..pi?٠)9%IYIgRp̔mͣ5Ej'c{.^5|rP$JP MT?`Ԃ 5\8UO 9?!t)H{_GY=6TKTgruD5R.вDBy1ՊF8uJԃ5[ƥ"Bj) ѲEx+*XS#[bUBlF5RN(o7fM^ͽ6G8E3)/J K*ژR+yhװJVC`mms {پ d7$SLs:/EȩqYvaG:L{UR||֦j-\b&IP$ If?3-t},eNE3Qz6ۛ$\t$ѴBI|'pl68iJ& jY:fUcAʤYd}O[sx]qPU5m\'iB$@%_iguHpM$Z'u&IxvB)Y9>&EHh=K>"0&,T-A#JB$K6ILIeFdXجpҀ1HS#1V_r9@N)i 0${t!Kll f1rl˘]:YL䌄,>aBH+T2WhJ{>YؠkK̺Me?ddC&&ݾ4 ~u$MKC)̷( G(JϷzI2A;j/E8j!O#tzpzoZ"S؂ &* ЍK谆_jGJ(1"Kh6 !6كxCWN@4ƊͩFXW>y,Nll֗ј}~"_5s ڂB߬@;vo yiنA0-QWgw~-=ۖYaRhcd.cTK;Lb%wf$YeL`(%x4< l=sFuPIXJ$-s@'>' tc3fMId]e9$p4iQ NPo)L@.7ڹo MYdZwbTLڗ5{R(6RZN2h_ :uJXE,zyEXMhb Ӆfdxa2E*SVR8QkԂYaSN5.0P\G3lP &[vbI¬c) MUGOY*eϚi KoU*`C x]s?(W苖4V XA~thQ+X[֘'Z9U~9c2 Q#Nr|{R KoIc;3So-*hK] UX}Zsr꾾cVc v,311O<׾5}QnjzR([=s+ݕ 8y,-hَHRp-[o妛n\.;/Gw]|fi9('UJqnvN'_45}tLb~&#icMN*%I$mXI(IexsXV PdV.iwcm^kf(pI uUHLw3׿8l$ɈR9ml 4%n,kҀ۸xRzב,V>9\ڮ&XͲ&Бrbcek+e3& BɲI1eꈇ'5H7\AGPBf`9™z +H@ j5lEgMm&ieWZgLr_Mo6iw)`iMs%iGK2a,]h#Bh|erB*&Hپ:R1qB<ϟV130--\}`%]zHܴ" ^biN5U ({^?lv 1I/0(8E Nq*7Yc!ͦv_a`*ñ.-&_Cgמ=δ=XҊ_g62u]˾煼/P}AΝ=#O-r\ aL瞋ߤ20mV0!h2S}qq"<:$R@k|iuQ:hbC2 rYj ==P1I#3zㄑUºzFנQ'vh|ߣ(.5N~Uՠ9rE>~x,yLg98Gy(8 NP][.VH!SeB)&~rhsy.SvAe߾iǂ'=VZB)0ux} ?a 7k mX]ts9}1N>gӜ;1 hV*bϵ\:t]v}vvر޸s=oO>4l6[bc@ǘlNf7o`UWw裏r]w}s4 J )jJ$Pl.COA_%{#5@`K'\iqP;%߫<k$ 779žĖ܀ĨԄ .7M͈ǫK xl: 65=_7x#E/Wnݺ9-xׯ/GіyLR=*' FH>)z''rl%I$Y.#''S"V*1@wrE#36PhdbUkaxE8lmY<ܦVbl ؔKL[y[YS,PobkKt8l $6Ӗ) f9t9\#LVId)YJ'4u2ɲiwBA$mNoAc`ĦFVGy [dNAz$*<> F]EMқ$Iv%[J.18(1_syz"1ŹF*w]7l-& !,Yn$6u&4Lrl7Ytd)%@NI`l̇zOKŤC\,Hua"!**jLg^S,|KVnxLN@:K ЦkGtVް`2YyGpp}BRtJR1Z7?^X3ҊjcjI߆^so [P駟GᡇGg-ŕpds@' =^$q'#ϡ>Dv;Hvŵ\ѫkcǸknȁ~Sdx_{g01L]/x_E@ߜ띘 _"_g>ã=FOOr M9/8N_pp`O:T z%v*}ɔNу]"U$+< eOSpvMQ䀉b8S8E #\]qbRs5A硴G_:۶nx}k[9xs˫ܰbxS/ƿm*iIyQ-՞i[|2. {$PKS-dv^BW68g*'YJ&&TbZ޶2ˡn N\3輡m 1@, *uܩ馞qx4u4 j'6dKLՐNFR 9<@n`eˁUF7ʏ,ED0&Vm6%i x@i05ӛIr9i:&DqBܤH2MͯST{\<#WWMj>ouxzýPC>RJ|Uc(xH/n&c+' tR.I&i 2I*`lLUJr6Z$?M$[ޒؓ2ZiTL=2r֜Gw& 2aF zL}KZCW6Iy,ؕ6ZGyGy,W>>c~}jؑ}?l۵uAŋ+>{/=Д:IXW` [*늈(e(_?Gx|xy ^s8,8 ܼuEՃeٵ7 'cu'i^ҼT%o0x2?y>OQ.9vǎ㕯z_Eٴko~cwv{>1Qg1>\_| םۣzg?g?9FGGq6n{ɫIn +PT4 %A!#9]?7|,9Pf34UgWN-ԛ>g>pz+yӛ̾{g<'N>rǘK$HKLLz,ꙝ|̦Z1TMΩEX|#ĊM 1$d6\fؠ3^=94 >HCuŬϏrQeꗩ\FLYis^ߡ ۬{P#>p&9JYecvlجqLp\۰w[yY6HE,:Ǭ7NV;=4X$M$ *I*ip9T+1mpl>Ι4u4Sd}(L_,TkNTDy#]ƛ<9jTrM"˚lL9\'T3#OPr\ԆMSeidXIdk&ƶd̄;p>h?-Yua1S*[CD/b|ɼcEMY@HETGk9y7(ފKPGuu.2 NQFy,>zGyGy,eNVkN2%^ﺝʼ쮻8s?En ~t*=}8{a["Pt! <(XWDLJ=]}v."|w=^qp\`F@87 5'>q Txᇹ_wykx^7E)<^|7?Y6ݲyyb΀Ҋ(԰u_z+G?4eko;3Qro7 8T\sXQvU$?sxS`؜#454S txg Ij%B..>/w}w򖷼7jx篼|w80 $-q,%j%Y*H&S˖v9XؔmPI/&*1KLeNC2OlWt<3>ƪm)!Y8p'& nzJg1`>gJH$i#C0za%S˗Y*' 4:FyVdÄLҔQ&ٍMN;rd IT.f 7t-,ql8 $+&X7m9oz0SOLɡggOrjYຫR13)3eAmJdD}IJ~ɏ^L,[뷺h-MyjQva}iCdžS+c!DL]tHp;%6xPK &UgȤ(pfmHJƉ_1>)jddѣu:D_ D1h4JP.%r K'mܟ=zE7#<#Dcݿ6ny+}+_OO{8~P.Y~=yuEDpJd/q@,bRCH ~Ѧxs΀ `.?$6 'eYt({(nC8jT#` _\*S(4wwg?S?0oDH#v?|d3kY7S aA4busկ|b 9a>} ֩ٽ}hW҅ *M%^3>{w'x'w7ͳW\~[lg:%ӗJ;H`H!۾'ҕuצfbͱ%ں9EֹlSI'h9UNKVL4 )`Iu|jYk /e7I~Cuxz16WgGmDjPRʬ71mrmNBA'NK$R z tfN9ktZ$DlGa"lqmv8k/rdE4V.T1}|òg)f(tP$y Rؾg)NZwҊZP[PG|1P=S#`X,DM?REk{ &~۠h0Ca}3 /483 l. jm:M^1]hM|vܚ%W5NdS%I@[%6$m^ 4pFfcV6 \[؈6ȉ^:2FKb "BhF4 O سRPell`Ɂ!4zсc5F~GyGyۜs0D۰czA&-/GG}= (F7Ķ Vd]pthC h(hM'G(_Dk_{y&vo;_./b ϺY*`:H3&;^w77?>+WBPr]Ûw\'X_h0DN]6 |{V񗏆\ g_e<<[Q+n]NZ$q9m簖Su l廍4hT4-t7_ǴIL1!ZP#mI4|xoyuH_Tk_}'΅8KZ1GLo3,H2,iSG!pw I5 |emv;zuRT(ɪ6}T&ːRQN3F[WQ/E91`gnAt~VFDQZ9 %4JIGΒ&20_]&(T0R.^4Æ"hcM!R\@5dB6::E:^bM/:ҝ:.BDM=$1MT eMNI'S$SMV.vtV֦p-0%7rdM1ĦTb*L]R`n>1KNUҹ J w$0bMәlmv:N#S&gm"6pΕ%ګ22㛘R𮀣{T&nhߌڇiNS=XѤS4Rl% mɘM:I?JԣcޝBcSI&¦d ؔLRy*:3.qIP%mSqBcI,Ie>8 FGPYgsӈ(U=3V-Kl9g0q 0G:qw|p#G>M68Gɒe Vޜg'uw힙WJGLWWUTwW?ԧ?ٚ  rsRv ?th#=XH<&RѫVUjUZ3.)8o[:|-mm殻׿/~8.ka+װr1 ~g.Xɼ +ů~+^{5r3y8e)oI&҃K|&bJ+92B':n#,NYN€8HgkAHP A(Q&oM7m=pKpHgB,>8bg8ym$nh;p2,&AH I9%/:sg%!aɛ8ɝ8J8X6'X6U*rR`0 'L#$mx3DEU ?]c(iK4h7ڙK%sI \OT bڙpaAlU%5i3&°1Y:Ӈ`wOi2㔃KSTD9agTaol }m,&:t&v<ė%URj2cd35"V'ekJNLq,U`hkbfM5qi~|TJ24І]HT/=FYԆjtjUZժVUmr2\ob(;P.ih>u-s泟{5<# 1Vϥk1,OjǔXMwC0 yG>Q.;q Jľ8&S%3Јd8 28F8撸g"KJS`ȐȢQ4$BǷ.$Zmj̺5IPE/R6>u|@4L)?a*$  Q)Q $\Wa fT=(v(0SIHT1Tȳ*dZ(#,USJ&?̈R Ś>tJy+l%n4ȩbHO%XRMr4z(PtD9MxqqҚE)IRY9')QXXOXe԰Ҋd BH bFQ5_mw5HPgScxd$. S%oKİJF&S4TDpif6^ lTj\L5UIgChl" !4l #Ϲ4a8414VX|mZժVUjUu\2 o&.i]{3 N<(|׻/74Eo=׮j+6l9rn5gBVo[Z0\A}MwnϦ%kEwCfp'eC*V]󶷿nTUuJwK--i |L+WJvF24%#g||H2OcO]UdJz4YL4?-ǧ 4#A`I0=w_DGię,r 28B iTkY$,ݒol0FMS=5xl?5h$$M@ɶbB%~چes(LRt8)f Zo b^,U{8W RVjUZժVukFsDxÿKOoO~رT[X}X4(zs<1Y}e= `ȿnRl})d?Ӵ6,W}r~ƎGw#)QΔV gjZ%o}}sy\.Xd0dY5S$A+%[_{+_2\u v_>:G,RD y ÷Kľ{ɔ(4)2{eRr7v3IH([7Q'Y԰Jbi䬵Tu͒lA҂1nD>(̀)r1 s"_MPRJ& * [\[ oˆA):rQూS >vՎL0+iQr9QiDJ+WȼQ778@'~CHLq jz(Gy-դw҂=]p# Rs8ApTЉh(N)AH[ Ӹ0|GWl4$"@2G)YqTPǞ M6[p#hu0F[}d8*d*7~Bu7Ԭ}P v!yX/R63zT02TjUZժVU(ݔq0]qjkMI(0Y5@itF̭j9&/M:泟,{>a̙3S).E|?'=8vy$9 g9A)eμqttԧB ⍋MA[WgpGc3Y"M6~c |9_! t'6-xy7C*Lg/?4iT"Q%AH3f[X#$uVBsrI KӃ[0%ɝJi&+ #PWIh>c[քi`C׃x^928aNkM5 =D /j .`d:y} F5QE=l&aH0TRjGU&L%qL$q 8f`~Z)Jy'$ T4(6(I$|NT;z$ehJ;@GB{_G 4q٤=}dO@ hNҘlr|{8PVm ;aaDpY%-rN;7(lU`q1(wVlQ4$^ <]1Gy%-6N8rA" rٕD1Tb" 70ʂZr#* h iJɎzaNJۣ O8&55Y Áq6 qƗ|1gkD;t#Lai\e0N>We/Q?2amTjUZժVEO5d4x.g'T̚ _4uf -cޫNjGg CiDC.chXskqnNn>>2oyտ^?#xT9oh u 8?0- iZ/kRc@֭Ʒ1\CƆ&˛=6~Qw6o1PҐ CcCeVLC%D<ď z @ɡzߨg1YM 'ApIp_Is%$5f dNQBi%V=ۇ",vezR9L6 0G3_ROk}>Xg+;C| H$VWgpT8IqAH,b(~)Yr<[O֪+b% :qiA9wOT (?Ρu nTT0,5i{D>\W2<،etuz\2u q:T \3l B»;g-Dc #(Kx?ёfz%U;MmTjUZժVS`$7Tv9ʳ.CHfΕ!L犹XjҐw5X=1~ښZ~?`;gYx]w7}#k#-d ]֋9u o|瘉eO{Վ~92Ep$> oy7… c&Lk›w"-(`3zA&qJ'aƒ'gUDı1DlGiht^/u9d]7n4xz2,/T0 2Y>1~? JX:'/  ǁHRO !aiJMܗH:K˕T*dKn āLQ +1%\HHp_8xiaٛ0IL$̀*Y!LPp%~*{$%CBLq hJIJ90S1tst6).1O Y`Q1̯[`>FQ\唤rv1ki˼%1DKiQ}AI,&:1ENX"? Pdxfjk3LW J-[ON04Bk{X*p6 >Ex`|>c$S9,,Gi-pl|>UagF)`+8l%k2N:DU;J[ժVUjU9a8;PKXz1WʉŽJl``˿?C$Rtb Qkc O\{|3ΘVǟss Aw npQu—ӎ__|k_C 䟖'dUc*>Bacw_=555eiȵx5?_ t!YJd x$S%#w D}K’8KYX?'iсscf抳]ruks0 3Ӆ] ()':[$?/Rm>@#ֈb$A)rub4 %?V۪#̢E(f8`H$NT $N%y&bf(|MD2H%I5 1L[}\hp5u~nv $ ,x47cW/i v˖R)jjRlܸO3|gժU_yi3]Rf"'\PW_[=o~/| $1 ޷2%s$$Rj%AIP&O/()?R"2I!㮝](NxdS$j10'1:pAPH)H9R0cH<O`Z8=̒/ @]< 09'M l,$q!Q7SGG*͙:3xu<8$$\6pY#fj{YY/d0DO)#E{M- |Vcs kF9ue`(@J6āLK&>PA#aI0<ӣ z,&Bh. ;m%>$nJקQZN*-W,x%`yOpGgQhp@32Lf.}nu zV٩Qh(=UpIժVUm͟ > ?=QZ+n~ƟͶk3[!$;MWL{'9uY$ԬiLQk5/;& ,|)4wP%{f/464pǟ?|_iL%o裡Y΀^21OJy9 .oO}$1K-.kf9$axft(MR0┖g@ʀ0K;[kX$yˉa0?#Tl_̞-)qb\RFOL3JrlD4Ϳ?߃r8{7lYLl:l%&S~4{52)ui~S)b+ɵ?0 ~^uBĂ?T"kg:r8A4NI\Hx;,S @6)'SǪ#€0H{)RR:Q(֔j hecF,%Q&QR)|S;5&iL4?CLR , =[9ȜZN ;nqߧka4)$*-R⟧0I) ]iQǍnC@Oe1 )Q9<0!jk3_D~QYٔ *{q å&,XjJK8".$,4*ekAq`cvN%GϒB3gt $Rc-Ȏ3T(@ժVUx,f0`bNF 9YlU:5-\q}0\֢AN>9'KN肜ta1v!/q7U3[Gj78)hH44sugܹ(Fr _tp}uLi`ײ-p*la iih殿}C׿μyϛrѵr:KgK וhQa*>?G>Q JZ\eg,, 5`;I{Ki5Y(ȻmR@BvfOv>fSFAґjv 4@|AH]+x˛\|&k|::oqL3%s^{:V*|敵ѝPbIλш*$ iA]0bX3y.-L2Ɠ9b ~CXIJ;"IqSǪ#1(S4r9Ql&qR:Q+?/ DR|\Tz9H)`0`$)/m,H"c%s0D (I5>8Fr 'Qtem*w Lt5SVW4WJqlV$ A&"VVA3ue٤Th-Rض5fb33u u"`ɬg-\V\D3 <}{u VULVma `+4g3gRHF3,8d1C0Ψ5sc8׭gl=jM3\5nFY5FlJ" c2ГFLi=G8Y\`q_%-^/V}saa6$XgsFM0e,eSboGwfhߡӟ̿#|d2YqU]~;5+r aI"'M5TOq^B"]]]?H5pq[XBSz~H0ܰϻF5C9JL0VpkO0iIL<6u;iaE)(Ji &,XU'qf8ؾXH/psgbѪs1nzK8De[ #iPϒ;ij2]نQcfgB _XC6ԯ馛Xp!'*Cr;^gKT2n;); H2x;.3ìkɻ%h2iW;\떽5ؑ{@xS4'ŌE5h nvư Ihk?)a_O+>v|)1[oElל`~D-c7XbE:.zySպD[ fky S2ay3$F5*dDf6)@֘H˘P@#(j3Qh#!+ I.\ÉgPqz+/vMg.BgnJ-p BA,sZ9̅:[*Ut4wFe1RZ@h\}\ێU?w 'k_󚊫ją=~r,iqR/)ssϨ7p7x#FM,KF0YjN O(43뎍J~tVpnO(q1c6K@O^.![ X4*-_ѧ[Ӛ_uڼkYb֞<33sw#=_?NCCC 5.>DPtx0P IߎbEc+Sگn$SIX gyߧkR>"3>* ӂ&ņ:84 Xk 5薙ZMe"LTr$i#ӑ b0cGJdy{vǯ]pX%`R,&qrq $Qq8Qm !x2u@ʙЋ'p٨*Oۥ%Q@ F,RD6gQ*f )F9:'2Tv"}K~t1m#ϰw#/\z &̦GIۣ`GW;;( p bRυ٪@p5P30f $j1g]A#:d53 *.$b6&g*Ȅ0̞7!IcfAx2Ғ3{jHP t!j;s{O{,4|{FD`|t:7:e!늿D2i;w|>Ŝ+hgR{2?ڂ5:]B؃53 2UptItޅ v(t;‚CyKq Ga5E߲+O|Ϻu*̗g`wteGs#EDo嘦YO~ْafIzKL ]i9j}ڥN^ ?uLLQu: 5H1,SXmWp;θK3(Xo?dS>WUe/[ZŖ-?e<(\WԌg JN*L7Ry9](1]:ϘZwWy눾M|g6:Q6AyH?Xo3є_f9Yco3xT֒()mLy+dz1ɨL(;4*A c {;&\זR1{ĥyؽk1mXۋA&RTԑ@ٕ12R24TJ0\! P)Qs8E~|1p"}CLBÈp$$1N"dX` (`hB~Kft΅G8(Ŷ'BN#:.<1{ћ'8oWc-˜ќYdVJ9YX3Xx>Y;{og.lU(.> Y:{-u9w 75Icj=PKә-;n/ lۈ=, o6;ٻHc?ѳ]0fka3G¥3~yf!qCRw\V !R&sfRx3!V,̙!fw>@#_8CLIUjU|@J3S_!Үx[4/~{ﻏD- 1%!,yHbfhgOD0*)pmH7!I~5Y3bdw}6ɲU,lXxm mstQڥ-$֣YQ(KBwfxxۿӟ1-u?e#Sw\L=hXfy5G?11M[ ^"f7c€{kLSW+.:U֬q.B‚W_ KۢD]|iRhsI1=y oӗ 3?$ql%Es XI$J',C3垊 /0HTݕD*sZ`2,sIL\$? d2HrH0-*_8-/!XK>5U'ȔQ$iϏC@&#+H4ĆO9Ɖq\ "*-N"ǫKLY$ #QK۶=n8kH1Fڮb|h8"=ZƦ2 (ViLE"bwza) q5q"4T 4ض \e/ńM~>ۅF9&m䲵Dkp]es[1MYVe>B#D6y+ZW Atnrg{qlK Zȥ-TNBյwtz[A_}#PZaHUCB&hCHq4(UFa+%?o9K1OXQe(ᘛ~ml{# diuxiENx>VO-p Ț&jx9Ug tc5Iɻ)yc0_e+1tXZns{t$M_C8t*=¬]Zժvϕd cE 3ar+bOZW5)+I5WjYC1Ъi>\SӜjeWpœu(ǢfVu }#]wcEKc3kehgrW*.P7-ױkpѶ Y$j!0^b>3͛>ƗXւ-;i1-:wM/͍Ǘe︼b_w?HIێ>.zEƱ`ณ Ә 8.-XXГ̢]5EaGtSddKGS<|??ɲR9K_WƒtJl8"^*V_'! $)6]pZT:n$cIɤ4FzJ}r9U2m"CEl&AI$* .Lb,y B?$=j;|8*êY/eӢp$n2]i1NYM*LG'(SJbgF&!Tf.]_)(ـKNiMN)ٚyt&ϡ/uTmA:ިcG7Q$~}Qp̥m9s{Qt b*z"6w} nDkAcp eha((h[quL㏎1$7+b\fVHg 2\´Hs_پGՔ>W6#Ԯ+ a&< ȴ;@eG<;2ocr:6`,ZvlVtirI'^}/pwmQ6t&8uY6-5OR0wAF Árcg>ęrP mXgٱ?0yrS_J"pcySh].dfI_Wx+ w\?E/9G9jͲ6PΓ9Nw[^Wq`[VE~LZ zΩ |\6KLYa>PQ[B4w4%cM*m\se HμmSJR/{D#VP.!4~#}Qi{>ۮr(ZS3YI aDH $P%4*o'SV' QJ*h$$\gʵjGU9gL"_0$NF'/٤q~HDIR9AVT*SvSbb:P̶@:(tԦK[c$N*b,T(ؾ`;PzE0ФdN0d4 ;ɾ֤Ұk2rٚq %zRw((Ԍ408Њm[X֊6ӋTt;U]򯲖=+ B( $\04S~Q;fSvn}R\/E.kB m\y Ň21\PpbI.YG{G{Eݾ};?f2$ ;ZG o+nKr㝒dbv]ז P_}?lU+ ^(V;|կʎ-ҐuթR˞R1 $"tG-_s(`2] ~Ӄyr'z*LKЉ&er}x,wB3.a8 ~4"G$0/ /ǐӋF8 E/ ĵ/Rvê3#G #jx;$J'X: %\ !aI$މ, &G`:ptZTA$ARG&F|'67D* 49qoqva`4V:4"g/LyD(?30ᔚ|>A_\*2bL3fRJfEΎٮHdj蛃3jIػ{ƣnLSVS.g2ӸO 9MhgfZ)%'bu@+y>X) 3dJa_ 4&X;w=sI!ZkRfj]#$V:8 4̄ *%ܥ\bY Okbq!S:A$0ۗ )Њ^wU5Fb.dҨAL؃Y2;Dș SR7[r=Mdv̜HplH2;qrȔyOf|g/옎c o1:4M.YI6jL!nnS҅уz9萌# 'nQA-|J3+A.㗿%oXqŭ,8cܵ4){/{*}_i%xɊ:Y$!sPW%TC;pLc j4 -|+_lEgEcV[w;˞Ay4hU[I˫#"6%i㧕4%piqA"ya}w8ƔCE?g ~)U$$/Q Y(Jq"Q0I% Q%ϳyk f1D1EFJHyJIāZf|IT"k39;eqdt@,~r2<d2+AMt0z8GD@Oi F @&Q*Q=*-(iX/?ٻ&LӉt(b8&pBS($m'GJ =UǞY|3r!4Hd60K_O] 9]HC1*×)%{I KߣC!0)^ն`*{Ϫ#FEфa>dDUMEK;J*?\ܱOZ wif01t5r:ïd YoԁDGLo]^1,S JLW&'N2?Jq!lI\<Cٽd( RݕMMQnB/4JI[ou xkn]HZyUض@;#M(߳X ]g8{N! 9&iBujU<h8d&S8¨Ep>3,KWaJrGP9w& 3R`l)Sv=+0%v#-<{p_nF:g3pn쾱ۨH?S}KصjeFXƳ8sFv~.OYg!txN<ݻu.{ mH d#鍝5A#:$ߕ1 r8CYDDX??н{FA0t^}!.0 z4}n{V { K &SkUtM[{fk-/>X/_Tm_۷caPbM-VdD}EKH` % L̗G ΥJ+v4bck=KV-踛6mq r0,FrvWɣA9/. h27\8nP%Vߡw>Gp sBᆲe5 VjK^ou_g)bRdR?+-8YO*a0%%b$o& d6p?=TڝD7iS$l0c'{uHXΌ,h|MTZdG)\UG\Z)擪Vf) oT撨AH$'\ ~u p#QR7~(Ɠ(8ƕp;*+@ D1aCkʸ`oƌh] 5=T9ЕrJIK :a}J b0 AHG*Ljp>?, u SƢɗ:.u\<I6`,ZZH&3u&ni#A$LC8%s"LVmNٲ`jUZivlRk^Ha&5GԺtz<{W;)w}ƢNa}cht,0 F7uYSYZيŔ#lckJW?JQ_Юb^ל1 8']! I-xPmi5@ϯm}sIF7t{fo8S!))t݋0$q:54OZ!qJgR{l[C`g Yd i- þ<cWT&ZsFU\+x@-X-Xc !z~̶~|AHt?\ei;#Tz f6[Os <, H?OO6b`or!I Akگ8qM%}8ytqhtZ! hq͘=:!4O[UO___שI֐l ܌f%/X\k֙)0>nx+_YQLsL=#N$ggqCWK&Yqoӟxꩧf['a}EvktD V v41q!c'Σ!!OcA1/OJ7d 4׬6ܣ|[o,cyso%3)z28f1A%>$/(Sɸ.JpE1WL(6d̈xGzr ^jz^)Fb^p\!*6)D5(ƒ(9JXG@Nxi%QpZP' ~R'*o*cUhaYJ%ar`8I)gRa IP&ݯ3 ' Nb;\NPNx;xR@Aak0{Y[$QSv!"*56r[tM;Yosy*-nKŤ$J&  {$(ւ}{QSu$ZHGr*(_ !t&&P!4BO# OO?p'Jv p #4Y՗Rtgc* 2=MSmMs0,;8UjUxB )jzv. 6}nE?5`ZU֣JGqIdt߰{ &^STj@ۊ?dvUvڼE υtq;KuE4?@38f4@}iny7k}fd`UǣrA/Smd௻юKϯvj7yTDN='1 ݷBOoZOsAf$-r{GXgZ834~x/܁cX4ds}n10ffٿOFd}Ar9 36n8[I̩E7ݒ>#=Н<]؄vvU|H1ercEiǬ^S+?ҚNR2Ash:cqc! JG. M{֑4J[J4A_bmByHdjДlo56N4HEmWr~ucQC#gZ08І]H8B"᳙%,#w[l8O2Dv(/P:7^3(o l[;] y2λtߴe{1u4Od tb3nae"-cCSCok1',lٱ10,muiJ\=|+C@ʀzcYуlU`iJH5񋋦@P[czHoڱλt3xIo-ʎl0%1F7w %G IsIþS"Wb,ov_׿r^Tލ1$k?LJ-B;UVѱ^6l$;L>'O 4 )hZUa`BOQ8iR7aJ1QWaUfa@Hx$$  JihXf)8i !Ql#qq#a I0ODC7TL7IA5H`HK–Eօ 07)X2JNxނ:7lwA} W2vrD8RIjc0-7U&dqSPl_ٱ'"bfSS*29>m`cXyv,F)Y 9WRC3P֓'il64\XiF;120!m2:҄㘳\BjrZN.WsPiJB&F} e:Ῐ΃rQTnԚ o!}OI.HYҒi'7oA$~%M$;KLhGtr30Ez[?{޲h[\D)ݺ uI4uMg."īr o&WA2<蝃},yY,kM%"!Qz~Q V 7cC,*h0jM<Fia Zj`pTModޫ⎕f$5JuSc$M=Fniv^Z.˵QXȣh[ۛ,~zf` rΒKK2"'av 3V2XYL9RP7 a@[ORz.v5!C؆[ϔ쭚>#yv}^D\y’0HoOǵLBe' c[r$a*?ilWplŜV)A@Lm:hC%מ)+xJc&ށِJd`ݲ ;koG%2;'312`8[1Ueg\sa@JZO'{ C:~ .(.%mMt,>fׅƋuޣM54$QczI{ V| |&ߺ ;;,|VE&=b_/8<(>54_pxK c6j(jS/A4:㌯~{EorNSi  b߶u ܻiOiDԘhm=ZX6VY!$[KN+L.k̆~6W#ZSg/ };vp]wq`YVm ZmL}T"YNF,P=g5dyVq9I1iaBqƍ Y[CS?^qjͪŊ 4uIjj+frp͋]~:׶dTbcc)% a6m{5)/ovࢥonqݻŋ,w+{ t.6_o<0IP*R)r1u0ۉ*ԴN{$SM8m LL!Dw'khBx ZAWhMLy$oʖJ$!$R.oX$*oM9FrUiUhFJK*fDŦU(0x$,[g~'>$ H{:mtHUKYC>/ZWZQgSg3*؝UlvH[\iWc==^XbI)LNERam h#֐ D-,S $X뗛~LHXj'RjbYj`@0kHm6 IFI%h=:Xhc1%ބlё&ZH9`:B(\`Ε4tye?.dѦЎ0kйLo z1'A UOՎ1p Ԯ F!T<[80c=8H ?PRv3Mm۩_=cfӽ =FHlvw%tx#tDdDJϯ8ZL3U&Fomn4ˍ_n!ߕ5 N]"xEwO$XӨ?q.ǁo 9L_,hJǯKBMhGkExIBW?z 7jJ2YN}EilG헯jJI$4Y\{×E/ .\FП|ȘK/6c6%id%BMe4jLriznB'p!]ov `o`N#,y"WfLx_<|? Hd/wX2O32NZ78|+ q;Kihy,KX u7Qu]Z4wx0ad ~'$ztfċHdw1]hŰ$a^&XS0J[|^"?[緰dEeA?H%u N[0.8܎q [8_݂leq\2a'(hw{"`UT7M^e kL%o@kHZicswr^իO'9咵ˇg%Hh|+O\V<3v㏓:eu"UCqe=Vh+sӪqTx2?[9BihF}߶x'naX n{@$?r9{eyߖ hM [(1-xMd:Z緒v`/׍lR P^wLdoYJKLEHa\Ap9!d $R>k4aGɄ2)e%k8i8Ɠ0I?F%RjGU&GYH߃ sI8-? 8ՖX`H`_9tXMdqKG/ oGR8yR1DO  AO8]-6z24.9ՠMc3.` ~fN#df&jLMTe HH|@IkII]tdܔ%)a;wO"Y`}ӄhIsx=H#|ں1F1LL .63iY #4T pkV'])ɞ]+oh}?ףVqy G+\{֎\UAvi.ug]U%F$cOp 8yFroeKCC0~nF'䧌12i͓(iC: ]$b0s_ˁb&aTޡO1V/;lA0|b F}mt] 7''Ls̗F^o=·J>d!w6-5.,m}n6i?ڈQqg2pNXS15[vb]r,P-\9"~n/ZCө QY='MvX,l\Ҧ4Z*^Z0̫_*=rh߬}38d?QiE}8fN<^Saaa3خCRaB Qn.gyyG*!Xyڲc&qS[:oذG}LryIP$U[,!p։zULF0<܍kl6sm9p幊+ru|% Umt\rmL&mV`م×B/c0"ǣ(QT\3K& %JYce _F}H@!13: JIߔLW=Dlq7}Eq``0j/LpDIؔJ0T{#2&NJmO#U$Ѥc)>) &[@2kGǁbbrQ x&.H`E|c@1i{B )0DI8}(&1bg5O}Q8M|H|PIId:2=2FDSS}N;(RɫiܩW.BB"KQ_?J}LJ%ËLR`dtH&bc\PaWL&E4r=IF!G~뱘<}k;jk^ m2Thuj_T򼫵>F~3ax5.DޥOSxWxr6=7?IM[B5o*Y1-I2F9 #y\u+o㞔<=0-ׅ:8jFs6ӰYcMD+eҠ7FfL\V9[)ՒfWB=`֓SI/%S'36IKrZ7s? ?c[7 ]i:^ѐ(dғ,8o|$i*79ΚX5þ>B;͈6y c)D0 .$"/6(KΦve'3>awl Lvh1! ̻m-ic'_BEr 3&]8 OVJ{=4--Wl)=2t]#Z3 bZݶΟ>.hɹ')>\-L{ [#oq4y`̲o=.w;IF]0 jښxxmH%^L|I6k2tnc%б+\AɇK5 N>oMEߑfAvڒXj*+L9)b 8K訟O{\jBQpFiT |YX߳=8vhMU6kN Frkh;L@GCi1Z0j=Y.roHӜ{GgT/:.,ҝ|Zk`l|qFFh3u y7w:<:XJX@?ٔtυyCߐKk~M`c[qul~ ֮) Ysq{ʉE4cIԾU+FKq*e*]uNsg3b2SOWMKT`}0g8 D ' < 3ʥMo#q5qR,%QH 'Uˌӗj7/GKڝX 袅qggcJ>?m"3zN~Cp΋, +(?!͉BNQ_הYp%sAh'La4S zEW^sV!r\~/,Н5dU L8-S%q{)j{fbEDLzu&(33 PbSS㶃&%" K* 5J婩F Iosl||!i:3zТtlUҞsp$B24X1gq Kٿw3L(70-jN}zZ¡ ],ojSyfaH^.K%8GZ```͓۠ڋQve+* ݻ4YPKN]4$-8e;&PyڕmXm߶_=|ᕒsW v?NO\ X,iB=3E,-d |e-NP3<3 pFvҰB3׸[ Tl(RP#@EOl{hn' zN(*x>;Fa~18֌FPɚ4rś.&J-O|c%j5֜U$]k1{w [ۜB.]2K]~,Kܔ+({ܯ|na9A,iAUOGBV&kgۏPrY-uN7>={)cMryQp=C1zsK.a/A߾}s}"ue cCsK:-ۆ]v~=}ߜsl-Ž:Z5&NR6ׅ:Xw<, meg1;}YX r9eC`6h,\O;d}{Oib85X+KāK(YÓ E9KiL|lB2běxߕ8_+h`(?@ӄ)N\+b_ FM+Ie&RH(^ct> %*=x o-5 up0-XWU)B mYgK:,S(F>/,D  %(vva0{ %sF:2ǘ2~(d1YE$i$$vuqӞZʬƨ)(9ӸS^>gט7xqww|n[-Vִ) r؍AGQ9yQZN2/ :a(:fI8@t$ p#;_>$ 2<:l♝+dj'_P*'*Io<{֢5H9%v[RY\oUC^jf%+N#q;1O ZPuطݿdVߠUZf0z ЮwO1gpMF'nsrz(M;^p $?2ay&z~7 L x߻m^BiI\[&)rtøŢ͂v3z`Iq݌=у e0t^nۆNJVϟ+r\ IC@&}"YS@]z~BC^`q$kD-u N["pL{0˾>B(HMa=} GA]3/tk=4y+&1z442R`g8pF?n|}{^ Q~aqd;{ {qF\[rik*~l WhSIo9H`Od Kr9.x!=J'L5z栤DK?܍0%FEϯ$DZH5Ǯ$blj $0(gFc\ӤQY;mq\=/|[Hizn{Ӹi-$@rqড়ࢗ|h`򽤷R',|2De>m^k2 {GЎz3)+uyE}_tv St߰IV /_lBihnIN=N1VBuaam ޳?٘b=t|3PWT{Es5Beہ5y͢t|:[yɩ5We oiiWb<3R(ktPOP޽{yꩧЀRCI*ṙ%)zp ¥/vn(R_ [6)QeÒ8q&U{]pdX #('sˇ늒)U_>J'/Qty(pG0| M~p㖪˝Q:av9a4&zܱ,~.Cfd]_dfWFq^wnl)-9 /"iJΧ :y:uQ> ~ b cGLXa|,|b5 w3dN=}:xF>hJ)IfZq]c:prVFkm[ ϡ{\ JYZٱ`Qjժ6;.ooR6crɗ6Mo;ix`UjG)s(!;m>QS(L[79XQ۶3xz~=s1Lɇ]Ђocl^a ܂KmFFݻ Sռ.͓l yN_&x^  cOu9<@AXim/[ZTnF׍[pldҢ{V΁ל*&S|V ߫g.WHz<7lwOc IS.yGM9wԏY.<` ݻh=+$σOTNxNZx =Z[!yx?cObcv133H1f؃9O''oēΣ*߻LSPKжす^w>`&pضv}^F9 ܹ e{;/,oXK\k$t@Z'kmt./tX4&Q4K>t@I2<_ד-9k_|$8c,h|*iK=Nfֆ%ϿB\cO3^қcp wʥ޻Go| @M[I`+8p1s/v˷uaq٦ ܂ft]\0tg05Z&X2 5LF7uq}#+_O[R|.hIzk/{vp.0=|B9AH To'!-II54RCatc'XҴ^LU3i1 _ER;p>Wq,2!>,d1 />&䁒)/߽u:0ǁ"dL7aN| Ӄ29#(cQ`R(9(Jܱ ~z< %:|1@ I!qI TbGɉHG\`0$x`c `=uoOH0,7/ײi V#qs>;{ ”8$Hv^YPm+Gg~ޙ$T,SIqߨHI-]}]й+5+qq/Ѥn*(%( ?ߧYdf2܆'qBqz>d946=Ţhs:L0(hczԍapE7[0e;-_v\]ZcdjZAx޹~cd-`SժvX}Y1/z+q7߉\p?u ]V6a^olE*8DŇuMbwm|~e]l,6p [y#aҘkpYǷ/;Or. sc=3Dv9i;]bpa<\y` #( ߺ 9Eө \[Q|ReD˒\$H};4tucʘSJ=J\OmH8H z~Բқ{[fk$xpIs5,lo\#+n 5=J*((}VMu!UW ,e-ݶ|WG =Qɿ1ML%*oł96OJ}{˓qp\~5 +$1PJ5XHu pU;/m-hR&gqJmb "~0' )C%uUlak'%p F7u1x2i[D(1wӀW%wM4VK @&M~m(ho]Z{2L/>Kw/w7CO;p+q߹4R{uv+/_Hm|2x.Vh x47\v_ne ,CiN1u8nʊ( I碟ca ,NiYrփfRZxmc@>O}0G!#:jIu%뮻lF:̡{WPoR5婆GFx|&Zɂ@&ci.gecB .+WZōV>I NԙDBI5U|vQs000GK6oi[Hyl ALM 3==D_ 0BE+ I+IJkSJRlb~n`Q&sWoHQΞypI/MEfbD&>zvuO-)ꩈ"@'EzBJ·%~^2( 0G;⯾;Fr=:(>+ > |]?8{G,Uiju3覢xa l={ۛ1|XKs7px o]u`v V|%WPBm\0SԆH~^+IJ3 W#H1/KMXC ͷJn۫O+jq2歯T P[7ާ)~7Cchdp~F^{%>dnIe8 ~꽒$\4C}k[ر)oO*.Nh_C#%-eI犿V/D _Oݮ|K<񼠏X_s}.qCc;.h48y*VJߺ0)=sn1w캗CGfՊz\}_bl,{Ή'x"WuxDzN/*nsx7Ay|rbN~N!7Bn;Z9- H>iT2>8;q4> AX|ŀ)?qˍʱ8&8Hߝ,r\m/$.w,/N. 1qa T$U+H^6XYZR(1_< d"jbؿM@ĕ (qy۲ |˙7v~6[o/ d }+,0\'32[xlOHF4?' bj9 v ~~꣊%*%'ٜ|_;KF{=/NEcAoH?8yYR}{5ZM-o_}JPk4FZ|l +7?Pk$?}h?A9TJ,рs/xQANV#l*xW +kj+?d_g2Q UO|gD/~@@zL#|HOX8rwj~"\*31oG $6M+mas" ~?*~"8 `(IA)\fG"9w ?q'|F}7"hmz"4.P4C,cn0P/Y.8V]F :=<<Țh(I@H_~xRhJv]Q/Rkߎ\NLL3 {+]eZ'"CNq9 \ln娔`f?'Pw3Чٷ+Q^kˮF#`zzS/q2cq؄KRK:< Bi/w;C ߶[ &o3U-Q2z`"DrILOU֚09ṉULlT.a{yWX 4-OrA+`~V*GqJ'iSӥaXXiJeS5אs&vefuh0 Hb(ݪ eչ 2qmE\p\Sڶ,rY|ךٙ2#SDQV8.P"ԥЉDr|Rj"hRԑB@+΋EE$FFJ^VK>%Iw;z Q q#WS{3_%~TEl kQ|^u?/ }1bʥ.]X %V*Έi75 VKșZeѷJ}T.qA `b^W4$jMphG~P"GC@eϾ_uW7u&ybb^Ј9o=_01'Uok{M;ޡ8qVr}i4 Na~[#{N'%oJt4uwǚ3,<%$%03 H&et0~`r~\~mWWp4_"JI= T(<\+cݦWFYZ'׭wV~we;ĄA$eZ>7Wn:6\cog|9 ܺzJ暨bg.*Az\nD߷mneэyh=SSSڵR^DinQFZ̙3\0FHv%V'<5i,q3E_Us`7ռN[S %m{C CK7 /l6;^ݏݖ8v̺߳TKl X*'}1p嶺j(Ǫ}N?SxDkݦjb#6a&totЫڈzbT1绠;o].پQ&[1oYdwcN)t ,1 ts M\eO4u93ɻ[z_ًJP/ ,wӒNI%\9Ƞ6* Hplmq9ɯJ~Z?KkMRb?*zJ'оD-:ܵ?QB饸SWsw J~Oղ| 4fESog4S:.p /ovV2Iw߯xJohߨ~=;X Uo$6;Gk.___vB x-}ǘ',ݲm= )IO@Ƀ "1V}QZ3\MK+pX! wT)ːǟx|a#{ !Q7̱NRqۃ]w?З&pJ2C`YYiB8Y /I](@oy<Dhh:}0*f6vI20>>s3;vᎀmcK|*&^Pfs$lU8IMp %:1/hڛNQ,̶IʐXq 'iLR$< 6zk[ҧyuc)\p+\ &6S|0HTRɖ - oi|'yTI[S9smRI|S# WķR 7Z3?@&o9ÞZ0( |Zqx4e sa0S.7Tk5ȽŴޗRI@mJQ^G!QHWڵݎ}Zr1.(V%ElQ]{n4L(bK5evpV402y}JJKς]QTQ:QDg]j a!Z~7o]0MsP$02MNoI01/W &pD*KoƊ$xAi"OD xw7Q4?Swy*EZs2e?³.O!`vvÿ&W'_Dar>~1ӧ$ F ȳ b±d5c%|1JFj驰a;s-{%("GG`<^"/͎qa 箭,Ƶ%dgu7wHuM̯fj'GBa_̍X/\ģ&0pnk!N4S|Tw>L4ɽ!GwgUPB#I渮aS$k pږpp(GB ARb;{E@l>﻽ ]J& VUN8:'dXtO4қ˘B"YJ%.m >S@e9G͜f[i.t^\t.ȶ6im/UO\b%-[ݤMzSçc*Zk*/{]e\^%!@Z rQ"BrlRTj.lF5mZli(*JII,G.^AfEp;E# z(-a^}<2U (v9ɮ)R)'6qO*kRp-Ò[FZ$ &gΜIt1Vk;.$ʉ&i &ӄ= &N [~69BN?RK,U:I:S|׾ >asw%fIQ&0\ 8-R%-?l$ q)I[K$!Ki&KcgOsYH5N{w .qs~ 2;;+Nu$wmSc}k+ <,q\ЉLfVIp*gLc`blz 񂒉t M=QzZQl_TKMJ&JrAF 6(*lo(@k ZH;&X5 VGء:Y~^EH$(%B ɡ]D)(I>q>#\/[y_ n<˷]:B"C™~=jA)ڡy q9m=yiD$]~ u| 7Z{G2\i8*c\wy?y_WUnnJw%!vک+lD>_ GH^(QIqSwd|ۄF.(t:g \s ">1G|J& ֭0Iz4A lLG*>)XGJ/%JH\t {$j%)\őFryC~2lMzu.u9jNZ ( C> 3P aDFJMTA RL;mpDQHKTE!QD;dW,%=гګFʋngb|'kUNElD P1xSs? ŸHX }OVRg.g%&sОڮddmL+Mٞƍ4M@P3™?dlkRgW47JI%_p1MmmiT vϟ<ٹX zmIzHbL^Ws aYy {k,)"L67-Lo3+zЊ A % dc#tf>,J [$Q2gzNKt J%Yv8N`OllDd,6h T0uʕzHδKr)ƾd_dC+űCsm/?gٔ=l -pBICZW^i; PaӞEhl6-J᢭{wV3e);aNx+3v/,r(bkg_| ݬQzBԄBGFQ<\{Klp~4PʛM}/~=_zȥ_{M1,Nm|,"gsmc:`> 333H!(T|z\K$4Ә'?7 _"BBSOl6|G_s~X'`ׁ|/uƐ2/M . Ʈ\6ҟ\]NNk@\<[^tcY)ó/ .^}&>0PZr5A: TMRĆI@&OwR0Dy$@W^.z[ΧV\*gee}cwҺP7vjq㚗J <1ˮs9- (hz3؍Np}J &S9qխ]YmKLbO&& *qi>n%{vn ;v'Z ൡZtȤql?gm4۰ ˳ي Ƶ=~Vʆ(WQĦ@T_AO]Epw8 5fE;s-;77Q*oU_rWkZ#}88x3jq"4FNVE_0w?@Irv'|ZyƛT51HbNs=0'j "Q*nEL[夵qkK֔Ӎi^x7N^^l"Uz6XG1䲆WJ!\`y{wBAQ'&.m;ȆGKV@db/R$Yd).KdRDDQ'Z,'/}'d)FgudtnNfgcNccw p:qu^tt/V?aGCy_cОZ.+L$4;),$.gc{j+VZcO 뚙ijwri1q,X]yɾ:1hMa"2.ܙdLL{ϟ"(b#Dps8S:rLVpÕ ͫOS?$}w`@Q/k}toB)[D} oP:y/ @8o W5rqv1-_dnnJ%{ ͂HE:u*#9{FSC M0b3\m9:/N>ן/ől+]_ %N'UW۱A2>3[$k;z`V8+o{z7i {n[|B嘿mW446 Dxpu zt;ԫMuY=6'4ߥb3B^8y+s9zJFkRINφ(GVEF33C?{ׯpw "7@DuPYFr?g;Ϣ 7&RP!!ن&R8Vz F` L T~"aǰ}o ޫ)"֮ڬ7.׌ž/Y!sfӄu.Z7%$T1wEkD5LHR T+·ԝ^YXۗ)WJQfAb- KƩ`Zت%w=?{d{nr]OMT'ߍ\4K► dK'2wfF4Wb:=zÏ0 &/|˒kOp>t@#i ls|J[5NE2. 3/4|Pn[El(-y-K7sylqr)e+i s֛HI@- &o²@qY3|ZxJ|yY9󠾛.B@Ĵ˱e}g[ߘ0gg8fݤil^&+΂_.dnn0c܀L.jvڏc6L.DjPze쌷KuQD|07PO*t}5<o%oRfL aIqql&7nPkI선JNQ {hFVbmPoRH m9,rv0gNd;Ltk暳/5Dtr60:v?L_Ҫm<{t0#XVέhX;pl$*5zmA#>>ǴIu\y*ZK( e|4ǵ(i7߯4JqQ% BLru2Gn΄Ei.hħbڟ\M{_:lָJ|\x ;4h)bU¥:bχv@gc+{,$ˮƶiPbd1;rY$+/5ZAt ,2vvuv/TN C=Np6$F]6xbC;.U $*Q 6DŽL\B?f j&v#ɑ8pp Ze+h>7 fG|q븈",g JU;He3Iۅ{okD|!RK5V$qU.J}#9-K*=߶1yt7 9zMGζp5 ]6-[=r i*ٱLT̲NnU0qeӺ!~m7SSC%vﹶf//aC%5eYSOٖ%L%GW/ٛ7!Xҋu ocV"ZƼFUVkD+P>qu$訹v)Ww0AVf{D&J0{,6h6l*PXU0>-ޟ4P Hd04⾐al N߀>xE =Xt:vs^IKC(3'4wxm]o=+%Ӟ<)>шJm^ *k_*o7հLܢ]Dݒ^\%GoGc -"HhCNuJS+;l2TL֥Мla Qr-c(dPˆgs=# 0+7ڸ  PI 6*[ZT ?7I| <0mF Ւ"Z \bg+. 3O+eɑ}jCyx!\ lpP:L2_f}o ʋR2 i9o]Vb&ٶ`1I"InQ죒oyNW^)m20˯I\ivVUJ?:Yٸj hA\V9vNJW0\;{Y@b+64b.gi|Fę޲ɲUG>P׆AL5 ƞ"-cNsvr}} 9T7 HsR qA$ipm3.Ӿ0I|e͒JJ\Ј |69vGgY[*+{MgyJV{@pQgzJ#|bZWrM(7*dtlfNOBGMjO ឣFm~w&AԵ3;?I,:h,߸(/ C?:^0O')%D Q&~q^QG"wB=r}3AEzeħN !qc;8r%nw2O>~xs d0_y$",!۽.ũUvc> <#y+b@"EZ)^h wv l^Dg y{=3J2oxPnݯMRބ9c!' ɼZ~w?͂W//D?\+O#J^\Cç{{%9y t][Ğg @eەMDdV9|]&64I*&Kĭ|`/dyRdwZ޷M$FV3R11OTUiu5%N>+;&8|sB_7Kv X2. Mp;V0UFۇBdM<$3I,Q_*S"%16 _䳏L%>\87Ҽv-Z `b.L&|/7fal2YO̸f.TC"J!!G+}Չ^ R ENp0QI}wgS߾T-b5{ *FV"r`1\NV.;~w>w*]*g35͋3p!;%!#%0*bCw p$Kiʙ.ev-CLۛN ݧr"?g.%V1%c F:pG}U#"ۜ:'8u^WJX{^HeE]ec+tRd-Hwlر٪'ZA(>NHl(-6[^tJ%2֥TbC(aE:Yؖ6|Sǥ\ZG/a,qؠH\T6_5^:^%}oZHk?$er]}:N^EMZ{piqb|!̾"X|>7i/MAz1Bh&GrW.(kxӑw/JF4Npww_n}7#*C`AO]v!j}Yh} _z=7Apu4"%Du(yUSh#ԅO~e.Iw$]w`?%Yacqc:'n< 7N_2ЗWo!o`q( ",C܀R">$o06MBO~5vb,6ORѽ @+SJSf'>NeɵTtFs=4ǞGT)^}JAy݊vxpqCƮ^9W>0Xo 'y_O= h1ǿ\RvA# R9wwP $3!DrcpeZ3SLzWaȦؤ/GgQ]/^@)P)i*_i@&xZ__$c %Td_J&V0Z^/tV3'R EfZ[U7Z'J-o.Pv6.Drݘ :uRZ=Z g8Q98Le գ#ߺ; ijŸ<m(Rޠ6ϞFC8V␱eޫw9ҊlsmY֠]dusl8Jԛ!a13=K~m/zekm1r]q^E"fӔr+\Pе'?E\rg#r?5v`:+@ELr)Wo\2DOsln.~S1jz8X&3[h>*a}׵h|]P5&N+汐w)1I/|v86P 2qQmd%i\ItR ʄAXEcvTwqig.0, hb9'1"Q&b.\իT*t= q36vqJA0堜L (ɲYrlY>Mo.G,LDʅ 84|I$}ұ68m+`C'j9ɊV3{sTE^oݶ:=/mDXJGhzwǿע( OQ.sswnۄNnq'g(.\cմȉUoBa5$dP:)wV"0q),(%T ح9{z U *p`[q%a 35G'#I>քC$vFr UeR[ 0'4_~A, x?/W{{U`dPPHMM`UMG>Յ˒KĎ&ip{oUp%p =by5?볚˳c<~!|]_ko՜"y9NS;3~AN*QP3)bSoq| n9y񈷽Z_'g?A-. AC)r8s<]RoG5 mh=t(K-Ҩ>ƑuĺLcF ISyLΏ>?)Z; kGݻv?󮻨pdjj_g pϞW+QqH֚p[{CiNH:f[v_1ULi.E,8 2\`KwJJ,rtZ_'Ŕn˔;G&{.x6 bB 4sy8KtVޑVZec[4njي&fĞƢ)h>a81j"v1!z䱠kM8agiC rcHPjeZ.+bZF}Kf=C1*;ʕX g?3מe[v@yh+Vؓg&^5<̾2^$et+apl%^0u utTp? LЬ;+=LUtmQAHE:B~0#f=uUU)URW:n(}m۩x21p,^}{9>zۺSD R@eIߨ=[3.BiwHvZ3h[C1PSC^,&NzU,և6$!/%~KNx?&x: {\d?|i}R3HTMM8W?5}4c)Bp_ߩՈ:Z؇cO amxoG0߀{0SO0RTM.aN?&q,t>S5fz9C8Vzm[Eѓk8fZj 3[?!=-o/Ԥ$2U(a' /tϥ"Ĵ˱dʈ l[ħ`"}U)"d{!Bui`A\.sFFG[۔Y 8pǏgV3<  Zl0{ĥ4b$orKB|&mF .qͳRV&)TLo,eYΥlb\]6:fY}&y!*тJ\$N$M^Xw"ځ;iyM\9=`"۠tR*&i–icޤ[8KF .ɳյr˖2w9A\Ma[ֶ42UDPw!GտzA|wi^|> Z. 9!vJ Z%,Sď}`ױ woz5/tT£~wǘsg>Py{׭M7hppDm|H%Uk1 DV dRv|gT%-X%~0>1ЗCyI=nCMJᣕD#J>wS1 2.(-(ܼeAɞr967-jD#d_DwR7u Z3;3VSk@">yA9$%͍5 }ょOkjg.l:$D>oy/*6!/}C?F^{. E]Lwݤ?_j]  XrQ*M(^H ILm, ERI3%^(D|~/4 zK]8hZ|nl64 8-Nӱ*IL8BAbE\i"ud}ry`W^|[q^X dFl#6lbB!. ťFbKO HhQ|c$0S7V&qdYt eA&PlH@lteIR~7\b"&Y!h6;pfc2Ƕ:ץqjI7}}ӭjLM˧N3SC .\׫Bᎃ'?LmTCmp5oPbE黠ojR^݇A܀jsേ){94^zxS.kˏЌ5w 7InٳZ9$V>:_W_k՘ \]1&Q,7xAM)xb G_zQ?z|?{װ[3[vF'u;Ū_3 E}H՗4iLmq8J1r`-4^?O}TTonT$B&E}Qg+t`3_L]KĜ4lb~OJ?=$^䔈UO5͢8" !pqzb$J'KmiuKl˺2q}<:HyLhd)۰+ $qO_6.]ws-ӱaSt* qM%.#R#*I틼V9&t\M|vu0eʞfN,˾m re&Y'\ONm}DcЂ!K@{k5ʥ2Z 9|{KXDֱ=a\Tz]8B^ɮ~ #drvEjq fG.z{Pl=k@!_|o\yGyա7P =|%gP=yՁ43Ɨe"|7'8ZS%4OH[nCPB|CTn~51ǭzfǩzQ@G bgӁw uyU@"G~Pw y䷾V:x;CoLM87u$^d>5# >sJSwH~꣉ޑ}oz" zQOFȰe7k|jMkXF [߸b(wR.bCGO$o޾7y6`+:hpM_&?[!'9_!c஽UUDv?g.yK7-Bf ¤u)zI= ecNw 5ؐINJ%mN,յXTZU !$Z/%Ć+[Fߩb tD\j%( @gq~t\ ‰U,K@)VGu [!S3\H 6SŴIӺgۧg]O pozKY%4oN玆ؿ]@In+Ϳ qA$O3Sj$ Z4!p #O2=3KCi[d렷}w ՑGqL r<+p0S#QHA5W8r-zA [i B1f;sx_5.mG\i֝we=n(eNOkR1yw{EYшܶ.vJ֡5>P˽ )!܃#tcmz!jn';:S+[^\&΃ž([ً<|:jP:|:8w)g<{iͯJ+fΡ&xM.}\ N߳Y(KVԎ+k yf@nUŊ a`?UD.lpuk_S!ӿoݘ+8Elڜ)oGD7qa^Q.'EwP0rJ>[xOa`[Μo]X"+۬SxmkJmDXIa%y@SgӋp)&6TbZgMJ\첸aw/El( ,\@H{\HNV*\F lS$:2Yj&%BYlp!fi0K$.۬rlX$VʩvbdA&:~Yf>7[=ĄM| ftABye2`ë2bi&Pb*䵱?ں;gJ5eΞ>S_9/+2;34Rml)XAҊW|=w{UҊ՝TuhA3 tV\#;]px(E_{F`? `5&[.^٥tRhv]}rK )bcWɱ5|_qi;(("XӦp;^b&cʲXHdzMDVU<=>S47uRnke%KeWb" &<\[C%f Yv(0nR.a;Kĥ> dTE|"6W|<&|b(6+lbRDmv]*%Y˙j&W>[5/o=v76)>(Ķ1ӛŎky׺Q\2rŕG'/$RQ@Hq2ȐNO]e2Z%J%A-(anN6>B91KUĵ\oWCP1˖eqcOswP[pرw2жtWꕽ3## MS$%h鴯Ypcdo Zt(XP+A 3LM2~}z(r"mV !$/x_X+ؑG _Vqѫfƽg,(%`]I-ɕ<(Ew7Ռ*su \2a"i[+b @iFM[wi~ϗ:.v6JKJ}jFp`7~ǾSMS7T$ŹXzv"qV^8M]9s;wUGi~fZtJL5φE&Xֱqj=8ytVTUEl̰Ӹ,rV֦˶Ii}69fN9v:ՍƧzRDYQ&[0\ۥL 0q|Lu'ͳ|bݭTbOs1/4DQfڕܨ[,FQmݧbTM.Μ/*5?YnKkk[FkT*CDi5@rx<ݸksI-ke)@!_YFZ?"TJ"eﮆY>,r|(i17{cfivAD)VbcUbM@P R(T4_;3CT/ыƲ,1U"_ϱiƅ (W,ݴ6GEu!EUeGͷ >t>" h4O xi[|L6uVo3W)ƘD@4qcs_jAPĆ^5}IsMo<;XS: u ݼ]Yc]@/\ 9P\9tt-t=τLi&bϗ^ކ(0b幟tF:'64\b/ħJcu".UXڶ>)bx(`k϶fiWH6XD|H^%^2{Mŭ,b%Y=MVIoU0JTK\ty!$g/pSׯԋܶ.bVs&@ưm.1U.K#|9iyPR%@ptR̳7,$&w0qcJ %I$VĢI0H6 =n7azD 29!$^x[ǃ(JBЌ(j A#-gjb'# lU׎"XαgɎ=- WFEEQDc@շxMC)P!d/Dǂ@?xEpaU|x.bk DŃ"6}}ql58yBEh.ĆN򜳦j=Ow%ՓnK` "1NitKm$$bUQbߤ +\$4IXd uq.+&:tcSD`" .cc%&b(&bwd)"R9@; 1ӘӻQ 1z: ~nOtXS0WypI%r׮Wۍ t9l_A47jy7QF"8;;7pAR".OƬ6tA$+U3|Sǝ# .q)Yj&Z5o*j1g(iv\($Bfg~m7gjCSLVut+\"sI/4eazjFE5+/bEt;'E|ǙmȐ;;vC#TDEle"8jw1xPs( OQh= X1{*#AGjVOh+nDMk5f]*lk2R48j+ OĕLoUQ|O5ʹ}V $|aR!,$or1gcmcB>pag'K^^N_D-bQ[7|$;"Fl4n)l;&IqY,vu<˛d[ؐKec'I#慉mN|;}aSJF`YՒOi}{yҗ8sc$;)eogЖs5:pt G7PG־b~6Je%(ȥXR>鼛(ue;rqKwژW%ffA(Yfdr!R$2B,ԃNqrT傢V-2M 0LP27;0sZ8a``I. \4ًH!88xЅUDEnьx+bB7Si4a4\vi1fMn(jg'Ai/ퟵ0ÃYsFR&E_` O^/TlrlXDoFĄK|`IKyJ/𨌱U0ISIك m3:PY>OذkۧJbv"Y#JI+06w}J'6ZLc-m./'|J%6᲻gc~yeQ.qYL),{_G5vw\:s9Meb}ܻ6jLruhrPv6(]*&.5,FʴF$k_DyM̲e3- H''Sm%n]i.0FkAafz!._ڟA 3 fVk 4R*H#d81j%2 mFZI @  kUbd GI\69.JzS;Wo|`~j"XǾ(b[D)kK[4*I'%SrNElZroyōF\JtG:N?b9F\j)Y`KV31nmq:YO[59MS5UHy U7 Lb(&dg}jLpvh[Qhby1 MTbNv?>TWR0Ķɷ '-6~py`ڝ;fitCndaZ*ޑxS#LOL/#9JJuR$c} nI_EE#!J'% Z( i6 zYQ>թ[uB[FsemPeoQZ3ߜ+곈"XH ˚xfYCC$E,5sMՓBgh?皳g{"XWJ@#J#`$HAS'gRS;lp|7.N|+\d[5ʹI?M }.9ඹs=Op Zrq|7.%y]8ˁD HQh@&CE$+ ;_*VGsiYyuPypl 3_͍˞ &l$Mc5-5Npet:93$b-st4Sd4@ju"]P& ]6)}@(B:>eMYLȤ5>d$Һ=10;ܒgZML/&αn X.O+dӜWeF +a\ICxK$ qd6ERTLLPŎòKK)aEFǤC>8I ѱcAJehU+ݫn7}[:YH˒jb3kZE0>(+"2$_|@i.k<虙;i͢N9 1[ i4B%cxK!UGMs 8EiIh FC}\Dk/iZ:)ɱ_|{%= ;{َm@m9/0\Cwվm7id)tw|I7pI4lĶ lWzKĜoMS@%Etu.UuVςK<;3‰Y S@'d*ǥJziɣNb.k_Ma&0|v{Cy=Kk6Œ}9/o (a֣u[=L|F6F~6-nKV4v8:N@>1ʖ]pۊ{¿SVɶjZԴp,V ^: >phFm5PVD[.=u bx7:)UYطtZ>{VGq\e۷aw߬Rԛڽy@)RPQm[Dkw^l2\&xDc;b6E؟ln,ĕ֞MHjscm$i]K_aC. d8HRus9W|p>ǎ*dY>7 :sTPQ*)rp^* ʰAKťlb&柫 `,{N$fMV^&Xba$܇9  h ,0ſM;%5Ndv:+Y V_j ImM>s?q{#Tg#vՒ YL^:m,۝6kݶ; ي"}#[Q/Spq,z2722Ω 6 +"de%_-٧ ,':EQDLõi]$d_=\X-{(n׭} >̮@sx._ĦHx$AHI`QĶ4 ( ӂ>0vD(wXr*I!۬rdeͭi/S}VTve 3ZgΓ9:R6e<3*_͉zJ\7i[y]}R&LŕK^W d⸀Wn"6:|J#wqO˹Ҙ]m+ ]CĕƞƗ ,0[2HD\G[ IJ,r<;50ƥ YH_tRmX[*ǜ¦>'S9gʑB7<7R]?\Bq9^!ZK,w=7u~E| Qکçre7ԠQ[v s}/6"&hb|Iue#"(S(." Q _ԛ J;Ѫ L&}tch=r ^ %8's0 E{.oYUf׋.P$KmĶI<\HRP$Ft4(eB6k pg+ILT2aHf?R'rI{MR 11s!R)bQ mA@Y&.ĕ/|tX6蘟K7(uTL{sK뼨64\:tsy_Yu:+bZZCw۶ôZ V[eIcaޗJs9C$(b.o)~d1-gVέY 7K6ǙX46tvE+YN7= k=5-QDk0!(m 1Gi|?=i-VDE.gE8EA_Epm׿\APECJ> đF;.Fa:!eAr%g oTR/"6}B|fEؽ.1a'tiC%_ KA'kicZH!P7{wsA @9=Ni.8ĆV\Jim5pNqA'>P% Lm["(m.; ai|\iw?47H޺;*sqq-b}cQ R0I-s\Ჳ 1869JIּoM ˘=M, HU4(H ے7'yYB"v{Oe$ ŒBɤe)*(6(KU!IL:#Y0K7?䑕lvl$:]8f„:,urZcZ׍eN'[T$MgO׼W*I6@zjyfT.1L|ѮkoIZ&Zs d'v~NK$[@NVsMa"(N|ġbj%ߍnǓѱ*VHΡ<ˬH9$bɠVQ ElQ}6!AHPѓ_AA"(MB$`,F(bA/]Χf!{{[!TĶuH8~Qɿ%P7 dK amj tz4pmcO3Y-qmc*$,)j%U-(N_nIK\@JG:iitYWV#*I:Me-ʫIjRDq^TAV"q)IgTR\a.w{;ږf\0˒&+my!>Փ֛ViQu{;9 d,u~d.[9#+|J&6F:UkB&S]EQ5C1j3]W/_}YG^1}=S) wpkCwQs7>E|ae3ɝo*PQDElUrRDڧ-`CRJ?B.\Z1 ޻]<.btY\W;*d}lo;Xb>.)bݻyTKg:&. .1NJ%|T*8t\^sv`ߴƜQ|*&>a*NIMJWD(FVq0 $)0g擂%ݔdA$ϱnFn:Nq%߮Ȳ&-3ӳW\'uugtt֐ma9j.xcQϡnҩ~;Y]Np(bb+j(YǶLV#Ui1D^+dwu==O[J;PQ֌aHJߏ5 hƧyQTDEEC)=Lb>JEꂈ!yDcM8Tb߇E$Pbwc% 9mŝ;KDأ6$KAV&imL=0\u,V;€GO_9TLZmW"&P)pYޚ6X\&8nI|ɱ./l"C,x#.!t\$'v팊(b%ѬCX!Ƚ }CUJ_>YoEś%-Mx8J }CdZ:  Ј7֛UEuhhw!ACH~Z3\P݇K|ǡ\R&=v&M{_%S$ce LKg&>D @ݓn*}`ƕg2YypKްUElm.;5NKgcc"` åTG$ .q-Rq)Q+1wdⲯYؠ Lq)tSYi:;K#ZLni@3{?)toI'X⢜6tbYjܵ+ض8.t>˲8޷\e3˟-yL 巹\ @M:tznB&vYk%&`(z\]t}Ap,=썅\rݍ2Po.zt}[f-bیHh{o4 }D_dQ/Eʀ}g&K&]\s(e 76 S) j9?Bqמđ5wC 6 VD+i!ZF~B'.\.A%kv|{ A"6}~QO,Zݻ0#i%tY &+ .1tBkm"5Zj_%QS$]&I|nUL$G4rf2d.Dlp!>5~Fi\\^F'Z|oZ)kyJrY !~ *ء~қΑ_H6%6Y΃p]9T [d,sw H-qt=(w},1:qV0YL[>Ʋ@P/o=NIЪF1]D&ݠWËX)D f#1ewsb"ho RM-YHlO `V ,H{[esb j:'bA$`IXWH>|]C]eA |/lq[|y}K|ЈiS(iЉYoG$5NqG!&@BemִvN(Wt2qA).{ZĆR(b9Q&[<:!y)b+tG's=ꀋyjؐG'B ض7.5*߉iUJ[ c)mF^N8.@ʶ~裡rQ7:YӸI|3:@UmSFhtn^jT1gzf"+p.):"-9roNtPYInod+re6]Ys"`WXCLē @@jv"(a*b!ʛ|Vs_OGCy-g|8>;߾4U1STTnCc">HLo[yZw3չS[wGwyWѤgA]ֿn6s=+"y頍 jBO27bQDqn&?. Ih# (gM֛*x]kN?EWw)%vQ1|ߑ?}GV Ut$aIvrLV)1s^:ecy$.XLRlƂM`a=b%P TT $.;lp5/.<˘`/yIt.(% ɚ^@&Et`„4 Nfe/c V9>XeEu`!|K| @+Bm[H_`UĄE6lb6yL|}8@_؄J\ӺK|.s\Sq0f9B&:tgr/]'axg""0S/WĻg:˒c5@.nUL\vMdi-"XjlF7CAŅ3jM^Ina`dlnҊ(b,7E,1e[}%#=+Q=[z9Ihho+k4?a}wU2q).qi.sfIDB#\;C<,rV?[Brr)d+S|s^/`{ERq{,u_y&>p#KwK\ z0k>NZ(qף-tڙ/}vG{N]3Y9y_lņ^L$M/V{ nIХ dNwjY6 EeYG>a2ϳL\׹"(bO|qLm?w Dn|m׉K x-"*vn6j͍[~YkXjOm&&z3;4;;z`ʁ!T=B5^<(lr8 "zRܖ ֚ t%&Xv;u@KhS-ɂLzntC%.21V95St^ZHSɂ@lEWx ,lo0u1mN'$/xb7};dQ۽tT1ӤMec/rQw(S~4|` )&.trIDb+t*o玍l\ &R0L8֨ ~0 ULZNR,Z0JO]& "]\ ؖFVmRCm.`w' øO:I"*u9:%TD[zlD[Gƶ+s=]p}>ٖSyv߮Rg[EzpIESԕ0;xQuqUWhB z d`-J(bu]8sCoPфZ~-WRKjyկ5<|Zqɴ֔w띷0t^‘*t((Agq*YNux橫+skດK:٦wz q."״\ʸ0@H>69f:{  f (Jz^ a%m%V"-o\{64M0.IMLXĶ e,J~QT eM͍ ml\*(柝+ZdQe㚟'؞W l|3Oj[Jw95sNGL&V)#gjlluR4q)}few|F@T ՙ0TQ³Iq.օ8vNvoW1^GΊVo_udڬ(m+,(.])}w՜G]y j3 `7ǁD@ DX&[0)DP,T-VR.]iTX=-7:~:<=pcM5aG+;36nK7QsE,UX(Kx_~)?37Tuf=}T(1-rl[ĜS?Le}cIiݴ\~[JL M<(-rz ;|7Y7M8bB(v~߅ n+Uta!0!w:ͥ6'+NP#*eBEmR-q.%]X8tY؀ib/JdUg_Qj ۭZTK\$v^i|ݹƦϟѕ6a` ygLvZi9RNIt"Dw|*{]6*7uMRZ @q `"aX-[dQXa=H7ڰ7P>Y![뵀!V6KF 56l @t@هuj"IDXZ 'x  A ? 4Xۃkw]r B603_@&+K Ќ p v/_E=#p2])WrRk(J!EK PA<~5} VГYg͟kKGM7o` &B,)%Oaz״}B_zOcuӄpҴ)b~;>%}+a)gmv6bfsl&ߺ ZN,wk]|0rI,j{U̙O,\5³05tQC@%!S_Wݷ&FP4?M/&Aʋ3㈡k?Y#8zG7ϣkɫ!ГQ_@%DXeSʷT,gW ^hQC7˿cVO-0{ E%4 W'a 44c T0W>'ٿSSBj?/@|zXuE>R١_W$W|CG Va-iߌ\e>?>&yD.<7p˳c( z8e%pv\suc!V0]d߇Rrˎ۹s=DI9"a{5zldZ=t-\&fcZޝN8~"+W/c _3]HaDŽKrv\J:)d[KRmP _Y:DK~Ԝz^K'Ӹ-l\69>use rY]ϦƆMRXĥnb(6d^D=*`FHdžȑIl b[yLP:YdM8o\Kw1%Zs\|4˥sViW ,dWK$kJiu rtcUcKWec/YKvyS$-ykg^+NOw*a~ DCu j%2~ fuۑ̳{:R>ёyWT3y[kPX=9g'^_֜@@$8rڵpNBE8GU:4 @PNQC!u^eA7d^}O)@5,dۈ?ru4 *X K.D,ԱfNJ{Bǂ4K9 % w6O44/r$SW\8? IX8>o ַļ-uBNބSF NK1zXh4,CGhpmXe]r (ernqGEleUnvM z{Yh hӜ<'2TLGB|cc^ =}фoإ40'RpĶIKM&שqu8q%N'ݴ(-lz{hm#jN7S5dǴ͐/gg S1Ą=l@JoN˻"z\+`F^0Ĝ¦a)Y+>r'K9%/ض4Y*'rgcOY縠5U X4,@*@$Q|9"'p|v&ji&'o*auYPڶkgfSgZ`9o baDXv%Q l.'*{n4n01J(y]RN2vHj7ȍ(y!VYC-O@hʡ?po| RċW 8wEpmB|1$ R\^!B,qϞWrn4f.s7?~OB@ Õ^@TM.ό!D̙;᚜bf.r$I5=dgu7M1vԋ_eB/HӿvE_8p}q"VX۰( u/~| @>6B_}Qw~[g `rm]!5d͝+f`l}&m3hrd&^8Lo06s㣷& Ӳ@aj?vY ]q5 0tbb+dê'Cbq-$b -G1 bɶDZ; @MhWɴqh^~vy~:)b5:"J&j\7c_e{^Ai`̈́":ߋ#ċ8~cAP84t+P7./#߂ynkz11՗ NS<3_=f{oZH׬ycD(U(eJf3l~,nY2j@$Oӏ/)6׉> Sס[Go4K'EqП/v\KqМ'K R/ o`GuWz>p KܲN?`𓿯yuw!b/@=CRN872EoDp~j WNʅOi.N&R$汑[mpvE%H>dسC/6fg.龠ZR&۪{M')$p{}ܱvf34zہ'=4'sh$rA w$w]Mc9M#nm+R-)I9"T3#Wg>ؒٷ7Q1Z\ˬ#)$#՝=)XIcbZ_XaX&1Tɭʐ8@t%L &mp 86zkWVEȱKl*>*ܣ 517fے>YeҋϜeJA_\S-ig%puZS ;f|b+v6˟漬D'K&k7i d>#Rͥ^n3J+H#e/ emkKpjk?΂H.çbb.Yy<)"KQEwSAiY:%,^;!mq&f::q2ls,5`[niJ*%Y%ULnFJǜx㣷@%&☍X[^v:myƱE4WςMs 3q2xTK:)䘝\)^=1Ўt95bmr22CoKq~4|@ hP&#ܺ`Gu'/L<|Oy#=0<E[X2Nn~ bҖ[}4렏:[n9 P=ANlF O6T~}{~xEGN8Kc5[crb8B\nZC•WGL=ƑK˥A.GJ+}K/!\ȷ)r p=ؽ qǶ r=4W5m}7.fShulCsˏR[Z6ºB2Vl{;߶_mgG.FL{F@ݠ7ǎݤ r]+W>v]oc\=GgGimuY]ڻ Wx>&i+CJBJ I{6v e,#Hu>EfJӔUiY洯J]r+ O&gD:g±Rd`Kwq+=2͞Lc~8ZD4J iȕ:bb$5@^߶MY/s{EɯTz˅kms)dK$G/rlG- RWyiy|Z4l}T!yoFWm ڋfՂl0Vأx1[j+츝ME3kd[oYl( {5<㚯~˜-MgT<ʂ6͏E~㖫sIGse,!+p[SU@مmCqz5>K/; f5{%QHKo߱Է &$QG="IQI#H=HDB0gi]_-S],y#~b3JL&+ W1Y_rnaep/\&]V]oR7 lFIhV]VK l۳gXuR0loۅ%eU&c _ٲ%N\iK(4L*S/Q-YEMӥIϞe8l~w+V4-u2C|lt@75}7ґꊽtb/vT?zRG.o <)tnT{ӝz*3r{:3W!/KJ9Nt/RX94Wtgzѱ yw"͚%meu}])uM;2-icVk'TKZȉ#DY4\`L`ĩDFW>j'zc}c5 z! ώ<ުݱ"'xZT5ΫxyEf3̔ҟ۱@2(#t<}/Y;H5 bq {A:8HUՐ($N]ʼnvUncNYڮp-ҫR刔hTEJ o(*$_~@$HjݟFp,_82tLV &9<"z69-ik^+ѓ{IsCO6Jڋit| )O(uǝ~[isݦhgD%Q{I+S,e^;Rf], 6`j5{HDY2%P>0lvٹ%x*&TIeM:a4@\ՒD$rL`D Z82JޱLLL ɎDc>uWdxfQϞekn{s\uDմ,ly_2g0ŹHDlUJHJKLi>P@I$&6e%JIZ',ylp5A W'Ve9+U! yLw-9QKtezxq]M<;g_uE_+RV\m;_ޮdeژ_°&%,}y}ũwx>LV毳C}$mL1^87K$ J9b|"*^MR Yg)xrr l4"U'ND Ϩ]霢NkyNODY6]GI۱ 'e˫˪+=Mgqo&!af7ifJS /pv4r)e.̝epug:^e8Lq{m1֋ $N$&w(m& &TaJLlx Ĥ`%zrbq[`m9?b:& -?o/L/߷t{SjkI'j8c#p]ŵ2I  4Nz_ |@a%M+-k6hIDu\ J՝:5e/(xuE_2>#LI.}KZ/};֭ʹF{Bx[;,IB1JݠhR x d\LuWڱ 1[S^mg3S.i;[o`a\RpF7oWʧ'Ggd,@B.iKd{yT`d0m!MfAOF\Ϣ:aQomryʍT.ݚ 6pxS$0U%vXZR@R]:$lg>$$A!BJ5թ~7V%&"K{2}ͺ3^$llsڗB 35MLpj,\&,.J,#'qE&2B&紳};wCR6ZWXfKlT<V11m8ԪMLlA{$jS]&-wO$ywWO$8=%88;81utmԢxNx*(fxwЙX:`ML"9aEi6%FpSŇ:+Bt%:32_()83 ?_,me(ZŖgoę:9l,y[I$W yTg@ NlV@ 8_TD^öO6i;Kͯfk .mN;Y;Ǽ;K+n*$cgis:-_Q7S,_$i;CӾw6vX-V~ ڮJ>"me6\ZC> :m"BURk-X]W'TS)ͷӢeCm\9)y㭊b",S)/#IolfͶH+1_\>BH7xO ?BMR׏ٔ\oltz&A}hdIc"4ӉP„m-KU$+A=&2Z4cw^q/ 0 ^B.zj$~D$տ}Nj~ghfL;Ҩx]+?ϑKH-)"=_Q,X . ՒGTJf\Bțlr%]&DDqe~Nm5X|U<i $sN)xJ ޷ \!]nli3[tź{JёɻLVKt{ϼ;qBt%9B~_{I]\{-ڜg>x+z\Rm ,V6vt|_g(?U82M^$mN;)y|[Ĩڿo[ee\KX!mKX:,a@$5WsNWZcY"i@dKqI%T ӡX2Y?e)io<233'SݕLV. N?-C=w(=G1F*V8U[߅2ZK6:ǂY?-Z=頮$XYilqäYt ֭' AݬMN.cl&X]އ\b>zqn*?^vȔQJCF#qeu,oMS.'R%뢚ɞ<;J+lp}߭tZFt훪5kZU.#Գicm"Θ5d\LPbZ'%mڇli W63l^ 8"nĘ![ fʗgß sE+rf\}]nf3~98*s6*)Ӷ򼆯k*M- :vɻ*V}"e{ lQ^_{W Մ q;©L69KdYs|GrٕtW=1[WGhKO VFM& ^/hselR7)MG,Ybc+TjVI&xa#Tc r9x@/~¨s%ۯQM II$GG ocR@GZI`Mڡ$_I%qDCeL"&88rrRE )dLT8I=G3eM:ae겸QI٤J>h@x@f>ˣ-&I\&T7.VmrIDԭ@DL>̤8c9JsU# Eri/'CO:O y(x㯞Iɠc}7o6ڜ%h$h:#ӻV24橡ynIc񯎤ؓ|,-n<'V$JP J5DK0ӛ^D!m-S3vJUf6{ʏ}~Dc`6sCHwQ.uL±5@sHY)^BH-‘)2v&JY)RV_ R >u65ב.^~ADR%V"!*ʫAxR6EBb ۨ eUeUjd%7(_%W-77sNWx_=/-6%&~!t(߹Iގ;)nZ2[U \OS^nn˦ i6杫W̼kR¬/=UHy8%2L4##xV\t9;$_wɦRB2YѸ lpW-xAI;,eh_Mu«MILyX2)umі;k1W>O iä, Z*@*^25!92) mnd{`yjHqjR JQdˀy1%$w\\ҨU/%!cp1m]|cϠ4V!"wyueFlI*sv ?Xa4ю{a-j1q9 m'cZGiDI-¯ߣ=GdBplRm,GӟUm\:80MK%8qe8>ZUjn[OH8!RBEB^<+ 30=/H9>~ݤӴ+GH~+_E=Uz$8 V>%F=[0ԳI%mv8Hd-ьI&H=uNtqY^jHuy!$jѲ4@Mݐ:'LmNR'\6. XÞe͢J ZTVe|MHέҗ_`*){AC{,Jɯ"=>u#e ,{:p{UL$d4=Tg!<&B.#N5͉:ty}Gyws׽͐K\WHdR탯յ-W-> lji΢JAL"BBԁʉ|k7R|GaIZnU29IM%AeQ%QsU|V(GJ4;zKLV8׹Mty=I#ˆI6&ՒGF1NU70i$lcIi$ bV%^[o}UN=Գ1]g}<[pn^̕5 )޶_a+A w))uMw:uRI{ܬFv9 (7ؒJ%WAB.YdLKMj .ǖ >*H A' &}u1)RɮخO=~Ӄ>}-W4F&opnU]X7otaGTQ ,[8ؕx%^vmW+2h@كb֐MCj 2έ=Xd7?u=8ykH"p=px~/j2Mh&R%TpL!-r+Jmh[иKcI(ٶ[{;aVaVͶ-ږtw$T QzˀuFz瓐KX\6Ggc"TǝST$nݪ_ DCˢj%mLcճىK(U{uYgycRB.B6E.D "͔ am8YFZj%&e}N~Td \+u䉋>yvI l,.|Uai~w~ 3[!3ET֤NGͼ;˓/.<)o):A!]!~5j 5<%'X7IE~M`I  6YPB,rt) [y yʣsZ##qLR+8"ل׋@ym+/̷-:rV e*>>F5kWPjyex݊, &D-;\o:;4?)NM`|&fyH`%ٚ%7~)q&2I+DJ tp5%:TLĆ1ภP|>AL:V'86PN@ҕv+>U"J$1K)D #qj&Ѳq+^K amM %&G3 %$&zLM$-N=Hxq#T?[rkJcU0$j%m_]F oc.4ƀĤfԄS7#ĩ\(p[]G/ÚӰ̻otyp@-t6\=] !}DEu+<(8|xu ,~p$rPmZ d~\%r$ؼv4iC\ρ)$2dvRE[Q/}o0!>yߵɱ|ܷ@1G7iFd)$n+]k,Jkq8?KpAX2y+ )adBpԫrӸy"ȃJpUbIKmW WE gi'VM] i؂rRk`7X=eXvfD]j#J.S!UC,YkZii  (nF㫠GۣKjT I V!cKY4,z$c#4"$H*I:RŒ8ő [Z&Tb"re)VYV *ĕ[o۩gdߥMLDzdu2QzeͿO5yjULLZI$FLl#b'KLm=[rIY&Q}po?()(m0[SE]w^-^w%>ֳnZ8%4 y9; S>_?ߦ(tujf+RIpIab //`3ߓ`3V'Hc1'naOAvu(4Ώ(4pѱt7JMW2_IE4'΃8ҩ$pnI 4'_i܄].̜e`,s9T4?8++x*Qu =UHDmJ; u ~v'_?Đbdq@*L4 Pf~Fk|v(7d)+Y S,_%Y/%-~:h~^_\UH95-xa{FrCnǦ|>1:+8ksW'waJäZ^^%Ӡ`$LM 4[5R@ھ#SS51O8}վ.M+ AK> bH QY䄿QI!Ŵ>L2G3Ēfʹ~tC6RH2"W4q6A`/dG$YI%K!#),rZdCI$J&15:%)˵QZ-JLv:&-6I5%O\95nsc#<|^aɠt͖xݮ7=@K3!p2?7dbȠf /σc`UTeoDʃЮnjd}wXK]bi & HK& o b~5F9YBG3 jt< B rJ2\K v#E퀴nwl?\-f-'alGr%m)x_?26#9/ sI /'{m)TWGDQyN~Si˙Y&}/Q|,h^*"S/apӺfTKL68q8q:X ܥ L 6B8Up $>o\ , $D#L3Dj>LGi2xq@NsڸmHu5$\&Գ҉ ǴlIYC 7}#s.j{S]f*4`,qj tFm"k%E")]cUSp.7_{sIgje&\*S\ B.5ܹ 8cߘר3Z@bQ&й8?{6c޹WV, ! XXk{-hI} ? .zF$ZY$Y[ mn( i_u|$zh9WnEkҮc sYđ8 ηҔu.ցG4'E1ek6޴5YV]Am)d.EvO'vw/R^WiD|.VLQfH+ +Jm*UH(4Bɇdʳ$E?>( }"DRpN|F0R%4ƑBZ)|N\ X꽚}l^4B)YgyG\n&MIXM7u_1$8œz8&H-%4GUe"&a$N,.8Br&abHT}$p%D3YDkwosǤb.[{'$&Œ8Ȧq$D&#l{0];$7nkyp6g1'9R&>ɓ>sWﴰuS&%7oݹqK,3&b;iߣSv*-O=?A1berIm?`e6dLF1Kb AsmrIVOu $JT=R4.Jgp|S"sUg.8:.xO =0Dvu?|-\9S`8>HƑNO,ycۏ\;U۝ӾBUVywSUY#M+shyDQ+fJLQ5)])^!PKƧ ܥlBR76Q[޾Ĥ| Q$Q+IH& $<"gmb"DI#QœF69}ƩlszUraՑcFMT$,|R]U4[-۪m\bZ4F뜨2Iu_7U'#%W֐GLZ xmL=FzV8aRI,6QIigNNU=ׁWq|AM{jNf}N~Qg #i:3i85FC %?C{$$xK[$!K$䒕II $Զrޯ^3>p,WEk"ĒvG^zEǨsϕLʨ*xE7Ri]ӛh %5&'1Jޫ /nAWvû_jMƹ sUc]!4BZP!:cRB&V=dž)8uNذOqh7XY$ &L"\*ä(b o^G"Y$$`%3v7ʛ[%~sm=ɚtNrB,a5xUZ\ "Q;8{2qĒVr>LqJqdfeK"&IV5hR r%`8nZB2Q:(Øw]֜<9}֚Kڂ~"p֛ 1k;FeS}ַj"<.nj7)Nr`0R Sn phHl! މ#G&X^!Aݞ7S&!^^Td&Ae?]rI Ջ[KIlqVѦ_ҼPu}?ri`4d990d|Mdd(-?*9 +8~o[01 /M{,%-qdf #7&N/rls!27(Бܵⱋ3{vA^#_=rjBux=l)tsu7=nc$}Oٯ2U` }?+hKrɕ-q%cFr2{,%<'l'H`NwYoit !$HqHB*YzI릛)s٤ZPriZ(69fОh J眠qmϖ;Q&b\TLV9@bpL'u+J= ?D\U}7멄I'&JIxcr V $A L7QbIaR(S#1L?z.cEm&lR'*ᘶ~7F߈t)$&Gכ,"'L4 6)md& #7I5K6*$a+y޴G 5cz̹bI;v5[nI,vN0|YU. ;dqo 3)\ Y ~~ÏtaA$r8qSM\4E ?$ 6J^/ʊ#A}O>7]  dѤd[(P'ce#:Y$ [.谲!!h-zzJCخX\p^.}Y*bR[]fY6T.XTr? IR ?K+ d`y7(ѾZ\.o#!&IuQ۝Fđ'j#!$EIxY!.L2ZđILD65o=ŔF4q8ˆĨ#&Is3D0$NENu{i,ZHb ~&@^GF h%,ѩG.tM{ovؒd3&Džyp,p;_U׵ؑ~75^[glyWAoMI%}+/%V֨qO1ƶ#YB3A>h iD3) h $Hi1W8ޅXeՎ-ic1OkR$`?/%j|,x*ȕ~*wWl)|U Rp^2͑Z,;W / +Hi-!@Zv*A({%Gǖl-mf_e4w''ǟ/c[mڹTF!J /T6z IX4R1YR!FYwt&ՕFY$hHKL),: &X4b%4cS%^g")\Cj&2bׁnD8#TGיNf`W'װ^722᎝p5-tZv,D%G|Wwg)krxÏ촙Ip$q.ڦiMVw .S&stGP[hk$HQcub41dIhq}YD߻E^<ڠ %?%9[5v%Ͼ$<Ȧ`Q9|KAN lGK]r ΐAmX\ nJOڮj\EH&D 'mD.6v,#Sxc<|R[CI_mmid0Ɛ9sbI$QGZ]g.} $z"!$Xf4ROĤzROD1BL$8Hty3&#oH}MLj9g50{*&aՑ%A`hyPW>zYr,)>G"ae>Z%DFpܪI$J2\Y\4FB[:ܲrIA]NՌEqTϢC?wq5t~xÌHyPe,qHU,}%s{ \ܦ^WO D4x5cI [$HZ^ nẋ4ZP {OWnM ,%* Zy¶TK\ \u n<=St?ͩ[I6#xI[jJYUm7YSh x> Ώɳ ,bCG?=9u|#Id$^]VΑׂ^8WtgzH[|K1Y4LpYBfϻH!޾ HMN(HRHob`L4D#a$g=,b"md\][?UnS%XҎ%dcR5 /ҩG21)4&ĩmc1-_zMZ3i.C(6AfTLN\B0bMa{Y;d,;4O2ixz͵ڬKٞii`p<9u<^EWx6;!ׅ&%aWV4jS.6|ktFKpUM& \DK2 AO$1Ö-(xyF憸mP bRZH$< 7dt!d0y/n<ߍ=%,.E+ӛ W\<+55|4W8+B52 \'śmVK5ﰙ(k>sÕ3V֍_$/'ymŝ=J'5%|}yj^3J(S#đILߣ卹z)-sۙ.MA F>k&<Vak( ́t/.LYh*Ē8+uʘ*$AFB0I|2IQOդ8JǴKE=cGJJL*(㚎Uo?(4 "v9uX$m,W.nE:'.hIx,LLq#TädEF膬Eef5pfe>m^ ~H{X|h[)|)m;G ^ynOI3V@FڈuXgm 蹋'$H A 6\G yE&૧>K_v+c8=1U'_)I`ݱ+;vU[s-ß>8:/>#SsZS$VYe5~׉q{x1| )x{^kC%z2pU'+(+'PTfsWŜ8 g *͒IZ"QՒrI)+Msﲻc?g2Αeg.uǮ#&Xg 9GHXτuV'n}t&Iܹ$HHj_H$JD?7nb:N0GHS4D%(V ihbn"]*diV$J,*U ?I9uXJ:1Je^u!jZ $a҉B/tLK5'i2ϡ3fW^P mC>[wY6[-:lQ_.tOaHq&Kz0N3p}4 $H A$NHbu,*xl+r|n|,XZ-?zXIJi{#/p~+ʢ-c;[q5>Pm]HpvdVi(+Zr= :|B>06m቙"N$:'~%,rNyw\MJ}LD)^m/VQ_CHIwmm%Q%ʇgwhzhV%AVLL$z7@S*&qҨLz^,(^%c"αMNk*YC M꩙D?Uo_)~!g,R-g"41fHS0 E&RIT$J8IL>@5+UX9<&Szy9rky6xu^hkbswEe-k /kwjX+8"K/}LV5LV'H A V3h!لg+Fq~QCAgP@6ġnc,$mE=xvTɣ<27S>ݞ"+mcI|Uh|CUJNn/1a"rLe$2GFiIW{;2u]?{;zqL?6O>±a-82`#h#H$eqV;eXDPH`%L\ZkiFdcƤHҬ:XK!VOn"T_vq1ˤr^ D *4>Lu߇Zۛ(brMnH$SIŸv9 6Fʽ_YGd4F#UsNr+(L}l \(j<˧fD3z+$=;j:$p Wml[-b\*Np|YI.F 6G#$YK>ƀ>.n~'=-ɍ"d--uHCGgK[%ˊŋJ=ۈ߫z5nO .LdjLtмTa HY7k#\}"!ajFE1s:yw9jTO|2mSxu/Hyd9u}m%&bGlQKh8&HH& ZʦH$b-CL=;kqD i!HR]_=& 2Uˆj ĴFVI,XT5ʱlXR+2<#ҽ_.& , OMW9tu;J/S1h꽞t73)V6J!)y͜mH[@Q3R %[R.G^VlS./IV xecf,}d4s 3v~ӺiMЕ=IJ$%=֋aILcyw Νg04$Vd{;cݙ^3V9xK(-E {=Iw6cCticO4$R $,jτ-RPpqrrs6b^.cx=걮q\^\$}-Ñ)-kf0xAsbL3Wnn?$l@OF& NtJ7ItYxaTNRdtGi]cZ%}9=~e/unh/*2eS>anrcW2҈I{pMNJ"JJI&  $AKAI=őV=nܹT$㇗VVQHTĴO%*Pb"R..̄Iou;5NtFd KUNtz $Ѳ5A\bR/ dFQ0 )D&N2Mw-٭5g 4$vb%,J _6G$`_+#I#uT'~RbL9fάlP;K_n{};~<ËcG9> /FW,$`I.1^[ofGbx~p.ݹuyh goޮloߵ@::32]x8J+$gr#lt7gp|NJmJ?GU!LwsmM\{Y'Qiu $cK 3Hq' xs'UsjDH(oX"4Kt^$H-iƈsӭQRR'^Q JA{ ޲O#W[ܵSXe}s =q*ؗ5FdrSY ceQZQK5p877U_>w}>dFJ#)ǟcAY;wa8|#H\#'z!!$hQuRx%m=NQFD$nq/g0I$,nbڮ0\*n@jJ8&2ITd%%ĕ1FpMQuy$\ьVpekX$) %DW:[:Q.f%UJBRYB0XL5Zõi -q< ^c#ȓ~ ՔH%Y_Nj=xa^{]}lmg4?̃J"RHv)dk> A+RV'^Kܳ-\ffJ<;8'F[x;GL0{14voJjH&8DOtqLj7!$Xm$M#N:I=hz8&I3J%2Z~!!L[hM*'aI#(y5K(ip@d{%DsZ)]W7F–8&H=cDWID2nl2lS dßrYd$gA:3DSoSdraOպ,4]mHJ`Q3Vδ$-ņny w~WNO ]NWMș{sx#d6r[~rrfeJܺu<7QJ^w} 47_dl~'ȏbY6&xe%/P#kfw>Rтg<#^{3gpxem[ ĵ'E/ϩxn r2Y4T k߀ճʬx@+&{[H]X3ĵŸ=wɇnٳ櫼hs7iN^o< $;mZPHp,jMw)  *fEDڂy/#2-u[ўސ]p؜zJܞ?f >y#>Ku]}t`ϝ|Y\>z- 8.]Od%H&*F2J:ML6:0 %Pz[ڜ;v_~I0]w9|B4YӜFBl_cWzt3C7*RHަ#V]ݿM`5Z4 HeG'QēKF5TR-cKǧ}QGL< 4"+kI۸,Z6J.ipŐDBIIJZ&6f;QrIYrID.Y# &MkybI&pð Q˚g!tLy'c/Xdz&\.)հ++H (oDX˖8t5&թS V3:eG>2VR%4} _gwsmmHDE{%2q^:J3Us岽}'|{#չp\tKڔ"~'R깁m]dfݒS%Ud0+lyvF~cknrIF-m\Î]|/2WK@>mw!Fv.?P.MuLxBVWafF(&yN>-+% $HR"O U(]aϟ`0^YP[%i aY0j)- ;^9͘H<4݇]~^EG֫s8|Ϗ(^Tܾæm݈|gy^ HeTkU!$;WS@LT#kgvM4g_|f"fg.un:_-v}6meΫXȔM(c!Ɛi+=n+c$QIxgĐ&H$hlmʆGtZ1L$(i%ғTig$?lytOk&@U%1S 1+nytꭋ5G+WΒ2 AV@R]nZn6:q8rIIeNRif%2UH=rIUBJm@qtakuJ9SSzID2a)$\L%D0D, fQveiيUս'jCG]8U=7qzR2j*d֝S.BHڝ.(e_\ftyna <*kT'oܺN^;4Xlt/q4ʾΫt]X t ɖvS]{Wckn;oVw$\%,n:<2@t~?AJ3H&$o 'F^CX?+hDdN=5}7ёL*a $H"?Sds'y"~6M[m’}UsPۍ T M3e[7j!&*OWGc` ,*漠_W7(驵˥ `Nx]>NiK)Q1D#rI ԪJjI B` IɑR{yJ SǼ`$iD;S0OۨWRcS=N'Nдo*44#m6;Pu *EaږqJ^ۛPXBr3_."$%v|KU-m\}3ώ}oά7x-7ߐ^]S tc+SRHrZ w>=̖89 _fw>^M'7sK\&o?h]LZfz[NR2X.Dآa ø.J*!h4hOuԐԗߨ5 ђ`N\l[x9 h`_Vf5R@ч'+oҦ3ӳ%N3=jQ ҽ"Z1] eeٝ+JL:S̔'t\bh: m-lz/C!&X+qOM"{R:P>wLK x1 vo󵬐K31fej:bY+!U{$5"e#6‘XpMA- [{ڟʖhFsΌzZ՚9y:64,,vAA TNc$?H~ sg}=+%9_b&˄[\0luKK'~kgP<;f; yN<4Ѐ#t>Nو'D""g@U. :P@攂sI_=^z[@|˶L9AY]f f hKVyE@F+˶djs.cW)# 9"Il^B`K{q$X(yXt079H/aoG]?; he][^sUoLY(_~%pS*SM/u?DK?m꿐w<υ=MM鸱?H_F'BH#tұ=6 J~}? ga^bdq#t߽ ̝!wV# HP:!v4N{m$RcR+x^5z[Ϭhx4w)ÉW%-gHU\WYwkFݣjEY٪CEMu]sVRUrIhB %-,"OX9\:ؾ){%87}lw_7"C^.Jy(<.뻙{TOyӘaB'LAYD2m j"!$XC1Ĵ}=+hJIJT%J@ 9;lyܪAI$`I3̕g:)+MG3P0)YcԱXA,!QH&"ƥt4g̈khs:bG'q$eN\Ѵ,RoYKg)${:3ZFP1ͿH^Ce5,a /^y"eloۉhtRڐI Q^6s6 E3"loɗypÑ;I.jEy%`KJ@VV  }>;-$v 累#Ii+OD)¡D1J *Zy,S_}_b{vl< mN{’+LjTȟ$kY2e͔S&) +Zk!)tgP%ZW$ť$hgsGfls$VhVdPDcd %.cڢ-}(4$ҨmlL*%Q{酿2ԐT'aRzA$kH ㅑ !(p۠pɲ6aރ2-TsR;u_R&g``KtzjPďF8iYqgwlӺI39 &IIYĴNf lA:}YBk<X?#FGR:L륵 xNi>入Ėq}m۹jyN=stFqgE}y0$0k*XB!G&||zA(2OJ ,wqZ|僵WFpd640 $Xh RMe/f{{~d핒ܷ%y"S`;-ʌMihqC?mK~ ɟ<ʞ_ܑ-- [2wbcO栗Ai'/0F2V` _ SSe!vM؝e Zm3O2j{ֆrgjAipoݑ(0y؅LY#a{A,H}AdںnuId֡/c]?# > S{Fm3O0Җ\gu=Ma[hTu ?riF>wUp12ztRQe><_x-o> #}d&"uA~2~ χ|Wԋ'_\c)%[ҼVۮ( %} CFࣰ% .f _6|\"%dS]7(][5ų_|'mW&#,*z ~yJf1ΛZx ʣySA1P2i!+ w2|WnْCipᯟ,fZQ`lJg1fb62{P%3x'J )| [q~+S0yn+l4G›(05˴vȬw^eSPF=~ȲL_&8 ĵ$jŏ=[z8-ƁB ^ckImmk]yB~sF7 2+ca#?WbSzpr+-FzB}qBm|N%E|ےL?G6u kEpkz%eH*͒KkJB9u:lNѝBB8.LJu@^kkdV]ٴ>j-%)L9N``٨gc"l5{_BH;=MmK}q[g"D[f80|햛%F&FDi$]'oZ% )a$2vcgpUI ^g*r UIX$Zδmx8"@\U6_'G{]Žy |ݮ)U%OTW#g'w\D(C)?:Vvtũ^!&d] ]PMV3f-ZT,\Co3g;_5hĚXfk]{y6.7Jݛ,XT0Ik $X\rA?Ps|ϱzv.VzvJ)–L>xxņp,y>3O_R8;Ź{?ZrW5=.RC?cHǢpzs \g)^E8́wx΢b2y8ݙao'%,?yw\~V:o߅?[n*)7[f3Ǚ=6Ֆb!q ߰-->St4ʦ(_=1SN[h~xQzl/ՑFڒ8D՞fً ~@C?<׵-$2GR`;h)% n>y$XW^o%z Z☖#e˱1)U;Jk(լޤ()k8<>9)#+?TmҘJ&(khLƂ@m͐HY,askCiiG+˿éє"%[hwpUbO F{e~ܡS~/JY4N̅|R@c+/CfO'M%p BmJJ`eR/LsOe?y-mWm fyZ)&8ķ^A aKP0tݺXہՖGfH[-edbn@HP@83 ӐR0E?}]",Y^f͔(<:ȗ^$Ԗl`q)W3SL|Udڦ9_ggFm;vϞ@iAƁPy(3O_d뻯A7A7SdSǘyf8Y |am]1?{+8 ~y{U[4EDǟǝ,REOG{Uif`R؂i.33%[|hopԠw146GfAVGoNS5b#?tuBৎR0H[L﻾e)XxS.ߧ|x%,T 0[냷VJPEO<@y,tߵ'ކHX8}mkJ~WH^2 .oͩA. oUөn|蝂/_|͗xE}{d ZGrLI e_oX $4SP ܹ"8} ?>i35 qW.~];T|ohX,N\̕mZx ssLJ?ls<Y#l+G<1)O/b"$덄``PO$J1}V1TnD,1moFI$wkm+D$D^15yi22tO~pd*q N_mt=[;a1t}MRIP*D_yh!ebra]k繺L"j(EdciJ#U"O7H=$RHiw)C_5RU]'Tr%J.qKD(&-;pEF.N"ҏw $$~A}]NX-;:'oiZ# <L<1z$W+c ӏ08Zv ~.4^H{U}]ˑxS>qŷ-z_+(ycy{}63cxS%DFS ~G"R"S 3\3_@ْ,n9U Ea ", 3S6o"y¾EM91Sl} mDJrOgm![$ ͟Rt5ß;ݑAʆAV[O<*x)R[['BIJCs[6np]Kdvwuκ$k(.]SL=~_JRWoy6|>3WL| vg\״5BqdBk(9OGÂ="ٶ?%7^Y*wxA9`fB* ~=>GQ*5~)|{^-F+?)w^yr)7u_ ԐDtgj %eQI{5hl#A??-Ea'tT;F$٤&~/j=h`$T#m '&5QRIϦ5"4B]HQ%#1*Dp!&"LVZDK*'qYpMh^W\vt(3䑸f+PjIpS!V,4:Oiq6E%. Vc)J^[?L`[mCo3F@QԖ~gk!!nI,j@. g,A;f$Up\|/|M+[7mS.rꌧܦۥ QuC/tz8}#;%O'O ^;?|O0[":$|n {;ٛV!hkf L ~y&w_C. Z,R2>+Rs!lkzN߼킢(OG;1l ϗҋ̟G:h+QSxua/Eq?\!?WW 0`2^pfog[lr Eo:PEY?וR S6_9gΖnv} ed2L?q+̿4+v9oN֭#)ϖ)h3/?qM_n %sL?~OX]˸Bғ~jrýd`32\?OK~00@P<& Gp67uYܻF%C:OK^wQf³${r_;S~逃$^c/0cK",{N0cs}us 4w9dWI?{aKaK?}/+pr0śl >m>&mK| |336S0vHlK\w^eK'W+am?yEG uGϛ.1c ziy.L=Kri7؀槮x YG{WN"1]@yp,:ӂIcQ.3Ǐ2y)>$5H ^R'%)\WǿQ溃_*|/!k\⃒?Ee0]oZϥYI'"dӁ݊͡{oS2ЊA.#xE+_0<Xa].UaH\Ж'JKo떏#kcxp7@g'W4jmR!EI6lt[ Ď%Hp*#aT%xQrJqj)q˛E3Ĕzu&rǒ:h_xw%0YfDuQIݗRG84X&#TN rʨ,fT$ъCv:@]nKG:C,Z&{k&%2*VP^WAa9#jy~j+B֨2d E{'>4I tM46dGH%a{ õ47:އuLYUH.Slh.UO Yw@6t.8[ylO&_[̼;sOO!O >뗱Ml^hE2l&A`elF_Vl % ~NOW_bAdf!lIyh(3SZ~.]-.jm^CPFPwǘ;:\Ki_}Gמu67Sd / lQHŸ)1)K]ؓ"-;>7/%ngcSH[",seƾql,m[~吱L~ |#A@)aK/0s.X;{,~6i=y))1q+)˸iJRCl~jҚ-)oI*g218dfӔd ]xɾ.Iٱ| F$U F"~!z=% &67;6iGPv5=;G%R0w|ij-R;m)~xߒ }8#_:*zKt$qᯟasCgJ;W9X޳Ha9RY1hB`WPE_~zMU_3nONWN2c doiOc+/>~t-܊Ctm6ZJǟpv2xVLM@ڦtqϜ44+$?vǯqƾV֮OR ұ~#2ΌasuT[m铸BRǞ :$aKcO2~SWAك_ǯ, _>c4 }(𦽒?~V" }(#_:.{ W$?Ͻd<ڲk?qpnc-ɍ4y>{>OJJ@ajjI8W7W 0;/wOέl@<9GgTIoYä $?x$uLZI(%DL )sKH'2(2P+ Es6|a t8A=t\VUA$($8+F {*-\+fHqjITD 17xG*1cC@x%8E8VC%&e>]Zї #%J8U ͑^Ke$%a5IlǤrIu0jSkKӎ%@ujl](=%TI&U"DXdTzIA"HU _}P(%mkƐY np#JkVZLә5>CHvMun)Y<`&emJ0B:$4RHR$X*(x;oہ֚ _>)>GxucVH o'lc)2>`,Jq^) iFzw4LYȴEq`sSvw {d%)=c<}1XgKৎ2՗оZ ?ϞͻR-H%4d-xV:-J)G13Kog4o~vCj})AYsCG( Lcjx3%&<*ؖC78$)y/ W?le[|# X(O1YJE#7W8j6@6Rp5_zO<"ݎq.ͳ(['w:bK^Wڼo#)|Fr^P R03}ܽ!-xc'<Rp$3c3cܺ][lr;,sU\) ~=v>^i%ҶMVPO ~F7쑸!fGg.2K!S9q2wڼ3V:$QRΖѧ}bf8FfF;4?d2P%o)I-A|15#,~?< l*4[QnJkHnW\WW{/m^NB|^j'4G%)̐-^`5/іӔ\A/vie Ux>ٯhqo~cvÓ/ ק-f7Z E$ѲQY4 NN uU&Ώnr qU7/ ~irۿzdz$}V6zbO.' JF߫M.t̰ NWQ2Ktr&5P%t!cMT%Jf1}?zΩly]$#˚>7։K1E„($jcܨgIbRɨ7_U) X tHu-B0Rke V~Ş&*9C|gO#VFx?תf]:UՒ:YZ?+Ԃ#rNY'gHh2Jsj1ze:F&b%{,\F9+K,ܧ豢u˖yDQKIa^Jaўꨨ$S6\ˠt}k7*c#SNe:"aIg9oO:H%KL޸*y&A+(xJwwZȤ~Nmb5qN~I@ct}ywcIlc,?"[MiHxM0W䧱QuAse\޻zx'Oq`+RƯWI|`ԙ齏b[iyEvh K Z;^OaFE6'o`$?Lz5 &e Sd,xRHŃCҀ: j/ M ĭ+cp낺iq6 cÇIDO1c֒8.f@Aƒb P$x- W J P2iN** %D$sÀ*}]G!9'qsdO1L"WJ P.+:Lv84ȝgXs;`HX|xu%qNA{Ru^9NiE6{92N\(b%oQy ?OzR]}#m~&M7 0xeoKcfW,5I<;BwzU#F} (MOwaTI)xg+$CEd][HIpgLO qa[zZdm^:9XIߺښ4>8M𒵒= yR0Hˠϧ)(e|`!!Nh-^Vٕ srsbǚaIz9c'qMI%xwE)qh006:a}.-~,]}g+-nc a1Cs he;.CH/=E0!^Cxap.?>4$m8y2k >KE΅Δ9]g9_ϲ}W"@$ wy#a,O>}AQNN-A۠0iOn)dU^^0\梁3ۧ@eRִf uI28oO00hM`ڍQ߻?9 Q gȄ[heo1)xu7BO8 swE;o4MV\zl=߸`$ G^;=˦U>)RP_ ؎ W\U v<_o?$rmSw*TLq2skվ*Faſ-δ`uJRo JG c[387oCg7I&pƓI'ŸNc'c~S;<$tp cm?M/J}r/;fD]+2EDp?@^@~F%d @OOp^.[v-,<̉-_HCқܲZXZN[I1`8gR͂yMH^7ZÏA]D&Mr䱳|4| v)+w.t}{7V2 Gn\1\$'=b߹’cN! F)Rبyȗa1/11A].(wCKAGB%ƀ^IHN2XHcMKLS-.pxZC\^[osx\ָ4;Z;;N[*DTsSI|p2?ØJG0HIuaU|!$]=Epn&I=' &J+,aV\2Y Sx&%AUK*Ŕ.I@1Jf<@&ar3Ja#t'PdȖ7@f֔VuV=75MyCz۱y{Np[l$u߻dM#؊߻`ZSsZ|U.JwaY7 KS((ꓒwo3j䁓c!N}iTe4yaWzr;| ֤9X?F*=\47\b2,F\O9]~9dUL[|pM dYW+x +S9!Zj&~bSw7&3mDٯ"ߗŰ ^෯1Ix"BCUR{-A&0?=ݟC[ ^`8"mW !BSD'M^f5 ҆ y,^nI]YA0%OpqdĭMZf)->wr.) ZVKЖUZk->w})3&gS&)OzOha60i:dG`s8wk,^VK nyDž$|2}#}0I[Iojv1zeJ7YS2<5ۅZ-#8]t~?؋31 ޶O.(X9[!Jeljs$W5\R7.{6a=,9#' nLGt[ri,<%0 HZӀ͛47>&w\! TS9_e7'w4yŮA/\~zNr]Wx՘d~}g2qJHfݦ`IO +"WάKzuݥj=+x ?~≽R|{{.b##do( t@&~I0ɸDN)ȄyH[cBMY?]ȆRz<ԒRѮN)JLblU@k]LIy086% veSHKӒ_!Y(pyFOh=ɟWʁipYw1iM# Tsɲ:= 9xl7%K&e資 ) W6||}zcx&煭Hw teIChx׷S^.p,,$ŴԳʓ9|Mv9ȤA67o usɻI,mg%{9G$:jJ{!<$&i lm|J{{!,0h׭Sޑ=.iF4-FןȂ~kuv#$!᝗X KͪM ڄГ?2-4]MhbɂxL7SÈ#6Wj95R1Ww\}Fa95 :Z4ZQV.}}6hBBGa.i_򶗺J;$Ш~ww&EeLgs;4N>\JA]nܮذRq[\YqvM._H^{ e46i^~[i |qu+q@P% R,NW+Y)3=&#m@kC0>̵ Xdi0F˂ֈ_|L(E`}z0RRhથ7LbD}v!:aQ@ȹ@0H%r&6ﵸbI T6 5`qT4Ley#I$\`0V Ф@` V! X<]C;1 %j^<t`RF'&lq<HL&ɕ[3V((3NئW˴v X2KXѸg-d0[l<F:)"q%6b-ؠyo0.;[C]Oⷯp͡o\i04+}֦%ZjG IIlk4:fąOoNpʥR*PuS7Nԙ70y_g)ej~{Admli)pQ趆wu&7_:0x4``HpUZ],ӣ8; RrRɟbҔ=LS۷m|aC6n~hM%IYW;L,qEOmLj)/ʹc [ `Y˖fy^ka(ͽX`]ZJIq8G]?h OUqs6gnlv5{8t~jgG^\ ){llHkOxzcW}W䊥;>/U$rgv8֧*|kJ,E oLqǁ'N2 Yc-w)e{0C?tdG/D˽Fb}d:.ړ;6kjqeǐ/I)5Vh6uj dP[Mߠ{$8_݃ d0I_ Fohk|˖VK?< !_U"Xj,m ~exvઋo}K`1?~ˠXPEG^; }Iܩi/5u<{@3k4K,.;2 ~΋tX$L'Fk0;!rF 9:GH$g|DG-U$(gI82C:bp%-qFO} ؊=\v90 !E+&-$x.tJ7ĶbI+T WNZIbIXz1%yWCoZaqC|`u옊eN ޲Ҥ-)4YKОdǞ:lɈ8cIZTޮX)Ս7Ƕ7Gy@[VK޻ݠ;wqƔI4h&{IM:PT)(7&k,r%&tQ .:޷&#Zvly.[*&c :˩/Կ?sRpj.6<1_Whޱu FA[\!qη<ƞߋ| ƔɺM5g&"O]k0"iMی"d|#sr- {Z{֦ g0 ĊZ_݌ H[^E [[yZ j xuPxbj RVe&K҂u͂5Ҵ(~2WS4iKԂ $ 1c;nSPx͖klfZxr7K!x$(-X(ĕUBS >c+Y &.eλ' &wE]FhNj}IY};('Wo4-j-Ћ*̇lW~m.nTZk_OO\WzιA)o1K|, 97M+H&rf;g$ +;\Hwio:E}. >|߾v1%6j{ռ"$ ekϣ U%{ɨ1k>:oy-%ן:1u\d1 l^\ (qԦ4 -;$ o.Mh0q1ʐ> C͟|-o\$>FnT\UyLIY{#)IpXEBΠ/jWOICM053W 9 4!x ;D3/| aBK#|6' ݒ_?=xXw-y\2;4__9pO2ع_Jm#x \6u*PQ[3BP0 DJcʉv`qPg'xl^^\[-|{򤐌ȻypqHEsbc#bEױdnH, pJ#oXCtMۗc)Gʱ] _bmQ/"mY 'RqTR%r$82k'S{Y/!r8(E1OŤ&\&FRIj?7yLqNu]iܿs%t}D54 sI8cHA_n/P s"]TQ#Lg2|;2zJN dN|$\4W 5Ry(=?/o䌗)\Bē-)`vZ ~s[Es4l FѰ*%x2 K. v&L^4&- FY;/5kLҖKL^Zwƀ=Ogl8I[5m׬$޽/omABNlv,hJy;WX/w,AL=t} f}lz(!H'7Y)8u69zFlP56hy8q> k&쒜R xWp#|h=赉K?4/dr5~] }՝],&a7ΈLKzû^ 򚯞98_b3y͞a `FŖuc 0H $U.E1%jskvq^sm_yD58_7yyRpf_}F/h&_͚K5 2^xY&a ~6-k5%~jc/QgfK>+]/[Y<'.tP&jG̺U ҇^r0/\\@ 69tF 7h)dQiu[}3.a5T |As'$ψqtvUi-Q 2YOStxj's/L+LA},bOgnn(Il,&vUyc#R8+_rR6X_7ĸ_]jGa(~k!4@(?xǫ/~6 KDGׂ`'Ķ-6kg ݛO Kv-I?D7P@C $ěx7B"Q p/SSQUucId s NH$Q`j&Ql Aɐ` drT%cR5}y ;7UV?pP(~%r@Ig\LM' ơKj͔}zULz)! *a X-&a4.!%R\xmbPlͥ?ȡ}تm^B-foaxѸBwΙ%)޳ؾD, ̀ 4jП,Fa0y66jO4\0{4 5 L>uь;Imvs[(fɤ!y,v1MfGf5߼GS!@Jj 4pg2C{oUțGøuXh֓EwgA%-F (6L"A G0l0NX00I%lۂcElYH.5$r-)~0H5:Qa+S*Y1[0" $ R O0l0tr€EV @k5I>tUʔTFH$~jLBT| _6օ0F?TvOU ?rV e|׽:,Tb (RY\fLP g#(aaa3%=IPV9 QuP#&yt4_Y(fei~z{yg52._:1D[zɅ*'7;~°nןE ڳgdh\[LKQdфg wAwpE <,i[>{6l^⪭.۽]VhܢxӋ]7m7mrT Wݤp\%w?&( XQ\ 7:aΩjz2r"ğl[oyC.#9Q<3pTZ5urf@{tדp`QnedDLzb ]MizJQ/ouIco8йTSy2 P*G.Q(@UJY| a녗w]j1R`IS77jF& yԂj }@x~Ԓ)0%kOYLq$p*1Tk1$j.Y(0NpÀ,A? P%,̴ʤ (F$&kZR+58y/pXLaUy.ԥ+4k)#xbDŌ5A<ּPHSuJK 6$-ضAU2ǝwx6ö^ã2K[LSc=Y= P?8 JD}NS/%R:RN|z86o I|Ncwqk?\"90gQ4PFNZnXWE&a;Q჌'~0Jl]hb'Ay`Hع0PdgT)# ,R<b3)w|W.26?*$N %n,(pU R*ӑ9)L= X2U]b( q\X* ~_ib>Ɩd9Ro6e3)q+MXނ 'Lί({>O*ʩP b~'/ d'`\S3DR&qwKeH_b '~K2:?~|g6۶m!Ȼ!dfK;Y'tˇ}e )+ns>1'IbPW~Gv)ذRڔ'b:Yx A;vBz 30'I8WnUt xl[niЬlZپIawX?*WL٪qy3>QBN5$aSǢG@)¤u45I#fX[h kX7r.O 01!68z: or^[Dž-k<Ј GE Lk~c8HTX2?eY9ƒ" {[ w_iW+_GK1~!ғ)1R%>P/6n֪C_ًz,]U] KӈuP;zۛ)@~u5n1ٌr31~lHS]/ha p3vY mN, ᷠMI1_>J^>$*QR?͔A&r8a,#k%#=%{tN᧺6W ߄ReX =#(RpI@d1TNdDLZXH*MvbA@81Y\] B11)Q+}%?JPw=#&]3"A&u&a9 )9h!E7QȊ(.8QAg!6dXO!)-r؞تvaZ&o|2{D;5]_ҁvU\@3ՎLAH-nv͐+8~֓jkl\IX$||$I%shm\^ gvl`*aŠ%#t_nk}ve a0fйTc)*klK']E7Xކ#>,Qj9ixWg{a==-ہ I%$vY 0mNHX (`$,ʱTgX~W,L'^N|N0~X9g0_= D*SfҪT . HdphI 88-8yr`3~L95*e# G HzNLAy?+Fp6("CE j ԙ6LO5<gcQmm<$ڋ%#lZX]pߋx"Yo]SZl[z'`0\~)+Bn >s5;‰-ڮ5ZМX"Vm V[x>M/t^}AM^|ˡS&nexiv,E㦙-^wN;-Ntym:4$%"3b NVSlj<Ěe*ՂЪjCWWG4WА 4C6(m=Nh5C >V]Q;*ax 9ba W||q|e0ONj[pV\Ύ-C"1(۝(9-F$_>.gflay.mN)ZP '(3]`I Jm![ 0mάZ֐(HgI\ZxQ]? ?.ğVqG0`xa:igAv1d]f,iω)z.$a׼(ENυDl!pɉB #xI2|Tʙ} T_Ӹ %,/tČ&(#ʉd OE& 9.t^UM¦2)W L9/Ep4b L{CS=sEBXʹIiu+?;Cntјl.w0$VpYT>CfOHtn/308R\ Îfd:QJ.EMry iS!'F=1[ܴۖH>{jyFۿq֫~8~o'w̳84v\\W𳒽YJ*Y2N ,S# (=yHJRWgbJS")%Ki03W 1Bi&e5愨 [ͲZT"B׈. VrcL 1#S ۊ"Qq5$_Z+MjM3Ғ /RP-x)eZւU |u%52r%l$@ $ g0 ZX:1$l1$Yjq¬+H,NMNT6! ($HP\4b, L$ hpdp?{crY$ R"dH7 \)+RNN}N$q*3y0-Ch/J 5հ%gXѡ`r:Id`n(T:ĴM(a3e0KeޏpSs[Εu(Up%EgdfHAהqG5`Dè=4FM+gm^֊3%sZpf\4)+KxIz38ܻV¨,}'Ico!CjK<}'*{_2_+s;XHԋ;/ނ&KeŎF 2T?u`ԙ9/@]jCd٩?JC[ c!4 ٗgg!R)D®VkRɀ=!L#›v-`8 CPWyrv5X^ V~\'8@0n9-:nre HЖQZmM=@_`ةwHx:_a2\#Cg5.yRȐ`{Ǎ|$L"'v:5V ~IRp 4?D.>p%4zP8gQybՇF֘1IAQ+J DvbPIlbIl?aa?;ISI1M ~5 &AvP~$q?E-\&SX{zwўZ:Idb/`Uݿ|YH(V@)y*x] $J, S ")WAP%i#?4LN׊U_ԟNyYrn"` JwrpHe kJg:GK] !*弼jv\a$mћFkEw4 [[F1El2R6SsnS^,V6=[OBnL*P~ܘ|)tLS޿dH*]%`i&|d{tqz@Q`e"F5Y?ŒufJC!X(9'i\UḠ*Z,AB!WCʜ[)SV4 w+Eoy²كaY̼\VeWDN|A%06ec"cP'6k0j )hu=c`/v_]gXQPo.ut-* b&)T20Ŷ }q6{c LA ^8x>RR <&LˡZ?+IsAJÖKs溥8 8;zstbY $ȎQ-Ӊg$J*ř(r8% g6Z2O< [𳓄1AAPG#lm4L\/|V`^ODXPyeY ީԛ!*;B1a`q$Qv)e'rʉb3[1E Q&/S_ c{9N `e:F,#ҜvezEpG;:JiZRm|=3@SM˼g1D]˫7ܶNhG];16(lNsfG{oNjӱ v;IH!{^AM,e{]zsɰ=#vP-U<뒒 /N+n_YZv>Uk{D,0M+ 3 s4=iWL(% UP[iSo%E9 awQds 7"4p jԥ.1Ĭ^O>)4"!fa-]U{tcnڹueUkǧ5RF2`49rZɸA ,o\Zqɬ. re*0Vlly7V.D]LXG#^_AICar\2w $B)eD(^5&/H *s!_6c 4N\}hQr \b`۬tv/W  V.Qߋ3(SzT)CMT:Z7a0ƒJ@XbEjr=],[19i@¢Tbʘ-*$ PMOD;#ʤ9yЬBUb Q7ฒu+5o +SjH[$b=$AFd„!褦=)HIpEkΔP^sYɚeXgk5-hr`sM#:^}֢$<}@7ZŽ%s~I\|d&L*=׉υAZI=,}˥7ju&}CN@)1kIlbIl dB]$6RM8j72?LXj)H⌇Qgc,AiFD1IT ..jXˑz* pr(6c1)^N>еSK$~IT%| ղlFП%cNj z0s*}V\o/; RrV4$iicU`IC~Tuyԕ]s j%J0ifm93 ҢHEI3EKԒY)%$׭{l#K+iYFLEfA.gFҟ-n!4׬暖y_ZjX^[4#мLتggos\ Q9>t|/U,2sZ01 }!IeSVof!q W9N4 f*L7w?c@ԉq3/%X6ݙqXdkq]3?%Jsax?Ҁ(~'>a7Qcļ9IOÚOksIC$ 'GWfu 5e|7.uA)z9!>ۇie& D=i!4BԠ !G,f*HpQSБXR`2U38'`CȈ{$ 6nqҏ$}#G~mhIsˁ~-kvKG01ɞ#W/rKA x$: ;.. 2c,)ۋ0oGPGrt Kb5!'6d(A Qr7հ;[l bIlsf0D  2Eadvߣ%SS, J`r&AHTa (v$ ja=ÅA尧YVԭƔV({IPώavט5$ՂK?$~':&3L#3>=KM0,AcM\^LB".շ0]ٓ,ƦX'QuViő<1FX$I d3W.ΆfI5bles d0{cCz?yBa z $Mh{ys-]y4|Å0.x]By%1ZpagsO,@ Mc9#:3 ǵp׸ tn' .a3hF9 Kc\X/Z<# C\Vw.\6մp[؏3Tou;r Ƀp:_:!".b$OhM gS |YᅙsW3Dd.e)c+G=`!h[h8x’-mXᤚy]ؚc,[ɕ˯霎W<{ Cb5?b 0&4 YxzK{E( Ϙ}KIvC$$~=}[]":! x&y2ӳT%T_8^You "@Wbqst;y<ຕ`Ik6ghLdRvds8զ(Nv 3>*5X񘨋(P(2D+< qBQ; Кzkc?_GU7yy~UzprrN)₝y uhDk bicFqO@$)B6*n\' <["`!H=YMQVus}I^e4n c+/voݒg\ρ. [MMҒ}9#nVpeB$}C -xfZkz.U , #~D"Ӎ; =u\р.,RC3*29VZ4ڞTb0 ^:-f1$cI>G E 0f{Ll2]&-]`5{vRo5PhMœIA $(S-H$d*ixNRIVd#8@mڈu@cC9;z 31])d*8A0& -#,FMn@&ryQN.4Y^ єj^}\~q~z31\qM/ܳL0bɇt\;qsK0`/ #YLdtT%:~?3o7Z9ia-Z%rDF9dwhyKgi"&]{ݽHSc֎.,v&cSPyV:j< g] a6)֒Imlіszq3q< FdM֜QQt>HԄ9[Ԙ)4N=paS. H)Liq5V\`C}XQIgSs߱s2\HD;+V{! #>m08Rcy?qY]-4>Rk OW˽$ӌh+.ri"aB'Sp$ ru!eq0$7g؆0^)1s i3k&m k1H[kJџ”;,I/ü- M8%:r,iG>gNJp޿fy2*M ]>KN]zw1%|=%&\\c%knI*ILuY(?-j1niJÎ -hH4+j%r26) POeGDY[YPaa_smڄn ۉ?]&ҕ9˞]c+:iH6ߟF%4f~@I $* 'QG91|0zMܲe4J/\IWn7G.u섑`GMo{Y۴Vފ)qpdp {BW d`po7ϣ`>[@WގѸ/i;Ƚc Z9V6a}ٽyI] }{ӳkHwY*FLЛ=]uF֫YY>Mq?ɑ>L͔LeQkV̎H[qTBpn,;Emnł/a(Cy#88yljWҖZJՀ9"8G1\2c˩#dFa,1Қ[ 7(xJikjQ^( nخZ&X69?Y:)7 _ ƥTmljފB+B|gGM\7BIJ =&WhwC x= sz5͋~0zo'd!7sLb.%2)#)ilc nOǑh'IݍowHƑaE}?J+zl&P$dؘdbU]%-wsBwE_BÚ-aI4&Zhi9h4 F^Mi@3jmkH4uSl[`(Fr_QR^ RX?64پԥ/&% ʦ9«6M[pM]AsmAwti#?:mziI.aKUtWswAcUb#Kӫyr=/|SZw7su)MYW/ݮ RW4O $%Ὼ෮C|+H'{l)wH rJ L^Llwi9[@{߾$։U^Zp*>!J{t4X޳:V4[^fr"y~풔ݻXۼvfɌ4@] ~i 01$/C `^5Wlen;t#û1]v&2x˩s=i0zxokWSME:gq=A!pwZE>x4|Ll406 X~vv"G(7rMB@2w 5:Kpkɲp9k6jl6xR/h}dRͫ5!Dž)&w>l0|x7lm0hKgn<ߣG9xb0Zx ]~.K6_$ >_ ].䬵2 %#,@JrK,6xMg#Mvwa-J E׷w]LZ4]Ԫ&ܬЄ8ʩ(ZRO;\-B'Cl%[P 'ň=L/r* RG9dVyG*v.x (3Ec+iH4LʱD'pÅAz=8ʡ-˗]%- naQԁD[/aW9ɞgy. -zm ܱ>QM-[jٍRSQ(փDNUӈb}<va%^T@lS0rԿ> 0Rf(?04[n5= ɡ hMli,](&9ɑH$FVo2t5W;(岲n=> <ZhV̊N N>f.R(WcU}=b"_.R5F`vc9VW;pY߼10lW/,'iK81t Aʨ+Hؾܤ#<0y7ˑ\ZZS󖷑'hHwh0ECO.U[i>ןq@ּ( 'ǩ]-Rv6Ii&ck ׵|doy-ӬI{va1z6K5!ၝボdtjZжBrzhD-ܻ>ChS\>Ft dr. ?yL% ^yye/"Dž)NIXg%~Լl ZM2nҫh{[mt$?q)-66_JCev'wj36\ JvhԺ=tR&u Qڗʍ`-DW2Õeu+Yݴ?Uq5մpq6~~i֚Y0୼cim'#G8:)$y,ÅA- W0W{l&W6AIoVǣ)ܸR]F U#D)H}=hH͝#h[мlੳT[޴"=6PƶK&vhpnk|bfb i&O!QGk&db 5c”SNbFV?`p6orrF9>_4 t?Ӥ׵Pm) hG!,c#8vO&)~-.u)N, +&v9bI-:3K*&29$g ]g}7")!&j՜wJ>9MS=c ,7GksF\ 5R]q%w(ݪXR/p!/e L-qz, {rCÆY@$}^w򏠩Y@-k>rzlL \r} h{f$=k)FʱIl-4&- eirL#aN|Rb[xoK-f aLtBn "C ݒpS9ݟn@3tǀ?ǵo&e' &QQV0Fw'`z0[>8-ܢ-R r?D ҶWG:J5}$Gq+ф ꄌPq߱pzڱ:n}/kZ865wb- ZӜ\86||/Zk;Y^&?W,m71[y>b *Yߊl@ -F0[WaԷbghiƬ~)ѱ1JV=  h aҐlɜcMH^q5FS`xZC%p4&=-6=ScR3 X,4%'GdFKkY'͔.nI kӒ(뵺V$)88󻜟v/`Qw˷MlLmFʌs0ά]Bc/gLkm8cxV-m.]g:Oh?COƬ!kLPk{=GII0ټZ;ow2E:Y . ~ AЈ /^'{ K=ٙg#Q(D41_mp uioO$)qGal|d_3v' 6z26IXBӹ%W zGNq#ɪ%mfMG7dEI2 (7i; lcyץh$)Hsyr(($}${(R7-΁LY4߸cg| W,'_ؾ4sؽ7xJ܌='.gN@db`ۜ[R8aqʁI,*|)?wp`8Ē .mX*Y )(;q,;OS9U/ ~/S6.l$O}$rBak7RcԔ$xFXx.,=ҹwN)Q>H9>R @w,{fu^ΤROx1E\꓍l_v5'q.lh*Sp'\?y+:iX_0&` &G WIuu!Dkc?) Ӎ^j~u!̌c0OUYpdhAC HY "gΛϤ1\xTq7!Z=X gZ+ a".Y'i `l9?fU1?T\ym$'pCYolf 4GAB2)Eg0pi} uv2SvF2{ +vM~l1;j.W|g,Py5b+Tw!$MVwh*\hmmP .4@4`aX^z=ϭŤLAV~i1Q֖ xN5xrd(M3Jpsܹn-9ೇlW](8y.m힟KK“EWٗL~ATy]n!^?&H~!@$A)kABy#'D+EͪFZnYKwgt_O"d#ႛcܩa;V#e~f;IX$&Ġݰ2.s XRoq"0*pt[~-vBL݆Apbq#^6E TQi1ǀ]g(|I!l5_`#& ~/ Pɤ4A%@*z(u*y|zRo'QZqdӞ(3' my $Śu4%[,szݙ.8^A I2GNzBpil_rUY֓M= AB9HJ0½\,[G핯A9obLAɰm#`EZWlztRANi)%$;E:yKiwtcBk_~F|!AHPJo7MFP4\nDXomLi޲c{}.O~!ј:[mq؎ ڲF}#<}@Ngz$מ4`͗l^I%ǘ3\D,{V61_YBG'I ^u6z>c?1,䠻v|n]$c`W$i6?%Gm&&8φ' >}vIZ^Qj]ھ1넔 3yxy_ɑdqy.QhLW&%cOx\NxJ9A0~2j7  ]L ^""RD*)~;q /^ ^ {" a԰a3Vl[le!b5 64K_I 0Fs'7$8?x· zFȴEXmIKe&jj7WqOé!v5[[m^~f͠`o8i@MF% }!\dK!w,Yp e%8!Hfvc}#-45%7zE v ,YPim៎xl^wdC'Fk.ѬljPwcc|208" s%j^ Iq,X&), !| DM[ @Dԧ.eaE30j=O;:@}G߱({ (@{ad^5=uQxoY7EĀ.D&K+TRF׃,'դƌb*29(S\[ IäuLfA1JD0BTp)L\:AIya)() c1Kԓ4jpH$fqp'D0B=IvYVuM8JzKPᘟ{ngZ!O+ʳIndizkPЅpb-b-cx}Uf\B?+yB&ֵܼ$h;cC׬lNq;}̐)O\Xf.rv8cBI$-Mߠ]okHI)M.8*P,4LD - ʔNI6Hi63cp5WC҄OmJ^q=rSIlۨشJӹLfOExHp Aij\ilkx[ LÅ[OJ%Q8Qr8k^f>U)%]TSVz؊&^I!'|ɥ‘3 z>@lO|TaBI;~pITNXŶ-6pH$(AdYd ',\p2&GX%A )~ %qFIDIT&0Jχ1]\9WM)d* AIP~'83'aEߟ(Tk[6rNa͂)_\,%W-M-["A60DT˙c?Ξw1G;y4 [^vUjUMzNbm~Q$il; ]j-4a`Oc%.u/4_ܼS(,Io׮Ajs<' KQlYٶAjq좺7$HC8d~Gsd:Ȅq2WG]P{$<<&*%ڬ Ӻ3.d7'7!er.f$~i.xSrV+ syleϐQͨx|= <!4%+\B5&)xDH(I1NJR9c29RLHvcԘj&&ad0 8J' PF&Mw-!0羷gvYćk@~pIt('$,|l-f&-s9 J9F%+yX6F0`H5%a cI0-?J9f~:&$H9i ??= \, c y (1a<*?6%1j~=GQh!тbbmQ-)7Z&A}"vᚫOZfyF XmiKl"K:lB\ܬ?f*hMHonz4llY\YR-&?4 =8-8pBdaA04X.-BixJkW@ڀcS_ ,3DrmYL34ɹ&Ji`^a6Ê#ũ 4)CP30bV`s6F%%a(#%Q@$ T?VA'EP x}^:L2Qs^=( ’Ȥ <}YPDX\Mp?#{gWw$f?[ljAlnF(FgHpO#%riVcG$aa"Ql$a'xF1m'S 8H$wja@TOG6': ELd#`g.<^H@gE}'k6=zGɜv) aL9~dI apqX}& c*\9Il-V&- Ws> Dݷ(3y  c& y 0(&0?P$6 8$xMYL $$xH<O&SX2`A&@O+j:V7c]dŪ5Iڙsee$ ?M}X)Mn\":U|v5:)d}~@9Oͨ=1,YK@X:d^^:3TAŬB1<+b56.*gʤ?{+˒a_DVy{͞C9#id2 3M~}_Ȋ+׊wcSV~}xDNbZ@\X~v&9L11axmWUlo=ηoa7CLF]c|nÕuWax 0Wׁ¯$NM @HR9RzX̵eH1v[2G6 ^0Ӊew'0>uo|ជ5Hep97Z5=XZX2hIYZ |{9jr8+1y|2pc p .p5lhC_| pR%4O&)vLIjDh#\f'li?$<<l[ 2 chD+h|(#T X`.A&a/hyi1H,%Lm#nGi_h{ȥŋ/~_…pdmTv~GVCUk:^Qҗ|!QCgfؠ6;fƘ];{]װ/˗5 \R&i҆gbMgt;kO^ sb3;ߋ@wKg<ϔ0Ml~*dwLp#<=1엟rm`{ f6=qdrJAp>!:-S]? yNC`o߱G? ɫg8jR*&"d^p\HX {1dq¶cuwsLE[{#vs/E֚(+pɀ|ۢ&Lbg ؉,I1hT$0ʤ%bZbMʑ$Jp.iC$X)`Izg~@tZF'8o"$I8"FYM3P9cs!F/_~^~#|Ο3~p40n!֫  /](a!q8ЄL:p;}^<.ʯa%% nͤCw=6I0e[ c!~epm`*{bŖNLcnTraVw}#076kmKP|g )?_/JcZuq&\\b.XIl$IιZ~ZƣRtdȑ]wGÏ&q[iޅ/PI l-'Ob ؉Y j$ HTb:P"|dY`d$@"4&IHč[ߣl 1J`&G}]iX^ "3VڀL(ͦ؞oY|po⧞\ݼtXTo7^uNQ6[/^xW] ၌o%<>1~d~||0|3{e2FgFx"+v62>op_x 0fn0kbgb:|}o}¿LV-Vؒ]VԳ5m1ǔfa C0C]5kŅC aeY G9qbgȗ G/!Νb.`BBYK9wB[Esi<טZ"m֢XFva,Z@ l%\R,Z[9!$J&R}Kr1 e^EM_XOx ̶Зy<$N8N4@&1v΀&ts 0DIr9՝'=r#z哸O?ޅ׎2·n~ Ú oD AA4h#pɽ^2ǠMjp[~?x0•_5 ^4*J;``!F+v~k!6{?/'K~ c7>1bV1mlR2kZbŊ;Sfk +Wޅ} a|hb1XdIY˻+bŀDe1,$h%U J ع`̞nڍ 5(nfLRŖj(%a9XRM+b+k9 'EHhDh`I*Iڀ Ҫ'%P4 ˏvG($KcLKhz <a;dq6I"G%NM/BắԹ="wTk ?_>q31~O72.]Ͽxvo*#N8$'̞a>4{6&n?af.ypjXg­6>z&oŏ/cW? L|q܋KOa2`/v}h~Xb· -1֫oK.SkIbd0I_)MqZ۰X,/2n;<#2$XSw/&(vZ, TKHn#W8kI B夥%D $@\OrLrZ}?8HDTF' ۶D`K'YgyVhld~ ޸=#pq2W:|}gLe~-5Q>1}LFX= }KVڨ;׵;k~\(1FOg_l]d4Zbɱ/:6+ ~9 kM+VQ:tJb4і`"y)ȩ;6y}Y LS#@q&_.IH~5 z>`7<_y텂Er 4R@%ΚI4D$L"էU4Ď5cЃKh:-t)89>Vaa) 3Dh$$Mr')p g,lmRI>l&ܑ=[=p=űq ?_=uY صLx q;W9\_Cu.xoo"`H⛻~( bgǼ8?Iۿwx[W~ y'`M!.V,\UڠOY0[9+VXn4De]SOxg -ա\lRr8QIh`f?t&@k d_l'm{Eua wwX;vg-˹9Ŋ+b+g$pp @)с9<96O+Cy䐀Dh1",%~R %-&!I*/H @1j]NrvϲLIaEe*|'pm9ta$l"2VXo7 6>s{;Kku& + [ٴ>gW.}_.F~;{_x.;XbN92xB=9bŊ+v.v؍psp=3p{ LJk>P$鄳<7|#h+Ncf'|2 7~rɓ ҟmTYKbPت$`ԐXD8 R`N9 Yj6D/Ox.# ԑ8 &I @*<-HDC&a`ǚq9.q`H 0u5`hi25۷ ~Ow/ҿBu*^noask_`6ZSicRV`Op8U>v7){l1k8( VXbƮ+VXb=}jh=|A;L98RM{2pߣLY^ +#\ *A-}pBo'`}&O[z%m\RqcBWv+D8Åb󲧬%yduLGm`H=2p&%)b4a<@%XLI.!]<jiY-r[_l~R></~Z[awŊ?/W?~ཝw T+kcl3.VXbŊ;A;wncp_ve4iF>1I>r_޹.݄t&P)7dkkI ,ޣ\N'+j0G{=ڛW[ݸa*)%γI8Dc54MOW.0D.1dI_J@ hB2RF.ہĘs M.c :T($2-p*?Ԕ Ŏ8<%sQcdp p{ft';G)~2Zu7]֒bRl[xxe_OTi}׮`kpq:.bŊ+Vɺ_ a-"b8uŊLр%q@@'ƚ)K|94:z"2v}my~T&;,6TR%γISktB-nBA"] 5P&y%u '1iֹH,?t-Kޔj>/{qߐ_ uW$ &}@%Nr"\&?e1[9{]l/`'Gl3Nj sYf0[pobpjxb~`t[YΞ9 ʥW~L}bKkWK/YbŊ+VX;ә?q[@Ŋ >W%|;e*K48t{hI( '`eܽp#?rg"V@%ŊV&Vd H3&WW&cKI'RxZ BA\G/m5IJc%H>T2,d8R7]lRKoDmTIj%{Wx/1r#~gOI?w?rip{1xc0ksIg-^wQ>(v6mR$KQmas~ibŊ+VXSdLGǤoht\XƬ:29G8K :0BA&t=l8`+ n0=~98DN)vnV$7'գ_ю5׬ FGng^0 VsLPyZI2>J t|}>J8\Nh9GtD3))z0mA?RH c ([쨌|{4MR`DYPmިrTR>bsV2d-= 7O9x$, Ib񈱰؍Jc${'09PK+VXbNḬb/QakLe/V1.S&kz?ƷA+AF g6x@0Lm8"I y0)vjLęDGP>;>REƓw8٭҅W^w@/}&![=Ƶg˟…KI0 HusPJA|L))\ 0Ihx=KsOZtR6H(@Eu.BXnH$#Fgkf}צ]*MVtdݷ1yxGa;s̥MhK|7^RXkk:'=z#b{'5بWbŊ+Vۑ&1+cblB%r"c-@YKPKIL CCh2*4վ>ɓCLd뒭+FNŘGmL2$p(D᠓w۵a,^~slء;;;o n]T\I4HA # -54 飐os@#Ӗ˱VL%1pI Nu/`Nfh"0%zGl]D>]` յak𣃓9Zάբ@bŊGm|ױVn=?)&  Ë%WXbŊ+vFOlҎ=C)bŢFJ8؄@aTr8T6M%0{N}o Pm '{3ۍ k'xn3]oq& y0)#}%@V7CA'pn3hynl 6:e:ct7.]Ơ-oi& >ɾ$VG%}n>}ߺ󧸱~_w8h$ YTKP9dv dEM.CBKRte^Yra==TW^ݺ*|=XLbWK6bγ~z<1׶W0fͳs^ybŊ+*VyG;̴j8?gyԷ"vVXsζZH8!-HJo5uӖMZɝ{g8^~a*sPc7r x'_܅+<MFVgL&tRX[y"նK|y8k ?Β2`^b~q,x>Ah'w:LaG`o8!eh:jXSur|!_Mxs߽ >Ɠ<^~tBp(P>c@!T>b:ycuL q#A#;hߦ,['2rN w0y|ƫ4c7;th+vn)'?x?:+Mԏ/Mã\^V$r+6X '[pXg^jOQXLVr0v'ʯ7;#`pyjI]ğw[O>8c0me$pIX i~]Dc 5x_ovSScUB9sra4Tno'呾6FHR&ΣISi 5 dҗnꐤr[/a{x>11n=9ƵgyqI&DheIr_֒EvŵKȥѝxwpy*6ͦ $I "1PpI7W;~eJ;hQژ:Y9$Z|ֈ76i_ ז% VLVv^#ɂo1&𓹫l{nOd| ٟ֭·t=._ݟ,b;] {o81d6~Cej`;cYl ucw/^PbAfwm,&S-pIwXT4 l>vI\Gs]jT>(E0s ?R썒oVqU[A@Pٜ.)v֭L: v.#@6.cÃqmvMˏ-V?!>\^ŵKr[1 =D 93,4,@!^|>n~{{[D9.ޙ7A&P@=Ys a >te$&?@#\&,wc9lTn Pi:8 Tpzrf~c9TW^Y>^Oi3G-"ҍD@&;go|CM|g$C O1 a ?.]] preU Qx:w[U?.P9oҦ]le]'<V]K~3c>pLj=<ܝL1‚,e`7':p5 > 7'``wF3>%vGsMeaתƝ3.`Zycsx7y|QF 0tΦc<c ѝ ~J<* fv_(`{xicM<1{OВJxJ jjpLb'[:1 ?/f'nVb ߫yi/ῴToҴO9RyC8/Ku>;V&NI@0%p9Ѐ !޽ X6puZ%`LqC࠱L/9&"4>(jܬ%}Spٛ`-|pn7|nKW: NDb5cGb$ [~a"l\d>~ =~l=;Ӓ,mj Jn_.1Q4(иG3C 1I7wl `~kFu L )l?:-]fc~` [obt k7:םS(-E^/o10C߿SK Ux2ۃy&ٺQ$J溅5=z X:~noD½e׷0c}ja5{{wqmcX1/_;ÝpOu)z&vk+}/lg6_čzIf7naۻ p{҉2Tva5Z8 L6 3<=xý=pXڸ\Z7֝ `?}z #Xo5x|L']agW/ M-asʊqa6[{,Of:YIe1~rf`y` ^܏m``Xo=7on;OxOskaY#q-;wށ.;~p7?ރȃ)7q-% Fy<|xx+W`8Lka}5Ε(vNZqoŏ;k@e\^e!OѱH2EL n\s^͝pxя 7o~ o=zj^ Woy׃Lg\^LeWT0}*;^+'~.㥋=vk.ar}0O. _7~8Z/I]z_}[ޙോc0Cw2 L!{7>7c_?b~WN\]Ca2ewݶ c3;wج ֫ |:22|tw{[[O'+=jZ?֝Ek~TZx}qw`c ~o_ry z7_}$7Y`c|bh}'c+CId3e/"`}}<^FeTҦ.%kn&3aڏ8Õd,#B"4fBh>D*+PZL6Fp _KxƎ`$ )b ةNn@ƁtJ,uuA+)i``1g#Du/4tfN|J9T**SW>[bowwG.}76k 1\Z'e\"}L`NpFYOो;?oC|>>q3v0kσ_Ѹi ݴY֯ो?<<^)lV[w\x8?wo}h`p[GM|g>ܨ-n\ ;G~ȍ걕1&#~o`_+@UW&F&0\o^]뿎{𱫟:6}켃;Oo'')<=9] 7>S| [g`FCtc,c!k*<>|H uL ?BO>y:>@e+TvO_<֫eڰZG|?z:.Tc;c O^lyD2{{c\W{`8C/\ +`oߚ$xo{c65XNIZe?{scz6ށ!Sg ܺ=}w?? ?rcxv<ȼx1?x=xVC厓;1$|(T0&YݞSƒͷ'nC;eW^;}ob[CΏ߼lM"2썞bX׿73xjĂwRy^W%׼}w`6.`C<1ph?D m:` >w'qcyL&b: PQ^"_a윿_'`ƓC|wqa2֫-W`'.vGOj rI=xxn\zír{*=NQx?:0v~a/\1(~1&Oa>6a49ď77/Z[;ݽ`TZ'|]|~3 o>v ^m&Oq۝n8co;Юa`sn0}lpezx{7>{^hqc[:|o5Waasc[npe4pdx1oCO^,£8p?ݟ`h?#=5 !>usxя;z#1~W9jˇ#?/<奃I *]?A 3[MҗklYK{'yoyH(b򍲒h9A\2s%f.,%3۰oG2p8$}Y$i\HIHI &Z^.)q+vޭJe+mb??[/|m\$f``w{Zb&~'x.IY3,YW?] M_& ?ݛxgM<=i^C.*~_ƅadt:Iv qݽxo)O\L,#Wc.IIȽ֝}+xv lrvjI$`Ip'nv ?.<~ YccP k:KO]уJ̈́:oڕc,y,N`f8"酇}'V{wTb:{ {c+:p n.?m/!p;ėi|4\29\G~_ğٽ5r{w>@e%n{oOñ5bc^ <n>&߻A+= 1y._._ŵ7pg=n?V=/Ѵ/ ^O<%xl /?x:z'G=m'!/o\n|/^|~%$ xa ço>uX/$&;`m xҫp.cvXJs⁽TbPYtU<"~xTpsfxN`O_؍1;߄y=6/8_ UV5Y6S4._7pxgw`q2>s'kЮuoӒXdkk om^؊3-~"M锓J u+vލ2~%pvcIۂ wS7h&'w^rH._+C:4b-,@#4.ΏAc) IbISg1@f+ a&E3\\zg_Os?~/`0JV?u(&~⹽!EN8HcIKywvOAP&w`ObA^h`/bcC8pgxfYTj>T;DGk =}c`yW8Q=(ޡU~so.dk_p[p$'aqۻ7qx|}Wvl?|Kds19RRY:놂M s}yڀ.?<||>F5 f}>^*^ \Yz>.^M&lNWM߇:ƕk/}޸=s'='xf~_ƇOÛhr8\8֨[3Ԭ%}c7xׯ_<>xGI`/]~[ 3;z㸱<~#|>ww;K#v VP>q89lK?;pDo{x/_zl=Zv~Ұn~ۻtw~h;k /]|dġox /l^l׵Nc5w-<Nr c˴;e3' gǤt$<];^U0Pe^7kgnĒ˒`^6Oy&}<=څ_> wJey^>~ippQ*{;WOǓ<ܿӹzlS:f+pi 6`r8l/'n>OCܨnK` ȍw …+5y^98xn=/'=zX7ť+ƞp W֯eTumKKS fʆbwL_ij[x6.n_gpOۚ)ûu R~NubgX, \hB,0+6Ph5StumɔO:a. )Kx$K_ƒDb %6a>dp8%&#JJ b΋I3kT+C^۸_|_ݛw;q099;!4д [ȁ3s`zE<|j8+3cLܘu-;ĥ+xput'Ks-F>\fkl2\ 1ӵfCXA6k|6߸do;͒xڮkPD>%2hłj? x7I dAl5njLV#1IQjuL !l\k_iiNC}>0C\ۼQ=3Qp\cW5kb 9cv mxƮqfc^Μsoʙ~e\ZR6 KՍk3Z=F21 4a9m˚飪c*x6i*\ۖ^b'x?JHtlk:|5 7.V<дdTbdI[<} *@+I߂fc{D%s̍8dl:6 $IhR=9uX8Db6kKh%4% y0)vHr:a2`*<"^H() e'l 0dCZ|򿁝Gx|PXr>O`MRҲO$)''IXcqu:._jLj>IGpyfVrLf;R~9v޵-Ƙf=ua41(Bxi^HZ8.n_c Z^V;>'MKO֬?ckbŖ 5ϙU'+v2pK(EM/F#u8aH,43JsOc2:`,gdcz$3 "kukKL {Khujdpr/=&)Vlz?&(vMLC=1vmк8SBZX@ZU$o=r`.gcmHAc.K4 unĒ#u;to2v)vx;ԙ2~R5p'ί+6:= Ie* `tK2:<9&CFFN>j^*U<8'1T.2HN;ƒH=Rj]'/]Ͻ-e7Mb `M\bu6aE0ùjlI\b`L}[扳 j )@{̣> {Ơv*Yij{] ʶ1;8 X~x:Ɠvj-Q%~-[޳GB}>KbA0sLǚ=}+rTN 脺cTBtYb%I4 ݞb3}k뱼C$H2pƒst`Rع|N&(vM}H`b X+7mÁ'`e^ $gLIX0E/0t7\SB]#ifv $䣿_`cTgmg/X7EZ׀Xʵ_SZm<ֵ5nΌc%) mMBD-8"2?{lZ`kFFk~Qѡ篶8FnϜaC;p3q/!zp5 kڵ2 92X69>s TYl 9Z4`{x3{-x ;>Wǜwlbm~R8G/+lʻumVckҬU`k4sۨ6v,9Ce+l']br+Ǡ.gMՅD{Dϯ k`rP[ic.X0FS(kcKȗ Ry_$v)_J̙lҝve`paĹ]l'vC;ӖX0 l\Ce9|G:^E;z:޵@&Ga~?Wq;> |=/ʍ.x60r#wl<)scZåaF)f `W7hg%w˜XSSla{"֫}hMk@fLl0,bϪmE8MI"8!n26w!& +bgE_kM$&NVMtG$l%ryB$a]!rIHM|q򭆧Sp"p@H|N'գpG;bγI3g}>8hA:g#Kr7|3x uJ4pRMa #K#}F^:FYUxFy|.SNfL556W^uqaFCL1v.uݕ#qa.ռf Z GXiszMP!`TIәz# ˷ ҾRZFbBi d,*cՈ}Xh 0bo7ش=y{A%bH,(bG@XB+Nzp$FҔڞ-4ׯDT>8.l` . ;;p~R>٦Ԁ)+ȥ=`'ݦ5{p[-XSa0ѓ՜k%݀e}43%U{moD_-l 6W#h`~1(—/v1C 5yC"n!}L S3t۾ 0#h2kM6a#ŝC(g z=rAaM-T_WG+/T e3eh&1~ \x/yIۢdV)!vʹ^`rFn4'2U)bZ`C]N0|p̳b}j[t;8?ȍN`/w8`;/M9v0laͮuc7Na:=Nt|`.&nrfl|z^NUk1؏1,ӬX00DZ,bqظpX81Q*&PQ/dkmn gi89H4C jZ>< ,Bi_ HmPkw E{ZĭЄT1Z#& ^\` ڈT$L<& O+W@%Ŋ)c0)vLܑ(R,4ZoL) ZCb9~c~ LѶK` "I4칒9@n[dDsh"7Y rҥuZ=q$m#9$Z*Y<`daNG=M^[^07j 4 |x\น j,ocRs}:^>{nӜ ftNT__Љ 9]~{7 amhb_32U{0z\eޯNxafUk2۴ĜE? 7u/ڳDȓ7EU.Yǩsk6ӱXgЕt6aII01)Gx$N\m cߣ=;y.Pb "įM7I4w7ZmV %?;ap(gԻ_ZPlsSUYТ:Uo T3(r#9)g.ioyD1b2to&^>ھRLjDCh}M H)&Tz"8Tv%k*Y\%q(pF$6"(M>%V miX|~ .~fSF=]TXv&F])IFb2@#RȲ%QiN+G%nbL)V=K;VMg4i64/:i~?g[ue c_Hb{ P :bI'z݅<#Ɓ"t p MmR&C95.mS38$<4o B_oy@Dd$1imgjof ۅ3PV2~3`оsڣCMuH//rb1hp/q˞KN/zkw\Ke."e+~tO!k4s^5{OtD"ږX? %/ 6+ (3ݦtSHZ"MJhHDb) c9~,IbL4Ym$|Pf\Љyߒ4J󾑷 m_3)LN tY!)Py:y4MCKHux2Ée^t pB;/Ia1)VlL.MPY !1aX1&Ó+˓)ۈT&B(I A"$GZIt+y"H2mڼ6i:he$r ˔$rlCh-I.L,?k{*~kTyEvo%er$c|Ɨ4{C h3)%(HJ4oXxܹn$t/h+h2pdSֶ)+V< 9)e]$¥Q)qkm>+&#G91D5 gQai|ã;t/f<&p&B^r+^DT8) *#'18DvnIRGƐXo tEc(xK6$I^pF\ЈĂMU%4OMJFcN=bŊM 7KHZ/eI@NINGgQ @aYB(F$^FhuYK4 cSHDbS4V _+K5s*cT 3DWI5SS[\?a9Jen5U~,%T.'[YPĖDF&X{xX$ itfdYrOIJKâp'>UBfO (tf.bŊ+O]G9%Dx/r<\S/;qHj_Yr,=>>_͎"ʢ+]s%I,1֒XL}D>Yjs|% {uro)0JHlݺlJTJ 4$'H"O̡t9`"}I*JG$VΥq: J)7e*ֶGߜsp~~!O%sS j9%a!4jejm1E $+/P`VTNbHю5&SXKޑ Cr@DM('I}i}NR`l@eA%5SYmbBL>W)qƚ;a#|(bAnxpM$~ $ Pbr>Nl$le%3,%JID݇?}'͎Rӂ$ R޾Qx .HӋs`2FLR38ӽ<4*{`<{tXD2(x$LbR9T'f})R "1ҸĄH"(VXRY\J4MPT.uhYI@Dgp)ZG !)@&CHH@ (>wf$nNGb9I}NԑԠ𛒥?0oXL$v Oڮ%nr(QgL|dzPdЄPtv8Y/=PP΂-4-Fc֘WIL&ڽY>ϋ*ZbSw77ǴwǵbŊ|9Ir_ќ?[Ŷ CKr$+Ýns,"̴-dOG~y*ǚT1G,c1I;sӀ*%Ő'~(#R[K/OH6 ͍WMJ(s д4tY$2l&/9%]d>%}H//c4mj̬ Ij< Uʼn$VTdhBuIAcE'o ()I,GX?L ˜D9bŊtibgr>8Ho JҼ#@?|ba ƽP,O,'$II2(%u~큥P6 (*ՃĶ9NR J.A'%#N4`ݘvnO|Qتny:zUl&YL6Yb[Ҍ$ ,>7r%Z^=A~l&K%}߻9Ux@Qcr $y-ΚicaXbgpM^r<ǟ^;-;lkjk,r]8Zd?KȲ$FVW۟υlP v:(wbQk_9EhjG ,G1 %B0,S\L%\"Z+Jp #'iRf@ l#TM(=/r[0@W $SԾW`9اXbNsnя6C$yG +$}#ے:/q}e~Ţz}ܙ-A,n&ph@&p%&R"J4\vS;IH5 XMb8ɪ & ɍ&P<bR8aY 29<M M@]fe-fkik؀f/KAޣ֐.e#mR~o.d !m v $җÏI˯9y29hb—9D:TymRڼ9O\NLnEZec;kg;Zvπ%PBSNlw ^Gā$(HM$Cs@1RWIIH29,Zg1s#Q-6M4  )18g5 A)Y"ŞumfI2h GHe܋e9RT?znDé)n룿?6QXbVc=s4{|1E!O04N|L[oKn|`xSk_tI#ׁ?bgu!HR1. $y,_./aH&/|Mq /2Q.sk,ڲ8󲓤M&yC'<ߺv P9{Mn|<9s3)p]jiq]44%V>$grPӤh(+$jpFT=4t¥i$FvT*a1xƒ6cyh'MP#:Db+cXV"0$i;H <cOX2:f;WS֤$f L&}3ӴpWVs# @k#; })Igm BC]5TB%tx8ˋ0]E$!r1v</mZXJVn>iѴɜXzbs4AdܡIل4A'#+V8A+lK'='z`ܗ<9) zȐ{ߑsToDMaKHfe7\ν֥缌HiG$I9OSڗ|ͼrLK>e(m֒$j@(,H'4#ll(Q/\H Ēk&CyY l&!p6 0+Vl>+b8H8-+D$F fٷ$2;%ЄP躖-K(VP`Y/4ɷi~۶~iz,\4%\g2'L^Ʃ)Qj_4GzMˑmIp -KK.1u+Ζq=|4#)3cMc)R7t}NJӧ0`]b'8݀*98ilo;`TV>bŊ=gb9y3EXo&,=/݋k#Ѻ.|wߥi#&s\&tɸGh kI,n[&嗽e@?_AI`3M84#$(Єk<;=YywPXii "9yϯ*&}h*[>Fx^ HB% ?`$G^'f. в6i\:GIb˳0)v-l(trBSǙ{\sU&ce, 8cV.mTΖ0RH@飸 h@ 1֒5I8I)Q4GTvJ,tb}!]'aRl%!v=)RS;=8.e#nb(pvɧ5Ȥ&)Epfk_bzXckFA#t e3 y>;$eeQ`mH+ _8hZk#NkqùZ&I]Yݖ7锑@(t"؄G8@%lr4J%re$R'~(I IΡN,MPؼ $)o_$G6G:>Бe!D2)` M<Фq$pp܏{<950 PU X+7©碀`* Nx$\4D99+`Mh(.x\J$uCc;C<'Лb=cʝSc:Ȅg5xƉqI ry۝3ߏ?T]SX򬐘 duLmpG^שyW|0][b `3Ӎ1ؙĝ9*OkL=mrDP`扰kAA-H,aIc'CK(xDH%6 33drt5HrA%@"WZ'L.]DZVJ^[$ޣIӞ~<_`#%7#C(n; 5 l8ShysO4pbŊE޳ eN"54yP@VB(؄B3m˓Cx&(\GH@mXOx>.CqVi],,E;3(YL8(#h9f]䔯*rE_lpMQ{EjN3-3ä4}Eoף]G`Fs Y9Y ܟ >+V,>qfm| .>cr=K$We|̏iL$1߭wQw/{DzPG d֧pݏ9,>gX$wiX5$riPr^.ӵeWIH#T/RY0_?rN8:K5F}(@Γ 2x!4/a]H `ͧP$"a=P"%Ҿ̍lO#J RXs4Ah"VBӹ,/b6@o^VO d ,i y>4V/|R9$F%y^FY{$wEt &=(StȖJ$gq N:i#v]|˷;ԎUgĜ'9%0Xl$#a.#21o"qpMG d3r$v=0!M:Z ^PMb{!uv|̛i%̗.v.-5C\/VVud \,-ﻯyF6h3aMԓ:0,ܽE=$ gT`Q?R: ^' $#CrE6 >kL($6eKK g*GFO'No?/X 5DcHDZbǭ,CuH $+mKIpƔsX+V&Ω)$yC%Mzd%=pF p94&o@$|h$v$䰋h @XLa %$l~z9$Hh4dޠ$ZDۛ $#LIL .euBڇIYCa<( A=0j~?K,Cr'樇mv:4 (si d^b1H ~?fۤ#vq0/p*~8 2EwhTO~R Ŋ[5>.v:Qgz#m_G6D3á"Tٖ ?gߡ3qYXRW J4яն~)Mo6,LHrg_7hF!}3mRy΀1 Ni/puئYk`Lsm Ls-ړ=uZ4:ט ]k %\2@mHBץ\^畀*4+9_y# g S$COH,(ҾSǫ6!ĀIDmu$` БA;E$tR% uIy)!4)G祿hBi @}51Oח 4ۢ3c%qMI[:OhC2"rGZD/S HcE݃h/s&'֏0(N_&zrAi4~(sդkΊ|Ga4)ޤ3JbGslViG!339nh'xː%c~V6DiTzm?g = M(p$J8胳h[b3ɑi@3G~1sA>Vd,^zXp66BƘ_GM+ŪK!e6'YQ@ [Nń(Щ&\8,fRKIpb5D"%J츗e)FVGv2դX΃c2\6ZO8mr98B2tA#R $qh=tYӡVEesj=൛'N_K'24G8ˉ<xEfU]TwFc3xEJ'WH;fi6FeiIDxQǁ&ĥ(:9Z>.-NlKIL `DPD>*H=ES.S}!BygL"DwZF|O䴳TdŊW_S@\gӎQ$QQDj4c?ƕXD!ljx$$5!)z BiIKI>QG2H@45̙pS4^%qx,4]nL3Mb/1t%8նkFBZ@ethY^^c>O:}MB7:#n/;-GcT)riߎdM BS>#H0$&b3"h ')"I}p&~\t?H6bt+2KW,1)bK4n^qTBץV,4 KxLbI({I2Pn(1 e8Ydιd`ZȆtXd\S9hBJޘQʼ$ Il A\FH & &/u}pIbY;&7K@u$ƀ $vb)ȄXW~seq2dOҤھr3)$6  &3ujpٜ :}7ܙRraƉƆp%srX_p $%byA5:hp54LN |epȺhX=i7N!21e-{ri{UFcw/LR1eł*;ϟ '!^B8J6|)V,I}H|X/v>obޣxPR瑘s/4¤-C?ZwMd\~4>kL'MN!qdL_PGġu&Ec}>'LəRbSRfqY^罰]7XkcWN]& f{N$.3XAƌ= pPs $ƌk0 2:hь$}`gmM2$NYJ2^jꣿRI2<168#e eѶC_D1n+@bŎ عƙIBQԍpBŘHg2MbԇDP0&s^] '<3X2Y":@pXI}Nc%TNgkԹ;vS^k Xsj1`X zy1oŹ{g.дDŅm`҂>$J'&hKyF6ִ봺pSGN/ nD>s'?CŊgO4Q@ɲ?+>~|ǼV촙4?N`}&ZlIڮ.3̑{,ubѦܩ1jײKɘTRHU/Jh:]ɫe5F@&^ k/0PI[¤1.1@!1H_I;Dݤ17.]A&4]Z3sL9fnHI{t IֻBP'iJ!\†KxI9|R^8R&/R ̌$UMc&ui61훳hL(Ŋ˷0)V,$.CA$R^Wz8DIէ%6 tS)ұIu.-Pa30 g0~%9yYL((H2MI4>&#%yR>ZCʝR媱Yk(BMDV@4ѿnn8CYKe͊D@xHp/͒ӂ=t o<;V%!LQ酟O.GPJ-'_cY @rN~-bŎVgZl~ا?iCo;q'G` ֘%w>SAD׀>? xn I <} 0hc\f "1}B㑚Rptlˀ>13в:{ܺrQ>}K2FA @$vqsMņ\Xs֘i,lvGKj=9HHqP&[b*)_-pxY 16"Ip4Bep8$pKbx&(v^-XIr%przcaYz#2?f:K$4ش:Go6@"|ɫe14I*Shy(e4ɡfqhl1`IpD6K" Luhbm!ڴ1itrh)K7=ڰ{qVv ˉ@ ""T~?)d8Ou~?*sNc{4ڜ+uF/$`9T쬘fwX1DIEO[6H,U;.eH?vƿptN³w1q3$C}˓ő(8AGy1Pl=dʐyxi|L\ PBK@(T䀇4(,&9L%ZeHയ&M'N?Ka q Xʵ$qB8璀N̈́p'6{IhwA6#W W\rVҒI0%^ y4)ebBP9yYKb&1̎-H@e?R빠<(р!BK%C;!g`;]7Ff]d1')M C8 ExyZOXc˹c4M,2H8I27|[+V,-MP{Y@H ^ۿ${C)KfqtYc-Sh} Ubsqrs8HDcр)aKHu^G| kem{h$4Of.D%ќjAfJsUJshA'v}Ug,4`vL"_KTz"* FH$ ~R(f5kr2G4NɥT.GkX9I??^3گzxϜ)vM|PXId1>`,=q+RKR 8A&<6Ysh-wQ}Kc.cT/Ư@>ſLP7dZ;ƘQ@hBF1 QQ"qv K$ g-&}'Ox$SvN[Gb }Lz$!Bh?$c[*^;8u)3pvMb3д\~D ge,Lb`$fX0)V,$ٜK]`_$pvvT>dK~$qu*IZH*ˁ$tvHoe,X-b)L$X**}8\jZ}JpkA;}4 t(u)DoѠko~^ &1,~x9E*~t<剱dyhXz=c׉}5SXoI{f`x b$1 4(x/>ӹ]^ߗyQ& ۟py$[r %{Ic39,bZ`* 4#Zj0 r1xOKMF qXwuYr֝km |h'&-'H6)ToG*i"yi_ 7u3ft {Iš%),dvrAM0}$AIa Z[:čy8DHr8C@rsIwb|&(V,sl'anw0PF(II`E,9P%"t{cO|=u&NGuYM4?{Xy1)mưO5Y !W*AljcŎ-7&/6_Z˒ݢ7^S_p&J젱{Xg0"{rcr2eQG`/1C}XnL3KI r%cvR^uX7TRlFZI%(Ih`ΐg^` YM,7<50YK<ӥpR2qpyDՉPpĄ"œPrءmO;4C(xnKI+bŎ XF%i8qмhc!r; Kesp`ܐ9:9Q*\$Ћ4v T{H+_60EZow Z}4q|J%JdįY'Xf{hNz NyI @&tRmN'.fViyoSxgzHFcΦ~8{>8 E#&Ƿk}K@ΪtmX{ɭ>M,[J.^p9Z dۮL̅$c_6kﴨ{#^.=u}A,NșREm\ |b@TʙOVR+$/I8IS9$9DH(~]br\UbHhit[ 4bm%Kx|QY'$\YkgdɁ84PhMlXR g-@#0DuJ(H%zzcs&_.uÙH4I2'&Ï!bŊ-f`RXQ:x^GKE_ZѤ|@%E (1Vյ]@({I9Ij?-V.IP"12 xs;hiGv\T$9#]_k-հ$[a.ɝ%Bd(vfh^TL.C%$uжVm"XBY 21H+ohh0, j.9)W}Xy;IViP E=I,ݜs:++}_{H+VLz?;wY_`cƽ@"77XUq|?.9ϳy2S$OZ1P;oZqV^ 3ck8h혻6HyĘK.߹rL2) %5yeI8a+ǥlh2;a.Yi8t{3'uR̸9c&.*~bH ڮ!kدmkmlL?cyܒ߂r3\)"=-ibǘHe.%|ۄG(+ ߶~y4_Ȅr4T Dr5əO+;5kM/dN=]4pGH|mP'E%]$lp  0ó8Os!R9ܲeSl^h"IT&fI7JƁBk&  ˜$k@NGlBxcs x\3uy 6h.;6U,H 78@$4"M>cΉ[S} ]b/뚴 ]l'4DRXK[Ib >$0HqDڧƖ"3&#g&);|]b2m\nK& "V%0b %@H#D,Kb&Z@u)mQKN<ѥuin} qh44\M$ %Q$FM?mbm}O>]bd@<ӌªAY+byCj3䙂\7TKw]br_ԑƙdZ q1$pYbPIVXbV͜`4JM0ɢ>O ck%} >> w}c~Ռ! :;:L% !]# (K$:@p%vhKJ|r{jF ~qUddo $h3^r >˗vO/+,1e{{Z,^+ 4)bŊ+Jo(bg|-cdz )|cpmI{}vChl@9**Hԕ|EHؼ}j^,.ZaQD#57!r]$)] j8I2olIXϟ<Ē$ݶ/]cLVilRV; OҭKKc}E8P6f餴k̬69IfvY6w$xd7e h,(a{ X$1P<,%)4غ2 ·ѲR9i{X(V(MPTdwi }$Ve9XFR1Swv{*l$h-'1p gFIH8\D%uh>P}Hg*kx^)-/C%qh:׆#m]u2+:Լ,ucL'νDYJy Qղtd˝&zpCYQeH˜ $baS`EVR,ͪD?@hsY|*AO3Gf;>P\' bŊ+voծ$eߏXX/[]u<#,xI5YsȦ_ä5#gˆ繱h7%=ɘhħr\hR9&<&IHۥ7Z>)OJS*~&pY-(s%u7:'~ sIiwSX-g!pM~h\v~s'JPp#9? `G |Z(9Jl'Ŋ;>+bz "\ "MJ( oXt>cV]c1u $ #4qyqb$EdNN~ZOOJ$-?_65 POr>R6,?mF1Wx]t_Z]_ ~?qfx^0YCaIF%OzKĎj7~MMK'ZcH#KGOL;v>M„ǘMIMф獱J8Rzj][8dKb?hRK1p밇0HX B%~26HG(#4m ykMۛФip^_Ă"Yrzreqr=qM&,S G_\р$1bŊIb}% @AϧI .81/I ;; e4p8K<s]p}/#_#Z,&RI 8}f HqN VkI'Wrc X, =Mh2Y RbPI8 :&!>t_&T6; H=aŰu\~8՜:1? t->EW-9-iN*̈́ a .h[r)  @&s>@{Ixx?s+3c *5ښ$Gvb׳|+VXb7=t]J-T"[.U&9r_q|G103ߖm.ӧBėo('^+]F`&"h}Lt=Ҥ=d֒G 5Z|2I'^"Ŏ$sj8mG:ZC!9#j8OX+7N{QY (Bro(Kr_KM&sR0C DKB:µ q@%.1AҲdTֆ.MXrA#LcJ %|9%)I$67")%ŊIb&C$ wPPqXJx?+kLrM$@Y@"ڡ+ySA<2,bD qj&C^k+ AM9|?ڬ\ܺԥuM\&RPCYMr^\N>rTlӁ<-Ay䁊Tf`dΡfeh0q r =$>jc>V9qPO3qGbŊ;G: tepߵ[ XCu--×eɗ8"2 1Ɛ_V]qR&*KC$-8wA~{פ%Yd)VDIS|R XbML(pUڬ~1H&9ӿ%`I $BYMx]I'Q@hߵI`!UM giUSn&p 8r392H+"@hY ;Dʈ>b`MG+J4vsŊ[Ibv@ fHL(<:1@sv}JQ) MFhA*cT1IfyHW>Ki@BYIԑcV >.syHPG"3Mg|LLR:BpeQ91fS$D=jT4f"BSv^)Д448M]s2,=z^d8Τ>Vzʬh1y,2+VX1>V>Fm@/kz@~DzF+cK<(I,/e0 HBhBR*)j3ZƘLӆ fvЩe*[.cI !Gx^}ٞAeh4j1`ĂM>e/ł.IbŎ X&C8$@1:S(NMFјWe+;l.]#p#Z4&E:A?:x40ɼ)$6Ls)Z&<@?48ܬ젹lqzθe&ʚ\Ǜ()#QyTg3F$Hy, W߭kUv7Ղu= `DJgubڷk^$c0x B?9-p"E"<ϺŮIbŊ~ZB*c+l%{8d U- Hh GOS|Qڤc-ɹ{KMR٬0HL&La_}F؄,de-JZIqI/KL%H⃱R 4ӭ *h29tfJ~#+'d 5yNes"1ԳF ˿yIȄb yxYU֛JK)+【_ڟTgh PIbo`RX@CΈh.#Kc(I^4Kh$!HuR0}hǫ#ՙ1(pJBB^!&*oB#46SqzΎdd:ciBñJwJ4[φqO3)z]/SI\3}OKiPhEa aU@ID x>9lW#ڼ<\v41vnl$o'{ ήSbŊosNz-'dK~α2.l̵킠1Q/F7q$2?Z v&^^5YwL|܈s|_tK ˫M:YHH,4ęniHƑT,`tn#+*BG_ML%n1j5$NlgI8׬dVgo\6 _H7!//Axt8_rdgYPJy~i\uie X0)V,)#pAB9Θ"Ih W&GkpfM&%t}uI:Hzyҹ*ڀ:BK:l p}AH(8H r*9T+hLdj*M/_E_J(9d"mfa4NDò{H8aNyXAkY}Kj! H Z<ʃ9&3#uЅ2Օϊ>!n8IN|f(g]j%:R(y+V꾵|6[Ia)Yk7Za@Y7ϡ}?ߖ&QGc6I)P? WD&?b-uw!$1iXlj=wp4bu ˼` GRjI߀H+)N#c㼇ƻB I_dʬ#U1iYc0MtSe鬲H_ IbŊޛɋK;k7QSwX-gL:IL4!L1 s:ҽM8853dpv0O ,)I3 褟kϫw@ؒJ%9so4h6y' A gj|T$R`z? ^A;禬%N̒_ gI?$*MIhR26 KM4A)\N'7?^i{bN XGqyFG8sb6McDp&÷rt{l㒎'&[\Fb ΁)<"1hR 4$HB:35ZTi ΀ڡOܱ  ɜ} P(j_g9fڌk,&T&'qIX@7MM7('|o<5Yfbv1`reUhӿUhlAUNJ+V< `Vl5qLח]PNe)A^ߝ $O G,8(4-($}8[I ae);Is"aH4JLti/ q+|9CҙO4f&/x'~1hx4 H{<$JBѼH-i!&hL޹^$msgk̥rhZNZL&R:(&C([$I ݄}I710Vn$SX0)Vl @ 1f Xcl)Rp*9#4$>t_H$x#SPG{,3H.#$Jp y$&K1JmDڼmŮi}^0پ4t$iئʉ$ H tLѫ#ČTLbtA7nS-P%Ť8Ȝ\Xbdcc.iU@%4X\Ku}m^G.Aw?$9oVHȰ2ҽ=z}$9Zk|b@Oo-=d3z:LGpibx0 'l:.I+K0.Ih̍H&t%)"$/pVΥpxy`"m13b$v=Zr8aƴ4g h!E@80%o~ ұQF ನ>r\Fb> #T'u 1^w)Ŋ;:+bzX X44i3H$雐c4@ΐs}ZK<&y#+,SJ,W+c.}h &ZZEK%xb%-'"5T R?&n2tƘYL$'8S P׌3jQGv4IUM"Egu%>tT&kY71ABG>%;A:(2b"R9xfbDgyXD>$Ӌ+VX +KW֣҇`(͕|'?,1@9vlu,M!L5lNߊђifSKT}6}Q p/+MaV &$Xμx&M ̘L8x$V\[AR]RpWmD#I4]d߆Xh`6 LLegױfQj)\@$|]D8@(@Q ю ,,$p.#+G&%wd" "S[+Ar$ldyvNO8; _ίM%YM_JF:FZHy|9L?RS VKrXQr>gb&(KZްn.ЃhYcU- )jSrJί4"X $E+gp C:!f5JS]gq wrp$U&R`-Af4J7!9vRh.{=8s2IO|:ˌ&9+Vز$ivA&Ss]s4?($cdk%?qܷ5dSZDHcXQ1~ƾR "km:S_6'BYR29!3j <P/M:K RR Nʝťn8; sId${-L"X"Tz#8[XvBfB)/q޴s< 8(Ӳp%rJbVɵ>A 1h%tɄסJ}+VlL[8Cy4p&oF$ m (= -/`K}p@JhTݡu۩t$ 1vv|Rzp@&_ T2q}9K 0nhAyy0^ 7: <Ҵ`9WaVF?>"Qa/ќXz,ʿX< 4`cN G#ᙼr>m#FhU3{j,v.:U y XbFR.<+4\,_hvQG+ dYoF/ SLcTbm'ݸC&ڱ=#~ +E&0DXqg4ɉI1) 1׊ŷWTꆂE8p4/s~wl[TiC* ` ppb`^xviϑ_4pi]&zuG:ĮƈۥLl{g'wJ5ٟt¶R1e4cw!-vlpʯjH^GnRJpZNh,&R13&cc))!~oaB+1{%D "(S6^GLGޡ:aI$H4\dsh.^V:>~lұH Xձ0)VlAa0xy.[HitH2:#"29&ԤBrk9Zy ā.kqvT(\}Cp$FhKiur}\Z:vz(]+lP ,7SQ)׋UjAyh0AZ *9 D)[LDNH3|iMt@'h~'Ճ+li׉$92JDu ,Aw$e9kx SߪJN絍]3"2+M%ipLKw''Řΰu]3A ЩO}=A@NO.y؛xܡ3i/MMJ%䀥x /Z']4nշ\'b1ٕs179n] gv%bgH4 7?IrI&:t-um'֘iW/޻i @McIk<9,%3r `(xr7ubu+VL;@"h%\g>$sh`9/"D$ "1`ߗv89Rby($&n.ηqIHI,)3R('(1&z6a`$N>ӂLb8wإ 9ԣ:A)( v:Ҭ#{t2  j :r&Nؤ׃w+V,Mr\Z%*'|H9kc,uOep a謶l $ >H~~H42Gdkv>$LGOVjNWX3v$Mc^BhEķa.i#Ӏ&4&RFm)ϿX#eJ$؄緙`H7%6?>>,}Ty7c BPL7#哤vˆ}Pf6Ď?R$wi]ڱ+VL;"˕ LXw$I gV@Kdr(~y1yq."ݞ98! Ip +7 ?J(s0y7F%a=ZkUg 8ǒ6N$8̈́Ҕl6 @qZciӀ#<&<'8؊KOuAOLSM\Q`W~|bxWbM:fKNa< J]7hfdbuXbNۓ+M]T]sOrֱQ}lΉ1s'yZl vnhl9~;̩D(3H s ?OU6[-81W:IJ87cPo 'ݗ$_9{Lzoj5> )qĀ" wX$s iXJ|tFXKf&a3 $﬉Pi/ M^LpB9`CߡuJ oe@&R.H(1<% ]y4 -Gv'4,4S0Hp :eiLG_LfJ a5;y8p2/=i4PЉ$ \Qb;3쟀I8 H } e*sgJA &IN =H)Q^,t5l)8dvo:[X>v?I"2g6ɹ_bŊsr7xT$cxmQ*|ْ&3v" KIĖU\%L5P pVZHјO}|>ٓtkp I-9_+nEMeh3,'i[nIc+'^.b.*˯eγaVIXc֥o8uK&udBkmS~g̴@ڇP&Ml H1Pdt2H@wH!h2<\F-$u^|߅X0)VLepHF%3p$}c)I1cja#G(Si#0K6iq}h"J7yXqhij?:@BA!< i\BA'IJ=@bB%λPۮڈM]S@IXۭ3i%szOyLh׫1dMiht&e5r9$RIA 7WkDHj.O3#d-RJLZ[PYϷ͸NvZd vz(}|-Vزbfj`Y̟'ѣRAw'soڵS! ɜ~s_k<&?~c7q ח5U#d~c A_b?C őLhGbʥq&sq!!ƙJ(0Echt{3>gb`@ TXH_C$N$+ЦBmM̳pMeu5Hb@N3Fh #T'9:I! CRp0 ՝VX0)Vl^)I&|I4^&G"3|q !Ir OS+#\rMbR8t`Lx^cE]'_G""IPNh"ۘ1$λ&2T5&o u)g!iKd YuY H!dsH"pF\BA'L&Y9=lei pOrJ^9Y3&9Y,Ѵjv>jD2 ܂Mrn97ŊN%4(AgH >:`i#ȚQni7l?J+V,S< zڇb03c'b?~+&F/铒4NN_8mP/aMdo4@J,>3kC+jq &IśhLOMfI/ݮbq ~g/ϟ2 @.jfq8ַ\xz?5,%Gl=q$5y=qV~ A"H$8DKM>'Ll^MrFH BK* _1Ib'o`R b'RR=aYcMюO_4N{5gLz6hXB(t]hǛ:ҸI7DN =dmP d*Xh4mT!cH$tWvr9`S- 9>9 ؄lJ+6A)'P h`sGRr4Ђ _du$Ǘ:XbF5Z K3)[f%}@&>YH3 !*8hñ”ȜBXҕG*="],HRpv9&}x78] #t|xXrV/J&P;g~P2gceMᤎ_Jwl,WU iT ̌DxH!R|D ņw¾NJRmٖQFNgmL IM b0}LD9Duu-IH>x3:T7WMAI,OxO'jY3ǩjkLsMڱo_6g1hٞ9eF4Hb+`By %$gXL(`D@)/#C8%q #1+VlL;! \[H8Cɑ۴v|˰f pVN#4јTU ҷiL#2m^'pMNgy׻-3kWbb0`UD]d1S1% V(:$:wS٧C!] 5.|v ]fH3)DN,ВY%LIHfXMfyy=H—6Q< hDZ-z~Ol{*t$x' ?k8CfpTJLQ%2RJIV֕/UՖj_foԕfR2)2RHHpA) psΝ }=v_|-\FI@qc}A~?3 u@vgZ]E G+SؿVw?0S S#[@Lܣ["г)gRO fZ4TĚ?],F< (rn^= o ¼<ɈQXO[H#^9.4r\2CG; _896b˩)mKIDCE]G84}REUM= S3kF:AB k)F/*F} KmA2S 4ф)_F&lspٺUYLdkt#}XnmuPv>JCH%Leu:r>L(j:dQ3QXk\!CB{j )m:m42ndze0 ftPg䀂Pm74sI0A{hs"J&WK=k)T fzhPD"Dܧh&N9CJ;B_I; = ӣj E%*?Yj&ֿ5zMI]j o2k/~\;b\K.H jgmfw:|5pܽ2[,sUBJ,K`ŽV=Nssif ڦ7e֌5 @Ҳ+AƳ1pt[֪Xj%nbMb.Ir,U*SI&k*0\FGLIv7,a2\M!Ӭ-qͥ,ل0S,Ifp0xVthSl'TK:f69x,nnf)05*% $79Dl mo0M.O ̝UM3(Z ("G/Y<=NZY'Gs3o_艬M68m&i9N:ti8H3) Pqc﷖M3{uD{]ЧdjHgOR6ѿ' 'CycZYw- a~fLG9j6Z;58y*8uzJ~M*AUqu 1Bgf5fŔ2;isU\v>o21lYS h2T˼=]JH)axQ DŤyuE"nh$G a7Mb%pe3SI&y?H'ՃB!h?SҤtz;;E2mGK M= S(lkr)cxkԨqLj(%^$G0b)`˖]5ϮZ7T 6lfqchccJG;MqtZ6N~ c|Zˏ,D LM"рSak,IIH$)E`d;M $XoT=a%lrāDQI,>~Q eE0yCF4IDN< @BJ-%kԨqpLj@KHzH1Tz>d #`=# \Dn#F> (9vl$:$p r ;~#V3&MtD%Jb(\7Ħ) omS#tt5$-3+!38R']w!X%P<0! ~kV RI\ѻD(3v9oc+T51ˋ'aog4f̠"k& .0A_\eU >Hׁj|e X>{1DV ")5~=k_VOVjhk,ʼn+!}v|;:N+[, PL4q=KIzrc v>)/xi+ұDb4C4N8Y&sXxH_K)hJ$iMB*|Թm^>OGI Qr0mZoHXEOJ&yJ&M$f2ym*ǕK~F`iކ&O,+"G`0 !ia;ۖV+ъ&gzf %ZUI{3?(]ǤOVINq%fE(LhM+4.  $JJi-sž1owFˁ[R[jpz&LXXɏZX*5_S?[TL믒22hR(#X%]2"I)Β(_5jɱdn6mƒ`{>EI=@[38%:zgh-¿JP>=.'iF{oQ0]s'Ng7hSB8a*!]0C6,ގ$T2a,f̢I*5j8Q &5jc?p&vX2# =#mm/2* QRyv- A" RP%DgLʲi]NML(82ԡ:lKHaݎ{63lr'3l2,bI[ܚ @rcvKzT%%R%v@SK-d֬d1:* w[Y Y(Gk^bdjy:rWPf,uZ֖{r-,*nmϢeRvPUѢ7[j#NjDhv@y#[Av=UEX,IZ;VPRbi`#//b#E`bGm n,e6 )@}h,+)U-)XyX&0bItT7a "N۶ukofLIlnxo3U62ɫ}:"tSБ#`Z$X}lOdH1<TjGZLj#>VTM,#5uYF/*Fo<5؎$$|b]/mP T3ɩ}}ͼcZ0T;aV6h똢J=:O"ݎsK$TZ@ ;wMcGac}Ґf);s ` Rj$AB:QL̈́J㗪XV,a"}q^+\4eIR:f9۷(?L mFT\9Ω̫7t';uDi$A{7gl:RT;lqJegZ 1bH$f~k e@XR١eƛmm+MV] l''A2,zr$m 3ɕE1FeuL'het \ҿ^OUvӲnRv59D[ݤZ %gŗ9 Sdc={+4jni6IadR Kc:I* S4a-kP$%%ޱRgOoLYTI1%ϧF/*F[뿸% -ޠ>u~} #=iYhH5u0%RL9U"a&h;`RN3&4nCCfIQ{v8VyuDC(gܴ$rGgdg S?UkN"Rg҄Ś h*t5PeMeIg&Q6Ii Zl pHXH$d2̲]3#΄rI_W֌Ƚdbw'Βv35yP/+#d8`[eSH(%D]d<`FA.{+E6YMm mȵ[Bvj={qzؓ(dQ` r>돕k* a֯L(CO"o eUJ4FPVXV<%X1zGX9b-eZdXOě 2٭ͨ<܋,Sj Cȃ?jN 욏:A>_.[\P'@IH[:q4x/^5j?x;d)Q)!%fqIAL'@gcMtb9<z\!GJ,qr"mH")!tH(^9pd[;sw~9-mN'ztl=PI'ҵո#0h`ؓhmnzdCiL]tB,!8"LPTIu&x8C>KP 8SږGfbNhBXt9q_$khDfpVN 5><Ra67F"޽X<5j51JU,J\Z d?fuׂJ)CuH#%LcM,"V7Ak5 tEf 8vGaJ![<!y;3KiBCH9CKl&W/u&QNq_FلhѠC> adOVΚ%FUa-)T4ae& EG53ӒgN˚b./t½U(P_=e-;4csl38[XQqUjݻ!Z>ydqPr4q$e]W~Ht};H'L$_w}{1o z1S-fpʻY{h_ pPD/!D罴c{R3$50[,ҿb'0ڴ^J D KҪ$湗ngkNXeфfi*@fMo_$;ad1ƙB kM,BѷfxD 0;s L P̼Aۛf!ݜ5=ԃ:d I"XS 3L̻pi?3@e=2KUr;3>~ pX KuKr7y1U%hQ$SX Wf "RnW3k<I$5o8 _ȐmoYQ&mz| {\f3 мʐJr0oE6;}OTEҿE%Ld޳NPKkRQl|,ObF(ai=,'aK'mV98RYZ1HZI$ 'T0y K:{u;g{1'J@Uͬm<aj$/S=4CUGw"QJ@n~MZZI.GvQ`R! յ k   !1J !Z- LY)hbgu`9RB:Yʉem;s#hW5#:S!fUXZhcHޝY,s\c,btD5Dw[sf^-݆JFc 뷵Os5C)߰/˫=T2|1drcQ opI.h:3lBe54Ouz+zA?V' {@OC'!74˰RcĚ:\ $z] IJKrKQQDI0 OiyfCm;SQfē_ZIu!4}&Ʉ~2PYp$Ö́mD/#a@pV?NE! NR:$0bR1]5WTI49g sxDڳ#$w0Ef!Dp$΅9%!Cm`L -q<!e#91(RBh&mlgj#3+:dbIfצ^wP$u4JI)\5Tᄁ+ ;:Gl8V9&Xi\Yqs}0oreDb[@plK8ܝ`:al~(E*B|x3Z V A:*򷕧W XW^ȕ=:t9֦:,%ج j=n;'DcOfCb&_JV:nJI)mY(8"Y{,O~|>S::W&X؃sXm j4YHMTD LCl ]VgM<gH0#IDIqr|T69Aknfz\bTLYX@H9e}˖GُFHP}sTR04YRr5j5hXv!Z]d ;ۆ%C,JA]a.Pµn`*_חD qϟ>9#6/E,ʟA r] 'gH\t *J)!xv8%ʩ}k aFL&uK,qRKkXsY:[j$zV0uH4#Y#mT|)5fXoDZE+$m0S`,r4"0ONd7H'Hʰ=C-chi;@*ԨqD%Ԩqó TBDLpO:]7SOPJ=߀(%#i.ŽH&Le;Ǣ69fIh}D$6j]g./`̩xOV9:AO6؁Ŵ7:!tdIudž]I F"IQ4N+H)fJi94j"2edenP-z `ܜ-aGJi5UNXs3bu}9I #vX%,FlwxM9kXUF#*FCClq_Oz\zE:a9 SkN#vT,A #x}uZj)x}K+jHbG"M+lqJmsreϹ#;7`' slc:g0\ҧ$3uN4p%91i{ E aj%zGUz$M)\h-WzH$t・ O+m)z x3cY7 ]~DLRs[ӗ:kU2{$[6S) lrp: Ҍ"xdgx^#%j55jZyxEI}%/ÿG{ej7d\m[i<;VM5>x\? 'hWE)Ǒ>;j,5h~} fj/Y$1k;W/r*ob 0]=GGJqB K):ȏ<ﭕfm۶I@&aj$qJ2%F"p(KJ)Q#jޟYE )!ԨQJ0Q#XDK$ƴS4ӵxj)OQ;d&TDX:۲z ;?-*hb J19bX= :̤i7fw:̈&JDw;a)α%uCp*@MHդ2̊AEzޏ9CިY~z zV+ !0[+M(AXJPl4DkvZTh௝4Oل>qEcfQmG,YnSYa@gt"+(XY#~r\)>poVplu68+۞~dυ74n39=AD( e*b`I-{.=YIDKz&X69&X NvC%4X:WcKb9&0n4)UƲggYaL2Ï4ֱ߶+đ&6=\o090J"x \TR<‰κUF RaV6,-S,с$Wrēܶ5j5Qx Ld2TIZ۠eϓcZd:XTJoԬhCTHq Bb #;n:1Fof>`lI$a`6E%YP[AM640eCA!Ot33=&&8ךzT/vEk.H= d`P#Mbj\d + ,[w8G[gyO{C!@߳8 iHVJ4+攨Z~'8i&뙒UFKS(Gwk.XCy%:z/{0Am"M"U>X Y劅y}% ~#G4IF+,3}@׿/$U )ٖpʯXx) |p#M"ǔssYZy42b*h[JcsְjnĨ$*ϊ]̈Nַ:6m:A8T(!tx65$wlOnL"NE46ZtL/B4!:/-Sa元]P:3$\Dhd3qmf=%FX1g¬rLC&MPns#nJz,"!dV, .G%e!1k B-PE&]٠)%Y11Was1sChEy(T C83R~wPE(K~8`rV۝SOCOJZh0^de8'*WDM6&๖խhԠ>Upky&ȠRH *&nqaƋ?"X*&ֻ.H*!փH F A‰^vAH68mO;!=˞:ae8+ϗ{N<#1:f""Ru\$ !,b ۆM,<$t>GFG#*F8Hn6ve$mيXeDKmP04J̎Fg@5R+V2H*V"8.3{AVcz==jFmY|Xv;C˫,_[yS))hv(҉^,tR0#:Ԡ`2MU);;p[DIo6fyuNٙN;W5!`J%X-sr!^ȥ[Y *[YX7%'L)EHQFþ-6zxKJiCkREX }\RvrJ΄Z0ElN ]8Ю $l@?g;GncӖ^h F+.B(H#\J%)[?{~%kBQ,!i9)0eߢKY(!L%왂O3ێ|R ?LD0GZzܾfR{MmčR;T9akR#0KcmQ`R!MNnUF,ev,L[b;bYA+}n7؁azBK4)x9 ReL}$u:FML H6t2-B{y_zO]Ddb-3n#L$C0=ۆyj#z}6'$J#22 ېxG[ "X<5j8Q &5j(~3{9AY*'욆m-#X[oF4A#h6=j&xkz,?MNI޲xo,.c=I„#Y@.G[ ŽA/hQl ۮcwa( JᄑQl$MsH詔;l&T<ɑ. 98Sliq,}%`u2ik~Ȳz4DI)`_,#7Nru8* ̞ xR* M&%'pVfaG9S"&0bIk2J2Gǿ` I+ݙH<xbRL9koƣ\-RZ>ςg5A#6ȟ9 Wtb2E ك5jԨѭx>}Jkxlڰa%Ads¬eP%9nWsyT;o^9D ]P%m"Sp! iZeN'vG5[$EF~w0FylT,IфP<ܦt0cfK@qW-U~2AUF0e` i7+)l0Jd燾19Oz׭؃HAE ϣ_J':}"0p!O2!% q_T^瞤5 @XyĒfF骜0 ZT \XF @xS#+/>^@ZJ^,Ϟ]1o蒊2 * ߂ +/5jԨᩒ:}}xv6o l;0Kѱ5l>"#{&7-ŒFGc CYzݿ(9Xw9 ,n,w`ʯ<,&E:'=c__^dmuՍަ(7RrvT?N&5dH iZ`?$B|3 ,pT-HX¬wt,vźǒ` 6hR OPuI 9 #X$ZԨQ#۾F`V1M:-(efzfDi1j o`d}adFa=YO4F\RUNzSaJ;+w80I` 0'Y㴝g8'tTQ@1E3I6cEoy2[R d>(;}kJ,f ;5GzMDʴ.Or%| )1W+hX '?]\`2~p\gK=88Žc)?taY_8.U5jX7+|pٲHoײ1j忩o]O]WEU|&[c}"G,^r;Ѩ.8S dGsR)nc 8W!8'g+-sz3hbyiKpt{2j|}MR-ani:˃Ƥ_S<**JbL6;ʅH $vH!L$G2Ω0#yX7Yߠ: ;K%o5^TILqbg 4&$15W"XV:,!h5] NS3ѝOY+9Ty@-A⊧k}:kRtTs"l t"0"KU#~05BEFlr5ɍs@ MGm$ր& }~ݙFI-p|`D)H_)Mf!ȃ:Ȓ̦ƒͥ֨ώ)h3iSY2'dn80/Ǟd#`!}6dV0tKjMD$f2} >ޗ2tc>QbތJ8QFֲ$ʬy EZJryų_##y!NY3(X?S@E7:EԎ[<{Ldg&v0k]’9q6ML"`De_ N4*yW}vj~oHNc%ƗfayM18㚬8r6U*I 1da #1Gΰ,ip]xj%a]{R Aˆp_sH8QF7>5oxD .g!*^F ;nI+ A:$xX8FH5yؽhh:,ˆ%mT;O3|$tIjYzaDHR5a I3tɬD:ai,yp$#LD'ˀ9ѿr)̱|t(= PDKӕGUѲ`=[i{XZfF7Way$5Fa6, b W&f(իM}ڈg"9\ZըQh7h@Lh%-RKQ݆v=#2VdW0,ylDT^Ϲ nZh~KҲs2%r8HQ!0*H>YəGPPKPɄ%LIV[ [6KKp޵eIs_NnGVA(&!i+4U1'xLwgl*4m]QۘDgNcBݯY&),fe3ĒXrHxFll4CA+bRL5VTI8,ӈRDxj&z=*Ax$!o/,Oyۦmv0mv$y"Vr*&g+XJ$9i< X;ec)sg?c0 Ym,< tH&5#j٣WܾYD0&0@DzB[\}g;yJ&$R Z% -_u "g[cj)Jys>ķ .0ֿWo 8Qٯr@cIQ >+5jԨz3|ccu8ZwgQ+>8݆z$6Sǎ'l烵mLR!!V^OXWvˈ%6$,?:)+[b+h|M!xj$֤qȫ kR ca?dKei~##${0= %XKCSDg(IKFJe$9`/Qj9jo2'm$ZuE#Gȑ.D5i9-HNdN_mrj8Q &5jGa,ж&e)=;>e1)x ۝ -rPijӥ$jsoϮ ;./K1V]N+'Gavf$F%`"pJt;:Rml:`hOŤ:'"Z"0s<'=E@_朢I(+ P7 -cl\`T6s^s,)O[gPbӗfv, F*0^_̴O:G _~S6랥']5j:ѓER$BNS񮕩FxvEH(L=dqC҉^_B@R>~)B5Su6FCwNX0LUK H;2$GA"[r!8DAA¬Cٝ]%zGz9mO4ce܎%H; hś \t2xҀ #gjKfR1iY/h3:V@ 6)> kb^DFGؑ0%gQ"6@J$H$q$G*TS6jGw066$sGrV9Ly"L$"MRY 0CS9=7؝lqDބ7n%$axZ>fiGfr^ tlT^Kn$$hӖk,e2Ep-BZJ7$} zXr?AgY4Fi6{('^dQ T &r%֨Q0m%L.Jr&`[mƻeV4q? )]rxNRY;U*a4rB! Se6^^~f+6Y#GMi]fZ %LUt38.'!̯w\p\iZ߽_f-`N&mN™ali iۉIwB3 aB4B+(a%qSK)k*({%67i}TEpo)xeQLj8Q &5jܧ0bŽG,UkP_r߫ѤnOAb XđFpo({͖MV"/ʱ_g0_2 Ko)xĨq~B5eoӓnJ&1NOk:sI͹ rрަR9U$E*,ଢD&ahJW&[ҿNߧ& Q2d.VՃmN|}5,xB 䡣9D/z,t>dyrC+y/Oj ըQ~UY,&q!`Owe)`7/(?F'$0O7k{x*2/&J.Fa O+aP`&i=2I dzɵ.߄#7e6TDC0KD68Dy)wZ}q$|hV&IKDH"l,J0_q:(E&늦ihhM $f2#h\}W,*z:eg$5mxv $XXe0b̲gZD)IUH55`6pls~ĺFgɒdqTI(H26h:u:K$gL(f@6KoJe67hJ(9<"󰥈:p] sR23œ@fi"h2JR1]c7MtG'k ;L"LA?7 DWWh dLp,RQL 0〤fٌR$X*HuBP~<nFڢgQ{_-#v0>lD w?%lRFݮ{A4Eɐ]t~#luUe,:{@9y4:R/^#YןJI4l{U/橗̰Nw.}_T8M,aJVf'b LmhKa&9x\k4P?"&mnYnPZ n3hW#uvΐq1BqjJ YC!4,͚)ڞFR3)!huo"j!c1BdT1CDNz5jԨ!R &5j(UH!F%Qk|bRSUݗgi2,̝GLD+X$.Y⬍,> oۏhRgTR-5j,R:""ut"V^(t]4.KF h((#,v3e7mo,HI{ YO0}~#9XHLl8x2mp^%H>FrbD B`F ъlt(`ʮg=uDzK$Cf,b^\\N Se8I+)̋L.5 'oܤD$xDFmxL+u9+xT@#)崯/c%zT,ad#TRJG;*FCj V:F,B,+$;Zx׌<%*F HaB5܇)hf;"P.iH 0mÈ$1ʥGY^FgxyDt8qJ܇# !ρVx6;'r` eJ'QE_M2YXҽ%@\&fn5BoKor@ ";Yq={,^#ned,lr Ÿ́뙩%!/,~FK{oRQ"Ud*U רQhT"DH7;5y`7P~/mw5xC&-lxjZ>1~sJzvΏb/yX6=gc)QjJd0)vFg_FF>OHјB>H(.`X1jbRN&c[g׸hX8 "8wkXϮ!ecmSbF4E\c`.Q7Hˆ!hc]CPŽc F,J)̕7h0Y0* +u4[4bĒpȫzIbyP-zRgJZ9 [mz++J+KI0mOfx6Ҙ{cg"p5ktgݖ\l/? `_3fHkԸ"8̳YEW8un*wtHW2Wp8frcp$XJ/(nB#kR0YIJFhFa6qƒ2DߵrOCr4H#)43)u<ܜ: n[` 1i[3, "mc.k}ɉ$Dh0lT2 *tpFg.FҚ>uve$eqwyFFXO l3BWuΞ[L=")LF.8JgaDU[i̢on3~(y(ʪUDxηeh y \Jeͳk,V-Ê*{*$`3}|n+ ^A`7?^: $zImaj2*MbCQ}g{0Omo@>J_i : Ƕ: u>Mj$:K;L S݇/FMDDR$ڬkH-cxKUL:ql~V:$@V&p#-5j0Ԩqt-A: ČAMisYx_j)Z S8I+SI״6ZQ&k^5Y e8zCoYX,_r (x\Q ҳ_p&=éN2JfvF^(`́0zTr XJ@pdZ`x!-sKAmXHn]PedRF F` iTᩪXvxll ۛ~:O .X 'NO[΂煩 3Gp3S1a:k,"ΏV~Xg \P!t p":Npk^B$'M3"IK|qf$oږkRIvfl–3`fR.@bWy^JZ ʝ9]1)D~Q8͞$H&sZ0%k_Xq)s'"Rۭ^|g=5Z~3>8dQ,wKA22U^ =Hb6>Fj)s6gzp+AzKwB{_Nz Quh~Mug)> Ή%rE#T02nc # $8TLx,FG#*F#̢4-ۖSii|Nc,-34\'RCi"چo`=pR Aa:L4֠7[05$31ҔRFB؊Lg>EBGGu$Mo~ҲQ % a !V/a:'HC.M,Ap!H&z]'HbS^cxe$K(!x,෥@XA)鋳\?У  \/V̚1fyg=[ }lbE'/Aх[[irXk8\e$G;ΒuQ:Ȓ=yvVqqEu/L<צ F K3\B:fmFN~pqN3gcXώyݍ3S.ۨBQl(km9~SNnܐcM9ySNݔ\ߒfFrw|\riuB޽:+7;ۧxCǣێiN  O)uI?Z+oW?41$ 9c˝kr;rk=}Cܖv۝@(hSNSg9qNn'fD" []=DcheHc,(xXԲ(ijI(AmcdKI)hcADkԨQWWGPшՃl4xMa6;5b!|59R:AO)%mO '!{tVcڒ#d AL0 OrqJlz<̓,&$[Hw ֯J!#eK$4w:mccbcj/C6)RMBeL[hbq/Kpcʈ%I}"uMEL(^Hugk#0 hR=M:eizlE9CLhz8wa-ۂO$C,JFi-"&xgMuY Cu<ԃaxy([50<(*/Z[5.(Q?dVc[Hޭr%U#6&ݪg`_f߶e޹W624yR/e$bBD$)ƺH {W=1!V?<~yЩ7wHB媶-̳흓r{7W_^{I}}J›v;^>Xm,"SJ*\f{֣vey֭{7mY GN=!L6F.$F$FU?,f3lroOqT٤tiERDpߜ #L9TŤF5=J0Q3L( {*نAUMJTKrKLuuAiGKL:OmOAo,mVd7#3Y<5̛Z&̻DkV6t$wNvx8t?k#R7)Q-A I%9=.N>i2/aBu9T'4D[ඒrm)<6.0/9 u^+?ZPv eaW uu1_וhrLle9$^ڠ&\P剸S-)B߅i`Rrb/~<$:,p#xxKuA;g6ߕ}]>_&'X!?M c)"H mh7Gi4KH$nOYjJ7N]zmAuA䅷>&o|ײɩ.K.AD,,Zr$oE(˖*Iӌ(Mn{O^y{ߖ;oޅ~H:h T7y1a|i=l] #x.IQFKz>tH$&NJJFQƠ^I%ԨqtbJOJH"LӰtT,ru\<2InIzG6 Mqk[9_!Ai&zPr Fp\z6&X&ri!OŤtդgd $0{#z2*&C}yXφX}Lr(LJl -{bmOtnL0i#ro*!5xv=l0g$=RUòY԰XJ9D{ AYyߌ%%_#2ճInC”s U.ɥ+&Cwu81|.yK򡇿$ymBh#KXIyoܺsZNʝpZM9&a$v]I V7c9ܕ{r)ޔ7r TdrcV67?"_zx*b T|ͩ%%,rĚkZߤubت;/˷Mݺv~G͚@‰E2IsZ)vkrR)eϞB詔@(A.<'/FP 4r:Ԭ5sHocPhJ<ɪM&8W5IۋNJ% S23e*BSB1VlS2{''.d|{*D=4M)qch#~HJ9J)n-97}:GzF޳9Je,fGI^\[eϯ){!,X.e@}k%]<7֖FeAԝ%H'%JrLDDߖ?9c'ޚ߄ݭ 6~P#ru\ܹyRd{!m۲o?網>ږ͵-9ܔM9wy[rm.{9-_}Cay#܀a i1699cdh*zy|9g3j&7'_o䵛p5Ng4k"5q|OO۷/v!㶏Y`?7-m_Myg^sIf$r{|{?$_'ݻgMuR bHҫ,^hh=eY"l~_[7`o&Sg}\6G8Nb̖ĞHaMz4Ӂ%C&%DO!2 \gY #TrJ'U٤FK*Fa7bmZ,mXYXp-k6Kx!$%ĔEHiRtNY:TJ7$Z|hBfgx3" $Hq;f S1@JlIҽHG"A2G.(L 4+3/T4AB Ho`Rb}e^4DmR hw" ^Ȑ^07*{⡒S S I=1W9ݴ<k Pj,W/J*qUW,s0k8۫%W!]+{]@2I.䎳t>ZDzr\ ^,?ԟȇ}EgI;7n~P^~ %ok{Y'tX}}}S.>xY6ݙ "t廗䏿շ>*u+(xS',rGNZ֊$<9Ѥ(/]xǣ= ? ]t'P g-[or"G(&!Xd[x2GDL9Fa!0RF=G*F )E45" u^S2Zǎ;dU. AFaԛRB,^@cNːLfЇ KJr%`Cxt0fOk/99\Ɠ-<3bÔL `7,*}k{i厕̋Hgtp 8S2 y{5luF{I.\$rI5>|~:W~E͛e%Juo۞y:yg/AՐ@.G~G 4l|Vt*!n^u9I8]>~S>ğ}i9ȼ Nw;|@z|hUs)JTK<Qo-yo\:V$?iDև_)ydz8DD2xE%vXq[my/k7_i[;!>w_=5l٭{'$!UgAl Q!uXӗRFE=J0QB 8ҊHpb7k" [VydѴ1DF.Bh @`ĐeX^'YTXt>2 HV$BYhP{eLfIdWA]x .ͲAu&f4f1 ;3uUK4!&L6kFWf'x&וc ¤ǂK87Ӽ^eI&,0Ēo)Nop]Y@n`^+ 5v#8HQ#&4rJ,Yl%:bJ%ygH5U"Wn_v&I,B,4&{m.8|/xY$D)B#ri?&ޏRa)XPoSkļkeqT+M3w#s䝻G+?.O?𡥎IbPvke#X̢-Q+eYF%ԨQceY%ԨQ7^I&[߰}!t&qפlC9!"9K;P>Fd`97>=%LtdyVFJ*0VLٳG, Pp+oNF4;*'˥7p#L.&0Iѵ+ۜ+{eVB!5fΈ'Yq%C,I)#8xb.~^q;ޖ%x.K$X)TjԨQ =@zÖvJr*7K)+:m0 v"2+=8J)0bK/=]'X~?Q-qfͤo֍G䯿 w՝~u_dk]ϭ""k͎<}|e7yZ0 W>$7o^؃vaI7h-L›HQWZ_0+Oŷ>+ݻ^?N5jt*5@;0%oBY7 #iB#8Nt;UIL˺~;?xkdT:B2jF2jFA;"hmZyf:'댰mp.n~LV'ݮ\SYai\F`M@6HsdϳiY>6k3rT%צ!1މM6B{0]aisĘp 0S2e3W}AX#ӺbyѬ |V2;G.m]M~ FWOa-{_EMbMrNϖ&t# ioG4Hic<2l3Js>7O>'ߒܧ+i{fQrO[ ߹ -L #/kF0$i"ml+'oؒs'I݋iœo3!O[7/Ͱ\ b>H"$ !Xs̯q\::歹jɼAH>!cC݁!䒔E(sey`V2 l)e,ƒQ !H'<M(I6:{ހ;L:mW]zTu}JкVDa aEBȁZ@|dU>KtAD}-)d~޽ qp (U fR 1pl{<| 0{Ye{gEha^@?迖μ 2jDnȟɽvsq&65A {Q\sAzcƍ 9{HCOmܕ/}C㶼vqm 9p=)d8웬~.[#$I#5;o޾oߴ]O\qpayk;wv{O.( # Ew&b*l[ X>~:λG a۬K"$ pi9CR:b=t=d0oFXQFJ0Q]AzpҵSq"O= '\%II' K<#hUM 2v4dF 2χm9$6hm)aD~R>s t)̏X%9 F3@!z88i5 C0?j&.-{?FmNuDfלT]?C@`=lN%0pfd'NJ"}m_=rM^S`3qC%u?XgrLI`w!7~rblɍrƱ举q,O\e@|`x_[WG5lն&3jr yGUoFAoJ+aډtUFD*$ Y(H}tT{5j5jdAlu6PᄥE&h2JRi`v6Q%ը`9U :э\i5#h" c3T%aV=-L4A^}T?Ф%(}< $Sa\y |i[H(<4Z&E,Z"vF0M@3.t2z9) N7v. ݷM7 #@D (ff#52ry؝Y{eO@ē fW%'/gyxR/6lzeӒ~As_o#5U1rЉwk̪mzn8=YX֧n:u!hըZy ns_ eEӆ%穿GTtËG~-XaviYb8mfD".c+1ڒwX$ڏu1_oܾ{:L%_k?6k1Ͱz2IAvdC^tCr-}[U"O}Ew}3!f[of:۳tHgL⒚X8!4r޻ŷ>+7]߷oKO<6TN'7~sݷEbN>Bk`&(ƴ-aH&3Z ,qXj฿V8I$ "8.9DL\h̓j%"dzQF݈J0Q_IV z[ՃKC.HPу ѳ}1> zW22$tc^#ENt׿59)8#; (ֱٞ/#mp:݁g\x8](hc)x7r-o0߲<$tψ kB%zUm-du׳ur$X.t4-*.f"t (|uo'WTĩY|еis^3K)H4A+, g" , Z+b⁀A°g`}a$|{\gy];$4{F2-[՟JsQv$+9^D\"oWBx^XMmk"{H7"67~oKqScC-qRÉ@]Jbuv1:҇|\hDZYzSI?aD+o6/EMUo/+Lrj%LI%.WsJv^8+ν)Ǜ;c9}<з moP&X )/NAphs\X $mӤ}[;wKB޹{y_{k>,O:vQDl< M;vL<`&Vz;M4CMI&z#˷I*=Kҹq]Ku&m묶Gh&uZkeM[~=Hǰ%HFQFUE%ԨQ#ٞU0hmToZVЊ$R=A }6W)V¨^,6kA}V_76pxn 龎9ikLQ%v,}9.ل'ibLLcvS}ܺq”QFbF[аg`4{'-(&L^LIGHIg F5ZYA y(K\PׅrKd&Wnu|c2( X:]bÓ=n-6Ir'k_Ж%$&+:^55'v1\dd_V4?1ߌyK@ʮ|K='Dz|ۢukUaruAzFы* >?=CJYwH{2m9|CJ>pECoD޹ocW\㦄N6pd/jQJh&i޷"7)P̬[q+2ANK/|S޽{V.z@zJ$-k_\]l|?Ieٖ%:]y/_~}5sr}ھq-g6{#?q¡5!aƚ/# '-"ma蹰IЊ# p4DG|1[Oy>]ԨQƪLjԨ1ک@@02R^N$s$x<=8臭x N2'FFM.2696ם$0L mGVkc"L]DPHI2DDoifedT=I + 3Ct@規3pǴ(ieeH'`ݤKҳC%t}5De}hNf}fHW٤gXH]sF.S5\촮P1RB {:+) >>|-K" T(<%2Uk``]!'*2='B"uER'GI"hMyMlc'/ə&לp_;)o~78{ڱ5'2ݍ'.2҉9Hj $ҾH&*hmY 'i"HyDArd$x$J.QƪLjԨ1PI1a6D}9TЊ'i2 Z5| v0QP7.y :JBrN%NpNj&~]C"+tjUu؅68X&J5u@#`83SCoV,Z$&4Cr_`,5yY3Æ\s>?)8=?ϡ*9.ǿnZ]{bIp^Dq@N'CkHN>EqF7JH'saH¾K) ߝ7€%€%3s5o]XSqȑ|5W.1uK93K[Va6V֖)aj!mPڶMLjw!C//]°6l^?}[wz0 KI՟iW?Se#=eu4W,Qk /*mz[۱*ll7 +/44 b-pR\ێ7~W6J $kQ˳)7o\sZ5G:Y/X^Fem=&Z䝻WWj_͆|@XZ<|r\8VB3A/Nl&޻&-`-w'рK"umۑ׫;΢mN?=hBHR @N 'ZqJgkM~kN4YH_]N=ms4 AT&{e37v%lИLl(ȽȬ0l@4a hZ< & OX>^,2RFAA -z5tnu ~4(е%[FM(NXjW G)+M.z2 ۷/˗/]l0[f,O\{V~` .RYQ"xJҪ nX'i[o3g7|frr<|i^4i>pGW۷ | 5MSUI9"N g/i HQːtu3, vzA #d^AF IMc#J2s EH՟+:fKRꇽLx w;j\4⊮^ `竾,Hj9_ﴒNkP_ \zR*bH4%,9֡gQ-dz=;o-nZ}+^O5BafvCj}\GeMOFC[D$IjFN$P""#킔 )7:G> !7_X9a˥ؙRie^1 kQcH<5!6=u|=)S WiH.QKe8uph4>9HڍeԆ K̞Rv܊SȾPPU,+n_3b*N7Nߒ_oʓmKF"o߼$ykt ` ۙ#uG.}9[[ uFIyA܆Je{k縼xy96=z^(43!>ɤ?[N{X"ՖB0SX'<ܼﴮQBj6;Úb3LF~`ON3gxAt*\n)w9Y =geMAw]rInr.4fv-*oz62VF:.V-l_[n)䬣t_Y;PJhgSV~ߖ\1("FG_gdžZBav>#藹lߓ /#'^.˹cWlݕ 82QԲq&߼߼-OyMȋڶ^;\x-a yAX9˕͒"6!*7 1v% 868-󝖑MĒd˽N$Xߺi`TM\=Q٤EYͯo>L(K[5p8GPimxp5s/RJ%!B"Z6[;3&FSepvnH#N_u}ìV[F268a}Ga2ɷS668Ky|쁪)9_ *uZvޞ")Fsy_Uӈ\qI~kLܼ/#TQNߒ^|ʏ<'w|ߥg/~C8yg#O_xQbl䍛MH{k[#?*:1[m9~KΟx[8|ʇ.~M\}:$uWܹGË]hָ$LmUV:ޗEYL~;.dDsrc_xrjHfSO<]9q["2WX|`r7D؊0+eߔm}FMa/= k䑑|cgސO^0_yG݋EyȭY0w.k;.f-H^׶c}Cvoz;;dst'NJФbw+Iqܸϝv[֛uy= VOlj$Kɏ [ֿF6R/[*'Ի$O'X8y3aGED891&hEGjԨqТLjԨ1"h2GR]Н<0DGm!V9' I&>,!SYߨ!H) da`۶3&ju%WƵEN"дJcH1  A;jEz Gl$ihl )a1pdB5,u"[E&%6r6:$Vjgi [FmbGo+ϭlt5j`A0ulZ\ _)hhuX[g>V R2뛼b? #^+>O T2E{/G /JyÃp޴f[~/>๯Z7 |ՏyMv6>ӑ\<}E>p%ENߕgϽ(:59{=)7θMJѸDc t CnמpR`wޯY <3Og L$?| oH_XpSOO2Ο|[~#-?i㒭(䃯<-;#zb{/HӴ++6S^?5yԛrwu <Xl/'ݒSk|Pblۺ2Dvjkz["h 'i[ܺwCvK5{`OȥSwyq f:w9SRHI%h jDtZKjԨqLjԨ+S91+)DLV%/CBDdnҌdԬ6X#ZǶ!GX nD”F*$6GIOtY}P{TGv4*TCjIX٭XGӄF<~G.ĺFyC̙y6 -+4@&$'(;HWNҵ/*$II9IyugC/%l%Q6>hys Ջ -y"@Sv %<Z\ef8~!ǚלmѪۇ{d^Mg67s3רQn-Iksop>YۣIÅ}yv㯴{VG( gk_p11 $q&SrfYX DSD#9vM>%oQ;/CK iBI"jI__oLEAWR Gڼ%_1uyrjj˪[m˥Soʇ\8uY޽{Vnl\ :X(|ULR~@nlzQB,QDMq,A6z^t9ۗ.ZM^݁Њ&$rI<#pK.РF(>(b\T#2uNUJpYM@a}A4Q%}̟SaXGB,!mt0PA=$̮@9;QұựssIz@iZ0 DH}S9ɢl$Ű/~|왚࠺_@0 FNդi]%Xs9$5j:mv7n%A3b%3m;5 k=X?Y;4KZL% 7KgRRzlrOrkmۨۿ̿}K$GD޼7;>VC[۪1ʇ[$+=N:LKp^K#QN2vthySnf-_|Q_"T/ZZdVY$e/J_)^zG^qbw)aR+P'M>dЉGd{|O޻wYO<*kmzP^Ģ fLJzRAwDƲ @Bءf$'{{LW,I6~_6!'>OFL//: J_ۊG/߾wB~_;$%j[ߜmYOY( m*LiF-`u\y֫2;rcݑwL1,;xc38vRź#~Ct0_ěM"61bv_no[X>~=8++kJF5BF+Ck/8n64ѬMo^}8O5k[olɛ>d\c5 ,R߁EζY?w+O_3׃ bH|櫳cJ˧l_ͰǂtRMp]X mm/CÞ*1+o.:5j@"3-ۑ [.tA0;|r[j}s!ϵXc&]Rp]0yᵔE>gx uv`X~ Np{^Z'Ξ_k.̟ϔhMBED^їB'mI{IoRIu O_^Gf:OZ?}CxwOOJ7b–Zt}N=U,:ԭ]z_;9yWd&"&;"{E$Aj&zXk~רQAJ0QJC>R))98z_F8ьy>cY vÒ-񲄒YQ^SIۮ߾*>0qQ|?m/-$~>m{ƥ͐Djmny*rlzX}5%ax=Cک*N#M/h2:#HN]%|6MDaWYGxVM[Ȏij+F9+/F Ӽn7rVgϏ=>_w82B"ɷxI}!B_G_gc`9JzV8TZkK wjȹo'+HJOӞ?yAʔLDՙCEs#R"NܑcnO^|җ~MZmS~K*o]d""=5$xW~os}f, kz\h*H(ao%7o6ջW[ߕO_޷\k_l[s@)u5yDD:*$HAl {M̥+ Oq"g$<.#Xׁ$~SjԨQEȩQRY0k2" *XF͚Q͌ -R*TۆRF[tlwVlP r;M,XoͬpHYv5/,zVGY@zfαTFU~#YDҶ~C.IJw&[X$ب:capkgV{'Ld5!CVG{*[SEVAR-M+ѶO=cǯJKiD>w{fh=7>۲9ڒ=#rh,Wb+"A;?)7N^ gȥK.&mg%h&Mnܐş4d>VV~鿔S#Wy9}q+}"ܾ,;i7W{Ii^vn ֎ˍ{ΝOlzR u$X%S$ɥgiؤQFDA$z ,v(.F-*FKSH'JRzM DF`AZ.>fy$4mܕ6NKLPo3IA` lz1O9`a>,d5)Dc8"TUդF~EȐXޭA#Z*TV#9vr+ƶE߯[_bߟ_Pcےoxv [Ssۛi9~cz=*A.ȕuV'5+7?}ъ>G)ߕNҵ", i;wCYh\bhl;5q:ꌮEhrry[;w;oQKMVd2бw&LIXx*!fh|ԨQAJ{QoDorc~F3@bB4?c ԟFseFO_{8pI'gޕ_g[N.#m?`}ic+Ͻ(E;{TLOU~I~o?%ZbLߦ 'cO ׮"'(_|rigۋY%K;ݭkBH\f]>+Or}y Gf\&[dp| g䓜5fXTF5+*F{H.a{)\4#Y !c0i^C)\Y_sitFkk3?3/oL@,Ž2[<<()=X4a(hGHa6, 1,~Xg:ظX. .*`hm$گ\yJ\I<@u\= ƅprUF˽ kpdxѲJ2F:)0G%, 7o@cGa$G[4CXT%3mLy>쾚8͇~44J%!ZJTJ|};́d=,fID=['*$)^IPQ& ?i4=r{ _}H+o3D;_dG~ Oy%M#1yD=$ɽ|әƻ{*"硿=|?4fF&Kvw'?dQ//}Ye ZR ߑ;][dYmx24$) !\8<|1y~ۺ6Lbd y{D6QgA5jG,s-Nq9uJH(э7\o5:1.0醿Kr)96 Pe 4)QXKU&ZaCSYWI9{FQGK!BRr_77h/@Fc:Dc!9(RXޭ:l o{VUaZO7$HʔX9rX42ηIU-W[{j7ؒ&is|m7l"mQ{-NNaDUZ6MđF)4#kX|ǭw~\v\JtheM'.|/J>]ɫ?#t}??[2 {;"?./_J޼qTb~B>vo7;(FD~/_ iZ>U)Bk%N"LErۇ. H RIWDKD&3|X޹"[;~ܖ۷e#䶯xx;M,Q/<>cc l}:HJMjԨQc_ԨQc?cF=NCP5IiS Ј`Zڤ_T_B"|q<Ü2ɼ0JA؟k+່bW_>eײ9xh;άķt{Z P2)9V#ѿ-bg6}{=5V߆`up5T ԓ^ݩGK!,Щs>}sY5GHGKﺜ4~n[uYwrI>G}c,Ma 6Ѩl+sJwF.5Һ-=qyʍgz4qY4MI Ϝs?٫tZo}'xS]=$VG^iVܸ%??rq?#E FN__zC'g Nǘ=)f)ܸwPWi[e"a;/ϝ#wVZqR".[*%TJ,5q=ҕlOg$.^_F5I5v5J:I͎595d !dF$6w9gOѢSRQn߾-;Ԓ>*2pԲ 3Q-ə(TxÞWkjOs?E;nsrԩLN"cF"W{J&ֱء1ޚ $Aj+ٺpG|y9_cl`T}$orb ,yKAs˞IJ]N9"%+SH.B+Ib<9Nf`We#o}I]^2[i*s|Ƕq! $anv`M-ŞMμ7-ʾYz_W r/nȗA}IhB nOǯ}d=;{T i޺ Dnl?۩0)埖3'Ki۽c< h [a A~yyKr|/߾1gl%mul? {ھy8qHFo~J#hSg]yڗ]^N-oC'(_k Z}[ZIA!V.U :Lt~~7pun~Z-nAb7hc9_UO٣y95Ս:2glߋ F> RWF?L$7ҺvF̗=Rb%ES WA3f+'"/ݣ\eLiJKY_ {UT%B'J_Z߫<H=v{ؙhѬzODKpQR<w.|ar {T6!W|W͛HLƶG2iՠ}ZsBɎ<ץ'.q,Cߕ'xUui7c_aݓZ=|דLgir$饊&dV Gz`f-j/z޵sߘ%6d2PK^'ΗI %qᲔS`+RΰH^%>jk5e rENc;60MoN/G,Ig%zA#mf&\yI^}H26R)u'oyDd#lɳ9#x"^]<(_Ҋ,{W=;z5ijaJ%zI4Ʉs=XbLVtꞷweݖfX'#H]$,mol\?w/xJ2Qa>5jwiM YƓc~1,wR1i5.??vLy2#EQKG _ڧQ;cؔ /ӿ}՜;wN __Kn-&;&$_KC=ĭȭ[ӿDz&Hږ?cig翧jʝwx{#I=`t8.h yI޶֬˕AC0@0ُwZj/cv5r")UȾ`T%"K9A}\!8%d,G+Qa3=yE6€ͮc˺w{d/zƹ2i1ߕVd'[~!1m5>١|-w-jlHŢm|0B!QksXۺK(A{рVϕIҺdj&ƪB}{NT@1scw#}'ߔw&4 ~]kߚXDwϼ)Gq,r҄6ۇb/?'[;hwѳ4d Do#VøsKƇt|ݖ{i1]S[}|%髊 k㞅^ÓE?y;(q$v96r' >%Nr@5jԨqТLjԨrt$BN3¨&(kxuLF/gc5Y5yn(냉-6 CeLU7قoȉ'ߕ;e_'y@Ehգ=&! S;;__憌F [&xHI[Y>iFZ?Fؐ\(`ݗu^k ryKy~SIci!&5u^JDe&}.٤>޷i$Oe"og^yi9AdyQ<ׂgY#d-.tzFp_>BI-r@$װgxQΞ|wbqw縼xó#ZD>ȅo>YzֹA$(wړ>{%&4=5Sݤmm[)Og6jZFUE"oyDظvž߻|c4C$#.d6UKpE*$\w2?ֽ֡% E|p(֬s>&q; 3Y K dL Do܀g׌X^wU6QaJ0QƁ$L%] Q3*xrtl5r K&^ђ{vbrD>IQ3v#s8>!4AΜ=-_3muyߐ_(M˟ܠR)ٟYqrS=ޫcwu.\ٖ6ȇ䃀 $%y!oln`ˀ/IdV%KZvVK;3c{U]_y=3u׷z~Xznhh?pp$e1N@J4**qm< ;C)]zJ䀟B0-~^nW$:C^ϫ$qT2d>0fƔ;2n~vO^b/]uH^'p­!DkGůb'%0N*xLQcLW_M.`$7i )О Rο}`S:Ô ]K2_sJPiJ7PIj0 P<2; L5N0R`Hj b/+1˂_|RmjеM!Y>ylDmuPgKJ'KuX0G* h?C nE1P]1yLJd Fxp;ٵY,@(q<oy@D ), D9$\Up,bWrX̟+ ,ڎ$-:(VYF\BND@We;F2\WiL&"B哝lҺ1lLu!,dz29,K%D'A3(tU>~+ vNݓPPZhJ`ZhbLɘU@~aQQ8*TQIPw&WYJa2PZ&I#=R(s*?Ux]}+A$D~G9 VX;;{F̷K+ػQp@:Ƃ ׹t:'])(A0 mbәlWp"A]u| Z@Jrݢg|F,<4၅\\uIfrtL'&u\@EAC{Qרv뎛.pN]QEJaɵ-k iU㘞7(b}v#N়ⲗ ;4 *BYKla_K{*$ 翮}w=z!J+б!&"G~9 :QĀ L@S[ڰɾ6`e NmP g1m۞Ou/w;/A4Oq2#F ǯ@ڎɻm= I1lڍb5&:JGwݫ,AmraYh>ss)ذKfKCc.(o=h|u 2Rd "onUH -B{aZh|@L f9#MСANyPI B' (4ɉ0pE-VMlFOıxiN+^ǂ -\PcN8BŦcÆ7ێd"!ici57PЮ:D9>xsf#AaLVU%2m]*:Wy5ObM6]Pb :sR;JGJG$`ڎu':6 Er>E(wZQm*g8cuJY I-똊t(>mb8ӛMxsZ"KAv1ouEY2TSF&mTUDUROZk-B{5[0 -.p4͊NBäMV?jLjS.vELVO-qyit5&y/kծ}{$t&c5tl :&!Fz(.:kc:XЏ0eܾr} u庿S b4Td*ޙ(o2O&@Tǂd!6TOHpLwKyey$ ^;GGX(TYKv-b16raoDƎ++OVу(eVZ߀z^<9D =Df+q:23gbS O,hzƙLXPI,H"Js|byaRnWҪ)J꡴ L3M3׭h7s²XF5H[nwC+yx X<8m0M9bX8&RԧdlP՛ \MYR60k2\̒."Jш*s2)$Gp(H!SEz^Q9 7MLA 4}j1SG.JiRآ(mq(uRl[I&J MQGf 4ɏ/y?2)egQ[~̋T6S<,\u;LT@<'K[!8"?>p'wc7`(U%$YP⻪Id,fS,o"Ÿ3 +܉-:~nd*:fB~",.i8QxԍJF#`Sg¯@G[H)S:WaŴX34TNƙL!NFG(sMe HB -תB b H£w-Lt)ER+CTtusPZ= iɑwR6K^p?)g,*(G˞k7s7gXn>.%WHn;N@,>u9,&VŠ9cFcqS- RBN\LP>pe&4|Q;T;KPywwEapR j8AwjT V\%=2z|˸]wD43E#jQ)qjP9~f2 ٫Hp%Aujmc5E9|E=IP8tF T-%M/`xߣ9Oz @X>T2n8iSRn@*2$Abݥ.r|-ja.Cʍ븪 +e,|KaRmI}Ul վj8z,16y^oq]$a.P3\P[^Rz#PIPi:s^T %?5Cy#{wӒ]"e){Nv?n8y-S{y%pl{˿U:oY 2q%b81l:ŞW࿟7fCTኦ/*rqoDTCQm]*Y"g60CJBB刿sƲ8N[|u.O+k@uȧZP3jpepɔ>0G}M[J16o¨6Rg+UukZhf [B bO:GFSe:յP>~P6{שRL$z&ÜA?.OrK-lQV^!h~N^x[ޢQ:Ա.+n']wxv۳̛##غe'^4ԜsaƌXu*WV]SN;eb3pJwA<~^YYӧHs}}}~ Z7e1yU/ NP4ĤU?}(ۄe&hA c掜nNT"An*c@:•Vun\2bo8-) F眼xb=1iG;O`O׆* pAX2/н{Pub>VWi6歘B]}_zKpIu}毚*[9m@@πYk17W jAw{/t`t("3\gTs٘r6j@_@{KDV$kXP[޻-'%ƦXwZtnP;԰w써Ǝ/M8ju8}`RiE?]8hl?ᴖ]Q6&+ Y|ho@,mA)5Xv!jѰTW({-'{@"4&Y9hlEvp]ho9c-'Wݸ"Us03!YO֞Brm=i^ w{@+kn_w#nE4 YJ qӽסiDFȈE!1E6O-݃JsZa{L" H)Bm%l&L%gXB<gF69uؤ(q6Q"8(N^Wcr>4Tw!qPb'CS*VqLO>dPN3G8uf&B h!$BS U6j'uGS> dQ 0K 2qB`2QP3aߴ\d xˇWVVU=gW8ccc_bR1l&r,[ { 6DpϽ`US2,vS1pαuV<ԓ.=܃Z XQv?þkpm!)L3+`pp8uӧ'\t,Y5k֠ PQQX,˲9f1::.ׂ;waǎI S՗Ft89FL^ѱKp-3w6,X$ʓ•PQ} ق@0&iu%vdB4ʫ!(QI9 YC^*EjGWnMvpL+A][ #etqNrB!A 4ѝƺ+RH~~-'c$#06T㎿hFx{KSpJDsl^,;mڅ=`ۏw{SgF˱5 pARil{x%_}[޻M4ɊDɠuu?-n~ Ysس Rқ֋m7+:(f0 抾WK.BcӜBUc]Fm.cEFȃ@=Ԍݛ}5inO|HwoޏmG_)h&+X{j %fY!}C۱{>&U'+k+{oI_}q=^܁_t;UsЗ~Cۏ({ 3&<2=nj>ֽǽ>n)Lѥ`0y2VMY{hj vw_ ;YTg)X܆"e@&hٞ:tDLIMGΎ 2YJ`{>nD0 N^9 xuxhj%G0wI4t8yn.tK-+h Gҹ ,5W{atA_IaZ,Nff e*}0 %my jN9lԯ&FE ɩ~_b <ɬҲ6bE0|գc]#08և\:5 gbXDدU~Koԅ} b_OԵAk:0DB -^LB -?1DPAAPqOT` EypS=5W;h8)`:T&80þ-;j߁+RqW@zQ1/&r`kp5'G6®wMw ccc@$;991|ۻ@+boºyA;ci 𖷼555m{\4bӦT] wu˃wqa6,0<<^Xf!vlܥ_-ulc`ո`^llIe{"cuIl ,]wSe) wcw}V,]8FSd[(o6ϻx7?"3G+dwoW~ i߰ԑQ1X`iHYSFRL&A7`b?ERRv ,tH##v;m8е<6(QD+`E@6@f ù$Fʑ+ +)}8?@"G(JN /XU]1dAzkSQ$Q 9 '2DxbX} fW.B:h82x${vJG2o](Qyc'1Zhj`ZhJeЉ< lRtl%@T5 6E`6;Nsor-yilKoZml3~OWݾ5SMYv tq >V$|l#MsH=cPen}h;>ܬ|yM1cA=q l t {;6±, Ìu_Pk!NrS%Gkd\{>qZN"5Om}5WeW`~qe5q-Lg }f,Us+ܰy%{.I]{x\Ј"$?+0*iǨND9K«J l_KJ'qvlZX`xc52:w(FD74IȬ# *b3`#վ6P楛n,g}sN,;W-l4[3#5[-5iFI-w,"K` c2*ZG9rDXYzЫ5Z %)C]K]3BԊ#"$Ӊf{pfK n%&ݺbIQgA7&lܹ4n&R Sk Ake1 -B{5Z0 -.$qt :LĪA0{L ߸; $bhkkCGG\w:\rCWڰuV%?ގp]TcXմ ^w-V55dСCx҂'N N6He2̝;WaŊ~ ;X \;|΅Od),\@pw֬ kJ qp9[ 1їͱxCt LP#zI,vzKm<ǪUCN:ed7 l֬"˽6VuEpS3Q>(Л6BEay$r>q(y QNG:1*_;ŏ0$P0JŜBV"SuX*fj/cAtr~ÕB:8 *{\UDYtý=EF^J҈}zgu. MZNz4dp Ûv?-G~tGw?F4o ·"˓~^-b@moŞ-{~{,Y#waƗ|==grukPst_,&VZԡYN3PdAQQFEkyjqoټ5w\;mOm}5n7ݛ$۵ζt`}R_]w>)N\{j\N_z_6M+pn\a%KALxKX _v/mڇw#.ߐp8u{*3+\+#/be})H2;M^W#J a XKD-\_CElZ1c@_j* Z[H[+0##_d2  7QTFGut/L{o\[Wy;4nӗ#cǔ~ΌLYS8f~F }9I/}K8sv h4n{3:BVDHa'";|s<+H}C=J 3DvA c8~\  c@4S'n}b+V{APp-$xK/a`@@P^^?t_pXT;/g+=~[pudP:UPJfrʚqA[׼0*dn)Aui#^5qN0 CA1u86[.Uw嘪1y;ŰqU|A.y+.(20XXyFp?_%v95ƣ_}&X5ڶt^,w=ߐ`1Jа*#&󽽥?"HclTU{trݫo=cK$D69Gv=k.x jD暥lNpm0eZ_T%kE@ɒ5 դ)a N'_~][_ PQD7^8ݏ_^ڼ/8UM`8yDZa폼{UÀ)JPߢMMNGCz.ف=/spjKFSX/Yֱ~|<ȧ.Oiv|_1`T) q}WN뮻UHz<9ho;g` P:b(JbƬhkk3e_|6UvǏbY{-ȋqF%a`8x {10DԓH\/AZ/eXHBee7)ek׮EUU5)qß_`48~ lHs7}ym2__c޽عskN.'hA?C{vt#LI`)W @nnJ^vO{ F zf4,JJBj)ҔZ@&&I BzLh%¬0XKU^ur9"haY@TuLـd&XU7-srdQٶiX0]۞^>8p8σL7l)YP DFqlo=,]Hx/;m\w<k@(ˢ b0y@żrV ΍oLb,эDy'_Qȏ9suPQydnd0GFYY|aU>,fˀփۏjH/KXS=,lCOt:;}4>cD3g-]3g;C8aqp)r ̘`Fsx'1ޥ//D" Ͽ/ӗ144q^hߏ}{Qѱ9ؘ%޷O=tD"oL&}姪g|yíފ+|?008q{ _͛;_[[wؿ?FGGÎD$v^ԦRN]3uS h =-P &9*WL-cFl)~RMQ]:%Q+d VCIoY0l"rX j:^*x%qhWq "5vλr<` 0ojq&NުMs߇cƒ`'|u#mù~u7 \H8b6Ҧ}.df.yy% l}9-ukf"SyɍS&m&qapPY6xo4Vq/HD82ab6$b^1WtbJE|2M``d NKʖ`$rt7|&1#;p߀90oi1y V!,k bBZE+2 x"^#> 9En؜ c8 .Uƫ*$"IO{|UbK1j!N ljV ʣLE*_h|r|V%fZnpaHѪIWv辗*Z$A⥬'$5C -.6 %rB -Ȅ%Ly0U T::=j U|Bo~\^ eY @?y+VFZxpw]UU;?v$ )N`=׾HSя;9QL2o{O~oh;_܉Ϗ088@'JA&gҥD#^!\a)Vs 0\.h$Ӧ"(02:є/J?^:092Z~Ν8mtǡcY4R~ohX1)aLؼy3vMPSS 4|lذ(>|A\vh(%snf,^8xZ2Nrj"OM`FNCʡdt8* Q&ġ[JzCUfTC2P,'%VɊXHVN lO)\A%5*b=ͳAS'$Q 0$aq86H }i)Lz:[{}H:uw6 [9f,2N}+Zpm6OV4.$ Xϫ$r(pI(pj,O88V܏7.{(PqH&kdhllK2J'^1>8"NTU2R+Wh۶gQ`>SpEP+2ELQO䁱d^jxIxpY\.~~d2 ۖܳgZw.X7qߧ;Nħ?iy"‘DZn:#ݛЌԧ.\I;L/4"{8 o򔒽V)?CJzG''`QN'!?vR jxp USzfcin0& ( 4':ѱPgPQP^砞aqT8#w~OƞAhCiO\hE"?jxmkw@7@M} p[(2h,f0+<(Dq@O٧3zLPT(`cJqbgٓLs3|OMwqettA~ @§[h vD~ c@&#)<ȋy 4KvmjQ7A]@f9 w8"T'R#9**+QYUw\2;4(//94mn_{K0K-掎*%2^(++)>S~D,%K|_|3J㱱 mۆaڵkD^=Ĥb:I4.Jƍ|P:G4b*.XЮg 0VTOr;b1PϨbn>B/FoЄ 6anӑQlU2nPי(O>NFT #5bOVmc) pBb4ShnH-qЭCU]0ΕdjA_U*SXaWz @b(6f!NIuC -^B -*3ϧ0}P &l!A{r/5Xxtfս&: 7st7]GR)  QUYIxՊ_,0xw_s5Xj{uXxÍx0e$p9sAu]իW{o4w;QU]ʊJAJӦjc``@bPzm%y&͒FN+O~ SM#wܝI[PW^y%>򑏸 9|PYYz ۶=\.y9 (99sfСCӲWVVbΜ9JG gf---AU_wѢŨٳgFSNUΓ IT:`VEVaw@H^AGrmdXӶ U6NSPlJGbgӷB!wL-˘tf .p1`]dp*9VP=5{ݳ-?/qΤ8y+;p]m=hXPdEMs_:WJuu0k,)-?L&u;EbFj {9}iUDm7Tyy-Z?̙~ZҞ^G?*8]^㊊ LJOϜ9ҹgϞC}}Y.OsfOrL3IGǜOf vdh7<9` 5y9~QdƐ&P;e2, Sםw$<8}L'+I3BQ]o@qa"Cs<;t;_)v:^ LT2~Źʶj>JJv\~ $+x#?klT 5n=؜dpVhʞXg"D6q7?y% Є|}]} oӍa)T YH@$AH3g31񈏵ȟr8ܚc'9~6lV"M@}DNOpb|R&3XQwk>{}F 8ѱ8`B)߈DX`+?f۶Ɲ3/SCLZ\-icNϼ1 gF}89x `U>T Hªd*s)j?c:$"I(7SU$& s1T (8B -^JZh . VKlQ9qJ Ci5jP1L4'JC_tlKh<Kb(T5{6_guSl||e1D,e9#pYd0$uۀy׊/ʱ9yp G qsL)XU\ٰ8Sgw.qQ݉/Ue(Yvd:cssX1m55ױM} 2}S'qWNUob9QAhk.BJ Q!U40A-5PIۘH@&OT;AdskX %D>C*R6$I+Ή?N#!>EBf XrvL0F=3_-%sn!n*%?\PhO}gΞQ *QTN-! hhh|'8t–-O3D f rXsIB1+Kxve#Mw$P*ӱW#¢$2D^"K:|RI$ĥukB6 M&-ÔtL[٘)_\ /Wm :V.?IZh,ZhLE _n p:JbFQݘGT2;AdRAߝlDr3FEcR+sf{h4HIrYd2ce{l[з^9NR"GՕ1g7~tzwmw8ء!|3Ç|M[A%o:L+x.<%~`mسg>ϠCQ8DAwhTymfsm|FE| E|q" &5®0HJ'h}m,V:yo< g!Gة]|^j2hy> W7/1tJNs8&/R/&߇kɒq46֜O`Xv\{6˧bzG;vl|Ǭg-[~n>z|!3PVry GW[O`; 03Xw>LfyNm+jQ[oC>5Ʒ>?8oFvoڇafIV$++p$voޏݛnC -B+aZhN=/$NIMl\B UUNhA*<N&駿(?QD"~4r٬BN&ճn )x<]*yti4+L̝*EN3{20p΃f(!ᦛn__J*ܶV%4b q9zn z/lзSr4̟Hk֬ ^|}dd0::Br%K*eee(/%wrngn uh>q DMҭS PA *cKteOCI4* +~Q Am?.Q|> -4᝟qpᑝofxYLf ,&h3 \vːr)=lw\vrظK9x u' PN۞cECG=<㱖n Xb@_9[DE3 r=Ɋށǿ lo>c?AmC5n,fa5l tcJG{H&&(kBIhV4* 50 Q r0:nPӈ4 b.)]1xű!DcQ$Iҋ980tz Pu>Ӧaztt\\--mX ö9z{{e0c;s߿Z[=;d9:NDeejjk\NP "JWVnCiIeo2,9T~tB]%cMw6=`u`;/Y(2qE;::ՅH$2466"MiH$z~pAܹs@,SNŴiQbiSQ[[CKRUJE6>XL^&XLTa]kF7 :dIŔkd̤b"SQ4Jp¡"̢_H)#/@$P. -Xj8ъͭ.t,pQ]ݛJvoޏmW׀+H܊*l}N7(&M~H~,f1ޱŻ| @LWvEfpqjȘJWc"l".^O?wo%6D3yDP`N G%PX+벝&a,2X43) "(fvy޴%HP"7?ƇE3ڰ &(i%DN>pQ+M zy%yv t))OzTf;v\"[`|`NITƫ➹9 0bԍÅ!f%&`apjضMc:JFѡ@(N3*fa-7$bzYɋvc3t qy=@N zB -ׂB po_F!y8Uk)QԳXKL@*RwdŢ1TVUW`hxj+W/l&=ؿVZEzOϜ9~8ۋwݸ[Q^^Z\veCs#NznTUU$;w J(J*!JcddXE6MOw7/-[|?唎GvǴX`YpUWŲe|y=|7C& W> H`j{/UU4ɓ'׏&TR৘^6ʡǍPpj (ArH2`] څ,PT'DUgEE]TPZ=3_㯃~6Fˇ 'O~w]0K,۳̠.0i6׿.)h̺Yc%{{8F8.:53mǡxF"zF Z㩑4voڇݛa~\k]dEo;m=2dM<"r @x@;H0͘O.CML@(;7ڋ~-jk\p <{)YO*,CPt}n3 ByrεL&60(LDITBFc'uM z>ϕW^ 5dX Ͽq9B+"9,Jaxe_ϖv:E9S\Эu ]=at W:IKRnL;TϪhPL.Jg%֨|ӁTZfNO%{4*8j6F4w '~h,5<߶w _H/;=0pE]VwXL[wAld`aÂ: ՞ 'K,'EP3ŀV[Dy-ZPV:oե/ՇSΝm=h޸4}ؾ'~ǿ>~/UbYps ~8`wW ܜ[S3C)@ `H A֑%o(DY1 h%qT4Ac)`(b 2!u]8x PIP9|hkBIh6EUD̄nfTwVMhY8U w=XU>vNu*߼o/$d8 -B &j>W>wP C70iTjS95QM؎q~LʪjP,Ȉ(X>ַ|>;д ?Nw]3w~mmx}Ї8~4_gꪫ2e q(82^>2ٌ/Hmm-Nmۧbr;st3PHD{A<-$<S׹3+vҋ[rRoyΑDgL6mݻ}`7o.X*#ǎó>+~֭{=b1,YfC#ڵ {!Ĝ\IWJzDV6Gŀ#b"Jdp J)!9,Rͧ&LjaH(\juY,_N~kDwô1|QY z{R7L)^8Bv.&۳ 2$E1yR&ǰc.bpE^yDe}]nȄ.-5IY '>(kE@spoQĔgj-0hd^ԂۋԸr9W zƙ28BsW6Tɱ9O/M#+'㼋(. *߉1[N_Y*sj̩?4ND.h]8[`.Z14MՉON}a*6B ܍%Č"V\֡|qG+0j^>sT$.SJ~GQUKB -B0 B -462n?B]W*b!QL(T7EBQP2TąqmdsYOǴip_{[+IK.g?9|S<El2|ӟ\yU}᳟Nutuo XVg>46'==8?r9dY,j[?/ ,lFQituu7[K-f>TVU]/6lL_,~ #=hܹذa=lD5CHBkk+^~2ٌQU\Y>C.󱜔W[o/~ (~_oĢE|Ϟ=6m0r6z"ʕ+~V"Y:Vhۂ@$L[4X 3 '{y!Cf>)f_!uJLF=W$Q ArØ Pm\t'+<>)D~3)YNT- B%ɫrb2M yݱBhxϿ@G_BjxLSVKAE#_ї.Ƽ8Ở.FÂ<85.蒆uK,O\T;`C-09L<w+Ut"2I_|@&*vwJF -/Ù$KbxO\"#N|pR[w;̭mGUbCJ}+@#T"3ԧ|^Crb>$>R&o%YK}g@*xN_&'" J8+Sqpf80j!:146Pr'"I_?5t-/"I*c՘^wY;t.x$h0JF6p"]#MWWkSZlѾHR4[dϭW49b*J^kWC -B[0 -V\cK 3RCq\sZ|f XAIFc27p s΅Lq7_*;wahxlL"EuU5֯ 0aF`zڵ=q~#b#DD"8{,NuwSS̜90}tU9 7܀nAxpooǽgϞ%D]jY&P.±g xL ǒTR%5ڲe W{x.Zwy'bطo|4c |3ؽ{H$p%KpUWq~`˖'B8^BxJ2q1@~AXMs%d ,ZFe88l.hDUfD',#S'` Cy'$HBZ;F-dWy Ĉk@2Ǡ-sSt r{<YY횪/T갘\5=k-?3^%͟~(5t|z،S@J $1cA] A Q9^[_ ֫3L%qDV]TCɌPȹDO8iL[JPg*q'2 &32p EE.r723o"rtoxL7~UGd˓C'aRr;G<@4IDQsKؐT&^ [(+-3߸D"]0 Bԝ_ UbARy䤎ETvwIRcZ1ϱBUSPx ʣU 62Ic(W6Y9D,Ŕt|nzFO}Jusۧn[wN6ik(~2 -B37$-МE_mV "h~%Yf?1)upor~u2l6*̟߈.1xfD/Z/gy6oƞݻ?l6N*+++Gox^u/˗-bӦMx򩧰efaqVUbոMk5L c?_bQ,\4:nkA10Ӌnfh-^iӧe#n†]fV 'ISZTB=?o?bQYY??/~ ٸ444}{Tp",\ڜl[<|+lb٫`!W\ph 8Q]GQ-PaP4 ֌<ʅi>jDH>-qB]o,7Qǩ;kɬ&BnPddjq7ffu_U% ^CX B+.]޴wbƗr_%p3ևw,f56zY hAp3.[5hlƦ9%+qlÆR%+h_ѵwn&YN8梳M2/`uF?gbA{gZQX2ca=n{ߍNr~HĹ1y\yNLp20~%d U9j7 dhfLKOxG72 i1`L1w ܳ΁y""l4l4Uy=Y8g»}2:9(*8c@*,p9企<%jxa%$k'(ʬ:V/ĩv.)sv\ #h?s3ʆtd,݋<3عT/ΥSPU',ZP82 ѱ8"!KPGգ*^6XP,,C"Q·MUh XBȃMr\Zhf7IZh®ł̲$)_t HB(#!>;^8cE5g&; >3o+EɇD"X~֯_?~gz{JL&1u4466z<[n-܂aooǙ3gN'0n:5*oXcd] 3gyrqE^'|$A6'yDL&BSVJv1V#S6W_tWs}v8&_/ZwuΥi|@&.hxؼy3/b``MWMS42ΜQKkcQ @5DFw&R:mJDZjtunNB#SԻ]:*OTeiYTt@2.q1uk'D U ݽL%ZP'D"pxƦZ>)"#FAyf-']5Sj0#ŴѴHڷ@4 jS>܌;K֖g'+YWj]֐/ :1 wζ2.[w_*OI则|E5V|"`˜i3PK;1\-8\b{Hhǀqo}+.d.@1"mO³29/{\N9_C"6i(;0)1x,\&Jj|:0fl$T^x @1)Lu(QҩbKv@,g=%EX q<c4zG;; YHFQBmb5 )C"eP AOOLсFİ:`^bL/85Ԏ0gcFxS.u!1|ACKY|Zhi0 B l~IRb2(ݘ J:GwN  zccchـDI߄1lټK.XLrGREEEy9/[ݎWѿPSYQ+Vb|#ޕ= ɐV,CuU5FGGgQ=@$09J?;dAV: X,=ZD* O]?я/~F)z++ַ7n,x*l7o>ҥK1uTJǏsQ+Z2$H-|䔟ZS~ SWP\Zhl!$^vK<إ'5h L<ɡ2ȡ3u>b8dd2KkKyӟu{V^M :FNpTt*GM6allwe"UW_+hmrh$Sh=ڦ Ǿ}pL/R(!/#֋~ܹ uu12:Ol)*[H&8v Et>}wx<\xX,ZF.O?-_awGa,.2lٲEN~f[6ʕMF2D4-8i8r4FFF֊gي-['^aF;P *ZfMP:3.QQ@ 8Ņ h"ˀeCu\"dL&&D8b uG≫EilbR(gN׾$t媝窭.~!S)j񣔅k@5qMk*sTEcp|Ҵxm4̠7??.iЏEDQ~?}N"x=ߥ7-%7L/YLN)߳xRV20Kcנ_Y?tcmf$SQ P3@Î55ҦC"j>LuS겹46E}v]׼&hKjqnևixʎv3`=|e3?)00+ua#SeYoh3>gGSk<岳3{ۊVoX`D%8t<ɋo@"1$~m);{$0fQѨMEEtg5Jsb5394&H9P^BP}BƓg Vq ݥl+zQ_5i%bޝA6ǡڈ`|x(gm=7:v$0gfY ;s\sG9q9 ,gF]ɚɰx$E<ɑ3g'-81x}X>r ;.ë#tILEMb;$iT)DNQIר6C${CHhZ0 -נ]l8*q(EFI᪁35@Vũ&@Dv3E?m`%Xx1vSxcѢE֬ZKy$Ř ?\&m>ujE ̛?c1C|?(2 ѽBH[U~*W2E6šN:8ȈT'$xVn R똳ޭTy!LGбsKXA#Z)\:0DИ P#Lڂ Izъ5w\ :Qpq)S~@K.cJ*ݶ=},&5_'w5_&I]Ĥ=3޲]xj1xq7dϒ\yԏtl+Lxka}jsEMV$pýUqnka9'~ζ8dIq͝W8C8wo~{&Zvb]D.׺:[Nq;p} E$Xk(#sE"<81$X]Ю;%pd9d<hʫ=es,ԊBKG2h=p& ddf/z.߷n!ΗE6d̩.@#*&T;$ IpgSuI1 |>Ԋ~.C Nyrs$DHs0y'_"i[&%2DYѯ1r.N !~ol;˧^v01a'*&oJ8䜼yQ%c"Cت͓*BB -ɷp9^kE^<5dmYK⪁}..dFGG1eJ-Z{+*z)ض`!{u {=x'x 7n̒89ۋ=Я( ɏ́l.L&l.W_V=C&my/'uxp,¶m$.L؜#  ̺`"s. W76A*5( ً?Oz!׏bǎ2.bV-&;z`ku5pE\Ƞ( .(EyhD Ov ::ôTy-~$nv៪ʧwI5 c\"&( \D>EY$9ote+(1?1Or >ИO8* L30c}ϷtDw써qLw7\j8}.Ӂ> w.AW[OY'W ud{'{kX UXsj2bB(n6 t"O4Ve,Mwr'*#t`Zl"$t4 w{@@w)LH_|.nU[_wn7_ph{s^^.ЄkɊ;q4&5G^twoUsc1 oXa]05Naצ[ΑL#W'5K4&K9:)icsNˑQEKgc"»қdPR U ] PW>K4D4Y8.۬T-@!GBKa{$#eQA'I݆F u*~zсg0:I\Zhe [B{kKG7 M(D+)JMHtuj-3n5"h, U06Ri\2ٵ;sY| p0[SVTRL`Bk~(~ Zͼ˰dRRU 9qCRES ґPIRbsB.Rԅ ZWױM@|Vu+L bAl&r-&v@I鈿ee*"GTJe9j<ʅ >TKTm$c? z@Tr}PU@X@P(0O Uuy WΕܖq c:Q1,`hgkx߂dE z/l>;Z=46š/GÂ:*yv(}fcɚtr|P?ԇqpl}Z`$YvFz$Tn}Xf!l97]jk4޴#\o0Ewؽi?C(kԶ#T$@qzx m=b~\7dg[c6+پt`F_5? ՘4Ǘ%5 5r6.۰s<O5< 1cA [qؽy?Z{p 4.eVz_o#onq͝WWomk~d'] ]KP=_57a Ҧ}8yN<Ũ-H`צ~ZN 5ÌX4yjk>ĀDf)J" ul e{"KyDf2Q &Y;XƩނ9&w X9}om}dP%HƼ#<1N{'_#2KDH1}r$eE0-qe!pУgGx$۶%Qb$xJ(C͡l]h")]9@w9v)28򄳢z_2.QTINEo gs\p*'qN *mJP9MkKiK%2L< T T@Ts"=?ϿɊ rWFgx{6P׺z'q{/>4VtuCL^a1qW~ж5xɊ{Mc A[{Il|Ida}m5b'/X?vy -CW[ FZv1^ڼONy@eW\+ɟXI J7GL [Nk&L1}plʒޡyN4?F'~{>~W`~\FW~\YJ^1j.=wd8x沅\a%.6_yL;~/ o].pd&ʞՋxW/:Ed"H(iƦ`{ӑ:`te^|]F2>X'v˧CvRgER+=8TB5Πɺ(4TZZqn&gb0]R@ֶsU׉HgLYn9r6r6c~*d"s9|cqgP7wYU5\eS/Hf#ƝEu+]U''[a1 +_ a2Df(1ѡdyJS~m6^u/GM \Q jCjhZh8LB+9%3h0i*C `en-j N u=* M_$!,_ ZDc12Ў_AWW}<0'udObBܹsWl2ͷn Nƙh Ǒ#/A$ ~[d}łb%MLU-P[Au+t &ed7iJ(679Q`Э"e̍M5mjPo*N6EiPj" X`iAe,7e0'C=]:8⾎%ƴO,Ek<_܈$(0022u۞\YV߻7ǷA-3h-'7'eL@~A˸|,5gx[?ݭO H`9N HY{~O0]ӮOs޼+6H *K ?MUm"(O*Rjx|ۏ ۣ~_~K! E8;&4:[t?c<'~KtLs8_9AGg}c\HOSE[:ǽ7%]:p8qau}qŸΌNXp5sY %&9po1[lJ 7Cp| #*Ql':0A]O2ccH$qMhk;/"׏>d"~tipDuڮ_t\y%.ͷn@&ɡޒ9{[~ޜbvWal۫⢒DR fiokM^ fKQ"7FĊ`,7g ˳::+F"gM({Pes2yPlU>C@Ih$'ah!$hh:49(Ar[ȿ'{\dz, b)q'wNΟgrxߏ9s(48+׽nkڎS?T۝Mm(++H@B%h/董Ħ8TQY*9LcbLe(x1VvNJPܝdJIA*-XZt *Aǵu=&9&]t BMicdc+YM(qIp54Iu:2bg (jÊBS=)vz TIy(zi XJeхW-ƨˎQ%UW@*rg0Wvo.P?L^mNٜ_2pT ͭs]X{IDByU4>(Dj8̨XCAuyf<TFoX;~/(ڲ˃G|O _`؆NG>^p;k'qjp-u8V@ΙH81띏CK4 LXxWe"#Djb"/WaY=9ɁY>yO}.Kl;gq@CskO<6qRzw#~/J 6YyG> @#"C$5ҁLAKțT;~`IY1G_Hr8:Q=;З>3SCǑ3X5*Tƫ} %2Dѡ&1]IQI' 7]vuaFs,`85#:&Jr'3H.ˤ\?SIə𕘏quO9\+pps`{Ê*q,#~glbW +KR 8v[d!q(pI &\"FdiT"3boKGXLl&{6g|h?;\] gTxl6luHxpbfU7!j=){xqleA`2%, ׵*[ZqpN/-Ci[뙹Hec08Dd2$d B()R $MqMIN ס2V]R^,c]Pa\j#IƮ0>ٜ0J@**my1m&:oSF 0)+xhZhc0 B gVTҋ2J[G[51!8J}7ݴDCCXsոwm7og>ltaLP#s:J͛7ᓟ| g&;߄t[.*a45OnFOwo.lꦔ ڹ?]e.djkLK.n%[ !ɫL圲nVYTmw@$x7ij?EqX]A9j<4M"pwzԧ8cL?n44"J7VW>PQF<&K ZEJs顙T"xUe]^z 项yʼYZP;cҍ9}ssTR-c([}ò">c9c CmuY@yy]ˠn)Y.e3D%nSL4|JxX4xN')buזt]:pj踐EƐD s^<߹ }e-T69*1[|ɲ|脡S lB -B3IZh9d-9&u" (lj@m2Ц⚜p*Ą/c4FGSqÍ7!Yg|_:Nu@MQyBeO'P'O??O} {x ox ˎ!W, H;_܉JdUP:p 3Mh"~R-B@.c2FOO&z)q0D'P R4tm\t'UbOQ2C;ԢNZMW&" ċ!g= 䪆M&TT=q<5ޜvH'{/T LG]R8~{py*<(>996s$"%!7,R80yJ"K?*Q.b en,ƴ&mhDP8,7{Q)8>8n2YeY_\hdmkћ6y.B^ZJɪyEe#0k9N7o<$ gFe|؏7V.`$ߎy."#]. #qv,?]H0Iaf 81Dҹr =<ɲ$tǛ;d2jXCyy9:Nt7ٱAnAxծQ3f֞8R!:dǔʙqƐ%EBP DC{%EN9TuZySdO:##՞} a\1_q<l2+7% OuRAR7B -0 B kxv6 h: -_4huDIX+&#" jEas{@+q"6WV>ݶm[ /^745ܹsDG2P=F&3'Ob׮yf<3#QodJ%X,'tuvɁ@z.Flrԧ)XCg+hA9GQeYEKXH(=]gf+TUX30iwW./uA^Bw GlwJL)EyqUSS( ZqJa11{Pjk|p|mx/#37bѝ3WTP Z >0.ԕbL;ЄlyTu iC UM򄭔 ?nAkƠAP?'>ڴ.E"B5VUEsAV)sMgyACox=ƅ6s!h2Y7KQ㧠qgGT28xpr8*< y%nc2M,}lMؾk[.E`5+XeQ,zfcm^8KciA" ^UDߪc]D]cQ`lr&϶ݣS 26Eyr 8s[`ј]s s:6HbX7:&Hܨ=΋&k=yD3ejL9# 9Y;ch?3PtϞWzFNcpcNE=)JPlr9*lS-I>l[%y& LJB - g!$^!hC| êf y-uZgQI')'AѓH$Q/C,(Nr'rG۞~ 5d8}4V_x=\}%xaC[aܲ,  a׮زi~%9suuuţdXsn Xj2YcH&h5+fN`p`\xء!ZkR^|AO9aQpa~i={0mL6 2`3Ɨϑ0". E O98)穸8MU$IP& v 6 h1Q-eiϋ,(+xŴR- SUתa(A */*y:UyRUX%^R1Į*x'ʀ _-SД=l=]aj:$kQ~N]{0S:@4Ut$r@j~"(_2<- ǜ"jE ϗ :jBcxGV7nRLTqX7vtb%QU"DȀTpmDɑNxoܑB{ Vls'C:O9eyٶ 88͘;Ap6%ƴ3trv:IPkܣX&)ofE]|gD71i>c)JG Nűy$PbH3$L/Q܆]b|X’)M v`ky^|*;q̬Q%* x%*_MSSd߳4B_/!o?B -0 B f!|Z)kŁ8P*t6%C M*1Ƙ#cŒˌYy5^mIXn B5\ y'rvI/N{9QS[ua|ޕ@樨ys`gs䲰(N PyfnsOi߈x"a&;;jiFij|}E.8 x"ݛP $@r{< 2x_J+C>%0I0o\ĢEFы "Ȥ~@܉k,_C-`et&Y@@R41>BB$ $> V=)5.ЙJFMgsGlms @"#x$mDyR$2#|.זL"NLM8UU@prw%..,r{./Il-s("Lmk7͍d;ƀG*#B::وGS,>D$D4Gζ0c,h&L#rdY8ړF`Z-H4J#dՖcy!$ x|㶃 @O&2"Ijٛ Qݜhʽ8f GcMPiA|c<cZ3QW> _:Pi3~ml[/c1y3$= 2EaDTZhVB{c3 oAj  >t‚hNrwldxASj`S$_7W#ktA(~pj'`E)IB8}_B/2g)wBC+IE.ցPT}_D%Վf|": ] pw¤=4QTXC8uf*dL]:l1A-O QDAyԕ۠N-H%. C'(SЋiD7+5"(LdžT_7ipلvQ.iɹPT2nudG9>k-- p:9t|t~z%Z߻go}>آ:ҕw%Z[8JgW.Ǟ#74)i @nn%,"[WVZ99TQZaZ$|$ !-f9#'6 =#vRˡD(o[j;6Ɍbe?-ОE_))^HhSDO \U`H\01wkQ^mpB;`/Hb@Cl$D[vJ "XrXJ @bJ\O_f"Dc%a ʴ^  l-+7?KOx'ߧgNA|\WL~O?ن/ӗ/^KWk|CJ{wZ-z%ҙ۴ssklg>pDڧ!--%3GowMoKt{8]^@o]89FjQηho@ߣѠ2hw++uϷq 5̀91TW[s8.{޾$_k\p$OL>}']5'h>A92b8xDI4pIk}K ?5p{/93HowNI0a3‹2[6*׋0TӒԭngՠ1|}B'pQETT3n<Ŋ$CI@_3~]m~r"p؅mҽ+L[@;b ,D.ݽ,ӦvO/$JIJRS ݵ^S <,Jϯ߈XD;Y{D}YL2( X "/jp_7 9\)@sҤD\KXh,&fYR8˕C?5v%y#jkC2fh śm=;YR]ԭwqc^.|ZxXdm1VbԱմ#ܺ4Č(8GR' qpgᆘI8XGdX \׿@_;tbxgY=Cz3Q&wK ߜDNh=}-z{'?qqJ%p<W i١GvkGH[۫'۟7o}o\݇￸u~~չ`>KsD@Zt#}N$~ܫ+$P<5 _\2펆}}[⠒p!":aaZۇXMDJ[H0I$][8B==]&]zCg))~DW6/}#DF2V XZCMtRS27:6Y@Q{@?gF;?;VSsWI:irR R v[ t[ZVȨBN!28S녕JvYLF:RyָwQ5[hVbC2 7s" qR$杅KkZ(?) p J(4H8aHdHL-k$aH1N%J3Xyʗ@)H y|%LnrHK,%Bein }g9ewlC-%ڜ!G >1Ϝw H&`y_YJ9^cumZ\ۛ&zW@D^y;V+mKOX†ɵOs u#A%Yci@J$q hr HvA3+9}[m]OlyMJ)&\wncM4::''OZjժ*Z7xV%SREU'ii%rط^{5kO;LyS 9" 91JP`Q[$U=륱vn\//j<>g>/+ ot*J>bY~spL`(a-RH :f9\iN]c ~ZO|DY؞R6ђӤ(lO]W}ܖ=,6_@Ixaz.~J^|aKRZtҾDSKs0}[l;m|3ߤ^7c ŐRzι,)d6c8H=mY#51cKb.L%M1@8L@&hXjV$I1 27MU%9L&?xiev=ŧ޾u,%o6}jt7r tcvkO^#Շ1:+wWtƭOzΓvgwzt-8B^#'iݥo]{޽xٯm4iA.hIokO.q}ݯJ qw*D;>0sRpF>r>#:rN-{w%q>a3+ڣtv-V."y![+e>2k {5zӨ\|EhiC=e+ÄYSQѥu?%zXI&/ }OowI[ǨmGiw0˷.e@tȑ'>atL=m7=8rwm񽾵}~x锨q  ݉tXFNJf津p$dt4眣# S_'}nn]ѝݛ;7^_{έ^'h,fl~c墴( s|MZj>~ނj&sYj o0C S()zC4`GZ]h?4b2+jI|2,HEG[KI -_Ɂt[kc /ӢiKLK@սQFlKv/Ck%BchQ=ju1hi: )@7bH1wVS<4nS,[otLojȒ$mPs̚D0W0f%dLmdy2)D4;T&gk첷8a%6 ):ֻ( #02~_bDXKJ(4`L, |ҷ腋/b#Z_}赫vˋAR9ѷo4B8 爜n?Kg=n;>?r>u{-bCS9&ߦ7n?Ff#yMbSwDΗq7.ۺvno긼vҒ m6|2N %D_l'cOܾF7}_BXQ:|N/KhYߋysc&#֚[+k;n+Zj>jɐypCR\yNX۵k9}SpGu畿u܌LV´hL͐H+h?0,Y;f-Z@qnxOT{0낧nMuHQ`%PmԵ{1ʄX}P;w&?g y瑺@+|'2ƶc(>~9imZ`1t-x:lYG g#Vv^'l%W l:4Jߔ /# E'%И@09W昪tL'-J.ЄEremdI%I]3MNHMr$q| re,WOy&YSYJ??xW5L 5[+tH?<+GO C/A-B7&)f3e+/~Zy'(ܘ`n "x+aP;ӆC$$Kp}˃Uzا#Om={6isC3 ܀+p.cK'1Z[8XaaD<)K6AkqcGu+"__Zjf 0V!UIP!8E3iccgd]йd3w%w3HmVT.#8\2kaTƇ+Ws.hh<7pQcqD^Ck Ѽ,>"ژC;g;73vA0Ɛ9RJXwc$HPJIPzۚHƑwI; [[_x;ƕ;O$] GWI/_X[nD/<]HTƠ٧3k`vczOCqwhu@/Fͤ{v#}2"Mj{aO~ѲۦF_{G9M@%>H"MdpT)%YI4a@#/ǥ1H+UZҙvZ&팶h{vF۴7ڡF~DMwqu˴ҟMj)܍A3#KuUGD;#]-Z|E`67Ď[?R=]?y>={uw?F?|'w}ntǑ<<\@% _gI\9ho6!pݣj4طᚉy tژ|6ǫsV+#%O)7-ϧX(-{jժU{V8U9n<41ht}֠E>h9;C{AT >&qwt'(SHx7,AfH: J۶YNTv(@#6O3@"!{W´T(Z, ߚ&hn'l` %Ŭa]>{# M#Y@;b@X b|2q⿜z9UJNfP--'Iԍ7X-IӨB)m r`d?w$y"ou#9 $u#;pbxq*q2/D$cR\05~̄0?rckۖGW+S7 mx?¯m\?{ʭ~tu݂7Zt~2yNJ2h _k˟c#v&hO1"}`4^X,#GfH{j܀p0miRY%J㏖L&?-7<"v׬Xr|)jժULU0><74>}t,wjERq 0h5MK Ga|LX$]MsmY>јK4I<[sLPDZLʈ:t1${ϒi$yR䎌fBJXS$,hOGw&/iro1fC?y?O{h|Zo^jфB|8"Y4߉s:ܦߡՅFL{~^dZɶmɅ!j{0C%>+LІ0C$Ē;ja9rsjS9Qtdk4&yZsKpˀRZjo`R<zҬ%c -J+|(<4}NK0A(6x9< ޚR!A۵ϝ 2.-"ɼ ?8;^h;D;ow }Kp42gӗN: Hv' *#h7>QPCed {BZly$eLx|k>{v)[2:B]vj5ixk1SOq\m-Kp pၕD˲{\x4,lskd'egR +л&KBru?l{dPM^(u;b?'hil63^遮D#ۍ&!3noB KLJ8#eb&+ -#0 h ZHgcQ[o1n ,m_wSh`m5 #(3$|s_F ;:I 4cgvw1x!wߥx5@߱2ow~w4D76O5 5MC~)Kڼbް|`ߍOJdz~nN;aK@6`C<(ee,PI (b%l,5VZjUIjUIjh? d" ht9@kY&J&Z:4v +b-X$cX6`\D $v ;?҇qdpo.{1p Go%&r{KtxzG} ~O =K"Ey4͠u r#:ԖRC #2\2Cvy#sh` vJVKbGs [B,$I\L&rH4\Ӥ,kSL$tv6oZfOd\R"y%eXL!.Tj"` /-‡N"\?SS`ɛ-yR+J}X6O (1rbi|2@.ge.n3M%]e)r?;Rsp uuZ`b6.Y$xD4hXkL/(^FԘ(Wd&@bMF+OcU9r gvnq96/I1.rIޛJwOsϲm.{ڧ (/Bmnj%`4ݵ"ыמDw'Gst2;MGi^x%iso}y4M/ )D,@%5aM_\X׍0VY4lv92>aAe5-WVZlO?Z v]}8LTyy/J*8 X)(Oˏ~8 17C~:r"winGQ~7A{&,O^M9#6*-a(PLRo<ձ3wΘ.%;qKqML(&FF{g y|>pbF㜊 q<y(M/ߌOI-A$ZDr_YcN&qel]>ԯ v=1FOe7bU18L\y9j: BD[<u}eI ϥ-ާ~AAh&m'D%9)Nz|鋿ɿ9y;nC(O;iI)h廩簗]m&vʁ߼;%=z'q%=hc}-7|?wm4&ci:x_\"OCv2˾a^ m|"7b- wJYܿ& M5VÄqzxB:c0tL#RrN7Z5ܹW ȱ;һwh1'Mz+%[&rC'{?U_.D>-qŎst^2!ѕK&j;Q;;>^c6.Lyqߘ >:K:O%rE(J׸nl_n\;te]x.oC6ߣWhsάr ߜXb,r\WVZ*ZjjOP9"CtI.'24@E^PbkyXJ4+ojt b>)рvDp ))IpF*pb]h>:/Okl{G3$K9 j!ָ&rp\sN@$cI<w|nwɑX"94oC9㵸mݝaGd<юe(_#B$\FoN.wѲX6K^4'w8>d 'wAKS&۶>1r4Ys7 n bV--ہ4{CE J h!YN v[I@/eK97C~hʂsˮVZj֪DNjpvS%\CdY;8vD|%7@9YODƫDrA`9ZڱzN 9-9_5Ѩg~PLni:HǦ#ˣ9-!|oPb .J%px6hNpІHzgji D 6Z28I;h&&I嵞| p I{@VKHE,NJ:!Wz7K.7d}$c7sԘn9cCJXFoZ}sc9HMxTB8?YaRGresYLƝHQđqkr&vxx^/t{ e0yƓ?|Gyo=3oC>ClͭSڵ@Һr@ 6П5|~%\iQ/z)z?~v/p*OFfHFwwL`nCF`izq?e"9̰|mHFI,Ї<$Oشr, R 66t%DD kw^R%DD+Uua_[cVZjUj9׌\5Nӗ Ѩ@/lJA \Fr9\ 1Pk@uR0Ԓ2EE,;F_ZO"9;\&7֤x8-6q̒Ik6 N>;q\OA:-9p畒Y;¤qdZ1@DD&9! RP.R4l"RuIhui FtQsYzoOb4M(1tf}{f@g.sC2:}{\x&,qɜOho;/N@f1;Wq:r.ҳ'Hf!t]}@,oTVg`Rڼ?*78.j4# 'BsIJ9 @0A>G~<+[ɁX<㹐Hƃ2d0P /̢8pi4IR{ٞ+1źptEQ+j;Ȅ;+9s` xo)py$<%DYr4;}gՇXNUsJ.wj(;k_rPvӺogihO&ܱ?uN~:wP8 ZWxeNOctҰ2t" gKqDmx!A Fχ4 x#_ZWZEuhCţE |-iP'kEǜ!h fYa^޳={?S#{׾sεvwQB;l%,7084[[絽z>Ob~^?o[t|ګa)L ӉglX$P>);RrI X|[\1g7^Ny7QAkq87l=>lJ`V _=A[Uz9-zƭO:@2i)0/ѫן':;NWCOZGD [$:Cs~|sGo%7~~viz1S`7$A3N`k7>'O# t ;/ZF~ Lf YksԆL#!_D|ZZZ* "7v: ɸY2NNϕ]zxϬP]$iܤ}kLA$rLOQ56 As\F]㛶KG@.'|#d; %1t,ЉJ?Q=ءJ{wSg"+׺2ά/:5̧}܇,GI'm>smdjժU{mXoAj7GC6VxCRKSӹDD`jTyOlnDs)'2c:Za^AV"z!RA;Jp. ܓ% %?&$>6~Ϫu3pai]zhx?Tby|,r,ȼZyM[(^K&YlQZ.W ̃!V9D3\DQ{Z)[J,d.(|T?v7\[f~zk -->RR˗N{.>=Zd~ѷ=~GCI|m@LO#& /JܔYZh׵1Vc~CKk %E?גWT_lLl0ϴEFm1qr õ2Zmw= N5-Oʲ9l9nFcekȓs :} wCDIsȮ n򩵭@tk ~.߽@Ww1;ܻsf6a>4ēן]ŧƲ8wOҿyo GYL>6V3/8gi%R+~8郓\̯r8ۣMsKst8\>͐.uȓx?y9ȷSjժUp[TvHk`~;p}5F4((O,e: n9ș"&hhM\" x`0=cmуN/- r/ܠ~??F ~E@࿓*n-x=A&ӗ;Nk qYLQA=śxAD"#JG[lr_P})v7zdy=huRH w%tƻ}|߻xV% *w3 A$bJxۃtR0=a,@'r }}Z}(] 6AҜt( 8J`2Ac-:I#OFJ눶e?t9rnCi=vn\~N )p^(HJbo TK|9TkqF]ؙG(ݽtwvw|t8]ySuGWʬVZjֻZ5UZY[ȶҥ&5G zkL*#`M,5pb1d"6G@܉ laA.ȁ01Q >)!Ai,I&i80ECXJ6!M8I$ I4 _V}&ZC &0Ж*5i:Ő^.a9 &%kKf%=× A6 Q $ aq -If2PkmLvh^_b{WX;5Ӆ}Yv^<*%Kdr8 B 3d]p)y>OTGto5/0EW _Na= @OC@Ld! -4ۊjk8KR2Oqs H4w 3}ݍ1zo LhX4RLp˄29֒)}r1# b( &8XQM9x11XPdgߦ|_ңާc#Go/߽g7J\-a19㝽]9x?Im;A2] isg@bq$'NegQ2pwfe>gXGspUл9O{-z3ϣ α/#w:|2CQ#hBGsiobRA~)FZlvOH9|ݳ\/э]`ί=+%t#OҰYTYsٲ59RuؾUVii ժZT+7>`US;^4I̓t3 uEHT| S-Zq!M('Uӻڴh(=x\.LC ;!taq&}Mb_45hc4y؀i< e$@牞Yi\8qwJzaLK=*$v7QNwl* zzi̯kGLaQ}= S{;y硫c)Ǹ54^Yv.q4; R.3ťʗ T2SGEL~;/Sru)Q:9w D:!\L&)bTlW%pCV" >O$W8 Z!Vrvd&Rqذ&zqd]Zmh /L#Yl97 s}Dz p >A5.J #3qǾ3x>䍏gleģ}!0/i;Yt @z8Lf89f,b# d. a1)lP gȿ|Fxgg0@. a;ͧʺ8V;ٟ~fGJ> ǘ1 ii`F+?Dnډ?M8cІҙ<pf'&]o3ޚ{p~py.wq:vb|2o':yn}J4>Ox޽4A{iZa3|c<ھNߠ޽]ۼLmZ]82DB ޹A#t{wJ7ޥ-Z[8Jh\C{ƛwV֨{.A׷.`˴^"6-Wieڥ}^29Gt|dtimXKtu}[6laYO|wς-HDĩMl$ŖW72NX,&Vx8xe\+L jT1/fy{|N"ǘHo(f+*luEekvad?Z;H@T2W۳&XqxDZ.z11Gq3C1x?ċ,`9zy J6l;OGGvgaOϝ \K}o Y@;@%X2ut>L@7Ͱk#Χ2%{197[tn:MvKF߻sQ[,d'@Q1'mPRf$DH_H[ҝt} ]ٸD7&mߧp-j;?hc>ml=}noߠ3+iq4eFߠ[M&]|6isnn_vέ^ӭ ?ߢљ_[ߧLh[?7ަDDt~Q""{~tUؿOwvo峴<\!"Koяo~tt8[:IW7ߣ]xަno_WiuaVk̷;/zwϟ9.oC7ҭ${wsnm_KhyIc%DX~k LWVZǚz UXժ=(˥ .K3r35 VtaLyxѻ3E?f6o@s$#e:qf_B^ +X5n =K}@Z>璾ַνש0=>7޸ mӨ6{~}wnK7K;]MZ߻ήlK7EW6/ѝ[]vF3&";7/v>ZoӋ7#ic>t޹]t|ھF;ޔ~e駕~{NjժUѰR^ZUIjr%:2N0T&YztS%#'hrt[C@TnG0K#6'MVk5Oa2>g!S IWxx/h@OJ%w7Bh01E6vRL#6>nc wΝD:e>$֤u!0f|'O*LӔ Ÿ?G0j{ A@k-P0yJЂE4t\0ydN\KL⠕'ĵaB'oSeH4e5i Dc-8At́qJ6U@la'{PO!Sus` ~%:%HQE "ɸEv@6Ga%ֻ.bҾ?>0jRX0:Ou3ڞj^Dca4nNsXC#*/jgm4g,,90.7h.c?9cwӖ',7O $EOi}7ḻ[?[}Zz~ _/M_%mԠtNvYOX獻?[ 1- Vh`~z뇴;=vi|8-3ٝ6]|^z?葧h )zd1:x2?!]C:#ǟ=G ktm}zwio4fj}G4tm.pNN;ǗNҗ}{л~>zI/aXbjm=i'K4|ժUVcZ5s?js@6!ID' X29Z5l0L9Ę# Ai`< ${L踥TS_s wؤꦁ_R7,Dx1 'zZEr\,;''uå\DK imێ Jw'::F,(@XӧMr; }b"C;zm_g$' ⴚX;SutTEP\,F^۹Y"6{G}Ac )vT&ѣɕ8k},yy_2{@)BS^?D}$xۇ#5d# /\Hx^L,.y.*zG4]9pl#O}.h Ї3|L"kG5]I:NRz3M0 p g3)F 0V$"Jt}"z_>1f! ws}-_~>{բ }EU5Ɠl͠VfY"j {35iđ+7o|-R_Y7^L{ϘV nR(YvwoM Gc|ac@^غB~хǻsZ>K b4}a]\{.yrߧv 8|-ymN‡Wާ.YZh !{[?@'6V<\O(rf<}huaN,0~ tey:>8Xd|=uYZ.#?s6d5xʿ\ZjNjՔ ujIȁdXAM$bs9t*-H\+^3¸N$Èd5A'xωb-hԑz! wtg!lP(I(3Pw"Au:gMxӍp$6Jc#]D8@`@+@&Lj 8jd8~ǰZ#iNyH$C'-wKp,[ v|Ztxh"zڣ{ p,%# Nx_. ̬I]%K~A۵/95^n 6VpMC.KdF@Œ!R\r\^>.{-yoElQ9/ zJ4H^Ǟc!2x 9bL:@#xhDc"Cl@\*6krhMDK@wI̡>Y95o8כr,#))IN񱙖I3c4J@dH &)<Q$@Dc  Pb]?{~ K'JvXէC_zgK_Z=ʮo*]åq 4Z>tAj?)D~Ӯo{ݭL}Ǟ>wSNϞz<ȏ8liܠ7+w<4LfB|9m%c |cRWu-?1ѣOv{w.~yB "20E0F[^'9zޢݻ]؉t|mKF`K‘ǻ:_߼L;]#Oprs*۽_:EVNݽ.l"^K{""=Kyjrc`1^ߺBgh}ٹ1=Y:r>öQY{D9 KrAn,VZjUIjb޸JS!i6HG-A91@# Rx8JbVMS%ZTzHMȄky>NRk;ZP:Ph"=cT'tLa'tTP< w8dΑîY@$GSK𼲬7e{ba#Ýa7?Gc^ttC/b';`Q'A%e\?vra-H0J!g,r-BmQQ.X"T\-YDCϑKCm\qb.16?,!ӓSnWו>:1L Ic3՞KWHmv'{e]?<VɼfKKj@im6X9f%L%o$ʏx?jKHj *.@heGJkP4Ix5W.2N˱9O8DMdZml;oUB-ZxOn|n~,Ƨ3}4]Ũ%:p?Kמ,H.ˉ2 aC4hɸ8(M~5]}-=sM֓ߥgϾA:I(kw~{0Dc[?/Td$$e ]x?A7h-~e>/˧s`޹ԍ+]œ:v.gN|^#\Y{=ꓹ.Y8J%{^hpv]ߺ]sN-݃qYzcjĨrb4\>7|~k͟~WVZUIj huV6J4ЇVu^e# \hL(h#e؃,a0)-M1hsNUs:!J$jk r&\98 LA_2 % Kd) *$#:}X qMDΰ 4"Rw*ݐ$ŤԬY}T_@G FAr9)&koja,&VԢVθF'ZZTW9I @IӀ&!H[D~xRB#GsX|xa}FyaEKZ!a"ް}mߧO~*΍c vY2]۾@DmwYk@܍8w!iid7Fv~zG7hݍXC=y=œ'Oo}l^"BDgi]-\zݡf6"#ёţ[}ﭿEW7/?)xI}9 ,Bgaa'AqͤZj>V&ժUpIJXx xT$v^9@2:DK MӘW9:d%x4a2m-ne]멅D͙/ojAyvsH 8IV X"(LR6gMvLғΙ+Q~e9It:LաiNQwHn\wm&!rtK\6("Ӈp"ӣ@Ï5YY+b:sBt( ;&|a1䰗XnTg8A}AC>J>!Rv)4&.Ů% $b=3akI{瀮)8*?ń{)s@Hοymn䲏h J6[ H 0X"d%JE+m1Rb3͡1WtNxT<0>~,&<,g̫֧-ɑ!f,ǁ"?sv~^~?#D.7~=]6~Pjx\%6Ùwo#&C:Do(wȇJD/:p'O΍D$<94V?.>^N.r?Ϗ|˘ƺrNӢe$k  {, έ=$#WTnH9j۶cVaa-<>97'=A]_vo5wp/pp 6:|+E33u x BSv+{] e9|R|;\|`Ҡw\OtDžH$ ,QیřSmhC{?m() q^bBsza@JAYGBheJ+RcKI՛sAIU ER=xTE(;b>8P`X9xcPofsu\XLJq{y IS05"@&SnWnm/z̆=wꋴpYW'"SggFfH E{,sLsЉӴ}E޸ή^~.51PS'>K[]ٕ Oр6SbHmLjժUx~6T$Z3ZCZ.` U#&~4f'*#eðhT2JS~*?$ v.B10rrO,{fI0eoQ˼΍D} +OwIe/ l"2o ͑{L'ةFDN(C2=&YMrw8i6>ѥq8c-i#ڎX{Ѹk2}|Xf|Gr\Na/otg!Ƶr%¢{H-4V  >%V'h爏4 #)-b(e@[,\WCZ~ ܢguYϻmKt1W0mNQbS FKg}Fk10X}ٷL1%)RcC6MeK,x}fpiP2d\۽x-O=w3&rc2&vЍ3ν'Kw;kd R2|ÈŲsNkmh{t~=sMz[tuZjrA?K77D{C/ĸC̃$,ߏkʕHFl̓?ywm""ZhMu=j}KZ[8FO@6ٹI[4`.c'<9GTOrfoK׷.h{hP`Q{@Em[^|'W"5n5}[Աg1[;hGѧ10xӝ}WWktv54ݤ3ڦ[Wh%= ! ܐ.+nn_|C_: x䉞Zjժ}L}_*Sca9z4!HicɆ&s&'ڤlRC\ J&_dwR-mɐr8spFNƥK<hF{> f91 @!o1IGLcZ9:A)FI'`DKQT˒)YBk1+Qg&-ȥ]>5 hRr:Q̑iE~EtXӠ˒@ xPKϼPLXg7ȸ\p6y-piޒvZ g6Lr~`pd$$wu1E)DJI,W&4H~1DbCn9cwKF͏1̟HMJgH ȤmGԴŋ?#Gou1#܀`Hvѻww?NynlLR8@ac`爆>YXN]'N\O^3+7iiiw (9;k; _U/?*A}YOIKcI;k~*ƻk]Dž'I ޹L/4ȿ+Kzu}6io'G{.0a@@S#ǤƃA3khX> :0 ȏtַ8X=KgW/=˿םiH+USƒ)TIjժ}lXoAO9rhj=s`H2dz׊+|>E\f1h@k,4AJ[q(\^c1]D@XDvg%$R,$؄-@9HR(SIt#ah,cs2Vz0D~G;3 4yRWƽgRwXю[^H?^oƅ"heE%~%<iu) & to^iu­$GWNҐoهtxX5x8O; %\Rr]3IדFzg7_p2ʈoC@\ÉV4ƈOȣ͵0j > 𛙉$wh4֒ؤ$է>QdRT . 4VIU978RA4i+yp.My"'*KDi>M|cM3}/^,}ї/έ N@"Gtj6\M_#-'yuݓDK;Z$Oo4 <ءYؤ3n#kU:{] ?}އ: .Yhco^yYA?O5M^"8 'x\iq"Xj-B2;Nwkڣ*!?,]8{~zt{F=h;)`GKߌ=ցK4i~`͌xRZj?jsrj9XUGN,uр")JdxJYNR>q6wD(72.KQxN9lH$pR;e,+%FHxV3K)л`͏9#H1Fc Tx;Z:b?!jQdF;&o,IHJN$ ¬xf@S "T`S"(7_J.Axiu0QZJ!k91n/hφ}j z9#K6_+I1X!;tszt^9ŀ"}](Foߧ]sؿ ܀έ\vo]—tz|)Y XUV*'$NI $cMob2&*;V_QE˧M$MHSv^J6d=.IvȼTNIJMs䰒X&#<Q ВuJ)|525լ}?fa"mlC$CJ+vDN'+ % (|c2Y@&Yͬs6&A@Y 8M,֒$ NAgvN:DI,6YXJr$C-$x`TI g~F_~wi5ZzY4rd5zv2j~Q5#j%<  {G&d\ovMYMzӕo<J8/2[@;,}T,2r#Ǐ$_zF;]simz4iLyݜKKtn ר0^Z67:G|.#ߎoҦ0^oWŵ{hKf<Y8pYҖU`Ijժ}L}̭K}|,50AjmZ '\[  ta%;5Y$iRY4A('kPvh,& &d^6 `ZXHQXJJL,@ | HEq0߼n8s@{Ixc2 yC"3+1v(IɬC_:Qj:%E,4u*>4,3A*$pccAoΆ[EQ-j Zy7j +A&B o*oSE"3=̒GʻcL轰 Oe;j{de4xcX9  fyV%E?:DKSTzc0Ipbt|i$az,JkN|Mr!c1H$ED$x<\SH!Gp" l#V)- !?!l !i{ b3NŁ\8D4KwEy,^r߽X DuLcE.$xV[.i'Z OϔOZx|Rv hpp `aɽs>2 bЀ-p.:x=7 bGԓhY8pcni9`5)i14Y_.㈔ m3SjQ@ DяI&%($ fCsymc)Bce ied:9!Pǂ(MJgV撨^l\17}kY%k J3}SyPM DF0go? ćp="zs럦'г_yYN[Dȏc_Y^z=y1BG0[OOoV&>ָASDz 9)%m¤OrYUrJ*:i=4-]+J LyюkmIrr2Xe,SΙ."͉ڡ󤴖SsNI @Iw_p&S bAL8X$w3jp` $uB{("H&G0p&'))-q]KJÏy>F!"uqEΡ{Ў`mGNR!2J, ˑbhz'b,Z8 `,+xYGb>I-,Há~Dr@"82dw<))y[rshjE.m|c.,8-w/)-!L TLYk&)!}k bdbBo4ΐlnq,ΣssƷxQx{U4ěts^^#\b5͠ݓt/ҟ-z| =;䱷tjY%]ܪv.=Kݻ@x޹(m` 6CDmR>+琛r(1OZjwq:zqL~#aJ|uGѰzsvheF#@ynşX>MW/m^|G\C/鑵i,~bmSW'ժUV-*Sc[|hMxBkAԧ$oɟU9I1MCɶ_ł&{S.;doG5ϓ.T{+dVRGXC$XDFPG#ZS 0Gmй匵$ۡ%S D$|+stj}x/D_<Iݠ4{t^>}# 0VWVZOUI9rZ2ȗTF 51qDqhI0,H"ie˙ whhxQ^ifqxb;sdJ,Љvg`һ  -]O29!o"˜H閹,&9m'#%1Hȴ]r_P]ڢO%R;,X Z$,t.p@ -{1[RBڽs;""Pz::jXߐFì|VMFk3x| .A@c:Dh1p & -`Se-1dDCljXyR@+<Xk*qq`JfV9m܊04?1!7@ 4ѤqJK{02$$+jTN{E~oieՅ;ȑtv:;vNܣS+hya4q>z!`APh] y?Mw[N>-$ Z:CM4fY2QZ]ٸD{.ͣGf1!Yl(dzRsf:skܤ;;7{? ]8Dҧ|WJ5V}gV'CDt~Q:tROP,惶ժUVa`RcaU'6  y@r^ Իҗ,(ZZmfJjPsZ4?5yϕґi3ڽ;pIB0Y,#+N+mRXH8L83 h`kI*A#HF@#rC|&uCPAgY߾>rYn95^2\hf|-+Pkl&H&GBӏ,|㔗>s V #ҙd !0JJ6I_Jq8QH*G[H0`Pd&+'XLf[V2 r@d)9TO c=+kǵ6++ ^oX~ڷ@h@,KVcQI@m,q3GAY/O- >t!V!+qR.pd.m(q6gg01%7e 52Nc%D2Vg"ۗ<-?WێޣA3 Y{ m[[gqBOG}:NWM:Ik[<ܦfv)E4I!펖h`Vhso6v1=FwVi}8`4/I9{j,sUsN飑i-[Stwήu_8k.MWVZw_oC+\%qUK sj7dɚGZ0OY}?jR:8oGKGQdYC}T~2oyP>8^c9$tPyΌjq Oq52nO;ݜ4ŪE&vOsS/8šHo%&%˜HHJf9$-右䵀')ܺ9<9HTVZxn\G*Z5k2"'H{&SĄrɚcJGyЖZt0CNsE5bUR]"h?FjѸ>H}dﲵvkK둓?yD#ǡrC: 8"ϝSp0DY0I OO馃D/WRd\H'\"\cǦﱑH4x =f /|N,Y໅yibO1*_Cz7&#4 T9EcP1ga5,`j)U Rކih3oC,%\NGH@$ mGi`m^hml>39Ǝ߹Iq9#]]?IR@Oda$"$+GL!L?*dmKI9~W ԡc |!l|%UV'*GҜkƃ .V-{jh49HyhJyNPM- RM&TM]"]$LSLA$Nr!I.iZR7g p™O4&-G+˕yG~I%&rw=cLBȑ`Y 4ܙHڭ)s,S=pOBF! X5җ~N-z!h$y,̦BEK * qJ-S/)黵|l`/:h4T5Na1-8 (`FcyWDJȹ`h$ T4= r8̅7si}`!5>'cq\жN%-9'S,\O۶&Vsҹ>6_  GcEwo<ڏdoLS@'}x87_jժUYT >j>fɍ5@ Kq*H.'Y@~3d`+!;;֑힉;g1<}`> v5h`/d 4a]9MNbp :rZcOLcܵG4yXN&VʑDwP]qZ]s0̋ͧ=S " @`\c "75 ^<,IK)xezrDS2s_T jh&p'^ָ@PL8H4&#AcVnCL!9Ha9YXQN00:%2M7 a(;A3Q&&lC]V'@Y"' q:$m#lbh,R%`45NHt,dBIj;Y60"CRLrG4'"$OIJH,gi9VQZjժ}0VW}̍*kIj3O$]ES9vm[C :߃&9ڎ DNQ0bv%ڤߊK9>Es]$hpyy_s>ZhE  qHH` g(IߕǻюBn$$ty`9G70w)|Er"!&#r'ϯk~H3HeZ0Hid/nK bĬ6I?p/CNgwߐɰI8Zt !I~^DuEW2Z0Jc0qDVZ ]z~ Lb@"$.[a71_76C) 8tsfG"p@@T$Jd~H"$X$Rz'S{Lxgj7N$(' oPƾ#3LK H?0<,|o sPg$Hx҅1F2$O))Fc|&ҏ$e%@90W 63MI)Vdi eTI,݄sϪUV'*G*S&J(uk"@&ȃl#2=BKL~f$iL#I*H& y5TNJƒu'kaIXyTJLrVr1@f 9ЃPd"`^P]i:!'-r 1ai\3uN#@ Y(gw JNR(vstsg}vrG<~V缼W8y+E8a1#)3}78gr|o|b,Wv~l"Xk>͑)9XD2?br@r~]%.AZR_oV,<&Yui&ʽOs3 A"MB i@KR,"`S0H@> $KdcK ssuG'q<5zTM8>ϐiQ^f!S_s (Ldpzq1h}kKvym﷍J{ͯ's;^ZI$%wLߨDa4VYKGII[Iιr$Ljh-?"UvZs zVZjj ijf4ԡ?4JHHA6 piYkr#3d0T8r(O2(A·DƧv8x4G&3G;n)MvǪ;]rRFN(s$ SrZ&sdz_n #y9'äv|stlL 'b*@ V,K B`#ʡhHOAIMvM(-bAׇ՝+ŴQ"*Œ@9HKsN}g址@C`m,Y2 (3a|)T?ۇK(J`@XPfHo4`,0h `C1b%De5YۈVDZX0#pJ$I `.ouiє{Ȥc~٦D {޼zvcPJޜ9aܖ'(+2Hn2Ff!%<ï/n -wh2ޚAe> I VY|yjժU6WPV\&JAאV<SZoMr'D,dcɳ6qל thȹM$@DHӃth6SS2pcJt\D! bYIt&rt\#RF'>sHˁ# \MH!ml2}18ECf91Hm{4J-%#wsF ǥ# :OY2<"Zl'(ڙfhc@-j:h7uT5AcH-~,*9r% :'rј]9r- Y'~R ;%1 6TGtNh4)vOJZ)%TԾXl%ڮz$y#V9D;&s}ulI=U-vR@#%adk|$HJD8WGIm6!s{'D*ˑU1_9Qb$ῥͼ,^8xĜ5È݄d&wJX[44)1ѡM˞x\/cJcMZGĚ9Il4 7YBTz/JfYX/%xئKІ;^壴xɆ\qe:VZj9j9׌\R3 .'+hrDKjMf4ZI9J& %0 |ܼp. 2A\2;G;e[A(.yXiBF_jh2#pTf)s=u7z;ڵeX[(O-Kro4< C_w)Gb1 2Xl"b89R) 4c1HVKX k1H PN9hF#),Ե柙D~B IެH;o*<]AmGLVdX.>q9QlXbVi$ C98bz^Df -<$ۈO$e.=!#%n$q`, %lA(:RӇ0g'XԄ }E^ bSHݼcylu>(t3Gmv粓rsiC2Y ? GcE ڠI?Q 7UsZAP##y2UܐXJ2TVZm`R!$άժUCE %)=QTuDGG6纑OJlTZYD)?!hBξ,"3b-6iٔR'ժUVmVW=$V%qUL|&a<)SRr&9baA"RMr'h"<O[d2&+˰ԎŽ=K8bCHpVsvqdYA`܄bzL59EQj-* iɈ0wJJx:_J>?*"<i`zb-!0HdJI [rAIU8K.gsIn"<.[`v #l4ƌ"1 yTkKJEXH+NeR|.ȴdiLo}HF.6bH]~kdeة,iӨ@K }*GQ?n Nb9&XFu, 5fc?m<Ɩ h 'dc3@5XE#nյͣoy "XӨ=MX$/ڵnA]l"OjBͽd\ >VQ4w^!};D\x>Aec J},6K0$&?P64&wXk~yUVZ5_Pڇl\ĩV4 Ş+Qb@L#Oбvhבfe1 Vs8h;V,9:kkI SvK k)g$_ "%.Hgв19 hDpt Nt$3?uđBKtNczXLP^i[FuL4a- 0xrv2B]>'"wKH tk7rh$2:r,tE'5 %O!d&σM4&ʖuDsQߕLƐ&_r@%AdzaDdHYL'kuKS (/ƪL}Gwjg7结MHنk`AVmT9IDB8Ch?N?5pf63nAq!R7W@"`Ec%l)ժUVZނj =jժ}pf?x4iRh"VBMMdPv%@IXj' q5G̟h]nYc<V%pUv@3"yeFXl2QyP΍khr:Ag)4Ըk¬hs=`sM̍X[̟raՖh~!S)u-9\t%1Pm^W/4`IXuYduo̒)Ck?Q'ۿvN䡶Y֧DG>M49ReEMA#*Ar79\I Фj1,%Oe:}|AGpEF^n'@61 Q/L@WpoI7 ~|?yd!_Jm??ޠ5%#Z͇#7q X<-bN:Rۈ+ #P;Rno}FrqժUV[[P4ZjŬa$.E EE>`DNФ3ͽԽ` ,ܝ'CEX@9, Js#!u6Y;$h3hJ\RG^ՙIf 8DmO#, ;v`z8J$Iw@I" h'#6$@vӴ;X$N{ d&Fᾗ\6Yy9ZyER2RMb-ӷҖ@iTyq5 *+uժUVz }06i\}U{X,י;B|" P&dMN$%սYVb9,"9o99,:S@YrY"o|l#Zr ϣ1'xs4֫U2aAr(фLNrArB&uڄͺ^ 'V=KtTsȿ9ԩ) (D旻z,̓vTh4&eqo R6/&N~ZzYwȐ$U&|OD;pَ֢oR>P2:!9ʙLo8D <E (VT~ҕȇuDR"$Y XpUxYH-CN'vӣ|H*G#M4yezP{fp]唀n$ť;GJ)\3$~:Γ*mrLYZ[fwIoF'1iP~N@E,`5>L~s *h^)oP黠hͣkI#=i.;^bZl};i&s-(.ٶ2k(2gx\~ R 9&cm#9o oA~ B%X#1ȿc\,6TA]uJ0LR4?h sk5OjժUfYT{ITpIjim$ DI:MrW_%Ug ^v&) A` 2̒ANTs18acd&A $4?_`0 <| Q\91h$ЮU21 9/̧0E-Y9Po zn[.E<E.YL)XNyka/: @&SP\d&YRwo D  8a %1bx4PKb7 D@St>kמ YsJfy~tDGl:%'BB 9D12Nk,vڹ#h#Zs)F &5_4Њ@^tNJFc:AR8j}2Nи:[+˿ȄK<*742#P"k l&NoN< ӝoҖB s"d76i#]:RX5ц GT"Im-Y|2ooN@4v?Tj,[.C3j(ŬJ')jIrUVZT{pN*SGr'HTYqhr$ADKȴ<a}@4dmmG G7uzMR;YxؾD'PRG4kRP-x$ `$]Xgg0w00D s2=|+IJ'Xt.1'Gp,D=WwQ:Nu-n^F}It '\kѼUsלr;7N8[ !QG旾AuNEvVR_"S>\FHɩu?Zjժ=H9A֮jժ}̚tiige65y.IMeMgi)Giʑ!EId Դ]_Kp?'g#П\$j!tH8Li!X,xi  TO좱ohe*Hx 4I!\K{3)DBieygd5~o  :Y 6Өm$DYf Ȅ1%L%rO)Y%EDR;syxs@I)&H[nŷ@(, >I7 1; wI'nj* kV$uxňN,l֝B@!=ߍg#UwְE\pZ<$'`-"f<,S.[ZXBCƪ2Hf MtK @!ڽdP^wt5 b ,ΩQr?t (Iߙ`,[|yn^n ~+mwyz.PP~NC|1%@bX<CLӗ粵qCn @J'/h~޸YX)3ok}&Ez`z`^n L%54A#n–"{ 0>6ڶ|ΪtJy hbm#|?4|>)0KHn$|GfKjBÓ@gbsYἮ)͏IkUVZ2v^&70'cժUhE&09 diԒ(LѨ/?wb+wRØ#rRnJ^,&Vv0̓&Xs!jb DMyE Hi9G~|1HDJpٜpR6H"vN}Yr;ۓ&hW%#qOƑ,|$ucFt8Ea`i< DK& ek 2=;.[1b qHZF>֢5_@+3 UDi -b:P96]-$yγ4vYN~)o -V";D`G/Vp+ # caymЯK@(￵\X, %9mVԘKc3)1y]Yr8T6$mĻ0`s|G}'H iANJҶPm,mṵߟn~ ИL$i%R/r¿h ܁Y_[>d"fy<'&y&-$%47-Ҍ%I[a(XZjժeN_oA[ĩVb9&Z>4QC7(Ik ; SdjSb0ɑќ/Jv y#Y͑SiJMsdi;raqdor-\FqH~pP H.cJ,@-IK#7eɁ'<-ﱞ0 L#].#) IqrKr+(0D滞D0Vf'$i\@[4y])E b6I &'< bCssw\ B1ʟPaɸpMɃ9乑Nku`!V:GY`L;KF$%G }@))Tc׹mI/|-m^b+$#\ƀV 5rqIYp ]n8 XXWPh,-esN 9΄sǚɜfH7h '8 yP451SNeL 1 Pf̚&X<"gA>KXi-DJd&,gY`k6Y9dCei%̔PR'ժUVaL >gj>Vɛ-m2g@a(<2ˤx@s @tIi#aD˖yr&%|4Ȭt% YĒy-f~P0HI(H4RgZa|v#>MlL%{zT>b@ȑxkZ.4HDǺ&4>CcEEc hב˵ꍘdJ><hwNJDiߚn#iY >ȺPu氱yWp<֤qRs.etD1hw9jX3H1eÏKvg3H F{ʧK8KV\P @$Yf0a$M3f4Þ|t9ul%5EX[15XBYN<#;D 2I'}#9G<E kjh;_!_A "}$^VX $4?uf|8_gIHMAP-n'WZjժUUI͹fb/IIY#V]dYOiuGqNN:X=RIQ"U۪`/%q)Q8$ibHɕ)z 0MX$HD2J4܉nQsG|舜.vvrrG mMT^n!KrBxynL-"2\@ &|CME]) M2#.xt^Qo-J|R1 &`]RebIM^CHI{X@%&c DM1)+ SMe8 +&ߖ;Y,$)dq|ԁ6䔰72fr|)힕lJ DRl%WB?^> 1H_̑Iɒ#y 4VZjUInp蝗ժUhBK?A24!&\rwAӀ)gsDs8hySR1n TL{I]k xQr2N,ρvtYZxYNҲX$d%xrQ(= l$u̐s}`XIB rkNDɑ7tnqma>k1 IX(@ע/ߦ(Z%Kd^PxK:R>,j"D瓻ݭKt=)K-A_||qh B<F 6%ޖ4:3?6lS`* !mdOcn,֑O}mc Ё?4Eir#91۔݇Jq/ޏrH dBAd8roR 'ڸ)<<XX4yp,O *Oq Uq_3@!8X@Nu&t8f)a&>  I9 "K 1,UƆ(A9un X2HnLdyUYv57尕 ?k6iG4[k+eV>?ZjժU+_[PxqTV0cj2J H4BIgTIM.!;Zf` vbр% vhk2;{AשQjrnI bN,3dg6AC?uPԳM,Jc;v鑴{<.O~k$s<Hq1oI4Ԏ\( !rC.HD4h Q[!̢i]|+%SlcB (R-W*Pj8-7Z׀@;XS P 1l<h!NC>Ȳ#ts͚?ۜwJ>[ QַK>2rޗRV:,NKxXl'Emҧ$edHᔤꅘO (1ҡ8-^AcxC,!gRySFKA)1hr<)cg!;(f/L'oxOBַDu#; G)pn9;%v(^Q?4~"p\r_iz R#<hhn;OMhDG,&AFUHPJj#N)e#ki~ jBb0Ah>JE+JR$ժUVô 0m\ĩV9鳎thJФK++56m4UhL&V$9,!аX;q c?-M rG3MO29 ,0ˑ֑79eZ  y`o!EsK1 ``ҕK1 T>sHD,DlmH[ʚ і C vb j1udoR4A$xb8I-")Llb-k <jAesY9idr%sR :JR4 Vr=%FE y)|SurNZ>uS o[g1;!fYH4'&yrnLo `Z53p59.c4fEyZ=}yG @*ԍdcTK&mez}iyA~Dswy?7g9EXJkM^Koؔ-ȝD9D}\)Y\vW{iN8/iiXjm^1LXES hw#=EPZ.{%鑳8ʕI(ϒ$J cI¼ 2{p@dd#,מ#d_ɲ&!e]3ے%{L07!j6Pq(IHJ.INAfJiT-Q^md⥬6#TK9oFBmxo$Oq_.dm !yͨ=$s$I :@ǠNm~\XN:b4p L'q>t.wvqx4 kQݩa/D,231e O"kĪ濑KXT΃#"[*?Y:!DP9i])-w[Zjժ}V&Ւ1UV-ghM b!*B:k)Y$5qLZyn0*31C:R4L6C */3 rMuY,_Kv~IǟKLk9.1A"!N XKq8OH%XN4 5ax)fXI@Kʓ9!mT/"N2a.)n bN;{K-@9 6'%?\w !.'?H:Kp Z}r:Q"%cI4;fi됲?!LhlHb tP]$]*KUIh9ZR5@{Iڠ@yg\yHrXEP;d)0 0%C:DXwLnC b$1  F6 8",fN $C5ΕR7!XbS%,I I`/ yͰwD@P~_ێ "~,I+V@.l JjA;:$nRrOچy+cl>A@~ ء,49a$SσRy&dsهyTM ЂΣaR2TVZ*a|SZj@MzF &g&edkE J$~ͽO9 ds@(S% ݢi#LjF*A)<4,%QuU +σ8,]lt^ac9` ",#KPZD++ *Z]Qy).o\A:F3*8nqC=8DG\f.H03v[V"wʿ ^V.=}~-k -iR9| hbnSTb )ʋg1xg{&,;?_r<"%nB2 P&sOa a7be! ȦWrJsַS6 {|?M-;ڠmF<־ ` aHōڃ@ҽ!m.mo꽺q ƙ5)^vO^tK9gD`klat9 U 26fmcsK`H_ 4|~+M8#)ZHa,.w?/]ZrīUVZ*Zoj8pnjժbӈLrb-р,)LJG5gšc5/"&yR"G#9O$ Hs:GrvzTK14' JP}ܑr<9NE:%( `D|5`bJ6tR;|)74y#J b5hS5-çN_3RcRl*f BL[鬍=ZR֖ ?-FD>D׳6Y9jժUVð"M$Nj䄲$^{$ѤvOdp4֜,CX vH)^&"Ď;|RN%SjTҁD:yZ+3D+׀5H ``AFQ9e:>I997" ub@'^@Et:{e1HQ42-䤘O4;,8Jd =.wy9&0y,#h3hF,'hWcCA姤)RwOa ʱ t ?*Yh`Y%:#ٛ}y-@Z,3V> pfcSZ&U~.PNrek톌Gv]ֆy~J[,Ta:T XD߈+ӠYh<$h$hDh\pH4dyG{qk aw ;0o\ӍfЅIPJ4  :L&~sf&;} c0`SF} AKmRH͓M@ 9@_BcI<4 f!$KG+H8ig~B~\?A8 iŦ%>ttNjժU{Lu*SZaN|DM&$Q|9XŚl沙[@i,Ԏ( gMJ]椙E3g`XiQY3HDhZ%fDTHX,&Z|b*a1vYҹo?ǑB{PKy8OJB/!Y^MvȒ 2cVRdڲ[DDҹHhwZkϗ\.Ikx"2 cnc~}&lTz*+dLSgE&tV:3Fw;aB3M:m/C6}p,_q?ZUɅDs2Ǖ>.qCshcǰ P4GV\6h:$1VȸX/4[&<%'cmќ+ &*RY-t-$·;R[YJJ4;C_kMs|b n* H6b[9ĭ`]UE/3]$Cm=D8%tls5$s 4" Cm5oI4b:K& `4HZ%jQ܃}ߧi: o CLBaJyZ({&xvmHL(ss[~ g~bS'lpqFeitP.قG w̮4Ԯv#E%`Fshs>w9hs5q'9HbM "-?㺖tDN*> E&jwn%7]eckR#wnίP5.&fm8hl75ni)[6h$;&$ב MełiWd!dI&lj&L'3sfB+S3gG$k{0#@1X6bQσH }K}"NZ]o6a;EUZ@Å#6j@C4)4V'9K涚Ӊ6( VFZ8}w7sަH% =>[(e0 Yp@$J$R8V~|Xej}Ĥ-r0]ĶxE9lu鴚Dڒ/ 7iOo#_B߸jm*L-/NCZu5#(q8ɂo @4xC\n%vҊ3,_ dt񍣬9j%kzLr!q9gJ$bs6lE߹Xܗ Qq)*q #']HLm+TcJ*;dNY!cZDtf>HGN%Ê). Α&xϥ"gĵO&IXQV@l}Ӕk~Mj%כ96!,NNk74iZrCvs5gT hl5wBO#+O]G g%=+vʤ$Ҟ/. Q؞}^Hᱢ$K-𺘋I$YWKXR.S#|]|w^~R؛\LAhxI4GREcXljj2K155uɩY!n]\WT2ϟ\bקX}|2”Dp14l"B %$#f_N ǁS:vQQD|Ϙjc6W0VұD]㛏QP4..m O;Os[ivR'P@`2I*r?lBXRww:>. O+(Fl+bkH'3nVFK,b _`O>h{ת4 tl1H!6RhSDKm/m3"hYq1%bn'M>ծfXӹL S .rxORDCH+]3-.lal&mZnhsÉt9t[p$]p\Alb휥ڹJƯ![J\6|C^kp[-ϽIsʰT}CHLRs]9 1&"\h{/BB[} Ql#wGq$f3N6^{[8i0<-M鱥]Xyc곰w\5f& vܩx̕oX\]jd^1 f%$kłx…,.ሶ@ j1c]q]u9\" ThI hǖ!@ ?=h!}3El#6 V3u(i8. #H(>S,b1 "<.`@XZ]tTkmMI*ߙNboN IM &1g{yH9hvw{t9}HjiI D|os9&}4n[x {1||-l-u"3Uw Мj/QZqw-}DyҖQ\uCQP__>p_P/j뻝&}.Ϲm 5m؄!E;ŕ|w"™\xK:&_en+-rC iKu(5472U8fw;>;w x﵎$f:P8+(ء \%\mE6 HַP;|E+܎+߬ojρymOZ?33kf:s~۹DmP7=) MVa.\P4! E)He )>1 L4`LyLy|3MR(NDL*euBTh۳LliΜ3Nk’KH;<=uo.fMFF#}?9=v,Q…Pŕ\4Mx>?F{wۨǒ5$F:I#ӏLiϋo>n՗\'\\hsmu|7YhS^}KM4 ֯< *TbKN;וmI"?pRQa 'IoA Id\Kx(@d25WX0+T ?28L:)s|6g ?ef_$b:MjRS6ymBPgkr Gf26WR/F`s5c|[>&,ǡ;BV\y+k-=XcQ4Gai|/]1q;TdTesiҾOJxⓞڀ;:4'[Ulc]c36wiD268R>tV:I1]y4-.v]> VI4ӖAD3\s6lape==T"}ƅ'f1e2=IiJMfBHOm!H'@Bؘ‘l# Bg3O1'*Rmшk`%|qK“Iܝ$Mm8]RsҋOId>'IPla8|_Ih1Hyle)&a>ӕl؄>slBB͵6Y19jh,QCOIy "9pH*wO~>_XB[󟚣 7_bs?0|m?lcqU>cvHDrƺ\amᬹ4'q~E( 0 $`겾VHNBG"St9Zlm\!\," SlI00>ȶ(߼r%[$KihB_[ c!h;)wHn">k!oϴm!K9\Zʿ&!OX'Ƃ`%?pGʘe7/)9$,5'HED{f}Wsqm Yyjy>L\ s$NspHK4!asnѮW ķWrpOH&Rh#BD!]/O_ d6Ww[gM{>ߚ˒K :Ts 4.sTz?6.g]5I(*&bI:LP ej֒yܵ&f~'\QQڷbU$_39uyV@2(̔ɩmR#i璬6tjVbAH&pLc2;(m d$2iJ뒄#fIK<;_ȏ>Q%XoEDZ$"_[xcw$BHcQn.F+P\\eژ4g$L)m%BRVZ|fn#u4M|b:I! h5$IiiPfk-͢WƵm ;\t?xITZqǷs. CLHZ"%шv.ҹe P X,Gac:d~$H&OslvsI] H1+N:|浘I2: iET޸QlB/[}WVBBH$.F4KƷ 9'(uM, +$q;Ko#h3-IX:۹ˢ۩l3eY8EGsM1tg7x#ǯu" KLGTjyjKTTTR!sf.8eK $ %3 6t @1+ٰYn%I!}B9N' &ӓl+rv(YB@bLc&t) HU4U2"- VzYmܦ6׮;gG13fsWLºVs'w]_|&mN߶1cjGl£؄|;{m[3=~&9W򕟗FIe>l5hd+;Q$ xb*I":^/q!걸cFͽ*xT\LQ$ґB",\4Q*;hJ҉dǰ;y ( BdځFdBFp]SF($LM BoBgdzv,J\|n|'tƥC@7m:=pgdNl){g"_, B|j#\bLLwq ?wW;C&|)\OhxF_r5|6Y:P# RT@H"]@ jMWɂp͉ķus9O?0A - ƶfIHgm>Gu/VXmA6A@%[[IsY*d 6oMb cijar$S١xf9+~nQ$aH:8b:dV !vSI#M~r0{n$H/Jux)5 ?&X6kmid/AH|_MHMBIn,}H*sTaN]h.w>qϝE㸺HDZ1Mly" C]Ǒ޸Gt$Kt /2\i*3WHxWäBs=2&yv'"%HN{i"_{\GRJYOao4-)$PPtQasAIe$Lک9LN]&J0;YdMpU1aqr7y ţ]C`'_lrCZiJeOI86R'e)p`###qđ+Tnr9.!Ilj9HXAQ%mL_rk[)4朢ɋ.'\!}LT"Dmv ha9?makcչύ8ĞT̸f3s>3]&R.3$O*%O9sc|V\p?U9cRGOK9+M>&m\fDsq![8W("N9+CHsV1\ SA{:^D6-x؞SI$ \lϴ,kn(f:]u_O 6$#w!L>|{. F{PstvH 0%<)-M'fGϝ (rLzKg8@^QQIS3c{IDt&Lq:p9 l' )c$WQD#)JeKB!=?>δ+J ErB&RWLRWr =xw-%9D LJno:a6!tL>e -I6ڢ-iLg1[ rꄲd"% %wiC {p J W)4y4Q ?۵Hq[[1BHv6[+lPEs*4|P\yBRq !{$Xф+|@0.wN C+oS Sh՘%%[~+x$Va{sJ6nup>T3? ~VpKBHI7?^.!|'E Us)TDP.\%[+&W4y).>"sO([{۱\.)>iEGsSBu _IF&2| G I 'Ñ2" \N+kqeҕ1T-P4 ~7$QCJ5ۻPYF ]By{;Rx)-Sbϱ9Bh"%@#pyd:VHtƩd*=q)TJyT*3؅ 7#Pɤ7.'Ͽc.&͈y߆ s$7b}E #ˏ_ӟޅ,d{Hۘ?P>g?Ԣ4>c(j6G" Z6x"  )J!$=f+jLIH;ڶbyDZcɏ[⨃U?Rz~}fkˬHi+|>Bv"bs{i_i0U`yX[LqItYM Q$s,.$3sw]e1͟NdɈZfNGH!IeSYqW v6>K|x &4Jpۄ+?mPN8|WkasL`L;͙<.O[H\m{HL:g6mo # I\iGqqɸuGrA˅ȧ̺BW ks9(>QwcBI%Pzoqe!$)G>)-Hky\v2VЇ2Lg$UTTReHUdbdJ3m Vf&8$2KQJ'5Cن_vfx^<#L$a4"y9X5,O}e_K'g#-BJip)m8o\ck$xm6&l.(}wNU 0)WGILކwnyGw5"I-y)wuRWD"YJP>8.^~R~\D '4^Yt/ Vv]יC o?2@~ö֧؂"uic>h'44cWcH2>'iۙ"\Mc)|[טNU 0) CZV)H`_Md; A$N{kCm+mA[l+yl!|;?CCvsuz( lc=B+191$IϤb|b,-r ;lfڂ1WQ5 0)yRTitJ;RgxJ+\]]n(ڪ /Uή- }.ö'8um~\i"UoJ;mS h+|6S.0?.%\(b B\N(6t\m `2@<4LQh'w@%)q$31n]SRfx̀}*B$\ }  ~B d?Bhӳwy$4lNڜD2&%wi6n$&vkϗv <"^=lڳ:)ߵCҘIbLr-D&D?gRluaJ)w63MɥL#I.B;]j~>+ܟFmǰ6ٖTRn죊)bAidrrdH kXVqC 40; ظY+NyÌj}X5ԶBmc 5vank S$I"%߱#I0" җki(!o{ (0Ttc16;uΣ&qpj,;>0֡!xxfө:u{>wa 1#a;4e~. H"mW"rY&MH·pQjb['|\SnL\qOs[$<}Ϸ%'Z'MЊJW>0} ?ieq*{\-'7P~'WDp>34!h[]ng9 w33-[xl'ֱU&ǥ%}&`CsN܎_KTɝ&AӜCP6]'m_u`ض*L)h%8y<۾p%؆ $\愊7"'be&)N OLAK==ia 0|1̖Ytm6q #'\> xlK.,|Rr_9v%#Y7\Iwn %K&}'ӅM<`sW\.U)sv%I+uK&>ʽվ!$ϳy\Oy=x+ [T/k.&9IxwVZ}}Iϳ&JBB_,)1C wI855q!1? 2Uq E~\V) h:̙}&| Sz'#kߦ5}R{$7P0%uL!`Zxi_S!h'8 K\\Q|8*m,M[`Ǧ|縃ks-~g\ !q D:RXsԑHeCZ壉G#W[3] cs-1MZYbJۈ"жBH4$1́\>v{bHStb4 }}a E%+*\ \k8sr&-tp@ZnD\ݦ1J>+A_n'e% ?k$` {÷ӎ吐({U9bNlh+M _]>D b_Gbs֐&%&8qZU8. .07Eka u4V>|?l"i9hCKa9qT^|V%]wzz3P5ҶZhvpD ?M)'Y.!> |\K 36E!R1>~IedSҠVT4`f~d \\I|sJPPߒ^!1E&q8s.(Ѷ!kjj6=NQ*Ķ*/n&!,41T̐6yqTz*s^S!~\n{m߶|6)*VKŅ&<ͬe6j$@ \Q\ala:lbW(W81Cۆt\b~ ?K˿ͩ%j$gcrߢFm_ o֕QSx=/⤑K^r4ۈt 1*7+=}Di ) gm'-L]b+IR4dsZ1i,MsHHD't 0_ $$Hi,9]-1iy:< kYENp#6܁Ķ w#}K~Ċꔯ]`AWpZ"1j@||f Oi:8/[ݜJB0=e8[آ5KH9: G SD"KWsؐ–%'\"=#6 ~l)RfHBIEnMb1Li-/Ⴔk*{20V>[I& ^eHB.PuY¥:Viu&ladx$vlW8?}D/e? A~ *v@6? fS4f kH 7FbTV,eڄR&<˩- - 4A-ĘYi35F3-[]㚢Տq?nHgM <GK^]5s2) qvYqH&#.IOe(FhnSbѩLURełm JEbV<.ٷ2Ur.jE2>b~G}oQVwЮ7˹&\H\z[{$"%|˥_b Kmrܔh"-MLb߭]4 -'ԏxIa>`Ǥl]ǒƹ_@e[|e;s墌L N* y qD!N&4i:\pb~;ܚC Nj!"xP$6R;)=I$P\ËvZ 9[2ڊ;m?M,b g#Vch;xo Q.&~׾R.8Hn*v,'s[s"Hr;MJ7y YsHHf6鰵}~z;i^T2םJ•,ǖfwJGp&D%Qg< ωOJ!"l>.'Iks-ɺG,b@ iф-. ~gp&bG #W>ELi\F*B/Mh! ,ExM#% &:&hq̨.䟙q1.;E:Ov|WEf)|M`$xԤ8"wv jf{ @*+d)6A[vfj'Yc:eag\O&g"Lw)ltZ;*EfDkbw$A \4l}Blu8Z_]HhxoFͷ\ Ǐq$iIsBm|6&36o܅S|*JW@k S9masyZv.ڶwfUj8S.6RɭDhN-ڀGZeu n|'Dg5? ~h6ilaqlbt&p7\ bnCw|_ # IxZv*=d%NvfBh$=Ad:hN(YǚI cBi2-<Hdd¯YVK$<FL 8,4?kmq@qkqW8$x\&ؐ+|4ř5eƻ| I,`"w'g D                                                      YJgOHc[.lbW ]ᡋմj$~Z7,E9|)? Gi`Nqq@w^&Y>䅭~)oXDڅ54pC9җX'}5IV>s>̖݁/'| yKٌ[&K,IydnrnŪ[lKG}H^CϷ$=j9,ǾU!1麰L,J2T2nz-:җøҺsTS /U'.+kGX %ƞ9oN[G>k CXTMҺ"ܣDP.}Ύ,qO2[{LU=#i=߬ޣ ʣlĭW]f-_|TNG}qr= I:O֝U{d=s.-2ւ{Z=sz9<uupn#` (9[;>O״=}}$p[WmڅɽL;wu+Ova5}qL\Yw=p;mޑv<~f y^{hԆE z]}dQ_:vp[S+&{ǹ26:AO|y,eZZ~i 9GGN[:=lmcAݕx^tl[O<%tl[WOkᡋtHO";Ys II?o޴7P v|[W>K6qӍ[&ri?vIn-dY u^A9җSsMQ߰ޣE}K[y) N_nEyV}{I$S}=T?3i>~^: EJ۞ 7Aڼ`w:n~ڱyy/UN&=v\{zl4YLzPJzȝj5U gx.qPeEuq?tV7RM.;;z7Ǫf!TMgGm-Ӫƞ;+cOrxvd rkߤޓCZ3Xs._c!ZqS ZnKՙ<9:ZVou s~)tuY~+ohT Je2Y8.7,kol;6oXD}t/{{˵ʹA/n +oG6yOGkV߰~'4. ]硋۷mO-+s߯|0k9vj~c\l-RbsBU\D&o]Atk7C-UZ@ Ծaul@tUszOȩl\LǪlJU+t,{rva 5~nٴi϶ϳV߰zi :#M 'I좰 njeZ>w>!}:zd"eʰc5c12KYI֭(KM?t5~֨$m۷mkol]\[EjKsOIQ!_`Ejj{Ξ/ DiZ շJQ=lrj߰"va5=TwY鶬h]|G$-;y~|q~vr r0n8mϮCTn+*ͯ&gZ;M׎JLoFH;ʹ]}凴nS~c3yVϬ4_;+c_d&Z*/3!{u< Uzq§uq?C9Wn'ty~~sIpubI#:6J0cm=zƿUQm'#ZӅ::7Z̖[ds7z}DU;3տ]oUU^zƪ*//k?V ]}Tkqz]qj]O/gtk":l뚏{_/?5z\Jutqb6A5jTʯ3嚪O>j=뚏Ӓ+z2-bV5s7U=R=_UPM'tl"T$*hZH_P,[6ǿ(5-k,Cؙϱ-60eZz" jVӖ<'Y\ÍRnt#["߃Em-95RkVol-YQD\-v>퓠';iY#=Gc?u-r84q ORe;P'Fܦ>[X^ocm̲US6ρfbP`~"[N[_h59#*w_)%r_r9{׼^Vm\BeDbǹwY)#Ѝ?,|-|Y|I@Y=oyW/+O>XԎbGOwS16:No BCeKHw.uƎum=t̠u⨭Ee|箃eW]ncxupnW' wvlQN[{ 56w7A\OK|Ÿͥ4RۚhZHw=p;yҳ`cۆǮ]X\z]uߕK~oV޽9jkoQ'TF'H=3U>x˦t뤵]XM?Mc:ww@`sX߰Zi{ R(óul=gU&~'yH-VYrSdviИG(m_~NFO|_wlt"g JkZH[NV o5b>3[NoG~ <{uq׼ Ѫ^:PJ0^~Z߯N-;Gy4?kG5{^=Acu_ cubl'\ FNWzɣ;+cm!q⯯uboȔdh 9Ug>RuP+l+2 =L?yZuY .Wu靁^˻t|sl؎J|>mפ憲+DL۞'iGtXh:d;+UY׵-V5f!AG;&=ߜ%ػfV7eri9ڼ^=Qv9ENj"lPTc7_R:-o P+b t,/T}5$kn&:c#ΎgitꢶغFiFݷmāځӃ7_]p-oW`nAtcaqvh[Ӓ:]zzul UlZK{^蜳nEw= w^wv=Gľ4)u#[福7VbPr<;Ύ,C+v6-?HUSzΎ,(|/y~wUYyt6^>K@Y9|ϿY I.z]}(4MIg*.t3D/>,'ۢC;;U'qF'5 %[|]X{um|"uͯ=~Ss* ĉ'=ќl%d>mD1X}3ϥ{oX|NJ]_DtjsN :}i}&ܻ[ĥFŒ/_~"q`~ ^"=/+/}&sEshZXIW1'^{MqJȞ(" 0_waI.ʰP*he'mb\udgBf hw>ikk奲3+ky#ᡋ^nEj!6cb}|w!p}HZea(>Hy]O׎}\&,|Vp ͝`iGgUcL؂dCBHv*K^QMdƤBS|{D37>|=c>,X;G{8QP"bmʳ&@y']9qϾSz4W}|s[84˻Vl(oq+MJՐ" y[N_NPϑĜkIBZ8=`AhbOdH]߸hޔϞ>gO~]QJe?R v)FYʽ]祀E&ys-DBzǻʣ}@7[.lZ<{ْ粜7sz|GZus}y@'9N.fpX7 z1'恵s~Dyi)Sϫ*MMkK62$|ϲHNضi-ʻV@[=p?{W[->`a8(}(Z?읁ȒLl?!MMݻfj/[j1_KiCrWTMPX,UZΎ\5K1EHm!'T}s${5EC:w3&JKn[@U tsWxgJL@c[O^HM|.GXZ]ʴOZAY:ۦoWѮg8huͿe8" r+CIwQ{l_D)Q])eZ?RZ|&]F!cF'2BZ Ŷќ +fm+0.+i ?X +V9S?s*b}qesıY܁bh;>ccLY"Kzx85jrYVᱺ{jB|n9\PJ--QITϹF\֝!@)Yʙ zߝ毡ᡋ։;@:olx LOwL=0RpEB>n珶S;cѽGJZę/$YWv8IguV̛:Xo o^EWf .']OX[Zw. |x.rPk\&G|'`s8Q{^=1c #&OD.]ޟn#We` ….*'/U&5}6=ԉ6{l D[M¸XX~6/s=LOZ5GgG*2HDwYMߧ?ݐ&>Կas@P ]]]o[c$RoM|kϿI=fAr%[ !RjZiB.Nfʧ+D.V!!E)P2`^3Z; K}@x=bcA [ׇ}ޣ.u|r0!@+,k&h5g}&H/U3'v.,HD)B qa<ťuĉ:z/2c^J,ı6 3 KkH2{p1ÎLʡnZgG zȒLVn⒠^[.}Gv@`swyj;ФoX$ޯ鉶k>1,v/ΠuSkF"!|N(߲i-}Lw=p{I]5A?e||;>PwInYQoyVZl&=}!qVg.3-LmLI6X?$һp|(K΅=DC*Y">ץV ̟Kz$)${Oɓt1Ds.V뿯/>Cq9;Dt0CytCw_Y460ԧkGh]q,;q (} %n\w6F>0!;ŜWKG=l-oО:uM"=!-ߺl]T:(s?'Gcޫe9G[h|t{5u8I `Rz hwpQR(c.&\PLuꚗU9H# F'VǗ:5 k 8oUi<3=}:=lF'h ^^BhߓGNE7מsU0l=iqrɊUBHBj {h.qBᝁ뚏+ mֵX]مȅ@Pe2\y M43p]~l U e2[ ZKw_) r7IbE 뚏ӏϋ(P_H;uUCoY8*BGԆHWOtP~k6m=:6F/ۺPX ڴXVΎ,)[_@` QW3o' EWP P=͗b]o|i\:S.ЩЏK3n~;ΕKYk,]YaU$⓻ʪ6-kt/g }+Jy{4T/IG{ Q#q|z6-kE*nj oVcoCBk@8[XYY؛uOht:;$ݕ##y4׎0~}KbBk5"RV/UdžIƞbeرw5UX'G?3b9ď`+ݻ&\o]2C+i#{׼gUcjcmN) /USC? 0e-ҶG8CNЮmµczL9 ;>Ӥ=RǶjsΖtgRW{7,*p{\O4=7Nwv<,i=GBzߧiגk [M?Ǜ<־tHm_`sW54Ja=/t&wjVSǶ jq^+}sT7D5@ߪTӃ־Nu:8oY)d1yU/UӾS5;ݛwMՄ`"{94i!wAx}MݻLVܗ ƖʼnKձ& MM'BlU-;7'.2[ KreODs~j]ܟh9\_K{YPc]qZK/Y|;靁t׽Bjdgnf( 0ehz0#[6IT@D4P9Eo;L6Y܆Ewv3{^t LqRx)Pу'C-NHu%mZ~:~l-sP+m潬Nr37Suq?m潢L "P>y_<{WOtKbx.Pf|h QwjdyAy>9a.>6tJѮj mM=t#wF~oӺ6Xp@ Iau%>8Fa:y&j| Vgx"uJ\o-h.|-o=}%rfaM:NЏvw[^Uںg|щ:.p( \[÷ {+sd.GOPuPZwlZKC^];J Ť|I:uƃoU:Ey0\:i? V1x>,=L㗪Vs.(ITMwW̦~.:6VP[:q3IXkGGm?D3ĜG-Ύ,wC+P.&ؐl \PJ1Kns T_;BÐ:|swteYKܘܻucFpM07 NLQ]ܞm[[;W.ۡ_7ʮ\t\ jV$.!'ٻ|X-&oHZ[{˼d.ҋO]OqmA>țQ|蹅I閥o1/9ce/..=з*gf{TaT\iYcm-YN~~4_I75'IP!9&Έ'ުޜ&W҅kEMD%@#|LLvX|Βi1\il~/,;G#,M$&ak&椨hZx7&)ym#Khx.ޒϕ[6| ( ^yzᐋASk#dSo]A?MgLR副~W|HE_Cn;l}lt)=е._SӃs:wwͫrWGm[W}a7)2aa\LJ,U.eMrceZB'V@Q?t;AD_bO 󭫯ڱ8{}Ru^KXI\xg`e#'_|&#w&TS5Aeq(_ZӺOj-D3+7'[0}!=\ 9a׎+p!I^{1efge%yʱnƞDK}ӽkRTECs@ß뽧6` d(NROw_^s'鉯~W]1>x)J}qsx=G<@â]w?;ߠ']z=-1F'_WSzʰ\:PS#olE>_$eQw[G #t}e쪆^%׎09)gp5Od0`R5=2tdu'@ggW_* :|DD;59yl r[7#FvR8TM5U8˟}!NmTMk\Ln/ 㗪ck&hUcONP͢7Z' \Z-gn׼= L8=(NFI ?$9!sض:u~m ~ jZY"v\r啧ō;Kp$4|%ib7, {UCC!7JӲƌ0t8Iw0n?mmu˼Cy=Һskޣ׼+|L.&RH$&z7T/,YSr Hk&hNuqѪZZMOZVuˡiP} tS5K(Cw"=%(P_[DBR Ѳq9;r՜KH B@ Y-C`RXw=1(sm~>ڲlǿhEQʩ k-(4W  Ijz{=l-;ǶǸLA_tA1IE38ny=; XNDh5-7)M ^D悒}4Ny=vMD+}n޺5N Ѝ? }wߚ7ͪf~&@{m"OL(MM' C>~kGD <bjTگuq?o:oI{q%mZ~0T6/?Hx}\ y /u75Y!/z7ήDJ5[75gnu["mE vT_;B/,:i;%yZ} q=PaE'8 ϞXeJڅ-mCjV VUӃ⤉#HǶ b}ѓն{^gZ u8| xG>:Zaw=p{Fe{GH<hZ;w, =l?O!Xe:ieޡlbx8X߰;LM.yiE}â3pf0r9u]XM_غe<EouvKR#MDh!"::*~Nm'+6`8P9sR](,:\pr@=循X"7ҫw)yꉎHys~j&hc^${p1cC1{auBVJ}HH3 b{׼NKQM=tmHe9iّ%b;׭m]qls@9 (*ҠKj·MMo'~g |Ҷ%<.ǿ(ul[<9?Ds[{sBMkɐ|H?}BP[g`|ltBWKӃږ[6Lq˦О'VsBQ:(ʿ'pUٮӶmmwr'DD{^x3h1<įiΧEӲFڦ \QogYG ~ꇷɼo F߿}MGarj"IKʲ}Je)I^>r*TXZw!=c#։#Kĕ盗tum,x{&ދ/Xjv di9(/ @N=n5 -_5"=ksq){u[..G_,[Z~Km{׼NyK v{u6׺z ĻCqR=sur|(g"ml (5-ko}hrr_ܸZW_N콵pAn80BSn)K\غ:wwQϑIZE]{+n9'^kcˏvw-5-?ZHV{^{9uP7[war4gG MVz-n< Nq2Ƕw|ZK}ִ=0:I=G2EH[׫LPTQeX{ns~XzE瓯UٮB.|zB5-tW7x'.( Dko;L[wA+mu ݼiuLE9/ri($E>p2ޣ?˄m׮ްBNP箃yKoUW !H⋸¬K{9TV5F·8uّF ]ŹU VÏjp$5ՍPk@ei9ZZf*HvEpg7}wjXgkXuI3P@`΋OHC!e"׾Z}ÊqAkIQ߰^{ͬ14_߰Hܶʟ}}\"ӃԹK|іva5ߺNN ־7{Ikݥ9Zexf:7_퇷N\WTvݞ:kʼnPxŬ6{s"gRO./l]O ADbx"zگ{BuqWޓSҮG9Y33jĴA>x2To]A 8%[C5U'/+/UC \L9 u}m^ޥq (=Q;Jdc_gMBja,NwF&nj:a=Կnky_T a`?32{Y5Utu+//,Lva*38zt:( a<0&[.㷭F]4I<=}⓻ä;N:~esWWɬ~kἹ,]7B87,'$yF'ھ]XMK}6/\BCo].&R F_|rwJo|7-kL#,OTMҺ QUDr(u!|=>L/\G)@ćb˱ȓKմq/ ثY|ᱺDG{H 8Kb)-)Ύ,qWOt$&B=ԿYHu׹s~[T9&$x=⓻cM ŜpE0ˀ=KsR~7vt%2~HÃ=Gss.>Ap0ƝB'=9־Ԏr4>p`C9\(O{^d1R1u8$|~L4Ѣ;}_uAŋOt}$=F.O~q@S1\@QˤVƥ|s=nKgn'׶/^=ёӵ=ZJ/UّuoLyZϔs@9R77gd(N?:FDDuW8]N|oo憐/F{Qjq9U}*(Qw{bJVt7vCv⌕=| \e>Bgd\΍{ؗ2}nOfa57^UF';珿i0U\p7?)&g۳:ҋO]/o/gY'A}'ۮ顿E/|{w}J.36_R}b#ls0dR)Qq+j2WlQ})\UKW;tn>NCj j'3տ,WOܞ[]q::PJzD]Z9}ʑhU?˺g~/~Zg9|Ny]oz#V0V:64y4\jTtss~pwPzcutl{n:ߎ?v<~_I/bw3)DD?8Jk?/oG}7XCs9/x\oP4-kEĬO飳?yeiҶ¹6gxbKfaMjR߰|O[p$Z~"jjm|~~"]8tH_M|{46:N$hx׊ߤ8P[{KZ u\:#ul[{ ^QyO ]yGknjme4Rƻg4Ko;}-OKOR2ݫ _жjpc'ub{J.36_R}RxG"ߒl;ʸ]'OW&}.#tekepsxta.Ҋ$jV7RMls^C?\tQW! !휓(9'q[g\1{P2[_;BŨW|[reH(EĎ3jUMώ\EP\; ~K*zN{soPŹƤuhiGe5~~|z7:fVv_s>5+V$a9?l{ +```````````````````````````````````````````````````FNIENDB`tiled-1.0.3/examples/sticker-knight/sprites.png000066400000000000000000003555441315121121300215650ustar00rootroot00000000000000PNG  IHDRZ. pHYs.#.#x?v OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FЏIDATxy|Td#!!HV@5ՈDZ E-J[-4T VC"A"\!5a>c2cL6~>y(3w;~9s vi""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""DvH2D  د%""""MI `Ƌ[8^/[7څ"""" v]{ADDDDDDDD?뀟joՀ:dڵ""""J p; 7sP]-"""" HzAZ9{Az"""""""""ލZu +_ DDDDDDDD\c~ 哿XSئMDDDD] """"""""p 1v1`x# Dϧ` K/gϞ=8&""""P h9W\|S5@1"PQg'afjl6?W_}ٌjn'$$JQnh+z x^>őx?-[~.,'NPSSCUU;{;.a9yݻ8x˗/gذa5(+"""" +~v0o;xz2V\ 6H0LTVVҩS':˯ʀ VCpP0~ٿ_~:/dPXDDDDDDDD zsY[XV d}XVz[îFEE֪*F#'ؐR &е[7O/%"""""~QXDDDDDDDD& 1O|-[ХK9}\kKQ^VFBE)pbbX`0pAmBhXݺvd4z{DDDDJHs]|Vid^~kI;_;u?]&"ns)k|:u{Gya.h胿;s^p>x8f6ͶS _P7qjڍ҆ hWjȹQWOnigo^71)S{={6srN͚5¾½8q|6:t㎟O$($7a(--k'1?'O{{ȥ@>UvAɏ?K;_{ \c`sͤޣ]!9[84*H0G*ߒǁU5grxux1BCCʕ$&$0~x1۶QQYIDHv}-QoO `0ܾ U\_|Ɨ_}Cޭ^- EDDDJBfeaXRIII=LI`if3k\:dIIIDD;y$ڋҖ䰷:ED(mםE!C|i^f3QlGֶI׺g;H $U [MEŹqOA555";u"/̺d'tރ*:v`n{F:EFr7`0O6,~{OEy9:tpU4|RW7%mLR1ѿX\\Īlܐ%KX,̛7CSj˥- '_~eFu299y$;Zz I~ cx, QDEu`O) '͢b$%%y%[w7`41TWWS]]M=I vf>߾Ätd"0( l6"SՕqލThi&xxcb=쭆o"9O>]_ι?clBC0L>e(9WoxoǕyRxsy>9{;'s).> @TTWBC\Ib99ܮ`ʊ3J1WWWSZ(|?aYboKf ͆n' ˇ Kh cMs5kX\n_>ģS0P ~L:_@ΒYx,),,$##kg]O{GNasN999J3l,p]2L'6⿴/O>OXA 뫐V"zl>mCLL ӦMvli=\⢢3ZK۹ mʢOEm-{IS&DwyXN`X6i[SSCMM N$'e!-[×m#Yt g𫩮^pyM:e 8(n cwŅcXwdOO?G4} Rtu98(JTtDEE36n&##_~o :,x[Ϙ?q =5),,dmVu6 )&_C֚NO7%g+K[ IHLj 1_MRïNȵYYyTUZsi9&ZZI3js|b',,cǎr1bzz}ݎcwl<9RT>dk%ޱ+""""g3/3`2Wpy&ulïJ*t;v0oh=`i9P*m%Աi̘9/8f9w&ھHoٜChh!f̜s pNX,?ޗ5f+is/";c3?<1_ǀsv?C_߃W0oEhhfHꩼQ7Z ـ\Ӧf7.:Ux aaa\~s.JJ,vS'٣pyt9%{}WDthh'uJ{Sw ':6AO^LlmH Jg1̈́1c,8Ż:$&e:I7ͧ`iA|w'**/gI<>@Xa@Cl\<3frm\oy[y>M5Wd;N{{ؾ-u\/x)vRj1588hk%44ϷoC4h^MM5555F 8%~;uw5v9;R/YBNmY97=@_4oj=8p~p݃H3s~51MgF9)k$ic[_=+xxcr.r0~2W:!6.u[OgFwwcR11}+oؚfkTff+ ,""""-Mk7ΖK`XfKS'ظxFC֚dddo%ݍ+VPXX*{v2jïNal/^mx[r)Z3U&z@=A3r u"zq4}=rsccs#㘅vB_ZC[ŤA@cH_ZI8]޹AמĹ}Z+H7K̪شz]46HݺucwqF֮y+ {TWWofr5`۵EDDDE(k>Ow,^uQu~/ؓO46n99u4k4]/YEaa!111:K5JS1,ԑ̬o?=IHCf#Gal6_^Ti/9.*+ }/-9]3G5qhh'qC6ӧOǼcfy|?-½{rNrw~s7rUWG)`4l~YE @ʵc4&lQZDDDD'*.fef6d9G [bV>T$}g4lłv]W4ɋ8gfSֳ&/iKï 3r3|RxsF\[U rϺ %IL:+BL8ɯ%K;yzP)۝۷m!o?_DDDx{FoYuvʔ_ݻ~KmL&nӱc8o _9z`Oo% w4Z""""_;r6ohtOo0M [_)ݍol\)#*+EEc6mwP-ݍΘ,oX?EE㪶hUX2Qo@sgټ{'OVs&[DEE0͊鎵YY}|AçL>}:HJJJTvt;OdYM֚Mczv5ZEK QF1{x/ΪTT_EDD$55v3yF#!!l)on38y]t >)/kX lvkO_;M T\\tEqaaac2͂ pw9k>Vk){Ի 8f85AH_41l͵[Bb694A [_4@wI7goُ@sgX_ZTw7Z,׮:6QsaX{[n|/ 3=>G%:;##Q#GzZ`Y;# |?Nuu5,awr{%vfO >N$:v`֭l߾/\w}?CEDDDmJ% UEcRR7 mbn3k,oDKy3l3toE_D_n,,, R$Ikg4:65 Pwmrom~77I|$&玟2vwPg7ETTTЩSg%$~_\6K >'zeY,}U.2}݁ym j"""".%ϒOzџl)|͂vj.m朜z;Az^'&:$QZwFsmB,i5EEOJRi^8fԘ'%K e kW G)ZLtؑΝLYxm6:t[n/>cʕDuٳ1 yqq|Co &``QSiߔ>KBCCIHߴŇ).*"))OekٔeM7y\xwK+9:)c78%Dߝϵ_hKspLu-켝f͋\׵VfZlnLh[F󠪪**++)((믿flڴܭ[f9z Rjjj0ѭ[w c5^͆fkpֱr^ze> z!BHHAAA _2GI艀qJ v_ۀjN""""mgIl\<3fj|>Y4 F)ΎQ#Gz,|V"!15)Z1s7K˗-5gkKs5uMqQO-]4\8^֬-y}6pqjj&88Νqh1͑\ަd06n<BCyql޼а0." FJJ ^HCj}}D3I l @Hۣp;Q\\m{XvmU[^mGmQ(1sc@_ڼLeГ< hk׾:V}z 8WQ=99{;[@Hp]CdHCB؟ v[(͆d/!ٽǎyf>\~nƌaׯ^ހ#Y|UL[}C`3pXMODDDPp΂:dh=,_* IMkv :dH}?_7!2MqQc@ZecIrNqR"""c@ڼ+?m4Oǁ/կ>8ZKdb!#1\R@L}=Bnݹn $$$O^ֵjlTTVPQQѢnSUUEbE\z pAvݷլ]._LwAݛ\XY_I~JfΙA<<&}n5zgd뛐fZPu׽6mM9I'of̜ݤ?$X=@ ,/me*` /׿nR;s9z QQ]Ig,1Kfi( R{4I7o.":+ﺇ˯ޱtp$^8q?xee%DGwG |9'}+/oӜ?2en|KW݉cp@Hp ZMYkVcS X__2!׽V t i@ٿNmlTRP΂ظ8\y;w(д`;T 8%ۥ~Ǣ_)ؓϢ6NJJvͮq8|(͊e.?n=n"&7aaTUUSZz* o 9\1d[ssx{ r> 60k,"""-08f+"""(B+ V\\Y0*~T)j\ڏR} if{u3QΊ0BCðZK(+k`{ʏKM8))O6m1tу|z‚]θm!˞l]0 d_j-~ Lx7_2jjj(++kS; QQQf+yyꩧryvL&F  $8(Q?sjLLIDDDPDEE7y'(Ϻ.&5WZ[s9zL5ɓ}u\߀_;h&[{W]`r%$&=;K_gin\BW6u⿴jEڤa4V{)O]{L::&lG|3nZ>`СmM% nj KKK={6K_}o翸t5TWW'O>aȑv۩VSCxx8qqOTT}!Ջ(z`1F)`Hp jNP˖R'͛mH/8ؑZ^Vk)gRX2"/[ʄ~s]y.攮v/M$F$BC\WlTm̀G?7%1_mPW|, h< 88~ ׏k뮽x/bE@2DUM]DDDQȆ>):ALW_hw!r6o~,sɄx>Yy;ͮ zyJb}*?&#G!$_?k֬rJi 0wluǁ36MsUqvzJ?cLVp<ױ8 q; k]{З4&_|k׮em߿b;S@& HPP`'"<[ ,`0XRn;:{QVf%..=}99BοBl`0`4r**9q]|ݻٹs'ټ\{u;y2\p/o5;5EDDD%_oyQX߬އ>f>0ng[,_iW@UJ=Rg99sg%s/bы ZfF#4o5&%%yHJJe-1 s}qp7~a6P%$&1r֬vXjZʪ>~j? %v? ?g\lv ul%{<rVLqJJJb/:gj_6:>jcǁ7"6.ԱiZɢR\TzVk)^\:#?R{ݲT_M2EEMR9:""@Vr{d=Թ ~<#IXr Xf }{*˩!(8@%&6݉ڍn={^|_f0& 6mC hj";+SNޱ<fߓI0j7 $((C'u#o_a$EW|}{dbV?8f =(z孏DZ8ࠚHSLGɷYY\zw'ZJ֚dYZ 8:B}rd^r8) y%K\ڗWƢR'E/.dы IHOTt9v).>|FN&T ǀ|}⦍̢3}33k \&Njqm 񿸸O~tm ]ZHߦEEٌq񄆆j=6_7=3HOCs8~ktYΘjecMQ71pp`O~z{'O%kf/ NH.3eгּנe`.4o~aƍs#+PXDDDPG$4ŋ>$_BTTWNӓ`ŎNЂ=?^S'Laa/ugB>Eֶ }jdG'sN֚l8" gnA t9g<2Wy}B: y)+4sNNkVA>="66U+3۹5s7oSO~Gp$՟??f 7|ƏO9q uR8(sٜ%Kw~,Զ 3;5|Rךugџ~,abXz} J˷62YkV3b?[ɓ5rM_mqx] >͹vx {ח-cuTVVM%׷/$&#&@P]]usTVT/-6k~U & [ W猄j]FK en17=F<Ļ5r%ҳW j.OSW_ ׷/㩬tgb@\s c[fؒˮoG3|Vn)̊C}#4#tdXATt4e,qVk) ۹Co4-/Ee)4"bX,3c3f|%$'445]fjh)s5sR|mOmX,Fx#=-0zW;fNΝ37x!C4±>~ ԷX,dXAFFyxc ~3Vk){}y;wB vO6{'On`g 8W O1X,MsvX3NQ$$w-k 8 ]O gxeX=2Л֭c6m5i x]~ڴKPt=bb?`?IJ"GDP]UEuuu3`M&Ň穨~-Ήf` 53ޭ;dE}lCt̍Dkݳ{ 1y~z,)!c\> ׌[od2O_` 8$cG@޽Ӈ'x &4'vEDDDZƹcD|dClXHOO's ϳNsv^Z?<8Vk)FV˛8Rkۼrrr؜yfL ?CST d׮]Lϰl_x}?!,_/~3"#~_j|!!!| ͥɏLgl eDX{|v:w>'Mb&g""""p<0yPDbqp/ro {;'ƍcСOJ7f "c{NNr[r0*:Աi-杶oegMJJ"--Q#G{ ,={?=M0O9b%Pʰ ݻ!i>Ҿ+8}mVYkzq=fu9{キ!_Qt yy3fs~qВN;C4lm(qӧO'44/RVk)go-CIi'6y:F; G%//]lPl4`h0Q6} _o}=zx\>;~c𧧟枻RFBBB8qE2Oa /t|]a QcZM7K7Yf:[s25sGlŧ9;5%g2 %ɶ6+S3?PO9FɬY|=ۧ8]6dw b8( pLAA>۷2b!L6M ĝ|F͆/..`O>{O=*:s=a 9o0f{~0]{hs>pW^x+wǑnO}=L{qNnO]t;zeXȾLΨ7 Fg>Ŧsȑh1Fm9fDPp0>wUoqAB;vkl$]tiii[s"ԇ+!iLgH(-=3sbǎIF @@P+ lZ[Ș?Nޏ@%""""lΥp?- ,!## БnbVmP'?:rgxX,dddxj je+y|߾DgG8hK IA( p}]3CCØp fqqVfR&׏kۿjHo1r_f=kf* X۹yf)aDEGZ\uƍs%0<21~<#g؈zoc 27x\ ^Q]ƭ7xOuA{6K;75Z53`ȑ̛7dRkl6s:=GCش6f/[UG"l> DC F%ΉH@%2|<9&ulY+T9B}@O{v ?|Ç\Nx>8L{[I3G-gEE 1s=zj;i՟rٿ?}-BppoY0mly3'';ﺋBBCØLFC``P Q\; 6ͬWR%מtm;?ad>w!%%hyk}9IxbwuDEG3cl:N :0s~?q$ת)πY8p k_;Y,|I?k`\BbRoO_>ĵ#np%[@N$$g)Ms]8~+(,,>-QXXϲb;~g60c w}%1zO<9|Bswֱ#-wnܵ{9?& §ٯ!=^GydT1cF#v{60( {ABCèVSnnS]]fKT=cbؾu  ..\JeYaaat9 OߟлwO200?|OdHF\M&zpQ v⫯?)lv)4RJf[SSOI :]ٝ"#b蕜8q=|G2j(O1@ڎqtnSxxc~t4_2={m99)x);b?ϴШA(&0?Dɵ#n/C&/99x}?ٮ@ 2WIgIT !O6+gr}0rbDl\ZEEGJ۾~\w^:fc޼y,}z-?@&)=쏈NoC$_>hF#nl eaxCnKHsNk9r5q^?kMM ]v}|t֝G\Gu={g֭[ ȡlV:qir25Mlt st4ٓOee%]w &^SK3wm3ή8(5#l6חNE3aڒ8F!''չsS;9/% rԬڌH HwwD ~L~(WjmVկCt%Y};Ar-͌ck?Qә=mzhh%3pP2g߾B>#f3)))cX;Tz:O=|AۧOǎ*t`wlٲ[}m\_H`PASUY ݷ?z2zÇ8v?_?ⲁ= / 7`[`0PQY'>s Z:v sdDDDУG?<3ݻd2Q|g9v(ǎ|gtҤGMM th4L^^\r \cy^Waa!oYj/l8E/.ɓ5kM?G끵m?[?;*ؓ9Xz8n+2pzcnqMtTj-3Co(}cj-et [82ݻY$<v?eת8}"Bf3k׮u͂t|ƳɧS뇛-r|g6{۞/ Jwmfq˭y3W\} ?@UU05Lp`>v|SZZJyYa炾$%'1)={;6v;AGQv6WXJ]瀀O&^Zmc‚$u} Sx1>\_W<|7ڽ͟|Baa!R@h\E $cGl6[_o{zm,\[ ibdxcmV+V:DZj-eK h_c&LD=oOg{ۿiqwb!#qXMk5H$'_K/w}zM^˗vO4 o #qThK9'0{V]22q{BbcX2tF3f|5/^*ח6kw$rsng=r۹ӧW zo*?dYݬ_p LHL:w/6. '|R2225rA-Xl66+ٜ͛q;ΉpTT43fr@_KLfKg6]mh?KXv-;x&IFL>p6u'HDD\7+ k״?o*++IHL Qٝ^!{A\/Na?Yp$OH>}xw(>r.]pWrW$Yj6loeeVf.howe21+|֮Y͛5jEϋ4NCb8:ZB7kj٫z.wsU z_edO{G %K<HE@$w7cXHHْ f>=g^߷o藐P' *q?aadXAZZlw@k6S;"6.ռaUs7oe}N0).*bL!RǦ}[.{IOO,4 Xmm_kn.3H}lm6ˇxt6䐓-?ߪQXXj@_#<>f Gtߢf{:fmVYkײ6+ r}!!tٓ=z)3l\YkV3r68`O>VY;6.8wN:`ݻ2{9qp r6mǁZ}mN<ɥKEEE_d fuF>C~[ tX+EwFUU=wgUWiF].0ˇb@ 7=~_n;k ]@Dd$6f4I<9pʕ|g:a#ghJ !!4`_jj֍ACUlW]u61\DDDD@{JKPXXHTttJ$7E㿝Qo\^^={CHe}ZɄzaLn ƍ4L@$(,,tzov [SS}JHdnMMu Xmظx_ ,^[ UjnN$`,bߪ`cj-_BO}طO33$kj_6r:b0 BWo߳W/I O%$)c33B!!\ԟ}Χ[Gt_mƉc<hmJ#G9z86.=9j6~On`xEy9+NEy9IIIL:Ӧ|j~_b e<,'NaZr7mkCQ?f͢ ʊCL8ױiF<]X@@@ Gwns]wѯ߅^n'yL&?NeEAѣӦMc̘1}|M>x8zo;Px|S9^n%EDDD|xOuK N8EG8/}_<9O/+:blOoi=nuw?!*qzؚcw%hе^kN x]Ջ7OsNkML["WL1XB8ASܚU$}-,,d\9laø33n6 fD9rw!zEr^ %$ԻgYM3s VdRQtf[Mσ>}cڵG]_F  b`Ӈ1L<裼d 7|3Z)UUU(\r:t3#Vfp,~y!O?֬~jy]6={a2)//w%׏y>˜9s cƍdr&R233}WCYi%b9,!?%[589ٕhSgdfO<ݻ;rdx ee$$$Ǹ;"瓍t1/B~?|g.]ӜyxTdb׾3`4Z?qs߽2O"cG>q/v;?fChϏ'<"6yHi/ `W_ӢoyO[ptt\X\y;wx&!15 ٱYNƜDNhhX|sMp&yOw%cIHOTt4%%%joq,Hg`mV PkU=}'g+ק!_ \N}+Vl~ cmK nS7 V Dj-ZIqQ={9>\UH},H>r)jr.Gﲵ i&o+8ʜ𯹤i7ܳW/&u*K|Yot֎Ӈ??~.8A/<6qCvG5:U9/! |]n O nĉcY*yj6W7sYi8f'݀3F9z|L&?IL1LDeE[?z|r&F1L@M+1?gc; /*. ~LV&O&00I,KH`0pI?sy睤c0؜y; %JK{^>̇{4X@DDDD=$=vH8;A~UJgS'߯oZ7vX;s\\ ;Ky쯏lxk-6k0ppZK]3ޔ0yݔόyj3̘920clbOΓfALhh̀IQkN%c/]; Ni')S\p=Bw&c ͛[ewv?sSs Nf7 -ے)[,[SN*QѮ>k~?I!G{v:?UͮƇҩsgW7>zq,'ͭ!!zt/[LxxzYjt I$$`3:|)e$ҾJ?;ݻ)(( CzЈ0 l̖Mܙg3sΚ5 jUWWc8x0=,^YJ.]d_3xGڽRh4BEEKt3Əωc~ ǎ=%*wKt4U|/"""" =lcgD3 ւ@YQN3Ra$$'ul s@w$׽ sfo@Su n7ni_c={rf晹uFDŽ$f̜J<3Y:;.Ukߙkm]z}VTt4! KSsqZk^c5jv O?**3=>/ z`ms_ڿ1n7y.c _zUUMiӮ`Oh, 9ρV 07%K\k66[WKw A>yy;w$pAkbO.%$x-q<5{-M s1bbbK~N+K{{7z (8/`4rA6dea4yG}mrgPVQjnc)++{3]l1Lǟϑb& *]m}nj[ttؑRb=ۺ>^Hǎ9t_}/   h!Eb!44̵^\s+.1K Ι,=$I盼3ݱW^{w&w'<2C|e 8""""⧶gasVu#Fɹ>ܯ/I}|3 <{)NҠy:ZWwv`^2l)ؓ ٮ6o|O L|u;,-,zq!3f:zOHg?ٿ. f>PԱil㛼C6lOsα!&JƱ;/n ٩A.elS`fgk..w[r[ p鿷zdС||v sg41 l55gg\fr=nfٹs'ǏʡC+|;Sw6jٿεZެ_OHsbvdb)ؓu]Gopr2U~_;bbx!tVEzk̝ :629Tf5߷m΂yPg켎n5׾\|I9֎Ob6Ǭ1O p,f)Ds=qc-i`9_~o)m΂ݾBbbbw*ͮq:u2 cd6nfu>oΨTwQ=ǀ4^;?b_a#FmANsw <,p,zqΥ~?IGEEEMqQw{~3l>cmq6m/|`9Ж YR`2)j[_Ol4(-9|CpPO͆f'.@`Vs FI cbfw6grבc2w{< ݃v0Pӄ_Rv ȱcyhު(ؓv%ڄ,س猵L2-*:QT_ֿ>=:ɟO0ylܐMhh)ęHQoIozzkߛƥXweb|Oׯu^WqG۫8^_Z?sl,fݻrS!--q|m8cs=WyJj!4ubanNZ,t^f[Q R b-'jx /nv1w:& ~4͇0j;O}SɿZ<\p6۷/%[>}(:tǎsq.HHQLue% ٳ:w>>=zٙ0%l /t%@""""`g[#8S]O36u]cU:"ݘ6nCk7k׮e%tу7ڦl\XTFmOǶ& _g NNf믑Ygvp%%%uQqCls%P\|m}3~O""M6u#FJ672R-wSx]G8i#+۷Q)u#F(S;{ sv7SyԭLNKUa%f]דa#FyG...{)\Z ~5Q2 @۷9AkFIZZ? h%OmaI(X0`GTTTp1LFrδ=v;2r(cUvM6NF2}q\]^iΝ;c؞eSz$F#o28|eTj*1qlZ2+)]Ϥdh2rǎcMfpp{ @ `έKg<ڎ>c|hVC 6cbb\#333`.LO}N'~tr>p> <M5 9#Ӿڏ Կ s,XeKO9+.vTHJJ;(G\m,13L&JNUUUWT`08/ȠHs;`4`h4ljuw^6x>ݲvL\D=38qb+$\| ={q5.,q IBB_|{3֞VEDDD|^?ؚ'c|222x ƌר۴n}qӍ~m[]X|k񾭹Lt7};^g!;y6j1w<v?v7zf(.zq5).*"<<ܯH6@ZVSaT׿CS=JJJq͍`=|<텿׻?F4ƙsΞU$x ?~'5?|R?c}"o_w)R-UݍigXxɧƥ5jve)Sۿo)~̀oLBKofOtGҩsgȉc(ؽvs~v`;z^wQ"Y8޿oe10ȏo>,=۲ Ng hvL&m6jjjΘl40)r8;1C(!] ؍F;iKp̴5oѣG4n6:tu}ρ l }/ 2_7RUU}/ EXKO|yt`Ν>Iw7pD_sml'ΜM,A,qg>clsN| vpwѳQfSx3ݲ;XB&LWoli]o"zwtGuƏ]ߢ=1 |ΒŋG Zıc|g6mn$$$:So?6 A t9{پ-5TnMMUr8֔Ҋ1_Bɗ38 j-u;|^ 6+%K_e)ؓϣSɮD3MyNT~ojYMkPD^\,Oym/ؓ_u4y4B@QYUEP`v1$Pc&KuM 56!!!tf;cFn >zw}CrTTBMM ]vChǏcǎoTDDD?m=BWFcGWsTNSv<L}lܐMhh(&NqzOMP.gGuٓ]9,Ï3;rDKG~^'ٿoYkVf)<8e >4A~}8xr^7yMPhΤ!Y&N:eɀgu~ L.}%$d<3w+PWxx8NҠv/!owjzm;7ڪ-1(O}xtꯘp *"Ъߐ iQxߦTQ^κw=%|94ɦ%5-dYcLeEp$`NCTTyyy>t==gv*+5&,ujjjڕPdoa!C<}""""i%b;?1?y|5]Mqqy;wָ㜧ܨ;`.r#Pf1 Gvvl46٫WddW⛼7yy,zq!^\xvɗ3tliDJuwcNN4f[b)SZ:1`|qE/-t2ךnmx}2:r- v&'Xl)毿b0x/M5ڽ;k2}^@eUP[hწ5,^o /u9  `j%M) `2:nktwg7i*F j@@kLsZ8**pl6􊉡{Nv:fimxsuxӖ>7<<|";㜧̡#`.3{_#,u-N =w 8g~XLt7^gϹt~~VSk"}@^ND oXg֯[GqQk@Pxx8ﺋwՠj~"cP藐\^&9+ZnbR/- 藐@V\zŃMiLNA4oxX¤Mb֭cHJJ摞6n+4SHZ`Ok|xxxAHӟ]r&IPP55`ʬ\MDEG3Hl Q;]Sw/nѣabIa&'k] |*͐ 8|ԀE6t%Dw^ s;')"##ֽ;).H>EMM+Q_fa4/9zchϿU@?p;j \-#H^[O^NJJJ'!!kG\ǭ5kG 羫 %϶n@c6ZrYm~ np^o]j0i֥k3)Eܜ8DZ30񮻚 `QL -z'ԼZkCBԹs1λ\pX[ٽfu^cYb'3k֬6Ӝy߷˖OsyQnTSvq;رc;.`JKK]UUU|Rܹ kR"ja97X Xl|M6p+ f63jHOũ)_9P1˅x0@ͫ}n=nM5([(_V$G* Mֹ#,/! ̇Qb)q 㜧4t}뿺AOOl6Hm~Çt\}ʬf4۴GӇ`pdr^ ذo^>LϞ Ց@WNE1̱o|egIpp- n11t֮%l d2a4)+rq,q?ƾ½Wȑ#Gwl6l56B bܸqt|zVGz;]k~h]Kqv>pNn={Rk;fO `%ήw7mMp [ss[Ňv]< ylbbX,$U!9B<+/c#na}CSRR3s,`7׮&︚⿓sPٺ&h$9)&*^u՝~I$m_AeE1c=m<``k(˺^q1/yy+TUW51TUWīK_aklM:>|<UU<1s& ̧ L&_~w\tEtV@%Tw#FgOnV\Fa--?~SRba9q}!!HBBϣwl,$/LLO-0HO[_uS~;lkm@o.̝>|S'ł:)h@6y) EoЧs&[<ęafΙs>ϥuu}]$cg_93:3@?,,Y{G6Mguթ)""Bn[#G 8l"""بy<͊DFFƻnbccC~hMw{7x'gtZo)Jk|9twF)nI/׮{,R.1ab~)ŮA:¿_v577U[Ȩ(EDD C u%"""(0XUSS ǎh s ";wN^:?!i66LGC Y^:C N9oGG>TyYbc(11Qqq:G:wΥXy<=Fqq:[S"M2wϯ 9lN/t1IFDŽwɑukXha]5.iR]C#laߡh \fH'|pu0?XzND*Xw*ӥb 1)ޮR{t*jZISR7f}5)R_(ȿ5&Jӊc \)bgNgN32{ow,I/t{)u)sN)$tC楗:tw@'MR k69bcc5~x7QF5jh={6P>`}CRn[ǏG}4՞=}5rdGPCCF&رt;wN11y9**@vw%IEB7`aWGE}j;TTYQwN;aߡFCއr8|Nw7]}e^6tJRuI vKf?R)f)>G_3az5ϔTfM Ih.c;ޯ3@49fuAfN~h4&3os¤ !-'Y]S&sߞ)G~ưҬS&u}Jo&@0f\ڽ.I I>2{IIJif0jYFw*=uJeSW=h]xᅊӹ^Ԅ L탻Y 3f竮,/F<|vfSjj^{5U~Ŧ&]tp=֐X]GjhV1CfvH̯ 9 Mc d6&b-dL7zl gc@5Y7~R&s*ѱFS8g0G tCCێDJUY₲?@y;CzzD#ggd ]7]?du(^:cmoܨQ**:xE~_بzl65Js!zcauj;m6@/4FRs/i(555>x<#!An[MMMrm3<^=zwkt༖QcƄCN2$e$=*鯇y"RS}@Xo:XeLuk..)D?HJ*b7 ? WJ)겥X}߲LK.oi9QR"&fI~,MXsNiSu)ud54wC;!kRr9FշϽ񨪪J~:W蝒US]%ͦ]O>FJ#>T.n5Z~AIy@%5pt@ 6FV8)> K5¦s( \6#a5@o]%%%JNNwQpbC-2dN (.zTө@לE-fHfJoۇ77;qoϚPwT񨩹YvXn[ѲjhlPcc:P駟Jv]߻^:::ZGBNTd>wonwkС*++:N]cƌVccflQ]NQQ:M>}J*ީ0 {Zdz>2j"aJ}~7G;&ldnmWt_ǁ$}r`֏V Fpk-/0 k?f}i9zLŶZR'Pdio%0H ~VQj={%Z ܬq-˥27jjjrɓ'n7"`s>Sy<ƴ+6&FNWcMVTLu~GeGAFc(&&V|DǏŗ~QMMM-գy쳪VʄT(92viSOjtQz Wu^1徺]7mԺu|ٲ!n/)5I:")v]֨Kv{˞֘1cZNjʔ)^窭չs.MHMUcCΝ;Kp;TGw{ +""B1*/+VDDNvR|ֿPX222ow]/pG< z7nP\\}pP/nΝӎW^VSSjk*6vR@E 3{uCaqȮeEFSE =S|MM.=:O)1bvuz_gײ)eB`Um˚W!wOt٬Y>޼^ _+oka0"FO~*U=ءtG;kxIz;uO_t]޽E7.iJ+`_ k_IZZ~k ΍e^~ݝFstG>FcS@ءs"#T^^&٣Nmenvtj:yꔿX2n IIj':~yJKO)%eP?DÕߵ_l6p84ydox>}tUW]﫟 @7?tG{k\R3q˛r8zUb\tJZewG%P%%JNN\溨YXxX555JFA:YC: OלC32SL]/ɓ{a`8~k*E4v8NK99r8JNN"wݭ{V@.Wޫ+Įvy$նf?(SsSvw Xo(2*JjOSS^6UUU)m]r>}3 f,ۣ@/3H#iH'/o|REE:vc >\_>Kzt Iƨ_nV={V5jT;It@ ęv9-~ˍ=5JoYڣ;eI|k5fJKM7fOpAВP5%Ļ6^wD39~XKneҦ(Ț{okc&9?edd(c찭ݺaoW%f/䨺:X*⮻3;#C;t:5kYj{{Dζ}w4?&S~QQQKd^SJJ.r7PѸqɲ튎Çg[-ުߙg}3ghFB#]0b;fEE_C^I%s'oK*ؿ_~.=Zfvn&&tyuPCz]g)Ps0G|eΌ{Cߓ;u^6k]FUFK2ȴ8.N%b  z[n3f~4,kgdd(ev}ݾ  uP~;:?2[?ht 7Ŝ|zfh¤4Jn[6MQQQjjj :ti[oiKqqqU+ۭao"jllW hȑG$[oܚKңfKгjĉ4qbw7ZDҿJ:ɯȗ3Fn֣1`z*RWw=AUϚuS\"Q[SDu G 7 nA15#K_ :yR}u<"""TUU?:){DuQݳGGqX۲ZW)ԟs^TeeƌC\fa^ci#""eumlx)-Us)"®&JlMn[eeU|ucjTT"##p$q:uvIb%+)>X'3I#鉖06]VO2NRI(1Dv*l`.  VTI {we zdԼwyN>mcG$ǰaJNNɓ%zfHt/|ARIIbbb4i$-_\ 5n!C3='l aС,22R5Z[$[3>>^Cxd)Oy-gޕIKe,/IzE὎d LRꡞG%Y̱6]"I9~Rv_;;rJZ _)#/\.*/W\\fz'㊊rl۪r9#KZ`XK޼@/KtiI?ODGG?? UXXsuu{3v{}l)ƍӍ7ިQFFiӦZ}iJZbccjNLO3ў!Cti;#TrjϞUɓ(o2:N"iSIa] JRes'՟;>#5C n1с9%\N2:[-3CLMΩStԩyý|}^MMȡ*(<U;E5 {Y%^dbmݺUNSy>l񞹿.f? Ei9s4gΜ6͞=2wܐ?JOVcC~|}J:Ujjl=yf){K.Q]kO۹S^Чvn$I2vW$8\z@ W)Ѷ-Õ0|xו)]@-g)?q:3!13]-K$:}~a}ۛ;Lx5iq˖%%r:JO-Ep`( s\_gNV1R#(yo^Gꑟs7r.jUí5kS'r3TЈAZODuZMܳ:=juMxǩHJt{o~nWdd:Qi}NMͽjllTBBz<ɪvFFhСjnnvі?ʘϧ޿~}+ap)&|y`7 ֭JOO7ZVV$qbls lVNSߺ&gOD< UUV;Dƌ30 ~[{SLlldIK#R]S {mMIK޵JJJnҫdmWqo *>vTycbcuYhty\8'z/??@o5 ɓ󼌎mu^9O+xζٶUn\E7.Qa<ҦNg{^V‡?J"{)d.IY2ւUR,[__ZEEEAuM= ogy<54ԫQ]3zh&N!C#G.c0,`=#7~LJȑ/RUe^ުoUR7eBrSQQr}XX>fͺK_88e6+eB;:Wikv]"U ?P]]m1s,~Bڽ5Ϳ6ͷ,m[r_}Y5v8+9ٍY~j=\[0 IuLS˷︣ͨRm^tІ<*>wcso5̓ܫEkm^PYiu:.W6oz^%Iz׿zyFV)~NB )NR8N.( "E-|qqq5ZtiykC1]tJI+dL\z BR9tXSLazonK Ξf炅[8:t}r_ݮ͛6O<82!Coss? 4U":өjLJҏ2w~_k~HQYi!t]wk|gtݓ}:yR;4[!؀31Ѷ^0BҐ!qi###e14lRjjbbbt*R 605DZa#JZnz5f.q {Gp 7- MB +lk~_0%п Z!YSnK` cQJ+(YjT -uJ;X{H փ? R&*m4>SNYըi?@i\Wl}/X+c:ŸIzO|5DF4㲙OT__SMݮƦFUWW)&&V{~K'O'̳Pv֥֞H8qBÇwi X ڏ en liciC #xOujIfUQQFATΦ֣C [GVc!t'ij^I"Š}^HҢh󦍒4 : b:x8FYQQm{yX?{m..ͦf5xO$<=[8=la.vxdM 6=PTdmvgACYM {OIIu.И1c'iӃ oD0(ꅴxh52)iucǍө't:XRoNAGp *uŁ}u$=o;t~G:{֛oG.2}I殏Pٳ}%9Ԫu](, +ݮg?Ӌ99(=] M575KlRdT{M-YXsƌ$I%c}f `7kGǏ秓 FEƍ5 @OSߖk:AL3$uИyyڼG/jsR|H9۶J233}󜞖6_鈇 !CZ 7>E#FݍucbcTQt7h"[:Y\(%^0BF7tƎȨ(UTT5`Dl_=n-SkE?nQ/_[3rx #^yGFȞ:yW8yXp5 X"^>! ^WTS)$-m`fftvKZ(AzUWW+22R$TsSSljnj'%%*䴾yq}_4ydrtUjF]__ 4 TPPEGG{?P6Kr8V۵`ayoʗ͚5 Gx n4Azzt:uhWu+vj7RN%v\p8ZxqA|;n/r:Mw@LOO&{{6uZ? SNo1e7U'SҔ:%#ڵkNUTk$$ͽb_(V7=E7.$=wEW}ƅybfwb)22RnjT6M.WNIsQLLLlt||0m;p@EG?|Ejjy?t OU\\}o>8L|r[N7mTz˭Tlڼiwm)]Z`ȾK>6_otJJJn5kq^ hƞ}+?-_^*/ӧQ% x^d\)CڑOIF-l(/68~@U{^>{\QQoqccewoͿi*?8lQ=Y|HAX疅 6 wֲu'Rܯ$l`r]wkQ߼i[zÄo+a־kKZilQ޽ʕKՃ]ȝ5rڡqqڛ0g*؟p8{#7WC32R܁Zf{'/x-$5Ǵ~Μ0Cv[dU:2]xᅊہVR$O1NFG6Í/5KsiYƤa4$vkΜ9^ cgE`hK7ǒ:4j/M2!U7߲T$I?3I nf̜ dL'g?"풏i@%Dλ<^xiWStl{kSܥS'OY~Mm8C89޿\adUC~H~:ÙWP2!UiSӽȑI~;:.)@\sq7v\XޫjjjzmLIKcXkj}XX%u˖-r:8U]]Np8|ٲ.}Y.;7 0OLj%-t6Ξ=ZKƌf$555lu&h/%ܗᒦ9\*?}Z'@{<!ǣf t: @ s$dO_qq=fJoM].W O=, +S$3^.8ZOe<2)I+l;}'$})r_ݮo,Zx=/]wzm&âCbcԤsa 9dӧIvJ5D|g4~iY FМW|HRuf}(bO-p{7r\.R&L$ME7gdp_cۦI :4 B}?yJ:[bȽ=I_;ndJl.- Z/s{˽*vE:v4xy<~퉀_Om۶lul}lp[ ca#G&%iэK4v[ðkf\.IFiSӃ98^zs} QL9irBx2]ȑI*:{Bf'B dhJlx]~laMMMɒ"$5#}*Lq gp#: #Я dA7'zd#N<)aលAR΋A*)) 4}F]kq:uo\~s @"%zpH**$o KFVU?Za-V^Ḥ_ESaaaΌ&ss0㷷'Ij5u tZ9M#ǎt8}ZgjĈ^:IRىdLM!O bK~:YLS I`zzzئAo}'ztc\ZRNNr:[;:#cǯ(}bz'Ǎ5`_"ڏo?J6ljjju@?=צO(5PުC;QR(ުY;Wvh:,ߝoP=3l=r^PشWͣkP@g?uwɕ;A|d瑥-r$eNн3Ie~pȐ!$S,u1(x< F&hܹ^jk9+-?#~""#5,!!,744#FpWPRpzz*˵]!_Q(vp7L/7c K/lmxI9T~krm/֝\TR_Ivb4Q۳ͷ/V4.))d|nO[ux_;QR ̀uiJ l۪3gya%ɘ_Vn[1;lΜ^ݡ\P(F vTuu ֬#GŏLJȑlU~;Hԝ;RIPUUWS钞5 hǎr:׊S̎)&i=۳UUY^mg̔$o\|H?_4JMÇ7/OK/C;z0sJe\)IZzyYl۪!3Vm֣};F~z=x(h^{V@O>\vvOk p+>^=ֻbJ@lIfXdZ!ozÇFR&[n둍pj'۬{A}墩*>z[˖i֭r:ZCڸA7wi[̊b7:LuJ~-y`~c/X׋NSYYYԦOT?_7mvxLͿ^ 4~Dc;so^`nxJ񊌌ԧR7F666*9eƎOwrqm~Kʖuzb׮]4 s!6MZ5#Ǝu3H{wj*KiSrzG.Xxf̼HGV>pwd4.q AE1eUWȑI-`ffGyéW<'? >NSW$Ϳz% ѽfJ᪪lL˾ڏlwA`ghF=$cnd7O\*;*WYiLmpi1˖y1BguNSWxݟ7y_nnݪ 6]F I_]HkezgᇼZ; IlI1;N[Zw_>2PߺߜvU zS&L7OXesSOz˵k%I%өwg!y^4Z"tPϸ4^f\xu爂mFبPO/ x%IKH7bIZYYY*))Ȥ$~q0|⎰w< ULlFRd fgd: !pW-~⋕O++UVZ ǍSssy3HR`fqOQMM\Z?W^];}M(g:-6I*i'wڥ'NȑtEDD>+/WՙJe|r/R%-% 5;{󖞞C[nUIIwM]s0ںQt0HNNִt-Ў\> qj7O|o;msƌ~Y@V+s!nͽb^ O? ҦNk)'URRot^}`toI *))ю*˽$cOsԼt,h}%%%J\7cLٺ߼iͿ^z{vwܔ ZZ ss'sΫ)arr֭[&INNlsNXZM@Crjr<.1yQUUVٲek^\bciGn?wz1UUVjۦtw:eC{PFdO05-M#FT'10A͊l6չ\''KYyݲmJI .Pl\qРIϥo+w$Ķ̐t'ڱckjarwcZkݮs.>-+Sccf̜HM3=SF/D/!hگYF]PQ:߀ի7/O1n>k8pXW;_Ӿ={ڵk}&7CիWkkv6<$Z:moh6F,\`A($Ptdo4y1sf̜53HLoo9ed޼ nqOώ\=쳒_ߧ'V|쨶ggX  vڀ f@,vjŝ=;}]ζ7oK/Ǭ3ǯ*;6 -r󼝀VuY}=}{l|76NNNvrcX} y1P]6Sr1evlmVYi_w}~}{xP{Dc LL?==] sDpqqQodE*`;y%$Np/I%%%ޥ^9g S~;L@ޙ JKܯοEuuT{yle̞l$"ӷkeLu٧?D f[cƌӤI5r(EFFYN#@~>*,YWUY'*neddh׽rC^,UUUzgUQVi_F6#m6bbcРc:Y\r݊#puƔ6ΨI7No1I)b9~>)F7ut:%IlΜ^2ӗ~jժ`kHvZOիWf{(nݰJ20#G&iэK;_k^v0'MvʻjoQ)K}VJ($5M K/֪UBvZ%uiߞ=?WkO%Uuoe)uv7AQi.W_s\5fLȣL_ݲ0p,Ue$iER0)Rt}g 3={,p㭷vX&JKN̘9K+?F"g!)=O~ iDϟQFRtX:)u0!U#f})#z{[zWt\Ni̘1o-YѣG^Pxdyy=#"tO/KW^#F^6]vMᆱӧNOUS]%w[Q1*IG(95USMSԉB_%$$(^imZB~}-M~?QRP[j{Vu{xT(8_~/[.MC|29eeeiT|H?*ӛoi4[Ţ>O{oXo_>+p85Hn@(PߺgIEEE6Qdr`}\R:So5ޞ;U_W]R@Vk^EՍUޑAF@3]ր,9Nco|mxIL(!ׯ׵X:m^$#Usi"yx\P=)VX]uUڲeァ͞sjBDEĨA555]B4{.䋊οGjjnŋK.8tRҏ%5fIɔn&=_z5;rD3f9_wUUY5Z_sU^^ccGcGugYWϛ8`-VwhyQ~F@؆b>n:9[֪}߆uuz9{w4dbON֊;6;6{kBuչ!o{?︳߅4i)10<J-K澺]9۶zuiVVcCeL1o΀k~PP Xg\؏_Q4DYwkv`]q92OpEEy.tOp8+Y\]fߞ=Ȥ +%O_Ϳ<ͺ+_mIjhh9k-#i?SzyW\|ꁟT;Z~>q(^tij7$EGG3f bN}Q;ӧN裏T[]v***JWu]8f&ۭs\:t}*:} _Ќ3H?$َ32zV){R5 ؒ%K^xAǎ8t귏> 333+t&Q q9/=+Earj52)ɻk{4x$};熸xoRGTVZo6p8|ٲ@/%HC_sv47o(VzWre~͂\2\^ކ:rzuw>3J0ǿtEEy7uu߳[,x'(s ЁtjՒ,3f/v={Kff޳KB׮]dN.w~?τҍWScϘnC 6JRttl6~?'٧1c{9~J{<=JnI_|vnf]QaEDD-5)Stt/W]F-Cܹsf fIOŶ!IeM7,noٷ9쒾g:~zR߰^66S!4ΚfTLw6u;hPf6v\Lxۼi:׾$$oSzRڿ,Xc+AN|HKm[z;Z[O2:g|1P?n٢tUUVj*x|^ogz{e\yuڵkuh຺|gIo%?'8p@ءÇ뿡QCCCv ɓ'o rr{HW.SAݽ ~_5kjjkبS'KHy<y<nn577nеHw};vGUc)V-3[p~)uV3wnjOӤ=䷷L٣~Qhߨ δ~Xrr7pjv;0+5]tFWK:DP}]v~z׭SueTT{@/-w/eԓ= ;uO_`^}`ۗEOQq@Of@? C+*ʽyfpWGӏ3FGA_X:sW+@h~z9`󦍽rhmv*>^ e%'';Y,պ>X_?Ho4ovQشi4%-]3.\ڶtLL<误֮Ѧ֥]iݓʨCIZ"0lޖZ!@/ 7װa?_>F)>wGƆ}KstJN?l٢?ρ>jD.5*]VVd4Brrl٢<=3ڑGS~X(Z{-A>Z/.l^q~4ҦNS\\\Pԓm~hժ`孽-?3>}{\ <0?|ۼiwUVy{,^%kkvrw0E-6f_|g00|.JOe_҈֊?uK]a{-ʒiL)~i%vK_x[/[`c!|Įzu_t+Zqr:ڼ%%+>^]}k~O˟6xd;R~u胃luB~.Y$-8OF СCum+Ԛ5kWY͚r8 ۭ:M9Njw^-\[e``ȑ() Ƒ;C{m loxcbc2i.JO3fjΝڽ5Iȫά(u῵2}6IƨdeeeiTQ^er6rdf̜z|Ͻ%h`;rjhGnrw޼Vy۸Nf0xɒP*>N Z릛t:[jkT߸x͸lRRR۬sٙ%!vum٠U>mt`K$ IT|(?**ʵ]˗-9WWWkGn!SN{>i/&6VǎUDZ+BkxN -{ O=r-qI~vm(uU!n\4CL'މNIFe˼$~ vK.Whs`WMU\\tӼͩ.pgcozji5,xuKPì[-:7m_3f9sWUY]\<Х m& \[n{mm3PʄTLHՌ4c,lqpht:rm,jUOܲEWl=KgB/̘;_S6O; 12s 4 Ut^KjhWA;:̡[y睚932R $mPAJ$@4/딑g{N=^Kr~𾾺5_W햤PF@ Py+!pUe8*+-UՙR3&ԵEpFF\ߧk*clӥ6CS|~kw _3W__H9ݷnɻُVTyN?fgd(99Y 3z \Zvzu\J0ACZ["~SOիWkT|(`X彾1=5uON˵™0~Gt}릛TVZ] t)p84-=] &%o V[|N={I*>v{bu-%ukzuG (@|PuWݥU6CG9w੗I֣o>(دs3\`{N~#x?fPzo$1B?}F/O~ׯA^񆭂`?5k QEErmU|xLNNּyTTOÆi@Umh]|tLJR|={vʼnF:IOɘn$%%nЮ7ЩS賡w[vRQ5t:*eB&x*m2!UWf̼\"LJȤQrjUYY)@=-=]Ӧ7g~\.wગ1]ZRRRl}zI%}ڢiF.iI3ذa׿.H'N>ҵ^u,=ؼiw wݭX5yź'4y,2*+-U\\!|Ҡk=eX+[3>s2w{|2I"ܴ%iLm]֤v8ڲeL'!/)VяbζA<+[Yg۳gNI뱖)cF#N|νҨۃsS|P%R~FKjv=A5J-_}hckY斕_?6i.Yw`{ZZ] IZ`?1:믿^?Ɡ,\Rvߦ@:Xޑ+[sשλ4ap|#NwP^1 ~Ie_nt[gd4l UV-Iyy^ۺQB`XlٶUk^M*j) TL֝M\\Vyf̜e;Osڵ޺p`A!zcw|M߰=VXsuإBU_Wjswݩ`ᵡ^KFk: ZךWmTxwiGd44>Vvnݳ*))ю\]`^OKߺ4.I92Q';瀪ʠ=42)o'%f:Z'ies@"/^=Ci]Ky{zgXCZ9 uMr=k\& rHQM66HZu{$_2Bm2 VR-E :}pjkZ3ݸDzR[n)gy7,[wkUxvk@I6FOxzzQ]]KF#4V^k,bW+N,ɻoEy8相xͽ*徺];v S))@8W_yEW즧ˑ I1`,_H烣PA@z9 HK{M\[_3Pzz޳JƬg%8_p[xbڽ59r~R&xRr-%U,5I2:dI͖KޞdR*Cj\7yD8zfȤ$4?U4 dLWe˖AK/ %''{3ʊ`ׇ](A` \PoX߮`brr֯_OO?QftNNݺ^aQ:!իe|_SٱHE땕لuXF$1p*KՒKR=E Zl$o^X|V|ρ}%h׃Dp"ӷnO쌌`;ld8I bJ0ϾPkx):T$css{  2F~MF (gwHwIi~eb~֋9K(clJ-:댌5! 4=[{pHNNVfff}6Ъni+a7?zD_vq}Gc~瀥fϿ+%v 5,vt0gD?]`cK}wau]⡖:ҪevY/B>_ V;$]+c6IaX0zHF?gD?£]․ޣGoz]d('#`W!c풚5 )E"s`L A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A g<#ш$tEr,(IXqZlj 5q}QU&[L"'8fd AϣJNHA8 Dqm 5B?}[RyTjusʹs#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#lYZVITtG%ې J|0b]^4pk˛].咞UE^紤I:[ NoX/NKi?Œe$aPI/@֫^6Kj [ UJڿljIR >iIO '庹z9:胼m;;p x=x `n"HϽĮ$cAF+T Gy+1Oo3|Aa(@ @y L+}-eՑѡXϱUƂV@&T{u]o]j^ i-~_H?H̉b%Y&m#@p__~1I ~αECdhf/{YyIߊ5'hw:;(o+nUHё6u @' #<{6HGxfeuY> ^MMM2(vZ"hL/}ELFVMMM$O}KZsE[*L<P਌$0[@ @Ƒ=Qcn5U"bH`iIx0K~/# Qܪ\ּ>u_X {nؾ=#cA-V_@z|3VdzKV[vK.bբ?$gGbgۿ?-_kW}#á_fEb1)*I5֫f%{Jz߲~G٪g?~x䴗hg)4 v7ߌuYOd?ϻyOIb7$I˿e_?͛~*aȼ_8&[?%mqBO*Z*Z ҕx<5풮0;(--:x$5Ϩ8xl6tU~J?I}'$wFѼI2 +J**m*xi/QEIjVWD˺>ox_?$X@'y f,I*sV$}o,v]d,0Ql#B=(~s}|3I}g-rX fx׀*ڴt0 Wh꺰Eb$ XSu[`ΝfX7SX.>2ccU:*Zk5N"|DȰGܬ@RYoollud4IqYc+J___X[AO `VμbEi{a-zt5#Gbݭ 57o~Ieuip6mv~5 2gE»zm L?e$3: ';:$).*+YQ1!6Fa߾}$$-( ɾ6 MWٳ/'OƺgA[#}  sls/0޷%) 6F,L0wSkC~A>&v|5w'v. d_In|LV۷O v%?H!ף^_or37~u.]&Zmv9+}գK(w2orh7P@Cfk3p؅vl̥H4v]]H^d[l`*U"#V d@Y`뾌L,03{33,~"Vd IN7s:7) HgpZ^2#}}lzg<``7Y  3HgVܲkvf{}=O.3=ś[@ @fVPqOXyao&3΁ L ܶD|% @' :QsI ?yͦ_[ys.9𽾞 \1ۿP|L j7-F[`[?RG>ow>VO 2<𣿻opoӥ.$BckʏOՓ@v+sVDlo2M@ t5҇ym ukIFQг7kƿ/}Ǽ?n[vϦZعaܸܸfӯi]'? -Б^=#?yI_tL_4-Dً 2ڷmK}I}+P?xŦK=%.xMf$@8vc>6"م\uIuQb.蚱Kc&`Ǹ |1m}tmzZ$nC;EܶDp?V~|R?Ӆ|}qۖL%~cI>@gByrL]<4C@!6JLige,zƂ^O'tw~9hOUiI`F6>U U;EW\m(G8}%}UF"Hp!q[Ƣq2x̛+׫wG^e566j޽rI${9u@OY) !Kfx<ڹsU_W%sgng⦤ݫ'}۬ow.Wu[䴗ˏ=)|?bhܲϚN}i/pE"6{ f}R﷬bI~=dݱ%}k~N.mKkݫ'#^x!OBk;%zm:֦/>fl Ή [vNׁf%MhWۦ%cUH b>r?|799ɻ]E>h|z<Tm 3/;|YپUw~nm޼Yn[jkS|@N侍P>'xniοrՖ-cu{{C}DB?|}գV^K Wfy.)uyOY$ %.9?;::;1au]Rg:']Sjiݻ ݑk@ )/hї{L~_v]Wnw xo:/dMܻwo"-Hza5T+EPǣi>,sVhn?a;Β83 6_+}kϞ=b6Z}2'~}XWmjjjJ_Q H@?,CuEGOhz vCI}AQ׼Q$AևU9FL/|(--ܻ7%}44K:b! JJh083jQDO '6ηb,x&oŅw^=R2IA+f>Z̭+\EvޝHkDdkp'4*f[J訌_(DO 7,xovcGGv)Hn-vKQEb]VuOI-{S-R0~__WtMZwǖ N{\k?. MIdXe58߯IҖz}v_ݲoֲ%Wһee}ڼysK GoIcݡњ z|3Z(˹7–oSEIVWg}E˗Nj!̹[=Usnxd$]*w=>~\L8СxaoźI/W m^YyfJ=xBCrD EB,[Qd("d[!\ŞDxŇ4IX@?c-ӂbWBpF]*(R5 =fۣ@%ͅ*ۭ_fFI/GbjV9 ec`2wJ3{aϿ8Qv]?M9%"{}=:xf$h ?nL}ޔe =fgJw;?w׫)]}PD'/r9QFwk4++Y}fEKv:Tц'T ?kՆu)MX޽[;ouYs<8~f}}K.{I/Z}n=%i,j\P/yD=>.-}*(J1>&)wMX!F57@r-2{6묻-}u^vYcݬ{JΗD /:qvqI\ =tۓcho{ZNpkWq_ZZkeɸOxߴo~~9%=%e Uy .-٪cu-ݹޤ;A9+TZ.)577СCZ.u0 j4Uo_:1ko{}=\NGO'?Q /*"f].%ef8'inn$լz`V۾IӵWK ʪTPVr"L\ku-:kS"<[%풑-O~_dX@eUZRH[Th4WEsǹA]W=Yk\V2zksk38ϰcgccC f"0P{O$'g/[x#9.ϫ/HĆ=x<~U$fS&r]~2Εfx<:!IVz$VsVL\,3b|Vvg·wHS;`̝9$Ra0l_$pCV\ ~!7{I:f2Ǿw×3+0zd޴<{kN_q̃(¸l*2 }M/Jk@o̗3$?mY-JJR=7nkyJmvVy2PEkVD36Z[lͷ~*ZO{Dɔ50gwL9c⪺wqTOhjlGs{J5*hF2Ix<:X |ӱz*Z!W -/Z)Wኔ^\(u"0N5֫{JGڴuV ,4p- b?l ]2]Iӑ69MD`,` =UBer.*hEҭd%_`@BȜ3MIFxL+u&ObC~IR-/\!͞8%X7󷿤rMlxE ZV6Й6I E^""8ky==hwuqׂD\Q)Dwi[}}~^$2a(տ{("d.T2:Ң}}i/QX(ZEQ×u}lDޡY]+sVX-c% XgV̬5]P=#_ksʉ03|MMV ~iQFd]K'OZMwB{1ʜrKR3WgߙZ`:H qkWAhR#Us.1:t\ͤc;|Y'OJT3t>(J ?j%Ă׾oZ1f*Q"bIƂk^_zճ $M-Y5"SliU`,ŗN:H9 . ~y<hwmy&H[Z֑n ݽ˅k'Y`/*sޞPK'P=ϩ≨ qݧ^_ڎHK‡Dקfni ׂd WXʜzbNZ}c:Gլ\h9N;|Y]SIs[.+MhF(".V}JFZxIՕKdk."I;a;d޷ƵV\/n-HF*4V欰#ѹ.xaCmU(I=yzk|ͮ;ݫU#%_`J4w*+)}RZĚvܹ^I-(U3tӢ:x-(Nd777ka1f`̞+1*Za=w:{*_`@=:ۮU(062Cli՝MzZm7f((+O'KX &=1lG˖+c1]J\kUZk$|/6]bxߑd켝si"URW={x'2<$v^jVOjt渮ؽzAk|w]yGgR\+Tj}\4wUn']<,mvx<΂,gZ .ikScccX'Lk <02 |}*1E˹l?ݒG4>oJ;"TGg=X 3PEPD'F5+W /=uKҚO1[=fMX@-(^ gnCf&’a'ZJ=PTߴ Kiӥ OHR `AɎXwfZ ,~ܹS;w [7]te8 hes5;,:F{6cV1Gpq̃]J/`]N(ٚok}T]U.s'%bM=[mmX]vm1 caI0) R,3EO'0}pHx >fr[:v=31w,/\e =[m}+zat' l&†T{O."_fw.4663RBv&@eQ{Ok"/0`-KqG4r]>W{߲v7'¹H|xΞ9"Sǣitܰ8W؅vka:]|aɟxׂ}SOxou^$?6<3!7ۥod%eY?ҢFI?XNg,#1 "-zwޞ)X\U3 vYx?MEs2YGOZc>6)] bȵ5τ] \KJ}`ӥGWAFp8cǎnq$fX'Y ?@pE'_ X;N28v]Tkwq4|\ g4ۥQIdE}̮إ8מ={$ WnfW§+Us0 Vь]D`XKWJ%I$9Fml ΁B\kr$6I̓mpgr-^S.ȊkuZT.mat!^ Q4("lMohdVgߙ,6t'ݳt.dO?qxmj)hllϙ+DseȘ_쎲RYb{#lPU(@Uiߏz{4%[VaEM|p.naX'8޵ H=H̓kAWvYGO gkz^1v mf--;T֫ʵVn)}JMsdI2v򖮒$b_o~+t+Lg>LU({z-ΫoꟚOI 4z9xb.TtƒYz-cc&T+ 3[ZP6mX]g}όlfP/r#j`ӳ*?aQD'lm rI;>G .PNa2L,]K>V3cJ L nȾDCtMk?t 2=40ӅE[>*kIX,XCScx<ޙ(gk{L1q-Yhկ)$GO e[8f={n;-;͝eiM^11t?|y7HTb{7}oH]_Zk{wk5Wb'qv3sΐB+bKN] ) ?f$_ikvDjl3v̴T4' s'ݷsZ_}RVˍ~^lЍL.~;_djPw?Px&dYesiϋ*/xd$@5;bO/zmq զ3l~͠ n,v]uwl T}6k DbiIG#|!zF @?lM  b.j^Z@{g$Ƨ(7إX$i ve |J q5/ollT__;_2U`ͯ4"D7&Fu&\ga9yc$|wY-gv-Ӿ}$Iߙh)+3y1wnׂY{-XP첮1T"|!2 ("`Ʋ%Q1^rK@ك1Ȭ_ngdp`NwߑkIw?9{ Obʙ~E]<֦#mmb2S XvzWW埓$tzP@2STQ~_e լZ2զ3gGzݦ3kIVUXׂya(lI5 }}}ڷ$Eʬ_\•yEUeP>U\ŶB~<eUK*V~ߓ|ܰ:Η)V䮗鋞 ug1Ʋm'{0H:NdZaŔDjә6ѮauF+W+g}Z_qWC_͒yp{" ?"2#jn6+JbL>͝`ҧvٴ,^9Ͽ~?yx1޵ʵVN{I'dN 4'_BG5,Ot(v 4gh'd(DO`˂װ5 }}}:"i>sn] JVvO WjyJu^^"ͮWW.UE^~,kjHFδ5ק230o eVZ_sKCV|PlHGmLſ-;T2xsɽU؅vI*tgq'qHͶ#/&yK%؋BՒ2 %o~ *ڸObsQ5+]cBe z$ ]kӢu7=~.?8]yu -\_/]KD72#Ç[ׂxFLLN,L] ̹k>fWk:/{]O<v-Pk\>>|8x/ghU. (" :\.# xowu_BON悪^RŪWױ ?:.$kQyEKb%j!ǓPDmh[ĹqvJY\C=5sa `3~_jcAZQ~ "9`Q(5+׫ Rr9 Jٗw-ة"FҫSn ?R1 n8f-z&N"E^2+tqGkUJ'̚AWo^' y*m*-Ȋ Oi" Ҽ 2mpB;%\VUTK去t/ҧZC=HNsl;rDQ鋈}VfM-VU.s=KʵTmZ\KJj0M[;MqƒacZ܉i-=FVTޮfzLc7q)W`$=gzh1>kKD&tmp3,0/0š;Ҫ FƆ#:BDQ-4<{S (" UssH_{W=d,vޞŒXe.L_\fW`,`-򸖔OY6[SOX |➅)(Iz$vsQZF[sٽҕk}rhUQ+ײgm^bMO̶6FuK^pB0gU _ Ahevׇ́i_去n)+)04B"Јgc?w2cijQ9žTt:ۮ΋'"$ic]6u.jUErk}gِ(@?\'#2}"E_D&0kWEۖH}jܓZII۞||B$i- /&"bj}JƂY;dbpnpQAɓI̓X-c=&§d$̤1^/5k$U~^y/ji&vw'@sc&dɶ_kWqX#ʏO B.}__@]cmOd[]l$B$ [²F6{s ("`&2\s'6k$cz%y/%ғ돎t{&GKæNO@-s*j.b}4:CyݥCNlH OL 勝+`uև.dj!mDZg*|(x3{au({0-|k掳kT0$k}sR 0$ɴ_֫g^R`,vL5LՓ{ }tmL ݢX@5֧M0_w.\~-x]as7 tcbniQD'LL̝sNv5+Vw?FLZI =qIRkwKX;0v^^"ͮ$- &Y1Dy_bB S|h7;]pO /0Wϼ$_`pfW2 䘎!cЮoi.0aݘd,zJSI(0v{Mżg# ˏ@2E 23fX@wT?޴?mK }IӚk/02sehϖkmywܬ: Q?5 }otGz^pCиn[b䘾 iY>F%M-z^͂@REPǂ O>4Ti' {jFo@U{a.mö́p ̴#}\Lx-M]Sݍ>ܸHgdlHT0:X]mdw@J҅`luqx\Qؓĵ^&nBaͅ$(("  `Ir.J<"dTm}%ғ_^lV[)&Ƃ;`3?s:ѓ O!pqG$ !i!h -함g] ߵu_$|FexWJu_XTa7J:H,N콫gXW"ׂ] kAg]!#cޚ?%i͛_%Tvϙ ޘ2w3z}~}uf;]ݖ -qSsHߤh @?&w&0EDiEb{rF%ʏO҇y$բnkf[\UŮ9FδkU~ɪT^4D[|"B3jE Xp-dݕ yEF,8yRڵh1}l;%qc~ 4:~Ō̠hnPD'fsLǓ $R_=_|^򢏵`[4w/\n,\M \dF@s ?@6˺$ھ%hUZ+Iǝ[6=s\6ߋHU .ɴ?\Le-SM'B vGe.w\1 < ~kɿfӥd٭9<07'xY8nHfbFMNG&@QD'@|smJIhRYDP6x!O%x!OjZ(IY~ퟍED` !f뵹d&&>8S֭8Xs,Hd|$z9:=o&f<o2wQS\f~-0QXW%Z0$[`zr[B"ݡċy LUh"yΞe4@7m ?H\&G!TuKp6I"η~O蚱X@Y]ʿx2U>fAIBWv,~&F^jmd,XOQ,i-:#}\ MƜ 4@]I^'%V yi]/4CڬL)e(oL%J2v=mvm#BM?fxʵ6$Xh|Of&as]d8q3 P@?&+{*fkH]D Ṷ-_\dsokj?._QY &#-زp禾߳O_~xCܢstc d[\k/@ۿ0jKЏRͮJ}K2;}>? :alsvݺsP`, ͞0)n Pjp*s*nKSٸUUl UG{QSSSE`yPnNvtVvdZN^U:=ZIݽ_t!j) QD2; .rUqȎ =QC7m5Oס2aoH¸-ӹ WhgVu_-3i/і/}5/)gC\0[x*ѺZPGUQP@|V^|m:W=7k~ӦW\(p@c~?26?6xan|y/GLUB|[]SQU>^enլLPɞ[}XPq,HsB-2v¸VnN3Ώu%V!V͊L H\kUб޷ճa@>ӯ߾yԬZ5dv?"rZ/l?Pc+|+kHׂR'bMs.N}i/ѣ' y.;De U.sϨgҢš kӥE1秊rN`CCukAp<{ _gkAh'?q'+>Éܭ\QnaeGpKKhKXB@O [eCGޱ}ۧ^_z}=BL20wm,~& P{Fw"0e债0D~m$@2-V &=:V>>4'H뒚#ݰy& =e%2զӜ[axװ.)Z_Վ$I#cNޮx8=yDPظO'Ɇygm~Ў;ܬs~7%%wn2s 3sWU= RV?pE#cw˳úaFtz H`*c4^蹪vk{y b] ;+͞6f;:1kT!]Z_ ihe+yi "{ ?H-K^Ǐ!,M/[."&+ѪT%Xl>$-٪Ϻo'X]ZZʬ=^t$@2-j+*%>0P{O$SU7-z.sKüf2 "$kÇBWXB&JyD_- *(ʚn:v0@(" ]%7iӽ)engGOڵ3_%?Y $+Cv(0PiiiyHilW:ѡ_v~̶LjY\8ԣWB9ɺ܅c9Bٛ7m }Q{nܹS.kc'd&w*f N{Iؙ|m$ݳ>_:$IeUY/I=g2SC@?-^E[ܵKGQkw$2xsG[xB-/=K3nL߃E<<{aVu^Oܽ{w8t=vޭ/>z16虘vzy$iYw$߳q/p$ɋбe+͛6i]mNvtXt4ς<0 b=Y4Ҫ"Zg̶$$\t5;  MPD$Mpy'wwrΗ6#Εc11 -yd^ ^_e~^ AtH7n+h.Psޜ]  5+]6>5ϨIn;Ch)GetIwD,?UcB OXEP9;=n0 zc"({ ̯t@W=?qvYz.~i_§LX@yɸ}IOS7d`2*5;Ěr;?CH|tv튕LLvGEꙗ QPOϾ8#ﵾy1#e?eGn(--US (# mp$[ұ S?#ek!MQDϞeb$wln"eakA1iO~5_Uoq=cWff+DW 9+T}H0^vܻi3r]-_U}V λ+D֏Hc?X=Qy&ؾ]ӚkA&VWbUQ_:\` rv\ ?f*? _Sbf?vYT3 L;}g^z$IMHJKKmy:<(--PթsgZ= }?'GA>xKd\7/v~ C=cwݻ>,ed pyl%]VϋC=8d (ru\GE@  ecxPҗp8CvMf"=a&#=y^>%7G3f0`̤$]7>O~ٖ<,%zTZZtm$Bk>VYwϣ`GyHZBHAHd 9zs$fQU?(g{ r:?dg:;#~$!e3ZV.3z}=a_N\zJ~-} . $M^5[guyO)C^-:gbX甆 k?:0ofe-bZ h;?UJ:mpD`'l?|A-/[O] lˍ8 ru\ `5(Fbv_NIjOb_fk&yp:ڍfpד.s:;}z楜JiwB(f<E{J-Vhk\kzk޷n疆\< y]͋ ?@6%HL{Z!l hJ^ɉy~JSo73Iݸj j΋'=H_ +~X!*ȉ񟿨𦱟Avžw-ػwvl.I:v]쵒0 o&ϵ؅vIҪ '$sw:$yo/$O t(wfx =_ߠp87ߴ~:/w~l%=ax/[>OXW>ŶBĨ ʪ§1.$g6LŸK'sGZjiMj;My:E\pX+ƿrݼ6WMc,(--e'i{8bh+jcZZĥ7f,;4yty@ дn( O'}2~~#8ڝvޭu(٫*Zm({PN{I'ޞ0cSU*wܥI K2O<~Ƙ4H #<ȰN`vmZW[FP{O:/Ж;mp{}=:%IK.Xl n)kח$9K]vQPNz)V7 vimi $QPNzﬤr7P?mJ y&;qB{㌹UkjVڞ0]Wւ#IgҡC;;p91̅.)r8e.)#uc?@s ?@6ʛOZ/@yGGu^k*Ul.FۭݻwGg"bIF VH6{yE~7g^ro:Vv^@t_tis#o-,%#ENmvݹ^U.svy/QaDzžV ugql8c9*9a|."ΘXc;tٚ]r-1 h-vJ҂;jd&-MїEI-˪zI =??t(ٝ2<ᝰ%=#%dßX3]`z}=`OYRK}C=rWTl2 !5d풤9q"ml(b$~Ms6k=T *<-Z\U kӕ7dKf$O~Z L߼l  qvdy䦿9,/+Ix<:|NvtDLj0lG2{앵ZRM =OSSǺ LLlO';:qzXD쿤#}QOL%KV΢f@IZ< lVCH[vx<:&ٳ֙]N7mD" y)Kwcb}￯--rP[\T+؅vM sc Z뒤;v0JsPAY}WvʉȷʶBh3Z0 t/])[;=nPD?v]+Z<@}^kǼ3mE 7rwy=KOqOp8“»vIV$-}=,?U%;%-Ctn+yڼysn[&P]ʷ=>[ZЎ;-1-iLмDjѡ--Zd[2:=%Pvb6jD`Xa2XNJSǼ=>|-v[b֊ou]l(XOkG("񃺭z|ƜaE:59:B rwz!şyӄ}Yh<~*7sNYg'f83oE65Y??tH_~1=Zd`8fםjrK$IޡY:r~~Pd́jmAg-FmvUlkW4_9ߝ7$I /0y͠^.,+),e1o/iKѢ~6ٳGKm{Q 7>sT^b V|C*eMwjKy?71?9&?nPq@|PS YѾ.̣iݬ)=^Ɏ,VƧ&7]?Jؾ]zͰ8n[rn&9+I0[&?lIau^mWkʜ*sVfzmrd;Ғȏ<9eq$ӳC+o^dWd y{fMj׸+}RYhpMԘ@ .9n_fohKCw֡C*迤&5jtĘq v]URY'kvb\+ܬ/>;85 k8<'5t$Ma:59O Q>8wh?<eb&;e~CF~VfYݻ#u8CSIYgeffx.)uyOIk~N|O_LLƿR090?7Zpg?g~J(^G;gt߰Vjk7 @#m{Qs~m{*T'A&-Mc~iwh= <@nɿ~A f2\zAF~WM<6ͪfMbG=(vO)UuZ\U5/|Kf+Qy&555;'*jll83it䦝66+K?Vǿ?k#]KW`ӳ7g;?9[bIuFy<,ٱ<46Mp!QQ555v:566ZuϤ6Ѱ2wm޴Izkl,g6|̷ ybJHF٭Z -tUd8&Y6X,--v~%F返" 9[RD_CEP|ZO`qú-@Nh7Yg-]imF[t MD<1U#]g&7=>,ߺc+Pm~~6o2c8֦d˴cZc3R{/fb%Xo/T͊}>Vj Ɋ:6Fi l:vPWC]i#]aZoJס6?90;#+v3$4'/vmd={goujŴ's)B*GSt=i,6k"0*lN#&H㼤HF^??th*b]2=&$5⿜8AI 2Θ>/n}3Ұ|h;XuyOY~8>'>8߼?n٬%6]W[o>ѬW$ F{siFȆ7=|pyOuL3]x{eZudBJ}^tk|ϫŲ}fju7̻Lj8~2:Σ\:7e,,hwr'pт;j2FG46Dá&%bX??9?*(JיZa[W`,xB؊nz߱cNkWV&MuuIF{^0}(^c0X1o/YujjjJd$^X׺:d4ClzVyKWl_DGڭ BٖW["0d9ut^R>I >힧=6[@bp+EIlebIxZq~~萶KnqVbLxz䯹&/ijo$onM9k5๨xqk]P{O~kjص+JKKհk !ؾ=ld&Έ{'5ViiH,7q@;1銅:B2OׇD~ёt P F{4ۥ@IOZn-ZQ/+iZF8f+ 48 #a E) 0wW{NM\TgZDkڮR)^PXOdܟ`:7ب--6KW%<]Μ^T Uo]_ZZݻw']TҊɎޡcJ2vQ巋s 狧%V1vƚ1{b.94Ōvt#nzMڽ{wAI?u8ryvQ 5(o*M+`wY^a򊖦zF@8Ƽ= ס g4y}X7=ZPޢB[%qiLx冷ww膷G>oI,YFœ9cvQKCl|:fTΙxt49:b9D^X=tp&k.$QPV|{|z  r8Z\wݪ].L1o|VlO(q@ItkJ>} 2pa?/ m ̎$󖮒D??o*gF5:ba7&HgHWzSURB$xt%^6I% iw ?pkllݻ%eyQ1gNk* 5ڝ6oڤO:ܩ>;?cȋa_R ]wh oRsS}5NN/sF"_p' ۭCeky5tՄ~񡇴m۶Js)i/rTy{Pɣߵ[ Raho|@{!4g&{KƉisZ$]w(`1@CC[Bgmy ភ&eWK>|lV$ner[v]e z ף+qvC-UQ_Fnߏ{w20ZuKTrʊ+*\a\QU$cܻ7^roP2 ڹs~va#Zpn_5Z7 !Ey G,c2--jl4~vMO&XiXsNiksKCR-GQK֘tPUX|MMaG3b)$c |A*Epؿ*U@nE9o~ٳG 8$?ΰk :muj [ =aw:ݿr6{y+0Z9 OE}n끲:լZM_/tX˒{k%נw 3R!MfL)8^Hعf7cwe-(n޴I{M53Mzwttk;w'jf?byTҗ:F/fmxBE<Г2g6~PeΊR{OuCO]`U@g摛g&c%08^OTPҕ*lu.]?Jq ;>Y$Rz\֜$) }^G+oꁲ&%fz= Wk;w{W3_LB_UoʵV,뛕׌; M`;555Y:5\nʵV|[VYb8|-+s;g}ۣƦj/GF`QzIk%iKep22";~:֝/_?Mb>ejK<ط:;ɢ85i+v7ߔDpg|$0_$9nWs2ͣ$cAߜ nx[~<&U4ծWAyIeIP׹ݖ\0_#a_?0NcJjV=R"U2Z)Ul$۷/]˃_32$UuYu?)hgp5#% X|?NF^ΘO\Zk&>bY}(|MJKKu"0FC ̫2O?1;cNj"0,$fW[巆J(I/Go@u.Z/);щ`:i0j$ݿrʵVN{~j}3zN{*gikujFK@3KvCy&M6偲:kGɖ1qZF|;-P}V- |I* bxsG/{ߑ3Ya %? 3H]om؉/6%l:jؿ^/H9ѡڴ<șv+63$)aŌh޽{gۿ?mv9+}գւf8-oe!pX [Z$pbtt63xvMלƮ2×u'` iw;@:f@Y(zb$BQ={pK]pG _ɡ!f2کNӑNб ؅|vi}͞g  Q%ir{%It>q€0Dhwjjj{gX,v3]Tby]=ϋ5Ɖi\&>85'5#Ihhh՟. mSuKKK(iYp3< H,hwڱ}YGHt9[Q&/`ɛ]bB"_TK_+懘 ]c1 u@,#9입J,G,ŊS$IeW' jص+ߡP?y1E~HDD-`PF 6jn ^^k|1\~J}~&lt0*kM `r@$?R[d) )s(@ `d $tyk0OtHrbr-!ܗkV$Z@@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90#H@  90gd[+&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`B{v 0_iL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0`BL`  0!&0 IENDB`tiled-1.0.3/examples/sticker-knight/ui/000077500000000000000000000000001315121121300177635ustar00rootroot00000000000000tiled-1.0.3/examples/sticker-knight/ui/backgroundSet.png000066400000000000000000000276561315121121300233040ustar00rootroot00000000000000PNG  IHDR@( pHYs.#.#x?v OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F$IDATxOi~o±,.!=CmC5S.d| >uq $.C3!z ė~c|t-'B-g^vYlΡJ4G#Mwu=b5 3U$0 ɤfŴUՑMUX/Ud> 0lOJ<4Ud6_ e4Uuh$^hZUw 2p4/ull0N@$@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @pL& g hhhhhhhhhhhhh\3;ggg?db"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@!0N' cCRe5 @" !^d21 #3/{ew)Ƈ[/.n6_WU5mpWUz7/jZ+ۢjguSU?.朝 lytgU=|qTU7/vVUe]?n_kl+'7q;Iz?o.Z{nsze3A=>2oio<'Gn>ݭ~3sck[UnuzoewǮ_~t ]TՍC7B@L&5/>}aUh ͗:vU{mjˡ{zSU\!U=6qГ<^:@hF%[ׯ%Pm^voZ265fPPe9Y/[C{>C0[4^v'h.~Mp}w hT%пH `6'W55@ @ к3\60 VՇ-gx6Cp>C?i6Wsaع?_:_?Gy,߬VUo烪,6z쯝Q=|Uzp_XU_]U7.6~~pگRU___{ ߨ/TZ=Z__U?u ߬;UUՏKyٹjU~rUVU|㗰_o~gzq |!|FUn'MU^aj AZzϹ~2o{i*V5~?QY?S!fUQUۇt?Wm^v6wz}8/>C^Q[ߟ]o/7fn_:SүXoxnwq~;py`ênjS#?5ӟzyOs/~`GUe%dG68Wv\~AU}#lhADz >wl:R ؿ?yzWU40Qegjگ|z:>_e齖޳;-wL&ϗ_rASU{?sj{wG]ϼQUSۗy]~ОpYfœ:2zٝգzb$^zG^ڎlWVΗw7j]#@@@@@@@@@@@@!ݙL&hh'@ժYUdž$T-8g/vTUSCz?g^ l83 /u}r~WC#uew0`k{0z}TU #ٙY|YcԈSCR kcz#-ؕ A>ଗ0\8pTg؃ze$"rЉ x`^h^v{?; go&Mccӈc_ lpأ|د,a hz#i|fyig[yqvB^?nSb/ 妱i|‰z]U-#z0guW>^ck%6*Aj տ~ױ_m꺵Jk4lWco[+bIGz ^U:7Og)4s=4֏.>ZY fb*⸪ޭna^F7UuAUugd{Uy|U`x,X4|89#xu%f5{TU7jQÌpsbpklin>s<5:Tö!Q%_EUUU8u#VUW{ؙVοl壚 h˯˧vgӪ-vߩwlP)ШM㨪40{hjewL`_Zȵ' hT% hhhhhh\3>j>TսgUh<"ʦvU4Gewg;F@{^v#ra#y}k GsTl9o5pz٭ C51|qTUOo]|mf ׏jSUY/7ب;Un#wdn q,F|M}ڈgUUiϪףvCua2th84]f~=065 F  .} тSC@#V/콍7MIN[>0ʵjG,J4z87};|Lr?;f[U]BOjωZwNz}qH!Q#wwq\Ƴ >ǍSSzmnkgdh4uXUզ0MڎL!#{pT5|O9}v+udN"#د7Uuѻmz_mq2 >o]jw{ڶ`6_EF^5۪Q-gœ|Y ׇL24i7iT;ic{#SΗgUgUڅ|9*|S\3oM w@ @ @ @ @ @ @p 6Ǽ]/rv\U7Go拷^߹mpAUaO_|Z/sllxa&V L@cgOKVuKT^L-qUc>| #hhhhhhhhhhhhhhhhhhhhhhh )mL'm0m6Um,[A8c>1hh|0ڬa]x]Мl83 444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444get IENDB`tiled-1.0.3/examples/sticker-knight/ui/block.png000066400000000000000000000054561315121121300215750ustar00rootroot00000000000000PNG  IHDR@@% pHYs.#.#x?v OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FYIDATx1 004juЬq>O:t;IENDB`tiled-1.0.3/examples/sticker-knight/ui/buttonHelp.png000066400000000000000000000126431315121121300226230ustar00rootroot00000000000000PNG  IHDR@Llx pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F IDATxmlO ):a=7,63/KB`r,5DV@PkGIαU+q%2gZ P(onowo}ܮ3i_nv3.Dt qB@(5& M.QI$ IvgN0I Wõuuo@`N-F"p(J U/T#Hr I> (GO[lӤgOر7#4[L9Tam2}wrQNz⩫CjK޳]9t5+71Uxs1:ʿ֪][`97 l_+pϞ~OIFأ'}QNI;U[w~t:l^'Qĺ Iq,U;m6'5#ߣbEꘪ8A-~mE7M%ѿ?"-$;? G/%1vΒЪZTZ"+R3D~}0({F[`6<:N~8 ҝN\7Ưg\2Bmi mWog,+9+_Ji?FReee90zCe PXX5IO)kޜ^eWۄ&!lL  iqSs_TT)Z%і,xHD`.*YlKMu ?z[wuv~D`Ocaa}Y 0vWͩE rF8U =K`u#/%3/a̾y8@M͆ a @B,{<)kJ|ӮYBCt{oD$kKT:dd#j|hmרǣCB<˴8jKSI zvb D"H=cl[ D)`8#^,nF#NcQQBp풗hB#.ytj[ˣfz=%x,{ !&e-(( @=К3COo_IKN\>Ad#p\OL0BRNxsvOz (//_ oz磄D"iv/ydݫBNŐRb, R.l3/-sg8Bn{&I)M{)Oao\OB|h.]*?{n'8~y0'/ R^K)z!m_!x<kv'?N@ũ6V@ 9o*rp45HrJKqϝ'c:։= FnLG~$\^geBL 0J2cL)qA'|cx Ÿ8K38~0a }>657 !,/ aLu`1@6z# %.Ji9oW^ fw9@1B~ˣ ?xAq` 3{s>1P4 Cx?,y@,X10//1~[ &@˫U IENDB`tiled-1.0.3/examples/sticker-knight/ui/buttonStart.png000066400000000000000000000130351315121121300230240ustar00rootroot00000000000000PNG  IHDR@Llx pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F HIDATx]mh^PΞs&1ú )~nE{Fh0kE4ȢF4FcMbTIA1PWy=sggkgIra>2yyg !pp}R!#`y\%,a"(UJ/k@)m?Ī4B%%IB 4n: /rpGÏZ&ׂ ^T_SQ֟ r 6VU!"JJq~@E"_cLl̙3?vXtCVW$D$B/v^'EM%^pO,!K#+R 䰇͇ Pqy1,_( Hh rTXTacUUZ;sF"Y[eIVl rTV?$"j9+ٟO["jePp2y ׅ89J6@&kEEOzW&7< L~j@Ž ?V/$ U 3 Q`jaE rD3gتwch/hLžSP;M[3/]^~pvZҹ]8;rM\gvn4=~Wl#SުWFcQ`So= |zf79q.=O:fd9Dtay≻Mg3b绰fPQ/kkǭ9Bfh: Ta򅶒?<#5I22\)3@A3AIÿu!.^!$]!B kA-ͧw[0tN bAUNǟq1cuM}\sn߂ͧwkޟ+7BBm]] Gr(rT#KN)שLBlxCnnn ]n8o:[N:Dkc(?w5 VН; kBTǖMd֟IQ(H .:K.^=VSx"_MI3c5 ڮ*Nݵ{rssuE '0==) I0%3#}8E_2`ruX}t6-s)M(=V>ѯ;&I?bGJ|P]]J!<<6: k۶JmۚB25+#ӻSUW@-PU9 77WZ"0C~(++KzG؉u ~fS 9Dh_+a`4@ @@,Gqm[*@ʊҞ:*(m`& (E`D~6~?g3JFYhm>em eg-u{8u8[lp#RzN!x?2=c]S2W4ouDu*S[`vh. dF @(M`g9> ~!d`ע~K"*h>>aQhg`BBF-=ٹ襷}<,ʠ%cֶmM/3 ~3טQ`v^]+cB(zMa^Ԯtijo~' H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxQJ`e!8@C B \EIfx}-R]H3Vx>Tڥ4os]t,Ct,\u uڦ4rY}Ywp??˺eMi&8RRop@(+a [;}Yݬp>/sl u_7nLzm_7 >\χWz#ԗCWxK:4~J>:Cw1B@m }6CAC@(? i0a>r@Qrrte1}Ǿ?L<@~ 1nUArou e3 A!@_{,@Dn,ڍBKaVmJ37 ">t].K $";? ÝV.|u;/6E B@)o+ @@@0ti!+=pKi.8hb .|4Ј}ݸ/k P FA @z r@) hmS kB@H9_ tp熀x/ W@mJP&_wrC10\w e+mL.v)ͻ\޴}tp ȇDt,۾nڡxߥ4o ]R}8x{siQ.ഋ~7t g ~;^h๕/>er=s4mT4ae SW`ζ6Ź)|kD =m_֧إ4|sjG쇺:SE>!7O$ |1o [?~8C+إ4woix d!M}vd׍{$8H`(h4\9Y/<\.V9@\N]\pp 8dps/r8v h\N  @^, Y@Y/<| 84{K@$pI@)ז=ئ4sӯz1rYpSئ4|(t`o+8 < i1 KijvQ@4~+69_Y'^ ۔fx"t Ch ,i!+C_!l38efP/ye>E4s߯_!{0٧~[B.i`Om_&z ar+C0Q8[t\}nakrY_^m6s7 pzuaL/{IENDB`tiled-1.0.3/examples/sticker-knight/ui/gem.png000066400000000000000000000076031315121121300212470ustar00rootroot00000000000000PNG  IHDR@@iq pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxK#I 00MFz뽊4fd(͈  -<yq΃=-}˞9.*Ӊѭ#TwW}ޯ{g@@@1)U*JJ P)=/V._I@JCE?qxTJR у;&\&$^L>^v{}unK)Q)}ШpsIk",c/Ji)ePRJR\7/4*OU/wN}EvN[q^s />^Nz=|*@T*uY['t.oH63c8 nW[t0r=Gw+>#jgR' ly7@2XeX_o9v\eF>c18)0M;cߦ6v} (BaTG;nOꓱ SL=Jz͵*3F9hP">bHQ23BDyTΏ%ױ3i_@c@BQV_D$yҽ]aAE5s΅BXsD'C W̳NJ}%'C5;kS (9D_׎YW }^&)g @!LQRBr1kN M,JV0ߢbрw~BT*'|mm#2:Gf3W[C%\M 6QRD;{IPz E(nCJl84TQh\bdVwxK~Mn&N14 JiԻgD&tTԜoodDϬ4+Gų=14WxLEq>!`7`7Wg z՚ߓa pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxOHYǿ& (tBZ`]4^j=ԓJK/-lŋx{hozfY^*.4$+%#(,C^8y37ї1oyyv| }_ PB PB PB PB PB PB PB PB  :::*~m0F0(d-j4A6CʟwIoӡAFc\|/f CGUi,[,Ca<S W$#?]CU"LBP*Ap$f 2!ۍ@!@0zeUcա&VT~V?(@}S;df0vzD3@Q}`Lhj8qʧ) ,&h

ǎ>)Wcȟ4:LWj2i 7> %eaL}JUK|HiD &^,} pe[I$`T!,ɥs YY-6)@J 5y\?٨4Ĥܞ=u]ah\6hxg3mi䗑dq$ PB PB PB PB PB PB PB PB o} [\M}rIENDB`tiled-1.0.3/examples/sticker-knight/ui/helpBackground.png000066400000000000000000001355721315121121300234360ustar00rootroot00000000000000PNG  IHDR6Y pHYs  8[iTXtXML:com.adobe.xmp 2016-11-14T09:25:33-07:00 2016-12-07T10:19:30-07:00 2016-12-07T10:19:30-07:00 Adobe Photoshop CC 2017 (Macintosh) image/png 3 xmp.iid:fae26f8f-acd4-4211-909a-09b8611bc043 xmp.did:fae26f8f-acd4-4211-909a-09b8611bc043 xmp.did:fae26f8f-acd4-4211-909a-09b8611bc043 saved xmp.iid:fae26f8f-acd4-4211-909a-09b8611bc043 2016-12-07T10:19:30-07:00 Adobe Photoshop CC 2017 (Macintosh) / 1 720000/10000 720000/10000 2 65535 416 416 0 cHRMz%u0`:o_FIDATxgp\י  4BH9 9(Y%ےl+3=z޹9̇;wnՙ:~;mIdklQHR bI#bшFݽϯJ%ؽ{zQAA KE@AA$@AADAA AADA$@A AAA$@AÍ>0~.[YQ\NEJ??xX>c<vv߂a~B͈ b2pq0Ф[t{r`UAD>yRD$)K$@X>EuEaDQ;E׽[tUWW ZeLC1 k!^TpüHA2X[0`b Cn7 cyD`bv'!LC%B b`71DY bEH0{}55A-B`_="DD1CE_VH f0+B$@A$Bh$ w"8( bEHF,𫪪{"b5#0$AAR꺶#\ATA3O4c;0kտ|PH=U3A?m2nEH#@ć bk!L2V  #Y?AUUWv+*--5RUA"0q~!ڈJ{`A< lcoD R! ! bDh]MD(""xD({L! ! bj'B$@A"|i"DDq$0m4UVW?KDALfU bDjEhNPA"03uދ"!j >^PGs$_ TsA$BfA3-'I Do3Q ~vHD8A8 M_(.7GPo0kS%B fD @#YAA \&$@̺^\qA$B#@ H#xDɸ{R\qAٌ0{lǡФEQ$ A!=4{If! !B*@<ϟ( <; 6Dt0Lnz  8mc7xy u AC&B\(˲qa~0LeeV If{0rV[~@Z? |~  a!|E(B /$z۳\o#xEAdZGg3"-{ɝ`mEtfSHBD(g@2 S0 Mxo"͑VSS}qb+ٹ~FF7E8qo~';~O;Ol'4D|~1}Ս.] 7PE|v!N+NeXG7"4;ڊhp9 Zy݃SE<%'HѸҏCW#+F{a[O ߊ)|ݞFSxCG Nq` -(|#e'0F{:C"BJ3I|'.7IB[Olq0(;؟%u.)3eMa M*9m4<=yTŊ޷i(>WOv& <.yRUVW?;̈eQ3o:G 0ab< ?"5x ,6؂w Hsj`1ꆽ#KnуeF|1Me3b%#i$E `3kJM72:P8ͤn$ 0Ye'K\<^)a%=1ea'"a7Sn>Vd5@Yc"Qd1C*'u;c:"O `Y@߻l1_4.qxyaƤ3, #aQN"wz1_pf5K |> z~.\o1:_fzJ v9`0\o5'Oav7bv= FnD@e%[n2h-4;j[N"TkXƒZX'n\AW^Aqz7.6۫TB"V6c1h\=JںC5Wlc{^E< ,5br/*1̦B ^VNHKv ?Y' z ] ;D_TĚl[\1l0V92/`4+aJӋq8X6gyAOn[:OAv7ikEu&txt&_*hRĝ)w{g/ !6UAbf^zcvSd3,L֡[j̾/{G)~U7/M`|v/\Rib"pX%`QuQ_G,pf]mjXnfxJ$dW@q,pCE l_ AV3 ]@230VvX.M(VV=8:s_^ Žy%V"~s4~|.6d,DQηqqĒ~yO9,xx Ձv ) eQ_1r=܇Gqf N>}YhqM<,?Khʹu3B.r˺?K< rC@YuuHq.V\oQ:FҠH$[:d]G0a00XU_ŇaYDlTXԥ\ ?3|Uf@CkJs}4IT,wtz)(t u<)5+ @_ʟ$}u[eE=X73%S[,K=.bg_jz?~fs}6Fm=Љyv%{X{δU\~v3zRY;lLv}vy^#0 ,gv3I= ~y pxaC5 )a/6jT;9l^䀯ؚ{ϷaӢRهWw J]Hh8uعBm򠺠ڀ=3y,sDb,1bwC%tF=!2 -3*xqS,Ӽ7+=u'qß!S"h ͇LxQ/}%ySpN :Mh ..—W#Wgܨy jJx|Y^ "APoƮe^\nO7[:O ضN3_ xd|p0KR2-@^׫-,6zT{Yf[eN3,& 4fKhlčF<ʇXZVR[ÖEeu,Kj,ȷt^+j F=$a< [_\Sˠk^{$I?āswAꋤXLZi+@vsjU" \ feܩbANprz n8.CӼJ*6xQ=+dd`p}mVolnnȽRڑ#xHJg8wgʷq3jpv"":ĒZ#v.ŝd݇i1̅5 NIc6r`12HeXLz͂}6e @43Oqy <_ n kQ8,|j(iKrVAq;*!Z*WeGs9+>R^E]xu[ԉUN̫t>4m|_cgGǚu4>\h6L}BJ2-E &bớ*(Ғ/k`>*]IajFT/wy}F5`gg:uQ96.T_~ *eTEsIɳuo9 t v֪S.w &=]]P˜ gzx}vH= &fK"MC":;*Qlެn5^RXA<͏vPs n"Ʉ'@$I3pꓵi5+jV-'uz.RqJ"]1TZZj!~*$ Fm5鰠 P0?LpxzRɸ=9{Ry F>>W7HqҚ(ܥ4g>bS]HY0V3p\-AƢag3FMiHvQ;ۋ2IvOW֞. 񞼿81U(3 ȷ:KkM,o`kEEP[PUMRq 6{ &8܏@~<7 p""3Pϭh~]6# [ff5%[J:<\p{fu%]l͢lJ,v0xq/4Jj_QvÙ :~ԃO{Oa#^XQIcs,شl *zl\P:SGm\Ŋ٦kNŇe=k<2j(;^ru@oXn XSp9Z^_DJJ`N>~ݝwԕٰmbfŧ6<_-< PG}HWSe6R׶uFR<̫Y [+۽p; ^RպIUBm.رbD-+BU#[[YpaԬ(k& <\Q:EVϯ,5Exyk رԉǗq$.ớ+(%u&<V|I6וKY ϬZ#ZYYP٬cˋ2A<Υ`qX> aɆ2xa֤~İtLO8 3Lz ϋ5|HaA ji,;z@@.1ic_|*P2?qT(u5!ɣq7o,?V7⳼ <4Z9e!L~W4B[(4Lvz|ɜQ¿--rCA,ȹ兩ɝ(>8 Fւx H$*\,vxw^=rNӷ{qMf>KS0{00(b6.hM8ṷ4brXM_ bN˜^i$NC^y6Tť: ]O4n<ԆswH@[_x`g`/ X7B"ԥ{W(>}b ';W HA'|}~E}3H,ěa ~@0$Yd.Nv R)m|D7<3 ^Ib2X;> ͑6\lJ[k7W7/m>(œoDW8qߵ<4G mKӮLM ^wEvhB,i> f(~-t>Ϩ$&g "1:=JW5cXz5e/Wr3>%kZ-8l^hS|wm3ϭ-}`9tM%u8VXxaMp9Vd5h'yȯ-BRi`clo\}PTiC$ңv (H]ǖ΍e.v8iu[+YYp }g:1܌K*p.1w6xQ0Lkmb)NǖUhn{\nwHqAV#E~ǻa1ԕmw *d薯_ 'QYlAOzѱn%ZI |nmjJ =$xU%FS? k@j#|T'ښBSQ,ݧ jgs39,T%³=^hi?3 JKLߨٮX/p⺹Ғ X)_mN g.#!ʿ!# o@"t0CUL iIl3Vީ[ufrM@_4dā~ՍKX3Ǔxc\┴s`G5iK< Tmq4X #-lu ^V[p@%Qfj ٱz"D}U?GToXp7dڏgVWm+Wa3DZ;O %U)8x%dZ#_^ 䍘,;ZF߈~r>$|f_oZ'&C?.;IbQ3c3shxx6-J`;Oq`p %p/D{5H֡ŋrXx!} k;zS3=VXU7= YW8^n|d_T;'a+Ͳ'6C5pQO>ZL"4:! |5+ͬNh"Rf)y,7r9(B" ,)u(u9׺X?Y5s=`ɢ)Uf~i nK E^tX\.w*3R/8Nݔ{Z,>V#H>f?-J_iIނӚO?aҳX5]Pm9,m#{0gGEqBUIU6ߜ ս=t 0!߂+5wB8Ct3t}Bmڲڧ+bavIY;a/n,C}cg|%V\hR:K*p`v]E"z;0ʩ] ۏXfpKW4I >u\NE %GMG@]u8Mb--3/fA8;EjM'z6?l¯lɫlrxRd?ނFx5έ#]=k<*"Q 8Gm_>YY][Vj0(rs(2uxzpOj<ϴuعB#@Ksi6/,V jSXZ'E]eH{&U7Ys*C\z:Mpٕ],<(F0[[Q<[ 85czVxqu6=@Р;jswqIJj=g5,+1|ފǖ"7zp23YT{̙THMY@y] ?e[8qC;:Ԏmm3[Ϻ0YDED:YMJ>lKp(y.Kne坢s&XSy\d̸u*ku5~2^4y'bd- fZΫ&c}@ɓɦmvd]Du(NWy&,q /"BS?Vחhw˚%8y"=X;/1%<\Sg<& UaSU{p08vEiuUpkDRv N5$6 `C!d9VV̻ LT.uP 7cv(,/NoUݸNZHN(9~CvJ4 Ɓ`<ֈG*>?RU>l[\>Ѓhf<9>u,qM(j> {Tn^]88qOE JuW2[F;39F3`i=c7箣lR} MA]z]?L̔kGk?$@ĸ0"ajל)f=g]k6spٌTe7)BS[M:,*g^CuFbi*ǻl8vo Ŧ$K)v`M4b_)pp1:yGE 2aw f 9Uiб7U\R# rTGu(s5.=r;LiiN2!kq9B:b,V AݗLcH$GgXst 2b@Av7TO5uO]mFcGEyݠ ^<]oK!8W׵a{Nj:jlh;3z$ƛ ykNENѯ=C/㣳0XS"u3>Հ}hდhW}gDĕ>8َ[yF(n"Lppw@~486]QdJp;r݆"DCų M#}@5B|pǮwɝV)?mJ"дNEm=!s^cG_\v Lebo"h{_\ ལmuu5jޓ %&nTN{􀱴-w]Qfvc,5疽s^w:u' ^p 8=%NaMAB9tXbq,%Y ܸx7Dh}i9f1$WcA]+#}q|r\oO#jF$.nҢQgZ~sa)~t_<:;W~慥h I VX=7hjF" X+mZ.5K7G0;6#V(Rp9 ~ $^l_f̈́Lt5!٥l/\'ǝ`3/_Z'| ]tDd;| Q")Dя.e Y/ep4o?j(ZMRVG0$V V-;$daC1nv-bIQE4ftZūqm^X5N=\vʠ?,F坂0H͈nʛO V:bˌo+,ga-+BQfТ#[[lIz'aY ϬZ#Z`xxmŬ,kZJ4xbE%v71EVϯxβ:B>MbI ϮiдN[2RZNMUBm>ر"繕<vKv K\pe\d橆I̮У8:k \YY]qt?bXGolaVүH& Pd3d(p&;{L͛_*=l x &ҝ.uŠ-xiN@Iީ WFBt" 8ah,҆LE?zGNe. F-։Mpt $s-O~I:McF &8XOv3O_XwkE0c]^'>g`nWDIJF*r|+:L&C{H8 de,+Om@g2XulAc1'Bu5nˠ•b_}DbMCxP=6̚7ޏX Rj?$@t :y7}cˊ&hF[)2 P*y<jplZV3CWJ~Fր)d`Ҧjލ+-1;txlYz2ʉX;3loAP!"Ŷ%ضwf3:# H   " H   "    H    H   " S  ~:) (H iͬ1̯H i჋"I@$@AĴ ߀ A1%n#_A›'Q?@DAL979\ϐAɡ{@ A1"4f6OGz T^I"p0 A1-9J5 A1%|pQ@ 2^X?ӱ%" &"dI ~ ʵ t!{/I4ӡ؈@d~D, {F̄'ťjlXZ8_ƪz}gښl^hdž,\&~DQ<4S bJI|~1Ŷ8t5+- *c^XLzt\Qۗ5c b"s[P0;G:恶^< `ikJBpv/nJڅkmITTC\6ǽ7Nr0F5 1%İLbRClloA\2.pCp8r-'Ogcro"ʘp'Q&,F zm?O㣳4w}.s.ck7_ue)Mi:;ɁFQ󧣭|?Gk@ĤI@,"_R'; \Gq0RPuٌx}G5Vϱ;|X,.7d D.Ħ4ӝo${m!#"&eMjB;_^lރeur9`(io%Eb)iLp9ر`+DD\AY;Ct,ֈW)> "s; C w(7sQad7"|\pĤXPeC?0E5\nl s{4eDqF  om@,O?Y0fb/II@v-¨{ަc,t+}G*/ڑp}.VY<>9  t;ܸ+7w Oga gw$Gh0ꁍ X3dʁx8wDLvVM*PH@<ІKq={n8 1o 8 +A𫃭yE*@]EVn<E63nգyw:-yr9}B8|~1Xz|wv4% ,qJ礖`c~3̞B?KDL*ěT(;Gǥ{0gע8qgvs2 XɴPp_G"O,zExxP6B[ ߲|?GAČ#)|Q3,Fߒ Yn-j|PG"ϟd~8qE7KMR^U\{5֕*)zSx -5s=he0X#Lf{1{I˲?:Y@} Ԯ* 7  (E &$ D~ab$.iUGA'*yHSKPC7X?ZxaI O|i5 NSFLe<@<8::{MDw JҔczPWrY| *;TNqr;LiiNkШA%}6>*V Id@eEf;f=i% *kcҙͷI yTZ 1\pČԩ,4i)#4()`m2 05̒m3jX{]ƿoGc{xBsZBѬ|RET~)-Do '4'&{r5h푞1耺2ۈ˸Kt ||)^W9t $MQ#~Hٳ0|"f |E8y#'mzE?AmxR~GAoXF)zex BoØ]nGiY$ںӈxX:46iL7jJC"a^L(Γ q8ND>{,7.ލ!Zy;G{_iN:d Jmv |㏺ª")$ q7($^l_ZP9ۇ2nau5 #D8F֌Ap5h&jx 6-,N,>r9D[$ UwpC\Ŋ1QtYسSdǥz๵̫TqٌfjkJjKuxby}b\˰ٹ̉%raķ7#s%L/1b҂! 8xey`>"凑@DHJxmGjK%0gVcҊ6X5X1&M*Ql^TAWݬGۂpX7bY;w'VTbwKTde: 9ttvre۫PWӱֈom}I/ue= |cU1Vkr˕oXv*Y9mkZJ- a1N+6y13ŃQ`~xmgl8hYY]t?bXGolaV/bHe7˜1?X.FȬMTZ1t8 'Q2Q7zI l^DzE1i\[+bI,PCEhnkmio-TTLȜjq~AQǢmV@|#fÈ3RYhM|-IOC`|)@]UUՖ#" &l00  A1mu` b~l?!" l} 6*%" bH iC-axZ bZP#tH"q6 8} ?z/ Ij#{")h{_!]-\mI~>mmf|NU_j1ndɛ yiܥP! sAjk85x$ UeUn;?ޡIW_݅ۗsv_h-ہt'Otʾہ$n#P8fΦ!+*)Ngp5. _\C30Ɲ`BN`;UpvT{Mﳣ71w粝>Ru;Ѝq{F*|'"cwg-c.N i};Ŧ0_Wy_?Nv|i~.?X\ϑ{gm?WI>mmf|f1u6VuXcl Dƍd3]*'Vx<8\pb*>Hۇ;r]׽A/ۈ|%zXL I}D?:0;YL &{M( u}pMf@xpܩk4^)OY:<72Bָ&񤈻8|%.wUj2TC$}:f{F'E}#_jG=w^yP]eKM?ru]q[bN~Rwmm2f|FܔX5i &>}6ē>\k,gawCsݲ"ۉ&ߢD}zgټg)k'b#^_9,kK7q(n) sR7RN{<)Dc߸ʤ׈"8/wWi\{jyzvU4c@l11x}{^^%,,*|9UuOo^XwFBw7௟zXP䂛;.5ΉRQQ/B֔Z5'@I2ن^26P4j3 q_ }4?ԲVU6,z-L jVfk"sҺ0}J -N|֡?< 5{zT~s&+?7Ԓ]T- jו,}ʾ8u xƂZe-g>&盾p IpN#,*ESҿH>'E||'oeQ1*G9]%B)_e*ΡPV$ 8;ʗWzrM=o@<)v  aeks.7M#@>MOw[7]gGKHlYT@^}2z c/ Pǖd`e/ビL JpbKj)F=#Rv@uvϨgF&v 9bP }%Xc\goGa2*sT3FΤ 3| È׷WBS'nOwTMYs2m~FɓNvō}@!g.52S#__^͒L+SB'$3l^R@EZ͒=+߫'cq(uiWHI>^̪6ѭZPLnPڿO(ru4u7FtB7UgH n0gǏwhNLQ)우߷w\vٝ}ڊcx+yO,̭TfshGqr?sfHO:0|EUqW[Hq_tO[ |brzw׽=k' t8|Y jAQ /&LꜲExm r#QSYlֆTߎc8v29W[[4yiώo-}zX.o-{u ]-. v<.Z z﫠\lzsE?:\pY]^q\_W1f^ˊLk ē",&F-r>8ٍ/Y<}вͻFhkM>:oOʧ{_)5Vzl+>aAf.߰a>\[i(7_Qi5V8Lj8g&yoR6hgA}Ajih6Y{|%z+0 gYS:teQ.-W_^[[*{Mά;tعteP5*\Pe҆N9yեawT al.cOVhϩ\muׄǜ #l̮N#eol?+{гr=Klg#qw1 ,f[uPG_B$QPSobǞH w:c(sǽ(=m7?ZGpj4fg}vͻsї@w8Uvo}aih +1TOٲ휾Zzmkʋl!_8w1$f[Gmc(|TYu<83d~aIk^--C%@A R @DAA$@AADAA AADA$@A AAA$@A AAA$@AADAA AADA$@A AAA$@A AAA$@AADAA AADA$@A AAA$@A AAA$@AAt" wQ{iNy^q7ecm8xy2Ny;ǕД}Ggon xz3/= RG!u":B);y``^ē"w`ϔ~/vܝೋ<7gz#I|xo11en'nZ]uÞxq9 ++Pl7MzZ}q|x*|ŖI89҉4K\98W/uG+P?=4ʊXl_AM:=sIRs?~ߏ^zH/GT;)`Vlov a5!i}r*swkKw$7ܝ4h 偎)LzTi^>&IQ٨vczfs=bi6|ݞ/~‰=yQB"+!R{<ݣxfIqOtkpRq0R`(1yvٌx}G5Vϱ;|XGҼ±4~s؏"pj߃:'"&AKC0MX3עVia " .&8SŢjNU$/[ B{T;GGxAD$kOxԏ$LRBR~ z`";h hX\[.ˌ+f9^|g3k3oG~~泍a|z$ֈ]˽0i_ Z:X\ce0tUcJG5v(V{Te;rS X2}띣`bb!k.>SR[VS{ɥwz7.6۫TB"V6c 3f9 wwG#Za$hlWǖ΍e.v8 n I⏧;1܌mq.1xk_NcNEi=v*ߟ',b|+.*Xufxr{yASb}u^n(A$C)*~ce9*<Έ^xZޓE`B'_?o<҃9^8؃wJ DpZ6hľ3]smؼ A<H]n<H`ߙN̫b2k(F[*u[7|R 4-v3`oty>,@4# ̗W8y#&?{%VU>Ҏ>JK v:` :skKH?"pټ7| X AV3 K&L*%A:"dzJ 40.V::4w =Nں[2'8уgV XX]>܆I[0VypW~ &D9'cpH1 DZhxx6-J`cf2""⪉ԏOχdN^׫jY( .gqN+fP9ݲzrڢr56vK;ds8x7׆q%)Op7"1}$;HWؾ4!`D[o+Z2uw7kE(|Rf4FHgs,_j^?5{_)c3Avt ?Xfnt $`ҳX5b`AX|uJ,>v3PW "9G<ɁeԔ% n읐,G,[AˌzU%VXM21I?C(V@d6Wa0ǫSoDw"K#{0g<;GE h !)M]4nP'VxaT@,N*3}rQ/&I|l2ښҬ9EiuHqήܖĶ"׃ -]<pXn6cr7Թzrpv/~{ 4 |$@3fjϋ"Ҽ7+=Άj23}{ ̚uru@e1ǖ"+ďwiQD'QK+4;V`29_T7֠L'to"euZW#]=kΩQ/J3j=;CgY!P2o10B;+=^E sB.qïERȮXLMוY5 @Lđk]p Ŏ܋O*EÄh ] y1M!.;#W&:hh"X^,rF]>O5`1&ՋeEzM0t+U~,EV,FG9͠J x=+WH <ÎĥǕՕIbL e!BS?_)pZâͿݬQϢL)WY֢L"zJriFP4=f-`|*K4g G!u.M׸h,obth hE?m-}"us8x% QNތV<DzE,aߙ<^5 )f>bPǬd34XDDиAǵVe0RILE:%v;z= ,q(Lp2Kr\^ǐI017ΈXZ^Sʲvb\Je?8VܝA\jnDN.QuЋAU7VTBj֣kPDf(hBÙ̱S=fn b)N^3 Dx΋a>sAf֎nVv*Ѡr)]dG Aҏ6ExfEUS2zR } mCLu͆Uy3jfhN@hDjxµuê'Ըh0. > X;˄4t0|o74޶U%|z1$Rx2q,hZ^XX@Nas>E8w[ ^9'5/F&xj1>sC_ _^3@2LVTN_0ᕭ8y7DziцLd2%akR4ѠWM}ɮsbgދT/ԈѠӸ\R0܎UEUnGU 1̆ڹVyp̹ؔ؂UJ=7O 46|ۉ5gu֝bܓ3H@}0D*=&2zXϮ.;G:J{׹qv 4 żJgAbNWri[/4`2tpr2-m~-v0ryXjg(K`upH8>1.80NrC2-fgv/lҸv.blSƽ&ò5b T*m+=blAUs a1I6yߓEɆzMyaq/~iRLRp.&vOD@-4?~hբIyD<܇4}MWUeF43goK+ūjEHrFEEFNxHe78BSpbi ta>yLr`;19!F݇Nd`sTjSn-$y,Ɂe4 NrӴ02V9I l:)2I7tJ2p[ i=vGM|I| yXfĎ,8{W XY732f䲑e&D"⓵VG yf@.qWܜ@c;=M|PK'|"1,4n7О @FG>̘|ˁ˽ÞtdNk6꥓kL * fGjR֞V@:uW[K~?{t9DoXD, t\w)-8t5^n- &9y H+:ƴuҼ(>aB1@eqk,pafp3 -QKGaD]6#^Qs,߰XGcTOWul$<BS9t ;}+OwLY/sɛ(%7V|ZA<ݣ/KqOtkpw<`t:PY#\Q6xA,/r Y[\79ZMzXZ1B]ٚ$/϶dzu= PV򍗅`6}eLN/xŦ|iU,Ԕ4h8: +b"Zܟ^wEvB,ɍiNvuœܰ~ ]S<|*A a~$nvp['WxP?d 83]n%e\;ֆ>cZ1I#v.٠/hBs,XL ~ Y~wViN1܏CHO>Z!_y2 zWqzN+=k*P5sXQbi' ʇŵEb?>{&q,zݡ63$Ԣ3[cRa> eN"S kXƒZ b)^ǖU:yY=8w'WUD=a PY#$hlWe.,scY ?)'XY?2Rmyi>]ō52;{'mĭ@GE`3J1܎A;ӅX X;׆ 4wdJ+6-,ñnolbk@22 X? TV\N cH?dR4%qtS͎oLv8 ϩ/JK v?u::>#ʻlB*n9rZK/u'ȮR pXē*kabxk e B<QiA5[V%+O%Uu!1ԭ^4.E;z_턦.mJmF6vKeۯL(7^oO R-߾;0BfsX ,W>EVl{#'@Bb?F@~W8ϯRtf=^!`!nU!/"\׃eEO*ƣS.c9W:nn-+9G<ɁVLjprP#rP]:0+i08`& pI{5K҉ە"Ńa _3u"iHz}^=¸6 ڀo俟#ŀHWg+3`h2~}MF[ZQK+4\Z Fuq\lV_fa1ۖs^VdeÝyPx'C7`qQԿ9Ds i^vu naT_G4RTJ'T"̯RK+PUb/ФK*pfo입Kwn_j&Kvfh}sZ8JY,e_== j>x=S=0j&3n_eG F gSb©HQk Ǐofn b)'oHpL`.*xuHZZȦXßћYQ]}jN@LYze{\ԐP-<]OKjXtr'Nߒ\G_^ aY_7RyTemd(n7ORrA)P{"mD͗W#8xE/8P)Ÿ&AӏLb|~0xVy;DjufPIgMR[,jhSbi*ǻjv>p)3c)j"~H"=jOe 87S!k՛OYV2Vwi7AUhvn?ㅩuMU.7W3mz_dޱ'=ŦUŠD3:v4y=ك/.yCAԕJ.Rٔ9w/. :0`9 ܃~Ab9T-:-JǽNPGC䨮Р( :/ZG=Gu >8cmhĥ~|x[\jGg }폦peufy&oV =)`(WяV4{c)NrfVQr"2} jp/S/'shV=ݎUhVJgu,m=1pV[ivD (Iyt-Ng"'7v^ h61 ŰepF)Nڔ'~4w)n~ǂ2esWF[㓳5Ȏۗ| ]R v<,dЕV?v,1b&Lc(s午m6n~>0 `tͨؾ$C.vrۙ#ţK6|k] 8qč݉ T\v,UUns5Qg-&Dއ2ZKnE+,&)B >>"U:c,U)Ոa'lr͎0JÞ[Z떅nW-̃QBfUf)ȂA}3}8zFN@ζLKZ|đ,v8Q ۂgV{- Qxb/l,5y5hFVϱȝ*۱[냯U Ҧ\'*">ۖ8X<-S?Oe7WMIe%Mpص‹ՒGD3.E9'˂"٪rLòzN XFb;95x:Ml>$R{V|fW†* Ȍ34(˞{6V :~ԃl0U< =+oݵ܋%R>E4fieчY=3WZ'7VPUo,^ܨǗW.9^ڨ<|qlFy)\?us`5ip Y,%dJ[S"/rޥSUbk;P[EرbXɠ6`B;TJ:H)YY], <ރs=dKkDkZ6/*ޫwVnC0xfu/qʂPZōiSKgÝ5c>fqM^^{HkZ-5XU_y`6J.ƕU)2رԉl!ڹZ^qgۗ:TC8f^` d[ұ ^+dRW׶W̙ukY&`I ?Q3rOUt,ol]RkTXLz|Ov#X ≟9rY`";[_5ue:7˖ &dQs}>_ uò[YJ0LHDw8R)(\v# o~"̫ܺtO@iA'rD)~D&Q4ڝH0OpEVð Ҝx=1z͇XL;bE8Lbk4"$imi%VɱU"h*mVȉ7&"6bN; yZ# ,Fݨ]3Qx5=b*ljlЍ,5嘍sM cLW"i/ľ3e9E%bYN$ jDX?= Atdm9{lYQAG=K MX1MSXK=UYt,T."{@$_IgqϏz, ~f&6Un\iءcF_[uH$,zۖc* )F|oK 8aG~x i Z! CALCA" v" 'DA1TZZj' 'AAA$@AADAA AADA$@A AAA$@A AAA$@AADAAĨyR " "3 ?QMOCALᄈzO~DQ# r=h'" &px~O A1nҺ_Az+[ۯGz 4^HOF{\pAĤ*1(1ºY@AĤ/{uv}" M6 dA>u>SgI qE{/ey=@ RwOeÅ (IJ?w< " f|eDvH idf fEIF㫩y T0xc zZ bZxc+Ut^ b=,&WWW bZ0OAŽ ^^#1,;fh6 A1irkl bp_{쪚 A1-,`ϸ‟|e$@AĴZV>~k= ԡvoI iA}T'ϒA:%4[0"" yB Aq!" H   " H   "    H    H   " H   "    H    H   " H   "    H    H   " H  ">( 0PTA$>(୓"ҿSeg9""Zx˾Ib^=}Z։flREeeev^?/ /gZ%P n6QAyd~Nkü0/u`>"I@^koi_bz* e!iGf(ݱl%N$2Vpki^LD^Ơ4hokۖ՜q YFWxࢀEiQY; »<4tva/1 S=U'<EçD$ĥ@ˤaf0+ z04m(Mmb404d7pH&DKR$T0+Aٽ;(j7abpQ~om2yFEAEO3ej1abԿhoo? Z{<2Rr bBz}{{zzzFy |% P C0."!b,ЛqR^//<}~(8^d1zt:]W{{{|/ʸ,cf2:W[@(///cYʓ $R`0 ¯|>Dz^ ϼ6lkZgrnDel$׻ \,bn]dZihfH$nF :;D pv0zPPUUey Nt/Dx y<2TFWxx^~?uJ:OL bZŌ  " H   "    H   " H wQ^ H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F%IDATxK[dV:ιw̌Ix,!啈(ABiy `AB,-ecwOUiA(ȪE?8oܛ38ڤmnƔ{= ȏF~?EQF u>0v 2ΑϝgWٕ-PUU7=c]cGEQF 䁱#G^Hn9'kxXI!K3|XMRK3zh}UUo #mK3:6VSiVr5Cﭚ53:N[HEQFcC BG Vjbc5Y;9v SV~е[N4b{y8 @]l6d͈$uxt+Ti|yLҦ P_/$Y5# p]b5VSR'}i8i~x\Z5 6 !x84>NF)h,۱9mx^NJ&_@ O `U=!L'r%+|zEEGz!!_8DD)7쁉+]B +p0o9Ve_x:~aPx ௭<рgo mD) {g࿣¿~X1QEɰ-3 Jm |3( VlX|くo缀EXJLE.Iܹ 7;>i6%'WQ(ن;WiF;% /+|yϐQBS i]wGC5 q^ 2aOޗ&mw[aaaЬR4^u ыrZzZ-EQ/-tw Tki+@ :Q8mt@j02B׳CDr (ʨ8}Pf)/Nv{IJӴBKz}*%#;Gt!la=:d}W sCMi._yuft,x2> suf10%`/!盢i`}E{2u4+ Gw% |/?ZvIENDB`tiled-1.0.3/examples/sticker-knight/ui/title.json000066400000000000000000000160111315121121300217760ustar00rootroot00000000000000{ "backgroundcolor":"#3b97d3", "height":26, "layers":[ { "draworder":"topdown", "height":26, "name":"background", "objects":[ { "gid":7, "height":262.666666666667, "id":11, "name":"", "rotation":0, "type":"", "visible":true, "width":1736, "x":-256, "y":920.666666666667 }, { "gid":6, "height":832, "id":34, "name":"", "rotation":0, "type":"", "visible":true, "width":1216, "x":122, "y":810 }], "opacity":1, "type":"objectgroup", "visible":true, "width":38, "x":0, "y":0 }, { "draworder":"topdown", "height":26, "name":"clouds", "objects":[ { "gid":8, "height":61.3333333333333, "id":14, "name":"", "rotation":0, "type":"", "visible":true, "width":184, "x":640, "y":320 }, { "gid":8, "height":61.3333333333333, "id":17, "name":"", "rotation":0, "type":"", "visible":true, "width":184, "x":336, "y":144 }, { "gid":8, "height":61.3333333333333, "id":21, "name":"", "rotation":0, "type":"", "visible":true, "width":192, "x":1024, "y":145 }, { "gid":2147483656, "height":61.3333333333333, "id":23, "name":"", "rotation":0, "type":"", "visible":true, "width":184, "x":44, "y":136 }, { "gid":6, "height":600, "id":8, "name":"", "rotation":0, "type":"", "visible":true, "width":954, "x":-226, "y":768 }, { "gid":2147483654, "height":546, "id":35, "name":"", "rotation":0, "type":"", "visible":true, "width":826, "x":710, "y":782 }, { "gid":2147483656, "height":103.333333333333, "id":36, "name":"", "rotation":0, "type":"", "visible":true, "width":284, "x":926, "y":307 }, { "gid":8, "height":103.333333333333, "id":37, "name":"", "rotation":0, "type":"", "visible":true, "width":284, "x":124, "y":353 }], "opacity":0.490000009536743, "type":"objectgroup", "visible":true, "width":38, "x":0, "y":0 }, { "draworder":"topdown", "height":38, "name":"title", "objects":[ { "gid":4, "height":386, "id":1, "name":"logo", "rotation":0, "type":"", "visible":true, "width":736, "x":256, "y":480 }], "opacity":1, "type":"objectgroup", "visible":true, "width":25, "x":0, "y":0 }, { "draworder":"topdown", "height":26, "name":"help", "objects":[ { "gid":3, "height":715.669407858419, "id":26, "name":"", "rotation":0, "type":"", "visible":true, "width":745.251573276788, "x":237.507948400548, "y":739.425850721188 }], "opacity":1, "type":"objectgroup", "visible":false, "width":38, "x":0, "y":0 }, { "draworder":"topdown", "height":38, "name":"buttons", "objects":[ { "gid":2, "height":85.3333333333333, "id":2, "name":"start", "rotation":0, "type":"", "visible":true, "width":256, "x":485, "y":655.333333333333 }, { "gid":1, "height":64, "id":3, "name":"help", "rotation":0, "type":"", "visible":true, "width":192, "x":515.599635905335, "y":761.206553703963 }], "opacity":1, "type":"objectgroup", "visible":true, "width":26, "x":0, "y":0 }], "nextobjectid":38, "orientation":"orthogonal", "renderorder":"right-down", "tileheight":32, "tilesets":[ { "columns":0, "firstgid":1, "margin":0, "name":"ui", "spacing":0, "tilecount":7, "tileheight":832, "tiles": { "0": { "image":"buttonHelp.png" }, "1": { "image":"buttonStart.png" }, "2": { "image":"helpBackground.png" }, "3": { "image":"title.png" }, "5": { "image":"backgroundSet.png" }, "6": { "image":"block.png" }, "7": { "image":"cloud.png" } }, "tilewidth":1232 }], "tilewidth":32, "version":1, "width":38 }tiled-1.0.3/examples/sticker-knight/ui/title.png000066400000000000000000000565051315121121300216250ustar00rootroot00000000000000PNG  IHDR pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FRpIDATx{XSgWv.HT!PV:8VNu<8C[/uF:vlT{:=uhZtiԑZŖ( \n\INB <ԋMbccF1(Z24pWx(?DDD 'IR`L7߾}[]d@nn{ === :S l6OP'ZP(ټysh\{ΝT^i$ ۞$IAppp_~`OlZ_IHHBH@ $IzܺuK6DFFJL&C$'IRjza${{{FcO{{ yqDѣOL0aH$ɔ' O6'_ꫯ'$$|e/zOVVFc;<={vSNN?@9lSݵFu:… [⦺; !(@P(o`/}2a= ܘ3/oژdɒܱFDp0m۶M]p[m `xxd0QXxҽe+QLIee[[=ˆD"̙37}Nx/N}tQ# E*)V:FfΜdLW_}>77=?yƻ349((M} ųHm=J=mMxxM6Nm(m۶6m:e"' ֢ӟOO[a{xx o>|~h܎o]0D7wQRR2o̙|}^l :d IO\]ckښT*WxB $Ouvv.;#f@PFIyy<%BA.BTQbG'NI5' fH$Jr8o'Wv/htojL(k ~F3 Nݹs!Ar|,Iт33%{lue$}ep{VIt$$'&@#W lm ScB!w(q W-*u+.*eY9h= @T?Tep V,%%eEyy<##jT UPR'lB+I32mw33 Vjٚ} 9 Hs淩D]vC kl^oWN6nXc9K}̀yP Gkm)10/9fw] 7 P(Ey2-|Eo-+<S~'3%&I4:89 )?e-uL4ݰmCA NahF˰tsmuuy$XDv/|Rum}N,w8T*v}Lmq!ܾK<BCCc\lgL;#ŀ cJxlC涿 lFo@_-.*| E I3`d2uPA$B'~˗/gXcp\FaN_W]Wk7SXBAe1 KAQLҭ7x\{/8FK͇m _hFk)1PB1Zm/qwe17w?[2svk:ೋh,]j32xbh*#\( Z <' Bw*X+#Xg/^S‹[Bkf=꣢68ol 5L!.@1 sa߿r $|eg'4SYOzc./?˽sPZĵ:mڶ>X?S0x`7Ez"~L$~BeՉR9'Q+&=,.fF5p`)v!(+R@4}I#aY5iN,s煆]Ҩ`$96V5O?wi_Œ;shMwK||~`Gy 4*e܃I7Or\ᔹ o[32Ν ̜Y #?+LD@ȹյ1A ozfIȳt;⷟Ûc9o]nXZd@ D1Zd !d X8AZiYs3vwQ15hzEs4 ޹s'Hr?={2g|4wՑzxi6lqSZ(~"X{>Zk.̤^F{Ӹ?=mAF~^,!!!0Xrw=iѣOЭ;tL ^ӉWNT}>~.~fM7Ҋ9wZ (E (cQL9,ZRY<e?{,K#ᕓ*8R-((hիWWێH,..h >'LN"yӥ*yd£e)~9>턏tXD0e|lX>НL^N;M1@jna@68Thh-fOrSw}4l[@TT.7nOW3 EL+|~NGk:,د͇9Rw-t68h9nTIU5j)1}Qm ڔ'?S)[8IH]g}+%h k@* hcuV`v{ oֻ SbBiwHm_2SY\\3l`F-cX`_G7'el ۽VP1DʥBaj{v=>X>aPذz@KwS~l=gRsMİ7,@-@~}?}?eWpdn*`755 $ss:ڣ X,%x@ߍ9©?}O9OξrحvW>DLLܺk7|EBk&+$ՠN {!PRs7iy`n>k gWxǓA˅Ǖ:Ahہlv5:x"j\[!7Lɹ2`Ey7.ШQά?d{т`9R6z_NY 0uwtBή8ȘZA8e.}te.K Ugpg۾R r}U^.kfc9@_Nofx&0i(,Ι!`˔PX:J7~pa2L"KfeY9W5 nnv?ԹqP߿Js!ALS oe-B~}ggKBLt$}vg@=x3 ;8îZ 'Pﻣ 5_s:w9^3 "X1]nk?s&懷;N=GCڎk:@@:Q~ΏJ,96T>F/̭Ӡ, ZWp6 ?rӆICiq . 976MH X\A˴ɩ..)Rה xF4@ $p=cƌv)Ń uBS'@ kh;sը*x]x%₹Ytg^?r7_hr"H/0AbPW.P/ zɺ7Wp tx_8 Y_,@2et'f?*tLY2`q<U_z6 TK 3:d#I'>^׉mX}M6^MKx< A ䷤ICsߝt{$L {OPaͰ1JDĐ-^Fc]H$ $ :Xvz@""h;7~6XN`>  lzn}[֬ ڨ>L.qV{L4o: srbI.t{eD?E D4.w^Luso7eER8T2<F=Z5CU 65{ 2z2W6?XJEY/M!0Ϳ0x9˗/7ckUSSSξtj~6v H(*ZᷟS ܻvy#I%0x獹 Odɸɸ/ܓAn=hqjwM<! AG"!MN fTVX^f=z"6Zlqvϕiu:ƺ` #6zI OL GY:E>NH1q#PO"2J_CjVf ,̎F/Q0ݿR](*<?UQN̬LT_8e.d/bMOOOH$jݱ ׹E_h#5L\`ݟȒ57]`QFd%)Y/h0]21*t~_HM;mKQǾ}( A4}!32KirrrMKKEYۅԣ QkIr|H{:P/σVd?1~T0X8woHǏ*[ EE S1;^|… [<^`EDtRy*%%e d>'˾G׵aJL(t7XȥBN U{ȑ&o]tv/^cq?e _|AAAmooW/MXm!Kݰ|ɒI)UoȚ.fs'd2Mѽt7xcoݺV @wc\; h;)28L?a\;̎Dž.Z}C6aaQh8Rİ-@9boO/P[>k"Ցl *;"h42 i3gnڶmT ʣtӍ9R'۩F@_}]_he}>?gm=I AIYTtෟS… ߚiS0PtA0##eBaP獴.Qc}S5wWAge;WAOZ}z˚NjP5uwNYȫ#\ ZgtK48 +6>Eov$ف-(++2`42(*e]RU }owJvDTA_.(sv!j]Xd7-\#5Ktr@V"PRq++&%%=E5'hfZZ*Y; }NB[f%KpzB] p'kPSZKA[9orRyC6x5l[S!SWZ5 pnMc&Q  \vrIIf[`n,,E6oM;sY<RtwH(!5rɤ;@_~*r $rzM?)Nhr8Ro?ScBm2G=5vh^纟#G\4iRH$Jfޯ͇dz`I)/)BtBa][~68x|9(2);bV%7P:S-ʼ\Qk'o{?=3SB AZ]Z]Y?=3SRYYVvvVgV_u]=5:Qq4 6.|Qg9CNVr}cbOyjL-_KWHR.V5C#qγuL^tF9-_+v߿kg[ෟ6SD5z@=iIlu@ 9W_wS[!g:]1>~O4FՑiF¤`#h䠉;%50Wp^+|zUr v} K[<~#W6aPAOuzwgTNҘX6{u]=L{Dd֋m&.0=XGb $U۷oX [XgkH^&au)VɂM&Sd>Hm/©VXl>H A?])0zK8XjH H@@0qGW\9e#2'8ej1oѺ?Sbt :,3X:g>yER!<_ w_1 aBt:wgӧj2TtZ _&!R7%&boZZ*O@۩cwx"Y3pqv`q7 @E=n޼y*..b>,Ι+)L`%x2wa%pHk$i j/EQ+_1*U"f=36v'q.# PrgGw&]/-.й@ !HP$y:x<^cSSӰ1655* ;wkY0L ϯ^kP?G;@."jͣ6BB.a/Rnם*f^9 oc\lZڣ5p+~&]7c}+lW͛>;;[sc,aS$o+W,fes(ho#S~GßĢ`ŴTx[B~tP>>s) K}">Bh#͍ 3~ YoiЀ.Zk4 !VݻwleUU՜JxJ},^ ͂y;ZBܷ3_1X\ $nwWp) T* mD\ԎұyA?=`,x3{}7غ@*g`#~ _zx\; Em[M%:tѺjqYp4ŰXpLo߾2>^}e!;q9U4vޑ<2Q0U`?F4{bx<^D, jg̘5--9*߲˦&YugxuŠ˓BEpmfL.πloԟz@3hBk2/:Idv S}3L.@`5q}FFˍ ;äogmk;?@j=J>%&?A,*;,]73,y8EP0o\N" FLLtC'οpG};~T0OLr\x~ddz`6nDݡ.ђ;aIV}/c HrvZ}^~(?cN+[#ryZ?C6LѣGT/)u!J6NY,3SisC2ts|D! VSLt|(!&ZFGQβb42,߲!+Ϸ T`n?*4 fLJ1Z뮈S^h(F* ϕ/T&ɉ & e|~ڞ/ E{t:JSK,[,44T.J-9mfP:;;)<8D)X$i4󓲲7!ʍeY9T_v "ZY0t8jޒW.02LF3ׂhCt=tLy {Yњ{4*Ƅ:I!D &ZgIy _H}zfoa.;A@c_iU ?$$$ [_}  Tg4y|8yB1TQaa섄'6# "}H ѣ$IJɳ6E 4p WTAu]"JzS(H@ `?-H$A$0owQ1/9byLt$i"##޺us_o E*󫯾ZO`%*AqE;N >I6mrEؖgLVU"wxgo(PB,,,jۡcJ Ȑ$91MNu쉉/>fz^R5q@r7AaDr WT1~'22r5圊lz\###%BqoÆ 4ݐemj1A$c^2'9ex/(S5A FeqqLm65%%eնCǔɉA $#]d|VgfJ.\6AH*@`ll 8ٳnB>0AA*tP2x㘾PRR2nL50'A mE[jjټ@NN 6"j Ȑ9T; 6:ݏN}j9QQQ2gOkjkk?rVK KhPAadխ˅s}Űf[ e.Y&O{ CMkk۩X `lld2%1:՚]nXA033 ceRQQG` _.' +E>é 5:NxseeZjP.ˉsee^{>\Aa߭ŏ n BHwߠ" Ǘ^:Gy( +t:;}~Oe}"< D… [" LwRmojj655xZO`NNΑgn[ $~@v߬`!g VՃJJW[̵tikx}N}?m;|xgʡKc ޿lv8_Q,CǔpʦM`뵋EXU69tLIxk4lYzSO҉ 1lԫP( 裏<)..n~ wA* 6?6Uˠ_ƌ,teDb G>ϙ#c\[x(ظƦ^w\܁7FBI<! bJgρYOͅ=7kv.Al^I2nXޫ&0n㇎)awQ14rؖt>\LCSc[leTK=ԭ63\meY9¤ЩgNC@%jk pӣϬN2X0 &HGY 7dFirʩKv~ds ` *$xO5ѣG{c1t&[vtfX:k77ᡴϯlmY'ݾGqI`㚻%2^+A~8Y;#H?}2gYXؑ:uFsqƺ'f3"oEy hO}rKZ>&7]Zmp?pQXX8;++k]'W:m&ѯ|42wEpIfFl%Ev$hgJ6FAϬrhˠ Ga+E=&`7-7I`u:/'pJV)-(!J yP g뵋6^ *o24iǫNN=w:Z}].C LɻoI&=+`mf|nO {oT9BI Ao1H X m-뮜ۛiJM&&ǣo@;o'upEf3l U|Lq)ۢ_CRu0OZP(HF˓9u&:6Eb\]LV;KێEξS1YO5qipJu]=Lc!In͋vt. QVgPT STg6|QQیu|J3C ܩ|L LipSNpnkP_Ϭouȹpv`$~d:gxT GhL-_O)~}й< ɽ0 b0y䍑QVgxYPm`),Zӏɺ3T ;`uT2YEy+;~)uh:ZZšuuI#Ckmlz58)Z蒣X8ǪZ.߼V&)8O]f^ٲxKBeVT{XƷnh*9B l\n VtlkVOUV$V76zꂆkߴi0JJmb6[i_ALvvR!}J% >S:sCy $9<}l뵋>@rڎ8B =zA6Aȉ7JfMA/U q:` ==t.5$YnK3绪ę:Ɓ'4Yp I}}}4=}L_^JjJ&((>uw/*s{Xر0\KeWS#[,aq i\9X Vh 9r)u;9/n]w`q|Zআ:Y62-3l4 5$٨뛝]߫Toju_O-@3jzddv# SMKLu~4;e3w9s gϡtS챙^@;iqEF[כTTTlHNNNJKK{Η/..;߿|r3 (Ikcc\.OV nܸ9sobv[$}Zt:}_@;^Mx#+\@YVNl#qǭ0^Nsh帯]~Em۶AZZOo>6⟠ #oT nC^?0U^Yofmui"8g>oB)h,3:&NZQE@`\T\WCfS&BbYgI pö#S}wTƥ#()h=))dzy_Q0'A8Y $'΂ˬo"rb%#ufbiXRYsgd0m9B Ah5tNoVYP]CG$I01FqJe/~%`U ItxRoAv$&P&Ζ+Txn{pn:"패?ā~!(n'#$N~->A֬ ȚAm0^It?[+5ޞx]'$nm$ (0Ʉ9%Te]yΏ*㉰ A q.+ Il-@d(%hԇ<_~g/_b @`#W"(`KAYG;{!LY'a/cPVcbl@d( 1:3 dm>Cg2& -̈c^U@dYl (|)Ng "Ϥ5;xCP!(F aеx:l22DG]VZ^#Ġ;u'u0#"+$DC!2SBs-ǎŕecS!(n vp]9 bQfs:|^UtTR?=0~H`coPG &&s(7gX[w60jXU khEPpSˬ{Es_hq?| ~l@ėlX b#)joB7wظnQMA[]†@D|I4 ^XC]: :/dqEsG.bN*.`ƛ@f*4(O ɉ74 X>&5 l^PAMp>nb2X?XMl( 89vǔۄ7g_fgx:=;^q% ` r\si c Ư:]oct>h BOLq;]7HJO|enjujo&&x%E>98c t3 5lX;!W{= _$cZ B] nЦ>p ,L'-!â=#Ġ7 :VρGǺ BT@WqfuijocGI@,EP0᳷@P=1!:{Y:{}4 ({_u ~6}ungN[}!J =ߏ/t,"tF|XTʘ F ] []Cǔ▿ЊaD! ~yaH=lSB1ˌ<[]?S?AD܆όM8tشh@;@@Ϭ6NGC@Y.J6nPoK(e¤a2ˬz2!ʙ0L}ۄ,"JAK+O ks&#Ql/ uzغBS'" !ma\," (thoA|V{hC=)Be=x3aS``q#Glkll,$!ӱ˪e ADL.P6 dddL'%l],/>҃Y-}'~M!dAD$)Nҡ!!/r^PT{~K߂eAOADsh]g?O҃-nO6o(*6CTݻtd;sxvLJ]S QW$ cX_~W' Pv8tL =7oF> {nV1aET t=no5ϯ^m76cbo< `@2--' zX rِ>5?񏷕Μ9s5`nU BVffČ^ \ѴA^3G Kd?X]APKNNΑm۶.\H$҉3]'2 _ܻwo " irssņ@AAAdr<^@6ѣB0&9???駟D"IW5k{n빲2pZ}pWDhٶm˗ qqqVXL  PJ/77=0}$EAD|&~˗/[',ܳg+x~Oh!FxxTR[ADR\s~"//O-"ezf{[gV\V x7nO߉V x!O?=[ $XE*u+>6m2uCǔ ggUÃ,+E 6^aP˶zP;݇T ^4<̰)ӥ醚pj`ɉ Rʚx12697]n8|\ RI(,\nhe {EP̘1cEv.Pyrn(xa dʰՋ[2]:L9v!\+ [fپ6MYF8q@9:74Zjsٜ*ґ>y,h7?9pemS]W,B]~6$yzfddAt">s*muwm[6^rX;tE"/n /9BXege,W8Zsm{ g㵇@L_.\Zw"""|ڙxS[m%Pq } ^s-'%k-Ƕ>/k ٷ³8g˅0i(:XKC+ϔC]+6a̒ڶӟܶl3a@_pA!hC!A k ;7;T[ܛɉPs"UVc#m\ f*|e(Y˚Wf#P]G8tLi bbbF A* چDť˹X[B9_ oejZ܇֟꒴v2wÂYRNm.,6JU= @bcc`Qw!P* ii>9b!ԭC^Y e eLte_>E-@įRϡcGEm ]jqy'˾yY}69jh6s\RIe\1ёr N}]nNTb.xYqԲbq|3}1Mv\9?AD `<91&xbTXӥ鶸:c#maq ^LNLp e*u%*z0=+0&:aEs=lAP$Aϯ^ңₕr &e Ϟxk#W-$MN+y|`(y(+=?2޲OE}yxWo.p[=\pǫy.2mj/T^qdӜDL,3[v:Xg0E.PJ婔-4Zsw<%123,'PVfXR)=~X|<RI(>9˵B8_QsjWg }q~TX|\LAAA%K]-\\ba^ WzV/Uramހ*[XϵÔ3ԙ·AD}(7ill,ݽ{"5AJU"^A.Ѯ~????iܹ"##J$dlA :NqQR]|useeZ *F@+ryq^^|ҤI1،|5f] 2$DA< A * [ADP@>4!(ȠP(bI–@|LohjjŦ@PA#66Vl2Hbk ޶ ͛ WBh4eAۗOB.!IvADU/@4n#2QuL8IENDB`tiled-1.0.3/examples/test_hexagonal_tile_60x60x30.png000066400000000000000000000055661315121121300223620ustar00rootroot00000000000000PNG  IHDR<<:rbKGD pHYsHHFk> IDATh[{pT}}d7#$H  A$5ڊ"HqJk(ju,$ I湏{?$M\@3gf=ys.a`l{Tytp*gYz\л~7hojf&u:Rӥ;{ץqyIͧKA{g «{=!VkfEwTYzQVǯeuLrb 3ds0gɞWrO`V0+fS`zBtE(guE($ڈe@R4x9m_n9ժ"]Ty"m K)x7}@ OoO~!UhDdj<}3w.|p5WqI}*.O?? ;9;.u`Y(W{spGLuMUplJ9{fbÉ't?R_& oWXXG:DLuAd`®ܺf"[aƳ}Ȱy#_zC,9HٕYȩʩFveu),Mw2sX\j|ݿO깷 U\pd"XS }f輷j)vCc9OdldymvyKw'afSmG+R;laF3dcJ)n?%G{AUs $\ D% p^:T&:O ue H~1ĩݶA:RzHA8q c:}z`Ͷ”ixHc ,gnV_cO1[Q/li369&y#|='GܳTb1^K&>ږ>$of, o˟Y3zp]99oQ 8tfħ縗qȄhC ŠP\q1qLxd,jФ +%-k)c]>ߐ,wI.Mt~dM:ЗL9R"Ԥ8gjnNVWugAD}lF )K3q~}= ]=u"=CGDgWȀ4xoJ]!a7ח-)OOt7#j0DtCpzM$C8J 6rQ@'s@p;ץnry\_,+ק/]p*Tc?=TOI~q'|^sW٫y艢ɶ%ᒍ0њ;ܾ}tj.)YbtjJƖl"푴ľ0`Eg! '$~U9iy%,1:-&: W%ْ*"m%DLɺ~aۢ1%jd䕽a?AZ}wnՏk/(lG\}!"0s?4|A֒dO;2ވlԄHof5$0%tEXtdate:create2017-02-16T07:33:21-05:00Pe%tEXtdate:modify2017-02-16T07:33:21-05:00 IENDB`tiled-1.0.3/examples/test_hexagonal_tile_60x60x30.tmx000066400000000000000000000026701315121121300223770ustar00rootroot00000000000000 1,536870913,268435457,3221225473,3758096385,3489660929,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 2147483649,2684354561,2415919105,1073741825,1610612737,1342177281,2147483649,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 tiled-1.0.3/examples/tmw_desert_spacing.png000066400000000000000000001117061315121121300210150ustar00rootroot00000000000000PNG  IHDR  sRGBbKGD pHYs  tIME8 RtEXtCommentCreated with The GIMPd%n IDATx{tՕ/ztW?zXd;Bp 冗3!q@eoM5_B ΚrɊ,;@DtO IBc[֫ϪSuUndu%9{*ʭʭ\.o3PA&> U0 $k Ó)y]bj?\͐UP% , ~y[6 $pȞy Pu*l*D:>6d̛: _1H7@<cld fO ;?dS{=]I~k=] W} VL=߼O@AOޟi`(@ 9Ԋt|0t>T2qx> EȤp C#1x! `*DO0C#1f%>@U3 9u‒1 2;[}Oq:J=X:ݽ 8*qw>=>Ȓl{z p}Mz 5itw#_ZPp0EOLay(D~T 55鱓SqrtTEq~_6:lz1lv*(m߼O޾rWk9MMGW: .8?z~!{>, FWR$⤳t_!~VLÇ P0!h5 -$0,tN1hא'Oޠh{AlJ %#d>rz#V^Eڏ>=L1=c[00ptˢd-4UayE"ì :0<|mu^YP?$1CO+P`7,O֛oE۟ў]=96,RLdQðeC+Q,{\ ر{no/Ϗ-( e}XjtjP(rbj- ~`^@0p,P5"!r*&G/PUe )ۀ^/Sd Hw㏕1.`pϔ^`kJ1YBL} ѿND38f u7]s1_/80N2Tͱs}9!h%é U0> ~Y-0;:C!(c0y7,m&u]8e15TF,o#Ƣ1̦uw]0ƽ㥒/ޏ^LAYs|/]6(l3A+,{ײ\ۚ]14Cѹ*dG}6#P74 E!Fq1ӇB0pۍv0@V 8 Lp H$EOEU}&KT cIC@IH$ /8(2}\jmxo>,UT} !&=} Ջ`lr'#E1u,j[;g=QP>-*L%Y,L:d? ߌF嬣,tuL %  =jg@HO zg8 8Rr jR&#gv mo{yWYiHɒ0f chlŽ&'غR&/F#}Um.4CmJA4Gd@D \ j'DjTTלZ>3k!3kg~kg@e=Щ1&{tWXfXDOwquc'x|/Qs1" C)A7zrK];v7sg.badRɱ l02]JP>0M8 Zb!Z-`Xn0V E1+.8v r̳b;^K ;b>5kY1B;,L$S1,od zʦn@QtsO89G"F0`;N8>ǖN:}tL ~BcI>Ce+}Lc{ާޤG ]-7Fi Ӆbd;.h~,1:3qQ߾bF F91\^ y1* (&B1  k)D0/@l [3Gib<9z"dN$N~y$'2=/NH(a3aݏ,v p,<4.+ A ˱$ojgu޿~pfcjdSkYC'iYe5 ꃎ ،Lj MUA U~c)ァPY{-[k)\o 0[6;x'Nt#IVLlM\ұxxv>$GGc9 }ywn}Eb`!d (Y(쾘1(J]!LlEuc­-g$}p` E&Bdڸ Ak#BeUEC\~ JֲK/ s$tPmP { +k0Y)jhkQ秳>;} k6jj,s F!ut 5>(@LsK?R&oAJ(w Ըʂ+JP>I Caax|e>1̥>ı=C\F"D%S Eΐxgܖօ䫭 ['z[[}ڛ'~>v >]B1kf7͚̰%}m|:[:ͻ| D\6nl"Kr7!(Aj$*݋51=}yZ2oc }ȇͪxnA:tP!EoSPFOw9+9и\u(SݿDGKh>Az7^m7+Y0  ;؍t|L2F101&mR=Yt70E$a.! C1Ѓa) ~ꄔ`BFl!N9h[,X8<4`0gO C1"ņDbAu[@Owz_C] s$^nVnz` xBUd0 E[uTzO#)Z13v7Q,.­- ~G۲m_X0J˞˶9iJSYzq:ºRA0cHG,@W9qHG빓Wa6{?X ;0Z.}--Wd!@Rgm Z?McI,m搚h&)9_o6 t}"p_>$ o4eHN 2x  YIQO,ʑE:>{KP>T/^#kYJ1$~zy9zz =]ޟ2`H'0q|E0bepw.zOY a>.rP5g!jaȠS rd)A1Ǔ}ۿ [({[/V@#+0<UcHNFu'zøD F'NGcdFbh[ ?uxPs$FhTN*C[C%c(Tf!4]pCA_Gl18y=VH0,}-6l4x_g>d鳈,iWY UY(*4D CcdE~ %Ƹ.rМaq P,-ԛ-k|?lLay(2I@jjc'!h5Oi6I+ 7ѝv"`psP%8cNR!ݽ}ITQTd C> (H!GKBP,z`]hh?(JhKz\냱H_A T$CG aTSd;WN>IFdan)H)(߃‹"%ɠ2tihгlF 4Yp C> 4jzR&ad2yP,zY0aI |-uA0̥>pq"k@Zchi V<ЬR[[à?|y2|D)E*_sې@G@B>:{HDC:> ^ZH,?yVDo4Lyp1`|'Iyc6^≟W [6R/C! x+_ K>x0̵>0v3*P,4Zy6 kz8x'> ]]E"x.mmu9'd~xxn!Jٿ7;J|,xY㕔@ T zjp-Z Υ^Ks?*2I>Rc3Z,RSH0 R$AѸuc'b[y°Ea(DZ)6tЧOP {ud0̗>xǡUU`@!Yȩ)!"6QʒD dI=0̇>pyqfE1 O r#q? CIglXA$é܄3fa\#>t}[6' U,N>H' {Y`(Y4 #Kw>2!g`(F3X09uksae! T1 0,<Ԭ%uXưjt I:s!tASnIcflпC?dJ_j "KH0wl VC8[u_,m %a(Y4 uiàgXvw߷00* vz~(sQz/ s௨Ft"AΦG:>ILARY(PiO:cfnwA؟n|3p`oCdr(LX=`<9o1;+-LÅYlm>C#1dϐ0_P=<4݊HOO!B;׃!PՔ# {BHRnc an-p- tBjsV1 !e|Ub }p`a.}΄a6@+' IDATMٌBl]e b*F*8оֲx D?n,f[}k̯|SY|+$°ӊl֜{lЊ-ZIn{$d12c(U0Xlƽ޾C1x]&X(I"eYl!ND3X|cm\)6KS{)#7Q50ٷ$!k)Sǟ+QXKrBӖR&Q2R!lNE`O2̓3ea2 b10 ˇ'u]8e Pa8O":%G+V+6:@EvT%Bad֍.z}JW`I3C~F  מzx]s!8,ok.I'9FeM'Σ>)D \7c>|-zʚOb\n3"NJ' ȗO$M\8ԪNd>臢Ȁ".g=pu]zq.)]Z,XVRjӧPx#gQ鈡}h켌aDZu#3z'?NN23a,AЯۼӏ 8"a -h[!^ԨuÕO\;A)އ[dvY;XM_AIǤ>(p@6pp;LG"^lem,__ݽ <YiHIxmhlUJ7 =1'$TXyzy1Fx}At'fb04InWT #(b&C>jU': Y)Mu+*yC͜:0m}}2 9t΁ ;o͛vzK4i8tjS~:W,3`Ȗ? ݢn?He^0bE9bhX]]F ˫b޴}Rݛ3 ,d P,QЄ+(f 0YmS?<`g@V"(VHivVLn|ynw x<豑J\b"SaGϦmȂa9- h;3b P/ӧYQ4_|7~}O ,d2n }Ө.kEpgq ]J$BNŌb'`6^'ݭV9EL.d;-濝Bu.ݫ%q cL E֔90z*3Y9tM1L_~4v\Jf<vy-٘`{-땓4[I@y1#uR}:'(ΖkXlz u-Kqh0()hЉa7kdz.Ruqx0+Y|mzk7o4 [64bWW5bI$G|- 'NtcQVLl\ұx8MM8䈸s4L<|f╷E__7kl0'y;ʡp`t_A3s$/&޳}/T bUHO Z+Y'0afP,LM8A;yICC: 6@U˄彆9KVv<';g2DGc<윉h "smݓ} F!ut 5>(@L\nAM$->Hɱe|p V2 0|W5 8+s,sjKL} ` xX/?+UOctRǐO3bYȱ_}8Ic8`x ˬ2Qd l$B3`8?|fφ|v9z N}EOP!fM&3,)?|& S~֞:0FDyGo2!ew۾0EcP ]\0ǖ'k,sJI.Wt,`k Xq(D'-{:ޯq"z@ [c{ q Oհ׹pRw]3bN9|ƒaOЗTU/PI{4R&AB2I^ y}3֋HUd 2<;P,Š%/AgI~l#PNm,tB17$g˙QdK, AD'5x nCGNOzKɃOb0}Em;wL"z$ T(pMc\ܼb*n J(RrV4E$(غ-eYwem!`(E'Y%4\Y|ơ NPN28 1GtK'\v?3)2jY 7;%x.6v LjjLbI[ TOx= >p}* v.蹗ꄔ;1ma.tRDWY|\ơX q(D'Fb6zIJFb#\Zϯp乼D'炰(?͓^ vO\tt  ^@PBVcSYofC:Y)g}M-M?tw5$9P0)`Β0̅Neqb12ꤵ|[}v( `BUF8?칸 9s6 L5 v#2$+ԶW756ՁZt7I&mo5 BuX$ Eb*Q!ƣ0* @fʊ)7i#ѾN"2VO:cbڇ{ RjNRPοE%EJA_~R$ KipDž>J\t ZN@)Yͭg5| HzY0aI {-Eg C:ѭXBOO T14auW+BhIpjŐ왥"LA}I/):0<|mu=I$OjC:> ^Z"J 61Yyp|'Ķc6^≟z~4Uc3F-_]rlXJD Ö tP,ouA0N2v3*P,4Zy6;D<1E2>6NzL _Gi7o;LrdsPh+%UCj R`Zµ}AK, Dq C) f-`9".lIeʂ<,z}DzD0-V k 8&a6:VUY$g! ‡pXE)K}0 SGUUFE>Xt`Ǎ'QІ%KBowWko_k e<]< ʓ(M'TBda0f@rHr;onXN1}|kJEJ0|`\ӭ>߲0!80, !TH\IaQ$f%<,2T3'Na`Q-0tnFA}8=p{b[1c<ͫ6,AVT@"\'jIxn%Sאߗ,Yt~t~E: |`]žEJON- DoQogsiJIHEB6qX"N[CttFW~ޭR/LZ%c`8?h:C'c4W#/TAfo DrWv>7 t~m>@"N rwؼb!@Q]1;>D3n:S јsF`0 R$maj_bI478fb0 `ɒ\N}Y^_l!d22!+*(BL] f5^s=m&M,6߹^!ha;lJfNx;ڥMHMTX1;[o`Cd!q`աg \$ RdL[ΥR'T֛c{iu=UuO,'Y쟷OJ{^}c=s&|_l35Z6AX:]SA!sW1X4.3-bnBeOW{.1TdиSph fVe1L]G :j.1 r,ALY%Xڗ4"8Zvz/usJRo KqťWk[ Kqڍ9&R10vàL$ Қ;"&RCRqz`ĺwf҆ieFDr)bfcڙ,TtknE> 1r zb09/|:hF8s$UT_StĮ[?yrbNNf7i}ts; a8XyO%c)f&1$aܓtNNq9l|΅й:bbr 2B' sPtũ R,,f`? In38 uUS@eBBx"7٥Qꂠk"Q%+8w792afSJo/:Ԣ16X&n,p6`3\qݼ Z) "K`y[, 0vBWvPpy!eݯJ&isǡVuBU( (""x[M~jƛr<9wfac|o0ڕ~Y%BrZ۪JE}EV3 1m0D3SBbjRj^G'jS cP2 >-c8=<ɋ:n\e}X8]QU+TCF±=P:0Eu9_Y C& tW,/ DW \qpkNAan9-p00vE8g\`00 *T [ dS)PE4)!ЙQhE,n lts]v|؜|e}X8q#!tcpXXdxrD}ESFe4x!"vWVCN)[U=W|=, < FD7d8|&%Kr}J$+0RXZf2xW]UiQ?i[//8~yֹ e}X8 C: 6@UD:'aRڶ˩QHTε[ %3p gX@8r(7`o >ep09.j2r(B,Oh;9k4y`@6 4OCr ?ua"oS/8`E8ݫ6Qև'^(2)(Y0 ~  ٢xXU Ts)ID_Axj< z:x8z9:y1pf>H2^bMU$rV4F!QINAL'!+(dlYEE9ge+c0K1 H`k|91̻'eYg!\\v?3)lvV[kYl_n^l4P|tQ,Wd0YҐ`TEZ 4e 37{>OǶ!-ۜ#_y>, q7 nSݿDG ʒ&v Jxqp\ lԈdFnAr$铨GF- DCR\A9 +ͩ wYⵎ5_mbz_FV*-BPLC!L#md NmEbsO慸k":;S%A0˭ʭܜv,6dP AjV%mUD5 YU( -e b $EkPբ*ڢ`7^qO`+P)B@TSo0?o IDAT!{-@UUQiH'݆BVXyS V"9=fXLU<cld$#o;. j,?z=Nؒ@`v0fje}X"!Z)b|d 6}@`xR ـxHFޡ9{PV fh$F H 9@JC,Ig.6Mݸ^.x<6e}X2XYQ9?"K$σM Y<3̈́E )z:37l Nˈa5܈T⢏L1{>s=" xPU##TGBUȒ`n#vc&+3-1詩LpHFi1o -9$WB[s/5xq!/68rwe}õ=j*j͵"k$4U˨hPTp؃u[_LIg(8! <  VGVLÇ ڃ>ݲ0˿BIR&a!xu^C~l =qՇ/×_}~ ƫ 5UAi{I @+R1 ĉ4xzj,ˍg!T<@ x  ԁsh3J!7{}H' Ay`Tl\qMkk.}o—_} Շzփ̈́e-5hPqv¾ ן_rN0Y a kѢHNf+>75v7[g@  9 15jb*nX=M N!CGa8jUVCUkׂq.L2k[h™:?X,Xy7vr"}\a oqn */2 ıS+ymY n\{_}_~~xwoaQc8?o{F,]p XKZa44,oEJL#DWBƏ8zXp o0,ұC8DpM_O :# Ys?e d Z2jj\'#﫸vܰ'ɛxf"fn\c,v`ǿ,YvLML` S{\10A:><_rC"t|t^>oHSE"["SL:[oHV`lΘg=.~n v>}q/7O{A2J:ٛN*eg~qbFSĺmv<>g;VՠzQ!X="W8s<cg>Bmb4ֵ"p抁!_BUI*׬$`BD2dӅ͚Sɨ$IALC .qR@ b ,VO<Pb載ohs#pC;qMo8~[˝{oʼnS+nD}ȏ/d3; %Λ&K/_pcg!JN?UU ?>LtY/se+j$=l:=bU%&KK$钌|`{r AO/\cҫgJ}Qٲ3{<>2i;=Xq瓈Im/P{+?8VZE|y|z ,mЉ4~µ*~+Ѿ {umȤxﭏH`֊K盠 N*+;BUx_R0` f{_܇nƂ!1猖FV.W˫kt Hb[ubb}q{(rUM졑"M&#aY?9.m"+8?.b123-`B~ú}ᚩN,oqt/I"~<:::0K_']jӞ B2Ǒ+Ap 1pl--8wjum`<*^~~?ĹYşKK(y)P.Ǽ00g ;Eܝ{\ OM;~EN%Մ5/?P<⁇ B]=yI@1$S1`ơA NBfjQW7㧀7qf=8~Sth5w6|{7ԧ` ( )-A0H3WwO}Im A#GqQd,gz|0X̤@V fi3W bxRbO܎NM|~mGY}Ggg֭[5zl>7Jl ( W' Aub( 5; }Um99, e(Ww;.UahVvPpjIZci~kT39\'=n<ˑXT[Ux~2k4z*d{}R&@=HIqU CT!և`?=AUA&"7(HR0/#URZv(2<+>Ç'{= 8s])6HآuA`xIeۮo7H>f1XG{cMv3Kn3)95)O%9a%3FNN"3F"`@@UU@{C!9G: r 15 )5 F}Njc;³L܌-㈎9v^mfMjd7\R ?lo\w5al9R;ܺ4D"#ÈVCU ݶ*]A,@8jU'Æא韡=pcZD/ND!TLU0f33# ʆ/+`åpjfTCɧa͌ܔQVLzv(Ֆm|[*e͆ 6z}8x`CYDfj;N;]]ݐe V1{֍N; YVy_f**jel6v\sځ`djMC! #J֔^2 GnT< A#8xq<ϙˁpЌ1<هbs|=qii.L0YM[T *fK+у3a=|odA/)a(E߽y\z o{wauO`WXS( C.#MMXMHknF{{/l6/_  t `юZh`fC~<9}ԩup9mQl+V@x,]MpÇNՍXFɦ͝p0::8f^4D(8Vt DͿ#i [f_Mn#CJ"!fߓ7GY1>á|Or vدDI˚ņW5;5BC%ty7R0kf/Zѐ^nб`* Spgm.V D[6 9%:E{W&p8v99n}Jpp  "` Rk+d@__/*+If ^*+}%ݻw),[Y Rʫ5,| g}aZq68,*R)I0{Eee%v%5R ]8' jH"%ho?;~oKA6{ύgXy{? ~ǚT!6NRNRu\dhjMA/ڊ`jM͘ZX Q*&s I p"<EHHJt\!D\%x_$Dp(*cZ{ÿ竂%=Nv|~88@3jj9.;ΝK?Ϗsx &.(ѣn|*5$… U VfYI|,܈FGG +Y`XzD!#W ֞: ?[X~)MUѕQCt(hp#u#:2$ ;! ݍsk0wn :;afǁ9px^-9V7g^ȿ99Cq)DpaaGwwΝk]/+6{Sqqjuc%G8=y4IZ}-ޯWOӟBe840rDIIs^R~ݥ-?hzAY_RO.a 8Ћh8#Tq.!K20t(LeG BJbi2RBkfxX0dn8s -(A$ؗ, *Q &[h%\~mţy>+2]vK q"ܺo߿2Q=SxF'Μc3pD0xNҧ\GcFA<@0BOQo_x&ttb"|eYu/꜕ +Qr`6 J a?}_ 6 llF$,r?!?5(ʧ'./Epz . ;7֬&֬_5dCq|OB$ ,%q%@<\!܂aZ19sPg:7E~FF2=w< vhݻ1eu`9#qypmU_k9L$I@69 cSgQ [ q98KNe08$ȇrʕ ީ m~ Wt! 8 Ŗ.zaV +[gX00Xi__?ADQLYB!4TJs"L䯵&5y]NgnWB: z 0\i_0j/'% 8h2Q$\c{[JPxNjhgۋ CCFq"1XԀDs #4xfͥha1d\ۇCt/x3_yxF"};z @үW On^TB_sH Be&IZ.FAXQ] NjI>YYc0X[pUtxu4Jua20XY/o60V\v2{85܅b_!]uuVsӯGK~ gᕝ)Q޷Y#⛷jA9v\qe }2Y HB) *@x](2dql6-t1)[~}ЫFT60 'U9(v0#L!ÚG_E-wJ5~my.2`;:~}ʾx-4G3эt74=Gɢ-T7oxk+UZ(L >\ڇD øuӟ6[UK7M:{ج`. O&CXb/0;jL IDAT8Gtt6% IBwq݅j~ cͦ3P+DOwlm. EЯ.{ʋ<W7]N;jz%s0㖻P-7k= k/GC.-QCa,ްU Q|qW?͈A*xB[rf`+vZN|a)$DOle'bͦ3(YdcSP2: z`M 7ҥ(W+wW'8E'48`ds Xa+%hA!DiC{)ӝ pFP0-ּuJ-41ГKЪgNn ^$=!>3M(KvYz ,c͚5*!2"U&ɦ{f)اk)YkFR完sb(Xv%wm{=j~ݥ 4PS<*Tҥh?x{5~ $}pڹ`1 zrlT e^߶V,ΡAHgIB|F ɌWv6co=/]]GCs?|nYr dtݡTwUmvc9RtлMzc t:0wn %^7\o7z֛F`8t0~ZPtF.r  D~ϟCZժai1I?چKVx,-\w-"f uނj#\1ߏhEP_w)/= _k ! SȂ^x%v$-ԯ/)r N͖Oѽ*~bXCJ/PArjqDDA"!&)/E ` yFZ(O-W}20X($vvM| IFhvk/ʅ(0<ƾ}`A-jkkrUWcœOаgYT|hB`1?ll'ŒK[x~'/];81YbKqݩx}A<6Î+IJаgI)T>?TlD=D'7[5rPxI E $Dv8p 5j1C?#f $jnK):DJ7Ju_h 1etxqA_`i N$i(Z6ķAqlJ*vbFHg4mh1mZ@N]]=܀ngF"ڟ*a=?W̊ſ|L`k67~>.Z]h<^|% qtFR ͅѾ` ?H X'Qb^j$U|?i"GɭJ}2[5 IxVy |kA. q,ް5Ɂξ.wz ]^wԔSB-FplF]]=***LZ ,NOR{F5zfD`0imVL@V0t`^#fsƇW/>*n4}JۇoRcoA1'K]x ^|!5۟/`HG;F⯯ߗ"ۋތآD,T?dsbb%C})9oiD[{hH%㕝͚ o؊Wv6c9trR⢜ -Zl* N> ,}mtoOF!]΍Rt#2audÊMeAor` VljZFdLOmǎ6z kr߽cœO`x{q݅hBv/O53B$/>G]#]3B&`݊$  9'_͂%Vn=6cgpɪC5φB1jM6_Q W#< tKKByyFE&2!1NR͈|,Bz:vO2U zVH30د ֺz444AeTT(UB]$zkj5} B.k6A 6*b6}o|PJh֠Χx|k?u 0OI֠As(,ްD.\#9$iA«J|-Q,TyIw뛱v>\N"vcm8+Lo`Sn1Ɂu扮|#D,9;}\4jQfB^Q$^י8fC[[+\.;xL6zqRK7j/ og8B\ 4~q s%skz`1럏ϧjR?^L5ۮmQtu~-=EA ,S!wxюh$ gU~ܘa*."0O0#>H vr :v"sz wOWH.Ŵ! 5XlANv.5ƍX| JFDA75*XU;,}*5{ȣM(NC$JՎK(\q;{G&F̻> 5!P+BX þ>2 Ck"ذ'kVm\TWœם11XIzOQ698P}2P&T ǍbS[>mG˟AXBF"tM&N_/>jn O=  N_$7aj4k`,Yhx~SsrT~ )/BI*H+h?"\emϦ)$Ɏ]ٸ.߼PҕYq`ƣavrԨ)j{ daRfl# ! @DWdO͌ԛ۱ \$]#Mg_ w HV~)d;y~x2Uxbkr`z8:o:wHYqzmh milG|u!ϟmrn9 K1/ړ^ho@v;#`3*jύȴ Nj!>R|ݥfq=NHA@P2NJAo(!FV1u=7ӳe?NJ[hҪI{_jDGg_ 9!K !Aw Gxl"Bq[UBgNc?R(:{bFlz-7IvC<C@ .?GqŕT'JܖOC5_XCSor7޼huv%"GԅvW\Hģ4ٟюO\hW@Ob2:#fo$BV C&9h9CCGdN +aXƺ2]6XVm> (~E žB K)ر$nA$ìS!IJjj( y- oxs{*>xvb4C% ۣuQz570< 8^; addT}CuZe%FqE%9Gð;)r8}6@*gD2ǶjgWb=OW_7޾her[Pl:Q3#ǛMT44$k@YٌF=˥19X1>#9<}{(z+ƅiiҘ=?./ZhjOXdxRb`d v(5._F5P.x0Sjq"9po|Z#5h6(?%H8a)A](e;Ϟ=ZAjY#2]cZ X s -[CcidaCKK3f--C n~p$$hF_/&&Z# >h[ 8nTi=1nLM"epvctKD@ڮϑ[ jfB|jUIl cz@_IoUa2CU]:ZHîo9h0PF( 5 `9~m1K~G >6k!?y`VOޝF84̣rF.lrxt7%|IDAT<b4̱n3L1 X L4lL%=8da0LzPa:0.Z1PhT)50`0X 9^XE3b?J62υrU |G(ͅ!u Vc _h4I$yA$$ѡ cI=%ufkȢG5HH΅(\ʯ)o򃗧B$`w(՝GUGݩLxNYdI=#GzQT4mm~5}7>H6;xdH z9(uȆz3ǔp`ГArTM3νre *S cΜsa!`5 #rxF (5:'H3nZϼ=J~1W_Y=pՄ`TkxՏqh*Rr$Pn MPٍg =v{\?!-)n3sa2VUҧ$IQc21 =h(wM| IFhvgBM:SN6K[:;;;p pa-vZ-ݚ4VP3gd\S9֭\5X2fvu kBco.p*\?5ع}% /)2*p%.%Ul5xaXU_Cuu5x:۬~HH J] ƩDž!c&lB5#*V`$2TVV"hղhM5ȁ%55E4Dcjj[9W^'ym1MzJrO^x|;$'Sr"DhHCފ_hn59 VA ]F?5d9ܾKP2D신rŋSK;gT@u)56Q5+$X{,@}7m3GKę6Qpi'X-8FӝOΌ 'SaJ+;5Vh8d.0N'!}]czR3;:<#Yty2n|!bع}Ity ux~S BJ\@tPK-@^a.@vo IYyc!gL4tQXd¼ax33oHdY$Isװ6dAS"9\7ϟgwI]Z7ycd8sS |me.0D@d5 Vw(D !B ,X%iE?Q9Pȫ " _Aa0lkadtte1"> IJRg*lG>0ҽFHHؿ\dTVR4:kR$a -@逜n.  @X$7`AOs3tPV'R5 YP"{hC:7aHJ UG%Wk*<@4,9D/J[ M zͳL0h&!rP? "# 3pz$IH$p8촴I=HRMeUaC[[ QT45#fcFF<ϰwPZZleجYݭ:4~Z 掏`8b '0aNOΓL6Yp-<<zz02F[[~v㬳D{{dە7\ggYpVaɒSkZrr\(+&W;`Ô)yo9DYY) ]]X^y/_Ǵ&nD@13FuCdS#M: cNA;hrChtm O02bn%څKV%/eIlC91vn߇KV%ޥkL1tG.z{e^ԘKO ֯t4u7%j`3HyS7B1:jCn,H3zXj2Jۉ'.NƳ> D І\10ЧEESC!T!ksa0/cq8vDCaMÌ1XZ$j=)ITDsЦi+&:%`'N(vDh4mxmʟR^@ qڱzjgxǕD Ќ .XYr9`%qP7|*3MpUʇ@ bkLtݱ΅~$$ݻ0 A ǍxBe*`}=xϸEГP mth05ׅPGB$6_N_jzRЛY5KSδ$xDy>jБBHKϟe͍ht|d0RJE<{q : i(D xO2HC$t!/;BU?h yoy^x今&O`Z|7%j-cyxn vjE2~/!9 LQgYu I1x49Q|KJ=GOh9t2BCGdN1n>U82rfofIT*`v.Rr$.pv;b0xAv⃷߆ãj|o3(xDx(^%D,YEy8xx!2(!,0I@ppmGJ\Q!ɈFAv)eps9\5zv8sYU -(A$ؗ,yanyے6divL㫀!۹x3 RF0緑F1oɘI[Ո#=pz=8: -HȊH$ȉl6JQ45ϣѼү,W{u  lL#iWT9)+fMC<ԯnAsCkT,La7lV7'ʙ0BCU,[\koAD \89ɇK1@J6_4!A,2>B4DhBBj{ݕ Oq 1f4J!71k)`D&Bp|=|u0KɮԱ .,bwy"z:/F9 =wCŘVg84{a8k1h{q|H< >IENDB`tiled-1.0.3/man/000077500000000000000000000000001315121121300133555ustar00rootroot00000000000000tiled-1.0.3/man/automappingconverter.1000066400000000000000000000012021315121121300177060ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "AUTOMAPPINGCONVERTER" "1" "July 2013" "" "" . .SH "NAME" \fBautomappingconverter\fR \- a converter for old Tiled automapping rules . .SH "SYNOPSIS" \fBautomappingconverter\fR . .SH "DESCRIPTION" This converter is used to convert automapping rules of the Tiled map editor from version 0\.8\.x and lower to 0\.9\.0 and later\. . .SH "AUTHORS" \fIhttps://github\.com/bjorn/tiled/blob/master/AUTHORS\fR . .SH "SEE ALSO" tiled(1), \fIhttp://www\.mapeditor\.org/\fR, \fIhttps://github\.com/bjorn/tiled/wiki/Automapping#wiki\-Converting_rules_from_08_and_below\fR tiled-1.0.3/man/automappingconverter.1.ronn000066400000000000000000000007631315121121300206740ustar00rootroot00000000000000automappingconverter(1) -- a converter for old Tiled automapping rules ======================================== ## SYNOPSIS `automappingconverter` ## DESCRIPTION This converter is used to convert automapping rules of the Tiled map editor from version 0.8.x and lower to 0.9.0 and later. ## AUTHORS ## SEE ALSO tiled(1), , tiled-1.0.3/man/tiled.1000066400000000000000000000021071315121121300145400ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "TILED" "1" "May 2015" "" "" . .SH "NAME" \fBtiled\fR \- tile map editor . .SH "SYNOPSIS" \fBtiled\fR [\fIOPTIONS\fR] [FILES\.\.\.] . .SH "DESCRIPTION" Tiled is a general purpose tile map editor\. It\'s built to be easy to use, yet flexible enough to work with varying game engines, whether your game is an RPG, platformer or Breakout clone\. Tiled is free software and written in C++, using the Qt application framework\. . .SH "OPTIONS" . .TP \fB\-h\fR \fB\-\-help\fR Displays the help . .TP \fB\-v\fR \fB\-\-version\fR Displays the version . .TP \fB\-\-quit\fR Only check validity of arguments . .TP \fB\-\-disable\-opengl\fR Disables hardware accelerated rendering . .TP \fB\-\-export\-map\fR [format] \fItmx file\fR \fItarget file\fR Exports the specified tmx file to target . .TP \fB\-\-export\-formats\fR Prints a list of supported export formats . .SH "AUTHORS" \fIhttps://github\.com/bjorn/tiled/blob/master/AUTHORS\fR . .SH "SEE ALSO" tmxviewer(1), tmxrasterizer(1), \fIhttp://www\.mapeditor\.org/\fR tiled-1.0.3/man/tiled.1.ronn000066400000000000000000000016211315121121300155130ustar00rootroot00000000000000tiled(1) -- tile map editor =========================== ## SYNOPSIS `tiled` [] [FILES...] ## DESCRIPTION Tiled is a general purpose tile map editor. It's built to be easy to use, yet flexible enough to work with varying game engines, whether your game is an RPG, platformer or Breakout clone. Tiled is free software and written in C++, using the Qt application framework. ## OPTIONS * `-h` `--help`: Displays the help * `-v` `--version`: Displays the version * `--quit`: Only check validity of arguments * `--disable-opengl`: Disables hardware accelerated rendering * `--export-map` [format] : Exports the specified tmx file to target * `--export-formats`: Prints a list of supported export formats ## AUTHORS ## SEE ALSO tmxviewer(1), tmxrasterizer(1), tiled-1.0.3/man/tmxrasterizer.1000066400000000000000000000030401315121121300163570ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "TMXRASTERIZER" "1" "September 2016" "" "" . .SH "NAME" \fBtmxrasterizer\fR \- renders a tile map to an image . .SH "SYNOPSIS" \fBtmxrasterizer\fR [\fIOPTIONS\fR] [INPUT FILE] [OUTPUT FILE] . .SH "DESCRIPTION" This application can be used to render maps created by the Tiled Map Editor to an image\. This is very helpful for creating small\-scale previews, such as mini\-maps\. . .SH "OPTIONS" . .TP \fB\-h\fR \fB\-\-help\fR Displays the help . .TP \fB\-v\fR \fB\-\-version\fR Displays the version . .TP \fB\-s\fR \fB\-\-scale\fR SIZE The scale of the output image . .TP \fB\-t\fR \fB\-\-tilesize\fR SIZE The requested size in pixels at which a tile is rendered\. Overrides the \-\-scale option\. . .TP \fB\-\-size\fR SIZE The output image fits within a SIZE x SIZE square\. Overrides the \-\-scale and \-\-tilesize options\. . .TP \fB\-a\fR \fB\-\-anti\-aliasing\fR Smooth the output image using anti\-aliasing . .TP \fB\-\-ignore\-visibility\fR Ignore all layer visibility flags in the map file and render all layers in the output (default is to omit invisible layers)\. . .TP \fB\-\-hide\-layer\fR Specifies a layer to omit from the output image\. Can be repeated to hide multiple layers\. The layername is case insensitive\. . .IP \fIExample\fR: . .IP \fBtmxrasterizer\fR \-\-hide\-layer collision \-\-hide\-layer otherlayer [\.\.\.] . .SH "AUTHOR" Vincent Petithory <\fIvincent\.petithory@gmail\.com\fR> . .SH "SEE ALSO" tiled(1), tmxviewer(1), \fIhttp://www\.mapeditor\.org/\fR tiled-1.0.3/man/tmxrasterizer.1.ronn000066400000000000000000000025201315121121300173340ustar00rootroot00000000000000tmxrasterizer(1) -- renders a tile map to an image ======================================== ## SYNOPSIS `tmxrasterizer` [] [INPUT FILE] [OUTPUT FILE] ## DESCRIPTION This application can be used to render maps created by the Tiled Map Editor to an image. This is very helpful for creating small-scale previews, such as mini-maps. ## OPTIONS * `-h` `--help`: Displays the help * `-v` `--version`: Displays the version * `-s` `--scale` SIZE: The scale of the output image * `-t` `--tilesize` SIZE: The requested size in pixels at which a tile is rendered. Overrides the --scale option. * `--size` SIZE: The output image fits within a SIZE x SIZE square. Overrides the --scale and --tilesize options. * `-a` `--anti-aliasing`: Smooth the output image using anti-aliasing * `--ignore-visibility`: Ignore all layer visibility flags in the map file and render all layers in the output (default is to omit invisible layers). * `--hide-layer`: Specifies a layer to omit from the output image. Can be repeated to hide multiple layers. The layername is case insensitive. *Example*: `tmxrasterizer` --hide-layer collision --hide-layer otherlayer [...] ## AUTHOR Vincent Petithory <> ## SEE ALSO tiled(1), tmxviewer(1), tiled-1.0.3/man/tmxviewer.1000066400000000000000000000011641315121121300154730ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "TMXVIEWER" "1" "January 2013" "" "" . .SH "NAME" \fBtmxviewer\fR \- a simple tile map viewer . .SH "SYNOPSIS" \fBtmxviewer\fR [\fIOPTIONS\fR] [FILES\.\.\.] . .SH "DESCRIPTION" This application can be used to quickly view a map that was created by the Tiled Map Editor\. . .SH "OPTIONS" . .TP \fB\-h\fR \fB\-\-help\fR Displays the help . .TP \fB\-v\fR \fB\-\-version\fR Displays the version . .SH "AUTHORS" \fIhttps://github\.com/bjorn/tiled/blob/master/AUTHORS\fR . .SH "SEE ALSO" tiled(1), tmxrasterizer(1), \fIhttp://www\.mapeditor\.org/\fR tiled-1.0.3/man/tmxviewer.1.ronn000066400000000000000000000007311315121121300164450ustar00rootroot00000000000000tmxviewer(1) -- a simple tile map viewer ======================================== ## SYNOPSIS `tmxviewer` [] [FILE] ## DESCRIPTION This application can be used to quickly view a map that was created by the Tiled Map Editor. ## OPTIONS * `-h` `--help`: Displays the help * `-v` `--version`: Displays the version ## AUTHORS ## SEE ALSO tiled(1), tmxrasterizer(1), tiled-1.0.3/mime/000077500000000000000000000000001315121121300135315ustar00rootroot00000000000000tiled-1.0.3/mime/tiled.thumbnailer000066400000000000000000000001561315121121300170700ustar00rootroot00000000000000[Thumbnailer Entry] TryExec=tmxrasterizer Exec=tmxrasterizer --size %s %u %o MimeType=application/x-tiled-tmx tiled-1.0.3/mime/tiled.xml000066400000000000000000000010501315121121300153500ustar00rootroot00000000000000 Tiled map Tiled tileset tiled-1.0.3/mkdocs.yml000066400000000000000000000015721315121121300146120ustar00rootroot00000000000000site_name: Tiled Documentation site_favicon: http://blog.mapeditor.org/favicon.ico repo_url: https://github.com/bjorn/tiled theme: readthedocs google_analytics: ['UA-380618-1', 'mapeditor.org'] pages: - Index: index.md - Manual: - Introduction: manual/introduction.md - Working with Layers: manual/layers.md - Editing Tile Layers: manual/editing-tile-layers.md - Working with Objects: manual/objects.md - Custom Properties: manual/custom-properties.md - Using the Terrain Tool: manual/using-the-terrain-tool.md - Using Commands: manual/using-commands.md - Keyboard Shortcuts: manual/keyboard-shortcuts.md - Reference: - TMX Map Format: reference/tmx-map-format.md - TMX Changelog: reference/tmx-changelog.md - Libraries and Frameworks: reference/support-for-tmx-maps.md extra_css: - css/extra.css markdown_extensions: - toc(permalink=true) tiled-1.0.3/qbs/000077500000000000000000000000001315121121300133675ustar00rootroot00000000000000tiled-1.0.3/qbs/imports/000077500000000000000000000000001315121121300150645ustar00rootroot00000000000000tiled-1.0.3/qbs/imports/TiledPlugin.qbs000066400000000000000000000021571315121121300200200ustar00rootroot00000000000000import qbs 1.0 DynamicLibrary { Depends { name: "libtiled" } Depends { name: "cpp" } Depends { name: "Qt"; submodules: "gui" } cpp.cxxLanguageVersion: "c++11" cpp.visibility: "minimal" cpp.useRPaths: project.useRPaths cpp.rpaths: { if (qbs.targetOS.contains("darwin")) return ["@loader_path/../Frameworks"]; else if (project.linuxArchive) return ["$ORIGIN/.."] else return ["$ORIGIN/../.."]; } bundle.isBundle: false Properties { condition: qbs.targetOS.contains("macos") cpp.cxxFlags: ["-Wno-unknown-pragmas"] } Group { qbs.install: true qbs.installDir: { if (qbs.targetOS.contains("windows") || project.linuxArchive) return "plugins/tiled" else if (qbs.targetOS.contains("macos")) return "Tiled.app/Contents/PlugIns" else return "lib/tiled/plugins" } fileTagsFilter: "dynamiclibrary" } FileTagger { patterns: "plugin.json" fileTags: ["qt_plugin_metadata"] } } tiled-1.0.3/qbs/imports/TiledQtGuiApplication.qbs000066400000000000000000000015151315121121300217740ustar00rootroot00000000000000import qbs QtGuiApplication { cpp.useRPaths: project.useRPaths cpp.rpaths: { if (qbs.targetOS.contains("darwin")) return ["@loader_path/../Frameworks"]; else if (project.linuxArchive) return ["$ORIGIN/lib"] else return ["$ORIGIN/../lib"]; } cpp.cxxLanguageVersion: "c++11" Properties { condition: qbs.targetOS.contains("macos") cpp.cxxFlags: ["-Wno-unknown-pragmas"] } Group { qbs.install: true qbs.installDir: { if (qbs.targetOS.contains("windows") || project.linuxArchive) return ""; else if (qbs.targetOS.contains("darwin")) return "Tiled.app/Contents/MacOS"; else return "bin"; } fileTagsFilter: product.type } } tiled-1.0.3/src/000077500000000000000000000000001315121121300133715ustar00rootroot00000000000000tiled-1.0.3/src/automappingconverter/000077500000000000000000000000001315121121300176455ustar00rootroot00000000000000tiled-1.0.3/src/automappingconverter/automappingconverter.pro000066400000000000000000000021231315121121300246410ustar00rootroot00000000000000include(../../tiled.pri) include(../libtiled/libtiled.pri) win32|!isEmpty(TILED_LINUX_ARCHIVE) { DESTDIR = ../.. } else { DESTDIR = ../../bin } macx { QMAKE_LIBDIR += $$OUT_PWD/../../bin/Tiled.app/Contents/Frameworks } else:win32 { LIBS += -L$$OUT_PWD/../../lib } else { QMAKE_LIBDIR = $$OUT_PWD/../../lib $$QMAKE_LIBDIR } # Make sure the executable can find libtiled !win32:!macx:!cygwin:contains(RPATH, yes) { QMAKE_RPATHDIR += \$\$ORIGIN/../lib # It is not possible to use ORIGIN in QMAKE_RPATHDIR, so a bit manually QMAKE_LFLAGS += -Wl,-z,origin \'-Wl,-rpath,$$join(QMAKE_RPATHDIR, ":")\' QMAKE_RPATHDIR = } QT += widgets TARGET = automappingconverter TEMPLATE = app target.path = $${PREFIX}/bin INSTALLS += target SOURCES += main.cpp \ converterdatamodel.cpp \ convertercontrol.cpp \ converterwindow.cpp HEADERS += \ converterdatamodel.h \ convertercontrol.h \ converterwindow.h FORMS += \ converterwindow.ui manpage.path = $${PREFIX}/share/man/man1/ manpage.files += ../../man/automappingconverter.1 INSTALLS += manpage tiled-1.0.3/src/automappingconverter/automappingconverter.qbs000066400000000000000000000015541315121121300246350ustar00rootroot00000000000000import qbs 1.0 TiledQtGuiApplication { name: "automappingconverter" targetName: name Depends { name: "libtiled" } Depends { name: "Qt"; submodules: ["widgets"] } cpp.includePaths: ["."] cpp.defines: ["QT_NO_FOREACH"] consoleApplication: false files: [ "convertercontrol.cpp", "convertercontrol.h", "converterdatamodel.cpp", "converterdatamodel.h", "converterwindow.cpp", "converterwindow.h", "converterwindow.ui", "main.cpp", ] Group { name: "Man page (Linux)" condition: qbs.targetOS.contains("linux") qbs.install: true qbs.installDir: "share/man/man1" files: [ "../../man/automappingconverter.1" ] } Properties { condition: qbs.targetOS.contains("macos") targetName: "Automapping Converter" } } tiled-1.0.3/src/automappingconverter/convertercontrol.cpp000066400000000000000000000067351315121121300237740ustar00rootroot00000000000000/* * convertercontrol.cpp * Copyright 2012, Stefan Beller, stefanbeller@googlemail.com * * This file is part of the AutomappingConverter, which converts old rulemaps * of Tiled to work with the latest version of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "convertercontrol.h" #include "map.h" #include "layer.h" #include "tileset.h" #include "mapreader.h" #include "mapwriter.h" #include #include using namespace Tiled; ConverterControl::ConverterControl() { } QString ConverterControl::automappingRuleFileVersion(const QString &fileName) { Tiled::MapReader reader; Tiled::Map *map = reader.readMap(fileName); if (!map) return versionNotAMap(); // version 1 check bool hasonlyruleprefix = true; for (Tiled::Layer *layer : map->layers()) { if (!layer->name().startsWith("rule", Qt::CaseInsensitive)) hasonlyruleprefix = false; } if (hasonlyruleprefix) return version1(); // version 2 check bool hasrule = false; bool hasoutput = false; bool hasregion = false; bool allused = true; for (Tiled::Layer *layer : map->layers()) { bool isunused = true; if (layer->name().startsWith("input", Qt::CaseInsensitive)) { hasrule = true; isunused = false; } if (layer->name().startsWith("output", Qt::CaseInsensitive)) { hasoutput = true; isunused = false; } if (layer->name().toLower() == "regions") { hasregion = true; isunused = false; } if (isunused) allused = false; } if (allused && hasoutput && hasregion && hasrule) return version2(); return versionUnknown(); } void ConverterControl::convertV1toV2(const QString &fileName) { Tiled::MapReader reader; QScopedPointer map(reader.readMap(fileName)); if (!map) { qWarning() << "Error at conversion of " << fileName << ":\n" << reader.errorString(); return; } for (Tiled::Layer *layer : map->layers()) { if (layer->name().startsWith("ruleset", Qt::CaseInsensitive)) { layer->setName("Input_set"); } else if (layer->name().startsWith("rulenotset", Qt::CaseInsensitive)) { layer->setName("InputNot_set"); } else if (layer->name().startsWith("ruleregions", Qt::CaseInsensitive)) { layer->setName("Regions"); } else if (layer->name().startsWith("rule", Qt::CaseInsensitive)) { const QString newname = layer->name().right(layer->name().length() - 4); layer->setName("Output" + newname); } else { qWarning() << QString("Warning at conversion of") << fileName << QString("unused layers found"); } } Tiled::MapWriter writer; writer.writeMap(map.data(), fileName); } tiled-1.0.3/src/automappingconverter/convertercontrol.h000066400000000000000000000025551315121121300234350ustar00rootroot00000000000000/* * convertercontrol.h * Copyright 2012, Stefan Beller, stefanbeller@googlemail.com * * This file is part of the AutomappingConverter, which converts old rulemaps * of Tiled to work with the latest version of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include class ConverterControl { public: ConverterControl(); QString version1() const { return QObject::tr("v0.8 and before"); } QString version2() const { return QObject::tr("v0.9 and later"); } QString versionUnknown() const { return QObject::tr("unknown"); } QString versionNotAMap() const { return QObject::tr("not a map"); } QString automappingRuleFileVersion(const QString &fileName); void convertV1toV2(const QString &fileName); }; tiled-1.0.3/src/automappingconverter/converterdatamodel.cpp000066400000000000000000000063021315121121300242340ustar00rootroot00000000000000/* * converterdatamodel.cpp * Copyright 2012, Stefan Beller, stefanbeller@googlemail.com * * This file is part of the AutomappingConverter, which converts old rulemaps * of Tiled to work with the latest version of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "converterdatamodel.h" #include "convertercontrol.h" #include ConverterDataModel::ConverterDataModel(ConverterControl *control, QObject *parent) : QAbstractListModel(parent) { mControl = control; } int ConverterDataModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : mFileNames.count(); } int ConverterDataModel::columnCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : 2; } QVariant ConverterDataModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); const int rowIndex = index.row(); const int columnIndex = index.column(); if (rowIndex < 0 || rowIndex > mFileNames.count()) return QVariant(); switch (role) { case Qt::DisplayRole: { const QString fileName = mFileNames.at(rowIndex); if (columnIndex == 0) return fileName; else if (columnIndex == 1) return mFileVersions[fileName]; else return QVariant(); } default: return QVariant(); } } QVariant ConverterDataModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole) { switch (section) { case 0: return tr("File"); break; case 1: return tr("Version"); break; } } return QAbstractListModel::headerData(section, orientation, role); } void ConverterDataModel::insertFileNames(const QStringList &fileNames) { const int row = mFileNames.size(); beginInsertRows(QModelIndex(), row, row + fileNames.count() - 1); mFileNames.append(fileNames); for (const QString &fileName : fileNames) mFileVersions[fileName] = mControl->automappingRuleFileVersion(fileName); endInsertRows(); } void ConverterDataModel::updateVersions() { for (int i = 0; i < count(); ++i) { const QString fileName = mFileNames.at(i); const QString version = mFileVersions[fileName]; qWarning() << "processing" << fileName << "at version" << version; if (version == mControl->version1()) { mControl->convertV1toV2(fileName); mFileVersions[fileName] = mControl->version2(); } } emit dataChanged(index(0), index(count())); } tiled-1.0.3/src/automappingconverter/converterdatamodel.h000066400000000000000000000036651315121121300237120ustar00rootroot00000000000000/* * converterdatamodel.h * Copyright 2012, Stefan Beller, stefanbeller@googlemail.com * * This file is part of the AutomappingConverter, which converts old rulemaps * of Tiled to work with the latest version of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include #include #include #include class ConverterControl; class ConverterDataModel : public QAbstractListModel { Q_OBJECT public: ConverterDataModel(ConverterControl *control, QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; void insertFileNames(const QStringList &fileNames); int count() const { return mFileNames.count(); } QString fileName(int i) const { return mFileNames.at(i); } QString versionOfFile(const QString &fileName) const { return mFileVersions[fileName]; } public slots: void updateVersions(); private: ConverterControl *mControl; QList mFileNames; QMap mFileVersions; }; tiled-1.0.3/src/automappingconverter/converterwindow.cpp000066400000000000000000000044171315121121300236160ustar00rootroot00000000000000/* * converterwindow.cpp * Copyright 2011, 2012, Stefan Beller, stefanbeller@googlemail.com * * This file is part of the AutomappingConverter, which converts old rulemaps * of Tiled to work with the latest version of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "converterwindow.h" #include "ui_converterwindow.h" #include #include ConverterWindow::ConverterWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { mControl = new ConverterControl; mDataModel = new ConverterDataModel(mControl, this); ui->setupUi(this); ui->saveButton->setText(tr("Save all as %1").arg(mControl->version2())); connect(ui->addbutton, SIGNAL(clicked()), this, SLOT(addRule())); connect(ui->saveButton, SIGNAL(clicked()), mDataModel, SLOT(updateVersions())); ui->treeView->setModel(mDataModel); QHeaderView *header = ui->treeView->header(); header->setSectionResizeMode(0, QHeaderView::Stretch); header->setSectionResizeMode(1, QHeaderView::ResizeToContents); } ConverterWindow::~ConverterWindow() { delete ui; delete mControl; } void ConverterWindow::addRule() { QString filter = tr("All Files (*)"); filter += QLatin1String(";;"); QString selectedFilter = tr("Tiled map files (*.tmx)"); filter += selectedFilter; QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Open Map"), QString(), filter, &selectedFilter); if (fileNames.isEmpty()) return; mDataModel->insertFileNames(fileNames); ui->saveButton->setEnabled(true); } tiled-1.0.3/src/automappingconverter/converterwindow.h000066400000000000000000000025501315121121300232570ustar00rootroot00000000000000/* * converterwindow.h * Copyright 2011, 2012, Stefan Beller, stefanbeller@googlemail.com * * This file is part of the AutomappingConverter, which converts old rulemaps * of Tiled to work with the latest version of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "converterdatamodel.h" #include "convertercontrol.h" #include #include #include namespace Ui { class MainWindow; } class ConverterWindow : public QMainWindow { Q_OBJECT public: explicit ConverterWindow(QWidget *parent = nullptr); ~ConverterWindow(); public slots: void addRule(); private: Ui::MainWindow *ui; QString getVersion(QString filename); ConverterDataModel *mDataModel; ConverterControl *mControl; }; tiled-1.0.3/src/automappingconverter/converterwindow.ui000066400000000000000000000037071315121121300234520ustar00rootroot00000000000000 MainWindow 0 0 576 264 Tiled Automapping Rule Files Converter false true false false Add new Automapping rules Qt::Horizontal 40 20 false Save all as v0.8.0 compatible tiled-1.0.3/src/automappingconverter/main.cpp000066400000000000000000000020311315121121300212710ustar00rootroot00000000000000/* * main.cpp * Copyright 2011, Stefan Beller, stefanbeller@googlemail.com * * This file is part of the AutomappingConverter, which converts old rulemaps * of Tiled to work with the latest version of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "converterwindow.h" #include int main(int argc, char *argv[]) { QApplication a(argc, argv); ConverterWindow w; w.show(); return a.exec(); } tiled-1.0.3/src/libtiled/000077500000000000000000000000001315121121300151615ustar00rootroot00000000000000tiled-1.0.3/src/libtiled/compression.cpp000066400000000000000000000114021315121121300202240ustar00rootroot00000000000000/* * compression.cpp * Copyright 2008, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "compression.h" #if defined(Q_OS_WIN) && (QT_VERSION < 0x050600 || Q_CC_MSVC) #include "QtZlib/zlib.h" #else #include #endif #include #include #ifdef Z_PREFIX #undef compress #endif using namespace Tiled; // TODO: Improve error reporting by showing these errors in the user interface static void logZlibError(int error) { switch (error) { case Z_MEM_ERROR: qDebug() << "Out of memory while (de)compressing data!"; break; case Z_VERSION_ERROR: qDebug() << "Incompatible zlib version!"; break; case Z_NEED_DICT: case Z_DATA_ERROR: qDebug() << "Incorrect zlib compressed data!"; break; default: qDebug() << "Unknown error while (de)compressing data!"; } } QByteArray Tiled::decompress(const QByteArray &data, int expectedSize) { QByteArray out; out.resize(expectedSize); z_stream strm; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.next_in = (Bytef *) data.data(); strm.avail_in = data.length(); strm.next_out = (Bytef *) out.data(); strm.avail_out = out.size(); int ret = inflateInit2(&strm, 15 + 32); if (ret != Z_OK) { logZlibError(ret); return QByteArray(); } do { ret = inflate(&strm, Z_SYNC_FLUSH); switch (ret) { case Z_NEED_DICT: case Z_STREAM_ERROR: ret = Z_DATA_ERROR; case Z_DATA_ERROR: case Z_MEM_ERROR: inflateEnd(&strm); logZlibError(ret); return QByteArray(); } if (ret != Z_STREAM_END) { int oldSize = out.size(); out.resize(out.size() * 2); strm.next_out = (Bytef *)(out.data() + oldSize); strm.avail_out = oldSize; } } while (ret != Z_STREAM_END); if (strm.avail_in != 0) { logZlibError(Z_DATA_ERROR); return QByteArray(); } const int outLength = out.size() - strm.avail_out; inflateEnd(&strm); out.resize(outLength); return out; } QByteArray Tiled::compress(const QByteArray &data, CompressionMethod method) { QByteArray out; out.resize(1024); int err; z_stream strm; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.next_in = (Bytef *) data.data(); strm.avail_in = data.length(); strm.next_out = (Bytef *) out.data(); strm.avail_out = out.size(); const int windowBits = (method == Gzip) ? 15 + 16 : 15; err = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY); if (err != Z_OK) { logZlibError(err); return QByteArray(); } do { err = deflate(&strm, Z_FINISH); Q_ASSERT(err != Z_STREAM_ERROR); if (err == Z_OK) { // More output space needed int oldSize = out.size(); out.resize(out.size() * 2); strm.next_out = (Bytef *)(out.data() + oldSize); strm.avail_out = oldSize; } } while (err == Z_OK); if (err != Z_STREAM_END) { logZlibError(err); deflateEnd(&strm); return QByteArray(); } const int outLength = out.size() - strm.avail_out; deflateEnd(&strm); out.resize(outLength); return out; } tiled-1.0.3/src/libtiled/compression.h000066400000000000000000000051231315121121300176740ustar00rootroot00000000000000/* * compression.h * Copyright 2008, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "tiled_global.h" class QByteArray; namespace Tiled { enum CompressionMethod { Gzip, Zlib }; /** * Decompresses either zlib or gzip compressed memory. Returns a null * QByteArray if decompressing failed. * * Needed because qUncompress does not support gzip compressed data. Also, * this method does not need the expected size to be prepended to the data, * but it can be passed as optional parameter. * * @param data the compressed data * @param expectedSize the expected size of the uncompressed data in bytes * @return the uncompressed data, or a null QByteArray if decompressing failed */ QByteArray TILEDSHARED_EXPORT decompress(const QByteArray &data, int expectedSize = 1024); /** * Compresses the give data in either gzip or zlib format. Returns a null * QByteArray if compression failed. * * Needed because qCompress does not support gzip compression. * * @param data the uncompressed data * @return the compressed data, or a null QByteArray if compression failed */ QByteArray TILEDSHARED_EXPORT compress(const QByteArray &data, CompressionMethod method = Zlib); } // namespace Tiled tiled-1.0.3/src/libtiled/filesystemwatcher.cpp000066400000000000000000000063741315121121300214410ustar00rootroot00000000000000/* * filesystemwatcher.cpp * Copyright 2011-2014, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "filesystemwatcher.h" #include #include #include #include namespace Tiled { FileSystemWatcher::FileSystemWatcher(QObject *parent) : QObject(parent), mWatcher(new QFileSystemWatcher(this)) { connect(mWatcher, SIGNAL(fileChanged(QString)), SLOT(onFileChanged(QString))); connect(mWatcher, SIGNAL(directoryChanged(QString)), SLOT(onDirectoryChanged(QString))); } void FileSystemWatcher::addPath(const QString &path) { // Just silently ignore the request when the file doesn't exist if (!QFile::exists(path)) return; QMap::iterator entry = mWatchCount.find(path); if (entry == mWatchCount.end()) { mWatcher->addPath(path); mWatchCount.insert(path, 1); } else { // Path is already being watched, increment watch count ++entry.value(); } } void FileSystemWatcher::removePath(const QString &path) { QMap::iterator entry = mWatchCount.find(path); if (entry == mWatchCount.end()) { if (QFile::exists(path)) qWarning() << "FileSystemWatcher: Path was never added:" << path; return; } // Decrement watch count --entry.value(); if (entry.value() == 0) { mWatchCount.erase(entry); mWatcher->removePath(path); } } void FileSystemWatcher::onFileChanged(const QString &path) { // If the file was replaced, the watcher is automatically removed and needs // to be re-added to keep watching it for changes. This happens commonly // with applications that do atomic saving. if (!mWatcher->files().contains(path)) if (QFile::exists(path)) mWatcher->addPath(path); emit fileChanged(path); } void FileSystemWatcher::onDirectoryChanged(const QString &path) { emit directoryChanged(path); } } // namespace Tiled tiled-1.0.3/src/libtiled/filesystemwatcher.h000066400000000000000000000044331315121121300211000ustar00rootroot00000000000000/* * filesystemwatcher.h * Copyright 2011-2014, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "tiled_global.h" #include #include class QFileSystemWatcher; namespace Tiled { /** * A wrapper around QFileSystemWatcher that deals gracefully with files being * watched multiple times. It also doesn't start complaining when a file * doesn't exist. * * It's meant to be used as drop-in replacement for QFileSystemWatcher. */ class TILEDSHARED_EXPORT FileSystemWatcher : public QObject { Q_OBJECT public: explicit FileSystemWatcher(QObject *parent = nullptr); void addPath(const QString &path); void removePath(const QString &path); signals: void fileChanged(const QString &path); void directoryChanged(const QString &path); private slots: void onFileChanged(const QString &path); void onDirectoryChanged(const QString &path); private: QFileSystemWatcher *mWatcher; QMap mWatchCount; }; } // namespace Tiled tiled-1.0.3/src/libtiled/gidmapper.cpp000066400000000000000000000155171315121121300176460ustar00rootroot00000000000000/* * gidmapper.cpp * Copyright 2011, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "gidmapper.h" #include "compression.h" #include "tile.h" #include "tileset.h" using namespace Tiled; // Bits on the far end of the 32-bit global tile ID are used for tile flags const int FlippedHorizontallyFlag = 0x80000000; const int FlippedVerticallyFlag = 0x40000000; const int FlippedAntiDiagonallyFlag = 0x20000000; const int RotatedHexagonal120Flag = 0x10000000; /** * Default constructor. Use \l insert to initialize the gid mapper * incrementally. */ GidMapper::GidMapper() : mInvalidTile(0) { } /** * Constructor that initializes the gid mapper using the given \a tilesets. */ GidMapper::GidMapper(const QVector &tilesets) : mInvalidTile(0) { unsigned firstGid = 1; for (const SharedTileset &tileset : tilesets) { insert(firstGid, tileset.data()); firstGid += tileset->nextTileId(); } } /** * Returns the cell data matched by the given \a gid. The \a ok parameter * indicates whether an error occurred. */ Cell GidMapper::gidToCell(unsigned gid, bool &ok) const { Cell result; // Read out the flags result.setFlippedHorizontally(gid & FlippedHorizontallyFlag); result.setFlippedVertically(gid & FlippedVerticallyFlag); result.setFlippedAntiDiagonally(gid & FlippedAntiDiagonallyFlag); result.setRotatedHexagonal120(gid & RotatedHexagonal120Flag); // Clear the flags gid &= ~(FlippedHorizontallyFlag | FlippedVerticallyFlag | FlippedAntiDiagonallyFlag | RotatedHexagonal120Flag); if (gid == 0) { ok = true; } else if (isEmpty()) { ok = false; } else { // Find the tileset containing this tile QMap::const_iterator i = mFirstGidToTileset.upperBound(gid); if (i == mFirstGidToTileset.begin()) { // Invalid global tile ID, since it lies before the first tileset ok = false; } else { --i; // Navigate one tileset back since upper bound finds the next int tileId = gid - i.key(); Tileset *tileset = i.value(); result.setTile(tileset, tileId); ok = true; } } return result; } /** * Returns the global tile ID for the given \a cell. Returns 0 when the cell is * empty or when its tileset isn't known. */ unsigned GidMapper::cellToGid(const Cell &cell) const { if (cell.isEmpty()) return 0; const Tileset *tileset = cell.tileset(); // Find the first GID for the tileset QMap::const_iterator i = mFirstGidToTileset.begin(); QMap::const_iterator i_end = mFirstGidToTileset.end(); while (i != i_end && i.value() != tileset) ++i; if (i == i_end) // tileset not found return 0; unsigned gid = i.key() + cell.tileId(); if (cell.flippedHorizontally()) gid |= FlippedHorizontallyFlag; if (cell.flippedVertically()) gid |= FlippedVerticallyFlag; if (cell.flippedAntiDiagonally()) gid |= FlippedAntiDiagonallyFlag; if (cell.rotatedHexagonal120()) gid |= RotatedHexagonal120Flag; return gid; } /** * Encodes the tile layer data of the given \a tileLayer in the given * \a format. This function should only be used for base64 encoding, with or * without compression. */ QByteArray GidMapper::encodeLayerData(const TileLayer &tileLayer, Map::LayerDataFormat format) const { Q_ASSERT(format != Map::XML); Q_ASSERT(format != Map::CSV); QByteArray tileData; tileData.reserve(tileLayer.height() * tileLayer.width() * 4); for (int y = 0; y < tileLayer.height(); ++y) { for (int x = 0; x < tileLayer.width(); ++x) { const unsigned gid = cellToGid(tileLayer.cellAt(x, y)); tileData.append((char) (gid)); tileData.append((char) (gid >> 8)); tileData.append((char) (gid >> 16)); tileData.append((char) (gid >> 24)); } } if (format == Map::Base64Gzip) tileData = compress(tileData, Gzip); else if (format == Map::Base64Zlib) tileData = compress(tileData, Zlib); return tileData.toBase64(); } GidMapper::DecodeError GidMapper::decodeLayerData(TileLayer &tileLayer, const QByteArray &layerData, Map::LayerDataFormat format) const { Q_ASSERT(format != Map::XML); Q_ASSERT(format != Map::CSV); QByteArray decodedData = QByteArray::fromBase64(layerData); const int size = (tileLayer.width() * tileLayer.height()) * 4; if (format == Map::Base64Gzip || format == Map::Base64Zlib) decodedData = decompress(decodedData, size); if (size != decodedData.length()) return CorruptLayerData; const unsigned char *data = reinterpret_cast(decodedData.constData()); int x = 0; int y = 0; bool ok; for (int i = 0; i < size - 3; i += 4) { const unsigned gid = data[i] | data[i + 1] << 8 | data[i + 2] << 16 | data[i + 3] << 24; const Cell result = gidToCell(gid, ok); if (!ok) { mInvalidTile = gid; return isEmpty() ? TileButNoTilesets : InvalidTile; } tileLayer.setCell(x, y, result); x++; if (x == tileLayer.width()) { x = 0; y++; } } return NoError; } tiled-1.0.3/src/libtiled/gidmapper.h000066400000000000000000000061031315121121300173020ustar00rootroot00000000000000/* * gidmapper.h * Copyright 2011, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "map.h" #include "tilelayer.h" #include namespace Tiled { /** * A class that maps cells to global IDs (gids) and back. */ class TILEDSHARED_EXPORT GidMapper { public: GidMapper(); GidMapper(const QVector &tilesets); void insert(unsigned firstGid, Tileset *tileset); void clear(); bool isEmpty() const; Cell gidToCell(unsigned gid, bool &ok) const; unsigned cellToGid(const Cell &cell) const; QByteArray encodeLayerData(const TileLayer &tileLayer, Map::LayerDataFormat format) const; enum DecodeError { NoError = 0, CorruptLayerData, TileButNoTilesets, InvalidTile }; DecodeError decodeLayerData(TileLayer &tileLayer, const QByteArray &layerData, Map::LayerDataFormat format) const; unsigned invalidTile() const; private: QMap mFirstGidToTileset; mutable unsigned mInvalidTile; }; /** * Insert the given \a tileset with \a firstGid as its first global ID. */ inline void GidMapper::insert(unsigned firstGid, Tileset *tileset) { mFirstGidToTileset.insert(firstGid, tileset); } /** * Clears the gid mapper, so that it can be reused. */ inline void GidMapper::clear() { mFirstGidToTileset.clear(); } /** * Returns true when no tilesets are known to this gid mapper. */ inline bool GidMapper::isEmpty() const { return mFirstGidToTileset.isEmpty(); } /** * Returns the GID of the invalid tile in case decodeLayerData() returns * the InvalidTile error. */ inline unsigned GidMapper::invalidTile() const { return mInvalidTile; } } // namespace Tiled tiled-1.0.3/src/libtiled/grouplayer.cpp000066400000000000000000000060611315121121300200610ustar00rootroot00000000000000/* * grouplayer.cpp * Copyright 2017, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "grouplayer.h" #include "map.h" namespace Tiled { GroupLayer::GroupLayer(const QString &name, int x, int y): Layer(GroupLayerType, name, x, y) { } GroupLayer::~GroupLayer() { qDeleteAll(mLayers); } void GroupLayer::addLayer(Layer *layer) { adoptLayer(layer); mLayers.append(layer); } void GroupLayer::insertLayer(int index, Layer *layer) { adoptLayer(layer); mLayers.insert(index, layer); } void GroupLayer::adoptLayer(Layer *layer) { layer->setParentLayer(this); if (map()) map()->adoptLayer(layer); else layer->setMap(nullptr); } Layer *GroupLayer::takeLayerAt(int index) { Layer *layer = mLayers.takeAt(index); layer->setMap(nullptr); layer->setParentLayer(nullptr); return layer; } bool GroupLayer::isEmpty() const { return mLayers.isEmpty(); } QSet GroupLayer::usedTilesets() const { QSet tilesets; for (const Layer *layer : mLayers) tilesets |= layer->usedTilesets(); return tilesets; } bool GroupLayer::referencesTileset(const Tileset *tileset) const { for (const Layer *layer : mLayers) if (layer->referencesTileset(tileset)) return true; return false; } void GroupLayer::replaceReferencesToTileset(Tileset *oldTileset, Tileset *newTileset) { const auto &children = mLayers; for (Layer *layer : children) layer->replaceReferencesToTileset(oldTileset, newTileset); } bool GroupLayer::canMergeWith(Layer *) const { // Merging group layers would be possible, but duplicating all child layers // is not the right approach. // todo: implement special case of reparenting child layers return false; } Layer *GroupLayer::mergedWith(Layer *) const { return nullptr; } GroupLayer *GroupLayer::clone() const { return initializeClone(new GroupLayer(mName, mX, mY)); } void GroupLayer::setMap(Map *map) { Layer::setMap(map); if (map) { for (Layer *layer : mLayers) map->adoptLayer(layer); } else { for (Layer *layer : mLayers) layer->setMap(nullptr); } } GroupLayer *GroupLayer::initializeClone(GroupLayer *clone) const { Layer::initializeClone(clone); for (const Layer *layer : mLayers) clone->addLayer(layer->clone()); return clone; } } // namespace Tiled tiled-1.0.3/src/libtiled/grouplayer.h000066400000000000000000000043771315121121300175360ustar00rootroot00000000000000/* * grouplayer.h * Copyright 2017, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "layer.h" #include namespace Tiled { class TILEDSHARED_EXPORT GroupLayer : public Layer { public: GroupLayer(const QString &name, int x, int y); ~GroupLayer(); int layerCount() const; Layer *layerAt(int index) const; const QList &layers() const { return mLayers; } void addLayer(Layer *layer); void insertLayer(int index, Layer *layer); Layer *takeLayerAt(int index); bool isEmpty() const override; QSet usedTilesets() const override; bool referencesTileset(const Tileset *tileset) const override; void replaceReferencesToTileset(Tileset *oldTileset, Tileset *newTileset) override; bool canMergeWith(Layer *other) const override; Layer *mergedWith(Layer *other) const override; GroupLayer *clone() const override; // Enable easy iteration over children with range-based for QList::iterator begin() { return mLayers.begin(); } QList::iterator end() { return mLayers.end(); } QList::const_iterator begin() const { return mLayers.begin(); } QList::const_iterator end() const { return mLayers.end(); } protected: void setMap(Map *map) override; GroupLayer *initializeClone(GroupLayer *clone) const; private: void adoptLayer(Layer *layer); QList mLayers; }; inline int GroupLayer::layerCount() const { return mLayers.size(); } inline Layer *GroupLayer::layerAt(int index) const { return mLayers.at(index); } } // namespace Tiled tiled-1.0.3/src/libtiled/hex.cpp000066400000000000000000000074471315121121300164650ustar00rootroot00000000000000/* * hex.cpp * Copyright 2017, Benjamin Trotter * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "hex.h" using namespace Tiled; Hex::Hex(int x, int y, int z): mX(x), mY(y), mZ(z) { } Hex::Hex(QPoint point, Map::StaggerIndex staggerIndex, Map::StaggerAxis staggerAxis) { setStaggered(point.x(), point.y(), staggerIndex, staggerAxis); } Hex::Hex(int col, int row, Map::StaggerIndex staggerIndex, Map::StaggerAxis staggerAxis) { setStaggered(col, row, staggerIndex, staggerAxis); } void Hex::setStaggered(int col, int row, Map::StaggerIndex staggerIndex, Map::StaggerAxis staggerAxis) { if (staggerAxis == Map::StaggerX) { if (staggerIndex == Map::StaggerEven) { mX = col; mZ = row - (col + (col & 1)) / 2; mY = -mX - mZ; } else { mX = col; mZ = row - (col - (col & 1)) / 2; mY = -mX - mZ; } } else { if (staggerIndex == Map::StaggerEven) { mX = col - (row + (row & 1)) / 2; mZ = row; mY = -mX - mZ; } else { mX = col - (row - (row & 1)) / 2; mZ = row; mY = -mX - mZ; } } } QPoint Hex::toStaggered(Map::StaggerIndex staggerIndex, Map::StaggerAxis staggerAxis) const { QPoint point; if (staggerAxis == Map::StaggerX) { if (staggerIndex == Map::StaggerEven) { point.setX(mX); point.setY(mZ + (mX + (mX & 1)) / 2); } else { point.setX(mX); point.setY(mZ + (mX - (mX & 1)) / 2); } } else { if (staggerIndex == Map::StaggerEven) { point.setX(mX + (mZ + (mZ & 1)) / 2); point.setY(mZ); } else { point.setX(mX + (mZ - (mZ & 1)) / 2); point.setY(mZ); } } return point; } void Hex::rotate(RotateDirection direction) { int tX = mX; if (direction == RotateLeft) { mX = -mY; mY = -mZ; mZ = -tX; } else { mX = -mZ; mZ = -mY; mY = -tX; } } Hex Hex::operator +(Hex h) const { return Hex(mX + h.x(), mY + h.y(), mZ + h.z()); } Hex Hex::operator -(Hex h) const { return Hex(mX - h.x(), mY - h.y(), mZ - h.z()); } Hex& Hex::operator +=(Hex h) { mX += h.x(); mY += h.y(); mZ += h.z(); return *this; } Hex& Hex::operator -=(Hex h) { mX -= h.x(); mY -= h.y(); mZ -= h.z(); return *this; } tiled-1.0.3/src/libtiled/hex.h000066400000000000000000000047071315121121300161260ustar00rootroot00000000000000/* * hex.h * Copyright 2017, Benjamin Trotter * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "tiled.h" #include "map.h" #include namespace Tiled { /** * Represents a hex position in cube coordinates. */ class Hex { public: Hex(int x, int y, int z); Hex(QPoint staggerPoint, Map::StaggerIndex staggerIndex, Map::StaggerAxis staggerAxis); Hex(int col, int row, Map::StaggerIndex staggerIndex, Map::StaggerAxis staggerAxis); QPoint toStaggered(Map::StaggerIndex staggerIndex, Map::StaggerAxis staggerAxis) const; void rotate(RotateDirection direction); int x() const { return mX; } int y() const { return mY; } int z() const { return mZ; } void setX(int x) { mX = x; } void setY(int y) { mY = y; } void setZ(int z) { mZ = z; } void setStaggered(int col, int row, Map::StaggerIndex staggerIndex, Map::StaggerAxis staggerAxis); Hex operator +(Hex h) const; Hex operator -(Hex h) const; Hex& operator +=(Hex h); Hex& operator -=(Hex h); private: int mX; int mY; int mZ; }; } // namespace Tiled tiled-1.0.3/src/libtiled/hexagonalrenderer.cpp000066400000000000000000000472771315121121300214030ustar00rootroot00000000000000/* * hexagonalrenderer.cpp * Copyright 2011-2014, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "hexagonalrenderer.h" #include "map.h" #include "mapobject.h" #include "tile.h" #include "tilelayer.h" #include "tileset.h" #include #include #include using namespace Tiled; HexagonalRenderer::RenderParams::RenderParams(const Map *map) : tileWidth(map->tileWidth() & ~1) , tileHeight(map->tileHeight() & ~1) , sideLengthX(0) , sideLengthY(0) , staggerX(map->staggerAxis() == Map::StaggerX) , staggerEven(map->staggerIndex() == Map::StaggerEven) { if (map->orientation() == Map::Hexagonal) { if (staggerX) sideLengthX = map->hexSideLength(); else sideLengthY = map->hexSideLength(); } sideOffsetX = (tileWidth - sideLengthX) / 2; sideOffsetY = (tileHeight - sideLengthY) / 2; columnWidth = sideOffsetX + sideLengthX; rowHeight = sideOffsetY + sideLengthY; } QSize HexagonalRenderer::mapSize() const { const RenderParams p(map()); // The map size is the same regardless of which indexes are shifted. if (p.staggerX) { QSize size(map()->width() * p.columnWidth + p.sideOffsetX, map()->height() * (p.tileHeight + p.sideLengthY)); if (map()->width() > 1) size.rheight() += p.rowHeight; return size; } else { QSize size(map()->width() * (p.tileWidth + p.sideLengthX), map()->height() * p.rowHeight + p.sideOffsetY); if (map()->height() > 1) size.rwidth() += p.columnWidth; return size; } } QRect HexagonalRenderer::boundingRect(const QRect &rect) const { const RenderParams p(map()); QPoint topLeft = tileToScreenCoords(rect.topLeft()).toPoint(); int width, height; if (p.staggerX) { width = rect.width() * p.columnWidth + p.sideOffsetX; height = rect.height() * (p.tileHeight + p.sideLengthY); if (rect.width() > 1) { height += p.rowHeight; if (p.doStaggerX(rect.x())) topLeft.ry() -= p.rowHeight; } } else { width = rect.width() * (p.tileWidth + p.sideLengthX); height = rect.height() * p.rowHeight + p.sideOffsetY; if (rect.height() > 1) { width += p.columnWidth; if (p.doStaggerY(rect.y())) topLeft.rx() -= p.columnWidth; } } return QRect(topLeft.x(), topLeft.y(), width, height); } void HexagonalRenderer::drawGrid(QPainter *painter, const QRectF &exposed, QColor gridColor) const { QRect rect = exposed.toAlignedRect(); if (rect.isNull()) return; const RenderParams p(map()); // Determine the tile and pixel coordinates to start at QPoint startTile = screenToTileCoords(rect.topLeft()).toPoint(); QPoint startPos = tileToScreenCoords(startTile).toPoint(); /* Determine in which half of the tile the top-left corner of the area we * need to draw is. If we're in the upper half, we need to start one row * up due to those tiles being visible as well. How we go up one row * depends on whether we're in the left or right half of the tile. */ const bool inUpperHalf = rect.y() - startPos.y() < p.sideOffsetY; const bool inLeftHalf = rect.x() - startPos.x() < p.sideOffsetX; if (inUpperHalf) startTile.ry()--; if (inLeftHalf) startTile.rx()--; startTile.setX(qMax(0, startTile.x())); startTile.setY(qMax(0, startTile.y())); startPos = tileToScreenCoords(startTile).toPoint(); const QPoint oct[8] = { QPoint(0, p.tileHeight - p.sideOffsetY), QPoint(0, p.sideOffsetY), QPoint(p.sideOffsetX, 0), QPoint(p.tileWidth - p.sideOffsetX, 0), QPoint(p.tileWidth, p.sideOffsetY), QPoint(p.tileWidth, p.tileHeight - p.sideOffsetY), QPoint(p.tileWidth - p.sideOffsetX, p.tileHeight), QPoint(p.sideOffsetX, p.tileHeight) }; QVector lines; lines.reserve(8); QPen gridPen = makeGridPen(painter->device(), gridColor); painter->setPen(gridPen); if (p.staggerX) { // Odd row shifting is applied in the rendering loop, so un-apply it here if (p.doStaggerX(startTile.x())) startPos.ry() -= p.rowHeight; for (; startPos.x() <= rect.right() && startTile.x() < map()->width(); startTile.rx()++) { QPoint rowTile = startTile; QPoint rowPos = startPos; if (p.doStaggerX(startTile.x())) rowPos.ry() += p.rowHeight; for (; rowPos.y() <= rect.bottom() && rowTile.y() < map()->height(); rowTile.ry()++) { lines.append(QLine(rowPos + oct[1], rowPos + oct[2])); lines.append(QLine(rowPos + oct[2], rowPos + oct[3])); lines.append(QLine(rowPos + oct[3], rowPos + oct[4])); const bool isStaggered = p.doStaggerX(startTile.x()); const bool lastRow = rowTile.y() == map()->height() - 1; const bool lastColumn = rowTile.x() == map()->width() - 1; const bool bottomLeft = rowTile.x() == 0 || (lastRow && isStaggered); const bool bottomRight = lastColumn || (lastRow && isStaggered); if (bottomRight) lines.append(QLine(rowPos + oct[5], rowPos + oct[6])); if (lastRow) lines.append(QLine(rowPos + oct[6], rowPos + oct[7])); if (bottomLeft) lines.append(QLine(rowPos + oct[7], rowPos + oct[0])); painter->drawLines(lines); lines.resize(0); rowPos.ry() += p.tileHeight + p.sideLengthY; } startPos.rx() += p.columnWidth; } } else { // Odd row shifting is applied in the rendering loop, so un-apply it here if (p.doStaggerY(startTile.y())) startPos.rx() -= p.columnWidth; for (; startPos.y() <= rect.bottom() && startTile.y() < map()->height(); startTile.ry()++) { QPoint rowTile = startTile; QPoint rowPos = startPos; if (p.doStaggerY(startTile.y())) rowPos.rx() += p.columnWidth; for (; rowPos.x() <= rect.right() && rowTile.x() < map()->width(); rowTile.rx()++) { lines.append(QLine(rowPos + oct[0], rowPos + oct[1])); lines.append(QLine(rowPos + oct[1], rowPos + oct[2])); lines.append(QLine(rowPos + oct[3], rowPos + oct[4])); const bool isStaggered = p.doStaggerY(startTile.y()); const bool lastRow = rowTile.y() == map()->height() - 1; const bool lastColumn = rowTile.x() == map()->width() - 1; const bool bottomLeft = lastRow || (rowTile.x() == 0 && !isStaggered); const bool bottomRight = lastRow || (lastColumn && isStaggered); if (lastColumn) lines.append(QLine(rowPos + oct[4], rowPos + oct[5])); if (bottomRight) lines.append(QLine(rowPos + oct[5], rowPos + oct[6])); if (bottomLeft) lines.append(QLine(rowPos + oct[7], rowPos + oct[0])); painter->drawLines(lines); lines.resize(0); rowPos.rx() += p.tileWidth + p.sideLengthX; } startPos.ry() += p.rowHeight; } } } void HexagonalRenderer::drawTileLayer(QPainter *painter, const TileLayer *layer, const QRectF &exposed) const { const RenderParams p(map()); QRect rect = exposed.toAlignedRect(); if (rect.isNull()) rect = boundingRect(layer->bounds()); QMargins drawMargins = layer->drawMargins(); drawMargins.setBottom(drawMargins.bottom() + p.tileHeight); drawMargins.setRight(drawMargins.right() - p.tileWidth); rect.adjust(-drawMargins.right(), -drawMargins.bottom(), drawMargins.left(), drawMargins.top()); // Determine the tile and pixel coordinates to start at QPoint startTile = screenToTileCoords(rect.topLeft()).toPoint(); // Compensate for the layer position startTile -= layer->position(); QPoint startPos = tileToScreenCoords(startTile + layer->position()).toPoint(); /* Determine in which half of the tile the top-left corner of the area we * need to draw is. If we're in the upper half, we need to start one row * up due to those tiles being visible as well. How we go up one row * depends on whether we're in the left or right half of the tile. */ const bool inUpperHalf = rect.y() - startPos.y() < p.sideOffsetY; const bool inLeftHalf = rect.x() - startPos.x() < p.sideOffsetX; if (inUpperHalf) startTile.ry()--; if (inLeftHalf) startTile.rx()--; CellRenderer renderer(painter, CellRenderer::HexagonalCells); if (p.staggerX) { startTile.setX(qMax(-1, startTile.x())); startTile.setY(qMax(-1, startTile.y())); startPos = tileToScreenCoords(startTile + layer->position()).toPoint(); startPos.ry() += p.tileHeight; bool staggeredRow = p.doStaggerX(startTile.x() + layer->x()); for (; startPos.y() < rect.bottom() && startTile.y() < layer->height();) { QPoint rowTile = startTile; QPoint rowPos = startPos; for (; rowPos.x() < rect.right() && rowTile.x() < layer->width(); rowTile.rx() += 2) { if (layer->contains(rowTile)) { const Cell &cell = layer->cellAt(rowTile); if (!cell.isEmpty()) { Tile *tile = cell.tile(); QSize size = tile ? tile->size() : map()->tileSize(); renderer.render(cell, rowPos, size, CellRenderer::BottomLeft); } } rowPos.rx() += p.tileWidth + p.sideLengthX; } if (staggeredRow) { startTile.rx() -= 1; startTile.ry() += 1; startPos.rx() -= p.columnWidth; staggeredRow = false; } else { startTile.rx() += 1; startPos.rx() += p.columnWidth; staggeredRow = true; } startPos.ry() += p.rowHeight; } } else { startTile.setX(qMax(0, startTile.x())); startTile.setY(qMax(0, startTile.y())); startPos = tileToScreenCoords(startTile + layer->position()).toPoint(); startPos.ry() += p.tileHeight; // Odd row shifting is applied in the rendering loop, so un-apply it here if (p.doStaggerY(startTile.y() + layer->y())) startPos.rx() -= p.columnWidth; for (; startPos.y() < rect.bottom() && startTile.y() < layer->height(); startTile.ry()++) { QPoint rowTile = startTile; QPoint rowPos = startPos; if (p.doStaggerY(startTile.y() + layer->y())) rowPos.rx() += p.columnWidth; for (; rowPos.x() < rect.right() && rowTile.x() < layer->width(); rowTile.rx()++) { const Cell &cell = layer->cellAt(rowTile); if (!cell.isEmpty()) { Tile *tile = cell.tile(); QSize size = tile ? tile->size() : map()->tileSize(); renderer.render(cell, rowPos, size, CellRenderer::BottomLeft); } rowPos.rx() += p.tileWidth + p.sideLengthX; } startPos.ry() += p.rowHeight; } } } void HexagonalRenderer::drawTileSelection(QPainter *painter, const QRegion ®ion, const QColor &color, const QRectF &exposed) const { painter->setBrush(color); painter->setPen(Qt::NoPen); foreach (const QRect &r, region.rects()) { for (int y = r.top(); y <= r.bottom(); ++y) { for (int x = r.left(); x <= r.right(); ++x) { const QPolygonF polygon = tileToScreenPolygon(x, y); if (QRectF(polygon.boundingRect()).intersects(exposed)) painter->drawConvexPolygon(polygon); } } } } QPointF HexagonalRenderer::tileToPixelCoords(qreal x, qreal y) const { return HexagonalRenderer::tileToScreenCoords(x, y); } QPointF HexagonalRenderer::pixelToTileCoords(qreal x, qreal y) const { return HexagonalRenderer::screenToTileCoords(x, y); } /** * Converts screen to tile coordinates. Sub-tile return values are not * supported by this renderer. */ QPointF HexagonalRenderer::screenToTileCoords(qreal x, qreal y) const { const RenderParams p(map()); if (p.staggerX) x -= p.staggerEven ? p.tileWidth : p.sideOffsetX; else y -= p.staggerEven ? p.tileHeight : p.sideOffsetY; // Start with the coordinates of a grid-aligned tile QPoint referencePoint = QPoint(qFloor(x / (p.columnWidth * 2)), qFloor(y / (p.rowHeight * 2))); // Relative x and y position on the base square of the grid-aligned tile const QVector2D rel(x - referencePoint.x() * (p.columnWidth * 2), y - referencePoint.y() * (p.rowHeight * 2)); // Adjust the reference point to the correct tile coordinates int &staggerAxisIndex = p.staggerX ? referencePoint.rx() : referencePoint.ry(); staggerAxisIndex *= 2; if (p.staggerEven) ++staggerAxisIndex; // Determine the nearest hexagon tile by the distance to the center QVector2D centers[4]; if (p.staggerX) { const int left = p.sideLengthX / 2; const int centerX = left + p.columnWidth; const int centerY = p.tileHeight / 2; centers[0] = QVector2D(left, centerY); centers[1] = QVector2D(centerX, centerY - p.rowHeight); centers[2] = QVector2D(centerX, centerY + p.rowHeight); centers[3] = QVector2D(centerX + p.columnWidth, centerY); } else { const int top = p.sideLengthY / 2; const int centerX = p.tileWidth / 2; const int centerY = top + p.rowHeight; centers[0] = QVector2D(centerX, top); centers[1] = QVector2D(centerX - p.columnWidth, centerY); centers[2] = QVector2D(centerX + p.columnWidth, centerY); centers[3] = QVector2D(centerX, centerY + p.rowHeight); } int nearest = 0; qreal minDist = std::numeric_limits::max(); for (int i = 0; i < 4; ++i) { const QVector2D ¢er = centers[i]; const qreal dc = (center - rel).lengthSquared(); if (dc < minDist) { minDist = dc; nearest = i; } } static const QPoint offsetsStaggerX[4] = { QPoint( 0, 0), QPoint(+1, -1), QPoint(+1, 0), QPoint(+2, 0), }; static const QPoint offsetsStaggerY[4] = { QPoint( 0, 0), QPoint(-1, +1), QPoint( 0, +1), QPoint( 0, +2), }; const QPoint *offsets = p.staggerX ? offsetsStaggerX : offsetsStaggerY; return referencePoint + offsets[nearest]; } /** * Converts tile to screen coordinates. Sub-tile return values are not * supported by this renderer. */ QPointF HexagonalRenderer::tileToScreenCoords(qreal x, qreal y) const { const RenderParams p(map()); const int tileX = qFloor(x); const int tileY = qFloor(y); int pixelX, pixelY; if (p.staggerX) { pixelY = tileY * (p.tileHeight + p.sideLengthY); if (p.doStaggerX(tileX)) pixelY += p.rowHeight; pixelX = tileX * p.columnWidth; } else { pixelX = tileX * (p.tileWidth + p.sideLengthX); if (p.doStaggerY(tileY)) pixelX += p.columnWidth; pixelY = tileY * p.rowHeight; } return QPointF(pixelX, pixelY); } QPoint HexagonalRenderer::topLeft(int x, int y) const { if (map()->staggerAxis() == Map::StaggerY) { if ((y & 1) ^ map()->staggerIndex()) return QPoint(x, y - 1); else return QPoint(x - 1, y - 1); } else { if ((x & 1) ^ map()->staggerIndex()) return QPoint(x - 1, y); else return QPoint(x - 1, y - 1); } } QPoint HexagonalRenderer::topRight(int x, int y) const { if (map()->staggerAxis() == Map::StaggerY) { if ((y & 1) ^ map()->staggerIndex()) return QPoint(x + 1, y - 1); else return QPoint(x, y - 1); } else { if ((x & 1) ^ map()->staggerIndex()) return QPoint(x + 1, y); else return QPoint(x + 1, y - 1); } } QPoint HexagonalRenderer::bottomLeft(int x, int y) const { if (map()->staggerAxis() == Map::StaggerY) { if ((y & 1) ^ map()->staggerIndex()) return QPoint(x, y + 1); else return QPoint(x - 1, y + 1); } else { if ((x & 1) ^ map()->staggerIndex()) return QPoint(x - 1, y + 1); else return QPoint(x - 1, y); } } QPoint HexagonalRenderer::bottomRight(int x, int y) const { if (map()->staggerAxis() == Map::StaggerY) { if ((y & 1) ^ map()->staggerIndex()) return QPoint(x + 1, y + 1); else return QPoint(x, y + 1); } else { if ((x & 1) ^ map()->staggerIndex()) return QPoint(x + 1, y + 1); else return QPoint(x + 1, y); } } QPolygonF HexagonalRenderer::tileToScreenPolygon(int x, int y) const { const RenderParams p(map()); const QPointF topRight = tileToScreenCoords(x, y); QPolygonF polygon(8); polygon[0] = topRight + QPoint(0, p.tileHeight - p.sideOffsetY); polygon[1] = topRight + QPoint(0, p.sideOffsetY); polygon[2] = topRight + QPoint(p.sideOffsetX, 0); polygon[3] = topRight + QPoint(p.tileWidth - p.sideOffsetX, 0); polygon[4] = topRight + QPoint(p.tileWidth, p.sideOffsetY); polygon[5] = topRight + QPoint(p.tileWidth, p.tileHeight - p.sideOffsetY); polygon[6] = topRight + QPoint(p.tileWidth - p.sideOffsetX, p.tileHeight); polygon[7] = topRight + QPoint(p.sideOffsetX, p.tileHeight); return polygon; } tiled-1.0.3/src/libtiled/hexagonalrenderer.h000066400000000000000000000072421315121121300210340ustar00rootroot00000000000000/* * staggeredrenderer.h * Copyright 2011-2014, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "orthogonalrenderer.h" namespace Tiled { /** * A hexagonal renderer. * * Only pointy-topped hexagons are supported at the moment, shifting either the * odd or the even rows to the right. * * The same problems as present when using the StaggeredRenderer happen with * this renderer. */ class TILEDSHARED_EXPORT HexagonalRenderer : public OrthogonalRenderer { protected: struct RenderParams { RenderParams(const Map *map); bool doStaggerX(int x) const { return staggerX && (x & 1) ^ staggerEven; } bool doStaggerY(int y) const { return !staggerX && (y & 1) ^ staggerEven; } const int tileWidth; const int tileHeight; int sideLengthX; int sideOffsetX; int sideLengthY; int sideOffsetY; int rowHeight; int columnWidth; const bool staggerX; const bool staggerEven; }; public: HexagonalRenderer(const Map *map) : OrthogonalRenderer(map) {} QSize mapSize() const override; QRect boundingRect(const QRect &rect) const override; void drawGrid(QPainter *painter, const QRectF &exposed, QColor gridColor) const override; void drawTileLayer(QPainter *painter, const TileLayer *layer, const QRectF &exposed = QRectF()) const override; void drawTileSelection(QPainter *painter, const QRegion ®ion, const QColor &color, const QRectF &exposed) const override; using OrthogonalRenderer::pixelToTileCoords; QPointF pixelToTileCoords(qreal x, qreal y) const override; using OrthogonalRenderer::tileToPixelCoords; QPointF tileToPixelCoords(qreal x, qreal y) const override; using OrthogonalRenderer::screenToTileCoords; QPointF screenToTileCoords(qreal x, qreal y) const override; using OrthogonalRenderer::tileToScreenCoords; QPointF tileToScreenCoords(qreal x, qreal y) const override; // Functions specific to this type of renderer QPoint topLeft(int x, int y) const; QPoint topRight(int x, int y) const; QPoint bottomLeft(int x, int y) const; QPoint bottomRight(int x, int y) const; QPolygonF tileToScreenPolygon(int x, int y) const; }; } // namespace Tiled tiled-1.0.3/src/libtiled/imagelayer.cpp000066400000000000000000000050421315121121300200050ustar00rootroot00000000000000/* * imagelayer.cpp * Copyright 2011, Gregory Nickonov * Copyright 2012, Alexander Kuhrt * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "imagelayer.h" #include "map.h" #include using namespace Tiled; ImageLayer::ImageLayer(const QString &name, int x, int y): Layer(ImageLayerType, name, x, y) { } ImageLayer::~ImageLayer() { } void ImageLayer::resetImage() { mImage = QPixmap(); mImageSource.clear(); } bool ImageLayer::loadFromImage(const QImage &image, const QString &fileName) { mImageSource = fileName; if (image.isNull()) { mImage = QPixmap(); return false; } mImage = QPixmap::fromImage(image); if (mTransparentColor.isValid()) { const QImage mask = image.createMaskFromColor(mTransparentColor.rgb()); mImage.setMask(QBitmap::fromImage(mask)); } return true; } bool ImageLayer::isEmpty() const { return mImage.isNull(); } ImageLayer *ImageLayer::clone() const { return initializeClone(new ImageLayer(mName, mX, mY)); } ImageLayer *ImageLayer::initializeClone(ImageLayer *clone) const { Layer::initializeClone(clone); clone->mImageSource = mImageSource; clone->mTransparentColor = mTransparentColor; clone->mImage = mImage; return clone; } tiled-1.0.3/src/libtiled/imagelayer.h000066400000000000000000000101631315121121300174520ustar00rootroot00000000000000/* * imagelayer.h * Copyright 2011, Gregory Nickonov * Copyright 2012, Alexander Kuhrt * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "tiled_global.h" #include "layer.h" #include #include class QImage; namespace Tiled { /** * An image on a map. */ class TILEDSHARED_EXPORT ImageLayer : public Layer { public: /** * Constructor. */ ImageLayer(const QString &name, int x, int y); /** * Destructor. */ ~ImageLayer(); QSet usedTilesets() const override { return QSet(); } bool referencesTileset(const Tileset *) const override { return false; } void replaceReferencesToTileset(Tileset *, Tileset *) override {} bool canMergeWith(Layer *) const override { return false; } Layer *mergedWith(Layer *) const override { return nullptr; } /** * Returns the transparent color, or an invalid color if no transparent * color is used. */ const QColor &transparentColor() const { return mTransparentColor; } /** * Sets the transparent color. Pixels with this color will be masked out * when loadFromImage() is called. */ void setTransparentColor(const QColor &c) { mTransparentColor = c; } /** * Sets image source file name */ void setSource(const QString &source) { mImageSource = source; } /** * Returns the file name of the layer image. */ const QString &imageSource() const { return mImageSource; } /** * Returns the image of this layer. */ const QPixmap &image() const { return mImage; } /** * Sets the image of this layer. */ void setImage(const QPixmap &image) { mImage = image; } /** * Resets layer image. */ void resetImage(); /** * Load this layer from the given \a image. This will replace the existing * image. The \a fileName becomes the new imageSource, regardless of * whether the image could be loaded. * * @param image the image to load the layer from * @param fileName the file name of the image, which will be remembered * as the image source of this layer. * @return true if loading was successful, otherwise * returns false */ bool loadFromImage(const QImage &image, const QString &fileName); bool loadFromImage(const QString &fileName); /** * Returns true if no image source has been set. */ bool isEmpty() const override; ImageLayer *clone() const override; protected: ImageLayer *initializeClone(ImageLayer *clone) const; private: QString mImageSource; QColor mTransparentColor; QPixmap mImage; }; inline bool ImageLayer::loadFromImage(const QString &fileName) { return loadFromImage(QImage(fileName), fileName); } } // namespace Tiled tiled-1.0.3/src/libtiled/imagereference.cpp000066400000000000000000000021251315121121300206260ustar00rootroot00000000000000/* * * Copyright 2015, Your Name * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "imagereference.h" namespace Tiled { bool ImageReference::hasImage() const { return !source.isEmpty() || !data.isEmpty(); } QImage Tiled::ImageReference::create() const { if (!source.isEmpty()) return QImage(source); else if (!data.isEmpty()) return QImage::fromData(data, format); return QImage(); } } // namespace Tiled tiled-1.0.3/src/libtiled/imagereference.h000066400000000000000000000021241315121121300202720ustar00rootroot00000000000000/* * * Copyright 2015, Your Name * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include #include namespace Tiled { class ImageReference { public: ImageReference() : loaded(false) {} QString source; QColor transparentColor; QSize size; QByteArray format; QByteArray data; bool loaded; bool hasImage() const; QImage create() const; }; } // namespace Tiled tiled-1.0.3/src/libtiled/isometricrenderer.cpp000066400000000000000000000476041315121121300214250ustar00rootroot00000000000000/* * isometricrenderer.cpp * Copyright 2009-2011, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "isometricrenderer.h" #include "map.h" #include "mapobject.h" #include "tile.h" #include "tilelayer.h" #include "tileset.h" #include using namespace Tiled; QSize IsometricRenderer::mapSize() const { // Map width and height contribute equally in both directions const int side = map()->height() + map()->width(); return QSize(side * map()->tileWidth() / 2, side * map()->tileHeight() / 2); } QRect IsometricRenderer::boundingRect(const QRect &rect) const { const int tileWidth = map()->tileWidth(); const int tileHeight = map()->tileHeight(); const int originX = map()->height() * tileWidth / 2; const QPoint pos((rect.x() - (rect.y() + rect.height())) * tileWidth / 2 + originX, (rect.x() + rect.y()) * tileHeight / 2); const int side = rect.height() + rect.width(); const QSize size(side * tileWidth / 2, side * tileHeight / 2); return QRect(pos, size); } QRectF IsometricRenderer::boundingRect(const MapObject *object) const { if (object->shape() == MapObject::Text) { const QPointF topLeft = pixelToScreenCoords(object->position()); return QRectF(topLeft, object->size()); } else if (!object->cell().isEmpty()) { const QSizeF objectSize { object->size() }; QSizeF scale { 1.0, 1.0 }; QPoint tileOffset; if (const Tile *tile = object->cell().tile()) { QSize imgSize = tile->size(); if (!imgSize.isNull()) { scale = QSizeF(objectSize.width() / imgSize.width(), objectSize.height() / imgSize.height()); } tileOffset = tile->offset(); } const QPointF bottomCenter = pixelToScreenCoords(object->position()); return QRectF(bottomCenter.x() + (tileOffset.x() * scale.width()) - objectSize.width() / 2, bottomCenter.y() + (tileOffset.y() * scale.height()) - objectSize.height(), objectSize.width(), objectSize.height()).adjusted(-1, -1, 1, 1); } else if (!object->polygon().isEmpty()) { qreal extraSpace = qMax(objectLineWidth(), qreal(1)); // Make some more room for the starting dot extraSpace += objectLineWidth() * 4; const QPointF &pos = object->position(); const QPolygonF polygon = object->polygon().translated(pos); const QPolygonF screenPolygon = pixelToScreenCoords(polygon); return screenPolygon.boundingRect().adjusted(-extraSpace, -extraSpace - 1, extraSpace, extraSpace); } else { // Take the bounding rect of the projected object, and then add a few // pixels on all sides to correct for the line width. const QRectF base = pixelRectToScreenPolygon(object->bounds()).boundingRect(); const qreal extraSpace = qMax(objectLineWidth() / 2, qreal(1)); return base.adjusted(-extraSpace, -extraSpace - 1, extraSpace, extraSpace); } } QPainterPath IsometricRenderer::shape(const MapObject *object) const { QPainterPath path; if (!object->cell().isEmpty() || object->shape() == MapObject::Text) { path.addRect(boundingRect(object)); } else { switch (object->shape()) { case MapObject::Ellipse: case MapObject::Rectangle: path.addPolygon(pixelRectToScreenPolygon(object->bounds())); break; case MapObject::Polygon: case MapObject::Polyline: { const QPointF &pos = object->position(); const QPolygonF polygon = object->polygon().translated(pos); const QPolygonF screenPolygon = pixelToScreenCoords(polygon); if (object->shape() == MapObject::Polygon) { path.addPolygon(screenPolygon); } else { for (int i = 1; i < screenPolygon.size(); ++i) { path.addPolygon(lineToPolygon(screenPolygon[i - 1], screenPolygon[i])); } path.setFillRule(Qt::WindingFill); } break; } case MapObject::Text: break; // already handled above } } return path; } void IsometricRenderer::drawGrid(QPainter *painter, const QRectF &rect, QColor gridColor) const { const int tileWidth = map()->tileWidth(); const int tileHeight = map()->tileHeight(); QRect r = rect.toAlignedRect(); r.adjust(-tileWidth / 2, -tileHeight / 2, tileWidth / 2, tileHeight / 2); const int startX = qMax(qreal(0), screenToTileCoords(r.topLeft()).x()); const int startY = qMax(qreal(0), screenToTileCoords(r.topRight()).y()); const int endX = qMin(qreal(map()->width()), screenToTileCoords(r.bottomRight()).x()); const int endY = qMin(qreal(map()->height()), screenToTileCoords(r.bottomLeft()).y()); QPen gridPen = makeGridPen(painter->device(), gridColor); painter->setPen(gridPen); for (int y = startY; y <= endY; ++y) { const QPointF start = tileToScreenCoords(startX, y); const QPointF end = tileToScreenCoords(endX, y); painter->drawLine(start, end); } for (int x = startX; x <= endX; ++x) { const QPointF start = tileToScreenCoords(x, startY); const QPointF end = tileToScreenCoords(x, endY); painter->drawLine(start, end); } } void IsometricRenderer::drawTileLayer(QPainter *painter, const TileLayer *layer, const QRectF &exposed) const { const int tileWidth = map()->tileWidth(); const int tileHeight = map()->tileHeight(); if (tileWidth <= 0 || tileHeight <= 1) return; QRect rect = exposed.toAlignedRect(); if (rect.isNull()) rect = boundingRect(layer->bounds()); QMargins drawMargins = layer->drawMargins(); drawMargins.setTop(drawMargins.top() - tileHeight); drawMargins.setRight(drawMargins.right() - tileWidth); rect.adjust(-drawMargins.right(), -drawMargins.bottom(), drawMargins.left(), drawMargins.top()); // Determine the tile and pixel coordinates to start at QPointF tilePos = screenToTileCoords(rect.x(), rect.y()); QPoint rowItr = QPoint((int) std::floor(tilePos.x()), (int) std::floor(tilePos.y())); QPointF startPos = tileToScreenCoords(rowItr); startPos.rx() -= tileWidth / 2; startPos.ry() += tileHeight; // Compensate for the layer position rowItr -= QPoint(layer->x(), layer->y()); /* Determine in which half of the tile the top-left corner of the area we * need to draw is. If we're in the upper half, we need to start one row * up due to those tiles being visible as well. How we go up one row * depends on whether we're in the left or right half of the tile. */ const bool inUpperHalf = startPos.y() - rect.y() > tileHeight / 2; const bool inLeftHalf = rect.x() - startPos.x() < tileWidth / 2; if (inUpperHalf) { if (inLeftHalf) { --rowItr.rx(); startPos.rx() -= tileWidth / 2; } else { --rowItr.ry(); startPos.rx() += tileWidth / 2; } startPos.ry() -= tileHeight / 2; } // Determine whether the current row is shifted half a tile to the right bool shifted = inUpperHalf ^ inLeftHalf; CellRenderer renderer(painter); for (int y = startPos.y() * 2; y - tileHeight * 2 < rect.bottom() * 2; y += tileHeight) { QPoint columnItr = rowItr; for (int x = startPos.x(); x < rect.right(); x += tileWidth) { if (layer->contains(columnItr)) { const Cell &cell = layer->cellAt(columnItr); if (!cell.isEmpty()) { Tile *tile = cell.tile(); QSize size = tile ? tile->size() : map()->tileSize(); renderer.render(cell, QPointF(x, (float)y / 2), size, CellRenderer::BottomLeft); } } // Advance to the next column ++columnItr.rx(); --columnItr.ry(); } // Advance to the next row if (!shifted) { ++rowItr.rx(); startPos.rx() += tileWidth / 2; shifted = true; } else { ++rowItr.ry(); startPos.rx() -= tileWidth / 2; shifted = false; } } } void IsometricRenderer::drawTileSelection(QPainter *painter, const QRegion ®ion, const QColor &color, const QRectF &exposed) const { painter->setBrush(color); painter->setPen(Qt::NoPen); foreach (const QRect &r, region.rects()) { QPolygonF polygon = tileRectToScreenPolygon(r); if (QRectF(polygon.boundingRect()).intersects(exposed)) painter->drawConvexPolygon(polygon); } } void IsometricRenderer::drawMapObject(QPainter *painter, const MapObject *object, const QColor &color) const { painter->save(); QPen pen(Qt::black); pen.setCosmetic(true); const Cell &cell = object->cell(); if (!cell.isEmpty()) { const QSizeF size = object->size(); const QPointF pos = pixelToScreenCoords(object->position()); CellRenderer(painter).render(cell, pos, size, CellRenderer::BottomCenter); if (testFlag(ShowTileObjectOutlines)) { QPointF tileOffset; if (const Tile *tile = cell.tile()) tileOffset = tile->offset(); QRectF rect(QPointF(pos.x() - size.width() / 2 + tileOffset.x(), pos.y() - size.height() + tileOffset.y()), size); pen.setStyle(Qt::SolidLine); painter->setPen(pen); painter->drawRect(rect); pen.setStyle(Qt::DotLine); pen.setColor(color); painter->setPen(pen); painter->drawRect(rect); } } else if (object->shape() == MapObject::Text) { const QPointF pos = pixelToScreenCoords(object->position()); const auto& textData = object->textData(); painter->setFont(textData.font); painter->setPen(textData.color); painter->drawText(QRectF(pos, object->size()), textData.text, textData.textOption()); } else { const qreal lineWidth = objectLineWidth(); const qreal scale = painterScale(); const qreal shadowOffset = (lineWidth == 0 ? 1 : lineWidth) / scale; QColor brushColor = color; brushColor.setAlpha(50); QBrush brush(brushColor); pen.setJoinStyle(Qt::RoundJoin); pen.setCapStyle(Qt::RoundCap); pen.setWidth(lineWidth); QPen colorPen(pen); colorPen.setColor(color); painter->setPen(pen); painter->setRenderHint(QPainter::Antialiasing); // TODO: Do something sensible to make null-sized objects usable switch (object->shape()) { case MapObject::Ellipse: { QPolygonF polygon = pixelRectToScreenPolygon(object->bounds()); float tw = map()->tileWidth(); float th = map()->tileHeight(); QPointF transformScale(1, 1); if (tw > th) transformScale = QPointF(1, th/tw); else transformScale = QPointF(tw/th, 1); QPointF l1 = polygon.at(1) - polygon.at(0); QPointF l2 = polygon.at(3) - polygon.at(0); QTransform trans; trans.scale(transformScale.x(), transformScale.y()); trans.rotate(45); QTransform iTrans = trans.inverted(); QPointF l1x = iTrans.map(l1); QPointF l2x = iTrans.map(l2); QSizeF ellipseSize(l1x.manhattanLength(), l2x.manhattanLength()); if (ellipseSize.width() > 0 && ellipseSize.height() > 0) { painter->save(); painter->setPen(pen); painter->translate(polygon.at(0)); painter->scale(transformScale.x(), transformScale.y()); painter->rotate(45); painter->drawEllipse(QRectF(QPointF(0, 0), ellipseSize)); painter->restore(); } painter->setBrush(Qt::NoBrush); painter->drawPolygon(polygon); painter->setPen(colorPen); painter->setBrush(Qt::NoBrush); painter->translate(QPointF(0, -shadowOffset)); painter->drawPolygon(polygon); painter->setBrush(brush); if (ellipseSize.width() > 0 && ellipseSize.height() > 0) { painter->save(); painter->translate(polygon.at(0)); painter->scale(transformScale.x(), transformScale.y()); painter->rotate(45); painter->drawEllipse(QRectF(QPointF(0, 0), ellipseSize)); painter->restore(); } break; } case MapObject::Rectangle: { QPolygonF polygon = pixelRectToScreenPolygon(object->bounds()); painter->drawPolygon(polygon); painter->setPen(colorPen); painter->setBrush(brush); polygon.translate(0, -shadowOffset); painter->drawPolygon(polygon); break; } case MapObject::Polygon: { const QPointF &pos = object->position(); const QPolygonF polygon = object->polygon().translated(pos); QPolygonF screenPolygon = pixelToScreenCoords(polygon); QPen thickPen(pen); QPen thickColorPen(colorPen); thickPen.setWidthF(thickPen.widthF() * 4); thickColorPen.setWidthF(thickColorPen.widthF() * 4); painter->drawPolygon(screenPolygon); painter->setPen(thickPen); painter->drawPoint(screenPolygon.first()); painter->setPen(colorPen); painter->setBrush(brush); screenPolygon.translate(0, -shadowOffset); painter->drawPolygon(screenPolygon); painter->setPen(thickColorPen); painter->drawPoint(screenPolygon.first()); break; } case MapObject::Polyline: { const QPointF &pos = object->position(); const QPolygonF polygon = object->polygon().translated(pos); QPolygonF screenPolygon = pixelToScreenCoords(polygon); QPen thickPen(pen); QPen thickColorPen(colorPen); thickPen.setWidthF(thickPen.widthF() * 4); thickColorPen.setWidthF(thickColorPen.widthF() * 4); painter->drawPolyline(screenPolygon); painter->setPen(thickPen); painter->drawPoint(screenPolygon.first()); pen.setColor(color); painter->setPen(pen); screenPolygon.translate(0, -shadowOffset); painter->drawPolyline(screenPolygon); painter->setPen(thickColorPen); painter->drawPoint(screenPolygon.first()); break; } case MapObject::Text: break; // already handled above } } painter->restore(); } QPointF IsometricRenderer::pixelToTileCoords(qreal x, qreal y) const { const int tileHeight = map()->tileHeight(); return QPointF(x / tileHeight, y / tileHeight); } QPointF IsometricRenderer::tileToPixelCoords(qreal x, qreal y) const { const int tileHeight = map()->tileHeight(); return QPointF(x * tileHeight, y * tileHeight); } QPointF IsometricRenderer::screenToTileCoords(qreal x, qreal y) const { const int tileWidth = map()->tileWidth(); const int tileHeight = map()->tileHeight(); x -= map()->height() * tileWidth / 2; const qreal tileY = y / tileHeight; const qreal tileX = x / tileWidth; return QPointF(tileY + tileX, tileY - tileX); } QPointF IsometricRenderer::tileToScreenCoords(qreal x, qreal y) const { const int tileWidth = map()->tileWidth(); const int tileHeight = map()->tileHeight(); const int originX = map()->height() * tileWidth / 2; return QPointF((x - y) * tileWidth / 2 + originX, (x + y) * tileHeight / 2); } QPointF IsometricRenderer::screenToPixelCoords(qreal x, qreal y) const { const int tileWidth = map()->tileWidth(); const int tileHeight = map()->tileHeight(); x -= map()->height() * tileWidth / 2; const qreal tileY = y / tileHeight; const qreal tileX = x / tileWidth; return QPointF((tileY + tileX) * tileHeight, (tileY - tileX) * tileHeight); } QPointF IsometricRenderer::pixelToScreenCoords(qreal x, qreal y) const { const int tileWidth = map()->tileWidth(); const int tileHeight = map()->tileHeight(); const int originX = map()->height() * tileWidth / 2; const qreal tileY = y / tileHeight; const qreal tileX = x / tileHeight; return QPointF((tileX - tileY) * tileWidth / 2 + originX, (tileX + tileY) * tileHeight / 2); } QPolygonF IsometricRenderer::pixelRectToScreenPolygon(const QRectF &rect) const { QPolygonF polygon; polygon << QPointF(pixelToScreenCoords(rect.topLeft())); polygon << QPointF(pixelToScreenCoords(rect.topRight())); polygon << QPointF(pixelToScreenCoords(rect.bottomRight())); polygon << QPointF(pixelToScreenCoords(rect.bottomLeft())); return polygon; } QPolygonF IsometricRenderer::tileRectToScreenPolygon(const QRect &rect) const { const int tileWidth = map()->tileWidth(); const int tileHeight = map()->tileHeight(); const QPointF topRight = tileToScreenCoords(rect.topRight()); const QPointF bottomRight = tileToScreenCoords(rect.bottomRight()); const QPointF bottomLeft = tileToScreenCoords(rect.bottomLeft()); QPolygonF polygon; polygon << QPointF(tileToScreenCoords(rect.topLeft())); polygon << QPointF(topRight.x() + tileWidth / 2, topRight.y() + tileHeight / 2); polygon << QPointF(bottomRight.x(), bottomRight.y() + tileHeight); polygon << QPointF(bottomLeft.x() - tileWidth / 2, bottomLeft.y() + tileHeight / 2); return polygon; } tiled-1.0.3/src/libtiled/isometricrenderer.h000066400000000000000000000066621315121121300210710ustar00rootroot00000000000000/* * isometricrenderer.h * Copyright 2009-2010, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "maprenderer.h" namespace Tiled { /** * An isometric map renderer. * * Isometric maps have diamond shaped tiles. This map renderer renders them in * such a way that the map will also be diamond shaped. The X axis points to * the bottom right while the Y axis points to the bottom left. */ class TILEDSHARED_EXPORT IsometricRenderer : public MapRenderer { public: IsometricRenderer(const Map *map) : MapRenderer(map) {} QSize mapSize() const override; QRect boundingRect(const QRect &rect) const override; QRectF boundingRect(const MapObject *object) const override; QPainterPath shape(const MapObject *object) const override; void drawGrid(QPainter *painter, const QRectF &rect, QColor grid) const override; void drawTileLayer(QPainter *painter, const TileLayer *layer, const QRectF &exposed = QRectF()) const override; void drawTileSelection(QPainter *painter, const QRegion ®ion, const QColor &color, const QRectF &exposed) const override; void drawMapObject(QPainter *painter, const MapObject *object, const QColor &color) const override; using MapRenderer::pixelToTileCoords; QPointF pixelToTileCoords(qreal x, qreal y) const override; using MapRenderer::tileToPixelCoords; QPointF tileToPixelCoords(qreal x, qreal y) const override; using MapRenderer::screenToTileCoords; QPointF screenToTileCoords(qreal x, qreal y) const override; using MapRenderer::tileToScreenCoords; QPointF tileToScreenCoords(qreal x, qreal y) const override; using MapRenderer::screenToPixelCoords; QPointF screenToPixelCoords(qreal x, qreal y) const override; using MapRenderer::pixelToScreenCoords; QPointF pixelToScreenCoords(qreal x, qreal y) const override; private: QPolygonF pixelRectToScreenPolygon(const QRectF &rect) const; QPolygonF tileRectToScreenPolygon(const QRect &rect) const; }; } // namespace Tiled tiled-1.0.3/src/libtiled/layer.cpp000066400000000000000000000177741315121121300170210ustar00rootroot00000000000000/* * layer.cpp * Copyright 2008-2010, Thorbjørn Lindeijer * Copyright 2009, Jeff Bland * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "layer.h" #include "grouplayer.h" #include "imagelayer.h" #include "map.h" #include "objectgroup.h" #include "tilelayer.h" namespace Tiled { Layer::Layer(TypeFlag type, const QString &name, int x, int y) : Object(LayerType), mName(name), mLayerType(type), mX(x), mY(y), mOpacity(1.0f), mVisible(true), mMap(nullptr), mParentLayer(nullptr) { } /** * Returns the effective opacity, which is the opacity multiplied by the * opacity of any parent layers. */ float Layer::effectiveOpacity() const { auto opacity = mOpacity; const Layer *layer = this; while ((layer = layer->parentLayer())) opacity *= layer->opacity(); return opacity; } /** * Returns whether this layer is hidden. A visible layer may still be hidden, * when one of its parent layers is not visible. */ bool Layer::isHidden() const { const Layer *layer = this; while (layer && layer->isVisible()) layer = layer->parentLayer(); return layer; // encountered an invisible layer } /** * Returns whether the given \a candidate is this layer or one of its parents. */ bool Layer::isParentOrSelf(const Layer *candidate) const { const Layer *layer = this; while (layer != candidate && layer->parentLayer()) layer = layer->parentLayer(); return layer == candidate; } /** * Returns the depth of this layer in the hierarchy. */ int Layer::depth() const { int d = 0; GroupLayer *p = mParentLayer; while (p) { ++d; p = p->parentLayer(); } return d; } /** * Returns the index of this layer among its siblings. */ int Layer::siblingIndex() const { if (mParentLayer) return mParentLayer->layers().indexOf(const_cast(this)); if (mMap) return mMap->layers().indexOf(const_cast(this)); return 0; } /** * Returns the list of siblings of this layer, including this layer. */ QList Layer::siblings() const { if (mParentLayer) return mParentLayer->layers(); if (mMap) return mMap->layers(); return QList(); } /** * Computes the total offset. which is the offset including the offset of all * parent layers. */ QPointF Layer::totalOffset() const { auto offset = mOffset; const Layer *layer = this; while ((layer = layer->parentLayer())) offset += layer->offset(); return offset; } /** * A helper function for initializing the members of the given instance to * those of this layer. Used by subclasses when cloning. * * Layer name, position and size are not cloned, since they are assumed to have * already been passed to the constructor. Also, map ownership is not cloned, * since the clone is not added to the map. * * \return the initialized clone (the same instance that was passed in) * \sa clone() */ Layer *Layer::initializeClone(Layer *clone) const { clone->mOffset = mOffset; clone->mOpacity = mOpacity; clone->mVisible = mVisible; clone->setProperties(properties()); return clone; } TileLayer *Layer::asTileLayer() { return isTileLayer() ? static_cast(this) : nullptr; } ObjectGroup *Layer::asObjectGroup() { return isObjectGroup() ? static_cast(this) : nullptr; } ImageLayer *Layer::asImageLayer() { return isImageLayer() ? static_cast(this) : nullptr; } GroupLayer *Layer::asGroupLayer() { return isGroupLayer() ? static_cast(this) : nullptr; } Layer *LayerIterator::next() { Layer *layer = mCurrentLayer; int index = mSiblingIndex; if (!layer) { // Traverse to the first layer of the map if (mMap && index == -1 && mMap->layerCount() > 0) { layer = mMap->layerAt(0); index = 0; } else { return nullptr; } } else { // Traverse to next sibling ++index; } const auto siblings = layer->siblings(); // Traverse to parent layer if last child if (index == siblings.size()) { layer = layer->parentLayer(); index = layer ? layer->siblingIndex() : -1; } else { layer = siblings.at(index); // If next layer is a group, traverse to its first child while (layer->isGroupLayer()) { auto groupLayer = static_cast(layer); if (groupLayer->layerCount() > 0) { index = 0; layer = groupLayer->layerAt(0); } else { break; } } } mCurrentLayer = layer; mSiblingIndex = index; return layer; } Layer *LayerIterator::previous() { Layer *layer = mCurrentLayer; int index = mSiblingIndex - 1; if (!layer) { // Traverse to the last layer of the map if at the end if (mMap && index < mMap->layerCount() && mMap->layerCount() > 0) { layer = mMap->layerAt(index); } else { return nullptr; } } else { // Traverse down to last child if applicable if (layer->isGroupLayer()) { auto groupLayer = static_cast(layer); if (groupLayer->layerCount() > 0) { mSiblingIndex = groupLayer->layerCount() - 1; mCurrentLayer = groupLayer->layerAt(mSiblingIndex); return mCurrentLayer; } } // Traverse to previous sibling (possibly of a parent) do { if (index >= 0) { const auto siblings = layer->siblings(); layer = siblings.at(index); break; } layer = layer->parentLayer(); if (layer) index = layer->siblingIndex() - 1; } while (layer); } mCurrentLayer = layer; mSiblingIndex = index; return layer; } void LayerIterator::toFront() { mCurrentLayer = nullptr; mSiblingIndex = -1; } void LayerIterator::toBack() { mCurrentLayer = nullptr; mSiblingIndex = mMap ? mMap->layerCount() : -1; } /** * Returns the global layer index for the given \a layer. Obtained by iterating * the layer's map while incrementing the index until layer is found. */ int globalIndex(Layer *layer) { if (!layer) return -1; LayerIterator counter(layer->map()); int index = 0; while (counter.next() && counter.currentLayer() != layer) ++index; return index; } /** * Returns the layer at the given global \a index. * * \sa globalIndex() */ Layer *layerAtGlobalIndex(const Map *map, int index) { LayerIterator counter(map); while (counter.next() && index > 0) --index; return counter.currentLayer(); } } // namespace Tiled tiled-1.0.3/src/libtiled/layer.h000066400000000000000000000206121315121121300164470ustar00rootroot00000000000000/* * layer.h * Copyright 2008-2010, Thorbjørn Lindeijer * Copyright 2009, Jeff Bland * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "object.h" #include "tileset.h" #include #include #include #include #include namespace Tiled { class GroupLayer; class Map; class ImageLayer; class ObjectGroup; class TileLayer; /** * A map layer. */ class TILEDSHARED_EXPORT Layer : public Object { public: enum TypeFlag { TileLayerType = 0x01, ObjectGroupType = 0x02, ImageLayerType = 0x04, GroupLayerType = 0x08 }; enum { AnyLayerType = 0xFF }; /** * Constructor. */ Layer(TypeFlag type, const QString &name, int x, int y); /** * Returns the type of this layer. */ TypeFlag layerType() const { return mLayerType; } /** * Returns the name of this layer. */ const QString &name() const { return mName; } /** * Sets the name of this layer. */ void setName(const QString &name) { mName = name; } /** * Returns the opacity of this layer. */ float opacity() const { return mOpacity; } /** * Sets the opacity of this layer. */ void setOpacity(float opacity) { mOpacity = opacity; } float effectiveOpacity() const; /** * Returns the visibility of this layer. */ bool isVisible() const { return mVisible; } bool isHidden() const; /** * Sets the visibility of this layer. */ void setVisible(bool visible) { mVisible = visible; } /** * Returns the map this layer is part of. */ Map *map() const { return mMap; } /** * Returns the parent layer, if any. */ GroupLayer *parentLayer() const { return mParentLayer; } bool isParentOrSelf(const Layer *candidate) const; int depth() const; int siblingIndex() const; QList siblings() const; /** * Returns the x position of this layer (in tiles). */ int x() const { return mX; } /** * Sets the x position of this layer (in tiles). */ void setX(int x) { mX = x; } /** * Returns the y position of this layer (in tiles). */ int y() const { return mY; } /** * Sets the y position of this layer (in tiles). */ void setY(int y) { mY = y; } /** * Returns the position of this layer (in tiles). */ QPoint position() const { return QPoint(mX, mY); } /** * Sets the position of this layer (in tiles). */ void setPosition(QPoint pos) { setPosition(pos.x(), pos.y()); } void setPosition(int x, int y) { mX = x; mY = y; } void setOffset(const QPointF &offset); QPointF offset() const; QPointF totalOffset() const; virtual bool isEmpty() const = 0; /** * Computes and returns the set of tilesets used by this layer. */ virtual QSet usedTilesets() const = 0; /** * Returns whether this layer is referencing the given tileset. */ virtual bool referencesTileset(const Tileset *tileset) const = 0; /** * Replaces all references to tiles from \a oldTileset with tiles from * \a newTileset. */ virtual void replaceReferencesToTileset(Tileset *oldTileset, Tileset *newTileset) = 0; /** * Returns whether this layer can merge together with the \a other layer. */ virtual bool canMergeWith(Layer *other) const = 0; /** * Returns a newly allocated layer that is the result of merging this layer * with the \a other layer. Where relevant, the other layer is considered * to be on top of this one. * * Should only be called when canMergeWith returns true. */ virtual Layer *mergedWith(Layer *other) const = 0; /** * Returns a duplicate of this layer. The caller is responsible for the * ownership of this newly created layer. */ virtual Layer *clone() const = 0; // These functions allow checking whether this Layer is an instance of the // given subclass without relying on a dynamic_cast. bool isTileLayer() const { return mLayerType == TileLayerType; } bool isObjectGroup() const { return mLayerType == ObjectGroupType; } bool isImageLayer() const { return mLayerType == ImageLayerType; } bool isGroupLayer() const { return mLayerType == GroupLayerType; } // These actually return this layer cast to one of its subclasses. TileLayer *asTileLayer(); ObjectGroup *asObjectGroup(); ImageLayer *asImageLayer(); GroupLayer *asGroupLayer(); protected: /** * Sets the map this layer is part of. Should only be called from the * Map class. */ virtual void setMap(Map *map) { mMap = map; } void setParentLayer(GroupLayer *groupLayer) { mParentLayer = groupLayer; } Layer *initializeClone(Layer *clone) const; QString mName; TypeFlag mLayerType; int mX; int mY; QPointF mOffset; float mOpacity; bool mVisible; Map *mMap; GroupLayer *mParentLayer; friend class Map; friend class GroupLayer; }; /** * Sets the drawing offset in pixels of this layer. */ inline void Layer::setOffset(const QPointF &offset) { mOffset = offset; } /** * Returns the drawing offset in pixels of this layer. */ inline QPointF Layer::offset() const { return mOffset; } /** * An iterator for iterating over the layers of a map. When iterating forward, * group layers are traversed after their children. * * Modifying the layer hierarchy while an iterator is active will lead to * undefined results! */ class TILEDSHARED_EXPORT LayerIterator { public: LayerIterator(const Map *map); LayerIterator(Layer *start); Layer *currentLayer() const; int currentSiblingIndex() const; bool hasNextSibling() const; bool hasPreviousSibling() const; bool hasParent() const; Layer *next(); Layer *previous(); void toFront(); void toBack(); private: const Map *mMap; Layer *mCurrentLayer; int mSiblingIndex; }; /** * Iterate the given map, starting from the first layer. */ inline LayerIterator::LayerIterator(const Map *map) : mMap(map) , mCurrentLayer(nullptr) , mSiblingIndex(-1) {} /** * Iterate the layer's map, starting at the given \a layer. */ inline LayerIterator::LayerIterator(Layer *start) : mMap(start ? start->map() : nullptr) , mCurrentLayer(start) , mSiblingIndex(start ? start->siblingIndex() : -1) {} inline Layer *LayerIterator::currentLayer() const { return mCurrentLayer; } inline int LayerIterator::currentSiblingIndex() const { return mSiblingIndex; } inline bool LayerIterator::hasNextSibling() const { if (!mCurrentLayer) return false; return mSiblingIndex + 1 < mCurrentLayer->siblings().size(); } inline bool LayerIterator::hasPreviousSibling() const { return mSiblingIndex > 0; } inline bool LayerIterator::hasParent() const { return mCurrentLayer && mCurrentLayer->parentLayer(); } TILEDSHARED_EXPORT int globalIndex(Layer *layer); TILEDSHARED_EXPORT Layer *layerAtGlobalIndex(const Map *map, int index); } // namespace Tiled tiled-1.0.3/src/libtiled/libtiled-src.pri000066400000000000000000000034431315121121300202560ustar00rootroot00000000000000INCLUDEPATH += $$PWD SOURCES += $$PWD/compression.cpp \ $$PWD/filesystemwatcher.cpp \ $$PWD/gidmapper.cpp \ $$PWD/grouplayer.cpp \ $$PWD/hex.cpp \ $$PWD/hexagonalrenderer.cpp \ $$PWD/imagelayer.cpp \ $$PWD/imagereference.cpp \ $$PWD/isometricrenderer.cpp \ $$PWD/layer.cpp \ $$PWD/map.cpp \ $$PWD/mapobject.cpp \ $$PWD/mapreader.cpp \ $$PWD/maprenderer.cpp \ $$PWD/maptovariantconverter.cpp \ $$PWD/mapwriter.cpp \ $$PWD/objectgroup.cpp \ $$PWD/orthogonalrenderer.cpp \ $$PWD/plugin.cpp \ $$PWD/pluginmanager.cpp \ $$PWD/properties.cpp \ $$PWD/savefile.cpp \ $$PWD/staggeredrenderer.cpp \ $$PWD/tile.cpp \ $$PWD/tileanimationdriver.cpp \ $$PWD/tilelayer.cpp \ $$PWD/tileset.cpp \ $$PWD/tilesetformat.cpp \ $$PWD/tilesetmanager.cpp \ $$PWD/varianttomapconverter.cpp HEADERS += $$PWD/compression.h \ $$PWD/filesystemwatcher.h \ $$PWD/gidmapper.h \ $$PWD/grouplayer.h \ $$PWD/hex.h \ $$PWD/hexagonalrenderer.h \ $$PWD/imagelayer.h \ $$PWD/imagereference.h \ $$PWD/isometricrenderer.h \ $$PWD/layer.h \ $$PWD/logginginterface.h \ $$PWD/map.h \ $$PWD/mapformat.h \ $$PWD/mapobject.h \ $$PWD/mapreader.h \ $$PWD/maprenderer.h \ $$PWD/maptovariantconverter.h \ $$PWD/mapwriter.h \ $$PWD/object.h \ $$PWD/objectgroup.h \ $$PWD/orthogonalrenderer.h \ $$PWD/plugin.h \ $$PWD/pluginmanager.h \ $$PWD/properties.h \ $$PWD/savefile.h \ $$PWD/staggeredrenderer.h \ $$PWD/terrain.h \ $$PWD/tile.h \ $$PWD/tileanimationdriver.h \ $$PWD/tiled.h \ $$PWD/tiled_global.h \ $$PWD/tilelayer.h \ $$PWD/tileset.h \ $$PWD/tilesetformat.h \ $$PWD/tilesetmanager.h \ $$PWD/varianttomapconverter.h tiled-1.0.3/src/libtiled/libtiled-static.pri000066400000000000000000000000661315121121300207540ustar00rootroot00000000000000include(./libtiled-src.pri) DEFINES += TILED_LIBRARY tiled-1.0.3/src/libtiled/libtiled.pri000066400000000000000000000000451315121121300174640ustar00rootroot00000000000000INCLUDEPATH += $$PWD LIBS *= -ltiled tiled-1.0.3/src/libtiled/libtiled.pro000066400000000000000000000014421315121121300174740ustar00rootroot00000000000000include(../../tiled.pri) TEMPLATE = lib TARGET = tiled target.path = $${LIBDIR} INSTALLS += target macx { DESTDIR = ../../bin/Tiled.app/Contents/Frameworks QMAKE_LFLAGS_SONAME = -Wl,-install_name,@executable_path/../Frameworks/ } else { DESTDIR = ../../lib } DLLDESTDIR = ../.. win32 { QMAKE_PROJECT_NAME = libtiled } else { # On other platforms it is necessary to link to zlib explicitly LIBS += -lz } DEFINES += QT_NO_CAST_FROM_ASCII \ QT_NO_CAST_TO_ASCII DEFINES += TILED_LIBRARY !isEmpty(TILED_LINUX_ARCHIVE):DEFINES += TILED_LINUX_ARCHIVE contains(QT_CONFIG, reduce_exports): CONFIG += hide_symbols include(./libtiled-src.pri) contains(INSTALL_HEADERS, yes) { headers.files = $${HEADERS} headers.path = $${PREFIX}/include/tiled INSTALLS += headers } tiled-1.0.3/src/libtiled/libtiled.qbs000066400000000000000000000063741315121121300174720ustar00rootroot00000000000000import qbs 1.0 DynamicLibrary { targetName: "tiled" Depends { name: "cpp" } Depends { name: "Qt"; submodules: "gui"; versionAtLeast: "5.4" } Properties { condition: !(qbs.toolchain.contains("msvc") || (qbs.toolchain.contains("mingw") && Qt.core.versionMinor < 6)) cpp.dynamicLibraries: base.concat(["z"]) } cpp.cxxLanguageVersion: "c++11" cpp.visibility: "minimal" cpp.defines: { var defs = [ "TILED_LIBRARY", "QT_NO_CAST_FROM_ASCII", "QT_NO_CAST_TO_ASCII" ]; if (project.linuxArchive) defs.push("TILED_LINUX_ARCHIVE"); return defs; } Properties { condition: qbs.targetOS.contains("macos") cpp.cxxFlags: ["-Wno-unknown-pragmas"] } bundle.isBundle: false cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined files: [ "compression.cpp", "compression.h", "filesystemwatcher.cpp", "filesystemwatcher.h", "gidmapper.cpp", "gidmapper.h", "grouplayer.cpp", "grouplayer.h", "hex.cpp", "hex.h", "hexagonalrenderer.cpp", "hexagonalrenderer.h", "imagelayer.cpp", "imagelayer.h", "imagereference.cpp", "imagereference.h", "isometricrenderer.cpp", "isometricrenderer.h", "layer.cpp", "layer.h", "logginginterface.h", "map.cpp", "map.h", "mapformat.h", "mapobject.cpp", "mapobject.h", "mapreader.cpp", "mapreader.h", "maprenderer.cpp", "maprenderer.h", "maptovariantconverter.cpp", "maptovariantconverter.h", "mapwriter.cpp", "mapwriter.h", "objectgroup.cpp", "objectgroup.h", "object.h", "orthogonalrenderer.cpp", "orthogonalrenderer.h", "plugin.cpp", "plugin.h", "pluginmanager.cpp", "pluginmanager.h", "properties.cpp", "properties.h", "savefile.cpp", "savefile.h", "staggeredrenderer.cpp", "staggeredrenderer.h", "tile.cpp", "tileanimationdriver.cpp", "tileanimationdriver.h", "tiled_global.h", "tiled.h", "tile.h", "tilelayer.cpp", "tilelayer.h", "tileset.cpp", "tileset.h", "tilesetformat.cpp", "tilesetformat.h", "tilesetmanager.cpp", "tilesetmanager.h", "varianttomapconverter.cpp", "varianttomapconverter.h", ] Group { condition: project.installHeaders qbs.install: true qbs.installDir: "include/tiled" fileTagsFilter: "hpp" } Export { Depends { name: "cpp" } Depends { name: "Qt" submodules: ["gui"] } cpp.includePaths: "." } Group { qbs.install: true qbs.installDir: { if (qbs.targetOS.contains("windows")) return "" else if (qbs.targetOS.contains("darwin")) return "Tiled.app/Contents/Frameworks" else return "lib" } fileTagsFilter: "dynamiclibrary" } } tiled-1.0.3/src/libtiled/logginginterface.h000066400000000000000000000040441315121121300206430ustar00rootroot00000000000000/* * logginginterface.h * Copyright 2013, Samuli Tuomola * Copyright 2015, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "tiled_global.h" #include class QString; namespace Tiled { /** * An object to be added by classes that want to signal the debug console. */ class TILEDSHARED_EXPORT LoggingInterface : public QObject { Q_OBJECT public: enum OutputType { INFO, ERROR }; void log(OutputType type, const QString &message) { if (type == INFO) emit info(message); else if (type == ERROR) emit error(message); } signals: void info(const QString &message); void error(const QString &message); }; } // namespace Tiled tiled-1.0.3/src/libtiled/map.cpp000066400000000000000000000260151315121121300164460ustar00rootroot00000000000000/* * map.cpp * Copyright 2008-2010, Thorbjørn Lindeijer * Copyright 2008, Roderic Morris * Copyright 2010, Andrew G. Crowell * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "map.h" #include "layer.h" #include "objectgroup.h" #include "tile.h" #include "tilelayer.h" #include "mapobject.h" #include using namespace Tiled; Map::Map(Orientation orientation, int width, int height, int tileWidth, int tileHeight): Object(MapType), mOrientation(orientation), mRenderOrder(RightDown), mWidth(width), mHeight(height), mTileWidth(tileWidth), mTileHeight(tileHeight), mHexSideLength(0), mStaggerAxis(StaggerY), mStaggerIndex(StaggerOdd), mDrawMarginsDirty(true), mLayerDataFormat(Base64Zlib), mNextObjectId(1) { } Map::Map(const Map &map): Object(map), mOrientation(map.mOrientation), mRenderOrder(map.mRenderOrder), mWidth(map.mWidth), mHeight(map.mHeight), mTileWidth(map.mTileWidth), mTileHeight(map.mTileHeight), mHexSideLength(map.mHexSideLength), mStaggerAxis(map.mStaggerAxis), mStaggerIndex(map.mStaggerIndex), mBackgroundColor(map.mBackgroundColor), mDrawMargins(map.mDrawMargins), mDrawMarginsDirty(map.mDrawMarginsDirty), mTilesets(map.mTilesets), mLayerDataFormat(map.mLayerDataFormat), mNextObjectId(1) { for (const Layer *layer : map.mLayers) { Layer *clone = layer->clone(); clone->setMap(this); mLayers.append(clone); } } Map::~Map() { qDeleteAll(mLayers); } QMargins Map::drawMargins() const { if (mDrawMarginsDirty) recomputeDrawMargins(); return mDrawMargins; } static QMargins maxMargins(const QMargins &a, const QMargins &b) { return QMargins(qMax(a.left(), b.left()), qMax(a.top(), b.top()), qMax(a.right(), b.right()), qMax(a.bottom(), b.bottom())); } /** * Computes the extra margins due to layer offsets. These need to be taken into * account when determining the bounding rect of the map for example. */ QMargins Map::computeLayerOffsetMargins() const { QMargins offsetMargins; for (const Layer *layer : mLayers) { const QPointF offset = layer->offset(); offsetMargins = maxMargins(QMargins(std::ceil(-offset.x()), std::ceil(-offset.y()), std::ceil(offset.x()), std::ceil(offset.y())), offsetMargins); } return offsetMargins; } /** * Recomputes the draw margins for this map and each of its tilesets. Needed * after the tile offset of a tileset has changed for example. */ void Map::recomputeDrawMargins() const { int maxTileSize = 0; QMargins offsetMargins; for (const SharedTileset &tileset : mTilesets) { const QPoint offset = tileset->tileOffset(); const QSize tileSize = tileset->tileSize(); maxTileSize = std::max(maxTileSize, std::max(tileSize.width(), tileSize.height())); offsetMargins = maxMargins(QMargins(-offset.x(), -offset.y(), offset.x(), offset.y()), offsetMargins); } // We subtract the tile size of the map, since that part does not // contribute to additional margin. mDrawMargins = QMargins(offsetMargins.left(), offsetMargins.top() + maxTileSize - mTileHeight, offsetMargins.right() + maxTileSize - mTileWidth, offsetMargins.bottom()); mDrawMarginsDirty = false; } int Map::layerCount(Layer::TypeFlag type) const { int count = 0; LayerIterator iterator(this); while (Layer *layer = iterator.next()) if (layer->layerType() == type) count++; return count; } QList Map::objectGroups() const { QList layers; LayerIterator iterator(this); while (Layer *layer = iterator.next()) if (ObjectGroup *og = layer->asObjectGroup()) layers.append(og); return layers; } QList Map::tileLayers() const { QList layers; LayerIterator iterator(this); while (Layer *layer = iterator.next()) if (TileLayer *tl = layer->asTileLayer()) layers.append(tl); return layers; } void Map::addLayer(Layer *layer) { adoptLayer(layer); mLayers.append(layer); } int Map::indexOfLayer(const QString &layerName, unsigned layertypes) const { for (int index = 0; index < mLayers.size(); index++) if (layerAt(index)->name() == layerName && (layertypes & layerAt(index)->layerType())) return index; return -1; } void Map::insertLayer(int index, Layer *layer) { adoptLayer(layer); mLayers.insert(index, layer); } void Map::adoptLayer(Layer *layer) { layer->setMap(this); if (ObjectGroup *group = layer->asObjectGroup()) initializeObjectIds(*group); } Layer *Map::takeLayerAt(int index) { Layer *layer = mLayers.takeAt(index); layer->setMap(nullptr); return layer; } bool Map::addTileset(const SharedTileset &tileset) { if (mTilesets.contains(tileset)) return false; mTilesets.append(tileset); return true; } void Map::addTilesets(const QSet &tilesets) { for (const SharedTileset &tileset : tilesets) addTileset(tileset); } void Map::insertTileset(int index, const SharedTileset &tileset) { Q_ASSERT(!mTilesets.contains(tileset)); mTilesets.insert(index, tileset); } int Map::indexOfTileset(const SharedTileset &tileset) const { return mTilesets.indexOf(tileset); } void Map::removeTilesetAt(int index) { mTilesets.remove(index); } bool Map::replaceTileset(const SharedTileset &oldTileset, const SharedTileset &newTileset) { Q_ASSERT(oldTileset != newTileset); const int index = mTilesets.indexOf(oldTileset); Q_ASSERT(index != -1); const auto &layers = mLayers; for (Layer *layer : layers) { layer->replaceReferencesToTileset(oldTileset.data(), newTileset.data()); } if (mTilesets.contains(newTileset)) { mTilesets.remove(index); return false; } else { mTilesets.replace(index, newTileset); return true; } } bool Map::isTilesetUsed(const Tileset *tileset) const { for (const Layer *layer : mLayers) if (layer->referencesTileset(tileset)) return true; return false; } void Map::initializeObjectIds(ObjectGroup &objectGroup) { for (MapObject *o : objectGroup) { if (o->id() == 0) o->setId(takeNextObjectId()); } } QString Tiled::staggerAxisToString(Map::StaggerAxis staggerAxis) { switch (staggerAxis) { default: case Map::StaggerY: return QLatin1String("y"); break; case Map::StaggerX: return QLatin1String("x"); break; } } Map::StaggerAxis Tiled::staggerAxisFromString(const QString &string) { Map::StaggerAxis staggerAxis = Map::StaggerY; if (string == QLatin1String("x")) staggerAxis = Map::StaggerX; return staggerAxis; } QString Tiled::staggerIndexToString(Map::StaggerIndex staggerIndex) { switch (staggerIndex) { default: case Map::StaggerOdd: return QLatin1String("odd"); break; case Map::StaggerEven: return QLatin1String("even"); break; } } Map::StaggerIndex Tiled::staggerIndexFromString(const QString &string) { Map::StaggerIndex staggerIndex = Map::StaggerOdd; if (string == QLatin1String("even")) staggerIndex = Map::StaggerEven; return staggerIndex; } QString Tiled::orientationToString(Map::Orientation orientation) { switch (orientation) { default: case Map::Unknown: return QLatin1String("unknown"); break; case Map::Orthogonal: return QLatin1String("orthogonal"); break; case Map::Isometric: return QLatin1String("isometric"); break; case Map::Staggered: return QLatin1String("staggered"); break; case Map::Hexagonal: return QLatin1String("hexagonal"); break; } } Map::Orientation Tiled::orientationFromString(const QString &string) { Map::Orientation orientation = Map::Unknown; if (string == QLatin1String("orthogonal")) { orientation = Map::Orthogonal; } else if (string == QLatin1String("isometric")) { orientation = Map::Isometric; } else if (string == QLatin1String("staggered")) { orientation = Map::Staggered; } else if (string == QLatin1String("hexagonal")) { orientation = Map::Hexagonal; } return orientation; } QString Tiled::renderOrderToString(Map::RenderOrder renderOrder) { switch (renderOrder) { default: case Map::RightDown: return QLatin1String("right-down"); break; case Map::RightUp: return QLatin1String("right-up"); break; case Map::LeftDown: return QLatin1String("left-down"); break; case Map::LeftUp: return QLatin1String("left-up"); break; } } Map::RenderOrder Tiled::renderOrderFromString(const QString &string) { Map::RenderOrder renderOrder = Map::RightDown; if (string == QLatin1String("right-up")) { renderOrder = Map::RightUp; } else if (string == QLatin1String("left-down")) { renderOrder = Map::LeftDown; } else if (string == QLatin1String("left-up")) { renderOrder = Map::LeftUp; } return renderOrder; } tiled-1.0.3/src/libtiled/map.h000066400000000000000000000323031315121121300161100ustar00rootroot00000000000000/* * map.h * Copyright 2008-2010, Thorbjørn Lindeijer * Copyright 2008, Roderic Morris * Copyright 2010, Andrew G. Crowell * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "layer.h" #include "object.h" #include "tileset.h" #include #include #include #include namespace Tiled { class Tile; class ObjectGroup; /** * A tile map. Consists of a stack of layers, each can be either a TileLayer * or an ObjectGroup. * * It also keeps track of the list of referenced tilesets. */ class TILEDSHARED_EXPORT Map : public Object { public: /** * The orientation of the map determines how it should be rendered. An * Orthogonal map is using rectangular tiles that are aligned on a * straight grid. An Isometric map uses diamond shaped tiles that are * aligned on an isometric projected grid. A Hexagonal map uses hexagon * shaped tiles that fit into each other by shifting every other row. */ enum Orientation { Unknown, Orthogonal, Isometric, Staggered, Hexagonal }; /** * The different formats in which the tile layer data can be stored. */ enum LayerDataFormat { XML = 0, Base64 = 1, Base64Gzip = 2, Base64Zlib = 3, CSV = 4 }; /** * The order in which tiles are rendered on screen. */ enum RenderOrder { RightDown = 0, RightUp = 1, LeftDown = 2, LeftUp = 3 }; /** * Which axis is staggered. Only used by the isometric staggered and * hexagonal map renderers. */ enum StaggerAxis { StaggerX, StaggerY }; /** * When staggering, specifies whether the odd or the even rows/columns are * shifted half a tile right/down. Only used by the isometric staggered and * hexagonal map renderers. */ enum StaggerIndex { StaggerOdd = 0, StaggerEven = 1 }; /** * Constructor, taking map orientation, size and tile size as parameters. */ Map(Orientation orientation, int width, int height, int tileWidth, int tileHeight); /** * Copy constructor. Makes sure that a deep-copy of the layers is created. */ Map(const Map &map); /** * Destructor. */ ~Map(); /** * Returns the orientation of the map. */ Orientation orientation() const { return mOrientation; } /** * Sets the orientation of the map. */ void setOrientation(Orientation orientation) { mOrientation = orientation; } /** * Returns the render order of the map. */ RenderOrder renderOrder() const { return mRenderOrder; } /** * Sets the render order of the map. */ void setRenderOrder(RenderOrder renderOrder) { mRenderOrder = renderOrder; } /** * Returns the width of this map in tiles. */ int width() const { return mWidth; } /** * Sets the width of this map in tiles. */ void setWidth(int width) { mWidth = width; } /** * Returns the height of this map in tiles. */ int height() const { return mHeight; } /** * Sets the height of this map in tiles. */ void setHeight(int height) { mHeight = height; } /** * Returns the size of this map. Provided for convenience. */ QSize size() const { return QSize(mWidth, mHeight); } /** * Returns the tile width of this map. */ int tileWidth() const { return mTileWidth; } /** * Sets the width of one tile. */ void setTileWidth(int width) { mTileWidth = width; } /** * Returns the tile height used by this map. */ int tileHeight() const { return mTileHeight; } /** * Sets the height of one tile. */ void setTileHeight(int height) { mTileHeight = height; } /** * Returns the size of one tile. Provided for convenience. */ QSize tileSize() const { return QSize(mTileWidth, mTileHeight); } int hexSideLength() const; void setHexSideLength(int hexSideLength); StaggerAxis staggerAxis() const; void setStaggerAxis(StaggerAxis staggerAxis); StaggerIndex staggerIndex() const; void setStaggerIndex(StaggerIndex staggerIndex); void invertStaggerIndex(); /** * Returns the margins that have to be taken into account when figuring * out which part of the map to repaint after changing some tiles. */ QMargins drawMargins() const; void invalidateDrawMargins(); QMargins computeLayerOffsetMargins() const; /** * Returns the number of layers of this map. */ int layerCount() const { return mLayers.size(); } /** * Convenience function that returns the number of layers of this map that * match the given \a type. */ int layerCount(Layer::TypeFlag type) const; int tileLayerCount() const { return layerCount(Layer::TileLayerType); } int objectGroupCount() const { return layerCount(Layer::ObjectGroupType); } int imageLayerCount() const { return layerCount(Layer::ImageLayerType); } int groupLayerCount() const { return layerCount(Layer::GroupLayerType); } /** * Returns the layer at the specified index. */ Layer *layerAt(int index) const { return mLayers.at(index); } /** * Returns the list of layers of this map. This is useful when you want to * use foreach. */ const QList &layers() const { return mLayers; } QList objectGroups() const; QList tileLayers() const; /** * Adds a layer to this map. */ void addLayer(Layer *layer); /** * Returns the index of the layer given by \a layerName, or -1 if no * layer with that name is found. * * The second optional parameter specifies the layer types which are * searched. */ int indexOfLayer(const QString &layerName, unsigned layerTypes = Layer::AnyLayerType) const; /** * Adds a layer to this map, inserting it at the given index. */ void insertLayer(int index, Layer *layer); /** * Removes the layer at the given index from this map and returns it. * The caller becomes responsible for the lifetime of this layer. */ Layer *takeLayerAt(int index); /** * Adds a tileset to this map. The map does not take ownership over its * tilesets, this is merely for keeping track of which tilesets are used by * the map, and their saving order. * * @param tileset the tileset to add * @return whether the tileset wasn't already part of the map */ bool addTileset(const SharedTileset &tileset); /** * Convenience function to be used together with Layer::usedTilesets() */ void addTilesets(const QSet &tilesets); /** * Inserts \a tileset at \a index in the list of tilesets used by this map. */ void insertTileset(int index, const SharedTileset &tileset); /** * Returns the index of the given \a tileset, or -1 if it is not used in * this map. */ int indexOfTileset(const SharedTileset &tileset) const; /** * Removes the tileset at \a index from this map. * * \warning Does not make sure that this map no longer refers to tiles from * the removed tileset! * * \sa addTileset */ void removeTilesetAt(int index); /** * Replaces all tiles from \a oldTileset with tiles from \a newTileset. * Also replaces the old tileset with the new tileset in the list of * tilesets. * * @return whether the new tileset was added to the map */ bool replaceTileset(const SharedTileset &oldTileset, const SharedTileset &newTileset); /** * Returns the number of tilesets of this map. */ int tilesetCount() const { return mTilesets.size(); } /** * Returns the tileset at the given index. */ SharedTileset tilesetAt(int index) const { return mTilesets.at(index); } /** * Returns the tilesets that the tiles on this map are using. */ const QVector &tilesets() const { return mTilesets; } /** * Returns the background color of this map. */ const QColor &backgroundColor() const { return mBackgroundColor; } /** * Sets the background color of this map. */ void setBackgroundColor(QColor color) { mBackgroundColor = color; } /** * Returns whether the given \a tileset is used by any tile layer of this * map. */ bool isTilesetUsed(const Tileset *tileset) const; /** * Returns whether the map is staggered */ bool isStaggered() const { return orientation() == Hexagonal || orientation() == Staggered; } LayerDataFormat layerDataFormat() const { return mLayerDataFormat; } void setLayerDataFormat(LayerDataFormat format) { mLayerDataFormat = format; } void setNextObjectId(int nextId); int nextObjectId() const; int takeNextObjectId(); void initializeObjectIds(ObjectGroup &objectGroup); private: friend class GroupLayer; // so it can call adoptLayer void adoptLayer(Layer *layer); void recomputeDrawMargins() const; Orientation mOrientation; RenderOrder mRenderOrder; int mWidth; int mHeight; int mTileWidth; int mTileHeight; int mHexSideLength; StaggerAxis mStaggerAxis; StaggerIndex mStaggerIndex; QColor mBackgroundColor; mutable QMargins mDrawMargins; mutable bool mDrawMarginsDirty; QList mLayers; QVector mTilesets; LayerDataFormat mLayerDataFormat; int mNextObjectId; }; inline int Map::hexSideLength() const { return mHexSideLength; } inline void Map::setHexSideLength(int hexSideLength) { mHexSideLength = hexSideLength; } inline Map::StaggerAxis Map::staggerAxis() const { return mStaggerAxis; } inline void Map::setStaggerAxis(StaggerAxis staggerAxis) { mStaggerAxis = staggerAxis; } inline Map::StaggerIndex Map::staggerIndex() const { return mStaggerIndex; } inline void Map::setStaggerIndex(StaggerIndex staggerIndex) { mStaggerIndex = staggerIndex; } inline void Map::invertStaggerIndex() { mStaggerIndex = static_cast(!mStaggerIndex); } inline void Map::invalidateDrawMargins() { mDrawMarginsDirty = true; } /** * Sets the next id to be used for objects on this map. */ inline void Map::setNextObjectId(int nextId) { Q_ASSERT(nextId > 0); mNextObjectId = nextId; } /** * Returns the next object id for this map. */ inline int Map::nextObjectId() const { return mNextObjectId; } /** * Returns the next object id for this map and allocates a new one. */ inline int Map::takeNextObjectId() { return mNextObjectId++; } TILEDSHARED_EXPORT QString staggerAxisToString(Map::StaggerAxis); TILEDSHARED_EXPORT Map::StaggerAxis staggerAxisFromString(const QString &); TILEDSHARED_EXPORT QString staggerIndexToString(Map::StaggerIndex staggerIndex); TILEDSHARED_EXPORT Map::StaggerIndex staggerIndexFromString(const QString &); /** * Helper function that converts the map orientation to a string value. Useful * for map writers. * * @return The map orientation as a lowercase string. */ TILEDSHARED_EXPORT QString orientationToString(Map::Orientation); /** * Helper function that converts a string to a map orientation enumerator. * Useful for map readers. * * @return The map orientation matching the given string, or Map::Unknown if * the string is unrecognized. */ TILEDSHARED_EXPORT Map::Orientation orientationFromString(const QString &); TILEDSHARED_EXPORT QString renderOrderToString(Map::RenderOrder renderOrder); TILEDSHARED_EXPORT Map::RenderOrder renderOrderFromString(const QString &); } // namespace Tiled Q_DECLARE_METATYPE(Tiled::Map::Orientation) Q_DECLARE_METATYPE(Tiled::Map::LayerDataFormat) Q_DECLARE_METATYPE(Tiled::Map::RenderOrder) tiled-1.0.3/src/libtiled/mapformat.h000066400000000000000000000140561315121121300173260ustar00rootroot00000000000000/* * mapformat.h * Copyright 2008-2015, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "pluginmanager.h" #include #include #include namespace Tiled { class Map; class TILEDSHARED_EXPORT FileFormat : public QObject { Q_OBJECT public: enum Capability { NoCapability = 0x0, Read = 0x1, Write = 0x2, ReadWrite = Read | Write }; Q_DECLARE_FLAGS(Capabilities, Capability) explicit FileFormat(QObject *parent = nullptr) : QObject(parent) {} /** * Returns whether this format has Read and/or Write capabilities. */ virtual Capabilities capabilities() const { return ReadWrite; } /** * Returns whether this format has all given capabilities. */ bool hasCapabilities(Capabilities caps) const { return (capabilities() & caps) == caps; } /** * Returns the absolute paths for the files that will be written by * this format for a given map. * * This is supported for Export formats only! */ virtual QStringList outputFiles(const Map *, const QString &fileName) const { return QStringList(fileName); } /** * Returns name filter for files in this map format. */ virtual QString nameFilter() const = 0; /** * Returns short name for this map format */ virtual QString shortName() const = 0; /** * Returns whether this map format supports reading the given file. * * Generally would do a file extension check. */ virtual bool supportsFile(const QString &fileName) const = 0; /** * Returns the error to be shown to the user if an error occured while * trying to read a map. */ virtual QString errorString() const = 0; }; /** * An interface to be implemented for adding support for a map format to Tiled. * It can implement support for either loading or saving to a certain map * format, or both. */ class TILEDSHARED_EXPORT MapFormat : public FileFormat { Q_OBJECT public: explicit MapFormat(QObject *parent = nullptr) : FileFormat(parent) {} /** * Reads the map and returns a new Map instance, or 0 if reading failed. */ virtual Map *read(const QString &fileName) = 0; /** * Writes the given \a map based on the suggested \a fileName. * * This function may write to a different file name or may even write to * multiple files. The actual files that will be written to can be * determined by calling outputFiles(). * * @return true on success, false when an error * occurred. The error can be retrieved by errorString(). */ virtual bool write(const Map *map, const QString &fileName) = 0; }; } // namespace Tiled Q_DECLARE_INTERFACE(Tiled::MapFormat, "org.mapeditor.MapFormat") Q_DECLARE_OPERATORS_FOR_FLAGS(Tiled::FileFormat::Capabilities) namespace Tiled { /** * Convenience class for adding a format that can only be read. */ class TILEDSHARED_EXPORT ReadableMapFormat : public MapFormat { Q_OBJECT Q_INTERFACES(Tiled::MapFormat) public: Capabilities capabilities() const override { return Read; } bool write(const Map *, const QString &) override { return false; } }; /** * Convenience class for adding a format that can only be written. */ class TILEDSHARED_EXPORT WritableMapFormat : public MapFormat { Q_OBJECT Q_INTERFACES(Tiled::MapFormat) public: Capabilities capabilities() const override { return Write; } Map *read(const QString &) override { return nullptr; } bool supportsFile(const QString &) const override { return false; } }; /** * Convenience class that can be used when implementing file dialogs. */ template class FormatHelper { public: FormatHelper(FileFormat::Capabilities capabilities, QString initialFilter = QString()) : mFilter(std::move(initialFilter)) { PluginManager::each([this,capabilities](Format *format) { if (format->hasCapabilities(capabilities)) { const QString nameFilter = format->nameFilter(); if (!mFilter.isEmpty()) mFilter += QLatin1String(";;"); mFilter += nameFilter; mFormats.append(format); mFormatByNameFilter.insert(nameFilter, format); } }); } const QString &filter() const { return mFilter; } const QList &formats() const { return mFormats; } Format *formatByNameFilter(const QString &nameFilter) const { return mFormatByNameFilter.value(nameFilter); } private: QString mFilter; QList mFormats; QMap mFormatByNameFilter; }; } // namespace Tiled tiled-1.0.3/src/libtiled/mapobject.cpp000066400000000000000000000214261315121121300176360ustar00rootroot00000000000000/* * mapobject.cpp * Copyright 2008-2013, Thorbjørn Lindeijer * Copyright 2008, Roderic Morris * Copyright 2017, Klimov Viktor * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mapobject.h" #include "map.h" #include "objectgroup.h" #include "tile.h" #include #include namespace Tiled { TextData::TextData() : font(QStringLiteral("sans-serif")) { font.setPixelSize(16); } int TextData::flags() const { return wordWrap ? (alignment | Qt::TextWordWrap) : alignment; } QTextOption TextData::textOption() const { QTextOption option(alignment); if (wordWrap) option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); else option.setWrapMode(QTextOption::ManualWrap); return option; } /** * Returns the size of the text when drawn without wrapping. */ QSizeF TextData::textSize() const { QFontMetricsF fontMetrics(font); return fontMetrics.size(0, text); } MapObject::MapObject(): Object(MapObjectType), mId(0), mSize(0, 0), mShape(Rectangle), mObjectGroup(nullptr), mRotation(0.0f), mVisible(true) { } MapObject::MapObject(const QString &name, const QString &type, const QPointF &pos, const QSizeF &size): Object(MapObjectType), mId(0), mName(name), mType(type), mPos(pos), mSize(size), mShape(Rectangle), mObjectGroup(nullptr), mRotation(0.0f), mVisible(true) { } /** * Returns the affective type of this object. This may be the type of its tile, * if the object does not have a type set explicitly. */ const QString &MapObject::effectiveType() const { if (mType.isEmpty()) if (const Tile *tile = mCell.tile()) return tile->type(); return mType; } /** * Sets the text data associated with this object. */ void MapObject::setTextData(const TextData &textData) { mTextData = textData; } /** * Shortcut to getting a QRectF from position() and size() that uses cell tile if present. */ QRectF MapObject::boundsUseTile() const { // FIXME: This is outdated code: // * It does not take into account that a tile object can be scaled. // * It neglects that origin is not the same in orthogonal and isometric // maps (see MapObject::alignment). // * It does not deal with rotation. if (const Tile *tile = mCell.tile()) { // Using the tile for determing boundary // Note the position given is the bottom-left corner so correct for that return QRectF(QPointF(mPos.x(), mPos.y() - tile->height()), tile->size()); } // No tile so just use regular bounds return bounds(); } /* * This is somewhat of a workaround for dealing with the ways different objects * align. * * Traditional rectangle objects have top-left alignment. * Tile objects have bottom-left alignment on orthogonal maps, but * bottom-center alignment on isometric maps. * * Eventually, the object alignment should probably be configurable. For * backwards compatibility, it will need to be configurable on a per-object * level. */ Alignment MapObject::alignment() const { if (mCell.isEmpty()) { return TopLeft; } else if (mObjectGroup) { if (Map *map = mObjectGroup->map()) if (map->orientation() == Map::Isometric) return Bottom; } return BottomLeft; } QVariant MapObject::mapObjectProperty(Property property) const { switch (property) { case NameProperty: return mName; case TypeProperty: return mType; case VisibleProperty: return mVisible; case TextProperty: return mTextData.text; case TextFontProperty: return mTextData.font; case TextAlignmentProperty: return QVariant::fromValue(mTextData.alignment); case TextWordWrapProperty: return mTextData.wordWrap; case TextColorProperty: return mTextData.color; } return QVariant(); } void MapObject::setMapObjectProperty(Property property, const QVariant &value) { switch (property) { case NameProperty: mName = value.toString(); break; case TypeProperty: mType = value.toString(); break; case VisibleProperty: mVisible = value.toBool(); break; case TextProperty: mTextData.text = value.toString(); break; case TextFontProperty: mTextData.font = value.value(); break; case TextAlignmentProperty: mTextData.alignment = value.value(); break; case TextWordWrapProperty: mTextData.wordWrap = value.toBool(); break; case TextColorProperty: mTextData.color = value.value(); break; } } /** * Flip this object in the given \a direction. This doesn't change the size * of the object. */ void MapObject::flip(FlipDirection direction, const QPointF &origin) { //computing new rotation and flip transform QTransform flipTransform; flipTransform.translate(origin.x(), origin.y()); qreal newRotation = 0; if (direction == FlipHorizontally) { newRotation = 180.0 - rotation(); flipTransform.scale(-1, 1); } else { //direction == FlipVertically flipTransform.scale(1, -1); newRotation = -rotation(); } flipTransform.translate(-origin.x(), -origin.y()); if (!mCell.isEmpty()) flipTileObject(flipTransform); else if (!mPolygon.isEmpty()) flipPolygonObject(flipTransform); else flipRectObject(flipTransform); //installing new rotation after computing new position setRotation(newRotation); } /** * Returns a duplicate of this object. The caller is responsible for the * ownership of this newly created object. */ MapObject *MapObject::clone() const { MapObject *o = new MapObject(mName, mType, mPos, mSize); o->setId(mId); o->setProperties(properties()); o->setTextData(mTextData); o->setPolygon(mPolygon); o->setShape(mShape); o->setCell(mCell); o->setRotation(mRotation); o->setVisible(mVisible); return o; } void MapObject::flipRectObject(const QTransform &flipTransform) { QPointF oldBottomLeftPoint = QPointF(cos(qDegreesToRadians(rotation() + 90)) * height() + x(), sin(qDegreesToRadians(rotation() + 90)) * height() + y()); QPointF newPos = flipTransform.map(oldBottomLeftPoint); setPosition(newPos); } void MapObject::flipPolygonObject(const QTransform &flipTransform) { QTransform polygonToMapTransform; polygonToMapTransform.translate(x(), y()); polygonToMapTransform.rotate(rotation()); QPointF localPolygonCenter = mPolygon.boundingRect().center(); QTransform polygonFlip; polygonFlip.translate(localPolygonCenter.x(), localPolygonCenter.y()); polygonFlip.scale(1, -1); polygonFlip.translate(-localPolygonCenter.x(), -localPolygonCenter.y()); QPointF oldBottomLeftPoint = polygonToMapTransform.map(polygonFlip.map(QPointF(0, 0))); QPointF newPos = flipTransform.map(oldBottomLeftPoint); mPolygon = polygonFlip.map(mPolygon); setPosition(newPos); } void MapObject::flipTileObject(const QTransform &flipTransform) { mCell.setFlippedVertically(!mCell.flippedVertically()); //old tile position is bottomLeftPoint QPointF topLeftTilePoint = QPointF(cos(qDegreesToRadians(rotation() - 90)) * height() + x(), sin(qDegreesToRadians(rotation() - 90)) * height() + y()); QPointF newPos = flipTransform.map(topLeftTilePoint); setPosition(newPos); } } // namespace Tiled tiled-1.0.3/src/libtiled/mapobject.h000066400000000000000000000244021315121121300173000ustar00rootroot00000000000000/* * mapobject.h * Copyright 2008-2013, Thorbjørn Lindeijer * Copyright 2008, Roderic Morris * Copyright 2009, Jeff Bland * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "object.h" #include "tiled.h" #include "tilelayer.h" #include #include #include #include #include #include namespace Tiled { class ObjectGroup; class Tile; struct TILEDSHARED_EXPORT TextData { enum FontAttributes { FontFamily = 0x1, FontSize = 0x2, FontStyle = 0x8 }; TextData(); QString text; QFont font; QColor color = Qt::black; Qt::Alignment alignment = Qt::AlignTop | Qt::AlignLeft; bool wordWrap = true; int flags() const; QTextOption textOption() const; QSizeF textSize() const; }; /** * An object on a map. Objects are positioned and scaled using floating point * values, ensuring they are not limited to the tile grid. They are suitable * for adding any kind of annotation to your maps, as well as free placement of * images. * * Common usages of objects include defining portals, monsters spawn areas, * ambient effects, scripted areas, etc. */ class TILEDSHARED_EXPORT MapObject : public Object { public: /** * Enumerates the different object shapes. Rectangle is the default shape. * When a polygon is set, the shape determines whether it should be * interpreted as a filled polygon or a line. * * Text objects contain arbitrary text, contained withih their rectangle * (in screen coordinates). */ enum Shape { Rectangle, Polygon, Polyline, Ellipse, Text }; /** * Can be used to get/set property values using QVariant. */ enum Property { NameProperty, TypeProperty, VisibleProperty, TextProperty, TextFontProperty, TextAlignmentProperty, TextWordWrapProperty, TextColorProperty }; MapObject(); MapObject(const QString &name, const QString &type, const QPointF &pos, const QSizeF &size); int id() const; void setId(int id); void resetId(); const QString &name() const; void setName(const QString &name); const QString &type() const; void setType(const QString &type); const QString &effectiveType() const; const QPointF &position() const; void setPosition(const QPointF &pos); qreal x() const; void setX(qreal x); qreal y() const; void setY(qreal y); const QSizeF &size() const; void setSize(const QSizeF &size); void setSize(qreal width, qreal height); qreal width() const; void setWidth(qreal width); qreal height() const; void setHeight(qreal height); void setBounds(const QRectF &bounds); const TextData &textData() const; void setTextData(const TextData &textData); const QPolygonF &polygon() const; void setPolygon(const QPolygonF &polygon); Shape shape() const; void setShape(Shape shape); bool isPolyShape() const; QRectF bounds() const; QRectF boundsUseTile() const; const Cell &cell() const; void setCell(const Cell &cell); ObjectGroup *objectGroup() const; void setObjectGroup(ObjectGroup *objectGroup); qreal rotation() const; void setRotation(qreal rotation); Alignment alignment() const; bool isVisible() const; void setVisible(bool visible); QVariant mapObjectProperty(Property property) const; void setMapObjectProperty(Property property, const QVariant &value); void flip(FlipDirection direction, const QPointF &origin); MapObject *clone() const; private: void flipRectObject(const QTransform &flipTransform); void flipPolygonObject(const QTransform &flipTransform); void flipTileObject(const QTransform &flipTransform); int mId; QString mName; QString mType; QPointF mPos; QSizeF mSize; TextData mTextData; QPolygonF mPolygon; Shape mShape; Cell mCell; ObjectGroup *mObjectGroup; qreal mRotation; bool mVisible; }; /** * Returns the id of this object. Each object gets an id assigned that is * unique for the map the object is on. */ inline int MapObject::id() const { return mId; } /** * Sets the id of this object. */ inline void MapObject::setId(int id) { mId = id; } /** * Sets the id back to 0. Mostly used when a new id should be assigned * after the object has been cloned. */ inline void MapObject::resetId() { setId(0); } /** * Returns the name of this object. The name is usually just used for * identification of the object in the editor. */ inline const QString &MapObject::name() const { return mName; } /** * Sets the name of this object. */ inline void MapObject::setName(const QString &name) { mName = name; } /** * Returns the type of this object. The type usually says something about * how the object is meant to be interpreted by the engine. */ inline const QString &MapObject::type() const { return mType; } /** * Sets the type of this object. */ inline void MapObject::setType(const QString &type) { mType = type; } /** * Returns the position of this object. */ inline const QPointF &MapObject::position() const { return mPos; } /** * Sets the position of this object. */ inline void MapObject::setPosition(const QPointF &pos) { mPos = pos; } /** * Returns the x position of this object. */ inline qreal MapObject::x() const { return mPos.x(); } /** * Sets the x position of this object. */ inline void MapObject::setX(qreal x) { mPos.setX(x); } /** * Returns the y position of this object. */ inline qreal MapObject::y() const { return mPos.y(); } /** * Sets the x position of this object. */ inline void MapObject::setY(qreal y) { mPos.setY(y); } /** * Returns the size of this object. */ inline const QSizeF &MapObject::size() const { return mSize; } /** * Sets the size of this object. */ inline void MapObject::setSize(const QSizeF &size) { mSize = size; } inline void MapObject::setSize(qreal width, qreal height) { setSize(QSizeF(width, height)); } /** * Returns the width of this object. */ inline qreal MapObject::width() const { return mSize.width(); } /** * Sets the width of this object. */ inline void MapObject::setWidth(qreal width) { mSize.setWidth(width); } /** * Returns the height of this object. */ inline qreal MapObject::height() const { return mSize.height(); } /** * Sets the height of this object. */ inline void MapObject::setHeight(qreal height) { mSize.setHeight(height); } /** * Sets the position and size of this object. */ inline void MapObject::setBounds(const QRectF &bounds) { mPos = bounds.topLeft(); mSize = bounds.size(); } /** * Returns the text associated with this object, when it is a text object. */ inline const TextData &MapObject::textData() const { return mTextData; } /** * Returns the polygon associated with this object. Returns an empty * polygon when no polygon is associated with this object. */ inline const QPolygonF &MapObject::polygon() const { return mPolygon; } /** * Sets the polygon associated with this object. The polygon is only used * when the object shape is set to either Polygon or Polyline. * * \sa setShape() */ inline void MapObject::setPolygon(const QPolygonF &polygon) { mPolygon = polygon; } /** * Returns the shape of the object. */ inline MapObject::Shape MapObject::shape() const { return mShape; } /** * Sets the shape of the object. */ inline void MapObject::setShape(MapObject::Shape shape) { mShape = shape; } /** * Returns true if this is a Polygon or a Polyline. */ inline bool MapObject::isPolyShape() const { return mShape == Polygon || mShape == Polyline; } /** * Shortcut to getting a QRectF from position() and size(). */ inline QRectF MapObject::bounds() const { return QRectF(mPos, mSize); } /** * Returns the tile associated with this object. */ inline const Cell &MapObject::cell() const { return mCell; } /** * Sets the tile that is associated with this object. The object will * display as the tile image. * * \warning The object shape is ignored for tile objects! */ inline void MapObject::setCell(const Cell &cell) { mCell = cell; } /** * Returns the object group this object belongs to. */ inline ObjectGroup *MapObject::objectGroup() const { return mObjectGroup; } /** * Sets the object group this object belongs to. Should only be called * from the ObjectGroup class. */ inline void MapObject::setObjectGroup(ObjectGroup *objectGroup) { mObjectGroup = objectGroup; } /** * Returns the rotation of the object in degrees clockwise. */ inline qreal MapObject::rotation() const { return mRotation; } /** * Sets the rotation of the object in degrees clockwise. */ inline void MapObject::setRotation(qreal rotation) { mRotation = rotation; } inline bool MapObject::isVisible() const { return mVisible; } inline void MapObject::setVisible(bool visible) { mVisible = visible; } } // namespace Tiled #if QT_VERSION < 0x050500 Q_DECLARE_METATYPE(Qt::Alignment) #endif tiled-1.0.3/src/libtiled/mapreader.cpp000066400000000000000000001126541315121121300176360ustar00rootroot00000000000000/* * mapreader.cpp * Copyright 2008-2014, Thorbjørn Lindeijer * Copyright 2010, Jeff Bland * Copyright 2010, Dennis Honeyman * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mapreader.h" #include "compression.h" #include "gidmapper.h" #include "grouplayer.h" #include "imagelayer.h" #include "objectgroup.h" #include "map.h" #include "mapobject.h" #include "tile.h" #include "tilelayer.h" #include "tilesetmanager.h" #include "terrain.h" #include #include #include #include #include #include using namespace Tiled; using namespace Tiled::Internal; namespace Tiled { namespace Internal { class MapReaderPrivate { Q_DECLARE_TR_FUNCTIONS(MapReader) friend class Tiled::MapReader; public: MapReaderPrivate(MapReader *mapReader): p(mapReader), mReadingExternalTileset(false) {} Map *readMap(QIODevice *device, const QString &path); SharedTileset readTileset(QIODevice *device, const QString &path); bool openFile(QFile *file); QString errorString() const; private: void readUnknownElement(); Map *readMap(); SharedTileset readTileset(); void readTilesetTile(Tileset &tileset); void readTilesetGrid(Tileset &tileset); void readTilesetImage(Tileset &tileset); void readTilesetTerrainTypes(Tileset &tileset); ImageReference readImage(); Layer *tryReadLayer(); TileLayer *readTileLayer(); void readTileLayerData(TileLayer &tileLayer); void decodeBinaryLayerData(TileLayer &tileLayer, const QByteArray &data, Map::LayerDataFormat format); void decodeCSVLayerData(TileLayer &tileLayer, QStringRef text); /** * Returns the cell for the given global tile ID. Errors are raised with * the QXmlStreamReader. * * @param gid the global tile ID * @return the cell data associated with the given global tile ID, or an * empty cell if not found */ Cell cellForGid(unsigned gid); ImageLayer *readImageLayer(); void readImageLayerImage(ImageLayer &imageLayer); ObjectGroup *readObjectGroup(); MapObject *readObject(); QPolygonF readPolygon(); TextData readObjectText(); GroupLayer *readGroupLayer(); QVector readAnimationFrames(); Properties readProperties(); void readProperty(Properties *properties); MapReader *p; QString mError; QString mPath; QScopedPointer mMap; GidMapper mGidMapper; bool mReadingExternalTileset; QXmlStreamReader xml; }; } // namespace Internal } // namespace Tiled Map *MapReaderPrivate::readMap(QIODevice *device, const QString &path) { mError.clear(); mPath = path; Map *map = nullptr; xml.setDevice(device); if (xml.readNextStartElement() && xml.name() == QLatin1String("map")) { map = readMap(); } else { xml.raiseError(tr("Not a map file.")); } mGidMapper.clear(); return map; } SharedTileset MapReaderPrivate::readTileset(QIODevice *device, const QString &path) { mError.clear(); mPath = path; SharedTileset tileset; mReadingExternalTileset = true; xml.setDevice(device); if (xml.readNextStartElement() && xml.name() == QLatin1String("tileset")) tileset = readTileset(); else xml.raiseError(tr("Not a tileset file.")); mReadingExternalTileset = false; return tileset; } QString MapReaderPrivate::errorString() const { if (!mError.isEmpty()) { return mError; } else { return tr("%3\n\nLine %1, column %2") .arg(xml.lineNumber()) .arg(xml.columnNumber()) .arg(xml.errorString()); } } bool MapReaderPrivate::openFile(QFile *file) { if (!file->exists()) { mError = tr("File not found: %1").arg(file->fileName()); return false; } else if (!file->open(QFile::ReadOnly | QFile::Text)) { mError = tr("Unable to read file: %1").arg(file->fileName()); return false; } return true; } void MapReaderPrivate::readUnknownElement() { qDebug().nospace() << "Unknown element (fixme): " << xml.name() << " at line " << xml.lineNumber() << ", column " << xml.columnNumber(); xml.skipCurrentElement(); } Map *MapReaderPrivate::readMap() { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("map")); const QXmlStreamAttributes atts = xml.attributes(); const int mapWidth = atts.value(QLatin1String("width")).toInt(); const int mapHeight = atts.value(QLatin1String("height")).toInt(); const int tileWidth = atts.value(QLatin1String("tilewidth")).toInt(); const int tileHeight = atts.value(QLatin1String("tileheight")).toInt(); const int hexSideLength = atts.value(QLatin1String("hexsidelength")).toInt(); const QString orientationString = atts.value(QLatin1String("orientation")).toString(); const Map::Orientation orientation = orientationFromString(orientationString); if (orientation == Map::Unknown) { xml.raiseError(tr("Unsupported map orientation: \"%1\"") .arg(orientationString)); } const QString staggerAxisString = atts.value(QLatin1String("staggeraxis")).toString(); const Map::StaggerAxis staggerAxis = staggerAxisFromString(staggerAxisString); const QString staggerIndexString = atts.value(QLatin1String("staggerindex")).toString(); const Map::StaggerIndex staggerIndex = staggerIndexFromString(staggerIndexString); const QString renderOrderString = atts.value(QLatin1String("renderorder")).toString(); const Map::RenderOrder renderOrder = renderOrderFromString(renderOrderString); const int nextObjectId = atts.value(QLatin1String("nextobjectid")).toInt(); mMap.reset(new Map(orientation, mapWidth, mapHeight, tileWidth, tileHeight)); mMap->setHexSideLength(hexSideLength); mMap->setStaggerAxis(staggerAxis); mMap->setStaggerIndex(staggerIndex); mMap->setRenderOrder(renderOrder); if (nextObjectId) mMap->setNextObjectId(nextObjectId); QStringRef bgColorString = atts.value(QLatin1String("backgroundcolor")); if (!bgColorString.isEmpty()) mMap->setBackgroundColor(QColor(bgColorString.toString())); while (xml.readNextStartElement()) { if (Layer *layer = tryReadLayer()) mMap->addLayer(layer); else if (xml.name() == QLatin1String("properties")) mMap->mergeProperties(readProperties()); else if (xml.name() == QLatin1String("tileset")) mMap->addTileset(readTileset()); else readUnknownElement(); } // Clean up in case of error if (xml.hasError()) { mMap.reset(); } else { // Try to load the tileset images auto tilesets = mMap->tilesets(); for (SharedTileset &tileset : tilesets) { if (!tileset->isCollection() && tileset->fileName().isEmpty()) tileset->loadImage(); } // Fix up sizes of tile objects LayerIterator iterator(mMap.data()); while (Layer *layer = iterator.next()) { if (ObjectGroup *objectGroup = layer->asObjectGroup()) { for (MapObject *object : *objectGroup) { if (const Tile *tile = object->cell().tile()) { const QSizeF tileSize = tile->size(); if (object->width() == 0) object->setWidth(tileSize.width()); if (object->height() == 0) object->setHeight(tileSize.height()); } } } } } return mMap.take(); } SharedTileset MapReaderPrivate::readTileset() { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("tileset")); const QXmlStreamAttributes atts = xml.attributes(); const QString source = atts.value(QLatin1String("source")).toString(); const unsigned firstGid = atts.value(QLatin1String("firstgid")).toUInt(); SharedTileset tileset; if (source.isEmpty()) { // Not an external tileset const QString name = atts.value(QLatin1String("name")).toString(); const int tileWidth = atts.value(QLatin1String("tilewidth")).toInt(); const int tileHeight = atts.value(QLatin1String("tileheight")).toInt(); const int tileSpacing = atts.value(QLatin1String("spacing")).toInt(); const int margin = atts.value(QLatin1String("margin")).toInt(); const int columns = atts.value(QLatin1String("columns")).toInt(); QStringRef bgColorString = atts.value(QLatin1String("backgroundcolor")); if (tileWidth < 0 || tileHeight < 0 || (firstGid == 0 && !mReadingExternalTileset)) { xml.raiseError(tr("Invalid tileset parameters for tileset" " '%1'").arg(name)); } else { tileset = Tileset::create(name, tileWidth, tileHeight, tileSpacing, margin); tileset->setColumnCount(columns); if (!bgColorString.isEmpty()) tileset->setBackgroundColor(QColor(bgColorString.toString())); while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("tile")) { readTilesetTile(*tileset); } else if (xml.name() == QLatin1String("tileoffset")) { const QXmlStreamAttributes oa = xml.attributes(); int x = oa.value(QLatin1String("x")).toInt(); int y = oa.value(QLatin1String("y")).toInt(); tileset->setTileOffset(QPoint(x, y)); xml.skipCurrentElement(); } else if (xml.name() == QLatin1String("grid")) { readTilesetGrid(*tileset); } else if (xml.name() == QLatin1String("properties")) { tileset->mergeProperties(readProperties()); } else if (xml.name() == QLatin1String("image")) { if (tileWidth == 0 || tileHeight == 0) { xml.raiseError(tr("Invalid tileset parameters for tileset" " '%1'").arg(name)); tileset.clear(); break; } else { readTilesetImage(*tileset); } } else if (xml.name() == QLatin1String("terraintypes")) { readTilesetTerrainTypes(*tileset); } else { readUnknownElement(); } } } } else { // External tileset const QString absoluteSource = p->resolveReference(source, mPath); QString error; tileset = p->readExternalTileset(absoluteSource, &error); if (!tileset) { // Insert a placeholder to allow the map to load tileset = Tileset::create(QFileInfo(absoluteSource).completeBaseName(), 32, 32); tileset->setFileName(absoluteSource); tileset->setLoaded(false); } xml.skipCurrentElement(); } if (tileset && !mReadingExternalTileset) mGidMapper.insert(firstGid, tileset.data()); return tileset; } void MapReaderPrivate::readTilesetTile(Tileset &tileset) { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("tile")); const QXmlStreamAttributes atts = xml.attributes(); const int id = atts.value(QLatin1String("id")).toInt(); if (id < 0) { xml.raiseError(tr("Invalid tile ID: %1").arg(id)); return; } Tile *tile = tileset.findOrCreateTile(id); tile->setType(atts.value(QLatin1String("type")).toString()); // Read tile quadrant terrain ids QString terrain = atts.value(QLatin1String("terrain")).toString(); if (!terrain.isEmpty()) { QStringList quadrants = terrain.split(QLatin1String(",")); if (quadrants.size() == 4) { for (int i = 0; i < 4; ++i) { int t = quadrants[i].isEmpty() ? -1 : quadrants[i].toInt(); tile->setCornerTerrainId(i, t); } } } // Read tile probability QStringRef probability = atts.value(QLatin1String("probability")); if (!probability.isEmpty()) tile->setProbability(probability.toFloat()); while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("properties")) { tile->mergeProperties(readProperties()); } else if (xml.name() == QLatin1String("image")) { ImageReference imageReference = readImage(); if (imageReference.hasImage()) { QImage image = imageReference.create(); if (image.isNull()) { if (imageReference.source.isEmpty()) xml.raiseError(tr("Error reading embedded image for tile %1").arg(id)); } tileset.setTileImage(tile, QPixmap::fromImage(image), imageReference.source); } } else if (xml.name() == QLatin1String("objectgroup")) { tile->setObjectGroup(readObjectGroup()); } else if (xml.name() == QLatin1String("animation")) { tile->setFrames(readAnimationFrames()); } else { readUnknownElement(); } } // Temporary code to support TMW-style animation frame properties if (!tile->isAnimated() && tile->hasProperty(QLatin1String("animation-frame0"))) { QVector frames; for (int i = 0; ; i++) { QString frameName = QLatin1String("animation-frame") + QString::number(i); QString delayName = QLatin1String("animation-delay") + QString::number(i); if (tile->hasProperty(frameName) && tile->hasProperty(delayName)) { Frame frame; frame.tileId = tile->property(frameName).toInt(); frame.duration = tile->property(delayName).toInt() * 10; frames.append(frame); } else { break; } } tile->setFrames(frames); } } void MapReaderPrivate::readTilesetGrid(Tileset &tileset) { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("grid")); const QXmlStreamAttributes atts = xml.attributes(); const QString orientation = atts.value(QLatin1String("orientation")).toString(); const int width = atts.value(QLatin1String("width")).toInt(); const int height = atts.value(QLatin1String("height")).toInt(); tileset.setOrientation(Tileset::orientationFromString(orientation)); const QSize gridSize(width, height); if (!gridSize.isEmpty()) tileset.setGridSize(gridSize); xml.skipCurrentElement(); } void MapReaderPrivate::readTilesetImage(Tileset &tileset) { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("image")); tileset.setImageReference(readImage()); } ImageReference MapReaderPrivate::readImage() { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("image")); const QXmlStreamAttributes atts = xml.attributes(); ImageReference image; image.source = atts.value(QLatin1String("source")).toString(); image.format = atts.value(QLatin1String("format")).toLatin1(); image.size = QSize(atts.value(QLatin1String("width")).toInt(), atts.value(QLatin1String("height")).toInt()); QString trans = atts.value(QLatin1String("trans")).toString(); if (!trans.isEmpty()) { if (!trans.startsWith(QLatin1Char('#'))) trans.prepend(QLatin1Char('#')); if (QColor::isValidColor(trans)) image.transparentColor = QColor(trans); } if (image.source.isEmpty()) { while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("data")) { const QXmlStreamAttributes atts = xml.attributes(); QStringRef encoding = atts.value(QLatin1String("encoding")); image.data = xml.readElementText().toLatin1(); if (encoding == QLatin1String("base64")) image.data = QByteArray::fromBase64(image.data); } else { readUnknownElement(); } } } else { image.source = p->resolveReference(image.source, mPath); xml.skipCurrentElement(); } return image; } Layer *MapReaderPrivate::tryReadLayer() { Q_ASSERT(xml.isStartElement()); if (xml.name() == QLatin1String("layer")) return readTileLayer(); else if (xml.name() == QLatin1String("objectgroup")) return readObjectGroup(); else if (xml.name() == QLatin1String("imagelayer")) return readImageLayer(); else if (xml.name() == QLatin1String("group")) return readGroupLayer(); else return nullptr; } void MapReaderPrivate::readTilesetTerrainTypes(Tileset &tileset) { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("terraintypes")); while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("terrain")) { const QXmlStreamAttributes atts = xml.attributes(); QString name = atts.value(QLatin1String("name")).toString(); int tile = atts.value(QLatin1String("tile")).toInt(); Terrain *terrain = tileset.addTerrain(name, tile); while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("properties")) terrain->mergeProperties(readProperties()); else readUnknownElement(); } } else { readUnknownElement(); } } } static void readLayerAttributes(Layer &layer, const QXmlStreamAttributes &atts) { const QStringRef opacityRef = atts.value(QLatin1String("opacity")); const QStringRef visibleRef = atts.value(QLatin1String("visible")); bool ok; const float opacity = opacityRef.toFloat(&ok); if (ok) layer.setOpacity(opacity); const int visible = visibleRef.toInt(&ok); if (ok) layer.setVisible(visible); const QPointF offset(atts.value(QLatin1String("offsetx")).toDouble(), atts.value(QLatin1String("offsety")).toDouble()); layer.setOffset(offset); } TileLayer *MapReaderPrivate::readTileLayer() { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("layer")); const QXmlStreamAttributes atts = xml.attributes(); const QString name = atts.value(QLatin1String("name")).toString(); const int x = atts.value(QLatin1String("x")).toInt(); const int y = atts.value(QLatin1String("y")).toInt(); const int width = atts.value(QLatin1String("width")).toInt(); const int height = atts.value(QLatin1String("height")).toInt(); TileLayer *tileLayer = new TileLayer(name, x, y, width, height); readLayerAttributes(*tileLayer, atts); while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("properties")) tileLayer->mergeProperties(readProperties()); else if (xml.name() == QLatin1String("data")) readTileLayerData(*tileLayer); else readUnknownElement(); } return tileLayer; } void MapReaderPrivate::readTileLayerData(TileLayer &tileLayer) { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("data")); const QXmlStreamAttributes atts = xml.attributes(); QStringRef encoding = atts.value(QLatin1String("encoding")); QStringRef compression = atts.value(QLatin1String("compression")); Map::LayerDataFormat layerDataFormat; if (encoding.isEmpty()) { layerDataFormat = Map::XML; } else if (encoding == QLatin1String("csv")) { layerDataFormat = Map::CSV; } else if (encoding == QLatin1String("base64")) { if (compression.isEmpty()) { layerDataFormat = Map::Base64; } else if (compression == QLatin1String("gzip")) { layerDataFormat = Map::Base64Gzip; } else if (compression == QLatin1String("zlib")) { layerDataFormat = Map::Base64Zlib; } else { xml.raiseError(tr("Compression method '%1' not supported") .arg(compression.toString())); return; } } else { xml.raiseError(tr("Unknown encoding: %1").arg(encoding.toString())); return; } mMap->setLayerDataFormat(layerDataFormat); int x = 0; int y = 0; while (xml.readNext() != QXmlStreamReader::Invalid) { if (xml.isEndElement()) { break; } else if (xml.isStartElement()) { if (xml.name() == QLatin1String("tile")) { if (y >= tileLayer.height()) { xml.raiseError(tr("Too many elements")); continue; } const QXmlStreamAttributes atts = xml.attributes(); unsigned gid = atts.value(QLatin1String("gid")).toUInt(); tileLayer.setCell(x, y, cellForGid(gid)); x++; if (x >= tileLayer.width()) { x = 0; y++; } xml.skipCurrentElement(); } else { readUnknownElement(); } } else if (xml.isCharacters() && !xml.isWhitespace()) { if (encoding == QLatin1String("base64")) { decodeBinaryLayerData(tileLayer, xml.text().toLatin1(), layerDataFormat); } else if (encoding == QLatin1String("csv")) { decodeCSVLayerData(tileLayer, xml.text()); } } } } void MapReaderPrivate::decodeBinaryLayerData(TileLayer &tileLayer, const QByteArray &data, Map::LayerDataFormat format) { GidMapper::DecodeError error = mGidMapper.decodeLayerData(tileLayer, data, format); switch (error) { case GidMapper::CorruptLayerData: xml.raiseError(tr("Corrupt layer data for layer '%1'").arg(tileLayer.name())); return; case GidMapper::TileButNoTilesets: xml.raiseError(tr("Tile used but no tilesets specified")); return; case GidMapper::InvalidTile: xml.raiseError(tr("Invalid tile: %1").arg(mGidMapper.invalidTile())); return; case GidMapper::NoError: break; } } void MapReaderPrivate::decodeCSVLayerData(TileLayer &tileLayer, QStringRef text) { QString trimText = text.trimmed().toString(); QStringList tiles = trimText.split(QLatin1Char(',')); if (tiles.length() != tileLayer.width() * tileLayer.height()) { xml.raiseError(tr("Corrupt layer data for layer '%1'") .arg(tileLayer.name())); return; } for (int y = 0; y < tileLayer.height(); y++) { for (int x = 0; x < tileLayer.width(); x++) { bool conversionOk; const unsigned gid = tiles.at(y * tileLayer.width() + x) .toUInt(&conversionOk); if (!conversionOk) { xml.raiseError( tr("Unable to parse tile at (%1,%2) on layer '%3'") .arg(x + 1).arg(y + 1).arg(tileLayer.name())); return; } tileLayer.setCell(x, y, cellForGid(gid)); } } } Cell MapReaderPrivate::cellForGid(unsigned gid) { bool ok; const Cell result = mGidMapper.gidToCell(gid, ok); if (!ok) { if (mGidMapper.isEmpty()) xml.raiseError(tr("Tile used but no tilesets specified")); else xml.raiseError(tr("Invalid tile: %1").arg(gid)); } return result; } ObjectGroup *MapReaderPrivate::readObjectGroup() { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("objectgroup")); const QXmlStreamAttributes atts = xml.attributes(); const QString name = atts.value(QLatin1String("name")).toString(); const int x = atts.value(QLatin1String("x")).toInt(); const int y = atts.value(QLatin1String("y")).toInt(); ObjectGroup *objectGroup = new ObjectGroup(name, x, y); readLayerAttributes(*objectGroup, atts); const QString color = atts.value(QLatin1String("color")).toString(); if (!color.isEmpty()) objectGroup->setColor(color); if (atts.hasAttribute(QLatin1String("draworder"))) { QString value = atts.value(QLatin1String("draworder")).toString(); ObjectGroup::DrawOrder drawOrder = drawOrderFromString(value); if (drawOrder == ObjectGroup::UnknownOrder) { delete objectGroup; xml.raiseError(tr("Invalid draw order: %1").arg(value)); return nullptr; } objectGroup->setDrawOrder(drawOrder); } while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("object")) objectGroup->addObject(readObject()); else if (xml.name() == QLatin1String("properties")) objectGroup->mergeProperties(readProperties()); else readUnknownElement(); } return objectGroup; } ImageLayer *MapReaderPrivate::readImageLayer() { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("imagelayer")); const QXmlStreamAttributes atts = xml.attributes(); const QString name = atts.value(QLatin1String("name")).toString(); const int x = atts.value(QLatin1String("x")).toInt(); const int y = atts.value(QLatin1String("y")).toInt(); ImageLayer *imageLayer = new ImageLayer(name, x, y); readLayerAttributes(*imageLayer, atts); // Image layer pixel position moved from x/y to offsetx/offsety for // consistency with other layers. This is here for backwards compatibility. if (!atts.hasAttribute(QLatin1String("offsetx"))) imageLayer->setOffset(QPointF(x, y)); while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("image")) readImageLayerImage(*imageLayer); else if (xml.name() == QLatin1String("properties")) imageLayer->mergeProperties(readProperties()); else readUnknownElement(); } return imageLayer; } void MapReaderPrivate::readImageLayerImage(ImageLayer &imageLayer) { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("image")); const QXmlStreamAttributes atts = xml.attributes(); QString source = atts.value(QLatin1String("source")).toString(); QString trans = atts.value(QLatin1String("trans")).toString(); if (!trans.isEmpty()) { if (!trans.startsWith(QLatin1Char('#'))) trans.prepend(QLatin1Char('#')); imageLayer.setTransparentColor(QColor(trans)); } source = p->resolveReference(source, mPath); imageLayer.loadFromImage(source); xml.skipCurrentElement(); } MapObject *MapReaderPrivate::readObject() { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("object")); const QXmlStreamAttributes atts = xml.attributes(); const int id = atts.value(QLatin1String("id")).toInt(); const QString name = atts.value(QLatin1String("name")).toString(); const unsigned gid = atts.value(QLatin1String("gid")).toUInt(); const qreal x = atts.value(QLatin1String("x")).toDouble(); const qreal y = atts.value(QLatin1String("y")).toDouble(); const qreal width = atts.value(QLatin1String("width")).toDouble(); const qreal height = atts.value(QLatin1String("height")).toDouble(); const QString type = atts.value(QLatin1String("type")).toString(); const QStringRef visibleRef = atts.value(QLatin1String("visible")); const QPointF pos(x, y); const QSizeF size(width, height); MapObject *object = new MapObject(name, type, pos, size); object->setId(id); bool ok; const qreal rotation = atts.value(QLatin1String("rotation")).toDouble(&ok); if (ok) object->setRotation(rotation); if (gid) object->setCell(cellForGid(gid)); const int visible = visibleRef.toInt(&ok); if (ok) object->setVisible(visible); while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("properties")) { object->mergeProperties(readProperties()); } else if (xml.name() == QLatin1String("polygon")) { object->setPolygon(readPolygon()); object->setShape(MapObject::Polygon); } else if (xml.name() == QLatin1String("polyline")) { object->setPolygon(readPolygon()); object->setShape(MapObject::Polyline); } else if (xml.name() == QLatin1String("ellipse")) { xml.skipCurrentElement(); object->setShape(MapObject::Ellipse); } else if (xml.name() == QLatin1String("text")) { object->setTextData(readObjectText()); object->setShape(MapObject::Text); } else { readUnknownElement(); } } return object; } QPolygonF MapReaderPrivate::readPolygon() { Q_ASSERT(xml.isStartElement() && (xml.name() == QLatin1String("polygon") || xml.name() == QLatin1String("polyline"))); const QXmlStreamAttributes atts = xml.attributes(); const QString points = atts.value(QLatin1String("points")).toString(); const QStringList pointsList = points.split(QLatin1Char(' '), QString::SkipEmptyParts); QPolygonF polygon; bool ok = true; for (const QString &point : pointsList) { const int commaPos = point.indexOf(QLatin1Char(',')); if (commaPos == -1) { ok = false; break; } const qreal x = point.left(commaPos).toDouble(&ok); if (!ok) break; const qreal y = point.mid(commaPos + 1).toDouble(&ok); if (!ok) break; polygon.append(QPointF(x, y)); } if (!ok) xml.raiseError(tr("Invalid points data for polygon")); xml.skipCurrentElement(); return polygon; } static int intAttribute(const QXmlStreamAttributes& atts, const char *name, int def) { bool ok = false; int value = atts.value(QLatin1String(name)).toInt(&ok); return ok ? value : def; } TextData MapReaderPrivate::readObjectText() { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("text")); const QXmlStreamAttributes atts = xml.attributes(); TextData textData; if (atts.hasAttribute(QLatin1String("fontfamily"))) textData.font = QFont(atts.value(QLatin1String("fontfamily")).toString()); if (atts.hasAttribute(QLatin1String("pixelsize"))) textData.font.setPixelSize(atts.value(QLatin1String("pixelsize")).toInt()); textData.wordWrap = intAttribute(atts, "wrap", 0) == 1; textData.font.setBold(intAttribute(atts, "bold", 0) == 1); textData.font.setItalic(intAttribute(atts, "italic", 0) == 1); textData.font.setUnderline(intAttribute(atts, "underline", 0) == 1); textData.font.setStrikeOut(intAttribute(atts, "strikeout", 0) == 1); textData.font.setKerning(intAttribute(atts, "kerning", 1) == 1); QStringRef colorString = atts.value(QLatin1String("color")); if (!colorString.isEmpty()) textData.color = QColor(colorString.toString()); Qt::Alignment alignment = 0; QStringRef hAlignString = atts.value(QLatin1String("halign")); if (hAlignString == QLatin1String("center")) alignment |= Qt::AlignHCenter; else if (hAlignString == QLatin1String("right")) alignment |= Qt::AlignRight; else alignment |= Qt::AlignLeft; QStringRef vAlignString = atts.value(QLatin1String("valign")); if (vAlignString == QLatin1String("center")) alignment |= Qt::AlignVCenter; else if (vAlignString == QLatin1String("bottom")) alignment |= Qt::AlignBottom; else alignment |= Qt::AlignTop; textData.alignment = alignment; textData.text = xml.readElementText(); return textData; } GroupLayer *MapReaderPrivate::readGroupLayer() { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("group")); const QXmlStreamAttributes atts = xml.attributes(); const QString name = atts.value(QLatin1String("name")).toString(); const int x = atts.value(QLatin1String("x")).toInt(); const int y = atts.value(QLatin1String("y")).toInt(); GroupLayer *groupLayer = new GroupLayer(name, x, y); readLayerAttributes(*groupLayer, atts); while (xml.readNextStartElement()) { if (Layer *layer = tryReadLayer()) groupLayer->addLayer(layer); else if (xml.name() == QLatin1String("properties")) groupLayer->mergeProperties(readProperties()); else readUnknownElement(); } return groupLayer; } QVector MapReaderPrivate::readAnimationFrames() { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("animation")); QVector frames; while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("frame")) { const QXmlStreamAttributes atts = xml.attributes(); Frame frame; frame.tileId = atts.value(QLatin1String("tileid")).toInt(); frame.duration = atts.value(QLatin1String("duration")).toInt(); frames.append(frame); xml.skipCurrentElement(); } else { readUnknownElement(); } } return frames; } Properties MapReaderPrivate::readProperties() { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("properties")); Properties properties; while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("property")) readProperty(&properties); else readUnknownElement(); } return properties; } void MapReaderPrivate::readProperty(Properties *properties) { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("property")); const QXmlStreamAttributes atts = xml.attributes(); QString propertyName = atts.value(QLatin1String("name")).toString(); QString propertyValue = atts.value(QLatin1String("value")).toString(); QString propertyType = atts.value(QLatin1String("type")).toString(); while (xml.readNext() != QXmlStreamReader::Invalid) { if (xml.isEndElement()) { break; } else if (xml.isCharacters() && !xml.isWhitespace()) { if (propertyValue.isEmpty()) propertyValue = xml.text().toString(); } else if (xml.isStartElement()) { readUnknownElement(); } } QVariant variant(propertyValue); if (!propertyType.isEmpty()) { int type = nameToType(propertyType); if (type == filePathTypeId()) variant = p->resolveReference(variant.toString(), mPath); variant = fromExportValue(variant, type); } properties->insert(propertyName, variant); } MapReader::MapReader() : d(new MapReaderPrivate(this)) { } MapReader::~MapReader() { delete d; } Map *MapReader::readMap(QIODevice *device, const QString &path) { return d->readMap(device, path); } Map *MapReader::readMap(const QString &fileName) { QFile file(fileName); if (!d->openFile(&file)) return nullptr; return readMap(&file, QFileInfo(fileName).absolutePath()); } SharedTileset MapReader::readTileset(QIODevice *device, const QString &path) { SharedTileset tileset = d->readTileset(device, path); if (tileset && !tileset->isCollection()) tileset->loadImage(); return tileset; } SharedTileset MapReader::readTileset(const QString &fileName) { QFile file(fileName); if (!d->openFile(&file)) return SharedTileset(); SharedTileset tileset = readTileset(&file, QFileInfo(fileName).absolutePath()); if (tileset) tileset->setFileName(fileName); return tileset; } QString MapReader::errorString() const { return d->errorString(); } QString MapReader::resolveReference(const QString &reference, const QString &mapPath) { if (!reference.isEmpty() && QDir::isRelativePath(reference)) return QDir::cleanPath(mapPath + QLatin1Char('/') + reference); return reference; } SharedTileset MapReader::readExternalTileset(const QString &source, QString *error) { return TilesetManager::instance()->loadTileset(source, error); } tiled-1.0.3/src/libtiled/mapreader.h000066400000000000000000000075361315121121300173050ustar00rootroot00000000000000/* * mapreader.h * Copyright 2008-2010, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "tiled_global.h" #include "tileset.h" #include class QFile; namespace Tiled { class Map; namespace Internal { class MapReaderPrivate; } /** * A fast QXmlStreamReader based reader for the TMX and TSX formats. * * Can be subclassed when special handling of external images and tilesets is * needed. */ class TILEDSHARED_EXPORT MapReader { public: MapReader(); virtual ~MapReader(); /** * Reads a TMX map from the given \a device. Optionally a \a path can * be given, which will be used to resolve relative references to external * images and tilesets. * * Returns 0 and sets errorString() when reading failed. * * The caller takes ownership over the newly created map. */ Map *readMap(QIODevice *device, const QString &path = QString()); /** * Reads a TMX map from the given \a fileName. * \overload */ Map *readMap(const QString &fileName); /** * Reads a TSX tileset from the given \a device. Optionally a \a path can * be given, which will be used to resolve relative references to external * images. * * Returns 0 and sets errorString() when reading failed. * * The caller takes ownership over the newly created tileset. */ SharedTileset readTileset(QIODevice *device, const QString &path = QString()); /** * Reads a TSX tileset from the given \a fileName. * \overload */ SharedTileset readTileset(const QString &fileName); /** * Returns the error message for the last occurred error. */ QString errorString() const; protected: /** * Called for each \a reference to an external file. Should return the path * to be used when loading this file. \a mapPath contains the path to the * map or tileset that is currently being loaded. */ QString resolveReference(const QString &reference, const QString &mapPath); /** * Called when an external tileset is encountered while a map is loaded. * The default implementation just calls Tiled::readTileset(). * * If an error occurred, the \a error parameter should be set to the error * message. */ virtual SharedTileset readExternalTileset(const QString &source, QString *error); private: Q_DISABLE_COPY(MapReader) friend class Internal::MapReaderPrivate; Internal::MapReaderPrivate *d; }; } // namespace Tiled tiled-1.0.3/src/libtiled/maprenderer.cpp000066400000000000000000000202501315121121300201700ustar00rootroot00000000000000/* * maprenderer.cpp * Copyright 2011, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "maprenderer.h" #include "imagelayer.h" #include "tile.h" #include "tilelayer.h" #include #include #include #include using namespace Tiled; QRectF MapRenderer::boundingRect(const ImageLayer *imageLayer) const { return QRectF(QPointF(), imageLayer->image().size()); } void MapRenderer::drawImageLayer(QPainter *painter, const ImageLayer *imageLayer, const QRectF &exposed) { Q_UNUSED(exposed) painter->drawPixmap(QPointF(), imageLayer->image()); } void MapRenderer::setFlag(RenderFlag flag, bool enabled) { if (enabled) mFlags |= flag; else mFlags &= ~flag; } /** * Converts a line running from \a start to \a end to a polygon which * extends 5 pixels from the line in all directions. */ QPolygonF MapRenderer::lineToPolygon(const QPointF &start, const QPointF &end) { QPointF direction = QVector2D(end - start).normalized().toPointF(); QPointF perpendicular(-direction.y(), direction.x()); const qreal thickness = 5.0f; // 5 pixels on each side direction *= thickness; perpendicular *= thickness; QPolygonF polygon(4); polygon[0] = start + perpendicular - direction; polygon[1] = start - perpendicular - direction; polygon[2] = end - perpendicular + direction; polygon[3] = end + perpendicular + direction; return polygon; } QPen MapRenderer::makeGridPen(const QPaintDevice *device, QColor color) const { #if QT_VERSION >= 0x050600 const qreal devicePixelRatio = device->devicePixelRatioF(); #else const int devicePixelRatio = device->devicePixelRatio(); #endif #ifdef Q_OS_MAC const qreal dpiScale = 1.0f; #else const qreal dpiScale = device->logicalDpiX() / 96.0; #endif const qreal dashLength = std::ceil(2.0 * dpiScale * devicePixelRatio); color.setAlpha(128); QPen pen(color); pen.setCosmetic(true); pen.setDashPattern({dashLength, dashLength}); return pen; } static void renderMissingImageMarker(QPainter &painter, const QRectF &rect) { QRectF r { rect.adjusted(0.5, 0.5, -0.5, -0.5) }; QPen pen { Qt::red, 1 }; pen.setCapStyle(Qt::FlatCap); pen.setJoinStyle(Qt::MiterJoin); painter.save(); painter.fillRect(r, QColor(0, 0, 0, 128)); painter.setRenderHint(QPainter::Antialiasing); painter.setPen(pen); painter.drawRect(r); painter.drawLine(r.topLeft(), r.bottomRight()); painter.drawLine(r.topRight(), r.bottomLeft()); painter.restore(); } static bool hasOpenGLEngine(const QPainter *painter) { const QPaintEngine::Type type = painter->paintEngine()->type(); return (type == QPaintEngine::OpenGL || type == QPaintEngine::OpenGL2); } CellRenderer::CellRenderer(QPainter *painter, const CellType cellType) : mPainter(painter) , mTile(nullptr) , mIsOpenGL(hasOpenGLEngine(painter)) , mCellType(cellType) { } /** * Renders a \a cell with the given \a origin at \a pos, taking into account * the flipping and tile offset. * * For performance reasons, the actual drawing is delayed until a different * kind of tile has to be drawn. For this reason it is necessary to call * flush when finished doing drawCell calls. This function is also called by * the destructor so usually an explicit call is not needed. */ void CellRenderer::render(const Cell &cell, const QPointF &pos, const QSizeF &size, Origin origin) { const Tile *tile = cell.tile(); if (tile) tile = tile->currentFrameTile(); if (!tile || tile->image().isNull()) { QRectF target { pos - QPointF(0, size.height()), size }; if (origin == BottomCenter) target.moveLeft(target.left() - size.width() / 2); renderMissingImageMarker(*mPainter, target); return; } if (mTile != tile) flush(); const QPixmap &image = tile->image(); const QSizeF imageSize = image.size(); if (imageSize.isEmpty()) return; const QSizeF scale(size.width() / imageSize.width(), size.height() / imageSize.height()); const QPoint offset = tile->offset(); const QPointF sizeHalf = QPointF(size.width() / 2, size.height() / 2); bool flippedHorizontally = cell.flippedHorizontally(); bool flippedVertically = cell.flippedVertically(); QPainter::PixmapFragment fragment; fragment.x = pos.x() + (offset.x() * scale.width()) + sizeHalf.x(); fragment.y = pos.y() + (offset.y() * scale.height()) + sizeHalf.y() - size.height(); fragment.sourceLeft = 0; fragment.sourceTop = 0; fragment.width = imageSize.width(); fragment.height = imageSize.height(); fragment.scaleX = flippedHorizontally ? -1 : 1; fragment.scaleY = flippedVertically ? -1 : 1; fragment.rotation = 0; fragment.opacity = 1; if (origin == BottomCenter) fragment.x -= sizeHalf.x(); if (mCellType == HexagonalCells) { if (cell.flippedAntiDiagonally()) fragment.rotation += 60; if (cell.rotatedHexagonal120()) fragment.rotation += 120; } else if (cell.flippedAntiDiagonally()) { Q_ASSERT(mCellType == OrthogonalCells); fragment.rotation = 90; flippedHorizontally = cell.flippedVertically(); flippedVertically = !cell.flippedHorizontally(); // Compensate for the swap of image dimensions const qreal halfDiff = sizeHalf.y() - sizeHalf.x(); fragment.y += halfDiff; if (origin != BottomCenter) fragment.x += halfDiff; } fragment.scaleX = scale.width() * (flippedHorizontally ? -1 : 1); fragment.scaleY = scale.height() * (flippedVertically ? -1 : 1); if (mIsOpenGL || (fragment.scaleX > 0 && fragment.scaleY > 0)) { mTile = tile; mFragments.append(fragment); return; } // The Raster paint engine as of Qt 4.8.4 / 5.0.2 does not support // drawing fragments with a negative scaling factor. flush(); // make sure we drew all tiles so far const QTransform oldTransform = mPainter->transform(); QTransform transform = oldTransform; transform.translate(fragment.x, fragment.y); transform.rotate(fragment.rotation); transform.scale(fragment.scaleX, fragment.scaleY); const QRectF target(fragment.width * -0.5, fragment.height * -0.5, fragment.width, fragment.height); const QRectF source(0, 0, fragment.width, fragment.height); mPainter->setTransform(transform); mPainter->drawPixmap(target, image, source); mPainter->setTransform(oldTransform); } /** * Renders any remaining cells. */ void CellRenderer::flush() { if (!mTile) return; mPainter->drawPixmapFragments(mFragments.constData(), mFragments.size(), mTile->image()); mTile = nullptr; mFragments.resize(0); } tiled-1.0.3/src/libtiled/maprenderer.h000066400000000000000000000212471315121121300176440ustar00rootroot00000000000000/* * maprenderer.h * Copyright 2009-2011, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "tiled_global.h" #include namespace Tiled { class Cell; class Layer; class Map; class MapObject; class Tile; class TileLayer; class ImageLayer; enum RenderFlag { ShowTileObjectOutlines = 0x1 }; Q_DECLARE_FLAGS(RenderFlags, RenderFlag) /** * This interface is used for rendering tile layers and retrieving associated * metrics. The different implementations deal with different map * orientations. */ class TILEDSHARED_EXPORT MapRenderer { public: MapRenderer(const Map *map) : mMap(map) , mFlags(nullptr) , mObjectLineWidth(2) , mPainterScale(1) {} virtual ~MapRenderer() {} /** * Returns the map this renderer is associated with. */ const Map *map() const; /** * Returns the size in pixels of the map associated with this renderer. */ virtual QSize mapSize() const = 0; /** * Returns the bounding rectangle in pixels of the given \a rect given in * tile coordinates. * * This is useful for calculating the bounding rect of a tile layer or of * a region of tiles that was changed. */ virtual QRect boundingRect(const QRect &rect) const = 0; /** * Returns the bounding rectangle in pixels of the given \a object, as it * would be drawn by drawMapObject(). */ virtual QRectF boundingRect(const MapObject *object) const = 0; /** * Returns the bounding rectangle in pixels of the given \a imageLayer, as * it would be drawn by drawImageLayer(). */ QRectF boundingRect(const ImageLayer *imageLayer) const; /** * Returns the shape in pixels of the given \a object. This is used for * mouse interaction and should match the rendered object as closely as * possible. */ virtual QPainterPath shape(const MapObject *object) const = 0; /** * Draws the tile grid in the specified \a rect using the given * \a painter. */ virtual void drawGrid(QPainter *painter, const QRectF &rect, QColor gridColor = Qt::black) const = 0; /** * Draws the given \a layer using the given \a painter. * * Optionally, you can pass in the \a exposed rect (of pixels), so that * only tiles that can be visible in this area will be drawn. */ virtual void drawTileLayer(QPainter *painter, const TileLayer *layer, const QRectF &exposed = QRectF()) const = 0; /** * Draws the tile selection given by \a region in the specified \a color. * * The implementation can be optimized by taking into account the * \a exposed rectangle, to avoid drawing too much. */ virtual void drawTileSelection(QPainter *painter, const QRegion ®ion, const QColor &color, const QRectF &exposed) const = 0; /** * Draws the \a object in the given \a color using the \a painter. */ virtual void drawMapObject(QPainter *painter, const MapObject *object, const QColor &color) const = 0; /** * Draws the given image \a layer using the given \a painter. */ void drawImageLayer(QPainter *painter, const ImageLayer *imageLayer, const QRectF &exposed = QRectF()); /** * Returns the tile coordinates matching the given pixel position. */ virtual QPointF pixelToTileCoords(qreal x, qreal y) const = 0; inline QPointF pixelToTileCoords(const QPointF &point) const { return pixelToTileCoords(point.x(), point.y()); } QPolygonF pixelToScreenCoords(const QPolygonF &polygon) const { QPolygonF screenPolygon(polygon.size()); for (int i = polygon.size() - 1; i >= 0; --i) screenPolygon[i] = pixelToScreenCoords(polygon[i]); return screenPolygon; } /** * Returns the pixel coordinates matching the given tile coordinates. */ virtual QPointF tileToPixelCoords(qreal x, qreal y) const = 0; inline QPointF tileToPixelCoords(const QPointF &point) const { return tileToPixelCoords(point.x(), point.y()); } inline QRectF tileToPixelCoords(const QRectF &area) const { return QRectF(tileToPixelCoords(area.topLeft()), tileToPixelCoords(area.bottomRight())); } /** * Returns the tile coordinates matching the given screen position. */ virtual QPointF screenToTileCoords(qreal x, qreal y) const = 0; inline QPointF screenToTileCoords(const QPointF &point) const; /** * Returns the screen position matching the given tile coordinates. */ virtual QPointF tileToScreenCoords(qreal x, qreal y) const = 0; inline QPointF tileToScreenCoords(const QPointF &point) const; /** * Returns the pixel position matching the given screen position. */ virtual QPointF screenToPixelCoords(qreal x, qreal y) const = 0; inline QPointF screenToPixelCoords(const QPointF &point) const; /** * Returns the screen position matching the given pixel position. */ virtual QPointF pixelToScreenCoords(qreal x, qreal y) const = 0; inline QPointF pixelToScreenCoords(const QPointF &point) const; qreal objectLineWidth() const { return mObjectLineWidth; } void setObjectLineWidth(qreal lineWidth) { mObjectLineWidth = lineWidth; } void setFlag(RenderFlag flag, bool enabled = true); bool testFlag(RenderFlag flag) const { return mFlags.testFlag(flag); } qreal painterScale() const { return mPainterScale; } void setPainterScale(qreal painterScale) { mPainterScale = painterScale; } RenderFlags flags() const { return mFlags; } void setFlags(RenderFlags flags) { mFlags = flags; } static QPolygonF lineToPolygon(const QPointF &start, const QPointF &end); protected: QPen makeGridPen(const QPaintDevice *device, QColor color) const; private: const Map *mMap; RenderFlags mFlags; qreal mObjectLineWidth; qreal mPainterScale; }; inline const Map *MapRenderer::map() const { return mMap; } inline QPointF MapRenderer::screenToTileCoords(const QPointF &point) const { return screenToTileCoords(point.x(), point.y()); } inline QPointF MapRenderer::tileToScreenCoords(const QPointF &point) const { return tileToScreenCoords(point.x(), point.y()); } inline QPointF MapRenderer::screenToPixelCoords(const QPointF &point) const { return screenToPixelCoords(point.x(), point.y()); } inline QPointF MapRenderer::pixelToScreenCoords(const QPointF &point) const { return pixelToScreenCoords(point.x(), point.y()); } /** * A utility class for rendering cells. */ class CellRenderer { public: enum Origin { BottomLeft, BottomCenter }; enum CellType { OrthogonalCells, HexagonalCells }; explicit CellRenderer(QPainter *painter, CellType cellType = OrthogonalCells); ~CellRenderer() { flush(); } void render(const Cell &cell, const QPointF &pos, const QSizeF &size, Origin origin); void flush(); private: QPainter * const mPainter; const Tile *mTile; QVector mFragments; const bool mIsOpenGL; const CellType mCellType; }; } // namespace Tiled Q_DECLARE_OPERATORS_FOR_FLAGS(Tiled::RenderFlags) tiled-1.0.3/src/libtiled/maptovariantconverter.cpp000066400000000000000000000466731315121121300223420ustar00rootroot00000000000000/* * maptovariantconverter.cpp * Copyright 2011, Porfírio José Pereira Ribeiro * Copyright 2011-2015, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "maptovariantconverter.h" #include "grouplayer.h" #include "imagelayer.h" #include "map.h" #include "mapobject.h" #include "objectgroup.h" #include "properties.h" #include "tile.h" #include "tilelayer.h" #include "tileset.h" #include "terrain.h" #include using namespace Tiled; static QString colorToString(const QColor &color) { if (color.alpha() != 255) return color.name(QColor::HexArgb); return color.name(); } QVariant MapToVariantConverter::toVariant(const Map &map, const QDir &mapDir) { mMapDir = mapDir; mGidMapper.clear(); QVariantMap mapVariant; mapVariant[QLatin1String("type")] = QLatin1String("map"); mapVariant[QLatin1String("version")] = 1.0; mapVariant[QLatin1String("tiledversion")] = QCoreApplication::applicationVersion(); mapVariant[QLatin1String("orientation")] = orientationToString(map.orientation()); mapVariant[QLatin1String("renderorder")] = renderOrderToString(map.renderOrder()); mapVariant[QLatin1String("width")] = map.width(); mapVariant[QLatin1String("height")] = map.height(); mapVariant[QLatin1String("tilewidth")] = map.tileWidth(); mapVariant[QLatin1String("tileheight")] = map.tileHeight(); mapVariant[QLatin1String("nextobjectid")] = map.nextObjectId(); addProperties(mapVariant, map.properties()); if (map.orientation() == Map::Hexagonal) { mapVariant[QLatin1String("hexsidelength")] = map.hexSideLength(); } if (map.orientation() == Map::Hexagonal || map.orientation() == Map::Staggered) { mapVariant[QLatin1String("staggeraxis")] = staggerAxisToString(map.staggerAxis()); mapVariant[QLatin1String("staggerindex")] = staggerIndexToString(map.staggerIndex()); } const QColor bgColor = map.backgroundColor(); if (bgColor.isValid()) mapVariant[QLatin1String("backgroundcolor")] = colorToString(bgColor); QVariantList tilesetVariants; unsigned firstGid = 1; for (const SharedTileset &tileset : map.tilesets()) { tilesetVariants << toVariant(*tileset, firstGid); mGidMapper.insert(firstGid, tileset.data()); firstGid += tileset->nextTileId(); } mapVariant[QLatin1String("tilesets")] = tilesetVariants; mapVariant[QLatin1String("layers")] = toVariant(map.layers(), map.layerDataFormat()); return mapVariant; } QVariant MapToVariantConverter::toVariant(const Tileset &tileset, const QDir &directory) { mMapDir = directory; return toVariant(tileset, 0); } QVariant MapToVariantConverter::toVariant(const Tileset &tileset, int firstGid) const { QVariantMap tilesetVariant; if (firstGid > 0) tilesetVariant[QLatin1String("firstgid")] = firstGid; const QString &fileName = tileset.fileName(); if (!fileName.isEmpty()) { QString source = mMapDir.relativeFilePath(fileName); tilesetVariant[QLatin1String("source")] = source; // Tileset is external, so no need to write any of the stuff below return tilesetVariant; } // Include a 'type' property if we are writing the tileset to its own file if (firstGid == 0) tilesetVariant[QLatin1String("type")] = QLatin1String("tileset"); tilesetVariant[QLatin1String("name")] = tileset.name(); tilesetVariant[QLatin1String("tilewidth")] = tileset.tileWidth(); tilesetVariant[QLatin1String("tileheight")] = tileset.tileHeight(); tilesetVariant[QLatin1String("spacing")] = tileset.tileSpacing(); tilesetVariant[QLatin1String("margin")] = tileset.margin(); tilesetVariant[QLatin1String("tilecount")] = tileset.tileCount(); tilesetVariant[QLatin1String("columns")] = tileset.columnCount(); const QColor bgColor = tileset.backgroundColor(); if (bgColor.isValid()) tilesetVariant[QLatin1String("backgroundcolor")] = colorToString(bgColor); addProperties(tilesetVariant, tileset.properties()); const QPoint offset = tileset.tileOffset(); if (!offset.isNull()) { QVariantMap tileOffset; tileOffset[QLatin1String("x")] = offset.x(); tileOffset[QLatin1String("y")] = offset.y(); tilesetVariant[QLatin1String("tileoffset")] = tileOffset; } if (tileset.orientation() != Tileset::Orthogonal || tileset.gridSize() != tileset.tileSize()) { QVariantMap grid; grid[QLatin1String("orientation")] = Tileset::orientationToString(tileset.orientation()); grid[QLatin1String("width")] = tileset.gridSize().width(); grid[QLatin1String("height")] = tileset.gridSize().height(); tilesetVariant[QLatin1String("grid")] = grid; } // Write the image element const QString &imageSource = tileset.imageSource(); if (!imageSource.isEmpty()) { const QString rel = mMapDir.relativeFilePath(tileset.imageSource()); tilesetVariant[QLatin1String("image")] = rel; const QColor transColor = tileset.transparentColor(); if (transColor.isValid()) tilesetVariant[QLatin1String("transparentcolor")] = transColor.name(); tilesetVariant[QLatin1String("imagewidth")] = tileset.imageWidth(); tilesetVariant[QLatin1String("imageheight")] = tileset.imageHeight(); } // Write the properties, terrain, external image, object group and // animation for those tiles that have them. QVariantMap tilePropertiesVariant; QVariantMap tilePropertyTypesVariant; QVariantMap tilesVariant; for (const Tile *tile : tileset.tiles()) { const Properties properties = tile->properties(); if (!properties.isEmpty()) { tilePropertiesVariant[QString::number(tile->id())] = toVariant(properties); tilePropertyTypesVariant[QString::number(tile->id())] = propertyTypesToVariant(properties); } QVariantMap tileVariant; if (!tile->type().isEmpty()) tileVariant[QLatin1String("type")] = tile->type(); if (tile->terrain() != 0xFFFFFFFF) { QVariantList terrainIds; for (int j = 0; j < 4; ++j) terrainIds << QVariant(tile->cornerTerrainId(j)); tileVariant[QLatin1String("terrain")] = terrainIds; } if (tile->probability() != 1.f) tileVariant[QLatin1String("probability")] = tile->probability(); if (!tile->imageSource().isEmpty()) { const QString rel = mMapDir.relativeFilePath(tile->imageSource()); tileVariant[QLatin1String("image")] = rel; const QSize tileSize = tile->size(); if (!tileSize.isNull()) { tileVariant[QLatin1String("imagewidth")] = tileSize.width(); tileVariant[QLatin1String("imageheight")] = tileSize.height(); } } if (tile->objectGroup()) tileVariant[QLatin1String("objectgroup")] = toVariant(*tile->objectGroup()); if (tile->isAnimated()) { QVariantList frameVariants; for (const Frame &frame : tile->frames()) { QVariantMap frameVariant; frameVariant[QLatin1String("tileid")] = frame.tileId; frameVariant[QLatin1String("duration")] = frame.duration; frameVariants.append(frameVariant); } tileVariant[QLatin1String("animation")] = frameVariants; } if (!tileVariant.empty()) tilesVariant[QString::number(tile->id())] = tileVariant; } if (!tilePropertiesVariant.empty()) { tilesetVariant[QLatin1String("tileproperties")] = tilePropertiesVariant; tilesetVariant[QLatin1String("tilepropertytypes")] = tilePropertyTypesVariant; } if (!tilesVariant.empty()) tilesetVariant[QLatin1String("tiles")] = tilesVariant; // Write terrains if (tileset.terrainCount() > 0) { QVariantList terrainsVariant; for (int i = 0; i < tileset.terrainCount(); ++i) { Terrain *terrain = tileset.terrain(i); const Properties &properties = terrain->properties(); QVariantMap terrainVariant; terrainVariant[QLatin1String("name")] = terrain->name(); terrainVariant[QLatin1String("tile")] = terrain->imageTileId(); addProperties(terrainVariant, properties); terrainsVariant << terrainVariant; } tilesetVariant[QLatin1String("terrains")] = terrainsVariant; } return tilesetVariant; } QVariant MapToVariantConverter::toVariant(const Properties &properties) const { QVariantMap variantMap; Properties::const_iterator it = properties.constBegin(); Properties::const_iterator it_end = properties.constEnd(); for (; it != it_end; ++it) { QVariant value = toExportValue(it.value()); if (it.value().userType() == filePathTypeId()) value = mMapDir.relativeFilePath(value.toString()); variantMap[it.key()] = value; } return variantMap; } QVariant MapToVariantConverter::propertyTypesToVariant(const Properties &properties) const { QVariantMap variantMap; Properties::const_iterator it = properties.constBegin(); Properties::const_iterator it_end = properties.constEnd(); for (; it != it_end; ++it) variantMap[it.key()] = typeToName(it.value().userType()); return variantMap; } QVariant MapToVariantConverter::toVariant(const QList &layers, Map::LayerDataFormat format) const { QVariantList layerVariants; for (const Layer *layer : layers) { switch (layer->layerType()) { case Layer::TileLayerType: layerVariants << toVariant(*static_cast(layer), format); break; case Layer::ObjectGroupType: layerVariants << toVariant(*static_cast(layer)); break; case Layer::ImageLayerType: layerVariants << toVariant(*static_cast(layer)); break; case Layer::GroupLayerType: layerVariants << toVariant(*static_cast(layer), format); } } return layerVariants; } QVariant MapToVariantConverter::toVariant(const TileLayer &tileLayer, Map::LayerDataFormat format) const { QVariantMap tileLayerVariant; tileLayerVariant[QLatin1String("type")] = QLatin1String("tilelayer"); tileLayerVariant[QLatin1String("width")] = tileLayer.width(); tileLayerVariant[QLatin1String("height")] = tileLayer.height(); addLayerAttributes(tileLayerVariant, tileLayer); switch (format) { case Map::XML: case Map::CSV: { QVariantList tileVariants; for (int y = 0; y < tileLayer.height(); ++y) for (int x = 0; x < tileLayer.width(); ++x) tileVariants << mGidMapper.cellToGid(tileLayer.cellAt(x, y)); tileLayerVariant[QLatin1String("data")] = tileVariants; break; } case Map::Base64: case Map::Base64Zlib: case Map::Base64Gzip: { tileLayerVariant[QLatin1String("encoding")] = QLatin1String("base64"); if (format == Map::Base64Zlib) tileLayerVariant[QLatin1String("compression")] = QLatin1String("zlib"); else if (format == Map::Base64Gzip) tileLayerVariant[QLatin1String("compression")] = QLatin1String("gzip"); QByteArray layerData = mGidMapper.encodeLayerData(tileLayer, format); tileLayerVariant[QLatin1String("data")] = layerData; break; } } return tileLayerVariant; } QVariant MapToVariantConverter::toVariant(const ObjectGroup &objectGroup) const { QVariantMap objectGroupVariant; objectGroupVariant[QLatin1String("type")] = QLatin1String("objectgroup"); if (objectGroup.color().isValid()) objectGroupVariant[QLatin1String("color")] = colorToString(objectGroup.color()); objectGroupVariant[QLatin1String("draworder")] = drawOrderToString(objectGroup.drawOrder()); addLayerAttributes(objectGroupVariant, objectGroup); QVariantList objectVariants; for (const MapObject *object : objectGroup.objects()) { QVariantMap objectVariant; const QString &name = object->name(); const QString &type = object->type(); addProperties(objectVariant, object->properties()); objectVariant[QLatin1String("id")] = object->id(); objectVariant[QLatin1String("name")] = name; objectVariant[QLatin1String("type")] = type; if (!object->cell().isEmpty()) objectVariant[QLatin1String("gid")] = mGidMapper.cellToGid(object->cell()); objectVariant[QLatin1String("x")] = object->x(); objectVariant[QLatin1String("y")] = object->y(); objectVariant[QLatin1String("width")] = object->width(); objectVariant[QLatin1String("height")] = object->height(); objectVariant[QLatin1String("rotation")] = object->rotation(); objectVariant[QLatin1String("visible")] = object->isVisible(); /* Polygons are stored in this format: * * "polygon/polyline": [ * { "x": 0, "y": 0 }, * { "x": 1, "y": 1 }, * ... * ] */ switch (object->shape()) { case MapObject::Rectangle: break; case MapObject::Polygon: case MapObject::Polyline: { QVariantList pointVariants; for (const QPointF &point : object->polygon()) { QVariantMap pointVariant; pointVariant[QLatin1String("x")] = point.x(); pointVariant[QLatin1String("y")] = point.y(); pointVariants.append(pointVariant); } if (object->shape() == MapObject::Polygon) objectVariant[QLatin1String("polygon")] = pointVariants; else objectVariant[QLatin1String("polyline")] = pointVariants; break; } case MapObject::Ellipse: objectVariant[QLatin1String("ellipse")] = true; break; case MapObject::Text: objectVariant[QLatin1String("text")] = toVariant(object->textData()); break; } objectVariants << objectVariant; } objectGroupVariant[QLatin1String("objects")] = objectVariants; return objectGroupVariant; } QVariant MapToVariantConverter::toVariant(const TextData &textData) const { QVariantMap textVariant; textVariant[QLatin1String("text")] = textData.text; if (textData.font.family() != QLatin1String("sans-serif")) textVariant[QLatin1String("fontfamily")] = textData.font.family(); if (textData.font.pixelSize() >= 0 && textData.font.pixelSize() != 16) textVariant[QLatin1String("pixelsize")] = textData.font.pixelSize(); if (textData.wordWrap) textVariant[QLatin1String("wrap")] = textData.wordWrap; if (textData.color != Qt::black) textVariant[QLatin1String("color")] = colorToString(textData.color); if (textData.font.bold()) textVariant[QLatin1String("bold")] = textData.font.bold(); if (textData.font.italic()) textVariant[QLatin1String("italic")] = textData.font.italic(); if (textData.font.underline()) textVariant[QLatin1String("underline")] = textData.font.underline(); if (textData.font.strikeOut()) textVariant[QLatin1String("strikeout")] = textData.font.strikeOut(); if (!textData.font.kerning()) textVariant[QLatin1String("kerning")] = textData.font.kerning(); if (!textData.alignment.testFlag(Qt::AlignLeft)) { if (textData.alignment.testFlag(Qt::AlignHCenter)) textVariant[QLatin1String("halign")] = QLatin1String("center"); else if (textData.alignment.testFlag(Qt::AlignRight)) textVariant[QLatin1String("halign")] = QLatin1String("right"); } if (!textData.alignment.testFlag(Qt::AlignTop)) { if (textData.alignment.testFlag(Qt::AlignVCenter)) textVariant[QLatin1String("valign")] = QLatin1String("center"); else if (textData.alignment.testFlag(Qt::AlignBottom)) textVariant[QLatin1String("valign")] = QLatin1String("bottom"); } return textVariant; } QVariant MapToVariantConverter::toVariant(const ImageLayer &imageLayer) const { QVariantMap imageLayerVariant; imageLayerVariant[QLatin1String("type")] = QLatin1String("imagelayer"); addLayerAttributes(imageLayerVariant, imageLayer); const QString rel = mMapDir.relativeFilePath(imageLayer.imageSource()); imageLayerVariant[QLatin1String("image")] = rel; const QColor transColor = imageLayer.transparentColor(); if (transColor.isValid()) imageLayerVariant[QLatin1String("transparentcolor")] = transColor.name(); return imageLayerVariant; } QVariant MapToVariantConverter::toVariant(const GroupLayer &groupLayer, Map::LayerDataFormat format) const { QVariantMap groupLayerVariant; groupLayerVariant[QLatin1String("type")] = QLatin1String("group"); addLayerAttributes(groupLayerVariant, groupLayer); groupLayerVariant[QLatin1String("layers")] = toVariant(groupLayer.layers(), format); return groupLayerVariant; } void MapToVariantConverter::addLayerAttributes(QVariantMap &layerVariant, const Layer &layer) const { layerVariant[QLatin1String("name")] = layer.name(); layerVariant[QLatin1String("x")] = layer.x(); layerVariant[QLatin1String("y")] = layer.y(); layerVariant[QLatin1String("visible")] = layer.isVisible(); layerVariant[QLatin1String("opacity")] = layer.opacity(); const QPointF offset = layer.offset(); if (!offset.isNull()) { layerVariant[QLatin1String("offsetx")] = offset.x(); layerVariant[QLatin1String("offsety")] = offset.y(); } addProperties(layerVariant, layer.properties()); } void MapToVariantConverter::addProperties(QVariantMap &variantMap, const Properties &properties) const { if (properties.isEmpty()) return; QVariantMap propertiesMap; QVariantMap propertyTypesMap; Properties::const_iterator it = properties.constBegin(); Properties::const_iterator it_end = properties.constEnd(); for (; it != it_end; ++it) { int type = it.value().userType(); QVariant value = toExportValue(it.value()); if (type == filePathTypeId()) value = mMapDir.relativeFilePath(value.toString()); propertiesMap[it.key()] = value; propertyTypesMap[it.key()] = typeToName(type); } variantMap[QLatin1String("properties")] = propertiesMap; variantMap[QLatin1String("propertytypes")] = propertyTypesMap; } tiled-1.0.3/src/libtiled/maptovariantconverter.h000066400000000000000000000047641315121121300220020ustar00rootroot00000000000000/* * maptovariantconverter.h * Copyright 2011, Porfírio José Pereira Ribeiro * Copyright 2011-2015, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include #include "gidmapper.h" namespace Tiled { class GroupLayer; struct TextData; /** * Converts Map instances to QVariant. Meant to be used together with * JsonWriter. */ class TILEDSHARED_EXPORT MapToVariantConverter { public: MapToVariantConverter() {} /** * Converts the given \s map to a QVariant. The \a mapDir is used to * construct relative paths to external resources. */ QVariant toVariant(const Map &map, const QDir &mapDir); /** * Converts the given \s tileset to a QVariant. The \a directory is used to * construct relative paths to external resources. */ QVariant toVariant(const Tileset &tileset, const QDir &directory); private: QVariant toVariant(const Tileset &tileset, int firstGid) const; QVariant toVariant(const Properties &properties) const; QVariant propertyTypesToVariant(const Properties &properties) const; QVariant toVariant(const QList &layers, Map::LayerDataFormat format) const; QVariant toVariant(const TileLayer &tileLayer, Map::LayerDataFormat format) const; QVariant toVariant(const ObjectGroup &objectGroup) const; QVariant toVariant(const TextData &textData) const; QVariant toVariant(const ImageLayer &imageLayer) const; QVariant toVariant(const GroupLayer &groupLayer, Map::LayerDataFormat format) const; void addLayerAttributes(QVariantMap &layerVariant, const Layer &layer) const; void addProperties(QVariantMap &variantMap, const Properties &properties) const; QDir mMapDir; GidMapper mGidMapper; }; } // namespace Tiled tiled-1.0.3/src/libtiled/mapwriter.cpp000066400000000000000000000710261315121121300177050ustar00rootroot00000000000000/* * mapwriter.cpp * Copyright 2008-2014, Thorbjørn Lindeijer * Copyright 2010, Jeff Bland * Copyright 2010, Dennis Honeyman * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mapwriter.h" #include "compression.h" #include "gidmapper.h" #include "grouplayer.h" #include "map.h" #include "mapobject.h" #include "imagelayer.h" #include "objectgroup.h" #include "savefile.h" #include "tile.h" #include "tilelayer.h" #include "tileset.h" #include "terrain.h" #include #include #include #include using namespace Tiled; using namespace Tiled::Internal; static QString colorToString(const QColor &color) { if (color.alpha() != 255) return color.name(QColor::HexArgb); return color.name(); } namespace Tiled { namespace Internal { class MapWriterPrivate { Q_DECLARE_TR_FUNCTIONS(MapReader) public: MapWriterPrivate(); void writeMap(const Map *map, QIODevice *device, const QString &path); void writeTileset(const Tileset &tileset, QIODevice *device, const QString &path); bool openFile(SaveFile *file); QString mError; Map::LayerDataFormat mLayerDataFormat; bool mDtdEnabled; private: void writeMap(QXmlStreamWriter &w, const Map &map); void writeTileset(QXmlStreamWriter &w, const Tileset &tileset, unsigned firstGid); void writeLayers(QXmlStreamWriter &w, const QList &layers); void writeTileLayer(QXmlStreamWriter &w, const TileLayer &tileLayer); void writeLayerAttributes(QXmlStreamWriter &w, const Layer &layer); void writeObjectGroup(QXmlStreamWriter &w, const ObjectGroup &objectGroup); void writeObject(QXmlStreamWriter &w, const MapObject &mapObject); void writeObjectText(QXmlStreamWriter &w, const TextData &textData); void writeImageLayer(QXmlStreamWriter &w, const ImageLayer &imageLayer); void writeGroupLayer(QXmlStreamWriter &w, const GroupLayer &groupLayer); void writeProperties(QXmlStreamWriter &w, const Properties &properties); QDir mMapDir; // The directory in which the map is being saved GidMapper mGidMapper; bool mUseAbsolutePaths; }; } // namespace Internal } // namespace Tiled MapWriterPrivate::MapWriterPrivate() : mLayerDataFormat(Map::Base64Zlib) , mDtdEnabled(false) , mUseAbsolutePaths(false) { } bool MapWriterPrivate::openFile(SaveFile *file) { if (!file->open(QIODevice::WriteOnly | QIODevice::Text)) { mError = tr("Could not open file for writing."); return false; } return true; } namespace { class AutoFormattingWriter : public QXmlStreamWriter { public: explicit AutoFormattingWriter(QIODevice *device) : QXmlStreamWriter(device) { setAutoFormatting(true); setAutoFormattingIndent(1); } }; } // anonymous namespace void MapWriterPrivate::writeMap(const Map *map, QIODevice *device, const QString &path) { mMapDir = QDir(path); mUseAbsolutePaths = path.isEmpty(); mLayerDataFormat = map->layerDataFormat(); AutoFormattingWriter writer(device); writer.writeStartDocument(); if (mDtdEnabled) { writer.writeDTD(QLatin1String("")); } writeMap(writer, *map); writer.writeEndDocument(); } void MapWriterPrivate::writeTileset(const Tileset &tileset, QIODevice *device, const QString &path) { mMapDir = QDir(path); mUseAbsolutePaths = path.isEmpty(); AutoFormattingWriter writer(device); writer.writeStartDocument(); if (mDtdEnabled) { writer.writeDTD(QLatin1String("")); } writeTileset(writer, tileset, 0); writer.writeEndDocument(); } void MapWriterPrivate::writeMap(QXmlStreamWriter &w, const Map &map) { w.writeStartElement(QLatin1String("map")); const QString orientation = orientationToString(map.orientation()); const QString renderOrder = renderOrderToString(map.renderOrder()); w.writeAttribute(QLatin1String("version"), QLatin1String("1.0")); w.writeAttribute(QLatin1String("tiledversion"), QCoreApplication::applicationVersion()); w.writeAttribute(QLatin1String("orientation"), orientation); w.writeAttribute(QLatin1String("renderorder"), renderOrder); w.writeAttribute(QLatin1String("width"), QString::number(map.width())); w.writeAttribute(QLatin1String("height"), QString::number(map.height())); w.writeAttribute(QLatin1String("tilewidth"), QString::number(map.tileWidth())); w.writeAttribute(QLatin1String("tileheight"), QString::number(map.tileHeight())); if (map.orientation() == Map::Hexagonal) { w.writeAttribute(QLatin1String("hexsidelength"), QString::number(map.hexSideLength())); } if (map.orientation() == Map::Staggered || map.orientation() == Map::Hexagonal) { w.writeAttribute(QLatin1String("staggeraxis"), staggerAxisToString(map.staggerAxis())); w.writeAttribute(QLatin1String("staggerindex"), staggerIndexToString(map.staggerIndex())); } if (map.backgroundColor().isValid()) { w.writeAttribute(QLatin1String("backgroundcolor"), colorToString(map.backgroundColor())); } w.writeAttribute(QLatin1String("nextobjectid"), QString::number(map.nextObjectId())); writeProperties(w, map.properties()); mGidMapper.clear(); unsigned firstGid = 1; for (const SharedTileset &tileset : map.tilesets()) { writeTileset(w, *tileset, firstGid); mGidMapper.insert(firstGid, tileset.data()); firstGid += tileset->nextTileId(); } writeLayers(w, map.layers()); w.writeEndElement(); } static QString makeTerrainAttribute(const Tile *tile) { QString terrain; for (int i = 0; i < 4; ++i ) { if (i > 0) terrain += QLatin1String(","); int t = tile->cornerTerrainId(i); if (t > -1) terrain += QString::number(t); } return terrain; } static bool includeTile(const Tile *tile) { if (!tile->type().isEmpty()) return true; if (!tile->properties().isEmpty()) return true; if (!tile->imageSource().isEmpty()) return true; if (tile->objectGroup()) return true; if (tile->isAnimated()) return true; if (tile->terrain() != 0xFFFFFFFF) return true; if (tile->probability() != 1.f) return true; return false; } void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset, unsigned firstGid) { w.writeStartElement(QLatin1String("tileset")); if (firstGid > 0) w.writeAttribute(QLatin1String("firstgid"), QString::number(firstGid)); const QString &fileName = tileset.fileName(); if (!fileName.isEmpty()) { QString source = fileName; if (!mUseAbsolutePaths) source = mMapDir.relativeFilePath(source); w.writeAttribute(QLatin1String("source"), source); // Tileset is external, so no need to write any of the stuff below w.writeEndElement(); return; } w.writeAttribute(QLatin1String("name"), tileset.name()); w.writeAttribute(QLatin1String("tilewidth"), QString::number(tileset.tileWidth())); w.writeAttribute(QLatin1String("tileheight"), QString::number(tileset.tileHeight())); const int tileSpacing = tileset.tileSpacing(); const int margin = tileset.margin(); if (tileSpacing != 0) w.writeAttribute(QLatin1String("spacing"), QString::number(tileSpacing)); if (margin != 0) w.writeAttribute(QLatin1String("margin"), QString::number(margin)); w.writeAttribute(QLatin1String("tilecount"), QString::number(tileset.tileCount())); w.writeAttribute(QLatin1String("columns"), QString::number(tileset.columnCount())); if (tileset.backgroundColor().isValid()) { w.writeAttribute(QLatin1String("backgroundcolor"), colorToString(tileset.backgroundColor())); } const QPoint offset = tileset.tileOffset(); if (!offset.isNull()) { w.writeStartElement(QLatin1String("tileoffset")); w.writeAttribute(QLatin1String("x"), QString::number(offset.x())); w.writeAttribute(QLatin1String("y"), QString::number(offset.y())); w.writeEndElement(); } if (tileset.orientation() != Tileset::Orthogonal || tileset.gridSize() != tileset.tileSize()) { w.writeStartElement(QLatin1String("grid")); w.writeAttribute(QLatin1String("orientation"), Tileset::orientationToString(tileset.orientation())); w.writeAttribute(QLatin1String("width"), QString::number(tileset.gridSize().width())); w.writeAttribute(QLatin1String("height"), QString::number(tileset.gridSize().height())); w.writeEndElement(); } // Write the tileset properties writeProperties(w, tileset.properties()); // Write the image element const QString &imageSource = tileset.imageSource(); if (!imageSource.isEmpty()) { w.writeStartElement(QLatin1String("image")); QString source = imageSource; if (!mUseAbsolutePaths) source = mMapDir.relativeFilePath(source); w.writeAttribute(QLatin1String("source"), source); const QColor transColor = tileset.transparentColor(); if (transColor.isValid()) w.writeAttribute(QLatin1String("trans"), transColor.name().mid(1)); if (tileset.imageWidth() > 0) w.writeAttribute(QLatin1String("width"), QString::number(tileset.imageWidth())); if (tileset.imageHeight() > 0) w.writeAttribute(QLatin1String("height"), QString::number(tileset.imageHeight())); w.writeEndElement(); } // Write the terrain types if (tileset.terrainCount() > 0) { w.writeStartElement(QLatin1String("terraintypes")); for (int i = 0; i < tileset.terrainCount(); ++i) { const Terrain *t = tileset.terrain(i); w.writeStartElement(QLatin1String("terrain")); w.writeAttribute(QLatin1String("name"), t->name()); w.writeAttribute(QLatin1String("tile"), QString::number(t->imageTileId())); writeProperties(w, t->properties()); w.writeEndElement(); } w.writeEndElement(); } // Write the properties for those tiles that have them for (const Tile *tile : tileset.tiles()) { if (imageSource.isEmpty() || includeTile(tile)) { w.writeStartElement(QLatin1String("tile")); w.writeAttribute(QLatin1String("id"), QString::number(tile->id())); if (!tile->type().isEmpty()) w.writeAttribute(QLatin1String("type"), tile->type()); if (tile->terrain() != 0xFFFFFFFF) w.writeAttribute(QLatin1String("terrain"), makeTerrainAttribute(tile)); if (tile->probability() != 1.f) w.writeAttribute(QLatin1String("probability"), QString::number(tile->probability())); if (!tile->properties().isEmpty()) writeProperties(w, tile->properties()); if (imageSource.isEmpty()) { w.writeStartElement(QLatin1String("image")); const QSize tileSize = tile->size(); if (!tileSize.isNull()) { w.writeAttribute(QLatin1String("width"), QString::number(tileSize.width())); w.writeAttribute(QLatin1String("height"), QString::number(tileSize.height())); } if (tile->imageSource().isEmpty()) { w.writeAttribute(QLatin1String("format"), QLatin1String("png")); w.writeStartElement(QLatin1String("data")); w.writeAttribute(QLatin1String("encoding"), QLatin1String("base64")); QBuffer buffer; tile->image().save(&buffer, "png"); w.writeCharacters(QString::fromLatin1(buffer.data().toBase64())); w.writeEndElement(); // } else { QString source = tile->imageSource(); if (!mUseAbsolutePaths) source = mMapDir.relativeFilePath(source); w.writeAttribute(QLatin1String("source"), source); } w.writeEndElement(); // } if (tile->objectGroup()) writeObjectGroup(w, *tile->objectGroup()); if (tile->isAnimated()) { const QVector &frames = tile->frames(); w.writeStartElement(QLatin1String("animation")); for (const Frame &frame : frames) { w.writeStartElement(QLatin1String("frame")); w.writeAttribute(QLatin1String("tileid"), QString::number(frame.tileId)); w.writeAttribute(QLatin1String("duration"), QString::number(frame.duration)); w.writeEndElement(); // } w.writeEndElement(); // } w.writeEndElement(); // } } w.writeEndElement(); } void MapWriterPrivate::writeLayers(QXmlStreamWriter &w, const QList &layers) { for (const Layer *layer : layers) { switch (layer->layerType()) { case Layer::TileLayerType: writeTileLayer(w, *static_cast(layer)); break; case Layer::ObjectGroupType: writeObjectGroup(w, *static_cast(layer)); break; case Layer::ImageLayerType: writeImageLayer(w, *static_cast(layer)); break; case Layer::GroupLayerType: writeGroupLayer(w, *static_cast(layer)); break; } } } void MapWriterPrivate::writeTileLayer(QXmlStreamWriter &w, const TileLayer &tileLayer) { w.writeStartElement(QLatin1String("layer")); writeLayerAttributes(w, tileLayer); writeProperties(w, tileLayer.properties()); QString encoding; QString compression; if (mLayerDataFormat == Map::Base64 || mLayerDataFormat == Map::Base64Gzip || mLayerDataFormat == Map::Base64Zlib) { encoding = QLatin1String("base64"); if (mLayerDataFormat == Map::Base64Gzip) compression = QLatin1String("gzip"); else if (mLayerDataFormat == Map::Base64Zlib) compression = QLatin1String("zlib"); } else if (mLayerDataFormat == Map::CSV) encoding = QLatin1String("csv"); w.writeStartElement(QLatin1String("data")); if (!encoding.isEmpty()) w.writeAttribute(QLatin1String("encoding"), encoding); if (!compression.isEmpty()) w.writeAttribute(QLatin1String("compression"), compression); if (mLayerDataFormat == Map::XML) { for (int y = 0; y < tileLayer.height(); ++y) { for (int x = 0; x < tileLayer.width(); ++x) { const unsigned gid = mGidMapper.cellToGid(tileLayer.cellAt(x, y)); w.writeStartElement(QLatin1String("tile")); w.writeAttribute(QLatin1String("gid"), QString::number(gid)); w.writeEndElement(); } } } else if (mLayerDataFormat == Map::CSV) { QString tileData; for (int y = 0; y < tileLayer.height(); ++y) { for (int x = 0; x < tileLayer.width(); ++x) { const unsigned gid = mGidMapper.cellToGid(tileLayer.cellAt(x, y)); tileData.append(QString::number(gid)); if (x != tileLayer.width() - 1 || y != tileLayer.height() - 1) tileData.append(QLatin1String(",")); } tileData.append(QLatin1String("\n")); } w.writeCharacters(QLatin1String("\n")); w.writeCharacters(tileData); } else { QByteArray tileData = mGidMapper.encodeLayerData(tileLayer, mLayerDataFormat); w.writeCharacters(QLatin1String("\n ")); w.writeCharacters(QString::fromLatin1(tileData)); w.writeCharacters(QLatin1String("\n ")); } w.writeEndElement(); // w.writeEndElement(); // } void MapWriterPrivate::writeLayerAttributes(QXmlStreamWriter &w, const Layer &layer) { if (!layer.name().isEmpty()) w.writeAttribute(QLatin1String("name"), layer.name()); const int x = layer.x(); const int y = layer.y(); const qreal opacity = layer.opacity(); if (x != 0) w.writeAttribute(QLatin1String("x"), QString::number(x)); if (y != 0) w.writeAttribute(QLatin1String("y"), QString::number(y)); if (layer.layerType() == Layer::TileLayerType) { auto &tileLayer = static_cast(layer); w.writeAttribute(QLatin1String("width"), QString::number(tileLayer.width())); w.writeAttribute(QLatin1String("height"), QString::number(tileLayer.height())); } if (!layer.isVisible()) w.writeAttribute(QLatin1String("visible"), QLatin1String("0")); if (opacity != qreal(1)) w.writeAttribute(QLatin1String("opacity"), QString::number(opacity)); const QPointF offset = layer.offset(); if (!offset.isNull()) { w.writeAttribute(QLatin1String("offsetx"), QString::number(offset.x())); w.writeAttribute(QLatin1String("offsety"), QString::number(offset.y())); } } void MapWriterPrivate::writeObjectGroup(QXmlStreamWriter &w, const ObjectGroup &objectGroup) { w.writeStartElement(QLatin1String("objectgroup")); if (objectGroup.color().isValid()) w.writeAttribute(QLatin1String("color"), colorToString(objectGroup.color())); if (objectGroup.drawOrder() != ObjectGroup::TopDownOrder) { w.writeAttribute(QLatin1String("draworder"), drawOrderToString(objectGroup.drawOrder())); } writeLayerAttributes(w, objectGroup); writeProperties(w, objectGroup.properties()); for (const MapObject *mapObject : objectGroup.objects()) writeObject(w, *mapObject); w.writeEndElement(); } void MapWriterPrivate::writeObject(QXmlStreamWriter &w, const MapObject &mapObject) { w.writeStartElement(QLatin1String("object")); w.writeAttribute(QLatin1String("id"), QString::number(mapObject.id())); const QString &name = mapObject.name(); const QString &type = mapObject.type(); if (!name.isEmpty()) w.writeAttribute(QLatin1String("name"), name); if (!type.isEmpty()) w.writeAttribute(QLatin1String("type"), type); if (!mapObject.cell().isEmpty()) { const unsigned gid = mGidMapper.cellToGid(mapObject.cell()); w.writeAttribute(QLatin1String("gid"), QString::number(gid)); } const QPointF pos = mapObject.position(); const QSizeF size = mapObject.size(); w.writeAttribute(QLatin1String("x"), QString::number(pos.x())); w.writeAttribute(QLatin1String("y"), QString::number(pos.y())); if (size.width() != 0) w.writeAttribute(QLatin1String("width"), QString::number(size.width())); if (size.height() != 0) w.writeAttribute(QLatin1String("height"), QString::number(size.height())); const qreal rotation = mapObject.rotation(); if (rotation != 0.0) w.writeAttribute(QLatin1String("rotation"), QString::number(rotation)); if (!mapObject.isVisible()) w.writeAttribute(QLatin1String("visible"), QLatin1String("0")); writeProperties(w, mapObject.properties()); switch (mapObject.shape()) { case MapObject::Rectangle: break; case MapObject::Polygon: case MapObject::Polyline: { if (mapObject.shape() == MapObject::Polygon) w.writeStartElement(QLatin1String("polygon")); else w.writeStartElement(QLatin1String("polyline")); QString points; for (const QPointF &point : mapObject.polygon()) { points.append(QString::number(point.x())); points.append(QLatin1Char(',')); points.append(QString::number(point.y())); points.append(QLatin1Char(' ')); } points.chop(1); w.writeAttribute(QLatin1String("points"), points); w.writeEndElement(); break; } case MapObject::Ellipse: w.writeEmptyElement(QLatin1String("ellipse")); break; case MapObject::Text: { writeObjectText(w, mapObject.textData()); break; } } w.writeEndElement(); } void MapWriterPrivate::writeObjectText(QXmlStreamWriter &w, const TextData &textData) { w.writeStartElement(QLatin1String("text")); if (textData.font.family() != QLatin1String("sans-serif")) w.writeAttribute(QLatin1String("fontfamily"), textData.font.family()); if (textData.font.pixelSize() >= 0 && textData.font.pixelSize() != 16) w.writeAttribute(QLatin1String("pixelsize"), QString::number(textData.font.pixelSize())); if (textData.wordWrap) w.writeAttribute(QLatin1String("wrap"), QLatin1String("1")); if (textData.color != Qt::black) w.writeAttribute(QLatin1String("color"), colorToString(textData.color)); if (textData.font.bold()) w.writeAttribute(QLatin1String("bold"), QLatin1String("1")); if (textData.font.italic()) w.writeAttribute(QLatin1String("italic"), QLatin1String("1")); if (textData.font.underline()) w.writeAttribute(QLatin1String("underline"), QLatin1String("1")); if (textData.font.strikeOut()) w.writeAttribute(QLatin1String("strikeout"), QLatin1String("1")); if (!textData.font.kerning()) w.writeAttribute(QLatin1String("kerning"), QLatin1String("0")); if (!textData.alignment.testFlag(Qt::AlignLeft)) { if (textData.alignment.testFlag(Qt::AlignHCenter)) w.writeAttribute(QLatin1String("halign"), QLatin1String("center")); else if (textData.alignment.testFlag(Qt::AlignRight)) w.writeAttribute(QLatin1String("halign"), QLatin1String("right")); } if (!textData.alignment.testFlag(Qt::AlignTop)) { if (textData.alignment.testFlag(Qt::AlignVCenter)) w.writeAttribute(QLatin1String("valign"), QLatin1String("center")); else if (textData.alignment.testFlag(Qt::AlignBottom)) w.writeAttribute(QLatin1String("valign"), QLatin1String("bottom")); } w.writeCharacters(textData.text); w.writeEndElement(); } void MapWriterPrivate::writeImageLayer(QXmlStreamWriter &w, const ImageLayer &imageLayer) { w.writeStartElement(QLatin1String("imagelayer")); writeLayerAttributes(w, imageLayer); // Write the image element const QString &imageSource = imageLayer.imageSource(); if (!imageSource.isEmpty()) { w.writeStartElement(QLatin1String("image")); QString source = imageSource; if (!mUseAbsolutePaths) source = mMapDir.relativeFilePath(source); w.writeAttribute(QLatin1String("source"), source); const QColor transColor = imageLayer.transparentColor(); if (transColor.isValid()) w.writeAttribute(QLatin1String("trans"), transColor.name().mid(1)); const QSize imageSize = imageLayer.image().size(); if (!imageSize.isNull()) { w.writeAttribute(QLatin1String("width"), QString::number(imageSize.width())); w.writeAttribute(QLatin1String("height"), QString::number(imageSize.height())); } w.writeEndElement(); } writeProperties(w, imageLayer.properties()); w.writeEndElement(); } void MapWriterPrivate::writeGroupLayer(QXmlStreamWriter &w, const GroupLayer &groupLayer) { w.writeStartElement(QLatin1String("group")); writeLayerAttributes(w, groupLayer); writeProperties(w, groupLayer.properties()); writeLayers(w, groupLayer.layers()); w.writeEndElement(); } void MapWriterPrivate::writeProperties(QXmlStreamWriter &w, const Properties &properties) { if (properties.isEmpty()) return; w.writeStartElement(QLatin1String("properties")); Properties::const_iterator it = properties.constBegin(); Properties::const_iterator it_end = properties.constEnd(); for (; it != it_end; ++it) { w.writeStartElement(QLatin1String("property")); w.writeAttribute(QLatin1String("name"), it.key()); int type = it.value().userType(); QString typeName = typeToName(type); if (typeName != QLatin1String("string")) w.writeAttribute(QLatin1String("type"), typeName); QString value = toExportValue(it.value()).toString(); if (type == filePathTypeId() && !mUseAbsolutePaths) value = mMapDir.relativeFilePath(value); if (value.contains(QLatin1Char('\n'))) w.writeCharacters(value); else w.writeAttribute(QLatin1String("value"), value); w.writeEndElement(); } w.writeEndElement(); } MapWriter::MapWriter() : d(new MapWriterPrivate) { } MapWriter::~MapWriter() { delete d; } void MapWriter::writeMap(const Map *map, QIODevice *device, const QString &path) { d->writeMap(map, device, path); } bool MapWriter::writeMap(const Map *map, const QString &fileName) { SaveFile file(fileName); if (!d->openFile(&file)) return false; writeMap(map, file.device(), QFileInfo(fileName).absolutePath()); if (file.error() != QFileDevice::NoError) { d->mError = file.errorString(); return false; } if (!file.commit()) { d->mError = file.errorString(); return false; } return true; } void MapWriter::writeTileset(const Tileset &tileset, QIODevice *device, const QString &path) { d->writeTileset(tileset, device, path); } bool MapWriter::writeTileset(const Tileset &tileset, const QString &fileName) { SaveFile file(fileName); if (!d->openFile(&file)) return false; writeTileset(tileset, file.device(), QFileInfo(fileName).absolutePath()); if (file.error() != QFileDevice::NoError) { d->mError = file.errorString(); return false; } if (!file.commit()) { d->mError = file.errorString(); return false; } return true; } QString MapWriter::errorString() const { return d->mError; } void MapWriter::setDtdEnabled(bool enabled) { d->mDtdEnabled = enabled; } bool MapWriter::isDtdEnabled() const { return d->mDtdEnabled; } tiled-1.0.3/src/libtiled/mapwriter.h000066400000000000000000000065611315121121300173540ustar00rootroot00000000000000/* * mapwriter.h * Copyright 2008-2010, Thorbjørn Lindeijer * Copyright 2010, Dennis Honeyman * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "map.h" #include "tiled_global.h" #include class QIODevice; namespace Tiled { class Map; class Tileset; namespace Internal { class MapWriterPrivate; } /** * A QXmlStreamWriter based writer for the TMX and TSX formats. */ class TILEDSHARED_EXPORT MapWriter { public: MapWriter(); ~MapWriter(); /** * Writes a TMX map to the given \a device. Optionally a \a path can * be given, which will be used to create relative references to external * images and tilesets. * * Error checking will need to be done on the \a device after calling this * function. */ void writeMap(const Map *map, QIODevice *device, const QString &path = QString()); /** * Writes a TMX map to the given \a fileName. * * Returns false and sets errorString() when reading failed. * \overload */ bool writeMap(const Map *map, const QString &fileName); /** * Writes a TSX tileset to the given \a device. Optionally a \a path can * be given, which will be used to create relative references to external * images. * * Error checking will need to be done on the \a device after calling this * function. */ void writeTileset(const Tileset &tileset, QIODevice *device, const QString &path = QString()); /** * Writes a TSX tileset to the given \a fileName. * * Returns false and sets errorString() when reading failed. * \overload */ bool writeTileset(const Tileset &tileset, const QString &fileName); /** * Returns the error message for the last occurred error. */ QString errorString() const; /** * Sets whether the DTD reference is written when saving the map. */ void setDtdEnabled(bool enabled); bool isDtdEnabled() const; private: Q_DISABLE_COPY(MapWriter) Internal::MapWriterPrivate *d; }; } // namespace Tiled tiled-1.0.3/src/libtiled/object.h000066400000000000000000000077041315121121300166100ustar00rootroot00000000000000/* * object.h * Copyright 2010, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "properties.h" namespace Tiled { /** * The base class for anything that can hold properties. */ class TILEDSHARED_EXPORT Object { public: enum TypeId { LayerType, MapObjectType, MapType, TerrainType, TilesetType, TileType }; Object(TypeId typeId) : mTypeId(typeId) {} Object(const Object &object) : mTypeId(object.mTypeId), mProperties(object.mProperties) {} /** * Virtual destructor. */ virtual ~Object() {} /** * Returns the type of this object. */ TypeId typeId() const { return mTypeId; } /** * Returns the properties of this object. */ const Properties &properties() const { return mProperties; } /** * Replaces all existing properties with a new set of properties. */ void setProperties(const Properties &properties) { mProperties = properties; } /** * Merges \a properties with the existing properties. Properties with the * same name will be overridden. * * \sa Properties::merge */ void mergeProperties(const Properties &properties) { mProperties.merge(properties); } /** * Returns the value of the object's \a name property. */ QVariant property(const QString &name) const { return mProperties.value(name); } /** * Returns the value of the object's \a name property, as a string. * * This is a workaround for the Python plugin, because I do not know how * to pass a QVariant back to Python. */ QString propertyAsString(const QString &name) const { return mProperties.value(name).toString(); } /** * Returns whether this object has a property with the given \a name. */ bool hasProperty(const QString &name) const { return mProperties.contains(name); } /** * Sets the value of the object's \a name property to \a value. */ void setProperty(const QString &name, const QVariant &value) { mProperties.insert(name, value); } /** * Removes the property with the given \a name. */ void removeProperty(const QString &name) { mProperties.remove(name); } bool isPartOfTileset() const; private: const TypeId mTypeId; Properties mProperties; }; /** * Returns whether this object is stored as part of a tileset. */ inline bool Object::isPartOfTileset() const { switch (mTypeId) { case Object::TilesetType: case Object::TileType: case Object::TerrainType: return true; default: return false; } } } // namespace Tiled tiled-1.0.3/src/libtiled/objectgroup.cpp000066400000000000000000000167741315121121300202270ustar00rootroot00000000000000/* * objectgroup.cpp * Copyright 2008, Roderic Morris * Copyright 2008-2014, Thorbjørn Lindeijer * Copyright 2009-2010, Jeff Bland * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "objectgroup.h" #include "layer.h" #include "map.h" #include "mapobject.h" #include "tile.h" #include using namespace Tiled; ObjectGroup::ObjectGroup() : Layer(ObjectGroupType, QString(), 0, 0) , mDrawOrder(TopDownOrder) { } ObjectGroup::ObjectGroup(const QString &name, int x, int y) : Layer(ObjectGroupType, name, x, y) , mDrawOrder(TopDownOrder) { } ObjectGroup::~ObjectGroup() { qDeleteAll(mObjects); } void ObjectGroup::addObject(MapObject *object) { mObjects.append(object); object->setObjectGroup(this); if (mMap && object->id() == 0) object->setId(mMap->takeNextObjectId()); } void ObjectGroup::insertObject(int index, MapObject *object) { mObjects.insert(index, object); object->setObjectGroup(this); if (mMap && object->id() == 0) object->setId(mMap->takeNextObjectId()); } int ObjectGroup::removeObject(MapObject *object) { const int index = mObjects.indexOf(object); Q_ASSERT(index != -1); mObjects.removeAt(index); object->setObjectGroup(nullptr); return index; } void ObjectGroup::removeObjectAt(int index) { MapObject *object = mObjects.takeAt(index); object->setObjectGroup(nullptr); } void ObjectGroup::moveObjects(int from, int to, int count) { // It's an error when 'to' lies within the moving range of objects Q_ASSERT(count >= 0); Q_ASSERT(to <= from || to >= from + count); // Nothing to be done when 'to' is the start or the end of the range, or // when the number of objects to be moved is 0. if (to == from || to == from + count || count == 0) return; const QList movingObjects = mObjects.mid(from, count); mObjects.erase(mObjects.begin() + from, mObjects.begin() + from + count); if (to > from) to -= count; for (int i = 0; i < count; ++i) mObjects.insert(to + i, movingObjects.at(i)); } QRectF ObjectGroup::objectsBoundingRect() const { QRectF boundingRect; for (const MapObject *object : mObjects) boundingRect = boundingRect.united(object->bounds()); return boundingRect; } bool ObjectGroup::isEmpty() const { return mObjects.isEmpty(); } QSet ObjectGroup::usedTilesets() const { QSet tilesets; for (const MapObject *object : mObjects) if (const Tile *tile = object->cell().tile()) tilesets.insert(tile->sharedTileset()); return tilesets; } bool ObjectGroup::referencesTileset(const Tileset *tileset) const { for (const MapObject *object : mObjects) { if (object->cell().tileset() == tileset) return true; } return false; } void ObjectGroup::replaceReferencesToTileset(Tileset *oldTileset, Tileset *newTileset) { for (MapObject *object : mObjects) { if (object->cell().tileset() == oldTileset) { Cell cell = object->cell(); cell.setTile(newTileset, cell.tileId()); object->setCell(cell); } } } void ObjectGroup::offsetObjects(const QPointF &offset, const QRectF &bounds, bool wrapX, bool wrapY) { for (MapObject *object : mObjects) { const QPointF objectCenter = object->bounds().center(); if (!bounds.contains(objectCenter)) continue; QPointF newCenter(objectCenter + offset); if (wrapX && bounds.width() > 0) { qreal nx = std::fmod(newCenter.x() - bounds.left(), bounds.width()); newCenter.setX(bounds.left() + (nx < 0 ? bounds.width() + nx : nx)); } if (wrapY && bounds.height() > 0) { qreal ny = std::fmod(newCenter.y() - bounds.top(), bounds.height()); newCenter.setY(bounds.top() + (ny < 0 ? bounds.height() + ny : ny)); } object->setPosition(object->position() + (newCenter - objectCenter)); } } bool ObjectGroup::canMergeWith(Layer *other) const { return other->isObjectGroup(); } Layer *ObjectGroup::mergedWith(Layer *other) const { Q_ASSERT(canMergeWith(other)); const ObjectGroup *og = static_cast(other); ObjectGroup *merged = clone(); for (const MapObject *mapObject : og->objects()) merged->addObject(mapObject->clone()); return merged; } /** * Returns a duplicate of this ObjectGroup. * * \sa Layer::clone() */ ObjectGroup *ObjectGroup::clone() const { return initializeClone(new ObjectGroup(mName, mX, mY)); } /** * Resets the ids of all objects to 0. Mostly used when new ids should be * assigned after the object group has been cloned. */ void ObjectGroup::resetObjectIds() { const QList &objects = mObjects; for (MapObject *object : objects) object->resetId(); } /** * Returns the highest object id in use by this object group, or 0 if no object * with assigned id exists. */ int ObjectGroup::highestObjectId() const { int id = 0; for (const MapObject *object : mObjects) id = std::max(id, object->id()); return id; } ObjectGroup *ObjectGroup::initializeClone(ObjectGroup *clone) const { Layer::initializeClone(clone); for (const MapObject *object : mObjects) clone->addObject(object->clone()); clone->setColor(mColor); clone->setDrawOrder(mDrawOrder); return clone; } QString Tiled::drawOrderToString(ObjectGroup::DrawOrder drawOrder) { switch (drawOrder) { default: case ObjectGroup::UnknownOrder: return QLatin1String("unknown"); break; case ObjectGroup::TopDownOrder: return QLatin1String("topdown"); break; case ObjectGroup::IndexOrder: return QLatin1String("index"); break; } } ObjectGroup::DrawOrder Tiled::drawOrderFromString(const QString &string) { ObjectGroup::DrawOrder drawOrder = ObjectGroup::UnknownOrder; if (string == QLatin1String("topdown")) drawOrder = ObjectGroup::TopDownOrder; else if (string == QLatin1String("index")) drawOrder = ObjectGroup::IndexOrder; return drawOrder; } tiled-1.0.3/src/libtiled/objectgroup.h000066400000000000000000000161551315121121300176650ustar00rootroot00000000000000/* * objectgroup.h * Copyright 2008, Roderic Morris * Copyright 2008-2014, Thorbjørn Lindeijer * Copyright 2009-2010, Jeff Bland * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "tiled_global.h" #include "layer.h" #include #include #include namespace Tiled { class MapObject; /** * A group of objects on a map. */ class TILEDSHARED_EXPORT ObjectGroup : public Layer { public: /** * Objects within an object group can either be drawn top down (sorted * by their y-coordinate) or by index (manual stacking order). * * The default is top down. */ enum DrawOrder { UnknownOrder = -1, TopDownOrder, IndexOrder }; /** * Default constructor. */ ObjectGroup(); /** * Constructor with some parameters. */ ObjectGroup(const QString &name, int x, int y); /** * Destructor. */ ~ObjectGroup(); /** * Returns a pointer to the list of objects in this object group. */ const QList &objects() const { return mObjects; } /** * Returns the number of objects in this object group. */ int objectCount() const { return mObjects.size(); } /** * Returns the object at the specified index. */ MapObject *objectAt(int index) const { return mObjects.at(index); } /** * Adds an object to this object group. */ void addObject(MapObject *object); /** * Inserts an object at the specified index. This is only used for undoing * the removal of an object at the moment, to make sure not to change the * saved order of the objects. */ void insertObject(int index, MapObject *object); /** * Removes an object from this object group. Ownership of the object is * transferred to the caller. * * @return the index at which the specified object was removed */ int removeObject(MapObject *object); /** * Removes the object at the given index. Ownership of the object is * transferred to the caller. * * This is faster than removeObject when you've already got the index. * * @param index the index at which to remove an object */ void removeObjectAt(int index); /** * Moves \a count objects starting at \a from to the index given by \a to. * * The \a to index may not lie within the range of objects that is * being moved. */ void moveObjects(int from, int to, int count); /** * Returns the bounding rect around all objects in this object group. */ QRectF objectsBoundingRect() const; /** * Returns whether this object group contains any objects. */ bool isEmpty() const override; /** * Computes and returns the set of tilesets used by this object group. */ QSet usedTilesets() const override; /** * Returns whether any tile objects in this object group reference tiles * in the given tileset. */ bool referencesTileset(const Tileset *tileset) const override; /** * Replaces all references to tiles from \a oldTileset with tiles from * \a newTileset. */ void replaceReferencesToTileset(Tileset *oldTileset, Tileset *newTileset) override; /** * Offsets all objects within the group by the \a offset given in pixel * coordinates, and optionally wraps them. The object's center must be * within \a bounds, and wrapping occurs if the displaced center is out of * the bounds. * * \sa TileLayer::offsetTiles() */ void offsetObjects(const QPointF &offset, const QRectF &bounds, bool wrapX, bool wrapY); bool canMergeWith(Layer *other) const override; Layer *mergedWith(Layer *other) const override; const QColor &color() const; void setColor(const QColor &color); DrawOrder drawOrder() const; void setDrawOrder(DrawOrder drawOrder); ObjectGroup *clone() const override; void resetObjectIds(); int highestObjectId() const; // Enable easy iteration over objects with range-based for QList::iterator begin() { return mObjects.begin(); } QList::iterator end() { return mObjects.end(); } QList::const_iterator begin() const { return mObjects.begin(); } QList::const_iterator end() const { return mObjects.end(); } protected: ObjectGroup *initializeClone(ObjectGroup *clone) const; private: QList mObjects; QColor mColor; DrawOrder mDrawOrder; }; /** * Returns the color of the object group, or an invalid color if no color * is set. */ inline const QColor &ObjectGroup::color() const { return mColor; } /** * Sets the display color of the object group. */ inline void ObjectGroup::setColor(const QColor &color) { mColor = color; } /** * Returns the draw order for the objects in this group. * * \sa ObjectGroup::DrawOrder */ inline ObjectGroup::DrawOrder ObjectGroup::drawOrder() const { return mDrawOrder; } /** * Sets the draw order for the objects in this group. * * \sa ObjectGroup::DrawOrder */ inline void ObjectGroup::setDrawOrder(DrawOrder drawOrder) { mDrawOrder = drawOrder; } /** * Helper function that converts a drawing order to its string value. Useful * for map writers. * * @return The draw order as a lowercase string. */ TILEDSHARED_EXPORT QString drawOrderToString(ObjectGroup::DrawOrder); /** * Helper function that converts a string to a drawing order enumerator. * Useful for map readers. * * @return The draw order matching the given string, or * ObjectGroup::UnknownOrder if the string is unrecognized. */ TILEDSHARED_EXPORT ObjectGroup::DrawOrder drawOrderFromString(const QString &); } // namespace Tiled Q_DECLARE_METATYPE(Tiled::ObjectGroup*) tiled-1.0.3/src/libtiled/orthogonalrenderer.cpp000066400000000000000000000404651315121121300216010ustar00rootroot00000000000000/* * orthogonalrenderer.cpp * Copyright 2009-2011, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "orthogonalrenderer.h" #include "map.h" #include "mapobject.h" #include "tile.h" #include "tilelayer.h" #include "tileset.h" #include using namespace Tiled; QSize OrthogonalRenderer::mapSize() const { return QSize(map()->width() * map()->tileWidth(), map()->height() * map()->tileHeight()); } QRect OrthogonalRenderer::boundingRect(const QRect &rect) const { const int tileWidth = map()->tileWidth(); const int tileHeight = map()->tileHeight(); return QRect(rect.x() * tileWidth, rect.y() * tileHeight, rect.width() * tileWidth, rect.height() * tileHeight); } QRectF OrthogonalRenderer::boundingRect(const MapObject *object) const { const QRectF bounds = object->bounds(); QRectF boundingRect; if (!object->cell().isEmpty()) { const QSizeF objectSize { object->size() }; QSizeF scale { 1.0, 1.0 }; QPoint tileOffset; if (const Tile *tile = object->cell().tile()) { QSize imgSize = tile->size(); if (!imgSize.isNull()) { scale = QSizeF(objectSize.width() / imgSize.width(), objectSize.height() / imgSize.height()); } tileOffset = tile->offset(); } const QPointF bottomLeft = bounds.topLeft(); boundingRect = QRectF(bottomLeft.x() + (tileOffset.x() * scale.width()), bottomLeft.y() + (tileOffset.y() * scale.height()) - objectSize.height(), objectSize.width(), objectSize.height()).adjusted(-1, -1, 1, 1); } else { qreal extraSpace = qMax(objectLineWidth(), qreal(1)); switch (object->shape()) { case MapObject::Ellipse: case MapObject::Rectangle: if (bounds.isNull()) { boundingRect = bounds.adjusted(-10 - extraSpace, -10 - extraSpace, 10 + extraSpace + 1, 10 + extraSpace + 1); } else { boundingRect = bounds.adjusted(-extraSpace, -extraSpace, extraSpace + 1, extraSpace + 1); } break; case MapObject::Polygon: case MapObject::Polyline: { // Make some more room for the starting dot extraSpace += objectLineWidth() * 4; const QPointF &pos = object->position(); const QPolygonF polygon = object->polygon().translated(pos); QPolygonF screenPolygon = pixelToScreenCoords(polygon); boundingRect = screenPolygon.boundingRect().adjusted(-extraSpace, -extraSpace, extraSpace + 1, extraSpace + 1); break; } case MapObject::Text: boundingRect = object->bounds(); break; } } return boundingRect; } QPainterPath OrthogonalRenderer::shape(const MapObject *object) const { QPainterPath path; if (!object->cell().isEmpty()) { path.addRect(boundingRect(object)); } else { switch (object->shape()) { case MapObject::Rectangle: { const QRectF bounds = object->bounds(); if (bounds.isNull()) { path.addRect(object->x() - 10, object->y() - 10, 20, 20); } else { path.addRect(bounds); } break; } case MapObject::Polygon: case MapObject::Polyline: { const QPointF &pos = object->position(); const QPolygonF polygon = object->polygon().translated(pos); const QPolygonF screenPolygon = pixelToScreenCoords(polygon); if (object->shape() == MapObject::Polygon) { path.addPolygon(screenPolygon); } else { for (int i = 1; i < screenPolygon.size(); ++i) { path.addPolygon(lineToPolygon(screenPolygon[i - 1], screenPolygon[i])); } path.setFillRule(Qt::WindingFill); } break; } case MapObject::Ellipse: { const QRectF bounds = object->bounds(); if (bounds.isNull()) { path.addEllipse(bounds.topLeft(), 20, 20); } else { path.addEllipse(bounds); } break; } case MapObject::Text: { path.addRect(object->bounds()); break; } } } return path; } void OrthogonalRenderer::drawGrid(QPainter *painter, const QRectF &rect, QColor gridColor) const { const int tileWidth = map()->tileWidth(); const int tileHeight = map()->tileHeight(); if (tileWidth <= 0 || tileHeight <= 0) return; const int startX = qMax(0, (int) (rect.x() / tileWidth) * tileWidth); const int startY = qMax(0, (int) (rect.y() / tileHeight) * tileHeight); const int endX = qMin(qCeil(rect.right()), map()->width() * tileWidth + 1); const int endY = qMin(qCeil(rect.bottom()), map()->height() * tileHeight + 1); QPen gridPen = makeGridPen(painter->device(), gridColor); if (startY < endY) { gridPen.setDashOffset(startY); painter->setPen(gridPen); for (int x = startX; x < endX; x += tileWidth) painter->drawLine(x, startY, x, endY - 1); } if (startX < endX) { gridPen.setDashOffset(startX); painter->setPen(gridPen); for (int y = startY; y < endY; y += tileHeight) painter->drawLine(startX, y, endX - 1, y); } } void OrthogonalRenderer::drawTileLayer(QPainter *painter, const TileLayer *layer, const QRectF &exposed) const { const int tileWidth = map()->tileWidth(); const int tileHeight = map()->tileHeight(); if (tileWidth <= 0 || tileHeight <= 0) return; const QPointF layerPos(layer->x() * tileWidth, layer->y() * tileHeight); int startX = 0; int startY = 0; int endX = layer->width() - 1; int endY = layer->height() - 1; if (!exposed.isNull()) { QMargins drawMargins = layer->drawMargins(); drawMargins.setTop(drawMargins.top() - tileHeight); drawMargins.setRight(drawMargins.right() - tileWidth); QRectF rect = exposed.adjusted(-drawMargins.right(), -drawMargins.bottom(), drawMargins.left(), drawMargins.top()); rect.translate(-layerPos); startX = qMax(qFloor(rect.x() / tileWidth), 0); startY = qMax(qFloor(rect.y() / tileHeight), 0); endX = qMin(qCeil(rect.right()) / tileWidth, endX); endY = qMin(qCeil(rect.bottom()) / tileHeight, endY); } // Return immediately when there is nothing to draw if (startX > endX || startY > endY) return; const QTransform savedTransform = painter->transform(); painter->translate(layerPos); CellRenderer renderer(painter); Map::RenderOrder renderOrder = map()->renderOrder(); int incX = 1, incY = 1; switch (renderOrder) { case Map::RightUp: std::swap(startY, endY); incY = -1; break; case Map::LeftDown: std::swap(startX, endX); incX = -1; break; case Map::LeftUp: std::swap(startX, endX); std::swap(startY, endY); incX = -1; incY = -1; break; case Map::RightDown: default: break; } endX += incX; endY += incY; for (int y = startY; y != endY; y += incY) { for (int x = startX; x != endX; x += incX) { const Cell &cell = layer->cellAt(x, y); if (cell.isEmpty()) continue; Tile *tile = cell.tile(); QSize size = tile ? tile->size() : map()->tileSize(); renderer.render(cell, QPointF(x * tileWidth, (y + 1) * tileHeight), size, CellRenderer::BottomLeft); } } renderer.flush(); painter->setTransform(savedTransform); } void OrthogonalRenderer::drawTileSelection(QPainter *painter, const QRegion ®ion, const QColor &color, const QRectF &exposed) const { foreach (const QRect &r, region.rects()) { const QRectF toFill = QRectF(boundingRect(r)).intersected(exposed); if (!toFill.isEmpty()) painter->fillRect(toFill, color); } } void OrthogonalRenderer::drawMapObject(QPainter *painter, const MapObject *object, const QColor &color) const { painter->save(); const QRectF bounds = object->bounds(); QRectF rect(bounds); painter->translate(rect.topLeft()); rect.moveTopLeft(QPointF(0, 0)); const Cell &cell = object->cell(); if (!cell.isEmpty()) { const QSizeF size = object->size(); CellRenderer(painter).render(cell, QPointF(), size, CellRenderer::BottomLeft); if (testFlag(ShowTileObjectOutlines)) { QPointF tileOffset; if (const Tile *tile = cell.tile()) tileOffset = tile->offset(); QRectF rect(QPointF(tileOffset.x(), tileOffset.y() - size.height()), size); QPen pen(Qt::SolidLine); pen.setCosmetic(true); painter->setPen(pen); painter->drawRect(rect); pen.setStyle(Qt::DotLine); pen.setColor(color); painter->setPen(pen); painter->drawRect(rect); } } else { const qreal lineWidth = objectLineWidth(); const qreal scale = painterScale(); const qreal shadowDist = (lineWidth == 0 ? 1 : lineWidth) / scale; const QPointF shadowOffset = QPointF(shadowDist * 0.5, shadowDist * 0.5); QPen linePen(color, lineWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); linePen.setCosmetic(true); QPen shadowPen(linePen); shadowPen.setColor(Qt::black); QColor brushColor = color; brushColor.setAlpha(50); const QBrush fillBrush(brushColor); painter->setRenderHint(QPainter::Antialiasing); // Trying to draw an ellipse with 0-width is causing a hang in // CoreGraphics when drawing the path requested by the // QCoreGraphicsPaintEngine. Draw them as rectangle instead. MapObject::Shape shape = object->shape(); if (shape == MapObject::Ellipse && ((rect.width() == qreal(0)) ^ (rect.height() == qreal(0)))) { shape = MapObject::Rectangle; } switch (shape) { case MapObject::Rectangle: { if (rect.isNull()) rect = QRectF(QPointF(-10, -10), QSizeF(20, 20)); // Draw the shadow painter->setPen(shadowPen); painter->drawRect(rect.translated(shadowOffset)); painter->setPen(linePen); painter->setBrush(fillBrush); painter->drawRect(rect); break; } case MapObject::Polyline: { QPolygonF screenPolygon = pixelToScreenCoords(object->polygon()); QPen thickShadowPen(shadowPen); QPen thickLinePen(linePen); thickShadowPen.setWidthF(thickShadowPen.widthF() * 4); thickLinePen.setWidthF(thickLinePen.widthF() * 4); painter->setPen(shadowPen); painter->drawPolyline(screenPolygon.translated(shadowOffset)); painter->setPen(thickShadowPen); painter->drawPoint(screenPolygon.first() + shadowOffset); painter->setPen(linePen); painter->setBrush(fillBrush); painter->drawPolyline(screenPolygon); painter->setPen(thickLinePen); painter->drawPoint(screenPolygon.first()); break; } case MapObject::Polygon: { QPolygonF screenPolygon = pixelToScreenCoords(object->polygon()); QPen thickShadowPen(shadowPen); QPen thickLinePen(linePen); thickShadowPen.setWidthF(thickShadowPen.widthF() * 4); thickLinePen.setWidthF(thickLinePen.widthF() * 4); painter->setPen(shadowPen); painter->drawPolygon(screenPolygon.translated(shadowOffset)); painter->setPen(thickShadowPen); painter->drawPoint(screenPolygon.first() + shadowOffset); painter->setPen(linePen); painter->setBrush(fillBrush); painter->drawPolygon(screenPolygon); painter->setPen(thickLinePen); painter->drawPoint(screenPolygon.first()); break; } case MapObject::Ellipse: { if (rect.isNull()) rect = QRectF(QPointF(-10, -10), QSizeF(20, 20)); // Draw the shadow painter->setPen(shadowPen); painter->drawEllipse(rect.translated(shadowOffset)); painter->setPen(linePen); painter->setBrush(fillBrush); painter->drawEllipse(rect); break; } case MapObject::Text: { const auto& textData = object->textData(); painter->setFont(textData.font); painter->setPen(textData.color); painter->drawText(rect, textData.text, textData.textOption()); break; } } } painter->restore(); } QPointF OrthogonalRenderer::pixelToTileCoords(qreal x, qreal y) const { return QPointF(x / map()->tileWidth(), y / map()->tileHeight()); } QPointF OrthogonalRenderer::tileToPixelCoords(qreal x, qreal y) const { return QPointF(x * map()->tileWidth(), y * map()->tileHeight()); } QPointF OrthogonalRenderer::screenToTileCoords(qreal x, qreal y) const { return QPointF(x / map()->tileWidth(), y / map()->tileHeight()); } QPointF OrthogonalRenderer::tileToScreenCoords(qreal x, qreal y) const { return QPointF(x * map()->tileWidth(), y * map()->tileHeight()); } QPointF OrthogonalRenderer::screenToPixelCoords(qreal x, qreal y) const { return QPointF(x, y); } QPointF OrthogonalRenderer::pixelToScreenCoords(qreal x, qreal y) const { return QPointF(x, y); } tiled-1.0.3/src/libtiled/orthogonalrenderer.h000066400000000000000000000062711315121121300212430ustar00rootroot00000000000000/* * orthogonalrenderer.h * Copyright 2009-2010, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "maprenderer.h" namespace Tiled { /** * The orthogonal map renderer. This is the most basic map renderer, * dealing with maps that use rectangular tiles. */ class TILEDSHARED_EXPORT OrthogonalRenderer : public MapRenderer { public: OrthogonalRenderer(const Map *map) : MapRenderer(map) {} QSize mapSize() const override; QRect boundingRect(const QRect &rect) const override; QRectF boundingRect(const MapObject *object) const override; QPainterPath shape(const MapObject *object) const override; void drawGrid(QPainter *painter, const QRectF &rect, QColor gridColor) const override; void drawTileLayer(QPainter *painter, const TileLayer *layer, const QRectF &exposed = QRectF()) const override; void drawTileSelection(QPainter *painter, const QRegion ®ion, const QColor &color, const QRectF &exposed) const override; void drawMapObject(QPainter *painter, const MapObject *object, const QColor &color) const override; using MapRenderer::pixelToTileCoords; QPointF pixelToTileCoords(qreal x, qreal y) const override; using MapRenderer::tileToPixelCoords; QPointF tileToPixelCoords(qreal x, qreal y) const override; using MapRenderer::screenToTileCoords; QPointF screenToTileCoords(qreal x, qreal y) const override; using MapRenderer::tileToScreenCoords; QPointF tileToScreenCoords(qreal x, qreal y) const override; using MapRenderer::screenToPixelCoords; QPointF screenToPixelCoords(qreal x, qreal y) const override; using MapRenderer::pixelToScreenCoords; QPointF pixelToScreenCoords(qreal x, qreal y) const override; }; } // namespace Tiled tiled-1.0.3/src/libtiled/plugin.cpp000066400000000000000000000041531315121121300171660ustar00rootroot00000000000000/* * plugin.cpp * Copyright 2015, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "plugin.h" #include "pluginmanager.h" namespace Tiled { Plugin::~Plugin() { for (QObject *object : mAddedObjects) PluginManager::removeObject(object); } /** * Convenience function that calls PluginManager::addObject and makes sure that * the added object gets removed when the plugin is unloaded. * * If you remove an object added with this function, you need to use * removeObject(). */ void Plugin::addObject(QObject *object) { PluginManager::addObject(object); mAddedObjects.append(object); } /** * Convenience function that calls PluginManager::removeObject. */ void Plugin::removeObject(QObject *object) { PluginManager::removeObject(object); mAddedObjects.removeOne(object); } } // namespace Tiled tiled-1.0.3/src/libtiled/plugin.h000066400000000000000000000037041315121121300166340ustar00rootroot00000000000000/* * plugin.h * Copyright 2015, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "tiled_global.h" #include #include namespace Tiled { /** * @brief The interface to be implemented by Tiled plugins. * * This interface provides access to the extensions implemented by the plugin. */ class TILEDSHARED_EXPORT Plugin : public QObject { Q_OBJECT public: ~Plugin(); virtual void initialize() = 0; protected: void addObject(QObject *object); void removeObject(QObject *object); private: QList mAddedObjects; }; } // namespace Tiled Q_DECLARE_INTERFACE(Tiled::Plugin, "org.mapeditor.Plugin") tiled-1.0.3/src/libtiled/pluginmanager.cpp000066400000000000000000000153521315121121300205240ustar00rootroot00000000000000/* * pluginmanager.cpp * Copyright 2010, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "pluginmanager.h" #include "mapformat.h" #include "plugin.h" #include #include #include #include #include namespace Tiled { QString PluginFile::fileName() const { if (loader) return loader->fileName(); return QStringLiteral(""); } bool PluginFile::hasError() const { if (instance) return false; return state == PluginEnabled || (defaultEnable && state == PluginDefault); } QString PluginFile::errorString() const { if (loader) return loader->errorString(); return QString(); } PluginManager *PluginManager::mInstance; PluginManager::PluginManager() { } PluginManager::~PluginManager() { } /** * Sets the enabled state of the given plugin to be explicitly enabled or * disabled or to use the default state. * * Returns whether the change was successful. */ bool PluginManager::setPluginState(const QString &fileName, PluginState state) { if (state == PluginDefault) mPluginStates.remove(fileName); else mPluginStates.insert(fileName, state); PluginFile *plugin = pluginByFileName(fileName); if (!plugin) return false; plugin->state = state; bool loaded = plugin->instance != nullptr; bool enable = state == PluginEnabled || (plugin->defaultEnable && state != PluginDisabled); bool success = false; if (enable && !loaded) { success = loadPlugin(plugin); } else if (!enable && loaded) { success = unloadPlugin(plugin); } else { success = true; } return success; } bool PluginManager::loadPlugin(PluginFile *plugin) { plugin->instance = plugin->loader->instance(); if (plugin->instance) { if (Plugin *p = qobject_cast(plugin->instance)) p->initialize(); else addObject(plugin->instance); return true; } else { qWarning().noquote() << "Error:" << plugin->loader->errorString(); return false; } } bool PluginManager::unloadPlugin(PluginFile *plugin) { bool derivedPlugin = qobject_cast(plugin->instance) != nullptr; if (plugin->loader->unload()) { if (!derivedPlugin) removeObject(plugin->instance); plugin->instance = nullptr; return true; } else { return false; } } PluginManager *PluginManager::instance() { if (!mInstance) mInstance = new PluginManager; return mInstance; } void PluginManager::deleteInstance() { delete mInstance; mInstance = nullptr; } void PluginManager::addObject(QObject *object) { Q_ASSERT(object); Q_ASSERT(mInstance); Q_ASSERT(!mInstance->mObjects.contains(object)); mInstance->mObjects.append(object); emit mInstance->objectAdded(object); } void PluginManager::removeObject(QObject *object) { if (!mInstance) return; Q_ASSERT(object); Q_ASSERT(mInstance->mObjects.contains(object)); emit mInstance->objectAboutToBeRemoved(object); mInstance->mObjects.removeOne(object); } void PluginManager::loadPlugins() { // Load static plugins const QObjectList &staticPluginInstances = QPluginLoader::staticInstances(); for (QObject *instance : staticPluginInstances) { mPlugins.append(PluginFile(PluginStatic, instance)); if (Plugin *plugin = qobject_cast(instance)) plugin->initialize(); else addObject(instance); } // Determine the plugin path based on the application location #ifndef TILED_PLUGIN_DIR QString pluginPath = QCoreApplication::applicationDirPath(); #endif #if defined(Q_OS_WIN32) || defined(TILED_LINUX_ARCHIVE) pluginPath += QLatin1String("/plugins/tiled"); #elif defined(Q_OS_MAC) pluginPath += QLatin1String("/../PlugIns"); #elif defined(TILED_PLUGIN_DIR) QString pluginPath = QLatin1String(TILED_PLUGIN_DIR); #else pluginPath += QLatin1String("/../lib/tiled/plugins"); #endif // Load dynamic plugins QDirIterator iterator(pluginPath, QDir::Files | QDir::Readable); while (iterator.hasNext()) { const QString &pluginFile = iterator.next(); if (!QLibrary::isLibrary(pluginFile)) continue; QString fileName = QFileInfo(pluginFile).fileName(); PluginState state = mPluginStates.value(fileName); auto *loader = new QPluginLoader(pluginFile, this); auto metaData = loader->metaData().value(QStringLiteral("MetaData")).toObject(); bool defaultEnable = metaData.value(QStringLiteral("defaultEnable")).toBool(); bool enable = state == PluginEnabled || (defaultEnable && state != PluginDisabled); QObject *instance = nullptr; if (enable) { instance = loader->instance(); if (!instance) qWarning().noquote() << "Error:" << loader->errorString(); } mPlugins.append(PluginFile(state, instance, loader, defaultEnable)); if (!instance) continue; if (Plugin *plugin = qobject_cast(instance)) plugin->initialize(); else addObject(instance); } } PluginFile *PluginManager::pluginByFileName(const QString &fileName) { for (PluginFile &plugin : mPlugins) if (plugin.loader && QFileInfo(plugin.loader->fileName()).fileName() == fileName) return &plugin; return nullptr; } } // namespace Tiled tiled-1.0.3/src/libtiled/pluginmanager.h000066400000000000000000000106541315121121300201710ustar00rootroot00000000000000/* * pluginmanager.h * Copyright 2010, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "tiled_global.h" #include #include #include #include #include class QPluginLoader; namespace Tiled { enum PluginState { PluginDefault, PluginEnabled, PluginDisabled, PluginStatic }; struct TILEDSHARED_EXPORT PluginFile { PluginFile(PluginState state, QObject *instance, QPluginLoader *loader = nullptr, bool defaultEnable = true) : state(state) , instance(instance) , loader(loader) , defaultEnable(defaultEnable) {} QString fileName() const; bool hasError() const; QString errorString() const; PluginState state; QObject *instance; QPluginLoader *loader; bool defaultEnable; }; /** * The plugin manager loads the plugins and provides ways to access them. */ class TILEDSHARED_EXPORT PluginManager : public QObject { Q_OBJECT public: /** * Returns the plugin manager instance. */ static PluginManager *instance(); static void deleteInstance(); /** * Scans the plugin directory for plugins and attempts to load them. */ void loadPlugins(); /** * Returns the list of plugins found by the plugin manager. */ const QList &plugins() const { return mPlugins; } /** * Adds the given \a object. This allows the object to be found later based * on the interfaces it implements. */ static void addObject(QObject *object); /** * Removes the given \a object. */ static void removeObject(QObject *object); /** * Returns the list of objects that implement a given interface. */ template static QList objects() { QList results; if (mInstance) for (QObject *object : mInstance->mObjects) if (T *result = qobject_cast(object)) results.append(result); return results; } /** * Calls the given function for each object implementing a given interface. */ template static void each(std::function function) { if (mInstance) for (QObject *object : mInstance->mObjects) if (T *result = qobject_cast(object)) function(result); } PluginFile *pluginByFileName(const QString &fileName); const QMap &pluginStates() const; bool setPluginState(const QString &fileName, PluginState state); signals: void objectAdded(QObject *object); void objectAboutToBeRemoved(QObject *object); private: Q_DISABLE_COPY(PluginManager) PluginManager(); ~PluginManager(); bool loadPlugin(PluginFile *plugin); bool unloadPlugin(PluginFile *plugin); static PluginManager *mInstance; QList mPlugins; QMap mPluginStates; QObjectList mObjects; }; inline const QMap &PluginManager::pluginStates() const { return mPluginStates; } } // namespace Tiled tiled-1.0.3/src/libtiled/properties.cpp000066400000000000000000000121351315121121300200630ustar00rootroot00000000000000/* * properties.cpp * Copyright 2010, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "properties.h" #include #include namespace Tiled { void Properties::merge(const Properties &other) { // Based on QMap::unite, but using insert instead of insertMulti const_iterator it = other.constEnd(); const const_iterator b = other.constBegin(); while (it != b) { --it; insert(it.key(), it.value()); } } QJsonArray Properties::toJson() const { QJsonArray json; const_iterator it = begin(); const const_iterator it_end = end(); for (; it != it_end; ++it) { const QString &name = it.key(); const QJsonValue value = QJsonValue::fromVariant(toExportValue(it.value())); const QString type = typeToName(it.value().userType()); QJsonObject propertyObject; propertyObject.insert(QLatin1String("name"), name); propertyObject.insert(QLatin1String("value"), value); propertyObject.insert(QLatin1String("type"), type); json.append(propertyObject); } return json; } Properties Properties::fromJson(const QJsonArray &json) { Properties properties; for (const QJsonValue &property : json) { const QJsonObject propertyObject = property.toObject(); const QString name = propertyObject.value(QLatin1String("name")).toString(); const QString typeName = propertyObject.value(QLatin1String("type")).toString(); QVariant value = propertyObject.value(QLatin1String("value")).toVariant(); if (!typeName.isEmpty()) value = fromExportValue(value, nameToType(typeName)); properties.insert(name, value); } return properties; } void AggregatedProperties::aggregate(const Properties &properties) { auto it = properties.constEnd(); const auto b = properties.constBegin(); while (it != b) { --it; auto pit = find(it.key()); if (pit != end()) { AggregatedPropertyData &propertyData = pit.value(); propertyData.aggregate(it.value()); } else { insert(it.key(), AggregatedPropertyData(it.value())); } } ++mAggregatedCount; } QString typeToName(int type) { switch (type) { case QVariant::String: return QStringLiteral("string"); case QVariant::Double: return QStringLiteral("float"); case QVariant::Color: return QStringLiteral("color"); default: if (type == filePathTypeId()) return QStringLiteral("file"); } return QLatin1String(QVariant::typeToName(type)); } int nameToType(const QString &name) { if (name == QLatin1String("string")) return QVariant::String; if (name == QLatin1String("float")) return QVariant::Double; if (name == QLatin1String("color")) return QVariant::Color; if (name == QLatin1String("file")) return filePathTypeId(); return QVariant::nameToType(name.toLatin1().constData()); } static QString colorToString(const QColor &color) { if (!color.isValid()) return QString(); return color.name(QColor::HexArgb); } QVariant toExportValue(const QVariant &value) { int type = value.userType(); if (type == QVariant::Color) return colorToString(value.value()); if (type == filePathTypeId()) return value.value().absolutePath; return value; } int filePathTypeId() { return qMetaTypeId(); } QVariant fromExportValue(const QVariant &value, int type) { if (type == QVariant::Invalid) return value; if (value.userType() == type) return value; if (type == filePathTypeId()) return QVariant::fromValue(FilePath { value.toString() }); QVariant variant(value); variant.convert(type); return variant; } } // namespace Tiled tiled-1.0.3/src/libtiled/properties.h000066400000000000000000000067101315121121300175320ustar00rootroot00000000000000/* * properties.h * Copyright 2010, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "tiled_global.h" #include #include #include #include namespace Tiled { struct FilePath { QString absolutePath; }; /** * Collection of properties and their values. */ class TILEDSHARED_EXPORT Properties : public QMap { public: void merge(const Properties &other); QJsonArray toJson() const; static Properties fromJson(const QJsonArray &json); }; class TILEDSHARED_EXPORT AggregatedPropertyData { public: AggregatedPropertyData() : mPresenceCount(0) , mValueConsistent(true) {} explicit AggregatedPropertyData(const QVariant &value) : mValue(value) , mPresenceCount(1) , mValueConsistent(true) {} void aggregate(const QVariant &value) { mValueConsistent &= value == mValue; mPresenceCount += 1; } const QVariant &value() const { return mValue; } int presenceCount() const { return mPresenceCount; } bool valueConsistent() const { return mValueConsistent; } bool operator==(const AggregatedPropertyData &other) const { return mValue == other.mValue && mPresenceCount == other.mPresenceCount && mValueConsistent == other.mValueConsistent; } private: QVariant mValue; int mPresenceCount; bool mValueConsistent; }; /** * Collection of properties with information about the consistency of their * presence and value over several property collections. */ class TILEDSHARED_EXPORT AggregatedProperties : public QMap { public: void aggregate(const Properties &properties); int aggregatedCount() { return mAggregatedCount; } private: int mAggregatedCount; }; TILEDSHARED_EXPORT int filePathTypeId(); TILEDSHARED_EXPORT QString typeToName(int type); TILEDSHARED_EXPORT int nameToType(const QString &name); TILEDSHARED_EXPORT QVariant toExportValue(const QVariant &value); TILEDSHARED_EXPORT QVariant fromExportValue(const QVariant &value, int type); } // namespace Tiled Q_DECLARE_METATYPE(Tiled::FilePath) tiled-1.0.3/src/libtiled/savefile.cpp000066400000000000000000000040311315121121300174610ustar00rootroot00000000000000/* * savefile.cpp * Copyright 2017, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "savefile.h" #include #include namespace Tiled { bool SaveFile::mSafeSavingEnabled = true; SaveFile::SaveFile(const QString &name) { if (mSafeSavingEnabled) mFileDevice.reset(new QSaveFile(name)); else mFileDevice.reset(new QFile(name)); } bool SaveFile::commit() { if (auto saveFile = qobject_cast(mFileDevice.data())) return saveFile->commit(); return mFileDevice->error() == QFileDevice::NoError; } bool SaveFile::safeSavingEnabled() { return mSafeSavingEnabled; } void SaveFile::setSafeSavingEnabled(bool enabled) { mSafeSavingEnabled = enabled; } } // namespace Tiled tiled-1.0.3/src/libtiled/savefile.h000066400000000000000000000046231315121121300171350ustar00rootroot00000000000000/* * savefile.h * Copyright 2017, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "tiled_global.h" #include #include #include namespace Tiled { /** * A wrapper around QSaveFile and QFile. Allows safe writing of files to be * turned off globally. */ class TILEDSHARED_EXPORT SaveFile { public: SaveFile(const QString &name); QFileDevice* device() const; bool open(QIODevice::OpenMode mode); bool commit(); QFileDevice::FileError error() const; QString errorString() const; static bool safeSavingEnabled(); static void setSafeSavingEnabled(bool enabled); private: QScopedPointer mFileDevice; static bool mSafeSavingEnabled; }; inline QFileDevice *SaveFile::device() const { return mFileDevice.data(); } inline bool SaveFile::open(QIODevice::OpenMode mode) { return mFileDevice->open(mode); } inline QFileDevice::FileError SaveFile::error() const { return mFileDevice->error(); } inline QString SaveFile::errorString() const { return mFileDevice->errorString(); } } // namespace Tiled tiled-1.0.3/src/libtiled/staggeredrenderer.cpp000066400000000000000000000062221315121121300213630ustar00rootroot00000000000000/* * staggeredrenderer.cpp * Copyright 2011-2014, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "staggeredrenderer.h" #include using namespace Tiled; /** * Converts screen to tile coordinates. Sub-tile return values are not * supported by this renderer. * * This override exists because the method used by the HexagonalRenderer * does not produce nice results for isometric shapes in the tile corners. */ QPointF StaggeredRenderer::screenToTileCoords(qreal x, qreal y) const { const RenderParams p(map()); if (p.staggerX) x -= p.staggerEven ? p.sideOffsetX : 0; else y -= p.staggerEven ? p.sideOffsetY : 0; // Start with the coordinates of a grid-aligned tile QPoint referencePoint = QPoint(qFloor(x / p.tileWidth), qFloor(y / p.tileHeight)); // Relative x and y position on the base square of the grid-aligned tile const QPointF rel(x - referencePoint.x() * p.tileWidth, y - referencePoint.y() * p.tileHeight); // Adjust the reference point to the correct tile coordinates int &staggerAxisIndex = p.staggerX ? referencePoint.rx() : referencePoint.ry(); staggerAxisIndex *= 2; if (p.staggerEven) ++staggerAxisIndex; const qreal y_pos = rel.x() * ((qreal) p.tileHeight / p.tileWidth); // Check whether the cursor is in any of the corners (neighboring tiles) if (p.sideOffsetY - y_pos > rel.y()) return topLeft(referencePoint.x(), referencePoint.y()); if (-p.sideOffsetY + y_pos > rel.y()) return topRight(referencePoint.x(), referencePoint.y()); if (p.sideOffsetY + y_pos < rel.y()) return bottomLeft(referencePoint.x(), referencePoint.y()); if (p.sideOffsetY * 3 - y_pos < rel.y()) return bottomRight(referencePoint.x(), referencePoint.y()); return referencePoint; } tiled-1.0.3/src/libtiled/staggeredrenderer.h000066400000000000000000000061351315121121300210330ustar00rootroot00000000000000/* * staggeredrenderer.h * Copyright 2011-2014, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "hexagonalrenderer.h" namespace Tiled { /** * A staggered isometric renderer. * * This renderer is meant to be used with isometric tiles, but rather than * doing a true isometric projection the tiles are shifted in order to fit * together. This has the advantage that the map has a rectangular shape. * * Only one variation of staggered map rendering is supported at the moment, * namely shifting the uneven rows to the right. * * Objects are handled the same way as the OrthogonalRenderer, though they * snap at half the tile width and height. * * At the moment, several Tiled features will not work correctly with this * renderer. This is due to the way the shifting messes with the coordinate * system. List of known issues: * * Fill tool: * * Doesn't work properly cause its assumptions about neighboring are * broken by this renderer. * * Stamp tool: * * A stamp only makes sense if it's placed at an even y offset from * where it was created. When moved by an uneven y offset, the rows * that are shifted swap, messing up the stamp. * * The circle and line drawing modes of the stamp tool won't work * properly due to the irregular coordinate system. * * Rectangular select tool: * * This one will appear to behave somewhat erratic. * * Map resize and offset actions: * * Similar problem as with stamps when offsetting at an uneven y offset. * */ class TILEDSHARED_EXPORT StaggeredRenderer : public HexagonalRenderer { public: StaggeredRenderer(const Map *map) : HexagonalRenderer(map) {} using HexagonalRenderer::screenToTileCoords; QPointF screenToTileCoords(qreal x, qreal y) const override; }; } // namespace Tiled tiled-1.0.3/src/libtiled/terrain.h000066400000000000000000000112401315121121300167740ustar00rootroot00000000000000/* * terrain.h * Copyright 2012, Manu Evans * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "object.h" #include "tileset.h" #include #include #include namespace Tiled { /** * Represents a terrain type. */ class TILEDSHARED_EXPORT Terrain : public Object { public: Terrain(int id, Tileset *tileset, QString name, int imageTileId): Object(TerrainType), mId(id), mTileset(tileset), mName(std::move(name)), mImageTileId(imageTileId) { } int id() const; Tileset *tileset() const; QSharedPointer sharedTileset() const; QString name() const; void setName(const QString &name); int imageTileId() const; void setImageTileId(int imageTileId); Tile *imageTile() const; int transitionDistance(int targetTerrainType) const; void setTransitionDistance(int targetTerrainType, int distance); void setTransitionDistances(const QVector &transitionDistances); Terrain *clone(Tileset *tileset) const; private: int mId; Tileset *mTileset; QString mName; int mImageTileId; QVector mTransitionDistance; friend class Tileset; // To allow changing the terrain id }; /** * Returns ID of this terrain type. */ inline int Terrain::id() const { return mId; } /** * Returns the tileset this terrain type belongs to. */ inline Tileset *Terrain::tileset() const { return mTileset; } /** * Returns the tileset this terrain type belongs to as a shared pointer. */ inline QSharedPointer Terrain::sharedTileset() const { return mTileset->sharedPointer(); } /** * Returns the name of this terrain type. */ inline QString Terrain::name() const { return mName; } /** * Sets the name of this terrain type. */ inline void Terrain::setName(const QString &name) { mName = name; } /** * Returns the index of the tile that visually represents this terrain type. */ inline int Terrain::imageTileId() const { return mImageTileId; } /** * Sets the index of the tile that visually represents this terrain type. */ inline void Terrain::setImageTileId(int imageTileId) { mImageTileId = imageTileId; } /** * Returns a Tile that represents this terrain type in the terrain palette. */ inline Tile *Terrain::imageTile() const { return mTileset->findTile(mImageTileId); } /** * Returns the transition penalty(/distance) from this terrain type to another terrain type. */ inline int Terrain::transitionDistance(int targetTerrainType) const { return mTransitionDistance[targetTerrainType + 1]; } /** * Sets the transition penalty(/distance) from this terrain type to another terrain type. */ inline void Terrain::setTransitionDistance(int targetTerrainType, int distance) { mTransitionDistance[targetTerrainType + 1] = distance; } /** * Returns the array of terrain penalties(/distances). */ inline void Terrain::setTransitionDistances(const QVector &transitionDistances) { mTransitionDistance = transitionDistances; } /** * Returns a duplicate of this terrain, to be added to the given \a tileset. */ inline Terrain *Terrain::clone(Tileset *tileset) const { Terrain *c = new Terrain(mId, tileset, mName, mImageTileId); c->setProperties(properties()); c->mTransitionDistance = mTransitionDistance; return c; } } // namespace Tiled Q_DECLARE_METATYPE(Tiled::Terrain*) tiled-1.0.3/src/libtiled/tile.cpp000066400000000000000000000127441315121121300166320ustar00rootroot00000000000000/* * tile.cpp * Copyright 2012-2014, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "tile.h" #include "objectgroup.h" #include "tileset.h" using namespace Tiled; Tile::Tile(int id, Tileset *tileset): Object(TileType), mId(id), mTileset(tileset), mTerrain(-1), mProbability(1.f), mObjectGroup(nullptr), mCurrentFrameIndex(0), mUnusedTime(0) {} Tile::Tile(const QPixmap &image, int id, Tileset *tileset): Object(TileType), mId(id), mTileset(tileset), mImage(image), mTerrain(-1), mProbability(1.f), mObjectGroup(nullptr), mCurrentFrameIndex(0), mUnusedTime(0) {} Tile::~Tile() { delete mObjectGroup; } /** * Returns the tileset that this tile is part of as a shared pointer. */ QSharedPointer Tile::sharedTileset() const { return mTileset->sharedPointer(); } /** * Returns the tile to render when taking into account tile animations. * * \warning May return null when the tileset is invalid or the image could * not be loaded. */ const Tile *Tile::currentFrameTile() const { if (isAnimated()) { const Frame &frame = mFrames.at(mCurrentFrameIndex); return mTileset->findTile(frame.tileId); } return this; } /** * Returns the drawing offset of the tile (in pixels). */ QPoint Tile::offset() const { return mTileset->tileOffset(); } /** * Returns the Terrain of a given corner. */ Terrain *Tile::terrainAtCorner(int corner) const { return mTileset->terrain(cornerTerrainId(corner)); } /** * Set the terrain for each corner of the tile. */ void Tile::setTerrain(unsigned terrain) { if (mTerrain == terrain) return; mTerrain = terrain; mTileset->markTerrainDistancesDirty(); } /** * Sets \a objectGroup to be the group of objects associated with this tile. * The Tile takes ownership over the ObjectGroup and it can't also be part of * a map. */ void Tile::setObjectGroup(ObjectGroup *objectGroup) { Q_ASSERT(!objectGroup || !objectGroup->map()); if (mObjectGroup == objectGroup) return; delete mObjectGroup; mObjectGroup = objectGroup; } /** * Swaps the object group of this tile with \a objectGroup. The tile releases * ownership over its existing object group and takes ownership over the new * one. * * @return The previous object group referenced by this tile. */ ObjectGroup *Tile::swapObjectGroup(ObjectGroup *objectGroup) { ObjectGroup *previousObjectGroup = mObjectGroup; mObjectGroup = objectGroup; return previousObjectGroup; } /** * Sets the animation frames to be used by this tile. Resets any currently * running animation. */ void Tile::setFrames(const QVector &frames) { resetAnimation(); mFrames = frames; } /** * Resets the tile animation. Returns whether this caused the current tileId to * change. */ bool Tile::resetAnimation() { if (!isAnimated()) return false; Frame previousFrame = mFrames.at(mCurrentFrameIndex); Frame currentFrame = mFrames.at(0); mCurrentFrameIndex = 0; mUnusedTime = 0; return previousFrame.tileId != currentFrame.tileId; } /** * Advances this tile animation by the given amount of milliseconds. Returns * whether this caused the current tileId to change. */ bool Tile::advanceAnimation(int ms) { if (!isAnimated()) return false; mUnusedTime += ms; Frame frame = mFrames.at(mCurrentFrameIndex); const int previousTileId = frame.tileId; while (frame.duration > 0 && mUnusedTime > frame.duration) { mUnusedTime -= frame.duration; mCurrentFrameIndex = (mCurrentFrameIndex + 1) % mFrames.size(); frame = mFrames.at(mCurrentFrameIndex); } return previousTileId != frame.tileId; } /** * Returns a duplicate of this tile, to be added to the given \a tileset. */ Tile *Tile::clone(Tileset *tileset) const { Tile *c = new Tile(mImage, mId, tileset); c->setProperties(properties()); c->mImageSource = mImageSource; c->mTerrain = mTerrain; c->mProbability = mProbability; if (mObjectGroup) c->mObjectGroup = mObjectGroup->clone(); c->mFrames = mFrames; c->mCurrentFrameIndex = mCurrentFrameIndex; c->mUnusedTime = mUnusedTime; return c; } tiled-1.0.3/src/libtiled/tile.h000066400000000000000000000163071315121121300162760ustar00rootroot00000000000000/* * tile.h * Copyright 2008-2014, Thorbjørn Lindeijer * Copyright 2009, Edward Hutchins * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "object.h" #include #include namespace Tiled { class ObjectGroup; class Terrain; class Tileset; /** * Convenience function for creating tile terrain information. */ inline unsigned makeTerrain(int id) { id &= 0xFF; return id << 24 | id << 16 | id << 8 | id; } /** * Convenience function for creating tile terrain information. */ inline unsigned makeTerrain(int topLeft, int topRight, int bottomLeft, int bottomRight) { return (topLeft & 0xFF) << 24 | (topRight & 0xFF) << 16 | (bottomLeft & 0xFF) << 8 | (bottomRight & 0xFF); } /** * Returns the given \a terrain with the \a corner modified to \a terrainId. */ inline unsigned setTerrainCorner(unsigned terrain, int corner, int terrainId) { unsigned mask = 0xFF << (3 - corner) * 8; unsigned insert = terrainId << (3 - corner) * 8; return (terrain & ~mask) | (insert & mask); } /** * A single frame of an animated tile. */ struct Frame { bool operator == (const Frame &frame) const { return tileId == frame.tileId && duration == frame.duration; } int tileId; int duration; }; class TILEDSHARED_EXPORT Tile : public Object { public: Tile(int id, Tileset *tileset); Tile(const QPixmap &image, int id, Tileset *tileset); ~Tile(); int id() const; Tileset *tileset() const; QSharedPointer sharedTileset() const; const QPixmap &image() const; void setImage(const QPixmap &image); const Tile *currentFrameTile() const; const QString &imageSource() const; void setImageSource(const QString &imageSource); int width() const; int height() const; QSize size() const; QPoint offset() const; const QString &type() const; void setType(const QString &type); Terrain *terrainAtCorner(int corner) const; int cornerTerrainId(int corner) const; void setCornerTerrainId(int corner, int terrainId); inline unsigned terrain() const; void setTerrain(unsigned terrain); float probability() const; void setProbability(float probability); ObjectGroup *objectGroup() const; void setObjectGroup(ObjectGroup *objectGroup); ObjectGroup *swapObjectGroup(ObjectGroup *objectGroup); const QVector &frames() const; void setFrames(const QVector &frames); bool isAnimated() const; int currentFrameIndex() const; bool resetAnimation(); bool advanceAnimation(int ms); bool imageLoaded() const; Tile *clone(Tileset *tileset) const; private: int mId; Tileset *mTileset; QPixmap mImage; QString mImageSource; QString mType; unsigned mTerrain; float mProbability; ObjectGroup *mObjectGroup; QVector mFrames; int mCurrentFrameIndex; int mUnusedTime; friend class Tileset; // To allow changing the tile id }; /** * Returns ID of this tile within its tileset. */ inline int Tile::id() const { return mId; } /** * Returns the tileset that this tile is part of. */ inline Tileset *Tile::tileset() const { return mTileset; } /** * Returns the image of this tile. */ inline const QPixmap &Tile::image() const { return mImage; } /** * Sets the image of this tile. */ inline void Tile::setImage(const QPixmap &image) { mImage = image; } /** * Returns the file name of the external image that represents this tile. * When this tile doesn't refer to an external image, an empty string is * returned. */ inline const QString &Tile::imageSource() const { return mImageSource; } inline void Tile::setImageSource(const QString &imageSource) { mImageSource = imageSource; } /** * Returns the width of this tile. */ inline int Tile::width() const { return mImage.width(); } /** * Returns the height of this tile. */ inline int Tile::height() const { return mImage.height(); } /** * Returns the size of this tile. */ inline QSize Tile::size() const { return mImage.size(); } /** * Returns the type of this tile. Tile objects that do not have a type * explicitly set on them are assumed to be of the type returned by this * function. */ inline const QString &Tile::type() const { return mType; } /** * Sets the type of this tile. * \sa type() */ inline void Tile::setType(const QString &type) { mType = type; } /** * Returns the terrain id at a given corner. */ inline int Tile::cornerTerrainId(int corner) const { unsigned t = (terrain() >> (3 - corner)*8) & 0xFF; return t == 0xFF ? -1 : (int)t; } /** * Set the terrain type of a given corner. */ inline void Tile::setCornerTerrainId(int corner, int terrainId) { setTerrain(setTerrainCorner(mTerrain, corner, terrainId)); } /** * Returns the terrain for each corner of this tile. */ inline unsigned Tile::terrain() const { return mTerrain; } /** * Returns the relative probability of this tile appearing while painting. */ inline float Tile::probability() const { return mProbability; } /** * Set the relative probability of this tile appearing while painting. */ inline void Tile::setProbability(float probability) { mProbability = probability; } /** * @return The group of objects associated with this tile. This is generally * expected to be used for editing collision shapes. */ inline ObjectGroup *Tile::objectGroup() const { return mObjectGroup; } inline const QVector &Tile::frames() const { return mFrames; } inline bool Tile::isAnimated() const { return !mFrames.isEmpty(); } inline int Tile::currentFrameIndex() const { return mCurrentFrameIndex; } /** * Returns whether the image referenced by this tile was loaded. */ inline bool Tile::imageLoaded() const { return !mImage.isNull(); } } // namespace Tiled tiled-1.0.3/src/libtiled/tileanimationdriver.cpp000066400000000000000000000040271315121121300217410ustar00rootroot00000000000000/* * tileanimationdriver.cpp * Copyright 2014, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "tileanimationdriver.h" namespace Tiled { TileAnimationDriver::TileAnimationDriver(QObject *parent) : QAbstractAnimation(parent) , mLastTime(0) { setLoopCount(-1); // loop forever } int TileAnimationDriver::duration() const { return 1000; } void TileAnimationDriver::updateCurrentTime(int currentTime) { int elapsed = currentTime - mLastTime; if (elapsed < 0) elapsed += 1000; mLastTime = currentTime; emit update(elapsed); } void TileAnimationDriver::updateState(State newState, State oldState) { Q_UNUSED(oldState) if (newState == Stopped) mLastTime = 0; } } // namespace Tiled tiled-1.0.3/src/libtiled/tileanimationdriver.h000066400000000000000000000037661315121121300214170ustar00rootroot00000000000000/* * tileanimationdriver.h * Copyright 2014, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "tiled_global.h" #include namespace Tiled { class TILEDSHARED_EXPORT TileAnimationDriver : public QAbstractAnimation { Q_OBJECT public: explicit TileAnimationDriver(QObject *parent = nullptr); int duration() const override; signals: /** * Emitted every time a logic update should be made. \a deltaTime is in * milliseconds. */ void update(int deltaTime); protected: void updateCurrentTime(int currentTime) override; void updateState(State newState, State oldState) override; private: int mLastTime; }; } // namespace Tiled tiled-1.0.3/src/libtiled/tiled.h000066400000000000000000000037121315121121300164360ustar00rootroot00000000000000/* * tiled.h * Copyright 2013, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once namespace Tiled { enum FlipDirection { FlipHorizontally, FlipVertically }; enum RotateDirection { RotateLeft, RotateRight }; enum Alignment { TopLeft, Top, TopRight, Left, Center, Right, BottomLeft, Bottom, BottomRight }; static const char TILES_MIMETYPE[] = "application/vnd.tile.list"; static const char FRAMES_MIMETYPE[] = "application/vnd.frame.list"; static const char LAYERS_MIMETYPE[] = "application/vnd.layer.list"; static const char PROPERTIES_MIMETYPE[] = "application/vnd.properties.list"; } // namespace Tiled tiled-1.0.3/src/libtiled/tiled_global.h000066400000000000000000000030511315121121300177520ustar00rootroot00000000000000/* * tiled_global.h * Copyright 2010, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include #if defined(TILED_LIBRARY) # define TILEDSHARED_EXPORT Q_DECL_EXPORT #else # define TILEDSHARED_EXPORT Q_DECL_IMPORT #endif tiled-1.0.3/src/libtiled/tilelayer.cpp000066400000000000000000000467311315121121300176720ustar00rootroot00000000000000/* * tilelayer.cpp * Copyright 2008-2011, Thorbjørn Lindeijer * Copyright 2009, Jeff Bland * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "tilelayer.h" #include "tile.h" #include "hex.h" using namespace Tiled; TileLayer::TileLayer(const QString &name, int x, int y, int width, int height) : Layer(TileLayerType, name, x, y) , mWidth(width) , mHeight(height) , mGrid(width * height) , mUsedTilesetsDirty(false) { Q_ASSERT(width >= 0); Q_ASSERT(height >= 0); } static QMargins maxMargins(const QMargins &a, const QMargins &b) { return QMargins(qMax(a.left(), b.left()), qMax(a.top(), b.top()), qMax(a.right(), b.right()), qMax(a.bottom(), b.bottom())); } static QMargins computeDrawMargins(const QSet &tilesets) { int maxTileSize = 0; QMargins offsetMargins; for (const SharedTileset &tileset : tilesets) { const QPoint offset = tileset->tileOffset(); const QSize tileSize = tileset->tileSize(); maxTileSize = std::max(maxTileSize, std::max(tileSize.width(), tileSize.height())); offsetMargins = maxMargins(QMargins(-offset.x(), -offset.y(), offset.x(), offset.y()), offsetMargins); } return QMargins(offsetMargins.left(), offsetMargins.top() + maxTileSize, offsetMargins.right() + maxTileSize, offsetMargins.bottom()); } QMargins TileLayer::drawMargins() const { return computeDrawMargins(usedTilesets()); } QRegion TileLayer::region(std::function condition) const { QRegion region; for (int y = 0; y < mHeight; ++y) { for (int x = 0; x < mWidth; ++x) { if (condition(cellAt(x, y))) { const int rangeStart = x; for (++x; x <= mWidth; ++x) { if (x == mWidth || !condition(cellAt(x, y))) { const int rangeEnd = x; region += QRect(rangeStart + mX, y + mY, rangeEnd - rangeStart, 1); break; } } } } } return region; } /** * Sets the cell at the given coordinates. */ void Tiled::TileLayer::setCell(int x, int y, const Cell &cell) { Q_ASSERT(contains(x, y)); Cell &existingCell = mGrid[x + y * mWidth]; if (!mUsedTilesetsDirty) { Tileset *oldTileset = existingCell.isEmpty() ? nullptr : existingCell.tileset(); Tileset *newTileset = cell.tileset(); if (oldTileset != newTileset) { if (oldTileset) mUsedTilesetsDirty = true; else if (newTileset) mUsedTilesets.insert(newTileset->sharedPointer()); } } existingCell = cell; } TileLayer *TileLayer::copy(const QRegion ®ion) const { const QRegion area = region.intersected(QRect(0, 0, width(), height())); const QRect bounds = region.boundingRect(); const QRect areaBounds = area.boundingRect(); const int offsetX = qMax(0, areaBounds.x() - bounds.x()); const int offsetY = qMax(0, areaBounds.y() - bounds.y()); TileLayer *copied = new TileLayer(QString(), 0, 0, bounds.width(), bounds.height()); for (const QRect &rect : area.rects()) for (int x = rect.left(); x <= rect.right(); ++x) for (int y = rect.top(); y <= rect.bottom(); ++y) copied->setCell(x - areaBounds.x() + offsetX, y - areaBounds.y() + offsetY, cellAt(x, y)); return copied; } void TileLayer::merge(const QPoint &pos, const TileLayer *layer) { // Determine the overlapping area QRect area = QRect(pos, QSize(layer->width(), layer->height())); area &= QRect(0, 0, width(), height()); for (int y = area.top(); y <= area.bottom(); ++y) { for (int x = area.left(); x <= area.right(); ++x) { const Cell &cell = layer->cellAt(x - pos.x(), y - pos.y()); if (!cell.isEmpty()) setCell(x, y, cell); } } } void TileLayer::setCells(int x, int y, TileLayer *layer, const QRegion &mask) { // Determine the overlapping area QRegion area = QRect(x, y, layer->width(), layer->height()); area &= QRect(0, 0, width(), height()); if (!mask.isEmpty()) area &= mask; for (const QRect &rect : area.rects()) for (int _x = rect.left(); _x <= rect.right(); ++_x) for (int _y = rect.top(); _y <= rect.bottom(); ++_y) setCell(_x, _y, layer->cellAt(_x - x, _y - y)); } /** * Sets the tiles in the given \a area to \a tile. Flipping flags are * preserved. */ void TileLayer::setTiles(const QRegion &area, Tile *tile) { Q_ASSERT(area.subtracted(QRegion(0, 0, mWidth, mHeight)).isEmpty()); for (const QRect &rect : area.rects()) { for (int x = rect.left(); x <= rect.right(); ++x) { for (int y = rect.top(); y <= rect.bottom(); ++y) { Cell cell = cellAt(x, y); cell.setTile(tile); setCell(x, y, cell); } } } } void TileLayer::erase(const QRegion &area) { const Cell emptyCell; for (const QRect &rect : area.rects()) for (int x = rect.left(); x <= rect.right(); ++x) for (int y = rect.top(); y <= rect.bottom(); ++y) setCell(x, y, emptyCell); } void TileLayer::flip(FlipDirection direction) { QVector newGrid(mWidth * mHeight); Q_ASSERT(direction == FlipHorizontally || direction == FlipVertically); for (int y = 0; y < mHeight; ++y) { for (int x = 0; x < mWidth; ++x) { Cell &dest = newGrid[x + y * mWidth]; if (direction == FlipHorizontally) { const Cell &source = cellAt(mWidth - x - 1, y); dest = source; dest.setFlippedHorizontally(!source.flippedHorizontally()); } else if (direction == FlipVertically) { const Cell &source = cellAt(x, mHeight - y - 1); dest = source; dest.setFlippedVertically(!source.flippedVertically()); } } } mGrid = newGrid; } void TileLayer::flipHexagonal(FlipDirection direction) { QVector newGrid(mWidth * mHeight); Q_ASSERT(direction == FlipHorizontally || direction == FlipVertically); // for more info see impl "void TileLayer::rotateHexagonal(RotateDirection direction)" static const char flipMaskH[16] = { 8, 6, 5, 4, 12, 2, 1, 0, 0, 14, 13, 12, 4, 10, 9, 8 }; // [0,15]<=>[8,7]; 2<=>5; 1<=>6; [12,3]<=>[4,11]; 14<=>9; 13<=>10; static const char flipMaskV[16] = { 4, 10, 9, 8, 0, 14, 13, 12, 12, 2, 1, 0, 8, 6, 5, 4 }; // [0,15]<=>[4,11]; 2<=>9; 1<=>10; [12,3]<=>[8,7]; 14<=>5; 13<=>6; const char (&flipMask)[16] = (direction == FlipHorizontally ? flipMaskH : flipMaskV); for (int y = 0; y < mHeight; ++y) { for (int x = 0; x < mWidth; ++x) { const Cell &source = (direction == FlipHorizontally ? cellAt(mWidth - x - 1, y) : cellAt(x, mHeight - y - 1)); Cell &dest = newGrid[x + y * mWidth]; dest = source; unsigned char mask = (static_cast(dest.flippedHorizontally()) << 3) | (static_cast(dest.flippedVertically()) << 2) | (static_cast(dest.flippedAntiDiagonally()) << 1) | (static_cast(dest.rotatedHexagonal120()) << 0); mask = flipMask[mask]; dest.setFlippedHorizontally((mask & 8) != 0); dest.setFlippedVertically((mask & 4) != 0); dest.setFlippedAntiDiagonally((mask & 2) != 0); dest.setRotatedHexagonal120((mask & 1) != 0); } } mGrid = newGrid; } void TileLayer::rotate(RotateDirection direction) { static const char rotateRightMask[8] = { 5, 4, 1, 0, 7, 6, 3, 2 }; static const char rotateLeftMask[8] = { 3, 2, 7, 6, 1, 0, 5, 4 }; const char (&rotateMask)[8] = (direction == RotateRight) ? rotateRightMask : rotateLeftMask; int newWidth = mHeight; int newHeight = mWidth; QVector newGrid(newWidth * newHeight); for (int y = 0; y < mHeight; ++y) { for (int x = 0; x < mWidth; ++x) { const Cell &source = cellAt(x, y); Cell dest = source; unsigned char mask = (dest.flippedHorizontally() << 2) | (dest.flippedVertically() << 1) | (dest.flippedAntiDiagonally() << 0); mask = rotateMask[mask]; dest.setFlippedHorizontally((mask & 4) != 0); dest.setFlippedVertically((mask & 2) != 0); dest.setFlippedAntiDiagonally((mask & 1) != 0); if (direction == RotateRight) newGrid[x * newWidth + (mHeight - y - 1)] = dest; else newGrid[(mWidth - x - 1) * newWidth + y] = dest; } } mWidth = newWidth; mHeight = newHeight; mGrid = newGrid; } void TileLayer::rotateHexagonal(RotateDirection direction, Map *map) { Map::StaggerIndex staggerIndex = map->staggerIndex(); Map::StaggerAxis staggerAxis = map->staggerAxis(); Hex bottomRight(mWidth, mHeight, staggerIndex, staggerAxis); Hex topRight(mWidth, 0, staggerIndex, staggerAxis); Hex center(mWidth / 2, mHeight / 2, staggerIndex, staggerAxis); bottomRight -= center; topRight -= center; bottomRight.rotate(RotateRight); topRight.rotate(RotateRight); int newWidth = topRight.toStaggered(staggerIndex, staggerAxis).x() * 2 + 2; int newHeight = bottomRight.toStaggered(staggerIndex, staggerAxis).y() * 2 + 2; QVector newGrid(newWidth * newHeight); Hex newCenter(newWidth / 2, newHeight / 2, staggerIndex, staggerAxis); /* https://github.com/bjorn/tiled/pull/1447 0 or 15 0: None or (Rotated60 | Rotated120 | FlippedVertically | FlippedHorizontally) 2 60: Rotated60 1 120: Rotated120 12 or 3 180: (FlippedHorizontally | FlippedVertically) or (Rotated60 | Rotated120) 14 240: Rotated60 | FlippedHorizontally | FlippedVertically 13 300: Rotated120 | FlippedHorizontally | FlippedVertically 8 or 7 0: FlippedHorizontally or (Rotated60 | Rotated120 | FlippedVertically) 10 60: Rotated60 | FlippedHorizontally 9 120: Rotated120 | FlippedHorizontally 4 or 11 180: (FlippedVertically) or (Rotated60 | Rotated120 | FlippedHorizontally) 6 240: Rotated60 | FlippedVertically 5 300: Rotated120 | FlippedVertically */ static const char rotateRightMask[16] = { 2, 12, 1, 14, 6, 8, 5, 10, 10, 4, 9, 0, 14, 0, 13, 2 }; // [0,15]->2->1->[12,3]->14->13; [8,7]->10->9->[4,11]->6->5; static const char rotateLeftMask[16] = { 13, 2, 0, 1, 9, 6, 4, 5, 5, 10, 8, 9, 1, 14, 12, 13 }; // [0,15]->13->14->[12,3]->1->2; [8,7]->5->6->[4,11]->9->10; const char (&rotateMask)[16] = (direction == RotateRight) ? rotateRightMask : rotateLeftMask; for (int y = 0; y < mHeight; ++y) { for (int x = 0; x < mWidth; ++x) { const Cell &source = cellAt(x, y); Cell dest = source; unsigned char mask = (static_cast(dest.flippedHorizontally()) << 3) | (static_cast(dest.flippedVertically()) << 2) | (static_cast(dest.flippedAntiDiagonally()) << 1) | (static_cast(dest.rotatedHexagonal120()) << 0); mask = rotateMask[mask]; dest.setFlippedHorizontally((mask & 8) != 0); dest.setFlippedVertically((mask & 4) != 0); dest.setFlippedAntiDiagonally((mask & 2) != 0); dest.setRotatedHexagonal120((mask & 1) != 0); Hex rotatedHex(x, y, staggerIndex, staggerAxis); rotatedHex -= center; rotatedHex.rotate(direction); rotatedHex += newCenter; QPoint rotatedPoint = rotatedHex.toStaggered(staggerIndex, staggerAxis); int index = rotatedPoint.y() * newWidth + rotatedPoint.x(); newGrid[index] = dest; } } mWidth = newWidth; mHeight = newHeight; mGrid = newGrid; QRect filledRect = region().boundingRect(); if (staggerAxis == Map::StaggerY) { if (filledRect.y() & 1) map->invertStaggerIndex(); } else { if (filledRect.x() & 1) map->invertStaggerIndex(); } resize(filledRect.size(), -filledRect.topLeft()); } QSet TileLayer::usedTilesets() const { if (mUsedTilesetsDirty) { QSet tilesets; for (const Cell &cell : mGrid) if (const Tile *tile = cell.tile()) tilesets.insert(tile->sharedTileset()); mUsedTilesets.swap(tilesets); mUsedTilesetsDirty = false; } return mUsedTilesets; } bool TileLayer::hasCell(std::function condition) const { for (const Cell &cell : mGrid) if (condition(cell)) return true; return false; } bool TileLayer::referencesTileset(const Tileset *tileset) const { return usedTilesets().contains(tileset->sharedPointer()); } void TileLayer::removeReferencesToTileset(Tileset *tileset) { for (int i = 0, i_end = mGrid.size(); i < i_end; ++i) { if (mGrid.at(i).tileset() == tileset) mGrid.replace(i, Cell()); } mUsedTilesets.remove(tileset->sharedPointer()); } void TileLayer::replaceReferencesToTileset(Tileset *oldTileset, Tileset *newTileset) { for (Cell &cell : mGrid) { if (cell.tileset() == oldTileset) cell.setTile(newTileset, cell.tileId()); } if (mUsedTilesets.remove(oldTileset->sharedPointer())) mUsedTilesets.insert(newTileset->sharedPointer()); } void TileLayer::resize(const QSize &size, const QPoint &offset) { if (this->size() == size && offset.isNull()) return; QVector newGrid(size.width() * size.height()); // Copy over the preserved part const int startX = qMax(0, -offset.x()); const int startY = qMax(0, -offset.y()); const int endX = qMin(mWidth, size.width() - offset.x()); const int endY = qMin(mHeight, size.height() - offset.y()); for (int y = startY; y < endY; ++y) { for (int x = startX; x < endX; ++x) { const int index = x + offset.x() + (y + offset.y()) * size.width(); newGrid[index] = cellAt(x, y); } } mGrid = newGrid; setSize(size); } void TileLayer::offsetTiles(const QPoint &offset, const QRect &bounds, bool wrapX, bool wrapY) { QVector newGrid(mWidth * mHeight); for (int y = 0; y < mHeight; ++y) { for (int x = 0; x < mWidth; ++x) { // Skip out of bounds tiles if (!bounds.contains(x, y)) { newGrid[x + y * mWidth] = cellAt(x, y); continue; } // Get position to pull tile value from int oldX = x - offset.x(); int oldY = y - offset.y(); // Wrap x value that will be pulled from if (wrapX && bounds.width() > 0) { while (oldX < bounds.left()) oldX += bounds.width(); while (oldX > bounds.right()) oldX -= bounds.width(); } // Wrap y value that will be pulled from if (wrapY && bounds.height() > 0) { while (oldY < bounds.top()) oldY += bounds.height(); while (oldY > bounds.bottom()) oldY -= bounds.height(); } // Set the new tile if (contains(oldX, oldY) && bounds.contains(oldX, oldY)) newGrid[x + y * mWidth] = cellAt(oldX, oldY); else newGrid[x + y * mWidth] = Cell(); } } mGrid = newGrid; } bool TileLayer::canMergeWith(Layer *other) const { return other->isTileLayer(); } Layer *TileLayer::mergedWith(Layer *other) const { Q_ASSERT(canMergeWith(other)); const TileLayer *o = static_cast(other); const QRect unitedBounds = bounds().united(o->bounds()); const QPoint offset = position() - unitedBounds.topLeft(); TileLayer *merged = clone(); merged->resize(unitedBounds.size(), offset); merged->merge(o->position() - unitedBounds.topLeft(), o); return merged; } QRegion TileLayer::computeDiffRegion(const TileLayer *other) const { QRegion ret; const int dx = other->x() - mX; const int dy = other->y() - mY; QRect r = QRect(0, 0, width(), height()); r &= QRect(dx, dy, other->width(), other->height()); for (int y = r.top(); y <= r.bottom(); ++y) { for (int x = r.left(); x <= r.right(); ++x) { if (cellAt(x, y) != other->cellAt(x - dx, y - dy)) { const int rangeStart = x; while (x <= r.right() && cellAt(x, y) != other->cellAt(x - dx, y - dy)) { ++x; } const int rangeEnd = x; ret += QRect(rangeStart, y, rangeEnd - rangeStart, 1); } } } return ret; } bool TileLayer::isEmpty() const { for (const Cell &cell : mGrid) if (!cell.isEmpty()) return false; return true; } /** * Returns a duplicate of this TileLayer. * * \sa Layer::clone() */ TileLayer *TileLayer::clone() const { return initializeClone(new TileLayer(mName, mX, mY, mWidth, mHeight)); } TileLayer *TileLayer::initializeClone(TileLayer *clone) const { Layer::initializeClone(clone); clone->mGrid = mGrid; clone->mUsedTilesets = mUsedTilesets; clone->mUsedTilesetsDirty = mUsedTilesetsDirty; return clone; } tiled-1.0.3/src/libtiled/tilelayer.h000066400000000000000000000273251315121121300173350ustar00rootroot00000000000000/* * tilelayer.h * Copyright 2008-2011, Thorbjørn Lindeijer * Copyright 2009, Jeff Bland * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "tiled_global.h" #include "map.h" #include "layer.h" #include "tiled.h" #include "tile.h" #include "tileset.h" #include #include #include #include #include namespace Tiled { class Tile; /** * A cell on a tile layer grid. */ class Cell { public: Cell() : _tileset(nullptr), _tileId(-1), _flippedHorizontally(false), _flippedVertically(false), _flippedAntiDiagonally(false), _rotatedHexagonal120(false) {} explicit Cell(Tile *tile) : _tileset(tile ? tile->tileset() : nullptr), _tileId(tile ? tile->id() : -1), _flippedHorizontally(false), _flippedVertically(false), _flippedAntiDiagonally(false), _rotatedHexagonal120(false) {} bool isEmpty() const { return _tileset == nullptr; } bool operator == (const Cell &other) const { return _tileset == other._tileset && _tileId == other._tileId && _flippedHorizontally == other._flippedHorizontally && _flippedVertically == other._flippedVertically && _flippedAntiDiagonally == other._flippedAntiDiagonally && _rotatedHexagonal120 == other._rotatedHexagonal120; } bool operator != (const Cell &other) const { return _tileset != other._tileset || _tileId != other._tileId || _flippedHorizontally != other._flippedHorizontally || _flippedVertically != other._flippedVertically || _flippedAntiDiagonally != other._flippedAntiDiagonally || _rotatedHexagonal120 != other._rotatedHexagonal120; } Tileset *tileset() const { return _tileset; } int tileId() const { return _tileId; } bool flippedHorizontally() const { return _flippedHorizontally; } bool flippedVertically() const { return _flippedVertically; } bool flippedAntiDiagonally() const { return _flippedAntiDiagonally; } bool rotatedHexagonal120() const { return _rotatedHexagonal120; } void setFlippedHorizontally(bool f) { _flippedHorizontally = f; } void setFlippedVertically(bool f) { _flippedVertically = f; } void setFlippedAntiDiagonally(bool f) { _flippedAntiDiagonally = f; } void setRotatedHexagonal120(bool f) { _rotatedHexagonal120 = f; } Tile *tile() const; void setTile(Tile *tile); void setTile(Tileset *tileset, int tileId); bool refersTile(const Tile *tile) const; private: Tileset *_tileset; int _tileId; bool _flippedHorizontally; bool _flippedVertically; bool _flippedAntiDiagonally; bool _rotatedHexagonal120; }; inline Tile *Cell::tile() const { return _tileset ? _tileset->findTile(_tileId) : nullptr; } inline void Cell::setTile(Tile *tile) { if (tile) setTile(tile->tileset(), tile->id()); else setTile(nullptr, -1); } inline void Cell::setTile(Tileset *tileset, int tileId) { _tileset = tileset; _tileId = tileId; } inline bool Cell::refersTile(const Tile *tile) const { return _tileset == tile->tileset() && _tileId == tile->id(); } /** * A tile layer is a grid of cells. Each cell refers to a specific tile, and * stores how the tile is flipped. * * Coordinates and regions passed to function parameters are in local * coordinates and do not take into account the position of the layer. */ class TILEDSHARED_EXPORT TileLayer : public Layer { public: /** * Constructor. */ TileLayer(const QString &name, int x, int y, int width, int height); /** * Returns the width of this layer. */ int width() const { return mWidth; } /** * Returns the height of this layer. */ int height() const { return mHeight; } /** * Returns the size of this layer. */ QSize size() const { return QSize(mWidth, mHeight); } void setSize(const QSize &size); /** * Returns the bounds of this layer. */ QRect bounds() const { return QRect(mX, mY, mWidth, mHeight); } QMargins drawMargins() const; bool contains(int x, int y) const; bool contains(const QPoint &point) const; /** * Calculates the region of cells in this tile layer for which the given * \a condition returns true. */ QRegion region(std::function condition) const; /** * Calculates the region occupied by the tiles of this layer. Similar to * Layer::bounds(), but leaves out the regions without tiles. */ QRegion region() const; const Cell &cellAt(int x, int y) const; const Cell &cellAt(const QPoint &point) const; void setCell(int x, int y, const Cell &cell); /** * Returns a copy of the area specified by the given \a region. The * caller is responsible for the returned tile layer. */ TileLayer *copy(const QRegion ®ion) const; TileLayer *copy(int x, int y, int width, int height) const { return copy(QRegion(x, y, width, height)); } /** * Merges the given \a layer onto this layer at position \a pos. Parts that * fall outside of this layer will be lost and empty tiles in the given * layer will have no effect. */ void merge(const QPoint &pos, const TileLayer *layer); /** * Removes all cells in the specified region. */ void erase(const QRegion ®ion); /** * Sets the cells starting at the given position to the cells in the given * \a tileLayer. Parts that fall outside of this layer will be ignored. * * When a \a mask is given, only cells that fall within this mask are set. * The mask is applied in local coordinates. */ void setCells(int x, int y, TileLayer *tileLayer, const QRegion &mask = QRegion()); void setTiles(const QRegion &area, Tile *tile); /** * Flip this tile layer in the given \a direction. Direction must be * horizontal or vertical. This doesn't change the dimensions of the * tile layer. */ void flip(FlipDirection direction); /** * Hexagonal flip this tile layer in the given \a direction. Direction must be * horizontal or vertical. This doesn't change the dimensions of the * tile layer. */ void flipHexagonal(FlipDirection direction); /** * Rotate this tile layer by 90 degrees left or right. The tile positions * are rotated within the layer, and the tiles themselves are rotated. The * dimensions of the tile layer are swapped. */ void rotate(RotateDirection direction); /** * Hexagonal rotate this tile layer by 60 degrees left or right. The tile positions * are rotated within the layer, and the tiles themselves are rotated. * As a temporary measure, a Map* is passed to give information about stagger index * and axis, which affects rotation. The stagger index of this map can change. */ void rotateHexagonal(RotateDirection direction, Map *map); /** * Computes and returns the set of tilesets used by this tile layer. */ QSet usedTilesets() const override; /** * Returns whether this tile layer has any cell for which the given * \a condition returns true. */ bool hasCell(std::function condition) const; /** * Returns whether this tile layer is referencing the given tileset. */ bool referencesTileset(const Tileset *tileset) const override; /** * Removes all references to the given tileset. This sets all tiles on this * layer that are from the given tileset to null. */ void removeReferencesToTileset(Tileset *tileset); /** * Replaces all tiles from \a oldTileset with tiles from \a newTileset. */ void replaceReferencesToTileset(Tileset *oldTileset, Tileset *newTileset) override; /** * Resizes this tile layer to \a size, while shifting all tiles by * \a offset. */ void resize(const QSize &size, const QPoint &offset); /** * Offsets the tiles in this layer within \a bounds by \a offset, * and optionally wraps them. * * \sa ObjectGroup::offsetObjects() */ void offsetTiles(const QPoint &offset, const QRect &bounds, bool wrapX, bool wrapY); bool canMergeWith(Layer *other) const override; Layer *mergedWith(Layer *other) const override; /** * Returns the region where this tile layer and the given tile layer * are different. The relative positions of the layers are taken into * account. The returned region is relative to this tile layer. */ QRegion computeDiffRegion(const TileLayer *other) const; /** * Returns true if all tiles in the layer are empty. */ bool isEmpty() const override; TileLayer *clone() const override; // Enable easy iteration over cells with range-based for QVector::iterator begin() { return mGrid.begin(); } QVector::iterator end() { return mGrid.end(); } QVector::const_iterator begin() const { return mGrid.begin(); } QVector::const_iterator end() const { return mGrid.end(); } protected: TileLayer *initializeClone(TileLayer *clone) const; private: int mWidth; int mHeight; QVector mGrid; mutable QSet mUsedTilesets; mutable bool mUsedTilesetsDirty; }; /** * Sets the size of this layer. */ inline void TileLayer::setSize(const QSize &size) { mWidth = size.width(); mHeight = size.height(); } /** * Returns whether (x, y) is inside this map layer. */ inline bool TileLayer::contains(int x, int y) const { return x >= 0 && y >= 0 && x < mWidth && y < mHeight; } inline bool TileLayer::contains(const QPoint &point) const { return contains(point.x(), point.y()); } inline QRegion TileLayer::region() const { return region([] (const Cell &cell) { return !cell.isEmpty(); }); } /** * Returns a read-only reference to the cell at the given coordinates. The * coordinates have to be within this layer. */ inline const Cell &TileLayer::cellAt(int x, int y) const { Q_ASSERT(contains(x, y)); return mGrid.at(x + y * mWidth); } inline const Cell &TileLayer::cellAt(const QPoint &point) const { return cellAt(point.x(), point.y()); } typedef QSharedPointer SharedTileLayer; } // namespace Tiled tiled-1.0.3/src/libtiled/tileset.cpp000066400000000000000000000530371315121121300173460ustar00rootroot00000000000000/* * tileset.cpp * Copyright 2008-2015, Thorbjørn Lindeijer * Copyright 2009, Edward Hutchins * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "tileset.h" #include "terrain.h" #include "tile.h" #include "tilesetformat.h" #include using namespace Tiled; Tileset::Tileset(QString name, int tileWidth, int tileHeight, int tileSpacing, int margin): Object(TilesetType), mName(std::move(name)), mTileWidth(tileWidth), mTileHeight(tileHeight), mTileSpacing(tileSpacing), mMargin(margin), mOrientation(Orthogonal), mGridSize(tileWidth, tileHeight), mColumnCount(0), mExpectedColumnCount(0), mExpectedRowCount(0), mNextTileId(0), mTerrainDistancesDirty(false), mLoaded(true) { Q_ASSERT(tileSpacing >= 0); Q_ASSERT(margin >= 0); } Tileset::~Tileset() { qDeleteAll(mTiles); qDeleteAll(mTerrainTypes); } void Tileset::setFormat(TilesetFormat *format) { mFormat = format; } TilesetFormat *Tileset::format() const { return mFormat; } /** * Sets the tile size of this tileset. Affects how image is cut in loadImage. * * @warning Invalid for image collection tilesets! */ void Tileset::setTileSize(QSize tileSize) { Q_ASSERT(!tileSize.isEmpty()); mTileWidth = tileSize.width(); mTileHeight = tileSize.height(); } /** * Sets the space in pixels between tiles in the tileset. Affects how image is * cut in loadImage. */ void Tileset::setTileSpacing(int tileSpacing) { Q_ASSERT(tileSpacing >= 0); mTileSpacing = tileSpacing; } /** * Sets the margin used by the tileset image. This is the number of pixels * at the top-left border of the image that is skipped when cutting out tiles. * Affects how image is cut in loadImage. */ void Tileset::setMargin(int margin) { Q_ASSERT(margin >= 0); mMargin = margin; } /** * Returns the tile with the given ID, creating it when it does not exist yet. */ Tile *Tileset::findOrCreateTile(int id) { if (Tile *tile = mTiles.value(id)) return tile; mNextTileId = std::max(mNextTileId, id + 1); return mTiles[id] = new Tile(id, this); } /** * Returns the number of tile rows in the tileset image. */ int Tileset::rowCount() const { if (isCollection()) return 1; return rowCountForHeight(mImageReference.size.height()); } /** * Sets the transparent color. Pixels with this color will be masked out * when loadFromImage() is called. */ void Tileset::setTransparentColor(const QColor &c) { mImageReference.transparentColor = c; } /** * Sets the image reference data for tileset image based tilesets. * * This function also sets the expected column count, which can be used later * for automatic adjustment of tile indexes in case the tileset image width has * changed. */ void Tileset::setImageReference(const ImageReference &reference) { mImageReference = reference; mExpectedColumnCount = columnCountForWidth(mImageReference.size.width()); mExpectedRowCount = rowCountForHeight(mImageReference.size.height()); } /** * Load this tileset from the given tileset \a image. This will replace * existing tile images in this tileset with new ones. If the new image * contains more tiles than exist in the tileset new tiles will be * appended, if there are fewer tiles the excess images will be blanked. * * The tile width and height of this tileset must be higher than 0. * * @param image the image to load the tiles from * @param fileName the file name of the image, which will be remembered * as the image source of this tileset. * @return true if loading was successful, otherwise * returns false */ bool Tileset::loadFromImage(const QImage &image, const QString &fileName) { mImageReference.source = fileName; if (image.isNull()) { mImageReference.loaded = false; return false; } const QSize tileSize = this->tileSize(); const int margin = this->margin(); const int spacing = this->tileSpacing(); Q_ASSERT(tileSize.width() > 0 && tileSize.height() > 0); const int stopWidth = image.width() - tileSize.width(); const int stopHeight = image.height() - tileSize.height(); int tileNum = 0; for (int y = margin; y <= stopHeight; y += tileSize.height() + spacing) { for (int x = margin; x <= stopWidth; x += tileSize.width() + spacing) { const QImage tileImage = image.copy(x, y, tileSize.width(), tileSize.height()); QPixmap tilePixmap = QPixmap::fromImage(tileImage); const QColor &transparent = mImageReference.transparentColor; if (transparent.isValid()) { const QImage mask = tileImage.createMaskFromColor(transparent.rgb()); tilePixmap.setMask(QBitmap::fromImage(mask)); } auto it = mTiles.find(tileNum); if (it != mTiles.end()) it.value()->setImage(tilePixmap); else mTiles.insert(tileNum, new Tile(tilePixmap, tileNum, this)); ++tileNum; } } // Blank out any remaining tiles to avoid confusion (todo: could be more clear) for (Tile *tile : mTiles) { if (tile->id() >= tileNum) { QPixmap tilePixmap = QPixmap(tileSize); tilePixmap.fill(); tile->setImage(tilePixmap); } } mNextTileId = std::max(mNextTileId, tileNum); mImageReference.size = image.size(); mColumnCount = columnCountForWidth(mImageReference.size.width()); mImageReference.loaded = true; return true; } /** * Tries to load the image this tileset is referring to. * * @return true if loading was successful, otherwise * returns false */ bool Tileset::loadImage() { return loadFromImage(mImageReference.create(), mImageReference.source); } /** * Returns whether the tiles in \a candidate use the same images as the ones * in \a subject. Note that \a candidate is allowed to have additional tiles * as well. */ static bool sameTileImages(const Tileset &subject, const Tileset &candidate) { for (const Tile *subjectTile : subject.tiles()) { const Tile *replacementTile = candidate.findTile(subjectTile->id()); if (!replacementTile) return false; if (subjectTile->imageSource() != replacementTile->imageSource()) return false; } return true; } /** * This checks if there is a similar tileset in the given list. * It is needed for replacing this tileset by its similar copy. */ SharedTileset Tileset::findSimilarTileset(const QVector &tilesets) const { for (const SharedTileset &candidate : tilesets) { Q_ASSERT(candidate != this); if (candidate->tileCount() != tileCount()) continue; if (candidate->imageSource() != imageSource()) continue; if (candidate->tileSize() != tileSize()) continue; if (candidate->tileSpacing() != tileSpacing()) continue; if (candidate->margin() != margin()) continue; if (candidate->tileOffset() != tileOffset()) continue; // For an image collection tileset, check the image sources if (isCollection()) if (!sameTileImages(*this, *candidate)) continue; return candidate; } return SharedTileset(); } /** * Changes the source of the tileset image. * * Only takes affect when loadImage is called. */ void Tileset::setImageSource(const QString &imageSource) { mImageReference.source = imageSource; } /** * Returns the column count that this tileset would have if the tileset * image would have the given \a width. This takes into account the tile * size, margin and spacing. */ int Tileset::columnCountForWidth(int width) const { if (mTileWidth <= 0) return 0; return (width - mMargin + mTileSpacing) / (mTileWidth + mTileSpacing); } /** * Returns the row count that this tileset would have if the tileset * image would have the given \a width. This takes into account the tile * size, margin and spacing. */ int Tileset::rowCountForHeight(int height) const { if (mTileHeight <= 0) return 0; return (height - mMargin + mTileSpacing) / (mTileHeight + mTileSpacing); } /** * Adds a new terrain type. * * @param name the name of the terrain * @param imageTile the id of the tile that represents the terrain visually * @return the created Terrain instance */ Terrain *Tileset::addTerrain(const QString &name, int imageTileId) { Terrain *terrain = new Terrain(terrainCount(), this, name, imageTileId); insertTerrain(terrainCount(), terrain); return terrain; } /** * Adds the \a terrain type at the given \a index. * * The terrain should already have this tileset associated with it. */ void Tileset::insertTerrain(int index, Terrain *terrain) { Q_ASSERT(terrain->tileset() == this); mTerrainTypes.insert(index, terrain); // Reassign terrain IDs for (int terrainId = index; terrainId < mTerrainTypes.size(); ++terrainId) mTerrainTypes.at(terrainId)->mId = terrainId; // Adjust tile terrain references for (Tile *tile : mTiles) { for (int corner = 0; corner < 4; ++corner) { const int terrainId = tile->cornerTerrainId(corner); if (terrainId >= index) tile->setCornerTerrainId(corner, terrainId + 1); } } mTerrainDistancesDirty = true; } /** * Removes the terrain type at the given \a index and returns it. The * caller becomes responsible for the lifetime of the terrain type. * * This will cause the terrain ids of subsequent terrains to shift up to * fill the space and the terrain information of all tiles in this tileset * will be updated accordingly. */ Terrain *Tileset::takeTerrainAt(int index) { Terrain *terrain = mTerrainTypes.takeAt(index); // Reassign terrain IDs for (int terrainId = index; terrainId < mTerrainTypes.size(); ++terrainId) mTerrainTypes.at(terrainId)->mId = terrainId; // Clear and adjust tile terrain references for (Tile *tile : mTiles) { for (int corner = 0; corner < 4; ++corner) { const int terrainId = tile->cornerTerrainId(corner); if (terrainId == index) tile->setCornerTerrainId(corner, 0xFF); else if (terrainId > index) tile->setCornerTerrainId(corner, terrainId - 1); } } mTerrainDistancesDirty = true; return terrain; } /** * Returns the transition penalty(/distance) between 2 terrains. -1 if no * transition is possible. */ int Tileset::terrainTransitionPenalty(int terrainType0, int terrainType1) const { if (mTerrainDistancesDirty) { const_cast(this)->recalculateTerrainDistances(); const_cast(this)->mTerrainDistancesDirty = false; } terrainType0 = terrainType0 == 255 ? -1 : terrainType0; terrainType1 = terrainType1 == 255 ? -1 : terrainType1; // Do some magic, since we don't have a transition array for no-terrain if (terrainType0 == -1 && terrainType1 == -1) return 0; if (terrainType0 == -1) return mTerrainTypes.at(terrainType1)->transitionDistance(terrainType0); return mTerrainTypes.at(terrainType0)->transitionDistance(terrainType1); } /** * Calculates the transition distance matrix for all terrain types. */ void Tileset::recalculateTerrainDistances() { // some fancy macros which can search for a value in each byte of a word simultaneously #define hasZeroByte(dword) (((dword) - 0x01010101UL) & ~(dword) & 0x80808080UL) #define hasByteEqualTo(dword, value) (hasZeroByte((dword) ^ (~0UL/255 * (value)))) // Terrain distances are the number of transitions required before one terrain may meet another // Terrains that have no transition path have a distance of -1 for (int i = 0; i < terrainCount(); ++i) { Terrain *type = terrain(i); QVector distance(terrainCount() + 1, -1); // Check all tiles for transitions to other terrain types for (const Tile *tile : mTiles) { if (!hasByteEqualTo(tile->terrain(), i)) continue; // This tile has transitions, add the transitions as neightbours (distance 1) int tl = tile->cornerTerrainId(0); int tr = tile->cornerTerrainId(1); int bl = tile->cornerTerrainId(2); int br = tile->cornerTerrainId(3); // Terrain on diagonally opposite corners are not actually a neighbour if (tl == i || br == i) { distance[tr + 1] = 1; distance[bl + 1] = 1; } if (tr == i || bl == i) { distance[tl + 1] = 1; distance[br + 1] = 1; } // terrain has at least one tile of its own type distance[i + 1] = 0; } type->setTransitionDistances(distance); } // Calculate indirect transition distances bool bNewConnections; do { bNewConnections = false; // For each combination of terrain types for (int i = 0; i < terrainCount(); ++i) { Terrain *t0 = terrain(i); for (int j = 0; j < terrainCount(); ++j) { if (i == j) continue; Terrain *t1 = terrain(j); // Scan through each terrain type, and see if we have any in common for (int t = -1; t < terrainCount(); ++t) { int d0 = t0->transitionDistance(t); int d1 = t1->transitionDistance(t); if (d0 == -1 || d1 == -1) continue; // We have cound a common connection int d = t0->transitionDistance(j); Q_ASSERT(t1->transitionDistance(i) == d); // If the new path is shorter, record the new distance if (d == -1 || d0 + d1 < d) { d = d0 + d1; t0->setTransitionDistance(j, d); t1->setTransitionDistance(i, d); // We're making progress, flag for another iteration... bNewConnections = true; } } } } // Repeat while we are still making new connections (could take a // number of iterations for distant terrain types to connect) } while (bNewConnections); } /** * Adds a new tile to the end of the tileset. */ Tile *Tileset::addTile(const QPixmap &image, const QString &source) { Tile *newTile = new Tile(takeNextTileId(), this); newTile->setImage(image); newTile->setImageSource(source); mTiles.insert(newTile->id(), newTile); if (mTileHeight < image.height()) mTileHeight = image.height(); if (mTileWidth < image.width()) mTileWidth = image.width(); return newTile; } /** * Adds the given list of tiles to this tileset. * * The tiles should already have unique tile IDs associated with them! */ void Tileset::addTiles(const QList &tiles) { for (Tile *tile : tiles) { Q_ASSERT(!mTiles.contains(tile->id())); mTiles.insert(tile->id(), tile); } updateTileSize(); } /** * Removes the given list of tiles from this tileset. * * @warning The tiles are not deleted! */ void Tileset::removeTiles(const QList &tiles) { for (Tile *tile : tiles) { Q_ASSERT(mTiles.contains(tile->id())); mTiles.remove(tile->id()); } updateTileSize(); } /** * Removes the given tile from this set and deletes it. */ void Tileset::deleteTile(int id) { delete mTiles.take(id); } /** * Sets the \a image to be used for the tile with the given \a id. * * This function makes sure the tile width and tile height properties of the * tileset reflect the maximum size. It is only expected to be used for * image collection tilesets. */ void Tileset::setTileImage(Tile *tile, const QPixmap &image, const QString &source) { Q_ASSERT(isCollection()); Q_ASSERT(mTiles.value(tile->id()) == tile); const QSize previousImageSize = tile->image().size(); const QSize newImageSize = image.size(); tile->setImage(image); tile->setImageSource(source); if (previousImageSize != newImageSize) { // Update our max. tile size if (previousImageSize.height() == mTileHeight || previousImageSize.width() == mTileWidth) { // This used to be the max image; we have to recompute updateTileSize(); } else { // Check if we have a new maximum if (mTileHeight < newImageSize.height()) mTileHeight = newImageSize.height(); if (mTileWidth < newImageSize.width()) mTileWidth = newImageSize.width(); } } } void Tileset::swap(Tileset &other) { const Properties p = properties(); setProperties(other.properties()); other.setProperties(p); std::swap(mFileName, other.mFileName); std::swap(mImageReference, other.mImageReference); std::swap(mTileWidth, other.mTileWidth); std::swap(mTileHeight, other.mTileHeight); std::swap(mTileSpacing, other.mTileSpacing); std::swap(mMargin, other.mMargin); std::swap(mTileOffset, other.mTileOffset); std::swap(mOrientation, other.mOrientation); std::swap(mGridSize, other.mGridSize); std::swap(mColumnCount, other.mColumnCount); std::swap(mExpectedColumnCount, other.mExpectedColumnCount); std::swap(mExpectedRowCount, other.mExpectedRowCount); std::swap(mTiles, other.mTiles); std::swap(mNextTileId, other.mNextTileId); std::swap(mTerrainTypes, other.mTerrainTypes); std::swap(mTerrainDistancesDirty, other.mTerrainDistancesDirty); std::swap(mLoaded, other.mLoaded); std::swap(mBackgroundColor, other.mBackgroundColor); std::swap(mFormat, other.mFormat); // Don't swap mWeakPointer, since it's a reference to this. // Update back references from tiles and terrains for (auto tile : mTiles) tile->mTileset = this; for (auto terrain : mTerrainTypes) terrain->mTileset = this; for (auto tile : other.mTiles) tile->mTileset = &other; for (auto terrain : other.mTerrainTypes) terrain->mTileset = &other; } SharedTileset Tileset::clone() const { SharedTileset c = create(mName, mTileWidth, mTileHeight, mTileSpacing, mMargin); c->setProperties(properties()); // mFileName stays empty c->mImageReference = mImageReference; c->mTileOffset = mTileOffset; c->mOrientation = mOrientation; c->mGridSize = mGridSize; c->mColumnCount = mColumnCount; c->mExpectedColumnCount = mExpectedColumnCount; c->mExpectedRowCount = mExpectedRowCount; c->mNextTileId = mNextTileId; c->mTerrainDistancesDirty = mTerrainDistancesDirty; c->mLoaded = mLoaded; c->mBackgroundColor = mBackgroundColor; c->mFormat = mFormat; QMapIterator tileIterator(mTiles); while (tileIterator.hasNext()) { tileIterator.next(); const int id = tileIterator.key(); const Tile *tile = tileIterator.value(); c->mTiles.insert(id, tile->clone(c.data())); } c->mTerrainTypes.reserve(mTerrainTypes.size()); for (Terrain *terrain : mTerrainTypes) c->mTerrainTypes.append(terrain->clone(c.data())); return c; } /** * Sets tile size to the maximum size. */ void Tileset::updateTileSize() { int maxWidth = 0; int maxHeight = 0; for (Tile *tile : mTiles) { const QSize size = tile->size(); if (maxWidth < size.width()) maxWidth = size.width(); if (maxHeight < size.height()) maxHeight = size.height(); } mTileWidth = maxWidth; mTileHeight = maxHeight; } QString Tileset::orientationToString(Tileset::Orientation orientation) { switch (orientation) { default: case Tileset::Orthogonal: return QLatin1String("orthogonal"); break; case Tileset::Isometric: return QLatin1String("isometric"); break; } } Tileset::Orientation Tileset::orientationFromString(const QString &string) { Orientation orientation = Orthogonal; if (string == QLatin1String("isometric")) orientation = Isometric; return orientation; } tiled-1.0.3/src/libtiled/tileset.h000066400000000000000000000355401315121121300170120ustar00rootroot00000000000000/* * tileset.h * Copyright 2008-2015, Thorbjørn Lindeijer * Copyright 2009, Edward Hutchins * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "imagereference.h" #include "object.h" #include #include #include #include #include #include #include #include class QImage; namespace Tiled { class Tile; class Tileset; class TilesetFormat; class Terrain; typedef QSharedPointer SharedTileset; /** * A tileset, representing a set of tiles. * * This class is meant to be used by either loading tiles from a tileset image * (using loadFromImage) or by adding/removing individual tiles (using * addTile, insertTiles and removeTiles). These two use-cases are not meant to * be mixed. */ class TILEDSHARED_EXPORT Tileset : public Object { public: /** * The orientation of the tileset determines the projection used in the * TileCollisionDock and for the terrain information overlay of the * TilesetView. */ enum Orientation { Orthogonal, Isometric, }; /** * Creates a new tileset with the given parameters. Using this function * makes sure the internal weak pointer is initialized, which enables the * sharedPointer() function. * * @param name the name of the tileset * @param tileWidth the width of the tiles in the tileset * @param tileHeight the height of the tiles in the tileset * @param tileSpacing the spacing between the tiles in the tileset image * @param margin the margin around the tiles in the tileset image */ static SharedTileset create(const QString &name, int tileWidth, int tileHeight, int tileSpacing = 0, int margin = 0) { SharedTileset tileset(new Tileset(name, tileWidth, tileHeight, tileSpacing, margin)); tileset->mWeakPointer = tileset; return tileset; } private: /** * Private constructor. Use create() instead. */ Tileset(QString name, int tileWidth, int tileHeight, int tileSpacing = 0, int margin = 0); public: ~Tileset(); const QString &name() const; void setName(const QString &name); const QString &fileName() const; void setFileName(const QString &fileName); bool isExternal() const; void setFormat(TilesetFormat *format); TilesetFormat *format() const; int tileWidth() const; int tileHeight() const; QSize tileSize() const; void setTileSize(QSize tileSize); int tileSpacing() const; void setTileSpacing(int tileSpacing); int margin() const; void setMargin(int margin); QPoint tileOffset() const; void setTileOffset(QPoint offset); Orientation orientation() const; void setOrientation(Orientation orientation); QSize gridSize() const; void setGridSize(QSize gridSize); const QMap &tiles() const; inline Tile *findTile(int id) const; Tile *tileAt(int id) const { return findTile(id); } // provided for Python Tile *findOrCreateTile(int id); int tileCount() const; int columnCount() const; int rowCount() const; void setColumnCount(int columnCount); int expectedColumnCount() const; int expectedRowCount() const; void syncExpectedColumnsAndRows(); int imageWidth() const; int imageHeight() const; QColor transparentColor() const; void setTransparentColor(const QColor &c); const QColor &backgroundColor() const; void setBackgroundColor(QColor color); void setImageReference(const ImageReference &reference); bool loadFromImage(const QImage &image, const QString &fileName); bool loadFromImage(const QString &fileName); bool loadImage(); SharedTileset findSimilarTileset(const QVector &tilesets) const; const QString &imageSource() const; void setImageSource(const QString &imageSource); bool isCollection() const; int columnCountForWidth(int width) const; int rowCountForHeight(int height) const; const QList &terrains() const; int terrainCount() const; Terrain *terrain(int index) const; Terrain *addTerrain(const QString &name, int imageTileId); void insertTerrain(int index, Terrain *terrain); Terrain *takeTerrainAt(int index); int terrainTransitionPenalty(int terrainType0, int terrainType1) const; Tile *addTile(const QPixmap &image, const QString &source = QString()); void addTiles(const QList &tiles); void removeTiles(const QList &tiles); void deleteTile(int id); void setNextTileId(int nextId); int nextTileId() const; int takeNextTileId(); void setTileImage(Tile *tile, const QPixmap &image, const QString &source = QString()); void markTerrainDistancesDirty(); SharedTileset sharedPointer() const; void setLoaded(bool loaded); bool loaded() const; bool imageLoaded() const; void swap(Tileset &other); SharedTileset clone() const; /** * Helper function that converts the tileset orientation to a string value. * Useful for map writers. * * @return The tileset orientation as a lowercase string. */ static QString orientationToString(Orientation); /** * Helper function that converts a string to a tileset orientation enumerator. * Useful for map readers. * * @return The tileset orientation matching the given string, or * Tileset::Orthogonal if the string is unrecognized. */ static Orientation orientationFromString(const QString &); private: void updateTileSize(); void recalculateTerrainDistances(); QString mName; QString mFileName; ImageReference mImageReference; int mTileWidth; int mTileHeight; int mTileSpacing; int mMargin; QPoint mTileOffset; Orientation mOrientation; QSize mGridSize; int mColumnCount; int mExpectedColumnCount; int mExpectedRowCount; QMap mTiles; int mNextTileId; QList mTerrainTypes; bool mTerrainDistancesDirty; bool mLoaded; QColor mBackgroundColor; QPointer mFormat; QWeakPointer mWeakPointer; }; /** * Returns the name of this tileset. */ inline const QString &Tileset::name() const { return mName; } /** * Sets the name of this tileset. */ inline void Tileset::setName(const QString &name) { mName = name; } /** * Returns the file name of this tileset. When the tileset isn't an * external tileset, the file name is empty. */ inline const QString &Tileset::fileName() const { return mFileName; } /** * Sets the filename of this tileset. */ inline void Tileset::setFileName(const QString &fileName) { mFileName = fileName; } /** * Returns whether this tileset is external. */ inline bool Tileset::isExternal() const { return !mFileName.isEmpty(); } /** * Returns the maximum width of the tiles in this tileset. */ inline int Tileset::tileWidth() const { return mTileWidth; } /** * Returns the maximum height of the tiles in this tileset. */ inline int Tileset::tileHeight() const { return mTileHeight; } /** * Returns the maximum size of the tiles in this tileset. */ inline QSize Tileset::tileSize() const { return QSize(mTileWidth, mTileHeight); } /** * Returns the spacing between the tiles in the tileset image. */ inline int Tileset::tileSpacing() const { return mTileSpacing; } /** * Returns the margin around the tiles in the tileset image. */ inline int Tileset::margin() const { return mMargin; } /** * Returns the offset that is applied when drawing the tiles in this * tileset. */ inline QPoint Tileset::tileOffset() const { return mTileOffset; } /** * @see tileOffset */ inline void Tileset::setTileOffset(QPoint offset) { mTileOffset = offset; } /** * Returns the orientation of the tiles in this tileset. */ inline Tileset::Orientation Tileset::orientation() const { return mOrientation; } /** * @see orientation */ inline void Tileset::setOrientation(Orientation orientation) { mOrientation = orientation; } /** * Returns the grid size that is used when the tileset has Isometric * orientation. */ inline QSize Tileset::gridSize() const { return mGridSize; } /** * @see gridSize */ inline void Tileset::setGridSize(QSize gridSize) { mGridSize = gridSize; } /** * Returns a const reference to the tiles in this tileset. */ inline const QMap &Tileset::tiles() const { return mTiles; } /** * Returns the tile with the given tile ID. The tile IDs are local to this * tileset. */ inline Tile *Tileset::findTile(int id) const { return mTiles.value(id); } /** * Returns the number of tiles in this tileset. * * Note that the tiles are not necessarily consecutive. */ inline int Tileset::tileCount() const { return mTiles.size(); } /** * Returns the number of tile columns in the tileset image. */ inline int Tileset::columnCount() const { return mColumnCount; } /** * Sets the column count to use when displaying this tileset. For tileset image * based tilesets, this reflects the number of tile columns in the image. */ inline void Tileset::setColumnCount(int columnCount) { mColumnCount = columnCount; } /** * Returns the number of tile columns expected to be in the tileset image. This * may differ from the actual amount of columns encountered when loading the * image, and can be used for automatically adjusting tile indexes. */ inline int Tileset::expectedColumnCount() const { return mExpectedColumnCount; } /** * Returns the number of tile rows expected to be in the tileset image. This * may differ from the actual amount of rows encountered when loading the * image, and is checked when automatically adjusting tile indexes. */ inline int Tileset::expectedRowCount() const { return mExpectedRowCount; } /** * Sets the expected column and row count to the actual column count. Usually * called after checking with the user whether he wants the map to be adjusted * to a change to the tileset image size. */ inline void Tileset::syncExpectedColumnsAndRows() { mExpectedColumnCount = mColumnCount; mExpectedRowCount = rowCount(); } /** * Returns the width of the tileset image. */ inline int Tileset::imageWidth() const { return mImageReference.size.width(); } /** * Returns the height of the tileset image. */ inline int Tileset::imageHeight() const { return mImageReference.size.height(); } /** * Returns the transparent color, or an invalid color if no transparent * color is used. */ inline QColor Tileset::transparentColor() const { return mImageReference.transparentColor; } /** * Returns the background color of this tileset. */ inline const QColor &Tileset::backgroundColor() const { return mBackgroundColor; } /** * Sets the background color of this tileset. */ inline void Tileset::setBackgroundColor(QColor color) { mBackgroundColor = color; } /** * Convenience override that loads the image using the QImage constructor. */ inline bool Tileset::loadFromImage(const QString &fileName) { return loadFromImage(QImage(fileName), fileName); } /** * Returns the file name of the external image that contains the tiles in * this tileset. Is an empty string when this tileset doesn't have a * tileset image. */ inline const QString &Tileset::imageSource() const { return mImageReference.source; } /** * Returns whether this tileset is a collection of images. In this case, the * tileset itself has no image source. */ inline bool Tileset::isCollection() const { return imageSource().isEmpty(); } /** * Returns a const reference to the list of terrains in this tileset. */ inline const QList &Tileset::terrains() const { return mTerrainTypes; } /** * Returns the number of terrain types in this tileset. */ inline int Tileset::terrainCount() const { return mTerrainTypes.size(); } /** * Returns the terrain type at the given \a index. */ inline Terrain *Tileset::terrain(int index) const { return index >= 0 ? mTerrainTypes[index] : nullptr; } /** * Sets the next id to be used for tiles in this tileset. */ inline void Tileset::setNextTileId(int nextId) { Q_ASSERT(nextId > 0); mNextTileId = nextId; } /** * Returns the next tile id for this tileset. */ inline int Tileset::nextTileId() const { return mNextTileId; } /** * Returns the next tile id for this tileset and allocates a new one. */ inline int Tileset::takeNextTileId() { return mNextTileId++; } /** * Used by the Tile class when its terrain information changes. */ inline void Tileset::markTerrainDistancesDirty() { mTerrainDistancesDirty = true; } inline SharedTileset Tileset::sharedPointer() const { return SharedTileset(mWeakPointer); } /** * Sets whether this tileset was loaded successfully. This variable is true by * default, but it can be set to false to indicate a failed attempt at loading * an external tileset. */ inline void Tileset::setLoaded(bool loaded) { mLoaded = loaded; } /** * Returns whether this tileset was loaded succesfully. Only valid for * external tilesets (fileName() != empty). */ inline bool Tileset::loaded() const { return mLoaded; } /** * Returns whether the image used by this tileset was loaded succesfully. Only * valid for tilesets based on a single image (imageSource() != empty). */ inline bool Tileset::imageLoaded() const { return mImageReference.loaded; } } // namespace Tiled Q_DECLARE_METATYPE(Tiled::SharedTileset) tiled-1.0.3/src/libtiled/tilesetformat.cpp000066400000000000000000000047531315121121300205600ustar00rootroot00000000000000/* * tilesetformat.cpp * Copyright 2015, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "tilesetformat.h" #include "mapreader.h" namespace Tiled { SharedTileset readTileset(const QString &fileName, QString *error) { // Try the first registered tileset format that claims to support the file if (TilesetFormat *format = findSupportingFormat(fileName)) { SharedTileset tileset = format->read(fileName); if (error) { if (!tileset) *error = format->errorString(); else *error = QString(); } if (tileset) tileset->setFormat(format); return tileset; } // Fall back to default reader (TSX format) MapReader reader; SharedTileset tileset = reader.readTileset(fileName); if (error) { if (!tileset) *error = reader.errorString(); else *error = QString(); } return tileset; } TilesetFormat *findSupportingFormat(const QString &fileName) { for (TilesetFormat *format : PluginManager::objects()) if (format->supportsFile(fileName)) return format; return nullptr; } } // namespace Tiled tiled-1.0.3/src/libtiled/tilesetformat.h000066400000000000000000000060511315121121300202160ustar00rootroot00000000000000/* * tilesetformat.h * Copyright 2015, Thorbjørn Lindeijer * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "mapformat.h" #include "tileset.h" namespace Tiled { /** * An interface to be implemented for adding support for a tileset format to * Tiled. It can implement support for either loading or saving to a certain * tileset format, or both. */ class TILEDSHARED_EXPORT TilesetFormat : public FileFormat { Q_OBJECT public: explicit TilesetFormat(QObject *parent = nullptr) : FileFormat(parent) {} /** * Reads the tileset and returns a new Tileset instance, or a null shared * pointer if reading failed. */ virtual SharedTileset read(const QString &fileName) = 0; /** * Writes the given \a tileset based on the suggested \a fileName. * * This function may write to a different file name or may even write to * multiple files. The actual files that will be written to can be * determined by calling outputFiles(). * * @return true on success, false when an error * occurred. The error can be retrieved by errorString(). */ virtual bool write(const Tileset &tileset, const QString &fileName) = 0; }; /** * Attempt to read the given tileset using any of the tileset formats added * to the plugin manager, falling back to the TSX format if none are capable. */ TILEDSHARED_EXPORT SharedTileset readTileset(const QString &fileName, QString *error = nullptr); /** * Attempts to find a tileset format supporting the given file. */ TILEDSHARED_EXPORT TilesetFormat *findSupportingFormat(const QString &fileName); } // namespace Tiled Q_DECLARE_INTERFACE(Tiled::TilesetFormat, "org.mapeditor.TilesetFormat") tiled-1.0.3/src/libtiled/tilesetmanager.cpp000066400000000000000000000207741315121121300207030ustar00rootroot00000000000000/* * tilesetmanager.cpp * Copyright 2008-2014, Thorbjørn Lindeijer * Copyright 2009, Edward Hutchins * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "tilesetmanager.h" #include "filesystemwatcher.h" #include "tileanimationdriver.h" #include "tile.h" #include "tilesetformat.h" #include namespace Tiled { TilesetManager *TilesetManager::mInstance; /** * Constructor. Only used by the tileset manager itself. */ TilesetManager::TilesetManager(): mWatcher(new FileSystemWatcher(this)), mAnimationDriver(new TileAnimationDriver(this)), mReloadTilesetsOnChange(false) { connect(mWatcher, SIGNAL(fileChanged(QString)), this, SLOT(fileChanged(QString))); mChangedFilesTimer.setInterval(500); mChangedFilesTimer.setSingleShot(true); connect(&mChangedFilesTimer, &QTimer::timeout, this, &TilesetManager::fileChangedTimeout); connect(mAnimationDriver, &TileAnimationDriver::update, this, &TilesetManager::advanceTileAnimations); } TilesetManager::~TilesetManager() { // Since all MapDocuments should be deleted first, we assert that there are // no remaining tileset references. Q_ASSERT(mTilesets.isEmpty()); } /** * Requests the tileset manager. When the manager doesn't exist yet, it * will be created. */ TilesetManager *TilesetManager::instance() { if (!mInstance) mInstance = new TilesetManager; return mInstance; } /** * Deletes the tileset manager instance, when it exists. */ void TilesetManager::deleteInstance() { delete mInstance; mInstance = nullptr; } /** * Loads the tileset with the given \a fileName. If the tileset is already * loaded, returns that instance. * * When an error occurs during loading it is assigned to the optional \a error * parameter. */ SharedTileset TilesetManager::loadTileset(const QString &fileName, QString *error) { SharedTileset tileset = findTileset(fileName); if (!tileset) tileset = readTileset(fileName, error); return tileset; } /** * Searches for a tileset matching the given file name. * @return a tileset matching the given file name, or 0 if none exists */ SharedTileset TilesetManager::findTileset(const QString &fileName) const { QMapIterator it(mTilesets); while (it.hasNext()) { const SharedTileset &tileset = it.next().key(); if (tileset->fileName() == fileName) return tileset; } return SharedTileset(); } /** * Adds a tileset reference. This will make sure the tileset is watched for * changes and can be found using findTileset(). */ void TilesetManager::addReference(const SharedTileset &tileset) { if (mTilesets.contains(tileset)) { mTilesets[tileset]++; } else { mTilesets.insert(tileset, 1); if (!tileset->imageSource().isEmpty()) mWatcher->addPath(tileset->imageSource()); } } /** * Removes a tileset reference. When the last reference has been removed, * the tileset is no longer watched for changes. */ void TilesetManager::removeReference(const SharedTileset &tileset) { Q_ASSERT(mTilesets.value(tileset) > 0); mTilesets[tileset]--; if (mTilesets.value(tileset) == 0) { mTilesets.remove(tileset); if (!tileset->imageSource().isEmpty()) mWatcher->removePath(tileset->imageSource()); } } /** * Convenience method to add references to multiple tilesets. * @see addReference */ void TilesetManager::addReferences(const QVector &tilesets) { for (const SharedTileset &tileset : tilesets) addReference(tileset); } /** * Convenience method to remove references from multiple tilesets. * @see removeReference */ void TilesetManager::removeReferences(const QVector &tilesets) { for (const SharedTileset &tileset : tilesets) removeReference(tileset); } /** * Forces a tileset to reload. */ void TilesetManager::reloadImages(const SharedTileset &tileset) { if (!mTilesets.contains(tileset)) return; if (tileset->isCollection()) { for (Tile *tile : tileset->tiles()) tile->setImage(QPixmap(tile->imageSource())); emit tilesetImagesChanged(tileset.data()); } else { if (tileset->loadImage()) emit tilesetImagesChanged(tileset.data()); } } /** * Sets whether tilesets are automatically reloaded when their tileset * image changes. */ void TilesetManager::setReloadTilesetsOnChange(bool enabled) { mReloadTilesetsOnChange = enabled; // TODO: Clear the file system watcher when disabled } /** * Sets whether tile animations are running. */ void TilesetManager::setAnimateTiles(bool enabled) { // TODO: Avoid running the driver when there are no animated tiles if (enabled) mAnimationDriver->start(); else mAnimationDriver->stop(); } bool TilesetManager::animateTiles() const { return mAnimationDriver->state() == QAbstractAnimation::Running; } void TilesetManager::tilesetImageSourceChanged(const Tileset &tileset, const QString &oldImageSource) { Q_ASSERT(mTilesets.contains(tileset.sharedPointer())); Q_ASSERT(!oldImageSource.isEmpty()); Q_ASSERT(!tileset.imageSource().isEmpty()); mWatcher->removePath(oldImageSource); mWatcher->addPath(tileset.imageSource()); } void TilesetManager::fileChanged(const QString &path) { if (!mReloadTilesetsOnChange) return; /* * Use a one-shot timer since GIMP (for example) seems to generate many * file changes during a save, and some of the intermediate attempts to * reload the tileset images actually fail (at least for .png files). */ mChangedFiles.insert(path); mChangedFilesTimer.start(); } void TilesetManager::fileChangedTimeout() { QMapIterator it(mTilesets); while (it.hasNext()) { const SharedTileset &tileset = it.next().key(); QString fileName = tileset->imageSource(); if (mChangedFiles.contains(fileName)) if (tileset->loadFromImage(fileName)) emit tilesetImagesChanged(tileset.data()); } mChangedFiles.clear(); } /** * Resets all tile animations. Used to keep animations synchronized when they * are edited. */ void TilesetManager::resetTileAnimations() { // TODO: This could be more optimal by keeping track of the list of // actually animated tiles QMapIterator it(mTilesets); while (it.hasNext()) { const SharedTileset &tileset = it.next().key(); bool imageChanged = false; for (Tile *tile : tileset->tiles()) imageChanged |= tile->resetAnimation(); if (imageChanged) emit repaintTileset(tileset.data()); } } void TilesetManager::advanceTileAnimations(int ms) { // TODO: This could be more optimal by keeping track of the list of // actually animated tiles QMapIterator it(mTilesets); while (it.hasNext()) { const SharedTileset &tileset = it.next().key(); bool imageChanged = false; for (Tile *tile : tileset->tiles()) imageChanged |= tile->advanceAnimation(ms); if (imageChanged) emit repaintTileset(tileset.data()); } } } // namespace Tiled tiled-1.0.3/src/libtiled/tilesetmanager.h000066400000000000000000000073351315121121300203460ustar00rootroot00000000000000/* * tilesetmanager.h * Copyright 2008-2014, Thorbjørn Lindeijer * Copyright 2009, Edward Hutchins * * This file is part of libtiled. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "tileset.h" #include #include #include #include #include #include namespace Tiled { class FileSystemWatcher; class TileAnimationDriver; /** * The tileset manager keeps track of all tilesets used by loaded maps. It also * watches the tileset images for changes and will attempt to reload them when * they change. */ class TILEDSHARED_EXPORT TilesetManager : public QObject { Q_OBJECT public: static TilesetManager *instance(); static void deleteInstance(); SharedTileset loadTileset(const QString &fileName, QString *error = nullptr); SharedTileset findTileset(const QString &fileName) const; void addReference(const SharedTileset &tileset); void removeReference(const SharedTileset &tileset); void addReferences(const QVector &tilesets); void removeReferences(const QVector &tilesets); void reloadImages(const SharedTileset &tileset); void setReloadTilesetsOnChange(bool enabled); bool reloadTilesetsOnChange() const; void setAnimateTiles(bool enabled); bool animateTiles() const; void resetTileAnimations(); void tilesetImageSourceChanged(const Tileset &tileset, const QString &oldImageSource); signals: /** * Emitted when a tileset's images have changed and views need updating. */ void tilesetImagesChanged(Tileset *tileset); /** * Emitted when any images of the tiles in the given \a tileset have * changed as a result of playing tile animations. */ void repaintTileset(Tileset *tileset); private slots: void fileChanged(const QString &path); void fileChangedTimeout(); void advanceTileAnimations(int ms); private: Q_DISABLE_COPY(TilesetManager) TilesetManager(); ~TilesetManager(); static TilesetManager *mInstance; /** * Stores the tilesets and maps them to the number of references. */ QMap mTilesets; FileSystemWatcher *mWatcher; TileAnimationDriver *mAnimationDriver; QSet mChangedFiles; QTimer mChangedFilesTimer; bool mReloadTilesetsOnChange; }; inline bool TilesetManager::reloadTilesetsOnChange() const { return mReloadTilesetsOnChange; } } // namespace Tiled tiled-1.0.3/src/libtiled/varianttomapconverter.cpp000066400000000000000000000617421315121121300223340ustar00rootroot00000000000000/* * varianttomapconverter.cpp * Copyright 2011, Porfírio José Pereira Ribeiro * Copyright 2011-2015, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "varianttomapconverter.h" #include "grouplayer.h" #include "imagelayer.h" #include "map.h" #include "objectgroup.h" #include "properties.h" #include "terrain.h" #include "tile.h" #include "tilelayer.h" #include "tileset.h" #include "tilesetmanager.h" #include namespace Tiled { static QString resolvePath(const QDir &dir, const QVariant &variant) { QString fileName = variant.toString(); if (!fileName.isEmpty() && QDir::isRelativePath(fileName)) return QDir::cleanPath(dir.absoluteFilePath(fileName)); return fileName; } Map *VariantToMapConverter::toMap(const QVariant &variant, const QDir &mapDir) { mGidMapper.clear(); mMapDir = mapDir; const QVariantMap variantMap = variant.toMap(); const QString orientationString = variantMap[QLatin1String("orientation")].toString(); Map::Orientation orientation = orientationFromString(orientationString); if (orientation == Map::Unknown) { mError = tr("Unsupported map orientation: \"%1\"") .arg(orientationString); return nullptr; } const QString staggerAxisString = variantMap[QLatin1String("staggeraxis")].toString(); Map::StaggerAxis staggerAxis = staggerAxisFromString(staggerAxisString); const QString staggerIndexString = variantMap[QLatin1String("staggerindex")].toString(); Map::StaggerIndex staggerIndex = staggerIndexFromString(staggerIndexString); const QString renderOrderString = variantMap[QLatin1String("renderorder")].toString(); Map::RenderOrder renderOrder = renderOrderFromString(renderOrderString); const int nextObjectId = variantMap[QLatin1String("nextobjectid")].toInt(); QScopedPointer map(new Map(orientation, variantMap[QLatin1String("width")].toInt(), variantMap[QLatin1String("height")].toInt(), variantMap[QLatin1String("tilewidth")].toInt(), variantMap[QLatin1String("tileheight")].toInt())); map->setHexSideLength(variantMap[QLatin1String("hexsidelength")].toInt()); map->setStaggerAxis(staggerAxis); map->setStaggerIndex(staggerIndex); map->setRenderOrder(renderOrder); if (nextObjectId) map->setNextObjectId(nextObjectId); mMap = map.data(); map->setProperties(extractProperties(variantMap)); const QString bgColor = variantMap[QLatin1String("backgroundcolor")].toString(); if (!bgColor.isEmpty() && QColor::isValidColor(bgColor)) map->setBackgroundColor(QColor(bgColor)); const auto tilesetVariants = variantMap[QLatin1String("tilesets")].toList(); for (const QVariant &tilesetVariant : tilesetVariants) { SharedTileset tileset = toTileset(tilesetVariant); if (!tileset) return nullptr; map->addTileset(tileset); } const auto layerVariants = variantMap[QLatin1String("layers")].toList(); for (const QVariant &layerVariant : layerVariants) { Layer *layer = toLayer(layerVariant); if (!layer) return nullptr; map->addLayer(layer); } // Try to load the tileset images auto tilesets = map->tilesets(); for (SharedTileset &tileset : tilesets) { if (!tileset->imageSource().isEmpty() && tileset->fileName().isEmpty()) tileset->loadImage(); } return map.take(); } SharedTileset VariantToMapConverter::toTileset(const QVariant &variant, const QDir &directory) { mMapDir = directory; mReadingExternalTileset = true; SharedTileset tileset = toTileset(variant); if (tileset && !tileset->imageSource().isEmpty()) tileset->loadImage(); mReadingExternalTileset = false; return tileset; } Properties VariantToMapConverter::toProperties(const QVariant &propertiesVariant, const QVariant &propertyTypesVariant) const { const QVariantMap propertiesMap = propertiesVariant.toMap(); const QVariantMap propertyTypesMap = propertyTypesVariant.toMap(); Properties properties; QVariantMap::const_iterator it = propertiesMap.constBegin(); QVariantMap::const_iterator it_end = propertiesMap.constEnd(); for (; it != it_end; ++it) { int type = nameToType(propertyTypesMap.value(it.key()).toString()); if (type == QVariant::Invalid) type = QVariant::String; QVariant value = it.value(); if (type == filePathTypeId()) value = resolvePath(mMapDir, value); value = fromExportValue(value, type); properties[it.key()] = value; } return properties; } SharedTileset VariantToMapConverter::toTileset(const QVariant &variant) { const QVariantMap variantMap = variant.toMap(); const int firstGid = variantMap[QLatin1String("firstgid")].toInt(); // Handle external tilesets const QVariant sourceVariant = variantMap[QLatin1String("source")]; if (!sourceVariant.isNull()) { QString source = resolvePath(mMapDir, sourceVariant); QString error; SharedTileset tileset = TilesetManager::instance()->loadTileset(source, &error); if (!tileset) { // Insert a placeholder to allow the map to load tileset = Tileset::create(QFileInfo(source).completeBaseName(), 32, 32); tileset->setFileName(source); tileset->setLoaded(false); } else { mGidMapper.insert(firstGid, tileset.data()); } return tileset; } const QString name = variantMap[QLatin1String("name")].toString(); const int tileWidth = variantMap[QLatin1String("tilewidth")].toInt(); const int tileHeight = variantMap[QLatin1String("tileheight")].toInt(); const int spacing = variantMap[QLatin1String("spacing")].toInt(); const int margin = variantMap[QLatin1String("margin")].toInt(); const QVariantMap tileOffset = variantMap[QLatin1String("tileoffset")].toMap(); const QVariantMap grid = variantMap[QLatin1String("grid")].toMap(); const int tileOffsetX = tileOffset[QLatin1String("x")].toInt(); const int tileOffsetY = tileOffset[QLatin1String("y")].toInt(); const int columns = variantMap[QLatin1String("columns")].toInt(); const QString bgColor = variantMap[QLatin1String("backgroundcolor")].toString(); if (tileWidth <= 0 || tileHeight <= 0 || (firstGid == 0 && !mReadingExternalTileset)) { mError = tr("Invalid tileset parameters for tileset '%1'").arg(name); return SharedTileset(); } SharedTileset tileset(Tileset::create(name, tileWidth, tileHeight, spacing, margin)); tileset->setTileOffset(QPoint(tileOffsetX, tileOffsetY)); tileset->setColumnCount(columns); if (!grid.isEmpty()) { const QString orientation = grid[QLatin1String("orientation")].toString(); const QSize gridSize(grid[QLatin1String("width")].toInt(), grid[QLatin1String("height")].toInt()); tileset->setOrientation(Tileset::orientationFromString(orientation)); if (!gridSize.isEmpty()) tileset->setGridSize(gridSize); } if (!bgColor.isEmpty() && QColor::isValidColor(bgColor)) tileset->setBackgroundColor(QColor(bgColor)); QVariant imageVariant = variantMap[QLatin1String("image")]; if (!imageVariant.isNull()) { const int imageWidth = variantMap[QLatin1String("imagewidth")].toInt(); const int imageHeight = variantMap[QLatin1String("imageheight")].toInt(); ImageReference imageRef; imageRef.source = resolvePath(mMapDir, imageVariant); imageRef.size = QSize(imageWidth, imageHeight); tileset->setImageReference(imageRef); } const QString trans = variantMap[QLatin1String("transparentcolor")].toString(); if (!trans.isEmpty() && QColor::isValidColor(trans)) tileset->setTransparentColor(QColor(trans)); tileset->setProperties(extractProperties(variantMap)); // Read terrains QVariantList terrainsVariantList = variantMap[QLatin1String("terrains")].toList(); for (int i = 0; i < terrainsVariantList.count(); ++i) { QVariantMap terrainMap = terrainsVariantList[i].toMap(); Terrain *terrain = tileset->addTerrain(terrainMap[QLatin1String("name")].toString(), terrainMap[QLatin1String("tile")].toInt()); terrain->setProperties(extractProperties(terrainMap)); } // Read tiles (everything except their properties) const QVariantMap tilesVariantMap = variantMap[QLatin1String("tiles")].toMap(); QVariantMap::const_iterator it = tilesVariantMap.constBegin(); for (; it != tilesVariantMap.end(); ++it) { bool ok; const int tileId = it.key().toInt(); if (tileId < 0) { mError = tr("Invalid (negative) tile id: %1").arg(tileId); return SharedTileset(); } Tile *tile = tileset->findOrCreateTile(tileId); const QVariantMap tileVar = it.value().toMap(); tile->setType(tileVar[QLatin1String("type")].toString()); QList terrains = tileVar[QLatin1String("terrain")].toList(); if (terrains.count() == 4) { for (int i = 0; i < 4; ++i) { int terrainId = terrains.at(i).toInt(&ok); if (ok && terrainId >= 0 && terrainId < tileset->terrainCount()) tile->setCornerTerrainId(i, terrainId); } } float probability = tileVar[QLatin1String("probability")].toFloat(&ok); if (ok) tile->setProbability(probability); imageVariant = tileVar[QLatin1String("image")]; if (!imageVariant.isNull()) { QString imagePath = resolvePath(mMapDir, imageVariant); tileset->setTileImage(tile, QPixmap(imagePath), imagePath); } QVariantMap objectGroupVariant = tileVar[QLatin1String("objectgroup")].toMap(); if (!objectGroupVariant.isEmpty()) { ObjectGroup *objectGroup = toObjectGroup(objectGroupVariant); if (objectGroup) objectGroup->setProperties(extractProperties(objectGroupVariant)); tile->setObjectGroup(objectGroup); } QVariantList frameList = tileVar[QLatin1String("animation")].toList(); if (!frameList.isEmpty()) { QVector frames(frameList.size()); for (int i = frameList.size() - 1; i >= 0; --i) { const QVariantMap frameVariantMap = frameList[i].toMap(); Frame &frame = frames[i]; frame.tileId = frameVariantMap[QLatin1String("tileid")].toInt(); frame.duration = frameVariantMap[QLatin1String("duration")].toInt(); } tile->setFrames(frames); } } // Read tile properties QVariantMap propertiesVariantMap = variantMap[QLatin1String("tileproperties")].toMap(); QVariantMap propertyTypesVariantMap = variantMap[QLatin1String("tilepropertytypes")].toMap(); for (it = propertiesVariantMap.constBegin(); it != propertiesVariantMap.constEnd(); ++it) { const int tileId = it.key().toInt(); const QVariant propertiesVar = it.value(); const QVariant propertyTypesVar = propertyTypesVariantMap.value(it.key()); const Properties properties = toProperties(propertiesVar, propertyTypesVar); tileset->findOrCreateTile(tileId)->setProperties(properties); } if (!mReadingExternalTileset) mGidMapper.insert(firstGid, tileset.data()); return tileset; } Layer *VariantToMapConverter::toLayer(const QVariant &variant) { const QVariantMap variantMap = variant.toMap(); Layer *layer = nullptr; if (variantMap[QLatin1String("type")] == QLatin1String("tilelayer")) layer = toTileLayer(variantMap); else if (variantMap[QLatin1String("type")] == QLatin1String("objectgroup")) layer = toObjectGroup(variantMap); else if (variantMap[QLatin1String("type")] == QLatin1String("imagelayer")) layer = toImageLayer(variantMap); else if (variantMap[QLatin1String("type")] == QLatin1String("group")) layer = toGroupLayer(variantMap); if (layer) { layer->setProperties(extractProperties(variantMap)); const QPointF offset(variantMap[QLatin1String("offsetx")].toDouble(), variantMap[QLatin1String("offsety")].toDouble()); layer->setOffset(offset); } return layer; } TileLayer *VariantToMapConverter::toTileLayer(const QVariantMap &variantMap) { const QString name = variantMap[QLatin1String("name")].toString(); const int width = variantMap[QLatin1String("width")].toInt(); const int height = variantMap[QLatin1String("height")].toInt(); const QVariant dataVariant = variantMap[QLatin1String("data")]; typedef QScopedPointer TileLayerPtr; TileLayerPtr tileLayer(new TileLayer(name, variantMap[QLatin1String("x")].toInt(), variantMap[QLatin1String("y")].toInt(), width, height)); const qreal opacity = variantMap[QLatin1String("opacity")].toReal(); const bool visible = variantMap[QLatin1String("visible")].toBool(); tileLayer->setOpacity(opacity); tileLayer->setVisible(visible); const QString encoding = variantMap[QLatin1String("encoding")].toString(); const QString compression = variantMap[QLatin1String("compression")].toString(); Map::LayerDataFormat layerDataFormat; if (encoding.isEmpty() || encoding == QLatin1String("csv")) { layerDataFormat = Map::CSV; } else if (encoding == QLatin1String("base64")) { if (compression.isEmpty()) { layerDataFormat = Map::Base64; } else if (compression == QLatin1String("gzip")) { layerDataFormat = Map::Base64Gzip; } else if (compression == QLatin1String("zlib")) { layerDataFormat = Map::Base64Zlib; } else { mError = tr("Compression method '%1' not supported").arg(compression); return nullptr; } } else { mError = tr("Unknown encoding: %1").arg(encoding); return nullptr; } mMap->setLayerDataFormat(layerDataFormat); switch (layerDataFormat) { case Map::XML: case Map::CSV: { const QVariantList dataVariantList = dataVariant.toList(); if (dataVariantList.size() != width * height) { mError = tr("Corrupt layer data for layer '%1'").arg(name); return nullptr; } int x = 0; int y = 0; bool ok; for (const QVariant &gidVariant : dataVariantList) { const unsigned gid = gidVariant.toUInt(&ok); if (!ok) { mError = tr("Unable to parse tile at (%1,%2) on layer '%3'") .arg(x).arg(y).arg(tileLayer->name()); return nullptr; } const Cell cell = mGidMapper.gidToCell(gid, ok); tileLayer->setCell(x, y, cell); x++; if (x >= tileLayer->width()) { x = 0; y++; } } break; } case Map::Base64: case Map::Base64Zlib: case Map::Base64Gzip: { const QByteArray data = dataVariant.toByteArray(); GidMapper::DecodeError error = mGidMapper.decodeLayerData(*tileLayer, data, layerDataFormat); switch (error) { case GidMapper::CorruptLayerData: mError = tr("Corrupt layer data for layer '%1'").arg(name); return nullptr; case GidMapper::TileButNoTilesets: mError = tr("Tile used but no tilesets specified"); return nullptr; case GidMapper::InvalidTile: mError = tr("Invalid tile: %1").arg(mGidMapper.invalidTile()); return nullptr; case GidMapper::NoError: break; } break; } } return tileLayer.take(); } ObjectGroup *VariantToMapConverter::toObjectGroup(const QVariantMap &variantMap) { typedef QScopedPointer ObjectGroupPtr; ObjectGroupPtr objectGroup(new ObjectGroup(variantMap[QLatin1String("name")].toString(), variantMap[QLatin1String("x")].toInt(), variantMap[QLatin1String("y")].toInt())); const qreal opacity = variantMap[QLatin1String("opacity")].toReal(); const bool visible = variantMap[QLatin1String("visible")].toBool(); objectGroup->setOpacity(opacity); objectGroup->setVisible(visible); objectGroup->setColor(variantMap.value(QLatin1String("color")).value()); const QString drawOrderString = variantMap.value(QLatin1String("draworder")).toString(); if (!drawOrderString.isEmpty()) { objectGroup->setDrawOrder(drawOrderFromString(drawOrderString)); if (objectGroup->drawOrder() == ObjectGroup::UnknownOrder) { mError = tr("Invalid draw order: %1").arg(drawOrderString); return nullptr; } } const auto objectVariants = variantMap[QLatin1String("objects")].toList(); for (const QVariant &objectVariant : objectVariants) { const QVariantMap objectVariantMap = objectVariant.toMap(); const QString name = objectVariantMap[QLatin1String("name")].toString(); const QString type = objectVariantMap[QLatin1String("type")].toString(); const int id = objectVariantMap[QLatin1String("id")].toInt(); const int gid = objectVariantMap[QLatin1String("gid")].toInt(); const qreal x = objectVariantMap[QLatin1String("x")].toReal(); const qreal y = objectVariantMap[QLatin1String("y")].toReal(); const qreal width = objectVariantMap[QLatin1String("width")].toReal(); const qreal height = objectVariantMap[QLatin1String("height")].toReal(); const qreal rotation = objectVariantMap[QLatin1String("rotation")].toReal(); const QPointF pos(x, y); const QSizeF size(width, height); MapObject *object = new MapObject(name, type, pos, size); object->setId(id); object->setRotation(rotation); if (gid) { bool ok; object->setCell(mGidMapper.gidToCell(gid, ok)); if (const Tile *tile = object->cell().tile()) { const QSizeF &tileSize = tile->size(); if (width == 0) object->setWidth(tileSize.width()); if (height == 0) object->setHeight(tileSize.height()); } } if (objectVariantMap.contains(QLatin1String("visible"))) object->setVisible(objectVariantMap[QLatin1String("visible")].toBool()); object->setProperties(extractProperties(objectVariantMap)); objectGroup->addObject(object); const QVariant polylineVariant = objectVariantMap[QLatin1String("polyline")]; const QVariant polygonVariant = objectVariantMap[QLatin1String("polygon")]; const QVariant textVariant = objectVariantMap[QLatin1String("text")]; if (polygonVariant.isValid()) { object->setShape(MapObject::Polygon); object->setPolygon(toPolygon(polygonVariant)); } if (polylineVariant.isValid()) { object->setShape(MapObject::Polyline); object->setPolygon(toPolygon(polylineVariant)); } if (objectVariantMap.contains(QLatin1String("ellipse"))) object->setShape(MapObject::Ellipse); if (textVariant.isValid()) { object->setTextData(toTextData(textVariant.toMap())); object->setShape(MapObject::Text); } } return objectGroup.take(); } ImageLayer *VariantToMapConverter::toImageLayer(const QVariantMap &variantMap) { typedef QScopedPointer ImageLayerPtr; ImageLayerPtr imageLayer(new ImageLayer(variantMap[QLatin1String("name")].toString(), variantMap[QLatin1String("x")].toInt(), variantMap[QLatin1String("y")].toInt())); const qreal opacity = variantMap[QLatin1String("opacity")].toReal(); const bool visible = variantMap[QLatin1String("visible")].toBool(); imageLayer->setOpacity(opacity); imageLayer->setVisible(visible); const QString trans = variantMap[QLatin1String("transparentcolor")].toString(); if (!trans.isEmpty() && QColor::isValidColor(trans)) imageLayer->setTransparentColor(QColor(trans)); QVariant imageVariant = variantMap[QLatin1String("image")].toString(); if (!imageVariant.isNull()) { QString imagePath = resolvePath(mMapDir, imageVariant); imageLayer->loadFromImage(imagePath); } return imageLayer.take(); } GroupLayer *VariantToMapConverter::toGroupLayer(const QVariantMap &variantMap) { const QString name = variantMap[QLatin1String("name")].toString(); const int x = variantMap[QLatin1String("x")].toInt(); const int y = variantMap[QLatin1String("y")].toInt(); const qreal opacity = variantMap[QLatin1String("opacity")].toReal(); const bool visible = variantMap[QLatin1String("visible")].toBool(); QScopedPointer groupLayer(new GroupLayer(name, x, y)); groupLayer->setOpacity(opacity); groupLayer->setVisible(visible); const auto layerVariants = variantMap[QLatin1String("layers")].toList(); for (const QVariant &layerVariant : layerVariants) { Layer *layer = toLayer(layerVariant); if (!layer) return nullptr; groupLayer->addLayer(layer); } return groupLayer.take(); } QPolygonF VariantToMapConverter::toPolygon(const QVariant &variant) const { QPolygonF polygon; const auto pointVariants = variant.toList(); for (const QVariant &pointVariant : pointVariants) { const QVariantMap pointVariantMap = pointVariant.toMap(); const qreal pointX = pointVariantMap[QLatin1String("x")].toReal(); const qreal pointY = pointVariantMap[QLatin1String("y")].toReal(); polygon.append(QPointF(pointX, pointY)); } return polygon; } TextData VariantToMapConverter::toTextData(const QVariantMap &variant) const { TextData textData; const QString family = variant[QLatin1String("fontfamily")].toString(); const int pixelSize = variant[QLatin1String("pixelsize")].toInt(); if (!family.isEmpty()) textData.font = QFont(family); if (pixelSize > 0) textData.font.setPixelSize(pixelSize); textData.wordWrap = variant[QLatin1String("wrap")].toInt() == 1; textData.font.setBold(variant[QLatin1String("bold")].toInt() == 1); textData.font.setItalic(variant[QLatin1String("italic")].toInt() == 1); textData.font.setUnderline(variant[QLatin1String("underline")].toInt() == 1); textData.font.setStrikeOut(variant[QLatin1String("strikeout")].toInt() == 1); if (variant.contains(QLatin1String("kerning"))) textData.font.setKerning(variant[QLatin1String("kerning")].toInt() == 1); QString colorString = variant[QLatin1String("color")].toString(); if (!colorString.isEmpty()) textData.color = QColor(colorString); Qt::Alignment alignment = 0; QString hAlignString = variant[QLatin1String("halign")].toString(); if (hAlignString == QLatin1String("center")) alignment |= Qt::AlignHCenter; else if (hAlignString == QLatin1String("right")) alignment |= Qt::AlignRight; else alignment |= Qt::AlignLeft; QString vAlignString = variant[QLatin1String("valign")].toString(); if (vAlignString == QLatin1String("center")) alignment |= Qt::AlignVCenter; else if (vAlignString == QLatin1String("bottom")) alignment |= Qt::AlignBottom; else alignment |= Qt::AlignTop; textData.alignment = alignment; textData.text = variant[QLatin1String("text")].toString(); return textData; } Properties VariantToMapConverter::extractProperties(const QVariantMap &variantMap) const { return toProperties(variantMap[QLatin1String("properties")], variantMap[QLatin1String("propertytypes")]); } } // namespace Tiled tiled-1.0.3/src/libtiled/varianttomapconverter.h000066400000000000000000000060101315121121300217640ustar00rootroot00000000000000/* * varianttomapconverter.h * Copyright 2011, Porfírio José Pereira Ribeiro * Copyright 2011-2015, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "gidmapper.h" #include "mapobject.h" #include #include #include namespace Tiled { class GroupLayer; class Layer; class Map; class ObjectGroup; class Properties; class Tileset; /** * Converts a QVariant to a Map instance. Meant to be used together with * JsonReader. */ class TILEDSHARED_EXPORT VariantToMapConverter { // Using the MapReader context since the messages are the same Q_DECLARE_TR_FUNCTIONS(MapReader) public: VariantToMapConverter() : mMap(nullptr) , mReadingExternalTileset(false) {} /** * Tries to convert the given \a variant to a Map instance. The \a mapDir * is necessary to resolve any relative references to external images. * * Returns 0 in case of an error. The error can be obstained using * errorString(). */ Map *toMap(const QVariant &variant, const QDir &mapDir); /** * Tries to convert the given \a variant to a Tileset instance. The * \a directory is necessary to resolve any relative references to external * images. * * Returns 0 in case of an error. The error can be obstained using * errorString(). */ SharedTileset toTileset(const QVariant &variant, const QDir &directory); /** * Returns the last error, if any. */ QString errorString() const { return mError; } private: Properties toProperties(const QVariant &propertiesVariant, const QVariant &propertyTypesVariant) const; SharedTileset toTileset(const QVariant &variant); Layer *toLayer(const QVariant &variant); TileLayer *toTileLayer(const QVariantMap &variantMap); ObjectGroup *toObjectGroup(const QVariantMap &variantMap); ImageLayer *toImageLayer(const QVariantMap &variantMap); GroupLayer *toGroupLayer(const QVariantMap &variantMap); QPolygonF toPolygon(const QVariant &variant) const; TextData toTextData(const QVariantMap &variant) const; Properties extractProperties(const QVariantMap &variantMap) const; Map *mMap; QDir mMapDir; bool mReadingExternalTileset; GidMapper mGidMapper; QString mError; }; } // namespace Tiled tiled-1.0.3/src/plugins/000077500000000000000000000000001315121121300150525ustar00rootroot00000000000000tiled-1.0.3/src/plugins/csv/000077500000000000000000000000001315121121300156455ustar00rootroot00000000000000tiled-1.0.3/src/plugins/csv/csv.pro000066400000000000000000000001631315121121300171620ustar00rootroot00000000000000include(../plugin.pri) DEFINES += CSV_LIBRARY SOURCES += csvplugin.cpp HEADERS += csvplugin.h \ csv_global.h tiled-1.0.3/src/plugins/csv/csv.qbs000066400000000000000000000002641315121121300171510ustar00rootroot00000000000000import qbs 1.0 TiledPlugin { cpp.defines: ["CSV_LIBRARY"] files: [ "csv_global.h", "csvplugin.cpp", "csvplugin.h", "plugin.json", ] } tiled-1.0.3/src/plugins/csv/csv_global.h000066400000000000000000000016521315121121300201350ustar00rootroot00000000000000/* * CSV Tiled Plugin * Copyright 2014, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #if defined(CSV_LIBRARY) # define CSVSHARED_EXPORT Q_DECL_EXPORT #else # define CSVSHARED_EXPORT Q_DECL_IMPORT #endif tiled-1.0.3/src/plugins/csv/csvplugin.cpp000066400000000000000000000076061315121121300203740ustar00rootroot00000000000000/* * CSV Tiled Plugin * Copyright 2014, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "csvplugin.h" #include "map.h" #include "savefile.h" #include "tile.h" #include "tilelayer.h" #include #include using namespace Tiled; using namespace Csv; CsvPlugin::CsvPlugin() { } bool CsvPlugin::write(const Map *map, const QString &fileName) { // Get file paths for each layer QStringList layerPaths = outputFiles(map, fileName); // Traverse all tile layers uint currentLayer = 0u; for (const Layer *layer : map->layers()) { if (layer->layerType() != Layer::TileLayerType) continue; const TileLayer *tileLayer = static_cast(layer); SaveFile file(layerPaths.at(currentLayer)); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { mError = tr("Could not open file for writing."); return false; } auto device = file.device(); // Write out tiles either by ID or their name, if given. -1 is "empty" for (int y = 0; y < tileLayer->height(); ++y) { for (int x = 0; x < tileLayer->width(); ++x) { if (x > 0) device->write(",", 1); const Cell &cell = tileLayer->cellAt(x, y); const Tile *tile = cell.tile(); if (tile && tile->hasProperty(QLatin1String("name"))) { device->write(tile->property(QLatin1String("name")).toString().toUtf8()); } else { const int id = tile ? tile->id() : -1; device->write(QByteArray::number(id)); } } device->write("\n", 1); } if (file.error() != QFileDevice::NoError) { mError = file.errorString(); return false; } if (!file.commit()) { mError = file.errorString(); return false; } ++currentLayer; } return true; } QString CsvPlugin::errorString() const { return mError; } QStringList CsvPlugin::outputFiles(const Tiled::Map *map, const QString &fileName) const { QStringList result; // Extract file name without extension and path QFileInfo fileInfo(fileName); const QString base = fileInfo.completeBaseName() + QLatin1String("_"); const QString path = fileInfo.path(); // Loop layers to calculate the path for the exported file for (const Layer *layer : map->layers()) { if (layer->layerType() != Layer::TileLayerType) continue; // Get the output file name for this layer const QString layerName = layer->name(); const QString layerFileName = base + layerName + QLatin1String(".csv"); const QString layerFilePath = QDir(path).filePath(layerFileName); result.append(layerFilePath); } // If there was only one tile layer, there's no need to change the name // (also keeps behavior backwards compatible) if (result.size() == 1) result[0] = fileName; return result; } QString CsvPlugin::nameFilter() const { return tr("CSV files (*.csv)"); } QString CsvPlugin::shortName() const { return QLatin1String("csv"); } tiled-1.0.3/src/plugins/csv/csvplugin.h000066400000000000000000000025561315121121300200400ustar00rootroot00000000000000/* * CSV Tiled Plugin * Copyright 2014, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "mapformat.h" #include "csv_global.h" namespace Csv { class CSVSHARED_EXPORT CsvPlugin : public Tiled::WritableMapFormat { Q_OBJECT Q_PLUGIN_METADATA(IID "org.mapeditor.MapFormat" FILE "plugin.json") public: CsvPlugin(); bool write(const Tiled::Map *map, const QString &fileName) override; QString errorString() const override; QStringList outputFiles(const Tiled::Map *map, const QString &fileName) const override; QString shortName() const override; protected: QString nameFilter() const override; private: QString mError; }; } // namespace Csv tiled-1.0.3/src/plugins/csv/plugin.json000066400000000000000000000000321315121121300200310ustar00rootroot00000000000000{ "defaultEnable": true } tiled-1.0.3/src/plugins/defold/000077500000000000000000000000001315121121300163075ustar00rootroot00000000000000tiled-1.0.3/src/plugins/defold/defold.pro000066400000000000000000000002021315121121300202600ustar00rootroot00000000000000include(../plugin.pri) DEFINES += CSV_LIBRARY SOURCES += defoldplugin.cpp HEADERS += defoldplugin.h \ defoldplugin_global.h tiled-1.0.3/src/plugins/defold/defold.qbs000066400000000000000000000003401315121121300202500ustar00rootroot00000000000000import qbs 1.0 TiledPlugin { cpp.defines: ["DEFOLD_LIBRARY"] files: [ "defoldplugin_global.h", "defoldplugin.cpp", "defoldplugin.h", "plugin.json", "tokendefines.h", ] } tiled-1.0.3/src/plugins/defold/defoldplugin.cpp000066400000000000000000000105221315121121300214670ustar00rootroot00000000000000/* * Defold Tiled Plugin * Copyright 2016, Nikita Razdobreev * Copyright 2016, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "defoldplugin.h" #include "tokendefines.h" #include "layer.h" #include "map.h" #include "mapobject.h" #include "objectgroup.h" #include "savefile.h" #include "tile.h" #include "tilelayer.h" #include #include namespace Defold { static QString replaceTags(QString context, const QVariantHash &map) { QHashIterator it{map}; while (it.hasNext()) { it.next(); context.replace(QLatin1String("{{") + it.key() + QLatin1String("}}"), it.value().toString()); } return context; } QStringList DefoldPlugin::outputFiles(const Tiled::Map *, const QString &fileName) const { return QStringList() << fileName; } QString DefoldPlugin::nameFilter() const { return tr("Defold files (*.tilemap)"); } QString DefoldPlugin::shortName() const { return QLatin1String("defold"); } QString DefoldPlugin::errorString() const { return mError; } DefoldPlugin::DefoldPlugin() { } bool DefoldPlugin::write(const Tiled::Map *map, const QString &fileName) { QVariantHash map_h; QList> types; int layerWidth = 0; int layerHeight = 0; QString layers = ""; foreach (Tiled::TileLayer *tileLayer, map->tileLayers()) { QVariantHash layer_h; layer_h["id"] = tileLayer->name(); layer_h["z"] = 0; layer_h["is_visible"] = tileLayer->isVisible() ? 1 : 0; QString cells = ""; layerWidth = std::max(tileLayer->width(), layerWidth); layerHeight = std::max(tileLayer->height(), layerHeight); for (int x = 0; x < tileLayer->width(); ++x) { QList t; if (types.size() < tileLayer->width()) types.append(t); for (int y = 0; y < tileLayer->height(); ++y) { const Tiled::Cell &cell = tileLayer->cellAt(x, y); if (cell.isEmpty()) continue; QVariantHash cell_h; cell_h["x"] = x; cell_h["y"] = tileLayer->height() - y - 1; cell_h["tile"] = cell.tileId(); cell_h["h_flip"] = cell.flippedHorizontally() ? 1 : 0; cell_h["v_flip"] = cell.flippedVertically() ? 1 : 0; cells.append(replaceTags(QLatin1String(cell_t), cell_h)); if (const Tiled::Tile *tile = cell.tile()) { if (types[x].size() < tileLayer->height()) types[x].append(tile->property("Type").toString()); else if (!tile->property("Type").toString().isEmpty()) types[x][tileLayer->height() - y - 1] = tile->property("Type").toString(); } } } layer_h["cells"] = cells; layers.append(replaceTags(QLatin1String(layer_t), layer_h)); } map_h["layers"] = layers; map_h["material"] = "/builtins/materials/tile_map.material"; map_h["blend_mode"] = "BLEND_MODE_ALPHA"; map_h["tile_set"] = ""; QString result = replaceTags(QLatin1String(map_t), map_h); Tiled::SaveFile mapFile(fileName); if (!mapFile.open(QIODevice::WriteOnly | QIODevice::Text)) { mError = tr("Could not open file for writing."); return false; } QTextStream stream(mapFile.device()); stream << result; if (mapFile.error() != QFileDevice::NoError) { mError = mapFile.errorString(); return false; } if (!mapFile.commit()) { mError = mapFile.errorString(); return false; } return true; } } // namespace Defold tiled-1.0.3/src/plugins/defold/defoldplugin.h000066400000000000000000000027251315121121300211420ustar00rootroot00000000000000/* * Defold Tiled Plugin * Copyright 2016, Nikita Razdobreev * Copyright 2016, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "defoldplugin_global.h" #include "tiled.h" #include "mapformat.h" namespace Defold { class DEFOLDPLUGINSHARED_EXPORT DefoldPlugin : public Tiled::WritableMapFormat { Q_OBJECT Q_PLUGIN_METADATA(IID "org.mapeditor.MapFormat" FILE "plugin.json") public: DefoldPlugin(); bool write(const Tiled::Map *map, const QString &fileName) override; QString errorString() const override; QString shortName() const override; QStringList outputFiles(const Tiled::Map *, const QString &fileName) const override; protected: QString nameFilter() const override; private: QString mError; }; } // namespace Defold tiled-1.0.3/src/plugins/defold/defoldplugin_global.h000066400000000000000000000016731315121121300224630ustar00rootroot00000000000000/* * Defold Tiled Plugin * Copyright 2016, Nikita Razdobreev * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #if defined(DEFOLD_LIBRARY) # define DEFOLDPLUGINSHARED_EXPORT Q_DECL_EXPORT #else # define DEFOLDPLUGINSHARED_EXPORT Q_DECL_IMPORT #endif tiled-1.0.3/src/plugins/defold/plugin.json000066400000000000000000000000331315121121300204740ustar00rootroot00000000000000{ "defaultEnable": false } tiled-1.0.3/src/plugins/defold/tokendefines.h000066400000000000000000000023601315121121300211370ustar00rootroot00000000000000/* * Defold Tiled Plugin * Copyright 2016, Nikita Razdobreev * Copyright 2016, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once static const char cell_t[] = " cell {\n\ x: {{x}}\n\ y: {{y}}\n\ tile: {{tile}}\n\ h_flip: {{h_flip}}\n\ v_flip: {{v_flip}}\n\ }\n"; static const char layer_t[] = "layers {\n\ id: \"{{id}}\"\n\ z: {{z}}\n\ is_visible: {{is_visible}}\n\ {{cells}}\ }\n"; static const char map_t[] = "tile_set: \"{{tile_set}}\"\n\ {{layers}}\n\ material: \"{{material}}\"\n\ blend_mode: {{blend_mode}}\n"; tiled-1.0.3/src/plugins/droidcraft/000077500000000000000000000000001315121121300171735ustar00rootroot00000000000000tiled-1.0.3/src/plugins/droidcraft/droidcraft.pro000066400000000000000000000003201315121121300220310ustar00rootroot00000000000000include(../plugin.pri) DEFINES += DROIDCRAFT_LIBRARY SOURCES += droidcraftplugin.cpp HEADERS += droidcraftplugin.h\ droidcraft_global.h RESOURCES += \ droidcraft.qrc OTHER_FILES = plugin.json tiled-1.0.3/src/plugins/droidcraft/droidcraft.qbs000066400000000000000000000003521315121121300220230ustar00rootroot00000000000000import qbs 1.0 TiledPlugin { cpp.defines: ["DROIDCRAFT_LIBRARY"] files: [ "droidcraft_global.h", "droidcraftplugin.cpp", "droidcraftplugin.h", "droidcraft.qrc", "plugin.json", ] } tiled-1.0.3/src/plugins/droidcraft/droidcraft.qrc000066400000000000000000000001321315121121300220170ustar00rootroot00000000000000 tileset.png tiled-1.0.3/src/plugins/droidcraft/droidcraft_global.h000066400000000000000000000016751315121121300230160ustar00rootroot00000000000000/* * Droidcraft Tiled Plugin * Copyright 2011, seeseekey * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #if defined(DROIDCRAFT_LIBRARY) # define DROIDCRAFTSHARED_EXPORT Q_DECL_EXPORT #else # define DROIDCRAFTSHARED_EXPORT Q_DECL_IMPORT #endif tiled-1.0.3/src/plugins/droidcraft/droidcraftplugin.cpp000066400000000000000000000077651315121121300232560ustar00rootroot00000000000000/* * Droidcraft Tiled Plugin * Copyright 2011, seeseekey * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "droidcraftplugin.h" #include "map.h" #include "savefile.h" #include "tile.h" #include "tileset.h" #include "tilelayer.h" #include "compression.h" #include namespace Droidcraft { DroidcraftPlugin::DroidcraftPlugin() { } // Reader Tiled::Map *DroidcraftPlugin::read(const QString &fileName) { using namespace Tiled; QByteArray uncompressed; // Read data QFile f(fileName); if (f.open(QIODevice::ReadOnly)) { QByteArray compressed = f.readAll(); f.close(); uncompressed = decompress(compressed, 48 * 48); } // Check the data if (uncompressed.count() != 48 * 48) { mError = tr("This is not a valid Droidcraft map file!"); return nullptr; } // Build 48 x 48 map // Create a Map -> Create a Tileset -> Add Tileset to map // -> Create a TileLayer -> Fill layer -> Add TileLayer to Map Map *map = new Map(Map::Orthogonal, 48, 48, 32, 32); SharedTileset mapTileset(Tileset::create("tileset", 32, 32)); mapTileset->loadFromImage(QImage(":/tileset.png"), "tileset.png"); map->addTileset(mapTileset); // Fill layer TileLayer *mapLayer = new TileLayer("map", 0, 0, 48, 48); // Load for (int i = 0; i < 48 * 48; i++) { unsigned char tileId = uncompressed.at(i); int y = i / 48; int x = i - (48 * y); Tile *tile = mapTileset->findTile(tileId); mapLayer->setCell(x, y, Cell(tile)); } map->addLayer(mapLayer); return map; } bool DroidcraftPlugin::supportsFile(const QString &fileName) const { return fileName.endsWith(QLatin1String(".dat"), Qt::CaseInsensitive); } // Writer bool DroidcraftPlugin::write(const Tiled::Map *map, const QString &fileName) { using namespace Tiled; // Check layer count and type if (map->layerCount() != 1 || !map->layerAt(0)->isTileLayer()) { mError = tr("The map needs to have exactly one tile layer!"); return false; } TileLayer *mapLayer = map->layerAt(0)->asTileLayer(); // Check layer size if (mapLayer->width() != 48 || mapLayer->height() != 48) { mError = tr("The layer must have a size of 48 x 48 tiles!"); return false; } // Create QByteArray and compress it QByteArray uncompressed = QByteArray(48 * 48, 0); const int width = mapLayer->width(); const int height = mapLayer->height(); for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { if (Tile *tile = mapLayer->cellAt(x, y).tile()) uncompressed[y * width + x] = (unsigned char) tile->id(); } } QByteArray compressed = compress(uncompressed, Gzip); // Write QByteArray SaveFile file(fileName); if (!file.open(QIODevice::WriteOnly)) { mError = tr("Could not open file for writing."); return false; } file.device()->write(compressed); if (!file.commit()) { mError = file.errorString(); return false; } return true; } QString DroidcraftPlugin::nameFilter() const { return tr("Droidcraft map files (*.dat)"); } QString DroidcraftPlugin::shortName() const { return QLatin1String("droidcraft"); } QString DroidcraftPlugin::errorString() const { return mError; } } // namespace Droidcraft tiled-1.0.3/src/plugins/droidcraft/droidcraftplugin.h000066400000000000000000000027451315121121300227140ustar00rootroot00000000000000/* * Droidcraft Tiled Plugin * Copyright 2011, seeseekey * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "droidcraft_global.h" #include "map.h" #include "mapformat.h" #include namespace Droidcraft { class DROIDCRAFTSHARED_EXPORT DroidcraftPlugin : public Tiled::MapFormat { Q_OBJECT Q_INTERFACES(Tiled::MapFormat) Q_PLUGIN_METADATA(IID "org.mapeditor.MapFormat" FILE "plugin.json") public: DroidcraftPlugin(); Tiled::Map *read(const QString &fileName) override; bool supportsFile(const QString &fileName) const override; bool write(const Tiled::Map *map, const QString &fileName) override; QString nameFilter() const override; QString shortName() const override; QString errorString() const override; private: QString mError; }; } // namespace Droidcraft tiled-1.0.3/src/plugins/droidcraft/plugin.json000066400000000000000000000000331315121121300213600ustar00rootroot00000000000000{ "defaultEnable": false } tiled-1.0.3/src/plugins/droidcraft/tileset.png000066400000000000000000001566141315121121300213670ustar00rootroot00000000000000PNG  IHDRxsRGBbKGD pHYsltIME IDATxyeיٗ$}!BTm=x=*^Q^Wz縜Aq ( ,a˾gLYתGuUwϒ_^C/UOꩧ]?_oPw*Oƴ#͘$ 6~O?LO|!utt BrhiiA4;F<SUF|>LǏ0m4^/B:;;CUUN8A8F"']`FBw kyy@F@BrxJO~)y=K i*ǿ}Jkt/hJW)y CBB0 a HYȪ, $yQ=,8NPUs:(B__TXEQ4D"A__d]z8ND"!$ 04 Il |.{!@,7׆~SF|j)__^=  _JmUʔp122z322.! FH )8tT0L@YQb1 `*dY&LbFbNp000@"@Q멨@4E!Ni=F4dK0;4FBYQAJT{l"I`+cj.\HKK 7?l+3xFN>C*,/R[ Z8~p@GG|ǻmO5ٯ  2~9p`?ipe`_HF52I  1&@RS@R$iT^V!sb14p*N'$L&Bֿin ànjkkq8Ȳa8l4 ˅&JRV{,~]zi$M ݟB =&q* s}sHB5X(JMu5dkYǕW^ ٳ}CON'zxI!Cl$'еj2j HFY`G{Lǻ-NR\8M`xy=O8U.! a9|'O檫Q7d􄌒<._ٗ@BJH) >.$$Pz{BQYY,6h;xH&\.xl3@uEAQn7J@4%ɘ1쵑$H?5V@2~*j)0ٕhUZŠ`0yDx1} NK.eʕ8{[ccp γn#(/O#3!kܳ1dW̯Hx"jAH꘽$;VD!Q ~k*i']3 >L+\/sq8]nV_~EY4 !%s [j ٜE9*VQ3I!Pͼl8Y+rrH&j+tv WUmƊB*L&c$ Yq\!l>$u62ĎFd G> #iHv&XGq+HH=l@?KĚ5Wq \xᅣOIXt)K._raȣ,cɈ㉾mEd-4 KmV!jYΙ3ɤ3h/x '^}o|8NN?AUu >}ie`t7}n9 @aQ) #!M MU T CT*Ȋ^aСC$ 9qT ECC$9~KD(ؾg>EQ%p)!HӤ<+|IvqWk}&"~*jR]IR}I٥4"cVK_ ;/k׭vV\9u8yG?5v$>DBC0}QK @P|bnux<,]zfv߲0@P! RL}(v8@( eߧ[An32j-Ivٟ$Ii$3~:Fu[)!"~!ǃ,LV`X Icd d p:smւyՂ9yyİ7o\lYQ?O|;8% ߒ8tAW|xId=NjGBR WlQK U 3[ G t: Elf@ ̧md`0\~ڍ,d]vt%`޽,\3fW 9̙TWt:f͢m֬WVF$UUfHr܀~9bQ 2/YZux匿ˮ$ Emm]&h$?Ͻ5QO"(DZGq($hNK%0p$w?[gi0Ĉ( bBUW+9njjSN8=ig#Ѫ0/n|=3໔g4q4W!鞍'琍UWestvv& ~;z]%ƶ*:8qɉc̝7T2E}}}(h׏gk7o++#ZՕHqIf_2 ;j)|=X$-VEQXX^uӉ]uT*E? 8!!;Jz%0F@q(Uz=?//W&"1ဦ9طoߤ)o{Oz^7b)ek ѪW+xOSٻ%"]BI ՏT\}芏%r[Rό .(mpپ#?;%l_Μ>Mu$z<9300ۏL&i5t*ԔX@f0 ""TJ037 3sa$I;:\."]l!===ؠr6mLx _*KKkk61:iSijm>==Dzv(?'|}z9edY$]׉D"tww6 0|>L~S1H 4XXEtOũ87CY a[VgV"t2$IB4֭[7s=ׄ0U¶ HgӯTjqDM2[A}!2=bU#>yRd}iKc~#/`0X6G)ffϭ#PP :}:m3HK446Dy\r* sNJED%DJFrGa{ jV.+ȲMca&!JeJ[Qd2d2D8Z UUuI$&:H8jgV"2[?mC,Q9/ _ nb{O.Y?\0wey2Zg}2Dr 7\3 տ?F`0XN6Ģ1z7wP(@-huPVb$Fd@mDb1 ]p€W fl Vf@Y|L&B!Ml6?l~+9t:M<r D"ߟdL86@q+zNN胡I{9B07y-Mވ7\9ﯢšeduxCOy5ÀoiGB8_3gi .ȇ#x^;i$io?J*by;KWG7({¹ Xf^+2:Iexqi.AeIkk+i$IBbFn~.zzzz^5558M{Yᰝ/a;dGONtIٟ V PHʽ|R -]H,{H+W؋:ˀ% | k?0};[o,Kp}:UVs%Nٷo/;^~zeG0 CPxdQ1iى(+Css3466ڍ#dl@0s2^0,\޹>%.jm(rm}$H~*V8D~썺e˖xUhUH"Me#xCMZauF:WyvYt ?s4<4Utwu *˘%LeXl$$>g˅#ڙH^u*E!HPYYiTWWDMMMA2먪G#9dU _ } Rq   ^[2/+ Е K鯽VGez3~Izs/6mMe?~pF/_ҋ.-}D6ں:dIw_cTe\sנ''ɐH$p\ %Gav )`QaJP%Kˏg! 'ؗ of sPV0Iw+ɼg5Jf@+q'T׫`7|Fz{8|aE4LqY83f]d9bp8p8$2o``NLRL&C$$ T*Euu5v}<[76JV aya "`pJaիW2_–XJho&휆Faf~FXS#[; 457hbdYc#z\nnd"1J&ts ȲCeRN:h4J:8PU^*++ Xd  x|\.bDQSٰ z5;nVp $̕Je`!8pşgnV;D gb.C Q{v U {td۶gȞ=y'H| /_#GUŐc5#}Ã],D"!hmmEu:;;qve@*ɓ(BUUg%Iv]455c'l?;/|?O y¼H$B2`ٲeCnbʩry0-td=d RqBRU߫qj xP\ٹsմN?E[,|>Vf…=sfX`#`90:jU 3 Pq< |(bg[؄ Bhnl$hb ˲b1$uuu2mڴKVTy^Q@geb08gSSO=5i`~x3d9pLt:m”$*>}:ӧOftXUU6!%g$-r|_`R^_Hx&W !-/<1h2m5^U2ræ<ͯK/X x^r`2)8+PPϮv(tuu|w{#Ցv4cla6yKٌB&_oA$G6P.[=fpI2"z9%]GB~nfUxD"HDss`U d2B]]]b1[p:D"Μ9C<'NE__`v#;/K+(@iD̙ݻ۷m.j i0}M$" g{%Af>_^jf}Mn7PcKxf~\[ tU IBR9 pI&vBӷۍG(*3EQz~?Lۋtg3 644U&ȱ2L3A!o SHg0` <ȣn:jk=?˼緗@1d'IF2#/f !)eW_K03߷~#zy}FΝSO># pi~sKkg9r0/hfSNΌ3 @1De2*ညDcWz{{1 f2L>x8{,d.4ndln ðY>ٳg%"ou߿/B0d`o@w^Ξ=/"z+\pv]s]F!݉bUIx`Nb(ZY/杦 ̌[oUBx<\{<㶗S\j5s.K80nlm3t[3²P/j*nN`.ij___v& !d2h4J4uºAY9}KWBe!`z#ʃ  2s̡H>}Ξ=S^\H?,R-dZi5Ye]}7rf.fȡʘ/x=zjjsz%I&H"2ӦD<>?}((x9(P= e^0d28EV`?X kY@8tIzTWWۍᠫ0.D׷bU?C\h+L&C{QkOJvE"$N-S T@ɄI;m7t ]񛚚_)J@_)VZZ[tL8rR[[颮%˨^q(+hj~ IDAT$9$>g+p~]2$(9rp\JD;J 0bob1k/18Jo-o4RƋY=5M#g'\@2 ! 3}%;/KV$ JAY__Z Pׄ8Q?)twa p5 `2e%?W}L]F㹷s"CZ` N?BYS]x5cddE (UE@&v59 4lwJw)wqG9`:`" ٘|e%uLI" q$,_ Y6CY1RLPTPU:@˾ye)KY(KY^jxgY9 'q~5k$kg@SA)b|ԁ@@Q H=۷nzccv{衇qMܓS%ߺM[Nܱfa2Kd5 `6Tj*V_~<2n羚/;OrequOf۶mL6kגNٶmۘOd@IpѶLWF%'k8 :qihj b*ep-|pw߱O@5h`0 M42k pic!C&ì*mĬ-@.졕 )T v3}T;f_A~+r[V zՑUg.d=q#lhhm\M>H7?Ot Fj;(.5}4^l0,!fMR͛޽Us;-܂(\|\q$-{yγ::{ۚ3˩ӫ Yu /g>J*SK'X@ WɌlyQvEWgiIϚōo,bޙ7 rNAtX}ۺp8 V&wz+kmitXϏϫU`0go`VvӒG}u/{waݻxOc뮙UUT2: $FPs-xJ;I; a`F~f:9Nfؼ8 1&=ʦ_7q2(V[yI}g_X`_JM  .ytuuq]wIg$y}f42l'9p Pc6Su/fwH)N>,`p9#m Xt)x(M_r ?߼eI^7s o@~`0^q-ZݻohήNEO'$v0Z%۩P"' \ X\q0vbDfo>KgW{>.ihŮn7'|Tmyv_V +yn1?To^kyIgjƢ(5?ZO@)v-So8Rd YWe_  [6ρ=`p[ XI.H0y_x<֮]K[[}}}'dooK~,xnYT$=3=g:x2 SRw>5PT X V1|x<^nam۞-Vl)# @6oW6m3~#/op. qYs4 ]B`Y?[L{SFL@.L| * z2,[ EDEA_s۴ؿ "/Ap95?ZO]-9Y }W|KQUXoztӾ%U$~5vdy_?|.vO/QsEo~3ӦMӧO\s5vCr5p饗>#2lgpɩcYli΋.yO ^ fO:dUOκ1唙ؤ.Ro>Yc'|W`f>|cQ~qc1.nN*~yh?#b2;'>4߮e^ɫwhiYJ9 [Y`P;g';LyI]}E^w8uj)ծX+gvNJW,~Ѭp 8  J#>juY3f=bk׎tRfϞ=̜{2Zc{bDl^}dR.>*l,I̼9u3 Q̶Y%׾'s|!*-s:p Ѕ* 9+)&ĉ5n8+ZܚԤ ;svׄƷXdR*sT\F_،־J^iRD`|SWoORTJy&}رϼ\$*5З~l;<"B, xM-wOSlK?]) 9fU |GaJn}o~I|<%qn_ K+n^1G۪z'j'-gR8[Ny?fXV_~2 @WWO?4<2gr=|˗Q׿9%ȩx77̔Z=YgD_ /`-YvES<([3o>~{I5ês0yl<^,澊 MP &~gaf|qFyS+ΰ1)!c2o 2PIe~u^Me7W35|w= {8n & ƯvrҥsZrW) "KMˏ{>SG@Us 7ceu=?U{x<~,cR_7Jig-ioWXK;XaxǀGZOf2΂%~3qq$I8N4^p{|c{mq%7v\9 LibOu<~1YĿA(p_OaAc?w|կVB1H, mkF]P3qPU̿d(`yo_&s*G.T&t籰+]4tV69Mt9Tv'4QϼOJo\ɟ#Gc+VͿ'@Us;NWudn"Hx<ӵ9|ωPgtuX=3qoI`F r=/LarqGVo/ĉG?flRpM8B4ޘ+/w/.~߱&*2/̂SbuOa2\T~_u.~A ЇXJXwifvxFaHGC#{-nz?gU|om K<%*I%iNܠ?} {8~I>.:ݬo;ė>';d?)v藍pߡTVU 7RPUUڵk'99 ՘6LbֿW~9gA{ jug3kߪuց@Zg?/9teYf#tPU /IF$F,\жG+Zwu'?hS-/u(A|gѬoKrځbm{+/+/cD$NM׳d:{T}2/6K 1ߧ2>y'{]:M4ӧ0PYV9@KLR#w1$vuƉ?>e:gb7V f%э*$~ηמ(E1yzjL\a\٠ oM*_)H$zc\.8ǁ۲k7v_tXO_vro灯~ (U%OqWH׾5Λ7*Μ9ÓO>9>ndž{B9}euϻL@)Х#dCZO/ZgK Wc%o&ӄϽŋ?DDcxer.i,mpd 8QeiMVjC-[nfڏ2Rc#´L ,µoIڡܚA8)wtxLJFj|:v2d~z2|i)fpjk~/LGAZȈ cJVX G8{ 'dcà8J@=c͙e˖3f㓶.\xTYc<9ٵXMe*Z gZ`Q\/4d@qߗOrOD<~Pi$$FU,ïd2ϜTxdqU1x/w\rZ|{{s; 'slVJ_c; %+y]CYO6ϟ:H4o?)4Rcd.Y-_oLmm-'Ojdڴic$+q'^Y"0ܴ/lqi]PO=/j]nk[5̜ 3Kfrdw{j"qQygbKc <,R?|CAq߀ W&m]2޽I8UKy9(6p5&?[C.jXP%/0˟₪+Ҭ%cHC\N$gc>>6<ַ{H}4\?-?@lCr,WifY(J]y啎۷sL9֭[(Ì3waD]C6p9&׫#qMIѤ+Vs=pd2: ۥ&>7w8!d=  ӥ:Ϝ]-'tW?&LQD y!bS%!DWf ߔ?@l~XW EʽW%)G$Kf93[+6ЄbeHc;UQ^aUR0l91v??fבTg,6/K <9gŊ6ssu{W;^O}hkpz&"fFJBgd@Y!̤oG-Z\R뿘L\ +=40\cf aE*)1: x&79XfНߙ6_̵\74i,E`8b|u_џ~ePŸWrD?fo YH2Kn{/ IDATx<-zN]Q5d{[9%ܺЄW]=ToBsȩgOM kvWc|@CNLv0@ZU~?3f`Νʕ+Fú::t;we/=FS\l,:'%𞆣D\*.h(Ο=eu)>yhN(fko#Д&cMĭǶ*C'rw=SV͕ NMx}-]|C0*>+V0|f̘͛K.gլZG7|GN{9'POBIK3rǺ3t7E$ s|./gs|dKfs3QBS s܀վK'_C#!^mBk^ZXI^ZΫr|5/f;J6-8_!(|>kjkkl;TWW~Y?ZcR['K!MxJܜw.CnhԬhllu+++G?륯Yy{B!VZECCTjDK9#NH n1D6 2OD? D1&` Ɍi'RKо-7T)o!`0SUͰA_s9gEÂh~Z]]]… q .,X _Bf de f%;g6?It{&o?fqrR?O}|Sb#b10 .䗿%Nt{oGu^xsv/E{h<߯=ʁ%'QZy`^ey4\~# >~#-չf"%b3Sg+b?-/"2-``L%UUU!"o}[vjСCttt`#H TRμQ\C~~{`F sa²S9vIǗQWﶷ8YNc% ;GNn,O|;)M ~Xv}NdZ#6Fl<wބan)/")Hjsse rN浥ox.BഘPbD@?o)/&r&R{~N&=tڥwӦM.:˅HWVV*eYq %ou+#靝tvvN?꒎\‚ss.,n\x; aX^(I@f3;*{9k! "jjV[Vz{jֺW[mojp+ *JY9 $$$`:33Ϝgw6VqG/@/$82(~V ~:#8hp$dߑrn͉_zi&zu IiDeQuAqG,W>{[S?won] & xG]?B\!7rb'+`s  xQd(֜B LUq`eާߕm{@_N01qH SPj:!;W`A\ Qktn y^}t!+D0q|$= MM529&+Gw#аM̉!^ liS"88T8e,{F(((YO\:uã 'Z{[G~qk W\uSϜJ4G h6Z6o;By9H`6hԸo8ԡoa2)#?JG 2w.ơqTtpDOҿoǐBD t/]edn!Xn%MepawlH>/ߥ{σu~i.ZC A+H7$O BMhH)17vХ5m;v%͓#l,iyzPPP0tv*1:H 'ځ(,,${wmuũ5U iQ0􂥁.!ل#:iR}YA!-S_r`Ff_J rCAAi mZ \;-poJ^AtdU 3Fy],b[W<{-_47NB *#s2^(Hh!--(53<Ƴi pK+.4XBk[Z8 ԕ&n͈e?Jc?vۆ[_(((S6= ܵmZ[Q ;{ `2o)1BžuEYGFDt-1y<i$qՋ ??A ..;۲d{6 7dxr4Ԩz_!up^4>̆pIyzԂ!7e>:d0hd|/CpIr$\0iͶ4>^o}J;lXXM^Y6C~y6ˇUEܕ1Ԛsw=w 2F3;NKF6x:j_ .p]9Dp,Y𦁑uhl@d7ۇ~]`-aƐ*8Аv\PiH<2ժp`KA zК!7vRmaa!uuu̝;7}~-`&?я4hPӶ̙31cƴ=-L6zL |zDH#OXu~xk, B~ 5`T5I:^ ~?cH}Q:dŠBU IIW@j5>yO|x|0dÐ7jz 4M;-_QuPblޖѬ5xV?#q/n?CspAmV>ګ /v<.FUqu;9U,ʿLVNWRI\ YNl&䧿+0!m"4Ep@RZ1QKH&zuOCkfٙ6m;vUB֭[yyǎwڴiTVVslB:j-v] j1 w9':އ~)Ay6%wG ] EsVx6OO]1dO_Jՠma s]iNۻȃpArp鳦siJz3lXoLl'.r v~Ar\BctrLTաέ\ mJU J  dH%UkI$HLQ`^If_IA`noIQq^Y2 o,j=uK3}nMD ({Ude.]pҍ?:[1h~ | *b~?մ `BhC`vR.AFkU+;b\ ]hʗ@e)a'HOpcwш PC8-/ V|9,Hj@n\31 MgΜ9檾ZoпƏOVV1ЅLzaejSmTs':Gv10 jVH@p1 vO?J߭;-:(s7,|w 6~Y&OW)KgvڎY HPBJep9PU/Ahs~>c`h,ثR6I1jӏ vn8}&LIJ )lKr%>5c $9f/Tvx68U71 |r4:Oh=3R)pf RDCx1[,Xo_W˘ @8x3F À@ iWUEdC"q!Z.~md,kNC WRjfWOH Jb.¤-) x@IiH1 C: G vX>C&} ~/*3_~5k`Cꫯ>{g B# a̙g믿O>p++`Y7_t4S(#O),,4?$TӎoPŹ;wp$޿ͽK3O;.jЊK/y/rB-߿\7#9X67aWj^z%VScZlJQWza>Jؗغ/e8`\범aLLPTAZ(2J6^Rmv+M&8, I7T2qCrdNAA鐛/9÷56 d,O`]=e D[xգR79kkHkU 1)_Ѐ wI 5g2Ds,v_]x\g\ZT/cSMsQDP7;a4#ju~[m`ɘdOzq*ÈRfLseF3d>ޭ*FX*->^J]^e8gp7eRRߎD( ^t܄/m*Q)J%ZߵWRb) E`!gyok#]!\"'E3 ٢8_̅^i\G rW^y%eee!HLL䪫bĈMA(;>]& 0ґWPChwlYY7hŵꂂ->l"9q ߾[d1y~ڜ[_)3'LKkuɓ>ϛODxǎ;M\ 2oh[Ųט.X as2>pnH;SMl~INg>0>GPC0bL9ۡdg9ᄂSSN0@;lHV($|a=.#pܒK[غK&qDžIUc ;TA'>;SԔY!6;i\;  i/K2DpϮ ZU?ZC+۾M=kaO:gK¶U}SdxnZ !nF5V\a;i76hB2ӱ)A#۸7#ί ( c8x_Gr?ӉbK 8s\#K<%% O@CW 6jA-5wxѿuRK*;=?( |GC.:}J=V4OXUܕB@ x?jkkٹs'̺tCg;+xW ; (ߍe[F_WV*B s*P [h U2m-ط]÷l/A7 ?|ΡnV !~0#G UsTo d콱wN#f$f+IzNOcwjҤHݩ+?wr0KwIHs[d0 !6!r}VlC̛bױ0'TDي|H5«y[v`'Ү{{0BIzamN> Ēh}n.((X]GjMlYݰ 3V"Kjnp!O]B),,駞gz.q`w lOUfԾc@_ݥ R x4؞uc.m r4̵4>zGF/NymgoϒfE.rIoTڟE;/UXI"A:.i!|) 2[4bkCH $L@ qmGsL\ZBq\ >vdu `͗$ʮqǙw{0kj .0x~/pTUkϾWkBkg03D!DyV}om<=o믳jx~.D^xr$]ʼŵ KTC|%>8^kiX1CZ#2ʡIm̓ڸ1A*?{_`n7yHIƄ;$}Wg2/:-h@8~Ϧ)1سoɢѱؾ^wj" j ZoX7k ɘr)wQT]S[xυ"ә Ί[{Pn2T@)ĒuMD]6;M~$- mJII<{cRᑶߝz wXof7ķǤXOcZ&}Ѻ>* uuu\wuvi:^4%z5Faw}R$wj| )((x<LWPP:L \ԜI_GrS;Ӈqi2+3Bq3Cܓ~a'PJ<'nJT:#T ]Ӡ֭j4RBMWtl[[u֙8a(Mku6ڣ)@ q6~1%05b:B'e^V )3h`fE8_r!HljF]iɆ^(R8i/GV`;kegL.׸Ts IDATpC VAF0(0`?|w[mo{.jADAZOڱM+MBÅHL ub *c.ƺc,.i1Laz-NK*))$54oMUUW\TVVMVV6mc|M e!4oA羧ߵ&ȷ0XPPT!q"+`bF\DZ:{uh$rUMXpxo,cݰWCZˮ@eU{;!dMv'܃#%mm('Xƺ PCJ Z Ӿ yC$"=5Ѭyk H WZ]LiSo*{rwy}CR]6ggSu5Mw)\J1yQc?"<:A|OU'kN)^Aݰ9w;zkΒccX@ HR`Gm.B | k:Ŧ\1Cr 9N6*R~~>?0m=3fikl߾D͛GVV'NdĉG>q`/922d]KQ" 4cgo),, a0* ,uv͆ 0aRZZޒtNҎyBZ3xp {θ_|lW:]uio15H҇+0~/K>Er Uǣ+xUHȊ[gbJsp-{TBOfsc N,`胸 ސۏӏӁp;&Im)[-xc!AT򿵎FcJ o^c00xh exv*((U ɲɷM;oD < ߌ_iGo74S ,1X0kSPg}Fծ ^*'+V h9\pYJʮ]l 9jY_ 9Sai,VVW+3d|9:]pEnsMYqdcO 68b;IECO[@3/`._p[I,YG8{X8QYhv~rBWRmklz^W%mN:QB1)-!&>#z"@ ].['!OAb^f/q9ޣ-gJ$c\TsG|sM_0u+o7#߂ER*4UdDAAB8Ɵ?7bEzw*N p%#진!0e1n8:|ehwuqPmip~Uƣ.UOWe*L5pU@+*aD1`jg8e5KrH _|Pm XJNz)Y|"bSM"( ̀dPP썸0 87G= @FU W"v 4 ,.@t4> 0d$tK?F#:M73d_O v'uc?dɒ%m6^z%}~_i&V\ʕ+[~a}Qz){96n}󎃭y^ UKUzp~#/gs򽲣[XX>n:ppgƟ:WO0 yxH`?ɔ!B=n߿5i`q6FB>썸6O)^qT6!ވ1aE/_oMY.; ;RӗB[iM7;L7&QZ&h* ?bC_ 'wuIٿ"W|\wuM͞=eLn"9Nzz:m"=,|bEt,Ksȝ/.WIbk)a!׌n& Z˔o\Om?\sGpx<.[tW]{XCR0FSyH=L.x%~jo쀩eIqc`8n 96WuJJ&I\n0\0hô k iYWO4LN~%~sMlMou!c4&T GbrhRez=85LS'$a\hT/v?݌;+$, 6G_4_#MֺP߿rqff&E/ąkbVYnWApw]MK3#.|$u*{X < khcQE Uo`C0.v(`g Ɇ-iJPVv3`*,l([k(Xj?]rhçTQy9xK<(9GÌ*+quU* l(-}v:h[Ͷ9+QOK!2=,$O`jMuc6&xċ'ƕjKH\ |H0G|2`Kp"'VΉ~&NmHl0ҎGd׌+J'lS  J[֩u|B2SO?X#`sxe /4XM- WmaSs4kTd1>vT}jf X,YѶq}4n6O[oo:xÆU:_vHݰ ңʜ)]vI"5My|4<1J E^[ 9ɦj*{ 3b má{f+ /Ҳ$;$J>xKdF$ o x-4ʎtlR'cK)j=jکaܕ:AG{9 aUJS,fo$nux}gz{-:<գ Uȟ\K"D# I2{h{Q=Oį54&*&:d"^_L'=iʟX2Z V+;vn>xYqGe{#L<2N$D'$*,"]D⮁^t1mee%唕a]GGF;d|g,83p}O/*X>nI鶛4x*௼⸎Ky}lnyn{4 7ZɆgp&~JK[VR?BY$MJb•U6Qkro^h3i;PRƎ"A,:WPm)XdѤJ\dTvbɷؾ 3/UsT^Q 瀀W&ͮAU}Z-Sףu'%_dp!#n]8jLc<@5xMxS(sWzKv#|i L7c=Q\ʮ]7i$fP^{x%GuF7_/Y{q^ >J,f&}!ɿ/pYgrofmKSL_:$wgƣ M+v(`o" lscVǶnoi̹f~MI한66ذJ# i0,!$4ԈNErWThBz@#3/QQcfڸ+[.h(PChIpxnb6ӣL1]V ݳr~=XVtcHX=eyDG5D݂co-]# \pj֯_tv65Oۻ8\m](XqĔQD[42-qI{z7_\}֯_Ϲ>`Zt]oQ)pҤI 2)%Bk,Z{cc3pb&{@GI'wTUvMo]n&N-߿xCGKE ?RY=&G la@ix-x5., 9 {5yQp96#$)54*[㨞ٵY}oX\:Eyk.z@-t9/&SrFd/ߨuQ}{&p~$au7#+TSSb"0%=PwP7h8X?hTXz &0Аh8%&+B/fǦX[uЅNLŁ+ -ݏnw ֨m~iw>r8~k^*!, v&߸(ʀV~(?m݂DI9 dO뱯C.8wNN' ~1EPO佃CH&nvq@5jLLvr]=u`4*CUE{߮Kڸ㚿%tFQC<$c"ETZ4rK`#-́BSTitt=57n̓KaL'GռJh44B9Lđ6tp$艘.C^OMu =Ps!ǟj0G0-ۅ[Yw6!۶X,>UJjҗeR OIwޚߞ6<X Etpa\MMG3,Mav!቟iS_s3CIiSq"Z-mF$&ŕBĎ/{{O {~ֳˇ}{ŸPA=Z|)M뽑^,U߿y@[ i8A lȗ;vN(K_D͂˾JWJݗer㮻:ߓR_^ _fE/zqVMF<^μXkW=ovVu[C@} (TT9pCUt-P1HIE/8FsNOee%`)%>}ljӋ^]G Ym= oUߚR'R9Wk!tp{WS_o_=O>$~#GqyU^GÑ#`AZ'#μ\ ׏XUqh'lneڿ]ɩi9O\μ|Uwֹ~oJ5; (ugnC`/ƧqTq>0զ7[WZ@FMJ;Œ~ 6nߘ?&!mu#amLI1ߘu,oޝ55tIzaaa9_J[oŭފ_o?~-`wٴr b 3dhYX _~$⏩i-Z믿NCCCm+FU>b_Fɛ ~o]|{~<Wk]y E5Δ#})}v*Ϳj`+' zfk$.qM NہP\ښo67_8ZOZmkJm+X~~~qdߑ{Iߞ]ѷdׄc%?8HJJv75,L$##X,+tMZ|iSK_{o9g֓> E7ŕqy@k5ܯݾlbmѣYzQ@s,7>:kW=._=8j8ߛnxs!Ny@n[StT| dk[@z)BϏ9'Q}'4l+`W.gsNoE[߸1gOOP.'O^X7qoHn4SRSSCii)@E5Ϥ$|>q6~KKEjj*K.eСjB y'5k}W FfӦ"OV+ʛ4QFw&~i?jR#6Dp$xt"pig:Ae>/풒yWk{{Rn^Ep* '[9v :4ILL׿5֭cӦM̟?g}<L0֮]˴iӈD"]>ŋ1b6D>nhi0M!@^{ 3f`ƌ /HKKs% |e:=1JWF Q@f4T~;qmYI7@^T cRցV" \ʝ=*h]Rv`G"\pk׮e!x<8pI&nݺc[|޷Oԙb -ͬkGX*2'ut{xȧu4Ld}a˖-3UV5iuuu׏H$Bjj*a0uTYv-}ŶmnW@FH 0my3vX^WD"MϞ={[f <|k_N`wY&ͷڣ?_EqRrPćK1 owb׻bV$IGHM(>&DmoKAmLeKH Ed3ga0c H))**?䢋.jW,s$] ƶ౸U硸}_Qӿ!n1I|? < ,F_OdtF%cqqގ-gYElx@@bJRL´SaJ3PRzs?t 4e#[r޲ۀ߼\l>|P~b"~Dɟ/VV.WO lmދX hooG?QtttoK//zTUoUCz+P^O%zW#V*\k:y} b ~}^ @;Y2XmSSSd2 Ya&A@Xmۈbؽ{7vڅg}iPK^T^BS oqg?//EA{{;|A|޽x;.<Ýwމ7MxЇՅ\}{=߭OlSQ?=s[:ox$dew,'VV_[֜Y~ތ nsOـ宼ЮU@5:r;---|2.^FH{A"__s#p |Yԓ,kX8(Wwx;t_hđ$ ssslqe$  tk\g!IZOÖaŋO~8{lwM7wwߏ߁$I򗿌/| 0Mԧ> cTq||<TUeTCVN|6`˟|3FH_rH2c\_/ GY2pfP4TZ9[nAKK b1D"WBQtvvP(Օ~ˊ xaUVXq}gJի.|Gi XF( RvYvui$IBT,ˈD"me= )* mۈ4|Ÿ@e9s&,_3(x $ À(Go6>O~7q|ӟ~xN]W&gE^f~WƊ1B'M~]ՈIة-||jǫZh =яz(H^TZP4AfeOs]4F)Կv?${mPU5\vߵk:;;199V8dW芰E;/Z=zԧpe(Ox} tw(xbk =^|EtwwСCx1;; 0p*sW_,be% Y >z<bB=V6+-$*U ء~o>[~+JBaNP^D뎫G?xnB4Cێ?yg%X g Oï~[u?Qy}킷v?lpDQ(owvvbffiqXՔ%jt+aہ;[oى'D"$,'?I!.]OS;v gqw㮻Bkk+^~ec=K>{q|իWw^LOO?GFonox$&,o2O,{c6- $h,;}yfhe=~o௑z=hdFK_GvI:::0>>o,̙3سg4MÏc>}X y{f?Z>@CCwuWM ._2N]‡>!9sT ?OQ.nV8tv؁;v`xxo|x[Ѿɓ?-M<|,H/*S0Y.]]޿P &@]~Dp->ebXk~V G"o$xCc?_((?z5 hdFv \sG?~Յ9ض__ٳgO"gr >ܹs/D"> G?8X }/&''m Y  ۷/Ν;08ܹsFhmm]w݅~ݛ/w^}r+hkX8 ow@BgWJ% ˱ߟ>{}9KU?447GyaxߖN3u.e| |G/^%x_e@oϕJePN\fďogd;B_qxgyO>$.\> YiR$Ii(4 "… {ow ҄ އ3VTò8%WPW?>%*Ž]=;}94oߎ*]KAwAxse,$^:p$?[WZC?>__EWW^y<䓰mO<>a޽a݀|]w݅__N:;Ǐi_E؍^g]& J#P4"hSG[ (r};ξSKe;?)lM67lwnݻT e~7,W}cH&O~}s={ .] ⡇BP~=zgp}W_ťK|;nÿKD./ W|P=p@`羏8#Vq?ǞM߿[ewG;oz~AqGO>?/7ϣv>*=Ve{l*Mtb8(l?xBGgkS_ߺ7? /l&[yzkx۶m|Ư_*ẃ x]qJW\m|3A&.$/2\9 ͘/ v;:V,>r"o?\>mmmv /l}w-FN>/ש T  GPu 8enߝq#Gu&DT~vmpw;\:;wv?@E {X8gތA%I|s_OulO>urv{ޕJ] wVX~Kz?%MkO%P*/Ӊ_1Kߪ\V/q`5uhFgogbEoo5z2Xxehz|{V@{,~9[_''{z3˿$VU^#@AժwT.~:}kw= & SX>ovbzzN>]H+ٓ=~C}*^=\~]-dd'Ch']V6紕k=w|nߺ~ b[7|3 ".^۶q-|˗Æ\,G1??AŽr{Akk+'oiY2= 2dT>MmS5݁k_ym}7qBֳo> O~@\+JpP~VmD"C4HyJ%#LBxQa6< [k;=`{^NB EBA2ʎ†4,<(e("KyLOn]ׅiaWyXX,H$qpʕI8PmB۶iZ/ ߙQR[t@UDT <ի, xՋa @B5=˲ ].(fPWd:;BPgމD$aff/n6q(VLOOT*#C4p?χ?Hq8 $I D"Y=  y(m* X~@0,6r\˅nMBt#™~fBJ@:a@$nL/ᄒfz+˯mm§VAcIT\_fQ$E+hjP6dMEH,cn~w($f?qʲ~@+Ű]\EQ¥yu,[.]yp]b1| T6= ope̟3!T]C nɅ=c4QD⍭Rpy.2`Oj`BkA$K%bD5]^1$); yvIFiN yp"Қq" J$ɅH߼# ;=f,E?Tn(0._t>z0y%s#``Ϟ=PUb1,u r5 (b*сd2.(( E{@ii0^@[a])*AI#Rհ.-g mo @~d@u˳<3/ʄ?Oۇ?vv6n" pBM6w$XX~ VTD3Br"%bWY)EȪE-l(ͫ%Hua ']_4'׽%0U\%{,߻d`Wmmm,+F, ?$ ǩqɲbRRQ( 4Mib(JAgggm_X.JW 2\ۅ<<ǟ+IPwPvh5xP*› XFHxb9 p+~ h[ IDATu?S9S[e̙Q|?zw!RUSg"g!gE%Ē1V3۲¿[ gxB]Dk/ 1< AbuQɃ$ """% &DeWv(\,˂q2TEA2X4(aꕙN؟yP---0MxmmmP$sssr(a`sNp_X|>RT2ri-U- T][گ}o!OTQ/ /Dc;;;GF%`,eUB:.DE|B -i$6MwwIry:L\(wV( 8p`0c 5xQEa\a[?o@Ԥp@G|O<&JCY(\l#  ]S8C(Ku(iPWv k%)KbV~JU:UK"rK ,X));J.Yg`jzzռ۶6 jmm)d@4\?;; 0zHR $[?H.emC+3:<(@گ{ },/\߭/J՞Z x:HFH&iV/J"dYڒCu`Uiq_ %!+WLs]wI7%%"˗qq| UUEW*.W Ah4ZrȲH$bX,V8DQ AF>sW@T~ꙺWy0 A~1@`qU|J`Qb[g@X)׏'JlU87k./{U++u t<~}UZzW.1]XDu]VS%<ǟH$"D,LNN\.iTJX mmm󘝝EXD{{;8l}5jp=1l[3_6@ __`Ȼ@3 d<<ؿ>_mUME.#A%%Dc-?o1>c@\ u' ౫rM+ PE"$]%W*tE#?Smj$IB<|> d ^$IDPOݻwqLOO#χP(®A,C$A.åKz EGBA0ٯ:FWW}¹lA씁)[ W&&ĵsggCIT2vx<vDTfggw^XASY(Jy133&+Aa؃r=+O(O21*֌VE 5~V+5JE OU~&}aC4<<\1&! v_5$(2✶@] @E/YD\hu &]__nT(s͈b̼2( mzjPblGG4M(H$hooHRBGGGTTD"عs'ى6BءY. e 1!s(](ra@uaUT^TBR Wlf?W o6-ȫ e krh[FT:073\!Aʰ <!R\w-u"( HWE@] S}nf$ՁU9 `6^x1< "(Ҵaffb1lD%|>d2 `F 8- 28N JdXX,bΝ6<w! P uo,B#ROJ6` @uu)ɻ .V ޼ K3V {%fo! ¶lί9hMMN# ٞD-H,)sŕz%cLVVg!"XC]p bi"dHo$@\% |8y_&@8Dam`/>@:dr|>BA0;;`~~33ttt,J%#[ O%]μKy@[Pn|g$@=ʗEWE;oʅ8nZJ}7&y3C!_DhAEUЦbRnC]DE#**K?$\JĆ)/<=hWM^87] v&m%W6C\p ]Uݔ𖤃y3MA4+}Uꕂy?Xi$i<0j}A_Kv킦ism;l$2; "fggT*a׮]#B^ey_IX(gR\.'gC!U|D@qi<xRZ$^gB6bRZTEиZV*5gtK %b/" 7*zHH Uic" CZq.w?o]4O’E(0Vw$ xY xk,*JXwqaDvb1EJ@Cze@9P3P(077D"D"UU+˗tBLByg e׫ 2  B/81`@i硘/5jԆ8~@Ձ(:f!H lps %2hrZe *@$҂x<_ BEyAP(`YvY4"@)IJ!*.m d@쒪N,*5\;Ƿw#9? !E]huC1p333Z"bL^@uuD"bUUkN9^+9 ᩄ`lPӾ'cbQ=/t /.jGh}oBZ+q- G,BP@"EXmѿ oq o@Ӵ0X* UAO^߫YLֿ᷄%m%!wpԿ|/!du _~~KzO&ﯹJ0<< 0066%TO?_>s۶tt:]냪d2fFooo~F駟~t7gy>%#3`7g7@B1 u{Bnv-|^?!48yy=& }{B_ `g7ֿۆa@XZ2H$iZxlV5O?׆Ss2uŷ=ߏL&S"J|=Ju5Ġ~駿Mon̗\.#G@U՚BMQPX:֜g~iM2VBDXڲSccc8uԒ(`VO?׈ ?yhhzןL&166X07Z6E:;RUGKUo<4qiO?7] \,W ز,L&l6nYO?O? CCC!rCJBB!0 Be+.9a n$ h[U\O?Os5>zhxn#L&l6nYO?O? CCC!rCJBB!0 Be+.9a n$ h[U\O?Os5>zhxn#L&l6nYO?O? CCC!rCJBB!0 Be+.9a n$ h[U\O?Os5>zhxn#>>>>>{8yS$ʲL :zW&@""""""b ""dns^Ղ]BpW!tx}{{ۿp$*BUURrRWWWZ#ޫ:]__3ZDT^]ι gExݎ6mǽ?۶G Q,Ktss3z:JM+v웰֪,K5Mo 7}uޱ~]?g4ڶۭٙ=SD dxb4MtO:y;u-c...$Bޫi sϻ%*EQ4MUZ~al$""b """"""b """"""b """"""b """"""b """""":i_ukcXAl1ZZczss*\Y:UUKhj6key?M4M#km񮺮DZPAu]AJY{^tzg1rΩѭB?DQ,2giZvg \zon3즐b!T2|8a(RQrW۶l6{SL>>>>>>{8yS$ʲL :zW&@""""""b ""dns^Ղ]BpW!tx}{{ۿp$*BUURrRWWWZ#ޫ:]__3ZDT^]ι gExݎ6mǽ?۶G Q,Ktss3z:JM+v웰֪,K5Mo 7}uޱ~]?g4ڶۭٙ=SD dxb4MtO:y;u-c...$Bޫi sϻ%*EQ4MUZ~al$""b """"""b """"""b """"""b """"""b """""":i_ukcXAl1ZZczss*\Y:UUKhj6key?M4M#km񮺮DZPAu]AJY{^tzg1rΩѭB?DQ,2giZvg \zon3즐b!T2|8a(RQrW۶l6{SL>>>>>>{8yS$ʲL :zW&@""""""b ""dns^Ղ]BpW!tx}{{ۿp$*BUURrRWWWZ#ޫ:]__3ZDT^]ι gExݎ6mǽ?۶G Q,Ktss3z:JM+v웰֪,K5Mo 7}uޱ~]?g4ڶۭٙ=SD dxb4MtO:y;u-c...$Bޫi sϻ%*EQ4MUZ~al$""b """"""b """"""b """"""b """"""b """""":i_ukcXAl1ZZczss*\Y:UUKhj6key?M4M#km񮺮DZPAu]AJY{^tzg1rΩѭB?DQ,2giZvg \zon3즐b!T2|8a(RQrW۶l6{SL>>>>>>{8yS$ʲL :zW&@""""""b ""dns^Ղ]BpW!tx}{{ۿp$*BUURrRWWWZ#ޫ:]__3ZDT^]ι gExݎ6mǽ?۶G Q,Ktss3z:JM+v웰֪,K5Mo 7}uޱ~]?g4ڶۭٙ=SD dxb4MtO:y;u-c...$Bޫi sϻ%*EQ4MUZ~al$""b """"""b """"""?>]GQIENDB`tiled-1.0.3/src/plugins/flare/000077500000000000000000000000001315121121300161435ustar00rootroot00000000000000tiled-1.0.3/src/plugins/flare/flare.pro000066400000000000000000000002431315121121300177550ustar00rootroot00000000000000include(../plugin.pri) DEFINES += FLARE_LIBRARY HEADERS += \ flare_global.h \ flareplugin.h SOURCES += \ flareplugin.cpp OTHER_FILES = plugin.json tiled-1.0.3/src/plugins/flare/flare.qbs000066400000000000000000000002741315121121300177460ustar00rootroot00000000000000import qbs 1.0 TiledPlugin { cpp.defines: ["FLARE_LIBRARY"] files: [ "flare_global.h", "flareplugin.cpp", "flareplugin.h", "plugin.json", ] } tiled-1.0.3/src/plugins/flare/flare_global.h000066400000000000000000000017451315121121300207340ustar00rootroot00000000000000/* * Flare Tiled Plugin * Copyright 2010, Jaderamiso * Copyright 2011, Stefan Beller * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #if defined(FLARE_LIBRARY) # define FLARESHARED_EXPORT Q_DECL_EXPORT #else # define FLARESHARED_EXPORT Q_DECL_IMPORT #endif tiled-1.0.3/src/plugins/flare/flareplugin.cpp000066400000000000000000000336731315121121300211730ustar00rootroot00000000000000/* * Flare Tiled Plugin * Copyright 2010, Jaderamiso * Copyright 2011, Stefan Beller * Copyright 2011, Clint Bellanger * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "flareplugin.h" #include "gidmapper.h" #include "map.h" #include "mapobject.h" #include "savefile.h" #include "tile.h" #include "tilelayer.h" #include "tileset.h" #include "objectgroup.h" #include #include #include #include #include using namespace Tiled; namespace Flare { FlarePlugin::FlarePlugin() { } Tiled::Map *FlarePlugin::read(const QString &fileName) { QFile file(fileName); if (!file.open (QIODevice::ReadOnly)) { mError = tr("Could not open file for reading."); return nullptr; } // default to values of the original flare alpha game. QScopedPointer map(new Map(Map::Isometric, 256, 256, 64, 32)); QTextStream stream (&file); QString line; QString sectionName; bool newsection = false; QString path = QFileInfo(file).absolutePath(); int base = 10; GidMapper gidMapper; int gid = 1; TileLayer *tilelayer = nullptr; ObjectGroup *objectgroup = nullptr; MapObject *mapobject = nullptr; bool tilesetsSectionFound = false; bool headerSectionFound = false; bool tilelayerSectionFound = false; // tile layer or objects while (!stream.atEnd()) { line = stream.readLine(); if (!line.length()) continue; QChar startsWith = line.at(0); if (startsWith == QChar('[')) { sectionName = line.mid(1, line.indexOf(QChar(']')) - 1); newsection = true; continue; } if (sectionName == QLatin1String("header")) { headerSectionFound = true; //get map properties int epos = line.indexOf(QChar('=')); if (epos != -1) { QString key = line.left(epos).trimmed(); QString value = line.mid(epos + 1, -1).trimmed(); if (key == QLatin1String("width")) map->setWidth(value.toInt()); else if (key == QLatin1String("height")) map->setHeight(value.toInt()); else if (key == QLatin1String("tilewidth")) map->setTileWidth(value.toInt()); else if (key == QLatin1String("tileheight")) map->setTileHeight(value.toInt()); else if (key == QLatin1String("orientation")) map->setOrientation(orientationFromString(value)); else map->setProperty(key, value); } } else if (sectionName == QLatin1String("tilesets")) { tilesetsSectionFound = true; int epos = line.indexOf(QChar('=')); QString key = line.left(epos).trimmed(); QString value = line.mid(epos + 1, -1).trimmed(); if (key == QLatin1String("tileset")) { QStringList list = value.split(QChar(',')); QString absoluteSource(list.first()); if (QDir::isRelativePath(absoluteSource)) absoluteSource = path + QLatin1Char('/') + absoluteSource; int tilesetwidth = 0; int tilesetheight = 0; if (list.size() > 2) { tilesetwidth = list[1].toInt(); tilesetheight = list[2].toInt(); } SharedTileset tileset(Tileset::create(QFileInfo(absoluteSource).fileName(), tilesetwidth, tilesetheight)); bool ok = tileset->loadFromImage(absoluteSource); if (!ok) { mError = tr("Error loading tileset %1, which expands to %2. Path not found!") .arg(list[0], absoluteSource); return nullptr; } else { if (list.size() > 4) tileset->setTileOffset(QPoint(list[3].toInt(),list[4].toInt())); gidMapper.insert(gid, tileset.data()); if (list.size() > 5) { gid += list[5].toInt(); } else { gid += tileset->tileCount(); } map->addTileset(tileset); } } } else if (sectionName == QLatin1String("layer")) { if (!tilesetsSectionFound) { mError = tr("No tilesets section found before layer section."); return nullptr; } tilelayerSectionFound = true; int epos = line.indexOf(QChar('=')); if (epos != -1) { QString key = line.left(epos).trimmed(); QString value = line.mid(epos + 1, -1).trimmed(); if (key == QLatin1String("type")) { tilelayer = new TileLayer(value, 0, 0, map->width(),map->height()); map->addLayer(tilelayer); } else if (key == QLatin1String("format")) { if (value == QLatin1String("dec")) { base = 10; } else if (value == QLatin1String("hex")) { base = 16; } } else if (key == QLatin1String("data")) { for (int y=0; y < map->height(); y++) { line = stream.readLine(); QStringList l = line.split(QChar(',')); for (int x=0; x < qMin(map->width(), l.size()); x++) { bool ok; int tileid = l[x].toInt(nullptr, base); Cell c = gidMapper.gidToCell(tileid, ok); if (!ok) { mError += tr("Error mapping tile id %1.").arg(tileid); return nullptr; } tilelayer->setCell(x, y, c); } } } else { tilelayer->setProperty(key, value); } } } else { if (newsection) { if (map->indexOfLayer(sectionName) == -1) { objectgroup = new ObjectGroup(sectionName, 0, 0); map->addLayer(objectgroup); } else { objectgroup = dynamic_cast(map->layerAt(map->indexOfLayer(sectionName))); } mapobject = new MapObject(); objectgroup->addObject(mapobject); newsection = false; } if (!mapobject) continue; if (startsWith == QChar('#')) { QString name = line.mid(1).trimmed(); mapobject->setName(name); } int epos = line.indexOf(QChar('=')); if (epos != -1) { QString key = line.left(epos).trimmed(); QString value = line.mid(epos + 1, -1).trimmed(); if (key == QLatin1String("type")) { mapobject->setType(value); } else if (key == QLatin1String("location")) { QStringList loc = value.split(QChar(',')); float x,y; int w,h; if (map->orientation() == Map::Orthogonal) { x = loc[0].toFloat()*map->tileWidth(); y = loc[1].toFloat()*map->tileHeight(); if (loc.size() > 3) { w = loc[2].toInt()*map->tileWidth(); h = loc[3].toInt()*map->tileHeight(); } else { w = map->tileWidth(); h = map->tileHeight(); } } else { x = loc[0].toFloat()*map->tileHeight(); y = loc[1].toFloat()*map->tileHeight(); if (loc.size() > 3) { w = loc[2].toInt()*map->tileHeight(); h = loc[3].toInt()*map->tileHeight(); } else { w = h = map->tileHeight(); } } mapobject->setPosition(QPointF(x, y)); mapobject->setSize(w, h); } else { mapobject->setProperty(key, value); } } } } if (!headerSectionFound || !tilesetsSectionFound || !tilelayerSectionFound) { mError = tr("This seems to be no valid flare map. " "A Flare map consists of at least a header " "section, a tileset section and one tile layer."); return nullptr; } return map.take(); } bool FlarePlugin::supportsFile(const QString &fileName) const { return fileName.endsWith(QLatin1String(".txt"), Qt::CaseInsensitive); } QString FlarePlugin::nameFilter() const { return tr("Flare map files (*.txt)"); } QString FlarePlugin::shortName() const { return QLatin1String("flare"); } QString FlarePlugin::errorString() const { return mError; } bool FlarePlugin::write(const Tiled::Map *map, const QString &fileName) { SaveFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) { mError = tr("Could not open file for writing."); return false; } QTextStream out(file.device()); out.setCodec("UTF-8"); const int mapWidth = map->width(); const int mapHeight = map->height(); // write [header] out << "[header]\n"; out << "width=" << mapWidth << "\n"; out << "height=" << mapHeight << "\n"; out << "tilewidth=" << map->tileWidth() << "\n"; out << "tileheight=" << map->tileHeight() << "\n"; out << "orientation=" << orientationToString(map->orientation()) << "\n"; // write all properties for this map Properties::const_iterator it = map->properties().constBegin(); Properties::const_iterator it_end = map->properties().constEnd(); for (; it != it_end; ++it) { out << it.key() << "=" << toExportValue(it.value()).toString() << "\n"; } out << "\n"; QDir mapDir = QFileInfo(fileName).absoluteDir(); out << "[tilesets]\n"; for (const SharedTileset &tileset : map->tilesets()) { const QString &imageSource = tileset->imageSource(); QString source = mapDir.relativeFilePath(imageSource); out << "tileset=" << source << "," << tileset->tileWidth() << "," << tileset->tileHeight() << "," << tileset->tileOffset().x() << "," << tileset->tileOffset().y() << "\n"; } out << "\n"; GidMapper gidMapper(map->tilesets()); // write layers for (Layer *layer : map->layers()) { if (TileLayer *tileLayer = layer->asTileLayer()) { out << "[layer]\n"; out << "type=" << layer->name() << "\n"; out << "data=\n"; for (int y = 0; y < mapHeight; ++y) { for (int x = 0; x < mapWidth; ++x) { Cell t = tileLayer->cellAt(x, y); int id = gidMapper.cellToGid(t); out << id; if (x < mapWidth - 1) out << ","; } if (y < mapHeight - 1) out << ","; out << "\n"; } out << "\n"; } if (ObjectGroup *group = layer->asObjectGroup()) { for (const MapObject *o : group->objects()) { if (!o->type().isEmpty()) { out << "[" << group->name() << "]\n"; // display object name as comment if (!o->name().isEmpty()) out << "# " << o->name() << "\n"; out << "type=" << o->type() << "\n"; int x,y,w,h; if (map->orientation() == Map::Orthogonal) { x = o->x()/map->tileWidth(); y = o->y()/map->tileHeight(); w = o->width()/map->tileWidth(); h = o->height()/map->tileHeight(); } else { x = o->x()/map->tileHeight(); y = o->y()/map->tileHeight(); w = o->width()/map->tileHeight(); h = o->height()/map->tileHeight(); } out << "location=" << x << "," << y; out << "," << w << "," << h << "\n"; // write all properties for this object Properties::const_iterator it = o->properties().constBegin(); Properties::const_iterator it_end = o->properties().constEnd(); for (; it != it_end; ++it) { out << it.key() << "=" << it.value().toString() << "\n"; } out << "\n"; } } } } if (!file.commit()) { mError = file.errorString(); return false; } return true; } } // namespace Flare tiled-1.0.3/src/plugins/flare/flareplugin.h000066400000000000000000000027751315121121300206370ustar00rootroot00000000000000/* * Flare Tiled Plugin * Copyright 2010, Jaderamiso * Copyright 2011, Stefan Beller * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "flare_global.h" #include "mapformat.h" #include #include namespace Flare { class FLARESHARED_EXPORT FlarePlugin : public Tiled::MapFormat { Q_OBJECT Q_INTERFACES(Tiled::MapFormat) Q_PLUGIN_METADATA(IID "org.mapeditor.MapFormat" FILE "plugin.json") public: FlarePlugin(); Tiled::Map *read(const QString &fileName) override; bool supportsFile(const QString &fileName) const override; bool write(const Tiled::Map *map, const QString &fileName) override; QString nameFilter() const override; QString shortName() const override; QString errorString() const override; private: QString mError; }; } // namespace Flare tiled-1.0.3/src/plugins/flare/plugin.json000066400000000000000000000000331315121121300203300ustar00rootroot00000000000000{ "defaultEnable": false } tiled-1.0.3/src/plugins/gmx/000077500000000000000000000000001315121121300156455ustar00rootroot00000000000000tiled-1.0.3/src/plugins/gmx/gmx.pro000066400000000000000000000001631315121121300171620ustar00rootroot00000000000000include(../plugin.pri) DEFINES += GMX_LIBRARY SOURCES += gmxplugin.cpp HEADERS += gmxplugin.h \ gmx_global.h tiled-1.0.3/src/plugins/gmx/gmx.qbs000066400000000000000000000002641315121121300171510ustar00rootroot00000000000000import qbs 1.0 TiledPlugin { cpp.defines: ["GMX_LIBRARY"] files: [ "gmx_global.h", "gmxplugin.cpp", "gmxplugin.h", "plugin.json", ] } tiled-1.0.3/src/plugins/gmx/gmx_global.h000066400000000000000000000016411315121121300201330ustar00rootroot00000000000000/* * GMX Tiled Plugin * Copyright 2016, Jones Blunt * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #if defined(GMX_LIBRARY) # define GMXSHARED_EXPORT Q_DECL_EXPORT #else # define GMXSHARED_EXPORT Q_DECL_IMPORT #endif tiled-1.0.3/src/plugins/gmx/gmxplugin.cpp000066400000000000000000000334051315121121300203700ustar00rootroot00000000000000/* * GMX Tiled Plugin * Copyright 2016, Jones Blunt * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "gmxplugin.h" #include "map.h" #include "savefile.h" #include "tile.h" #include "tilelayer.h" #include "mapobject.h" #include "objectgroup.h" #include #include #include #include using namespace Tiled; using namespace Gmx; template static T optionalProperty(const Object *object, const QString &name, const T &def) { const QVariant var = object->property(name); return var.isValid() ? var.value() : def; } template static QString toString(T number) { return QString::number(number); } static QString toString(bool b) { return QString::number(b ? -1 : 0); } template static void writeProperty(QXmlStreamWriter &writer, const Object *object, const QString &name, const T &def) { const T value = optionalProperty(object, name, def); writer.writeTextElement(name, toString(value)); } static QString sanitizeName(QString name) { static const QRegularExpression regexp(QLatin1String("[^a-zA-Z0-9]")); return name.replace(regexp, QLatin1String("_")); } static QString effectiveObjectType(const MapObject *object) { if (!object->type().isEmpty()) return object->type(); if (Tile *tile = object->cell().tile()) return tile->type(); return QString(); } GmxPlugin::GmxPlugin() { } bool GmxPlugin::write(const Map *map, const QString &fileName) { SaveFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { mError = tr("Could not open file for writing."); return false; } QXmlStreamWriter stream(file.device()); stream.setAutoFormatting(true); stream.setAutoFormattingIndent(2); stream.writeComment("This Document is generated by Tiled, if you edit it by hand then you do so at your own risk!"); stream.writeStartElement("room"); int mapPixelWidth = map->tileWidth() * map->width(); int mapPixelHeight = map->tileHeight() * map->height(); stream.writeTextElement("width", QString::number(mapPixelWidth)); stream.writeTextElement("height", QString::number(mapPixelHeight)); stream.writeTextElement("vsnap", QString::number(map->tileHeight())); stream.writeTextElement("hsnap", QString::number(map->tileWidth())); writeProperty(stream, map, "speed", 30); writeProperty(stream, map, "persistent", false); writeProperty(stream, map, "clearDisplayBuffer", true); stream.writeTextElement("isometric", toString(map->orientation() == Map::Orientation::Isometric)); stream.writeStartElement("instances"); QSet usedNames; int layerCount = 0; // Write out object instances LayerIterator iterator(map); while (const Layer *layer = iterator.next()) { ++layerCount; if (layer->layerType() != Layer::ObjectGroupType) continue; const ObjectGroup *objectLayer = static_cast(layer); for (const MapObject *object : objectLayer->objects()) { const QString type = effectiveObjectType(object); if (type.isEmpty()) continue; stream.writeStartElement("instance"); // The type is used to refer to the name of the object stream.writeAttribute("objName", sanitizeName(type)); QPointF pos = object->position(); qreal scaleX = 1; qreal scaleY = 1; if (!object->cell().isEmpty()) { // Tile objects have bottom-left origin in Tiled, so the // position needs to be translated for top-left origin in // GameMaker, taking into account the rotation. QTransform transform; transform.rotate(object->rotation()); pos += transform.map(QPointF(0, -object->height())); // For tile objects we can support scaling and flipping, though // flipping in combination with rotation doesn't work in GameMaker. if (auto tile = object->cell().tile()) { const QSize tileSize = tile->size(); scaleX = object->width() / tileSize.width(); scaleY = object->height() / tileSize.height(); if (object->cell().flippedHorizontally()) { scaleX *= -1; pos += transform.map(QPointF(object->width(), 0)); } if (object->cell().flippedVertically()) { scaleY *= -1; pos += transform.map(QPointF(0, object->height())); } } } stream.writeAttribute("x", QString::number(qRound(pos.x()))); stream.writeAttribute("y", QString::number(qRound(pos.y()))); // Include object ID in the name when necessary because duplicates are not allowed if (object->name().isEmpty()) { stream.writeAttribute("name", QString("inst_%1").arg(object->id())); } else { QString name = sanitizeName(object->name()); while (usedNames.contains(name)) name += QString("_%1").arg(object->id()); usedNames.insert(name); stream.writeAttribute("name", name); } stream.writeAttribute("scaleX", QString::number(scaleX)); stream.writeAttribute("scaleY", QString::number(scaleY)); stream.writeAttribute("rotation", QString::number(-object->rotation())); stream.writeEndElement(); } } stream.writeEndElement(); stream.writeStartElement("tiles"); uint tileId = 0u; // Write out tile instances iterator.toFront(); while (const Layer *layer = iterator.next()) { QString depth = QString::number(optionalProperty(layer, QLatin1String("depth"), layerCount)); switch (layer->layerType()) { case Layer::TileLayerType: { auto tileLayer = static_cast(layer); for (int y = 0; y < tileLayer->height(); ++y) { for (int x = 0; x < tileLayer->width(); ++x) { const Cell &cell = tileLayer->cellAt(x, y); if (const Tile *tile = cell.tile()) { const Tileset *tileset = tile->tileset(); stream.writeStartElement("tile"); int pixelX = x * map->tileWidth(); int pixelY = y * map->tileHeight(); qreal scaleX = 1; qreal scaleY = 1; if (cell.flippedHorizontally()) { scaleX = -1; pixelX += tile->width(); } if (cell.flippedVertically()) { scaleY = -1; pixelY += tile->height(); } QString bgName; int xo = 0; int yo = 0; if (tileset->isCollection()) { bgName = QFileInfo(tile->imageSource()).baseName(); } else { bgName = tileset->name(); int xInTilesetGrid = tile->id() % tileset->columnCount(); int yInTilesetGrid = (int)(tile->id() / tileset->columnCount()); xo = tileset->margin() + (tileset->tileSpacing() + tileset->tileWidth()) * xInTilesetGrid; yo = tileset->margin() + (tileset->tileSpacing() + tileset->tileHeight()) * yInTilesetGrid; } stream.writeAttribute("bgName", bgName); stream.writeAttribute("x", QString::number(pixelX)); stream.writeAttribute("y", QString::number(pixelY)); stream.writeAttribute("w", QString::number(tile->width())); stream.writeAttribute("h", QString::number(tile->height())); stream.writeAttribute("xo", QString::number(xo)); stream.writeAttribute("yo", QString::number(yo)); stream.writeAttribute("id", QString::number(++tileId)); stream.writeAttribute("depth", depth); stream.writeAttribute("scaleX", QString::number(scaleX)); stream.writeAttribute("scaleY", QString::number(scaleY)); stream.writeEndElement(); } } } break; } case Layer::ObjectGroupType: { auto objectGroup = static_cast(layer); auto objects = objectGroup->objects(); // Make sure the objects export in the rendering order if (objectGroup->drawOrder() == ObjectGroup::TopDownOrder) { qStableSort(objects.begin(), objects.end(), [](const MapObject *a, const MapObject *b) { return a->y() < b->y(); }); } foreach (const MapObject *object, objects) { // Objects with types are already exported as instances if (!effectiveObjectType(object).isEmpty()) continue; // Non-typed tile objects are exported as tiles. Rotation is // not supported here, but scaling is. if (const Tile *tile = object->cell().tile()) { const Tileset *tileset = tile->tileset(); const QSize tileSize = tile->size(); qreal scaleX = object->width() / tileSize.width(); qreal scaleY = object->height() / tileSize.height(); qreal x = object->x(); qreal y = object->y() - object->height(); if (object->cell().flippedHorizontally()) { scaleX *= -1; x += object->width(); } if (object->cell().flippedVertically()) { scaleY *= -1; y += object->height(); } stream.writeStartElement("tile"); QString bgName; int xo = 0; int yo = 0; if (tileset->isCollection()) { bgName = QFileInfo(tile->imageSource()).baseName(); } else { bgName = tileset->name(); int xInTilesetGrid = tile->id() % tileset->columnCount(); int yInTilesetGrid = (int)(tile->id() / tileset->columnCount()); xo = tileset->margin() + (tileset->tileSpacing() + tileset->tileWidth()) * xInTilesetGrid; yo = tileset->margin() + (tileset->tileSpacing() + tileset->tileHeight()) * yInTilesetGrid; } stream.writeAttribute("bgName", bgName); stream.writeAttribute("x", QString::number(qRound(x))); stream.writeAttribute("y", QString::number(qRound(y))); stream.writeAttribute("w", QString::number(tile->width())); stream.writeAttribute("h", QString::number(tile->height())); stream.writeAttribute("xo", QString::number(xo)); stream.writeAttribute("yo", QString::number(yo)); stream.writeAttribute("id", QString::number(++tileId)); stream.writeAttribute("depth", depth); stream.writeAttribute("scaleX", QString::number(scaleX)); stream.writeAttribute("scaleY", QString::number(scaleY)); stream.writeEndElement(); } } break; } case Layer::ImageLayerType: // todo: maybe export as backgrounds? break; case Layer::GroupLayerType: // Recursion handled by LayerIterator break; } --layerCount; } stream.writeEndElement(); writeProperty(stream, map, "PhysicsWorld", false); writeProperty(stream, map, "PhysicsWorldTop", 0); writeProperty(stream, map, "PhysicsWorldLeft", 0); writeProperty(stream, map, "PhysicsWorldRight", mapPixelWidth); writeProperty(stream, map, "PhysicsWorldBottom", mapPixelHeight); writeProperty(stream, map, "PhysicsWorldGravityX", 0.0); writeProperty(stream, map, "PhysicsWorldGravityY", 10.0); writeProperty(stream, map, "PhysicsWorldPixToMeters", 0.1); stream.writeEndDocument(); if (!file.commit()) { mError = file.errorString(); return false; } return true; } QString GmxPlugin::errorString() const { return mError; } QString GmxPlugin::nameFilter() const { return tr("GameMaker room files (*.room.gmx)"); } QString GmxPlugin::shortName() const { return QLatin1String("gmx"); } tiled-1.0.3/src/plugins/gmx/gmxplugin.h000066400000000000000000000024101315121121300200250ustar00rootroot00000000000000/* * GMX Tiled Plugin * Copyright 2016, Jones Blunt * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "mapformat.h" #include "gmx_global.h" namespace Gmx { class GMXSHARED_EXPORT GmxPlugin : public Tiled::WritableMapFormat { Q_OBJECT Q_PLUGIN_METADATA(IID "org.mapeditor.MapFormat" FILE "plugin.json") public: GmxPlugin(); bool write(const Tiled::Map *map, const QString &fileName) override; QString errorString() const override; QString shortName() const override; protected: QString nameFilter() const override; private: QString mError; }; } // namespace Gmx tiled-1.0.3/src/plugins/gmx/plugin.json000066400000000000000000000000321315121121300200310ustar00rootroot00000000000000{ "defaultEnable": true } tiled-1.0.3/src/plugins/json/000077500000000000000000000000001315121121300160235ustar00rootroot00000000000000tiled-1.0.3/src/plugins/json/json.pro000066400000000000000000000002541315121121300175170ustar00rootroot00000000000000include(../plugin.pri) DEFINES += JSON_LIBRARY SOURCES += jsonplugin.cpp \ qjsonparser/json.cpp HEADERS += jsonplugin.h \ json_global.h \ qjsonparser/json.h tiled-1.0.3/src/plugins/json/json.qbs000066400000000000000000000003661315121121300175100ustar00rootroot00000000000000import qbs 1.0 TiledPlugin { cpp.defines: ["JSON_LIBRARY"] files: [ "json_global.h", "jsonplugin.cpp", "jsonplugin.h", "plugin.json", "qjsonparser/json.cpp", "qjsonparser/json.h", ] } tiled-1.0.3/src/plugins/json/json_global.h000066400000000000000000000017751315121121300204770ustar00rootroot00000000000000/* * JSON Tiled Plugin * Copyright 2011, Porfírio José Pereira Ribeiro * Copyright 2011, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #if defined(JSON_LIBRARY) # define JSONSHARED_EXPORT Q_DECL_EXPORT #else # define JSONSHARED_EXPORT Q_DECL_IMPORT #endif tiled-1.0.3/src/plugins/json/jsonplugin.cpp000066400000000000000000000217521315121121300207260ustar00rootroot00000000000000/* * JSON Tiled Plugin * Copyright 2011, Porfírio José Pereira Ribeiro * Copyright 2011, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "jsonplugin.h" #include "maptovariantconverter.h" #include "varianttomapconverter.h" #include "savefile.h" #include "qjsonparser/json.h" #include #include #include #include #include namespace Json { void JsonPlugin::initialize() { addObject(new JsonMapFormat(JsonMapFormat::Json, this)); addObject(new JsonMapFormat(JsonMapFormat::JavaScript, this)); addObject(new JsonTilesetFormat(this)); } JsonMapFormat::JsonMapFormat(SubFormat subFormat, QObject *parent) : Tiled::MapFormat(parent) , mSubFormat(subFormat) {} Tiled::Map *JsonMapFormat::read(const QString &fileName) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { mError = tr("Could not open file for reading."); return nullptr; } JsonReader reader; QByteArray contents = file.readAll(); if (mSubFormat == JavaScript && contents.size() > 0 && contents[0] != '{') { // Scan past JSONP prefix; look for an open curly at the start of the line int i = contents.indexOf(QLatin1String("\n{")); if (i > 0) { contents.remove(0, i); contents = contents.trimmed(); // potential trailing whitespace if (contents.endsWith(';')) contents.chop(1); if (contents.endsWith(')')) contents.chop(1); } } reader.parse(contents); const QVariant variant = reader.result(); if (!variant.isValid()) { mError = tr("Error parsing file."); return nullptr; } Tiled::VariantToMapConverter converter; Tiled::Map *map = converter.toMap(variant, QFileInfo(fileName).dir()); if (!map) mError = converter.errorString(); return map; } bool JsonMapFormat::write(const Tiled::Map *map, const QString &fileName) { Tiled::SaveFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { mError = tr("Could not open file for writing."); return false; } Tiled::MapToVariantConverter converter; QVariant variant = converter.toVariant(*map, QFileInfo(fileName).dir()); JsonWriter writer; writer.setAutoFormatting(true); if (!writer.stringify(variant)) { // This can only happen due to coding error mError = writer.errorString(); return false; } QTextStream out(file.device()); if (mSubFormat == JavaScript) { // Trim and escape name JsonWriter nameWriter; QString baseName = QFileInfo(fileName).baseName(); nameWriter.stringify(baseName); out << "(function(name,data){\n if(typeof onTileMapLoaded === 'undefined') {\n"; out << " if(typeof TileMaps === 'undefined') TileMaps = {};\n"; out << " TileMaps[name] = data;\n"; out << " } else {\n"; out << " onTileMapLoaded(name,data);\n"; out << " }\n"; out << " if(typeof module === 'object' && module && module.exports) {\n"; out << " module.exports = data;\n"; out << " }})(" << nameWriter.result() << ",\n"; } out << writer.result(); if (mSubFormat == JavaScript) { out << ");"; } out.flush(); if (file.error() != QFileDevice::NoError) { mError = tr("Error while writing file:\n%1").arg(file.errorString()); return false; } if (!file.commit()) { mError = file.errorString(); return false; } return true; } QString JsonMapFormat::nameFilter() const { if (mSubFormat == Json) return tr("Json map files (*.json)"); else return tr("JavaScript map files (*.js)"); } QString JsonMapFormat::shortName() const { if (mSubFormat == Json) return QLatin1String("json"); else return QLatin1String("js"); } bool JsonMapFormat::supportsFile(const QString &fileName) const { if (mSubFormat == Json) { if (!fileName.endsWith(QLatin1String(".json"), Qt::CaseInsensitive)) return false; } else { if (!fileName.endsWith(QLatin1String(".js"), Qt::CaseInsensitive)) return false; } QFile file(fileName); if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { QByteArray contents = file.readAll(); if (mSubFormat == JavaScript && contents.size() > 0 && contents[0] != '{') { // Scan past JSONP prefix; look for an open curly at the start of the line int i = contents.indexOf(QLatin1String("\n{")); if (i > 0) { contents.remove(0, i); contents = contents.trimmed(); // potential trailing whitespace if (contents.endsWith(';')) contents.chop(1); if (contents.endsWith(')')) contents.chop(1); } } const QJsonObject object = QJsonDocument::fromJson(contents).object(); // This is a good indication, but not present in older map files if (object.value(QLatin1String("type")).toString() == QLatin1String("map")) return true; // Guess based on expected property if (object.contains(QLatin1String("orientation"))) return true; } return false; } QString JsonMapFormat::errorString() const { return mError; } JsonTilesetFormat::JsonTilesetFormat(QObject *parent) : Tiled::TilesetFormat(parent) { } Tiled::SharedTileset JsonTilesetFormat::read(const QString &fileName) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { mError = tr("Could not open file for reading."); return Tiled::SharedTileset(); } JsonReader reader; QByteArray contents = file.readAll(); reader.parse(contents); const QVariant variant = reader.result(); if (!variant.isValid()) { mError = tr("Error parsing file."); return Tiled::SharedTileset(); } Tiled::VariantToMapConverter converter; Tiled::SharedTileset tileset = converter.toTileset(variant, QFileInfo(fileName).dir()); if (!tileset) mError = converter.errorString(); else tileset->setFileName(fileName); return tileset; } bool JsonTilesetFormat::supportsFile(const QString &fileName) const { if (fileName.endsWith(QLatin1String(".json"), Qt::CaseInsensitive)) { QFile file(fileName); if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { const QJsonObject object = QJsonDocument::fromJson(file.readAll()).object(); // This is a good indication, but not present in older external tilesets if (object.value(QLatin1String("type")).toString() == QLatin1String("tileset")) return true; // Guess based on some expected properties if (object.contains(QLatin1String("name")) && object.contains(QLatin1String("tilewidth")) && object.contains(QLatin1String("tileheight"))) return true; } } return false; } bool JsonTilesetFormat::write(const Tiled::Tileset &tileset, const QString &fileName) { Tiled::SaveFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { mError = tr("Could not open file for writing."); return false; } Tiled::MapToVariantConverter converter; QVariant variant = converter.toVariant(tileset, QFileInfo(fileName).dir()); JsonWriter writer; writer.setAutoFormatting(true); if (!writer.stringify(variant)) { // This can only happen due to coding error mError = writer.errorString(); return false; } QTextStream out(file.device()); out << writer.result(); out.flush(); if (file.error() != QFileDevice::NoError) { mError = tr("Error while writing file:\n%1").arg(file.errorString()); return false; } if (!file.commit()) { mError = file.errorString(); return false; } return true; } QString JsonTilesetFormat::nameFilter() const { return tr("Json tileset files (*.json)"); } QString JsonTilesetFormat::shortName() const { return QLatin1String("json"); } QString JsonTilesetFormat::errorString() const { return mError; } } // namespace Json tiled-1.0.3/src/plugins/json/jsonplugin.h000066400000000000000000000046421315121121300203720ustar00rootroot00000000000000/* * JSON Tiled Plugin * Copyright 2011, Porfírio José Pereira Ribeiro * Copyright 2011, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "json_global.h" #include "mapformat.h" #include "plugin.h" #include "tilesetformat.h" #include namespace Tiled { class Map; } namespace Json { class JSONSHARED_EXPORT JsonPlugin : public Tiled::Plugin { Q_OBJECT Q_INTERFACES(Tiled::Plugin) Q_PLUGIN_METADATA(IID "org.mapeditor.Plugin" FILE "plugin.json") public: void initialize() override; }; class JSONSHARED_EXPORT JsonMapFormat : public Tiled::MapFormat { Q_OBJECT Q_INTERFACES(Tiled::MapFormat) public: enum SubFormat { Json, JavaScript, }; JsonMapFormat(SubFormat subFormat, QObject *parent = nullptr); Tiled::Map *read(const QString &fileName) override; bool supportsFile(const QString &fileName) const override; bool write(const Tiled::Map *map, const QString &fileName) override; QString nameFilter() const override; QString shortName() const override; QString errorString() const override; protected: QString mError; SubFormat mSubFormat; }; class JSONSHARED_EXPORT JsonTilesetFormat : public Tiled::TilesetFormat { Q_OBJECT Q_INTERFACES(Tiled::TilesetFormat) public: JsonTilesetFormat(QObject *parent = nullptr); Tiled::SharedTileset read(const QString &fileName) override; bool supportsFile(const QString &fileName) const override; bool write(const Tiled::Tileset &tileset, const QString &fileName) override; QString nameFilter() const override; QString shortName() const override; QString errorString() const override; protected: QString mError; }; } // namespace Json tiled-1.0.3/src/plugins/json/plugin.json000066400000000000000000000000321315121121300202070ustar00rootroot00000000000000{ "defaultEnable": true } tiled-1.0.3/src/plugins/json/qjsonparser/000077500000000000000000000000001315121121300203725ustar00rootroot00000000000000tiled-1.0.3/src/plugins/json/qjsonparser/json.cpp000066400000000000000000000327141315121121300220560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (c) 2010 Girish Ramakrishnan ** ** Use, modification and distribution is allowed without limitation, ** warranty, liability or support of any kind. ** ****************************************************************************/ #include "json.h" #include "jsonparser.cpp" #include #include /*! \class JsonReader \reentrant \brief The JsonReader class provides a fast parser for reading well-formed JSON into a QVariant. The parser converts JSON types into QVariant types. For example, JSON arrays are translated into QVariantList and JSON objects are translated into QVariantMap. For example, \code JsonReader reader; if (reader.parse(QString("{ \"id\": 123, \"class\": \"JsonReader\", \"authors\": [\"Denis\",\"Ettrich\",\"Girish\"] }"))) { QVariant result = reader.result(); QVariantMap map = result.toMap(); // the JSON object qDebug() << map.count(); // 3 qDebug() << map["id"].toInt(); // 123 qDebug() << map["class"].toString(); // "JsonReader" QVariantList list = map["authors"].toList(); qDebug() << list[2].toString(); // "Girish" } else { qDebug() << reader.errorString(); } \endcode As seen above, the reader converts the JSON into a QVariant with arbitrary nesting. A complete listing of JSON to QVariant conversion is documented at parse(). JsonWriter can be used to convert a QVariant into JSON string. */ /*! Constructs a JSON reader. */ JsonReader::JsonReader() { } /*! Destructor */ JsonReader::~JsonReader() { } /*! Parses the JSON \a ba as a QVariant. If the parse succeeds, this function returns true and the QVariant can be accessed using result(). If the parse fails, this function returns false and the error message can be accessed using errorMessage(). The encoding of \ba is auto-detected based on the pattern of nulls in the initial 4 octets as described in "Section 3. Encoding" of RFC 2647. If an encoding could not be auto-detected, this function assumes UTF-8. The conversion from JSON type into QVariant type is as listed below: \table \row \o false \o QVariant::Bool with the value false. \row \o true \o QVariant::Bool with the value true. \row \o null \o QVariant::Invalid i.e QVariant() \row \o object \o QVariant::Map i.e QVariantMap \row \o array \o QVariant::List i.e QVariantList \row \o string \o QVariant::String i.e QString \row \o number \o QVariant::Double or QVariant::LongLong. If the JSON number contains a '.' or 'e' or 'E', QVariant::Double is used. \endtable The byte array \ba may or may not contain a BOM. */ bool JsonReader::parse(const QByteArray &ba) { QTextCodec *codec = QTextCodec::codecForUtfText(ba, 0); // try BOM detection if (!codec) { int mib = 106; // utf-8 if (ba.length() > 3) { // auto-detect const char *data = ba.constData(); if (data[0] != 0) { if (data[1] != 0) mib = 106; // utf-8 else if (data[2] != 0) mib = 1014; // utf16 le else mib = 1019; // utf32 le } else if (data[1] != 0) mib = 1013; // utf16 be else mib = 1018; // utf32 be } codec = QTextCodec::codecForMib(mib); } QString str = codec->toUnicode(ba); return parse(str); } /*! Parses the JSON string \a str as a QVariant. If the parse succeeds, this function returns true and the QVariant can be accessed using result(). If the parse fails, this function returns false and the error message can be accessed using errorMessage(). */ bool JsonReader::parse(const QString &str) { JsonLexer lexer(str); JsonParser parser; if (!parser.parse(&lexer)) { m_errorString = parser.errorMessage(); m_result = QVariant(); return false; } m_errorString.clear(); m_result = parser.result(); return true; } /*! Returns the result of the last parse() call. If parse() failed, this function returns an invalid QVariant. */ QVariant JsonReader::result() const { return m_result; } /*! Returns the error message for the last parse() call. If parse() succeeded, this functions return an empty string. The error message should be used for debugging purposes only. */ QString JsonReader::errorString() const { return m_errorString; } /*! \class JsonWriter \reentrant \brief The JsonWriter class converts a QVariant into a JSON string. The writer converts specific supported types stored in a QVariant into JSON. For example, \code QVariantMap map; map["id"] = 123; map["class"] = "JsonWriter"; QVariantList list; list << "Denis" << "Ettrich" << "Girish"; map["authors"] = list; JsonWriter writer; if (writer.stringify(map)) { QString json = writer.result(); qDebug() << json; // {"authors": ["Denis", "Ettrich", "Girish"], "class": "JsonWriter", "id": 123 } } else { qDebug() << "Failed to stringify " << writer.errorString(); } \endcode The list of QVariant types that the writer supports is listed in stringify(). Note that custom C++ types registered using Q_DECLARE_METATYPE are not supported. */ /*! Creates a JsonWriter. */ JsonWriter::JsonWriter() : m_autoFormatting(false), m_autoFormattingIndent(4, QLatin1Char(' ')) { } /*! Destructor. */ JsonWriter::~JsonWriter() { } /*! Enables auto formatting if \a enable is \c true, otherwise disables it. When auto formatting is enabled, the writer automatically inserts spaces and new lines to make the output more human readable. The default value is \c false. */ void JsonWriter::setAutoFormatting(bool enable) { m_autoFormatting = enable; } /*! Returns \c true if auto formattting is enabled, otherwise \c false. */ bool JsonWriter::autoFormatting() const { return m_autoFormatting; } /*! Sets the number of spaces or tabs used for indentation when auto-formatting is enabled. Positive numbers indicate spaces, negative numbers tabs. The default indentation is 4. \sa setAutoFormatting() */ void JsonWriter::setAutoFormattingIndent(int spacesOrTabs) { m_autoFormattingIndent = QString(qAbs(spacesOrTabs), QLatin1Char(spacesOrTabs >= 0 ? ' ' : '\t')); } /*! Retuns the numbers of spaces or tabs used for indentation when auto-formatting is enabled. Positive numbers indicate spaces, negative numbers tabs. The default indentation is 4. \sa setAutoFormatting() */ int JsonWriter::autoFormattingIndent() const { return m_autoFormattingIndent.count(QLatin1Char(' ')) - m_autoFormattingIndent.count(QLatin1Char('\t')); } /*! \internal Inserts escape character \ for characters in string as described in JSON specification. */ static QString escape(const QVariant &variant) { QString str = variant.toString(); QString res; res.reserve(str.length()); for (int i = 0; i < str.length(); i++) { if (str[i] == QLatin1Char('\b')) { res += QLatin1String("\\b"); } else if (str[i] == QLatin1Char('\f')) { res += QLatin1String("\\f"); } else if (str[i] == QLatin1Char('\n')) { res += QLatin1String("\\n"); } else if (str[i] == QLatin1Char('\r')) { res += QLatin1String("\\r"); } else if (str[i] == QLatin1Char('\t')) { res += QLatin1String("\\t"); } else if (str[i] == QLatin1Char('\"')) { res += QLatin1String("\\\""); } else if (str[i] == QLatin1Char('\\')) { res += QLatin1String("\\\\"); } else if (str[i] == QLatin1Char('/')) { res += QLatin1String("\\/"); } else if (str[i].unicode() > 127) { res += QLatin1String("\\u") + QString::number(str[i].unicode(), 16).rightJustified(4, QLatin1Char('0')); } else { res += str[i]; } } return res; } /*! \internal Stringifies \a variant. */ void JsonWriter::stringify(const QVariant &variant, int depth) { if (variant.type() == QVariant::List || variant.type() == QVariant::StringList) { m_result += QLatin1Char('['); QVariantList list = variant.toList(); for (int i = 0; i < list.count(); i++) { if (i != 0) { m_result += QLatin1Char(','); if (m_autoFormatting) m_result += QLatin1Char(' '); } stringify(list[i], depth+1); } m_result += QLatin1Char(']'); } else if (variant.type() == QVariant::Map) { QString indent = m_autoFormattingIndent.repeated(depth); QVariantMap map = variant.toMap(); if (m_autoFormatting && depth != 0) { m_result += QLatin1Char('\n'); m_result += indent; m_result += QLatin1String("{\n"); } else { m_result += QLatin1Char('{'); } for (QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it) { if (it != map.constBegin()) { m_result += QLatin1Char(','); if (m_autoFormatting) m_result += QLatin1Char('\n'); } if (m_autoFormatting) m_result += indent + QLatin1Char(' '); m_result += QLatin1Char('\"') + escape(it.key()) + QLatin1String("\":"); stringify(it.value(), depth+1); } if (m_autoFormatting) { m_result += QLatin1Char('\n'); m_result += indent; } m_result += QLatin1Char('}'); } else if (variant.type() == QVariant::String || variant.type() == QVariant::ByteArray) { m_result += QLatin1Char('\"') + escape(variant) + QLatin1Char('\"'); } else if (variant.type() == QVariant::Double || (int)variant.type() == (int)QMetaType::Float) { double d = variant.toDouble(); if (qIsFinite(d)) m_result += QString::number(variant.toDouble(), 'g', 15); else m_result += QLatin1String("null"); } else if (variant.type() == QVariant::Bool) { m_result += variant.toBool() ? QLatin1String("true") : QLatin1String("false"); } else if (variant.type() == QVariant::Invalid) { m_result += QLatin1String("null"); } else if (variant.type() == QVariant::ULongLong) { m_result += QString::number(variant.toULongLong()); } else if (variant.type() == QVariant::LongLong) { m_result += QString::number(variant.toLongLong()); } else if (variant.type() == QVariant::Int) { m_result += QString::number(variant.toInt()); } else if (variant.type() == QVariant::UInt) { m_result += QString::number(variant.toUInt()); } else if (variant.type() == QVariant::Char) { QChar c = variant.toChar(); if (c.unicode() > 127) m_result += QLatin1String("\"\\u") + QString::number(c.unicode(), 16).rightJustified(4, QLatin1Char('0')) + QLatin1Char('\"'); else m_result += QLatin1Char('\"') + c + QLatin1Char('\"'); } else if (variant.canConvert()) { m_result += QString::number(variant.toLongLong()); } else if (variant.canConvert()) { m_result += QLatin1Char('\"') + escape(variant) + QLatin1Char('\"'); } else { if (!m_errorString.isEmpty()) m_errorString.append(QLatin1Char('\n')); QString msg = QString::fromLatin1("Unsupported type %1 (id: %2)").arg(QString::fromUtf8(variant.typeName())).arg(variant.userType()); m_errorString.append(msg); qWarning() << "JsonWriter::stringify - " << msg; m_result += QLatin1String("null"); } } /*! Converts the variant \a var into a JSON string. The stringizer converts \a var into JSON based on the type of it's contents. The supported types and their conversion into JSON is as listed below: \table \row \o QVariant::List, QVariant::StringList \o JSON array [] \row \o QVariant::Map \o JSON object {} \row \o QVariant::String, QVariant::ByteArray \o JSON string encapsulated in double quotes. String contents are escaped using '\' if necessary. \row \o QVariant::Double, QMetaType::Float \o JSON number with a precision 15. Infinity and NaN are converted into null. \row \o QVariant::Bool \o JSON boolean true and false \row \o QVariant::Invalid \o JSON null \row \o QVariant::ULongLong, QVariant::LongLong, QVariant::Int, QVariant::UInt, \o JSON number \row \o QVariant::Char \o JSON string. Non-ASCII characters are converted into the \uXXXX notation. \endtable As a fallback, the writer attempts to convert a type not listed above into a long long or a QString using QVariant::canConvert. See the QVariant documentation for possible conversions. JsonWriter does not support stringizing custom user types stored in the QVariant. Any such value would be converted into JSON null. */ bool JsonWriter::stringify(const QVariant &var) { m_errorString.clear(); m_result.clear(); stringify(var, 0 /* depth */); return m_errorString.isEmpty(); } /*! Returns the result of the last stringify() call. If stringify() failed, this function returns a null QString. */ QString JsonWriter::result() const { return m_result; } /*! Returns the error message for the last stringify() call. If stringify() succeeded, this functions return an empty string. The error message should be used for debugging purposes only. */ QString JsonWriter::errorString() const { return m_errorString; } tiled-1.0.3/src/plugins/json/qjsonparser/json.h000066400000000000000000000022551315121121300215200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (c) 2010 Girish Ramakrishnan ** ** Use, modification and distribution is allowed without limitation, ** warranty, liability or support of any kind. ** ****************************************************************************/ #pragma once #include #include class JsonReader { public: JsonReader(); ~JsonReader(); bool parse(const QByteArray &ba); bool parse(const QString &str); QVariant result() const; QString errorString() const; private: QVariant m_result; QString m_errorString; }; class JsonWriter { public: JsonWriter(); ~JsonWriter(); bool stringify(const QVariant &variant); QString result() const; QString errorString() const; void setAutoFormatting(bool autoFormat); bool autoFormatting() const; void setAutoFormattingIndent(int spaceOrTabs); int autoFormattingIndent() const; private: void stringify(const QVariant &variant, int depth); QString m_result; QString m_errorString; bool m_autoFormatting; QString m_autoFormattingIndent; }; tiled-1.0.3/src/plugins/json/qjsonparser/jsonparser.cpp000066400000000000000000000342341315121121300232720ustar00rootroot00000000000000// This file was generated by qlalr - DO NOT EDIT! #ifndef JSONPARSER_CPP #define JSONPARSER_CPP class JsonGrammar { public: enum VariousConstants { EOF_SYMBOL = 0, ERROR = 12, T_COLON = 7, T_COMMA = 8, T_FALSE = 9, T_LCURLYBRACKET = 3, T_LSQUAREBRACKET = 5, T_NULL = 11, T_NUMBER = 2, T_RCURLYBRACKET = 4, T_RSQUAREBRACKET = 6, T_STRING = 1, T_TRUE = 10, ACCEPT_STATE = 12, RULE_COUNT = 17, STATE_COUNT = 27, TERMINAL_COUNT = 13, NON_TERMINAL_COUNT = 7, GOTO_INDEX_OFFSET = 27, GOTO_INFO_OFFSET = 37, GOTO_CHECK_OFFSET = 37 }; static const char *const spell []; static const short lhs []; static const short rhs []; #ifndef QLALR_NO_JSONGRAMMAR_DEBUG_INFO static const int rule_index []; static const int rule_info []; #endif // QLALR_NO_JSONGRAMMAR_DEBUG_INFO static const short goto_default []; static const short action_default []; static const short action_index []; static const short action_info []; static const short action_check []; static inline int nt_action (int state, int nt) { const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt; if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt) return goto_default [nt]; return action_info [GOTO_INFO_OFFSET + yyn]; } static inline int t_action (int state, int token) { const int yyn = action_index [state] + token; if (yyn < 0 || action_check [yyn] != token) return - action_default [state]; return action_info [yyn]; } }; const char *const JsonGrammar::spell [] = { "end of file", "string", "number", "{", "}", "[", "]", ":", ",", "false", "true", "null", "error", #ifndef QLALR_NO_JSONGRAMMAR_DEBUG_INFO "Root", "Value", "Object", "Members", "Array", "Values", "$accept" #endif // QLALR_NO_JSONGRAMMAR_DEBUG_INFO }; const short JsonGrammar::lhs [] = { 13, 15, 16, 16, 16, 14, 14, 14, 14, 14, 14, 14, 17, 18, 18, 18, 19}; const short JsonGrammar::rhs [] = { 1, 3, 3, 5, 0, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 0, 2}; #ifndef QLALR_NO_JSONGRAMMAR_DEBUG_INFO const int JsonGrammar::rule_info [] = { 13, 14 , 15, 3, 16, 4 , 16, 1, 7, 14 , 16, 16, 8, 1, 7, 14 , 16 , 14, 9 , 14, 10 , 14, 11 , 14, 15 , 14, 17 , 14, 2 , 14, 1 , 17, 5, 18, 6 , 18, 14 , 18, 18, 8, 14 , 18 , 19, 13, 0}; const int JsonGrammar::rule_index [] = { 0, 2, 6, 10, 16, 17, 19, 21, 23, 25, 27, 29, 31, 35, 37, 41, 42}; #endif // QLALR_NO_JSONGRAMMAR_DEBUG_INFO const short JsonGrammar::action_default [] = { 0, 10, 9, 0, 6, 5, 16, 8, 11, 12, 7, 1, 17, 0, 0, 0, 2, 0, 0, 4, 0, 3, 14, 0, 0, 13, 15}; const short JsonGrammar::goto_default [] = { 3, 11, 2, 13, 1, 23, 0}; const short JsonGrammar::action_index [] = { 24, -13, -13, 12, -13, -1, 24, -13, -13, -13, -13, -13, -13, 1, -5, 2, -13, -6, 24, -13, 24, -13, -13, -2, 24, -13, -13, -7, -7, -7, -7, -7, -7, 1, -7, -7, -7, -7, -7, -7, -7, -7, -7, -7, -7, 0, -7, -1, -7, -7, -7, 5, -7, -7}; const short JsonGrammar::action_info [] = { 14, 18, 20, 17, 25, 16, 24, 0, 0, 15, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 5, 0, 6, 0, 0, 0, 4, 10, 7, 0, 21, 19, 22, 0, 0, 0, 26, 0, 0, 0, 0, 0}; const short JsonGrammar::action_check [] = { 1, 7, 7, 1, 6, 4, 8, -1, -1, 8, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 3, -1, 5, -1, -1, -1, 9, 10, 11, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1}; #line 29 "json.g" /**************************************************************************** ** ** Copyright (c) 2010 Girish Ramakrishnan ** Copyright (c) 2011 Denis Dzyubenko ** ** Use, modification and distribution is allowed without limitation, ** warranty, liability or support of any kind. ** ****************************************************************************/ #ifndef JSONPARSER_P_H #define JSONPARSER_P_H #include #include #include class JsonLexer { public: JsonLexer(const QString &string); ~JsonLexer(); int lex(); QVariant symbol() const { return m_symbol; } int lineNumber() const { return m_lineNumber; } int pos() const { return m_pos; } private: int parseNumber(); int parseString(); int parseKeyword(); QString m_strdata; int m_lineNumber; int m_pos; QVariant m_symbol; }; class JsonParser : protected JsonGrammar { public: JsonParser(); ~JsonParser(); bool parse(JsonLexer *lex); QVariant result() const { return m_result; } QString errorMessage() const { return QString::fromLatin1("%1 at line %2 pos %3").arg(m_errorMessage).arg(m_errorLineNumber).arg(m_errorPos); } private: void reallocateStack(); inline QVariant &sym(int index) { return m_symStack[m_tos + index - 1]; } inline QVariantMap &map(int index) { return m_mapStack[m_tos + index - 1]; } inline QVariantList &list(int index) { return m_listStack[m_tos + index - 1]; } int m_tos; QVector m_stateStack; QVector m_symStack; QVector m_mapStack; QVector m_listStack; QString m_errorMessage; int m_errorLineNumber; int m_errorPos; QVariant m_result; }; #endif // JSONPARSER_P_H #line 103 "json.g" /**************************************************************************** ** ** Copyright (c) 2010 Girish Ramakrishnan ** Copyright (c) 2011 Denis Dzyubenko ** ** Use, modification and distribution is allowed without limitation, ** warranty, liability or support of any kind. ** ****************************************************************************/ #include #define L1C(c) ushort(uchar(c)) JsonLexer::JsonLexer(const QString &str) : m_strdata(str), m_lineNumber(1), m_pos(0) { } JsonLexer::~JsonLexer() { } int JsonLexer::parseString() { bool esc = false; ++m_pos; // skip initial " int start = m_pos; const ushort *uc = m_strdata.utf16(); const int remaining = m_strdata.length() - m_pos; int i; for (i = 0; i < remaining; ++i) { const ushort c = uc[m_pos + i]; if (c == L1C('\"')) { m_symbol = QString((QChar *)uc + m_pos, i); m_pos += i; ++m_pos; // eat quote return JsonGrammar::T_STRING; } else if (c == L1C('\\')) { ++m_pos; // eat backslash esc = true; break; } } QString str; if (i) { str.resize(i); memcpy((char *)str.utf16(), uc + start, i * 2); m_pos += i; } for (; m_pos < m_strdata.length(); ++m_pos) { const ushort c = uc[m_pos]; if (esc) { if (c == L1C('b')) str += QLatin1Char('\b'); else if (c == L1C('f')) str += QLatin1Char('\f'); else if (c == L1C('n')) str += QLatin1Char('\n'); else if (c == L1C('r')) str += QLatin1Char('\r'); else if (c == L1C('t')) str += QLatin1Char('\t'); else if (c == L1C('\\')) str += QLatin1Char('\\'); else if (c == L1C('\"')) str += QLatin1Char('\"'); else if (c == L1C('u') && m_pos+4= L1C('0') && c <= L1C('9')) { if (!isDouble) { value *= 10; value += c - L1C('0'); } continue; } break; } if (!isDouble) { m_symbol = value * negative; } else { QString number = QString::fromRawData((QChar *)uc+start, m_pos-start); m_symbol = number.toDouble(); } return JsonGrammar::T_NUMBER; } int JsonLexer::parseKeyword() { int start = m_pos; for (; m_pos < m_strdata.length(); ++m_pos) { const ushort c = m_strdata.at(m_pos).unicode(); if (c >= L1C('a') && c <= L1C('z')) continue; break; } const ushort *k = (const ushort *)m_strdata.constData() + start; const int l = m_pos-start; if (l == 4) { static const ushort true_data[] = { 't', 'r', 'u', 'e' }; static const ushort null_data[] = { 'n', 'u', 'l', 'l' }; if (!memcmp(k, true_data, 4 * sizeof(ushort))) return JsonGrammar::T_TRUE; if (!memcmp(k, null_data, 4 * sizeof(ushort))) return JsonGrammar::T_NULL; } else if (l == 5) { static const ushort false_data[] = { 'f', 'a', 'l', 's', 'e' }; if (!memcmp(k, false_data, 5 * sizeof(ushort))) return JsonGrammar::T_FALSE; } return JsonGrammar::ERROR; } int JsonLexer::lex() { m_symbol.clear(); const ushort *uc = m_strdata.utf16(); const int len = m_strdata.length(); while (m_pos < len) { const ushort c = uc[m_pos]; switch (c) { case L1C('['): ++m_pos; return JsonGrammar::T_LSQUAREBRACKET; case L1C(']'): ++m_pos; return JsonGrammar::T_RSQUAREBRACKET; case L1C('{'): ++m_pos; return JsonGrammar::T_LCURLYBRACKET; case L1C('}'): ++m_pos; return JsonGrammar::T_RCURLYBRACKET; case L1C(':'): ++m_pos; return JsonGrammar::T_COLON; case L1C(','): ++m_pos; return JsonGrammar::T_COMMA; case L1C(' '): case L1C('\r'): case L1C('\t'): ++m_pos; break; case L1C('\n'): ++m_pos; ++m_lineNumber; break; case L1C('"'): return parseString(); default: if (c == L1C('+') || c == L1C('-') || (c >= L1C('0') && c <= L1C('9'))) { return parseNumber(); } if (c >= L1C('a') && c <= L1C('z')) { return parseKeyword(); } return JsonGrammar::ERROR; } } return JsonGrammar::EOF_SYMBOL; } #undef L1C JsonParser::JsonParser() : m_tos(0) , m_errorLineNumber(-1) , m_errorPos(-1) { } JsonParser::~JsonParser() { } void JsonParser::reallocateStack() { int size = m_stateStack.size(); if (size == 0) size = 128; else size <<= 1; m_symStack.resize(size); m_mapStack.resize(size); m_listStack.resize(size); m_stateStack.resize(size); } bool JsonParser::parse(JsonLexer *lexer) { const int INITIAL_STATE = 0; int yytoken = -1; reallocateStack(); m_tos = 0; m_stateStack[++m_tos] = INITIAL_STATE; while (true) { const int state = m_stateStack[m_tos]; if (yytoken == -1 && -TERMINAL_COUNT != action_index[state]) { yytoken = lexer->lex(); } int act = t_action(state, yytoken); if (act == ACCEPT_STATE) return true; else if (act > 0) { if (++m_tos == m_stateStack.size()) reallocateStack(); m_stateStack[m_tos] = act; m_symStack[m_tos] = lexer->symbol(); yytoken = -1; } else if (act < 0) { int r = -act-1; m_tos -= rhs[r]; act = m_stateStack.at(m_tos++); switch (r) { #line 334 "json.g" case 0: { m_result = sym(1); break; } #line 337 "json.g" case 1: { sym(1) = map(2); break; } #line 340 "json.g" case 2: { QVariantMap m; m.insert(sym(1).toString(), sym(3)); map(1) = m; break; } #line 343 "json.g" case 3: { map(1).insert(sym(3).toString(), sym(5)); break; } #line 346 "json.g" case 4: { map(1) = QVariantMap(); break; } #line 349 "json.g" case 5: { sym(1) = QVariant(false); break; } #line 352 "json.g" case 6: { sym(1) = QVariant(true); break; } #line 361 "json.g" case 12: { sym(1) = list(2); break; } #line 364 "json.g" case 13: { QVariantList l; l.append(sym(1)); list(1) = l; break; } #line 367 "json.g" case 14: { list(1).append(sym(3)); break; } #line 370 "json.g" case 15: { list(1) = QVariantList(); break; } #line 372 "json.g" } // switch m_stateStack[m_tos] = nt_action(act, lhs[r] - TERMINAL_COUNT); } else { int ers = state; int shifts = 0; int reduces = 0; int expected_tokens[3]; for (int tk = 0; tk < TERMINAL_COUNT; ++tk) { int k = t_action(ers, tk); if (! k) continue; else if (k < 0) ++reduces; else if (spell[tk]) { if (shifts < 3) expected_tokens[shifts] = tk; ++shifts; } } m_errorLineNumber = lexer->lineNumber(); m_errorPos = lexer->pos(); m_errorMessage.clear(); if (shifts && shifts < 3) { bool first = true; for (int s = 0; s < shifts; ++s) { if (first) m_errorMessage += QLatin1String("Expected "); else m_errorMessage += QLatin1String(", "); first = false; m_errorMessage += QLatin1String("'"); m_errorMessage += QLatin1String(spell[expected_tokens[s]]); m_errorMessage += QLatin1String("'"); } } return false; } } return false; } #endif // JSONPARSER_CPP tiled-1.0.3/src/plugins/json/qjsonparser/qjsonparser.pri000066400000000000000000000000751315121121300234570ustar00rootroot00000000000000INCLUDEPATH += $$PWD SOURCES += json.cpp HEADERS += json.h tiled-1.0.3/src/plugins/lua/000077500000000000000000000000001315121121300156335ustar00rootroot00000000000000tiled-1.0.3/src/plugins/lua/lua.pro000066400000000000000000000002421315121121300171340ustar00rootroot00000000000000include(../plugin.pri) DEFINES += LUA_LIBRARY SOURCES += luaplugin.cpp \ luatablewriter.cpp HEADERS += luaplugin.h\ lua_global.h \ luatablewriter.h tiled-1.0.3/src/plugins/lua/lua.qbs000066400000000000000000000003561315121121300171270ustar00rootroot00000000000000import qbs 1.0 TiledPlugin { cpp.defines: ["LUA_LIBRARY"] files: [ "lua_global.h", "luaplugin.cpp", "luaplugin.h", "luatablewriter.cpp", "luatablewriter.h", "plugin.json", ] } tiled-1.0.3/src/plugins/lua/lua_global.h000066400000000000000000000016521315121121300201110ustar00rootroot00000000000000/* * Lua Tiled Plugin * Copyright 2011, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #if defined(LUA_LIBRARY) # define LUASHARED_EXPORT Q_DECL_EXPORT #else # define LUASHARED_EXPORT Q_DECL_IMPORT #endif tiled-1.0.3/src/plugins/lua/luaplugin.cpp000066400000000000000000000516451315121121300203520ustar00rootroot00000000000000/* * Lua Tiled Plugin * Copyright 2011, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "luaplugin.h" #include "luatablewriter.h" #include "grouplayer.h" #include "imagelayer.h" #include "mapobject.h" #include "objectgroup.h" #include "properties.h" #include "savefile.h" #include "terrain.h" #include "tile.h" #include "tilelayer.h" #include "tileset.h" #include #include /** * See below for an explanation of the different formats. One of these needs * to be defined. */ #define POLYGON_FORMAT_FULL //#define POLYGON_FORMAT_PAIRS //#define POLYGON_FORMAT_OPTIMAL using namespace Tiled; namespace Lua { LuaPlugin::LuaPlugin() { } bool LuaPlugin::write(const Map *map, const QString &fileName) { SaveFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { mError = tr("Could not open file for writing."); return false; } mMapDir = QFileInfo(fileName).path(); LuaTableWriter writer(file.device()); writer.writeStartDocument(); writeMap(writer, map); writer.writeEndDocument(); if (file.error() != QFileDevice::NoError) { mError = file.errorString(); return false; } if (!file.commit()) { mError = file.errorString(); return false; } return true; } QString LuaPlugin::nameFilter() const { return tr("Lua files (*.lua)"); } QString LuaPlugin::shortName() const { return QLatin1String("lua"); } QString LuaPlugin::errorString() const { return mError; } static void writeColor(LuaTableWriter &writer, const char *name, const QColor &color) { // Example: backgroundcolor = { 255, 200, 100 } writer.writeStartTable(name); writer.setSuppressNewlines(true); writer.writeValue(color.red()); writer.writeValue(color.green()); writer.writeValue(color.blue()); if (color.alpha() != 255) writer.writeValue(color.alpha()); writer.writeEndTable(); writer.setSuppressNewlines(false); } void LuaPlugin::writeMap(LuaTableWriter &writer, const Map *map) { writer.writeStartReturnTable(); writer.writeKeyAndValue("version", "1.1"); writer.writeKeyAndValue("luaversion", "5.1"); writer.writeKeyAndValue("tiledversion", QCoreApplication::applicationVersion()); const QString orientation = orientationToString(map->orientation()); const QString renderOrder = renderOrderToString(map->renderOrder()); writer.writeKeyAndValue("orientation", orientation); writer.writeKeyAndValue("renderorder", renderOrder); writer.writeKeyAndValue("width", map->width()); writer.writeKeyAndValue("height", map->height()); writer.writeKeyAndValue("tilewidth", map->tileWidth()); writer.writeKeyAndValue("tileheight", map->tileHeight()); writer.writeKeyAndValue("nextobjectid", map->nextObjectId()); if (map->orientation() == Map::Hexagonal) writer.writeKeyAndValue("hexsidelength", map->hexSideLength()); if (map->orientation() == Map::Staggered || map->orientation() == Map::Hexagonal) { writer.writeKeyAndValue("staggeraxis", staggerAxisToString(map->staggerAxis())); writer.writeKeyAndValue("staggerindex", staggerIndexToString(map->staggerIndex())); } const QColor &backgroundColor = map->backgroundColor(); if (backgroundColor.isValid()) writeColor(writer, "backgroundcolor", backgroundColor); writeProperties(writer, map->properties()); writer.writeStartTable("tilesets"); mGidMapper.clear(); unsigned firstGid = 1; for (const SharedTileset &tileset : map->tilesets()) { writeTileset(writer, tileset.data(), firstGid); mGidMapper.insert(firstGid, tileset.data()); firstGid += tileset->nextTileId(); } writer.writeEndTable(); writeLayers(writer, map->layers(), map->layerDataFormat()); writer.writeEndTable(); } void LuaPlugin::writeProperties(LuaTableWriter &writer, const Properties &properties) { writer.writeStartTable("properties"); Properties::const_iterator it = properties.constBegin(); Properties::const_iterator it_end = properties.constEnd(); for (; it != it_end; ++it) { QVariant value = toExportValue(it.value()); if (it.value().userType() == filePathTypeId()) value = mMapDir.relativeFilePath(value.toString()); writer.writeQuotedKeyAndValue(it.key(), value); } writer.writeEndTable(); } static bool includeTile(const Tile *tile) { if (!tile->type().isEmpty()) return true; if (!tile->properties().isEmpty()) return true; if (!tile->imageSource().isEmpty()) return true; if (tile->objectGroup()) return true; if (tile->isAnimated()) return true; if (tile->terrain() != 0xFFFFFFFF) return true; if (tile->probability() != 1.f) return true; return false; } void LuaPlugin::writeTileset(LuaTableWriter &writer, const Tileset *tileset, unsigned firstGid) { writer.writeStartTable(); writer.writeKeyAndValue("name", tileset->name()); writer.writeKeyAndValue("firstgid", firstGid); if (!tileset->fileName().isEmpty()) { const QString rel = mMapDir.relativeFilePath(tileset->fileName()); writer.writeKeyAndValue("filename", rel); } /* Include all tileset information even for external tilesets, since the * external reference is generally a .tsx file (in XML format). */ writer.writeKeyAndValue("tilewidth", tileset->tileWidth()); writer.writeKeyAndValue("tileheight", tileset->tileHeight()); writer.writeKeyAndValue("spacing", tileset->tileSpacing()); writer.writeKeyAndValue("margin", tileset->margin()); if (!tileset->imageSource().isEmpty()) { const QString rel = mMapDir.relativeFilePath(tileset->imageSource()); writer.writeKeyAndValue("image", rel); writer.writeKeyAndValue("imagewidth", tileset->imageWidth()); writer.writeKeyAndValue("imageheight", tileset->imageHeight()); } if (tileset->transparentColor().isValid()) { writer.writeKeyAndValue("transparentcolor", tileset->transparentColor().name()); } const QColor &backgroundColor = tileset->backgroundColor(); if (backgroundColor.isValid()) writeColor(writer, "backgroundcolor", backgroundColor); const QPoint offset = tileset->tileOffset(); writer.writeStartTable("tileoffset"); writer.writeKeyAndValue("x", offset.x()); writer.writeKeyAndValue("y", offset.y()); writer.writeEndTable(); const QSize gridSize = tileset->gridSize(); writer.writeStartTable("grid"); writer.writeKeyAndValue("orientation", Tileset::orientationToString(tileset->orientation())); writer.writeKeyAndValue("width", gridSize.width()); writer.writeKeyAndValue("height", gridSize.height()); writer.writeEndTable(); writeProperties(writer, tileset->properties()); writer.writeStartTable("terrains"); for (int i = 0; i < tileset->terrainCount(); ++i) { const Terrain *t = tileset->terrain(i); writer.writeStartTable(); writer.writeKeyAndValue("name", t->name()); writer.writeKeyAndValue("tile", t->imageTileId()); writeProperties(writer, t->properties()); writer.writeEndTable(); } writer.writeEndTable(); writer.writeKeyAndValue("tilecount", tileset->tileCount()); writer.writeStartTable("tiles"); for (const Tile *tile : tileset->tiles()) { // For brevity only write tiles with interesting properties if (!includeTile(tile)) continue; writer.writeStartTable(); writer.writeKeyAndValue("id", tile->id()); if (!tile->type().isEmpty()) writer.writeKeyAndValue("type", tile->type()); if (!tile->properties().isEmpty()) writeProperties(writer, tile->properties()); if (!tile->imageSource().isEmpty()) { const QString src = mMapDir.relativeFilePath(tile->imageSource()); const QSize tileSize = tile->size(); writer.writeKeyAndValue("image", src); if (!tileSize.isNull()) { writer.writeKeyAndValue("width", tileSize.width()); writer.writeKeyAndValue("height", tileSize.height()); } } unsigned terrain = tile->terrain(); if (terrain != 0xFFFFFFFF) { writer.writeStartTable("terrain"); writer.setSuppressNewlines(true); for (int i = 0; i < 4; ++i ) writer.writeValue(tile->cornerTerrainId(i)); writer.writeEndTable(); writer.setSuppressNewlines(false); } if (tile->probability() != 1.f) writer.writeKeyAndValue("probability", tile->probability()); if (ObjectGroup *objectGroup = tile->objectGroup()) writeObjectGroup(writer, objectGroup, "objectGroup"); if (tile->isAnimated()) { const QVector &frames = tile->frames(); writer.writeStartTable("animation"); for (const Frame &frame : frames) { writer.writeStartTable(); writer.writeKeyAndValue("tileid", frame.tileId); writer.writeKeyAndValue("duration", frame.duration); writer.writeEndTable(); } writer.writeEndTable(); // animation } writer.writeEndTable(); // tile } writer.writeEndTable(); // tiles writer.writeEndTable(); // tileset } void LuaPlugin::writeLayers(LuaTableWriter &writer, const QList &layers, Map::LayerDataFormat format) { writer.writeStartTable("layers"); for (const Layer *layer : layers) { switch (layer->layerType()) { case Layer::TileLayerType: writeTileLayer(writer, static_cast(layer), format); break; case Layer::ObjectGroupType: writeObjectGroup(writer, static_cast(layer)); break; case Layer::ImageLayerType: writeImageLayer(writer, static_cast(layer)); break; case Layer::GroupLayerType: writeGroupLayer(writer, static_cast(layer), format); break; } } writer.writeEndTable(); } void LuaPlugin::writeTileLayer(LuaTableWriter &writer, const TileLayer *tileLayer, Map::LayerDataFormat format) { writer.writeStartTable(); writer.writeKeyAndValue("type", "tilelayer"); writer.writeKeyAndValue("name", tileLayer->name()); writer.writeKeyAndValue("x", tileLayer->x()); writer.writeKeyAndValue("y", tileLayer->y()); writer.writeKeyAndValue("width", tileLayer->width()); writer.writeKeyAndValue("height", tileLayer->height()); writer.writeKeyAndValue("visible", tileLayer->isVisible()); writer.writeKeyAndValue("opacity", tileLayer->opacity()); const QPointF offset = tileLayer->offset(); writer.writeKeyAndValue("offsetx", offset.x()); writer.writeKeyAndValue("offsety", offset.y()); writeProperties(writer, tileLayer->properties()); switch (format) { case Map::XML: case Map::CSV: writer.writeKeyAndValue("encoding", "lua"); writer.writeStartTable("data"); for (int y = 0; y < tileLayer->height(); ++y) { if (y > 0) writer.prepareNewLine(); for (int x = 0; x < tileLayer->width(); ++x) writer.writeValue(mGidMapper.cellToGid(tileLayer->cellAt(x, y))); } writer.writeEndTable(); break; case Map::Base64: case Map::Base64Zlib: case Map::Base64Gzip: { writer.writeKeyAndValue("encoding", "base64"); if (format == Map::Base64Zlib) writer.writeKeyAndValue("compression", "zlib"); else if (format == Map::Base64Gzip) writer.writeKeyAndValue("compression", "gzip"); QByteArray layerData = mGidMapper.encodeLayerData(*tileLayer, format); writer.writeKeyAndValue("data", layerData); break; } } writer.writeEndTable(); } void LuaPlugin::writeObjectGroup(LuaTableWriter &writer, const ObjectGroup *objectGroup, const QByteArray &key) { if (key.isEmpty()) writer.writeStartTable(); else writer.writeStartTable(key); writer.writeKeyAndValue("type", "objectgroup"); writer.writeKeyAndValue("name", objectGroup->name()); writer.writeKeyAndValue("visible", objectGroup->isVisible()); writer.writeKeyAndValue("opacity", objectGroup->opacity()); const QPointF offset = objectGroup->offset(); writer.writeKeyAndValue("offsetx", offset.x()); writer.writeKeyAndValue("offsety", offset.y()); writer.writeKeyAndValue("draworder", drawOrderToString(objectGroup->drawOrder())); writeProperties(writer, objectGroup->properties()); writer.writeStartTable("objects"); for (MapObject *mapObject : objectGroup->objects()) writeMapObject(writer, mapObject); writer.writeEndTable(); writer.writeEndTable(); } void LuaPlugin::writeImageLayer(LuaTableWriter &writer, const ImageLayer *imageLayer) { writer.writeStartTable(); writer.writeKeyAndValue("type", "imagelayer"); writer.writeKeyAndValue("name", imageLayer->name()); writer.writeKeyAndValue("visible", imageLayer->isVisible()); writer.writeKeyAndValue("opacity", imageLayer->opacity()); const QPointF offset = imageLayer->offset(); writer.writeKeyAndValue("offsetx", offset.x()); writer.writeKeyAndValue("offsety", offset.y()); const QString rel = mMapDir.relativeFilePath(imageLayer->imageSource()); writer.writeKeyAndValue("image", rel); if (imageLayer->transparentColor().isValid()) { writer.writeKeyAndValue("transparentcolor", imageLayer->transparentColor().name()); } writeProperties(writer, imageLayer->properties()); writer.writeEndTable(); } void LuaPlugin::writeGroupLayer(LuaTableWriter &writer, const GroupLayer *groupLayer, Map::LayerDataFormat format) { writer.writeStartTable(); writer.writeKeyAndValue("type", "group"); writer.writeKeyAndValue("name", groupLayer->name()); writer.writeKeyAndValue("visible", groupLayer->isVisible()); writer.writeKeyAndValue("opacity", groupLayer->opacity()); const QPointF offset = groupLayer->offset(); writer.writeKeyAndValue("offsetx", offset.x()); writer.writeKeyAndValue("offsety", offset.y()); writeProperties(writer, groupLayer->properties()); writeLayers(writer, groupLayer->layers(), format); writer.writeEndTable(); } static const char *toString(MapObject::Shape shape) { switch (shape) { case MapObject::Rectangle: return "rectangle"; case MapObject::Polygon: return "polygon"; case MapObject::Polyline: return "polyline"; case MapObject::Ellipse: return "ellipse"; case MapObject::Text: return "text"; } return "unknown"; } void LuaPlugin::writeMapObject(LuaTableWriter &writer, const Tiled::MapObject *mapObject) { writer.writeStartTable(); writer.writeKeyAndValue("id", mapObject->id()); writer.writeKeyAndValue("name", mapObject->name()); writer.writeKeyAndValue("type", mapObject->type()); writer.writeKeyAndValue("shape", toString(mapObject->shape())); writer.writeKeyAndValue("x", mapObject->x()); writer.writeKeyAndValue("y", mapObject->y()); writer.writeKeyAndValue("width", mapObject->width()); writer.writeKeyAndValue("height", mapObject->height()); writer.writeKeyAndValue("rotation", mapObject->rotation()); if (!mapObject->cell().isEmpty()) writer.writeKeyAndValue("gid", mGidMapper.cellToGid(mapObject->cell())); writer.writeKeyAndValue("visible", mapObject->isVisible()); switch (mapObject->shape()) { case MapObject::Rectangle: case MapObject::Ellipse: break; case MapObject::Polygon: case MapObject::Polyline: writePolygon(writer, mapObject); break; case MapObject::Text: writeTextProperties(writer, mapObject); break; } writeProperties(writer, mapObject->properties()); writer.writeEndTable(); } void LuaPlugin::writePolygon(LuaTableWriter &writer, const MapObject *mapObject) { if (mapObject->shape() == MapObject::Polygon) writer.writeStartTable("polygon"); else writer.writeStartTable("polyline"); #if defined(POLYGON_FORMAT_FULL) /* This format is the easiest to read and understand: * * { * { x = 1, y = 1 }, * { x = 2, y = 2 }, * { x = 3, y = 3 }, * ... * } */ for (const QPointF &point : mapObject->polygon()) { writer.writeStartTable(); writer.setSuppressNewlines(true); writer.writeKeyAndValue("x", point.x()); writer.writeKeyAndValue("y", point.y()); writer.writeEndTable(); writer.setSuppressNewlines(false); } #elif defined(POLYGON_FORMAT_PAIRS) /* This is an alternative that takes about 25% less memory. * * { * { 1, 1 }, * { 2, 2 }, * { 3, 3 }, * ... * } */ for (const QPointF &point : mapObject->polygon()) { writer.writeStartTable(); writer.setSuppressNewlines(true); writer.writeValue(point.x()); writer.writeValue(point.y()); writer.writeEndTable(); writer.setSuppressNewlines(false); } #elif defined(POLYGON_FORMAT_OPTIMAL) /* Writing it out in two tables, one for the x coordinates and one for * the y coordinates. It is a compromise between code readability and * performance. This takes the least amount of memory (60% less than * the first approach). * * x = { 1, 2, 3, ... } * y = { 1, 2, 3, ... } */ writer.writeStartTable("x"); writer.setSuppressNewlines(true); for (const QPointF &point : mapObject->polygon()) writer.writeValue(point.x()); writer.writeEndTable(); writer.setSuppressNewlines(false); writer.writeStartTable("y"); writer.setSuppressNewlines(true); for (const QPointF &point : mapObject->polygon()) writer.writeValue(point.y()); writer.writeEndTable(); writer.setSuppressNewlines(false); #endif writer.writeEndTable(); } void LuaPlugin::writeTextProperties(LuaTableWriter &writer, const MapObject *mapObject) { const TextData &textData = mapObject->textData(); writer.writeKeyAndValue("text", textData.text); if (textData.font.family() != QLatin1String("sans-serif")) writer.writeKeyAndValue("fontfamily", textData.font.family()); if (textData.font.pixelSize() >= 0 && textData.font.pixelSize() != 16) writer.writeKeyAndValue("pixelsize", textData.font.pixelSize()); if (textData.wordWrap) writer.writeKeyAndValue("wrap", textData.wordWrap); if (textData.color != Qt::black) writeColor(writer, "color", textData.color); if (textData.font.bold()) writer.writeKeyAndValue("bold", textData.font.bold()); if (textData.font.italic()) writer.writeKeyAndValue("italic", textData.font.italic()); if (textData.font.underline()) writer.writeKeyAndValue("underline", textData.font.underline()); if (textData.font.strikeOut()) writer.writeKeyAndValue("strikeout", textData.font.strikeOut()); if (!textData.font.kerning()) writer.writeKeyAndValue("kerning", textData.font.kerning()); if (!textData.alignment.testFlag(Qt::AlignLeft)) { if (textData.alignment.testFlag(Qt::AlignHCenter)) writer.writeKeyAndValue("halign", "center"); else if (textData.alignment.testFlag(Qt::AlignRight)) writer.writeKeyAndValue("halign", "right"); } if (!textData.alignment.testFlag(Qt::AlignTop)) { if (textData.alignment.testFlag(Qt::AlignVCenter)) writer.writeKeyAndValue("valign", "center"); else if (textData.alignment.testFlag(Qt::AlignBottom)) writer.writeKeyAndValue("valign", "bottom"); } } } // namespace Lua tiled-1.0.3/src/plugins/lua/luaplugin.h000066400000000000000000000052201315121121300200030ustar00rootroot00000000000000/* * Lua Tiled Plugin * Copyright 2011, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "lua_global.h" #include "gidmapper.h" #include "map.h" #include "mapformat.h" #include #include namespace Tiled { class GroupLayer; class MapObject; class ObjectGroup; class Properties; class TileLayer; class Tileset; } namespace Lua { class LuaTableWriter; /** * This plugin allows exporting maps as Lua files. */ class LUASHARED_EXPORT LuaPlugin : public Tiled::WritableMapFormat { Q_OBJECT Q_PLUGIN_METADATA(IID "org.mapeditor.MapFormat" FILE "plugin.json") public: LuaPlugin(); bool write(const Tiled::Map *map, const QString &fileName) override; QString nameFilter() const override; QString shortName() const override; QString errorString() const override; private: void writeMap(LuaTableWriter &, const Tiled::Map *); void writeProperties(LuaTableWriter &, const Tiled::Properties &); void writeTileset(LuaTableWriter &, const Tiled::Tileset *, unsigned firstGid); void writeLayers(LuaTableWriter &, const QList &layers, Tiled::Map::LayerDataFormat format); void writeTileLayer(LuaTableWriter &, const Tiled::TileLayer *, Tiled::Map::LayerDataFormat); void writeObjectGroup(LuaTableWriter &, const Tiled::ObjectGroup *, const QByteArray &key = QByteArray()); void writeImageLayer(LuaTableWriter &, const Tiled::ImageLayer *); void writeGroupLayer(LuaTableWriter &, const Tiled::GroupLayer *, Tiled::Map::LayerDataFormat); void writeMapObject(LuaTableWriter &, const Tiled::MapObject *); void writePolygon(LuaTableWriter &, const Tiled::MapObject *); void writeTextProperties(LuaTableWriter &, const Tiled::MapObject *); QString mError; QDir mMapDir; // The directory in which the map is being saved Tiled::GidMapper mGidMapper; }; } // namespace Lua tiled-1.0.3/src/plugins/lua/luatablewriter.cpp000066400000000000000000000116721315121121300213740ustar00rootroot00000000000000/* * Lua Tiled Plugin * Copyright 2011-2013, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "luatablewriter.h" #include namespace Lua { LuaTableWriter::LuaTableWriter(QIODevice *device) : m_device(device) , m_indent(0) , m_valueSeparator(',') , m_suppressNewlines(false) , m_newLine(true) , m_valueWritten(false) , m_error(false) { } void LuaTableWriter::writeStartDocument() { Q_ASSERT(m_indent == 0); } void LuaTableWriter::writeEndDocument() { Q_ASSERT(m_indent == 0); write('\n'); } void LuaTableWriter::writeStartTable() { prepareNewLine(); write('{'); ++m_indent; m_newLine = false; m_valueWritten = false; } void LuaTableWriter::writeStartReturnTable() { prepareNewLine(); write("return {"); ++m_indent; m_newLine = false; m_valueWritten = false; } void LuaTableWriter::writeStartTable(const QByteArray &name) { prepareNewLine(); write(name + " = {"); ++m_indent; m_newLine = false; m_valueWritten = false; } void LuaTableWriter::writeEndTable() { Q_ASSERT(m_indent > 0); --m_indent; if (m_valueWritten) writeNewline(); write('}'); m_newLine = false; m_valueWritten = true; } void LuaTableWriter::writeValue(const QByteArray &value) { prepareNewValue(); write('"'); write(value); write('"'); m_newLine = false; m_valueWritten = true; } void LuaTableWriter::writeUnquotedValue(const QByteArray &value) { prepareNewValue(); write(value); m_newLine = false; m_valueWritten = true; } void LuaTableWriter::writeKeyAndValue(const QByteArray &key, const char *value) { prepareNewLine(); write(key); write(" = \""); write(value); write('"'); m_newLine = false; m_valueWritten = true; } void LuaTableWriter::writeKeyAndValue(const QByteArray &key, const QByteArray &value) { prepareNewLine(); write(key); write(" = \""); write(value); write('"'); m_newLine = false; m_valueWritten = true; } void LuaTableWriter::writeQuotedKeyAndValue(const QString &key, const QVariant &value) { prepareNewLine(); write('['); write(quote(key).toUtf8()); write("] = "); switch (value.type()) { case QVariant::Int: case QVariant::UInt: case QVariant::LongLong: case QVariant::ULongLong: case QVariant::Double: case QVariant::Bool: write(value.toString().toLatin1()); break; default: write(quote(value.toString()).toUtf8()); break; } m_newLine = false; m_valueWritten = true; } void LuaTableWriter::writeKeyAndUnquotedValue(const QByteArray &key, const QByteArray &value) { prepareNewLine(); write(key); write(" = "); write(value); m_newLine = false; m_valueWritten = true; } /** * Quotes the given string, escaping special characters as necessary. */ QString LuaTableWriter::quote(const QString &str) { QString quoted("\""); for (const QChar c : str) { switch (c.unicode()) { case '\\': quoted.append(QLatin1String("\\\\")); break; case '"': quoted.append(QLatin1String("\\\"")); break; case '\n': quoted.append(QLatin1String("\\n")); break; default: quoted.append(c); } } quoted.append(QLatin1Char('"')); return quoted; } void LuaTableWriter::prepareNewLine() { if (m_valueWritten) { write(m_valueSeparator); m_valueWritten = false; } writeNewline(); } void LuaTableWriter::prepareNewValue() { if (!m_valueWritten) { writeNewline(); } else { write(m_valueSeparator); write(' '); } } void LuaTableWriter::writeIndent() { for (int level = m_indent; level; --level) write(" "); } void LuaTableWriter::writeNewline() { if (!m_newLine) { if (m_suppressNewlines) { write(' '); } else { write('\n'); writeIndent(); } m_newLine = true; } } void LuaTableWriter::write(const char *bytes, qint64 length) { if (m_device->write(bytes, length) != length) m_error = true; } } // namespace Lua tiled-1.0.3/src/plugins/lua/luatablewriter.h000066400000000000000000000107431315121121300210370ustar00rootroot00000000000000/* * Lua Tiled Plugin * Copyright 2011-2013, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include #include class QIODevice; namespace Lua { /** * Makes it easy to produce a well formatted Lua table. */ class LuaTableWriter { public: LuaTableWriter(QIODevice *device); void writeStartDocument(); void writeEndDocument(); void writeStartTable(); void writeStartReturnTable(); void writeStartTable(const QByteArray &name); void writeEndTable(); void writeValue(int value); void writeValue(unsigned value); void writeValue(const QByteArray &value); void writeValue(const QString &value); void writeUnquotedValue(const QByteArray &value); void writeKeyAndValue(const QByteArray &key, int value); void writeKeyAndValue(const QByteArray &key, unsigned value); void writeKeyAndValue(const QByteArray &key, float value); void writeKeyAndValue(const QByteArray &key, double value); void writeKeyAndValue(const QByteArray &key, bool value); void writeKeyAndValue(const QByteArray &key, const char *value); void writeKeyAndValue(const QByteArray &key, const QByteArray &value); void writeKeyAndValue(const QByteArray &key, const QString &value); void writeQuotedKeyAndValue(const QString &key, const QVariant &value); void writeKeyAndUnquotedValue(const QByteArray &key, const QByteArray &value); void setSuppressNewlines(bool suppressNewlines); bool suppressNewlines() const; void prepareNewLine(); bool hasError() const { return m_error; } static QString quote(const QString &str); private: void prepareNewValue(); void writeIndent(); void writeNewline(); void write(const char *bytes, qint64 length); void write(const char *bytes); void write(const QByteArray &bytes); void write(char c); QIODevice *m_device; int m_indent; char m_valueSeparator; bool m_suppressNewlines; bool m_newLine; bool m_valueWritten; bool m_error; }; inline void LuaTableWriter::writeValue(int value) { writeUnquotedValue(QByteArray::number(value)); } inline void LuaTableWriter::writeValue(unsigned value) { writeUnquotedValue(QByteArray::number(value)); } inline void LuaTableWriter::writeValue(const QString &value) { writeUnquotedValue(quote(value).toUtf8()); } inline void LuaTableWriter::writeKeyAndValue(const QByteArray &key, int value) { writeKeyAndUnquotedValue(key, QByteArray::number(value)); } inline void LuaTableWriter::writeKeyAndValue(const QByteArray &key, unsigned value) { writeKeyAndUnquotedValue(key, QByteArray::number(value)); } inline void LuaTableWriter::writeKeyAndValue(const QByteArray &key, float value) { writeKeyAndValue(key, static_cast(value)); } inline void LuaTableWriter::writeKeyAndValue(const QByteArray &key, double value) { writeKeyAndUnquotedValue(key, QByteArray::number(value)); } inline void LuaTableWriter::writeKeyAndValue(const QByteArray &key, bool value) { writeKeyAndUnquotedValue(key, value ? "true" : "false"); } inline void LuaTableWriter::writeKeyAndValue(const QByteArray &key, const QString &value) { writeKeyAndUnquotedValue(key, quote(value).toUtf8()); } inline void LuaTableWriter::write(const char *bytes) { write(bytes, qstrlen(bytes)); } inline void LuaTableWriter::write(const QByteArray &bytes) { write(bytes.constData(), bytes.length()); } inline void LuaTableWriter::write(char c) { write(&c, 1); } /** * Sets whether newlines should be suppressed. While newlines are suppressed, * the writer will write out spaces instead of newlines. */ inline void LuaTableWriter::setSuppressNewlines(bool suppressNewlines) { m_suppressNewlines = suppressNewlines; } inline bool LuaTableWriter::suppressNewlines() const { return m_suppressNewlines; } } // namespace Lua tiled-1.0.3/src/plugins/lua/plugin.json000066400000000000000000000000321315121121300200170ustar00rootroot00000000000000{ "defaultEnable": true } tiled-1.0.3/src/plugins/plugin.pri000066400000000000000000000017721315121121300170730ustar00rootroot00000000000000isEmpty(TARGET) { error("plugin.pri: You must provide a TARGET") } TEMPLATE = lib CONFIG += plugin contains(QT_CONFIG, reduce_exports): CONFIG += hide_symbols win32|!isEmpty(TILED_LINUX_ARCHIVE) { DESTDIR = $$OUT_PWD/../../../plugins/tiled } else:macx { DESTDIR = $$OUT_PWD/../../../bin/Tiled.app/Contents/PlugIns } else { DESTDIR = $$OUT_PWD/../../../lib/tiled/plugins } include(../../tiled.pri) target.path = $${LIBDIR}/tiled/plugins INSTALLS += target include(../libtiled/libtiled.pri) macx { QMAKE_LIBDIR += $$OUT_PWD/../../../bin/Tiled.app/Contents/Frameworks } else:win32 { LIBS += -L$$OUT_PWD/../../../lib } else { QMAKE_LIBDIR += $$OUT_PWD/../../../lib } # Set rpath so that the plugin will resolve libtiled correctly !win32:!macx:!cygwin:contains(RPATH, yes) { QMAKE_RPATHDIR += \$\$ORIGIN/../.. # It is not possible to use ORIGIN in QMAKE_RPATHDIR, so a bit manually QMAKE_LFLAGS += -Wl,-z,origin \'-Wl,-rpath,$$join(QMAKE_RPATHDIR, ":")\' QMAKE_RPATHDIR = } tiled-1.0.3/src/plugins/plugins.pro000066400000000000000000000006031315121121300172540ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS = csv \ defold \ droidcraft \ flare \ gmx \ json \ lua \ replicaisland \ tengine \ tmw include(python/find_python.pri) contains(HAVE_PYTHON, yes) { message("Have Python, will slither") SUBDIRS += python } else { !build_pass:message("No Python support") } tiled-1.0.3/src/plugins/plugins.qbs000066400000000000000000000003731315121121300172450ustar00rootroot00000000000000Project { name: "plugins" references: [ "csv", "defold", "droidcraft", "flare", "json", "lua", "python", "replicaisland", "tengine", "tmw", "gmx" ] } tiled-1.0.3/src/plugins/python/000077500000000000000000000000001315121121300163735ustar00rootroot00000000000000tiled-1.0.3/src/plugins/python/find_python.pri000066400000000000000000000012411315121121300214260ustar00rootroot00000000000000!contains(DISABLE_PYTHON_PLUGIN, yes) { unix { packagesExist(python-2.7) { HAVE_PYTHON = yes CONFIG += link_pkgconfig PKGCONFIG += python-2.7 } else:system(python-config --prefix) { # currently here for reference, only 2.7 is tested HAVE_PYTHON = yes QMAKE_CXXFLAGS += `python-config --cflags` QMAKE_LFLAGS += `python-config --ldflags` } } win32 { exists(C:/Python27/include/Python.h) { HAVE_PYTHON = yes QMAKE_CXXFLAGS += -IC:/Python27/include/ QMAKE_LIBS += -LC:/Python27/libs -lpython27 } } } tiled-1.0.3/src/plugins/python/plugin.json000066400000000000000000000000321315121121300205570ustar00rootroot00000000000000{ "defaultEnable": true } tiled-1.0.3/src/plugins/python/python.pro000066400000000000000000000002401315121121300204320ustar00rootroot00000000000000include(../plugin.pri) include(find_python.pri) QT += widgets DEFINES += PYTHON_LIBRARY SOURCES += pythonplugin.cpp pythonbind.cpp HEADERS += pythonplugin.h tiled-1.0.3/src/plugins/python/python.qbs000066400000000000000000000031101315121121300204160ustar00rootroot00000000000000import qbs 1.0 import qbs.Probes as Probes import qbs.File TiledPlugin { Depends { name: "Qt"; submodules: ["widgets"] } condition: { if (qbs.targetOS.contains("linux")) { return pkgConfig.found; } else if (qbs.targetOS.contains("windows")) { // On Windows, currently only the default install location of // Python 2.7 is supported, and only when compiling with MinGW in // release mode. Also, avoid Python 2.7.10, since it results in a // linker error. // return File.exists("C:/Python27") && qbs.toolchain.contains("mingw") && !qbs.debugInformation; } // Not sure how to properly support Python on Mac OS X yet // (possibly requires using python-config) return false; } Probes.PkgConfigProbe { id: pkgConfig name: "python-2.7" } Properties { condition: qbs.targetOS.contains("linux") cpp.cxxFlags: pkgConfig.cflags // This should be it, but it doesn't work because the -lpython2.7 ends // up too early on the command line. //cpp.linkerFlags: pkgConfig.libs cpp.dynamicLibraries: ["python2.7"] } Properties { condition: qbs.targetOS.contains("windows") cpp.includePaths: ["C:/Python27/include"] cpp.libraryPaths: ["C:/Python27/libs"] cpp.dynamicLibraries: ["python27"] } files: [ "plugin.json", "pythonplugin.cpp", "pythonplugin.h", "pythonbind.cpp", ] } tiled-1.0.3/src/plugins/python/pythonbind.cpp000066400000000000000000006407441315121121300212740ustar00rootroot00000000000000 #ifdef __MINGW32__ #include // included before Python.h to fix ::hypot not declared issue #endif /* This file was generated by PyBindGen 0.17.0 */ #define PY_SSIZE_T_CLEAN #include #include #if PY_VERSION_HEX < 0x020400F0 #define PyEval_ThreadsInitialized() 1 #define Py_CLEAR(op) \ do { \ if (op) { \ PyObject *tmp = (PyObject *)(op); \ (op) = NULL; \ Py_DECREF(tmp); \ } \ } while (0) #define Py_VISIT(op) \ do { \ if (op) { \ int vret = visit((PyObject *)(op), arg); \ if (vret) \ return vret; \ } \ } while (0) #endif #if PY_VERSION_HEX < 0x020500F0 typedef int Py_ssize_t; # define PY_SSIZE_T_MAX INT_MAX # define PY_SSIZE_T_MIN INT_MIN typedef inquiry lenfunc; typedef intargfunc ssizeargfunc; typedef intobjargproc ssizeobjargproc; #endif #ifndef PyVarObject_HEAD_INIT #define PyVarObject_HEAD_INIT(type, size) \ PyObject_HEAD_INIT(type) size, #endif #if PY_VERSION_HEX >= 0x03000000 typedef void* cmpfunc; #define PyCObject_FromVoidPtr(a, b) PyCapsule_New(a, NULL, b) #define PyCObject_AsVoidPtr(a) PyCapsule_GetPointer(a, NULL) #define PyString_FromString(a) PyBytes_FromString(a) #define Py_TPFLAGS_CHECKTYPES 0 /* this flag doesn't exist in python 3 */ #endif #if __GNUC__ > 2 # define PYBINDGEN_UNUSED(param) param __attribute__((__unused__)) #elif __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) # define PYBINDGEN_UNUSED(param) __attribute__((__unused__)) param #else # define PYBINDGEN_UNUSED(param) param #endif /* !__GNUC__ */ #ifndef _PyBindGenWrapperFlags_defined_ #define _PyBindGenWrapperFlags_defined_ typedef enum _PyBindGenWrapperFlags { PYBINDGEN_WRAPPER_FLAG_NONE = 0, PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED = (1<<0), } PyBindGenWrapperFlags; #endif #include "pythonplugin.h" #include "map.h" #include "layer.h" #include "tile.h" #include "mapobject.h" #include "imagelayer.h" #include "tilelayer.h" #include "objectgroup.h" #include "tileset.h" #include #include #include #include /* --- forward declarations --- */ typedef struct { PyObject_HEAD Python::PythonScript *obj; PyObject *inst_dict; PyBindGenWrapperFlags flags:8; } PyPythonPythonScript; extern PyTypeObject PyPythonPythonScript_Type; /* --- forward declarations --- */ typedef struct { PyObject_HEAD QPointF *obj; PyBindGenWrapperFlags flags:8; } PyQPointF; extern PyTypeObject PyQPointF_Type; typedef struct { PyObject_HEAD QSizeF *obj; PyBindGenWrapperFlags flags:8; } PyQSizeF; extern PyTypeObject PyQSizeF_Type; typedef struct { PyObject_HEAD QRgb *obj; PyBindGenWrapperFlags flags:8; } PyQRgb; extern PyTypeObject PyQRgb_Type; typedef struct { PyObject_HEAD QColor *obj; PyBindGenWrapperFlags flags:8; } PyQColor; extern PyTypeObject PyQColor_Type; typedef struct { PyObject_HEAD QImage *obj; PyBindGenWrapperFlags flags:8; } PyQImage; extern PyTypeObject PyQImage_Type; typedef struct { PyObject_HEAD QPixmap *obj; PyBindGenWrapperFlags flags:8; } PyQPixmap; extern PyTypeObject PyQPixmap_Type; typedef struct { PyObject_HEAD QWidget *obj; PyBindGenWrapperFlags flags:8; } PyQWidget; extern PyTypeObject PyQWidget_Type; typedef struct { PyObject_HEAD QFileDialog *obj; PyBindGenWrapperFlags flags:8; } PyQFileDialog; extern PyTypeObject PyQFileDialog_Type; typedef struct { PyObject_HEAD QVector *obj; } PyQVector__lt__QRgb__gt__; typedef struct { PyObject_HEAD PyQVector__lt__QRgb__gt__ *container; QVector::iterator *iterator; } PyQVector__lt__QRgb__gt__Iter; extern PyTypeObject PyQVector__lt__QRgb__gt___Type; extern PyTypeObject PyQVector__lt__QRgb__gt__Iter_Type; int _wrap_convert_py2c__QVector__lt___QRgb___gt__(PyObject *arg, QVector *container); typedef struct { PyObject_HEAD QList *obj; } PyQList__lt__QString__gt__; typedef struct { PyObject_HEAD PyQList__lt__QString__gt__ *container; QList::iterator *iterator; } PyQList__lt__QString__gt__Iter; extern PyTypeObject PyQList__lt__QString__gt___Type; extern PyTypeObject PyQList__lt__QString__gt__Iter_Type; int _wrap_convert_py2c__QList__lt___QString___gt__(PyObject *arg, QList *container); /* --- forward declarations --- */ typedef struct { PyObject_HEAD Tiled::Properties *obj; PyBindGenWrapperFlags flags:8; } PyTiledProperties; extern PyTypeObject PyTiledProperties_Type; typedef struct { PyObject_HEAD Tiled::Object *obj; PyBindGenWrapperFlags flags:8; } PyTiledObject; extern PyTypeObject PyTiledObject_Type; typedef struct { PyObject_HEAD Tiled::Tile *obj; PyBindGenWrapperFlags flags:8; } PyTiledTile; extern PyTypeObject PyTiledTile_Type; typedef struct { PyObject_HEAD Tiled::SharedTileset *obj; PyBindGenWrapperFlags flags:8; } PyTiledSharedTileset; extern PyTypeObject PyTiledSharedTileset_Type; typedef struct { PyObject_HEAD Tiled::Tileset *obj; PyBindGenWrapperFlags flags:8; } PyTiledTileset; extern PyTypeObject PyTiledTileset_Type; typedef struct { PyObject_HEAD Tiled::Layer *obj; PyBindGenWrapperFlags flags:8; } PyTiledLayer; extern PyTypeObject PyTiledLayer_Type; typedef struct { PyObject_HEAD Tiled::Map *obj; PyBindGenWrapperFlags flags:8; } PyTiledMap; extern PyTypeObject PyTiledMap_Type; typedef struct { PyObject_HEAD Tiled::Cell *obj; PyBindGenWrapperFlags flags:8; } PyTiledCell; extern PyTypeObject PyTiledCell_Type; typedef struct { PyObject_HEAD Tiled::TileLayer *obj; PyBindGenWrapperFlags flags:8; } PyTiledTileLayer; extern PyTypeObject PyTiledTileLayer_Type; typedef struct { PyObject_HEAD Tiled::ImageLayer *obj; PyBindGenWrapperFlags flags:8; } PyTiledImageLayer; extern PyTypeObject PyTiledImageLayer_Type; typedef struct { PyObject_HEAD Tiled::MapObject *obj; PyBindGenWrapperFlags flags:8; } PyTiledMapObject; extern PyTypeObject PyTiledMapObject_Type; typedef struct { PyObject_HEAD Tiled::ObjectGroup *obj; PyBindGenWrapperFlags flags:8; } PyTiledObjectGroup; extern PyTypeObject PyTiledObjectGroup_Type; typedef struct { PyObject_HEAD Tiled::LoggingInterface *obj; PyBindGenWrapperFlags flags:8; } PyTiledLoggingInterface; extern PyTypeObject PyTiledLoggingInterface_Type; #pragma GCC diagnostic ignored "-Wmissing-field-initializers" int _wrap_convert_py2c__QRgb(PyObject *value, QRgb *address); int _wrap_convert_py2c__QString(PyObject *value, QString *address); static PyMethodDef tiled_qt_functions[] = { {NULL, NULL, 0, NULL} }; /* --- classes --- */ static int _wrap_PyQPointF__tp_init(PyQPointF *self, PyObject *args, PyObject *kwargs) { float x; float y; const char *keywords[] = {"x", "y", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "ff", (char **) keywords, &x, &y)) { return -1; } self->obj = new QPointF(x, y); self->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return 0; } PyObject * _wrap_PyQPointF_y(PyQPointF *self) { PyObject *py_retval; int retval; retval = self->obj->y(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyQPointF_x(PyQPointF *self) { PyObject *py_retval; int retval; retval = self->obj->x(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyQPointF_setX(PyQPointF *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int x; const char *keywords[] = {"x", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &x)) { return NULL; } self->obj->setX(x); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyQPointF_setY(PyQPointF *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int y; const char *keywords[] = {"y", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &y)) { return NULL; } self->obj->setY(y); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } static PyMethodDef PyQPointF_methods[] = { {(char *) "y", (PyCFunction) _wrap_PyQPointF_y, METH_NOARGS, NULL }, {(char *) "x", (PyCFunction) _wrap_PyQPointF_x, METH_NOARGS, NULL }, {(char *) "setX", (PyCFunction) _wrap_PyQPointF_setX, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "setY", (PyCFunction) _wrap_PyQPointF_setY, METH_KEYWORDS|METH_VARARGS, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyQPointF__tp_dealloc(PyQPointF *self) { QPointF *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyQPointF__tp_richcompare (PyQPointF *PYBINDGEN_UNUSED(self), PyQPointF *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyQPointF_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyQPointF_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.qt.QPointF", /* tp_name */ sizeof(PyQPointF), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyQPointF__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyQPointF__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyQPointF_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyQPointF__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyQSizeF__tp_init(PyQSizeF *self, PyObject *args, PyObject *kwargs) { float w; float h; const char *keywords[] = {"w", "h", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "ff", (char **) keywords, &w, &h)) { return -1; } self->obj = new QSizeF(w, h); self->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return 0; } PyObject * _wrap_PyQSizeF_setHeight(PyQSizeF *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int h; const char *keywords[] = {"h", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &h)) { return NULL; } self->obj->setHeight(h); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyQSizeF_width(PyQSizeF *self) { PyObject *py_retval; int retval; retval = self->obj->width(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyQSizeF_setWidth(PyQSizeF *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int w; const char *keywords[] = {"w", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &w)) { return NULL; } self->obj->setWidth(w); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyQSizeF_height(PyQSizeF *self) { PyObject *py_retval; int retval; retval = self->obj->height(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } static PyMethodDef PyQSizeF_methods[] = { {(char *) "setHeight", (PyCFunction) _wrap_PyQSizeF_setHeight, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "width", (PyCFunction) _wrap_PyQSizeF_width, METH_NOARGS, NULL }, {(char *) "setWidth", (PyCFunction) _wrap_PyQSizeF_setWidth, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "height", (PyCFunction) _wrap_PyQSizeF_height, METH_NOARGS, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyQSizeF__tp_dealloc(PyQSizeF *self) { QSizeF *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyQSizeF__tp_richcompare (PyQSizeF *PYBINDGEN_UNUSED(self), PyQSizeF *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyQSizeF_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyQSizeF_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.qt.QSizeF", /* tp_name */ sizeof(PyQSizeF), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyQSizeF__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyQSizeF__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyQSizeF_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyQSizeF__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyQRgb__tp_init(void) { PyErr_SetString(PyExc_TypeError, "class 'QRgb' cannot be constructed ()"); return -1; } static PyMethodDef PyQRgb_methods[] = { {NULL, NULL, 0, NULL} }; static void _wrap_PyQRgb__tp_dealloc(PyQRgb *self) { QRgb *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyQRgb__tp_richcompare (PyQRgb *PYBINDGEN_UNUSED(self), PyQRgb *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyQRgb_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyQRgb_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.qt.QRgb", /* tp_name */ sizeof(PyQRgb), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyQRgb__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyQRgb__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyQRgb_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyQRgb__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyQColor__tp_init__0(PyQColor *self, PyObject *args, PyObject *kwargs, PyObject **return_exception) { PyQRgb *col; const char *keywords[] = {"col", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyQRgb_Type, &col)) { { PyObject *exc_type, *traceback; PyErr_Fetch(&exc_type, return_exception, &traceback); Py_XDECREF(exc_type); Py_XDECREF(traceback); } return -1; } self->obj = new QColor(*((PyQRgb *) col)->obj); self->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return 0; } static int _wrap_PyQColor__tp_init__1(PyQColor *self, PyObject *args, PyObject *kwargs, PyObject **return_exception) { int r; int g; int b; const char *keywords[] = {"r", "g", "b", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "iii", (char **) keywords, &r, &g, &b)) { { PyObject *exc_type, *traceback; PyErr_Fetch(&exc_type, return_exception, &traceback); Py_XDECREF(exc_type); Py_XDECREF(traceback); } return -1; } self->obj = new QColor(r, g, b); self->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return 0; } static int _wrap_PyQColor__tp_init__2(PyQColor *self, PyObject *args, PyObject *kwargs, PyObject **return_exception) { int r; int g; int b; int a; const char *keywords[] = {"r", "g", "b", "a", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "iiii", (char **) keywords, &r, &g, &b, &a)) { { PyObject *exc_type, *traceback; PyErr_Fetch(&exc_type, return_exception, &traceback); Py_XDECREF(exc_type); Py_XDECREF(traceback); } return -1; } self->obj = new QColor(r, g, b, a); self->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return 0; } int _wrap_PyQColor__tp_init(PyQColor *self, PyObject *args, PyObject *kwargs) { int retval; PyObject *error_list; PyObject *exceptions[3] = {0,}; retval = _wrap_PyQColor__tp_init__0(self, args, kwargs, &exceptions[0]); if (!exceptions[0]) { return retval; } retval = _wrap_PyQColor__tp_init__1(self, args, kwargs, &exceptions[1]); if (!exceptions[1]) { Py_DECREF(exceptions[0]); return retval; } retval = _wrap_PyQColor__tp_init__2(self, args, kwargs, &exceptions[2]); if (!exceptions[2]) { Py_DECREF(exceptions[0]); Py_DECREF(exceptions[1]); return retval; } error_list = PyList_New(3); PyList_SET_ITEM(error_list, 0, PyObject_Str(exceptions[0])); Py_DECREF(exceptions[0]); PyList_SET_ITEM(error_list, 1, PyObject_Str(exceptions[1])); Py_DECREF(exceptions[1]); PyList_SET_ITEM(error_list, 2, PyObject_Str(exceptions[2])); Py_DECREF(exceptions[2]); PyErr_SetObject(PyExc_TypeError, error_list); Py_DECREF(error_list); return -1; } PyObject * _wrap_PyQColor_rgb(PyQColor *self) { PyObject *py_retval; PyQRgb *py_QRgb; QRgb retval = self->obj->rgb(); py_QRgb = PyObject_New(PyQRgb, &PyQRgb_Type); py_QRgb->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_QRgb->obj = new QRgb(retval); py_retval = Py_BuildValue((char *) "N", py_QRgb); return py_retval; } PyObject * _wrap_PyQColor_rgba(PyQColor *self) { PyObject *py_retval; PyQRgb *py_QRgb; QRgb retval = self->obj->rgba(); py_QRgb = PyObject_New(PyQRgb, &PyQRgb_Type); py_QRgb->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_QRgb->obj = new QRgb(retval); py_retval = Py_BuildValue((char *) "N", py_QRgb); return py_retval; } static PyMethodDef PyQColor_methods[] = { {(char *) "rgb", (PyCFunction) _wrap_PyQColor_rgb, METH_NOARGS, NULL }, {(char *) "rgba", (PyCFunction) _wrap_PyQColor_rgba, METH_NOARGS, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyQColor__tp_dealloc(PyQColor *self) { QColor *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyQColor__tp_richcompare (PyQColor *PYBINDGEN_UNUSED(self), PyQColor *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyQColor_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyQColor_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.qt.QColor", /* tp_name */ sizeof(PyQColor), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyQColor__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyQColor__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyQColor_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyQColor__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyQImage__tp_init__0(PyQImage *self, PyObject *args, PyObject *kwargs, PyObject **return_exception) { const char *keywords[] = {NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "", (char **) keywords)) { { PyObject *exc_type, *traceback; PyErr_Fetch(&exc_type, return_exception, &traceback); Py_XDECREF(exc_type); Py_XDECREF(traceback); } return -1; } self->obj = new QImage(); self->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return 0; } static int _wrap_PyQImage__tp_init__1(PyQImage *self, PyObject *args, PyObject *kwargs, PyObject **return_exception) { int w; int h; QImage::Format f; const char *keywords[] = {"w", "h", "f", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "iii", (char **) keywords, &w, &h, &f)) { { PyObject *exc_type, *traceback; PyErr_Fetch(&exc_type, return_exception, &traceback); Py_XDECREF(exc_type); Py_XDECREF(traceback); } return -1; } self->obj = new QImage(w, h, f); self->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return 0; } int _wrap_PyQImage__tp_init(PyQImage *self, PyObject *args, PyObject *kwargs) { int retval; PyObject *error_list; PyObject *exceptions[2] = {0,}; retval = _wrap_PyQImage__tp_init__0(self, args, kwargs, &exceptions[0]); if (!exceptions[0]) { return retval; } retval = _wrap_PyQImage__tp_init__1(self, args, kwargs, &exceptions[1]); if (!exceptions[1]) { Py_DECREF(exceptions[0]); return retval; } error_list = PyList_New(2); PyList_SET_ITEM(error_list, 0, PyObject_Str(exceptions[0])); Py_DECREF(exceptions[0]); PyList_SET_ITEM(error_list, 1, PyObject_Str(exceptions[1])); Py_DECREF(exceptions[1]); PyErr_SetObject(PyExc_TypeError, error_list); Py_DECREF(error_list); return -1; } PyObject * _wrap_PyQImage_load(PyQImage *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; bool retval; const char *fileName; Py_ssize_t fileName_len; char *fmt; const char *keywords[] = {"fileName", "fmt", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "s#s", (char **) keywords, &fileName, &fileName_len, &fmt)) { return NULL; } retval = self->obj->load(QString::fromUtf8(fileName), fmt); py_retval = Py_BuildValue((char *) "N", PyBool_FromLong(retval)); return py_retval; } PyObject * _wrap_PyQImage_setColor(PyQImage *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int i; PyQRgb *c; const char *keywords[] = {"i", "c", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "iO!", (char **) keywords, &i, &PyQRgb_Type, &c)) { return NULL; } self->obj->setColor(i, *((PyQRgb *) c)->obj); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyQImage_color(PyQImage *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int i; const char *keywords[] = {"i", NULL}; PyQRgb *py_QRgb; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &i)) { return NULL; } QRgb retval = self->obj->color(i); py_QRgb = PyObject_New(PyQRgb, &PyQRgb_Type); py_QRgb->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_QRgb->obj = new QRgb(retval); py_retval = Py_BuildValue((char *) "N", py_QRgb); return py_retval; } PyObject * _wrap_PyQImage_mirrored(PyQImage *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; bool horiz; PyObject *py_horiz; bool vert; PyObject *py_vert; const char *keywords[] = {"horiz", "vert", NULL}; PyQImage *py_QImage; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "OO", (char **) keywords, &py_horiz, &py_vert)) { return NULL; } horiz = (bool) PyObject_IsTrue(py_horiz); vert = (bool) PyObject_IsTrue(py_vert); QImage const & retval = self->obj->mirrored(horiz, vert); py_QImage = PyObject_New(PyQImage, &PyQImage_Type); py_QImage->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_QImage->obj = new QImage(retval); py_retval = Py_BuildValue((char *) "N", py_QImage); return py_retval; } PyObject * _wrap_PyQImage_height(PyQImage *self) { PyObject *py_retval; int retval; retval = self->obj->height(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyQImage_setPixel__0(PyQImage *self, PyObject *args, PyObject *kwargs, PyObject **return_exception) { PyObject *py_retval; int x; int y; unsigned int color; const char *keywords[] = {"x", "y", "color", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "iiI", (char **) keywords, &x, &y, &color)) { { PyObject *exc_type, *traceback; PyErr_Fetch(&exc_type, return_exception, &traceback); Py_XDECREF(exc_type); Py_XDECREF(traceback); } return NULL; } self->obj->setPixel(x, y, color); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyQImage_setPixel__1(PyQImage *self, PyObject *args, PyObject *kwargs, PyObject **return_exception) { PyObject *py_retval; int x; int y; PyQRgb *color; const char *keywords[] = {"x", "y", "color", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "iiO!", (char **) keywords, &x, &y, &PyQRgb_Type, &color)) { { PyObject *exc_type, *traceback; PyErr_Fetch(&exc_type, return_exception, &traceback); Py_XDECREF(exc_type); Py_XDECREF(traceback); } return NULL; } self->obj->setPixel(x, y, *((PyQRgb *) color)->obj); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyQImage_setPixel(PyQImage *self, PyObject *args, PyObject *kwargs) { PyObject * retval; PyObject *error_list; PyObject *exceptions[2] = {0,}; retval = _wrap_PyQImage_setPixel__0(self, args, kwargs, &exceptions[0]); if (!exceptions[0]) { return retval; } retval = _wrap_PyQImage_setPixel__1(self, args, kwargs, &exceptions[1]); if (!exceptions[1]) { Py_DECREF(exceptions[0]); return retval; } error_list = PyList_New(2); PyList_SET_ITEM(error_list, 0, PyObject_Str(exceptions[0])); Py_DECREF(exceptions[0]); PyList_SET_ITEM(error_list, 1, PyObject_Str(exceptions[1])); Py_DECREF(exceptions[1]); PyErr_SetObject(PyExc_TypeError, error_list); Py_DECREF(error_list); return NULL; } PyObject * _wrap_PyQImage_width(PyQImage *self) { PyObject *py_retval; int retval; retval = self->obj->width(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyQImage_colorTable(PyQImage *self) { PyObject *py_retval; QVector< QRgb > retval; PyQVector__lt__QRgb__gt__ *py_QVector__lt__QRgb__gt__; retval = self->obj->colorTable(); py_QVector__lt__QRgb__gt__ = PyObject_New(PyQVector__lt__QRgb__gt__, &PyQVector__lt__QRgb__gt___Type); py_QVector__lt__QRgb__gt__->obj = new QVector(retval); py_retval = Py_BuildValue((char *) "N", py_QVector__lt__QRgb__gt__); return py_retval; } PyObject * _wrap_PyQImage_setColorTable(PyQImage *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; QVector colors_value; const char *keywords[] = {"colors", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O&", (char **) keywords, _wrap_convert_py2c__QVector__lt___QRgb___gt__, &colors_value)) { return NULL; } self->obj->setColorTable(colors_value); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyQImage_fill(PyQImage *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int color; const char *keywords[] = {"color", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &color)) { return NULL; } self->obj->fill(color); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } static PyMethodDef PyQImage_methods[] = { {(char *) "load", (PyCFunction) _wrap_PyQImage_load, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "setColor", (PyCFunction) _wrap_PyQImage_setColor, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "color", (PyCFunction) _wrap_PyQImage_color, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "mirrored", (PyCFunction) _wrap_PyQImage_mirrored, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "height", (PyCFunction) _wrap_PyQImage_height, METH_NOARGS, NULL }, {(char *) "setPixel", (PyCFunction) _wrap_PyQImage_setPixel, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "width", (PyCFunction) _wrap_PyQImage_width, METH_NOARGS, NULL }, {(char *) "colorTable", (PyCFunction) _wrap_PyQImage_colorTable, METH_NOARGS, NULL }, {(char *) "setColorTable", (PyCFunction) _wrap_PyQImage_setColorTable, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "fill", (PyCFunction) _wrap_PyQImage_fill, METH_KEYWORDS|METH_VARARGS, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyQImage__tp_dealloc(PyQImage *self) { QImage *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyQImage__tp_richcompare (PyQImage *PYBINDGEN_UNUSED(self), PyQImage *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyQImage_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyQImage_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.qt.QImage", /* tp_name */ sizeof(PyQImage), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyQImage__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyQImage__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyQImage_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyQImage__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyQPixmap__tp_init(void) { PyErr_SetString(PyExc_TypeError, "class 'QPixmap' cannot be constructed ()"); return -1; } PyObject * _wrap_PyQPixmap_convertFromImage(PyQPixmap *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; PyQImage *image; const char *keywords[] = {"image", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyQImage_Type, &image)) { return NULL; } self->obj->convertFromImage(*((PyQImage *) image)->obj); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyQPixmap_width(PyQPixmap *self) { PyObject *py_retval; int retval; retval = self->obj->width(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyQPixmap_toImage(PyQPixmap *self) { PyObject *py_retval; PyQImage *py_QImage; QImage const & retval = self->obj->toImage(); py_QImage = PyObject_New(PyQImage, &PyQImage_Type); py_QImage->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_QImage->obj = new QImage(retval); py_retval = Py_BuildValue((char *) "N", py_QImage); return py_retval; } PyObject * _wrap_PyQPixmap_fromImage(PyQPixmap *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; PyQImage *image; const char *keywords[] = {"image", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyQImage_Type, &image)) { return NULL; } self->obj->fromImage(*((PyQImage *) image)->obj); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyQPixmap_height(PyQPixmap *self) { PyObject *py_retval; int retval; retval = self->obj->height(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } static PyMethodDef PyQPixmap_methods[] = { {(char *) "convertFromImage", (PyCFunction) _wrap_PyQPixmap_convertFromImage, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "width", (PyCFunction) _wrap_PyQPixmap_width, METH_NOARGS, NULL }, {(char *) "toImage", (PyCFunction) _wrap_PyQPixmap_toImage, METH_NOARGS, NULL }, {(char *) "fromImage", (PyCFunction) _wrap_PyQPixmap_fromImage, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "height", (PyCFunction) _wrap_PyQPixmap_height, METH_NOARGS, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyQPixmap__tp_dealloc(PyQPixmap *self) { QPixmap *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyQPixmap__tp_richcompare (PyQPixmap *PYBINDGEN_UNUSED(self), PyQPixmap *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyQPixmap_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyQPixmap_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.qt.QPixmap", /* tp_name */ sizeof(PyQPixmap), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyQPixmap__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyQPixmap__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyQPixmap_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyQPixmap__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyQWidget__tp_init(void) { PyErr_SetString(PyExc_TypeError, "class 'QWidget' cannot be constructed ()"); return -1; } static PyMethodDef PyQWidget_methods[] = { {NULL, NULL, 0, NULL} }; static void _wrap_PyQWidget__tp_dealloc(PyQWidget *self) { QWidget *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyQWidget__tp_richcompare (PyQWidget *PYBINDGEN_UNUSED(self), PyQWidget *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyQWidget_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyQWidget_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.qt.QWidget", /* tp_name */ sizeof(PyQWidget), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyQWidget__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyQWidget__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyQWidget_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyQWidget__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyQFileDialog__tp_init(void) { PyErr_SetString(PyExc_TypeError, "class 'QFileDialog' cannot be constructed ()"); return -1; } PyObject * _wrap_PyQFileDialog_getOpenFileName(PyQFileDialog *PYBINDGEN_UNUSED(dummy), PyObject *args, PyObject *kwargs) { PyObject *py_retval; QString retval; PyQWidget *parent; QWidget *parent_ptr; const char *caption; Py_ssize_t caption_len; const char *dir; Py_ssize_t dir_len; const char *filter; Py_ssize_t filter_len; const char *selectedFilter; QFileDialog::Option options; const char *keywords[] = {"parent", "caption", "dir", "filter", "selectedFilter", "options", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "Os#s#s#|si", (char **) keywords, &parent, &caption, &caption_len, &dir, &dir_len, &filter, &filter_len, &selectedFilter, &options)) { return NULL; } if (parent && ((PyObject *) parent != Py_None) && !PyObject_IsInstance((PyObject *) parent, (PyObject *) &PyQWidget_Type)) { PyErr_SetString(PyExc_TypeError, "Parameter 1 must be of type QWidget"); return NULL; } if (parent) { if ((PyObject *) parent == Py_None) parent_ptr = NULL; else parent_ptr = parent->obj; } else { parent_ptr = NULL; } retval = QFileDialog::getOpenFileName(parent_ptr, QString::fromUtf8(caption), QString::fromUtf8(dir), QString::fromUtf8(filter), new QString(""), 0); py_retval = Py_BuildValue((char *) "s", retval.toUtf8().data()); return py_retval; } static PyMethodDef PyQFileDialog_methods[] = { {(char *) "getOpenFileName", (PyCFunction) _wrap_PyQFileDialog_getOpenFileName, METH_KEYWORDS|METH_VARARGS|METH_STATIC, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyQFileDialog__tp_dealloc(PyQFileDialog *self) { QFileDialog *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyQFileDialog__tp_richcompare (PyQFileDialog *PYBINDGEN_UNUSED(self), PyQFileDialog *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyQFileDialog_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyQFileDialog_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.qt.QFileDialog", /* tp_name */ sizeof(PyQFileDialog), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyQFileDialog__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyQFileDialog__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyQFileDialog_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyQFileDialog__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; /* --- containers --- */ static void PyQVector__lt__QRgb__gt__Iter__tp_clear(PyQVector__lt__QRgb__gt__Iter *self) { Py_CLEAR(self->container); delete self->iterator; self->iterator = NULL; } static int PyQVector__lt__QRgb__gt__Iter__tp_traverse(PyQVector__lt__QRgb__gt__Iter *self, visitproc visit, void *arg) { Py_VISIT((PyObject *) self->container); return 0; } static void _wrap_PyQVector__lt__QRgb__gt____tp_dealloc(PyQVector__lt__QRgb__gt__ *self) { delete self->obj; self->obj = NULL; Py_TYPE(self)->tp_free((PyObject*)self); } static void _wrap_PyQVector__lt__QRgb__gt__Iter__tp_dealloc(PyQVector__lt__QRgb__gt__Iter *self) { Py_CLEAR(self->container); delete self->iterator; self->iterator = NULL; Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyQVector__lt__QRgb__gt____tp_iter(PyQVector__lt__QRgb__gt__ *self) { PyQVector__lt__QRgb__gt__Iter *iter = PyObject_GC_New(PyQVector__lt__QRgb__gt__Iter, &PyQVector__lt__QRgb__gt__Iter_Type); Py_INCREF(self); iter->container = self; iter->iterator = new QVector::iterator(self->obj->begin()); return (PyObject*) iter; } static PyObject* _wrap_PyQVector__lt__QRgb__gt__Iter__tp_iter(PyQVector__lt__QRgb__gt__Iter *self) { Py_INCREF(self); return (PyObject*) self; } static PyObject* _wrap_PyQVector__lt__QRgb__gt__Iter__tp_iternext(PyQVector__lt__QRgb__gt__Iter *self) { PyObject *py_retval; QVector::iterator iter; PyQRgb *py_QRgb; iter = *self->iterator; if (iter == self->container->obj->end()) { PyErr_SetNone(PyExc_StopIteration); return NULL; } ++(*self->iterator); py_QRgb = PyObject_New(PyQRgb, &PyQRgb_Type); py_QRgb->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_QRgb->obj = new QRgb((*iter)); py_retval = Py_BuildValue((char *) "N", py_QRgb); return py_retval; } int _wrap_convert_py2c__QRgb(PyObject *value, QRgb *address) { PyObject *py_retval; PyQRgb *tmp_QRgb; py_retval = Py_BuildValue((char *) "(O)", value); if (!PyArg_ParseTuple(py_retval, (char *) "O!", &PyQRgb_Type, &tmp_QRgb)) { Py_DECREF(py_retval); return 0; } *address = *tmp_QRgb->obj; Py_DECREF(py_retval); return 1; } int _wrap_convert_py2c__QVector__lt___QRgb___gt__(PyObject *arg, QVector *container) { if (PyObject_IsInstance(arg, (PyObject*) &PyQVector__lt__QRgb__gt___Type)) { *container = *((PyQVector__lt__QRgb__gt__*)arg)->obj; } else if (PyList_Check(arg)) { container->clear(); Py_ssize_t size = PyList_Size(arg); for (Py_ssize_t i = 0; i < size; i++) { QRgb item; if (!_wrap_convert_py2c__QRgb(PyList_GET_ITEM(arg, i), &item)) { return 0; } container->push_back(item); } } else { PyErr_SetString(PyExc_TypeError, "parameter must be None, a QVector__lt__QRgb__gt__ instance, or a list of QRgb"); return 0; } return 1; } static int _wrap_PyQVector__lt__QRgb__gt____tp_init(PyQVector__lt__QRgb__gt__ *self, PyObject *args, PyObject *kwargs) { const char *keywords[] = {"arg", NULL}; PyObject *arg = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "|O", (char **) keywords, &arg)) { return -1; } self->obj = new QVector; if (arg == NULL) return 0; if (!_wrap_convert_py2c__QVector__lt___QRgb___gt__(arg, self->obj)) { delete self->obj; self->obj = NULL; return -1; } return 0; } PyTypeObject PyQVector__lt__QRgb__gt___Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.qt.QVector__lt__QRgb__gt__", /* tp_name */ sizeof(PyQVector__lt__QRgb__gt__), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyQVector__lt__QRgb__gt____tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)NULL, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)_wrap_PyQVector__lt__QRgb__gt____tp_iter, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)NULL, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ NULL, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyQVector__lt__QRgb__gt____tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; PyTypeObject PyQVector__lt__QRgb__gt__Iter_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.qt.QVector__lt__QRgb__gt__Iter", /* tp_name */ sizeof(PyQVector__lt__QRgb__gt__Iter), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyQVector__lt__QRgb__gt__Iter__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)PyQVector__lt__QRgb__gt__Iter__tp_traverse, /* tp_traverse */ (inquiry)PyQVector__lt__QRgb__gt__Iter__tp_clear, /* tp_clear */ (richcmpfunc)NULL, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)_wrap_PyQVector__lt__QRgb__gt__Iter__tp_iter, /* tp_iter */ (iternextfunc)_wrap_PyQVector__lt__QRgb__gt__Iter__tp_iternext, /* tp_iternext */ (struct PyMethodDef*)NULL, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ NULL, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)NULL, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static void PyQList__lt__QString__gt__Iter__tp_clear(PyQList__lt__QString__gt__Iter *self) { Py_CLEAR(self->container); delete self->iterator; self->iterator = NULL; } static int PyQList__lt__QString__gt__Iter__tp_traverse(PyQList__lt__QString__gt__Iter *self, visitproc visit, void *arg) { Py_VISIT((PyObject *) self->container); return 0; } static void _wrap_PyQList__lt__QString__gt____tp_dealloc(PyQList__lt__QString__gt__ *self) { delete self->obj; self->obj = NULL; Py_TYPE(self)->tp_free((PyObject*)self); } static void _wrap_PyQList__lt__QString__gt__Iter__tp_dealloc(PyQList__lt__QString__gt__Iter *self) { Py_CLEAR(self->container); delete self->iterator; self->iterator = NULL; Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyQList__lt__QString__gt____tp_iter(PyQList__lt__QString__gt__ *self) { PyQList__lt__QString__gt__Iter *iter = PyObject_GC_New(PyQList__lt__QString__gt__Iter, &PyQList__lt__QString__gt__Iter_Type); Py_INCREF(self); iter->container = self; iter->iterator = new QList::iterator(self->obj->begin()); return (PyObject*) iter; } static PyObject* _wrap_PyQList__lt__QString__gt__Iter__tp_iter(PyQList__lt__QString__gt__Iter *self) { Py_INCREF(self); return (PyObject*) self; } static PyObject* _wrap_PyQList__lt__QString__gt__Iter__tp_iternext(PyQList__lt__QString__gt__Iter *self) { PyObject *py_retval; QList::iterator iter; iter = *self->iterator; if (iter == self->container->obj->end()) { PyErr_SetNone(PyExc_StopIteration); return NULL; } ++(*self->iterator); py_retval = Py_BuildValue((char *) "s", (*iter).toUtf8().data()); return py_retval; } int _wrap_convert_py2c__QString(PyObject *value, QString *address) { PyObject *py_retval; const char *retval_ptr; Py_ssize_t retval_len; py_retval = Py_BuildValue((char *) "(O)", value); if (!PyArg_ParseTuple(py_retval, (char *) "s#", &retval_ptr, &retval_len)) { Py_DECREF(py_retval); return 0; } *address = QString(retval_ptr); Py_DECREF(py_retval); return 1; } int _wrap_convert_py2c__QList__lt___QString___gt__(PyObject *arg, QList *container) { if (PyObject_IsInstance(arg, (PyObject*) &PyQList__lt__QString__gt___Type)) { *container = *((PyQList__lt__QString__gt__*)arg)->obj; } else if (PyList_Check(arg)) { container->clear(); Py_ssize_t size = PyList_Size(arg); for (Py_ssize_t i = 0; i < size; i++) { QString item; if (!_wrap_convert_py2c__QString(PyList_GET_ITEM(arg, i), &item)) { return 0; } container->push_back(item); } } else { PyErr_SetString(PyExc_TypeError, "parameter must be None, a QList__lt__QString__gt__ instance, or a list of QString"); return 0; } return 1; } static int _wrap_PyQList__lt__QString__gt____tp_init(PyQList__lt__QString__gt__ *self, PyObject *args, PyObject *kwargs) { const char *keywords[] = {"arg", NULL}; PyObject *arg = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "|O", (char **) keywords, &arg)) { return -1; } self->obj = new QList; if (arg == NULL) return 0; if (!_wrap_convert_py2c__QList__lt___QString___gt__(arg, self->obj)) { delete self->obj; self->obj = NULL; return -1; } return 0; } PyTypeObject PyQList__lt__QString__gt___Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.qt.QList__lt__QString__gt__", /* tp_name */ sizeof(PyQList__lt__QString__gt__), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyQList__lt__QString__gt____tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)NULL, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)_wrap_PyQList__lt__QString__gt____tp_iter, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)NULL, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ NULL, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyQList__lt__QString__gt____tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; PyTypeObject PyQList__lt__QString__gt__Iter_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.qt.QList__lt__QString__gt__Iter", /* tp_name */ sizeof(PyQList__lt__QString__gt__Iter), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyQList__lt__QString__gt__Iter__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)PyQList__lt__QString__gt__Iter__tp_traverse, /* tp_traverse */ (inquiry)PyQList__lt__QString__gt__Iter__tp_clear, /* tp_clear */ (richcmpfunc)NULL, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)_wrap_PyQList__lt__QString__gt__Iter__tp_iter, /* tp_iter */ (iternextfunc)_wrap_PyQList__lt__QString__gt__Iter__tp_iternext, /* tp_iternext */ (struct PyMethodDef*)NULL, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ NULL, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)NULL, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; /* --- enumerations --- */ bool isImageLayerAt(Tiled::Map *map, int idx) { return (dynamic_cast(map->layerAt(idx)) != 0); } bool isTileLayerAt(Tiled::Map *map, int idx) { return (dynamic_cast(map->layerAt(idx)) != 0); } bool isObjectGroupAt(Tiled::Map *map, int idx) { return (dynamic_cast(map->layerAt(idx)) != 0); } Tiled::ImageLayer* imageLayerAt(Tiled::Map *map, int idx) { return static_cast(map->layerAt(idx)); } Tiled::TileLayer* tileLayerAt(Tiled::Map *map, int idx) { return static_cast(map->layerAt(idx)); } Tiled::ObjectGroup* objectGroupAt(Tiled::Map *map, int idx) { return static_cast(map->layerAt(idx)); } bool loadTilesetFromFile(Tiled::Tileset *ts, QString file) { QImage img(file); return ts->loadFromImage(img, file); } #if PY_VERSION_HEX >= 0x03000000 static struct PyModuleDef qt_moduledef = { PyModuleDef_HEAD_INIT, "tiled.qt", NULL, -1, tiled_qt_functions, }; #endif static PyObject * inittiled_qt(void) { PyObject *m; #if PY_VERSION_HEX >= 0x03000000 m = PyModule_Create(&qt_moduledef); #else m = Py_InitModule3((char *) "tiled.qt", tiled_qt_functions, NULL); #endif if (m == NULL) { return NULL; } /* Register the 'QPointF' class */ if (PyType_Ready(&PyQPointF_Type)) { return NULL; } PyModule_AddObject(m, (char *) "QPointF", (PyObject *) &PyQPointF_Type); /* Register the 'QSizeF' class */ if (PyType_Ready(&PyQSizeF_Type)) { return NULL; } PyModule_AddObject(m, (char *) "QSizeF", (PyObject *) &PyQSizeF_Type); /* Register the 'QRgb' class */ if (PyType_Ready(&PyQRgb_Type)) { return NULL; } PyModule_AddObject(m, (char *) "QRgb", (PyObject *) &PyQRgb_Type); /* Register the 'QColor' class */ if (PyType_Ready(&PyQColor_Type)) { return NULL; } PyModule_AddObject(m, (char *) "QColor", (PyObject *) &PyQColor_Type); /* Register the 'QImage' class */ if (PyType_Ready(&PyQImage_Type)) { return NULL; } PyModule_AddObject(m, (char *) "QImage", (PyObject *) &PyQImage_Type); /* Register the 'QPixmap' class */ if (PyType_Ready(&PyQPixmap_Type)) { return NULL; } PyModule_AddObject(m, (char *) "QPixmap", (PyObject *) &PyQPixmap_Type); /* Register the 'QWidget' class */ if (PyType_Ready(&PyQWidget_Type)) { return NULL; } PyModule_AddObject(m, (char *) "QWidget", (PyObject *) &PyQWidget_Type); /* Register the 'QFileDialog' class */ if (PyType_Ready(&PyQFileDialog_Type)) { return NULL; } PyModule_AddObject(m, (char *) "QFileDialog", (PyObject *) &PyQFileDialog_Type); /* Register the 'QVector' class */ if (PyType_Ready(&PyQVector__lt__QRgb__gt___Type)) { return NULL; } if (PyType_Ready(&PyQVector__lt__QRgb__gt__Iter_Type)) { return NULL; } PyModule_AddObject(m, (char *) "QVector__lt__QRgb__gt__", (PyObject *) &PyQVector__lt__QRgb__gt___Type); PyModule_AddObject(m, (char *) "QVector__lt__QRgb__gt__Iter", (PyObject *) &PyQVector__lt__QRgb__gt__Iter_Type); /* Register the 'QList' class */ if (PyType_Ready(&PyQList__lt__QString__gt___Type)) { return NULL; } if (PyType_Ready(&PyQList__lt__QString__gt__Iter_Type)) { return NULL; } PyModule_AddObject(m, (char *) "QList__lt__QString__gt__", (PyObject *) &PyQList__lt__QString__gt___Type); PyModule_AddObject(m, (char *) "QList__lt__QString__gt__Iter", (PyObject *) &PyQList__lt__QString__gt__Iter_Type); { PyObject *tmp_value; // QImage::Format_Invalid tmp_value = PyLong_FromLong(QImage::Format_Invalid); PyDict_SetItemString((PyObject*) PyQImage_Type.tp_dict, "Format_Invalid", tmp_value); Py_DECREF(tmp_value); // QImage::Format_Mono tmp_value = PyLong_FromLong(QImage::Format_Mono); PyDict_SetItemString((PyObject*) PyQImage_Type.tp_dict, "Format_Mono", tmp_value); Py_DECREF(tmp_value); // QImage::Format_MonoLSB tmp_value = PyLong_FromLong(QImage::Format_MonoLSB); PyDict_SetItemString((PyObject*) PyQImage_Type.tp_dict, "Format_MonoLSB", tmp_value); Py_DECREF(tmp_value); // QImage::Format_Indexed8 tmp_value = PyLong_FromLong(QImage::Format_Indexed8); PyDict_SetItemString((PyObject*) PyQImage_Type.tp_dict, "Format_Indexed8", tmp_value); Py_DECREF(tmp_value); // QImage::Format_RGB32 tmp_value = PyLong_FromLong(QImage::Format_RGB32); PyDict_SetItemString((PyObject*) PyQImage_Type.tp_dict, "Format_RGB32", tmp_value); Py_DECREF(tmp_value); // QImage::Format_ARGB32 tmp_value = PyLong_FromLong(QImage::Format_ARGB32); PyDict_SetItemString((PyObject*) PyQImage_Type.tp_dict, "Format_ARGB32", tmp_value); Py_DECREF(tmp_value); // QImage::Format_ARGB32_Premultiplied tmp_value = PyLong_FromLong(QImage::Format_ARGB32_Premultiplied); PyDict_SetItemString((PyObject*) PyQImage_Type.tp_dict, "Format_ARGB32_Premultiplied", tmp_value); Py_DECREF(tmp_value); // QImage::Format_RGB16 tmp_value = PyLong_FromLong(QImage::Format_RGB16); PyDict_SetItemString((PyObject*) PyQImage_Type.tp_dict, "Format_RGB16", tmp_value); Py_DECREF(tmp_value); // QImage::Format_ARGB8565_Premultiplied tmp_value = PyLong_FromLong(QImage::Format_ARGB8565_Premultiplied); PyDict_SetItemString((PyObject*) PyQImage_Type.tp_dict, "Format_ARGB8565_Premultiplied", tmp_value); Py_DECREF(tmp_value); // QImage::Format_RGB666 tmp_value = PyLong_FromLong(QImage::Format_RGB666); PyDict_SetItemString((PyObject*) PyQImage_Type.tp_dict, "Format_RGB666", tmp_value); Py_DECREF(tmp_value); // QImage::Format_ARGB6666_Premultiplied tmp_value = PyLong_FromLong(QImage::Format_ARGB6666_Premultiplied); PyDict_SetItemString((PyObject*) PyQImage_Type.tp_dict, "Format_ARGB6666_Premultiplied", tmp_value); Py_DECREF(tmp_value); // QImage::Format_RGB555 tmp_value = PyLong_FromLong(QImage::Format_RGB555); PyDict_SetItemString((PyObject*) PyQImage_Type.tp_dict, "Format_RGB555", tmp_value); Py_DECREF(tmp_value); // QImage::Format_ARGB8555_Premultiplied tmp_value = PyLong_FromLong(QImage::Format_ARGB8555_Premultiplied); PyDict_SetItemString((PyObject*) PyQImage_Type.tp_dict, "Format_ARGB8555_Premultiplied", tmp_value); Py_DECREF(tmp_value); // QImage::Format_RGB888 tmp_value = PyLong_FromLong(QImage::Format_RGB888); PyDict_SetItemString((PyObject*) PyQImage_Type.tp_dict, "Format_RGB888", tmp_value); Py_DECREF(tmp_value); // QImage::Format_RGB444 tmp_value = PyLong_FromLong(QImage::Format_RGB444); PyDict_SetItemString((PyObject*) PyQImage_Type.tp_dict, "Format_RGB444", tmp_value); Py_DECREF(tmp_value); // QImage::Format_ARGB4444_Premultiplied tmp_value = PyLong_FromLong(QImage::Format_ARGB4444_Premultiplied); PyDict_SetItemString((PyObject*) PyQImage_Type.tp_dict, "Format_ARGB4444_Premultiplied", tmp_value); Py_DECREF(tmp_value); } { PyObject *tmp_value; // QFileDialog::ShowDirsOnly tmp_value = PyLong_FromLong(QFileDialog::ShowDirsOnly); PyDict_SetItemString((PyObject*) PyQFileDialog_Type.tp_dict, "ShowDirsOnly", tmp_value); Py_DECREF(tmp_value); // QFileDialog::DontResolveSymlinks tmp_value = PyLong_FromLong(QFileDialog::DontResolveSymlinks); PyDict_SetItemString((PyObject*) PyQFileDialog_Type.tp_dict, "DontResolveSymlinks", tmp_value); Py_DECREF(tmp_value); // QFileDialog::DontConfirmOverwrite tmp_value = PyLong_FromLong(QFileDialog::DontConfirmOverwrite); PyDict_SetItemString((PyObject*) PyQFileDialog_Type.tp_dict, "DontConfirmOverwrite", tmp_value); Py_DECREF(tmp_value); // QFileDialog::DontUseNativeDialog tmp_value = PyLong_FromLong(QFileDialog::DontUseNativeDialog); PyDict_SetItemString((PyObject*) PyQFileDialog_Type.tp_dict, "DontUseNativeDialog", tmp_value); Py_DECREF(tmp_value); // QFileDialog::ReadOnly tmp_value = PyLong_FromLong(QFileDialog::ReadOnly); PyDict_SetItemString((PyObject*) PyQFileDialog_Type.tp_dict, "ReadOnly", tmp_value); Py_DECREF(tmp_value); // QFileDialog::HideNameFilterDetails tmp_value = PyLong_FromLong(QFileDialog::HideNameFilterDetails); PyDict_SetItemString((PyObject*) PyQFileDialog_Type.tp_dict, "HideNameFilterDetails", tmp_value); Py_DECREF(tmp_value); // QFileDialog::DontUseSheet tmp_value = PyLong_FromLong(QFileDialog::DontUseSheet); PyDict_SetItemString((PyObject*) PyQFileDialog_Type.tp_dict, "DontUseSheet", tmp_value); Py_DECREF(tmp_value); } return m; } static PyMethodDef tiled_Tiled_functions[] = { {NULL, NULL, 0, NULL} }; /* --- classes --- */ static int _wrap_PyTiledProperties__tp_init(void) { PyErr_SetString(PyExc_TypeError, "class 'Properties' cannot be constructed ()"); return -1; } PyObject * _wrap_PyTiledProperties_keys(PyTiledProperties *self) { PyObject *py_retval; QList< QString > retval; PyQList__lt__QString__gt__ *py_QList__lt__QString__gt__; retval = self->obj->keys(); py_QList__lt__QString__gt__ = PyObject_New(PyQList__lt__QString__gt__, &PyQList__lt__QString__gt___Type); py_QList__lt__QString__gt__->obj = new QList(retval); py_retval = Py_BuildValue((char *) "N", py_QList__lt__QString__gt__); return py_retval; } static PyMethodDef PyTiledProperties_methods[] = { {(char *) "keys", (PyCFunction) _wrap_PyTiledProperties_keys, METH_NOARGS, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyTiledProperties__tp_dealloc(PyTiledProperties *self) { Tiled::Properties *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyTiledProperties__tp_richcompare (PyTiledProperties *PYBINDGEN_UNUSED(self), PyTiledProperties *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyTiledProperties_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyTiledProperties_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.Tiled.Properties", /* tp_name */ sizeof(PyTiledProperties), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyTiledProperties__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyTiledProperties__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyTiledProperties_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyTiledProperties__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyTiledObject__tp_init(void) { PyErr_SetString(PyExc_TypeError, "class 'Object' cannot be constructed ()"); return -1; } PyObject * _wrap_PyTiledObject_setProperty(PyTiledObject *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; const char *prop; Py_ssize_t prop_len; const char *val; Py_ssize_t val_len; const char *keywords[] = {"prop", "val", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "s#s#", (char **) keywords, &prop, &prop_len, &val, &val_len)) { return NULL; } self->obj->setProperty(QString::fromUtf8(prop), QString::fromUtf8(val)); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledObject_propertyAsString(PyTiledObject *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; QString retval; const char *prop; Py_ssize_t prop_len; const char *keywords[] = {"prop", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "s#", (char **) keywords, &prop, &prop_len)) { return NULL; } retval = self->obj->propertyAsString(QString::fromUtf8(prop)); py_retval = Py_BuildValue((char *) "s", retval.toUtf8().data()); return py_retval; } PyObject * _wrap_PyTiledObject_properties(PyTiledObject *self) { PyObject *py_retval; PyTiledProperties *py_Properties; Tiled::Properties const retval = self->obj->properties(); py_Properties = PyObject_New(PyTiledProperties, &PyTiledProperties_Type); py_Properties->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_Properties->obj = new Tiled::Properties(retval); py_retval = Py_BuildValue((char *) "N", py_Properties); return py_retval; } static PyMethodDef PyTiledObject_methods[] = { {(char *) "setProperty", (PyCFunction) _wrap_PyTiledObject_setProperty, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "propertyAsString", (PyCFunction) _wrap_PyTiledObject_propertyAsString, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "properties", (PyCFunction) _wrap_PyTiledObject_properties, METH_NOARGS, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyTiledObject__tp_dealloc(PyTiledObject *self) { Tiled::Object *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyTiledObject__tp_richcompare (PyTiledObject *PYBINDGEN_UNUSED(self), PyTiledObject *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyTiledObject_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyTiledObject_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.Tiled.Object", /* tp_name */ sizeof(PyTiledObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyTiledObject__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyTiledObject__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyTiledObject_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyTiledObject__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyTiledTile__tp_init(PyTiledTile *self, PyObject *args, PyObject *kwargs) { PyQPixmap *image; int id; PyTiledTileset *tileset; Tiled::Tileset *tileset_ptr; const char *keywords[] = {"image", "id", "tileset", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!iO!", (char **) keywords, &PyQPixmap_Type, &image, &id, &PyTiledTileset_Type, &tileset)) { return -1; } tileset_ptr = (tileset ? tileset->obj : NULL); self->obj = new Tiled::Tile(*((PyQPixmap *) image)->obj, id, tileset_ptr); self->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return 0; } PyObject * _wrap_PyTiledTile_tileset(PyTiledTile *self) { PyObject *py_retval; Tiled::Tileset *retval; PyTiledTileset *py_Tileset; retval = self->obj->tileset(); if (!(retval)) { Py_INCREF(Py_None); return Py_None; } py_Tileset = PyObject_New(PyTiledTileset, &PyTiledTileset_Type); py_Tileset->obj = retval; py_Tileset->flags = PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED; py_retval = Py_BuildValue((char *) "N", py_Tileset); return py_retval; } PyObject * _wrap_PyTiledTile_setImage(PyTiledTile *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; PyQPixmap *image; const char *keywords[] = {"image", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyQPixmap_Type, &image)) { return NULL; } self->obj->setImage(*((PyQPixmap *) image)->obj); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledTile_image(PyTiledTile *self) { PyObject *py_retval; PyQPixmap *py_QPixmap; QPixmap const & retval = self->obj->image(); py_QPixmap = PyObject_New(PyQPixmap, &PyQPixmap_Type); py_QPixmap->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_QPixmap->obj = new QPixmap(retval); py_retval = Py_BuildValue((char *) "N", py_QPixmap); return py_retval; } PyObject * _wrap_PyTiledTile_height(PyTiledTile *self) { PyObject *py_retval; int retval; retval = self->obj->height(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledTile_width(PyTiledTile *self) { PyObject *py_retval; int retval; retval = self->obj->width(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledTile_id(PyTiledTile *self) { PyObject *py_retval; int retval; retval = self->obj->id(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } static PyMethodDef PyTiledTile_methods[] = { {(char *) "tileset", (PyCFunction) _wrap_PyTiledTile_tileset, METH_NOARGS, NULL }, {(char *) "setImage", (PyCFunction) _wrap_PyTiledTile_setImage, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "image", (PyCFunction) _wrap_PyTiledTile_image, METH_NOARGS, NULL }, {(char *) "height", (PyCFunction) _wrap_PyTiledTile_height, METH_NOARGS, NULL }, {(char *) "width", (PyCFunction) _wrap_PyTiledTile_width, METH_NOARGS, NULL }, {(char *) "id", (PyCFunction) _wrap_PyTiledTile_id, METH_NOARGS, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyTiledTile__tp_dealloc(PyTiledTile *self) { Tiled::Tile *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyTiledTile__tp_richcompare (PyTiledTile *PYBINDGEN_UNUSED(self), PyTiledTile *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyTiledTile_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyTiledTile_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.Tiled.Tile", /* tp_name */ sizeof(PyTiledTile), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyTiledTile__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyTiledTile__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyTiledTile_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyTiledTile__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyTiledSharedTileset__tp_init(void) { PyErr_SetString(PyExc_TypeError, "class 'SharedTileset' cannot be constructed ()"); return -1; } static PyMethodDef PyTiledSharedTileset_methods[] = { {NULL, NULL, 0, NULL} }; static void _wrap_PyTiledSharedTileset__tp_dealloc(PyTiledSharedTileset *self) { Tiled::SharedTileset *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyTiledSharedTileset__tp_richcompare (PyTiledSharedTileset *PYBINDGEN_UNUSED(self), PyTiledSharedTileset *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyTiledSharedTileset_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyTiledSharedTileset_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.Tiled.SharedTileset", /* tp_name */ sizeof(PyTiledSharedTileset), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyTiledSharedTileset__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyTiledSharedTileset__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyTiledSharedTileset_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyTiledSharedTileset__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyTiledTileset__tp_init(void) { PyErr_SetString(PyExc_TypeError, "class 'Tileset' cannot be constructed ()"); return -1; } PyObject * _wrap_PyTiledTileset_columnCount(PyTiledTileset *self) { PyObject *py_retval; int retval; retval = self->obj->columnCount(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledTileset_loadFromImage(PyTiledTileset *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; bool retval; PyQImage *img; const char *file; Py_ssize_t file_len; const char *keywords[] = {"img", "file", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!s#", (char **) keywords, &PyQImage_Type, &img, &file, &file_len)) { return NULL; } retval = self->obj->loadFromImage(*((PyQImage *) img)->obj, QString::fromUtf8(file)); py_retval = Py_BuildValue((char *) "N", PyBool_FromLong(retval)); return py_retval; } PyObject * _wrap_PyTiledTileset_tileSpacing(PyTiledTileset *self) { PyObject *py_retval; int retval; retval = self->obj->tileSpacing(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledTileset_name(PyTiledTileset *self) { PyObject *py_retval; QString retval; retval = self->obj->name(); py_retval = Py_BuildValue((char *) "s", retval.toUtf8().data()); return py_retval; } PyObject * _wrap_PyTiledTileset_setName(PyTiledTileset *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; const char *name; Py_ssize_t name_len; const char *keywords[] = {"name", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "s#", (char **) keywords, &name, &name_len)) { return NULL; } self->obj->setName(QString::fromUtf8(name)); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledTileset_tileHeight(PyTiledTileset *self) { PyObject *py_retval; int retval; retval = self->obj->tileHeight(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledTileset_tileWidth(PyTiledTileset *self) { PyObject *py_retval; int retval; retval = self->obj->tileWidth(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledTileset_create(PyTiledTileset *PYBINDGEN_UNUSED(dummy), PyObject *args, PyObject *kwargs) { PyObject *py_retval; const char *name; Py_ssize_t name_len; int tileWidth; int tileHeight; int tileSpacing; int margin; const char *keywords[] = {"name", "tileWidth", "tileHeight", "tileSpacing", "margin", NULL}; PyTiledSharedTileset *py_SharedTileset; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "s#iiii", (char **) keywords, &name, &name_len, &tileWidth, &tileHeight, &tileSpacing, &margin)) { return NULL; } Tiled::SharedTileset retval = Tiled::Tileset::create(QString::fromUtf8(name), tileWidth, tileHeight, tileSpacing, margin); py_SharedTileset = PyObject_New(PyTiledSharedTileset, &PyTiledSharedTileset_Type); py_SharedTileset->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_SharedTileset->obj = new Tiled::SharedTileset(retval); py_retval = Py_BuildValue((char *) "N", py_SharedTileset); return py_retval; } PyObject * _wrap_PyTiledTileset_transparentColor(PyTiledTileset *self) { PyObject *py_retval; PyQColor *py_QColor; QColor retval = self->obj->transparentColor(); py_QColor = PyObject_New(PyQColor, &PyQColor_Type); py_QColor->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_QColor->obj = new QColor(retval); py_retval = Py_BuildValue((char *) "N", py_QColor); return py_retval; } PyObject * _wrap_PyTiledTileset_setFileName(PyTiledTileset *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; const char *name; Py_ssize_t name_len; const char *keywords[] = {"name", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "s#", (char **) keywords, &name, &name_len)) { return NULL; } self->obj->setFileName(QString::fromUtf8(name)); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledTileset_tileAt(PyTiledTileset *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; Tiled::Tile *retval; int id; const char *keywords[] = {"id", NULL}; PyTiledTile *py_Tile; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &id)) { return NULL; } retval = self->obj->tileAt(id); if (!(retval)) { Py_INCREF(Py_None); return Py_None; } py_Tile = PyObject_New(PyTiledTile, &PyTiledTile_Type); py_Tile->obj = retval; py_Tile->flags = PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED; py_retval = Py_BuildValue((char *) "N", py_Tile); return py_retval; } PyObject * _wrap_PyTiledTileset_fileName(PyTiledTileset *self) { PyObject *py_retval; QString retval; retval = self->obj->fileName(); py_retval = Py_BuildValue((char *) "s", retval.toUtf8().data()); return py_retval; } PyObject * _wrap_PyTiledTileset_tileCount(PyTiledTileset *self) { PyObject *py_retval; int retval; retval = self->obj->tileCount(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledTileset_imageHeight(PyTiledTileset *self) { PyObject *py_retval; int retval; retval = self->obj->imageHeight(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledTileset_imageWidth(PyTiledTileset *self) { PyObject *py_retval; int retval; retval = self->obj->imageWidth(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledTileset_setTransparentColor(PyTiledTileset *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; PyQColor *col; const char *keywords[] = {"col", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyQColor_Type, &col)) { return NULL; } self->obj->setTransparentColor(*((PyQColor *) col)->obj); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledTileset_margin(PyTiledTileset *self) { PyObject *py_retval; int retval; retval = self->obj->margin(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledTileset_isExternal(PyTiledTileset *self) { PyObject *py_retval; bool retval; retval = self->obj->isExternal(); py_retval = Py_BuildValue((char *) "N", PyBool_FromLong(retval)); return py_retval; } static PyMethodDef PyTiledTileset_methods[] = { {(char *) "columnCount", (PyCFunction) _wrap_PyTiledTileset_columnCount, METH_NOARGS, NULL }, {(char *) "loadFromImage", (PyCFunction) _wrap_PyTiledTileset_loadFromImage, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "tileSpacing", (PyCFunction) _wrap_PyTiledTileset_tileSpacing, METH_NOARGS, NULL }, {(char *) "name", (PyCFunction) _wrap_PyTiledTileset_name, METH_NOARGS, NULL }, {(char *) "setName", (PyCFunction) _wrap_PyTiledTileset_setName, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "tileHeight", (PyCFunction) _wrap_PyTiledTileset_tileHeight, METH_NOARGS, NULL }, {(char *) "tileWidth", (PyCFunction) _wrap_PyTiledTileset_tileWidth, METH_NOARGS, NULL }, {(char *) "create", (PyCFunction) _wrap_PyTiledTileset_create, METH_KEYWORDS|METH_VARARGS|METH_STATIC, NULL }, {(char *) "transparentColor", (PyCFunction) _wrap_PyTiledTileset_transparentColor, METH_NOARGS, NULL }, {(char *) "setFileName", (PyCFunction) _wrap_PyTiledTileset_setFileName, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "tileAt", (PyCFunction) _wrap_PyTiledTileset_tileAt, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "fileName", (PyCFunction) _wrap_PyTiledTileset_fileName, METH_NOARGS, NULL }, {(char *) "tileCount", (PyCFunction) _wrap_PyTiledTileset_tileCount, METH_NOARGS, NULL }, {(char *) "imageHeight", (PyCFunction) _wrap_PyTiledTileset_imageHeight, METH_NOARGS, NULL }, {(char *) "imageWidth", (PyCFunction) _wrap_PyTiledTileset_imageWidth, METH_NOARGS, NULL }, {(char *) "setTransparentColor", (PyCFunction) _wrap_PyTiledTileset_setTransparentColor, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "margin", (PyCFunction) _wrap_PyTiledTileset_margin, METH_NOARGS, NULL }, {(char *) "isExternal", (PyCFunction) _wrap_PyTiledTileset_isExternal, METH_NOARGS, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyTiledTileset__tp_dealloc(PyTiledTileset *self) { Tiled::Tileset *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyTiledTileset__tp_richcompare (PyTiledTileset *PYBINDGEN_UNUSED(self), PyTiledTileset *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyTiledTileset_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyTiledTileset_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.Tiled.Tileset", /* tp_name */ sizeof(PyTiledTileset), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyTiledTileset__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyTiledTileset__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyTiledTileset_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyTiledTileset__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyTiledLayer__tp_init(void) { PyErr_SetString(PyExc_TypeError, "class 'Layer' cannot be constructed ()"); return -1; } PyObject * _wrap_PyTiledLayer_opacity(PyTiledLayer *self) { PyObject *py_retval; float retval; retval = self->obj->opacity(); py_retval = Py_BuildValue((char *) "f", retval); return py_retval; } PyObject * _wrap_PyTiledLayer_map(PyTiledLayer *self) { PyObject *py_retval; Tiled::Map *retval; PyTiledMap *py_Map; retval = self->obj->map(); if (!(retval)) { Py_INCREF(Py_None); return Py_None; } py_Map = PyObject_New(PyTiledMap, &PyTiledMap_Type); py_Map->obj = retval; py_Map->flags = PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED; py_retval = Py_BuildValue((char *) "N", py_Map); return py_retval; } PyObject * _wrap_PyTiledLayer_asTileLayer(PyTiledLayer *self) { PyObject *py_retval; Tiled::TileLayer *retval; PyTiledTileLayer *py_TileLayer; retval = self->obj->asTileLayer(); if (!(retval)) { Py_INCREF(Py_None); return Py_None; } py_TileLayer = PyObject_New(PyTiledTileLayer, &PyTiledTileLayer_Type); py_TileLayer->obj = retval; py_TileLayer->flags = PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED; py_retval = Py_BuildValue((char *) "N", py_TileLayer); return py_retval; } PyObject * _wrap_PyTiledLayer_name(PyTiledLayer *self) { PyObject *py_retval; QString retval; retval = self->obj->name(); py_retval = Py_BuildValue((char *) "s", retval.toUtf8().data()); return py_retval; } PyObject * _wrap_PyTiledLayer_setName(PyTiledLayer *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; const char *name; Py_ssize_t name_len; const char *keywords[] = {"name", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "s#", (char **) keywords, &name, &name_len)) { return NULL; } self->obj->setName(QString::fromUtf8(name)); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledLayer_setX(PyTiledLayer *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int x; const char *keywords[] = {"x", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &x)) { return NULL; } self->obj->setX(x); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledLayer_asObjectGroup(PyTiledLayer *self) { PyObject *py_retval; Tiled::ObjectGroup *retval; PyTiledObjectGroup *py_ObjectGroup; retval = self->obj->asObjectGroup(); if (!(retval)) { Py_INCREF(Py_None); return Py_None; } py_ObjectGroup = PyObject_New(PyTiledObjectGroup, &PyTiledObjectGroup_Type); py_ObjectGroup->obj = retval; py_ObjectGroup->flags = PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED; py_retval = Py_BuildValue((char *) "N", py_ObjectGroup); return py_retval; } PyObject * _wrap_PyTiledLayer_setOpacity(PyTiledLayer *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; float opacity; const char *keywords[] = {"opacity", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "f", (char **) keywords, &opacity)) { return NULL; } self->obj->setOpacity(opacity); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledLayer_isVisible(PyTiledLayer *self) { PyObject *py_retval; bool retval; retval = self->obj->isVisible(); py_retval = Py_BuildValue((char *) "N", PyBool_FromLong(retval)); return py_retval; } PyObject * _wrap_PyTiledLayer_y(PyTiledLayer *self) { PyObject *py_retval; int retval; retval = self->obj->y(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledLayer_x(PyTiledLayer *self) { PyObject *py_retval; int retval; retval = self->obj->x(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledLayer_setPosition(PyTiledLayer *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int x; int y; const char *keywords[] = {"x", "y", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "ii", (char **) keywords, &x, &y)) { return NULL; } self->obj->setPosition(x, y); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledLayer_setVisible(PyTiledLayer *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; bool visible; PyObject *py_visible; const char *keywords[] = {"visible", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O", (char **) keywords, &py_visible)) { return NULL; } visible = (bool) PyObject_IsTrue(py_visible); self->obj->setVisible(visible); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledLayer_setY(PyTiledLayer *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int y; const char *keywords[] = {"y", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &y)) { return NULL; } self->obj->setY(y); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } static PyMethodDef PyTiledLayer_methods[] = { {(char *) "opacity", (PyCFunction) _wrap_PyTiledLayer_opacity, METH_NOARGS, NULL }, {(char *) "map", (PyCFunction) _wrap_PyTiledLayer_map, METH_NOARGS, NULL }, {(char *) "asTileLayer", (PyCFunction) _wrap_PyTiledLayer_asTileLayer, METH_NOARGS, NULL }, {(char *) "name", (PyCFunction) _wrap_PyTiledLayer_name, METH_NOARGS, NULL }, {(char *) "setName", (PyCFunction) _wrap_PyTiledLayer_setName, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "setX", (PyCFunction) _wrap_PyTiledLayer_setX, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "asObjectGroup", (PyCFunction) _wrap_PyTiledLayer_asObjectGroup, METH_NOARGS, NULL }, {(char *) "setOpacity", (PyCFunction) _wrap_PyTiledLayer_setOpacity, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "isVisible", (PyCFunction) _wrap_PyTiledLayer_isVisible, METH_NOARGS, NULL }, {(char *) "y", (PyCFunction) _wrap_PyTiledLayer_y, METH_NOARGS, NULL }, {(char *) "x", (PyCFunction) _wrap_PyTiledLayer_x, METH_NOARGS, NULL }, {(char *) "setPosition", (PyCFunction) _wrap_PyTiledLayer_setPosition, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "setVisible", (PyCFunction) _wrap_PyTiledLayer_setVisible, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "setY", (PyCFunction) _wrap_PyTiledLayer_setY, METH_KEYWORDS|METH_VARARGS, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyTiledLayer__tp_dealloc(PyTiledLayer *self) { Tiled::Layer *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyTiledLayer__tp_richcompare (PyTiledLayer *PYBINDGEN_UNUSED(self), PyTiledLayer *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyTiledLayer_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyTiledLayer_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.Tiled.Layer", /* tp_name */ sizeof(PyTiledLayer), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyTiledLayer__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyTiledLayer__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyTiledLayer_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyTiledLayer__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyTiledMap__tp_init__0(PyTiledMap *self, PyObject *args, PyObject *kwargs, PyObject **return_exception) { PyTiledMap *ctor_arg; const char *keywords[] = {"ctor_arg", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyTiledMap_Type, &ctor_arg)) { { PyObject *exc_type, *traceback; PyErr_Fetch(&exc_type, return_exception, &traceback); Py_XDECREF(exc_type); Py_XDECREF(traceback); } return -1; } self->obj = new Tiled::Map(*((PyTiledMap *) ctor_arg)->obj); self->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return 0; } static int _wrap_PyTiledMap__tp_init__1(PyTiledMap *self, PyObject *args, PyObject *kwargs, PyObject **return_exception) { Tiled::Map::Orientation orient; int w; int h; int tileW; int tileH; const char *keywords[] = {"orient", "w", "h", "tileW", "tileH", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "iiiii", (char **) keywords, &orient, &w, &h, &tileW, &tileH)) { { PyObject *exc_type, *traceback; PyErr_Fetch(&exc_type, return_exception, &traceback); Py_XDECREF(exc_type); Py_XDECREF(traceback); } return -1; } self->obj = new Tiled::Map(orient, w, h, tileW, tileH); self->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return 0; } int _wrap_PyTiledMap__tp_init(PyTiledMap *self, PyObject *args, PyObject *kwargs) { int retval; PyObject *error_list; PyObject *exceptions[2] = {0,}; retval = _wrap_PyTiledMap__tp_init__0(self, args, kwargs, &exceptions[0]); if (!exceptions[0]) { return retval; } retval = _wrap_PyTiledMap__tp_init__1(self, args, kwargs, &exceptions[1]); if (!exceptions[1]) { Py_DECREF(exceptions[0]); return retval; } error_list = PyList_New(2); PyList_SET_ITEM(error_list, 0, PyObject_Str(exceptions[0])); Py_DECREF(exceptions[0]); PyList_SET_ITEM(error_list, 1, PyObject_Str(exceptions[1])); Py_DECREF(exceptions[1]); PyErr_SetObject(PyExc_TypeError, error_list); Py_DECREF(error_list); return -1; } PyObject * _wrap_PyTiledMap_setOrientation(PyTiledMap *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; Tiled::Map::Orientation o; const char *keywords[] = {"o", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &o)) { return NULL; } self->obj->setOrientation(o); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMap_setHeight(PyTiledMap *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int h; const char *keywords[] = {"h", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &h)) { return NULL; } self->obj->setHeight(h); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMap_isTilesetUsed(PyTiledMap *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; bool retval; PyTiledTileset *tileset; Tiled::Tileset *tileset_ptr; const char *keywords[] = {"tileset", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyTiledTileset_Type, &tileset)) { return NULL; } tileset_ptr = (tileset ? tileset->obj : NULL); retval = self->obj->isTilesetUsed(tileset_ptr); py_retval = Py_BuildValue((char *) "N", PyBool_FromLong(retval)); return py_retval; } PyObject * _wrap_PyTiledMap_layerAt(PyTiledMap *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; Tiled::Layer *retval; int idx; const char *keywords[] = {"idx", NULL}; PyTiledLayer *py_Layer; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &idx)) { return NULL; } retval = self->obj->layerAt(idx); if (!(retval)) { Py_INCREF(Py_None); return Py_None; } py_Layer = PyObject_New(PyTiledLayer, &PyTiledLayer_Type); py_Layer->obj = retval; py_Layer->flags = PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED; py_retval = Py_BuildValue((char *) "N", py_Layer); return py_retval; } PyObject * _wrap_PyTiledMap_removeTilesetAt(PyTiledMap *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int pos; const char *keywords[] = {"pos", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &pos)) { return NULL; } self->obj->removeTilesetAt(pos); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMap_orientation(PyTiledMap *self) { PyObject *py_retval; Tiled::Map::Orientation retval; retval = self->obj->orientation(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledMap_tileLayerCount(PyTiledMap *self) { PyObject *py_retval; int retval; retval = self->obj->tileLayerCount(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledMap_tileHeight(PyTiledMap *self) { PyObject *py_retval; int retval; retval = self->obj->tileHeight(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledMap_insertTileset(PyTiledMap *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int pos; PyTiledSharedTileset *tileset; const char *keywords[] = {"pos", "tileset", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "iO!", (char **) keywords, &pos, &PyTiledSharedTileset_Type, &tileset)) { return NULL; } self->obj->insertTileset(pos, *((PyTiledSharedTileset *) tileset)->obj); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMap_tileWidth(PyTiledMap *self) { PyObject *py_retval; int retval; retval = self->obj->tileWidth(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledMap_height(PyTiledMap *self) { PyObject *py_retval; int retval; retval = self->obj->height(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledMap_width(PyTiledMap *self) { PyObject *py_retval; int retval; retval = self->obj->width(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledMap_replaceTileset(PyTiledMap *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; PyTiledSharedTileset *oldTileset; PyTiledSharedTileset *newTileset; const char *keywords[] = {"oldTileset", "newTileset", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!O!", (char **) keywords, &PyTiledSharedTileset_Type, &oldTileset, &PyTiledSharedTileset_Type, &newTileset)) { return NULL; } self->obj->replaceTileset(*((PyTiledSharedTileset *) oldTileset)->obj, *((PyTiledSharedTileset *) newTileset)->obj); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMap_indexOfTileset(PyTiledMap *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int retval; PyTiledSharedTileset *tileset; const char *keywords[] = {"tileset", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyTiledSharedTileset_Type, &tileset)) { return NULL; } retval = self->obj->indexOfTileset(*((PyTiledSharedTileset *) tileset)->obj); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledMap_addTileset(PyTiledMap *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; PyTiledSharedTileset *tileset; const char *keywords[] = {"tileset", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyTiledSharedTileset_Type, &tileset)) { return NULL; } self->obj->addTileset(*((PyTiledSharedTileset *) tileset)->obj); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMap_layerCount(PyTiledMap *self) { PyObject *py_retval; int retval; retval = self->obj->layerCount(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledMap_addLayer__0(PyTiledMap *self, PyObject *args, PyObject *kwargs, PyObject **return_exception) { PyObject *py_retval; PyTiledImageLayer *l; Tiled::ImageLayer *l_ptr; const char *keywords[] = {"l", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyTiledImageLayer_Type, &l)) { { PyObject *exc_type, *traceback; PyErr_Fetch(&exc_type, return_exception, &traceback); Py_XDECREF(exc_type); Py_XDECREF(traceback); } return NULL; } l_ptr = (l ? l->obj : NULL); self->obj->addLayer(l_ptr); if (l) { l->obj = NULL; } Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMap_addLayer__1(PyTiledMap *self, PyObject *args, PyObject *kwargs, PyObject **return_exception) { PyObject *py_retval; PyTiledTileLayer *l; Tiled::TileLayer *l_ptr; const char *keywords[] = {"l", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyTiledTileLayer_Type, &l)) { { PyObject *exc_type, *traceback; PyErr_Fetch(&exc_type, return_exception, &traceback); Py_XDECREF(exc_type); Py_XDECREF(traceback); } return NULL; } l_ptr = (l ? l->obj : NULL); self->obj->addLayer(l_ptr); if (l) { l->obj = NULL; } Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMap_addLayer__2(PyTiledMap *self, PyObject *args, PyObject *kwargs, PyObject **return_exception) { PyObject *py_retval; PyTiledObjectGroup *l; Tiled::ObjectGroup *l_ptr; const char *keywords[] = {"l", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyTiledObjectGroup_Type, &l)) { { PyObject *exc_type, *traceback; PyErr_Fetch(&exc_type, return_exception, &traceback); Py_XDECREF(exc_type); Py_XDECREF(traceback); } return NULL; } l_ptr = (l ? l->obj : NULL); self->obj->addLayer(l_ptr); if (l) { l->obj = NULL; } Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMap_addLayer(PyTiledMap *self, PyObject *args, PyObject *kwargs) { PyObject * retval; PyObject *error_list; PyObject *exceptions[3] = {0,}; retval = _wrap_PyTiledMap_addLayer__0(self, args, kwargs, &exceptions[0]); if (!exceptions[0]) { return retval; } retval = _wrap_PyTiledMap_addLayer__1(self, args, kwargs, &exceptions[1]); if (!exceptions[1]) { Py_DECREF(exceptions[0]); return retval; } retval = _wrap_PyTiledMap_addLayer__2(self, args, kwargs, &exceptions[2]); if (!exceptions[2]) { Py_DECREF(exceptions[0]); Py_DECREF(exceptions[1]); return retval; } error_list = PyList_New(3); PyList_SET_ITEM(error_list, 0, PyObject_Str(exceptions[0])); Py_DECREF(exceptions[0]); PyList_SET_ITEM(error_list, 1, PyObject_Str(exceptions[1])); Py_DECREF(exceptions[1]); PyList_SET_ITEM(error_list, 2, PyObject_Str(exceptions[2])); Py_DECREF(exceptions[2]); PyErr_SetObject(PyExc_TypeError, error_list); Py_DECREF(error_list); return NULL; } PyObject * _wrap_PyTiledMap_tilesetAt(PyTiledMap *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int idx; const char *keywords[] = {"idx", NULL}; PyTiledSharedTileset *py_SharedTileset; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &idx)) { return NULL; } Tiled::SharedTileset retval = self->obj->tilesetAt(idx); py_SharedTileset = PyObject_New(PyTiledSharedTileset, &PyTiledSharedTileset_Type); py_SharedTileset->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_SharedTileset->obj = new Tiled::SharedTileset(retval); py_retval = Py_BuildValue((char *) "N", py_SharedTileset); return py_retval; } PyObject * _wrap_PyTiledMap_objectGroupCount(PyTiledMap *self) { PyObject *py_retval; int retval; retval = self->obj->objectGroupCount(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledMap_setWidth(PyTiledMap *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int w; const char *keywords[] = {"w", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &w)) { return NULL; } self->obj->setWidth(w); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMap_tilesetCount(PyTiledMap *self) { PyObject *py_retval; int retval; retval = self->obj->tilesetCount(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } static PyObject* _wrap_PyTiledMap__copy__(PyTiledMap *self) { PyTiledMap *py_copy; py_copy = PyObject_New(PyTiledMap, &PyTiledMap_Type); py_copy->obj = new Tiled::Map(*self->obj); py_copy->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return (PyObject*) py_copy; } static PyMethodDef PyTiledMap_methods[] = { {(char *) "setOrientation", (PyCFunction) _wrap_PyTiledMap_setOrientation, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "setHeight", (PyCFunction) _wrap_PyTiledMap_setHeight, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "isTilesetUsed", (PyCFunction) _wrap_PyTiledMap_isTilesetUsed, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "layerAt", (PyCFunction) _wrap_PyTiledMap_layerAt, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "removeTilesetAt", (PyCFunction) _wrap_PyTiledMap_removeTilesetAt, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "orientation", (PyCFunction) _wrap_PyTiledMap_orientation, METH_NOARGS, NULL }, {(char *) "tileLayerCount", (PyCFunction) _wrap_PyTiledMap_tileLayerCount, METH_NOARGS, NULL }, {(char *) "tileHeight", (PyCFunction) _wrap_PyTiledMap_tileHeight, METH_NOARGS, NULL }, {(char *) "insertTileset", (PyCFunction) _wrap_PyTiledMap_insertTileset, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "tileWidth", (PyCFunction) _wrap_PyTiledMap_tileWidth, METH_NOARGS, NULL }, {(char *) "height", (PyCFunction) _wrap_PyTiledMap_height, METH_NOARGS, NULL }, {(char *) "width", (PyCFunction) _wrap_PyTiledMap_width, METH_NOARGS, NULL }, {(char *) "replaceTileset", (PyCFunction) _wrap_PyTiledMap_replaceTileset, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "indexOfTileset", (PyCFunction) _wrap_PyTiledMap_indexOfTileset, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "addTileset", (PyCFunction) _wrap_PyTiledMap_addTileset, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "layerCount", (PyCFunction) _wrap_PyTiledMap_layerCount, METH_NOARGS, NULL }, {(char *) "addLayer", (PyCFunction) _wrap_PyTiledMap_addLayer, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "tilesetAt", (PyCFunction) _wrap_PyTiledMap_tilesetAt, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "objectGroupCount", (PyCFunction) _wrap_PyTiledMap_objectGroupCount, METH_NOARGS, NULL }, {(char *) "setWidth", (PyCFunction) _wrap_PyTiledMap_setWidth, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "tilesetCount", (PyCFunction) _wrap_PyTiledMap_tilesetCount, METH_NOARGS, NULL }, {(char *) "__copy__", (PyCFunction) _wrap_PyTiledMap__copy__, METH_NOARGS, NULL}, {NULL, NULL, 0, NULL} }; static void _wrap_PyTiledMap__tp_dealloc(PyTiledMap *self) { Tiled::Map *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyTiledMap__tp_richcompare (PyTiledMap *PYBINDGEN_UNUSED(self), PyTiledMap *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyTiledMap_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyTiledMap_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.Tiled.Map", /* tp_name */ sizeof(PyTiledMap), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyTiledMap__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyTiledMap__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyTiledMap_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyTiledMap__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyTiledCell__tp_init(PyTiledCell *self, PyObject *args, PyObject *kwargs) { PyTiledTile *tile; Tiled::Tile *tile_ptr; const char *keywords[] = {"tile", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyTiledTile_Type, &tile)) { return -1; } tile_ptr = (tile ? tile->obj : NULL); self->obj = new Tiled::Cell(tile_ptr); self->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return 0; } PyObject * _wrap_PyTiledCell_tile(PyTiledCell *self) { PyObject *py_retval; Tiled::Tile *retval; PyTiledTile *py_Tile; retval = self->obj->tile(); if (!(retval)) { Py_INCREF(Py_None); return Py_None; } py_Tile = PyObject_New(PyTiledTile, &PyTiledTile_Type); py_Tile->obj = retval; py_Tile->flags = PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED; py_retval = Py_BuildValue((char *) "N", py_Tile); return py_retval; } PyObject * _wrap_PyTiledCell_isEmpty(PyTiledCell *self) { PyObject *py_retval; bool retval; retval = self->obj->isEmpty(); py_retval = Py_BuildValue((char *) "N", PyBool_FromLong(retval)); return py_retval; } static PyMethodDef PyTiledCell_methods[] = { {(char *) "tile", (PyCFunction) _wrap_PyTiledCell_tile, METH_NOARGS, NULL }, {(char *) "isEmpty", (PyCFunction) _wrap_PyTiledCell_isEmpty, METH_NOARGS, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyTiledCell__tp_dealloc(PyTiledCell *self) { Tiled::Cell *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyTiledCell__tp_richcompare (PyTiledCell *PYBINDGEN_UNUSED(self), PyTiledCell *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyTiledCell_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyTiledCell_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.Tiled.Cell", /* tp_name */ sizeof(PyTiledCell), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyTiledCell__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyTiledCell__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyTiledCell_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyTiledCell__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyTiledTileLayer__tp_init(PyTiledTileLayer *self, PyObject *args, PyObject *kwargs) { const char *name; Py_ssize_t name_len; int x; int y; int w; int h; const char *keywords[] = {"name", "x", "y", "w", "h", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "s#iiii", (char **) keywords, &name, &name_len, &x, &y, &w, &h)) { return -1; } self->obj = new Tiled::TileLayer(QString::fromUtf8(name), x, y, w, h); self->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return 0; } PyObject * _wrap_PyTiledTileLayer_referencesTileset(PyTiledTileLayer *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; bool retval; PyTiledTileset *ts; Tiled::Tileset *ts_ptr; const char *keywords[] = {"ts", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyTiledTileset_Type, &ts)) { return NULL; } ts_ptr = (ts ? ts->obj : NULL); retval = self->obj->referencesTileset(ts_ptr); py_retval = Py_BuildValue((char *) "N", PyBool_FromLong(retval)); return py_retval; } PyObject * _wrap_PyTiledTileLayer_cellAt(PyTiledTileLayer *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int x; int y; const char *keywords[] = {"x", "y", NULL}; PyTiledCell *py_Cell; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "ii", (char **) keywords, &x, &y)) { return NULL; } Tiled::Cell retval = self->obj->cellAt(x, y); py_Cell = PyObject_New(PyTiledCell, &PyTiledCell_Type); py_Cell->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_Cell->obj = new Tiled::Cell(retval); py_retval = Py_BuildValue((char *) "N", py_Cell); return py_retval; } PyObject * _wrap_PyTiledTileLayer_height(PyTiledTileLayer *self) { PyObject *py_retval; int retval; retval = self->obj->height(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledTileLayer_width(PyTiledTileLayer *self) { PyObject *py_retval; int retval; retval = self->obj->width(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledTileLayer_setCell(PyTiledTileLayer *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int x; int y; PyTiledCell *c; const char *keywords[] = {"x", "y", "c", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "iiO!", (char **) keywords, &x, &y, &PyTiledCell_Type, &c)) { return NULL; } self->obj->setCell(x, y, *((PyTiledCell *) c)->obj); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledTileLayer_isEmpty(PyTiledTileLayer *self) { PyObject *py_retval; bool retval; retval = self->obj->isEmpty(); py_retval = Py_BuildValue((char *) "N", PyBool_FromLong(retval)); return py_retval; } static PyMethodDef PyTiledTileLayer_methods[] = { {(char *) "referencesTileset", (PyCFunction) _wrap_PyTiledTileLayer_referencesTileset, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "cellAt", (PyCFunction) _wrap_PyTiledTileLayer_cellAt, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "height", (PyCFunction) _wrap_PyTiledTileLayer_height, METH_NOARGS, NULL }, {(char *) "width", (PyCFunction) _wrap_PyTiledTileLayer_width, METH_NOARGS, NULL }, {(char *) "setCell", (PyCFunction) _wrap_PyTiledTileLayer_setCell, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "isEmpty", (PyCFunction) _wrap_PyTiledTileLayer_isEmpty, METH_NOARGS, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyTiledTileLayer__tp_dealloc(PyTiledTileLayer *self) { Tiled::TileLayer *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyTiledTileLayer__tp_richcompare (PyTiledTileLayer *PYBINDGEN_UNUSED(self), PyTiledTileLayer *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyTiledTileLayer_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyTiledTileLayer_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.Tiled.TileLayer", /* tp_name */ sizeof(PyTiledTileLayer), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyTiledTileLayer__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyTiledTileLayer__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyTiledTileLayer_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyTiledTileLayer__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyTiledImageLayer__tp_init(PyTiledImageLayer *self, PyObject *args, PyObject *kwargs) { const char *name; Py_ssize_t name_len; int x; int y; const char *keywords[] = {"name", "x", "y", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "s#ii", (char **) keywords, &name, &name_len, &x, &y)) { return -1; } self->obj = new Tiled::ImageLayer(QString::fromUtf8(name), x, y); self->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return 0; } PyObject * _wrap_PyTiledImageLayer_image(PyTiledImageLayer *self) { PyObject *py_retval; PyQPixmap *py_QPixmap; QPixmap const & retval = self->obj->image(); py_QPixmap = PyObject_New(PyQPixmap, &PyQPixmap_Type); py_QPixmap->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_QPixmap->obj = new QPixmap(retval); py_retval = Py_BuildValue((char *) "N", py_QPixmap); return py_retval; } PyObject * _wrap_PyTiledImageLayer_loadFromImage(PyTiledImageLayer *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; bool retval; PyQImage *img; const char *file; Py_ssize_t file_len; const char *keywords[] = {"img", "file", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!s#", (char **) keywords, &PyQImage_Type, &img, &file, &file_len)) { return NULL; } retval = self->obj->loadFromImage(*((PyQImage *) img)->obj, QString::fromUtf8(file)); py_retval = Py_BuildValue((char *) "N", PyBool_FromLong(retval)); return py_retval; } PyObject * _wrap_PyTiledImageLayer_setImage(PyTiledImageLayer *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; PyQPixmap *image; const char *keywords[] = {"image", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyQPixmap_Type, &image)) { return NULL; } self->obj->setImage(*((PyQPixmap *) image)->obj); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } static PyMethodDef PyTiledImageLayer_methods[] = { {(char *) "image", (PyCFunction) _wrap_PyTiledImageLayer_image, METH_NOARGS, NULL }, {(char *) "loadFromImage", (PyCFunction) _wrap_PyTiledImageLayer_loadFromImage, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "setImage", (PyCFunction) _wrap_PyTiledImageLayer_setImage, METH_KEYWORDS|METH_VARARGS, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyTiledImageLayer__tp_dealloc(PyTiledImageLayer *self) { Tiled::ImageLayer *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyTiledImageLayer__tp_richcompare (PyTiledImageLayer *PYBINDGEN_UNUSED(self), PyTiledImageLayer *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyTiledImageLayer_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyTiledImageLayer_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.Tiled.ImageLayer", /* tp_name */ sizeof(PyTiledImageLayer), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyTiledImageLayer__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyTiledImageLayer__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyTiledImageLayer_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyTiledImageLayer__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyTiledMapObject__tp_init__0(PyTiledMapObject *self, PyObject *args, PyObject *kwargs, PyObject **return_exception) { const char *keywords[] = {NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "", (char **) keywords)) { { PyObject *exc_type, *traceback; PyErr_Fetch(&exc_type, return_exception, &traceback); Py_XDECREF(exc_type); Py_XDECREF(traceback); } return -1; } self->obj = new Tiled::MapObject(); self->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return 0; } static int _wrap_PyTiledMapObject__tp_init__1(PyTiledMapObject *self, PyObject *args, PyObject *kwargs, PyObject **return_exception) { const char *name; Py_ssize_t name_len; const char *type; Py_ssize_t type_len; PyQPointF *pos; PyQSizeF *size; const char *keywords[] = {"name", "type", "pos", "size", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "s#s#O!O!", (char **) keywords, &name, &name_len, &type, &type_len, &PyQPointF_Type, &pos, &PyQSizeF_Type, &size)) { { PyObject *exc_type, *traceback; PyErr_Fetch(&exc_type, return_exception, &traceback); Py_XDECREF(exc_type); Py_XDECREF(traceback); } return -1; } self->obj = new Tiled::MapObject(QString::fromUtf8(name), QString::fromUtf8(type), *((PyQPointF *) pos)->obj, *((PyQSizeF *) size)->obj); self->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return 0; } int _wrap_PyTiledMapObject__tp_init(PyTiledMapObject *self, PyObject *args, PyObject *kwargs) { int retval; PyObject *error_list; PyObject *exceptions[2] = {0,}; retval = _wrap_PyTiledMapObject__tp_init__0(self, args, kwargs, &exceptions[0]); if (!exceptions[0]) { return retval; } retval = _wrap_PyTiledMapObject__tp_init__1(self, args, kwargs, &exceptions[1]); if (!exceptions[1]) { Py_DECREF(exceptions[0]); return retval; } error_list = PyList_New(2); PyList_SET_ITEM(error_list, 0, PyObject_Str(exceptions[0])); Py_DECREF(exceptions[0]); PyList_SET_ITEM(error_list, 1, PyObject_Str(exceptions[1])); Py_DECREF(exceptions[1]); PyErr_SetObject(PyExc_TypeError, error_list); Py_DECREF(error_list); return -1; } PyObject * _wrap_PyTiledMapObject_height(PyTiledMapObject *self) { PyObject *py_retval; float retval; retval = self->obj->height(); py_retval = Py_BuildValue((char *) "f", retval); return py_retval; } PyObject * _wrap_PyTiledMapObject_shape(PyTiledMapObject *self) { PyObject *py_retval; Tiled::MapObject::Shape retval; retval = self->obj->shape(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledMapObject_setCell(PyTiledMapObject *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; PyTiledCell *c; const char *keywords[] = {"c", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyTiledCell_Type, &c)) { return NULL; } self->obj->setCell(*((PyTiledCell *) c)->obj); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMapObject_setWidth(PyTiledMapObject *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; float w; const char *keywords[] = {"w", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "f", (char **) keywords, &w)) { return NULL; } self->obj->setWidth(w); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMapObject_setPosition(PyTiledMapObject *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; PyQPointF *pos; const char *keywords[] = {"pos", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyQPointF_Type, &pos)) { return NULL; } self->obj->setPosition(*((PyQPointF *) pos)->obj); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMapObject_setType(PyTiledMapObject *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; const char *n; Py_ssize_t n_len; const char *keywords[] = {"n", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "s#", (char **) keywords, &n, &n_len)) { return NULL; } self->obj->setType(QString::fromUtf8(n)); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMapObject_cell(PyTiledMapObject *self) { PyObject *py_retval; PyTiledCell *py_Cell; Tiled::Cell const retval = self->obj->cell(); py_Cell = PyObject_New(PyTiledCell, &PyTiledCell_Type); py_Cell->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_Cell->obj = new Tiled::Cell(retval); py_retval = Py_BuildValue((char *) "N", py_Cell); return py_retval; } PyObject * _wrap_PyTiledMapObject_width(PyTiledMapObject *self) { PyObject *py_retval; float retval; retval = self->obj->width(); py_retval = Py_BuildValue((char *) "f", retval); return py_retval; } PyObject * _wrap_PyTiledMapObject_setRotation(PyTiledMapObject *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; float r; const char *keywords[] = {"r", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "f", (char **) keywords, &r)) { return NULL; } self->obj->setRotation(r); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMapObject_type(PyTiledMapObject *self) { PyObject *py_retval; QString retval; retval = self->obj->type(); py_retval = Py_BuildValue((char *) "s", retval.toUtf8().data()); return py_retval; } PyObject * _wrap_PyTiledMapObject_setName(PyTiledMapObject *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; const char *n; Py_ssize_t n_len; const char *keywords[] = {"n", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "s#", (char **) keywords, &n, &n_len)) { return NULL; } self->obj->setName(QString::fromUtf8(n)); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMapObject_rotation(PyTiledMapObject *self) { PyObject *py_retval; float retval; retval = self->obj->rotation(); py_retval = Py_BuildValue((char *) "f", retval); return py_retval; } PyObject * _wrap_PyTiledMapObject_setX(PyTiledMapObject *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; float x; const char *keywords[] = {"x", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "f", (char **) keywords, &x)) { return NULL; } self->obj->setX(x); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMapObject_setY(PyTiledMapObject *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; float y; const char *keywords[] = {"y", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "f", (char **) keywords, &y)) { return NULL; } self->obj->setY(y); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMapObject_setHeight(PyTiledMapObject *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; float h; const char *keywords[] = {"h", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "f", (char **) keywords, &h)) { return NULL; } self->obj->setHeight(h); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMapObject_name(PyTiledMapObject *self) { PyObject *py_retval; QString retval; retval = self->obj->name(); py_retval = Py_BuildValue((char *) "s", retval.toUtf8().data()); return py_retval; } PyObject * _wrap_PyTiledMapObject_setSize(PyTiledMapObject *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; PyQSizeF *size; const char *keywords[] = {"size", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyQSizeF_Type, &size)) { return NULL; } self->obj->setSize(*((PyQSizeF *) size)->obj); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMapObject_isVisible(PyTiledMapObject *self) { PyObject *py_retval; bool retval; retval = self->obj->isVisible(); py_retval = Py_BuildValue((char *) "N", PyBool_FromLong(retval)); return py_retval; } PyObject * _wrap_PyTiledMapObject_y(PyTiledMapObject *self) { PyObject *py_retval; float retval; retval = self->obj->y(); py_retval = Py_BuildValue((char *) "f", retval); return py_retval; } PyObject * _wrap_PyTiledMapObject_x(PyTiledMapObject *self) { PyObject *py_retval; float retval; retval = self->obj->x(); py_retval = Py_BuildValue((char *) "f", retval); return py_retval; } PyObject * _wrap_PyTiledMapObject_setVisible(PyTiledMapObject *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; bool v; PyObject *py_v; const char *keywords[] = {"v", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O", (char **) keywords, &py_v)) { return NULL; } v = (bool) PyObject_IsTrue(py_v); self->obj->setVisible(v); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledMapObject_setShape(PyTiledMapObject *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; Tiled::MapObject::Shape s; const char *keywords[] = {"s", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &s)) { return NULL; } self->obj->setShape(s); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } static PyMethodDef PyTiledMapObject_methods[] = { {(char *) "height", (PyCFunction) _wrap_PyTiledMapObject_height, METH_NOARGS, NULL }, {(char *) "shape", (PyCFunction) _wrap_PyTiledMapObject_shape, METH_NOARGS, NULL }, {(char *) "setCell", (PyCFunction) _wrap_PyTiledMapObject_setCell, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "setWidth", (PyCFunction) _wrap_PyTiledMapObject_setWidth, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "setPosition", (PyCFunction) _wrap_PyTiledMapObject_setPosition, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "setType", (PyCFunction) _wrap_PyTiledMapObject_setType, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "cell", (PyCFunction) _wrap_PyTiledMapObject_cell, METH_NOARGS, NULL }, {(char *) "width", (PyCFunction) _wrap_PyTiledMapObject_width, METH_NOARGS, NULL }, {(char *) "setRotation", (PyCFunction) _wrap_PyTiledMapObject_setRotation, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "type", (PyCFunction) _wrap_PyTiledMapObject_type, METH_NOARGS, NULL }, {(char *) "setName", (PyCFunction) _wrap_PyTiledMapObject_setName, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "rotation", (PyCFunction) _wrap_PyTiledMapObject_rotation, METH_NOARGS, NULL }, {(char *) "setX", (PyCFunction) _wrap_PyTiledMapObject_setX, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "setY", (PyCFunction) _wrap_PyTiledMapObject_setY, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "setHeight", (PyCFunction) _wrap_PyTiledMapObject_setHeight, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "name", (PyCFunction) _wrap_PyTiledMapObject_name, METH_NOARGS, NULL }, {(char *) "setSize", (PyCFunction) _wrap_PyTiledMapObject_setSize, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "isVisible", (PyCFunction) _wrap_PyTiledMapObject_isVisible, METH_NOARGS, NULL }, {(char *) "y", (PyCFunction) _wrap_PyTiledMapObject_y, METH_NOARGS, NULL }, {(char *) "x", (PyCFunction) _wrap_PyTiledMapObject_x, METH_NOARGS, NULL }, {(char *) "setVisible", (PyCFunction) _wrap_PyTiledMapObject_setVisible, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "setShape", (PyCFunction) _wrap_PyTiledMapObject_setShape, METH_KEYWORDS|METH_VARARGS, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyTiledMapObject__tp_dealloc(PyTiledMapObject *self) { Tiled::MapObject *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyTiledMapObject__tp_richcompare (PyTiledMapObject *PYBINDGEN_UNUSED(self), PyTiledMapObject *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyTiledMapObject_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyTiledMapObject_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.Tiled.MapObject", /* tp_name */ sizeof(PyTiledMapObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyTiledMapObject__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyTiledMapObject__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyTiledMapObject_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyTiledMapObject__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyTiledObjectGroup__tp_init(PyTiledObjectGroup *self, PyObject *args, PyObject *kwargs) { const char *name; Py_ssize_t name_len; int x; int y; const char *keywords[] = {"name", "x", "y", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "s#ii", (char **) keywords, &name, &name_len, &x, &y)) { return -1; } self->obj = new Tiled::ObjectGroup(QString::fromUtf8(name), x, y); self->flags = PYBINDGEN_WRAPPER_FLAG_NONE; return 0; } PyObject * _wrap_PyTiledObjectGroup_addObject(PyTiledObjectGroup *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; PyTiledMapObject *object; Tiled::MapObject *object_ptr; const char *keywords[] = {"object", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyTiledMapObject_Type, &object)) { return NULL; } object_ptr = (object ? object->obj : NULL); self->obj->addObject(object_ptr); if (object) { object->obj = NULL; } Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledObjectGroup_referencesTileset(PyTiledObjectGroup *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; bool retval; PyTiledTileset *ts; Tiled::Tileset *ts_ptr; const char *keywords[] = {"ts", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyTiledTileset_Type, &ts)) { return NULL; } ts_ptr = (ts ? ts->obj : NULL); retval = self->obj->referencesTileset(ts_ptr); py_retval = Py_BuildValue((char *) "N", PyBool_FromLong(retval)); return py_retval; } PyObject * _wrap_PyTiledObjectGroup_objectAt(PyTiledObjectGroup *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; Tiled::MapObject *retval; int index; const char *keywords[] = {"index", NULL}; PyTiledMapObject *py_MapObject; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &index)) { return NULL; } retval = self->obj->objectAt(index); if (!(retval)) { Py_INCREF(Py_None); return Py_None; } py_MapObject = PyObject_New(PyTiledMapObject, &PyTiledMapObject_Type); py_MapObject->obj = retval; py_MapObject->flags = PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED; py_retval = Py_BuildValue((char *) "N", py_MapObject); return py_retval; } PyObject * _wrap_PyTiledObjectGroup_objectCount(PyTiledObjectGroup *self) { PyObject *py_retval; int retval; retval = self->obj->objectCount(); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } PyObject * _wrap_PyTiledObjectGroup_insertObject(PyTiledObjectGroup *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int idx; PyTiledMapObject *object; Tiled::MapObject *object_ptr; const char *keywords[] = {"idx", "object", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "iO!", (char **) keywords, &idx, &PyTiledMapObject_Type, &object)) { return NULL; } object_ptr = (object ? object->obj : NULL); self->obj->insertObject(idx, object_ptr); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } PyObject * _wrap_PyTiledObjectGroup_removeObject(PyTiledObjectGroup *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; int retval; PyTiledMapObject *object; Tiled::MapObject *object_ptr; const char *keywords[] = {"object", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!", (char **) keywords, &PyTiledMapObject_Type, &object)) { return NULL; } object_ptr = (object ? object->obj : NULL); retval = self->obj->removeObject(object_ptr); py_retval = Py_BuildValue((char *) "i", retval); return py_retval; } static PyMethodDef PyTiledObjectGroup_methods[] = { {(char *) "addObject", (PyCFunction) _wrap_PyTiledObjectGroup_addObject, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "referencesTileset", (PyCFunction) _wrap_PyTiledObjectGroup_referencesTileset, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "objectAt", (PyCFunction) _wrap_PyTiledObjectGroup_objectAt, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "objectCount", (PyCFunction) _wrap_PyTiledObjectGroup_objectCount, METH_NOARGS, NULL }, {(char *) "insertObject", (PyCFunction) _wrap_PyTiledObjectGroup_insertObject, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "removeObject", (PyCFunction) _wrap_PyTiledObjectGroup_removeObject, METH_KEYWORDS|METH_VARARGS, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyTiledObjectGroup__tp_dealloc(PyTiledObjectGroup *self) { Tiled::ObjectGroup *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyTiledObjectGroup__tp_richcompare (PyTiledObjectGroup *PYBINDGEN_UNUSED(self), PyTiledObjectGroup *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyTiledObjectGroup_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyTiledObjectGroup_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.Tiled.ObjectGroup", /* tp_name */ sizeof(PyTiledObjectGroup), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyTiledObjectGroup__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyTiledObjectGroup__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyTiledObjectGroup_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyTiledObjectGroup__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; static int _wrap_PyTiledLoggingInterface__tp_init(void) { PyErr_SetString(PyExc_TypeError, "class 'LoggingInterface' cannot be constructed ()"); return -1; } PyObject * _wrap_PyTiledLoggingInterface_log(PyTiledLoggingInterface *self, PyObject *args, PyObject *kwargs) { PyObject *py_retval; Tiled::LoggingInterface::OutputType type; const char *msg; Py_ssize_t msg_len; const char *keywords[] = {"type", "msg", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "is#", (char **) keywords, &type, &msg, &msg_len)) { return NULL; } self->obj->log(type, QString::fromUtf8(msg)); Py_INCREF(Py_None); py_retval = Py_None; return py_retval; } static PyMethodDef PyTiledLoggingInterface_methods[] = { {(char *) "log", (PyCFunction) _wrap_PyTiledLoggingInterface_log, METH_KEYWORDS|METH_VARARGS, NULL }, {NULL, NULL, 0, NULL} }; static void _wrap_PyTiledLoggingInterface__tp_dealloc(PyTiledLoggingInterface *self) { self->obj = NULL; Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyTiledLoggingInterface__tp_richcompare (PyTiledLoggingInterface *PYBINDGEN_UNUSED(self), PyTiledLoggingInterface *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyTiledLoggingInterface_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyTiledLoggingInterface_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.Tiled.LoggingInterface", /* tp_name */ sizeof(PyTiledLoggingInterface), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyTiledLoggingInterface__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)NULL, /* tp_traverse */ (inquiry)NULL, /* tp_clear */ (richcmpfunc)_wrap_PyTiledLoggingInterface__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyTiledLoggingInterface_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)_wrap_PyTiledLoggingInterface__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; /* --- enumerations --- */ #if PY_VERSION_HEX >= 0x03000000 static struct PyModuleDef Tiled_moduledef = { PyModuleDef_HEAD_INIT, "tiled.Tiled", NULL, -1, tiled_Tiled_functions, }; #endif static PyObject * inittiled_Tiled(void) { PyObject *m; #if PY_VERSION_HEX >= 0x03000000 m = PyModule_Create(&Tiled_moduledef); #else m = Py_InitModule3((char *) "tiled.Tiled", tiled_Tiled_functions, NULL); #endif if (m == NULL) { return NULL; } /* Register the 'Tiled::Properties' class */ if (PyType_Ready(&PyTiledProperties_Type)) { return NULL; } PyModule_AddObject(m, (char *) "Properties", (PyObject *) &PyTiledProperties_Type); /* Register the 'Tiled::Object' class */ if (PyType_Ready(&PyTiledObject_Type)) { return NULL; } PyModule_AddObject(m, (char *) "Object", (PyObject *) &PyTiledObject_Type); /* Register the 'Tiled::Tile' class */ PyTiledTile_Type.tp_base = &PyTiledObject_Type; if (PyType_Ready(&PyTiledTile_Type)) { return NULL; } PyModule_AddObject(m, (char *) "Tile", (PyObject *) &PyTiledTile_Type); /* Register the 'Tiled::SharedTileset' class */ if (PyType_Ready(&PyTiledSharedTileset_Type)) { return NULL; } PyModule_AddObject(m, (char *) "SharedTileset", (PyObject *) &PyTiledSharedTileset_Type); /* Register the 'Tiled::Tileset' class */ PyTiledTileset_Type.tp_base = &PyTiledObject_Type; if (PyType_Ready(&PyTiledTileset_Type)) { return NULL; } PyModule_AddObject(m, (char *) "Tileset", (PyObject *) &PyTiledTileset_Type); /* Register the 'Tiled::Layer' class */ PyTiledLayer_Type.tp_base = &PyTiledObject_Type; if (PyType_Ready(&PyTiledLayer_Type)) { return NULL; } PyModule_AddObject(m, (char *) "Layer", (PyObject *) &PyTiledLayer_Type); /* Register the 'Tiled::Map' class */ PyTiledMap_Type.tp_base = &PyTiledObject_Type; if (PyType_Ready(&PyTiledMap_Type)) { return NULL; } PyModule_AddObject(m, (char *) "Map", (PyObject *) &PyTiledMap_Type); /* Register the 'Tiled::Cell' class */ if (PyType_Ready(&PyTiledCell_Type)) { return NULL; } PyModule_AddObject(m, (char *) "Cell", (PyObject *) &PyTiledCell_Type); /* Register the 'Tiled::TileLayer' class */ PyTiledTileLayer_Type.tp_base = &PyTiledLayer_Type; if (PyType_Ready(&PyTiledTileLayer_Type)) { return NULL; } PyModule_AddObject(m, (char *) "TileLayer", (PyObject *) &PyTiledTileLayer_Type); /* Register the 'Tiled::ImageLayer' class */ PyTiledImageLayer_Type.tp_base = &PyTiledLayer_Type; if (PyType_Ready(&PyTiledImageLayer_Type)) { return NULL; } PyModule_AddObject(m, (char *) "ImageLayer", (PyObject *) &PyTiledImageLayer_Type); /* Register the 'Tiled::MapObject' class */ PyTiledMapObject_Type.tp_base = &PyTiledObject_Type; if (PyType_Ready(&PyTiledMapObject_Type)) { return NULL; } PyModule_AddObject(m, (char *) "MapObject", (PyObject *) &PyTiledMapObject_Type); /* Register the 'Tiled::ObjectGroup' class */ PyTiledObjectGroup_Type.tp_base = &PyTiledLayer_Type; if (PyType_Ready(&PyTiledObjectGroup_Type)) { return NULL; } PyModule_AddObject(m, (char *) "ObjectGroup", (PyObject *) &PyTiledObjectGroup_Type); /* Register the 'Tiled::LoggingInterface' class */ if (PyType_Ready(&PyTiledLoggingInterface_Type)) { return NULL; } PyModule_AddObject(m, (char *) "LoggingInterface", (PyObject *) &PyTiledLoggingInterface_Type); { PyObject *tmp_value; // Tiled::Map::Unknown tmp_value = PyLong_FromLong(Tiled::Map::Unknown); PyDict_SetItemString((PyObject*) PyTiledMap_Type.tp_dict, "Unknown", tmp_value); Py_DECREF(tmp_value); // Tiled::Map::Orthogonal tmp_value = PyLong_FromLong(Tiled::Map::Orthogonal); PyDict_SetItemString((PyObject*) PyTiledMap_Type.tp_dict, "Orthogonal", tmp_value); Py_DECREF(tmp_value); // Tiled::Map::Isometric tmp_value = PyLong_FromLong(Tiled::Map::Isometric); PyDict_SetItemString((PyObject*) PyTiledMap_Type.tp_dict, "Isometric", tmp_value); Py_DECREF(tmp_value); } { PyObject *tmp_value; // Tiled::MapObject::Rectangle tmp_value = PyLong_FromLong(Tiled::MapObject::Rectangle); PyDict_SetItemString((PyObject*) PyTiledMapObject_Type.tp_dict, "Rectangle", tmp_value); Py_DECREF(tmp_value); // Tiled::MapObject::Polygon tmp_value = PyLong_FromLong(Tiled::MapObject::Polygon); PyDict_SetItemString((PyObject*) PyTiledMapObject_Type.tp_dict, "Polygon", tmp_value); Py_DECREF(tmp_value); // Tiled::MapObject::Polyline tmp_value = PyLong_FromLong(Tiled::MapObject::Polyline); PyDict_SetItemString((PyObject*) PyTiledMapObject_Type.tp_dict, "Polyline", tmp_value); Py_DECREF(tmp_value); } { PyObject *tmp_value; // Tiled::LoggingInterface::INFO tmp_value = PyLong_FromLong(Tiled::LoggingInterface::INFO); PyDict_SetItemString((PyObject*) PyTiledLoggingInterface_Type.tp_dict, "INFO", tmp_value); Py_DECREF(tmp_value); // Tiled::LoggingInterface::ERROR tmp_value = PyLong_FromLong(Tiled::LoggingInterface::ERROR); PyDict_SetItemString((PyObject*) PyTiledLoggingInterface_Type.tp_dict, "ERROR", tmp_value); Py_DECREF(tmp_value); } return m; } /* --- module functions --- */ PyObject * _wrap_tiled_isTileLayerAt(PyObject * PYBINDGEN_UNUSED(dummy), PyObject *args, PyObject *kwargs) { PyObject *py_retval; bool retval; PyTiledMap *map; Tiled::Map *map_ptr; int idx; const char *keywords[] = {"map", "idx", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!i", (char **) keywords, &PyTiledMap_Type, &map, &idx)) { return NULL; } map_ptr = (map ? map->obj : NULL); retval = isTileLayerAt(map_ptr, idx); py_retval = Py_BuildValue((char *) "N", PyBool_FromLong(retval)); return py_retval; } PyObject * _wrap_tiled_isTileLayerAt(PyObject * PYBINDGEN_UNUSED(dummy), PyObject *args, PyObject *kwargs); PyObject * _wrap_tiled_loadTilesetFromFile(PyObject * PYBINDGEN_UNUSED(dummy), PyObject *args, PyObject *kwargs) { PyObject *py_retval; bool retval; PyTiledTileset *ts; Tiled::Tileset *ts_ptr; const char *file; Py_ssize_t file_len; const char *keywords[] = {"ts", "file", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!s#", (char **) keywords, &PyTiledTileset_Type, &ts, &file, &file_len)) { return NULL; } ts_ptr = (ts ? ts->obj : NULL); retval = loadTilesetFromFile(ts_ptr, QString::fromUtf8(file)); py_retval = Py_BuildValue((char *) "N", PyBool_FromLong(retval)); return py_retval; } PyObject * _wrap_tiled_loadTilesetFromFile(PyObject * PYBINDGEN_UNUSED(dummy), PyObject *args, PyObject *kwargs); PyObject * _wrap_tiled_objectGroupAt(PyObject * PYBINDGEN_UNUSED(dummy), PyObject *args, PyObject *kwargs) { PyObject *py_retval; Tiled::ObjectGroup *retval; PyTiledMap *map; Tiled::Map *map_ptr; int idx; const char *keywords[] = {"map", "idx", NULL}; PyTiledObjectGroup *py_ObjectGroup; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!i", (char **) keywords, &PyTiledMap_Type, &map, &idx)) { return NULL; } map_ptr = (map ? map->obj : NULL); retval = objectGroupAt(map_ptr, idx); if (!(retval)) { Py_INCREF(Py_None); return Py_None; } py_ObjectGroup = PyObject_New(PyTiledObjectGroup, &PyTiledObjectGroup_Type); py_ObjectGroup->obj = retval; py_ObjectGroup->flags = PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED; py_retval = Py_BuildValue((char *) "N", py_ObjectGroup); return py_retval; } PyObject * _wrap_tiled_objectGroupAt(PyObject * PYBINDGEN_UNUSED(dummy), PyObject *args, PyObject *kwargs); PyObject * _wrap_tiled_isObjectGroupAt(PyObject * PYBINDGEN_UNUSED(dummy), PyObject *args, PyObject *kwargs) { PyObject *py_retval; bool retval; PyTiledMap *map; Tiled::Map *map_ptr; int idx; const char *keywords[] = {"map", "idx", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!i", (char **) keywords, &PyTiledMap_Type, &map, &idx)) { return NULL; } map_ptr = (map ? map->obj : NULL); retval = isObjectGroupAt(map_ptr, idx); py_retval = Py_BuildValue((char *) "N", PyBool_FromLong(retval)); return py_retval; } PyObject * _wrap_tiled_isObjectGroupAt(PyObject * PYBINDGEN_UNUSED(dummy), PyObject *args, PyObject *kwargs); PyObject * _wrap_tiled_tileLayerAt(PyObject * PYBINDGEN_UNUSED(dummy), PyObject *args, PyObject *kwargs) { PyObject *py_retval; Tiled::TileLayer *retval; PyTiledMap *map; Tiled::Map *map_ptr; int idx; const char *keywords[] = {"map", "idx", NULL}; PyTiledTileLayer *py_TileLayer; if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O!i", (char **) keywords, &PyTiledMap_Type, &map, &idx)) { return NULL; } map_ptr = (map ? map->obj : NULL); retval = tileLayerAt(map_ptr, idx); if (!(retval)) { Py_INCREF(Py_None); return Py_None; } py_TileLayer = PyObject_New(PyTiledTileLayer, &PyTiledTileLayer_Type); py_TileLayer->obj = retval; py_TileLayer->flags = PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED; py_retval = Py_BuildValue((char *) "N", py_TileLayer); return py_retval; } PyObject * _wrap_tiled_tileLayerAt(PyObject * PYBINDGEN_UNUSED(dummy), PyObject *args, PyObject *kwargs); static PyMethodDef tiled_functions[] = { {(char *) "isTileLayerAt", (PyCFunction) _wrap_tiled_isTileLayerAt, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "loadTilesetFromFile", (PyCFunction) _wrap_tiled_loadTilesetFromFile, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "objectGroupAt", (PyCFunction) _wrap_tiled_objectGroupAt, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "isObjectGroupAt", (PyCFunction) _wrap_tiled_isObjectGroupAt, METH_KEYWORDS|METH_VARARGS, NULL }, {(char *) "tileLayerAt", (PyCFunction) _wrap_tiled_tileLayerAt, METH_KEYWORDS|METH_VARARGS, NULL }, {NULL, NULL, 0, NULL} }; /* --- classes --- */ static int _wrap_PyPythonPythonScript__tp_init(void) { PyErr_SetString(PyExc_TypeError, "class 'PythonScript' cannot be constructed ()"); return -1; } static PyMethodDef PyPythonPythonScript_methods[] = { {NULL, NULL, 0, NULL} }; static void PyPythonPythonScript__tp_clear(PyPythonPythonScript *self) { Py_CLEAR(self->inst_dict); Python::PythonScript *tmp = self->obj; self->obj = NULL; if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) { delete tmp; } } static int PyPythonPythonScript__tp_traverse(PyPythonPythonScript *self, visitproc visit, void *arg) { Py_VISIT(self->inst_dict); return 0; } static void _wrap_PyPythonPythonScript__tp_dealloc(PyPythonPythonScript *self) { PyPythonPythonScript__tp_clear(self); Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* _wrap_PyPythonPythonScript__tp_richcompare (PyPythonPythonScript *PYBINDGEN_UNUSED(self), PyPythonPythonScript *other, int opid) { if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &PyPythonPythonScript_Type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } switch (opid) { case Py_LT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_LE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_EQ: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_NE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GE: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; case Py_GT: Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* closes switch (opid) */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyTypeObject PyPythonPythonScript_Type = { PyVarObject_HEAD_INIT(NULL, 0) (char *) "tiled.PythonScript", /* tp_name */ sizeof(PyPythonPythonScript), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)_wrap_PyPythonPythonScript__tp_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)NULL, /* tp_getattr */ (setattrfunc)NULL, /* tp_setattr */ (cmpfunc)NULL, /* tp_compare */ (reprfunc)NULL, /* tp_repr */ (PyNumberMethods*)NULL, /* tp_as_number */ (PySequenceMethods*)NULL, /* tp_as_sequence */ (PyMappingMethods*)NULL, /* tp_as_mapping */ (hashfunc)NULL, /* tp_hash */ (ternaryfunc)NULL, /* tp_call */ (reprfunc)NULL, /* tp_str */ (getattrofunc)NULL, /* tp_getattro */ (setattrofunc)NULL, /* tp_setattro */ (PyBufferProcs*)NULL, /* tp_as_buffer */ Py_TPFLAGS_BASETYPE|Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC, /* tp_flags */ NULL, /* Documentation string */ (traverseproc)PyPythonPythonScript__tp_traverse, /* tp_traverse */ (inquiry)PyPythonPythonScript__tp_clear, /* tp_clear */ (richcmpfunc)_wrap_PyPythonPythonScript__tp_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)NULL, /* tp_iter */ (iternextfunc)NULL, /* tp_iternext */ (struct PyMethodDef*)PyPythonPythonScript_methods, /* tp_methods */ (struct PyMemberDef*)0, /* tp_members */ 0, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ (descrgetfunc)NULL, /* tp_descr_get */ (descrsetfunc)NULL, /* tp_descr_set */ offsetof(PyPythonPythonScript, inst_dict), /* tp_dictoffset */ (initproc)_wrap_PyPythonPythonScript__tp_init, /* tp_init */ (allocfunc)PyType_GenericAlloc, /* tp_alloc */ (newfunc)PyType_GenericNew, /* tp_new */ (freefunc)0, /* tp_free */ (inquiry)NULL, /* tp_is_gc */ NULL, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ (destructor) NULL /* tp_del */ }; #if PY_VERSION_HEX >= 0x03000000 static struct PyModuleDef tiled_moduledef = { PyModuleDef_HEAD_INIT, "tiled", NULL, -1, tiled_functions, }; #endif #if PY_VERSION_HEX >= 0x03000000 #define MOD_ERROR NULL #define MOD_INIT(name) PyObject* PyInit_##name(void) #define MOD_RETURN(val) val #else #define MOD_ERROR #define MOD_INIT(name) void init##name(void) #define MOD_RETURN(val) #endif #if defined(__cplusplus) extern "C" #endif #if defined(__GNUC__) && __GNUC__ >= 4 __attribute__ ((visibility("default"))) #endif MOD_INIT(tiled) { PyObject *m; PyObject *submodule; #if PY_VERSION_HEX >= 0x03000000 m = PyModule_Create(&tiled_moduledef); #else m = Py_InitModule3((char *) "tiled", tiled_functions, NULL); #endif if (m == NULL) { return MOD_ERROR; } /* Register the 'Python::PythonScript' class */ if (PyType_Ready(&PyPythonPythonScript_Type)) { return MOD_ERROR; } PyModule_AddObject(m, (char *) "Plugin", (PyObject *) &PyPythonPythonScript_Type); submodule = inittiled_qt(); if (submodule == NULL) { return MOD_ERROR; } Py_INCREF(submodule); PyModule_AddObject(m, (char *) "qt", submodule); submodule = inittiled_Tiled(); if (submodule == NULL) { return MOD_ERROR; } Py_INCREF(submodule); PyModule_AddObject(m, (char *) "Tiled", submodule); return MOD_RETURN(m); } PyObject* _wrap_convert_c2py__Tiled__LoggingInterface(Tiled::LoggingInterface *cvalue) { PyObject *py_retval; PyTiledLoggingInterface *py_LoggingInterface; py_LoggingInterface = PyObject_New(PyTiledLoggingInterface, &PyTiledLoggingInterface_Type); py_LoggingInterface->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_LoggingInterface->obj = cvalue; py_retval = Py_BuildValue((char *) "N", py_LoggingInterface); return py_retval; } int _wrap_convert_py2c__Tiled__Map___star__(PyObject *value, Tiled::Map * *address) { PyObject *py_retval; PyTiledMap *tmp_Map; py_retval = Py_BuildValue((char *) "(O)", value); if (!PyArg_ParseTuple(py_retval, (char *) "O!", &PyTiledMap_Type, &tmp_Map)) { Py_DECREF(py_retval); return 0; } *address = new Tiled::Map(*tmp_Map->obj); Py_DECREF(py_retval); return 1; } PyObject* _wrap_convert_c2py__Tiled__Map_const(Tiled::Map const *cvalue) { PyObject *py_retval; PyTiledMap *py_Map; py_Map = PyObject_New(PyTiledMap, &PyTiledMap_Type); py_Map->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_Map->obj = new Tiled::Map(*cvalue); py_retval = Py_BuildValue((char *) "N", py_Map); return py_retval; } tiled-1.0.3/src/plugins/python/pythonplugin.cpp000066400000000000000000000267161315121121300216530ustar00rootroot00000000000000/* * Python Tiled Plugin * Copyright 2012-2013, Samuli Tuomola * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "pythonplugin.h" #include "map.h" #include #include #include namespace Python { /** * Call whenever there might be an error (if error state is not cleared it * leaks to next PyErr_Occurred check and reports error in wrong place causing * confusion) */ static void handleError() { if (PyErr_Occurred() != nullptr) PyErr_Print(); } PythonPlugin::PythonPlugin() : mScriptDir(QDir::homePath() + "/.tiled") , mPluginClass(nullptr) { mReloadTimer.setSingleShot(true); mReloadTimer.setInterval(1000); connect(&mReloadTimer, &QTimer::timeout, this, &PythonPlugin::reloadModules); } PythonPlugin::~PythonPlugin() { for (const ScriptEntry &script : mScripts) { Py_DECREF(script.module); Py_DECREF(script.mapFormat->pythonClass()); } Py_XDECREF(mPluginClass); Py_Finalize(); } void PythonPlugin::initialize() { addObject(&mLogger); if (!Py_IsInitialized()) { // PEP370 Py_NoSiteFlag = 1; Py_NoUserSiteDirectory = 1; Py_Initialize(); inittiled(); // Get reference to base class to find its extensions later on PyObject *pmod = PyImport_ImportModule("tiled"); if (pmod) { PyObject *tiledPlugin = PyObject_GetAttrString(pmod, "Plugin"); Py_DECREF(pmod); if (tiledPlugin) { if (PyCallable_Check(tiledPlugin)) { mPluginClass = tiledPlugin; } else { Py_DECREF(tiledPlugin); } } } if (!mPluginClass) { log(Tiled::LoggingInterface::ERROR, "Can't find tiled.Plugin baseclass\n"); handleError(); return; } // w/o differentiating error messages could just rename "log" // to "write" in the binding and assign plugin directly to stdout/stderr PySys_SetObject((char *)"_tiledplugin", _wrap_convert_c2py__Tiled__LoggingInterface(&mLogger)); PyRun_SimpleString("import sys\n" "#from tiled.Tiled.LoggingInterface import INFO,ERROR\n" "class _Catcher:\n" " def __init__(self, type):\n" " self.buffer = ''\n" " self.type = type\n" " def write(self, msg):\n" " self.buffer += msg\n" " if self.buffer.endswith('\\n'):\n" " sys._tiledplugin.log(self.type, self.buffer)\n" " self.buffer = ''\n" "sys.stdout = _Catcher(0)\n" "sys.stderr = _Catcher(1)\n"); PyRun_SimpleString(QString("import sys; sys.path.insert(0, \"%1\")") .arg(mScriptDir).toUtf8().constData()); log(QString("-- Added %1 to path\n").arg(mScriptDir)); } reloadModules(); if (QFile::exists(mScriptDir)) { mFileSystemWatcher.addPath(mScriptDir); connect(&mFileSystemWatcher, SIGNAL(directoryChanged(QString)), &mReloadTimer, SLOT(start())); } } void PythonPlugin::log(Tiled::LoggingInterface::OutputType type, const QString &msg) { mLogger.log(type, msg); } void PythonPlugin::log(const QString &msg) { log(Tiled::LoggingInterface::INFO, msg); } /** * (Re)load modules in the script directory */ void PythonPlugin::reloadModules() { log(tr("Reloading Python scripts")); const QStringList pyfilter("*.py"); QDirIterator iter(mScriptDir, pyfilter, QDir::Files | QDir::Readable); while (iter.hasNext()) { iter.next(); QString name = iter.fileInfo().baseName(); ScriptEntry script = mScripts.take(name); script.name = name; // Throw away any existing class reference if (script.mapFormat) { PyObject *pluginClass = script.mapFormat->pythonClass(); Py_DECREF(pluginClass); } if (loadOrReloadModule(script)) { mScripts.insert(name, script); } else { if (!script.module) { PySys_WriteStderr("** Parse exception **\n"); PyErr_Print(); PyErr_Clear(); } if (script.mapFormat) { removeObject(script.mapFormat); delete script.mapFormat; } } } } /** * Finds the first python class that extends tiled.Plugin */ PyObject *PythonPlugin::findPluginSubclass(PyObject *module) { PyObject *dir = PyObject_Dir(module); PyObject *result = nullptr; for (int i = 0; i < PyList_Size(dir); i++) { PyObject *value = PyObject_GetAttr(module, PyList_GetItem(dir, i)); if (!value) { handleError(); break; } if (value != mPluginClass && PyCallable_Check(value) && PyObject_IsSubclass(value, mPluginClass) == 1) { result = value; handleError(); break; } Py_DECREF(value); } Py_DECREF(dir); return result; } bool PythonPlugin::loadOrReloadModule(ScriptEntry &script) { const QByteArray name = script.name.toUtf8(); if (script.module) { PySys_WriteStdout("-- Reloading %s\n", name.constData()); PyObject *module = PyImport_ReloadModule(script.module); Py_DECREF(script.module); script.module = module; } else { PySys_WriteStdout("-- Loading %s\n", name.constData()); script.module = PyImport_ImportModule(name.constData()); } if (!script.module) return false; PyObject *pluginClass = findPluginSubclass(script.module); if (!pluginClass) { PySys_WriteStderr("Extension of tiled.Plugin not defined in " "script: %s\n", name.constData()); return false; } if (script.mapFormat) { script.mapFormat->setPythonClass(pluginClass); } else { script.mapFormat = new PythonMapFormat(name, pluginClass, *this); addObject(script.mapFormat); } return true; } PythonMapFormat::PythonMapFormat(const QString &scriptFile, PyObject *class_, PythonPlugin &plugin) : MapFormat(&plugin) , mClass(nullptr) , mPlugin(plugin) , mScriptFile(scriptFile) { setPythonClass(class_); } Tiled::Map *PythonMapFormat::read(const QString &fileName) { mError = QString(); mPlugin.log(tr("-- Using script %1 to read %2").arg(mScriptFile, fileName)); if (!PyObject_HasAttrString(mClass, "read")) { mError = "Please define class that extends tiled.Plugin and " "has @classmethod read(cls, filename)"; return nullptr; } PyObject *pinst = PyObject_CallMethod(mClass, (char *)"read", (char *)"(s)", fileName.toUtf8().constData()); Tiled::Map *ret = nullptr; if (!pinst) { PySys_WriteStderr("** Uncaught exception in script **\n"); } else { _wrap_convert_py2c__Tiled__Map___star__(pinst, &ret); Py_DECREF(pinst); } handleError(); if (ret) ret->setProperty("__script__", mScriptFile); return ret; } bool PythonMapFormat::write(const Tiled::Map *map, const QString &fileName) { mError = QString(); mPlugin.log(tr("-- Using script %1 to write %2").arg(mScriptFile, fileName)); PyObject *pmap = _wrap_convert_c2py__Tiled__Map_const(map); if (!pmap) return false; PyObject *pinst = PyObject_CallMethod(mClass, (char *)"write", (char *)"(Ns)", pmap, fileName.toUtf8().constData()); if (!pinst) { PySys_WriteStderr("** Uncaught exception in script **\n"); mError = tr("Uncaught exception in script. Please check console."); } else { bool ret = PyObject_IsTrue(pinst); Py_DECREF(pinst); if (!ret) mError = tr("Script returned false. Please check console."); return ret; } handleError(); return false; } bool PythonMapFormat::supportsFile(const QString &fileName) const { if (!PyObject_HasAttrString(mClass, "supportsFile")) return false; PyObject *pinst = PyObject_CallMethod(mClass, (char *)"supportsFile", (char *)"(s)", fileName.toUtf8().constData()); if (!pinst) { handleError(); return false; } bool ret = PyObject_IsTrue(pinst); Py_DECREF(pinst); return ret; } QString PythonMapFormat::nameFilter() const { QString ret; // find fun PyObject *pfun = PyObject_GetAttrString(mClass, "nameFilter"); if (!pfun || !PyCallable_Check(pfun)) { PySys_WriteStderr("Plugin extension doesn't define \"nameFilter\"\n"); return ret; } // have fun PyObject *pinst = PyEval_CallFunction(pfun, "()"); if (!pinst) { PySys_WriteStderr("** Uncaught exception in script **\n"); } else { ret = PyString_AsString(pinst); Py_DECREF(pinst); } handleError(); Py_DECREF(pfun); return ret; } QString PythonMapFormat::shortName() const { QString ret; // find fun PyObject *pfun = PyObject_GetAttrString(mClass, "shortName"); if (!pfun || !PyCallable_Check(pfun)) { PySys_WriteStderr("Plugin extension doesn't define \"shortName\". Falling back to \"nameFilter\"\n"); return nameFilter(); } // have fun PyObject *pinst = PyEval_CallFunction(pfun, "()"); if (!pinst) { PySys_WriteStderr("** Uncaught exception in script **\n"); } else { ret = PyString_AsString(pinst); Py_DECREF(pinst); } handleError(); Py_DECREF(pfun); return ret; } QString PythonMapFormat::errorString() const { return mError; } void PythonMapFormat::setPythonClass(PyObject *class_) { mClass = class_; mCapabilities = NoCapability; // @classmethod nameFilter(cls) if (PyObject_HasAttrString(mClass, "nameFilter")) { // @classmethod write(cls, map, filename) if (PyObject_HasAttrString(mClass, "write")) { mCapabilities |= Tiled::MapFormat::Write; } // @classmethod read(cls, filename) // @classmethod supportsFile(cls, filename) if (PyObject_HasAttrString(mClass, "read") && PyObject_HasAttrString(mClass, "supportsFile")) { mCapabilities |= Tiled::MapFormat::Read; } } } } // namespace Python tiled-1.0.3/src/plugins/python/pythonplugin.h000066400000000000000000000067631315121121300213200ustar00rootroot00000000000000/* * Python Tiled Plugin * Copyright 2012, Samuli Tuomola * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #ifdef __MINGW32__ #include // included before Python.h to fix ::hypot not declared issue #endif #include #include "logginginterface.h" #include "mapformat.h" #include "plugin.h" #include #include #include #include namespace Tiled { class Map; } namespace Python { class PythonMapFormat; struct ScriptEntry { ScriptEntry() : module(nullptr) , mapFormat(nullptr) {} QString name; PyObject *module; PythonMapFormat *mapFormat; }; class Q_DECL_EXPORT PythonPlugin : public Tiled::Plugin { Q_OBJECT Q_INTERFACES(Tiled::Plugin) Q_PLUGIN_METADATA(IID "org.mapeditor.Plugin" FILE "plugin.json") public: PythonPlugin(); ~PythonPlugin(); void initialize() override; void log(Tiled::LoggingInterface::OutputType type, const QString &msg); void log(const QString &msg); private slots: void reloadModules(); private: bool loadOrReloadModule(ScriptEntry &script); PyObject *findPluginSubclass(PyObject *module); QString mScriptDir; QMap mScripts; PyObject *mPluginClass; QFileSystemWatcher mFileSystemWatcher; QTimer mReloadTimer; Tiled::LoggingInterface mLogger; }; // Class exposed for python scripts to extend class PythonScript { public: // perhaps provide default that throws NotImplementedError Tiled::Map *read(const QString &fileName); bool supportsFile(const QString &fileName) const; bool write(const Tiled::Map *map, const QString &fileName); QString nameFilter() const; }; class PythonMapFormat : public Tiled::MapFormat { Q_OBJECT Q_INTERFACES(Tiled::MapFormat) public: PythonMapFormat(const QString &scriptFile, PyObject *class_, PythonPlugin &plugin); Capabilities capabilities() const override { return mCapabilities; } Tiled::Map *read(const QString &fileName) override; bool supportsFile(const QString &fileName) const override; bool write(const Tiled::Map *map, const QString &fileName) override; QString nameFilter() const override; QString shortName() const override; QString errorString() const override; PyObject *pythonClass() const { return mClass; } void setPythonClass(PyObject *class_); private: PyObject *mClass; PythonPlugin &mPlugin; QString mScriptFile; QString mError; Capabilities mCapabilities; }; } // namespace Python PyMODINIT_FUNC inittiled(void); extern int _wrap_convert_py2c__Tiled__Map___star__(PyObject *obj, Tiled::Map * *address); extern PyObject* _wrap_convert_c2py__Tiled__Map_const(Tiled::Map const *cvalue); extern PyObject* _wrap_convert_c2py__Tiled__LoggingInterface(Tiled::LoggingInterface *cvalue); tiled-1.0.3/src/plugins/python/qtbinding.py000066400000000000000000000202351315121121300207260ustar00rootroot00000000000000""" Python Tiled Plugin Copyright 2012, Samuli Tuomola This file is part of Tiled. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ import re from pybindgen import * import pybindgen.typehandlers.base as typehandlers from pybindgen.typehandlers.base import ForwardWrapperBase, PointerParameter """ class QFlagsTransformation(typehandlers.TypeTransformation): def __init__(self): self.rx = re.compile(r'(?:::)?QFlags<\s*(\w+)\s*>') def get_untransformed_name(self, name): m = self.rx.match(name) if m is None: return None else: return m.group(1)+' *' def create_type_handler(self, type_handler, *args, **kwargs): ctype = self.get_untransformed_name(args[0]) handler = type_handler(ctype, *args[1:], **kwargs) handler.has_been_transformed = True return handler typehandlers.param_type_matcher.register_transformation(QFlagsTransformation()) """ class QFlagsOptionParam(Parameter): DIRECTIONS = [Parameter.DIRECTION_IN] CTYPES = ['QFlags'] def get_c_error_return(self): return "return QFlags(0);" def convert_c_to_python(self, wrapper): raise NotImplementedError #wrapper.build_params.add_parameter("s", ['%s.toUtf8().data()' % self.value], prepend=True) def convert_python_to_c(self, wrapper): name = wrapper.declarations.declare_variable("QFileDialog::Option", self.name) wrapper.parse_params.add_parameter('i', ['&'+name], self.value, optional=bool(self.default_value)) if self.default_value is None: wrapper.call_params.append('(QFlags)%s' % name) else: wrapper.call_params.append(self.default_value) class QStringPtrParam(PointerParameter): DIRECTIONS = [Parameter.DIRECTION_IN] # could be out as well CTYPES = ['QString*'] def convert_c_to_python(self, wrapper): raise NotImplementedError def convert_python_to_c(self, wrapper): name = wrapper.declarations.declare_variable("const char *", self.name) if self.default_value is None: name_qst = wrapper.declarations.declare_variable("QString*", self.name + '_qst', 'new QString(%s)' % name) wrapper.call_params.append('%s' % name_qst) else: wrapper.call_params.append(self.default_value) wrapper.parse_params.add_parameter('s', ['&'+name], self.value, optional=bool(self.default_value)) class QStringParam(Parameter): DIRECTIONS = [Parameter.DIRECTION_IN] CTYPES = ['QString'] def get_c_error_return(self): return "return QString();" def convert_c_to_python(self, wrapper): wrapper.build_params.add_parameter("s", ['%s.toUtf8().data()' % self.value], prepend=True) def convert_python_to_c(self, wrapper): name = wrapper.declarations.declare_variable("const char *", self.name) len_ = wrapper.declarations.declare_variable("Py_ssize_t", self.name+"_len") wrapper.parse_params.add_parameter('s#', ['&'+name, '&'+len_], self.value) wrapper.call_params.append('QString::fromUtf8(%s)' % name) class QStringReturnValue(ReturnValue): CTYPES = ['QString'] def get_c_error_return(self): return "return QString();" def convert_python_to_c(self, wrapper): #raise NotImplementedError # TODO (needed only for virtual methods where C calls Python code) ptr = wrapper.declarations.declare_variable("const char *", "retval_ptr") len_ = wrapper.declarations.declare_variable("Py_ssize_t", "retval_len") wrapper.parse_params.add_parameter("s#", ['&'+ptr, '&'+len_]) wrapper.after_call.write_code("%s = QString(%s);" % (self.value, ptr)) def convert_c_to_python(self, wrapper): wrapper.build_params.add_parameter("s", ['%s.toUtf8().data()' % self.value], prepend=True) def generate(parent_mod): mod = module.SubModule('qt', parent_mod) mod.add_include('') mod.add_include('') mod.add_include('') mod.add_include('') #mod.add_include('"qtbind.h"') cls_qpointf = mod.add_class('QPointF') cls_qpointf.add_constructor([('float','x'),('float','y')]) cls_qpointf.add_method('x', 'int', []) cls_qpointf.add_method('setX', None, [('int','x')]) cls_qpointf.add_method('y', 'int', []) cls_qpointf.add_method('setY', None, [('int','y')]) cls_sizef = mod.add_class('QSizeF') cls_sizef.add_constructor([('float','w'),('float','h')]) cls_sizef.add_method('width', 'int', []) cls_sizef.add_method('setWidth', None, [('int','w')]) cls_sizef.add_method('height', 'int', []) cls_sizef.add_method('setHeight', None, [('int','h')]) cls_qrgb = mod.add_class('QRgb') mod.add_container('QVector', retval('QRgb'), 'vector') cls_color = mod.add_class('QColor') cls_color.add_constructor([('QRgb','col')]) cls_color.add_constructor([('int','r'), ('int','g'), ('int','b')]) cls_color.add_constructor([('int','r'), ('int','g'), ('int','b'),('int','a')]) cls_color.add_method('rgb', 'QRgb', []) cls_color.add_method('rgba', 'QRgb', []) cls_qimage = mod.add_class('QImage') cls_qimage.add_enum('Format', ('Format_Invalid','Format_Mono','Format_MonoLSB', 'Format_Indexed8','Format_RGB32','Format_ARGB32', 'Format_ARGB32_Premultiplied','Format_RGB16', 'Format_ARGB8565_Premultiplied','Format_RGB666', 'Format_ARGB6666_Premultiplied','Format_RGB555', 'Format_ARGB8555_Premultiplied','Format_RGB888','Format_RGB444', 'Format_ARGB4444_Premultiplied')) cls_qimage.add_constructor([]) cls_qimage.add_constructor([('int','w'), ('int','h'), ('Format','f')]) cls_qimage.add_method('color', 'QRgb', [('int','i')]) cls_qimage.add_method('colorTable', 'QVector', []) cls_qimage.add_method('fill', None, [('int','color')]) cls_qimage.add_method('load', 'bool', [('const QString','fileName'),('char*','fmt')]) cls_qimage.add_method('mirrored', retval('const QImage&'), [('bool','horiz'),('bool','vert')]) cls_qimage.add_method('width', 'int', []) cls_qimage.add_method('height', 'int', []) cls_qimage.add_method('setColor', None, [('int','i'),('QRgb','c')]) cls_qimage.add_method('setPixel', None, [('int','x'),('int','y'), ('unsigned int','color')]) cls_qimage.add_method('setPixel', None, [('int','x'),('int','y'), ('QRgb','color')]) cls_qimage.add_method('setColorTable', None, [('QVector','colors')]) cls_qpixmap = mod.add_class('QPixmap') cls_qpixmap.add_method('toImage', retval('const QImage&'), []) cls_qpixmap.add_method('fromImage', None, [('const QImage&','image')]) cls_qpixmap.add_method('convertFromImage', None, [('const QImage&','image')]) cls_qpixmap.add_method('width', 'int', []) cls_qpixmap.add_method('height', 'int', []) cls_qwidget = mod.add_class('QWidget') cls_qfiledialog = mod.add_class('QFileDialog') cls_qfiledialog.add_enum('Option', ('ShowDirsOnly','DontResolveSymlinks','DontConfirmOverwrite','DontUseNativeDialog', 'ReadOnly','HideNameFilterDetails','DontUseSheet')) cls_qfiledialog.add_method('getOpenFileName', 'QString', [ param('QWidget*','parent',transfer_ownership=False,null_ok=True), ('const QString','caption'),('const QString','dir'),('const QString','filter'), param('QString*','selectedFilter',default_value='new QString("")'), param('QFlags','options', direction=Parameter.DIRECTION_IN, default_value='0') ], is_static=True) mod.add_container('QList', retval('QString'), 'list') """ with open('qtbind.h','w') as fh: import pybindgen.typehandlers.codesink as cs sink = cs.MemoryCodeSink() mod.generate_forward_declarations(sink) includes = ['QImage','QFileDialog','QWidget','Qflags'] print >>fh, '\n'.join(['#include <%s>' % f for f in includes]) print >>fh, sink.flush() with open('qtbind.cpp','w') as fh: mod.generate(fh) """ tiled-1.0.3/src/plugins/python/scripts/000077500000000000000000000000001315121121300200625ustar00rootroot00000000000000tiled-1.0.3/src/plugins/python/scripts/fotf.py000066400000000000000000000070071315121121300213760ustar00rootroot00000000000000""" Fury of the Furries level loader for Tiled 2012, """ import sys, re from tiled import * from tiled.qt import * from os.path import dirname from lib import cpystruct, lbm from struct import pack,unpack from collections import namedtuple maps = {} tilesets = {} MetaData = namedtuple( 'MetaData', 'startX, startY, lType,'+ 'fin1X, fin1Y, u1, fin2X, fin2Y, lvl' ) class Fury(Plugin): @classmethod def nameFilter(cls): return "Fury of the Furries (*.bin)" @classmethod def supportsFile(cls, f): return open(f).read(4) == 'byt4' @classmethod def read(cls, f): print 'Loading map at',f fr = Fury(f) m = Tiled.Map(Tiled.Map.Orthogonal, fr.w, fr.h, 16, 16) maps[f] = m # probably defined explicitly somewhere in the data decs = [1,3,4,2,8,6,7,9,10,5] decnum = (int(re.findall('[0-9]+', f).pop())-1)/10 if decnum >= len(decs): decnum %= len(decs) gfxf = dirname(f)+'/../DEC/DECOR%02i.LBM' % decs[decnum] t = Tiled.Tileset('DECOR', 16,16, 0, 0) t.loadFromImage(fr.readtilegfx(gfxf), '') l = Tiled.TileLayer('Tiles',0,0, fr.w, fr.h) fr.populatetiles(l, t) # have to pass ownership so can't add tileset before populating layer m.addTileset(t) m.addLayer(l) #if not f.endswith('DATA19.BIN'): # del fr.lvl[:21*2] # skip some zeros, todo: more deterministic print len(fr.lvl), unpack('<40h', str(fr.lvl[:80])) print MetaData(*unpack('<9h', str(fr.lvl[:18]))) return m @classmethod def write(cls, m, fn): print "-- script doesn't support writing yet" fn += '.testing' print ".. map(%i,%i) to" % (m.width(),m.height()), fn lvl = [] with open(fn, 'w') as fh: for i in range(m.layerCount()): tiles = [] l = 0 if isTileLayerAt(m, i): l = tileLayerAt(m, i) print l elif isObjectGroupAt(m, i): #l = objectGroupAt(m, i) continue for x in range(l.width()): for y in range(l.height()): tiles.append( l.cellAt(x, y).tile.id() ) print >>fh, tiles return False def __init__(self, f): dat = bytearray() with open(f, 'rb') as fh: fh.read(4) #skip sig ldata = LevelData() rdata = RleData() while ldata.unpack(fh) and ldata.len != 0 : if len(ldata.d)==1 and ldata.d[0] == 0: break rdata.unpack(fh) dat.extend(ldata.d) dat.extend([rdata.val for i in range(rdata.rep)]) print 'le',len(dat) self.w, self.h = unpack("<2H", str(dat[:4])) del dat[:4] self.lvl = dat def readtilegfx(self, fn): lc = dict(lbm.parselbm(fn)) #print lc['BMHD'] bd = list(lbm.readbody(lc['BODY'], lc['BMHD'])) img = QImage(lc['BMHD'].sz.w, lc['BMHD'].sz.h, QImage.Format_Indexed8) img.setColorTable(lc['CMAP']) # there should be a faster alternative for y in range(img.height()): for x in range(img.width()): img.setPixel(x, y, bd[y*img.width()+x]) return img def populatetiles(self, l, t): i = 0 for y in range(self.h): for x in range(self.w): tpos = self.lvl[i+1]*t.columnCount() + self.lvl[i] if tpos < t.tileCount(): ti = t.tileAt(tpos) if ti != None: l.setCell(x, y, Tiled.Cell(ti)) i += 2 if self.w < 78: # padded to width of 78 tiles i += (78-self.w)*2 del self.lvl[:self.w*self.h*2] class LevelData(cpystruct.CpyStruct('ushort len; BYTE d[len];')): pass class RleData(cpystruct.CpyStruct('BYTE rep, sig, val')): pass tiled-1.0.3/src/plugins/python/scripts/lib/000077500000000000000000000000001315121121300206305ustar00rootroot00000000000000tiled-1.0.3/src/plugins/python/scripts/lib/__init__.py000066400000000000000000000000001315121121300227270ustar00rootroot00000000000000tiled-1.0.3/src/plugins/python/scripts/lib/cpystruct.py000066400000000000000000000213031315121121300232410ustar00rootroot00000000000000""" CreepyStruct - Convenience class for (un)packing structured binaries (c)2011-2012, This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ import re, sys, struct # struct.pack format characters prefixed by : REFMT = r':[@!<>=]?[0-9xcbBhHiIlLqQfdspP]+' # possible array definition or value assignment REARR = r'(?:\[(\w+)\])?(?:\s*=\s*([0-9a-fx]+))?' # skip C or python style comments to the end of line RECMT = r'\s*(?:#.*|//.*)?' # whole line with at least format/struct ref and attribute name REPCK = r'(%s|[\s\w]+|,)\s+(\w+)%s%s[;]?%s' % (REFMT, RECMT, REARR, RECMT) FORMATS = { 'c':'char', 'b':'signed char|SBYTE', 'B':'unsigned char|uchar|BYTE', '?':'_Bool|bool', 'h':'short|SWORD', 'H':'unsigned short|ushort|UWORD', 'i':'int', 'I':'unsigned int|uint|WORD', 'l':'long', 'L':'unsigned long|ulong|DWORD', 'q':'long long', 'Q':'unsigned long long', 'f':'float', 'd':'double' } fdict = {} for f in FORMATS: fdict.update( [(p,f) for p in FORMATS[f].split('|')] ) class CpySkeleton(struct.Struct): """ Not to be used directly, use CpyStruct() to build a class """ def __init__(self, dat=None, **kws): """ Takes keyword arguments to initialize attributes """ struct.Struct.__init__(self, getattr(self, '__fstr')) self.validate() if len(kws) > 0: for k in kws: setattr(self, k, kws[k]) if dat != None: self.unpack(dat) def validate(self): "check that the extending classes specify valid struct" for i,(f,n,a,v) in enumerate(self.formats): if a != '' and not a.isdigit() and i < len(self.formats): for b in self.formats[i:]: if a=='' or b[2].isdigit(): raise Exception('Varlength arrays only '+ 'supported at end of struct: %s[%s]' % (n,a)) def pack(self): "convert member values to binary" ret = '' for i,(f,n,a,v) in enumerate(self.formats): v = getattr(self, n) if issubclass(v.__class__, CpySkeleton): ret += v.pack() continue if type(f) != type(struct.Struct) and f in fdict: f = fdict[f] if a != '': # array (possibly varlength) a = int(a) if a.isdigit() else getattr(self, a) if f=='c': # chararray as string f = str(a)+'s' a = 0 if type(f) == type(struct.Struct): fstr = getattr(f, '__fstr') # temp hack because of qmap limitations in tiled map props sz = struct.calcsize(fstr) m = re.match('<[0-9]*[sc]',fstr) if a != '' and a > 0 and (m is None or m.group(0) != fstr): for j in range(len(v)): #a): v2 = f(v[j].ljust(sz,'\0')) ret += v2.pack() elif type(v) == list: print 'pack list' # todo else: #v = f(v.ljust(sz,'\0')) ret += struct.pack(getattr(f, '__fstr'), v) else: f = getattr(self, '__endianflag') + f if type(v) is list: for x in v: ret += struct.pack(f, x) else: # just an ordinary var ret += struct.pack(f, v) return ret def unpack(self, dat): """ Takes a string, file, mmap or StringIO instance """ rawpos = 0 # position in binary for custom types pos = 0 # in case substruct handles multiple values if dat.__class__.__name__ in ('file','mmap', 'StringIO'): # this doesn't cover varlen members, for that dat is read directly buf = dat.read(len(self)) else: buf = dat unpacked = None if hasattr(self, 'fromraw'): sz = struct.calcsize(getattr(self, '__fstr')) unpacked = self.fromraw(buf[:sz]) if unpacked is None: unpacked = list(struct.Struct.unpack(self, buf)) if hasattr(self, 'fromval'): unpacked = self.fromval(unpacked) if not hasattr(unpacked, '__iter__'): unpacked = [unpacked] #if len(self.formats) != len(unpacked): # print unpacked # raise LookupError('Unmatched number of unpacked variables: %i != %i' # % (len(self.formats),len(unpacked))) for i,(f,n,a,v) in enumerate(self.formats): if a != '' and not a.isdigit(): break arlen = 0 if a.isdigit() and (type(f) is type or fdict[f] != 'c'): arlen = int(a) v = unpacked[pos] if type(f) == type(struct.Struct): sz = struct.calcsize(getattr(f, '__fstr')) if arlen > 0: arr = [] for i in range(arlen): arr.append( f(buf[rawpos:rawpos+sz]) ) rawpos += sz pos += len(f.formats) setattr(self, n, arr) else: setattr(self, n, f(buf[rawpos:rawpos+sz])) rawpos += sz pos += len(f.formats) else: if arlen > 0: setattr(self, n, unpacked[pos:pos+arlen]) pos += arlen else: setattr(self, n, v) pos += 1 rawpos += getattr(self, "__fsz")[i] # variable-length members for f,n,a,v in self.formats: if a != '' and not a.isdigit(): c = getattr(self, a) # one level of custom varlen types should be enough for everyone if isinstance(c, struct.Struct): # would it be better to delegate this to the custom class? c = getattr(c, c.__slots__[0]) #dat.seek(rawpos) if type(f) == type(struct.Struct): # custom types sz = struct.calcsize(getattr(f, '__fstr')) arr = [] for i in range(c): arr.append( f(dat.read(sz)) ) rawpos += sz setattr(self, n, arr) else: # primitives f = str(c)+'s' if fdict[f]=='c' else str(c)+fdict[f] sz = struct.calcsize(f) val = struct.unpack(f, dat.read(sz)) #if len(val) == 1: val = val[0] rawpos += sz setattr(self, n, val) return buf def __len__(self): return struct.calcsize(getattr(self, '__fstr')) def __str__(self): ret = self.__class__.__name__+'[' for f,n,a,v in self.formats: ret += '%s=%s,' % (n,getattr(self, n, '')) return ret[:-1]+']' def peek(s, n): p = s.tell() r = s.read(n) s.seek(p) return r def parseformat(fmt, callscope=None): fstr = '' sz = [] for i,(f,n,a,v) in enumerate(fmt): if f == ',' and i > 0: fmt[i] = (fmt[i-1][0],n,a,v) f = fmt[i-1][0] elif f == ',': raise Exception('Unexpected comma at '+str(fmt[i])) fs = '' if fdict.has_key(f): if a.isdigit(): fs = 's' if fdict[f] == 'c' else fdict[f] elif a != '' and not a.isdigit(): # varlength array, read separately pass else: # C type fs = fdict[f] elif type(f) is type(CpySkeleton): # might have an alignment issue when mixing endians.. fs = re.sub('[<>]?','',f.__fstr) elif callscope.f_globals.has_key(f): # resolve references to other CpyStructs fmt[i] = (callscope.f_globals[f],n,a,v) fs = re.sub('[<>]?','',fmt[i][0].__fstr) elif f[0] == ':': # struct format uses colon as prefix for explicitness fs = f[1:] fmt[i] = (f[1:],n,a,v) else: raise Exception('Unknown format at '+str(fmt[i])) if a.isdigit(): # in case it's e.g. custom type of a string if fs[0].isdigit(): fs *= int(a) else: fs = a + fs #elif a != '': # fstr += '{'+a+'}' sz.append(struct.calcsize(fs)) fstr += fs return (fmt, fstr, sz) def CpyStruct(s, endianflg='<'): """ Call with a string specifying C-like struct to get a Struct class """ # f=format, n=name, a=arraydef, v=default value fmt = [(f.strip(),n,a,v) for f,n,a,v in re.findall(REPCK, s)] # peek into caller's namespace in case they refer to custom classes callscope = sys._getframe(1) try: fmt, fstr, fsz = parseformat(fmt, callscope) finally: del callscope # for backwards compatibility if endianflg == True: endianflg = '>' elif endianflg == False: endianflg = '<' d = {} d['__endianflag'] = endianflg d['__fstr'] = endianflg + fstr d['__fsz'] = fsz d['__slots__'] = [n for f,n,a,v in fmt] d['formats'] = fmt for f,n,a,v in fmt: if v != '': d[n] = int(v,0) return type('', (CpySkeleton,), d) tiled-1.0.3/src/plugins/python/scripts/lib/lbm.py000066400000000000000000000062201315121121300217540ustar00rootroot00000000000000""" ILBM pure python decoder 2012, This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ from tiled.qt import * from cpystruct import * #from PyQt4.Qt import QColor # to test outside tiled import struct class IFFhead(CpyStruct(":4s id; :I len; :4s type;", True)): pass class IFFchunk(CpyStruct(":4s id; :I len;", True)): @classmethod def parsefile(cls, f): """ Reads whole file consisting of IFF chunks Returns tuple generator of chunk name and body """ with open(f, 'rb') as fh: # header ih = IFFhead(fh) yield ih.type, ih # chunks ic = IFFchunk() filelen = ih.len - len(ih) while fh.tell() < filelen and ic.unpack(fh) != None: yield ic.id, fh.read(ic.len) class BMHDsize(CpyStruct("short w, h", True)): @classmethod def fromraw(cls, v): return struct.unpack(getattr(cls,'__fstr'), v) class BMHD(CpyStruct(""" BMHDsize sz; short x, y; BYTE planes, mask; short comp, trans; BYTE xaspect, yaspect; short pgw, pgh; """)): pass class CRNG(CpyStruct("short pad, cycrate, cycle, lowhireg;", True)): pass class CMAP(CpyStruct("BYTE color[3];", True)): @classmethod def parse(cls, dat): c = CMAP() sz = struct.calcsize(getattr(cls, '__fstr')) for i in range(len(dat)/sz): c.unpack(dat[i*sz:i*sz+sz]) yield QColor(c.color[0],c.color[1],c.color[2]).rgb() def uncomp(dat): i = 0 ret = bytearray() while i < len(dat): v = struct.unpack('b', dat[i])[0] i += 1 if v >= 0: for n in range(v+1): ret += dat[i] i += 1 elif v != -128: for n in range(v-1,0,1): ret += dat[i] i += 1 return ret def readbody(bd, ch): bj = [0,(ch.sz.w+15) / 16 * 2] for p in range(2,ch.planes): bj.append(bj[1] * p) sj = bj[1] * ch.planes for sl in range(0, sj*ch.sz.h, sj): for x in range(ch.sz.w): b = x & 7 bm = 128 >> b ib = sl + (x >> 3) px = (bd[ib] & bm) # only 4 planes tested for p in range(1,ch.planes,1): px |= (bd[ib+bj[p]] & bm) << p yield px >> (7 - b) def parselbm(f): for id,dat in list(IFFchunk.parsefile(f)): if id == 'BMHD': ch = BMHD(dat) yield id, ch elif id == 'CMAP': yield id, list(CMAP.parse(dat)) elif id == 'CRNG': yield id, CRNG(dat) elif id == 'CAMG': raise Exception('HAM/HALFBRITE not supported at the moment') elif id == 'BODY': if ch.comp == 1: bd = uncomp(dat) else: bd = dat yield id, bd if __name__ == "__main__": import sys print list(parselbm(sys.argv[1])) tiled-1.0.3/src/plugins/python/scripts/lib/mappy_types.py000066400000000000000000000077421315121121300235660ustar00rootroot00000000000000 from cpystruct import * """ #define AN_END -1 /* Animation types, AN_END = end of anims */ #define AN_NONE 0 /* No anim defined */ #define AN_LOOPF 1 /* Loops from start to end, then jumps to start etc */ #define AN_LOOPR 2 /* As above, but from end to start */ #define AN_ONCE 3 /* Only plays once */ #define AN_ONCEH 4 /* Only plays once, but holds end frame */ #define AN_PPFF 5 /* Ping Pong start-end-start-end-start etc */ #define AN_PPRR 6 /* Ping Pong end-start-end-start-end etc */ #define AN_PPRF 7 /* Used internally by playback */ #define AN_PPFR 8 /* Used internally by playback */ #define AN_ONCES 9 /* Used internally by playback */ """ class BLKSTR(CpyStruct(""" int olay[4]; unsigned int user1; unsigned int user2; // user long data */ unsigned short user3; unsigned short user4; // user short data */ unsigned char user5; unsigned char user6; unsigned char user7; // user byte data */ unsigned char tl; // bits for collision detection */ """)): pass """for newer fmp version? unsigned char tr; unsigned char bl; unsigned char br; unsigned char trigger; // bit to trigger an event */ unsigned char unused1; unsigned char unused2; unsigned char unused3; """ class ANISTR(CpyStruct(""" signed char antype; // Type of anim, AN_? */ signed char andelay; // Frames to go before next frame */ signed char ancount; // Counter, decs each frame, till 0, then resets to andelay */ signed char anuser; // User info */ long ancuroff; // Points to current offset in list */ long anstartoff; // Points to start of blkstr offsets list, AFTER ref. blkstr offset */ long anendoff; """)): pass class OBJSTR(CpyStruct(""" int xpos; int ypos; // pixel position in map to handle */ int gfxid; int tileid; int gxoff; int gyoff; // offset into graphic */ int gwidth; int gheight; int ghandlexoff; int ghandleyoff; // handle pos, from gxoff, gyoff */ int show; // display mode */ int user1; int user2; int user3; int user4; int user5; int user6; int user7; int flags; """)): pass class GENHEAD(CpyStruct(""" char id1; char id2; char id3; char id4; // 4 byte header id. */ long headsize; // size of header chunk. */ """)): pass #// char M,P,H,D; 4 byte chunk identification. */ #// long int mphdsize; size of map header. */ class MPHD(CpyStruct(""" BYTE mapverhigh; // map version number to left of . (ie X.0). */ BYTE mapverlow; // map version number to right of . (ie 0.X). */ BYTE lsb; // if 1, data stored LSB first, otherwise MSB first. */ BYTE type; // 0=old, 1=new, 2=iso short mapwidth; // width in blocks. */ short mapheight; // height in blocks. */ short reserved1; short reserved2; short blockwidth; // width of a block (tile) in pixels. */ short blockheight; // height of a block (tile) in pixels. */ short blockdepth; // depth of a block (tile) in planes (ie. 256 colours is 8) */ short blockstrsize; // size of a block data structure */ short numblockstr; // Number of block structures in BKDT */ short numblockgfx; // Number of 'blocks' in graphics (BODY) */ BYTE skip; SBYTE trans8bit; short transhi; """)): pass #// char E,D,H,D; 4 byte chunk identification. */ #// long int edhdsize; size of editor header. */ class EDHD(CpyStruct(""" short xmapoffset; // editor offset, in blocks, from left. */ short ymapoffset; // editor offset, in blocks, from right. */ long fgcolour; // fg colour for text, buttons etc. */ long bgcolour; // bg colour for text, buttons etc. */ short swidth; // width of current screen res */ short sheight; // height of current screen res */ short strtstr; // first structure in view */ short strtblk; // first block graphic in view */ short curstr; // current block structure */ short curanim; // current anim structure */ short animspd; // gap in frames between anims */ short span; // control panel height */ short numbrushes; // number of brushes to follow. */ """)): pass class MAPFILL(CpyStruct("short leftedge, width, yoff;")): pass class fmpchunk(CpyStruct(":4s id; :I len;",True)): pass class BODY(CpyStruct(":H dat[len]", True)): pass tiled-1.0.3/src/plugins/python/scripts/mappy.py000066400000000000000000000142021315121121300215610ustar00rootroot00000000000000""" Mappy support for Tiled 2012-2013, """ from tiled import * from tiled.qt import * import os, sys, struct from lib.mappy_types import BLKSTR, MPHD, fmpchunk import pickle from StringIO import StringIO from collections import OrderedDict from base64 import b64encode, b64decode class FMPPicklerMixin: @classmethod def unpackchunks(cls, f): chunks = OrderedDict() with open(f, 'rb') as fh: frm = fmpchunk() frm.unpack(fh) frm.data = fh.read(4) filelen = frm.len - 16 chunks[frm.id] = frm print frm while fh.tell() < filelen: fc = fmpchunk() if not fc.unpack(fh): break print fh.tell(), fc fc.data = fh.read(fc.len) chunks[fc.id] = fc return chunks @classmethod def packchunks(cls, fn, chunks): with open(fn, 'wb') as fh: for k,v in chunks.items(): print k, len(v) + v.len # chunk header + data fh.write(v.pack()) fh.write(v.data) @classmethod def picklechunks(cls, chunks): src = StringIO() pi = pickle.Pickler(src, 2) pi.dump(chunks) print "packlen", src.len return b64encode(src.getvalue()) @classmethod def unpicklechunks(cls, data): src = StringIO(b64decode(data)) print "unpacklen",src.len return pickle.Unpickler(src).load() class Mappy(Plugin, FMPPicklerMixin): @classmethod def nameFilter(cls): return "Mappy (*.fmp)" @classmethod def shortName(cls): return "mappy" @classmethod def supportsFile(cls, f): return open(f).read(4) == 'FORM' @classmethod def read(cls, f): print 'Loading map at',f chunks = cls.unpackchunks(f) hd = MPHD() # perhaps cpystruct should only read as many bytes as it can handle? hd.unpack(chunks['MPHD'].data[:len(hd)]) m = Tiled.Map(Tiled.Map.Orthogonal, hd.mapwidth, hd.mapheight, hd.blockwidth, hd.blockheight) if hd.type == 2: print 'Isometric maps not supported at the moment' return m m.setProperty('chunks', cls.picklechunks(chunks)) tset = Tiled.Tileset('Tiles', hd.blockwidth, hd.blockheight, 0, 0) cmap = list(FMPColormap.unpack(chunks['CMAP'].data)) tset.loadFromImage(FMPTileGfx.unpack(hd, chunks['BGFX'].data, cmap), "") blks = FMPBlocks(chunks['BKDT'].data, hd).blocks for c in ['LYR'+str(i) for i in range(7,0,-1)]+['BODY']: if not chunks.has_key(c): continue print 'populating',c lay = Tiled.TileLayer(c,0,0,hd.mapwidth, hd.mapheight) lvl = list(FMPLayer.unpack(hd, chunks[c].data)) FMPLayer.populate(lay, blks, tset, hd, lvl) m.addLayer(lay) m.addTileset(tset) return m @classmethod def write(cls, m, fn): if m.orientation() != Tiled.Map.Orthogonal: print 'Isometric maps not supported at the moment' return False if not m.property('chunks'): raise Exception("Export depends on unparsed binary blobs from original " +"fmp to be stored in the map property 'chunks'") print 'Writing map at',fn chunks = cls.unpicklechunks(m.property('chunks')) hd = MPHD() hd.unpack(chunks['MPHD'].data[:len(hd)]) blks = FMPBlocks(chunks['BKDT'].data, hd).blocks for i in range(m.layerCount()): if not isTileLayerAt(m, i): continue l = tileLayerAt(m, i) chunks[l.name()].data = FMPLayer.pack(hd, blks, l, i) cls.packchunks(fn, chunks) return True class FMPBlocks: @classmethod def unpack(cls, chunk, hd): mod = hd.blockwidth * hd.blockheight * ((hd.blockdepth+1)/8) for pos in range(0, hd.numblockstr*hd.blockstrsize, hd.blockstrsize): b = BLKSTR() b.unpack(chunk[pos:pos+hd.blockstrsize]) if hd.type == 0: for i in range(4): b.olay[i] /= mod yield b def __init__(self, chunk, hd): self.blocks = list(FMPBlocks.unpack(chunk, hd)) class FMPTileGfx: @classmethod def unpack(cls, hd, dat, cmap): n = 0 w,h = hd.blockwidth*10, hd.blockheight*hd.numblockgfx/10+hd.blockheight fmt = QImage.Format_Indexed8 if hd.blockdepth==8 else QImage.Format_ARGB32 img = QImage(w, h, fmt) img.setColorTable(cmap) for i in range(hd.numblockgfx): col,row = i%10, i/10 tx,ty = col*hd.blockwidth, row*hd.blockheight for y in range(hd.blockheight): for x in range(hd.blockwidth): c = struct.unpack('B', dat[n])[0] if hd.blockdepth==8: img.setPixel(tx+x, ty+y, c) else: img.setPixel(tx+x, ty+y, cmap[c]) n+=1 return img class FMPLayer: @classmethod def unpack(cls, hd, dat): for i in range(0,hd.mapheight*hd.mapwidth*2,2): d = struct.unpack('= len(blocks): pass#print 'unknown block at',i else: n = blocks[ldata[i]].olay[fg] if n != 0: ti = tileset.tileAt(n) if ti is None: print 'invalid tile',n,'at',x,y else: layer.setCell(x, y, Tiled.Cell(ti)) i += 1 class FMPColormap: @classmethod def unpack(self, cmap): """cmap -- rgb bytearray""" print 'got',len(cmap) for i in range(0,len(cmap),3): r,g,b = struct.unpack('3B', cmap[i:i+3]) yield QColor(r,g,b).rgb() @classmethod def pack(self, cmap): """cmap -- QImage.colorTable""" yield fmpchunk(id='CMAP', len=len(list(cmap))).pack() for c in cmap: yield struct.pack('3B', (c.qRed,c.qGreen,c.qBlue)) tiled-1.0.3/src/plugins/python/scripts/pk2.py000066400000000000000000000214551315121121300211370ustar00rootroot00000000000000""" Pekka Kana 2 map support for Tiled 2012, Notes: - should make PK2 classes mixins with Tiled ones """ import os, sys, re, string from tiled import * from tiled.qt import * from lib import cpystruct from os.path import dirname, exists from struct import pack,unpack,Struct from base64 import b64encode, b64decode maps = [] class PK2(Plugin): @classmethod def nameFilter(cls): return "Pekka Kana 2 (*.map)" @classmethod def shortName(cls): return "pk2" @classmethod def supportsFile(cls, f): return open(f, 'rb').read(4) == '1.3\0' @classmethod def read(cls, f): lvl = PK2MAP() with open(f, 'rb') as fh: lvl.unpack(fh) # spriteCount is +1 fh.seek(-len(lvl.spriteFiles[0]), 1) lay1 = PK2MAPLAYER(fh) lay2 = PK2MAPLAYER(fh) lay3 = PK2MAPLAYER(fh) print lvl # -- tileset img = QImage() imgfile = dirname(f)+'/../../gfx/tiles/'+str(lvl.tileFile) img.load(imgfile, 'BMP') t = Tiled.Tileset('Tiles', 32,32, 0, 0) t.setTransparentColor(QColor(img.color(255))) t.loadFromImage(img, imgfile) # find common bounding box for the layers bb = ['','',10,10] for l in [lay1,lay2,lay3]: print l bb[0] = min([bb[0], l.lx.num]) bb[1] = min([bb[1], l.ly.num]) bb[2] = max([bb[2], l.width()]) bb[3] = max([bb[3], l.height()]) print 'bounds', bb m = Tiled.Map(Tiled.Map.Orthogonal, bb[2], bb[3], 32,32) maps.append(m) # -- background image lai = Tiled.ImageLayer('Scenery', 0,0, bb[2], bb[3]) img = QImage() imgfile = dirname(f)+'/../../gfx/scenery/'+str(lvl.fieldFile) img.load(imgfile, 'BMP') lai.loadFromImage(img, imgfile) # -- layers la1 = Tiled.TileLayer('Back', 0,0, bb[2], bb[3]) lay1.doTiles(t, la1, bb) la2 = Tiled.TileLayer('Front', 0,0, bb[2], bb[3]) lay2.doTiles(t, la2, bb) sprdir = dirname(f)+'/../../sprites/' lay3.sprites = [0] lay3.spriteGfx = {} for s in lvl.spriteFiles: # spriteCount is +1 if not exists(sprdir+str(s)): break spr = PK2SPR(sprdir+str(s), m) if not lay3.spriteGfx.has_key(str(spr.kuvatiedosto)): sprfile = find_case_insensitive_filename(sprdir, str(spr.kuvatiedosto)) img = QImage() img.load(sprdir+sprfile, 'BMP') print 'loading', sprdir+sprfile sprts = Tiled.Tileset(sprfile, 32,32, 0, 0) sprts.setTransparentColor(QColor(img.color(255))) sprts.loadFromImage(img, sprdir+sprfile) lay3.spriteGfx[str(spr.kuvatiedosto)] = sprts #sprgfx[(str(spr.kuvatiedosto] lay3.sprites.append(spr) #print spr la3 = Tiled.ObjectGroup('Sprites', 0,0, bb[2], bb[3]) lay3.doSprites(la3, bb) m.addLayer(lai) m.addTileset(t) for sprts in lay3.spriteGfx.values(): m.addTileset(sprts) m.addLayer(la1) m.addLayer(la2) m.addLayer(la3) for f in lvl.__slots__: val = repr(getattr(lvl, f)) m.setProperty(f, b64encode(val)) return m @classmethod def write(cls, m, fn): out = PK2MAP() for f in m.properties().keys(): if not f.startswith('__'): setattr(out, f, b64decode(m.property(f))) #setattr(out, "sprites", ['pla']) with open(fn, 'wb') as fh: print >>fh, out.pack() for i in range(m.layerCount()): tiles = [] l = 0 if isTileLayerAt(m, i): l = tileLayerAt(m, i) print l elif isObjectGroupAt(m, i): #l = objectGroupAt(m, i) continue for y in range(l.height()): for x in range(l.width()): if l.cellAt(x, y).tile != None: tiles.append( l.cellAt(x, y).tile.id() ) print >>fh, 0,0, l.width(), l.height() print >>fh, bytearray(tiles) return True def find_case_insensitive_filename(path, fn): for f in os.listdir(path): if f.lower() == fn.lower(): return f class asciilongfile(cpystruct.CpyStruct("char filename[100]")): @classmethod def fromraw(cls, v): return re.search('[\w\.]*', v, re.U).group(0) def __repr__(self): return str(self) def __str__(self): return self.filename class asciifile(cpystruct.CpyStruct("char filename[13]")): @classmethod def fromraw(cls, v): return re.search('[\w\.]*', v, re.U).group(0) def __repr__(self): return str(self) def __str__(self): return self.filename class asciitxt(cpystruct.CpyStruct("char txt[40]")): @classmethod def fromraw(cls, v): return re.search('[\w\. ]', v, re.U).group(0) class asciinum(cpystruct.CpyStruct("char num[8]")): @classmethod def fromraw(cls, v): #v = ''.join(re.findall('[0-9]', v)) v = re.sub('[^0-9]','',v) return 0 if not v.strip().isdigit() else int(v) class PK2MAPLAYER(cpystruct.CpyStruct("asciinum lx, ly, w, h;")): MAXW = 256 MAXH = 224 MAXSZ = MAXW*MAXH def width(self): return self.w.num + 1 def height(self): return self.h.num + 1 def __init__(self, dat): # should make cpystruct support this usecase better super(self.__class__, self).__init__(dat) #print str(cpystruct.peek(dat, 128)) self.layer = bytearray(self.MAXSZ) for i in range(len(self.layer)): self.layer[i] = 0xff for y in range(self.ly.num, self.ly.num+self.height()): for x in range(self.lx.num, self.lx.num+self.width()): self.layer[x+y*self.MAXW] = dat.read(1) def findBounds(self): "find bounding box for coords that have tiles" mx,my,mw,mh = None,None,10,10 for y in range(self.ly, self.ly+self.height()): for x in range(self.lx, self.lx+self.width()): if self.layer[x + y * self.MAXW] != 255: if not my: my = y if not mx or x < mx: mx = x if x > mw: mw = x if y > mh: mh = y if not mx: mx = 0 if not my: my = 0 return mx, my, mw, mh def doSprites(self, la, bb): for y in range(self.height()): for x in range(self.width()): sprite = self.layer[self.lx.num + x + (self.ly.num + y) * self.MAXW] if sprite != 255: #if sprite > len(self.sprites): # print 'invalid spr',sprite # continue rx = self.lx.num + x - bb[0] ry = self.ly.num + y - bb[1] + 1 spr = self.sprites[sprite] obj = Tiled.MapObject(str(spr.kuvatiedosto), '', QPointF(rx, ry), QSizeF(1, 1)) #spr.width, spr.height)) # 0 should point to the actual sprite but how? obj.setCell(Tiled.Cell(self.spriteGfx[str(spr.kuvatiedosto)].tileAt(0))) la.addObject(obj) def doTiles(self, ts, la, bb): for y in range(self.height()): for x in range(self.width()): tile = self.layer[self.lx.num + x + (self.ly.num + y) * self.MAXW] if tile != 255: rx = self.lx.num + x - bb[0] ry = self.ly.num + y - bb[1] if tile == 149: print 'start @',rx,ry if tile == 150: print 'end @',rx,ry ti = ts.tileAt(tile) if ti != None and rx < bb[2] and ry < bb[3]: # app should check that coords are within layer #print rx,ry,self.ly,y la.setCell(rx, ry, Tiled.Cell(ti)) else: print 'invalid',rx,ry class PK2SPR_ANIM(cpystruct.CpyStruct(""" uchar seq[10]; uchar frames; bool loop; """)): def __repr__(self): return str(self) class PK2SPR(cpystruct.CpyStruct(""" asciinum tyyppi; asciilongfile kuvatiedosto; asciilongfile aanitiedostot[7]; int aanet[7]; uchar frameja; PK2SPR_ANIM animaatiot[20]; uchar animaatioita; uchar frame_rate; int kuva_x; int kuva_y; int kuva_frame_leveys; int kuva_frame_korkeus; int kuva_frame_vali; char nimi[30]; int width, height; double paino; bool vihollinen; int energia; int vahinko; uchar vahinko_tyyppi; uchar suojaus; int pisteet; int AI[10]; uchar max_hyppy; double max_nopeus; int latausaika; uchar vari; bool este; int tuhoutuminen; bool avain; bool tarisee; uchar bonusten_lkm; int hyokkays1_aika; int hyokkays2_aika; int pallarx_kerroin; char muutos_sprite[100]; char bonus_sprite[100]; char ammus1_sprite[100]; char ammus2_sprite[100]; bool tiletarkistus; DWORD aani_frq; bool random_frq; bool este_ylos; bool este_alas; bool este_oikealle; bool este_vasemmalle; uchar lapinakyvyys; bool hehkuu; int tulitauko; bool liitokyky; bool boss; bool bonus_aina; bool osaa_uida; """)): def __init__(self, f, m): with open(f, 'rb') as fh: super(self.__class__, self).__init__(fh) class PK2MAP(cpystruct.CpyStruct(""" char ver[4]; BYTE nan; asciifile tileFile, fieldFile, musicFile; asciitxt mapName, author; asciinum lvl, air, trig1, trig2, trig3; asciinum playTime, v1, background, plrSpr; asciinum lvlX, lvlY, icon; asciinum spriteCount; asciifile spriteFiles[spriteCount]; """)): pass tiled-1.0.3/src/plugins/python/scripts/zst.py000066400000000000000000000112101315121121300212470ustar00rootroot00000000000000""" Initial support for SNES emulator save states in Tiled 2012, Note: - assumes 8x8px tiles in 64x32 map of 4bpp gfx of max 7 palgroups - only supports bg1 of bgmode 1 http://snesemu.black-ship.net/misc/techdocs/snesdoc.html#GraphicsFormat """ import sys, re, string from tiled import * from tiled.qt import * from os.path import dirname from struct import pack,unpack,Struct from collections import namedtuple class ZST(Plugin): @classmethod def nameFilter(cls): return "zSNES Save State (*.zs?)" @classmethod def shortName(cls): return "zst" @classmethod def supportsFile(cls, f): return open(f).read(26) == 'ZSNES Save State File V0.6' @classmethod def read(cls, f): m = Tiled.Map(Tiled.Map.Orthogonal, 64,32, 8,8) # bg1-4 layer bpp counts bgmodes = ( (2, 4, 4, 8, 8, 4, 4, 0), (2, 4, 4, 4, 2, 2, 0, 0), (2, 2, 0, 0, 0, 0, 0, 0), (2, 0, 0, 0, 0, 0, 0, 0)) img = QImage(32*8, 32*8, QImage.Format_Indexed8) #img.fill(255) cmap = [] with open(f, 'rb') as fh: #fh.seek(0x66) #bgmode = unpack('B', fh.read(1))[0] #if bgmode != 7: raise Exception('only mode7 supported atm: '+str(bgmode)) # supporting new uncompressed save state formats should be just # a matter of adding correct addresses for these cgrambase = 0x618 tilemapbase = 0x20C13 # vram:0 tilebase = 0x2000 # vram offset fh.seek(cgrambase) cmap = list(parseColors(fh.read(0x200))) #img.setColorTable(cmap) colors = 16 tsets = [] for pal in range(7): img.setColorTable(cmap[pal*colors:pal*colors+colors]) fh.seek(tilemapbase+tilebase) readTileset(fh, img) tsets.append(Tiled.Tileset('Pal%i'%pal, 8,8, 0, 0)) tsets[pal].setTransparentColor(QColor(img.color(0))) tsets[pal].loadFromImage(img, 'script') la = Tiled.TileLayer('Back', 0,0, 64,32) fh.seek(tilemapbase) for y in range(la.height()): for x in range(32): t = parseTile(unpack('H', fh.read(2))[0]) try: tile = tsets[t.pal].tileAt(t.idx) pix = tile.image() tile.setImage(pix) """ overriding tile gfx could be an alternative to palgroup layers img = pix.toImage() img.setColorTable(cmap[t.pal*16:t.pal*16+16]) pix.convertFromImage(img) """ la.setCell(x, y, Tiled.Cell(tile)) except: print 'out of range %i,%i: %i' % (x,y,t.idx) if la.width() > 32: for y in range(la.height()): for x in range(32, la.width()): t = parseTile(unpack('H', fh.read(2))[0]) try: tile = tsets[t.pal].tileAt(t.idx) la.setCell(x, y, Tiled.Cell(tile)) except: print 'out of range %i,%i: %i' % (x,y,t.idx) for pal in range(7): m.addTileset(tsets[pal]) m.addLayer(la) return m def readTileset(dat, img, tvert=32, thoriz=32): tw, th = 8, 8 # iterate tiles for i in range(tvert*thoriz): tx,ty = i%tvert*tw, i/thoriz*th l1 = unpack('>16B', dat.read(16)) l2 = unpack('>16B', dat.read(16)) colordat = deplane4bpp([l1,l2]) # iterate lines in a tile for l in range(th): # ..pixels in a line for p in range(tw): c = colordat[l][p] img.setPixel(tx+p, ty+l, c) def deplane2bpp(src, dst): "takes 16 bytes, simplify" for i in range(8): b0 = src[i*2] b1 = src[i*2+1] if i <= len(dst): dst.append(bytearray(8)) dst[i][0] += (b0 >> 7) | b1 >> 6 & 2 dst[i][1] += (b0 >> 6 & 1) | b1 >> 5 & 2 dst[i][2] += (b0 >> 5 & 1) | b1 >> 4 & 2 dst[i][3] += (b0 >> 4 & 1) | b1 >> 3 & 2 dst[i][4] += (b0 >> 3 & 1) | b1 >> 2 & 2 dst[i][5] += (b0 >> 2 & 1) | b1 >> 1 & 2 dst[i][6] += (b0 >> 1 & 1) | b1 & 2 dst[i][7] += (b0 & 1) | b1 & 1 << 1 return dst #deplane2bpp( bytearray('3C3C4266 99 66 99 66 99 66 99 3C 42 00 3C 3C'.replace(' ','').decode('hex')) ) def deplane4bpp(src): "decode planar 4bpp line of 8px into packed color indexes" dst = deplane2bpp(src[1], list()) for i in range(len(dst)): for j in range(len(dst[i])): dst[i][j] <<= 2 return deplane2bpp(src[0], dst) def parseColors(cgram): for i in range(0, len(cgram), 2): col = unpack('H', cgram[i:i+2])[0] r = (col << 3) & 0xf8 g = ((col >> 5) << 3) & 0xf8 b = ((col >> 10) << 3) & 0xf8 #print (r,g,b), yield QColor(r,g,b).rgb() def parseTile(t): ret = namedtuple('Tile', 'idx pal prio flipx flipy') return ret(idx = t & 1023, pal = t >> 10 & 7, prio = t >> 13, flipx = t >> 14 != 0, flipy = t >> 15 != 0) tiled-1.0.3/src/plugins/python/tiledbinding.py000066400000000000000000000335041315121121300214060ustar00rootroot00000000000000""" Python Tiled Plugin Copyright 2012-2013, Samuli Tuomola This file is part of Tiled. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ from pybindgen import * mod = Module('tiled') mod.add_include('"pythonplugin.h"') mod.add_include('"map.h"') mod.add_include('"layer.h"') mod.add_include('"tile.h"') mod.add_include('"mapobject.h"') mod.add_include('"imagelayer.h"') mod.add_include('"tilelayer.h"') mod.add_include('"objectgroup.h"') mod.add_include('"tileset.h"') mod.header.writeln('#pragma GCC diagnostic ignored "-Wmissing-field-initializers"') # one day PyQt/PySide could be considered import qtbinding qtbinding.generate(mod) #mod.add_include('"qtbind.h"') tiled = mod.add_cpp_namespace('Tiled') cls_props = tiled.add_class('Properties') cls_props.add_method('keys', 'QList', []) #cls_propsc = tiled.add_container('QMap', ('QString','QString'), 'map', cls_props) cls_object = tiled.add_class('Object') cls_object.add_method('properties', retval('Tiled::Properties','p'), []) cls_object.add_method('propertyAsString', 'QString', [('QString','prop')]) cls_object.add_method('setProperty', None, [('QString','prop'),('QString','val')]) cls_tile = tiled.add_class('Tile', cls_object) cls_tile.add_method('id', 'int', []) cls_tile.add_method('image', retval('const QPixmap&'), []) cls_tile.add_method('setImage', None, [('const QPixmap&','image')]) cls_tile.add_method('width', 'int', []) cls_tile.add_method('height', 'int', []) #cls_tile.add_method('size', 'QSize', []) cls_sharedtileset = tiled.add_class('SharedTileset') cls_tileset = tiled.add_class('Tileset', cls_object) cls_tileset.add_method('create', 'Tiled::SharedTileset', [('QString','name'), ('int','tileWidth'), ('int','tileHeight'), ('int','tileSpacing'), ('int','margin')], is_static=True) cls_tileset.add_method('name', 'QString', []) cls_tileset.add_method('setName', None, [('QString','name')]) cls_tileset.add_method('fileName', 'QString', []) cls_tileset.add_method('setFileName', None, [('QString','name')]) cls_tileset.add_method('isExternal', 'bool', []) cls_tileset.add_method('tileWidth', 'int', []) cls_tileset.add_method('tileHeight', 'int', []) cls_tileset.add_method('tileSpacing', 'int', []) cls_tileset.add_method('margin', 'int', []) #cls_tileset.add_method('tileOffset', 'QPoint', []) cls_tileset.add_method('loadFromImage', 'bool', [('const QImage&','img'),('QString','file')]) cls_tileset.add_method('tileAt', retval('Tiled::Tile*',reference_existing_object=True), [('int','id')]) cls_tileset.add_method('tileCount', 'int', []) cls_tileset.add_method('columnCount', 'int', []) cls_tileset.add_method('imageWidth', 'int', []) cls_tileset.add_method('imageHeight', 'int', []) cls_tileset.add_method('setTransparentColor', None, [('QColor','col')]) cls_tileset.add_method('transparentColor', 'QColor', []) cls_tile.add_constructor([param('const QPixmap&','image'), param('int','id'), param('Tileset*','tileset',transfer_ownership=False)]) cls_tile.add_method('tileset', retval('Tiled::Tileset*',reference_existing_object=True), []) cls_layer = tiled.add_class('Layer', cls_object) #mod.add_container('QList', # retval('Tiled::Tileset*',caller_owns_return=False), 'list') cls_map = tiled.add_class('Map', cls_object) cls_map.add_enum('Orientation', ('Unknown','Orthogonal','Isometric')) cls_map.add_copy_constructor() cls_map.add_constructor([('Orientation','orient'), ('int','w'), ('int','h'), ('int','tileW'), ('int','tileH')]) cls_map.add_method('orientation', 'Orientation', []) cls_map.add_method('setOrientation', None, [('Orientation','o')]) cls_map.add_method('width', 'int', []) cls_map.add_method('setWidth', None, [('int','w')]) cls_map.add_method('height', 'int', []) cls_map.add_method('setHeight', None, [('int','h')]) cls_map.add_method('tileWidth', 'int', []) cls_map.add_method('tileHeight', 'int', []) cls_map.add_method('layerCount', 'int', []) cls_map.add_method('tileLayerCount', 'int', []) cls_map.add_method('objectGroupCount', 'int', []) cls_map.add_method('addTileset', None, [param('SharedTileset','tileset')]) cls_map.add_method('insertTileset', None, [('int','pos'),param('SharedTileset','tileset')]) cls_map.add_method('indexOfTileset', 'int', [param('const SharedTileset &','tileset')]) cls_map.add_method('removeTilesetAt', None, [('int','pos')]) cls_map.add_method('replaceTileset', None, [param('SharedTileset','oldTileset'), param('SharedTileset','newTileset')]) cls_map.add_method('tilesetAt', retval('Tiled::SharedTileset'), [('int','idx')]) cls_map.add_method('tilesetCount', 'int', []) cls_map.add_method('isTilesetUsed', 'bool', [param('const Tileset*','tileset')]) cls_cell = tiled.add_class('Cell') cls_cell.add_constructor([param('Tiled::Tile*','tile', transfer_ownership=False)]) cls_cell.add_method('isEmpty', 'bool', []) cls_cell.add_method('tile', retval('Tiled::Tile*',reference_existing_object=True), []) cls_tilelayer = tiled.add_class('TileLayer', cls_layer) cls_tilelayer.add_constructor([('QString','name'), ('int','x'), ('int','y'), ('int','w'), ('int','h')]) cls_tilelayer.add_method('width', 'int', []) cls_tilelayer.add_method('height', 'int', []) cls_tilelayer.add_method('cellAt', retval('Tiled::Cell'), [('int','x'),('int','y')]) cls_tilelayer.add_method('setCell', None, [('int','x'),('int','y'), ('Cell','c')]) cls_tilelayer.add_method('referencesTileset', 'bool', [param('Tileset*','ts',transfer_ownership=False)]) cls_tilelayer.add_method('isEmpty', 'bool', []) cls_imagelayer = tiled.add_class('ImageLayer', cls_layer) cls_imagelayer.add_constructor([('QString','name'), ('int','x'), ('int','y')]) cls_imagelayer.add_method('loadFromImage', 'bool', [('const QImage&','img'),('QString','file')]) cls_imagelayer.add_method('image', retval('const QPixmap&'), []) cls_imagelayer.add_method('setImage', None, [('const QPixmap&','image')]) cls_mapobject = tiled.add_class('MapObject', cls_object) cls_mapobject.add_constructor([]) cls_mapobject.add_constructor([('QString','name'), ('QString','type'), ('QPointF','pos'), ('QSizeF','size') ]) cls_mapobject.add_enum('Shape', ('Rectangle','Polygon','Polyline')) cls_mapobject.add_method('setPosition', None, [('QPointF','pos')]) cls_mapobject.add_method('x', 'float', []) cls_mapobject.add_method('setX', None, [('float','x')]) cls_mapobject.add_method('y', 'float', []) cls_mapobject.add_method('setY', None, [('float','y')]) cls_mapobject.add_method('setSize', None, [param('QSizeF','size')]) cls_mapobject.add_method('width', 'float', []) cls_mapobject.add_method('setWidth', None, [('float','w')]) cls_mapobject.add_method('height', 'float', []) cls_mapobject.add_method('setHeight', None, [('float','h')]) #cls_mapobject.add_method('setPolygon', None, [param('QPolygonF','pol')]) #cls_mapobject.add_method('polygon', 'QPolygonF', []) cls_mapobject.add_method('setShape', None, [param('Shape','s')]) cls_mapobject.add_method('shape', 'Shape', []) #cls_mapobject.add_method('bounds', 'QRectF', []) cls_mapobject.add_method('setCell', None, [param('const Tiled::Cell','c',)]) cls_mapobject.add_method('cell', retval('const Tiled::Cell'), []) #cls_mapobject.add_method('setObjectGroup', 'ObjectGroup*', []) #cls_mapobject.add_method('objectGroup', 'ObjectGroup*', []) cls_mapobject.add_method('rotation', 'float', []) cls_mapobject.add_method('setRotation', None, [('float','r')]) cls_mapobject.add_method('isVisible', 'bool', []) cls_mapobject.add_method('setVisible', None, [('bool','v')]) cls_mapobject.add_method('name', 'QString', []) cls_mapobject.add_method('setName', None, [('QString','n')]) cls_mapobject.add_method('type', 'QString', []) cls_mapobject.add_method('setType', None, [('QString','n')]) cls_objectgroup = tiled.add_class('ObjectGroup', cls_layer) cls_objectgroup.add_constructor([('QString','name'), ('int','x'), ('int','y')]) cls_objectgroup.add_method('addObject', None, [param('MapObject*','object',transfer_ownership=True)]) cls_objectgroup.add_method('insertObject', None, [('int','idx'),param('MapObject*','object',transfer_ownership=False)]) cls_objectgroup.add_method('removeObject', 'int', [param('MapObject*','object',transfer_ownership=False)]) #cls_tilelayer.add_method('cellAt', retval('Tiled::Cell'), # [('int','x'),('int','y')]) cls_objectgroup.add_method('objectAt', retval('Tiled::MapObject*',reference_existing_object=True),[('int','index')]) cls_objectgroup.add_method('objectCount', 'int',[]) #cls_objectgroup.add_method('objectsBoundingRect', 'QRectF', []) #cls_objectgroup.add_method('usedTilesets', 'QSet', []) cls_objectgroup.add_method('referencesTileset', 'bool', [param('Tileset*','ts',transfer_ownership=False)]) #MapObject *objectAt(int index) cls_map.add_method('addLayer', None, [param('ImageLayer*','l',transfer_ownership=True)]) cls_map.add_method('addLayer', None, [param('TileLayer*','l',transfer_ownership=True)]) cls_map.add_method('addLayer', None, [param('ObjectGroup*','l',transfer_ownership=True)]) cls_map.add_method('layerAt', retval('Tiled::Layer*',reference_existing_object=True), [('int','idx')]) cls_layer.add_method('name', 'QString', []) cls_layer.add_method('setName', None, [('QString','name')]) cls_layer.add_method('opacity', 'float', []) cls_layer.add_method('setOpacity', None, [('float','opacity')]) cls_layer.add_method('isVisible', 'bool', []) cls_layer.add_method('setVisible', None, [('bool','visible')]) cls_layer.add_method('map', retval('Tiled::Map*',reference_existing_object=True), []) cls_layer.add_method('x', 'int', []) cls_layer.add_method('setX', None, [('int','x')]) cls_layer.add_method('y', 'int', []) cls_layer.add_method('setY', None, [('int','y')]) cls_layer.add_method('setPosition', None, [('int','x'),('int','y')]) cls_layer.add_method('asTileLayer', retval('Tiled::TileLayer*',reference_existing_object=True), [], is_virtual=True) cls_layer.add_method('asObjectGroup', retval('Tiled::ObjectGroup*',reference_existing_object=True), [], is_virtual=True) mod.body.writeln(""" bool isImageLayerAt(Tiled::Map *map, int idx) { return (dynamic_cast(map->layerAt(idx)) != 0); } bool isTileLayerAt(Tiled::Map *map, int idx) { return (dynamic_cast(map->layerAt(idx)) != 0); } bool isObjectGroupAt(Tiled::Map *map, int idx) { return (dynamic_cast(map->layerAt(idx)) != 0); } Tiled::ImageLayer* imageLayerAt(Tiled::Map *map, int idx) { return static_cast(map->layerAt(idx)); } Tiled::TileLayer* tileLayerAt(Tiled::Map *map, int idx) { return static_cast(map->layerAt(idx)); } Tiled::ObjectGroup* objectGroupAt(Tiled::Map *map, int idx) { return static_cast(map->layerAt(idx)); } """) mod.add_function('isTileLayerAt', 'bool', [param('Tiled::Map*','map',transfer_ownership=False),('int','idx')]) mod.add_function('isObjectGroupAt', 'bool', [param('Tiled::Map*','map',transfer_ownership=False),('int','idx')]) mod.add_function('tileLayerAt', retval('Tiled::TileLayer*',reference_existing_object=True), [param('Tiled::Map*','map',transfer_ownership=False),('int','idx')]) mod.add_function('objectGroupAt', retval('Tiled::ObjectGroup*',reference_existing_object=True), [param('Tiled::Map*','map',transfer_ownership=False),('int','idx')]) mod.add_function('loadTilesetFromFile', 'bool', [param('Tileset*','ts',transfer_ownership=False),('QString','file')]) mod.body.writeln(""" bool loadTilesetFromFile(Tiled::Tileset *ts, QString file) { QImage img(file); return ts->loadFromImage(img, file); } """) """ C++ class PythonScript is seen as Tiled.Plugin from Python script (naming describes the opposite side from either perspective) """ cls_pp = mod.add_class('PythonScript', allow_subclassing=True, foreign_cpp_namespace='Python', custom_name='Plugin') """ PythonPlugin implements LoggingInterface for messaging to Tiled """ cls_logi = tiled.add_class('LoggingInterface', destructor_visibility='private') cls_logi.add_enum('OutputType', ('INFO','ERROR')) cls_logi.add_method('log', 'void', [('OutputType','type'),('const QString','msg')], is_virtual=True) with open('pythonbind.cpp','w') as fh: import pybindgen.typehandlers.codesink as cs sink = cs.MemoryCodeSink() print >>fh, """ #ifdef __MINGW32__ #include // included before Python.h to fix ::hypot not declared issue #endif """ mod.generate(fh) print >>fh, """ PyObject* _wrap_convert_c2py__Tiled__LoggingInterface(Tiled::LoggingInterface *cvalue) { PyObject *py_retval; PyTiledLoggingInterface *py_LoggingInterface; py_LoggingInterface = PyObject_New(PyTiledLoggingInterface, &PyTiledLoggingInterface_Type); py_LoggingInterface->flags = PYBINDGEN_WRAPPER_FLAG_NONE; py_LoggingInterface->obj = cvalue; py_retval = Py_BuildValue((char *) "N", py_LoggingInterface); return py_retval; } """ #mod.generate_c_to_python_type_converter( # utils.eval_retval(retval("Tiled::LoggingInterface")), # sink) mod.generate_python_to_c_type_converter( utils.eval_retval(retval('Tiled::Map*',caller_owns_return=True)), sink) mod.generate_c_to_python_type_converter( utils.eval_retval("const Tiled::Map"), sink) print >>fh, sink.flush() # vim: ai ts=4 sts=4 et sw=4 ft=python tiled-1.0.3/src/plugins/replicaisland/000077500000000000000000000000001315121121300176645ustar00rootroot00000000000000tiled-1.0.3/src/plugins/replicaisland/MAKING_TILESETS_FOR_OBJECTS.txt000066400000000000000000000024071315121121300245710ustar00rootroot00000000000000Replica Island has variably-sized objects, stored as individual images (and sequences of images for frames). But we need to represent our objects as a single tiled image. If you have a bunch of object images of various sizes, and you want to make a tiled image, you place one image of each object in a directory, numbering them sequentially and putting in transparent placeholders for unused object IDs: 00_player.png 01_coin.png 02_ruby.png 03_diary.png 04_trans.png You can then convert these images into a tile image using the 'convert' and 'montage' commands from ImageMagick: # Trim transparent borders off of images. This is necessary to make # nice tiles out of characters who are 1.5 tiles high with a 2-tile high # image. mkdir trimmed for F in *.png; do convert $F -bordercolor none -border 1x1 -trim +repage trimmed/$F done cd trimmed # Shrink images larger than 32x32. mkdir shrunk for F in *.png; do convert $F -resize '32x32>' shrunk/$F done cd shrunk # Center images on 32x32 tiles. mkdir fitted for F in *.png; do convert $F -background none -gravity center -extent 32x32 fitted/$F done cd fitted # Assemble tiles into a single image. montage *.png -tile 7x -geometry +0+0 -background none objects.png tiled-1.0.3/src/plugins/replicaisland/cave.png000066400000000000000000002522741315121121300213240ustar00rootroot00000000000000PNG  IHDRŐgtEXtSoftwareAdobe ImageReadyqe<T^IDATxk\Օ[qܙ3j=Cݶ~*CK EƖx/A!! =) $^ѸʒR!Y,ƌ=37b?̇?tܘ1qs'W:''OVReĎs{}ز/lq>ڿ>w ?Goh?{}]?tM[7wO]/yy[yb{{}g"]׳~g|XskY:~C#Eߜ\s+؏_o]:zYсۿǓ/7X{jLߞKĺK}_^џ^/m8;v]ۇWzkߗn_1Í_\fڦtۃO}{ }=#|~mS<_CM_Nǁo?k-|.lu':{~x>gn9:|im sW֯$_|@?yi`yzڴ_mgs W7~={w_^k׬u}Nq KU8o֘h& %"zaʳ򽘇bPܓ!x{0X ڑ6|aQx \d(ڿNyF +ߘk|پχ 쳩mt /L7/ |<,FBXu_!}-=tO>Z<; `,ƫS4xn'=T_DƭbA s-o^3nVA5x\YmEg{A0~H/{Ksh BidQr(wYz/L;b޳Cc&x?מQ7|'&o\MJ `gnyi~|CgI9͎]7>[ 8e3-X Zge€>1wg@_r^O:P&}'ƒ3`! }~XBijk~!?e?olAg?ǿ7@/ǿel5vr >7Qw ᦝ>硸7 }$٥Y=M:d8P/F9G?l43?}&a-oΘU8KL"`nhZ~'.YeCgEBQX:_97SEǞF@e_b?طxAK>Ul:d(c߸u>Ot֨] _Rk6 +o?=n9g<{SǮ?#鍧EnY=y[ϭyRkƼK &:0(96>H<1أkݚ&s64Q:\.KvqGoA?Vk& sKnzE4ebpYl8q';#t|(hA Sv鳘@.N}dD?:b3)젘G=Q6i8K>C+ᵢKRh-)D=!U[urs&ޝ^観Cyv^NX]Ӷ F (04:!p d{rz(Qȇcހ>!a.EZ\dn"dgvB-$ j`,V".z=4Af< L,ILa~g @֪NEg<$>sp83>;-'Yxf,1ǥcOu\ϵB6_ P]UcN58ew(~Prk%Eқ?]3Q*Y4tgc_]/n>ŻR|`XKv~jw ߔy!8Q\W$X"^&sNg($M n0` >>4Q @AQ"R;ev\ (kѦW/0n0XB|_ro20(qhJ{M@mw\مeGo6caK τ0T O e`s)`zvEZoriՏA?>?Px_a>gr$„YL"Сh ;p9$s0 T c,Zh~7 \߇;.}e d^-3(!DI-~[E `,a@X[#/F?YП]pvvzX`x=F/,:ќg@тg xlV+$;.wcIk"_gl|ڟgG׬+CtU.t]t_FW /-o]l5jK ҈ϊ+p#e@FY= D5 J}XG} nGgH z5.@IU b:_hkg+JPd6$əFl^7Da^fT 0v|:wMiNH @A ;~#7_xv4|GcTI02W( ~?>}gsxѳmM.[0Ӣe?]q_G߹/o\97>?@/?0c3IC;@);KImPp|3*u;Ifv]}b%KjBt/$ *I@^6ߚh}04[Q a̰W\2/U~)+}uO\Ed;s$B>N@$}_͗}ѓk myaZEqi^lԈ `lxֿi5_nfgDw,n*gDn\hՖEё+<|I)tl:!nPkiw7Mf w~ls!- 1Owq/ȥ?gb4:ᙵmsqYVؚ5x6?/|C(@^-@*}ns:G/'8daw?;2ߟ90VYXhho> Z9mxeM 0;^ DoGmD[6}%:[ODGw.Na`ΓWz}amw`vYNT8mW!Ztɲ;HяC*sgCºUrafUaB w%siN|2 !P)L*+&v4wse3q{5.ዂCneX(f@5qѭ)ߧ&P< R^D)BXʾils`744}& Mww}1iύ&v^=#[.zmsg&:}wDO^m#PPܬIW lf6i-m|+YN?qfg1n0ɾtFq%{gL xmX_p3!&jI{5{ ѺUf-'U L@'NRr/A&OS. VR#> kDu6rh|עWSܳu_^|{і~;:g-^o.^Peq5ڙ2 B< ' P;Tf7q鬭Ƶ/^ $ptsM2Qe? ǟ=uI0@NݿY,ⅳ,cU h~f?7bvj;^nzw5aW|lP `(;*^oRl[K 1LY"q4P ѾD~jtrkB?']ߦBx=ҋt-Lυo&y3uW]*jݻRe7Y<{cMr 媟w[`O"kΈrϊ.?}νOs\{'Dmw,\- 2C21S(wzt;e4S&VjS6H$g)[EB}k3P32{  W3NE_o`ܓq܈}hhet!}5qJkA͈3_p^n7%2P*:(8e<4#3Ղ|yŠ֒I- ÿG^|=,1'̵_)6"_Z,H Diҷ _N8hz/|1܎uo;&a?ڿaA'u81xgeE4xŧo\s3o?qE85M?c8q9W!1PɦKf<M= rj|}4YH0G=SޱyFX~{|$gKGzWrͪ2 U66=?jYbr?gLZ4` @`J#WJ]*†Eil@YdqÖ1Ϳ̒ ̶R%ۘQT#_5qƳ?s×Ʊ8Tl$gd|6N"m]ɫ٩%&0L+uk}DA- ߁5kb,32" M7?(pSA˦A:GUpN{.}&';cREhr;aSݖ? 1ťw`QoYѝ,hƓew'E>=6f|2z'27I{$ʗX.\$0/7f+eo%b'KUHF׀ &}܍01xLgl8F' ߆y>GNV*kR Β55fWy.2Y[pͫBc/s%[(z <@9WM 2 {сۿ:d1_a@ HmlÄI򻑜P d:KnX<PT0hE~ztMno[ןX.ыe!s9OV8a^u`<Qޜs6!^t&0 MH_#B \84p9Ϳ=\+fkQ~]!Yv;.?yp^w+TߚAC0לT*|(o\~bP]yo_X鲓bVdNI;`{{89hͧ}/zqE73sL9qFe~*^W P_@P>O*S}F ]yZf9&" e"S' J_1*&_BQgP3s̒a\Yg-8CSRN΄~gȅa\f,FY_H Fm?a]4@@qv/;9r&~O~~פȎon}@7r|hG:kweAnxlNϮψ~o{;)zphFOlFt`ѳP9[*ic8dž{qiL /9,7vZ=7FfΎy`E\b%_} vy߈>m4mDM}Es#I!?i6ӔlHN>("Khh3sӜ2!м.T^k[%޵Sg Q x4?'+M8!w2/JLctSpf??'`@jV/Щvewn<<=q>s99Il%ZqW9׏$i]U:P6ys睳5R֡Iǃ|EߗBLXvǨyENxnyچP!U@pmKv$"sU1b k@8lZ˴Hݭ+eU uv݋|(B; 9!YB9Q@=\$ܺ'͕_ea箕n7!z~W[ASe?~)Yv[8#Ta JelhMf}ŕ ˵L!s0ЧMʼn_C[ބ_>QB\O^9ې>; l3V?d21?:(yuܻזF4?>ݬ.aP!޴QZ(a9%'uT` W~7s_ (Pr%mP S$Ӓ&#d@^TEVLJd9R){O-鐡zgp0$Mf%շ-9'p?N„{àoΟ(ͷ"3 {n'?.޽~uS9a37!)+o CKOEs5lk$0DʇaL  csl_؏\%jBʈ@%s(-sJfHSIUKKm`VX}-4uF`lB1gwv0ͣYal܋ K/? 9ؗSn짳_+©0f@` K nҍ|v +Py/ XF"?.ׇN):Hȓ\UX90swsaP` (iS H+u@TK.PA D1D+ul팢e36;@mik a/ZBQd"}d~AWmB\>k6}"UY-[Bl%2 \7a)%@77柴-Oͷ4j b}UL낆aUY56ywX]3Đ?UmSB8t^F|7 jح-_-kZ9c9Ӫ6 kRYP2BIx $a{z: :f¤DlKfT<&QKH%liJB*?+rKr ͢u TQJz**Yk\gg꯫jd*I32gfcYC'x{/N'a@e-9q;>ccs@9Po`\d(`fڊ+{Pe˃$*L qZ"*2^&cߋ~wmڵ@?TjwѿܯL*kije^Xvv\Cs8)|n:dd$Vm>pOɕF0ĀNeFD&<֐ [Zx 3Ϥ`O-' ,"3+ %+G{h'!}@+(Kjuov)':FZK`?ӣߏc9lK)mYf_}gVqiq%eϙx>Mѳj_ @! _ێp;WgK~Kٸ4ZO}z LAasX 5%sIe.O88ZH2nYICx)tbSVf;&C/=?E t~mqx2i}(=c4p8@vr.a3i4*v15MU_&'!M)OϠRzެxrd3[ 7!~Ed]oLE9fǎEw=h^7=Jkk_FR?)?ẑje'yP4۟0Xa_⹧l;o >- NfٌƍQJ0 TN$lX)΂EPΏsU0LB"bK_ls4㡁Y惝 MCX6Uq|-T3؇>ó$XE؅ȣ[4REh #le}s}[rf}z& @AΏ G76LHπIXVDHq"b;{eՖѕEt¿i`tCuYv/WoV\tOE(JbÕNߗ8$]GۢNT$9 sV<3GRE^7|>_c@_ίf@x3PH1]!W٭dJ Ȍ#8=Jx0 ECxc€0ҀZAnB&Tx;'-Bݗ<˕ 0+3)W}V)) ]e=ctW ʑ%ȡ'IK]d,kf':V*rO!bwrk`Ḿw ,e<AǸ0a(dx΁0xSzXAnN.}Y8_hckO/Wcxhq]6c2zb]QDHDI?p|Ӯٺ/Z=-h F+wQC7!8(4Zc %[. Ozki]E*R?+=O\d޴| kF""A+ɪWl3d*|K*K Qf#5YY% dKuR-qi(*G9 TKrSL&zRjI[8؊}R@F@ $E~PB;xz݄BA51 bt8cM\/LR8FsTͪ/Y4%WnQ\CѵɊܑe kvq IՈ(k,rtˢϼw[߭)vVW "oDk?r,vh#K p-tZMywsȲWO*djĖZ"eBɆB8q%Za(F#P贫Q(^=2G`u 8vE~Ug4[ dԲ*x;*lR6!v ܸMM7^#KCo|9v(8ݰ}Y@5 9*dsk#qm #f_yUq U P29zzB%?I2 GG8uO,Lót @lK EVBG+I ~(r0|Ћ:?9wr@XL(!}~$ qjYе,<1<0Q̦B |&,%6hx$dD ŸNfm=Odd{1?o>?_aK)9`Bȸ'G2(ʬF1@g ^J2z[Tg4ub|q* sYdYn,^E ίEK؁zpŽ?Y ⎧_+#9BA_wiM,ˁ+K:Y[U~F4adj)+0?Hbk1z|sBI#>VB\q|]̖v'߫!aTЧ@*їCއ&2;ϩ]\C_1 .:gPSGP"RRaS xz$Qd??:Bi# `I Fٚc@Qy"y~='I?-Qm.j-aljǻ0kj:8~L/SG.ky^&Tůn~Jf0遭5Á ,1vΕ2u7?)JP[;&pf)AaѮE;B~eN@Hx"=xg)~>((@xOs%_e`]),5\J?2)Zҫ^أa95$R`=R3['Uw0/qsT/M̳Z؛;-SKA@ V [Rb!Y7~y B{X+@߅o5{m 㭘1ЊgW\?OTP«ʌP/좼hEʶ__@Yl[5 /GK+ZMW脾Smt߳k:*tޣ-(#QYeO)zEٱTj6K d=y$klxxW\gYϬr,V)EB´j,?Y-OyfpoC$<1gѷiYÝ ( NvA|i@ Hw:wbje W!gPh{ -usIY?D33?/7E;o4cBŃcplH&@bhWHZ\LP_aǽ{1 LPA<evV_NaOGtq'zYg1ep.`׮]՛njժl)}K3f(5Zvce7Q>qn'r_ڄY\{)X@z_ׇݜkPt֚O%\uיE" -_RQ1~i}¤Tؚsb3vE_׈։-/; ng{g3['p \ g,Y#d.OR|oe?c 2ॷK4wzqX Bd@ZP̰$i3S x[ߦz[peZNHldT) ޽;իWG&JycU$O/#+kŽN l^``QWqR*67ݷȜtJ\l/+3j0 d@%n;[U LVXrYeΧY&J1@xƭE-4<VD(2MaRNIŠuOD63~Tv c}R4MʮDS3W՝f87eIWK?gl4w0 :hL8VhLlYˠd±zvvOp@Y ׅ`xC ( $}bzaI(BK o.F4T5Qg'}(sp;WdMYA%]JH1*{ !+ |E٫-ub)8 ZEʌ,tHkkT[24(f^eڊM82e5x݆SESovjcS/oaR񟄶M;xsiv3q] =_2hærV&6-c,!GxWTahn: /~ORD}R$5UDV}?ifiZS7B]鼭Q8ɧl_WA٣M'4^dm< ZK(I# Tζݙ2yh/Nu6e `-5բy[/-Ad7&(g_R@4?hbeϫ=Я]͵/'"&X77#5$USOI݅U/c^aXs; D(%U'J$T,3/9/'F#fG !d||k{j~?a`Re#Qb@/sH`.r1x{T>? p.,0nR k.ƒBV\̜YQ5g0[>f ZfB23oAj&}[ŸJ)؇JXi ѹCmfM !s Lhl>s~XUCA P:T|49zQ wϳ5JM*E>@Yv^0S8a0OU> ϵ2C2/\'5,d2SWM2$z?Q?xFjJz. 970&Pcܐk4R.p.s pU0GMȿǜZ ߫O; WPPyNUdwJx{zIQ5 @YJD2볖%m2J3CLj64[y D RKSS<UBbTS5%\Q<[ = ȶ_B2rv*EM*)el:򬊻_MXGBIa(,b y3gi_%3A LŠ4R8"RlIa/GQ!{$ױMwi!Zl>˫G:aJR$>j80^+p!"7ʠ/ſG{ߨS輷~|}~ Phv P( P9<yC3ZSھt=WRP`mMjZРvLx7?LxX㷱-?pSq :k(:oCZء` 4> mxj۳vs ! @ga6='toϛQsg[[K_G F)K'9 9H_hi38ly)*`"`Q&vJl@Tu^P)\?a52KeÔ~ЏvE"1_2~_5ekƚ9]sW$1E6tF?⶞{Syɉ5M5ܣLN;( d^Y@Zvm _m4\WF:LO+u-(]ݼJsKbx <" h(;z֑c^6<(o?,:')oX* mݿ] N8 l}"`j ۳p ];FvwX XQErkgWزP -K,p@۰ +,f%u:gTɢ@6M'7r 0x-˺4Iu'gm<`>p1W7قfET?)jy8-OVf)A=F=6ņ K( E3w)9ي٤Vz o]'X/lR@n=ALU#cYRT~@IMzhDc p^V mY&[v^Vd%a/N[~μɭO~YYud b4a<=&dX+:12/<6 ib7 a0YeQP2˖@f p ֍se*ܥ20}{]؝e@U@:Mj'^f $ :Z!ܩB?b+E P $݋9՚1PN@<,бB䤗@4B::cX*`₻M(9(dS)}@xv`%_wDE2:({EYC`xF~+,e7_4b[1r+wu"'z1jِkn$|ITF{ig'|J"qn 'Rgqrڲ^u4@%h̫2eY̫s^<Yٴ!EF"F?Xy=di <bkK` 僕B^:>,3 jg\;}^󿼰B+0Ro@ׄj(\]@_d(kP~?JD8 Bt rkhJ0?J\hY5qVɒDFRcuA#G+7K(1: 1GùY X7n0DN a*+upWQKy8O1p %d/kH(DL̨M/Lxn͸a2axGя00͢3Ph ݗ۹VJ^]0ԏކ/y{ iuGU'1˂\Y_MUT^Eˤ>J<_H cGYpkay' ZMa ~-1@( 웅 (}*^^8KhNut{dQ?v7- "QKV7-@~g,ɮ|]P<胀t6o&U\26"qЧLR@`6'TH:drO"ې.< P@ !k>&ܷ`[roweqs1X%['@*O;5xV 㨥0L@6QE@(U{8QR$!8u?ڐ"[ɯ\ M?Ddᑤ&:8n^y}R FKIy-/܀ 'a $$j2ۅg"x`@$' P#—NUbZr# >5sj ?#DKNyJbCeJϸMoW5R<'@&S3g܋gPԆvv% B<*l3=t oE5qbS"`)iЂL {' ]jY` HXT&})2>}ާ^yاK e+pX+BgEav́_gci͖R? "! ⷵ_&r^J3[/v_QMYQ}}Qʟҷɬveoϙ0rw KPn~'@rql-QFVH("NZ 3bHQ(h" 6V-B hW$.@I)Y]yt<`#ؕqOnN#(dɩFsY&Fz+>2I!nWa0“ 9b|`Vhl8#-xLt}ǵ3V %*Wd4e: NK;-Z|ar~ 8Y-@H[߀9ka~L+yl"^D)ZP̱$BE[3YkwEP&}f}1xv(ζxOumiwYpK%n-]4d< Kd%, L@z ;;- vYpSyus(%-  ǻxG>fb1a|J[;vec9!m^D  }d$mjgbGܱũr5ߛߓzۓBIN?,|q{% >%`}Cci2i pR|j~`|`*b gmAݲ|P@iVw_sz jn]QyQת;_EeҗkWu $~AN>kX@ohʺH;n+l6tux\d#* 3IЄo%ӧ2 P:{tb=uVP a[Rٖ>H83b,63ҵYR zN ˣޗW!PB"*g͜#Z}iRߔ(:^xS|N&ST]_KG/sb@?{ݨ7WNL*iL$7FMaYŜƵg~>x\[T07Lie=$:HS.qaff$ 0혅mrr+;/z6 ,[6?س9vRܟqRJáocɯV1?9:DȷG:LJ}Z֚o t N]+@&k_u4S{p;֒vlS: {~1?_{坥NR]eot;.I~s? 8 }8zwLj6#HX*jk۝̙|.-Լ8i=MVQO1rHVR7>Vm9`ק٠oh2MjU<`7VfO;?k5 !MT ?ㄈ?ϽspȄ…9ȵDUAkKQtBfv"sRcgw/ᆟ@wAκ}X/\GA~tq2mKꈇ 88d[#:]j;urJv=]p,Hx z@}- 4^ypCy ğ#]R兛Uf"*vi'˵)k&V=$ұoYe_Ef/Kwtm Gt'Y/Sb퀕G!w$"c{@ch `–;@& 2#PbCĔd-$t!0SiY/d7UC^%$;H%,q%fwB Ї&BSCzU2#5XVQY95Ϣ=hvI_C{]~+/s);*ׄNIowd(9vrzY{osp&DHɠtdW1#DOƕVN@}Odgl&ů46?:`pFE7=Q(yBſ}ƵWN?4zzWo{G}4ڶmxif7U<ƴgzB 3e$ >0*?~ Y,p+arg)@ /_S#QP+gIEZI\339cvJ`@C<6BOXy +2%gƾ?Rі ,}xCzl_hUff;ogM1H8LuAVA{)DR"%)EgeοB0cP*u:JEϨ#@[Ӊ{ MQtU3+ xx&Y%eٽ+uEٝ[`w:-,ꬳK/ʙv: m`*XX-zWf-_J\ω7mNKG\W*d&? aZ<,4qzm)2e0釣˂T7˔VH&`IO_=p}tX+.JZT&9 e,Ч<;'E-@gj񣼱pZ(~oI/;]G< x^{HvwO_tE :8([)vYy<媰gj炕LrQVKKUBy@Ty*0RU9^a>9&J=P^| UswlAزAYu:_>s,P O[>jJ_ ]s P<uRp`r|bKW[`C;8ߵ p7:_s(,"lYNukj=zt8wuWtWwt/k@_ ,DU^v;P yCL2sO v\68~Ӹ?Z!L6%ma`>дgEƿ#$GXw2(U@a6&N* I{@AgR蚧:SSWAYG׺EdG(OP}tP Vtz@peϚଢ଼+?.lէ6n8]!P[9xfM2*:d@NŬve3 &۬8eGgRǬ8w{{WQcvYgRri. Iltg,;[Ӻ6Y+ #<@,6^`!wa >GQ6ҷbۿZX\J_(fyEQ9?ϵd5| w[6M{>qɓ`;.,٩D@,>д#Lfl̔={ЩUȘkðixQ~i"fuɗDMAYBB?pE?K[[W"_P 8>dƿٌ'G;?ܾ:?cyߔ6́ryd90IHŦ._ϯͿ"|E? uQ mG)@:8qS/{+@;pɭOD_kn LZJQ;`hh̛,[Ȏ @!Y{QF3ںJ۩ 6?*$Ⅱ -ү+>ğ3%صS}v+<*\ggpB7vs߈; ǿ%>MNXLc<-%Jοe eUsԁ?MMf bJjʁ5 01تG(_Q/ܻHƐUe[O{u'?<ӗw?oP+e)e7΅߾|}|?Hƕ]c4ߓ.ϿXδ DLB 'T'ߴp ̏b|a;U&Wi ,X6 hɵʱW'Vm$qV1ċҷ){9Z3vƿSW-L`# B I_m=E?b;grX`sv}hP!ԊiO,p'?iz7>R P?5 򾛍(7#\f~jwY?O;/ǭ,3 *zRS8v=,9(xl{,}iFL ]-5^TBg@ UY4q@b0{Z 2bQXYʨp%sb`kY'k O,ei$2c1KG;*4\ }@Yl$h (H!}g;j(W{GfH4y ѲOYffy9ۢ|(齔rvE:ʒL89PbD,%* ADI!ͣoc#܃khtOgV ?ΌX?K(p< LJQGoOPXTY-3(nQЎ?`?!rl=YzC>ʏ39eaSxG5%T^W~ 6lgc-,"w߷ BRz}6t`уc|d!$yL8 1ol __-Z|e[p7y0@0"dP";,?*G(5'Rvk#~rĜTIfjc|Q2Ya|{*w,~VX|C8%y=op}LsW1Z`3ʼn߰S{P e%'z΁YYGEY@s[.3XG}.,<"',@gXʑ2RE(Ƒ? mkBR$G_kN;|>` =k"X9>:KbuAϧMUក$Lj R `Cz$g/EnKt[ _/kTl%n;Jd[g!}Q_ѧON;~;Rmʌ\%ϵO`w n?αeJJ^wRcƯ`"_}"|h49 r톔)̆;Pڐ*y,%ʑ^(4~kݛ3°4Bπ*}lH7 <( y _K$7TE?wiO^RW{JJ?[g+ݰGVaYA e}ھ+PS+4|*re*L3Ϡ@}6ؑpA>χKH_:~6_~UHU P=1-c[g! ߁`ս'8uU%Q4ˡ*au^C8M~{,V"6 F}e @s[G}Hm|Xo^UQRVa=m ,v"L}8}.l~CU#&*@YˤyޑF p<*;vbijC;^tHYO?7L@(qLϦߓOFZ94^9(K :T'_ѷU}#?xlwP{o~}ѩ"@/>"@>m([6v@BA?@0SN֮'tR CO;y>vo/$7\ҙR g`'keʳ;V^$)2_E/';E7hGH“s Y{ar^dO^Z,<#k*<Gt}#(և8dB ڀ3f(O? ?L$k$+ ;|+@΃n Z\/PןE)7&w9)vvCfR"U^5o|pq\PJ#y`JH*W#oCswh64Gh7L$Losa,:;"hv΄U⢘m"k7y^QKPQ\Æw-dkkHBҗZ艿s Q?I2+ߘF_z+~v4>à4h׀\6+r ߽F9 S]c߉VUg? DZ>z{e cz[$e+k@ J3ܨ2Ya7b[[m~dBi,/Ūʞ\{-J*uNp6iT-<4%MIߔv_eЗI=kg.-ҟvmP%dP+TK} ،r8V w? 嫤<:NP]=rQʞ X?}u pus G~Ay.rrٻ]+sW?EPnK??>&pİCZ=0 ^nW27C~o_,+otC['( H 4yg,\&ZY[;E{4"_ 503LʢC_d@DdNױ߱sUZ!Q"E@*y@ ǼZצYܲ|c7{+5 @:$m@sC`9()+) 6͒ BcBI;rordzUa֟ZqşߍzmXo=۾/?<8波xndQ5”Ⱦm +Fvʷ.mrc6ן3mB`݆~)|%Zy'6?7[4=om]-~}hӽ_nhwգ?xftߚ{@|ޫǓwqt>,GA+iNaj'xW><8-6³U%&Py"hm6 gEHaJ rb7ɸXY [@P zǼo'gǠ/Oy Cu /&m׃5᪏a>EpFNs{\@x`>(o5{aapj's@~ʟ  \]E"G_߼uk}tӽg{8/{wշooK4ޮUUvW}bzSkO^?xxyvע.|+l!S׽;3oFjta^xhX~hSVs- :o~_ W@/(6Ρ`$)z;t?vIUǰdm9"e݂~}ULKasbk}.A+j,tL>ݣ_/$CNG&-4w 9 _E=?J(g[_ c[gRfN\]T-ٽ*z}tӢuWk76sp_dEoQtqS(q9Y7MOwtٱGlbqۧD.`.v|F{燝kju^8p`{]p.YbI,_Iq0~*E8y.HM_`3Q' j)Mr;mS,Sq'Ξ9Y)J7:f#J}DVm? 5秎3Zv9QSO3"Jn~@,Ȫ&@8(3dLW ʿ>yeI!TM@X#l~Kt-E|0; s.8t`', w{+.nL>v/lńd=`QlRyr/sqa-̆ɞFY0*aJ1JI^mpMXDh0&Y̑g;ohru(7?)׆_Vopcݸ`SI?<GKm`Do7sx:O?\$fzk]Zl[-_YpF9j#B1nz3'ɣxq+0&Գ\}izlq̣*vyǼKfL)ϰg~yQ9\!V8ú)ǚl *=N}7/v`̈́ b|?;Z@{@8I+DJw)< PY8DM$,oc1*`4g`M#(\$l,|eS:_`w$P:_ԾԜ-ITej[S ڹrƧ˚e0!X4Tf? 5ϱe9w_> -Y -rBV h \ 0쇣Lk8aceUQ=:zK ˤnļE&{ZROvsOe@?+#<^381_I;v8@I"ʤ0C[aLOr*LS\gk*yP܍K㇣҃%! ˋ >4O[L ^8z2z֩*z*Eh1P=p8?D<"9}p|W;VSaBeoJPPgFlsjQ&~p )pRźsnp fSUNkNMt's ^~|gcX&32;U {Tඔ-gp<@\]\gkD$Vm]$'ڶm*JȂW%61-Zcc_ #8p2B*8@<_-9y*^ 0^Ir$R%㯊*1)!XvT-Ρ{6~NN_ng7b}CG $Ϡ]83e}T4y-ıG0u84툍aflWQո _^8$J Iy'E”B8!)2]yoޛЋxo\d AJy#םyEE1K<'m)*⋹?n~#Sd,?Ʌí,V5\ϟ\?C+ 5#=7ρ\t=]|+)VNDT,"Bu@OH?M. /i&b6TPn'X74EJWzh (yN)Ik!et%[^7BHd^c&>!Gwą@];ג6,ʁR]>o_~ I7K5#=q}0xfuKzyc.`7 o"y٪*/_Me IC})8iE sJ9 QKI=Vo#IdfX ןXDq]ݴ/qj>a'l1 zz"|p[g?d0rxbMCkݕOպFx`gGtgjPLC$9HR1$HN_I d.?>yqT懜$tE,R,./3pty>H]#W9nwr!zY*>]D$˻!n&B:!JqCǿ)/)P}?x6ڈDZZ"##0W/z)]8Hn7<4` @* A Iy>T?).ǝ޾4/f@4R/>2)u\-< Q qt-+iƯ;/E\3ϟTsg 1J'&&8yct[=b|./<}E| duumimZz=Rۺ'" oDZ^n+ ғ׿ǧْ+U6'h)"2>!_ins폎s787 _ϟN>,gG8` Vi1^ Ǜ^GRxy ujy RCzoykr9$}}ZX:9_Vsq0޼4Q_p$m6R!lۗKsw-]nS7f'?A@EZ,G|-quvqIl|Z5a#-7>~2>Pᕬ)8QB .`-~{jbt?NxO`_$eQˉMzsw翷oo+]@_ߝʑ*,?tچi٭Bse3`Pi[R%`<4Dr%ܞcxz/?bQrë a,~ l3%Gwl3I1Hc #{%#Բ1<}0P2/8ٝyļfN%åG Kr݀qxwvL4= kbuu=/<тĬAe4翷oOV/cr5X@e]YHG:U`cf%f9fs.54翷;/fNTd|lP(bv F q:>c^vi2ݬ ` l]L_ʲ'_ȕGj{&."S/'Y"?mQM51D7YIF'a(/nѵc|_Ԃ$hij!)$|X'̗i hj'>q !&w| ^3zPD=bJ\ߧk_#qFZ'w?|F.j ') h.$)z:lC6A_'O3Y$b^v5>sҚ^1KyG?0H:ӬoG_:pCxuh`?\'1y+b_qz7ݦ~39KӣI#r9ncNXtq2ߩP1|}cCBqK)c. D–h>O{{˩7￞LvlV~h@⌀6Зy̌#˟f|8'&t-,ϟ] A|ľ!OO^(ߔ;':{. 4y2ҁz\Le+l @v)T\ر6,?͕._I~s@<" '<7P/RG9yJc LS<>_%H]cˋ7iVUQ\<_O!0GT˻e3s1?j REn?4H/=L~2=֜Y<66=z q[@kwR߅T(@4iyf`i*p $o=MlQ̪W͗)s[w#$7;t@ΛW@g\w \$qx gח5<.x/5—i6lAL\믎Ө(i_/1E` ԆVoG+=c u6 3g%=ȴ?Ϝ>ЅG0ɤ X7jT`)8wy,x/!mmmx/p ~!W\=8taׅVp̞=Æ x" 7aeJOf0pT##x `b"O~z 0# P@?-KNSE=`3j@ r'!7vҭ_o%,Au,1hb޿/z|]`Y'S.1c"h>K yLӟv= :GEG_( !ODb,ڭDrJqBA`H_j&t`522\|7T5Y޾0>5\`t@O(s'l5}j<ҟA9 _{DS:QA&ei1+sCdD^,T ,C_N~c2),/?l/SGOx%u/Fs^i 5g=M`("fUw"fZd/N6<7LqDmjOzG4j:qے `~(fjErd/j|y?O IWâ=EO@@M0&Y8 o38y$T78p@֭[bŊneٲe <=|E~w 묩0}һk2?'}6}7K{`7u2w c0>yc!] Ucc¸ѿQ^w?f<_ǘ<6yh!EiouR]ߏ'/}swm{{&䙞P.'O^G̢Al?gm~MsYQ}#8M% H= }X.c,Que-[~c)O "]G#Lu| йO[Ctܗ9_Ȋ̛1]PI_H I}ǧ/2<X0}Է !p/H ݪ\ot.z=EoK}Ϸ$ǀA<@^{<Ӌ!~r_<o,!PR7 @"z : WA@}F-c q܎l>VO?^o" [0XCd?W#G}߿!j%yφ?+,i&F=:ab3!pf%64< +ENx\$~P[ru_7sFH (0߽^}pS*BL4&*kN>ә}cU%"f}0[_3pu / 2lV .#^eyN)9Y=eo//fT[ں#I6 V!H >v${xŰ8(7Ŀ+?0}z"V%z&L?IZNtZTq 8UQ Qj`}A8B$!rBdx/KwҏǨ8 /'v t˲z`3W"ֈz|m?M>I'| $@`,QvʾnObHI~#fg|>P($9P⥤D :*Fkߜg&XsJ)e2}W@]^'2{9^݊`[$ǫk\ee{#Jܤ(a- .? L>E.;E3*jQVWy;~?5@;j"KD;1I$5 p,ͩSjEjƏ}X|=r$~HOf|(p! ,!)_}Ib< '^!:$ :JpT I 3e0V@I7./å4*}]P3&U`'@ :#4Le}|o)Sc:`A_ G+r8 /EUA?>X%8L/¿vV4}\?mCV4oF"{ 9hLKuo;kW 4Gt/O! I0'Vom}|˳~:_w(px 2<`J/OS:A]<iޙX =!S;ד|qvWq :_e_Pe/Cؑ,Wﳋ{,pPc"/,y1-د$>C6CەhS@r> dLGƈ4ւ}_5\^xIvB %@/,Y̙9%8ߏ1;X]P`_$֞u3J"6/EVԼ)x$@ǡZ?E xEq },ccrؗ @Xe5+.SۂE{RL\G6Lf' 3){㡒[aˮ͜[hsvE8ۆ}M7<~trʢoÚeCEjn͌ S:LB$SD/d ,dm)6m_+_<_$i~7>>%?(I6@!sg w5~/zB"4dC,ձ:pbĺT%aj Jq:):#spFEd׋7x]eںS3=i񼸐!y]/\BUn9vBuZ9waKF]|-lL `í+ͨgqD GQRkۮʖb\%"xaB@fm_O6I_A}{+EӦ="@RB0dp')gY# u@|FA5K'MRCG1ڴ3 ? >Wcp[xiE?AIW 8 n)tzOHj1J#?[- .$A sӰ@:Bl;,%oǀuk:wgzӛ􏙲ܚ\\V i}_bTD܂55q6TGՠ2LV\Y rmjLIžOW@ӃۧbG]! Jl D1w6c"B@ 9*z}[Ii! 3 ӱg[|:Zf4 bD6Yd0 eZtEz P8^G~<~`n Dfw|?Ob"1cen:V)W`e x6Bv!XX*<&wX/EY`1>9Ó2%+Σleo+CUt9l1VآkQ^;+l(Ph:݄3MvF9\ǩ/B|VP͎Ծ%Zc^32 ﻲp{f}3Ј@E, nCfAB~Ȑ wzi(m"4# /֠=',_/c\ fH\#ғ|$/@1~^_"{A?Ρ2(.^_Xy 7@e`ݡLlTÝ; NF O@gzO_sT/|O ݏBǖvX)*v܁-֊Z$5a_3rZaMQmQ`wζ߆+Q0 F~ahG ~oV# |H4 XdVt !tkd$rҤE  qǂ?] 2 dBz] @@݄]Tg]$L"u4x궍/~J_##±@t8nGG2tYe*LPd{ 3=iiTEeolB(+Cz-eHrTŔ.Zr G`׊oPDq[W V]đG1- !΂ Rϟ et t `}pNXL ` M޾#up|3l4~;*"]|KAH[ l~Lz7z+H|Ht@O1krftӁ49xsy/fazj|ئ>#fb,$Ƙmpݍ8O@gzm54; 8E7P ܉(E^+Zϵޅ6t@[z3*V'QώjTBj|V-e:~z.7 !Q>?rJV.`'o\]b7G?-.{Z\®?]h-ЏWh4SL."Fnߢ߬ %0hSߟf: #R?;(E8;~> _ N LlڃuM^[kĹGQCq73UT"h4@+Pa>,nG܄mO lGjP{ ! yxѢw6Pd>:+ ɟ?- LoW_CSھ;?4fLE #>i_':` :>c7sCORg[f %w Q@Tr:prBhi }\')& qu-m|OSץώڌ?~~JeݩڟU S`"+@RS6e#83օ `W2BZ0/62[YM_,-6G]D ʷrYbԟ.C]~5Oף\ηMڡAn)/8rqPu~#m渾loHZHOTA2YB.c`ÇSx^^OGFcO? žvS:6VM5awgδ1e`̝1]4(x  '"^G B}#$p1u3q1[D:bB"@tiFt @OSohJOi t9 _wn [11#Xo 9Iv3xYeMEfaR&oZ;]YLGW.k-;.(*^xu'o~|ѪPކըlCWB|ފŹşqW{.?ʧ}  @s6FRO D 0`Qr# zX?đ2دOS?|H{g@ {'Q|jShpMi^SIsVtp^8YiCM9XtKI_K06 EtI. K]J3OoNL Zi 0pV Mƨ$KO”dLoV gYPIPN*f[RUSi*6a4ղ@Lߎi[[=噞ŔzҰIͨcCy \OŰE'k\hGF4:6 KQ8ͧ`ͱ8sx{"Aȥ%lAl=UsW19ORt_D{GQ)4k+R43_E {,܁x<,;pPD%Bf?q}s쮼!@!5k?'=nEU=s\1Az$>tP+t q_'.'fzFH^s<%.%h:!f,P?| tAǀk0T} Ǥx'=)K-`{DmXHK8E&+0=#s21/#~*76]GUr5Jy@NL= {rϧɵÞ {V ocxO7MOS0<'A}r+'Sȳ()p n$fRqa)O1-- zÛ |+ =E\ zJ#_z q 0L0,ܼo d&`fc|6݊;#> @j+HL%>)' %0#6Ӣ1%" 6m%OOO]c' 3دz^5 JѲ u6Wzf}rCv_B;j4L ǛX|w>wWq/(bPm7qqey#s]6߄&-$ c~j@N l@>}أЪ@uϫ3a ɀ(@~Z(0f r nPt|i{R"WjU~@ܧ~CWjsub&z܃ C?Eh# 3)};f'nwNOJ4w%!Him؄wm '%cYInF`^")j_('&mہaW++1Gb†5xB<Wm MjįGRImw=zE'}{Q95+p>ߌ{|NɆ:ZXqg6wJH1>_VdYY2fv4oD:64lFoA~  `  ;8 *@76_ž@՜] b MXhOBt#bB'H꿟Sd}\יh2 a #cFOq?y-lѢ^[X@?39X/SeD8hK&+@ӿwf2fOZ:$+1FbT !aAxC`<発# z+JtP35 {?e Wp&8y_b%c7\؈mnѵhXaG͌}T `K<e;o|B/{r52,;XAӧvdl vwo9I R }x!.=fxCJ ̓&nOX3oŢq]`]B&{<&|…Q-H/pb3`&#z!;`vp\e0WRa&f3 u#Uhw0,wQ8+7 Pz wP\dE06աj_5OJd%_ 3\ߜ&RrNO!hfС `O 5i?] ?Ν1F 1@P >ݮA'I3 ŪuK͕ * u_Z>в>B>z:~uezVE"ᗢ@z X' ksSfOJ'۩>~9JW7bC #YDM  qLKd1d2@v8@F*&[0j[Qgzd8ߵԒ+h-nCۥh)l-ɎGQw7;ڲvm(^9'g܆C+F]M\;h/h-jT Z[и &ܜueaWY+l5PcAɇVnzѰɎ5EhYqgs)l;`Q5(TaT,qvW>ϋwu YGb_ro ٱM$iL*pۿ >E W!`}'KڟY\5}]1@ @$XO{=iΣ@:"{fחJ9N9n3AI#>O}PĊ!޼Xf}3d~n5FGl‚h,N@ȞdS dw2hUo": e!jQ@If2q ̊ىuxrLXCWcE('()O>1!e%_GQMGźT&TeT|gZ3jq? 9,yЃ KQ[PUӎeH\-h׊E6bM+ [RûW[==zY^7Ϩ}o޹bSA.tdP<+y`6 `0ߓb_gX'.7#Vhif+-: hR+~\u>~]HPՀ]b]ZS߉_ \#nmX)X KbtE|ȱ`i Wy)JHظς4J!lU'߂O`zf&%a8O:gzd8~c{/PnlԠr }֝RƳF_K 6fd 9,C/\Z.rhk?Ռ\Eд\/3gWtu-D#]nٽ ;`ÝWbCV}qڌFCM;ڀr ) PSt?9f|Ic?s4 Ic>  y<P 29 u&G7#%fЅoVyw&Dup6K`7wY  p )A-sʩ w^/˃+1dcѩoZ\@Sczb,|0~$ R0GErX PD(Iz"$ 4'Iu3Ʈ U n-[ItLLJ6 }ނV(QtY]h' .{q } tgH9*=&9ψSS1C yF,8G.num2mW0rՌP+J\G7! e.v Q[CJc?Y뚃 h;Ҋo|_W}_;."uQ{e1e8>[f+<x}3+qsԟKh8X FTO%W܆"x\%@ P_|9,|:s_ db70sze ́^zw"Vj#t 85r@?fZvR RKvӈVzA^5{:НY_Oct,ݺg7|u1xGyJzYWW,Ǡk0=d!(;A*,]VǠ-_ٝ2fXOE) VCq`I1$0#Ba֭H`DSmn1laVAYYBY;.! eQ:*rPt-u_[o9Ó2q5ߎV崡}W;QAx͑ZF`id}} mPv)Pj󯣭-_CyT #ja2ą|0=k>$HErm VCnCS@@aa RP@ r?oKm ?IXXM69z-, N|X=^oQ|~gsg"K! p19#z"@;X- 2օ`͞DߗeX9ɘIB04631;;?K24O:{Ef2Epl]A|~hZ0'# ,LΦ~p' 7\DÙh7qa94iBYϐ?wcM 6Uϕ"ZQ&7ǗA}}?}_j!K)D}., g <b̜i1}|iPקSR29#01< QXE ed`lx&ST@Y} (Mh4p-Zζ* %l;9+FVTQ0=sPTۨ>XJW$T%ZB7@f&%BwiJQE-Z(K],H)Z^vPwPEvYz59p q>Q=1B_Hc?MtHN8YsFj>I|V@:20`0g_سm0Mu|bz jP"L~G!ue,`*Y*#`D<8'h j`C=O 1= ?¡el ޸DMhX}p S`;$`A@+"! 7uutb @!J߄Q!9~;4)ߕYيD'{gr:^GchseGڊZev5.}.ym#WUxy&B%lobo *ra-Cݱr |іׂ{{jQ@V[kPu-Za;d yU.83PXh:gj-n-ц +n?2c&9PWo_T(@V1 >]H|3 z#>|GW$ej f~[W* Q1/e`N^Z" Ǜ[086 ;-ެ+  XEҰڿ\~eE6dZ6owfxmق1XNNxnyѺ#.Y#eh9{~3"`Q;nʻa[]&=ƧByv1n\ByF1l7P.kv[q/ vGKB+AJi;]oSiW`;7pf4'HR' @'_HW2.u< .zBfzj$zZtK\E@jB(t 2Y@ͩ& 4 4w\C_2wW.흁9-DBs ˔)?Lq-،9Q 5R阑-LּpgKN-Eu54^B6OC~34֜2K¾ΎKsOBqg_`IQTih m' ihVh[gFUfNՠ]F}A9wӎUz <_;QG@4.2!V Kr8hEaʔv i ht zE̦} MPgT㧘)5+59>|:\ t .)rfZ&k'|z9__~'j+@ Gٯ/ݦxgm[a Xl:f76n/"b08!lNA,ߝ5{S1`A"7~'c;Jtʹ/ͿZ:*El`/GК{d#8%Ѱh G`X  3$P&v)CwgYۗ Ds ''I@: w4)[ctd8"c 8x'DuƦmxk{,Ƨ` 4d#p9(_' y$a? @`J4%b^r<90; ^ilz Eje}m krkQwԎoW'AsYPư¥gqb^XE6XoNU*F24VY]P@~77]f4*׸_H@}4|a7@q;Zv7-+|Pu8MkחƭCE!VGKU? @q%hHW Г v`ĈBL4)Jc` ƍnHTNYBt- @S.H@rmO@3 %5V-#CI~(d tB\ <.N|z U_-̅{g$"K l13xq3!2ˠ@!+0` U`pLwNO[laaXӒ,ς5ҙ@/NFHVaߒj|ElQ ;aqr4ъCI)4Ljct4l}( %Ͽ<;}%WMZP_.3 wr `U]49P[z\F|{k|[-> ڏ|FT@ܻ~6|k[[%9x[Shhƭy7\؂ѷpf4,9 84vQ pқF)C) (@|'W@^xc֬<끿?DRa`ܞ2+{() @3;' e<0hJz5לnvv@ˀ b's)z5>y0v䛆3XOjCM>-p|}3Fbg ۄW6joǠ '"X:"g)U?:ki ȱ`]zCHEGn쭝`aN)0/%3-ɊH@gn*I,a~ 8|u,K7h8֩+Eh Rpr'R jUmTT9*V%7'AۡVXa/T  ͗[`+E"woD%Z6lG+Uh܆+<'Owר;t-_l=_ @BpG I4Ztb@RXi 3fBi tVOX^"`?j'|َ c .25~HUn"Vǁ)5q=%S3. >ߺ+@V$S P )jLd)l"@öl[sR 3Wv` ?{$ՙk2㻇Zx!Fx'lwEy}Uw>b 'ZBV!0%nػ1wvbc"vޙwds,y"HwD xc\u#f۝Xl–vr{(E/yQ 'y(9Q׃,~*ö*ĹaeS#Vy\XnwanYcDXGԯ < \z +˸{'#iguf>5~U _9}_uJDK| | 8q \]ߞ~vۈz6zǙ'qe?r_;O[>CqWE_yO>šWOQw._ęXpw]™g`4b#0Ɨ?^`g`Tp@Ss]2~0̯ыi1L!$Xd0-p;.DT=E[ -gG1:3#za [-QyȣCyc`y-g:!Q9H->RH? Ll*ǢlFGxLRZ`@1&Lit`vc#VljN7JP*{HkiB݆<&2j 5T!Qo@݊^5 | |p32 ى>Bׁ8c\x+\ۍkWcUGНtX t}ǫ>O^Y}$ .t빅~Q67۸M\+=V?_ *73m}ëqrG1+g@5|nk=c»9oೃ\POT7ݥؙFo57߸K.$w?E\E7Np'] tǻ_^k>GQu_H@(Fv  g8mZ`kF,X@(S*hmRJ[Uq[`s9 G]PQPU@u%?<A}P@g&miPt$.EdKUjcgbՉ"KNlhmB ;p Մ쨮Ca`X]TSMHlw#R[w7۝ɨ~1+'|b>EU |\k_>oW}Tc?s ?k|s~u7޸W= o/n~_$N:nM\5\H|nz8j t5|WAW9}%Ϊŏ?Ӹ X:&R=3oE{9WBƎqzjl<^=sb!sp3YᵕIh=&vo~wpv ]9ЕswN!{ \R9z/k~nQл_< 8 7>>3F/!ku:ԅWS>xLԇ8qgg=}6w\ow;41ON;P7Aj~8Xtߞ{4ujC2υ?˗z|U/u3i?^ 9ZzC`@*a|-`+ M>FAe!^OP}@_B (OyzA$ _)>(Ūz 6GjӀ(10xBip Åe"}ne8ى GRV$lah<ue$4ۑˍ}-XDV:zҾ4]&q\x4ng8]\ʼ3YqQ$a/|y._EϢ|ߞxn} 72?Qе .ƍ7qK _16|t:'^ŜrG)ݘw6қW v?S޿**wD81y (0M^L ݫm}E? gM@δAS{` ;"C ҇_pn(+^y t uJi ϛ"@?#6Tq pSh[Ȇrl#׈b22r 1 l+ۍ->׃"<(93j,Cxg8mH,Cؙe AZmo83FE𻋷"?Gw|uX m#{ܸt O_q=8%uߜc7N<'œ?8ы|%_`l n|U\*'8I{ ;tNΠ7P@Fg؞r~z{*4GTޏ1 92Т cߚ5ض"։.ǯ?MrkXCEbf0fQŇz*B6G j,0\~W12`$P@_,_:@}gx*رo ,`@-o"Î1IF "P^&,OBvGߋ>BR=:!ވ-ey'&$afF >l> omei y??={n{? aB|w Gs?™NↀB#^ŕ.ǻuᷧN⷟_wokrkۅ_y^-\Q;g󛫸Mygw~*>BkK\n\}?;v?;E\?g{g.?ʧ7GV+^X .5K~?s'0PFZz<0Xw覶>-@=qZ,D\ 9+)ne ū>|eJ uzs*VDc@6@n_F-ӱUHOi!Yh?(5 J0_raωV7:]AUbՇ}h<ЂN5!aö `Jj&6Td@' cN9Qxs*kF.?ӱ¹p1Q31N_G<ǯqN_}҃[?[oĵ]qsΨ=~\?f9\]_֟˴q8q8_#}Dg'ϊ~GQ)K [BW)V?;m,s<D0v&b`=ٞ8L=gA`j` cXWX9v%L}.?'GP`"G M0>_~L @o#I06:II9x[Hm_?g"qZL-Ĥr̬"˘ַŃmnd2׿_@@fTlFX^J]ؐae^oH,DVU N/R K_,Npi{?_x_GW⯌@ /pi|8Nz.Q p7>lf*x?o>oBwk7Nu?s N]NEp"N?S罳9tW]͊)ܪ/?0GY?4"d@W{T\hX˷}2_uP3.Y9H#.af\_K/=t?,G(|_(l! -?:p|sogSBn 0hD2wٱYə٘W kl2k=&|8FC T T²ۍ;MFLdAD1"eo3yoߐl~pq&n|r)PsׁP})S VAx~`zA F 09gƮo"\6~k5C>U:`_oH)PA&}Üadި߂ } (qy$x`[f.`Rr"2vz_o ?H3*b0[FbBf6bvM ؛ZMD{}rq%D!V$55 ш\ q)b97) _cOpqQ"3~r/q^utzO;Ӌ \5;+埞ƕw7Fϫb+|nʯ'A_=vXO5<|??ٙgqM !PO/Q/QPs t6r@SO_竊T s@ն`ci]*jǔÂJ7 j Pm{ h"n6~E:O0|c;K,ŶV*z{Gon4FoqT->LKe_[Nִxŋv)g[^Nd;4)1-i|^r@,&ŧ`Zz6Vbu] >?t~ھƉ=s:kwx7>Ɨ+A/ |=k@9/\c7NؕΠ5?@ҋnozN7u=g~^2: !~qӀ`ߥy]KY?!6@*6cc@{ѳxLf*`iM 9jD'lŔ,LlK96#z>lw#C݅N10kn6yd→ MH6sS0n[@*e`vAGU|rfza TS 0>C_e,ԧ7vA}Na!? ˂L"m?v5{Imzb7!`n\c9DGYWl9Cz* `s ^G`HtFh3@'ti?}O4@{3͠ğQ`T`ɂ1 w-$#5}AkfaviVYo ϧcZA!"ڈ6hEBǘߟ!⟹Dž  f\$QSϟ)t@a1VT"+v |lXoş-@H?T!Z8+GBf820@D=T%h(TޏPKg} mAPP[)ԬW z2 w4?Wˇx@_% +řyz?@=@X/SX8gzmE9u;2*_$a\V:b]c~`21󫪑ۃuM/ϜHDZmMڍ-v)M6#nԝ񘔠@e%z@x,el䱝Sy9f ^9o1][stm5rS5@bAv⯆PݗUg2pSN/YrWٶC~S\c?}#] !;<̑CSPsuz_[Xd?|Qذ!  @mo >j}^lN' ):z"؍O,_Yþ~ -n/&cm\}3rEQ rv lxr 5#s_3j1cC8Hmm!i{G@NJ1~{<&'azf.Ta&p!`ьUuaO _2eIc)A0(dz P<{jYl4{4xo~: Pڟ7+^{L?<}7?3ga͚>,_ J~}X(ǎX?幺G{ !!a1) Г' kz=.x}0cʀ3@)ld$@ L=_lŗbq:]}g{sb36T`ju"6lA^ѿ %U*Zx"%kف-p % m^$巈K]vd7ۑ)|z?-р4y)`01*H @Q UUa1>D |<?_ْ1!@قQǾˈJi|n8m^ng. v {.oz'$blx%XPח,./8/!arn`fbr^TEI iMHiYT4jPf$s^ D^Hs c?ׄkQ8%^#)31 /W`y~:rWD< ?zs? (c`C7eb j07;6ag狨g_{؇EU%}[-RDȳ" Z'gcqeQ(߄]N<EX^WYuXr"nv7:H46[(Ǽ* =d j6D6{+X~؁fune|࣎i]jpşϰ~ =}2TF4-c}=eJSwĂEAFN,_}\͟@ByqP3OOW BŗBm d ؠ  0”>yVKF{ (]UN]_c6;)`hL0I[)(0rlMxE>_ߢԻ0(wcc4Xlf>ٍ^K1-S 0 Q s LHN7O,*Ŝz ۚ]m vyh9vd`5s}v$k(=)| kZvcfQc>?q_?<;gsR=@E(}Qϕ=  OOc!X+k?&N3ρC4UOR#V`z?搾< 1 40 TﭾI뭎#֟t{k1Nc K_ϟ?@Ą;3.뛛0)7lʋvDY0X< X`fm#@p"S~K;@@A*K0)6e~p4aσEu+|<mmQG.@y,"Asj [ y=* l۴"#҇`$CcܢEqc1mQ <P5AۥD@>DX/Ӎ)`P9~%\D&\Y>͈l31zM`V (@){K޼G r0B P<¨@v ow)S1K=Mm2al٣WRPjcvi$bݎ S|@a.@nuaqi1f`NU5^_'`g(Lc@?YحH7V`}I!f&&cbL2far,cWrGnt$Ny@[5]O W||+`={yS@O`6 ,>j1cAy[ŋ;oPn];KV[8oyA 9'A@|Fueϋ\6.1SՆAog3K` 5`QO!"|/Xj'@f03:  Pj^붑❯<W`;c}:l1{tKH E))+P.zz`F ԰!,+b4rz*Jy>g`0⯢ 3 6`$ 1=k-waLn;X)o6C,2/~թѮxj1-'K*003bA6X ,*jC~5x/7aa?cwQ}H5V:-?-bmuE<dymX-iƂ0}J#R!j! 1lyNGϏ}C/|u/!}GcLq|*PU[P"h)PK}"fyF_z`@Ӱ,J1(_i@bk# I cM]%V#z7;]D?ÿ/ui8xi'v"Z+@Ѐ m/% )ecV~X*J*mw> hlOKL}@ؗǏ3iȪ+m]„k6 0 =*iNg\䣄j0郁tзe@_`{QtF\H#HP`GZykT9|zz=qU#`65.*M# 𞃉L{RUMF*\@}]>v8T_O5#E T Ҋc[*=k˱{= {ۜHpY1') JKaÜJ[`R~MBe%]iTy"VE9ro " u5X%Fn=>1~c!`ύ 'oojZlkT, = ʦt U_~gd$NxHˮ@l)FEV z_0PiB^D=.0O~6OCp sHnOB@(oߞ{e;8mZ{ "A@?G:w>5؇ПP3u rzBj+dECPPy9hZe"[ ᛽uy0`_UPC8x(Ԑ'mQՍzPÁc`a?A :9#}!1h{}R]5* ږY5j5qP^0]LH.,B@cX@x]43Wb2a `[ mH޸^-~GBAY/v1_UΟb ~j?Gh|su`h}{r40'  08]ۇ38fƌ#PhC0C*4 ljsmaO(&@ 2{mڀPl (j`:_u ;]r@"`-[f!** %00@Ŀ+|#,cт;0=k T^ޣ20? Ra > ׿"}Z}V oC.ᒞ`8mnZz"f?%(ЏO07 kK-201ޱJ+9ŘnĆ&}ԖcsQN;6>+f=H#[N*zlzk TaIc"Xu`GI{F #Y'No?C 'Og~a_Ž?PA.eUn:KFX<g\V:MzzCcH]_W{ 6s`OmDCVGc^D8E ש"t%]8Cɂ (@0" G_J7O 'zgHar}MLlF `4$w 0!]wB%g [;)ri<_!@]<߼E5˧ %+ "-"5} ;ωR)վ@ 3 IJ{e5X"͎t/ksaCI!UbˆŕEWו__=="#mFG=V/c*NĴ{˿(ˀ 作H4!ha"q6&Yv`Žt*n,9>8,؄~0 YBF`BA֭^:"_ |SY(?={ s[4sJ λ`4Ut(Y <eBM_kWVu JQ]3zBlX 1G *į<} @ gyR U` ':~{q;LVG ff2DG TWM`*@ ECP(ށjb5Xa[`E5bwSQ  :T ˛7 ** "P.` ş-'ilDL\Zg30!"߄}"o/ČDYkjeU ZwW}lo& "Xaʼn61(gO3J: <(h,W`#ZF`0rfdc.WW`yK><4䄟m~y89pS*ZC!8sk9,z !80W@P??2X @Q*]`^K`$a 𫰿('HΖB|vnU P#MTZ#0 a4IIo9+k-Qb:Wax{\$xlQUQX^R(H— DԔ`Y6T:RfbE9c@((EA\lGӆxNd$ Q+b+|t"^Lθ5 xq3|G9%4W8SWE~k 871B`F6{0|g%PFl#|,79N@Dk Ptcz%ZB.yPF Krs0).΂EF Q]vTOi|1^։[/@L˰vR=(a`ϟhqۍ?DWk0fDL!c^V̢ƈG}+iiiFg(៺ꇘ懘1]O+Fg<s7`{XjzQ 峟lPaBs:5Wu;j oKv(Ҭ׋t0u2ohsAd`!Ezl|J``7qp(hPy30*"_ѰQ*I_"b!>YpbgoFcϊR#kVו!U=T)zT0}E7m??A}>fwxQۋb?H@0fN$cYьcm5MXa,sgHdUNÂ? #!r؟Oaޏfa k/cC-L߃S#,"u"VQ>2yP߃n$¾PD7[/Pa?Tkvpxڱi?5#9] p02R HO6"EMT^c0=) 321;cW֎yaC?UC)PBo"?A#W }U"AyL (ЫUa8HU0/a}v@s Q@BjO0T*S}!BEB݇ߕb;V/߫G~-%6FQx'8osjJr@RK#0_TH4F⥔T`V{rwYx %Ċx5D\'@т3X`㷉ېkm"lbFB f?/'󋊱Kcš0vMYZly~]&+@E x>t_3A 0OV=kg螏f`ELpa!"G1 F zżQu ˥>\Ч,"^΀`^w^>DT  O_t)/ִ9p0@HN 8plF*vk/`ˉ vUzl)["Ho`h,`Φ{bGrKϿ`+,r%,ZP%{}ׂ\"yb6cQ@F+ r0/%󳲱 /`qe%˒F7o6- obOA7)||.#x`vZ|嫔>305V+3a Af3߷m1`tT#r)% * ;kS4z!"h0Q`0}/^yUŀf[͂*z!@>a= sY9y9FN(r@OÆjĸjD҈]M(G2[HHY.<Q_kG(K` ܨO!͎"~|GXPv;5"zW5 | MƦ$߸ X OsG`|?} 3__ G vdjǔ ş2L2D`}Syx8b ZG#RЃ0oԧEB:8Mn)~50]eeX\Y ^]/݁VGzk#vQu UXDv2;};؆"~5" I F;7b\HԾ&0I9M_T}hu#^E}8'a"%T c5/>4 *_o *׮"^* ;Զ?XG@*T1* 38`У" CJo:އu^ \ NqZ2X b.vGϞ/Ҁ|aDXGlLwd@zh"CA~zQw~`]i@)Trza%"²&0'q̜? :'X>C."mҒxfAp11ET4Q`\s,gD3F%SP)*@Gu> 1.e/~ uP+bx 5_#퀺@PQc=CF'N+E[+&b}6`K[ԖFq[D^k1Blj@ IkAV3ZZQ' `@(vhA>j=* # EVCdqV ‚ՕXXv+" pbviOK(}>YC9?Cg9~=v탶zGS\*5@D6*@DX0Q)"JSYֵl\GV}PQP~! b؊`;u{gNSBLSU l븸M坛*jF@@n `jK X^:+˃ 4 QfT#5*bV, "a:vذZ`- ?i-sC):P?OO^ymXCJy _#0f鈾Q F iȣ@`N @G0`k](!UKvRys}7< z)\x3_MntqoZ <} |mjQu 0 6I) ]ٝ;!ֿ*Vg҂n$ tޛ0_{uzc@#[H @@@:}(E^QZFwE+7 ,,++ h&+VX̒ΰ!@خȪv~VpxZ=z (?h7KL_9A|ĝqF Q@D M< E?PjtR( 5G6@s*`Q&\ÈMN!wPu/Az[Kliu_Vo8m01Ϩ5`1F$Sv{8PX_iC@ (TL)M xsQxi3m+81}H:Ei<2ecǖlK^xˊd-ZSeɦd{^]Ҳ3E8E_^^0 kJ;:)WRSn̷hÝ`TPvi¯eTO0?"Q-y8/za/ x foz?ХDe*u6F7 ݹܖOB4K˦S׿yzǩ*`DJ] AoM BQ,sDd`H\6*o4( D=3V:pH"iH@`1dPhMd.^\RW:+TVFFQ<+kGxЖY,Yp=P \"q* ='1 2. J*@³x#N >R%[B?NX @Ta3}ι͙a'q*OR7S++ﻤw_= ័E1 !@cOgMU6E@}!hh- T By=7lj P:F6vP@ut͐0/D{X@xx ۜ~ yPP';(\/Et-i9K/ X ,@aLΥ܊K.ل\}*}`55pz_&HO|[XJ(وЯwﶩˇ?7t,g !]-yH4=[X9oW 0J7BFܲ]x/ 2#q5O춡/ߞU]wG$@5jnjk؟'h#c- z3m@j#e@{% ~v~?1vPϼ7-C(ٴ g^|t zQ'@NdMQ8M0 ?دA~' {ǩOq9Op}':VӒ uu ߋ '}}{ NKK_GI{zn2\?%Àj|*(}H-wF1a'9nd-&t!S̆s0Q덣_FD 95EgzN s>jV=6Dctqbt}<=! (@}F: Q|t > c>CV8AA8ϧ#NJP0s`N @4 xPVf8w;v? &YYKUx,T9u#= ޱUCP!x#(٫ " j\`t6@|3^'' DEw5ފT >NvSEeCt Niم;?O*An9S +" 0Mcg`daJQx'@H? )' ,^ 9iiMHIyfF&KڵYS?xwN~MB,m\@g@D |K IO/Y)oh $ ˳ k_qw#Ϭ,`hq+|) x»>㦮FGMnB}20UC"#Ľy~Z=4 -LӰQ@?Р0yxA O|W- QqPKCs-TR.dQAyč]-RI@dw0C,Qn. n.b~#poz"or=j5omZ] 6@" ߇~ Px&P"[ዩ9 ) 1͖;M:8Z P(nйI=T҉gR8בi|@Kp- *1[o<]'lL@; `ҦmR賳G/&+\%%2g>ȬDH_-.\PSvҢ r~(/]y%*dP[\{\{"CT"x_u1w$gB}#j*_£OB»tjɤcQ W^Qf*we]q3{^ z /b{T\l˗7yy/:W[TxsTd͛@ߺ^$!J!?Uyl=gn3y^F׫i5" G*F @ξuiguЕ)u)[x :;u %@X\tQkp{:H3Aj)K@7@@<O<`>HOr;xp@묗Zk4б~jZRS,О-3N9׶sN>FGMV薹ڼZ$ /< >mhh0mٌF.>#b^=zD=/DCV~߱cЉ+Px ,zl9WHUd$K5PZT72wDleHD;w!΍3ܛ3/Q*LiP R #KX=?u{K=u6Xt4vI,B>RZRS?߱ʺH?U? z'Dy=[C!j~ોTP j Pk<3@ouOPg7O= ZF9n_K*[Y<Μ*(1h:vi>j4 aPS`X@cq u="@oRhY*n|:o a/i& ;sk)~ɂk2ߠ7%D&x]`T7}_W׮ӄ-~˜ڵH`к?t?O?, 8KcЦ{Ԙt>pi::LQHQQaZmm5ѿYޫ_ CaGt%` i"\\W57/[K>yaq~DA#B<ؐ otm~g#Ux#6 %w]Rkj q-1pi38?LRimw4IENDB`tiled-1.0.3/src/plugins/replicaisland/collision_map.png000066400000000000000000000024261315121121300232260ustar00rootroot00000000000000PNG  IHDR99tEXtSoftwareAdobe ImageReadyqe< PLTE~OtRNS AIDATxM -}aއ#N9 n`"݌O3M@ ""=N 3Ƥ8&9zxmSZ 'X131R^Ia&o7~oHdL༗D3:eW'7"&8, @X3q4 ?%u g&pu7&pߦO7 p3/!n&&%B % ,@hA8xWړ/#`y++Lw$p?`# L l8/o C@'21 `.A(soNVP'21 lue4yMN{ .`]!EPwB&R.b6r>~ FVK:YڋZYzY 9K99E Y[<-6dZlh+`7`_N&CSmg [nz+̤m͎4lw5ދHIENDB`tiled-1.0.3/src/plugins/replicaisland/grass.png000066400000000000000000002267751315121121300215340ustar00rootroot00000000000000PNG  IHDRŐg-IDATx Uչ?x CH!P㽷QQP͋>"P2CAPLTU , RCPc RF3*{__կ{~~gϝorګ{gO@@y2060%azy^笶@3;ft,]w=VcZ9- dqCbCX]^"^4Lyl?w6}EsU_uV?8D|#7du/G{k __vR}:*wxwss ר6?,.cwy}:Ow`Q|)AyFxoKH|'e d[x~ Ʀgΐ\C|ښ1;$8bWV=ȋo/pܶl9ϧykLg܎s¾eU^B{\YjK 3}N1:,әUKnj{Z0^5DغJLFio cxoo KG=sϳ6zaegF9@q1Cby_yG$b# $Ԫ|IXwmC?=r޷7{O+.ϯX$*'Uu8w[f,p{ڠ꣌Q?={[]߽y3ώƺ@|ߪ'05z9ϯo`)al??ޞ@U'M-v% |?Eۋ;tr~8bINs:+L; k[Bs1XJ'lbqВs"}d.>B@@:M GT*.4zӀ4 } d Kp~{(nWN(dAk&+Az4}7b oo,>sݿCCMar9~{bcbpn; Erz8o붸"CU׾Zko;rv040%Dt$ԏ*jHd &U]maz@?(Ϥ +RVQf35A_V=)LU wTb =@NbT Yݳ3\onº~NG g/-ph맅pf+bb9="̷"Ph_HtZIaU>},0 Ip DăKhNpS%(>7\&lF\D  /T$7| ,$T-1Lv|Sڠ#r5 3ĠnVu6X^WJUu;w@8R@"{n&{TX\?[gD@g2~{7;݋(r |o xgJ{ϥiKSM6kN@s`F@'g̷뺮uzsu\Q'w^ ꃅXùD+kL9O Uhv]xxl;C@Q)rh}?ﴲ:MA-3  0d{G`H|=5 ~*pb7r$W@HBvAU%Bxw6qG@]F睮02@8'O !kˤbXi5Do46b /T6m_ 'GGL dMߌM gc_]S$5'gH l S-2ng ̶~6_jUy>98ܣEE:D@T̿1g7 Uы 1᬴[C\bv|\6@K̖ `E@~C*7(hH~ڰ$ru96 gBuaQD^ZUkAֆs֯3 "G~op?I|lp"]6ܛs[$HUP2 Ӟ'3~=>~0lGAZpRwH z33n"|w7ځnįGr71S%h`3@#U32  @d³l|Yd|ˢ̷Dm|̉~6Odߪ~GeEsiXnK:qpr;Mwio"RJX]1 0jb ^`} c<$m j'MY]ƵMF=tc|& p?OE߯ &!d*1NutM_?|0az~?ޞI,dGojdh{;L* ~07~fɁ'DIĊe7Ȇ?'^ḌO)b:Y`v x{tP@ e\q¬'ʣψfs8/ð9(eJ<${x>ƌ')Uωfxa"'c(qpgGKG0n(NUp H U?!dLlP'T3HHv'?WVҧMMZu4tW$n2|p03L6oXtU`;vetf2$98WX Oo3,dDӋiĨy1Z0d㦱_1ET%qGxau?{޾o;;.p){&VSkQgGz {>cŻ  ׍Mk5?ܖY%#`[T}ۿ!Gd0D,cL?=oa > 愘&@nx[V_/|LҪ~q([q1B*|}D=VWmO(ECץLmkĦE3?g늤4F1ogOj3~GybB-4v{dɻD{cş^ω+1"hπyu?iKH:jRub@Kek2֙Z}} ,j$Z B@3U BU=:~:u94>!=qMŏ}J,ʹ~?7K Hxf2q牌T`X3KZՠ9JՌ&sZJd.K2WN.rBo LnBwi1>8MSQl y7Y7wX;OYV(sYt$$-I-sR#+L ߢ!ԂPs[ D~pU9ޖyo|T?JO鰖oYbTyfX20~n:?E2%JA05T+ceC_X/'gD~s駁J_+BHZ3 nc?.l^~kp-l8AS&*/i=;8=&cbM٭U?319ϠD ߏ ӎآ^{8c}xZ1U=cm`6$]rot>L9Ω)W9F|)/;ܪGG_U?@63? ˴I PvJď@%Op!IP!Z |ڣU|~ӓo'*&/_uCOzR/xoket/ɪJIaR9οEx-ur.-ʔPSD2P|W"tH{l 0/7 tpM6*]<+80$#dzS?]7~HWIio~ĕK>j!>~rS՟#/d#sZOdd`~#u% y@ׁ 0٫}EYX=詜r :Ն3:FZ-+'U]wwUmϝmJUw"mxZ0T矴I~))/gE¶vzM]̟]p do/_⥪N=rUZnD5$Oo:&?@'٬XK|9PǯJP|^uX~$JJ_MCwtz%uX(# \ UⅵH{2Gw^8P_Q\2z AG_s_.YN>?9Ɔl>֟AtaJq>'kWk"3_sRgtczmFp\ |"2Q*(ƀwDP\/ml&SoOr\R*遼{U&)\Ih#@j]xL7-(%Wxw+å*0>jb߬-0 <ߣ_"1:yKU1y#U}?˫V$But Eh, j&B3HHnp^IyOj:tg;;4aGhBjo6-sHL_ mBucTo ȼk:$}Á'^t I l\_NM `,rOTz\eHLiE1$>;2$wFϿ |WhԉNTL0-rXQg19_C!Au^)\h{uM'WiM6WFL7m;;`Y,'Ey9}KtM4dUxY` jbQq<ů.ߗ,$AO*7D1@RP[N[C<yw@ypLJ> p)v~D kJfϋ}z~z?4nh_N_/>՘T?9zl cf{eHM*}<( 5Y%ڙc>3^W>LւCL?nLK=WO[ sZp6&7z7-k|q=ʓKd槵kjkt)U-sS7qjXjI@пI@Cs4\_| HXR"*ǩC|U{ak;Q!q:?t?F!&{$$']*ca+\ptyIrB Kd1LP>=ȸd֟'KR?~bn/! sÃu[ %JO0v9Te~UA~~\4)R3{ehoE3qqaTR5 [dU;?MV $!|E7:?$}"ZH{|!ts_Uc)+_B\@=y>:V6P1IM ]h i-qPI@i9b\˫ !P\@E~jMg>]5jmCt)tO fj+@@* `bCC@ &4fr -P(({H?~iɡBPi&i|+iGHXr6~  _Z0xL[w F4Ag>0*K[3VMʗ@P`?8- !9h\u6+tu!x=4U Հplt”BM B&Q0wʁ_\YdHeFr %NY$knw 6j!fiwsZF$nv ܮ)_o='LCkGJ颹0|DeY.4E{9- Қ3U Gv_h t/(_4̃tE9/COZP@ R~^L?&X>lWk~}m |ɮ?ϣ+>`̷K[ pƽ^IuFXԚ +wcT-HEn0ũy%?$rMxż3c[P#@yiFt_VJ; %z}V6>L0wûXhiK5kJiT oW @{R Sw L}?%&;AR 9i?󶇺XL sa R?ld2n辰U7a?֎|*ӵ\=V.~5B `7_QNVVv:?QɎ'!Ze& ,.%^P@:HE4?  @*J7!/QvB 3ґ{^e[f'~{eߡ;3]ƺF:> rQmN-Zysuw d?4dSK xmլW>?nTpE{JC`ɷ@_d{<`5k#<- g{Z- @ӳw_O~޽{ѣGe۵k qFHе;w:,_\<쳲-\0bI;[ᅻTf5RL)u4Вb퓅[cyzrg 6äUd]wun8qC2JŅF1@UmmBu4:$~`NXVEA$vgz7d% f<2A:q]-iR?S qȥ̒C1~1k.6O}} D ^r;1tqgKt?Zw qfe1g98x{ǎb˖-)~ȑ#.F(}/sqI&tMHMuL@s:F*bH?\9 _$fRp*0Kӂ(I,`\\ѿ7ٷ&dǦ(skzM*!MEbTyP=vQLpuwAy ΀UN}م!F j/ӳjwuS~Wľ;vҘ,-KcS}[龖TGR8(" 4M~;^<'/`զL3wWIiᦇm߂;%3k~R=h$;\ 3Ado6en@ 4~0H&$ްad* $Pǽ:-A/JRʝ|5P:J'+ dúQ q&<]w$"~"=#ZVKYqKHD-Xo6m H/Ԋ{T&UR}YxM$BdX;DM@E@"?beUS@,Űn< M.#n@'FO-K~v|gz LHϕ3)z^$m-XO?BTdFBvl?^JAR?gpRx&p(G'*CZ$rM(<:c]U!i'ұ@5U+,YD &8`̙͙_zL\ `JMNo97 ߢfьfO Uhv]x8+'oJ92+CxDLtW't8E]c4\O  K. dCk Pď\Dn{q򇤯:-X@  ~>pfbh}P=XG)=:t.L $ʸ],@0|qjUiCĹYyZ PPm+;gRp>ّq*VykC̞Hވ~P ܼ_\2Sj Pkht<AKIJX8<hUm4l]QF?WÃ9Qڲ+.s'HpFg 7*~۶2wź~禕aCՓ?BTU?]f,܋OQ̀?/9}Q?i97c>73\ٿNa~d ^}5|ha&"0#  'Q=W zV0j{p"$oW6lbz@P&]!p3?;:ԥN59Wp/`}5k~6mkJ)0鮿m6[To,?ZC׉ww Gv$!NĢ*"0N 9 _x:*뛈iCb.]*nau>֭'~B0~|jm5䛃T})͉oKq}pIO S5 (K.?#GgZG P\{P5ś%+!$S sEM=]CD_][+=T;KK*o׆*Hu?g2rƩTv *#+~z|TM sru7~c}aVZGDxء[?&tgf ȸ=@ N7ޗ苺h߯qS0@0u,#zj<>,0H`F-R"oxc]mKr>3g?󶾇& Diք<~g~gNpx DSta*8ujq<2= A흴g eI{G إPEX~3ʮ럭x?97o QiC`"H=gD(gPիL@O0?͛@OdWK/ZLR`+; \03!gHsCd@̚8ڞ 8)tx=v%%KjJ? > r{ޅw߳lW!$q. 1 ^&s1".5K9 >ڝ߿q3r҃l] 2 #)oi0S*vz ~]Yԅ}?7MC};#?!G/,ep?|XNDT__J6}U@Ҽ5q-$~5u0}ʕL2%co,8Jh'>]22\/Q?i9,Y^P ʌC tMRvG#I A U +3%H|J $=97$[0xP-:DP'W:NvFAgZ33~%[?GpDF:?oZU\tMAm68dOe#i@mcܩ5|Cptyt2b/^zik_@|޿Lp~{@@Bi2C=I ¾aFtn$izOlJjelp K`9hN6V||`X\ɡę6 Tr/$q5ΩKK':EjyS 8wxk?{>GRhlދD~\s8$sߧOU~l/~`\O"tŮh~ښn1 r|Δ_o OС·WyCh`ۧ @6@ la"S..tF)46^z;Ҿ]PjJ$D|3 + 61)z`uPܭ7I`*tASRM9]0~PҥxL8_DJ`hʭ Fz ht PoA*Y%m[gK*+hAѠ}HĉVR 󟪁IO0熤tr 6O7X(H>]B 0y40}R  0c=92HMF&]LS$#sERId켲lI$}0}7aw92 ?tE )2@{?%`@ RB/sࠖt& +r%QY`Sj$|!FU,kk =*`tș`^,.P^.W V4yVqFH;x?A{1  P݀@Xm3Oȁ^S$k;wHZA> !tu}UkFK{mwt2O|nn`ccc)923ɡ`JTVVJ`ٲelfGm<j ALS2 JR>^К8XZ^8] \q"ۓɗh[ɨ)dDuR@R?1 s ׹IQ!T54?U L:B^Y0eN*%GߛKK(w]b`k@ PQ0uɯk#s=R1hqM_2r( A 2{ dGq`_&6ڹ<ڏ9@'o.JIBK:5'Q"PSy"~NhFgPDVmV":˝BEiyLVezB kK;ꠣU'JUU-jHL|U/? Y5ZtE@[cR:H LZXר`3ӆL[x$ BC!|(04uჅ1g;=M;|a?։ŪEY)~uYLg4% joG#6uU7^ig$8ڜ`~:*yUDR('舟z@u6xWUj UW d#&ʝtφ>+yT|Ip HX_HdV\RYÙ?RE ԁ'V:_25HMy>yC2('___? ~I)|Hh's=(/Z2(S _W Zf@ONpJjJ- $*`38/?n ?BăH%#*'*_uysI]ƨ# /e+7Y\b&Z?<״hk s [ ?`ȃxU?^LHeP1@7|f QH]]Ό}H6Z[nR\J=U,:g~?yҁEt $t" G$}2<ŀ滫^ *ӧPm3yh(䏴< 9(Hyc?a/Ü0bR,{j׿K^m|&N>Y*nsI%Nߴ0T \st_|$+1+$}m 8j65>dS~~%)AOILa|nIkG}bsߴ#ciر֦=t@/j_(J62r0uu,  gV=?1FՂ?H@yAJhO?@#ŞU^bY6d濾󜖩oH:nbYӭ)1n D}N 4t&.'6P8;ȩJ\@.)l,K 1CLƁ%%o8$ė! *V.DEjFcA `aH8yo>9b6ٰ;!;" x@"v")xPPk(ãyX9!?lݐr52UzcwT?WgrsAQڦay~!T>*v $R?zV&_Ki_UV {u6A10- h?1l~Hju_tA@矴O|qOK;$pe0$dj4`lvi3νh |9ZɁEv,0.F}pMD HsNphIةTĥX?* ix'iWU@A$T"*w:Zi#t!8lF~8\ꡊcW%v0=φ,4 lqT )!x0Tjn>=4z\_]{Vn=:c(LA0]?󗪟 3Nk:iCѶO?QH0sb "-0@ ( :裏f]F-LOj? 5WmWl'y~0|Zh 1mݽ*!~Zg>0Nvl GcCR" nꑧe:yTl`/ lʪ"n yy#^uNN/=W`R3xrhNė&Ԑh/BykK~SŞrvJ/G>Ǿ_7~n+FH_=ő  c\?^3@%r" ݑ:bΧdKlWQ. nKJT(&/qG9(?HM aY/ MF!|5-/i[)ԬӚmz粡"4E~̹oDj(8ꍙakO@XN*oZry:F͔1C<3^y ڄor1BWV]4i /?i vKj}0;!<Hǹ<NptR?w${-5 8~Whho}] ufTxm.Ngznsj3GC+$@ 6M綅\>7G?y0@;S#0SL9sFcrY kZNKPZŇD*g&Ҙyp1WmFqӱ w\(j {;)@CK U}Sכ2q)T&%MEM/w\C{ ۍ޺i1|Ï5xsSmCy>6?"䔰 h-[ݑO^Z;ēEo5$A$ZSGHCR?qWJ_*f1UӮ߯7Ƙm?Au{{ JrȯR_3~: k~0|@7M^|R:gc}6%3io`j w!O4+dM(NOHQ /m,aq%0 ը%:~ /D5l0R^j\zOlYa"0@z?<6~_=$*/=:`v-Nu ?TN} Zdl0P\Z%r &yU/;* 2H>|ڠ"T-ZRQW_5@F+W۹q-h~_ѷrr9ˤ7{?>O/Mx*. }?6XcMOOz=\W:$VmϜݳng_/~bˆb[yb5b>u/Zu=W(Z{ff[s:/oIh+_ :_gdS?6֙XWܲG'Dt|: rGn/V>(c">@AAj ^=tLId` ῡv~_@ $ATH.v#ڮL׽ja5 \~eVڦW(:L }CClo#ڇsȣ⦇rjoC,:|v9$LT< b z(P}XC/5VLIp*uϙ4=NozLd)@:ʙEv|U\ (5kL]KKBZ?&CSzU{^čvW?u \_$Î:Q!iPͩϜ%ҿz}#j_sd`,Z;,eߙ6];?ig/X6b/ pI@*wC<0HkPqQ;%g>'yS>Ӧ7 IR?aT08s}p Hf](`-}uIpïKH8@vxd >7 J\:-R(.vJO+(t$wKZ3$Vyp0q:B~|`0 <1[d@hj=ӄZ`}ԽxA>y'ጻê뺮W]/V@T,$L*ЌhGRPٓ-=P&I XOmg튶hٻL>LO-ɾNHdTP04RҿOU3jj:D:e]w$;\c6E90Pgжj}*X: $8`1ShHCPAD I]H*$n̛3qfK]$Ͳ}WUw߮U!~-VQ5 ػj[ !PCcP@>{9&b<`Kfng춴 |>b^s@{:P/uXʍ(/ᄎr_߿"HoElMX㚛[!9 rjԡgD\YVvkPKWJbה*6.̲u8a:M _l'.奠a@f s 4)7%)1x7Κ;23uCGfLBT Pdos… SO=%&M$:~~\Gς`Μ9 J;̽N\mo4:;BKzf} ]ӣwj ՊgtYLI?_I ?pįώ<0(R`ﳽUnmjb,b@?/A?;Q_;a'Til֒ˊ:ќQ-5"F4 e78R8T'XcnzFnϜR%'SI7IrWӫHwpuyy:| ص'@TLYl/4 1mSȪC淤 8CF3<#l`i߁O8SݏIM?XI'NZWi ;֖3ws4'͏'.yNĖT}T;]4\7<')̯yDNt`L(Jm3Y\-7Vha7٥+z&,8bN8ۀ"l>5na#A&U#2JAIu=l]㫀 (&`StJg(U]sAjAX}o aT$}RCZ'_Rf?o<=9vfɓ'jjj`„ =Gd5XRr8sSeWo䄭&T9 J`O ?S"%S7s/LцnT^izSǞ/ [44^5A, &# : Y|u@jyBHK*=V~牣3=1q8qB޷~$@} j r`vuK-lZk RX~vmFRH<yx5NJFtxnڿn Iy ZR'n:dL ~kַZ1:[DHp% c`'5_G0˻RQ#|vw2. \ ?ꡮ?K)5lʠY P KZm}ɓ'&i&uVǫ_ 4}?Q|;{-1G|}Rw@"0M+\kiSH| {}m0)HϦkTW$sտI'?|)v"1`{$یwЊ%A3g~uV/ Jb<(={$?@ a" L:_)7fu}!Λ):{??W T|X8cw7?[['?JdT?%?(8Ŀx|>%I1!$S뾬{ƴ* ~Zc-UOtSIF cA#`<`kOtT؁w](U^][,xlV6x뭷477;L}0qI;w^yv-C3 "@YSXW|n\gn]2Y=$H8 rJhIOz~Ƚሗl}.;F]n pʉE@b5?ēI@eߖ<{:$"6U^xh$ 3zTdQ?a2%e7L!\6dzPLCNx{"Hf;ULh_G+c"4a)>~xxccğyK/9̞KpW@- :@-yHˣ(>9]nh+ Jl[-G=.оX@Ïk_6G_?Ye_ @Ċ B78!:̸Q;”@."@i 9sof@:Iު6=g=gөN[A!pD2:Cef#2莪͢2QgS 9?JY_|km[CR0iݮ^3ѡRyW|̱k ϟky_<0ܨZE;2ˤPwzoTmB'n;< j+) $i>R5s8wd%v|~N4ڼ^S0W7[i;ZB<׵a_w05Y Q0Ȍ 0>e%G@ / PoH`0 @& df@4L(P'x"*|\ʀW1vQw_%3 W~͵,d&E.5Yg!60phXWCRQ"NOe5"X .$MEGX4&-b靄@8w!U ˩7K-$LdQ 碎:%DʎI93P̞f'⌟h8pD8e}eH Ɵ0x20"mpO'QmAC94HI&M-oinwۤ!Ph)'xty'fc?#Hf RRLs N{_nMD-u? rQ__TC@H0s\ %"zis,=1qdGpCDz 5TkN |Sakn Ό+'iؐ/4@BGHB( OlӉ+zN ye$G8rVaーtOX*D=.U4} b78IrdE^$r dTȹ#? f|44aռjP@=+O9ɛy `: A䔲:$8>Gӧ;)gϞ)pV@TG,g]t̿>k:oI0oo/^Kgvg[ i:Y&H`֡ Xj p`6_ 3n6"s3ϻXh[xNSHyKA;©R*7k!^s?يm_j?G;U@ $~3& A^zwzmxEəd%Mm0''4?u@U?dސwK PR'HfO}]2JG۞/%5lj2Sz fn գ![<O<~l 0iµp]aFO?t( 1w^%. sdA U\4#\ Uf5J1T8ks܁,Hh|gA*&K=-F=BCE2@{{٥̜x <~b'y.JMuR0uB{3'N Hs?-799?1>GvܟJOcyqĔFfل^|XQDr$-ceRa|ARhj:Br?+A*]^~=׏.z h В%3~~F_7- N}Ԡ  <&s̴ro׆<@C '@d %#9?NU_PfTI\'.{NO5 ::?ٟՓ<o+E P#z?S08MUΕ3_HL ;Tڸʪ|k>|'TUk-h\E0c-ZR HCkِuVI+Q%@zGgcG$ТE=H9fN p_{Znqxd7-0?=JgqL x\ʺ ̆D ̙9~!k %BBI< ?(P+=w{c/PA 4Kp8$-p!0>8=ρ*Oe蟊lQ]Ο }W,^m-Xu=*:z1jvKxF`x!~`<ܘg|Mtؑ4GvP@@O]9,J6kH@ OmgC~wKaXKc~j(KsM`B Vww㟹I`-AWLhҐ\ Zdɕ}Z+|hpC6?S`'AD BgbȔ1LIp &# o\%/Y͍ sÕvtEO"`␪; T8.0V6g-&m1-0%RB(>ZfQ3@xq];0zYEE"#z&Ei!8#@՘IҸI!dtHKM ){,k'0VN$ 3J2oNH\S%0n3 B)0va߸ף8dA~Rɸ~8bҝt%پ?>A'̎),I8vaGq֖Qa1UHeb6̱!0a(Gւe 0}tKm=Q$6>,ȱP%EuL89H0rip!_?Z_dPGY6SglF{Ӓ,TAyt8~A  'ވp?M0o*I0-R_@6jçΙۂFHLÝ%d"A?"pF' T#o ?֩ic4({;:%I06zTD5ih0  N $&NtuH YX3Ёq%8 @5E-v&d*.Wt6fCS{?.C[a^N~:B@ 5?@mV dH.Q͆m5s"uϜs&UQ.J܆NsH>Al`Dv|F߷e&Im?'gּ p?ӍMӽ}8s&&~V][@ -K{Pp\ 6~Ny58#_b30YhPǿgnjM@hftl9Yy[$}?4r;s``$e r4C@~"U|JQmݹwy jy 9LjI b@Ec![ shq9BHGtKuW@ ?:A@fu9;Rhmivo,dc`eFgAWDn/tMiպF )X>`&ف `9BT)6X@E:vy|N/EnzRh, dyBl- a-@12x[St[MUfΫŵFJ٪R7!@"RO5I |WH+b\:@:!t@g>,m\S6? a|yNk˰=D̟,ph".)\ߗ9dL˼U )4UpxikƛOg R sL?o.S_j (u9)鏯?&? ?oo͍ ljۗ>6Cn周, s흁kBC@ 4x @@䚡&B , q::{>öYڻ 60 8Nӽ0{BGDPG- )zD6OZ] A=nNXO'@I'=TS=Fd}|I;!E?z=b'^=/'\u_Np;ߒ'*+.c_J9PD`-s/OˆŇ '!Ϗ2.^( ceJlsN{pkׯ?e 6NB;~" =߮nPM>}|~;2?tN{;] B/^**la-6Q>@w>6OѴ(;o!P귥ɦ@f 0ojjd@v̀IB&u?|W9z\D6(ŒO?Aۀj?xṧ?wE  O yn['W-qhdE}<:bE@'*p6? pSCW/ٕު@88dαuUw5q!mz~YD ,T={9+ieVpi0m7{'=O}}gs{,XG_:s:>ֶXj :>U7<:_x/` VY&<7vLmh&d2wPޗ=˶2e@ͱ!a|mVZjL2@0(g?i~1:2h1xF?b@jXX$%W :=rpFtD <7 .0w=H/ Ke8@^c`ܮ٢[ B ILZDl~LTA=L@ph@Ă @U0JhXNK rC Lp[T` ??x1%%}itCts0?;~$-<"Udu-:;ݟ"0$"@G24XmWfw#[s6:+UE!W'b8Y'Z6P8ߜ~͹>Їt"+w_ju:DfI<&/~F)Ш_!yC}Nb"FOOW%g둫3[gm-Zwh Dv-\ _n&`(>>uϭAUZ_~R%T͘@g WX9P@j(Kb1+E?ӈc=G'x!EH~+m"֯i@!$qx<"4~G0?b(C])6E*Nf .gՑ7*/҇_ka vr|v>`r.)@ܖ,^`; )) ə?(IŸ6ߋF_o;897@AUե|qSMM_xMȵV[qg -!휠V]kyؔna}ӷa9gngf:N=5?bN R`i#lď~C `9?b~=eAݨq,؍zi6zFd48&~D>8'#Fw9lDmݽ}ӴNƝ !!&T>i|\Z g4iQ-P#byn<Zi=r+08=?r?~]'%@m0}W9Prq @eX :zsAHQZL=RV!'!,Џ}Q5ȹaD$ qvb[A.泄sy㩤Hk8, P9F5wk?:9uzPWf-]1 (_*ɷ{6#m٩zj c} l1l΃ OG0u=fiĀq)@֍z(;G9`|ЌUYȃ',0NF6 qDL>ڙ?0`d'3y8@$=thnA;I^P]ƘGg @@Kdl֥|YBT[N35-st#sy.˱`?Xq܁Vmoõ}6h O7 @ߟq˽g 9lnÈ:A GIMG纙`ylu-L6A'/{z8TҒ"C-C YaGtP-o4DѻW$hu4>yv۾tv#z/>[̾ſP[{g"W*7\V@{VH1?y)8qwWyST4B2[e q2uY#zdkLU.V^)r%ظ9U IjP,N/L_{Imk\{<ֳ?tx]tQ9K`JPb HNBȿ*=b B^wOsu.D?9[`[}~!/ōĀqCv׸ mߚ5 d(1TÛ&20Q~Q*P< := )NNwXW :jM<Aď 9d-=x+ygJl:*$jQ.8w"on&D`!P0oxxE @v !Ou7 ;W L1R\O<`_d@ٓA6|zﱹ}|V$38X%Y3?![=ikl#Ml6[A#,s@ `W#~!iVwDۮJRnUΠ=qdcx^l?-(x[s,Ph*i.0l8d^(.W 8=7P"!Sd,0c<&cu< d̠g4Ύ !$vo'nt|-'hCپ`ol;$IsmwYC!Xֿs?uBh~ӧƪ<4~T2?.X\Rv :'`%obR@8<8s߮r,`A|\RF_X`8p‘FL/s<H>Q PBqz֫)@9~0mzpPqYz\߿]'dirͪ_6 *G24^6.`)񹵹O^N4*ZDjz1bQ;޿2wvx+G6+#e_/ZT蜠; 9hjti w@IM& T=#t8ǿ?Y] d}'w / ɿGUsU㟇M:^^6J/kO/_, yl xNǑl}A/2~S `( Xqc s w|C^}:AL:UZJ/ϰw^ ˃X޷Ofj+r<@/K(p~*{,Q pr; {D9М +NԿA q ^R?+GJuMف-afo//߾Ppɭ> ]1?hؑ'l(O*aեڽRTI4h,P _xg}7}gvF?B՟]7_q Z{;G"@# 1Z^&:A1%` v [" +;(j2?|G!>"ne"P੯@KDȨ+-eE9Jާ[ WYCbsn< y 3N`x"s ||AV.;sCOzuƙГu9CArC@yּ0^Rv#{G 1TqT5K_VEYug %+?.5S#ǁu^x_,#ug$55ˏ;1T{MPP)# Q3 $s?~\ׄ#BT(̢\ :@L=@$pEJqТvgr>~}$WK][srVMJc0B-'-i Xx&VUm7jp&k7Al u1%Ksy$hKP ?|^O~Ÿ6? ! ٶٿipSE,_.Y/yaGI5U\(OPm>5ɓ7 %@]7qd@ 0g3N 1#fcXG 9C٦Op@ߋ</|DD0TdW mv" l$}${Xٿ* ՛{M}n$m ':UZ[gB(, x~f#"G;d"c:1wrtq̺9L 'OC~D_>:9,EI{mB+;AP/Dk$$CBd3cϝ&83!~fKcTx=I<#Fr}!Ь91RX`G%āY&@xlQv#|FG-'|F.?? `]w ?5{ΌCS**K;.l,eBƏ`8JsA9 2L>jX+N~lx<?zdG5|M,@t},/W\Ix:z>3C<~78J1 Ź/_B^'l59^ړlmX@9@} S F9JD;`c{MǍn' *׏籱́t 0ʮ ƮNV ZQ)s' ŸKIy83E=8'x;g0c@EZ/_;nF^_vر_~{7}(}a37`,:t#uƨzi`s d{vҿV8|vA nS>hE0`.g^?ܞHH- _y,Mm˦,4[4OsOu˚tf@7F |J B4r ei8=l}KW}X ITva׍םӁmHf-1?PI殺l>m7x˒>"1 H"`qP8 (K}8am7zWm?"`{@DX_`Af -)F/{Of;Ȃ#"Nb#!8#?mݎEF}Q xdVzH_zw}7#xvo#Ǐ_U.\C4776b/:iJe'Ł^/2[H=F@Ŋ I6Odf)w{~v⁓rDZ'!8qYC)ont |94CuniO>Tm@+ m52U|g@L0AXN7 noWm*X P'@rm^Զmwo`,?{#!LrQ%DzhsO,@Zhִ ,T̃0lhZkJVp1hчvxL/%]`lxtLW \bAcT  EϬ2}hqغ}[,)̙3!"ϟ@0ЖOe#f&l$I_:t?6_(#ܷ0 \D/i?p2KKw"^$ \_͹D'X#}.'FG@p\[2+iLd fϠ\3:fR@s B7?˼@a-?7\ >k̷Y. {T>E Vt Pt}zwB_%tJT7~PA,3 B:]4Fy ZlP`[UCfy}1#?||G ݨ2zAJ0:)ɥSdK ^'U0pᦧwӉR?2sd TWu!N" 6}&/_Z5blZ> ',z_[!=\(;<jgC} ?뇳YgSr,9^+ nsb

-kl/3dqg}0=M3hF3'sm'ums5L۩CVuڶs@bmu/ysft u`4>`JWnUxV} hRjAA8̛YiҥPvvqM[ >OS 0ьfbїkD=¹ &N@ p0}1PPP@B f$*KShF{\i~&W4@{jWO` 2' ?LT\\LeeeUZZ:)xvQia6 m&+rG?^/ HOZzlq%Mۨ}Q i]rePYYI :D˗/:m57R˲fZ޲&ֿ 77PjaiijM̵'v_}Q[xA0F!8*1Bk[rljcL j4=~ *(#Ń*ʫN6 sȚ&4@^^ edPzvR(+++==2ӓ23'Bi122(#+)3(-3R'73#czt$/΋?+3~P&;s's[N'`-Dž1^ݔFO-Oޕ1i:T~.8ؖLV9RyC1E^ r{o9 ƥfGyrn}[Z_W<Bl/>|a@b\8%]@]Eɔ@dd$ E1))^Rl~Ȩh+ZIpR,g\LBQFfp'EF'21 M gO(!&;猔Ms#LX)iCG+a|"5jԒLy[ь\"=y@ ~j iƀ/ !:bB@]P_]I٩iv|BCC),4C5^vra!vaW(?&,bÃTηRUpX]1aA0^'xd_9{,#$@l.zo] PkU%F3ڣj+9HK4/ 6*CA  ` @zj2%6 ,hKhda}c@~ɚ `fÃI ()8`!1,^D/v+l@u. 9 'KTW@@KIB?RXwa/ov<:ÏQ?˵3ҕ{B+:iVZڦ5n ,_:%MQ $$B(v2Ph/p6͛;̙[^h|(XE fܹs]u8m+ {bsK評%tzLY?_ e-F3# x챫Vw.-Vhw^X١ZDH}̞@\,FӒQQ$͛K ysZltΝzjGuD9K4~m`'V S SHkm:w?pֶ*/-øhȟ 7hM`X4A9u@  LS 1 EEDX>-BCC]* i|Nxe-q]Nי/~럪Q?L_g㩮bV!"h3'^>ïN)_z:@@.; ?v'B-.Ɠzjz gVO_ hLh3|[H^GK>j¾`i~",zܮVcG{h s*kXVҷkSj: %h3{S(5TM@3DGG;{N@l0 %&&NJfyFwD =Ion 3^Dw?[H',=*l|ڽ:o >l4,[9FMWۡv*%4@VJGF R@,TUUEu߫\mHԴk5,TSK]i&jlw[яvO{ onEs_3;Tl޻6ʆ ܈[ь6cUHYHpAO ƹꪫ(+ @ȸâ JR~IW*(Jť˩#QQR|,+u[h?eO:o*~ЖS  ?< }gB@#3hF{@>[P0HD !R!%$3\FUh+ BO8\*@tD8xdivX0 @NN TB)iɺL))n:kȕΎJL9H)fdK[_=xr^yY1ݸnS-KuN0ק8/ 4nF3ڣջ\P]E)IQ!RZбSJjan,23 Zx͚;@bvlS 9.bc.H0+Ĕb6; 's%%P9AIѪJHӌ8Wljc/׆~S_<7i?)nʘ_ KbܢfG ?ePUIiIlml pMDdB-b)b@AQ\1\!eJ vx/>2LRW;F 0E0}|"Ùg k/Wo-=94OSt\|߮(=&op0BXIH 4nQ81pVQzfE&R\TY b"B] k9$$$QtT D8d .\@P [,`\}N f @%煿]tx"Ojt0kȞ$`ꪊ_?-y~.d`4?=$Vӳ-=0)*.CE 9)(N  (0 f͞M>3DV=_5n[yАﯸR` |fD 4J ӟgEs}i)E>"@B"8 K| $m5͖@VI;6# 1gP+(BC. 1Ă>cO/}$]4|xj׏?`0Úﷺ{7A@?O>1A|000-۩kFZaVZGm+ePWW !9 0 pyi)WPYϪX[s,ez+yaOŮIi$o 1YƹAʀ0{T ?J>V./:4F06$;DRި,f0rfhnP{ vEwk޽$|) O??x a;W4ZjXA- J S hX>T9T |(PkltPC#VMkԲfZ|Zw[{oeߛ\mj]ƎZ꩹jʘJU\[Mu=o+0o.Fȝ%VW;Y2Û 㿽#*l#h {L42Pu~;;fv.P5;B`4'Fee޹֮clXx2զrY99md -3yJǘjP~~>#73Ӯd}L,tlRR'MI)9JeOzcSnF夙'%o+HD.}m?d`s+B(.y!gưxs@jN0>4Vn30##ML[p9BAgqO{z?.o[Im]\U7O:z<ZVvmX>*+۪ʟ|@emmSl[_R7PWWk Ҽ XS:BX'9). df琠R(11}A T7q%@϶E_sR2%Sbl *3~X-/~'%eU44y-+SYe=aR`&;7̘o;u1ҹm_I@z.ΜdhZ9s|8_eqCCPH OAΊZpd \ZaJ}9k ZY!wF5k0ppcc5ZK 0=|YÌ2B @ISDZ+UZQGՍnh; p;7ëQ1PBL`@,3w\fђ48- Bfx|Gi!ӜBJZLs4oτfS|Y OM[5Gz.jLYk<y"nͥ%^WDo ^e-!ZFsSaIK{m Z-h-, |1,@lt,EsD%x\ga7o.?O ^9ٳgG_^wrߜ  O{_HV6iXA:W K1%})%3gR^A9W/-"o>> Ό| / )INmņR3lNH3DkDEDX-BCCdTUZFn&u#]O`{ݻjf4kUeC_0aJ*PWBEQ%/u-3vZ`jaaPmC55QeM bfEDϳHλR)1@!>"@\~ Qt~]|k(``))]M%F! \ 5?4O^׌)șFȱRN)QϗSlD1u@jf"fhB^<%'F.+r%A;:#Օ84 Y* i B5A yS." bf).> @;b%3  ![97HrJ|qLд8U&%nC4w令G 3[+XXJfjB\ +DZ-۪]~B@Ki `>5U=D{ x{ 1S qA鱲g'Ȍ]_#>ZMJrbVmEahKK迥d$F3@h0(bi E8o5hj```ހumiyELLL61mI7Ka{C~RľN5 Gd *=OoX40Кu\ms%*|VϮG?~?߶mٻ+=UEe@zF7z #7k1ڠSp@7Owd/-??@C繭94>׿|fݫ,C' S/;2!k Vh~dsjwΉ^g;R;WUx\>39lD2T-=ٶ*D~lf~5 =ţ|GˆB aPQ]61`ժUC)))(8P2 !X$Mը k!_raJk?Q 7xpT Xbsc.6_Z>0P\90_i{xc;l"E]eZuBU%=*NPWGu\@t' ˥>Wȼ}K \Xa=z-tiglb^2!M Gu;,'Ҕ@,5? /3^|L:\3g֙?{=6o;w|#>ۣc?rq_K7u4Pc{ښ 0m%j;W%Z1 nvSV-wud-?//k4!@0g>rBkg;Q?agp@d>#LwF "6ߕf{`Mͱw?b >Wy;0kl9 ){H< k5|W~Z}XX q!Bx̺ 3g4ݨP,0w:JPPVmƍC~[ wG#_۞ v w  SSrUl33X2)!)""($$ӂ)0 myK 2HMMXK,E|'44t4222?)+#kA@b~ \S]XHyMZ?4:vܬ' PvvVǺ4X#bWX@fTciYNUJ 2h@f4 :3l/:F=+@> @-PW_5[ 0ȗFp :ŋiܹHǰ:>l{kQQSVVs~QQ֥K֋c#((<%|g (xZm/rIFT\^OcsӶmۨ(A;G,S#/V4ь,!ooN*xu@6``=2lt㜜̍32VDDTVV>0(a%vb8Fhh~t;M]Hc]x‰yz_y酃 (9)GOL޽{: t?TQQZ2hF{ { lաff=n Vvoޚme`eFfeƜ?CRR08a#z'J>&"b|'|{c[G?q Li|gZ4.@"߸z^|0]8G-Il`Xe|:`&JRniz種?2hF߶~f\ڧec˖-S* 5ĬɹWbcc7ӤDCESyhh躔~ ת PhgǍ\ffy !… rc Xݒw9ļEqysgRoo/mܸmG:}{Ŋ+YpTS; yL#j6 L7` ҥKEO/^ P`ʃ je> ra_ >Ar]?t=T=Kc0@su ` `OcZ)1|q/p8:]fy3VB{O…3tj]p~oMgZy6;:#Rqzh0Mr)ڷo[ 0L7L-pc\Q)ø;^Kڰa_ 'q/vV@@@}ee寚BCHHH9|~$a HJJo'#GpaDDD?7]vAg#>;M]s.h]M/_C/Cm5 bgp@qq0=S-Ottma|$>.eepʈӕKtAh}<~ސi&^{iΝn?$lڴy6#6RG:2H[~5, }^Z!4aQGs".<*)BA =0 F pB?cRDcPm"/!&hMSA+s|,1y̌7_ǽ$G5k y555~z~on7 YSO=lݺ7@HW"+AqE :ѣ<[)<'@Att$C|N%1cB~E0\̞Zr~,3LgMislKj o_$@ u1i@Xh`+FO ]Pb,_(v"X5P9u_m-*qYcS0Ծ42H!2s޿qm?]{8q(wx2*8PzZlwRr%Q('0@CCK(((DZ!48@QP (.]Ot8z}lkqDZ'/5 <]cx5u@rbJ!'QFe;ַ.+)Y *3 Wq8֮]K[עPJGjN@Br%?w(_zZkk@䩓`4v wYJ;Zdb6+FHTLֽGJv0$1j C$0Z?aa] > 9- ;#@Od_Ov;nf\2mc*N~!@J^~uPHX]x|kT:@ b"ƵtqFp XZ).`FSiHSQM6Z>~+_\G++&iv^[` c׾2Oj. q6׬A|N 0֏+kȝ`؞[ ]ڍ~^C/)Ql6^S/:m@k8Q4ߟ/ 6% :lހV D7 R;p,#/@zeL9ΰؿ,F[`P3m.3`ѮaJ䨎'z_=@Ghs},_dx1Ǩ|k45sRK~Jd%&-S e`4+o`NW-m+#fg /q@o{6x.}m^#4+j+]v/HS_ܰ5`J94XB]ܵP X+@_%3@YA&UZhe\ٺ=5π)s s^9ƧJ`PBWv?W-@ZP'tGD*n0 6 y?T?1{x>Mʘn s.GL ( Oofv _;R `Z-n=̍3䧙= (SՅ<Ν4qiq/eUs76oNjr,S7^F„LZ.pb?G:dѴVF[8y?BfD {u؈#DXd:1u.׿\ B)@fv>+/g?K /`Y r5Fv7u׾4ǪH[=/ln}xf)\Exn[ @snbFs.Dҙz)6[x(%Й3giߜl(>y-#|/,7r[Mn^V g4s_| 6j^V )))?1IF He;[Gft^3{JO2(+5—io.p|p|ȏcQ7`apI r4]-,Ǹ+ Yl?[Va1V*Zj͞=݋Еi=< 7**Mҽn +{n@ڤ#wFMNOғ͕pF?A}m̠0C.T Ìq4y Q;}= ZFF"inݿCý{2 02bU10(GnX{&o)p1}A*QS ( :::?f|?::ڪa !xؑ}m.o ^J%VM<{4hz2MMOTr Cgtnz+ 5 7b>P ];^WXTߗJ؏cC>mpnl p>lAOk{ŅϷѵTV=*xxu\\IUiיu@\lXlEmmG9P>e'hooDzb؏x{O`p6CN) vp{cn2 .))-k5?V #F?AgZW^=A? r$GnHPS "<0wH^F el> %O@bF0*P3A(F+87w_/ޅ8 2sgmEYct 7C|%?**ʱOW?63h;'v랴Cޓ+rxώM_j6xi7N~@߿\g Z2)#/=(t(--()$#E;ȃ( 8i! ӶiA&n{O8-V6yc/&`4vpC(v5A"y?Uj`4 ^^wkLSݻF (9=mvM=_C )1=NE,y qatJcl?iuE9ETQ.x9_Lp+虭[xA:Yӂ祅. Ӯ]x@CCCFSkV/ylwkA< 1L"%oH3|7` @`l6O02Ri+`umѐV/YO{F =5;"Q!D{)IOi8,[kGі')%% oo1ѡ\G;w<`f/`Va~ 3g (ԴVU;pe\Sf ۼ/@PYY9YwY H$pڧԘ{7i1 ȧ篏1Y5;Lz-l;,jE<0(*o^ۻrzHj"ƒ+i.>/#jÇmq .`4l{ -%W9HU?̧ 'F픚)ڭlP@ku)8ӯ" <A@L ܻW( Q902(_[7T]{hD,4VיgЭ1nj1{ f SC +R#5f 1բb@7ᰰo`ǫP/p$~M#3, 0mmLcSB(q(ctxS_+bd8%?媮;Og'PlY 4rK# cJwv"t'Vٳ*//\W\81i~*ڣHSJ7W^OG ޴`iMٞY^= s%Ep~_n]yaq_Кs ?/KpKHD!X I*F]~.̈k@V?}+>a `E D"@^A|]m*shQ.Mx9{=}ʖ._ȧ:@~^ {c3+,,DZaFSjylwZYڊ$~.:fB@-YC[O|f#‚F{V**.kz& r* TSJ]c_;q-HOzGۊ=sh3Õ $#;fΝ-+돩]c'yZ(d9{7`ߊ= I[-|feee  0l2]M^^ Qy?hf+g@OEԼJǷӂ}-Ut2~&+;i5GD:! ݻg'Q?۳?޿et ` wdT7ۗV4`{A~j!P f 3o p!Q(8:ًh?#ezJҾt m?^SxfSMaS_%?k"r?`*Qto"j0] B8F? |uKO!]_A/ 1=j+4ӫK = ͔*׬Y?m`m##ht4^8.JvVM~ i*/\>JE {]t{r]H. -oh+F;997%x:!P 0m_^iE ;-O,D! |9tfg!YDʁjvA@kmȲ0(//OҖeSM9s~ßŌ|&O8v_OX&S\A~ l+[c`ۊeeez J"@H۽{7XTT'QW,FDZ_`ΜهD-3 %<< HĔ~"JK.GP&oۖ[lԄ회xi1@^:bJI]>' ~z7Һ|M`3-\$&ӯ  |hK*8dUz Ɲ;vp@aa?PxLZ{C x6!`gz` YSEʞO6~jKY4_ '+afwQyHo2{ +)pmڴ/#V:׈%\{e3)))^,^ @?ڵK5m+*+٩ mQ\СZ%<~>{58vz<Ooa}.=E.ƕ-\K鵋O%nxF0 L2ExJ cHO=dgm+TVVmauܹzꂯÛk 8 X,P~V-m>uVrJKK\_O}vqPY~f_u5_"~ڿȢkmsMUYNM vC'T7,k>{58pUVV\j+е_vڹg 0Osvq^wW/muH.^J7R;dGa اLG?u\/aԘWĊv( ƣA۷oOC \0F :x Qx<GvttX_cG^o\`<>##c  $ql0v0Ij6 ;vc0 lXݮжjnVyQBhMtUߞs3{I裠>gAd''$۾%H/~{9`ۖ322ZrЮӑtߢqEOjD, &o-|~]u/_?0pKpB@  MCxGaP+Ӊ%{̆aۋu@Y8{Ga},(!" VUUmE(//{]P X\\X%<@7 j;{pAd''$e&IUE{/]]],Uu }ffnUK37gml s7U* M[;iC=L.Rc_rp}|[ Yn,B-Mz [0na kTQQAGz~\r7f . Pqih lX+bE$N8;L|"ow@FaDg) Jr/͸/Htb&/~S > c6#A5Â9rYc|Q @ٜ2w=)cB;y^yΫWVwU5ԇtR6ou4ӱ lf\x#<7&_igUVV"}C_ʂ-OC`,++pC^]]gj>CUGhY'x(@,g``W𙓖WMox)r+iHK*V+1{ f8lƮ׵񠕟^<#SYɓ'V^^n KcLAgѡ@h֭>QSc#hHLL P|/0xS*[ HG?>-DPߴ5K1 y(_C{G`4  -jjj;vRRSS0S4uIr>Z4[5EANg \~= Px~ٷQڙjޟB8= |=H0A/~Pp @K0YP(ks1SF-Y:a1*x0ٯM+OcLHN3{o'$ ћMgN1f. ؝Vi1GLF.3liYin=E1 9uسFu_Ҽ T6&@m׫K鵵cVW X2# PP_)q$wi[qi; >PZ.f@ @;_3n\{8erj?y(}0n kQ؄퉯1Gh|r]Gi<^;l2bϏL[Ʃ)X f,'B@=>/ L:}1 t3Zǒ}w%>e_KM?';+7^ [-6579{tq[__f7?_BՁ@ߠZ7g 4JOOF O*WǏ'\WJP!9!cíhಲ*; 0R@m_o}(aZ7_eɺV8wo"z}àI7c4RÀ@WZXBϏ̹e%@\!)ؕM0mxy]%$=}DL L_ZÀ[0\_;~[Ҷ=,>x'(&/QA+! j;QgѵkD=^|􍇋e֭@ ?D;hE Vܿz~R@EL~DP5l`#zߞ!`־|fM,hcE$u i! E oGZ`נڪ -ʡPBҚ'* PׯhAzWD"$9=Owo5 2ss70 %zoՁhs.>PtPSS_b !c `!,؜O̽G/d#'B6m,+HZ> }*AWҡe< JRW{p*2}z ^~=}S)]Eq#C|߻R1[e9)*~Q9>uDҰ & K \JHīx%@_ )++J/ Jrfp:;eaMX%x@9w"=_U~ g5!'pq^zJ~k7@/?0b$'d#Y^!kh@pj}.J}tôy[RR螴{d >>n`>^_UP ŇG὿ph '|w&k+M||?89ŠeyoYA}yG;n7??*)XIENDB`tiled-1.0.3/src/plugins/replicaisland/titletileset.png000066400000000000000000002034441315121121300231140ustar00rootroot00000000000000PNG  IHDRŐgtEXtSoftwareAdobe ImageReadyqe<IDATx ty&Wwc_ @p_DRܴK,oHdG^cَ('ɱs̜LcOΜ{9y쌳8&fEj!ŝ A o]WU)O]{o_ADaJpC߅|Iчwqqo (Z`x]U` vL8/  'A+7|/[|y. ( (E~?&3r.B_Wƫ~T@ (Z4 ׵{/i!"Cd M {|?q7 P@P@ i>xu,5 囚lQ O ( h1-91{fpe0={i gQEat,P@-) ϥ_5G4[S-a5~bθ R 漟t* ( (En^moy-Aj _ߘZ.@4}1Eӏ)cjT;3wS (Zp @&?W|uY"# `p@s 0=~R~LjT8Y:t  (ٯ 3 򴿪 "u0@[._ }K2_{N [ ]@P@Ky ;gk _Wҷ-;^lYg\^#3 J~ן<ȵ*O̴x98^z ɔjDkE vvh~Q~G?OEKNh?iў%vPD;"1юvJ3:hmNvṵ9\ӧN8}>%gLO;c|9sΜ3G:sv3w:sݙΜHPOZ*dX,M,=8*Ef׏yg"}גM<)ߋ>w/'ߜ:~K&d2?: 78w6@0{YLd kE_39O6O?9Z]8oӭy5>cM<=3Ȯw;~!LyHo=PM,y ];A=Is;Ebz5N+HD 4]݇jX^A7C:ґMϦn vOp.lPmip~>IL伪n2u3uc=>[fm~XkzS662->S>'Ꚑad*7yV>P3d?9F9~\O]C{&lFE~?[ ?J9Vf8lz?PhB;5"\2tl}n&T`!y}=*3;ғpMg@@@ew|HgԤ>87o0;si~//s)-խ%e?-G]]:#|h ff? f7u?97ku5΅M >'x ar3]PIm/A7߼`&Ix䳇>G fCз-qiZF??T@+MWAjp]U_禹c/}/JPu %:c"T׺O{RO'̑$[QǪ&H' fK΃|>#:4&hxz?f?\ӭBL6)J~z:nZsѼ#S=hOVz brPS^fĒmЗ rh \d.Ⱦ\U&t&'9uۍ EsA$0q7sq9х\Vߪ86[ ~Vu~TVs zԽKVf?i-[ ׺.]in~" "\-BVԹs[ϛ ϯ>~4|.ƃAϝO"} w44c[_=\\cC|^{uuLRU7Y,k-#J9keC(M+ VE+QZ򷐒ȽtTk\|Md`Wژh# +euڈn'uPH$t-ͤ22H7j_x6dK&Ga)l/ٓʧfS t>>{ ޲!BR ?_ `g#콾 &4 !02P@4פ҅[~:Ӹ_:Lݲ4cw+=\< (Ԉtݿ%B@ ]?ZdO3G~svWu ( h,nˇ [lc pd  P@P@K.܄wT_je4c+XP@Вn{.BPmXfL0h ߠ!P@P@j _:__h p_q @P@"pkT_@=2 (3B?*eSP (tzb/ml@@@P@K鱙% 13׀ (Z@/\m0ߵ ! (y \ 5  (+>U (;yZ P@P@EXXׅἍSOڋ> A_y/ܖKC|3<auϢJBkiMt@@~o~3q7[u57_syjiiYtdY)O<Ē YL 0@T }׮]cǧ{7XA s1Z =4}/U!1RnVJP`h7>СC # M߃9R3G~TUm c6*S-7YZsy3Rg `^Ǻэ!?CK*#{ՄhZ0'ԊU:j1ó$ϝ*(-rU3ֿӒXTMU6:O<͔pL  Ч3d&}¸oyިsu_3]3sᚸ <-ՠlzcx%G_W_53YoL_+hhESD{XGEh"Dh/hvVѺEmH1&D-&Z\4Sioj_19cwΜ?9sߝ93;s|3[uŃo$F~{-ZXp __e1$knZ[[=)C[I'ONM0Ք|ig{C<ztOkJژɜ[Fgc[9=S? s.ӵ^{5#sk\ΙqA} J.Q T4j@Q@RkvjV:RWp>tVd`&y,Ɓy5UIυump""IZ>0f6f;~X*&3}͸ #3//>Ipzw93 @:X6CÂFj-kK䎿83Ow>Ciаy7-U U^Y;M׊0g^ߣzjԹ9{WᅴglL܍0}&ZBZfz ׾ uzqMC=|a.ƫ[TqAkzӕBV67pI=dbNOQ z΁ʼ$cxyW=okA+zژɜnhLCմ R;]8:y.\Y<^h >oM7'<&Hf5Kw-an?~dEj@+U9- SK PE9q g0Ow~kE`6JYB_EcAd|&56.~'_}w)ոV`LRźgKEsiXW\s*o@1JP&E~$.NvAˢ6((Eiz& 3X& :c3;s#gwnNdTF2J^E[WEMӣƞRݼI@i Eo럞]@.)n+oewd6f23_ZB@3g~vg e!Klƫggzsi3 ,e7AܬvTUKBw;/-]G~# ZXV~xi4X46ӢKA|Y7cMTKkZźgM~B#4hَ?>}LD+ix]*Zheh9@|:-0!X.7!fd}q6A!NJ04>XUMF1ȶjBU͋Km&Ml3e69_{v=W=`p q \TnƝ6광kP@tR,8WSZ*ԋ/ݸ,9Q-`P@T *!ܥ$>ǯ xe ( hIXtպ 9S;K7&sE@+ (m7]NC462 hiӦMtw>馛(778r4M2\W^y^xyz3YQq!)dkD}wW݅P@-"A_oB `Ecd o9!QNNnV瞻~.^Ld@פ "U'PHX>րd.o^AnuW@@-2544<@CMcBZ7 ``(77LyTTO<W?&5k@җK9z_^}) ve&Nj E,ÀZx{ھ}uuuQ0Dirbod :fT\) L*-+;VX9SSStMe_)ÊGs>>׋x>B~1Fw1D]*ǝ0I:<,ÀZXڷo};|zH& oזM]ib,JW8SAaY֭]G`ZR(*>O L!|CU!jSWOjiA@@- m߾,4>b׎7e;? `NFib|ˋW Z` hrEQ_4iz\Y}7=~]O(_wL9璛%}%X0T^^NFhlԴ &~[˷ #hX>T,$8{ UTPeeo&}>qa?innLkS /\ZoM:(<^ 鹴u>ܨǴߨsP@-0}K_Zf?|m-!>&>ڕMqX3d R$Z{>:punЎ;{ݻP]mm?422LP@OS^e0`aEAgPf5 w.s`~ke (BC|ՒGϟ9ϧ7r*7B *8]0 @Y/5\J |S)JuzοlaE\/0Umn $ڜ9@@@- }Wo{hGMRj>ӿIł2kO4}7?]H)E@ZSFh:+.'.~bѥξ/V7twЩS'B ѣY& h0/4e/ WWht/dA<``|n Ch  Ao&ʫQSSGYC¼'‚B*tx49Ar,SHEeb9~n*l !xm*,>M@Y.WE"XVIXTI|D0  @9__b}\vػT(* MvI%K~j˨Y(:Ile1\ʉ cY΢`K\ Ѱmk;if})ra/5 .݂Tvn?A~ KCWKʂ~ha\[Q9JJĄ̐m&p~SYU! tǏ??3<2wBTVV\ƞ+<TTTJУ>F >s"9P‘HʕS[@zuq9BHT+WZVկo>/Ћ/{&Y7Bo|sB:BM2٨5t^ |Z3xr"f)icZ -»1/P__/kSp~J }I"FF& hYE55#"L{PDOtПB9)," D\#94('7"T+qwy7@KzI/Ft*J7lgV Nɜ~)Ê@ {Y `R2@ .Piq̅FHMsO@0뮻wwuI<4B`:BjbfxG3MF"j0R|McqҨ$d_XCk]+alA_E laA_SǾp8WG444s RS]˱06Slb3:.(qB?*j%f 9]mӞ VH)ѧQ*-)MhGlmoE۞0H(Ktww̟ 3,L͌?ăx3X(XV+";hJeq}3(JBcbbL!+|DܗH.]|d^@:*8EҺ$;Ɓ07''O|/ѩSDz:---Bxʕ^Z:1GW7@xߏMPO_.ѿW}} 0ĺիPGGu 0 ] P)=U) +yXt7@@cn2㏻Uijr#eA|w6a?1ay63*KɴBs0gSwʹcBG rXwCO<}[ߢg}v\ +5jKXhQG#K.d#QO%>'6ɔ!$3sνeY@& S?zO|6Oճ>G XP,R,n}> mk0l[d‘g"o *4B0t̅@!M@o'ii!'Z QA~! |.rx,bcWd?X`-/52&c$` `$V,<~u3կl丌'%IƿXɎB}[PRA*bA^+ p&?0Vs6TPz <8RYطia-rhbm?8v2 Q݊F:|-7`z B?~?[><1N8A/2gXxV, % ҟٟ3(w[n𯨨 Tc}ĽWFvqbh30-_^N7! #Gd7!jÇߦ~ȯ֪ݖ+&\:pОƝk@rFh1 7,E]B˺L7֬]Kf̢\錄"?U|:[~GhvGHw}O2zۭۚD\,Irǹ3o ڨ؎_1Ď1`c YXP (&+ɲH#4\c/5s\GV sHe-B K_yy!:=⸑, `x1`UzdpapΌ~\'QU}}ļ3xI X5R9,CCtmQӪIq 8Lz5P1Kqྯ_`e@H֥_-#5?a1^>kӠM:`&yWS K`Z)N96l-\WKaf nle 'B[)NŝToʼn$;)+B3x &)sc4%22Y1A0@@f~ b| 0k+U!>E~jS8Hw/2=c~gI!DDZ_R}ܑU.aScZrΔZ*[/,*E,tL5H0UJh=U~@˝>J.uя7 ;` .; Qh"NTj1}8'L( \)9yBF94+19Q׊%<}BSg-eJRh0ΘG|Ǹ&05 +!%52…v?g!_aC}x {\T[Ś+1 x ̙~ /^Xg.1[SIXŕ:gH":u(r_PSs{/\ipX f 9!fIzqz[tɘf276'Dr7yTf`AC02%^~l~ߺX6P7kcaz{{p6^Ξm]+²[3O4-@@YiYSd{n  h>UF_ XM y (.BOB%-+fdDBOQ)r`CAҲe},SXC ա !kㆭS30tw W:vGАҊz6dDOؓV@M}NEʇ-.5aGGSR&> ,&/#3-lh9/_cǏ HMͮb?L& 7_͛QN@0NW'˿[o63ĵ$POX@{)}}T_h 8){|d}[L!`ndtVo]Kmm4XUҸ>Fcw@f6|ĹOAȰu:TtzoA@!`# hX.'Oie- ~v6_-:z/Bu*nA5A HKMe˪hݚ t5%5^cEUT 0hJABl0]JqMhzTS.4wyG! Lzٍ;v,5rUt{mMTN>A+WְyYK5JG&ΚZFͫia͒_PJ_WD/CbrJ$Dǡȍ͸8ǧ!P NYvU0 K(v 0qHD?W_}^ųF:&`.#a{~b󝙆kc_+96:A͍kh޽\yu xPu,{(柭8 xiE366R v H >\1^T;׭[[X=yXWOfe(TI1(Bwb-q5@'ni>Wǚp[unLhړSY%(E'(/'U Qa<\=<Gw%HnWJ``8bp) Š@(Y-0RQ~ܳ ]-@U*u៶/hooo__}{nc_K0kV+@ ~b<U'ϲ}}֯NTzgvC{/>(L[ QN֭4>q%>٤7/-fJohA$Ћbu>C\ 09gB6-MM-w;a'?R(5_d F yy [+SĈ։Ȱ' _u~ȱ+1ӹ4'o7qQڼq#UUf=Іm=nZ+`ҧedc~ξ͉І驧~B'icno?w=qa붌hJE"`P$@v?Fi|lW7ǰ?2TArάZnѡQ.H5u8?/,à zj/RkGfдAT#+zFo@*8B2G+d"CcZHMZ|qXq+$@T^5?UMdkd5ƵTQWV pg JfEʼn #Kʪ+aԞ.=|S佺Q=44FOHo<@;oJ3/P;'`IK>v|aFZ!1`P8 [~~D0Ut-q'z{ZP/]/Xi&%bNlH.@sۣ4:2AcWZNjj^4O )S>z6۩B xʾzDpeϢt8~ m42(WrWr̜^)@qp-&~Z7]jDԵ ;x6'&a$? 7O;[.=-J}o8&|Lso|K /]ꤧS6JnF-9fJF)x :"3ĵf5Z,H߭iys`z4}OCثn34S;<'ž=fTEI6lX?Mո1CT3L/ !l=U|´ך%@^K0:|8<8&R!$̙S7ixh$PN֭H}F@`fvGo!lvƬOFSahڲdZ/GV>ZfN%,t&u73h&$AVۅY+$Tar [^CNm˲<:7:uKS@+76Y6 y{Gk5* XEr/&4twfqHs@`^JϷj]L@ۅB׀%{ި[޻&:-ʕ+8}|`b&ta;1ʀtB8bdAeP(!Xdž._ooT+],5]0c덃?oiyA M4kƹs?ȯAd{{ԸʶYk;4=]$oq|`k^}eP˚::y&fHl0lw=syLƼg.ڶmKT4{W,c>(7ĺYq7P!>_?KK+}s$mh5[h"=\hDmj8~-Jd!Xz@GNP`a,q?d`W,?vjhS IweЯoCvjP-XӘe%GQۅVoby L_۸[(Pǜ[ML3;PE+{>(&=іMET9F`aC]nݺS$m޴7C pJ$2F*~Wļpmk:X,%INSt2uK5 ^)洛MO?N<,xE.F@aLM{4"?a ps]^i}nҖ.@`(8=[_mMS]( &$tC-p0K rg6lڸV;)ej6a{W;a5nHucr18~c40ˀY zîU pᒝ 8YݼNa;5{1!>/J=K?{'ѯ}䣼ZB&c4bi>ȑ9XOtiv)d8ljR6Ae>"t OwiD!k#fbM@w~=pC6kNF!΅pE(k`λcN{q gqq9mذ=U• mYL M1Ϗ;!BK =Z(rnR?Gܧ6]B^=QW%*8S̱9/',[Kjjazqs逺 p;.u "iZ.`@'wcLO];ob_ږv {jV&3~R'^CS)+)]do i2oJn=Q(RRo8$4p-vOt>GbAg70_7Дؚ;ǹ3ٻ-Zv!n^ZYWñ jS2l!R#L5L@??ySh]}Bsgrm6`MZ\햗)OCCtwGoDNu-QT"LʪrZ֮kNOw>OwN 7596\6,Q}cPAouuWEDjx[ [ 125h)6+PV;:p2hRRie>X6VS[[577,Iծ5k+@sΰnü@JOO}_>@Og Xo.u~B, @B&4ә3gxq}]D7mۼyo%w }=.啼yK"PF&)95ϖ$Ў!W00-MAҍ1l9'6ermܰqLyeĝC?h֭~NZ`\Cqϓ좠Qiy-XmGΞv HZ MȀЄ/9 ; ߰? :W[f_S+P(p&' k&'{۶m!=آCUwFuonuk`}\IʩtyYT,e`)t @& M_\Z^z]O26F7l;ZMJSaI &ת}]< nC) HצTZ *{ IbqV mk#fͺDfflNDtBȰ9w^7Ɇ=6F`hؗ={GXajqFQT(xĜzt^ѱa_(Q( Lx!Wg۱ckzoLcGneV;Kc \G>NO=MeBml]xhALtY؆k.խ79>&=Sڮ[jVΛK)E2<ܿ +|[R|TDg&u~i ,}=wǩKTC6ziSM},u2***f$VfNE%ܼN>uݧF4 <7P/DFmT߃kIu />'K;?ڴ\H#ݰw{,n2OȖD¼&ᶉg|p, ?8q~gKb=vϕQ^&@l^r6l ƭ@6z̓}-ݷ o-(oܱ5T &Afɲk8 ;yL-0g(=q ,39wЬΝ?G۶aӎ|OW^//Y0&j!D|VYQ |?-r)N{O#c#tw  Lhyŧbl u-k'`oǛ"x;xg+h ;ye"|g0~/\ΏͨL6 o1KB٪&j4zu#-4!""_ c,pC0Z296H`&lzxlI_xŇ5 5ilt|Y:A_rU G`LyW78V<ϡܐRKHn$AZBmE,[򦂸dz&ց0Vg5ӧN +ajoMqεM-B_޻[*[^E{nтtu[[kZǎ@ 0q0G[1Nz TE?F= _#SP{:Q`v6;Ik_J.dW|+--J3~"ϻƝ ;}jVԱ}{nZftBܟ>DUׯRFh\L`r(]7lTqG?R 1@D"i+}Ga6Q~a~bꌲLsi ^@5-mǓ H:_O" v U "nlgnnD  k^-*gy̌磽]0)^EEt݌WӖ7Є@㓜 3x8 V75` :fZ+N@:~(+/`! ~I%!B#Gip`^~Eڲi CH1 <7gBu%ieE%o nSs'xaV%wt|+57$R${L *v&4䶮!Yf@(3$GCwUWr;짋~hd_~o'YitHr\`swD *ItdS(TT"v.ӝ^!fN8vlƶ8VLf@ FGoc*~&N  aKu53ۥXSd&M8Pl-ZVj3}@먝27b>W7@$c@&Zy>ޕ54489jkD Mzt&&P(ЙṆJ0Sv1i%S6&vr=톓AV966; 1L}`tIQ ͆Mffz0^vƖqFÎ4lybFa :6u#X x튆S!(/D?}i9!,s.w}ڻ;1ETZ>ƄOxvcf^)v\װ$0Mq:|GAOdF:MMTTT$]邓Ӏ]j Jl w-t {G>R:;q4+j$5#Mg;h#MP !*\؉eNx>DkֶpQק8BƍXn W l- :/|ȫl&υtM9|ټ_88ogTU]q:te4OsihZw:2 0)*F:v^}oUЯ= Fsv~q<Xpy'ngO/s!%X}ⱘ'qX =!0jg7҆ [6uyȀd%\Ũp$P^_GRCο~-(Ҋf7RX@7"!X)CT fuBར=.,,rQիK0>W:c\G#9-fM0.\NWodndcj$2 @m|b>y6ljs9\if@-/LsԐ}|V}ۅt߇?D͍knY60wux` Mrbw4xưG'^vM !Ny8OJhki$X̾R_6nj2E˥BઉCoPSl sj p|`eD;kBʨ7rؤNĞ H!,<'3Gwg&E18ף B-ڰa==ohc#rJTB|`kQQα6z] 0 sP "kQ?+mv& `rM7ea5PPx'ڕ`Lcۗ| 67y] _پRXSV֮f8L/vPo_7ܹ/_wìٳma#5eXˇW $,1 Gt43/Wu`9P+e0rd@J+X{Cty.E>:Ex9kkBmIa5@NbdDمfW̫_@WWM:a))^&$ $l9өhXl IÍ;q-JIR& uUT>q)6P1'%|5Ʉq#t=k1'#k%ga+KB:Zv=%et`Hj@h mٲ˪(lDDPѣB3G~ӜJ'#kafWR_z)v ?ô]r`]+W h;nOf6u3 =<]ۡݴ%QkQ踐q-.ḻU;~N'|'K_?8,pRX~ 56b! "h`?bU&v|ravzX_@#-_s>D%S)zEyHZ{âV ֹVn +asSΞriP?c1g Po/4줭a [gz1wطk+If1\ 4$'UYj@O"؎1d*|j8 QC@fp%9`U&shYeX Ŝ3`_ɴ`@f讀Wk"D5>{,^彾.wёwwߛ\( *GYI) x_5TVVAB+KJl~x]*4m=;O@_%Bh*yD"N>錙(RmDԸF<@_+Q t^G 6PV[Wß1d0||Ѱ'0pꚇdZA^p!ỏGN!ϊcA?u]:'` saѐki* b|n A7IFZj赸ֈ/4#q1x"^96HOBK@SfdJֺƒ(ױv+iDU&21Bn_BX'X8[Q_/?3&ƣ Co`crrsik&¯ B @εe+- "**Ӛ\݆FXPBa;nXȅ A@Шo (t5+o7>J+Z?ΉWr] 흣8}{)S2l߾[IdV8p:3 U~֐Ue 7t>^ݺN~'hNDYv~'DŽ*,Ĭfg.ӥg( $ Ldʛɚ(ךHJI.ڻ}@M_|-^=d󂈁aa#ˋt+BN۷v6_'ehuwJ H\OH$Po*M r=a4!ZurWڶLj6K\5Ƨ:җ.{E`a*h<.O|s4$)`U,id8MŌwJ{gKhm2{C ?.Yp w1FqUQP"Ur3::YW))S_}1(BN~^,m,@X  '?LЮ]idxTU*~0PC R{ I~^h!%RdŋdE'Z;щ41qAYo؎]O};6˿ۊ{4;LI_+f@pXxLƆYkd)@f#tlgٹ< )g3.5xpHa\ndBvv)͜G [QƢQi0ჴmt;}䱏p4j (ID[ sߡjkq#x,&  xΛL]K/'کҔelW]&)$イ}RoԳv}'veR%UfDXh #tsʚ&T/KI_U"VRլQ:cB-u峯~/uJ\)`h ;55-wf7}8FN 5j8*% f#0,߻ nr{]駟t *;B<4;}28>O#<(N}&h뾠Erّ䄔Ξ;eAzǨ/5vuVWJz% H2 k@=:|#t@ ǹ4#q'm:*ͷj ~c獱Nk k\8Hd2oE8np&Kn䲔+v<ړԑD{%KP+F3 (ͨJRigt|LO%Eck}OPOw_Y5JKl-d:1IeJ91|Ki |W7ϵ`Z*]2GZ 5{ OP޼}HkboPָ^M"pGIϛ*U8\`c;r:9'%n鄐Ve5n'9@ҝ8j^ueJ_{4NOPCd/aϠ{%{c;=CAdΜ4pS: fff8 k$n# dXF,W"+&o-'V$)f o<RYDw顶;̞Zr4G \wEڳ{?q®?wɼVw?/qtD`"H8 IAD!s5IRH0ЈG4p1FU'{nK] 2JzKj!;9S{ޒyE YM 9B*> |k+F^LEƔ̋_+zu\sS^|tb@Oꡥ%җTha~hY{σWkt^Q3-9??+ֶrtuu4tΘ0<$m@^x B dhrac/lIeT6I##Ҁt0Iw]ptN >a _8Cc/m6{9ڠUMQPo_2 뺯iv$*@mΛh-"ݴҍU.v*^ïѿ/Jb9GYFMgmK)~riY iOhz6ڵk@$s[,ղ띌CAV %48< { #{!W9r]!+*ϋѲ]er-p! 28ɗb/mM_ʗE-Br`HibP ԖV'JZ lDAӕIff,IqHc?^M 5NBg'h0,LqɔBv:[31 i[dlo߀RJVhOOeG? ѥ Gjh*v/آxC?K㯑}s㑯,*?fjRwOV8P/=W*%ԟ=ZW/c#ҤSgGhnz[) pa& ֒yw9X#ʉ%49N8@8EdsIqlJL[0eʏPXjf`~qerwtp9M Z؄vFI+ CE"L#cq8DoyE=me%=|:1gdpk"Q4"[ hqB9K/|oA> ,ji'S63u/Rd4q&S=.Ts8H^y;YABN1q3F'OӉ'd-DsdА&uUkgvW&cZCPn:Fs Rs}e j1Wg b|fD\6 ]iduXZ롞(oauyqzk!&8y[-S_K^Qo4R-l٦u 511I6P~uIxq)JW&ŋ8O8Ps:=oGXCbhau! 隲D[)o6 y334=='HX[ur k"QXE ԾCґ^~Qfīa@ֈL&GǏ_A^FY9PKv=qMoiZQk#yJjuf8idj T:4z_0׊1$Gӓt)WtzE ԩSt1-8zzzѣbqq}lunnӥse@Qut xLKBq>t3׸n%8bN|L\cj(+YR:EH'X1+}ǎ%2VԨL^3ĨfP#2 { X!i;Yu0MfWסր)Ӓ_yYiˋ(F~~0Br#wuwVr,iDRJ@wL~Mg^ kE|c7!?' ?$ϥ%h8~5'#OJ[(* ^eL:U[K? `e0~\?}˨Nv@KJ0Wknm;}Ӟt.8v=^poߥ &_ʰ6&9 *i6I&v ٹS/3uo."A- ȼx"*z|#*]Ν@vF& xAe='g"q~p}нݭf9,'e:Q\4 lo .^ڻ'En,9D&ʡ~keY0O WX%2GxnT%UB(9F~SW F8 nLso[2(h繧Y\NQQ}--" h}ٸ^x>ω(<τ{1(0WD`.PaikM\p42[ʊȆ -? 5N諍m}rnj| _71;[lA Yy~@Mȶsf:˒οZ5@8Kܔ08#[wpQC?J>+%-q"c&XͺoRq/-勴4+N;dJ_#GODq>Y%*NuPK u!B,T1p:BН %ܲnLAj( ZZU|o֥Oχs/4<.yѡCV5 Kl_%쉔j φSўz+ dp[2zBS]_dL0F=k /oڴu%ڽ{80y{y˴8%܀ղu FV I6QoWz'%bt)8~JbQ2jRgR^&s\A9D3Jg8Ȥ;}F_(bޞU4ʒ U#ƚnX\IDhEj0Lc $u{3]wu.v.l dT&0 4SY7g4Xs t8EG*Ydg˗l4?;C'8ptXClP-z!2MG $+-H%unZ #Jv9q]Ǟ {#zLȞP99x+Meϐ{Ͼ"]Hm6 V}m80ICyt (^ދe_=t d >[]x/\.9 hܡQ\Iu_Anoݐ;Bx Cҥj%ptt8>{{0*rh+˭֫|K3mi;vyv2^6Cu#W4W8U"퍍72H)q0UW7z=㑢l/al&=LSc[ @:ZΟ?/dᨩņ;Hn0NẀtB?R͹5D r!L;Frgc0ʼ WX3#aT ZVR? q25 @7w 2#(_jʡ.mnd&.JJ9Oe!N>(Rfܣ*Jj>qX;9~s>51MoutC=Lv~#o48C{(kQSJ6ޖ62zT[xu ? U^*D"Pܬl \6ph æUjRWZa$yFI0(@-h%[8Z^^r*_ ( {eXP :l7qeZF&PUOHV69vkoZE#:80(Jh- `&pcQZye=-A-TrI*'i5@@AIpKW^V;yU`udo3CF7a!2la%Qo0V]&JD9=ۨ(]^e!}nվADQM4C$+N)aMZ֪E slV?fmUp`Rb?!m%R$AaR-hǜZӟQ%5Rȗa<ԏW_nxRG?| s(A}ne&'.+%(G:}Lvv霁ȐS)Z4emÐ_D{ή6׃;w}{(oޣ 3Pp`f*ΚcOp`JvvRש+#Q$P{,]4KM75C.9ѿ= mmr#M]Y1n ˒6 D"*-\Kv^A*`xr;i2 .~'R!X[wvΝ{e"`!I/Gٸ c2|ܤjÜT@)K^ _@+=7c:RFCx^4< b؇|XHlV٪9X~F]-BZ :iDˆIt"OFԹ1>tTZ9+TR + *͌괾 4sfؕv(I)NAJdyj`[myjM]G[>ƣoȵ Х52&ٮ2H3&&9ٺS6ɓIK徛oWN?_#1iCT{G.]%@zG9L:?dA [s<*$d!q Bc36ZPj*ϘQM."Bh d3de^/|Wssi:r~swt)p TPEt&A程 DBdꫯJ$Qe"4<ؼ7$yQ x9QU#% Y#$n.􌭾~5Pi(S !Ej|?>vpnHV^?ݴg;Ӊ|}mלs(xJH3veߣU VC_.t`{$>j ~Nf,Sl491/Z\ p~Ww*YQ33y6 )?+o0s1{ C %~a9<G i1عmOdoh\9{]ꎪX͏Pvx_3?7#S쐮3TE?+fqrMuu ؎cʆ8SB!#46~zӇ'`<,B+żA/J- 4G t ޯ$G7￙n1!*v۷ʱf"9OۨmPK& ĚGU] MG.9"pQ{gYb*ָ>\2Jt TZ<ٮPwÄ0R BDZ.Kf0z]f;)p9LG8zV:phF63^ in?vL1Ct]}e"5 GvU)![`HGf+gӿXS5㙍9&j(;13̔*ߨd*9"5gF̯х ctR,X 2]')eNiiND7j )_¯v.q 6P˒ԺeL/ > "%ZoV8ʌD`0#GFqAag?}+Mº'@Nbp`2-cy]{~λ鮻3{;L{?88@[mY0-kT>fAc2j wg5eSfxdg~8 /z+a<X`dJ( LF0Js-ʼ/!^eJSzp}}r Q*7&T{TM.ep= Xǚyz3sEw?o^cTWmU 5[[V #r&iD><_Uy*v-Vx}A R,@@"}@$*j^X81uIqrcQ6/ɜ]Z1}OKO%vWcx Z7!Rw{)~#[Jb{.X7K[6,mI8o֖)EJ7J ֑ 7$XEB `kfO#/ y8! utQG466uSY !Tfz)3Ϝ9`9DK9~sЋnLs$\UQ`B",R/)`o|ҋ/=%)pƶ[|GKCѢ`,򍘹?SO}^3әPíJOvg}%#p<7#Vm7ѹ}6UzD2aN/ՙ7c,-Vɸ >;4'f|Dv3G݌}u~(T5X]Z)I*-7jV@DKc(~cg }="Iݫ(\S+&usQZȒ@zU3YS.>Wv\ixkMckv4`ѮHXmϩBaԝIR@ȟK `o@TِQNר) P1]Z zg? DTg,L+Yg,K)T|4"=1i/"/.-mJnw t*KidxFFo$8zxN$K˜_ kTWQD֑lL+I8 Xuɹ)?oF` V3R0ZΌRZvMRچfiU^Or=S?Tŗ^Nf{-U:^%_jwbn6)Wc B!'2M_/_k'N8!5۷K#A}j?G5Q[ F&5j3l궰Kdc#V](P[VLRqjQppm;5Mu9~h̜ 57V-]a%^,ddzլH?1.B ^X>S|ND4ݜh4*+LåW]A.z`(`XE?_ S>^}ڧrLJרz^0Ge8mZMU>dq%2r8U&/hŏPv6.h-.K>y JFoإ. 9} a`90"]Fq뾖s104[mD^rWmd[rؖSP]uXXV@9~ Q/9ldZ\Ld zv&ծ}{i&xW.ڂOUb*z]X+Q2տF@pCq*'?.| Жd~VU̶?kI(PUD ѐ]ty!-(sD# CmGj}[쵊 *NZ2Nԓ$wT+/k$s΍Ԛ2 6YJbjbdWhyyKr&6ƠSTG)Rr צHk8&g;Gdps@Y":yeՏBVJ>RƋ޺ J'(^3B`I fb;cL}5 l]b['S2@R\0 PBO*?s4')5T$a2@Id@ټnM.]@VY9m~NjX]ƲBaAkG?}NDÌUaNk btnతBB0e 6QJPэn&\.1.JWlt B&[.YR3{Э [MŒ҂G< i^,,iA hjiL3s@XtS,LCM^y]|uuHsکNv].tmV'EfI֏[4w^d2H 00o|42==ʦtt>E+? BrȖL=V3-̎Alo86d3RRԭd ߋ%% l%zF(Ȭ 7>'GP]x~Q0[4 \M\oӚ%3)LFizvRع0JZ joK˜(G&^'!&%d}^_yBa9!F cwh@sskFi Y Դ.elUY ߛmg*rj?sȃTa)PIj" K +Ǣcg h -2̙4i0;iL$7&YD]vC?RE.;Ժ'DoM8KTj,`8^[G`G@n.P.*h}Ns3~Fޭ^6ɜN:4{>O#⦗*,ikL/{n:sQ:Vk̯ m1`O|LK+Gωhr:/##:bN+JY6I]"7*AM\M.YpzP! eҥbn^ڹs7rk~o4vh"h=ǥ?t-wѶm;UwB,j_0Dp8^ny׾fbU o! %4 d/CQdU=QQD3'|SR[ӡu">SP^GX}jahW4>3ߝ)op* չdlZ6R;vQV'yV/g.F#{\(K' Q|ۘ-Aj"tƋJ4^]! SoXV^[{̚2=v2ʪu*aB*^>arQL}æcF"D%*tugC.7;%/(v9cs5@sC wD(XGzoHNN^[*#|cՎ*l~_H]i}ߡ q!pͮ8 ЁA4FѣeMz.h`㯙s/JBEH:"jc\mv_Jց-T@ ,l}>;arH]gN#DuA5Ji\آ.||g p,OjC߻ 6J]JShuKN'EwoGL~O;%uk#k/ &%3Rd))Ѧ eP4[qłk_i J ~=PCG)|GZԉDh"FV X9ғiJLP!$6h{yPb8&D+-5TDtfTҺfTJѿ "`Pc~i:{&CdY&#nsZ`tF6Okd,"f,DO&5\Jħ:,fD8+4X !xf"d[K1oZ;ArhqHykn.p?y ;?fFȸ;D/'h tQ-Yz\`wPE^lz饗EH3;?,^ݎij%$zl} zkN N.M(^ޖ4OATgIYȞ-Qv%/%R-F}P;z͜ P-y!Bcʴ5@sm zḍ_/7*0Vˎn_I;.?L/LpUQj2 Ug=ۥõ^׊s쎰8S ,\ux;:OeviZM S3r)ņuf\7 ܣf`)($&J.W!:y銥.Hæ5tֱe5eF/ײg8ԮvX͹~;1~V  w%31{O=~wih7`'D[xR(YmTt5㡁_ .N?mLR\F Wzoӗ7N,\ ɍ)_Sε6M]BLs{LdȔ*#GNWUQW5 FIzQtK480Lo唨5DS WEJ?IhaqbCws X3 O')Ƞ\!/xRsά?c*cp)zN/y^v.ayJ *22tv:,w:u!^tALcGg'"y6pEFH*g@v@Z?(B@)JNȾܬI#9&+ch[= 6`\i}[ߢ?.^'07?)u|IyUuͥiiyA8G°Fo}"j>6Пe:Qw;6)LP!fPM{nS'<pٟ"&(QJ,X$oeg.: 6zfY 5є{K A29NXN9k fqpdwRNEL`D{>WQ r`6(^$&o=l~Q UfN2Nr4?@^N^ۉv~A?lqRF'_ʕSHzVK_tùMIǃ碹 :,Sh.'}.gNT};I h"oկ9|a;}ߖҭ R{}=NShFK{Jk(8]Nt:j0+3Л5(xSG̽5luRը!z! 0@K::/;Zչ}_QOP:g7vMAx: 2 ?̘ 38͍L.Q:a߼ZohTf'(|mSM.XΝc˒ӟ8/k#q08=?o=}+B/P[[7[8ϒ)f#?e:ur=V,U+ş@npp#*Da,̦h9M J]Svҗoǯ fr!_ [GSYt)RjvZ\pny8;l \NzNu4_YȦ`/PTh܊}ep!s)"V;:6^CxW-$sѨ:k ~P0lQ'-͔vR#43L9p"joN\Xz|zk{[t;tWrhd1ҫE$0s?r}4" 9FEP65eWʀ:mo 188||V Go F<-JSrVx]ǩ5H.8G/Q{un_[hPD@IHd~q>A.JkwI#eYFc7`]7j^s S'ia2TAcpC.:;|hw9ϳUce0ϫѳӜR:[*;y\㊢|c;'/ug :@?}jf1@BR9NOmAiP"ӷW)OQTGk{GKt6#W (ղzK~thٝ0vG$r ㅾEM:zN)Ixײ.-)uMD TOCb`Sg_+TtLv`^$wQJ't8o6CLQ29XSQ6)šV=d! ޢ4xAgP+ntYA ܜ}9f pu+?Eħfh ~2L|?(;6GQ"L xy*{a{SR\OVk/CNF/d-n5L9̔z M.(, y;8r gu$ʱSϲoA`t!sl lu cizjyŜPA\K<]D-.r1P%/ HTnC2gNR)yC]6;n\I"{c$#N\츿CO%O`'Q4 ؎S4mvRz:-(v0in$e W[Eګ꾁zi{n2љH3r?h7 lWFZ\y*HWYtxP6sڜ|_=DwxC4WhCf@Z(Ȩ: 2%>')EQ1QV]/Bjcs_/ "U2<S^ h+EҢ 9/ PYG?BɳrUq k rp^BSB/wI4ZlMc@c uBR:p{8(s 1+QX25$6dtȋDWe!0z۵t Q-aZzag6.iZZ4;H:&\ y8;DS(B e!oS\%7˥I'+{\檣뿢-ezWkUq. ۋgL/G)զ!;g{fJ9 |H2W i)VR[螽-r8zP lGRc\zPV@@eѮC!*`REV+%o̽cwۨޮUi G CJ76PHD*  =N=U( t`زS`wL)lT L2AN3o% ώLN)OFxz~2B_.;>;#+bt3ŤGӅtm1ar&NNYNJ_HR!y[!WDLG8?l'AqT$"sE:rtvݏPp,H?_%JKȬJYZjCP)wު,2Ŷ}.̗he֠x)N3S唄o/o3s-$)*e}c[=Rt'zmy咎BD+++XI>J PAtD 7RxTD֓?nwhɤ5LG_Aee]6*GLB=ƂIv9fGoեf7C w7~:4HOSTmnP3D}͵{b8fگg2I^]3eGBkf"lI8r.IgРI[.:'It6W"ڂ_** M4e7PX*Pn%GN9eBɰ0 ߈`&DŽ+׎-e^lbgop˧5âWs&i>o@BΟFꠃ8}[s1K:( K-7͑/N(;DSIZ8@օVVy9BWI yLK>"{GT[=Ѯ ,—w2|exx4Ő7-DCQ|{Ȍ7".g/h3)mНldmS8X1'\зLTq]U XŞ$ֶPp 0ΕjV٪9[ ?nkfd0y-OΡ FD8Yח3˲q=}dI_bP3'b4ߦ6ƆpnṈ( o|{j6\zt -\fͿMM9Z~}y7t!.N{Iy+WXVP~R6MM ".WiK<Zh6Jm6y\vQuM>gĎe*#t zi-,G9*,9hlWX~TrLf\}ߪ7K{{A?E: 꼿&9)r~8. K͕-tG0H ʌaX)P` qPc4Rjʙ"yv޹lm=4\)&S0s8]|Qq>-jMOBo[k4u>,@u'evQ/k鴧iK# Qzzi:rP4"ͿjArIO9#6z u+ӗeI#uGoQ;k~$uxW'MdsӦ` 2 J8\t%e-}Q[@2S!mBtBvzM EpAAڶr1qs{#A~IlwO k|@/tRLJ&esV3 5ʙ#nbPއ9`5jPQn~,U MǧUݿ?i5MqJg3bJe ޽ ۪BTFn%^X -ԣ;gؚa5Hjlƥh68Nrdժ}ǮitZ4 z!F=d\L 2!{J&(,q6A *&\*??C \N؁$ߍ_nkAIՎfe\_7}EKyIIGZXShzD}}ޙq:XAGzȭ\ Qן'n'EZ ""[Z_/~ vw]n<;0L4cyO^;*RE{RqqUhlj$U!Y5I%hq\]X &f|} kk@DZK"B"hui(N|olӾmmgE.>9D.fL|-Hwv[j)^ƏST:4@s5&.}^ǚ v#%Sr3GY /^X G8r6B" )V2Wi1At _ }m2Fs9B[FdCZ(Sj EY Gh,-Ng(8@$LB:%| F<^^'s h:*df?P@8LA)v>?xxNMww3~AT&Kv_É-dŝfgH,H_0vn>tw8 r' :)sY"Q΀+~0 {{֠-df;{7{=|)WPDR0Na!RpޖSq:<9ܳS٫Z|9@77ѿ՝t΍[e:QE+˚N~_ 8clmU8|Ҧ{";tA Z+?h0G.$i(|u6cD ?z],=oص:b$1~j _>vQN\a/Dy5F+I ҩtͤ'V;LۛvqʱLնʢij&B#0\qzLR37Z.&ߞf[d|?Dq勞o?ںAkvT&kƈz\ mPt,rV2=4}@ f:9f`<;":]p NoMqrA}MJ_QR_;:GtC^^RDqTO{5(=Hsh @b tYPHu 7&pweOKM3GZ۩E)D(nּ酲3H#RArN]JTRL|({vJiptڹC.k[-҂e"Z?Nc|F <|5ŹN Y*Qe[-U6s-D 4Cqr~V/t1ٵ52)]M\u2 9.2ri.ڟF 뇇"4;hD#MS$oH+bD|z3 F?H)x@zAAmK4=634Cl 䃦\ؙ@ù7꼷&9R}h(@kb>G/po-2ve5ZoTs 8`{),M Äv7u2 ZziNʉox+ݹ6'Hr>XuVfO=QR^jZ;6BO7; J* J]1"}Eimqqot}};v M\um:m9d<͑~Q=H ?bOV+LC[q.԰5S9"SyCvu-s}1C)vVy_-D K5"qXF>;z\\CmtK0T>xqL,VG (>檴6ʥ*N6. !Jw烍4N_P>AS~ZS(o;j>Cg>KJcrloeБ5X{d7WsmyM3p)YDNlաW߀s ,Ǥ 9,PuP'AҪh_WJ&LْTs /YD-v4>ry\\(YA轞1pSdB9ٳC1|v̀3J 备azw3HtSݫ>/RRD%F1R 6ZWPoF]?s$Ǐ\],(ӯmПT~ʊZ t.#xK4E>>r#1) ~&&e`35Xjv{a.7禰!%~i7+(P.d b`hS]Yzڀ-GYYBT>T8ޛ>mo/]OMP2Vjjk8GlMFQ!!UN$:9i"/8e'o0ɮUUչ{{rh" I 'y6Xְ6`a6cmc`&I! #8:ʹ9W{f4$JS]?/ÿ:y1SiNWˋsصLY%F֢>hZgtD ȮR&6ٰ}}Q]=-"rh5l573ْ [ppTs}\Me8yV=xX=Np_+_ Uo ǿ:эKa,u蟟*D/ݯj/7yzy w-,l ty\?ҳa 97%8| b[Bl.~La_$~<R<-n@CM/1K^7y{_p.mZ4J\LPooYj>Ğ]8Dyy Cj8$f@%ub*@~~7$+sqC?B#4~/$7y99 %EUr4 "ZQfm09}Z ^~itTL~u|??r([\39zcaȩ=}6nAmlМK˭h8Kwl:_Sn_|w 7uU`Xs,k?nh4M$꫒sO  ]DbHC|諈_ `Ix [ueC,G.p ?BQűql*oΨ;oVq~vvr,˦c6mǮ]C|`AZAvnUC(_ܹ9^_˭3-OD#Az!Tf! ~L'}n}z}NdV[bUݨ͇TTS2lwFxs_y(E\Yoy"{ze(r{"pL kfydQǝ/q2}R:w'o^tuC$˃  Jʊz[B>8Fk:T2qXR65nt1>[RXa|Ta7gZQmg[}JkoI]T?z"}8z ;6mŸ?y v` @F^)p6WVHqλp7^ޅ]c浇#T/'Nv)(UCΫ*5TM:OfEaX؋wނ|Gy|hvRŪxm]"&+֐V1 ;4FcկC%(нGț|xy(ѡ^GTSJ Z4TB =CQld_ǥ]q|ozŊ",!kAXsX)JZzYq/`]IFg7y5ݝ-:Ɵ|da٢:u}8rڼ8^dxIJa_22ZQPKK\eJ:L9& >ϏN| 1: XC\U!m՞+5(-tOo{pez_Dxy|STSxX#9uHV׷O⓿KE}̚ dx𩓓Hqp&Zvr%YA CDxk"±"@w=Ks @и }jmaW+H5uJ >!׹oz;&Bsj>h)j>_+D߫S4v&cDrۋ˪0GOͨ) lz4 ' ¹׏^Tt2z!IE疫0z o_l*S_;K.swԭ3]c*T{-b}LM^v-g*ϋ9S?#ֹѪLQdnZQ] ?-^~ӥ 2Lw[~F|:gg{Xe0n>^щ1jx́F~xMy6>8UkY|MB*+ 9 x{?.srw,-@њ׽ݍH_Dg3Ѡ9>HF su^gF/ܪ 21T­(VlnR(.ʽ7V}c_UA٪pFDBAVMfoRFBc4Q_/룅eAQ:ЏhK<c_J-p&G"Tzy@Wt!=KOd&tykn|xt=űT(#qq=6Uă71 `5=s.em##^f^9Z?:w&%c$T#mn,i18*ͅq|w[{Bit3TϹ .DTj{m A$!?2'U`Qg\'bs ٝ{6Gy7-Jڞ~2k]a`9ZW`ElЍnVJ΋4W9ȧTD^Sn ʰ,{tNA5@R}`ꨎR1g#1i?e=^yzni'NcVSQ>4Yz K'+#W`CTQɄZ>eG~إu{.7kz*~ LJ{IhvƊԂZC'Om,B%pW^D~gC|T +:7vu^h܏+k>.S}rDnu5VwV&nb)]qT(~e,ܒ N>Y߬si]9W}Cc-_lX*-a6?kD~dl>PF'~h j "1–PG#N*Oz䌍\VՑVH{9TWh~=Nv?'ӤWGl*QAwkpdGc(./׬fG6<8xX;l5EOBu]9źRLw< &*kmcqu~a5?]**g(m xD9@waก D8HMNԚe}Y s\WeRRhdVTꪵ"ym;3<y+k_}u7YUwfV Sj7ᅇ#&gpF>= Tu+[ۇNj%\#d\-s)p)ϥ4Uq|#\־9EXr=mS ̀7DTMW,12o   nx1gu-A;WEb{8"ų1:'R` zުU/L0n%pWnQ=wD8h eraנP3~;8t%s_|_5M^VJ|yw7~a_Ӗ 1L׫a5}=|}h,Y#VD*.G8 T$Ԟ7'](@.}Ë{89gB Ŕ60\@pN7;&:Çsr<)g|ky\\1/>'W7JQ2g2,@ﭮ"[WKI@k9YѮvWMVKwG}i5'2.-8R&2c*k~Nv0Q@iz9Lg*LZ+/M$B::LE-aaݸ%Ӆ k{hIjj vLɠ1Eb:]k/;L3Uuqk}z\I8,44Trvħ-6Τbi|[8CW"4n<Z^m BbE.LCUӜ `қh޻pDZ_g]BeWcێ!旰R^E+p 1 sX7̊ y]Uoq9is4#'O̮t^dsĶSDܭQf;86 @<$aY2uxϧÿ.w21_g-s-zQQj^%bC (aU6d5؏Ȕʨ +nXjgStSO/HTS4JЍsJ{hЂ 1j4U]QZ<~w5Ըqq?؃ 8z/SIմSyР5t؅{`ʳŚ)冃P}nqUbg1M}rrYwfj'.s / tL/'R9-xM0[ ~i^,VQ5q4'=-W4#&ֺm׿sEDmCj̴?7A|se/yt* !'r9JyVN]&k1K@Z]ZdƳbjG^y*g5\Smb`)]m&) <¥;W̬ ˬDÇ9<ᄪ.-uz2hU؜å{5_\6cO$+}1dzDjZQbz^EDk/t-/B7Z_eQ0QE3zL>Vt3Io(ν 1-eT9*ϐ\E/U沺u# G^w8ڕMWCxa<<'t4a6SeK2ie8kּm`'>??iܸ&l8 W7}*Iž8һcߢRr/Vs`zGDNgFzkVaг%xϭ[Ub"k<1nNBmE͌MeXTR@p`2[LX@EX3"WPc_^PO0J1Ӭ۬ OzUZ1i>] $5/&ɛ T)'΅L-:vSwӛ LQ mlWζ~y{+uY*yjEyyxr\rEk=V]{ QΦۼ^>*ٍo/,/jU cW(t)U=dzq,TF߶6wYǜ6=_R!emZâ/s2:ص)}X^.7u1?⡣.e5mưsznˋ#\+EW+X`[`0%(R  `dć#Π@]0HDkɭ1m+{#hpZ@wPώ0oKi'Sgd y@g֥#(BKi8)c;"m$`N%ԗI|V\R%|D4Mhj T_#oUKSm@4J^Vo]:aYlKlݚ|}65,tY@p>GfQ"ЋuW'p*z?׵w*tM9ë,Pk/ٸAG+ {s0b=yH31$bhySl$8qr2]V־y"DcfVƳځU_H@@CC e0s 98~cUPI˅q @_D۳huY^~jjynv}qχh"1\ӍzzT#G01e&pۭL43ѯA:۳7tuaaa^-!NLK$%"nU-o546矮5URq"fƋ8H0mᅻm$`<`(*iIҥf#7v#e,LԔm:|~5K&Fxver߼g nI>V߷U F7ThgcuB: 3G`WT+dl8^BpXəPLJC<[\Y/F˧ 9hk:JRsW,UCy=^3"@ x{{ Gl|'/e%G j݃UۈqԪ^ZUI'hJǠTgqG*cjܫO1]81B٩M[iQv+ %X+"?߲Lks(r!"Jlͺ%CFnUKz O6sh-B@TnUBګPwp,ZSVI9d;޹~}|E'<$0:6SO>rT3Kgwx2l[j3 P-(Rp5hݮs *wolGqb>>pnye+ϙ-}ܑ>{|vc|X r" 9]?qڭ\!P]@+ zMoJFD!h` (s.CLAD$[77Ap4X 2\VeLf(o/S5.4}=l ~-}=shWd2yR'ۏfT.U!@lˆy]P5εJ@%,:GeN̒1jy\sөY7*2_@j|lя}~]qF/ =O5S'2`-5z5%}rjL%/;{O;Bs1'bl`mul,NΝ~7wm+I`K` S%dz>BŝLE*}Z1 q=.e{Y2\Nj6/蝆DwGvINN㣟~rZ%#r3jQnguz]UMzZme%w %kwud.[u Y"歗[X r3 3}x??#U_g}pDŽ l8Vƕ#UkR kn`_6)n}>zᖸ2NdH Dwmۈ׏'@ /`4xZÃr-ؼc.COgՃ&!'7βg(}+w wv\4ћt5: 'qh5̖\'x< mw<~-c,X!Y85> TQйԮS mߛÍw5-gj?pNj?QOk΍kNu؜Oi܊VT5auD;T}Ew*4y۪3~bs%BRsGWLD6ggKaS euo|( DBt2Hos}0t##L 2 yI`G<fR(53aϟ5GT>k;sfrg!%bko΍1KVDtZWƵl;KǎU_v~뾧gS;G<D2Yԭz.mx"kIL%C넎*4^isțxb_\V3k-*xi* &TO`H?|w=\ZI$*z<891 MXj%%=$'>{Pp ֈL{hSW'4ȨFOE"2I%M}ĉIk$D DB>"L*ˤ1t2%xa~l'pQK5c(֪(qA1o%j@dM'O/hpJxQꇧ86ݒRz ߒg[Yy'tn_oMO4h+ lzEemcÑ,BdD(+!@ݍ Ru NhW4pwW_lv5lj<9o2_rIc6-$: b2F X"MvTm>ZW-t׫ a TAåCHwFJq:g_~t{,>r]qhIz^eZm~wƒTUN.p|lcsO5DUN>|s7zfk(T+~Fs_Um|$uWUw' P&n"~ pōiK4[,Ųqh<6΃x6C+@@ ntݮ{|x+p`dsQ\/K1O$)W0]_D8pm.קθ s׏[U?*Vp}"|5j]){ M zkuؾV%oo^?'VQ/<>[½4W @ {gS[* {9T9MbϦ𪊕lXP?Eqå]D(U*q-jUe$) L繬ȥV?3*9u27G@ w޻go'OW)92UzV͞!FBd=p=XI@ 奔EVt 'K?_Q!B@p\6}>$D~}uD}~\Gr2U,J . @ !@@ !@ @  @@ !@ @  @@ !@ @  @@ !@ @  @@ B@ @ @ @ B@ @G@  4 @  @@ !@ @  @@ !@ @ @ @ B@ @ @ @ B@ @ @ @ B@ @ @ @ B@ @ @ !@ @  @@ !@ gk$kIENDB`tiled-1.0.3/src/plugins/replicaisland/tutorial.png000066400000000000000000000300771315121121300222440ustar00rootroot00000000000000PNG  IHDR\rftEXtSoftwareAdobe ImageReadyqe</IDATxُer}z{+(H? A_HJ/ `-)I 6/i;=Uu͕U9a"{2+2~ yrbŊqӉ[8.88 8.<'~|>_zOa !kx>~ƏS_?_o =o>$;O'/Z\B\\NG..{BpG..{BpG..{BpG..{BpG..{Bz|[(G+}Bkx!O0 xwtNCDp{..{.{\\N({\\N({O!+.= 8El( upQ2Q;Eѐ bQ )bQ )jq?|^G~\y 6?Y ~;g υd{xpʽ]N( {]N( {?1m{OO۷[([=?s? ̞].t0Y>a 츿'xqN?sXެo_BxF'}'txpCc(4z&id%N@pҢOs3N' r##1/Fi~Zy)~){SO E= ó]s)'8Fv\swq\kmqXcq>'8nQ{8Eswg$! p8Huq<((S<)?&Ը92JC(Bӎ;n'L>(ӊ;n'T>(Binn'\& pF$Q{7|9ww38Q{7|9FTww>G|O3_g(23==&E sWqyr=wN\{7|n)Q{7| , yvgܛJ11w>W{{ߝ_?&FIyK.o< s*^t!pp\\\Džq!p!pp\\Ng<9Wǡ號?8ϣ!c?c%K8 8 8 8 8 8 8 qǏ;O:x_2:֯۟ qq\qpqq\qpqq\qpqN?Y%] Ƞ6hH%90a]FvG̔-M&<6* [d=h£"v\O:%,wΌR&]m;]i;[I 0] Cip`_w}Q̲@0fsw'yeg'ۻ!ɵ]GlTlQ6(1<*M_8.Oapn4[qwӼv~i>^^Y:rzo7dDV'I/ouvZWZyXبDyP\q@뗊qfgj']vznr+Uk aeu!v1|]Jٮ魯GNp\aUq0؀o:.G4\qiѴ8db.VupYT%j⯶.<<[@5Ux0M:!рp/[\wzyܦӉ]|ya(_:RcXM`ϣc>r ˣV_kvu jYk\%Qg٫Ӧ˓Ftє/_XY 8CP6׻5S3ZjYhݦ];~8' VS3Mƭ^셦^XvCH~ژȫ#UQAUԸ `䗐 +S;IWS0չ~|>l$}O _y\]*xEq0MΤ:^\/_>[o`)RExV6kg[Ykv2Οņr q?|RsK[9SA͛~)9R̰0ڥIwy:^[W_8W yc-Xν4<j\j] kKXkLP ፫6 F RTiPDy@sw V_@z\+맔m|x=}D4u4H ;p0 Prܶk:^2KrWNHG yʹyrmw B+!j9Y<.@v=֫izq{7_#vRu?ƺ[?~|. -U#"(ưg%  d M HOZ{~׿y;w㩾7ׄ;sư/Ns3[nFׯ^!gGX?ѿ}P LUc0V|`k?i1|SKeXJ@h ҥ _?;}4#UOKWp.<|ۃ!o'.Nخu^|8n_SGG!!@x{E"XA,"AE hEbYY!x?y[9n!ˁ\ET/2s$AU[a9)_z~xmy!@;1u2A?ҿF355rH@@1JP" e5՗%c64 *B.߻}O_!K0Z]Xq7t:a#8ϣ0uXMճk*v~z`(?_~'ꠡl/O&(b Ȓ'(ro9[-? C(a2I uE}}{sC@Juww/u%D]rgq(|)>^E2Vl+V35C#3}'o+u,,{^E! 1i!A ;E P=` - ŨTdK@h)^fc6 +`VEh@glRl`g;g㸊\&Y)%|0̷VsŔ8WQ?+;X 5-n#MYн%0 倏LKjػuKY_V +MKYprDύXֶ-׎ U8lNRmU̜,UXL˄[Y ʞi"T'65)-ƟjR:]{uU 1e0%c@.dh{O ٘f)F{alcRTD#]9d)@3q\.ܙ.E̜,BJyMy~8W*>,o[j B+)޲}N_oh@ ͳx91-_U!,Ҡ>oPr A`B+ M%ӥNbB0T0CY^L )@<{7lL˂fje=1%{{ +4RCY8L@VϔH |o5Bg4){8C;Iҩ0%[H;'RBaK&G / JG6zKPalF3̨rOBAkKD P@KwJLd̝1g2) LTFST(Cif03j?S$, P)'H|}4 Qt sa\bS,.*)\J:4XnCGskƏBӰ58ۚJū[ր~hY6Kfka94a 9s6hHbF&{dqJ},ErYP!پ^|Cr8kICt.e)08'MT۔0(*?晔Yf x5XF;PTYCٶ]m62d? +T/74D$"*%E,RYh_ 0dڴ-cq.fq a#!rB||)YYYɶUɽXI Py3R{x /j"Z}b17Ue#$g M^oH/xH2p2H`1 T1PvpN^0Yt AUtMo( , 3b0Ԩ l >&HhYNG쟯>-0#LABĦjBܳ3OL @Um2@ @V:6!#-$afkPX(]ek0{`%U[6֛Zr%o3֗[1r֢J5 en` ՑA͢f~9'I,gZcZZÒY7nqY,Z556ijBa:͎ݟۇ Ҡ ^pAP`ZD0K4hƒ' RECESCz}="V0P4r6#f]F4"0x):s+?[%V? T,{`_`WATn0i˫m< |̖"TR?))ƚmx+&ijV[fSGf)uUbI>Ilk3 jU0/oD, ?XR  `B)G)^lILלfEzH*]sH'S4kN ]6$C71dK0mFs:2iӄFB`}Qc4Gzc@0 (v&ީlzϯ7#S5)SEP "J`r4OJU. 1%rJ*| ,DJŤD͐l9e!lʒFg/:'HN:LCހD>YzRa6P"3LbDȄPMHYV3RHl%@#/7USͦ9C"Tr+E 0Br&9"pc==Y$`9 뵟y9~4$h$)B V| <$@N"\hETe)_j "%D` 0A,CAFJlbC d!F+s6h5 Ry`ξ&=RfAJ!AQXQ!!(!ƚ M[ސC#RdD@Bf@(ʥL#:͗= I}~9')jf.i[su [t=K,)P QŐ޸1VU/h(`` }rk K4 Z;˜ &dB AjPrvKh0X]QF.ih999a4`C"fe i"&H I1%Q(!PD1!U0g /*L(ve1sIj HL)?fJq/k$j0+"aII&~ 9I@IK]1"f[k3z ?~˟,@ !e_:0$}.pМ,МL $*2i6ja9h@S #!pvf(vڙ!HˀwNR:!U@bP'\*ۂgOBlR&x]<)S~g?/yc>04~ŐL6ެ% }8"% X $!O3w&`\ +I!A8X19IDBT9%dU\Na/f:=#dqO,) e "Fc*su}^ǒiAʼ DVPHy`EUꋲ} t,eLH!Ȅd痛sܐ'&@!pզmO蓿yl,( Q(cfgfYL U@4)Xr2ndVs98KF7ebV p{e!fiuBf  С`"&!ԌVxbM;C@0e~Z<2q(ߝ}p?XEƪ*dfĽ/P|w_ރJU A&1`7pNrʠ|k"Ŕ͙1~xh#QE2F{OF?)_H)B s}`K&2g o`Od*Bv`vV$ܜ%\;im><;_|E iʌ3J@ d mVoC=-aG3'Z?xdN{ft(4!,el|˼+!Q؉T:FDI%#wc ;qe2&kewCkgg|,ec[۔3Mr7MI[flx3{ˆBwf$/\xge6- ۻy X޳/rN45c&vV-D{Q{Y5)[߳ƟeRW"7R@toA4%}Eq^½9ݴ2tܨDȭXc/3$ `l !㭴ծYyB97i) "?x698F~ހi5#f8aaS@Fԑ1r3FnC9Ve!"owӤvoweq,/BP3Rb3ZSU "3Ojc6L 0!}DR 9C~[~[n%Q]~ّUzdi/1y9hQd>in!I.W'?^/{emmIaeS뇁Skfe4m1:ՐEf}~Bޯ|oաUX7J6 uFDr#ZxQ]F h3&^?oko{^7NU6qv䄤d`c+ K0nKȿ_]oI}e!_"|ntk鵇Iج+nTl6ܯ ՗. T9Q̀+bU145^P %k@|02L34' +,g*4 ius/f߻7x+pbޞo@/u`o֑ul`֨ӗoL#M^_}=|d$"@_Ϧفl )[x7^w |Yͮz8jy|0l½&ۃ7w݋6_pu.Msiac0a[A4?*9}9;qL$3ۓ4=XQyQ[mMA%냆5υ;p/!0xFt6;˗V_Zpr >rA75 5߄;soH{ L4ťtz&]Wn*>h*y4r~ovq>$2MNw-Ώ[;ӥ|q8痪Tm q <~F?c+ͤNrku-k(k:ޙH8.hj&0m6cu2N\S8\;}D * * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #if defined(TENGINE_LIBRARY) # define TENGINESHARED_EXPORT Q_DECL_EXPORT #else # define TENGINESHARED_EXPORT Q_DECL_IMPORT #endif tiled-1.0.3/src/plugins/tengine/tengineplugin.cpp000066400000000000000000000323221315121121300220610ustar00rootroot00000000000000/* * The T-Engine 4 Tiled Plugin * Copyright 2010, Mikolai Fajer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "tengineplugin.h" #include "map.h" #include "mapobject.h" #include "objectgroup.h" #include "properties.h" #include "savefile.h" #include "tile.h" #include "tilelayer.h" #include #include #include #include using namespace Tengine; TenginePlugin::TenginePlugin() { } bool TenginePlugin::write(const Tiled::Map *map, const QString &fileName) { using namespace Tiled; SaveFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { mError = tr("Could not open file for writing."); return false; } QTextStream out(file.device()); // Write the header QString header = map->property("header").toString(); foreach (const QString &line, header.split("\\n")) { out << line << endl; } const int width = map->width(); const int height = map->height(); QList asciiMap; QHash cachedTiles; QList propertyOrder; propertyOrder.append("terrain"); propertyOrder.append("object"); propertyOrder.append("actor"); propertyOrder.append("trap"); propertyOrder.append("status"); propertyOrder.append("spot"); // Ability to handle overflow and strings for display bool outputLists = false; int asciiDisplay = ASCII_MIN; int overflowDisplay = 1; QHash::const_iterator i; // Add the empty tile int numEmptyTiles = 0; Properties emptyTile; emptyTile["display"] = "?"; cachedTiles["?"] = emptyTile; // Process the map, collecting used display strings as we go for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { Properties currentTile = cachedTiles["?"]; for (Layer *layer : map->layers()) { // If the layer name does not start with one of the tile properties, skip it QString layerKey; QListIterator propertyIterator = propertyOrder; while (propertyIterator.hasNext()) { QString currentProperty = propertyIterator.next(); if (layer->name().startsWith(currentProperty, Qt::CaseInsensitive)) { layerKey = currentProperty; break; } } if (layerKey.isEmpty()) continue; // Process the Tile Layer if (TileLayer *tileLayer = layer->asTileLayer()) { if (Tile *tile = tileLayer->cellAt(x, y).tile()) { currentTile["display"] = tile->property("display"); currentTile[layerKey] = tile->property("value"); } // Process the Object Layer } else if (ObjectGroup *objectLayer = layer->asObjectGroup()) { for (const MapObject *obj : objectLayer->objects()) { if (floor(obj->y()) <= y && y <= floor(obj->y() + obj->height())) { if (floor(obj->x()) <= x && x <= floor(obj->x() + obj->width())) { // Check the Object Layer properties if either display or value was missing if (!obj->property("display").isNull()) { currentTile["display"] = obj->property("display"); } else if (!objectLayer->property("display").isNull()) { currentTile["display"] = objectLayer->property("display"); } if (!obj->property("value").isNull()) { currentTile[layerKey] = obj->property("value"); } else if (!objectLayer->property("value").isNull()) { currentTile[layerKey] = objectLayer->property("value"); } } } } } } // If the currentTile does not exist in the cache, add it if (!cachedTiles.contains(currentTile["display"].toString())) { cachedTiles[currentTile["display"].toString()] = currentTile; // Otherwise check that it EXACTLY matches the cached one // and if not... } else if (currentTile != cachedTiles[currentTile["display"].toString()]) { // Search the cached tiles for a match bool foundInCache = false; QString displayString; for (i = cachedTiles.constBegin(); i != cachedTiles.constEnd(); ++i) { displayString = i.key(); currentTile["display"].setValue(displayString); if (currentTile == i.value()) { foundInCache = true; break; } } // If we haven't found a match then find a random display string // and cache it if (!foundInCache) { while (true) { // First try to use the ASCII characters if (asciiDisplay < ASCII_MAX) { displayString = QString(QChar::fromLatin1(asciiDisplay)); asciiDisplay++; // Then fall back onto integers } else { displayString = QString::number(overflowDisplay); overflowDisplay++; } currentTile["display"] = displayString; if (!cachedTiles.contains(displayString)) { cachedTiles[displayString] = currentTile; break; } else if (currentTile == cachedTiles[currentTile["display"].toString()]) { break; } } } } // Check the output type if (currentTile["display"].toString().length() > 1) { outputLists = true; } // Check if we are still the emptyTile if (currentTile == emptyTile) { numEmptyTiles++; } // Finally add the character to the asciiMap asciiMap.append(currentTile["display"].toString()); } } // Write the definitions to the file out << "-- defineTile section" << endl; for (i = cachedTiles.constBegin(); i != cachedTiles.constEnd(); ++i) { QString displayString = i.key(); // Only print the emptyTile definition if there were empty tiles if (displayString == QLatin1String("?") && numEmptyTiles == 0) { continue; } // Need to escape " and \ characters displayString.replace(QLatin1Char('\\'), "\\\\"); displayString.replace(QLatin1Char('"'), "\\\""); QString args = constructArgs(i.value(), propertyOrder); if (!args.isEmpty()) { args = QString(", %1").arg(args); } out << QString("defineTile(\"%1\"%2)").arg(displayString, args) << endl; } // Check for an ObjectGroup named AddSpot out << endl << "-- addSpot section" << endl; foreach (Layer *layer, map->layers()) { ObjectGroup *objectLayer = layer->asObjectGroup(); if (objectLayer && objectLayer->name().startsWith("addspot", Qt::CaseInsensitive)) { foreach (const MapObject *obj, objectLayer->objects()) { QList propertyOrder; propertyOrder.append("type"); propertyOrder.append("subtype"); propertyOrder.append("additional"); QString args = constructArgs(obj->properties(), propertyOrder); if (!args.isEmpty()) { args = QString(", %1").arg(args); } for (int y = floor(obj->y()); y <= floor(obj->y() + obj->height()); ++y) { for (int x = floor(obj->x()); x <= floor(obj->x() + obj->width()); ++x) { out << QString("addSpot({%1, %2}%3)").arg(x).arg(y).arg(args) << endl; } } } } } // Check for an ObjectGroup named AddZone out << endl << "-- addZone section" << endl; foreach (Layer *layer, map->layers()) { ObjectGroup *objectLayer = layer->asObjectGroup(); if (objectLayer && objectLayer->name().startsWith("addzone", Qt::CaseInsensitive)) { foreach (MapObject *obj, objectLayer->objects()) { QList propertyOrder; propertyOrder.append("type"); propertyOrder.append("subtype"); propertyOrder.append("additional"); QString args = constructArgs(obj->properties(), propertyOrder); if (!args.isEmpty()) { args = QString(", %1").arg(args); } int top_left_x = floor(obj->x()); int top_left_y = floor(obj->y()); int bottom_right_x = floor(obj->x() + obj->width()); int bottom_right_y = floor(obj->y() + obj->height()); out << QString("addZone({%1, %2, %3, %4}%5)").arg(top_left_x).arg(top_left_y).arg(bottom_right_x).arg(bottom_right_y).arg(args) << endl; } } } // Write the map QString returnStart; QString returnStop; QString lineStart; QString lineStop; QString itemStart; QString itemStop; QString seperator; if (outputLists) { returnStart = "{"; returnStop = "}"; lineStart = "{"; lineStop = "},"; itemStart = "[["; itemStop = "]]"; seperator = ","; } else { returnStart = "[["; returnStop = "]]"; lineStart = ""; lineStop = ""; itemStart = ""; itemStop = ""; seperator = ""; } out << endl << "-- ASCII map section" << endl; out << "return " << returnStart << endl; for (int y = 0; y < height; ++y) { out << lineStart; for (int x = 0; x < width; ++x) { out << itemStart << asciiMap[x + (y * width)] << itemStop << seperator; } if (y == height - 1) { out << lineStop << returnStop; } else { out << lineStop << endl; } } if (!file.commit()) { mError = file.errorString(); return false; } return true; } QString TenginePlugin::nameFilter() const { return tr("T-Engine4 map files (*.lua)"); } QString TenginePlugin::shortName() const { return QLatin1String("te4"); } QString TenginePlugin::errorString() const { return mError; } QString TenginePlugin::constructArgs(const Tiled::Properties &props, const QList &propOrder) const { QString argString; // We work backwards so we don't have to include a bunch of nils for (int i = propOrder.size() - 1; i >= 0; --i) { QString currentValue = props[propOrder[i]].toString(); // Special handling of the "additional" property if ((propOrder[i] == "additional") && currentValue.isEmpty()) { currentValue = constructAdditionalTable(props, propOrder); } if (!argString.isEmpty()) { if (currentValue.isEmpty()) { currentValue = "nil"; } argString = QString("%1, %2").arg(currentValue, argString); } else if (!currentValue.isEmpty()) { argString = currentValue; } } return argString; } // Finds unhandled properties and bundles them into a Lua table QString TenginePlugin::constructAdditionalTable(const Tiled::Properties &props, const QList &propOrder) const { QString tableString; QMap unhandledProps = QMap(props); // Remove handled properties for (const QString &prop : propOrder) unhandledProps.remove(prop); // Construct the Lua string if (unhandledProps.size() > 0) { tableString = "{"; QMapIterator i(unhandledProps); while (i.hasNext()) { i.next(); tableString = QString("%1%2=%3,").arg(tableString, i.key(), i.value().toString()); } tableString = QString("%1}").arg(tableString); } return tableString; } tiled-1.0.3/src/plugins/tengine/tengineplugin.h000066400000000000000000000033071315121121300215270ustar00rootroot00000000000000/* * The T-Engine 4 Tiled Plugin * Copyright 2010, Mikolai Fajer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "tengine_global.h" #include "mapformat.h" #include "properties.h" #include namespace Tengine { // ASCII characters between decimals 32 and 126 should be ok const int ASCII_MIN = 32; const int ASCII_MAX = 126; class TENGINESHARED_EXPORT TenginePlugin : public Tiled::WritableMapFormat { Q_OBJECT Q_PLUGIN_METADATA(IID "org.mapeditor.MapFormat" FILE "plugin.json") public: TenginePlugin(); bool write(const Tiled::Map *map, const QString &fileName) override; QString nameFilter() const override; QString shortName() const override; QString errorString() const override; private: QString mError; QString constructArgs(const Tiled::Properties &props, const QList &propOrder) const; QString constructAdditionalTable(const Tiled::Properties &props, const QList &propOrder) const; }; } // namespace Tengine tiled-1.0.3/src/plugins/tmw/000077500000000000000000000000001315121121300156615ustar00rootroot00000000000000tiled-1.0.3/src/plugins/tmw/plugin.json000066400000000000000000000000331315121121300200460ustar00rootroot00000000000000{ "defaultEnable": false } tiled-1.0.3/src/plugins/tmw/tmw.pro000066400000000000000000000001661315121121300172150ustar00rootroot00000000000000include(../plugin.pri) DEFINES += TMW_LIBRARY SOURCES += tmwplugin.cpp HEADERS += tmwplugin.h\ tmw_global.h tiled-1.0.3/src/plugins/tmw/tmw.qbs000066400000000000000000000002641315121121300172010ustar00rootroot00000000000000import qbs 1.0 TiledPlugin { cpp.defines: ["TMW_LIBRARY"] files: [ "plugin.json", "tmw_global.h", "tmwplugin.cpp", "tmwplugin.h", ] } tiled-1.0.3/src/plugins/tmw/tmw_global.h000066400000000000000000000016651315121121300201710ustar00rootroot00000000000000/* * The Mana World Tiled Plugin * Copyright 2010, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #if defined(TMW_LIBRARY) # define TMWSHARED_EXPORT Q_DECL_EXPORT #else # define TMWSHARED_EXPORT Q_DECL_IMPORT #endif tiled-1.0.3/src/plugins/tmw/tmwplugin.cpp000066400000000000000000000051301315121121300204120ustar00rootroot00000000000000/* * The Mana World Tiled Plugin * Copyright 2010, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "tmwplugin.h" #include "map.h" #include "savefile.h" #include "tile.h" #include "tilelayer.h" #include using namespace Tmw; TmwPlugin::TmwPlugin() { } bool TmwPlugin::write(const Tiled::Map *map, const QString &fileName) { using namespace Tiled; TileLayer *collisionLayer = nullptr; for (Layer *layer : map->layers()) { if (layer->name().compare(QLatin1String("collision"), Qt::CaseInsensitive) == 0) { if (TileLayer *tileLayer = layer->asTileLayer()) { if (collisionLayer) { mError = tr("Multiple collision layers found!"); return false; } collisionLayer = tileLayer; } } } if (!collisionLayer) { mError = tr("No collision layer found!"); return false; } SaveFile file(fileName); if (!file.open(QIODevice::WriteOnly)) { mError = tr("Could not open file for writing."); return false; } const int width = collisionLayer->width(); const int height = collisionLayer->height(); QDataStream stream(file.device()); stream.setByteOrder(QDataStream::LittleEndian); stream << (qint16) width; stream << (qint16) height; for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { Tile *tile = collisionLayer->cellAt(x, y).tile(); stream << (qint8) (tile && tile->id() > 0); } } if (!file.commit()) { mError = file.errorString(); return false; } return true; } QString TmwPlugin::nameFilter() const { return tr("TMW-eAthena collision files (*.wlk)"); } QString TmwPlugin::shortName() const { return QLatin1String("tmw"); } QString TmwPlugin::errorString() const { return mError; } tiled-1.0.3/src/plugins/tmw/tmwplugin.h000066400000000000000000000024441315121121300200640ustar00rootroot00000000000000/* * The Mana World Tiled Plugin * Copyright 2010, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "tmw_global.h" #include "mapformat.h" #include namespace Tmw { class TMWSHARED_EXPORT TmwPlugin : public Tiled::WritableMapFormat { Q_OBJECT Q_PLUGIN_METADATA(IID "org.mapeditor.MapFormat" FILE "plugin.json") public: TmwPlugin(); bool write(const Tiled::Map *map, const QString &fileName) override; QString nameFilter() const override; QString shortName() const override; QString errorString() const override; private: QString mError; }; } // namespace Tmw tiled-1.0.3/src/qtpropertybrowser/000077500000000000000000000000001315121121300172265ustar00rootroot00000000000000tiled-1.0.3/src/qtpropertybrowser/README.TXT000066400000000000000000000104561315121121300205720ustar00rootroot00000000000000Qt Solutions Component: Property Browser A property browser framework enabling the user to edit a set of properties. The framework provides a browser widget that displays the given properties with labels and corresponding editing widgets (e.g. line edits or comboboxes). The various types of editing widgets are provided by the framework's editor factories: For each property type, the framework provides a property manager (e.g. QtIntPropertyManager and QtStringPropertyManager) which can be associated with the preferred editor factory (e.g. QtSpinBoxFactory and QtLineEditFactory). The framework also provides a variant based property type with corresponding variant manager and factory. Finally, the framework provides three ready-made implementations of the browser widget: QtTreePropertyBrowser, QtButtonPropertyBrowser and QtGroupBoxPropertyBrowser. Version history: 2.1: - QtTreePropertyBrowser - tooltip of property applied to first column, while second column shows the value text of property in its tooltip - QtAbstractPropertyManager - initializeProperty() and uninitializeProperty() without const modifier now - QtTreePropertyBrowser and QtGroupBoxPropertyBrowser - internal margin set to 0 - QtProperty - setEnabled() and isEnabled() methods added - QtTreePropertyBrowser - "rootIsDecorated", "indentation" and "headerVisible" properties added - QtProperty - hasValue() method added, useful for group properties 2.2: - FocusOut event now filtered out in case of Qt::ActiveWindowFocusReason reason. In that case editor is not closed when its sub dialog is executed - Removed bug in color icon generation - Decimals attribute added to "double" property type - PointF, SizeF and RectF types supported - Proper translation calls for tree property browser - QtProperty - ensure inserted subproperty is different from "this" property - QtBrowserItem class introduced, useful for identifying browser's gui elements - Possibility to control expanded state of QtTreePropertyBrowser's items from code - QtTreePropertyBrowser - "resizeMode" and "splitterPosition" properties added - QtGroupBoxPropertyBrowser - fixed crash in case of deleting the editor factory and then deleting the manager - "Decoration" example added - it shows how to add new responsibilities to the existing managers and editor factories 2.3: - Various bugfixes and improvements - QtProperty - setModified() and isModified() methods added - QtTreePropertyBrowser - disabling an item closes its editor - KeySequence, Char, Locale and Cursor types supported - Support for icons in enum type added - Kerning subproperty exposed in Font type - New property browser class added - QtButtonPropertyBrowser with drop down button as a grouping element 2.4: - Fixed memory leak of QtProperty - QtTreePropertyBrowser - group items are rendered better - QtTreePropertyBrowser - propertiesWithoutValueMarked and alternatingRowColors features added - QtTreePropertyBrowser - possibility of coloring properties added - QtTreePropertyBrowser - keyboard navigation improved - New factories providing popup dialogs added: QtColorEditorFactory and QtFontEditorFactory - Single step attribute added to: QtIntPropertyManager and QtDoublePropertyManager 2.5: - "Object Controller" example added. It implements a similar widget to the property editor in QDesigner - Compile with QT_NO_CURSOR - Expand root item with single click on the '+' icon - QtRectPropertyManager and QtRectFPropertyManager - by default constraint is null rect meaning no constraint is applied 2.6: - QtGroupPropertyBrowser - don't force the layout to show the whole labels' contents for read only properties, show tooltips for them in addition. - QtTreePropertyBrowser - fixed painting of the editor for color property type when style sheet is used (QTSOLBUG-64). - Make it possible to change the style of the checkboxes with a stylesheet (QTSOLBUG-61). - Change the minimum size of a combobox so that it can show at least one character and an icon. - Make it possible to properly style custom embedded editors (e.g. the color editor provided with the solution). tiled-1.0.3/src/qtpropertybrowser/common.pri000066400000000000000000000004041315121121300212300ustar00rootroot00000000000000TEMPLATE += fakelib QTPROPERTYBROWSER_LIBNAME = $$qtLibraryTarget(QtSolutions_PropertyBrowser-head) TEMPLATE -= fakelib QTPROPERTYBROWSER_LIBDIR = $$PWD/lib unix:qtpropertybrowser-uselib:!qtpropertybrowser-buildlib:QMAKE_RPATHDIR += $$QTPROPERTYBROWSER_LIBDIR tiled-1.0.3/src/qtpropertybrowser/qtpropertybrowser.qbs000066400000000000000000000016501315121121300235740ustar00rootroot00000000000000import qbs 1.0 StaticLibrary { name: "qtpropertybrowser" Depends { name: "cpp" } Depends { name: "Qt"; submodules: ["widgets"] } cpp.includePaths: ["src"] cpp.cxxLanguageVersion: "c++11" files: [ "src/qtbuttonpropertybrowser.cpp", "src/qtbuttonpropertybrowser.h", "src/qteditorfactory.cpp", "src/qteditorfactory.h", "src/qtgroupboxpropertybrowser.cpp", "src/qtgroupboxpropertybrowser.h", "src/qtpropertybrowser.cpp", "src/qtpropertybrowser.h", "src/qtpropertybrowserutils.cpp", "src/qtpropertybrowserutils_p.h", "src/qtpropertymanager.cpp", "src/qtpropertymanager.h", "src/qttreepropertybrowser.cpp", "src/qttreepropertybrowser.h", "src/qtvariantproperty.cpp", "src/qtvariantproperty.h", ] Export { Depends { name: "cpp" } cpp.includePaths: "src" } } tiled-1.0.3/src/qtpropertybrowser/src/000077500000000000000000000000001315121121300200155ustar00rootroot00000000000000tiled-1.0.3/src/qtpropertybrowser/src/QtAbstractEditorFactoryBase000066400000000000000000000000371315121121300253020ustar00rootroot00000000000000#include "qtpropertybrowser.h" tiled-1.0.3/src/qtpropertybrowser/src/QtAbstractPropertyBrowser000066400000000000000000000000371315121121300251210ustar00rootroot00000000000000#include "qtpropertybrowser.h" tiled-1.0.3/src/qtpropertybrowser/src/QtAbstractPropertyManager000066400000000000000000000000371315121121300250500ustar00rootroot00000000000000#include "qtpropertybrowser.h" tiled-1.0.3/src/qtpropertybrowser/src/QtBoolPropertyManager000066400000000000000000000000371315121121300242000ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtBrowserItem000066400000000000000000000000371315121121300225070ustar00rootroot00000000000000#include "qtpropertybrowser.h" tiled-1.0.3/src/qtpropertybrowser/src/QtButtonPropertyBrowser000066400000000000000000000000451315121121300246300ustar00rootroot00000000000000#include "qtbuttonpropertybrowser.h" tiled-1.0.3/src/qtpropertybrowser/src/QtCharEditorFactory000066400000000000000000000000351315121121300236170ustar00rootroot00000000000000#include "qteditorfactory.h" tiled-1.0.3/src/qtpropertybrowser/src/QtCharPropertyManager000066400000000000000000000000371315121121300241620ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtCheckBoxFactory000066400000000000000000000000351315121121300232610ustar00rootroot00000000000000#include "qteditorfactory.h" tiled-1.0.3/src/qtpropertybrowser/src/QtColorEditorFactory000066400000000000000000000000351315121121300240200ustar00rootroot00000000000000#include "qteditorfactory.h" tiled-1.0.3/src/qtpropertybrowser/src/QtColorPropertyManager000066400000000000000000000000371315121121300243630ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtCursorEditorFactory000066400000000000000000000000351315121121300242170ustar00rootroot00000000000000#include "qteditorfactory.h" tiled-1.0.3/src/qtpropertybrowser/src/QtCursorPropertyManager000066400000000000000000000000371315121121300245620ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtDateEditFactory000066400000000000000000000000351315121121300232560ustar00rootroot00000000000000#include "qteditorfactory.h" tiled-1.0.3/src/qtpropertybrowser/src/QtDatePropertyManager000066400000000000000000000000371315121121300241620ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtDateTimeEditFactory000066400000000000000000000000351315121121300240750ustar00rootroot00000000000000#include "qteditorfactory.h" tiled-1.0.3/src/qtpropertybrowser/src/QtDateTimePropertyManager000066400000000000000000000000371315121121300250010ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtDoublePropertyManager000066400000000000000000000000371315121121300245170ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtDoubleSpinBoxFactory000066400000000000000000000000351315121121300243100ustar00rootroot00000000000000#include "qteditorfactory.h" tiled-1.0.3/src/qtpropertybrowser/src/QtEnumEditorFactory000066400000000000000000000000351315121121300236460ustar00rootroot00000000000000#include "qteditorfactory.h" tiled-1.0.3/src/qtpropertybrowser/src/QtEnumPropertyManager000066400000000000000000000000371315121121300242110ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtFlagPropertyManager000066400000000000000000000000371315121121300241560ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtFontEditorFactory000066400000000000000000000000351315121121300236500ustar00rootroot00000000000000#include "qteditorfactory.h" tiled-1.0.3/src/qtpropertybrowser/src/QtFontPropertyManager000066400000000000000000000000371315121121300242130ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtGroupBoxPropertyBrowser000066400000000000000000000000471315121121300251240ustar00rootroot00000000000000#include "qtgroupboxpropertybrowser.h" tiled-1.0.3/src/qtpropertybrowser/src/QtGroupPropertyManager000066400000000000000000000000371315121121300244010ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtIntPropertyManager000066400000000000000000000000371315121121300240370ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtKeySequenceEditorFactory000066400000000000000000000000351315121121300251630ustar00rootroot00000000000000#include "qteditorfactory.h" tiled-1.0.3/src/qtpropertybrowser/src/QtKeySequencePropertyManager000066400000000000000000000000371315121121300255260ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtLineEditFactory000066400000000000000000000000351315121121300232700ustar00rootroot00000000000000#include "qteditorfactory.h" tiled-1.0.3/src/qtpropertybrowser/src/QtLocalePropertyManager000066400000000000000000000000371315121121300245040ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtPointFPropertyManager000066400000000000000000000000371315121121300245040ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtPointPropertyManager000066400000000000000000000000371315121121300243760ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtProperty000066400000000000000000000000371315121121300220710ustar00rootroot00000000000000#include "qtpropertybrowser.h" tiled-1.0.3/src/qtpropertybrowser/src/QtRectFPropertyManager000066400000000000000000000000371315121121300243100ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtRectPropertyManager000066400000000000000000000000371315121121300242020ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtScrollBarFactory000066400000000000000000000000351315121121300234560ustar00rootroot00000000000000#include "qteditorfactory.h" tiled-1.0.3/src/qtpropertybrowser/src/QtSizeFPropertyManager000066400000000000000000000000371315121121300243250ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtSizePolicyPropertyManager000066400000000000000000000000371315121121300253770ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtSizePropertyManager000066400000000000000000000000371315121121300242170ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtSliderFactory000066400000000000000000000000351315121121300230150ustar00rootroot00000000000000#include "qteditorfactory.h" tiled-1.0.3/src/qtpropertybrowser/src/QtSpinBoxFactory000066400000000000000000000000351315121121300231550ustar00rootroot00000000000000#include "qteditorfactory.h" tiled-1.0.3/src/qtpropertybrowser/src/QtStringPropertyManager000066400000000000000000000000371315121121300245530ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtTimeEditFactory000066400000000000000000000000351315121121300232770ustar00rootroot00000000000000#include "qteditorfactory.h" tiled-1.0.3/src/qtpropertybrowser/src/QtTimePropertyManager000066400000000000000000000000371315121121300242030ustar00rootroot00000000000000#include "qtpropertymanager.h" tiled-1.0.3/src/qtpropertybrowser/src/QtTreePropertyBrowser000066400000000000000000000000431315121121300242520ustar00rootroot00000000000000#include "qttreepropertybrowser.h" tiled-1.0.3/src/qtpropertybrowser/src/QtVariantEditorFactory000066400000000000000000000000371315121121300243500ustar00rootroot00000000000000#include "qtvariantproperty.h" tiled-1.0.3/src/qtpropertybrowser/src/QtVariantProperty000066400000000000000000000000371315121121300234160ustar00rootroot00000000000000#include "qtvariantproperty.h" tiled-1.0.3/src/qtpropertybrowser/src/QtVariantPropertyManager000066400000000000000000000000371315121121300247110ustar00rootroot00000000000000#include "qtvariantproperty.h" tiled-1.0.3/src/qtpropertybrowser/src/images/000077500000000000000000000000001315121121300212625ustar00rootroot00000000000000tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-arrow.png000066400000000000000000000002531315121121300244350ustar00rootroot00000000000000PNG  IHDRm PLTEtRNS@fPIDATx^=α 0 ѤA"9Oh؁-k^cK?m :V-@Gêeΰqo_NpoYք^]IuZIENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-busy.png000066400000000000000000000003111315121121300242600ustar00rootroot00000000000000PNG  IHDR g PLTE~OtRNS@fnIDATx^ͱ 0P ~)~6idJWO.l(@ X`@ tJ!9l&aqlQ] ~#-搫I 8{4u4IENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-closedhand.png000066400000000000000000000002231315121121300254040ustar00rootroot00000000000000PNG  IHDR7 pHYs 7˭EIDAT(ϭ D-$pzS逢B@@r(2`' ـM^ PIENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-cross.png000066400000000000000000000002021315121121300244260ustar00rootroot00000000000000PNG  IHDRm PLTEtRNS@f'IDATc`  P Vpm=XK "IENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-forbidden.png000066400000000000000000000003071315121121300252370ustar00rootroot00000000000000PNG  IHDRm PLTEtRNS@flIDATx^uα C1P y \`4.L`"EB \RAc!OҾU+2ֵ_d\l+ Zz<'r:#7$/sIENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-hand.png000066400000000000000000000002371315121121300242170ustar00rootroot00000000000000PNG  IHDRm PLTEtRNS@fDIDAT[c``aL(=XzjБ JcZd N Ѫf @&ЫV-J7U%IENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-hsplit.png000066400000000000000000000002331315121121300246040ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@f@IDATc`..@ ͡TY;AӀtS`` e Cap0 w/PܪIENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-ibeam.png000066400000000000000000000001741315121121300243620ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@f!IDATc`"`*@340܇^TIENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-openhand.png000066400000000000000000000002401315121121300250730ustar00rootroot00000000000000PNG  IHDR7 pHYs 7˭RIDAT(υ_tW&DNt^a'`O#9#V*~Wa`'-$2d_=J;Ҁ>x0tbIENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-sizeall.png000066400000000000000000000002561315121121300247510ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@fSIDAT[c`\ f^5P00:H0:%BD&pÁ f/0watêNXIENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-sizeb.png000066400000000000000000000002411315121121300244140ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@fFIDATc` VjSC!*ҌPJBN1 D`uN:5J@(ƀbv l= jIENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-sizef.png000066400000000000000000000002411315121121300244200ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@fFIDATc` VjSCtD|j!z(00AtpBhQU 5JsBiPTa.$,= 'IENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-sizeh.png000066400000000000000000000002211315121121300244200ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@f6IDAT[c`h00p% l LSXBtg(D h8LL# /97IENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-sizev.png000066400000000000000000000002151315121121300244410ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@f2IDAT[c`L+ 4W kKC驡 Emf>>0܇4 SvIENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-uparrow.png000066400000000000000000000002041315121121300247760ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@f)IDAT[c`L+ 4W kKC驡 0` B7~2IENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-vsplit.png000066400000000000000000000002411315121121300246210ustar00rootroot00000000000000PNG  IHDRm PLTE~OtRNS@fFIDAT[c`  9Cjh3UfZR p`G3f~{VOIENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-wait.png000066400000000000000000000002541315121121300242500ustar00rootroot00000000000000PNG  IHDRm PLTEtRNS@fQIDATc`@RVӡ|:r&KS.ьK& ʜ10bpfD~%󦢚37--{PY IENDB`tiled-1.0.3/src/qtpropertybrowser/src/images/cursor-whatsthis.png000066400000000000000000000002771315121121300253270ustar00rootroot00000000000000PNG  IHDR g PLTEtRNS@fdIDATWch` ! U+Ai lS R #1B[&-3VHMa̘e,1TD֫6@D8 SÀ$W/qIENDB`tiled-1.0.3/src/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp000066400000000000000000000471261315121121300256240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtbuttonpropertybrowser.h" #include #include #include #include #include #include #include #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif class QtButtonPropertyBrowserPrivate { QtButtonPropertyBrowser *q_ptr; Q_DECLARE_PUBLIC(QtButtonPropertyBrowser) public: void init(QWidget *parent); void propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex); void propertyRemoved(QtBrowserItem *index); void propertyChanged(QtBrowserItem *index); QWidget *createEditor(QtProperty *property, QWidget *parent) const { return q_ptr->createEditor(property, parent); } void slotEditorDestroyed(); void slotUpdate(); void slotToggled(bool checked); struct WidgetItem { WidgetItem() : widget(0), label(0), widgetLabel(0), button(0), container(0), layout(0), /*line(0), */parent(0), expanded(false) { } QWidget *widget; // can be null QLabel *label; // main label with property name QLabel *widgetLabel; // label substitute showing the current value if there is no widget QToolButton *button; // expandable button for items with children QWidget *container; // container which is expanded when the button is clicked QGridLayout *layout; // layout in container WidgetItem *parent; QList children; bool expanded; }; private: void updateLater(); void updateItem(WidgetItem *item); void insertRow(QGridLayout *layout, int row) const; void removeRow(QGridLayout *layout, int row) const; int gridRow(WidgetItem *item) const; int gridSpan(WidgetItem *item) const; void setExpanded(WidgetItem *item, bool expanded); QToolButton *createButton(QWidget *panret = 0) const; QMap m_indexToItem; QMap m_itemToIndex; QMap m_widgetToItem; QMap m_buttonToItem; QGridLayout *m_mainLayout; QList m_children; QList m_recreateQueue; }; QToolButton *QtButtonPropertyBrowserPrivate::createButton(QWidget *parent) const { QToolButton *button = new QToolButton(parent); button->setCheckable(true); button->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); button->setArrowType(Qt::DownArrow); button->setIconSize(QSize(3, 16)); /* QIcon icon; icon.addPixmap(q_ptr->style()->standardPixmap(QStyle::SP_ArrowDown), QIcon::Normal, QIcon::Off); icon.addPixmap(q_ptr->style()->standardPixmap(QStyle::SP_ArrowUp), QIcon::Normal, QIcon::On); button->setIcon(icon); */ return button; } int QtButtonPropertyBrowserPrivate::gridRow(WidgetItem *item) const { QList siblings; if (item->parent) siblings = item->parent->children; else siblings = m_children; int row = 0; QListIterator it(siblings); while (it.hasNext()) { WidgetItem *sibling = it.next(); if (sibling == item) return row; row += gridSpan(sibling); } return -1; } int QtButtonPropertyBrowserPrivate::gridSpan(WidgetItem *item) const { if (item->container && item->expanded) return 2; return 1; } void QtButtonPropertyBrowserPrivate::init(QWidget *parent) { m_mainLayout = new QGridLayout(); parent->setLayout(m_mainLayout); QLayoutItem *item = new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding); m_mainLayout->addItem(item, 0, 0); } void QtButtonPropertyBrowserPrivate::slotEditorDestroyed() { QWidget *editor = qobject_cast(q_ptr->sender()); if (!editor) return; if (!m_widgetToItem.contains(editor)) return; m_widgetToItem[editor]->widget = 0; m_widgetToItem.remove(editor); } void QtButtonPropertyBrowserPrivate::slotUpdate() { QListIterator itItem(m_recreateQueue); while (itItem.hasNext()) { WidgetItem *item = itItem.next(); WidgetItem *parent = item->parent; QWidget *w = 0; QGridLayout *l = 0; const int oldRow = gridRow(item); if (parent) { w = parent->container; l = parent->layout; } else { w = q_ptr; l = m_mainLayout; } int span = 1; if (!item->widget && !item->widgetLabel) span = 2; item->label = new QLabel(w); item->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); l->addWidget(item->label, oldRow, 0, 1, span); updateItem(item); } m_recreateQueue.clear(); } void QtButtonPropertyBrowserPrivate::setExpanded(WidgetItem *item, bool expanded) { if (item->expanded == expanded) return; if (!item->container) return; item->expanded = expanded; const int row = gridRow(item); WidgetItem *parent = item->parent; QGridLayout *l = 0; if (parent) l = parent->layout; else l = m_mainLayout; if (expanded) { insertRow(l, row + 1); l->addWidget(item->container, row + 1, 0, 1, 2); item->container->show(); } else { l->removeWidget(item->container); item->container->hide(); removeRow(l, row + 1); } item->button->setChecked(expanded); item->button->setArrowType(expanded ? Qt::UpArrow : Qt::DownArrow); } void QtButtonPropertyBrowserPrivate::slotToggled(bool checked) { WidgetItem *item = m_buttonToItem.value(q_ptr->sender()); if (!item) return; setExpanded(item, checked); if (checked) emit q_ptr->expanded(m_itemToIndex.value(item)); else emit q_ptr->collapsed(m_itemToIndex.value(item)); } void QtButtonPropertyBrowserPrivate::updateLater() { QTimer::singleShot(0, q_ptr, SLOT(slotUpdate())); } void QtButtonPropertyBrowserPrivate::propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex) { WidgetItem *afterItem = m_indexToItem.value(afterIndex); WidgetItem *parentItem = m_indexToItem.value(index->parent()); WidgetItem *newItem = new WidgetItem(); newItem->parent = parentItem; QGridLayout *layout = 0; QWidget *parentWidget = 0; int row = -1; if (!afterItem) { row = 0; if (parentItem) parentItem->children.insert(0, newItem); else m_children.insert(0, newItem); } else { row = gridRow(afterItem) + gridSpan(afterItem); if (parentItem) parentItem->children.insert(parentItem->children.indexOf(afterItem) + 1, newItem); else m_children.insert(m_children.indexOf(afterItem) + 1, newItem); } if (!parentItem) { layout = m_mainLayout; parentWidget = q_ptr; } else { if (!parentItem->container) { m_recreateQueue.removeAll(parentItem); WidgetItem *grandParent = parentItem->parent; QGridLayout *l = 0; const int oldRow = gridRow(parentItem); if (grandParent) { l = grandParent->layout; } else { l = m_mainLayout; } QFrame *container = new QFrame(); container->setFrameShape(QFrame::Panel); container->setFrameShadow(QFrame::Raised); parentItem->container = container; parentItem->button = createButton(); m_buttonToItem[parentItem->button] = parentItem; q_ptr->connect(parentItem->button, SIGNAL(toggled(bool)), q_ptr, SLOT(slotToggled(bool))); parentItem->layout = new QGridLayout(); container->setLayout(parentItem->layout); if (parentItem->label) { l->removeWidget(parentItem->label); delete parentItem->label; parentItem->label = 0; } int span = 1; if (!parentItem->widget && !parentItem->widgetLabel) span = 2; l->addWidget(parentItem->button, oldRow, 0, 1, span); updateItem(parentItem); } layout = parentItem->layout; parentWidget = parentItem->container; } newItem->label = new QLabel(parentWidget); newItem->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); newItem->widget = createEditor(index->property(), parentWidget); if (newItem->widget) { QObject::connect(newItem->widget, SIGNAL(destroyed()), q_ptr, SLOT(slotEditorDestroyed())); m_widgetToItem[newItem->widget] = newItem; } else if (index->property()->hasValue()) { newItem->widgetLabel = new QLabel(parentWidget); newItem->widgetLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); } insertRow(layout, row); int span = 1; if (newItem->widget) layout->addWidget(newItem->widget, row, 1); else if (newItem->widgetLabel) layout->addWidget(newItem->widgetLabel, row, 1); else span = 2; layout->addWidget(newItem->label, row, 0, span, 1); m_itemToIndex[newItem] = index; m_indexToItem[index] = newItem; updateItem(newItem); } void QtButtonPropertyBrowserPrivate::propertyRemoved(QtBrowserItem *index) { WidgetItem *item = m_indexToItem.value(index); m_indexToItem.remove(index); m_itemToIndex.remove(item); WidgetItem *parentItem = item->parent; const int row = gridRow(item); if (parentItem) parentItem->children.removeAt(parentItem->children.indexOf(item)); else m_children.removeAt(m_children.indexOf(item)); const int colSpan = gridSpan(item); m_buttonToItem.remove(item->button); if (item->widget) delete item->widget; if (item->label) delete item->label; if (item->widgetLabel) delete item->widgetLabel; if (item->button) delete item->button; if (item->container) delete item->container; if (!parentItem) { removeRow(m_mainLayout, row); if (colSpan > 1) removeRow(m_mainLayout, row); } else if (parentItem->children.count() != 0) { removeRow(parentItem->layout, row); if (colSpan > 1) removeRow(parentItem->layout, row); } else { const WidgetItem *grandParent = parentItem->parent; QGridLayout *l = 0; if (grandParent) { l = grandParent->layout; } else { l = m_mainLayout; } const int parentRow = gridRow(parentItem); const int parentSpan = gridSpan(parentItem); l->removeWidget(parentItem->button); l->removeWidget(parentItem->container); delete parentItem->button; delete parentItem->container; parentItem->button = 0; parentItem->container = 0; parentItem->layout = 0; if (!m_recreateQueue.contains(parentItem)) m_recreateQueue.append(parentItem); if (parentSpan > 1) removeRow(l, parentRow + 1); updateLater(); } m_recreateQueue.removeAll(item); delete item; } void QtButtonPropertyBrowserPrivate::insertRow(QGridLayout *layout, int row) const { QMap itemToPos; int idx = 0; while (idx < layout->count()) { int r, c, rs, cs; layout->getItemPosition(idx, &r, &c, &rs, &cs); if (r >= row) { itemToPos[layout->takeAt(idx)] = QRect(r + 1, c, rs, cs); } else { idx++; } } const QMap::ConstIterator icend = itemToPos.constEnd(); for(QMap::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) { const QRect r = it.value(); layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height()); } } void QtButtonPropertyBrowserPrivate::removeRow(QGridLayout *layout, int row) const { QMap itemToPos; int idx = 0; while (idx < layout->count()) { int r, c, rs, cs; layout->getItemPosition(idx, &r, &c, &rs, &cs); if (r > row) { itemToPos[layout->takeAt(idx)] = QRect(r - 1, c, rs, cs); } else { idx++; } } const QMap::ConstIterator icend = itemToPos.constEnd(); for(QMap::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) { const QRect r = it.value(); layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height()); } } void QtButtonPropertyBrowserPrivate::propertyChanged(QtBrowserItem *index) { WidgetItem *item = m_indexToItem.value(index); updateItem(item); } void QtButtonPropertyBrowserPrivate::updateItem(WidgetItem *item) { QtProperty *property = m_itemToIndex[item]->property(); if (item->button) { QFont font = item->button->font(); font.setUnderline(property->isModified()); item->button->setFont(font); item->button->setText(property->propertyName()); item->button->setToolTip(property->toolTip()); item->button->setStatusTip(property->statusTip()); item->button->setWhatsThis(property->whatsThis()); item->button->setEnabled(property->isEnabled()); } if (item->label) { QFont font = item->label->font(); font.setUnderline(property->isModified()); item->label->setFont(font); item->label->setText(property->propertyName()); item->label->setToolTip(property->toolTip()); item->label->setStatusTip(property->statusTip()); item->label->setWhatsThis(property->whatsThis()); item->label->setEnabled(property->isEnabled()); } if (item->widgetLabel) { QFont font = item->widgetLabel->font(); font.setUnderline(false); item->widgetLabel->setFont(font); item->widgetLabel->setText(property->valueText()); item->widgetLabel->setToolTip(property->valueText()); item->widgetLabel->setEnabled(property->isEnabled()); } if (item->widget) { QFont font = item->widget->font(); font.setUnderline(false); item->widget->setFont(font); item->widget->setEnabled(property->isEnabled()); item->widget->setToolTip(property->valueText()); } } /*! \class QtButtonPropertyBrowser \brief The QtButtonPropertyBrowser class provides a drop down QToolButton based property browser. A property browser is a widget that enables the user to edit a given set of properties. Each property is represented by a label specifying the property's name, and an editing widget (e.g. a line edit or a combobox) holding its value. A property can have zero or more subproperties. QtButtonPropertyBrowser provides drop down button for all nested properties, i.e. subproperties are enclosed by a container associated with the drop down button. The parent property's name is displayed as button text. For example: \image qtbuttonpropertybrowser.png Use the QtAbstractPropertyBrowser API to add, insert and remove properties from an instance of the QtButtonPropertyBrowser class. The properties themselves are created and managed by implementations of the QtAbstractPropertyManager class. \sa QtTreePropertyBrowser, QtAbstractPropertyBrowser */ /*! \fn void QtButtonPropertyBrowser::collapsed(QtBrowserItem *item) This signal is emitted when the \a item is collapsed. \sa expanded(), setExpanded() */ /*! \fn void QtButtonPropertyBrowser::expanded(QtBrowserItem *item) This signal is emitted when the \a item is expanded. \sa collapsed(), setExpanded() */ /*! Creates a property browser with the given \a parent. */ QtButtonPropertyBrowser::QtButtonPropertyBrowser(QWidget *parent) : QtAbstractPropertyBrowser(parent) { d_ptr = new QtButtonPropertyBrowserPrivate; d_ptr->q_ptr = this; d_ptr->init(this); } /*! Destroys this property browser. Note that the properties that were inserted into this browser are \e not destroyed since they may still be used in other browsers. The properties are owned by the manager that created them. \sa QtProperty, QtAbstractPropertyManager */ QtButtonPropertyBrowser::~QtButtonPropertyBrowser() { const QMap::ConstIterator icend = d_ptr->m_itemToIndex.constEnd(); for (QMap::ConstIterator it = d_ptr->m_itemToIndex.constBegin(); it != icend; ++it) delete it.key(); delete d_ptr; } /*! \reimp */ void QtButtonPropertyBrowser::itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem) { d_ptr->propertyInserted(item, afterItem); } /*! \reimp */ void QtButtonPropertyBrowser::itemRemoved(QtBrowserItem *item) { d_ptr->propertyRemoved(item); } /*! \reimp */ void QtButtonPropertyBrowser::itemChanged(QtBrowserItem *item) { d_ptr->propertyChanged(item); } /*! Sets the \a item to either collapse or expanded, depending on the value of \a expanded. \sa isExpanded(), expanded(), collapsed() */ void QtButtonPropertyBrowser::setExpanded(QtBrowserItem *item, bool expanded) { QtButtonPropertyBrowserPrivate::WidgetItem *itm = d_ptr->m_indexToItem.value(item); if (itm) d_ptr->setExpanded(itm, expanded); } /*! Returns true if the \a item is expanded; otherwise returns false. \sa setExpanded() */ bool QtButtonPropertyBrowser::isExpanded(QtBrowserItem *item) const { QtButtonPropertyBrowserPrivate::WidgetItem *itm = d_ptr->m_indexToItem.value(item); if (itm) return itm->expanded; return false; } #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif #include "moc_qtbuttonpropertybrowser.cpp" tiled-1.0.3/src/qtpropertybrowser/src/qtbuttonpropertybrowser.h000066400000000000000000000061111315121121300252560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTBUTTONPROPERTYBROWSER_H #define QTBUTTONPROPERTYBROWSER_H #include "qtpropertybrowser.h" #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif class QtButtonPropertyBrowserPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtButtonPropertyBrowser : public QtAbstractPropertyBrowser { Q_OBJECT public: QtButtonPropertyBrowser(QWidget *parent = 0); ~QtButtonPropertyBrowser(); void setExpanded(QtBrowserItem *item, bool expanded); bool isExpanded(QtBrowserItem *item) const; Q_SIGNALS: void collapsed(QtBrowserItem *item); void expanded(QtBrowserItem *item); protected: virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem); virtual void itemRemoved(QtBrowserItem *item); virtual void itemChanged(QtBrowserItem *item); private: QtButtonPropertyBrowserPrivate *d_ptr; Q_DECLARE_PRIVATE(QtButtonPropertyBrowser) Q_DISABLE_COPY(QtButtonPropertyBrowser) Q_PRIVATE_SLOT(d_func(), void slotUpdate()) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed()) Q_PRIVATE_SLOT(d_func(), void slotToggled(bool)) }; #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif #endif tiled-1.0.3/src/qtpropertybrowser/src/qteditorfactory.cpp000066400000000000000000002467021315121121300237570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qteditorfactory.h" #include "qtpropertybrowserutils_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(Q_CC_MSVC) # pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */ #endif #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif // Set a hard coded left margin to account for the indentation // of the tree view icon when switching to an editor static inline void setupTreeViewEditorMargin(QLayout *lt) { enum { DecorationMargin = 4 }; if (QApplication::layoutDirection() == Qt::LeftToRight) lt->setContentsMargins(DecorationMargin, 0, 0, 0); else lt->setContentsMargins(0, 0, DecorationMargin, 0); } // ---------- EditorFactoryPrivate : // Base class for editor factory private classes. Manages mapping of properties to editors and vice versa. template class EditorFactoryPrivate { public: typedef QList EditorList; typedef QMap PropertyToEditorListMap; typedef QMap EditorToPropertyMap; Editor *createEditor(QtProperty *property, QWidget *parent); void initializeEditor(QtProperty *property, Editor *e); void slotEditorDestroyed(QObject *object); PropertyToEditorListMap m_createdEditors; EditorToPropertyMap m_editorToProperty; }; template Editor *EditorFactoryPrivate::createEditor(QtProperty *property, QWidget *parent) { Editor *editor = new Editor(parent); initializeEditor(property, editor); return editor; } template void EditorFactoryPrivate::initializeEditor(QtProperty *property, Editor *editor) { typename PropertyToEditorListMap::iterator it = m_createdEditors.find(property); if (it == m_createdEditors.end()) it = m_createdEditors.insert(property, EditorList()); it.value().append(editor); m_editorToProperty.insert(editor, property); } template void EditorFactoryPrivate::slotEditorDestroyed(QObject *object) { const typename EditorToPropertyMap::iterator ecend = m_editorToProperty.end(); for (typename EditorToPropertyMap::iterator itEditor = m_editorToProperty.begin(); itEditor != ecend; ++itEditor) { if (itEditor.key() == object) { Editor *editor = itEditor.key(); QtProperty *property = itEditor.value(); const typename PropertyToEditorListMap::iterator pit = m_createdEditors.find(property); if (pit != m_createdEditors.end()) { pit.value().removeAll(editor); if (pit.value().empty()) m_createdEditors.erase(pit); } m_editorToProperty.erase(itEditor); return; } } } // ------------ QtSpinBoxFactory class QtSpinBoxFactoryPrivate : public EditorFactoryPrivate { QtSpinBoxFactory *q_ptr; Q_DECLARE_PUBLIC(QtSpinBoxFactory) public: void slotPropertyChanged(QtProperty *property, int value); void slotRangeChanged(QtProperty *property, int min, int max); void slotSingleStepChanged(QtProperty *property, int step); void slotReadOnlyChanged(QtProperty *property, bool readOnly); void slotSetValue(int value); }; void QtSpinBoxFactoryPrivate::slotPropertyChanged(QtProperty *property, int value) { if (!m_createdEditors.contains(property)) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QSpinBox *editor = itEditor.next(); if (editor->value() != value) { editor->blockSignals(true); editor->setValue(value); editor->blockSignals(false); } } } void QtSpinBoxFactoryPrivate::slotRangeChanged(QtProperty *property, int min, int max) { if (!m_createdEditors.contains(property)) return; QtIntPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QSpinBox *editor = itEditor.next(); editor->blockSignals(true); editor->setRange(min, max); editor->setValue(manager->value(property)); editor->blockSignals(false); } } void QtSpinBoxFactoryPrivate::slotSingleStepChanged(QtProperty *property, int step) { if (!m_createdEditors.contains(property)) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QSpinBox *editor = itEditor.next(); editor->blockSignals(true); editor->setSingleStep(step); editor->blockSignals(false); } } void QtSpinBoxFactoryPrivate::slotReadOnlyChanged( QtProperty *property, bool readOnly) { if (!m_createdEditors.contains(property)) return; QtIntPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QSpinBox *editor = itEditor.next(); editor->blockSignals(true); editor->setReadOnly(readOnly); editor->blockSignals(false); } } void QtSpinBoxFactoryPrivate::slotSetValue(int value) { QObject *object = q_ptr->sender(); const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) { if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtIntPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } } /*! \class QtSpinBoxFactory \brief The QtSpinBoxFactory class provides QSpinBox widgets for properties created by QtIntPropertyManager objects. \sa QtAbstractEditorFactory, QtIntPropertyManager */ /*! Creates a factory with the given \a parent. */ QtSpinBoxFactory::QtSpinBoxFactory(QObject *parent) : QtAbstractEditorFactory(parent) { d_ptr = new QtSpinBoxFactoryPrivate(); d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtSpinBoxFactory::~QtSpinBoxFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); delete d_ptr; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtSpinBoxFactory::connectPropertyManager(QtIntPropertyManager *manager) { connect(manager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotPropertyChanged(QtProperty *, int))); connect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), this, SLOT(slotRangeChanged(QtProperty *, int, int))); connect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), this, SLOT(slotSingleStepChanged(QtProperty *, int))); connect(manager, SIGNAL(readOnlyChanged(QtProperty *, bool)), this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtSpinBoxFactory::createEditor(QtIntPropertyManager *manager, QtProperty *property, QWidget *parent) { QSpinBox *editor = d_ptr->createEditor(property, parent); editor->setSingleStep(manager->singleStep(property)); editor->setRange(manager->minimum(property), manager->maximum(property)); editor->setValue(manager->value(property)); editor->setKeyboardTracking(false); editor->setReadOnly(manager->isReadOnly(property)); connect(editor, SIGNAL(valueChanged(int)), this, SLOT(slotSetValue(int))); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtSpinBoxFactory::disconnectPropertyManager(QtIntPropertyManager *manager) { disconnect(manager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotPropertyChanged(QtProperty *, int))); disconnect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), this, SLOT(slotRangeChanged(QtProperty *, int, int))); disconnect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), this, SLOT(slotSingleStepChanged(QtProperty *, int))); disconnect(manager, SIGNAL(readOnlyChanged(QtProperty *, bool)), this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); } // QtSliderFactory class QtSliderFactoryPrivate : public EditorFactoryPrivate { QtSliderFactory *q_ptr; Q_DECLARE_PUBLIC(QtSliderFactory) public: void slotPropertyChanged(QtProperty *property, int value); void slotRangeChanged(QtProperty *property, int min, int max); void slotSingleStepChanged(QtProperty *property, int step); void slotSetValue(int value); }; void QtSliderFactoryPrivate::slotPropertyChanged(QtProperty *property, int value) { if (!m_createdEditors.contains(property)) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QSlider *editor = itEditor.next(); editor->blockSignals(true); editor->setValue(value); editor->blockSignals(false); } } void QtSliderFactoryPrivate::slotRangeChanged(QtProperty *property, int min, int max) { if (!m_createdEditors.contains(property)) return; QtIntPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QSlider *editor = itEditor.next(); editor->blockSignals(true); editor->setRange(min, max); editor->setValue(manager->value(property)); editor->blockSignals(false); } } void QtSliderFactoryPrivate::slotSingleStepChanged(QtProperty *property, int step) { if (!m_createdEditors.contains(property)) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QSlider *editor = itEditor.next(); editor->blockSignals(true); editor->setSingleStep(step); editor->blockSignals(false); } } void QtSliderFactoryPrivate::slotSetValue(int value) { QObject *object = q_ptr->sender(); const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor ) { if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtIntPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } } /*! \class QtSliderFactory \brief The QtSliderFactory class provides QSlider widgets for properties created by QtIntPropertyManager objects. \sa QtAbstractEditorFactory, QtIntPropertyManager */ /*! Creates a factory with the given \a parent. */ QtSliderFactory::QtSliderFactory(QObject *parent) : QtAbstractEditorFactory(parent) { d_ptr = new QtSliderFactoryPrivate(); d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtSliderFactory::~QtSliderFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); delete d_ptr; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtSliderFactory::connectPropertyManager(QtIntPropertyManager *manager) { connect(manager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotPropertyChanged(QtProperty *, int))); connect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), this, SLOT(slotRangeChanged(QtProperty *, int, int))); connect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), this, SLOT(slotSingleStepChanged(QtProperty *, int))); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtSliderFactory::createEditor(QtIntPropertyManager *manager, QtProperty *property, QWidget *parent) { QSlider *editor = new QSlider(Qt::Horizontal, parent); d_ptr->initializeEditor(property, editor); editor->setSingleStep(manager->singleStep(property)); editor->setRange(manager->minimum(property), manager->maximum(property)); editor->setValue(manager->value(property)); connect(editor, SIGNAL(valueChanged(int)), this, SLOT(slotSetValue(int))); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtSliderFactory::disconnectPropertyManager(QtIntPropertyManager *manager) { disconnect(manager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotPropertyChanged(QtProperty *, int))); disconnect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), this, SLOT(slotRangeChanged(QtProperty *, int, int))); disconnect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), this, SLOT(slotSingleStepChanged(QtProperty *, int))); } // QtSliderFactory class QtScrollBarFactoryPrivate : public EditorFactoryPrivate { QtScrollBarFactory *q_ptr; Q_DECLARE_PUBLIC(QtScrollBarFactory) public: void slotPropertyChanged(QtProperty *property, int value); void slotRangeChanged(QtProperty *property, int min, int max); void slotSingleStepChanged(QtProperty *property, int step); void slotSetValue(int value); }; void QtScrollBarFactoryPrivate::slotPropertyChanged(QtProperty *property, int value) { if (!m_createdEditors.contains(property)) return; QListIterator itEditor( m_createdEditors[property]); while (itEditor.hasNext()) { QScrollBar *editor = itEditor.next(); editor->blockSignals(true); editor->setValue(value); editor->blockSignals(false); } } void QtScrollBarFactoryPrivate::slotRangeChanged(QtProperty *property, int min, int max) { if (!m_createdEditors.contains(property)) return; QtIntPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; QListIterator itEditor( m_createdEditors[property]); while (itEditor.hasNext()) { QScrollBar *editor = itEditor.next(); editor->blockSignals(true); editor->setRange(min, max); editor->setValue(manager->value(property)); editor->blockSignals(false); } } void QtScrollBarFactoryPrivate::slotSingleStepChanged(QtProperty *property, int step) { if (!m_createdEditors.contains(property)) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QScrollBar *editor = itEditor.next(); editor->blockSignals(true); editor->setSingleStep(step); editor->blockSignals(false); } } void QtScrollBarFactoryPrivate::slotSetValue(int value) { QObject *object = q_ptr->sender(); const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtIntPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtScrollBarFactory \brief The QtScrollBarFactory class provides QScrollBar widgets for properties created by QtIntPropertyManager objects. \sa QtAbstractEditorFactory, QtIntPropertyManager */ /*! Creates a factory with the given \a parent. */ QtScrollBarFactory::QtScrollBarFactory(QObject *parent) : QtAbstractEditorFactory(parent) { d_ptr = new QtScrollBarFactoryPrivate(); d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtScrollBarFactory::~QtScrollBarFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); delete d_ptr; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtScrollBarFactory::connectPropertyManager(QtIntPropertyManager *manager) { connect(manager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotPropertyChanged(QtProperty *, int))); connect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), this, SLOT(slotRangeChanged(QtProperty *, int, int))); connect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), this, SLOT(slotSingleStepChanged(QtProperty *, int))); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtScrollBarFactory::createEditor(QtIntPropertyManager *manager, QtProperty *property, QWidget *parent) { QScrollBar *editor = new QScrollBar(Qt::Horizontal, parent); d_ptr->initializeEditor(property, editor); editor->setSingleStep(manager->singleStep(property)); editor->setRange(manager->minimum(property), manager->maximum(property)); editor->setValue(manager->value(property)); connect(editor, SIGNAL(valueChanged(int)), this, SLOT(slotSetValue(int))); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtScrollBarFactory::disconnectPropertyManager(QtIntPropertyManager *manager) { disconnect(manager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotPropertyChanged(QtProperty *, int))); disconnect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), this, SLOT(slotRangeChanged(QtProperty *, int, int))); disconnect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), this, SLOT(slotSingleStepChanged(QtProperty *, int))); } // QtCheckBoxFactory class QtCheckBoxFactoryPrivate : public EditorFactoryPrivate { QtCheckBoxFactory *q_ptr; Q_DECLARE_PUBLIC(QtCheckBoxFactory) public: void slotPropertyChanged(QtProperty *property, bool value); void slotTextVisibleChanged(QtProperty *property, bool textVisible); void slotSetValue(bool value); }; void QtCheckBoxFactoryPrivate::slotPropertyChanged(QtProperty *property, bool value) { if (!m_createdEditors.contains(property)) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QtBoolEdit *editor = itEditor.next(); editor->blockCheckBoxSignals(true); editor->setChecked(value); editor->blockCheckBoxSignals(false); } } void QtCheckBoxFactoryPrivate::slotTextVisibleChanged(QtProperty *property, bool textVisible) { if (!m_createdEditors.contains(property)) return; QtBoolPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QtBoolEdit *editor = itEditor.next(); editor->setTextVisible(textVisible); } } void QtCheckBoxFactoryPrivate::slotSetValue(bool value) { QObject *object = q_ptr->sender(); const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtBoolPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtCheckBoxFactory \brief The QtCheckBoxFactory class provides QCheckBox widgets for properties created by QtBoolPropertyManager objects. \sa QtAbstractEditorFactory, QtBoolPropertyManager */ /*! Creates a factory with the given \a parent. */ QtCheckBoxFactory::QtCheckBoxFactory(QObject *parent) : QtAbstractEditorFactory(parent) { d_ptr = new QtCheckBoxFactoryPrivate(); d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtCheckBoxFactory::~QtCheckBoxFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); delete d_ptr; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtCheckBoxFactory::connectPropertyManager(QtBoolPropertyManager *manager) { connect(manager, SIGNAL(valueChanged(QtProperty *, bool)), this, SLOT(slotPropertyChanged(QtProperty *, bool))); connect(manager, SIGNAL(textVisibleChanged(QtProperty *, bool)), this, SLOT(slotTextVisibleChanged(QtProperty *, bool))); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtCheckBoxFactory::createEditor(QtBoolPropertyManager *manager, QtProperty *property, QWidget *parent) { QtBoolEdit *editor = d_ptr->createEditor(property, parent); editor->setChecked(manager->value(property)); editor->setTextVisible(manager->textVisible(property)); connect(editor, SIGNAL(toggled(bool)), this, SLOT(slotSetValue(bool))); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtCheckBoxFactory::disconnectPropertyManager(QtBoolPropertyManager *manager) { disconnect(manager, SIGNAL(valueChanged(QtProperty *, bool)), this, SLOT(slotPropertyChanged(QtProperty *, bool))); disconnect(manager, SIGNAL(textVisibleChanged(QtProperty *, bool)), this, SLOT(slotTextVisibleChanged(QtProperty *, bool))); } // QtDoubleSpinBoxFactory class DoubleSpinBoxAnyPrecision : public QDoubleSpinBox { Q_OBJECT public: explicit DoubleSpinBoxAnyPrecision(QWidget *parent = nullptr) : QDoubleSpinBox(parent) {} QString textFromValue(double val) const override { QString text = QDoubleSpinBox::textFromValue(val); // remove redundant trailing 0's in case of high precision if (decimals() > 3) return removeRedundantTrialingZeros(text); return text; } }; class QtDoubleSpinBoxFactoryPrivate : public EditorFactoryPrivate { QtDoubleSpinBoxFactory *q_ptr; Q_DECLARE_PUBLIC(QtDoubleSpinBoxFactory) public: void slotPropertyChanged(QtProperty *property, double value); void slotRangeChanged(QtProperty *property, double min, double max); void slotSingleStepChanged(QtProperty *property, double step); void slotDecimalsChanged(QtProperty *property, int prec); void slotReadOnlyChanged(QtProperty *property, bool readOnly); void slotSetValue(double value); }; void QtDoubleSpinBoxFactoryPrivate::slotPropertyChanged(QtProperty *property, double value) { const auto editors = m_createdEditors[property]; for (auto editor : editors) { if (editor->value() != value) { editor->blockSignals(true); editor->setValue(value); editor->blockSignals(false); } } } void QtDoubleSpinBoxFactoryPrivate::slotRangeChanged(QtProperty *property, double min, double max) { if (!m_createdEditors.contains(property)) return; QtDoublePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; const auto editors = m_createdEditors[property]; for (auto editor : editors) { editor->blockSignals(true); editor->setRange(min, max); editor->setValue(manager->value(property)); editor->blockSignals(false); } } void QtDoubleSpinBoxFactoryPrivate::slotSingleStepChanged(QtProperty *property, double step) { if (!m_createdEditors.contains(property)) return; QtDoublePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; const auto editors = m_createdEditors[property]; for (auto editor : editors) { editor->blockSignals(true); editor->setSingleStep(step); editor->blockSignals(false); } } void QtDoubleSpinBoxFactoryPrivate::slotReadOnlyChanged( QtProperty *property, bool readOnly) { if (!m_createdEditors.contains(property)) return; QtDoublePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; const auto editors = m_createdEditors[property]; for (auto editor : editors) { editor->blockSignals(true); editor->setReadOnly(readOnly); editor->blockSignals(false); } } void QtDoubleSpinBoxFactoryPrivate::slotDecimalsChanged(QtProperty *property, int prec) { if (!m_createdEditors.contains(property)) return; QtDoublePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; const auto editors = m_createdEditors[property]; for (auto editor : editors) { editor->blockSignals(true); editor->setDecimals(prec); editor->setValue(manager->value(property)); editor->blockSignals(false); } } void QtDoubleSpinBoxFactoryPrivate::slotSetValue(double value) { QObject *object = q_ptr->sender(); const auto itcend = m_editorToProperty.constEnd(); for (auto itEditor = m_editorToProperty.constBegin(); itEditor != itcend; ++itEditor) { if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtDoublePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } } /*! \class QtDoubleSpinBoxFactory \brief The QtDoubleSpinBoxFactory class provides QDoubleSpinBox widgets for properties created by QtDoublePropertyManager objects. \sa QtAbstractEditorFactory, QtDoublePropertyManager */ /*! Creates a factory with the given \a parent. */ QtDoubleSpinBoxFactory::QtDoubleSpinBoxFactory(QObject *parent) : QtAbstractEditorFactory(parent) { d_ptr = new QtDoubleSpinBoxFactoryPrivate(); d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtDoubleSpinBoxFactory::~QtDoubleSpinBoxFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); delete d_ptr; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtDoubleSpinBoxFactory::connectPropertyManager(QtDoublePropertyManager *manager) { connect(manager, SIGNAL(valueChanged(QtProperty *, double)), this, SLOT(slotPropertyChanged(QtProperty *, double))); connect(manager, SIGNAL(rangeChanged(QtProperty *, double, double)), this, SLOT(slotRangeChanged(QtProperty *, double, double))); connect(manager, SIGNAL(singleStepChanged(QtProperty *, double)), this, SLOT(slotSingleStepChanged(QtProperty *, double))); connect(manager, SIGNAL(decimalsChanged(QtProperty *, int)), this, SLOT(slotDecimalsChanged(QtProperty *, int))); connect(manager, SIGNAL(readOnlyChanged(QtProperty *, bool)), this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtDoubleSpinBoxFactory::createEditor(QtDoublePropertyManager *manager, QtProperty *property, QWidget *parent) { QDoubleSpinBox *editor = d_ptr->createEditor(property, parent); editor->setSingleStep(manager->singleStep(property)); editor->setDecimals(manager->decimals(property)); editor->setRange(manager->minimum(property), manager->maximum(property)); editor->setValue(manager->value(property)); editor->setKeyboardTracking(false); editor->setReadOnly(manager->isReadOnly(property)); connect(editor, SIGNAL(valueChanged(double)), this, SLOT(slotSetValue(double))); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtDoubleSpinBoxFactory::disconnectPropertyManager(QtDoublePropertyManager *manager) { disconnect(manager, SIGNAL(valueChanged(QtProperty *, double)), this, SLOT(slotPropertyChanged(QtProperty *, double))); disconnect(manager, SIGNAL(rangeChanged(QtProperty *, double, double)), this, SLOT(slotRangeChanged(QtProperty *, double, double))); disconnect(manager, SIGNAL(singleStepChanged(QtProperty *, double)), this, SLOT(slotSingleStepChanged(QtProperty *, double))); disconnect(manager, SIGNAL(decimalsChanged(QtProperty *, int)), this, SLOT(slotDecimalsChanged(QtProperty *, int))); disconnect(manager, SIGNAL(readOnlyChanged(QtProperty *, bool)), this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); } // QtLineEditFactory class QtLineEditFactoryPrivate : public EditorFactoryPrivate { QtLineEditFactory *q_ptr; Q_DECLARE_PUBLIC(QtLineEditFactory) public: void slotPropertyChanged(QtProperty *property, const QString &value); void slotRegExpChanged(QtProperty *property, const QRegExp ®Exp); void slotSetValue(const QString &value); void slotEchoModeChanged(QtProperty *, int); void slotReadOnlyChanged(QtProperty *, bool); }; void QtLineEditFactoryPrivate::slotPropertyChanged(QtProperty *property, const QString &value) { if (!m_createdEditors.contains(property)) return; QListIterator itEditor( m_createdEditors[property]); while (itEditor.hasNext()) { QLineEdit *editor = itEditor.next(); if (editor->text() != value) { editor->blockSignals(true); editor->setText(value); editor->blockSignals(false); } } } void QtLineEditFactoryPrivate::slotRegExpChanged(QtProperty *property, const QRegExp ®Exp) { if (!m_createdEditors.contains(property)) return; QtStringPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QLineEdit *editor = itEditor.next(); editor->blockSignals(true); const QValidator *oldValidator = editor->validator(); QValidator *newValidator = 0; if (regExp.isValid()) { newValidator = new QRegExpValidator(regExp, editor); } editor->setValidator(newValidator); if (oldValidator) delete oldValidator; editor->blockSignals(false); } } void QtLineEditFactoryPrivate::slotEchoModeChanged(QtProperty *property, int echoMode) { if (!m_createdEditors.contains(property)) return; QtStringPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QLineEdit *editor = itEditor.next(); editor->blockSignals(true); editor->setEchoMode((EchoMode)echoMode); editor->blockSignals(false); } } void QtLineEditFactoryPrivate::slotReadOnlyChanged( QtProperty *property, bool readOnly) { if (!m_createdEditors.contains(property)) return; QtStringPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QLineEdit *editor = itEditor.next(); editor->blockSignals(true); editor->setReadOnly(readOnly); editor->blockSignals(false); } } void QtLineEditFactoryPrivate::slotSetValue(const QString &value) { QObject *object = q_ptr->sender(); const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtStringPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtLineEditFactory \brief The QtLineEditFactory class provides QLineEdit widgets for properties created by QtStringPropertyManager objects. \sa QtAbstractEditorFactory, QtStringPropertyManager */ /*! Creates a factory with the given \a parent. */ QtLineEditFactory::QtLineEditFactory(QObject *parent) : QtAbstractEditorFactory(parent) { d_ptr = new QtLineEditFactoryPrivate(); d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtLineEditFactory::~QtLineEditFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); delete d_ptr; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtLineEditFactory::connectPropertyManager(QtStringPropertyManager *manager) { connect(manager, SIGNAL(valueChanged(QtProperty *, const QString &)), this, SLOT(slotPropertyChanged(QtProperty *, const QString &))); connect(manager, SIGNAL(regExpChanged(QtProperty *, const QRegExp &)), this, SLOT(slotRegExpChanged(QtProperty *, const QRegExp &))); connect(manager, SIGNAL(echoModeChanged(QtProperty*, int)), this, SLOT(slotEchoModeChanged(QtProperty *, int))); connect(manager, SIGNAL(readOnlyChanged(QtProperty*, bool)), this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtLineEditFactory::createEditor(QtStringPropertyManager *manager, QtProperty *property, QWidget *parent) { QLineEdit *editor = d_ptr->createEditor(property, parent); editor->setEchoMode((EchoMode)manager->echoMode(property)); editor->setReadOnly(manager->isReadOnly(property)); QRegExp regExp = manager->regExp(property); if (regExp.isValid()) { QValidator *validator = new QRegExpValidator(regExp, editor); editor->setValidator(validator); } editor->setText(manager->value(property)); connect(editor, SIGNAL(textChanged(const QString &)), this, SLOT(slotSetValue(const QString &))); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtLineEditFactory::disconnectPropertyManager(QtStringPropertyManager *manager) { disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QString &)), this, SLOT(slotPropertyChanged(QtProperty *, const QString &))); disconnect(manager, SIGNAL(regExpChanged(QtProperty *, const QRegExp &)), this, SLOT(slotRegExpChanged(QtProperty *, const QRegExp &))); disconnect(manager, SIGNAL(echoModeChanged(QtProperty*,int)), this, SLOT(slotEchoModeChanged(QtProperty *, int))); disconnect(manager, SIGNAL(readOnlyChanged(QtProperty*, bool)), this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); } // QtDateEditFactory class QtDateEditFactoryPrivate : public EditorFactoryPrivate { QtDateEditFactory *q_ptr; Q_DECLARE_PUBLIC(QtDateEditFactory) public: void slotPropertyChanged(QtProperty *property, const QDate &value); void slotRangeChanged(QtProperty *property, const QDate &min, const QDate &max); void slotSetValue(const QDate &value); }; void QtDateEditFactoryPrivate::slotPropertyChanged(QtProperty *property, const QDate &value) { if (!m_createdEditors.contains(property)) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QDateEdit *editor = itEditor.next(); editor->blockSignals(true); editor->setDate(value); editor->blockSignals(false); } } void QtDateEditFactoryPrivate::slotRangeChanged(QtProperty *property, const QDate &min, const QDate &max) { if (!m_createdEditors.contains(property)) return; QtDatePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QDateEdit *editor = itEditor.next(); editor->blockSignals(true); editor->setDateRange(min, max); editor->setDate(manager->value(property)); editor->blockSignals(false); } } void QtDateEditFactoryPrivate::slotSetValue(const QDate &value) { QObject *object = q_ptr->sender(); const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtDatePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtDateEditFactory \brief The QtDateEditFactory class provides QDateEdit widgets for properties created by QtDatePropertyManager objects. \sa QtAbstractEditorFactory, QtDatePropertyManager */ /*! Creates a factory with the given \a parent. */ QtDateEditFactory::QtDateEditFactory(QObject *parent) : QtAbstractEditorFactory(parent) { d_ptr = new QtDateEditFactoryPrivate(); d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtDateEditFactory::~QtDateEditFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); delete d_ptr; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtDateEditFactory::connectPropertyManager(QtDatePropertyManager *manager) { connect(manager, SIGNAL(valueChanged(QtProperty *, const QDate &)), this, SLOT(slotPropertyChanged(QtProperty *, const QDate &))); connect(manager, SIGNAL(rangeChanged(QtProperty *, const QDate &, const QDate &)), this, SLOT(slotRangeChanged(QtProperty *, const QDate &, const QDate &))); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtDateEditFactory::createEditor(QtDatePropertyManager *manager, QtProperty *property, QWidget *parent) { QDateEdit *editor = d_ptr->createEditor(property, parent); editor->setCalendarPopup(true); editor->setDateRange(manager->minimum(property), manager->maximum(property)); editor->setDate(manager->value(property)); connect(editor, SIGNAL(dateChanged(const QDate &)), this, SLOT(slotSetValue(const QDate &))); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtDateEditFactory::disconnectPropertyManager(QtDatePropertyManager *manager) { disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QDate &)), this, SLOT(slotPropertyChanged(QtProperty *, const QDate &))); disconnect(manager, SIGNAL(rangeChanged(QtProperty *, const QDate &, const QDate &)), this, SLOT(slotRangeChanged(QtProperty *, const QDate &, const QDate &))); } // QtTimeEditFactory class QtTimeEditFactoryPrivate : public EditorFactoryPrivate { QtTimeEditFactory *q_ptr; Q_DECLARE_PUBLIC(QtTimeEditFactory) public: void slotPropertyChanged(QtProperty *property, const QTime &value); void slotSetValue(const QTime &value); }; void QtTimeEditFactoryPrivate::slotPropertyChanged(QtProperty *property, const QTime &value) { if (!m_createdEditors.contains(property)) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QTimeEdit *editor = itEditor.next(); editor->blockSignals(true); editor->setTime(value); editor->blockSignals(false); } } void QtTimeEditFactoryPrivate::slotSetValue(const QTime &value) { QObject *object = q_ptr->sender(); const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtTimePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtTimeEditFactory \brief The QtTimeEditFactory class provides QTimeEdit widgets for properties created by QtTimePropertyManager objects. \sa QtAbstractEditorFactory, QtTimePropertyManager */ /*! Creates a factory with the given \a parent. */ QtTimeEditFactory::QtTimeEditFactory(QObject *parent) : QtAbstractEditorFactory(parent) { d_ptr = new QtTimeEditFactoryPrivate(); d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtTimeEditFactory::~QtTimeEditFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); delete d_ptr; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtTimeEditFactory::connectPropertyManager(QtTimePropertyManager *manager) { connect(manager, SIGNAL(valueChanged(QtProperty *, const QTime &)), this, SLOT(slotPropertyChanged(QtProperty *, const QTime &))); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtTimeEditFactory::createEditor(QtTimePropertyManager *manager, QtProperty *property, QWidget *parent) { QTimeEdit *editor = d_ptr->createEditor(property, parent); editor->setTime(manager->value(property)); connect(editor, SIGNAL(timeChanged(const QTime &)), this, SLOT(slotSetValue(const QTime &))); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtTimeEditFactory::disconnectPropertyManager(QtTimePropertyManager *manager) { disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QTime &)), this, SLOT(slotPropertyChanged(QtProperty *, const QTime &))); } // QtDateTimeEditFactory class QtDateTimeEditFactoryPrivate : public EditorFactoryPrivate { QtDateTimeEditFactory *q_ptr; Q_DECLARE_PUBLIC(QtDateTimeEditFactory) public: void slotPropertyChanged(QtProperty *property, const QDateTime &value); void slotSetValue(const QDateTime &value); }; void QtDateTimeEditFactoryPrivate::slotPropertyChanged(QtProperty *property, const QDateTime &value) { if (!m_createdEditors.contains(property)) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QDateTimeEdit *editor = itEditor.next(); editor->blockSignals(true); editor->setDateTime(value); editor->blockSignals(false); } } void QtDateTimeEditFactoryPrivate::slotSetValue(const QDateTime &value) { QObject *object = q_ptr->sender(); const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtDateTimePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtDateTimeEditFactory \brief The QtDateTimeEditFactory class provides QDateTimeEdit widgets for properties created by QtDateTimePropertyManager objects. \sa QtAbstractEditorFactory, QtDateTimePropertyManager */ /*! Creates a factory with the given \a parent. */ QtDateTimeEditFactory::QtDateTimeEditFactory(QObject *parent) : QtAbstractEditorFactory(parent) { d_ptr = new QtDateTimeEditFactoryPrivate(); d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtDateTimeEditFactory::~QtDateTimeEditFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); delete d_ptr; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtDateTimeEditFactory::connectPropertyManager(QtDateTimePropertyManager *manager) { connect(manager, SIGNAL(valueChanged(QtProperty *, const QDateTime &)), this, SLOT(slotPropertyChanged(QtProperty *, const QDateTime &))); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtDateTimeEditFactory::createEditor(QtDateTimePropertyManager *manager, QtProperty *property, QWidget *parent) { QDateTimeEdit *editor = d_ptr->createEditor(property, parent); editor->setDateTime(manager->value(property)); connect(editor, SIGNAL(dateTimeChanged(const QDateTime &)), this, SLOT(slotSetValue(const QDateTime &))); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtDateTimeEditFactory::disconnectPropertyManager(QtDateTimePropertyManager *manager) { disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QDateTime &)), this, SLOT(slotPropertyChanged(QtProperty *, const QDateTime &))); } // QtKeySequenceEditorFactory class QtKeySequenceEditorFactoryPrivate : public EditorFactoryPrivate { QtKeySequenceEditorFactory *q_ptr; Q_DECLARE_PUBLIC(QtKeySequenceEditorFactory) public: void slotPropertyChanged(QtProperty *property, const QKeySequence &value); void slotSetValue(const QKeySequence &value); }; void QtKeySequenceEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, const QKeySequence &value) { if (!m_createdEditors.contains(property)) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QtKeySequenceEdit *editor = itEditor.next(); editor->blockSignals(true); editor->setKeySequence(value); editor->blockSignals(false); } } void QtKeySequenceEditorFactoryPrivate::slotSetValue(const QKeySequence &value) { QObject *object = q_ptr->sender(); const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtKeySequencePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtKeySequenceEditorFactory \brief The QtKeySequenceEditorFactory class provides editor widgets for properties created by QtKeySequencePropertyManager objects. \sa QtAbstractEditorFactory */ /*! Creates a factory with the given \a parent. */ QtKeySequenceEditorFactory::QtKeySequenceEditorFactory(QObject *parent) : QtAbstractEditorFactory(parent) { d_ptr = new QtKeySequenceEditorFactoryPrivate(); d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtKeySequenceEditorFactory::~QtKeySequenceEditorFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); delete d_ptr; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtKeySequenceEditorFactory::connectPropertyManager(QtKeySequencePropertyManager *manager) { connect(manager, SIGNAL(valueChanged(QtProperty *, const QKeySequence &)), this, SLOT(slotPropertyChanged(QtProperty *, const QKeySequence &))); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtKeySequenceEditorFactory::createEditor(QtKeySequencePropertyManager *manager, QtProperty *property, QWidget *parent) { QtKeySequenceEdit *editor = d_ptr->createEditor(property, parent); editor->setKeySequence(manager->value(property)); connect(editor, SIGNAL(keySequenceChanged(const QKeySequence &)), this, SLOT(slotSetValue(const QKeySequence &))); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtKeySequenceEditorFactory::disconnectPropertyManager(QtKeySequencePropertyManager *manager) { disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QKeySequence &)), this, SLOT(slotPropertyChanged(QtProperty *, const QKeySequence &))); } // QtCharEdit class QtCharEdit : public QWidget { Q_OBJECT public: QtCharEdit(QWidget *parent = 0); QChar value() const; bool eventFilter(QObject *o, QEvent *e); public Q_SLOTS: void setValue(const QChar &value); Q_SIGNALS: void valueChanged(const QChar &value); protected: void focusInEvent(QFocusEvent *e); void focusOutEvent(QFocusEvent *e); void keyPressEvent(QKeyEvent *e); void keyReleaseEvent(QKeyEvent *e); void paintEvent(QPaintEvent *); bool event(QEvent *e); private slots: void slotClearChar(); private: void handleKeyEvent(QKeyEvent *e); QChar m_value; QLineEdit *m_lineEdit; }; QtCharEdit::QtCharEdit(QWidget *parent) : QWidget(parent), m_lineEdit(new QLineEdit(this)) { QHBoxLayout *layout = new QHBoxLayout(this); layout->addWidget(m_lineEdit); layout->setMargin(0); m_lineEdit->installEventFilter(this); m_lineEdit->setReadOnly(true); m_lineEdit->setFocusProxy(this); setFocusPolicy(m_lineEdit->focusPolicy()); setAttribute(Qt::WA_InputMethodEnabled); } bool QtCharEdit::eventFilter(QObject *o, QEvent *e) { if (o == m_lineEdit && e->type() == QEvent::ContextMenu) { QContextMenuEvent *c = static_cast(e); QMenu *menu = m_lineEdit->createStandardContextMenu(); QList actions = menu->actions(); QListIterator itAction(actions); while (itAction.hasNext()) { QAction *action = itAction.next(); action->setShortcut(QKeySequence()); QString actionString = action->text(); const int pos = actionString.lastIndexOf(QLatin1Char('\t')); if (pos > 0) actionString = actionString.remove(pos, actionString.length() - pos); action->setText(actionString); } QAction *actionBefore = 0; if (actions.count() > 0) actionBefore = actions[0]; QAction *clearAction = new QAction(tr("Clear Char"), menu); menu->insertAction(actionBefore, clearAction); menu->insertSeparator(actionBefore); clearAction->setEnabled(!m_value.isNull()); connect(clearAction, SIGNAL(triggered()), this, SLOT(slotClearChar())); menu->exec(c->globalPos()); delete menu; e->accept(); return true; } return QWidget::eventFilter(o, e); } void QtCharEdit::slotClearChar() { if (m_value.isNull()) return; setValue(QChar()); emit valueChanged(m_value); } void QtCharEdit::handleKeyEvent(QKeyEvent *e) { const int key = e->key(); switch (key) { case Qt::Key_Control: case Qt::Key_Shift: case Qt::Key_Meta: case Qt::Key_Alt: case Qt::Key_Super_L: case Qt::Key_Return: return; default: break; } const QString text = e->text(); if (text.count() != 1) return; const QChar c = text.at(0); if (!c.isPrint()) return; if (m_value == c) return; m_value = c; const QString str = m_value.isNull() ? QString() : QString(m_value); m_lineEdit->setText(str); e->accept(); emit valueChanged(m_value); } void QtCharEdit::setValue(const QChar &value) { if (value == m_value) return; m_value = value; QString str = value.isNull() ? QString() : QString(value); m_lineEdit->setText(str); } QChar QtCharEdit::value() const { return m_value; } void QtCharEdit::focusInEvent(QFocusEvent *e) { m_lineEdit->event(e); m_lineEdit->selectAll(); QWidget::focusInEvent(e); } void QtCharEdit::focusOutEvent(QFocusEvent *e) { m_lineEdit->event(e); QWidget::focusOutEvent(e); } void QtCharEdit::keyPressEvent(QKeyEvent *e) { handleKeyEvent(e); e->accept(); } void QtCharEdit::keyReleaseEvent(QKeyEvent *e) { m_lineEdit->event(e); } void QtCharEdit::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } bool QtCharEdit::event(QEvent *e) { switch(e->type()) { case QEvent::Shortcut: case QEvent::ShortcutOverride: case QEvent::KeyRelease: e->accept(); return true; default: break; } return QWidget::event(e); } // QtCharEditorFactory class QtCharEditorFactoryPrivate : public EditorFactoryPrivate { QtCharEditorFactory *q_ptr; Q_DECLARE_PUBLIC(QtCharEditorFactory) public: void slotPropertyChanged(QtProperty *property, const QChar &value); void slotSetValue(const QChar &value); }; void QtCharEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, const QChar &value) { if (!m_createdEditors.contains(property)) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QtCharEdit *editor = itEditor.next(); editor->blockSignals(true); editor->setValue(value); editor->blockSignals(false); } } void QtCharEditorFactoryPrivate::slotSetValue(const QChar &value) { QObject *object = q_ptr->sender(); const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtCharPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtCharEditorFactory \brief The QtCharEditorFactory class provides editor widgets for properties created by QtCharPropertyManager objects. \sa QtAbstractEditorFactory */ /*! Creates a factory with the given \a parent. */ QtCharEditorFactory::QtCharEditorFactory(QObject *parent) : QtAbstractEditorFactory(parent) { d_ptr = new QtCharEditorFactoryPrivate(); d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtCharEditorFactory::~QtCharEditorFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); delete d_ptr; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtCharEditorFactory::connectPropertyManager(QtCharPropertyManager *manager) { connect(manager, SIGNAL(valueChanged(QtProperty *, const QChar &)), this, SLOT(slotPropertyChanged(QtProperty *, const QChar &))); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtCharEditorFactory::createEditor(QtCharPropertyManager *manager, QtProperty *property, QWidget *parent) { QtCharEdit *editor = d_ptr->createEditor(property, parent); editor->setValue(manager->value(property)); connect(editor, SIGNAL(valueChanged(const QChar &)), this, SLOT(slotSetValue(const QChar &))); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtCharEditorFactory::disconnectPropertyManager(QtCharPropertyManager *manager) { disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QChar &)), this, SLOT(slotPropertyChanged(QtProperty *, const QChar &))); } // QtEnumEditorFactory class QtEnumEditorFactoryPrivate : public EditorFactoryPrivate { QtEnumEditorFactory *q_ptr; Q_DECLARE_PUBLIC(QtEnumEditorFactory) public: void slotPropertyChanged(QtProperty *property, int value); void slotEnumNamesChanged(QtProperty *property, const QStringList &); void slotEnumIconsChanged(QtProperty *property, const QMap &); void slotSetValue(int value); }; void QtEnumEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, int value) { if (!m_createdEditors.contains(property)) return; QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QComboBox *editor = itEditor.next(); editor->blockSignals(true); editor->setCurrentIndex(value); editor->blockSignals(false); } } void QtEnumEditorFactoryPrivate::slotEnumNamesChanged(QtProperty *property, const QStringList &enumNames) { if (!m_createdEditors.contains(property)) return; QtEnumPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; QMap enumIcons = manager->enumIcons(property); QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QComboBox *editor = itEditor.next(); editor->blockSignals(true); editor->clear(); editor->addItems(enumNames); const int nameCount = enumNames.count(); for (int i = 0; i < nameCount; i++) editor->setItemIcon(i, enumIcons.value(i)); editor->setCurrentIndex(manager->value(property)); editor->blockSignals(false); } } void QtEnumEditorFactoryPrivate::slotEnumIconsChanged(QtProperty *property, const QMap &enumIcons) { if (!m_createdEditors.contains(property)) return; QtEnumPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; const QStringList enumNames = manager->enumNames(property); QListIterator itEditor(m_createdEditors[property]); while (itEditor.hasNext()) { QComboBox *editor = itEditor.next(); editor->blockSignals(true); const int nameCount = enumNames.count(); for (int i = 0; i < nameCount; i++) editor->setItemIcon(i, enumIcons.value(i)); editor->setCurrentIndex(manager->value(property)); editor->blockSignals(false); } } void QtEnumEditorFactoryPrivate::slotSetValue(int value) { QObject *object = q_ptr->sender(); const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtEnumPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtEnumEditorFactory \brief The QtEnumEditorFactory class provides QComboBox widgets for properties created by QtEnumPropertyManager objects. \sa QtAbstractEditorFactory, QtEnumPropertyManager */ /*! Creates a factory with the given \a parent. */ QtEnumEditorFactory::QtEnumEditorFactory(QObject *parent) : QtAbstractEditorFactory(parent) { d_ptr = new QtEnumEditorFactoryPrivate(); d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtEnumEditorFactory::~QtEnumEditorFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); delete d_ptr; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtEnumEditorFactory::connectPropertyManager(QtEnumPropertyManager *manager) { connect(manager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotPropertyChanged(QtProperty *, int))); connect(manager, SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)), this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &))); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtEnumEditorFactory::createEditor(QtEnumPropertyManager *manager, QtProperty *property, QWidget *parent) { QComboBox *editor = d_ptr->createEditor(property, parent); editor->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); editor->setMinimumContentsLength(1); editor->view()->setTextElideMode(Qt::ElideRight); QStringList enumNames = manager->enumNames(property); editor->addItems(enumNames); QMap enumIcons = manager->enumIcons(property); const int enumNamesCount = enumNames.count(); for (int i = 0; i < enumNamesCount; i++) editor->setItemIcon(i, enumIcons.value(i)); editor->setCurrentIndex(manager->value(property)); connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int))); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtEnumEditorFactory::disconnectPropertyManager(QtEnumPropertyManager *manager) { disconnect(manager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotPropertyChanged(QtProperty *, int))); disconnect(manager, SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)), this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &))); } // QtCursorEditorFactory Q_GLOBAL_STATIC(QtCursorDatabase, cursorDatabase) class QtCursorEditorFactoryPrivate { QtCursorEditorFactory *q_ptr; Q_DECLARE_PUBLIC(QtCursorEditorFactory) public: QtCursorEditorFactoryPrivate(); void slotPropertyChanged(QtProperty *property, const QCursor &cursor); void slotEnumChanged(QtProperty *property, int value); void slotEditorDestroyed(QObject *object); QtEnumEditorFactory *m_enumEditorFactory; QtEnumPropertyManager *m_enumPropertyManager; QMap m_propertyToEnum; QMap m_enumToProperty; QMap > m_enumToEditors; QMap m_editorToEnum; bool m_updatingEnum; }; QtCursorEditorFactoryPrivate::QtCursorEditorFactoryPrivate() : m_updatingEnum(false) { } void QtCursorEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, const QCursor &cursor) { // update enum property QtProperty *enumProp = m_propertyToEnum.value(property); if (!enumProp) return; m_updatingEnum = true; m_enumPropertyManager->setValue(enumProp, cursorDatabase()->cursorToValue(cursor)); m_updatingEnum = false; } void QtCursorEditorFactoryPrivate::slotEnumChanged(QtProperty *property, int value) { if (m_updatingEnum) return; // update cursor property QtProperty *prop = m_enumToProperty.value(property); if (!prop) return; QtCursorPropertyManager *cursorManager = q_ptr->propertyManager(prop); if (!cursorManager) return; #ifndef QT_NO_CURSOR cursorManager->setValue(prop, QCursor(cursorDatabase()->valueToCursor(value))); #endif } void QtCursorEditorFactoryPrivate::slotEditorDestroyed(QObject *object) { // remove from m_editorToEnum map; // remove from m_enumToEditors map; // if m_enumToEditors doesn't contains more editors delete enum property; const QMap::ConstIterator ecend = m_editorToEnum.constEnd(); for (QMap::ConstIterator itEditor = m_editorToEnum.constBegin(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QWidget *editor = itEditor.key(); QtProperty *enumProp = itEditor.value(); m_editorToEnum.remove(editor); m_enumToEditors[enumProp].removeAll(editor); if (m_enumToEditors[enumProp].isEmpty()) { m_enumToEditors.remove(enumProp); QtProperty *property = m_enumToProperty.value(enumProp); m_enumToProperty.remove(enumProp); m_propertyToEnum.remove(property); delete enumProp; } return; } } /*! \class QtCursorEditorFactory \brief The QtCursorEditorFactory class provides QComboBox widgets for properties created by QtCursorPropertyManager objects. \sa QtAbstractEditorFactory, QtCursorPropertyManager */ /*! Creates a factory with the given \a parent. */ QtCursorEditorFactory::QtCursorEditorFactory(QObject *parent) : QtAbstractEditorFactory(parent) { d_ptr = new QtCursorEditorFactoryPrivate(); d_ptr->q_ptr = this; d_ptr->m_enumEditorFactory = new QtEnumEditorFactory(this); d_ptr->m_enumPropertyManager = new QtEnumPropertyManager(this); connect(d_ptr->m_enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotEnumChanged(QtProperty *, int))); d_ptr->m_enumEditorFactory->addPropertyManager(d_ptr->m_enumPropertyManager); } /*! Destroys this factory, and all the widgets it has created. */ QtCursorEditorFactory::~QtCursorEditorFactory() { delete d_ptr; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtCursorEditorFactory::connectPropertyManager(QtCursorPropertyManager *manager) { connect(manager, SIGNAL(valueChanged(QtProperty *, const QCursor &)), this, SLOT(slotPropertyChanged(QtProperty *, const QCursor &))); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtCursorEditorFactory::createEditor(QtCursorPropertyManager *manager, QtProperty *property, QWidget *parent) { QtProperty *enumProp = 0; if (d_ptr->m_propertyToEnum.contains(property)) { enumProp = d_ptr->m_propertyToEnum[property]; } else { enumProp = d_ptr->m_enumPropertyManager->addProperty(property->propertyName()); d_ptr->m_enumPropertyManager->setEnumNames(enumProp, cursorDatabase()->cursorShapeNames()); d_ptr->m_enumPropertyManager->setEnumIcons(enumProp, cursorDatabase()->cursorShapeIcons()); #ifndef QT_NO_CURSOR d_ptr->m_enumPropertyManager->setValue(enumProp, cursorDatabase()->cursorToValue(manager->value(property))); #endif d_ptr->m_propertyToEnum[property] = enumProp; d_ptr->m_enumToProperty[enumProp] = property; } QtAbstractEditorFactoryBase *af = d_ptr->m_enumEditorFactory; QWidget *editor = af->createEditor(enumProp, parent); d_ptr->m_enumToEditors[enumProp].append(editor); d_ptr->m_editorToEnum[editor] = enumProp; connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtCursorEditorFactory::disconnectPropertyManager(QtCursorPropertyManager *manager) { disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QCursor &)), this, SLOT(slotPropertyChanged(QtProperty *, const QCursor &))); } // QtColorEditWidget class QtColorEditWidget : public QWidget { Q_OBJECT public: QtColorEditWidget(QWidget *parent); bool eventFilter(QObject *obj, QEvent *ev); public Q_SLOTS: void setValue(const QColor &value); Q_SIGNALS: void valueChanged(const QColor &value); protected: void paintEvent(QPaintEvent *); private Q_SLOTS: void buttonClicked(); private: QColor m_color; QLabel *m_pixmapLabel; QLabel *m_label; QToolButton *m_button; }; QtColorEditWidget::QtColorEditWidget(QWidget *parent) : QWidget(parent), m_pixmapLabel(new QLabel), m_label(new QLabel), m_button(new QToolButton) { QHBoxLayout *lt = new QHBoxLayout(this); setupTreeViewEditorMargin(lt); lt->setSpacing(0); lt->addWidget(m_pixmapLabel); lt->addWidget(m_label); lt->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored); m_button->setFixedWidth(20); setFocusProxy(m_button); setFocusPolicy(m_button->focusPolicy()); m_button->setText(tr("...")); m_button->installEventFilter(this); connect(m_button, SIGNAL(clicked()), this, SLOT(buttonClicked())); lt->addWidget(m_button); m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::brushValuePixmap(QBrush(m_color))); m_pixmapLabel->setVisible(m_color.isValid()); m_label->setText(QtPropertyBrowserUtils::colorValueText(m_color)); } void QtColorEditWidget::setValue(const QColor &c) { if (m_color != c) { m_color = c; m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::brushValuePixmap(QBrush(c))); m_pixmapLabel->setVisible(c.isValid()); m_label->setText(QtPropertyBrowserUtils::colorValueText(c)); } } void QtColorEditWidget::buttonClicked() { QColor newColor = QColorDialog::getColor(m_color, this, QString(), QColorDialog::ShowAlphaChannel); if (newColor.isValid() && newColor != m_color) { setValue(newColor); emit valueChanged(m_color); } } bool QtColorEditWidget::eventFilter(QObject *obj, QEvent *ev) { if (obj == m_button) { switch (ev->type()) { case QEvent::KeyPress: case QEvent::KeyRelease: { // Prevent the QToolButton from handling Enter/Escape meant control the delegate switch (static_cast(ev)->key()) { case Qt::Key_Escape: case Qt::Key_Enter: case Qt::Key_Return: ev->ignore(); return true; default: break; } } break; default: break; } } return QWidget::eventFilter(obj, ev); } void QtColorEditWidget::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } // QtColorEditorFactoryPrivate class QtColorEditorFactoryPrivate : public EditorFactoryPrivate { QtColorEditorFactory *q_ptr; Q_DECLARE_PUBLIC(QtColorEditorFactory) public: void slotPropertyChanged(QtProperty *property, const QColor &value); void slotSetValue(const QColor &value); }; void QtColorEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, const QColor &value) { const PropertyToEditorListMap::iterator it = m_createdEditors.find(property); if (it == m_createdEditors.end()) return; QListIterator itEditor(it.value()); while (itEditor.hasNext()) itEditor.next()->setValue(value); } void QtColorEditorFactoryPrivate::slotSetValue(const QColor &value) { QObject *object = q_ptr->sender(); const EditorToPropertyMap::ConstIterator ecend = m_editorToProperty.constEnd(); for (EditorToPropertyMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtColorPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtColorEditorFactory \brief The QtColorEditorFactory class provides color editing for properties created by QtColorPropertyManager objects. \sa QtAbstractEditorFactory, QtColorPropertyManager */ /*! Creates a factory with the given \a parent. */ QtColorEditorFactory::QtColorEditorFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtColorEditorFactoryPrivate()) { d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtColorEditorFactory::~QtColorEditorFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); delete d_ptr; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtColorEditorFactory::connectPropertyManager(QtColorPropertyManager *manager) { connect(manager, SIGNAL(valueChanged(QtProperty*,QColor)), this, SLOT(slotPropertyChanged(QtProperty*,QColor))); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtColorEditorFactory::createEditor(QtColorPropertyManager *manager, QtProperty *property, QWidget *parent) { QtColorEditWidget *editor = d_ptr->createEditor(property, parent); editor->setValue(manager->value(property)); connect(editor, SIGNAL(valueChanged(QColor)), this, SLOT(slotSetValue(QColor))); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtColorEditorFactory::disconnectPropertyManager(QtColorPropertyManager *manager) { disconnect(manager, SIGNAL(valueChanged(QtProperty*,QColor)), this, SLOT(slotPropertyChanged(QtProperty*,QColor))); } // QtFontEditWidget class QtFontEditWidget : public QWidget { Q_OBJECT public: QtFontEditWidget(QWidget *parent); bool eventFilter(QObject *obj, QEvent *ev); public Q_SLOTS: void setValue(const QFont &value); Q_SIGNALS: void valueChanged(const QFont &value); protected: void paintEvent(QPaintEvent *); private Q_SLOTS: void buttonClicked(); private: QFont m_font; QLabel *m_pixmapLabel; QLabel *m_label; QToolButton *m_button; }; QtFontEditWidget::QtFontEditWidget(QWidget *parent) : QWidget(parent), m_pixmapLabel(new QLabel), m_label(new QLabel), m_button(new QToolButton) { QHBoxLayout *lt = new QHBoxLayout(this); setupTreeViewEditorMargin(lt); lt->setSpacing(0); lt->addWidget(m_pixmapLabel); lt->addWidget(m_label); lt->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored); m_button->setFixedWidth(20); setFocusProxy(m_button); setFocusPolicy(m_button->focusPolicy()); m_button->setText(tr("...")); m_button->installEventFilter(this); connect(m_button, SIGNAL(clicked()), this, SLOT(buttonClicked())); lt->addWidget(m_button); m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::fontValuePixmap(m_font)); m_label->setText(QtPropertyBrowserUtils::fontValueText(m_font)); } void QtFontEditWidget::setValue(const QFont &f) { if (m_font != f) { m_font = f; m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::fontValuePixmap(f)); m_label->setText(QtPropertyBrowserUtils::fontValueText(f)); } } void QtFontEditWidget::buttonClicked() { bool ok = false; QFont oldFont = m_font; // Font dialogs generally deal with point sizes. When the font size is set // in pixels, convert to points. if (m_font.pixelSize() != -1) oldFont.setPointSizeF(oldFont.pixelSize() / logicalDpiX() * 72.0); QFont newFont = QFontDialog::getFont(&ok, oldFont, this, tr("Select Font")); if (ok && newFont != oldFont) { QFont f = m_font; // Convert back to pixels when the current font size is set in pixels if (m_font.pixelSize() != -1 && newFont.pointSize() != -1) { int pixelSize = qRound(newFont.pointSizeF() / 72.0 * logicalDpiX()); newFont.setPixelSize(pixelSize); } // prevent mask for unchanged attributes, don't change other attributes (like kerning, etc...) if (m_font.family() != newFont.family()) f.setFamily(newFont.family()); if (m_font.pixelSize() != newFont.pixelSize() && newFont.pixelSize() != -1) f.setPixelSize(newFont.pixelSize()); if (m_font.pointSize() != newFont.pointSize() && newFont.pointSize() != -1) f.setPointSizeF(newFont.pointSizeF()); if (m_font.bold() != newFont.bold()) f.setBold(newFont.bold()); if (m_font.italic() != newFont.italic()) f.setItalic(newFont.italic()); if (m_font.underline() != newFont.underline()) f.setUnderline(newFont.underline()); if (m_font.strikeOut() != newFont.strikeOut()) f.setStrikeOut(newFont.strikeOut()); setValue(f); emit valueChanged(m_font); } } bool QtFontEditWidget::eventFilter(QObject *obj, QEvent *ev) { if (obj == m_button) { switch (ev->type()) { case QEvent::KeyPress: case QEvent::KeyRelease: { // Prevent the QToolButton from handling Enter/Escape meant control the delegate switch (static_cast(ev)->key()) { case Qt::Key_Escape: case Qt::Key_Enter: case Qt::Key_Return: ev->ignore(); return true; default: break; } } break; default: break; } } return QWidget::eventFilter(obj, ev); } void QtFontEditWidget::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } // QtFontEditorFactoryPrivate class QtFontEditorFactoryPrivate : public EditorFactoryPrivate { QtFontEditorFactory *q_ptr; Q_DECLARE_PUBLIC(QtFontEditorFactory) public: void slotPropertyChanged(QtProperty *property, const QFont &value); void slotSetValue(const QFont &value); }; void QtFontEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, const QFont &value) { const PropertyToEditorListMap::iterator it = m_createdEditors.find(property); if (it == m_createdEditors.end()) return; QListIterator itEditor(it.value()); while (itEditor.hasNext()) itEditor.next()->setValue(value); } void QtFontEditorFactoryPrivate::slotSetValue(const QFont &value) { QObject *object = q_ptr->sender(); const EditorToPropertyMap::ConstIterator ecend = m_editorToProperty.constEnd(); for (EditorToPropertyMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtFontPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtFontEditorFactory \brief The QtFontEditorFactory class provides font editing for properties created by QtFontPropertyManager objects. \sa QtAbstractEditorFactory, QtFontPropertyManager */ /*! Creates a factory with the given \a parent. */ QtFontEditorFactory::QtFontEditorFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtFontEditorFactoryPrivate()) { d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtFontEditorFactory::~QtFontEditorFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); delete d_ptr; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtFontEditorFactory::connectPropertyManager(QtFontPropertyManager *manager) { connect(manager, SIGNAL(valueChanged(QtProperty*,QFont)), this, SLOT(slotPropertyChanged(QtProperty*,QFont))); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtFontEditorFactory::createEditor(QtFontPropertyManager *manager, QtProperty *property, QWidget *parent) { QtFontEditWidget *editor = d_ptr->createEditor(property, parent); editor->setValue(manager->value(property)); connect(editor, SIGNAL(valueChanged(QFont)), this, SLOT(slotSetValue(QFont))); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtFontEditorFactory::disconnectPropertyManager(QtFontPropertyManager *manager) { disconnect(manager, SIGNAL(valueChanged(QtProperty*,QFont)), this, SLOT(slotPropertyChanged(QtProperty*,QFont))); } #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif #include "moc_qteditorfactory.cpp" #include "qteditorfactory.moc" tiled-1.0.3/src/qtpropertybrowser/src/qteditorfactory.h000066400000000000000000000400131315121121300234070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTEDITORFACTORY_H #define QTEDITORFACTORY_H #include "qtpropertymanager.h" #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif class QtSpinBoxFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtSpinBoxFactory : public QtAbstractEditorFactory { Q_OBJECT public: QtSpinBoxFactory(QObject *parent = 0); ~QtSpinBoxFactory(); protected: void connectPropertyManager(QtIntPropertyManager *manager); QWidget *createEditor(QtIntPropertyManager *manager, QtProperty *property, QWidget *parent); void disconnectPropertyManager(QtIntPropertyManager *manager); private: QtSpinBoxFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtSpinBoxFactory) Q_DISABLE_COPY(QtSpinBoxFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int)) Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotReadOnlyChanged(QtProperty *, bool)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(int)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) }; class QtSliderFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtSliderFactory : public QtAbstractEditorFactory { Q_OBJECT public: QtSliderFactory(QObject *parent = 0); ~QtSliderFactory(); protected: void connectPropertyManager(QtIntPropertyManager *manager); QWidget *createEditor(QtIntPropertyManager *manager, QtProperty *property, QWidget *parent); void disconnectPropertyManager(QtIntPropertyManager *manager); private: QtSliderFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtSliderFactory) Q_DISABLE_COPY(QtSliderFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int)) Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(int)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) }; class QtScrollBarFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtScrollBarFactory : public QtAbstractEditorFactory { Q_OBJECT public: QtScrollBarFactory(QObject *parent = 0); ~QtScrollBarFactory(); protected: void connectPropertyManager(QtIntPropertyManager *manager); QWidget *createEditor(QtIntPropertyManager *manager, QtProperty *property, QWidget *parent); void disconnectPropertyManager(QtIntPropertyManager *manager); private: QtScrollBarFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtScrollBarFactory) Q_DISABLE_COPY(QtScrollBarFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int)) Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(int)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) }; class QtCheckBoxFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtCheckBoxFactory : public QtAbstractEditorFactory { Q_OBJECT public: QtCheckBoxFactory(QObject *parent = 0); ~QtCheckBoxFactory(); protected: void connectPropertyManager(QtBoolPropertyManager *manager); QWidget *createEditor(QtBoolPropertyManager *manager, QtProperty *property, QWidget *parent); void disconnectPropertyManager(QtBoolPropertyManager *manager); private: QtCheckBoxFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtCheckBoxFactory) Q_DISABLE_COPY(QtCheckBoxFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, bool)) Q_PRIVATE_SLOT(d_func(), void slotTextVisibleChanged(QtProperty *, bool)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(bool)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) }; class QtDoubleSpinBoxFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtDoubleSpinBoxFactory : public QtAbstractEditorFactory { Q_OBJECT public: QtDoubleSpinBoxFactory(QObject *parent = 0); ~QtDoubleSpinBoxFactory(); protected: void connectPropertyManager(QtDoublePropertyManager *manager); QWidget *createEditor(QtDoublePropertyManager *manager, QtProperty *property, QWidget *parent); void disconnectPropertyManager(QtDoublePropertyManager *manager); private: QtDoubleSpinBoxFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtDoubleSpinBoxFactory) Q_DISABLE_COPY(QtDoubleSpinBoxFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, double)) Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, double, double)) Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, double)) Q_PRIVATE_SLOT(d_func(), void slotDecimalsChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotReadOnlyChanged(QtProperty *, bool)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(double)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) }; class QtLineEditFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtLineEditFactory : public QtAbstractEditorFactory { Q_OBJECT public: QtLineEditFactory(QObject *parent = 0); ~QtLineEditFactory(); protected: void connectPropertyManager(QtStringPropertyManager *manager); QWidget *createEditor(QtStringPropertyManager *manager, QtProperty *property, QWidget *parent); void disconnectPropertyManager(QtStringPropertyManager *manager); private: QtLineEditFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtLineEditFactory) Q_DISABLE_COPY(QtLineEditFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QString &)) Q_PRIVATE_SLOT(d_func(), void slotRegExpChanged(QtProperty *, const QRegExp &)) Q_PRIVATE_SLOT(d_func(), void slotEchoModeChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotReadOnlyChanged(QtProperty *, bool)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QString &)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) }; class QtDateEditFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtDateEditFactory : public QtAbstractEditorFactory { Q_OBJECT public: QtDateEditFactory(QObject *parent = 0); ~QtDateEditFactory(); protected: void connectPropertyManager(QtDatePropertyManager *manager); QWidget *createEditor(QtDatePropertyManager *manager, QtProperty *property, QWidget *parent); void disconnectPropertyManager(QtDatePropertyManager *manager); private: QtDateEditFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtDateEditFactory) Q_DISABLE_COPY(QtDateEditFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QDate &)) Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, const QDate &, const QDate &)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QDate &)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) }; class QtTimeEditFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtTimeEditFactory : public QtAbstractEditorFactory { Q_OBJECT public: QtTimeEditFactory(QObject *parent = 0); ~QtTimeEditFactory(); protected: void connectPropertyManager(QtTimePropertyManager *manager); QWidget *createEditor(QtTimePropertyManager *manager, QtProperty *property, QWidget *parent); void disconnectPropertyManager(QtTimePropertyManager *manager); private: QtTimeEditFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtTimeEditFactory) Q_DISABLE_COPY(QtTimeEditFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QTime &)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QTime &)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) }; class QtDateTimeEditFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtDateTimeEditFactory : public QtAbstractEditorFactory { Q_OBJECT public: QtDateTimeEditFactory(QObject *parent = 0); ~QtDateTimeEditFactory(); protected: void connectPropertyManager(QtDateTimePropertyManager *manager); QWidget *createEditor(QtDateTimePropertyManager *manager, QtProperty *property, QWidget *parent); void disconnectPropertyManager(QtDateTimePropertyManager *manager); private: QtDateTimeEditFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtDateTimeEditFactory) Q_DISABLE_COPY(QtDateTimeEditFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QDateTime &)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QDateTime &)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) }; class QtKeySequenceEditorFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtKeySequenceEditorFactory : public QtAbstractEditorFactory { Q_OBJECT public: QtKeySequenceEditorFactory(QObject *parent = 0); ~QtKeySequenceEditorFactory(); protected: void connectPropertyManager(QtKeySequencePropertyManager *manager); QWidget *createEditor(QtKeySequencePropertyManager *manager, QtProperty *property, QWidget *parent); void disconnectPropertyManager(QtKeySequencePropertyManager *manager); private: QtKeySequenceEditorFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtKeySequenceEditorFactory) Q_DISABLE_COPY(QtKeySequenceEditorFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QKeySequence &)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QKeySequence &)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) }; class QtCharEditorFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtCharEditorFactory : public QtAbstractEditorFactory { Q_OBJECT public: QtCharEditorFactory(QObject *parent = 0); ~QtCharEditorFactory(); protected: void connectPropertyManager(QtCharPropertyManager *manager); QWidget *createEditor(QtCharPropertyManager *manager, QtProperty *property, QWidget *parent); void disconnectPropertyManager(QtCharPropertyManager *manager); private: QtCharEditorFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtCharEditorFactory) Q_DISABLE_COPY(QtCharEditorFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QChar &)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QChar &)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) }; class QtEnumEditorFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtEnumEditorFactory : public QtAbstractEditorFactory { Q_OBJECT public: QtEnumEditorFactory(QObject *parent = 0); ~QtEnumEditorFactory(); protected: void connectPropertyManager(QtEnumPropertyManager *manager); QWidget *createEditor(QtEnumPropertyManager *manager, QtProperty *property, QWidget *parent); void disconnectPropertyManager(QtEnumPropertyManager *manager); private: QtEnumEditorFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtEnumEditorFactory) Q_DISABLE_COPY(QtEnumEditorFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotEnumNamesChanged(QtProperty *, const QStringList &)) Q_PRIVATE_SLOT(d_func(), void slotEnumIconsChanged(QtProperty *, const QMap &)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(int)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) }; class QtCursorEditorFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtCursorEditorFactory : public QtAbstractEditorFactory { Q_OBJECT public: QtCursorEditorFactory(QObject *parent = 0); ~QtCursorEditorFactory(); protected: void connectPropertyManager(QtCursorPropertyManager *manager); QWidget *createEditor(QtCursorPropertyManager *manager, QtProperty *property, QWidget *parent); void disconnectPropertyManager(QtCursorPropertyManager *manager); private: QtCursorEditorFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtCursorEditorFactory) Q_DISABLE_COPY(QtCursorEditorFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QCursor &)) Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) }; class QtColorEditorFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtColorEditorFactory : public QtAbstractEditorFactory { Q_OBJECT public: QtColorEditorFactory(QObject *parent = 0); ~QtColorEditorFactory(); protected: void connectPropertyManager(QtColorPropertyManager *manager); QWidget *createEditor(QtColorPropertyManager *manager, QtProperty *property, QWidget *parent); void disconnectPropertyManager(QtColorPropertyManager *manager); private: QtColorEditorFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtColorEditorFactory) Q_DISABLE_COPY(QtColorEditorFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QColor &)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QColor &)) }; class QtFontEditorFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtFontEditorFactory : public QtAbstractEditorFactory { Q_OBJECT public: QtFontEditorFactory(QObject *parent = 0); ~QtFontEditorFactory(); protected: void connectPropertyManager(QtFontPropertyManager *manager); QWidget *createEditor(QtFontPropertyManager *manager, QtProperty *property, QWidget *parent); void disconnectPropertyManager(QtFontPropertyManager *manager); private: QtFontEditorFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtFontEditorFactory) Q_DISABLE_COPY(QtFontEditorFactory) Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QFont &)) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QFont &)) }; #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif #endif tiled-1.0.3/src/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp000066400000000000000000000423631315121121300261540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtgroupboxpropertybrowser.h" #include #include #include #include #include #include #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif class QtGroupBoxPropertyBrowserPrivate { QtGroupBoxPropertyBrowser *q_ptr; Q_DECLARE_PUBLIC(QtGroupBoxPropertyBrowser) public: void init(QWidget *parent); void propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex); void propertyRemoved(QtBrowserItem *index); void propertyChanged(QtBrowserItem *index); QWidget *createEditor(QtProperty *property, QWidget *parent) const { return q_ptr->createEditor(property, parent); } void slotEditorDestroyed(); void slotUpdate(); struct WidgetItem { WidgetItem() : widget(0), label(0), widgetLabel(0), groupBox(0), layout(0), line(0), parent(0) { } QWidget *widget; // can be null QLabel *label; QLabel *widgetLabel; QGroupBox *groupBox; QGridLayout *layout; QFrame *line; WidgetItem *parent; QList children; }; private: void updateLater(); void updateItem(WidgetItem *item); void insertRow(QGridLayout *layout, int row) const; void removeRow(QGridLayout *layout, int row) const; bool hasHeader(WidgetItem *item) const; QMap m_indexToItem; QMap m_itemToIndex; QMap m_widgetToItem; QGridLayout *m_mainLayout; QList m_children; QList m_recreateQueue; }; void QtGroupBoxPropertyBrowserPrivate::init(QWidget *parent) { m_mainLayout = new QGridLayout(); parent->setLayout(m_mainLayout); QLayoutItem *item = new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding); m_mainLayout->addItem(item, 0, 0); } void QtGroupBoxPropertyBrowserPrivate::slotEditorDestroyed() { QWidget *editor = qobject_cast(q_ptr->sender()); if (!editor) return; if (!m_widgetToItem.contains(editor)) return; m_widgetToItem[editor]->widget = 0; m_widgetToItem.remove(editor); } void QtGroupBoxPropertyBrowserPrivate::slotUpdate() { QListIterator itItem(m_recreateQueue); while (itItem.hasNext()) { WidgetItem *item = itItem.next(); WidgetItem *par = item->parent; QWidget *w = 0; QGridLayout *l = 0; int oldRow = -1; if (!par) { w = q_ptr; l = m_mainLayout; oldRow = m_children.indexOf(item); } else { w = par->groupBox; l = par->layout; oldRow = par->children.indexOf(item); if (hasHeader(par)) oldRow += 2; } if (item->widget) { item->widget->setParent(w); } else if (item->widgetLabel) { item->widgetLabel->setParent(w); } else { item->widgetLabel = new QLabel(w); item->widgetLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); item->widgetLabel->setTextFormat(Qt::PlainText); } int span = 1; if (item->widget) l->addWidget(item->widget, oldRow, 1, 1, 1); else if (item->widgetLabel) l->addWidget(item->widgetLabel, oldRow, 1, 1, 1); else span = 2; item->label = new QLabel(w); item->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); l->addWidget(item->label, oldRow, 0, 1, span); updateItem(item); } m_recreateQueue.clear(); } void QtGroupBoxPropertyBrowserPrivate::updateLater() { QTimer::singleShot(0, q_ptr, SLOT(slotUpdate())); } void QtGroupBoxPropertyBrowserPrivate::propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex) { WidgetItem *afterItem = m_indexToItem.value(afterIndex); WidgetItem *parentItem = m_indexToItem.value(index->parent()); WidgetItem *newItem = new WidgetItem(); newItem->parent = parentItem; QGridLayout *layout = 0; QWidget *parentWidget = 0; int row = -1; if (!afterItem) { row = 0; if (parentItem) parentItem->children.insert(0, newItem); else m_children.insert(0, newItem); } else { if (parentItem) { row = parentItem->children.indexOf(afterItem) + 1; parentItem->children.insert(row, newItem); } else { row = m_children.indexOf(afterItem) + 1; m_children.insert(row, newItem); } } if (parentItem && hasHeader(parentItem)) row += 2; if (!parentItem) { layout = m_mainLayout; parentWidget = q_ptr;; } else { if (!parentItem->groupBox) { m_recreateQueue.removeAll(parentItem); WidgetItem *par = parentItem->parent; QWidget *w = 0; QGridLayout *l = 0; int oldRow = -1; if (!par) { w = q_ptr; l = m_mainLayout; oldRow = m_children.indexOf(parentItem); } else { w = par->groupBox; l = par->layout; oldRow = par->children.indexOf(parentItem); if (hasHeader(par)) oldRow += 2; } parentItem->groupBox = new QGroupBox(w); parentItem->layout = new QGridLayout(); parentItem->groupBox->setLayout(parentItem->layout); if (parentItem->label) { l->removeWidget(parentItem->label); delete parentItem->label; parentItem->label = 0; } if (parentItem->widget) { l->removeWidget(parentItem->widget); parentItem->widget->setParent(parentItem->groupBox); parentItem->layout->addWidget(parentItem->widget, 0, 0, 1, 2); parentItem->line = new QFrame(parentItem->groupBox); } else if (parentItem->widgetLabel) { l->removeWidget(parentItem->widgetLabel); delete parentItem->widgetLabel; parentItem->widgetLabel = 0; } if (parentItem->line) { parentItem->line->setFrameShape(QFrame::HLine); parentItem->line->setFrameShadow(QFrame::Sunken); parentItem->layout->addWidget(parentItem->line, 1, 0, 1, 2); } l->addWidget(parentItem->groupBox, oldRow, 0, 1, 2); updateItem(parentItem); } layout = parentItem->layout; parentWidget = parentItem->groupBox; } newItem->label = new QLabel(parentWidget); newItem->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); newItem->widget = createEditor(index->property(), parentWidget); if (!newItem->widget) { newItem->widgetLabel = new QLabel(parentWidget); newItem->widgetLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); newItem->widgetLabel->setTextFormat(Qt::PlainText); } else { QObject::connect(newItem->widget, SIGNAL(destroyed()), q_ptr, SLOT(slotEditorDestroyed())); m_widgetToItem[newItem->widget] = newItem; } insertRow(layout, row); int span = 1; if (newItem->widget) layout->addWidget(newItem->widget, row, 1); else if (newItem->widgetLabel) layout->addWidget(newItem->widgetLabel, row, 1); else span = 2; layout->addWidget(newItem->label, row, 0, 1, span); m_itemToIndex[newItem] = index; m_indexToItem[index] = newItem; updateItem(newItem); } void QtGroupBoxPropertyBrowserPrivate::propertyRemoved(QtBrowserItem *index) { WidgetItem *item = m_indexToItem.value(index); m_indexToItem.remove(index); m_itemToIndex.remove(item); WidgetItem *parentItem = item->parent; int row = -1; if (parentItem) { row = parentItem->children.indexOf(item); parentItem->children.removeAt(row); if (hasHeader(parentItem)) row += 2; } else { row = m_children.indexOf(item); m_children.removeAt(row); } if (item->widget) delete item->widget; if (item->label) delete item->label; if (item->widgetLabel) delete item->widgetLabel; if (item->groupBox) delete item->groupBox; if (!parentItem) { removeRow(m_mainLayout, row); } else if (parentItem->children.count() != 0) { removeRow(parentItem->layout, row); } else { WidgetItem *par = parentItem->parent; QGridLayout *l = 0; int oldRow = -1; if (!par) { l = m_mainLayout; oldRow = m_children.indexOf(parentItem); } else { l = par->layout; oldRow = par->children.indexOf(parentItem); if (hasHeader(par)) oldRow += 2; } if (parentItem->widget) { parentItem->widget->hide(); parentItem->widget->setParent(0); } else if (parentItem->widgetLabel) { parentItem->widgetLabel->hide(); parentItem->widgetLabel->setParent(0); } else { //parentItem->widgetLabel = new QLabel(w); } l->removeWidget(parentItem->groupBox); delete parentItem->groupBox; parentItem->groupBox = 0; parentItem->line = 0; parentItem->layout = 0; if (!m_recreateQueue.contains(parentItem)) m_recreateQueue.append(parentItem); updateLater(); } m_recreateQueue.removeAll(item); delete item; } void QtGroupBoxPropertyBrowserPrivate::insertRow(QGridLayout *layout, int row) const { QMap itemToPos; int idx = 0; while (idx < layout->count()) { int r, c, rs, cs; layout->getItemPosition(idx, &r, &c, &rs, &cs); if (r >= row) { itemToPos[layout->takeAt(idx)] = QRect(r + 1, c, rs, cs); } else { idx++; } } const QMap::ConstIterator icend = itemToPos.constEnd(); for (QMap::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) { const QRect r = it.value(); layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height()); } } void QtGroupBoxPropertyBrowserPrivate::removeRow(QGridLayout *layout, int row) const { QMap itemToPos; int idx = 0; while (idx < layout->count()) { int r, c, rs, cs; layout->getItemPosition(idx, &r, &c, &rs, &cs); if (r > row) { itemToPos[layout->takeAt(idx)] = QRect(r - 1, c, rs, cs); } else { idx++; } } const QMap::ConstIterator icend = itemToPos.constEnd(); for (QMap::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) { const QRect r = it.value(); layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height()); } } bool QtGroupBoxPropertyBrowserPrivate::hasHeader(WidgetItem *item) const { if (item->widget) return true; return false; } void QtGroupBoxPropertyBrowserPrivate::propertyChanged(QtBrowserItem *index) { WidgetItem *item = m_indexToItem.value(index); updateItem(item); } void QtGroupBoxPropertyBrowserPrivate::updateItem(WidgetItem *item) { QtProperty *property = m_itemToIndex[item]->property(); if (item->groupBox) { QFont font = item->groupBox->font(); font.setUnderline(property->isModified()); item->groupBox->setFont(font); item->groupBox->setTitle(property->propertyName()); item->groupBox->setToolTip(property->toolTip()); item->groupBox->setStatusTip(property->statusTip()); item->groupBox->setWhatsThis(property->whatsThis()); item->groupBox->setEnabled(property->isEnabled()); } if (item->label) { QFont font = item->label->font(); font.setUnderline(property->isModified()); item->label->setFont(font); item->label->setText(property->propertyName()); item->label->setToolTip(property->toolTip()); item->label->setStatusTip(property->statusTip()); item->label->setWhatsThis(property->whatsThis()); item->label->setEnabled(property->isEnabled()); } if (item->widgetLabel) { QFont font = item->widgetLabel->font(); font.setUnderline(false); item->widgetLabel->setFont(font); item->widgetLabel->setText(property->valueText()); item->widgetLabel->setToolTip(property->valueText()); item->widgetLabel->setEnabled(property->isEnabled()); } if (item->widget) { QFont font = item->widget->font(); font.setUnderline(false); item->widget->setFont(font); item->widget->setEnabled(property->isEnabled()); item->widget->setToolTip(property->valueText()); } //item->setIcon(1, property->valueIcon()); } /*! \class QtGroupBoxPropertyBrowser \brief The QtGroupBoxPropertyBrowser class provides a QGroupBox based property browser. A property browser is a widget that enables the user to edit a given set of properties. Each property is represented by a label specifying the property's name, and an editing widget (e.g. a line edit or a combobox) holding its value. A property can have zero or more subproperties. QtGroupBoxPropertyBrowser provides group boxes for all nested properties, i.e. subproperties are enclosed by a group box with the parent property's name as its title. For example: \image qtgroupboxpropertybrowser.png Use the QtAbstractPropertyBrowser API to add, insert and remove properties from an instance of the QtGroupBoxPropertyBrowser class. The properties themselves are created and managed by implementations of the QtAbstractPropertyManager class. \sa QtTreePropertyBrowser, QtAbstractPropertyBrowser */ /*! Creates a property browser with the given \a parent. */ QtGroupBoxPropertyBrowser::QtGroupBoxPropertyBrowser(QWidget *parent) : QtAbstractPropertyBrowser(parent) { d_ptr = new QtGroupBoxPropertyBrowserPrivate; d_ptr->q_ptr = this; d_ptr->init(this); } /*! Destroys this property browser. Note that the properties that were inserted into this browser are \e not destroyed since they may still be used in other browsers. The properties are owned by the manager that created them. \sa QtProperty, QtAbstractPropertyManager */ QtGroupBoxPropertyBrowser::~QtGroupBoxPropertyBrowser() { const QMap::ConstIterator icend = d_ptr->m_itemToIndex.constEnd(); for (QMap::ConstIterator it = d_ptr->m_itemToIndex.constBegin(); it != icend; ++it) delete it.key(); delete d_ptr; } /*! \reimp */ void QtGroupBoxPropertyBrowser::itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem) { d_ptr->propertyInserted(item, afterItem); } /*! \reimp */ void QtGroupBoxPropertyBrowser::itemRemoved(QtBrowserItem *item) { d_ptr->propertyRemoved(item); } /*! \reimp */ void QtGroupBoxPropertyBrowser::itemChanged(QtBrowserItem *item) { d_ptr->propertyChanged(item); } #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif #include "moc_qtgroupboxpropertybrowser.cpp" tiled-1.0.3/src/qtpropertybrowser/src/qtgroupboxpropertybrowser.h000066400000000000000000000055351315121121300256210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTGROUPBOXPROPERTYBROWSER_H #define QTGROUPBOXPROPERTYBROWSER_H #include "qtpropertybrowser.h" #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif class QtGroupBoxPropertyBrowserPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtGroupBoxPropertyBrowser : public QtAbstractPropertyBrowser { Q_OBJECT public: QtGroupBoxPropertyBrowser(QWidget *parent = 0); ~QtGroupBoxPropertyBrowser(); protected: virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem); virtual void itemRemoved(QtBrowserItem *item); virtual void itemChanged(QtBrowserItem *item); private: QtGroupBoxPropertyBrowserPrivate *d_ptr; Q_DECLARE_PRIVATE(QtGroupBoxPropertyBrowser) Q_DISABLE_COPY(QtGroupBoxPropertyBrowser) Q_PRIVATE_SLOT(d_func(), void slotUpdate()) Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed()) }; #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif #endif tiled-1.0.3/src/qtpropertybrowser/src/qtpropertybrowser.cpp000066400000000000000000001776471315121121300244040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtpropertybrowser.h" #include #include #include #include #if defined(Q_CC_MSVC) # pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */ #endif #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif class QtPropertyPrivate { public: QtPropertyPrivate(QtAbstractPropertyManager *manager) : m_enabled(true), m_modified(false), m_manager(manager) {} QtProperty *q_ptr; QSet m_parentItems; QList m_subItems; QString m_toolTip; QString m_statusTip; QString m_whatsThis; QString m_name; QColor m_nameColor; QColor m_valueColor; bool m_enabled; bool m_modified; QtAbstractPropertyManager * const m_manager; }; class QtAbstractPropertyManagerPrivate { QtAbstractPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtAbstractPropertyManager) public: void propertyDestroyed(QtProperty *property); void propertyChanged(QtProperty *property) const; void propertyRemoved(QtProperty *property, QtProperty *parentProperty) const; void propertyInserted(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty) const; QSet m_properties; }; /*! \class QtProperty \brief The QtProperty class encapsulates an instance of a property. Properties are created by objects of QtAbstractPropertyManager subclasses; a manager can create properties of a given type, and is used in conjunction with the QtAbstractPropertyBrowser class. A property is always owned by the manager that created it, which can be retrieved using the propertyManager() function. QtProperty contains the most common property attributes, and provides functions for retrieving as well as setting their values: \table \header \o Getter \o Setter \row \o propertyName() \o setPropertyName() \row \o statusTip() \o setStatusTip() \row \o toolTip() \o setToolTip() \row \o whatsThis() \o setWhatsThis() \row \o isEnabled() \o setEnabled() \row \o isModified() \o setModified() \row \o valueText() \o Nop \row \o valueIcon() \o Nop \endtable It is also possible to nest properties: QtProperty provides the addSubProperty(), insertSubProperty() and removeSubProperty() functions to manipulate the set of subproperties. Use the subProperties() function to retrieve a property's current set of subproperties. Note that nested properties are not owned by the parent property, i.e. each subproperty is owned by the manager that created it. \sa QtAbstractPropertyManager, QtBrowserItem */ /*! Creates a property with the given \a manager. This constructor is only useful when creating a custom QtProperty subclass (e.g. QtVariantProperty). To create a regular QtProperty object, use the QtAbstractPropertyManager::addProperty() function instead. \sa QtAbstractPropertyManager::addProperty() */ QtProperty::QtProperty(QtAbstractPropertyManager *manager) { d_ptr = new QtPropertyPrivate(manager); d_ptr->q_ptr = this; } /*! Destroys this property. Note that subproperties are detached but not destroyed, i.e. they can still be used in another context. \sa QtAbstractPropertyManager::clear() */ QtProperty::~QtProperty() { QSetIterator itParent(d_ptr->m_parentItems); while (itParent.hasNext()) { QtProperty *property = itParent.next(); property->d_ptr->m_manager->d_ptr->propertyRemoved(this, property); } d_ptr->m_manager->d_ptr->propertyDestroyed(this); QListIterator itChild(d_ptr->m_subItems); while (itChild.hasNext()) { QtProperty *property = itChild.next(); property->d_ptr->m_parentItems.remove(this); } itParent.toFront(); while (itParent.hasNext()) { QtProperty *property = itParent.next(); property->d_ptr->m_subItems.removeAll(this); } delete d_ptr; } /*! Returns the set of subproperties. Note that subproperties are not owned by \e this property, but by the manager that created them. \sa insertSubProperty(), removeSubProperty() */ QList QtProperty::subProperties() const { return d_ptr->m_subItems; } /*! Returns a pointer to the manager that owns this property. */ QtAbstractPropertyManager *QtProperty::propertyManager() const { return d_ptr->m_manager; } /*! Returns the property's tool tip. \sa setToolTip() */ QString QtProperty::toolTip() const { return d_ptr->m_toolTip; } /*! Returns the property's status tip. \sa setStatusTip() */ QString QtProperty::statusTip() const { return d_ptr->m_statusTip; } /*! Returns the property's "What's This" help text. \sa setWhatsThis() */ QString QtProperty::whatsThis() const { return d_ptr->m_whatsThis; } /*! Returns the property's name. \sa setPropertyName() */ QString QtProperty::propertyName() const { return d_ptr->m_name; } /*! Returns the property's name color. \sa setNameColor() */ QColor QtProperty::nameColor() const { return d_ptr->m_nameColor; } /*! Returns the property's value color. \sa setValueColor() */ QColor QtProperty::valueColor() const { return d_ptr->m_valueColor; } /*! Returns whether the property is enabled. \sa setEnabled() */ bool QtProperty::isEnabled() const { return d_ptr->m_enabled; } /*! Returns whether the property is modified. \sa setModified() */ bool QtProperty::isModified() const { return d_ptr->m_modified; } /*! Returns whether the property has a value. \sa QtAbstractPropertyManager::hasValue() */ bool QtProperty::hasValue() const { return d_ptr->m_manager->hasValue(this); } /*! Returns an icon representing the current state of this property. If the given property type can not generate such an icon, this function returns an invalid icon. \sa QtAbstractPropertyManager::valueIcon() */ QIcon QtProperty::valueIcon() const { return d_ptr->m_manager->valueIcon(this); } /*! Returns a string representing the current state of this property. If the given property type can not generate such a string, this function returns an empty string. \sa QtAbstractPropertyManager::valueText() */ QString QtProperty::valueText() const { return d_ptr->m_manager->valueText(this); } /*! Returns the display text according to the echo-mode set on the editor. When the editor is a QLineEdit, this will return a string equal to what is displayed. \sa QtAbstractPropertyManager::valueText() */ QString QtProperty::displayText() const { return d_ptr->m_manager->displayText(this); } /*! Sets the property's tool tip to the given \a text. \sa toolTip() */ void QtProperty::setToolTip(const QString &text) { if (d_ptr->m_toolTip == text) return; d_ptr->m_toolTip = text; propertyChanged(); } /*! Sets the property's status tip to the given \a text. \sa statusTip() */ void QtProperty::setStatusTip(const QString &text) { if (d_ptr->m_statusTip == text) return; d_ptr->m_statusTip = text; propertyChanged(); } /*! Sets the property's "What's This" help text to the given \a text. \sa whatsThis() */ void QtProperty::setWhatsThis(const QString &text) { if (d_ptr->m_whatsThis == text) return; d_ptr->m_whatsThis = text; propertyChanged(); } /*! \fn void QtProperty::setPropertyName(const QString &name) Sets the property's name to the given \a name. \sa propertyName() */ void QtProperty::setPropertyName(const QString &text) { if (d_ptr->m_name == text) return; d_ptr->m_name = text; propertyChanged(); } /*! \fn void QtProperty::setNameColor(const QColor &color) Sets the property's name color to the given \a color. \sa nameColor() */ void QtProperty::setNameColor(const QColor &color) { if (d_ptr->m_nameColor == color) return; d_ptr->m_nameColor = color; propertyChanged(); } /*! \fn void QtProperty::setValueColor(const QColor &color) Sets the property's value color to the given \a color. \sa valueColor() */ void QtProperty::setValueColor(const QColor &color) { if (d_ptr->m_valueColor == color) return; d_ptr->m_valueColor = color; propertyChanged(); } /*! Enables or disables the property according to the passed \a enable value. \sa isEnabled() */ void QtProperty::setEnabled(bool enable) { if (d_ptr->m_enabled == enable) return; d_ptr->m_enabled = enable; propertyChanged(); } /*! Sets the property's modified state according to the passed \a modified value. \sa isModified() */ void QtProperty::setModified(bool modified) { if (d_ptr->m_modified == modified) return; d_ptr->m_modified = modified; propertyChanged(); } /*! Appends the given \a property to this property's subproperties. If the given \a property already is added, this function does nothing. \sa insertSubProperty(), removeSubProperty() */ void QtProperty::addSubProperty(QtProperty *property) { QtProperty *after = 0; if (d_ptr->m_subItems.count() > 0) after = d_ptr->m_subItems.last(); insertSubProperty(property, after); } /*! \fn void QtProperty::insertSubProperty(QtProperty *property, QtProperty *precedingProperty) Inserts the given \a property after the specified \a precedingProperty into this property's list of subproperties. If \a precedingProperty is 0, the specified \a property is inserted at the beginning of the list. If the given \a property already is inserted, this function does nothing. \sa addSubProperty(), removeSubProperty() */ void QtProperty::insertSubProperty(QtProperty *property, QtProperty *afterProperty) { if (!property) return; if (property == this) return; // traverse all children of item. if this item is a child of item then cannot add. QList pendingList = property->subProperties(); QMap visited; while (!pendingList.isEmpty()) { QtProperty *i = pendingList.first(); if (i == this) return; pendingList.removeFirst(); if (visited.contains(i)) continue; visited[i] = true; pendingList += i->subProperties(); } pendingList = subProperties(); int pos = 0; int newPos = 0; QtProperty *properAfterProperty = 0; while (pos < pendingList.count()) { QtProperty *i = pendingList.at(pos); if (i == property) return; // if item is already inserted in this item then cannot add. if (i == afterProperty) { newPos = pos + 1; properAfterProperty = afterProperty; } pos++; } d_ptr->m_subItems.insert(newPos, property); property->d_ptr->m_parentItems.insert(this); d_ptr->m_manager->d_ptr->propertyInserted(property, this, properAfterProperty); } /*! Removes the given \a property from the list of subproperties without deleting it. \sa addSubProperty(), insertSubProperty() */ void QtProperty::removeSubProperty(QtProperty *property) { if (!property) return; d_ptr->m_manager->d_ptr->propertyRemoved(property, this); QList pendingList = subProperties(); int pos = 0; while (pos < pendingList.count()) { if (pendingList.at(pos) == property) { d_ptr->m_subItems.removeAt(pos); property->d_ptr->m_parentItems.remove(this); return; } pos++; } } /*! \internal */ void QtProperty::propertyChanged() { d_ptr->m_manager->d_ptr->propertyChanged(this); } //////////////////////////////// void QtAbstractPropertyManagerPrivate::propertyDestroyed(QtProperty *property) { if (m_properties.contains(property)) { emit q_ptr->propertyDestroyed(property); q_ptr->uninitializeProperty(property); m_properties.remove(property); } } void QtAbstractPropertyManagerPrivate::propertyChanged(QtProperty *property) const { emit q_ptr->propertyChanged(property); } void QtAbstractPropertyManagerPrivate::propertyRemoved(QtProperty *property, QtProperty *parentProperty) const { emit q_ptr->propertyRemoved(property, parentProperty); } void QtAbstractPropertyManagerPrivate::propertyInserted(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty) const { emit q_ptr->propertyInserted(property, parentProperty, afterProperty); } /*! \class QtAbstractPropertyManager \brief The QtAbstractPropertyManager provides an interface for property managers. A manager can create and manage properties of a given type, and is used in conjunction with the QtAbstractPropertyBrowser class. When using a property browser widget, the properties are created and managed by implementations of the QtAbstractPropertyManager class. To ensure that the properties' values will be displayed using suitable editing widgets, the managers are associated with objects of QtAbstractEditorFactory subclasses. The property browser will use these associations to determine which factories it should use to create the preferred editing widgets. The QtAbstractPropertyManager class provides common functionality like creating a property using the addProperty() function, and retrieving the properties created by the manager using the properties() function. The class also provides signals that are emitted when the manager's properties change: propertyInserted(), propertyRemoved(), propertyChanged() and propertyDestroyed(). QtAbstractPropertyManager subclasses are supposed to provide their own type specific API. Note that several ready-made implementations are available: \list \o QtBoolPropertyManager \o QtColorPropertyManager \o QtDatePropertyManager \o QtDateTimePropertyManager \o QtDoublePropertyManager \o QtEnumPropertyManager \o QtFlagPropertyManager \o QtFontPropertyManager \o QtGroupPropertyManager \o QtIntPropertyManager \o QtPointPropertyManager \o QtRectPropertyManager \o QtSizePropertyManager \o QtSizePolicyPropertyManager \o QtStringPropertyManager \o QtTimePropertyManager \o QtVariantPropertyManager \endlist \sa QtAbstractEditorFactoryBase, QtAbstractPropertyBrowser, QtProperty */ /*! \fn void QtAbstractPropertyManager::propertyInserted(QtProperty *newProperty, QtProperty *parentProperty, QtProperty *precedingProperty) This signal is emitted when a new subproperty is inserted into an existing property, passing pointers to the \a newProperty, \a parentProperty and \a precedingProperty as parameters. If \a precedingProperty is 0, the \a newProperty was inserted at the beginning of the \a parentProperty's subproperties list. Note that signal is emitted only if the \a parentProperty is created by this manager. \sa QtAbstractPropertyBrowser::itemInserted() */ /*! \fn void QtAbstractPropertyManager::propertyChanged(QtProperty *property) This signal is emitted whenever a property's data changes, passing a pointer to the \a property as parameter. Note that signal is only emitted for properties that are created by this manager. \sa QtAbstractPropertyBrowser::itemChanged() */ /*! \fn void QtAbstractPropertyManager::propertyRemoved(QtProperty *property, QtProperty *parent) This signal is emitted when a subproperty is removed, passing pointers to the removed \a property and the \a parent property as parameters. Note that signal is emitted only when the \a parent property is created by this manager. \sa QtAbstractPropertyBrowser::itemRemoved() */ /*! \fn void QtAbstractPropertyManager::propertyDestroyed(QtProperty *property) This signal is emitted when the specified \a property is about to be destroyed. Note that signal is only emitted for properties that are created by this manager. \sa clear(), uninitializeProperty() */ /*! \fn void QtAbstractPropertyBrowser::currentItemChanged(QtBrowserItem *current) This signal is emitted when the current item changes. The current item is specified by \a current. \sa QtAbstractPropertyBrowser::setCurrentItem() */ /*! Creates an abstract property manager with the given \a parent. */ QtAbstractPropertyManager::QtAbstractPropertyManager(QObject *parent) : QObject(parent) { d_ptr = new QtAbstractPropertyManagerPrivate; d_ptr->q_ptr = this; } /*! Destroys the manager. All properties created by the manager are destroyed. */ QtAbstractPropertyManager::~QtAbstractPropertyManager() { clear(); delete d_ptr; } /*! Destroys all the properties that this manager has created. \sa propertyDestroyed(), uninitializeProperty() */ void QtAbstractPropertyManager::clear() const { while (!properties().isEmpty()) { QSetIterator itProperty(properties()); QtProperty *prop = itProperty.next(); delete prop; } } /*! Returns the set of properties created by this manager. \sa addProperty() */ QSet QtAbstractPropertyManager::properties() const { return d_ptr->m_properties; } /*! Returns whether the given \a property has a value. The default implementation of this function returns true. \sa QtProperty::hasValue() */ bool QtAbstractPropertyManager::hasValue(const QtProperty *property) const { Q_UNUSED(property) return true; } /*! Returns an icon representing the current state of the given \a property. The default implementation of this function returns an invalid icon. \sa QtProperty::valueIcon() */ QIcon QtAbstractPropertyManager::valueIcon(const QtProperty *property) const { Q_UNUSED(property) return QIcon(); } /*! Returns a string representing the current state of the given \a property. The default implementation of this function returns an empty string. \sa QtProperty::valueText() */ QString QtAbstractPropertyManager::valueText(const QtProperty *property) const { Q_UNUSED(property) return QString(); } /*! Returns a string representing the current state of the given \a property. The default implementation of this function returns an empty string. \sa QtProperty::valueText() */ QString QtAbstractPropertyManager::displayText(const QtProperty *property) const { Q_UNUSED(property) return QString(); } /*! Returns the echo mode representing the current state of the given \a property. The default implementation of this function returns QLineEdit::Normal. \sa QtProperty::valueText() */ EchoMode QtAbstractPropertyManager::echoMode(const QtProperty *property) const { Q_UNUSED(property) return QLineEdit::Normal; } /*! Creates a property with the given \a name which then is owned by this manager. Internally, this function calls the createProperty() and initializeProperty() functions. \sa initializeProperty(), properties() */ QtProperty *QtAbstractPropertyManager::addProperty(const QString &name) { QtProperty *property = createProperty(); if (property) { property->setPropertyName(name); d_ptr->m_properties.insert(property); initializeProperty(property); } return property; } /*! Creates a property. The base implementation produce QtProperty instances; Reimplement this function to make this manager produce objects of a QtProperty subclass. \sa addProperty(), initializeProperty() */ QtProperty *QtAbstractPropertyManager::createProperty() { return new QtProperty(this); } /*! \fn void QtAbstractPropertyManager::initializeProperty(QtProperty *property) = 0 This function is called whenever a new valid property pointer has been created, passing the pointer as parameter. The purpose is to let the manager know that the \a property has been created so that it can provide additional attributes for the new property, e.g. QtIntPropertyManager adds \l {QtIntPropertyManager::value()}{value}, \l {QtIntPropertyManager::minimum()}{minimum} and \l {QtIntPropertyManager::maximum()}{maximum} attributes. Since each manager subclass adds type specific attributes, this function is pure virtual and must be reimplemented when deriving from the QtAbstractPropertyManager class. \sa addProperty(), createProperty() */ /*! This function is called just before the specified \a property is destroyed. The purpose is to let the property manager know that the \a property is being destroyed so that it can remove the property's additional attributes. \sa clear(), propertyDestroyed() */ void QtAbstractPropertyManager::uninitializeProperty(QtProperty *property) { Q_UNUSED(property) } //////////////////////////////////// /*! \class QtAbstractEditorFactoryBase \brief The QtAbstractEditorFactoryBase provides an interface for editor factories. An editor factory is a class that is able to create an editing widget of a specified type (e.g. line edits or comboboxes) for a given QtProperty object, and it is used in conjunction with the QtAbstractPropertyManager and QtAbstractPropertyBrowser classes. When using a property browser widget, the properties are created and managed by implementations of the QtAbstractPropertyManager class. To ensure that the properties' values will be displayed using suitable editing widgets, the managers are associated with objects of QtAbstractEditorFactory subclasses. The property browser will use these associations to determine which factories it should use to create the preferred editing widgets. Typically, an editor factory is created by subclassing the QtAbstractEditorFactory template class which inherits QtAbstractEditorFactoryBase. But note that several ready-made implementations are available: \list \o QtCheckBoxFactory \o QtDateEditFactory \o QtDateTimeEditFactory \o QtDoubleSpinBoxFactory \o QtEnumEditorFactory \o QtLineEditFactory \o QtScrollBarFactory \o QtSliderFactory \o QtSpinBoxFactory \o QtTimeEditFactory \o QtVariantEditorFactory \endlist \sa QtAbstractPropertyManager, QtAbstractPropertyBrowser */ /*! \fn virtual QWidget *QtAbstractEditorFactoryBase::createEditor(QtProperty *property, QWidget *parent) = 0 Creates an editing widget (with the given \a parent) for the given \a property. This function is reimplemented in QtAbstractEditorFactory template class which also provides a pure virtual convenience overload of this function enabling access to the property's manager. \sa QtAbstractEditorFactory::createEditor() */ /*! \fn QtAbstractEditorFactoryBase::QtAbstractEditorFactoryBase(QObject *parent = 0) Creates an abstract editor factory with the given \a parent. */ /*! \fn virtual void QtAbstractEditorFactoryBase::breakConnection(QtAbstractPropertyManager *manager) = 0 \internal Detaches property manager from factory. This method is reimplemented in QtAbstractEditorFactory template subclass. You don't need to reimplement it in your subclasses. Instead implement more convenient QtAbstractEditorFactory::disconnectPropertyManager() which gives you access to particular manager subclass. */ /*! \fn virtual void QtAbstractEditorFactoryBase::managerDestroyed(QObject *manager) = 0 \internal This method is called when property manager is being destroyed. Basically it notifies factory not to produce editors for properties owned by \a manager. You don't need to reimplement it in your subclass. This method is implemented in QtAbstractEditorFactory template subclass. */ /*! \class QtAbstractEditorFactory \brief The QtAbstractEditorFactory is the base template class for editor factories. An editor factory is a class that is able to create an editing widget of a specified type (e.g. line edits or comboboxes) for a given QtProperty object, and it is used in conjunction with the QtAbstractPropertyManager and QtAbstractPropertyBrowser classes. Note that the QtAbstractEditorFactory functions are using the PropertyManager template argument class which can be any QtAbstractPropertyManager subclass. For example: \code QtSpinBoxFactory *factory; QSet managers = factory->propertyManagers(); \endcode Note that QtSpinBoxFactory by definition creates editing widgets \e only for properties created by QtIntPropertyManager. When using a property browser widget, the properties are created and managed by implementations of the QtAbstractPropertyManager class. To ensure that the properties' values will be displayed using suitable editing widgets, the managers are associated with objects of QtAbstractEditorFactory subclasses. The property browser will use these associations to determine which factories it should use to create the preferred editing widgets. A QtAbstractEditorFactory object is capable of producing editors for several property managers at the same time. To create an association between this factory and a given manager, use the addPropertyManager() function. Use the removePropertyManager() function to make this factory stop producing editors for a given property manager. Use the propertyManagers() function to retrieve the set of managers currently associated with this factory. Several ready-made implementations of the QtAbstractEditorFactory class are available: \list \o QtCheckBoxFactory \o QtDateEditFactory \o QtDateTimeEditFactory \o QtDoubleSpinBoxFactory \o QtEnumEditorFactory \o QtLineEditFactory \o QtScrollBarFactory \o QtSliderFactory \o QtSpinBoxFactory \o QtTimeEditFactory \o QtVariantEditorFactory \endlist When deriving from the QtAbstractEditorFactory class, several pure virtual functions must be implemented: the connectPropertyManager() function is used by the factory to connect to the given manager's signals, the createEditor() function is supposed to create an editor for the given property controlled by the given manager, and finally the disconnectPropertyManager() function is used by the factory to disconnect from the specified manager's signals. \sa QtAbstractEditorFactoryBase, QtAbstractPropertyManager */ /*! \fn QtAbstractEditorFactory::QtAbstractEditorFactory(QObject *parent = 0) Creates an editor factory with the given \a parent. \sa addPropertyManager() */ /*! \fn QWidget *QtAbstractEditorFactory::createEditor(QtProperty *property, QWidget *parent) Creates an editing widget (with the given \a parent) for the given \a property. */ /*! \fn void QtAbstractEditorFactory::addPropertyManager(PropertyManager *manager) Adds the given \a manager to this factory's set of managers, making this factory produce editing widgets for properties created by the given manager. The PropertyManager type is a template argument class, and represents the chosen QtAbstractPropertyManager subclass. \sa propertyManagers(), removePropertyManager() */ /*! \fn void QtAbstractEditorFactory::removePropertyManager(PropertyManager *manager) Removes the given \a manager from this factory's set of managers. The PropertyManager type is a template argument class, and may be any QtAbstractPropertyManager subclass. \sa propertyManagers(), addPropertyManager() */ /*! \fn virtual void QtAbstractEditorFactory::connectPropertyManager(PropertyManager *manager) = 0 Connects this factory to the given \a manager's signals. The PropertyManager type is a template argument class, and represents the chosen QtAbstractPropertyManager subclass. This function is used internally by the addPropertyManager() function, and makes it possible to update an editing widget when the associated property's data changes. This is typically done in custom slots responding to the signals emitted by the property's manager, e.g. QtIntPropertyManager::valueChanged() and QtIntPropertyManager::rangeChanged(). \sa propertyManagers(), disconnectPropertyManager() */ /*! \fn virtual QWidget *QtAbstractEditorFactory::createEditor(PropertyManager *manager, QtProperty *property, QWidget *parent) = 0 Creates an editing widget with the given \a parent for the specified \a property created by the given \a manager. The PropertyManager type is a template argument class, and represents the chosen QtAbstractPropertyManager subclass. This function must be implemented in derived classes: It is recommended to store a pointer to the widget and map it to the given \a property, since the widget must be updated whenever the associated property's data changes. This is typically done in custom slots responding to the signals emitted by the property's manager, e.g. QtIntPropertyManager::valueChanged() and QtIntPropertyManager::rangeChanged(). \sa connectPropertyManager() */ /*! \fn virtual void QtAbstractEditorFactory::disconnectPropertyManager(PropertyManager *manager) = 0 Disconnects this factory from the given \a manager's signals. The PropertyManager type is a template argument class, and represents the chosen QtAbstractPropertyManager subclass. This function is used internally by the removePropertyManager() function. \sa propertyManagers(), connectPropertyManager() */ /*! \fn QSet QtAbstractEditorFactory::propertyManagers() const Returns the factory's set of associated managers. The PropertyManager type is a template argument class, and represents the chosen QtAbstractPropertyManager subclass. \sa addPropertyManager(), removePropertyManager() */ /*! \fn PropertyManager *QtAbstractEditorFactory::propertyManager(QtProperty *property) const Returns the property manager for the given \a property, or 0 if the given \a property doesn't belong to any of this factory's registered managers. The PropertyManager type is a template argument class, and represents the chosen QtAbstractPropertyManager subclass. \sa propertyManagers() */ /*! \fn virtual void QtAbstractEditorFactory::managerDestroyed(QObject *manager) \internal \reimp */ //////////////////////////////////// class QtBrowserItemPrivate { public: QtBrowserItemPrivate(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent) : m_browser(browser), m_property(property), m_parent(parent), q_ptr(0) {} void addChild(QtBrowserItem *index, QtBrowserItem *after); void removeChild(QtBrowserItem *index); QtAbstractPropertyBrowser * const m_browser; QtProperty *m_property; QtBrowserItem *m_parent; QtBrowserItem *q_ptr; QList m_children; }; void QtBrowserItemPrivate::addChild(QtBrowserItem *index, QtBrowserItem *after) { if (m_children.contains(index)) return; int idx = m_children.indexOf(after) + 1; // we insert after returned idx, if it was -1 then we set idx to 0; m_children.insert(idx, index); } void QtBrowserItemPrivate::removeChild(QtBrowserItem *index) { m_children.removeAll(index); } /*! \class QtBrowserItem \brief The QtBrowserItem class represents a property in a property browser instance. Browser items are created whenever a QtProperty is inserted to the property browser. A QtBrowserItem uniquely identifies a browser's item. Thus, if the same QtProperty is inserted multiple times, each occurrence gets its own unique QtBrowserItem. The items are owned by QtAbstractPropertyBrowser and automatically deleted when they are removed from the browser. You can traverse a browser's properties by calling parent() and children(). The property and the browser associated with an item are available as property() and browser(). \sa QtAbstractPropertyBrowser, QtProperty */ /*! Returns the property which is accosiated with this item. Note that several items can be associated with the same property instance in the same property browser. \sa QtAbstractPropertyBrowser::items() */ QtProperty *QtBrowserItem::property() const { return d_ptr->m_property; } /*! Returns the parent item of \e this item. Returns 0 if \e this item is associated with top-level property in item's property browser. \sa children() */ QtBrowserItem *QtBrowserItem::parent() const { return d_ptr->m_parent; } /*! Returns the children items of \e this item. The properties reproduced from children items are always the same as reproduced from associated property' children, for example: \code QtBrowserItem *item; QList childrenItems = item->children(); QList childrenProperties = item->property()->subProperties(); \endcode The \e childrenItems list represents the same list as \e childrenProperties. */ QList QtBrowserItem::children() const { return d_ptr->m_children; } /*! Returns the property browser which owns \e this item. */ QtAbstractPropertyBrowser *QtBrowserItem::browser() const { return d_ptr->m_browser; } QtBrowserItem::QtBrowserItem(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent) { d_ptr = new QtBrowserItemPrivate(browser, property, parent); d_ptr->q_ptr = this; } QtBrowserItem::~QtBrowserItem() { delete d_ptr; } //////////////////////////////////// typedef QMap > Map1; typedef QMap > > Map2; Q_GLOBAL_STATIC(Map1, m_viewToManagerToFactory) Q_GLOBAL_STATIC(Map2, m_managerToFactoryToViews) class QtAbstractPropertyBrowserPrivate { QtAbstractPropertyBrowser *q_ptr; Q_DECLARE_PUBLIC(QtAbstractPropertyBrowser) public: QtAbstractPropertyBrowserPrivate(); void insertSubTree(QtProperty *property, QtProperty *parentProperty); void removeSubTree(QtProperty *property, QtProperty *parentProperty); void createBrowserIndexes(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty); void removeBrowserIndexes(QtProperty *property, QtProperty *parentProperty); QtBrowserItem *createBrowserIndex(QtProperty *property, QtBrowserItem *parentIndex, QtBrowserItem *afterIndex); void removeBrowserIndex(QtBrowserItem *index); void clearIndex(QtBrowserItem *index); void slotPropertyInserted(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty); void slotPropertyRemoved(QtProperty *property, QtProperty *parentProperty); void slotPropertyDestroyed(QtProperty *property); void slotPropertyDataChanged(QtProperty *property); QList m_subItems; QMap > m_managerToProperties; QMap > m_propertyToParents; QMap m_topLevelPropertyToIndex; QList m_topLevelIndexes; QMap > m_propertyToIndexes; QtBrowserItem *m_currentItem; }; QtAbstractPropertyBrowserPrivate::QtAbstractPropertyBrowserPrivate() : m_currentItem(0) { } void QtAbstractPropertyBrowserPrivate::insertSubTree(QtProperty *property, QtProperty *parentProperty) { if (m_propertyToParents.contains(property)) { // property was already inserted, so its manager is connected // and all its children are inserted and theirs managers are connected // we just register new parent (parent has to be new). m_propertyToParents[property].append(parentProperty); // don't need to update m_managerToProperties map since // m_managerToProperties[manager] already contains property. return; } QtAbstractPropertyManager *manager = property->propertyManager(); if (m_managerToProperties[manager].isEmpty()) { // connect manager's signals q_ptr->connect(manager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), q_ptr, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); q_ptr->connect(manager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), q_ptr, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); q_ptr->connect(manager, SIGNAL(propertyDestroyed(QtProperty *)), q_ptr, SLOT(slotPropertyDestroyed(QtProperty *))); q_ptr->connect(manager, SIGNAL(propertyChanged(QtProperty *)), q_ptr, SLOT(slotPropertyDataChanged(QtProperty *))); } m_managerToProperties[manager].append(property); m_propertyToParents[property].append(parentProperty); QList subList = property->subProperties(); QListIterator itSub(subList); while (itSub.hasNext()) { QtProperty *subProperty = itSub.next(); insertSubTree(subProperty, property); } } void QtAbstractPropertyBrowserPrivate::removeSubTree(QtProperty *property, QtProperty *parentProperty) { if (!m_propertyToParents.contains(property)) { // ASSERT return; } m_propertyToParents[property].removeAll(parentProperty); if (!m_propertyToParents[property].isEmpty()) return; m_propertyToParents.remove(property); QtAbstractPropertyManager *manager = property->propertyManager(); m_managerToProperties[manager].removeAll(property); if (m_managerToProperties[manager].isEmpty()) { // disconnect manager's signals q_ptr->disconnect(manager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), q_ptr, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); q_ptr->disconnect(manager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), q_ptr, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); q_ptr->disconnect(manager, SIGNAL(propertyDestroyed(QtProperty *)), q_ptr, SLOT(slotPropertyDestroyed(QtProperty *))); q_ptr->disconnect(manager, SIGNAL(propertyChanged(QtProperty *)), q_ptr, SLOT(slotPropertyDataChanged(QtProperty *))); m_managerToProperties.remove(manager); } QList subList = property->subProperties(); QListIterator itSub(subList); while (itSub.hasNext()) { QtProperty *subProperty = itSub.next(); removeSubTree(subProperty, property); } } void QtAbstractPropertyBrowserPrivate::createBrowserIndexes(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty) { QMap parentToAfter; if (afterProperty) { QMap >::ConstIterator it = m_propertyToIndexes.find(afterProperty); if (it == m_propertyToIndexes.constEnd()) return; QList indexes = it.value(); QListIterator itIndex(indexes); while (itIndex.hasNext()) { QtBrowserItem *idx = itIndex.next(); QtBrowserItem *parentIdx = idx->parent(); if ((parentProperty && parentIdx && parentIdx->property() == parentProperty) || (!parentProperty && !parentIdx)) parentToAfter[idx->parent()] = idx; } } else if (parentProperty) { QMap >::ConstIterator it = m_propertyToIndexes.find(parentProperty); if (it == m_propertyToIndexes.constEnd()) return; QList indexes = it.value(); QListIterator itIndex(indexes); while (itIndex.hasNext()) { QtBrowserItem *idx = itIndex.next(); parentToAfter[idx] = 0; } } else { parentToAfter[0] = 0; } const QMap::ConstIterator pcend = parentToAfter.constEnd(); for (QMap::ConstIterator it = parentToAfter.constBegin(); it != pcend; ++it) createBrowserIndex(property, it.key(), it.value()); } QtBrowserItem *QtAbstractPropertyBrowserPrivate::createBrowserIndex(QtProperty *property, QtBrowserItem *parentIndex, QtBrowserItem *afterIndex) { QtBrowserItem *newIndex = new QtBrowserItem(q_ptr, property, parentIndex); if (parentIndex) { parentIndex->d_ptr->addChild(newIndex, afterIndex); } else { m_topLevelPropertyToIndex[property] = newIndex; m_topLevelIndexes.insert(m_topLevelIndexes.indexOf(afterIndex) + 1, newIndex); } m_propertyToIndexes[property].append(newIndex); q_ptr->itemInserted(newIndex, afterIndex); QList subItems = property->subProperties(); QListIterator itChild(subItems); QtBrowserItem *afterChild = 0; while (itChild.hasNext()) { QtProperty *child = itChild.next(); afterChild = createBrowserIndex(child, newIndex, afterChild); } return newIndex; } void QtAbstractPropertyBrowserPrivate::removeBrowserIndexes(QtProperty *property, QtProperty *parentProperty) { QList toRemove; QMap >::ConstIterator it = m_propertyToIndexes.find(property); if (it == m_propertyToIndexes.constEnd()) return; QList indexes = it.value(); QListIterator itIndex(indexes); while (itIndex.hasNext()) { QtBrowserItem *idx = itIndex.next(); QtBrowserItem *parentIdx = idx->parent(); if ((parentProperty && parentIdx && parentIdx->property() == parentProperty) || (!parentProperty && !parentIdx)) toRemove.append(idx); } QListIterator itRemove(toRemove); while (itRemove.hasNext()) { QtBrowserItem *index = itRemove.next(); removeBrowserIndex(index); } } void QtAbstractPropertyBrowserPrivate::removeBrowserIndex(QtBrowserItem *index) { QList children = index->children(); for (int i = children.count(); i > 0; i--) { removeBrowserIndex(children.at(i - 1)); } q_ptr->itemRemoved(index); if (index->parent()) { index->parent()->d_ptr->removeChild(index); } else { m_topLevelPropertyToIndex.remove(index->property()); m_topLevelIndexes.removeAll(index); } QtProperty *property = index->property(); m_propertyToIndexes[property].removeAll(index); if (m_propertyToIndexes[property].isEmpty()) m_propertyToIndexes.remove(property); delete index; } void QtAbstractPropertyBrowserPrivate::clearIndex(QtBrowserItem *index) { QList children = index->children(); QListIterator itChild(children); while (itChild.hasNext()) { clearIndex(itChild.next()); } delete index; } void QtAbstractPropertyBrowserPrivate::slotPropertyInserted(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty) { if (!m_propertyToParents.contains(parentProperty)) return; createBrowserIndexes(property, parentProperty, afterProperty); insertSubTree(property, parentProperty); //q_ptr->propertyInserted(property, parentProperty, afterProperty); } void QtAbstractPropertyBrowserPrivate::slotPropertyRemoved(QtProperty *property, QtProperty *parentProperty) { if (!m_propertyToParents.contains(parentProperty)) return; removeSubTree(property, parentProperty); // this line should be probably moved down after propertyRemoved call //q_ptr->propertyRemoved(property, parentProperty); removeBrowserIndexes(property, parentProperty); } void QtAbstractPropertyBrowserPrivate::slotPropertyDestroyed(QtProperty *property) { if (!m_subItems.contains(property)) return; q_ptr->removeProperty(property); } void QtAbstractPropertyBrowserPrivate::slotPropertyDataChanged(QtProperty *property) { if (!m_propertyToParents.contains(property)) return; QMap >::ConstIterator it = m_propertyToIndexes.find(property); if (it == m_propertyToIndexes.constEnd()) return; QList indexes = it.value(); QListIterator itIndex(indexes); while (itIndex.hasNext()) { QtBrowserItem *idx = itIndex.next(); q_ptr->itemChanged(idx); } //q_ptr->propertyChanged(property); } /*! \class QtAbstractPropertyBrowser \brief QtAbstractPropertyBrowser provides a base class for implementing property browsers. A property browser is a widget that enables the user to edit a given set of properties. Each property is represented by a label specifying the property's name, and an editing widget (e.g. a line edit or a combobox) holding its value. A property can have zero or more subproperties. \image qtpropertybrowser.png The top level properties can be retrieved using the properties() function. To traverse each property's subproperties, use the QtProperty::subProperties() function. In addition, the set of top level properties can be manipulated using the addProperty(), insertProperty() and removeProperty() functions. Note that the QtProperty class provides a corresponding set of functions making it possible to manipulate the set of subproperties as well. To remove all the properties from the property browser widget, use the clear() function. This function will clear the editor, but it will not delete the properties since they can still be used in other editors. The properties themselves are created and managed by implementations of the QtAbstractPropertyManager class. A manager can handle (i.e. create and manage) properties of a given type. In the property browser the managers are associated with implementations of the QtAbstractEditorFactory: A factory is a class able to create an editing widget of a specified type. When using a property browser widget, managers must be created for each of the required property types before the properties themselves can be created. To ensure that the properties' values will be displayed using suitable editing widgets, the managers must be associated with objects of the preferred factory implementations using the setFactoryForManager() function. The property browser will use these associations to determine which factory it should use to create the preferred editing widget. Note that a factory can be associated with many managers, but a manager can only be associated with one single factory within the context of a single property browser. The associations between managers and factories can at any time be removed using the unsetFactoryForManager() function. Whenever the property data changes or a property is inserted or removed, the itemChanged(), itemInserted() or itemRemoved() functions are called, respectively. These functions must be reimplemented in derived classes in order to update the property browser widget. Be aware that some property instances can appear several times in an abstract tree structure. For example: \table 100% \row \o \code QtProperty *property1, *property2, *property3; property2->addSubProperty(property1); property3->addSubProperty(property2); QtAbstractPropertyBrowser *editor; editor->addProperty(property1); editor->addProperty(property2); editor->addProperty(property3); \endcode \o \image qtpropertybrowser-duplicate.png \endtable The addProperty() function returns a QtBrowserItem that uniquely identifies the created item. To make a property editable in the property browser, the createEditor() function must be called to provide the property with a suitable editing widget. Note that there are two ready-made property browser implementations: \list \o QtGroupBoxPropertyBrowser \o QtTreePropertyBrowser \endlist \sa QtAbstractPropertyManager, QtAbstractEditorFactoryBase */ /*! \fn void QtAbstractPropertyBrowser::setFactoryForManager(PropertyManager *manager, QtAbstractEditorFactory *factory) Connects the given \a manager to the given \a factory, ensuring that properties of the \a manager's type will be displayed with an editing widget suitable for their value. For example: \code QtIntPropertyManager *intManager; QtDoublePropertyManager *doubleManager; QtProperty *myInteger = intManager->addProperty(); QtProperty *myDouble = doubleManager->addProperty(); QtSpinBoxFactory *spinBoxFactory; QtDoubleSpinBoxFactory *doubleSpinBoxFactory; QtAbstractPropertyBrowser *editor; editor->setFactoryForManager(intManager, spinBoxFactory); editor->setFactoryForManager(doubleManager, doubleSpinBoxFactory); editor->addProperty(myInteger); editor->addProperty(myDouble); \endcode In this example the \c myInteger property's value is displayed with a QSpinBox widget, while the \c myDouble property's value is displayed with a QDoubleSpinBox widget. Note that a factory can be associated with many managers, but a manager can only be associated with one single factory. If the given \a manager already is associated with another factory, the old association is broken before the new one established. This function ensures that the given \a manager and the given \a factory are compatible, and it automatically calls the QtAbstractEditorFactory::addPropertyManager() function if necessary. \sa unsetFactoryForManager() */ /*! \fn virtual void QtAbstractPropertyBrowser::itemInserted(QtBrowserItem *insertedItem, QtBrowserItem *precedingItem) = 0 This function is called to update the widget whenever a property is inserted or added to the property browser, passing pointers to the \a insertedItem of property and the specified \a precedingItem as parameters. If \a precedingItem is 0, the \a insertedItem was put at the beginning of its parent item's list of subproperties. If the parent of \a insertedItem is 0, the \a insertedItem was added as a top level property of \e this property browser. This function must be reimplemented in derived classes. Note that if the \a insertedItem's property has subproperties, this method will be called for those properties as soon as the current call is finished. \sa insertProperty(), addProperty() */ /*! \fn virtual void QtAbstractPropertyBrowser::itemRemoved(QtBrowserItem *item) = 0 This function is called to update the widget whenever a property is removed from the property browser, passing the pointer to the \a item of the property as parameters. The passed \a item is deleted just after this call is finished. If the the parent of \a item is 0, the removed \a item was a top level property in this editor. This function must be reimplemented in derived classes. Note that if the removed \a item's property has subproperties, this method will be called for those properties just before the current call is started. \sa removeProperty() */ /*! \fn virtual void QtAbstractPropertyBrowser::itemChanged(QtBrowserItem *item) = 0 This function is called whenever a property's data changes, passing a pointer to the \a item of property as parameter. This function must be reimplemented in derived classes in order to update the property browser widget whenever a property's name, tool tip, status tip, "what's this" text, value text or value icon changes. Note that if the property browser contains several occurrences of the same property, this method will be called once for each occurrence (with a different item each time). \sa QtProperty, items() */ /*! Creates an abstract property browser with the given \a parent. */ QtAbstractPropertyBrowser::QtAbstractPropertyBrowser(QWidget *parent) : QWidget(parent) { d_ptr = new QtAbstractPropertyBrowserPrivate; d_ptr->q_ptr = this; } /*! Destroys the property browser, and destroys all the items that were created by this property browser. Note that the properties that were displayed in the editor are not deleted since they still can be used in other editors. Neither does the destructor delete the property managers and editor factories that were used by this property browser widget unless this widget was their parent. \sa QtAbstractPropertyManager::~QtAbstractPropertyManager() */ QtAbstractPropertyBrowser::~QtAbstractPropertyBrowser() { QList indexes = topLevelItems(); QListIterator itItem(indexes); while (itItem.hasNext()) d_ptr->clearIndex(itItem.next()); delete d_ptr; } /*! Returns the property browser's list of top level properties. To traverse the subproperties, use the QtProperty::subProperties() function. \sa addProperty(), insertProperty(), removeProperty() */ QList QtAbstractPropertyBrowser::properties() const { return d_ptr->m_subItems; } /*! Returns the property browser's list of all items associated with the given \a property. There is one item per instance of the property in the browser. \sa topLevelItem() */ QList QtAbstractPropertyBrowser::items(QtProperty *property) const { return d_ptr->m_propertyToIndexes.value(property); } /*! Returns the top-level items associated with the given \a property. Returns 0 if \a property wasn't inserted into this property browser or isn't a top-level one. \sa topLevelItems(), items() */ QtBrowserItem *QtAbstractPropertyBrowser::topLevelItem(QtProperty *property) const { return d_ptr->m_topLevelPropertyToIndex.value(property); } /*! Returns the list of top-level items. \sa topLevelItem() */ QList QtAbstractPropertyBrowser::topLevelItems() const { return d_ptr->m_topLevelIndexes; } /*! Removes all the properties from the editor, but does not delete them since they can still be used in other editors. \sa removeProperty(), QtAbstractPropertyManager::clear() */ void QtAbstractPropertyBrowser::clear() { QList subList = properties(); QListIterator itSub(subList); itSub.toBack(); while (itSub.hasPrevious()) { QtProperty *property = itSub.previous(); removeProperty(property); } } /*! Appends the given \a property (and its subproperties) to the property browser's list of top level properties. Returns the item created by property browser which is associated with the \a property. In order to get all children items created by the property browser in this call, the returned item should be traversed. If the specified \a property is already added, this function does nothing and returns 0. \sa insertProperty(), QtProperty::addSubProperty(), properties() */ QtBrowserItem *QtAbstractPropertyBrowser::addProperty(QtProperty *property) { QtProperty *afterProperty = 0; if (d_ptr->m_subItems.count() > 0) afterProperty = d_ptr->m_subItems.last(); return insertProperty(property, afterProperty); } /*! \fn QtBrowserItem *QtAbstractPropertyBrowser::insertProperty(QtProperty *property, QtProperty *afterProperty) Inserts the given \a property (and its subproperties) after the specified \a afterProperty in the browser's list of top level properties. Returns item created by property browser which is associated with the \a property. In order to get all children items created by the property browser in this call returned item should be traversed. If the specified \a afterProperty is 0, the given \a property is inserted at the beginning of the list. If \a property is already inserted, this function does nothing and returns 0. \sa addProperty(), QtProperty::insertSubProperty(), properties() */ QtBrowserItem *QtAbstractPropertyBrowser::insertProperty(QtProperty *property, QtProperty *afterProperty) { if (!property) return 0; // if item is already inserted in this item then cannot add. QList pendingList = properties(); int pos = 0; int newPos = 0; while (pos < pendingList.count()) { QtProperty *prop = pendingList.at(pos); if (prop == property) return 0; if (prop == afterProperty) { newPos = pos + 1; } pos++; } d_ptr->createBrowserIndexes(property, 0, afterProperty); // traverse inserted subtree and connect to manager's signals d_ptr->insertSubTree(property, 0); d_ptr->m_subItems.insert(newPos, property); //propertyInserted(property, 0, properAfterProperty); return topLevelItem(property); } /*! Removes the specified \a property (and its subproperties) from the property browser's list of top level properties. All items that were associated with the given \a property and its children are deleted. Note that the properties are \e not deleted since they can still be used in other editors. \sa clear(), QtProperty::removeSubProperty(), properties() */ void QtAbstractPropertyBrowser::removeProperty(QtProperty *property) { if (!property) return; QList pendingList = properties(); int pos = 0; while (pos < pendingList.count()) { if (pendingList.at(pos) == property) { d_ptr->m_subItems.removeAt(pos); //perhaps this two lines d_ptr->removeSubTree(property, 0); //should be moved down after propertyRemoved call. //propertyRemoved(property, 0); d_ptr->removeBrowserIndexes(property, 0); // when item is deleted, item will call removeItem for top level items, // and itemRemoved for nested items. return; } pos++; } } /*! Creates an editing widget (with the given \a parent) for the given \a property according to the previously established associations between property managers and editor factories. If the property is created by a property manager which was not associated with any of the existing factories in \e this property editor, the function returns 0. To make a property editable in the property browser, the createEditor() function must be called to provide the property with a suitable editing widget. Reimplement this function to provide additional decoration for the editing widgets created by the installed factories. \sa setFactoryForManager() */ QWidget *QtAbstractPropertyBrowser::createEditor(QtProperty *property, QWidget *parent) { QtAbstractEditorFactoryBase *factory = 0; QtAbstractPropertyManager *manager = property->propertyManager(); if (m_viewToManagerToFactory()->contains(this) && (*m_viewToManagerToFactory())[this].contains(manager)) { factory = (*m_viewToManagerToFactory())[this][manager]; } if (!factory) return 0; return factory->createEditor(property, parent); } bool QtAbstractPropertyBrowser::addFactory(QtAbstractPropertyManager *abstractManager, QtAbstractEditorFactoryBase *abstractFactory) { bool connectNeeded = false; if (!m_managerToFactoryToViews()->contains(abstractManager) || !(*m_managerToFactoryToViews())[abstractManager].contains(abstractFactory)) { connectNeeded = true; } else if ((*m_managerToFactoryToViews())[abstractManager][abstractFactory] .contains(this)) { return connectNeeded; } if (m_viewToManagerToFactory()->contains(this) && (*m_viewToManagerToFactory())[this].contains(abstractManager)) { unsetFactoryForManager(abstractManager); } (*m_managerToFactoryToViews())[abstractManager][abstractFactory].append(this); (*m_viewToManagerToFactory())[this][abstractManager] = abstractFactory; return connectNeeded; } /*! Removes the association between the given \a manager and the factory bound to it, automatically calling the QtAbstractEditorFactory::removePropertyManager() function if necessary. \sa setFactoryForManager() */ void QtAbstractPropertyBrowser::unsetFactoryForManager(QtAbstractPropertyManager *manager) { if (!m_viewToManagerToFactory()->contains(this) || !(*m_viewToManagerToFactory())[this].contains(manager)) { return; } QtAbstractEditorFactoryBase *abstractFactory = (*m_viewToManagerToFactory())[this][manager]; (*m_viewToManagerToFactory())[this].remove(manager); if ((*m_viewToManagerToFactory())[this].isEmpty()) { (*m_viewToManagerToFactory()).remove(this); } (*m_managerToFactoryToViews())[manager][abstractFactory].removeAll(this); if ((*m_managerToFactoryToViews())[manager][abstractFactory].isEmpty()) { (*m_managerToFactoryToViews())[manager].remove(abstractFactory); abstractFactory->breakConnection(manager); if ((*m_managerToFactoryToViews())[manager].isEmpty()) { (*m_managerToFactoryToViews()).remove(manager); } } } /*! Returns the current item in the property browser. \sa setCurrentItem() */ QtBrowserItem *QtAbstractPropertyBrowser::currentItem() const { return d_ptr->m_currentItem; } /*! Sets the current item in the property browser to \a item. \sa currentItem(), currentItemChanged() */ void QtAbstractPropertyBrowser::setCurrentItem(QtBrowserItem *item) { QtBrowserItem *oldItem = d_ptr->m_currentItem; d_ptr->m_currentItem = item; if (oldItem != item) emit currentItemChanged(item); } #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif #include "moc_qtpropertybrowser.cpp" tiled-1.0.3/src/qtpropertybrowser/src/qtpropertybrowser.h000066400000000000000000000263661315121121300240400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTPROPERTYBROWSER_H #define QTPROPERTYBROWSER_H #include #include #include #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif #if defined(Q_OS_WIN) # if !defined(QT_QTPROPERTYBROWSER_EXPORT) && !defined(QT_QTPROPERTYBROWSER_IMPORT) # define QT_QTPROPERTYBROWSER_EXPORT # elif defined(QT_QTPROPERTYBROWSER_IMPORT) # if defined(QT_QTPROPERTYBROWSER_EXPORT) # undef QT_QTPROPERTYBROWSER_EXPORT # endif # define QT_QTPROPERTYBROWSER_EXPORT __declspec(dllimport) # elif defined(QT_QTPROPERTYBROWSER_EXPORT) # undef QT_QTPROPERTYBROWSER_EXPORT # define QT_QTPROPERTYBROWSER_EXPORT __declspec(dllexport) # endif #else # define QT_QTPROPERTYBROWSER_EXPORT #endif typedef QLineEdit::EchoMode EchoMode; class QtAbstractPropertyManager; class QtPropertyPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtProperty { public: virtual ~QtProperty(); QList subProperties() const; QtAbstractPropertyManager *propertyManager() const; QString toolTip() const; QString statusTip() const; QString whatsThis() const; QString propertyName() const; QColor nameColor() const; QColor valueColor() const; bool isEnabled() const; bool isModified() const; bool hasValue() const; QIcon valueIcon() const; QString valueText() const; QString displayText() const; void setToolTip(const QString &text); void setStatusTip(const QString &text); void setWhatsThis(const QString &text); void setPropertyName(const QString &text); void setNameColor(const QColor &color); void setValueColor(const QColor &color); void setEnabled(bool enable); void setModified(bool modified); void addSubProperty(QtProperty *property); void insertSubProperty(QtProperty *property, QtProperty *afterProperty); void removeSubProperty(QtProperty *property); protected: explicit QtProperty(QtAbstractPropertyManager *manager); void propertyChanged(); private: friend class QtAbstractPropertyManager; QtPropertyPrivate *d_ptr; }; class QtAbstractPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtAbstractPropertyManager : public QObject { Q_OBJECT public: explicit QtAbstractPropertyManager(QObject *parent = 0); ~QtAbstractPropertyManager(); QSet properties() const; void clear() const; QtProperty *addProperty(const QString &name = QString()); Q_SIGNALS: void propertyInserted(QtProperty *property, QtProperty *parent, QtProperty *after); void propertyChanged(QtProperty *property); void propertyRemoved(QtProperty *property, QtProperty *parent); void propertyDestroyed(QtProperty *property); protected: virtual bool hasValue(const QtProperty *property) const; virtual QIcon valueIcon(const QtProperty *property) const; virtual QString valueText(const QtProperty *property) const; virtual QString displayText(const QtProperty *property) const; virtual EchoMode echoMode(const QtProperty *) const; virtual void initializeProperty(QtProperty *property) = 0; virtual void uninitializeProperty(QtProperty *property); virtual QtProperty *createProperty(); private: friend class QtProperty; QtAbstractPropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtAbstractPropertyManager) Q_DISABLE_COPY(QtAbstractPropertyManager) }; class QT_QTPROPERTYBROWSER_EXPORT QtAbstractEditorFactoryBase : public QObject { Q_OBJECT public: virtual QWidget *createEditor(QtProperty *property, QWidget *parent) = 0; protected: explicit QtAbstractEditorFactoryBase(QObject *parent = 0) : QObject(parent) {} virtual void breakConnection(QtAbstractPropertyManager *manager) = 0; protected Q_SLOTS: virtual void managerDestroyed(QObject *manager) = 0; friend class QtAbstractPropertyBrowser; }; template class QtAbstractEditorFactory : public QtAbstractEditorFactoryBase { public: explicit QtAbstractEditorFactory(QObject *parent) : QtAbstractEditorFactoryBase(parent) {} QWidget *createEditor(QtProperty *property, QWidget *parent) { QSetIterator it(m_managers); while (it.hasNext()) { PropertyManager *manager = it.next(); if (manager == property->propertyManager()) { return createEditor(manager, property, parent); } } return 0; } void addPropertyManager(PropertyManager *manager) { if (m_managers.contains(manager)) return; m_managers.insert(manager); connectPropertyManager(manager); connect(manager, SIGNAL(destroyed(QObject *)), this, SLOT(managerDestroyed(QObject *))); } void removePropertyManager(PropertyManager *manager) { if (!m_managers.contains(manager)) return; disconnect(manager, SIGNAL(destroyed(QObject *)), this, SLOT(managerDestroyed(QObject *))); disconnectPropertyManager(manager); m_managers.remove(manager); } QSet propertyManagers() const { return m_managers; } PropertyManager *propertyManager(QtProperty *property) const { QtAbstractPropertyManager *manager = property->propertyManager(); QSetIterator itManager(m_managers); while (itManager.hasNext()) { PropertyManager *m = itManager.next(); if (m == manager) { return m; } } return 0; } protected: virtual void connectPropertyManager(PropertyManager *manager) = 0; virtual QWidget *createEditor(PropertyManager *manager, QtProperty *property, QWidget *parent) = 0; virtual void disconnectPropertyManager(PropertyManager *manager) = 0; void managerDestroyed(QObject *manager) { QSetIterator it(m_managers); while (it.hasNext()) { PropertyManager *m = it.next(); if (m == manager) { m_managers.remove(m); return; } } } private: void breakConnection(QtAbstractPropertyManager *manager) { QSetIterator it(m_managers); while (it.hasNext()) { PropertyManager *m = it.next(); if (m == manager) { removePropertyManager(m); return; } } } private: QSet m_managers; friend class QtAbstractPropertyEditor; }; class QtAbstractPropertyBrowser; class QtBrowserItemPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtBrowserItem { public: QtProperty *property() const; QtBrowserItem *parent() const; QList children() const; QtAbstractPropertyBrowser *browser() const; private: explicit QtBrowserItem(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent); ~QtBrowserItem(); QtBrowserItemPrivate *d_ptr; friend class QtAbstractPropertyBrowserPrivate; }; class QtAbstractPropertyBrowserPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtAbstractPropertyBrowser : public QWidget { Q_OBJECT public: explicit QtAbstractPropertyBrowser(QWidget *parent = 0); ~QtAbstractPropertyBrowser(); QList properties() const; QList items(QtProperty *property) const; QtBrowserItem *topLevelItem(QtProperty *property) const; QList topLevelItems() const; void clear(); template void setFactoryForManager(PropertyManager *manager, QtAbstractEditorFactory *factory) { QtAbstractPropertyManager *abstractManager = manager; QtAbstractEditorFactoryBase *abstractFactory = factory; if (addFactory(abstractManager, abstractFactory)) factory->addPropertyManager(manager); } void unsetFactoryForManager(QtAbstractPropertyManager *manager); QtBrowserItem *currentItem() const; void setCurrentItem(QtBrowserItem *); Q_SIGNALS: void currentItemChanged(QtBrowserItem *); public Q_SLOTS: QtBrowserItem *addProperty(QtProperty *property); QtBrowserItem *insertProperty(QtProperty *property, QtProperty *afterProperty); void removeProperty(QtProperty *property); protected: virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem) = 0; virtual void itemRemoved(QtBrowserItem *item) = 0; // can be tooltip, statustip, whatsthis, name, icon, text. virtual void itemChanged(QtBrowserItem *item) = 0; virtual QWidget *createEditor(QtProperty *property, QWidget *parent); private: bool addFactory(QtAbstractPropertyManager *abstractManager, QtAbstractEditorFactoryBase *abstractFactory); QtAbstractPropertyBrowserPrivate *d_ptr; Q_DECLARE_PRIVATE(QtAbstractPropertyBrowser) Q_DISABLE_COPY(QtAbstractPropertyBrowser) Q_PRIVATE_SLOT(d_func(), void slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)) Q_PRIVATE_SLOT(d_func(), void slotPropertyRemoved(QtProperty *, QtProperty *)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDataChanged(QtProperty *)) }; #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif #endif // QTPROPERTYBROWSER_H tiled-1.0.3/src/qtpropertybrowser/src/qtpropertybrowser.pri000066400000000000000000000022251315121121300243670ustar00rootroot00000000000000include(../common.pri) greaterThan(QT_MAJOR_VERSION, 4): QT *= widgets INCLUDEPATH += $$PWD DEPENDPATH += $$PWD qtpropertybrowser-uselib:!qtpropertybrowser-buildlib { LIBS += -L$$QTPROPERTYBROWSER_LIBDIR -l$$QTPROPERTYBROWSER_LIBNAME } else { SOURCES += $$PWD/qtpropertybrowser.cpp \ $$PWD/qtpropertymanager.cpp \ $$PWD/qteditorfactory.cpp \ $$PWD/qtvariantproperty.cpp \ $$PWD/qttreepropertybrowser.cpp \ $$PWD/qtbuttonpropertybrowser.cpp \ $$PWD/qtgroupboxpropertybrowser.cpp \ $$PWD/qtpropertybrowserutils.cpp HEADERS += $$PWD/qtpropertybrowser.h \ $$PWD/qtpropertymanager.h \ $$PWD/qteditorfactory.h \ $$PWD/qtvariantproperty.h \ $$PWD/qttreepropertybrowser.h \ $$PWD/qtbuttonpropertybrowser.h \ $$PWD/qtgroupboxpropertybrowser.h \ $$PWD/qtpropertybrowserutils_p.h RESOURCES += $$PWD/qtpropertybrowser.qrc } win32 { contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTPROPERTYBROWSER_EXPORT else:qtpropertybrowser-uselib:DEFINES += QT_QTPROPERTYBROWSER_IMPORT } tiled-1.0.3/src/qtpropertybrowser/src/qtpropertybrowser.qrc000066400000000000000000000016471315121121300243710ustar00rootroot00000000000000 images/cursor-arrow.png images/cursor-busy.png images/cursor-closedhand.png images/cursor-cross.png images/cursor-forbidden.png images/cursor-hand.png images/cursor-hsplit.png images/cursor-ibeam.png images/cursor-openhand.png images/cursor-sizeall.png images/cursor-sizeb.png images/cursor-sizef.png images/cursor-sizeh.png images/cursor-sizev.png images/cursor-uparrow.png images/cursor-vsplit.png images/cursor-wait.png images/cursor-whatsthis.png tiled-1.0.3/src/qtpropertybrowser/src/qtpropertybrowserutils.cpp000066400000000000000000000406141315121121300254440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtpropertybrowserutils_p.h" #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif QtCursorDatabase::QtCursorDatabase() { appendCursor(Qt::ArrowCursor, QCoreApplication::translate("QtCursorDatabase", "Arrow"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-arrow.png"))); appendCursor(Qt::UpArrowCursor, QCoreApplication::translate("QtCursorDatabase", "Up Arrow"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-uparrow.png"))); appendCursor(Qt::CrossCursor, QCoreApplication::translate("QtCursorDatabase", "Cross"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-cross.png"))); appendCursor(Qt::WaitCursor, QCoreApplication::translate("QtCursorDatabase", "Wait"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-wait.png"))); appendCursor(Qt::IBeamCursor, QCoreApplication::translate("QtCursorDatabase", "IBeam"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-ibeam.png"))); appendCursor(Qt::SizeVerCursor, QCoreApplication::translate("QtCursorDatabase", "Size Vertical"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizev.png"))); appendCursor(Qt::SizeHorCursor, QCoreApplication::translate("QtCursorDatabase", "Size Horizontal"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizeh.png"))); appendCursor(Qt::SizeFDiagCursor, QCoreApplication::translate("QtCursorDatabase", "Size Backslash"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizef.png"))); appendCursor(Qt::SizeBDiagCursor, QCoreApplication::translate("QtCursorDatabase", "Size Slash"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizeb.png"))); appendCursor(Qt::SizeAllCursor, QCoreApplication::translate("QtCursorDatabase", "Size All"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizeall.png"))); appendCursor(Qt::BlankCursor, QCoreApplication::translate("QtCursorDatabase", "Blank"), QIcon()); appendCursor(Qt::SplitVCursor, QCoreApplication::translate("QtCursorDatabase", "Split Vertical"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-vsplit.png"))); appendCursor(Qt::SplitHCursor, QCoreApplication::translate("QtCursorDatabase", "Split Horizontal"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-hsplit.png"))); appendCursor(Qt::PointingHandCursor, QCoreApplication::translate("QtCursorDatabase", "Pointing Hand"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-hand.png"))); appendCursor(Qt::ForbiddenCursor, QCoreApplication::translate("QtCursorDatabase", "Forbidden"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-forbidden.png"))); appendCursor(Qt::OpenHandCursor, QCoreApplication::translate("QtCursorDatabase", "Open Hand"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-openhand.png"))); appendCursor(Qt::ClosedHandCursor, QCoreApplication::translate("QtCursorDatabase", "Closed Hand"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-closedhand.png"))); appendCursor(Qt::WhatsThisCursor, QCoreApplication::translate("QtCursorDatabase", "What's This"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-whatsthis.png"))); appendCursor(Qt::BusyCursor, QCoreApplication::translate("QtCursorDatabase", "Busy"), QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-busy.png"))); } void QtCursorDatabase::clear() { m_cursorNames.clear(); m_cursorIcons.clear(); m_valueToCursorShape.clear(); m_cursorShapeToValue.clear(); } void QtCursorDatabase::appendCursor(Qt::CursorShape shape, const QString &name, const QIcon &icon) { if (m_cursorShapeToValue.contains(shape)) return; const int value = m_cursorNames.count(); m_cursorNames.append(name); m_cursorIcons.insert(value, icon); m_valueToCursorShape.insert(value, shape); m_cursorShapeToValue.insert(shape, value); } QStringList QtCursorDatabase::cursorShapeNames() const { return m_cursorNames; } QMap QtCursorDatabase::cursorShapeIcons() const { return m_cursorIcons; } QString QtCursorDatabase::cursorToShapeName(const QCursor &cursor) const { int val = cursorToValue(cursor); if (val >= 0) return m_cursorNames.at(val); return QString(); } QIcon QtCursorDatabase::cursorToShapeIcon(const QCursor &cursor) const { int val = cursorToValue(cursor); return m_cursorIcons.value(val); } int QtCursorDatabase::cursorToValue(const QCursor &cursor) const { #ifndef QT_NO_CURSOR Qt::CursorShape shape = cursor.shape(); if (m_cursorShapeToValue.contains(shape)) return m_cursorShapeToValue[shape]; #endif return -1; } #ifndef QT_NO_CURSOR QCursor QtCursorDatabase::valueToCursor(int value) const { if (m_valueToCursorShape.contains(value)) return QCursor(m_valueToCursorShape[value]); return QCursor(); } #endif QPixmap QtPropertyBrowserUtils::brushValuePixmap(const QBrush &b) { QImage img(16, 16, QImage::Format_ARGB32_Premultiplied); img.fill(0); QPainter painter(&img); painter.setCompositionMode(QPainter::CompositionMode_Source); painter.fillRect(0, 0, img.width(), img.height(), b); QColor color = b.color(); if (color.alpha() != 255) { // indicate alpha by an inset QBrush opaqueBrush = b; color.setAlpha(255); opaqueBrush.setColor(color); painter.fillRect(img.width() / 4, img.height() / 4, img.width() / 2, img.height() / 2, opaqueBrush); } painter.end(); return QPixmap::fromImage(img); } QIcon QtPropertyBrowserUtils::brushValueIcon(const QBrush &b) { return QIcon(brushValuePixmap(b)); } QString QtPropertyBrowserUtils::colorValueText(const QColor &c) { if (c.isValid()) { return QCoreApplication::translate("QtPropertyBrowserUtils", "[%1, %2, %3] (%4)") .arg(c.red()).arg(c.green()).arg(c.blue()).arg(c.alpha()); } else { return QCoreApplication::translate("QtPropertyBrowserUtils", "Not set"); } } QPixmap QtPropertyBrowserUtils::fontValuePixmap(const QFont &font, int size) { QFont f = font; QImage img(size, size, QImage::Format_ARGB32_Premultiplied); img.fill(0); QPainter p(&img); p.setRenderHint(QPainter::TextAntialiasing, true); p.setRenderHint(QPainter::Antialiasing, true); f.setPixelSize(img.height() - 2); p.setFont(f); QTextOption t; t.setAlignment(Qt::AlignCenter); p.drawText(img.rect(), QString(QLatin1Char('A')), t); return QPixmap::fromImage(img); } QIcon QtPropertyBrowserUtils::fontValueIcon(const QFont &f) { QIcon icon(fontValuePixmap(f, 16)); icon.addPixmap(fontValuePixmap(f, 32)); return icon; } QString QtPropertyBrowserUtils::fontValueText(const QFont &f) { int size = f.pointSize(); if (size == -1) size = f.pixelSize(); return QCoreApplication::translate("QtPropertyBrowserUtils", "[%1, %2]") .arg(f.family()).arg(size); } QtBoolEdit::QtBoolEdit(QWidget *parent) : QWidget(parent), m_checkBox(new QCheckBox(this)), m_textVisible(true) { QHBoxLayout *lt = new QHBoxLayout; if (QApplication::layoutDirection() == Qt::LeftToRight) lt->setContentsMargins(4, 0, 0, 0); else lt->setContentsMargins(0, 0, 4, 0); lt->addWidget(m_checkBox); setLayout(lt); connect(m_checkBox, SIGNAL(toggled(bool)), this, SIGNAL(toggled(bool))); setFocusProxy(m_checkBox); m_checkBox->setText(tr("True")); } void QtBoolEdit::setTextVisible(bool textVisible) { if (m_textVisible == textVisible) return; m_textVisible = textVisible; if (m_textVisible) m_checkBox->setText(isChecked() ? tr("True") : tr("False")); else m_checkBox->setText(QString()); } Qt::CheckState QtBoolEdit::checkState() const { return m_checkBox->checkState(); } void QtBoolEdit::setCheckState(Qt::CheckState state) { m_checkBox->setCheckState(state); } bool QtBoolEdit::isChecked() const { return m_checkBox->isChecked(); } void QtBoolEdit::setChecked(bool c) { m_checkBox->setChecked(c); if (!m_textVisible) return; m_checkBox->setText(isChecked() ? tr("True") : tr("False")); } bool QtBoolEdit::blockCheckBoxSignals(bool block) { return m_checkBox->blockSignals(block); } void QtBoolEdit::mousePressEvent(QMouseEvent *event) { if (event->buttons() == Qt::LeftButton) { m_checkBox->click(); event->accept(); } else { QWidget::mousePressEvent(event); } } void QtBoolEdit::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } QtKeySequenceEdit::QtKeySequenceEdit(QWidget *parent) : QWidget(parent), m_num(0), m_lineEdit(new QLineEdit(this)) { QHBoxLayout *layout = new QHBoxLayout(this); layout->addWidget(m_lineEdit); layout->setMargin(0); m_lineEdit->installEventFilter(this); m_lineEdit->setReadOnly(true); m_lineEdit->setFocusProxy(this); setFocusPolicy(m_lineEdit->focusPolicy()); setAttribute(Qt::WA_InputMethodEnabled); } bool QtKeySequenceEdit::eventFilter(QObject *o, QEvent *e) { if (o == m_lineEdit && e->type() == QEvent::ContextMenu) { QContextMenuEvent *c = static_cast(e); QMenu *menu = m_lineEdit->createStandardContextMenu(); const QList actions = menu->actions(); QListIterator itAction(actions); while (itAction.hasNext()) { QAction *action = itAction.next(); action->setShortcut(QKeySequence()); QString actionString = action->text(); const int pos = actionString.lastIndexOf(QLatin1Char('\t')); if (pos > 0) actionString.remove(pos, actionString.length() - pos); action->setText(actionString); } QAction *actionBefore = 0; if (actions.count() > 0) actionBefore = actions[0]; QAction *clearAction = new QAction(tr("Clear Shortcut"), menu); menu->insertAction(actionBefore, clearAction); menu->insertSeparator(actionBefore); clearAction->setEnabled(!m_keySequence.isEmpty()); connect(clearAction, SIGNAL(triggered()), this, SLOT(slotClearShortcut())); menu->exec(c->globalPos()); delete menu; e->accept(); return true; } return QWidget::eventFilter(o, e); } void QtKeySequenceEdit::slotClearShortcut() { if (m_keySequence.isEmpty()) return; setKeySequence(QKeySequence()); emit keySequenceChanged(m_keySequence); } void QtKeySequenceEdit::handleKeyEvent(QKeyEvent *e) { int nextKey = e->key(); if (nextKey == Qt::Key_Control || nextKey == Qt::Key_Shift || nextKey == Qt::Key_Meta || nextKey == Qt::Key_Alt || nextKey == Qt::Key_Super_L || nextKey == Qt::Key_AltGr) return; nextKey |= translateModifiers(e->modifiers(), e->text()); int k0 = m_keySequence[0]; int k1 = m_keySequence[1]; int k2 = m_keySequence[2]; int k3 = m_keySequence[3]; switch (m_num) { case 0: k0 = nextKey; k1 = 0; k2 = 0; k3 = 0; break; case 1: k1 = nextKey; k2 = 0; k3 = 0; break; case 2: k2 = nextKey; k3 = 0; break; case 3: k3 = nextKey; break; default: break; } ++m_num; if (m_num > 3) m_num = 0; m_keySequence = QKeySequence(k0, k1, k2, k3); m_lineEdit->setText(m_keySequence.toString(QKeySequence::NativeText)); e->accept(); emit keySequenceChanged(m_keySequence); } void QtKeySequenceEdit::setKeySequence(const QKeySequence &sequence) { if (sequence == m_keySequence) return; m_num = 0; m_keySequence = sequence; m_lineEdit->setText(m_keySequence.toString(QKeySequence::NativeText)); } QKeySequence QtKeySequenceEdit::keySequence() const { return m_keySequence; } int QtKeySequenceEdit::translateModifiers(Qt::KeyboardModifiers state, const QString &text) const { int result = 0; if ((state & Qt::ShiftModifier) && (text.size() == 0 || !text.at(0).isPrint() || text.at(0).isLetter() || text.at(0).isSpace())) result |= Qt::SHIFT; if (state & Qt::ControlModifier) result |= Qt::CTRL; if (state & Qt::MetaModifier) result |= Qt::META; if (state & Qt::AltModifier) result |= Qt::ALT; return result; } void QtKeySequenceEdit::focusInEvent(QFocusEvent *e) { m_lineEdit->event(e); m_lineEdit->selectAll(); QWidget::focusInEvent(e); } void QtKeySequenceEdit::focusOutEvent(QFocusEvent *e) { m_num = 0; m_lineEdit->event(e); QWidget::focusOutEvent(e); } void QtKeySequenceEdit::keyPressEvent(QKeyEvent *e) { handleKeyEvent(e); e->accept(); } void QtKeySequenceEdit::keyReleaseEvent(QKeyEvent *e) { m_lineEdit->event(e); } void QtKeySequenceEdit::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } bool QtKeySequenceEdit::event(QEvent *e) { if (e->type() == QEvent::Shortcut || e->type() == QEvent::ShortcutOverride || e->type() == QEvent::KeyRelease) { e->accept(); return true; } return QWidget::event(e); } /** * Strips a floating point number representation of redundant trailing zeros. * Examples: * * 0.01000 -> 0.01 * 3.000 -> 3.0 */ QString removeRedundantTrialingZeros(const QString &text) { const QChar decimalPoint = QLocale::system().decimalPoint(); int i = text.length() - 1; int redundantZeros = 0; while (i > 0) { if (text.at(i) == QLatin1Char('0')) { ++redundantZeros; } else { if (text.at(i) == decimalPoint) --redundantZeros; break; } --i; } if (redundantZeros > 0) return text.left(text.length() - redundantZeros); return text; } #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif tiled-1.0.3/src/qtpropertybrowser/src/qtpropertybrowserutils_p.h000066400000000000000000000116701315121121300254300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of Qt Designer. This header // file may change from version to version without notice, or even be removed. // // We mean it. // #ifndef QTPROPERTYBROWSERUTILS_H #define QTPROPERTYBROWSERUTILS_H #include #include #include #include #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif class QMouseEvent; class QCheckBox; class QLineEdit; class QtCursorDatabase { public: QtCursorDatabase(); void clear(); QStringList cursorShapeNames() const; QMap cursorShapeIcons() const; QString cursorToShapeName(const QCursor &cursor) const; QIcon cursorToShapeIcon(const QCursor &cursor) const; int cursorToValue(const QCursor &cursor) const; #ifndef QT_NO_CURSOR QCursor valueToCursor(int value) const; #endif private: void appendCursor(Qt::CursorShape shape, const QString &name, const QIcon &icon); QStringList m_cursorNames; QMap m_cursorIcons; QMap m_valueToCursorShape; QMap m_cursorShapeToValue; }; class QtPropertyBrowserUtils { public: static QPixmap brushValuePixmap(const QBrush &b); static QIcon brushValueIcon(const QBrush &b); static QString colorValueText(const QColor &c); static QPixmap fontValuePixmap(const QFont &f, int size = 16); static QIcon fontValueIcon(const QFont &f); static QString fontValueText(const QFont &f); }; class QtBoolEdit : public QWidget { Q_OBJECT public: QtBoolEdit(QWidget *parent = 0); bool textVisible() const { return m_textVisible; } void setTextVisible(bool textVisible); Qt::CheckState checkState() const; void setCheckState(Qt::CheckState state); bool isChecked() const; void setChecked(bool c); bool blockCheckBoxSignals(bool block); Q_SIGNALS: void toggled(bool); protected: void mousePressEvent(QMouseEvent * event); void paintEvent(QPaintEvent *); private: QCheckBox *m_checkBox; bool m_textVisible; }; class QtKeySequenceEdit : public QWidget { Q_OBJECT public: QtKeySequenceEdit(QWidget *parent = 0); QKeySequence keySequence() const; bool eventFilter(QObject *o, QEvent *e); public Q_SLOTS: void setKeySequence(const QKeySequence &sequence); Q_SIGNALS: void keySequenceChanged(const QKeySequence &sequence); protected: void focusInEvent(QFocusEvent *e); void focusOutEvent(QFocusEvent *e); void keyPressEvent(QKeyEvent *e); void keyReleaseEvent(QKeyEvent *e); void paintEvent(QPaintEvent *); bool event(QEvent *e); private slots: void slotClearShortcut(); private: void handleKeyEvent(QKeyEvent *e); int translateModifiers(Qt::KeyboardModifiers state, const QString &text) const; int m_num; QKeySequence m_keySequence; QLineEdit *m_lineEdit; }; QString removeRedundantTrialingZeros(const QString &text); #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif #endif tiled-1.0.3/src/qtpropertybrowser/src/qtpropertymanager.cpp000066400000000000000000006467001315121121300243220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtpropertymanager.h" #include "qtpropertybrowserutils_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(Q_CC_MSVC) # pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */ #endif #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif template static void setSimpleMinimumData(PrivateData *data, const Value &minVal) { data->minVal = minVal; if (data->maxVal < data->minVal) data->maxVal = data->minVal; if (data->val < data->minVal) data->val = data->minVal; } template static void setSimpleMaximumData(PrivateData *data, const Value &maxVal) { data->maxVal = maxVal; if (data->minVal > data->maxVal) data->minVal = data->maxVal; if (data->val > data->maxVal) data->val = data->maxVal; } template static void setSizeMinimumData(PrivateData *data, const Value &newMinVal) { data->minVal = newMinVal; if (data->maxVal.width() < data->minVal.width()) data->maxVal.setWidth(data->minVal.width()); if (data->maxVal.height() < data->minVal.height()) data->maxVal.setHeight(data->minVal.height()); if (data->val.width() < data->minVal.width()) data->val.setWidth(data->minVal.width()); if (data->val.height() < data->minVal.height()) data->val.setHeight(data->minVal.height()); } template static void setSizeMaximumData(PrivateData *data, const Value &newMaxVal) { data->maxVal = newMaxVal; if (data->minVal.width() > data->maxVal.width()) data->minVal.setWidth(data->maxVal.width()); if (data->minVal.height() > data->maxVal.height()) data->minVal.setHeight(data->maxVal.height()); if (data->val.width() > data->maxVal.width()) data->val.setWidth(data->maxVal.width()); if (data->val.height() > data->maxVal.height()) data->val.setHeight(data->maxVal.height()); } template static SizeValue qBoundSize(const SizeValue &minVal, const SizeValue &val, const SizeValue &maxVal) { SizeValue croppedVal = val; if (minVal.width() > val.width()) croppedVal.setWidth(minVal.width()); else if (maxVal.width() < val.width()) croppedVal.setWidth(maxVal.width()); if (minVal.height() > val.height()) croppedVal.setHeight(minVal.height()); else if (maxVal.height() < val.height()) croppedVal.setHeight(maxVal.height()); return croppedVal; } // Match the exact signature of qBound for VS 6. QSize qBound(QSize minVal, QSize val, QSize maxVal) { return qBoundSize(minVal, val, maxVal); } QSizeF qBound(QSizeF minVal, QSizeF val, QSizeF maxVal) { return qBoundSize(minVal, val, maxVal); } namespace { namespace { template void orderBorders(Value &minVal, Value &maxVal) { if (minVal > maxVal) qSwap(minVal, maxVal); } template static void orderSizeBorders(Value &minVal, Value &maxVal) { Value fromSize = minVal; Value toSize = maxVal; if (fromSize.width() > toSize.width()) { fromSize.setWidth(maxVal.width()); toSize.setWidth(minVal.width()); } if (fromSize.height() > toSize.height()) { fromSize.setHeight(maxVal.height()); toSize.setHeight(minVal.height()); } minVal = fromSize; maxVal = toSize; } void orderBorders(QSize &minVal, QSize &maxVal) { orderSizeBorders(minVal, maxVal); } void orderBorders(QSizeF &minVal, QSizeF &maxVal) { orderSizeBorders(minVal, maxVal); } } } //////// template static Value getData(const QMap &propertyMap, Value PrivateData::*data, const QtProperty *property, const Value &defaultValue = Value()) { typedef QMap PropertyToData; typedef typename PropertyToData::const_iterator PropertyToDataConstIterator; const PropertyToDataConstIterator it = propertyMap.constFind(property); if (it == propertyMap.constEnd()) return defaultValue; return it.value().*data; } template static Value getValue(const QMap &propertyMap, const QtProperty *property, const Value &defaultValue = Value()) { return getData(propertyMap, &PrivateData::val, property, defaultValue); } template static Value getMinimum(const QMap &propertyMap, const QtProperty *property, const Value &defaultValue = Value()) { return getData(propertyMap, &PrivateData::minVal, property, defaultValue); } template static Value getMaximum(const QMap &propertyMap, const QtProperty *property, const Value &defaultValue = Value()) { return getData(propertyMap, &PrivateData::maxVal, property, defaultValue); } template static void setSimpleValue(QMap &propertyMap, PropertyManager *manager, void (PropertyManager::*propertyChangedSignal)(QtProperty *), void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), QtProperty *property, const Value &val) { typedef QMap PropertyToData; typedef typename PropertyToData::iterator PropertyToDataIterator; const PropertyToDataIterator it = propertyMap.find(property); if (it == propertyMap.end()) return; if (it.value() == val) return; it.value() = val; emit (manager->*propertyChangedSignal)(property); emit (manager->*valueChangedSignal)(property, val); } template static void setValueInRange(PropertyManager *manager, PropertyManagerPrivate *managerPrivate, void (PropertyManager::*propertyChangedSignal)(QtProperty *), void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), QtProperty *property, const Value &val, void (PropertyManagerPrivate::*setSubPropertyValue)(QtProperty *, ValueChangeParameter)) { typedef typename PropertyManagerPrivate::Data PrivateData; typedef QMap PropertyToData; typedef typename PropertyToData::iterator PropertyToDataIterator; const PropertyToDataIterator it = managerPrivate->m_values.find(property); if (it == managerPrivate->m_values.end()) return; PrivateData &data = it.value(); if (data.val == val) return; const Value oldVal = data.val; data.val = qBound(data.minVal, val, data.maxVal); if (data.val == oldVal) return; if (setSubPropertyValue) (managerPrivate->*setSubPropertyValue)(property, data.val); emit (manager->*propertyChangedSignal)(property); emit (manager->*valueChangedSignal)(property, data.val); } template static void setBorderValues(PropertyManager *manager, PropertyManagerPrivate *managerPrivate, void (PropertyManager::*propertyChangedSignal)(QtProperty *), void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), void (PropertyManager::*rangeChangedSignal)(QtProperty *, ValueChangeParameter, ValueChangeParameter), QtProperty *property, const Value &minVal, const Value &maxVal, void (PropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, ValueChangeParameter, ValueChangeParameter, ValueChangeParameter)) { typedef typename PropertyManagerPrivate::Data PrivateData; typedef QMap PropertyToData; typedef typename PropertyToData::iterator PropertyToDataIterator; const PropertyToDataIterator it = managerPrivate->m_values.find(property); if (it == managerPrivate->m_values.end()) return; Value fromVal = minVal; Value toVal = maxVal; orderBorders(fromVal, toVal); PrivateData &data = it.value(); if (data.minVal == fromVal && data.maxVal == toVal) return; const Value oldVal = data.val; data.setMinimumValue(fromVal); data.setMaximumValue(toVal); emit (manager->*rangeChangedSignal)(property, data.minVal, data.maxVal); if (setSubPropertyRange) (managerPrivate->*setSubPropertyRange)(property, data.minVal, data.maxVal, data.val); if (data.val == oldVal) return; emit (manager->*propertyChangedSignal)(property); emit (manager->*valueChangedSignal)(property, data.val); } template static void setBorderValue(PropertyManager *manager, PropertyManagerPrivate *managerPrivate, void (PropertyManager::*propertyChangedSignal)(QtProperty *), void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), void (PropertyManager::*rangeChangedSignal)(QtProperty *, ValueChangeParameter, ValueChangeParameter), QtProperty *property, Value (PrivateData::*getRangeVal)() const, void (PrivateData::*setRangeVal)(ValueChangeParameter), const Value &borderVal, void (PropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, ValueChangeParameter, ValueChangeParameter, ValueChangeParameter)) { typedef QMap PropertyToData; typedef typename PropertyToData::iterator PropertyToDataIterator; const PropertyToDataIterator it = managerPrivate->m_values.find(property); if (it == managerPrivate->m_values.end()) return; PrivateData &data = it.value(); if ((data.*getRangeVal)() == borderVal) return; const Value oldVal = data.val; (data.*setRangeVal)(borderVal); emit (manager->*rangeChangedSignal)(property, data.minVal, data.maxVal); if (setSubPropertyRange) (managerPrivate->*setSubPropertyRange)(property, data.minVal, data.maxVal, data.val); if (data.val == oldVal) return; emit (manager->*propertyChangedSignal)(property); emit (manager->*valueChangedSignal)(property, data.val); } template static void setMinimumValue(PropertyManager *manager, PropertyManagerPrivate *managerPrivate, void (PropertyManager::*propertyChangedSignal)(QtProperty *), void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), void (PropertyManager::*rangeChangedSignal)(QtProperty *, ValueChangeParameter, ValueChangeParameter), QtProperty *property, const Value &minVal) { void (PropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, ValueChangeParameter, ValueChangeParameter, ValueChangeParameter) = 0; setBorderValue(manager, managerPrivate, propertyChangedSignal, valueChangedSignal, rangeChangedSignal, property, &PropertyManagerPrivate::Data::minimumValue, &PropertyManagerPrivate::Data::setMinimumValue, minVal, setSubPropertyRange); } template static void setMaximumValue(PropertyManager *manager, PropertyManagerPrivate *managerPrivate, void (PropertyManager::*propertyChangedSignal)(QtProperty *), void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), void (PropertyManager::*rangeChangedSignal)(QtProperty *, ValueChangeParameter, ValueChangeParameter), QtProperty *property, const Value &maxVal) { void (PropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, ValueChangeParameter, ValueChangeParameter, ValueChangeParameter) = 0; setBorderValue(manager, managerPrivate, propertyChangedSignal, valueChangedSignal, rangeChangedSignal, property, &PropertyManagerPrivate::Data::maximumValue, &PropertyManagerPrivate::Data::setMaximumValue, maxVal, setSubPropertyRange); } class QtMetaEnumWrapper : public QObject { Q_OBJECT Q_PROPERTY(QSizePolicy::Policy policy READ policy) public: QSizePolicy::Policy policy() const { return QSizePolicy::Ignored; } private: QtMetaEnumWrapper(QObject *parent) : QObject(parent) {} }; class QtMetaEnumProvider { public: QtMetaEnumProvider(); QStringList policyEnumNames() const { return m_policyEnumNames; } QStringList languageEnumNames() const { return m_languageEnumNames; } QStringList countryEnumNames(QLocale::Language language) const { return m_countryEnumNames.value(language); } QSizePolicy::Policy indexToSizePolicy(int index) const; int sizePolicyToIndex(QSizePolicy::Policy policy) const; void indexToLocale(int languageIndex, int countryIndex, QLocale::Language *language, QLocale::Country *country) const; void localeToIndex(QLocale::Language language, QLocale::Country country, int *languageIndex, int *countryIndex) const; private: void initLocale(); QStringList m_policyEnumNames; QStringList m_languageEnumNames; QMap m_countryEnumNames; QMap m_indexToLanguage; QMap m_languageToIndex; QMap > m_indexToCountry; QMap > m_countryToIndex; QMetaEnum m_policyEnum; }; #if QT_VERSION < 0x040300 static QList countriesForLanguage(QLocale::Language language) { QList countries; QLocale::Country country = QLocale::AnyCountry; while (country <= QLocale::LastCountry) { QLocale locale(language, country); if (locale.language() == language && !countries.contains(locale.country())) countries << locale.country(); country = (QLocale::Country)((uint)country + 1); // ++country } return countries; } #endif static QList sortCountries(const QList &countries) { QMultiMap nameToCountry; QListIterator itCountry(countries); while (itCountry.hasNext()) { QLocale::Country country = itCountry.next(); nameToCountry.insert(QLocale::countryToString(country), country); } return nameToCountry.values(); } void QtMetaEnumProvider::initLocale() { QMultiMap nameToLanguage; QLocale::Language language = QLocale::C; while (language <= QLocale::LastLanguage) { QLocale locale(language); if (locale.language() == language) nameToLanguage.insert(QLocale::languageToString(language), language); language = (QLocale::Language)((uint)language + 1); // ++language } const QLocale system = QLocale::system(); if (!nameToLanguage.contains(QLocale::languageToString(system.language()))) nameToLanguage.insert(QLocale::languageToString(system.language()), system.language()); QList languages = nameToLanguage.values(); QListIterator itLang(languages); while (itLang.hasNext()) { QLocale::Language language = itLang.next(); QList countries; #if QT_VERSION < 0x040300 countries = countriesForLanguage(language); #else countries = QLocale::countriesForLanguage(language); #endif if (countries.isEmpty() && language == system.language()) countries << system.country(); if (!countries.isEmpty() && !m_languageToIndex.contains(language)) { countries = sortCountries(countries); int langIdx = m_languageEnumNames.count(); m_indexToLanguage[langIdx] = language; m_languageToIndex[language] = langIdx; QStringList countryNames; QListIterator it(countries); int countryIdx = 0; while (it.hasNext()) { QLocale::Country country = it.next(); countryNames << QLocale::countryToString(country); m_indexToCountry[langIdx][countryIdx] = country; m_countryToIndex[language][country] = countryIdx; ++countryIdx; } m_languageEnumNames << QLocale::languageToString(language); m_countryEnumNames[language] = countryNames; } } } QtMetaEnumProvider::QtMetaEnumProvider() { QMetaProperty p; p = QtMetaEnumWrapper::staticMetaObject.property( QtMetaEnumWrapper::staticMetaObject.propertyOffset() + 0); m_policyEnum = p.enumerator(); const int keyCount = m_policyEnum.keyCount(); for (int i = 0; i < keyCount; i++) m_policyEnumNames << QLatin1String(m_policyEnum.key(i)); initLocale(); } QSizePolicy::Policy QtMetaEnumProvider::indexToSizePolicy(int index) const { return static_cast(m_policyEnum.value(index)); } int QtMetaEnumProvider::sizePolicyToIndex(QSizePolicy::Policy policy) const { const int keyCount = m_policyEnum.keyCount(); for (int i = 0; i < keyCount; i++) if (indexToSizePolicy(i) == policy) return i; return -1; } void QtMetaEnumProvider::indexToLocale(int languageIndex, int countryIndex, QLocale::Language *language, QLocale::Country *country) const { QLocale::Language l = QLocale::C; QLocale::Country c = QLocale::AnyCountry; if (m_indexToLanguage.contains(languageIndex)) { l = m_indexToLanguage[languageIndex]; if (m_indexToCountry.contains(languageIndex) && m_indexToCountry[languageIndex].contains(countryIndex)) c = m_indexToCountry[languageIndex][countryIndex]; } if (language) *language = l; if (country) *country = c; } void QtMetaEnumProvider::localeToIndex(QLocale::Language language, QLocale::Country country, int *languageIndex, int *countryIndex) const { int l = -1; int c = -1; if (m_languageToIndex.contains(language)) { l = m_languageToIndex[language]; if (m_countryToIndex.contains(language) && m_countryToIndex[language].contains(country)) c = m_countryToIndex[language][country]; } if (languageIndex) *languageIndex = l; if (countryIndex) *countryIndex = c; } Q_GLOBAL_STATIC(QtMetaEnumProvider, metaEnumProvider) // QtGroupPropertyManager /*! \class QtGroupPropertyManager \brief The QtGroupPropertyManager provides and manages group properties. This class is intended to provide a grouping element without any value. \sa QtAbstractPropertyManager */ /*! Creates a manager with the given \a parent. */ QtGroupPropertyManager::QtGroupPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { } /*! Destroys this manager, and all the properties it has created. */ QtGroupPropertyManager::~QtGroupPropertyManager() { } /*! \reimp */ bool QtGroupPropertyManager::hasValue(const QtProperty *property) const { Q_UNUSED(property) return false; } /*! \reimp */ void QtGroupPropertyManager::initializeProperty(QtProperty *property) { Q_UNUSED(property) } /*! \reimp */ void QtGroupPropertyManager::uninitializeProperty(QtProperty *property) { Q_UNUSED(property) } // QtIntPropertyManager class QtIntPropertyManagerPrivate { QtIntPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtIntPropertyManager) public: struct Data { Data() : val(0), minVal(-INT_MAX), maxVal(INT_MAX), singleStep(1), readOnly(false) {} int val; int minVal; int maxVal; int singleStep; bool readOnly; int minimumValue() const { return minVal; } int maximumValue() const { return maxVal; } void setMinimumValue(int newMinVal) { setSimpleMinimumData(this, newMinVal); } void setMaximumValue(int newMaxVal) { setSimpleMaximumData(this, newMaxVal); } }; typedef QMap PropertyValueMap; PropertyValueMap m_values; }; /*! \class QtIntPropertyManager \brief The QtIntPropertyManager provides and manages int properties. An int property has a current value, and a range specifying the valid values. The range is defined by a minimum and a maximum value. The property's value and range can be retrieved using the value(), minimum() and maximum() functions, and can be set using the setValue(), setMinimum() and setMaximum() slots. Alternatively, the range can be defined in one go using the setRange() slot. In addition, QtIntPropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes, and the rangeChanged() signal which is emitted whenever such a property changes its range of valid values. \sa QtAbstractPropertyManager, QtSpinBoxFactory, QtSliderFactory, QtScrollBarFactory */ /*! \fn void QtIntPropertyManager::valueChanged(QtProperty *property, int value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! \fn void QtIntPropertyManager::rangeChanged(QtProperty *property, int minimum, int maximum) This signal is emitted whenever a property created by this manager changes its range of valid values, passing a pointer to the \a property and the new \a minimum and \a maximum values. \sa setRange() */ /*! \fn void QtIntPropertyManager::singleStepChanged(QtProperty *property, int step) This signal is emitted whenever a property created by this manager changes its single step property, passing a pointer to the \a property and the new \a step value \sa setSingleStep() */ /*! Creates a manager with the given \a parent. */ QtIntPropertyManager::QtIntPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtIntPropertyManagerPrivate; d_ptr->q_ptr = this; } /*! Destroys this manager, and all the properties it has created. */ QtIntPropertyManager::~QtIntPropertyManager() { clear(); delete d_ptr; } /*! Returns the given \a property's value. If the given property is not managed by this manager, this function returns 0. \sa setValue() */ int QtIntPropertyManager::value(const QtProperty *property) const { return getValue(d_ptr->m_values, property, 0); } /*! Returns the given \a property's minimum value. \sa setMinimum(), maximum(), setRange() */ int QtIntPropertyManager::minimum(const QtProperty *property) const { return getMinimum(d_ptr->m_values, property, 0); } /*! Returns the given \a property's maximum value. \sa setMaximum(), minimum(), setRange() */ int QtIntPropertyManager::maximum(const QtProperty *property) const { return getMaximum(d_ptr->m_values, property, 0); } /*! Returns the given \a property's step value. The step is typically used to increment or decrement a property value while pressing an arrow key. \sa setSingleStep() */ int QtIntPropertyManager::singleStep(const QtProperty *property) const { return getData(d_ptr->m_values, &QtIntPropertyManagerPrivate::Data::singleStep, property, 0); } /*! Returns read-only status of the property. When property is read-only it's value can be selected and copied from editor but not modified. \sa QtIntPropertyManager::setReadOnly */ bool QtIntPropertyManager::isReadOnly(const QtProperty *property) const { return getData(d_ptr->m_values, &QtIntPropertyManagerPrivate::Data::readOnly, property, false); } /*! \reimp */ QString QtIntPropertyManager::valueText(const QtProperty *property) const { const QtIntPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); return QString::number(it.value().val); } /*! \fn void QtIntPropertyManager::setValue(QtProperty *property, int value) Sets the value of the given \a property to \a value. If the specified \a value is not valid according to the given \a property's range, the \a value is adjusted to the nearest valid value within the range. \sa value(), setRange(), valueChanged() */ void QtIntPropertyManager::setValue(QtProperty *property, int val) { void (QtIntPropertyManagerPrivate::*setSubPropertyValue)(QtProperty *, int) = 0; setValueInRange(this, d_ptr, &QtIntPropertyManager::propertyChanged, &QtIntPropertyManager::valueChanged, property, val, setSubPropertyValue); } /*! Sets the minimum value for the given \a property to \a minVal. When setting the minimum value, the maximum and current values are adjusted if necessary (ensuring that the range remains valid and that the current value is within the range). \sa minimum(), setRange(), rangeChanged() */ void QtIntPropertyManager::setMinimum(QtProperty *property, int minVal) { setMinimumValue(this, d_ptr, &QtIntPropertyManager::propertyChanged, &QtIntPropertyManager::valueChanged, &QtIntPropertyManager::rangeChanged, property, minVal); } /*! Sets the maximum value for the given \a property to \a maxVal. When setting maximum value, the minimum and current values are adjusted if necessary (ensuring that the range remains valid and that the current value is within the range). \sa maximum(), setRange(), rangeChanged() */ void QtIntPropertyManager::setMaximum(QtProperty *property, int maxVal) { setMaximumValue(this, d_ptr, &QtIntPropertyManager::propertyChanged, &QtIntPropertyManager::valueChanged, &QtIntPropertyManager::rangeChanged, property, maxVal); } /*! \fn void QtIntPropertyManager::setRange(QtProperty *property, int minimum, int maximum) Sets the range of valid values. This is a convenience function defining the range of valid values in one go; setting the \a minimum and \a maximum values for the given \a property with a single function call. When setting a new range, the current value is adjusted if necessary (ensuring that the value remains within range). \sa setMinimum(), setMaximum(), rangeChanged() */ void QtIntPropertyManager::setRange(QtProperty *property, int minVal, int maxVal) { void (QtIntPropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, int, int, int) = 0; setBorderValues(this, d_ptr, &QtIntPropertyManager::propertyChanged, &QtIntPropertyManager::valueChanged, &QtIntPropertyManager::rangeChanged, property, minVal, maxVal, setSubPropertyRange); } /*! Sets the step value for the given \a property to \a step. The step is typically used to increment or decrement a property value while pressing an arrow key. \sa singleStep() */ void QtIntPropertyManager::setSingleStep(QtProperty *property, int step) { const QtIntPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtIntPropertyManagerPrivate::Data data = it.value(); if (step < 0) step = 0; if (data.singleStep == step) return; data.singleStep = step; it.value() = data; emit singleStepChanged(property, data.singleStep); } /*! Sets read-only status of the property. \sa QtIntPropertyManager::setReadOnly */ void QtIntPropertyManager::setReadOnly(QtProperty *property, bool readOnly) { const QtIntPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtIntPropertyManagerPrivate::Data data = it.value(); if (data.readOnly == readOnly) return; data.readOnly = readOnly; it.value() = data; emit propertyChanged(property); emit readOnlyChanged(property, data.readOnly); } /*! \reimp */ void QtIntPropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QtIntPropertyManagerPrivate::Data(); } /*! \reimp */ void QtIntPropertyManager::uninitializeProperty(QtProperty *property) { d_ptr->m_values.remove(property); } // QtDoublePropertyManager class QtDoublePropertyManagerPrivate { QtDoublePropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtDoublePropertyManager) public: struct Data { Data() : val(0), minVal(-INT_MAX), maxVal(INT_MAX), singleStep(1), decimals(2), readOnly(false) {} double val; double minVal; double maxVal; double singleStep; int decimals; bool readOnly; double minimumValue() const { return minVal; } double maximumValue() const { return maxVal; } void setMinimumValue(double newMinVal) { setSimpleMinimumData(this, newMinVal); } void setMaximumValue(double newMaxVal) { setSimpleMaximumData(this, newMaxVal); } }; typedef QMap PropertyValueMap; PropertyValueMap m_values; }; /*! \class QtDoublePropertyManager \brief The QtDoublePropertyManager provides and manages double properties. A double property has a current value, and a range specifying the valid values. The range is defined by a minimum and a maximum value. The property's value and range can be retrieved using the value(), minimum() and maximum() functions, and can be set using the setValue(), setMinimum() and setMaximum() slots. Alternatively, the range can be defined in one go using the setRange() slot. In addition, QtDoublePropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes, and the rangeChanged() signal which is emitted whenever such a property changes its range of valid values. \sa QtAbstractPropertyManager, QtDoubleSpinBoxFactory */ /*! \fn void QtDoublePropertyManager::valueChanged(QtProperty *property, double value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! \fn void QtDoublePropertyManager::rangeChanged(QtProperty *property, double minimum, double maximum) This signal is emitted whenever a property created by this manager changes its range of valid values, passing a pointer to the \a property and the new \a minimum and \a maximum values \sa setRange() */ /*! \fn void QtDoublePropertyManager::decimalsChanged(QtProperty *property, int prec) This signal is emitted whenever a property created by this manager changes its precision of value, passing a pointer to the \a property and the new \a prec value \sa setDecimals() */ /*! \fn void QtDoublePropertyManager::singleStepChanged(QtProperty *property, double step) This signal is emitted whenever a property created by this manager changes its single step property, passing a pointer to the \a property and the new \a step value \sa setSingleStep() */ /*! Creates a manager with the given \a parent. */ QtDoublePropertyManager::QtDoublePropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtDoublePropertyManagerPrivate; d_ptr->q_ptr = this; } /*! Destroys this manager, and all the properties it has created. */ QtDoublePropertyManager::~QtDoublePropertyManager() { clear(); delete d_ptr; } /*! Returns the given \a property's value. If the given property is not managed by this manager, this function returns 0. \sa setValue() */ double QtDoublePropertyManager::value(const QtProperty *property) const { return getValue(d_ptr->m_values, property, 0.0); } /*! Returns the given \a property's minimum value. \sa maximum(), setRange() */ double QtDoublePropertyManager::minimum(const QtProperty *property) const { return getMinimum(d_ptr->m_values, property, 0.0); } /*! Returns the given \a property's maximum value. \sa minimum(), setRange() */ double QtDoublePropertyManager::maximum(const QtProperty *property) const { return getMaximum(d_ptr->m_values, property, 0.0); } /*! Returns the given \a property's step value. The step is typically used to increment or decrement a property value while pressing an arrow key. \sa setSingleStep() */ double QtDoublePropertyManager::singleStep(const QtProperty *property) const { return getData(d_ptr->m_values, &QtDoublePropertyManagerPrivate::Data::singleStep, property, 0); } /*! Returns the given \a property's precision, in decimals. \sa setDecimals() */ int QtDoublePropertyManager::decimals(const QtProperty *property) const { return getData(d_ptr->m_values, &QtDoublePropertyManagerPrivate::Data::decimals, property, 0); } /*! Returns read-only status of the property. When property is read-only it's value can be selected and copied from editor but not modified. \sa QtDoublePropertyManager::setReadOnly */ bool QtDoublePropertyManager::isReadOnly(const QtProperty *property) const { return getData(d_ptr->m_values, &QtDoublePropertyManagerPrivate::Data::readOnly, property, false); } /*! \reimp */ QString QtDoublePropertyManager::valueText(const QtProperty *property) const { const QtDoublePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); const int decimals = it.value().decimals; const QString text = QLocale::system().toString(it.value().val, 'f', decimals); // remove redundant trailing 0's in case of high precision if (decimals > 3) return removeRedundantTrialingZeros(text); return text; } /*! \fn void QtDoublePropertyManager::setValue(QtProperty *property, double value) Sets the value of the given \a property to \a value. If the specified \a value is not valid according to the given \a property's range, the \a value is adjusted to the nearest valid value within the range. \sa value(), setRange(), valueChanged() */ void QtDoublePropertyManager::setValue(QtProperty *property, double val) { void (QtDoublePropertyManagerPrivate::*setSubPropertyValue)(QtProperty *, double) = 0; setValueInRange(this, d_ptr, &QtDoublePropertyManager::propertyChanged, &QtDoublePropertyManager::valueChanged, property, val, setSubPropertyValue); } /*! Sets the step value for the given \a property to \a step. The step is typically used to increment or decrement a property value while pressing an arrow key. \sa singleStep() */ void QtDoublePropertyManager::setSingleStep(QtProperty *property, double step) { const QtDoublePropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtDoublePropertyManagerPrivate::Data data = it.value(); if (step < 0) step = 0; if (data.singleStep == step) return; data.singleStep = step; it.value() = data; emit singleStepChanged(property, data.singleStep); } /*! Sets read-only status of the property. \sa QtDoublePropertyManager::setReadOnly */ void QtDoublePropertyManager::setReadOnly(QtProperty *property, bool readOnly) { const QtDoublePropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtDoublePropertyManagerPrivate::Data data = it.value(); if (data.readOnly == readOnly) return; data.readOnly = readOnly; it.value() = data; emit propertyChanged(property); emit readOnlyChanged(property, data.readOnly); } /*! \fn void QtDoublePropertyManager::setDecimals(QtProperty *property, int prec) Sets the precision of the given \a property to \a prec. The valid decimal range is 0-13. The default is 2. \sa decimals() */ void QtDoublePropertyManager::setDecimals(QtProperty *property, int prec) { const QtDoublePropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtDoublePropertyManagerPrivate::Data data = it.value(); if (prec > 13) prec = 13; else if (prec < 0) prec = 0; if (data.decimals == prec) return; data.decimals = prec; it.value() = data; emit decimalsChanged(property, data.decimals); } /*! Sets the minimum value for the given \a property to \a minVal. When setting the minimum value, the maximum and current values are adjusted if necessary (ensuring that the range remains valid and that the current value is within in the range). \sa minimum(), setRange(), rangeChanged() */ void QtDoublePropertyManager::setMinimum(QtProperty *property, double minVal) { setMinimumValue(this, d_ptr, &QtDoublePropertyManager::propertyChanged, &QtDoublePropertyManager::valueChanged, &QtDoublePropertyManager::rangeChanged, property, minVal); } /*! Sets the maximum value for the given \a property to \a maxVal. When setting the maximum value, the minimum and current values are adjusted if necessary (ensuring that the range remains valid and that the current value is within in the range). \sa maximum(), setRange(), rangeChanged() */ void QtDoublePropertyManager::setMaximum(QtProperty *property, double maxVal) { setMaximumValue(this, d_ptr, &QtDoublePropertyManager::propertyChanged, &QtDoublePropertyManager::valueChanged, &QtDoublePropertyManager::rangeChanged, property, maxVal); } /*! \fn void QtDoublePropertyManager::setRange(QtProperty *property, double minimum, double maximum) Sets the range of valid values. This is a convenience function defining the range of valid values in one go; setting the \a minimum and \a maximum values for the given \a property with a single function call. When setting a new range, the current value is adjusted if necessary (ensuring that the value remains within range). \sa setMinimum(), setMaximum(), rangeChanged() */ void QtDoublePropertyManager::setRange(QtProperty *property, double minVal, double maxVal) { void (QtDoublePropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, double, double, double) = 0; setBorderValues(this, d_ptr, &QtDoublePropertyManager::propertyChanged, &QtDoublePropertyManager::valueChanged, &QtDoublePropertyManager::rangeChanged, property, minVal, maxVal, setSubPropertyRange); } /*! \reimp */ void QtDoublePropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QtDoublePropertyManagerPrivate::Data(); } /*! \reimp */ void QtDoublePropertyManager::uninitializeProperty(QtProperty *property) { d_ptr->m_values.remove(property); } // QtStringPropertyManager class QtStringPropertyManagerPrivate { QtStringPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtStringPropertyManager) public: struct Data { Data() : regExp(QString(QLatin1Char('*')), Qt::CaseSensitive, QRegExp::Wildcard), echoMode(QLineEdit::Normal), readOnly(false) { } QString val; QRegExp regExp; int echoMode; bool readOnly; }; typedef QMap PropertyValueMap; QMap m_values; }; /*! \class QtStringPropertyManager \brief The QtStringPropertyManager provides and manages QString properties. A string property's value can be retrieved using the value() function, and set using the setValue() slot. The current value can be checked against a regular expression. To set the regular expression use the setRegExp() slot, use the regExp() function to retrieve the currently set expression. In addition, QtStringPropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes, and the regExpChanged() signal which is emitted whenever such a property changes its currently set regular expression. \sa QtAbstractPropertyManager, QtLineEditFactory */ /*! \fn void QtStringPropertyManager::valueChanged(QtProperty *property, const QString &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! \fn void QtStringPropertyManager::regExpChanged(QtProperty *property, const QRegExp ®Exp) This signal is emitted whenever a property created by this manager changes its currenlty set regular expression, passing a pointer to the \a property and the new \a regExp as parameters. \sa setRegExp() */ /*! Creates a manager with the given \a parent. */ QtStringPropertyManager::QtStringPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtStringPropertyManagerPrivate; d_ptr->q_ptr = this; } /*! Destroys this manager, and all the properties it has created. */ QtStringPropertyManager::~QtStringPropertyManager() { clear(); delete d_ptr; } /*! Returns the given \a property's value. If the given property is not managed by this manager, this function returns an empty string. \sa setValue() */ QString QtStringPropertyManager::value(const QtProperty *property) const { return getValue(d_ptr->m_values, property); } /*! Returns the given \a property's currently set regular expression. If the given \a property is not managed by this manager, this function returns an empty expression. \sa setRegExp() */ QRegExp QtStringPropertyManager::regExp(const QtProperty *property) const { return getData(d_ptr->m_values, &QtStringPropertyManagerPrivate::Data::regExp, property, QRegExp()); } /*! \reimp */ EchoMode QtStringPropertyManager::echoMode(const QtProperty *property) const { return (EchoMode)getData(d_ptr->m_values, &QtStringPropertyManagerPrivate::Data::echoMode, property, 0); } /*! Returns read-only status of the property. When property is read-only it's value can be selected and copied from editor but not modified. \sa QtStringPropertyManager::setReadOnly */ bool QtStringPropertyManager::isReadOnly(const QtProperty *property) const { return getData(d_ptr->m_values, &QtStringPropertyManagerPrivate::Data::readOnly, property, false); } /*! \reimp */ QString QtStringPropertyManager::valueText(const QtProperty *property) const { const QtStringPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); return it.value().val; } /*! \reimp */ QString QtStringPropertyManager::displayText(const QtProperty *property) const { const QtStringPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); QLineEdit edit; edit.setEchoMode((EchoMode)it.value().echoMode); edit.setText(it.value().val); return edit.displayText(); } /*! \fn void QtStringPropertyManager::setValue(QtProperty *property, const QString &value) Sets the value of the given \a property to \a value. If the specified \a value doesn't match the given \a property's regular expression, this function does nothing. \sa value(), setRegExp(), valueChanged() */ void QtStringPropertyManager::setValue(QtProperty *property, const QString &val) { const QtStringPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtStringPropertyManagerPrivate::Data data = it.value(); if (data.val == val) return; if (data.regExp.isValid() && !data.regExp.exactMatch(val)) return; data.val = val; it.value() = data; emit propertyChanged(property); emit valueChanged(property, data.val); } /*! Sets the regular expression of the given \a property to \a regExp. \sa regExp(), setValue(), regExpChanged() */ void QtStringPropertyManager::setRegExp(QtProperty *property, const QRegExp ®Exp) { const QtStringPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtStringPropertyManagerPrivate::Data data = it.value() ; if (data.regExp == regExp) return; data.regExp = regExp; it.value() = data; emit regExpChanged(property, data.regExp); } void QtStringPropertyManager::setEchoMode(QtProperty *property, EchoMode echoMode) { const QtStringPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtStringPropertyManagerPrivate::Data data = it.value(); if (data.echoMode == echoMode) return; data.echoMode = echoMode; it.value() = data; emit propertyChanged(property); emit echoModeChanged(property, data.echoMode); } /*! Sets read-only status of the property. \sa QtStringPropertyManager::setReadOnly */ void QtStringPropertyManager::setReadOnly(QtProperty *property, bool readOnly) { const QtStringPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtStringPropertyManagerPrivate::Data data = it.value(); if (data.readOnly == readOnly) return; data.readOnly = readOnly; it.value() = data; emit propertyChanged(property); emit echoModeChanged(property, data.echoMode); } /*! \reimp */ void QtStringPropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QtStringPropertyManagerPrivate::Data(); } /*! \reimp */ void QtStringPropertyManager::uninitializeProperty(QtProperty *property) { d_ptr->m_values.remove(property); } // QtBoolPropertyManager // Return an icon containing a check box indicator static QIcon drawCheckBox(bool value) { QStyleOptionButton opt; opt.state |= value ? QStyle::State_On : QStyle::State_Off; opt.state |= QStyle::State_Enabled; const QStyle *style = QApplication::style(); // Figure out size of an indicator and make sure it is not scaled down in a list view item // by making the pixmap as big as a list view icon and centering the indicator in it. // (if it is smaller, it can't be helped) const int indicatorWidth = style->pixelMetric(QStyle::PM_IndicatorWidth, &opt); const int indicatorHeight = style->pixelMetric(QStyle::PM_IndicatorHeight, &opt); const int listViewIconSize = indicatorWidth; const int pixmapWidth = indicatorWidth; const int pixmapHeight = qMax(indicatorHeight, listViewIconSize); opt.rect = QRect(0, 0, indicatorWidth, indicatorHeight); QPixmap pixmap = QPixmap(pixmapWidth, pixmapHeight); pixmap.fill(Qt::transparent); { // Center? const int xoff = (pixmapWidth > indicatorWidth) ? (pixmapWidth - indicatorWidth) / 2 : 0; const int yoff = (pixmapHeight > indicatorHeight) ? (pixmapHeight - indicatorHeight) / 2 : 0; QPainter painter(&pixmap); painter.translate(xoff, yoff); style->drawPrimitive(QStyle::PE_IndicatorCheckBox, &opt, &painter); } return QIcon(pixmap); } class QtBoolPropertyManagerPrivate { QtBoolPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtBoolPropertyManager) public: QtBoolPropertyManagerPrivate(); struct Data { Data() : val(false), textVisible(true) {} bool val; bool textVisible; }; typedef QMap PropertyValueMap; PropertyValueMap m_values; const QIcon m_checkedIcon; const QIcon m_uncheckedIcon; }; QtBoolPropertyManagerPrivate::QtBoolPropertyManagerPrivate() : m_checkedIcon(drawCheckBox(true)), m_uncheckedIcon(drawCheckBox(false)) { } /*! \class QtBoolPropertyManager \brief The QtBoolPropertyManager class provides and manages boolean properties. The property's value can be retrieved using the value() function, and set using the setValue() slot. In addition, QtBoolPropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes. \sa QtAbstractPropertyManager, QtCheckBoxFactory */ /*! \fn void QtBoolPropertyManager::valueChanged(QtProperty *property, bool value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. */ /*! Creates a manager with the given \a parent. */ QtBoolPropertyManager::QtBoolPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtBoolPropertyManagerPrivate; d_ptr->q_ptr = this; } /*! Destroys this manager, and all the properties it has created. */ QtBoolPropertyManager::~QtBoolPropertyManager() { clear(); delete d_ptr; } /*! Returns the given \a property's value. If the given \a property is not managed by \e this manager, this function returns false. \sa setValue() */ bool QtBoolPropertyManager::value(const QtProperty *property) const { return getValue(d_ptr->m_values, property, false); } bool QtBoolPropertyManager::textVisible(const QtProperty *property) const { return getData(d_ptr->m_values, &QtBoolPropertyManagerPrivate::Data::textVisible, property, false); } /*! \reimp */ QString QtBoolPropertyManager::valueText(const QtProperty *property) const { const QtBoolPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); const QtBoolPropertyManagerPrivate::Data &data = it.value(); if (!data.textVisible) return QString(); static const QString trueText = tr("True"); static const QString falseText = tr("False"); return data.val ? trueText : falseText; } /*! \reimp */ QIcon QtBoolPropertyManager::valueIcon(const QtProperty *property) const { const QtBoolPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QIcon(); return it.value().val ? d_ptr->m_checkedIcon : d_ptr->m_uncheckedIcon; } /*! \fn void QtBoolPropertyManager::setValue(QtProperty *property, bool value) Sets the value of the given \a property to \a value. \sa value() */ void QtBoolPropertyManager::setValue(QtProperty *property, bool val) { const QtBoolPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtBoolPropertyManagerPrivate::Data data = it.value(); if (data.val == val) return; data.val = val; it.value() = data; emit propertyChanged(property); emit valueChanged(property, data.val); } void QtBoolPropertyManager::setTextVisible(QtProperty *property, bool textVisible) { const QtBoolPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtBoolPropertyManagerPrivate::Data data = it.value(); if (data.textVisible == textVisible) return; data.textVisible = textVisible; it.value() = data; emit propertyChanged(property); emit textVisibleChanged(property, data.textVisible); } /*! \reimp */ void QtBoolPropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QtBoolPropertyManagerPrivate::Data(); } /*! \reimp */ void QtBoolPropertyManager::uninitializeProperty(QtProperty *property) { d_ptr->m_values.remove(property); } // QtDatePropertyManager class QtDatePropertyManagerPrivate { QtDatePropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtDatePropertyManager) public: struct Data { Data() : val(QDate::currentDate()), minVal(QDate(1752, 9, 14)), maxVal(QDate(7999, 12, 31)) {} QDate val; QDate minVal; QDate maxVal; QDate minimumValue() const { return minVal; } QDate maximumValue() const { return maxVal; } void setMinimumValue(const QDate &newMinVal) { setSimpleMinimumData(this, newMinVal); } void setMaximumValue(const QDate &newMaxVal) { setSimpleMaximumData(this, newMaxVal); } }; QString m_format; typedef QMap PropertyValueMap; QMap m_values; }; /*! \class QtDatePropertyManager \brief The QtDatePropertyManager provides and manages QDate properties. A date property has a current value, and a range specifying the valid dates. The range is defined by a minimum and a maximum value. The property's values can be retrieved using the minimum(), maximum() and value() functions, and can be set using the setMinimum(), setMaximum() and setValue() slots. Alternatively, the range can be defined in one go using the setRange() slot. In addition, QtDatePropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes, and the rangeChanged() signal which is emitted whenever such a property changes its range of valid dates. \sa QtAbstractPropertyManager, QtDateEditFactory, QtDateTimePropertyManager */ /*! \fn void QtDatePropertyManager::valueChanged(QtProperty *property, const QDate &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! \fn void QtDatePropertyManager::rangeChanged(QtProperty *property, const QDate &minimum, const QDate &maximum) This signal is emitted whenever a property created by this manager changes its range of valid dates, passing a pointer to the \a property and the new \a minimum and \a maximum dates. \sa setRange() */ /*! Creates a manager with the given \a parent. */ QtDatePropertyManager::QtDatePropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtDatePropertyManagerPrivate; d_ptr->q_ptr = this; QLocale loc; d_ptr->m_format = loc.dateFormat(QLocale::ShortFormat); } /*! Destroys this manager, and all the properties it has created. */ QtDatePropertyManager::~QtDatePropertyManager() { clear(); delete d_ptr; } /*! Returns the given \a property's value. If the given \a property is not managed by \e this manager, this function returns an invalid date. \sa setValue() */ QDate QtDatePropertyManager::value(const QtProperty *property) const { return getValue(d_ptr->m_values, property); } /*! Returns the given \a property's minimum date. \sa maximum(), setRange() */ QDate QtDatePropertyManager::minimum(const QtProperty *property) const { return getMinimum(d_ptr->m_values, property); } /*! Returns the given \a property's maximum date. \sa minimum(), setRange() */ QDate QtDatePropertyManager::maximum(const QtProperty *property) const { return getMaximum(d_ptr->m_values, property); } /*! \reimp */ QString QtDatePropertyManager::valueText(const QtProperty *property) const { const QtDatePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); return it.value().val.toString(d_ptr->m_format); } /*! \fn void QtDatePropertyManager::setValue(QtProperty *property, const QDate &value) Sets the value of the given \a property to \a value. If the specified \a value is not a valid date according to the given \a property's range, the value is adjusted to the nearest valid value within the range. \sa value(), setRange(), valueChanged() */ void QtDatePropertyManager::setValue(QtProperty *property, const QDate &val) { void (QtDatePropertyManagerPrivate::*setSubPropertyValue)(QtProperty *, const QDate &) = 0; setValueInRange(this, d_ptr, &QtDatePropertyManager::propertyChanged, &QtDatePropertyManager::valueChanged, property, val, setSubPropertyValue); } /*! Sets the minimum value for the given \a property to \a minVal. When setting the minimum value, the maximum and current values are adjusted if necessary (ensuring that the range remains valid and that the current value is within in the range). \sa minimum(), setRange() */ void QtDatePropertyManager::setMinimum(QtProperty *property, const QDate &minVal) { setMinimumValue(this, d_ptr, &QtDatePropertyManager::propertyChanged, &QtDatePropertyManager::valueChanged, &QtDatePropertyManager::rangeChanged, property, minVal); } /*! Sets the maximum value for the given \a property to \a maxVal. When setting the maximum value, the minimum and current values are adjusted if necessary (ensuring that the range remains valid and that the current value is within in the range). \sa maximum(), setRange() */ void QtDatePropertyManager::setMaximum(QtProperty *property, const QDate &maxVal) { setMaximumValue(this, d_ptr, &QtDatePropertyManager::propertyChanged, &QtDatePropertyManager::valueChanged, &QtDatePropertyManager::rangeChanged, property, maxVal); } /*! \fn void QtDatePropertyManager::setRange(QtProperty *property, const QDate &minimum, const QDate &maximum) Sets the range of valid dates. This is a convenience function defining the range of valid dates in one go; setting the \a minimum and \a maximum values for the given \a property with a single function call. When setting a new date range, the current value is adjusted if necessary (ensuring that the value remains in date range). \sa setMinimum(), setMaximum(), rangeChanged() */ void QtDatePropertyManager::setRange(QtProperty *property, const QDate &minVal, const QDate &maxVal) { void (QtDatePropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, const QDate &, const QDate &, const QDate &) = 0; setBorderValues(this, d_ptr, &QtDatePropertyManager::propertyChanged, &QtDatePropertyManager::valueChanged, &QtDatePropertyManager::rangeChanged, property, minVal, maxVal, setSubPropertyRange); } /*! \reimp */ void QtDatePropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QtDatePropertyManagerPrivate::Data(); } /*! \reimp */ void QtDatePropertyManager::uninitializeProperty(QtProperty *property) { d_ptr->m_values.remove(property); } // QtTimePropertyManager class QtTimePropertyManagerPrivate { QtTimePropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtTimePropertyManager) public: QString m_format; typedef QMap PropertyValueMap; PropertyValueMap m_values; }; /*! \class QtTimePropertyManager \brief The QtTimePropertyManager provides and manages QTime properties. A time property's value can be retrieved using the value() function, and set using the setValue() slot. In addition, QtTimePropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes. \sa QtAbstractPropertyManager, QtTimeEditFactory */ /*! \fn void QtTimePropertyManager::valueChanged(QtProperty *property, const QTime &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! Creates a manager with the given \a parent. */ QtTimePropertyManager::QtTimePropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtTimePropertyManagerPrivate; d_ptr->q_ptr = this; QLocale loc; d_ptr->m_format = loc.timeFormat(QLocale::ShortFormat); } /*! Destroys this manager, and all the properties it has created. */ QtTimePropertyManager::~QtTimePropertyManager() { clear(); delete d_ptr; } /*! Returns the given \a property's value. If the given property is not managed by this manager, this function returns an invalid time object. \sa setValue() */ QTime QtTimePropertyManager::value(const QtProperty *property) const { return d_ptr->m_values.value(property, QTime()); } /*! \reimp */ QString QtTimePropertyManager::valueText(const QtProperty *property) const { const QtTimePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); return it.value().toString(d_ptr->m_format); } /*! \fn void QtTimePropertyManager::setValue(QtProperty *property, const QTime &value) Sets the value of the given \a property to \a value. \sa value(), valueChanged() */ void QtTimePropertyManager::setValue(QtProperty *property, const QTime &val) { setSimpleValue(d_ptr->m_values, this, &QtTimePropertyManager::propertyChanged, &QtTimePropertyManager::valueChanged, property, val); } /*! \reimp */ void QtTimePropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QTime::currentTime(); } /*! \reimp */ void QtTimePropertyManager::uninitializeProperty(QtProperty *property) { d_ptr->m_values.remove(property); } // QtDateTimePropertyManager class QtDateTimePropertyManagerPrivate { QtDateTimePropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtDateTimePropertyManager) public: QString m_format; typedef QMap PropertyValueMap; PropertyValueMap m_values; }; /*! \class QtDateTimePropertyManager \brief The QtDateTimePropertyManager provides and manages QDateTime properties. A date and time property has a current value which can be retrieved using the value() function, and set using the setValue() slot. In addition, QtDateTimePropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes. \sa QtAbstractPropertyManager, QtDateTimeEditFactory, QtDatePropertyManager */ /*! \fn void QtDateTimePropertyManager::valueChanged(QtProperty *property, const QDateTime &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. */ /*! Creates a manager with the given \a parent. */ QtDateTimePropertyManager::QtDateTimePropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtDateTimePropertyManagerPrivate; d_ptr->q_ptr = this; QLocale loc; d_ptr->m_format = loc.dateFormat(QLocale::ShortFormat); d_ptr->m_format += QLatin1Char(' '); d_ptr->m_format += loc.timeFormat(QLocale::ShortFormat); } /*! Destroys this manager, and all the properties it has created. */ QtDateTimePropertyManager::~QtDateTimePropertyManager() { clear(); delete d_ptr; } /*! Returns the given \a property's value. If the given \a property is not managed by this manager, this function returns an invalid QDateTime object. \sa setValue() */ QDateTime QtDateTimePropertyManager::value(const QtProperty *property) const { return d_ptr->m_values.value(property, QDateTime()); } /*! \reimp */ QString QtDateTimePropertyManager::valueText(const QtProperty *property) const { const QtDateTimePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); return it.value().toString(d_ptr->m_format); } /*! \fn void QtDateTimePropertyManager::setValue(QtProperty *property, const QDateTime &value) Sets the value of the given \a property to \a value. \sa value(), valueChanged() */ void QtDateTimePropertyManager::setValue(QtProperty *property, const QDateTime &val) { setSimpleValue(d_ptr->m_values, this, &QtDateTimePropertyManager::propertyChanged, &QtDateTimePropertyManager::valueChanged, property, val); } /*! \reimp */ void QtDateTimePropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QDateTime::currentDateTime(); } /*! \reimp */ void QtDateTimePropertyManager::uninitializeProperty(QtProperty *property) { d_ptr->m_values.remove(property); } // QtKeySequencePropertyManager class QtKeySequencePropertyManagerPrivate { QtKeySequencePropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtKeySequencePropertyManager) public: QString m_format; typedef QMap PropertyValueMap; PropertyValueMap m_values; }; /*! \class QtKeySequencePropertyManager \brief The QtKeySequencePropertyManager provides and manages QKeySequence properties. A key sequence's value can be retrieved using the value() function, and set using the setValue() slot. In addition, QtKeySequencePropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes. \sa QtAbstractPropertyManager */ /*! \fn void QtKeySequencePropertyManager::valueChanged(QtProperty *property, const QKeySequence &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. */ /*! Creates a manager with the given \a parent. */ QtKeySequencePropertyManager::QtKeySequencePropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtKeySequencePropertyManagerPrivate; d_ptr->q_ptr = this; } /*! Destroys this manager, and all the properties it has created. */ QtKeySequencePropertyManager::~QtKeySequencePropertyManager() { clear(); delete d_ptr; } /*! Returns the given \a property's value. If the given \a property is not managed by this manager, this function returns an empty QKeySequence object. \sa setValue() */ QKeySequence QtKeySequencePropertyManager::value(const QtProperty *property) const { return d_ptr->m_values.value(property, QKeySequence()); } /*! \reimp */ QString QtKeySequencePropertyManager::valueText(const QtProperty *property) const { const QtKeySequencePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); return it.value().toString(QKeySequence::NativeText); } /*! \fn void QtKeySequencePropertyManager::setValue(QtProperty *property, const QKeySequence &value) Sets the value of the given \a property to \a value. \sa value(), valueChanged() */ void QtKeySequencePropertyManager::setValue(QtProperty *property, const QKeySequence &val) { setSimpleValue(d_ptr->m_values, this, &QtKeySequencePropertyManager::propertyChanged, &QtKeySequencePropertyManager::valueChanged, property, val); } /*! \reimp */ void QtKeySequencePropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QKeySequence(); } /*! \reimp */ void QtKeySequencePropertyManager::uninitializeProperty(QtProperty *property) { d_ptr->m_values.remove(property); } // QtCharPropertyManager class QtCharPropertyManagerPrivate { QtCharPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtCharPropertyManager) public: typedef QMap PropertyValueMap; PropertyValueMap m_values; }; /*! \class QtCharPropertyManager \brief The QtCharPropertyManager provides and manages QChar properties. A char's value can be retrieved using the value() function, and set using the setValue() slot. In addition, QtCharPropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes. \sa QtAbstractPropertyManager */ /*! \fn void QtCharPropertyManager::valueChanged(QtProperty *property, const QChar &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. */ /*! Creates a manager with the given \a parent. */ QtCharPropertyManager::QtCharPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtCharPropertyManagerPrivate; d_ptr->q_ptr = this; } /*! Destroys this manager, and all the properties it has created. */ QtCharPropertyManager::~QtCharPropertyManager() { clear(); delete d_ptr; } /*! Returns the given \a property's value. If the given \a property is not managed by this manager, this function returns an null QChar object. \sa setValue() */ QChar QtCharPropertyManager::value(const QtProperty *property) const { return d_ptr->m_values.value(property, QChar()); } /*! \reimp */ QString QtCharPropertyManager::valueText(const QtProperty *property) const { const QtCharPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); const QChar c = it.value(); return c.isNull() ? QString() : QString(c); } /*! \fn void QtCharPropertyManager::setValue(QtProperty *property, const QChar &value) Sets the value of the given \a property to \a value. \sa value(), valueChanged() */ void QtCharPropertyManager::setValue(QtProperty *property, const QChar &val) { setSimpleValue(d_ptr->m_values, this, &QtCharPropertyManager::propertyChanged, &QtCharPropertyManager::valueChanged, property, val); } /*! \reimp */ void QtCharPropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QChar(); } /*! \reimp */ void QtCharPropertyManager::uninitializeProperty(QtProperty *property) { d_ptr->m_values.remove(property); } // QtLocalePropertyManager class QtLocalePropertyManagerPrivate { QtLocalePropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtLocalePropertyManager) public: QtLocalePropertyManagerPrivate(); void slotEnumChanged(QtProperty *property, int value); void slotPropertyDestroyed(QtProperty *property); typedef QMap PropertyValueMap; PropertyValueMap m_values; QtEnumPropertyManager *m_enumPropertyManager; QMap m_propertyToLanguage; QMap m_propertyToCountry; QMap m_languageToProperty; QMap m_countryToProperty; }; QtLocalePropertyManagerPrivate::QtLocalePropertyManagerPrivate() { } void QtLocalePropertyManagerPrivate::slotEnumChanged(QtProperty *property, int value) { if (QtProperty *prop = m_languageToProperty.value(property, 0)) { const QLocale loc = m_values[prop]; QLocale::Language newLanguage = loc.language(); QLocale::Country newCountry = loc.country(); metaEnumProvider()->indexToLocale(value, 0, &newLanguage, 0); QLocale newLoc(newLanguage, newCountry); q_ptr->setValue(prop, newLoc); } else if (QtProperty *prop = m_countryToProperty.value(property, 0)) { const QLocale loc = m_values[prop]; QLocale::Language newLanguage = loc.language(); QLocale::Country newCountry = loc.country(); metaEnumProvider()->indexToLocale(m_enumPropertyManager->value(m_propertyToLanguage.value(prop)), value, &newLanguage, &newCountry); QLocale newLoc(newLanguage, newCountry); q_ptr->setValue(prop, newLoc); } } void QtLocalePropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) { if (QtProperty *subProp = m_languageToProperty.value(property, 0)) { m_propertyToLanguage[subProp] = 0; m_languageToProperty.remove(property); } else if (QtProperty *subProp = m_countryToProperty.value(property, 0)) { m_propertyToCountry[subProp] = 0; m_countryToProperty.remove(property); } } /*! \class QtLocalePropertyManager \brief The QtLocalePropertyManager provides and manages QLocale properties. A locale property has nested \e language and \e country subproperties. The top-level property's value can be retrieved using the value() function, and set using the setValue() slot. The subproperties are created by QtEnumPropertyManager object. These submanager can be retrieved using the subEnumPropertyManager() function. In order to provide editing widgets for the subproperties in a property browser widget, this manager must be associated with editor factory. In addition, QtLocalePropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes. \sa QtAbstractPropertyManager, QtEnumPropertyManager */ /*! \fn void QtLocalePropertyManager::valueChanged(QtProperty *property, const QLocale &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! Creates a manager with the given \a parent. */ QtLocalePropertyManager::QtLocalePropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtLocalePropertyManagerPrivate; d_ptr->q_ptr = this; d_ptr->m_enumPropertyManager = new QtEnumPropertyManager(this); connect(d_ptr->m_enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotEnumChanged(QtProperty *, int))); connect(d_ptr->m_enumPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), this, SLOT(slotPropertyDestroyed(QtProperty *))); } /*! Destroys this manager, and all the properties it has created. */ QtLocalePropertyManager::~QtLocalePropertyManager() { clear(); delete d_ptr; } /*! Returns the manager that creates the nested \e language and \e country subproperties. In order to provide editing widgets for the mentioned subproperties in a property browser widget, this manager must be associated with an editor factory. \sa QtAbstractPropertyBrowser::setFactoryForManager() */ QtEnumPropertyManager *QtLocalePropertyManager::subEnumPropertyManager() const { return d_ptr->m_enumPropertyManager; } /*! Returns the given \a property's value. If the given property is not managed by this manager, this function returns the default locale. \sa setValue() */ QLocale QtLocalePropertyManager::value(const QtProperty *property) const { return d_ptr->m_values.value(property, QLocale()); } /*! \reimp */ QString QtLocalePropertyManager::valueText(const QtProperty *property) const { const QtLocalePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); QLocale loc = it.value(); int langIdx = 0; int countryIdx = 0; metaEnumProvider()->localeToIndex(loc.language(), loc.country(), &langIdx, &countryIdx); QString str = tr("%1, %2") .arg(metaEnumProvider()->languageEnumNames().at(langIdx)) .arg(metaEnumProvider()->countryEnumNames(loc.language()).at(countryIdx)); return str; } /*! \fn void QtLocalePropertyManager::setValue(QtProperty *property, const QLocale &value) Sets the value of the given \a property to \a value. Nested properties are updated automatically. \sa value(), valueChanged() */ void QtLocalePropertyManager::setValue(QtProperty *property, const QLocale &val) { const QtLocalePropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; const QLocale loc = it.value(); if (loc == val) return; it.value() = val; int langIdx = 0; int countryIdx = 0; metaEnumProvider()->localeToIndex(val.language(), val.country(), &langIdx, &countryIdx); if (loc.language() != val.language()) { d_ptr->m_enumPropertyManager->setValue(d_ptr->m_propertyToLanguage.value(property), langIdx); d_ptr->m_enumPropertyManager->setEnumNames(d_ptr->m_propertyToCountry.value(property), metaEnumProvider()->countryEnumNames(val.language())); } d_ptr->m_enumPropertyManager->setValue(d_ptr->m_propertyToCountry.value(property), countryIdx); emit propertyChanged(property); emit valueChanged(property, val); } /*! \reimp */ void QtLocalePropertyManager::initializeProperty(QtProperty *property) { QLocale val; d_ptr->m_values[property] = val; int langIdx = 0; int countryIdx = 0; metaEnumProvider()->localeToIndex(val.language(), val.country(), &langIdx, &countryIdx); QtProperty *languageProp = d_ptr->m_enumPropertyManager->addProperty(); languageProp->setPropertyName(tr("Language")); d_ptr->m_enumPropertyManager->setEnumNames(languageProp, metaEnumProvider()->languageEnumNames()); d_ptr->m_enumPropertyManager->setValue(languageProp, langIdx); d_ptr->m_propertyToLanguage[property] = languageProp; d_ptr->m_languageToProperty[languageProp] = property; property->addSubProperty(languageProp); QtProperty *countryProp = d_ptr->m_enumPropertyManager->addProperty(); countryProp->setPropertyName(tr("Country")); d_ptr->m_enumPropertyManager->setEnumNames(countryProp, metaEnumProvider()->countryEnumNames(val.language())); d_ptr->m_enumPropertyManager->setValue(countryProp, countryIdx); d_ptr->m_propertyToCountry[property] = countryProp; d_ptr->m_countryToProperty[countryProp] = property; property->addSubProperty(countryProp); } /*! \reimp */ void QtLocalePropertyManager::uninitializeProperty(QtProperty *property) { QtProperty *languageProp = d_ptr->m_propertyToLanguage[property]; if (languageProp) { d_ptr->m_languageToProperty.remove(languageProp); delete languageProp; } d_ptr->m_propertyToLanguage.remove(property); QtProperty *countryProp = d_ptr->m_propertyToCountry[property]; if (countryProp) { d_ptr->m_countryToProperty.remove(countryProp); delete countryProp; } d_ptr->m_propertyToCountry.remove(property); d_ptr->m_values.remove(property); } // QtPointPropertyManager class QtPointPropertyManagerPrivate { QtPointPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtPointPropertyManager) public: void slotIntChanged(QtProperty *property, int value); void slotPropertyDestroyed(QtProperty *property); typedef QMap PropertyValueMap; PropertyValueMap m_values; QtIntPropertyManager *m_intPropertyManager; QMap m_propertyToX; QMap m_propertyToY; QMap m_xToProperty; QMap m_yToProperty; }; void QtPointPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) { if (QtProperty *xprop = m_xToProperty.value(property, 0)) { QPoint p = m_values[xprop]; p.setX(value); q_ptr->setValue(xprop, p); } else if (QtProperty *yprop = m_yToProperty.value(property, 0)) { QPoint p = m_values[yprop]; p.setY(value); q_ptr->setValue(yprop, p); } } void QtPointPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) { if (QtProperty *pointProp = m_xToProperty.value(property, 0)) { m_propertyToX[pointProp] = 0; m_xToProperty.remove(property); } else if (QtProperty *pointProp = m_yToProperty.value(property, 0)) { m_propertyToY[pointProp] = 0; m_yToProperty.remove(property); } } /*! \class QtPointPropertyManager \brief The QtPointPropertyManager provides and manages QPoint properties. A point property has nested \e x and \e y subproperties. The top-level property's value can be retrieved using the value() function, and set using the setValue() slot. The subproperties are created by a QtIntPropertyManager object. This manager can be retrieved using the subIntPropertyManager() function. In order to provide editing widgets for the subproperties in a property browser widget, this manager must be associated with an editor factory. In addition, QtPointPropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes. \sa QtAbstractPropertyManager, QtIntPropertyManager, QtPointFPropertyManager */ /*! \fn void QtPointPropertyManager::valueChanged(QtProperty *property, const QPoint &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! Creates a manager with the given \a parent. */ QtPointPropertyManager::QtPointPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtPointPropertyManagerPrivate; d_ptr->q_ptr = this; d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotIntChanged(QtProperty *, int))); connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), this, SLOT(slotPropertyDestroyed(QtProperty *))); } /*! Destroys this manager, and all the properties it has created. */ QtPointPropertyManager::~QtPointPropertyManager() { clear(); delete d_ptr; } /*! Returns the manager that creates the nested \e x and \e y subproperties. In order to provide editing widgets for the subproperties in a property browser widget, this manager must be associated with an editor factory. \sa QtAbstractPropertyBrowser::setFactoryForManager() */ QtIntPropertyManager *QtPointPropertyManager::subIntPropertyManager() const { return d_ptr->m_intPropertyManager; } /*! Returns the given \a property's value. If the given \a property is not managed by this manager, this function returns a point with coordinates (0, 0). \sa setValue() */ QPoint QtPointPropertyManager::value(const QtProperty *property) const { return d_ptr->m_values.value(property, QPoint()); } /*! \reimp */ QString QtPointPropertyManager::valueText(const QtProperty *property) const { const QtPointPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); const QPoint v = it.value(); return QString(tr("(%1, %2)").arg(QString::number(v.x())) .arg(QString::number(v.y()))); } /*! \fn void QtPointPropertyManager::setValue(QtProperty *property, const QPoint &value) Sets the value of the given \a property to \a value. Nested properties are updated automatically. \sa value(), valueChanged() */ void QtPointPropertyManager::setValue(QtProperty *property, const QPoint &val) { const QtPointPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; if (it.value() == val) return; it.value() = val; d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToX[property], val.x()); d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToY[property], val.y()); emit propertyChanged(property); emit valueChanged(property, val); } /*! \reimp */ void QtPointPropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QPoint(0, 0); QtProperty *xProp = d_ptr->m_intPropertyManager->addProperty(); xProp->setPropertyName(tr("X")); d_ptr->m_intPropertyManager->setValue(xProp, 0); d_ptr->m_propertyToX[property] = xProp; d_ptr->m_xToProperty[xProp] = property; property->addSubProperty(xProp); QtProperty *yProp = d_ptr->m_intPropertyManager->addProperty(); yProp->setPropertyName(tr("Y")); d_ptr->m_intPropertyManager->setValue(yProp, 0); d_ptr->m_propertyToY[property] = yProp; d_ptr->m_yToProperty[yProp] = property; property->addSubProperty(yProp); } /*! \reimp */ void QtPointPropertyManager::uninitializeProperty(QtProperty *property) { QtProperty *xProp = d_ptr->m_propertyToX[property]; if (xProp) { d_ptr->m_xToProperty.remove(xProp); delete xProp; } d_ptr->m_propertyToX.remove(property); QtProperty *yProp = d_ptr->m_propertyToY[property]; if (yProp) { d_ptr->m_yToProperty.remove(yProp); delete yProp; } d_ptr->m_propertyToY.remove(property); d_ptr->m_values.remove(property); } // QtPointFPropertyManager class QtPointFPropertyManagerPrivate { QtPointFPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtPointFPropertyManager) public: struct Data { Data() : decimals(2) {} QPointF val; int decimals; }; void slotDoubleChanged(QtProperty *property, double value); void slotPropertyDestroyed(QtProperty *property); typedef QMap PropertyValueMap; PropertyValueMap m_values; QtDoublePropertyManager *m_doublePropertyManager; QMap m_propertyToX; QMap m_propertyToY; QMap m_xToProperty; QMap m_yToProperty; }; void QtPointFPropertyManagerPrivate::slotDoubleChanged(QtProperty *property, double value) { if (QtProperty *prop = m_xToProperty.value(property, 0)) { QPointF p = m_values[prop].val; p.setX(value); q_ptr->setValue(prop, p); } else if (QtProperty *prop = m_yToProperty.value(property, 0)) { QPointF p = m_values[prop].val; p.setY(value); q_ptr->setValue(prop, p); } } void QtPointFPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) { if (QtProperty *pointProp = m_xToProperty.value(property, 0)) { m_propertyToX[pointProp] = 0; m_xToProperty.remove(property); } else if (QtProperty *pointProp = m_yToProperty.value(property, 0)) { m_propertyToY[pointProp] = 0; m_yToProperty.remove(property); } } /*! \class QtPointFPropertyManager \brief The QtPointFPropertyManager provides and manages QPointF properties. A point property has nested \e x and \e y subproperties. The top-level property's value can be retrieved using the value() function, and set using the setValue() slot. The subproperties are created by a QtDoublePropertyManager object. This manager can be retrieved using the subDoublePropertyManager() function. In order to provide editing widgets for the subproperties in a property browser widget, this manager must be associated with an editor factory. In addition, QtPointFPropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes. \sa QtAbstractPropertyManager, QtDoublePropertyManager, QtPointPropertyManager */ /*! \fn void QtPointFPropertyManager::valueChanged(QtProperty *property, const QPointF &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! \fn void QtPointFPropertyManager::decimalsChanged(QtProperty *property, int prec) This signal is emitted whenever a property created by this manager changes its precision of value, passing a pointer to the \a property and the new \a prec value \sa setDecimals() */ /*! Creates a manager with the given \a parent. */ QtPointFPropertyManager::QtPointFPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtPointFPropertyManagerPrivate; d_ptr->q_ptr = this; d_ptr->m_doublePropertyManager = new QtDoublePropertyManager(this); connect(d_ptr->m_doublePropertyManager, SIGNAL(valueChanged(QtProperty *, double)), this, SLOT(slotDoubleChanged(QtProperty *, double))); connect(d_ptr->m_doublePropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), this, SLOT(slotPropertyDestroyed(QtProperty *))); } /*! Destroys this manager, and all the properties it has created. */ QtPointFPropertyManager::~QtPointFPropertyManager() { clear(); delete d_ptr; } /*! Returns the manager that creates the nested \e x and \e y subproperties. In order to provide editing widgets for the subproperties in a property browser widget, this manager must be associated with an editor factory. \sa QtAbstractPropertyBrowser::setFactoryForManager() */ QtDoublePropertyManager *QtPointFPropertyManager::subDoublePropertyManager() const { return d_ptr->m_doublePropertyManager; } /*! Returns the given \a property's value. If the given \a property is not managed by this manager, this function returns a point with coordinates (0, 0). \sa setValue() */ QPointF QtPointFPropertyManager::value(const QtProperty *property) const { return getValue(d_ptr->m_values, property); } /*! Returns the given \a property's precision, in decimals. \sa setDecimals() */ int QtPointFPropertyManager::decimals(const QtProperty *property) const { return getData(d_ptr->m_values, &QtPointFPropertyManagerPrivate::Data::decimals, property, 0); } /*! \reimp */ QString QtPointFPropertyManager::valueText(const QtProperty *property) const { const QtPointFPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); const QPointF v = it.value().val; const int dec = it.value().decimals; return QString(tr("(%1, %2)").arg(QString::number(v.x(), 'f', dec)) .arg(QString::number(v.y(), 'f', dec))); } /*! \fn void QtPointFPropertyManager::setValue(QtProperty *property, const QPointF &value) Sets the value of the given \a property to \a value. Nested properties are updated automatically. \sa value(), valueChanged() */ void QtPointFPropertyManager::setValue(QtProperty *property, const QPointF &val) { const QtPointFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; if (it.value().val == val) return; it.value().val = val; d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToX[property], val.x()); d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToY[property], val.y()); emit propertyChanged(property); emit valueChanged(property, val); } /*! \fn void QtPointFPropertyManager::setDecimals(QtProperty *property, int prec) Sets the precision of the given \a property to \a prec. The valid decimal range is 0-13. The default is 2. \sa decimals() */ void QtPointFPropertyManager::setDecimals(QtProperty *property, int prec) { const QtPointFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtPointFPropertyManagerPrivate::Data data = it.value(); if (prec > 13) prec = 13; else if (prec < 0) prec = 0; if (data.decimals == prec) return; data.decimals = prec; d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToX[property], prec); d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToY[property], prec); it.value() = data; emit decimalsChanged(property, data.decimals); } /*! \reimp */ void QtPointFPropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QtPointFPropertyManagerPrivate::Data(); QtProperty *xProp = d_ptr->m_doublePropertyManager->addProperty(); xProp->setPropertyName(tr("X")); d_ptr->m_doublePropertyManager->setDecimals(xProp, decimals(property)); d_ptr->m_doublePropertyManager->setValue(xProp, 0); d_ptr->m_propertyToX[property] = xProp; d_ptr->m_xToProperty[xProp] = property; property->addSubProperty(xProp); QtProperty *yProp = d_ptr->m_doublePropertyManager->addProperty(); yProp->setPropertyName(tr("Y")); d_ptr->m_doublePropertyManager->setDecimals(yProp, decimals(property)); d_ptr->m_doublePropertyManager->setValue(yProp, 0); d_ptr->m_propertyToY[property] = yProp; d_ptr->m_yToProperty[yProp] = property; property->addSubProperty(yProp); } /*! \reimp */ void QtPointFPropertyManager::uninitializeProperty(QtProperty *property) { QtProperty *xProp = d_ptr->m_propertyToX[property]; if (xProp) { d_ptr->m_xToProperty.remove(xProp); delete xProp; } d_ptr->m_propertyToX.remove(property); QtProperty *yProp = d_ptr->m_propertyToY[property]; if (yProp) { d_ptr->m_yToProperty.remove(yProp); delete yProp; } d_ptr->m_propertyToY.remove(property); d_ptr->m_values.remove(property); } // QtSizePropertyManager class QtSizePropertyManagerPrivate { QtSizePropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtSizePropertyManager) public: void slotIntChanged(QtProperty *property, int value); void slotPropertyDestroyed(QtProperty *property); void setValue(QtProperty *property, const QSize &val); void setRange(QtProperty *property, const QSize &minVal, const QSize &maxVal, const QSize &val); struct Data { Data() : val(QSize(0, 0)), minVal(QSize(0, 0)), maxVal(QSize(INT_MAX, INT_MAX)) {} QSize val; QSize minVal; QSize maxVal; QSize minimumValue() const { return minVal; } QSize maximumValue() const { return maxVal; } void setMinimumValue(const QSize &newMinVal) { setSizeMinimumData(this, newMinVal); } void setMaximumValue(const QSize &newMaxVal) { setSizeMaximumData(this, newMaxVal); } }; typedef QMap PropertyValueMap; PropertyValueMap m_values; QtIntPropertyManager *m_intPropertyManager; QMap m_propertyToW; QMap m_propertyToH; QMap m_wToProperty; QMap m_hToProperty; }; void QtSizePropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) { if (QtProperty *prop = m_wToProperty.value(property, 0)) { QSize s = m_values[prop].val; s.setWidth(value); q_ptr->setValue(prop, s); } else if (QtProperty *prop = m_hToProperty.value(property, 0)) { QSize s = m_values[prop].val; s.setHeight(value); q_ptr->setValue(prop, s); } } void QtSizePropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) { if (QtProperty *pointProp = m_wToProperty.value(property, 0)) { m_propertyToW[pointProp] = 0; m_wToProperty.remove(property); } else if (QtProperty *pointProp = m_hToProperty.value(property, 0)) { m_propertyToH[pointProp] = 0; m_hToProperty.remove(property); } } void QtSizePropertyManagerPrivate::setValue(QtProperty *property, const QSize &val) { m_intPropertyManager->setValue(m_propertyToW.value(property), val.width()); m_intPropertyManager->setValue(m_propertyToH.value(property), val.height()); } void QtSizePropertyManagerPrivate::setRange(QtProperty *property, const QSize &minVal, const QSize &maxVal, const QSize &val) { QtProperty *wProperty = m_propertyToW.value(property); QtProperty *hProperty = m_propertyToH.value(property); m_intPropertyManager->setRange(wProperty, minVal.width(), maxVal.width()); m_intPropertyManager->setValue(wProperty, val.width()); m_intPropertyManager->setRange(hProperty, minVal.height(), maxVal.height()); m_intPropertyManager->setValue(hProperty, val.height()); } /*! \class QtSizePropertyManager \brief The QtSizePropertyManager provides and manages QSize properties. A size property has nested \e width and \e height subproperties. The top-level property's value can be retrieved using the value() function, and set using the setValue() slot. The subproperties are created by a QtIntPropertyManager object. This manager can be retrieved using the subIntPropertyManager() function. In order to provide editing widgets for the subproperties in a property browser widget, this manager must be associated with an editor factory. A size property also has a range of valid values defined by a minimum size and a maximum size. These sizes can be retrieved using the minimum() and the maximum() functions, and set using the setMinimum() and setMaximum() slots. Alternatively, the range can be defined in one go using the setRange() slot. In addition, QtSizePropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes, and the rangeChanged() signal which is emitted whenever such a property changes its range of valid sizes. \sa QtAbstractPropertyManager, QtIntPropertyManager, QtSizeFPropertyManager */ /*! \fn void QtSizePropertyManager::valueChanged(QtProperty *property, const QSize &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! \fn void QtSizePropertyManager::rangeChanged(QtProperty *property, const QSize &minimum, const QSize &maximum) This signal is emitted whenever a property created by this manager changes its range of valid sizes, passing a pointer to the \a property and the new \a minimum and \a maximum sizes. \sa setRange() */ /*! Creates a manager with the given \a parent. */ QtSizePropertyManager::QtSizePropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtSizePropertyManagerPrivate; d_ptr->q_ptr = this; d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotIntChanged(QtProperty *, int))); connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), this, SLOT(slotPropertyDestroyed(QtProperty *))); } /*! Destroys this manager, and all the properties it has created. */ QtSizePropertyManager::~QtSizePropertyManager() { clear(); delete d_ptr; } /*! Returns the manager that creates the nested \e width and \e height subproperties. In order to provide editing widgets for the \e width and \e height properties in a property browser widget, this manager must be associated with an editor factory. \sa QtAbstractPropertyBrowser::setFactoryForManager() */ QtIntPropertyManager *QtSizePropertyManager::subIntPropertyManager() const { return d_ptr->m_intPropertyManager; } /*! Returns the given \a property's value. If the given \a property is not managed by this manager, this function returns an invalid size \sa setValue() */ QSize QtSizePropertyManager::value(const QtProperty *property) const { return getValue(d_ptr->m_values, property); } /*! Returns the given \a property's minimum size value. \sa setMinimum(), maximum(), setRange() */ QSize QtSizePropertyManager::minimum(const QtProperty *property) const { return getMinimum(d_ptr->m_values, property); } /*! Returns the given \a property's maximum size value. \sa setMaximum(), minimum(), setRange() */ QSize QtSizePropertyManager::maximum(const QtProperty *property) const { return getMaximum(d_ptr->m_values, property); } /*! \reimp */ QString QtSizePropertyManager::valueText(const QtProperty *property) const { const QtSizePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); const QSize v = it.value().val; return QString(tr("%1 x %2").arg(QString::number(v.width())) .arg(QString::number(v.height()))); } /*! \fn void QtSizePropertyManager::setValue(QtProperty *property, const QSize &value) Sets the value of the given \a property to \a value. If the specified \a value is not valid according to the given \a property's size range, the \a value is adjusted to the nearest valid value within the size range. \sa value(), setRange(), valueChanged() */ void QtSizePropertyManager::setValue(QtProperty *property, const QSize &val) { setValueInRange(this, d_ptr, &QtSizePropertyManager::propertyChanged, &QtSizePropertyManager::valueChanged, property, val, &QtSizePropertyManagerPrivate::setValue); } /*! Sets the minimum size value for the given \a property to \a minVal. When setting the minimum size value, the maximum and current values are adjusted if necessary (ensuring that the size range remains valid and that the current value is within the range). \sa minimum(), setRange(), rangeChanged() */ void QtSizePropertyManager::setMinimum(QtProperty *property, const QSize &minVal) { setBorderValue(this, d_ptr, &QtSizePropertyManager::propertyChanged, &QtSizePropertyManager::valueChanged, &QtSizePropertyManager::rangeChanged, property, &QtSizePropertyManagerPrivate::Data::minimumValue, &QtSizePropertyManagerPrivate::Data::setMinimumValue, minVal, &QtSizePropertyManagerPrivate::setRange); } /*! Sets the maximum size value for the given \a property to \a maxVal. When setting the maximum size value, the minimum and current values are adjusted if necessary (ensuring that the size range remains valid and that the current value is within the range). \sa maximum(), setRange(), rangeChanged() */ void QtSizePropertyManager::setMaximum(QtProperty *property, const QSize &maxVal) { setBorderValue(this, d_ptr, &QtSizePropertyManager::propertyChanged, &QtSizePropertyManager::valueChanged, &QtSizePropertyManager::rangeChanged, property, &QtSizePropertyManagerPrivate::Data::maximumValue, &QtSizePropertyManagerPrivate::Data::setMaximumValue, maxVal, &QtSizePropertyManagerPrivate::setRange); } /*! \fn void QtSizePropertyManager::setRange(QtProperty *property, const QSize &minimum, const QSize &maximum) Sets the range of valid values. This is a convenience function defining the range of valid values in one go; setting the \a minimum and \a maximum values for the given \a property with a single function call. When setting a new range, the current value is adjusted if necessary (ensuring that the value remains within the range). \sa setMinimum(), setMaximum(), rangeChanged() */ void QtSizePropertyManager::setRange(QtProperty *property, const QSize &minVal, const QSize &maxVal) { setBorderValues(this, d_ptr, &QtSizePropertyManager::propertyChanged, &QtSizePropertyManager::valueChanged, &QtSizePropertyManager::rangeChanged, property, minVal, maxVal, &QtSizePropertyManagerPrivate::setRange); } /*! \reimp */ void QtSizePropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QtSizePropertyManagerPrivate::Data(); QtProperty *wProp = d_ptr->m_intPropertyManager->addProperty(); wProp->setPropertyName(tr("Width")); d_ptr->m_intPropertyManager->setValue(wProp, 0); d_ptr->m_intPropertyManager->setMinimum(wProp, 0); d_ptr->m_propertyToW[property] = wProp; d_ptr->m_wToProperty[wProp] = property; property->addSubProperty(wProp); QtProperty *hProp = d_ptr->m_intPropertyManager->addProperty(); hProp->setPropertyName(tr("Height")); d_ptr->m_intPropertyManager->setValue(hProp, 0); d_ptr->m_intPropertyManager->setMinimum(hProp, 0); d_ptr->m_propertyToH[property] = hProp; d_ptr->m_hToProperty[hProp] = property; property->addSubProperty(hProp); } /*! \reimp */ void QtSizePropertyManager::uninitializeProperty(QtProperty *property) { QtProperty *wProp = d_ptr->m_propertyToW[property]; if (wProp) { d_ptr->m_wToProperty.remove(wProp); delete wProp; } d_ptr->m_propertyToW.remove(property); QtProperty *hProp = d_ptr->m_propertyToH[property]; if (hProp) { d_ptr->m_hToProperty.remove(hProp); delete hProp; } d_ptr->m_propertyToH.remove(property); d_ptr->m_values.remove(property); } // QtSizeFPropertyManager class QtSizeFPropertyManagerPrivate { QtSizeFPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtSizeFPropertyManager) public: void slotDoubleChanged(QtProperty *property, double value); void slotPropertyDestroyed(QtProperty *property); void setValue(QtProperty *property, const QSizeF &val); void setRange(QtProperty *property, const QSizeF &minVal, const QSizeF &maxVal, const QSizeF &val); struct Data { Data() : val(QSizeF(0, 0)), minVal(QSizeF(0, 0)), maxVal(QSizeF(INT_MAX, INT_MAX)), decimals(2) {} QSizeF val; QSizeF minVal; QSizeF maxVal; int decimals; QSizeF minimumValue() const { return minVal; } QSizeF maximumValue() const { return maxVal; } void setMinimumValue(const QSizeF &newMinVal) { setSizeMinimumData(this, newMinVal); } void setMaximumValue(const QSizeF &newMaxVal) { setSizeMaximumData(this, newMaxVal); } }; typedef QMap PropertyValueMap; PropertyValueMap m_values; QtDoublePropertyManager *m_doublePropertyManager; QMap m_propertyToW; QMap m_propertyToH; QMap m_wToProperty; QMap m_hToProperty; }; void QtSizeFPropertyManagerPrivate::slotDoubleChanged(QtProperty *property, double value) { if (QtProperty *prop = m_wToProperty.value(property, 0)) { QSizeF s = m_values[prop].val; s.setWidth(value); q_ptr->setValue(prop, s); } else if (QtProperty *prop = m_hToProperty.value(property, 0)) { QSizeF s = m_values[prop].val; s.setHeight(value); q_ptr->setValue(prop, s); } } void QtSizeFPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) { if (QtProperty *pointProp = m_wToProperty.value(property, 0)) { m_propertyToW[pointProp] = 0; m_wToProperty.remove(property); } else if (QtProperty *pointProp = m_hToProperty.value(property, 0)) { m_propertyToH[pointProp] = 0; m_hToProperty.remove(property); } } void QtSizeFPropertyManagerPrivate::setValue(QtProperty *property, const QSizeF &val) { m_doublePropertyManager->setValue(m_propertyToW.value(property), val.width()); m_doublePropertyManager->setValue(m_propertyToH.value(property), val.height()); } void QtSizeFPropertyManagerPrivate::setRange(QtProperty *property, const QSizeF &minVal, const QSizeF &maxVal, const QSizeF &val) { m_doublePropertyManager->setRange(m_propertyToW[property], minVal.width(), maxVal.width()); m_doublePropertyManager->setValue(m_propertyToW[property], val.width()); m_doublePropertyManager->setRange(m_propertyToH[property], minVal.height(), maxVal.height()); m_doublePropertyManager->setValue(m_propertyToH[property], val.height()); } /*! \class QtSizeFPropertyManager \brief The QtSizeFPropertyManager provides and manages QSizeF properties. A size property has nested \e width and \e height subproperties. The top-level property's value can be retrieved using the value() function, and set using the setValue() slot. The subproperties are created by a QtDoublePropertyManager object. This manager can be retrieved using the subDoublePropertyManager() function. In order to provide editing widgets for the subproperties in a property browser widget, this manager must be associated with an editor factory. A size property also has a range of valid values defined by a minimum size and a maximum size. These sizes can be retrieved using the minimum() and the maximum() functions, and set using the setMinimum() and setMaximum() slots. Alternatively, the range can be defined in one go using the setRange() slot. In addition, QtSizeFPropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes, and the rangeChanged() signal which is emitted whenever such a property changes its range of valid sizes. \sa QtAbstractPropertyManager, QtDoublePropertyManager, QtSizePropertyManager */ /*! \fn void QtSizeFPropertyManager::valueChanged(QtProperty *property, const QSizeF &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! \fn void QtSizeFPropertyManager::rangeChanged(QtProperty *property, const QSizeF &minimum, const QSizeF &maximum) This signal is emitted whenever a property created by this manager changes its range of valid sizes, passing a pointer to the \a property and the new \a minimum and \a maximum sizes. \sa setRange() */ /*! \fn void QtSizeFPropertyManager::decimalsChanged(QtProperty *property, int prec) This signal is emitted whenever a property created by this manager changes its precision of value, passing a pointer to the \a property and the new \a prec value \sa setDecimals() */ /*! Creates a manager with the given \a parent. */ QtSizeFPropertyManager::QtSizeFPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtSizeFPropertyManagerPrivate; d_ptr->q_ptr = this; d_ptr->m_doublePropertyManager = new QtDoublePropertyManager(this); connect(d_ptr->m_doublePropertyManager, SIGNAL(valueChanged(QtProperty *, double)), this, SLOT(slotDoubleChanged(QtProperty *, double))); connect(d_ptr->m_doublePropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), this, SLOT(slotPropertyDestroyed(QtProperty *))); } /*! Destroys this manager, and all the properties it has created. */ QtSizeFPropertyManager::~QtSizeFPropertyManager() { clear(); delete d_ptr; } /*! Returns the manager that creates the nested \e width and \e height subproperties. In order to provide editing widgets for the \e width and \e height properties in a property browser widget, this manager must be associated with an editor factory. \sa QtAbstractPropertyBrowser::setFactoryForManager() */ QtDoublePropertyManager *QtSizeFPropertyManager::subDoublePropertyManager() const { return d_ptr->m_doublePropertyManager; } /*! Returns the given \a property's value. If the given \a property is not managed by this manager, this function returns an invalid size \sa setValue() */ QSizeF QtSizeFPropertyManager::value(const QtProperty *property) const { return getValue(d_ptr->m_values, property); } /*! Returns the given \a property's precision, in decimals. \sa setDecimals() */ int QtSizeFPropertyManager::decimals(const QtProperty *property) const { return getData(d_ptr->m_values, &QtSizeFPropertyManagerPrivate::Data::decimals, property, 0); } /*! Returns the given \a property's minimum size value. \sa setMinimum(), maximum(), setRange() */ QSizeF QtSizeFPropertyManager::minimum(const QtProperty *property) const { return getMinimum(d_ptr->m_values, property); } /*! Returns the given \a property's maximum size value. \sa setMaximum(), minimum(), setRange() */ QSizeF QtSizeFPropertyManager::maximum(const QtProperty *property) const { return getMaximum(d_ptr->m_values, property); } /*! \reimp */ QString QtSizeFPropertyManager::valueText(const QtProperty *property) const { const QtSizeFPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); const QSizeF v = it.value().val; const int dec = it.value().decimals; return QString(tr("%1 x %2").arg(QString::number(v.width(), 'f', dec)) .arg(QString::number(v.height(), 'f', dec))); } /*! \fn void QtSizeFPropertyManager::setValue(QtProperty *property, const QSizeF &value) Sets the value of the given \a property to \a value. If the specified \a value is not valid according to the given \a property's size range, the \a value is adjusted to the nearest valid value within the size range. \sa value(), setRange(), valueChanged() */ void QtSizeFPropertyManager::setValue(QtProperty *property, const QSizeF &val) { setValueInRange(this, d_ptr, &QtSizeFPropertyManager::propertyChanged, &QtSizeFPropertyManager::valueChanged, property, val, &QtSizeFPropertyManagerPrivate::setValue); } /*! \fn void QtSizeFPropertyManager::setDecimals(QtProperty *property, int prec) Sets the precision of the given \a property to \a prec. The valid decimal range is 0-13. The default is 2. \sa decimals() */ void QtSizeFPropertyManager::setDecimals(QtProperty *property, int prec) { const QtSizeFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtSizeFPropertyManagerPrivate::Data data = it.value(); if (prec > 13) prec = 13; else if (prec < 0) prec = 0; if (data.decimals == prec) return; data.decimals = prec; d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToW[property], prec); d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToH[property], prec); it.value() = data; emit decimalsChanged(property, data.decimals); } /*! Sets the minimum size value for the given \a property to \a minVal. When setting the minimum size value, the maximum and current values are adjusted if necessary (ensuring that the size range remains valid and that the current value is within the range). \sa minimum(), setRange(), rangeChanged() */ void QtSizeFPropertyManager::setMinimum(QtProperty *property, const QSizeF &minVal) { setBorderValue(this, d_ptr, &QtSizeFPropertyManager::propertyChanged, &QtSizeFPropertyManager::valueChanged, &QtSizeFPropertyManager::rangeChanged, property, &QtSizeFPropertyManagerPrivate::Data::minimumValue, &QtSizeFPropertyManagerPrivate::Data::setMinimumValue, minVal, &QtSizeFPropertyManagerPrivate::setRange); } /*! Sets the maximum size value for the given \a property to \a maxVal. When setting the maximum size value, the minimum and current values are adjusted if necessary (ensuring that the size range remains valid and that the current value is within the range). \sa maximum(), setRange(), rangeChanged() */ void QtSizeFPropertyManager::setMaximum(QtProperty *property, const QSizeF &maxVal) { setBorderValue(this, d_ptr, &QtSizeFPropertyManager::propertyChanged, &QtSizeFPropertyManager::valueChanged, &QtSizeFPropertyManager::rangeChanged, property, &QtSizeFPropertyManagerPrivate::Data::maximumValue, &QtSizeFPropertyManagerPrivate::Data::setMaximumValue, maxVal, &QtSizeFPropertyManagerPrivate::setRange); } /*! \fn void QtSizeFPropertyManager::setRange(QtProperty *property, const QSizeF &minimum, const QSizeF &maximum) Sets the range of valid values. This is a convenience function defining the range of valid values in one go; setting the \a minimum and \a maximum values for the given \a property with a single function call. When setting a new range, the current value is adjusted if necessary (ensuring that the value remains within the range). \sa setMinimum(), setMaximum(), rangeChanged() */ void QtSizeFPropertyManager::setRange(QtProperty *property, const QSizeF &minVal, const QSizeF &maxVal) { setBorderValues(this, d_ptr, &QtSizeFPropertyManager::propertyChanged, &QtSizeFPropertyManager::valueChanged, &QtSizeFPropertyManager::rangeChanged, property, minVal, maxVal, &QtSizeFPropertyManagerPrivate::setRange); } /*! \reimp */ void QtSizeFPropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QtSizeFPropertyManagerPrivate::Data(); QtProperty *wProp = d_ptr->m_doublePropertyManager->addProperty(); wProp->setPropertyName(tr("Width")); d_ptr->m_doublePropertyManager->setDecimals(wProp, decimals(property)); d_ptr->m_doublePropertyManager->setValue(wProp, 0); d_ptr->m_doublePropertyManager->setMinimum(wProp, 0); d_ptr->m_propertyToW[property] = wProp; d_ptr->m_wToProperty[wProp] = property; property->addSubProperty(wProp); QtProperty *hProp = d_ptr->m_doublePropertyManager->addProperty(); hProp->setPropertyName(tr("Height")); d_ptr->m_doublePropertyManager->setDecimals(hProp, decimals(property)); d_ptr->m_doublePropertyManager->setValue(hProp, 0); d_ptr->m_doublePropertyManager->setMinimum(hProp, 0); d_ptr->m_propertyToH[property] = hProp; d_ptr->m_hToProperty[hProp] = property; property->addSubProperty(hProp); } /*! \reimp */ void QtSizeFPropertyManager::uninitializeProperty(QtProperty *property) { QtProperty *wProp = d_ptr->m_propertyToW[property]; if (wProp) { d_ptr->m_wToProperty.remove(wProp); delete wProp; } d_ptr->m_propertyToW.remove(property); QtProperty *hProp = d_ptr->m_propertyToH[property]; if (hProp) { d_ptr->m_hToProperty.remove(hProp); delete hProp; } d_ptr->m_propertyToH.remove(property); d_ptr->m_values.remove(property); } // QtRectPropertyManager class QtRectPropertyManagerPrivate { QtRectPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtRectPropertyManager) public: void slotIntChanged(QtProperty *property, int value); void slotPropertyDestroyed(QtProperty *property); void setConstraint(QtProperty *property, const QRect &constraint, const QRect &val); struct Data { Data() : val(0, 0, 0, 0) {} QRect val; QRect constraint; }; typedef QMap PropertyValueMap; PropertyValueMap m_values; QtIntPropertyManager *m_intPropertyManager; QMap m_propertyToX; QMap m_propertyToY; QMap m_propertyToW; QMap m_propertyToH; QMap m_xToProperty; QMap m_yToProperty; QMap m_wToProperty; QMap m_hToProperty; }; void QtRectPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) { if (QtProperty *prop = m_xToProperty.value(property, 0)) { QRect r = m_values[prop].val; r.moveLeft(value); q_ptr->setValue(prop, r); } else if (QtProperty *prop = m_yToProperty.value(property)) { QRect r = m_values[prop].val; r.moveTop(value); q_ptr->setValue(prop, r); } else if (QtProperty *prop = m_wToProperty.value(property, 0)) { Data data = m_values[prop]; QRect r = data.val; r.setWidth(value); if (!data.constraint.isNull() && data.constraint.x() + data.constraint.width() < r.x() + r.width()) { r.moveLeft(data.constraint.left() + data.constraint.width() - r.width()); } q_ptr->setValue(prop, r); } else if (QtProperty *prop = m_hToProperty.value(property, 0)) { Data data = m_values[prop]; QRect r = data.val; r.setHeight(value); if (!data.constraint.isNull() && data.constraint.y() + data.constraint.height() < r.y() + r.height()) { r.moveTop(data.constraint.top() + data.constraint.height() - r.height()); } q_ptr->setValue(prop, r); } } void QtRectPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) { if (QtProperty *pointProp = m_xToProperty.value(property, 0)) { m_propertyToX[pointProp] = 0; m_xToProperty.remove(property); } else if (QtProperty *pointProp = m_yToProperty.value(property, 0)) { m_propertyToY[pointProp] = 0; m_yToProperty.remove(property); } else if (QtProperty *pointProp = m_wToProperty.value(property, 0)) { m_propertyToW[pointProp] = 0; m_wToProperty.remove(property); } else if (QtProperty *pointProp = m_hToProperty.value(property, 0)) { m_propertyToH[pointProp] = 0; m_hToProperty.remove(property); } } void QtRectPropertyManagerPrivate::setConstraint(QtProperty *property, const QRect &constraint, const QRect &val) { const bool isNull = constraint.isNull(); const int left = isNull ? INT_MIN : constraint.left(); const int right = isNull ? INT_MAX : constraint.left() + constraint.width(); const int top = isNull ? INT_MIN : constraint.top(); const int bottom = isNull ? INT_MAX : constraint.top() + constraint.height(); const int width = isNull ? INT_MAX : constraint.width(); const int height = isNull ? INT_MAX : constraint.height(); m_intPropertyManager->setRange(m_propertyToX[property], left, right); m_intPropertyManager->setRange(m_propertyToY[property], top, bottom); m_intPropertyManager->setRange(m_propertyToW[property], 0, width); m_intPropertyManager->setRange(m_propertyToH[property], 0, height); m_intPropertyManager->setValue(m_propertyToX[property], val.x()); m_intPropertyManager->setValue(m_propertyToY[property], val.y()); m_intPropertyManager->setValue(m_propertyToW[property], val.width()); m_intPropertyManager->setValue(m_propertyToH[property], val.height()); } /*! \class QtRectPropertyManager \brief The QtRectPropertyManager provides and manages QRect properties. A rectangle property has nested \e x, \e y, \e width and \e height subproperties. The top-level property's value can be retrieved using the value() function, and set using the setValue() slot. The subproperties are created by a QtIntPropertyManager object. This manager can be retrieved using the subIntPropertyManager() function. In order to provide editing widgets for the subproperties in a property browser widget, this manager must be associated with an editor factory. A rectangle property also has a constraint rectangle which can be retrieved using the constraint() function, and set using the setConstraint() slot. In addition, QtRectPropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes, and the constraintChanged() signal which is emitted whenever such a property changes its constraint rectangle. \sa QtAbstractPropertyManager, QtIntPropertyManager, QtRectFPropertyManager */ /*! \fn void QtRectPropertyManager::valueChanged(QtProperty *property, const QRect &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! \fn void QtRectPropertyManager::constraintChanged(QtProperty *property, const QRect &constraint) This signal is emitted whenever property changes its constraint rectangle, passing a pointer to the \a property and the new \a constraint rectangle as parameters. \sa setConstraint() */ /*! Creates a manager with the given \a parent. */ QtRectPropertyManager::QtRectPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtRectPropertyManagerPrivate; d_ptr->q_ptr = this; d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotIntChanged(QtProperty *, int))); connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), this, SLOT(slotPropertyDestroyed(QtProperty *))); } /*! Destroys this manager, and all the properties it has created. */ QtRectPropertyManager::~QtRectPropertyManager() { clear(); delete d_ptr; } /*! Returns the manager that creates the nested \e x, \e y, \e width and \e height subproperties. In order to provide editing widgets for the mentioned subproperties in a property browser widget, this manager must be associated with an editor factory. \sa QtAbstractPropertyBrowser::setFactoryForManager() */ QtIntPropertyManager *QtRectPropertyManager::subIntPropertyManager() const { return d_ptr->m_intPropertyManager; } /*! Returns the given \a property's value. If the given \a property is not managed by this manager, this function returns an invalid rectangle. \sa setValue(), constraint() */ QRect QtRectPropertyManager::value(const QtProperty *property) const { return getValue(d_ptr->m_values, property); } /*! Returns the given \a property's constraining rectangle. If returned value is null QRect it means there is no constraint applied. \sa value(), setConstraint() */ QRect QtRectPropertyManager::constraint(const QtProperty *property) const { return getData(d_ptr->m_values, &QtRectPropertyManagerPrivate::Data::constraint, property, QRect()); } /*! \reimp */ QString QtRectPropertyManager::valueText(const QtProperty *property) const { const QtRectPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); const QRect v = it.value().val; return QString(tr("[(%1, %2), %3 x %4]").arg(QString::number(v.x())) .arg(QString::number(v.y())) .arg(QString::number(v.width())) .arg(QString::number(v.height()))); } /*! \fn void QtRectPropertyManager::setValue(QtProperty *property, const QRect &value) Sets the value of the given \a property to \a value. Nested properties are updated automatically. If the specified \a value is not inside the given \a property's constraining rectangle, the value is adjusted accordingly to fit within the constraint. \sa value(), setConstraint(), valueChanged() */ void QtRectPropertyManager::setValue(QtProperty *property, const QRect &val) { const QtRectPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtRectPropertyManagerPrivate::Data data = it.value(); QRect newRect = val.normalized(); if (!data.constraint.isNull() && !data.constraint.contains(newRect)) { const QRect r1 = data.constraint; const QRect r2 = newRect; newRect.setLeft(qMax(r1.left(), r2.left())); newRect.setRight(qMin(r1.right(), r2.right())); newRect.setTop(qMax(r1.top(), r2.top())); newRect.setBottom(qMin(r1.bottom(), r2.bottom())); if (newRect.width() < 0 || newRect.height() < 0) return; } if (data.val == newRect) return; data.val = newRect; it.value() = data; d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToX[property], newRect.x()); d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToY[property], newRect.y()); d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToW[property], newRect.width()); d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToH[property], newRect.height()); emit propertyChanged(property); emit valueChanged(property, data.val); } /*! Sets the given \a property's constraining rectangle to \a constraint. When setting the constraint, the current value is adjusted if necessary (ensuring that the current rectangle value is inside the constraint). In order to reset the constraint pass a null QRect value. \sa setValue(), constraint(), constraintChanged() */ void QtRectPropertyManager::setConstraint(QtProperty *property, const QRect &constraint) { const QtRectPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtRectPropertyManagerPrivate::Data data = it.value(); QRect newConstraint = constraint.normalized(); if (data.constraint == newConstraint) return; const QRect oldVal = data.val; data.constraint = newConstraint; if (!data.constraint.isNull() && !data.constraint.contains(oldVal)) { QRect r1 = data.constraint; QRect r2 = data.val; if (r2.width() > r1.width()) r2.setWidth(r1.width()); if (r2.height() > r1.height()) r2.setHeight(r1.height()); if (r2.left() < r1.left()) r2.moveLeft(r1.left()); else if (r2.right() > r1.right()) r2.moveRight(r1.right()); if (r2.top() < r1.top()) r2.moveTop(r1.top()); else if (r2.bottom() > r1.bottom()) r2.moveBottom(r1.bottom()); data.val = r2; } it.value() = data; emit constraintChanged(property, data.constraint); d_ptr->setConstraint(property, data.constraint, data.val); if (data.val == oldVal) return; emit propertyChanged(property); emit valueChanged(property, data.val); } /*! \reimp */ void QtRectPropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QtRectPropertyManagerPrivate::Data(); QtProperty *xProp = d_ptr->m_intPropertyManager->addProperty(); xProp->setPropertyName(tr("X")); d_ptr->m_intPropertyManager->setValue(xProp, 0); d_ptr->m_propertyToX[property] = xProp; d_ptr->m_xToProperty[xProp] = property; property->addSubProperty(xProp); QtProperty *yProp = d_ptr->m_intPropertyManager->addProperty(); yProp->setPropertyName(tr("Y")); d_ptr->m_intPropertyManager->setValue(yProp, 0); d_ptr->m_propertyToY[property] = yProp; d_ptr->m_yToProperty[yProp] = property; property->addSubProperty(yProp); QtProperty *wProp = d_ptr->m_intPropertyManager->addProperty(); wProp->setPropertyName(tr("Width")); d_ptr->m_intPropertyManager->setValue(wProp, 0); d_ptr->m_intPropertyManager->setMinimum(wProp, 0); d_ptr->m_propertyToW[property] = wProp; d_ptr->m_wToProperty[wProp] = property; property->addSubProperty(wProp); QtProperty *hProp = d_ptr->m_intPropertyManager->addProperty(); hProp->setPropertyName(tr("Height")); d_ptr->m_intPropertyManager->setValue(hProp, 0); d_ptr->m_intPropertyManager->setMinimum(hProp, 0); d_ptr->m_propertyToH[property] = hProp; d_ptr->m_hToProperty[hProp] = property; property->addSubProperty(hProp); } /*! \reimp */ void QtRectPropertyManager::uninitializeProperty(QtProperty *property) { QtProperty *xProp = d_ptr->m_propertyToX[property]; if (xProp) { d_ptr->m_xToProperty.remove(xProp); delete xProp; } d_ptr->m_propertyToX.remove(property); QtProperty *yProp = d_ptr->m_propertyToY[property]; if (yProp) { d_ptr->m_yToProperty.remove(yProp); delete yProp; } d_ptr->m_propertyToY.remove(property); QtProperty *wProp = d_ptr->m_propertyToW[property]; if (wProp) { d_ptr->m_wToProperty.remove(wProp); delete wProp; } d_ptr->m_propertyToW.remove(property); QtProperty *hProp = d_ptr->m_propertyToH[property]; if (hProp) { d_ptr->m_hToProperty.remove(hProp); delete hProp; } d_ptr->m_propertyToH.remove(property); d_ptr->m_values.remove(property); } // QtRectFPropertyManager class QtRectFPropertyManagerPrivate { QtRectFPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtRectFPropertyManager) public: void slotDoubleChanged(QtProperty *property, double value); void slotPropertyDestroyed(QtProperty *property); void setConstraint(QtProperty *property, const QRectF &constraint, const QRectF &val); struct Data { Data() : val(0, 0, 0, 0), decimals(2) {} QRectF val; QRectF constraint; int decimals; }; typedef QMap PropertyValueMap; PropertyValueMap m_values; QtDoublePropertyManager *m_doublePropertyManager; QMap m_propertyToX; QMap m_propertyToY; QMap m_propertyToW; QMap m_propertyToH; QMap m_xToProperty; QMap m_yToProperty; QMap m_wToProperty; QMap m_hToProperty; }; void QtRectFPropertyManagerPrivate::slotDoubleChanged(QtProperty *property, double value) { if (QtProperty *prop = m_xToProperty.value(property, 0)) { QRectF r = m_values[prop].val; r.moveLeft(value); q_ptr->setValue(prop, r); } else if (QtProperty *prop = m_yToProperty.value(property, 0)) { QRectF r = m_values[prop].val; r.moveTop(value); q_ptr->setValue(prop, r); } else if (QtProperty *prop = m_wToProperty.value(property, 0)) { Data data = m_values[prop]; QRectF r = data.val; r.setWidth(value); if (!data.constraint.isNull() && data.constraint.x() + data.constraint.width() < r.x() + r.width()) { r.moveLeft(data.constraint.left() + data.constraint.width() - r.width()); } q_ptr->setValue(prop, r); } else if (QtProperty *prop = m_hToProperty.value(property, 0)) { Data data = m_values[prop]; QRectF r = data.val; r.setHeight(value); if (!data.constraint.isNull() && data.constraint.y() + data.constraint.height() < r.y() + r.height()) { r.moveTop(data.constraint.top() + data.constraint.height() - r.height()); } q_ptr->setValue(prop, r); } } void QtRectFPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) { if (QtProperty *pointProp = m_xToProperty.value(property, 0)) { m_propertyToX[pointProp] = 0; m_xToProperty.remove(property); } else if (QtProperty *pointProp = m_yToProperty.value(property, 0)) { m_propertyToY[pointProp] = 0; m_yToProperty.remove(property); } else if (QtProperty *pointProp = m_wToProperty.value(property, 0)) { m_propertyToW[pointProp] = 0; m_wToProperty.remove(property); } else if (QtProperty *pointProp = m_hToProperty.value(property, 0)) { m_propertyToH[pointProp] = 0; m_hToProperty.remove(property); } } void QtRectFPropertyManagerPrivate::setConstraint(QtProperty *property, const QRectF &constraint, const QRectF &val) { const bool isNull = constraint.isNull(); const float left = isNull ? FLT_MIN : constraint.left(); const float right = isNull ? FLT_MAX : constraint.left() + constraint.width(); const float top = isNull ? FLT_MIN : constraint.top(); const float bottom = isNull ? FLT_MAX : constraint.top() + constraint.height(); const float width = isNull ? FLT_MAX : constraint.width(); const float height = isNull ? FLT_MAX : constraint.height(); m_doublePropertyManager->setRange(m_propertyToX[property], left, right); m_doublePropertyManager->setRange(m_propertyToY[property], top, bottom); m_doublePropertyManager->setRange(m_propertyToW[property], 0, width); m_doublePropertyManager->setRange(m_propertyToH[property], 0, height); m_doublePropertyManager->setValue(m_propertyToX[property], val.x()); m_doublePropertyManager->setValue(m_propertyToY[property], val.y()); m_doublePropertyManager->setValue(m_propertyToW[property], val.width()); m_doublePropertyManager->setValue(m_propertyToH[property], val.height()); } /*! \class QtRectFPropertyManager \brief The QtRectFPropertyManager provides and manages QRectF properties. A rectangle property has nested \e x, \e y, \e width and \e height subproperties. The top-level property's value can be retrieved using the value() function, and set using the setValue() slot. The subproperties are created by a QtDoublePropertyManager object. This manager can be retrieved using the subDoublePropertyManager() function. In order to provide editing widgets for the subproperties in a property browser widget, this manager must be associated with an editor factory. A rectangle property also has a constraint rectangle which can be retrieved using the constraint() function, and set using the setConstraint() slot. In addition, QtRectFPropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes, and the constraintChanged() signal which is emitted whenever such a property changes its constraint rectangle. \sa QtAbstractPropertyManager, QtDoublePropertyManager, QtRectPropertyManager */ /*! \fn void QtRectFPropertyManager::valueChanged(QtProperty *property, const QRectF &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! \fn void QtRectFPropertyManager::constraintChanged(QtProperty *property, const QRectF &constraint) This signal is emitted whenever property changes its constraint rectangle, passing a pointer to the \a property and the new \a constraint rectangle as parameters. \sa setConstraint() */ /*! \fn void QtRectFPropertyManager::decimalsChanged(QtProperty *property, int prec) This signal is emitted whenever a property created by this manager changes its precision of value, passing a pointer to the \a property and the new \a prec value \sa setDecimals() */ /*! Creates a manager with the given \a parent. */ QtRectFPropertyManager::QtRectFPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtRectFPropertyManagerPrivate; d_ptr->q_ptr = this; d_ptr->m_doublePropertyManager = new QtDoublePropertyManager(this); connect(d_ptr->m_doublePropertyManager, SIGNAL(valueChanged(QtProperty *, double)), this, SLOT(slotDoubleChanged(QtProperty *, double))); connect(d_ptr->m_doublePropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), this, SLOT(slotPropertyDestroyed(QtProperty *))); } /*! Destroys this manager, and all the properties it has created. */ QtRectFPropertyManager::~QtRectFPropertyManager() { clear(); delete d_ptr; } /*! Returns the manager that creates the nested \e x, \e y, \e width and \e height subproperties. In order to provide editing widgets for the mentioned subproperties in a property browser widget, this manager must be associated with an editor factory. \sa QtAbstractPropertyBrowser::setFactoryForManager() */ QtDoublePropertyManager *QtRectFPropertyManager::subDoublePropertyManager() const { return d_ptr->m_doublePropertyManager; } /*! Returns the given \a property's value. If the given \a property is not managed by this manager, this function returns an invalid rectangle. \sa setValue(), constraint() */ QRectF QtRectFPropertyManager::value(const QtProperty *property) const { return getValue(d_ptr->m_values, property); } /*! Returns the given \a property's precision, in decimals. \sa setDecimals() */ int QtRectFPropertyManager::decimals(const QtProperty *property) const { return getData(d_ptr->m_values, &QtRectFPropertyManagerPrivate::Data::decimals, property, 0); } /*! Returns the given \a property's constraining rectangle. If returned value is null QRectF it means there is no constraint applied. \sa value(), setConstraint() */ QRectF QtRectFPropertyManager::constraint(const QtProperty *property) const { return getData(d_ptr->m_values, &QtRectFPropertyManagerPrivate::Data::constraint, property, QRect()); } /*! \reimp */ QString QtRectFPropertyManager::valueText(const QtProperty *property) const { const QtRectFPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); const QRectF v = it.value().val; const int dec = it.value().decimals; return QString(tr("[(%1, %2), %3 x %4]").arg(QString::number(v.x(), 'f', dec)) .arg(QString::number(v.y(), 'f', dec)) .arg(QString::number(v.width(), 'f', dec)) .arg(QString::number(v.height(), 'f', dec))); } /*! \fn void QtRectFPropertyManager::setValue(QtProperty *property, const QRectF &value) Sets the value of the given \a property to \a value. Nested properties are updated automatically. If the specified \a value is not inside the given \a property's constraining rectangle, the value is adjusted accordingly to fit within the constraint. \sa value(), setConstraint(), valueChanged() */ void QtRectFPropertyManager::setValue(QtProperty *property, const QRectF &val) { const QtRectFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtRectFPropertyManagerPrivate::Data data = it.value(); QRectF newRect = val.normalized(); if (!data.constraint.isNull() && !data.constraint.contains(newRect)) { const QRectF r1 = data.constraint; const QRectF r2 = newRect; newRect.setLeft(qMax(r1.left(), r2.left())); newRect.setRight(qMin(r1.right(), r2.right())); newRect.setTop(qMax(r1.top(), r2.top())); newRect.setBottom(qMin(r1.bottom(), r2.bottom())); if (newRect.width() < 0 || newRect.height() < 0) return; } if (data.val == newRect) return; data.val = newRect; it.value() = data; d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToX[property], newRect.x()); d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToY[property], newRect.y()); d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToW[property], newRect.width()); d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToH[property], newRect.height()); emit propertyChanged(property); emit valueChanged(property, data.val); } /*! Sets the given \a property's constraining rectangle to \a constraint. When setting the constraint, the current value is adjusted if necessary (ensuring that the current rectangle value is inside the constraint). In order to reset the constraint pass a null QRectF value. \sa setValue(), constraint(), constraintChanged() */ void QtRectFPropertyManager::setConstraint(QtProperty *property, const QRectF &constraint) { const QtRectFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtRectFPropertyManagerPrivate::Data data = it.value(); QRectF newConstraint = constraint.normalized(); if (data.constraint == newConstraint) return; const QRectF oldVal = data.val; data.constraint = newConstraint; if (!data.constraint.isNull() && !data.constraint.contains(oldVal)) { QRectF r1 = data.constraint; QRectF r2 = data.val; if (r2.width() > r1.width()) r2.setWidth(r1.width()); if (r2.height() > r1.height()) r2.setHeight(r1.height()); if (r2.left() < r1.left()) r2.moveLeft(r1.left()); else if (r2.right() > r1.right()) r2.moveRight(r1.right()); if (r2.top() < r1.top()) r2.moveTop(r1.top()); else if (r2.bottom() > r1.bottom()) r2.moveBottom(r1.bottom()); data.val = r2; } it.value() = data; emit constraintChanged(property, data.constraint); d_ptr->setConstraint(property, data.constraint, data.val); if (data.val == oldVal) return; emit propertyChanged(property); emit valueChanged(property, data.val); } /*! \fn void QtRectFPropertyManager::setDecimals(QtProperty *property, int prec) Sets the precision of the given \a property to \a prec. The valid decimal range is 0-13. The default is 2. \sa decimals() */ void QtRectFPropertyManager::setDecimals(QtProperty *property, int prec) { const QtRectFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtRectFPropertyManagerPrivate::Data data = it.value(); if (prec > 13) prec = 13; else if (prec < 0) prec = 0; if (data.decimals == prec) return; data.decimals = prec; d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToX[property], prec); d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToY[property], prec); d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToW[property], prec); d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToH[property], prec); it.value() = data; emit decimalsChanged(property, data.decimals); } /*! \reimp */ void QtRectFPropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QtRectFPropertyManagerPrivate::Data(); QtProperty *xProp = d_ptr->m_doublePropertyManager->addProperty(); xProp->setPropertyName(tr("X")); d_ptr->m_doublePropertyManager->setDecimals(xProp, decimals(property)); d_ptr->m_doublePropertyManager->setValue(xProp, 0); d_ptr->m_propertyToX[property] = xProp; d_ptr->m_xToProperty[xProp] = property; property->addSubProperty(xProp); QtProperty *yProp = d_ptr->m_doublePropertyManager->addProperty(); yProp->setPropertyName(tr("Y")); d_ptr->m_doublePropertyManager->setDecimals(yProp, decimals(property)); d_ptr->m_doublePropertyManager->setValue(yProp, 0); d_ptr->m_propertyToY[property] = yProp; d_ptr->m_yToProperty[yProp] = property; property->addSubProperty(yProp); QtProperty *wProp = d_ptr->m_doublePropertyManager->addProperty(); wProp->setPropertyName(tr("Width")); d_ptr->m_doublePropertyManager->setDecimals(wProp, decimals(property)); d_ptr->m_doublePropertyManager->setValue(wProp, 0); d_ptr->m_doublePropertyManager->setMinimum(wProp, 0); d_ptr->m_propertyToW[property] = wProp; d_ptr->m_wToProperty[wProp] = property; property->addSubProperty(wProp); QtProperty *hProp = d_ptr->m_doublePropertyManager->addProperty(); hProp->setPropertyName(tr("Height")); d_ptr->m_doublePropertyManager->setDecimals(hProp, decimals(property)); d_ptr->m_doublePropertyManager->setValue(hProp, 0); d_ptr->m_doublePropertyManager->setMinimum(hProp, 0); d_ptr->m_propertyToH[property] = hProp; d_ptr->m_hToProperty[hProp] = property; property->addSubProperty(hProp); } /*! \reimp */ void QtRectFPropertyManager::uninitializeProperty(QtProperty *property) { QtProperty *xProp = d_ptr->m_propertyToX[property]; if (xProp) { d_ptr->m_xToProperty.remove(xProp); delete xProp; } d_ptr->m_propertyToX.remove(property); QtProperty *yProp = d_ptr->m_propertyToY[property]; if (yProp) { d_ptr->m_yToProperty.remove(yProp); delete yProp; } d_ptr->m_propertyToY.remove(property); QtProperty *wProp = d_ptr->m_propertyToW[property]; if (wProp) { d_ptr->m_wToProperty.remove(wProp); delete wProp; } d_ptr->m_propertyToW.remove(property); QtProperty *hProp = d_ptr->m_propertyToH[property]; if (hProp) { d_ptr->m_hToProperty.remove(hProp); delete hProp; } d_ptr->m_propertyToH.remove(property); d_ptr->m_values.remove(property); } // QtEnumPropertyManager class QtEnumPropertyManagerPrivate { QtEnumPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtEnumPropertyManager) public: struct Data { Data() : val(-1) {} int val; QStringList enumNames; QMap enumIcons; }; typedef QMap PropertyValueMap; PropertyValueMap m_values; }; /*! \class QtEnumPropertyManager \brief The QtEnumPropertyManager provides and manages enum properties. Each enum property has an associated list of enum names which can be retrieved using the enumNames() function, and set using the corresponding setEnumNames() function. An enum property's value is represented by an index in this list, and can be retrieved and set using the value() and setValue() slots respectively. Each enum value can also have an associated icon. The mapping from values to icons can be set using the setEnumIcons() function and queried with the enumIcons() function. In addition, QtEnumPropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes. The enumNamesChanged() or enumIconsChanged() signal is emitted whenever the list of enum names or icons is altered. \sa QtAbstractPropertyManager, QtEnumEditorFactory */ /*! \fn void QtEnumPropertyManager::valueChanged(QtProperty *property, int value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! \fn void QtEnumPropertyManager::enumNamesChanged(QtProperty *property, const QStringList &names) This signal is emitted whenever a property created by this manager changes its enum names, passing a pointer to the \a property and the new \a names as parameters. \sa setEnumNames() */ /*! \fn void QtEnumPropertyManager::enumIconsChanged(QtProperty *property, const QMap &icons) This signal is emitted whenever a property created by this manager changes its enum icons, passing a pointer to the \a property and the new mapping of values to \a icons as parameters. \sa setEnumIcons() */ /*! Creates a manager with the given \a parent. */ QtEnumPropertyManager::QtEnumPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtEnumPropertyManagerPrivate; d_ptr->q_ptr = this; } /*! Destroys this manager, and all the properties it has created. */ QtEnumPropertyManager::~QtEnumPropertyManager() { clear(); delete d_ptr; } /*! Returns the given \a property's value which is an index in the list returned by enumNames() If the given property is not managed by this manager, this function returns -1. \sa enumNames(), setValue() */ int QtEnumPropertyManager::value(const QtProperty *property) const { return getValue(d_ptr->m_values, property, -1); } /*! Returns the given \a property's list of enum names. \sa value(), setEnumNames() */ QStringList QtEnumPropertyManager::enumNames(const QtProperty *property) const { return getData(d_ptr->m_values, &QtEnumPropertyManagerPrivate::Data::enumNames, property, QStringList()); } /*! Returns the given \a property's map of enum values to their icons. \sa value(), setEnumIcons() */ QMap QtEnumPropertyManager::enumIcons(const QtProperty *property) const { return getData >(d_ptr->m_values, &QtEnumPropertyManagerPrivate::Data::enumIcons, property, QMap()); } /*! \reimp */ QString QtEnumPropertyManager::valueText(const QtProperty *property) const { const QtEnumPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); const QtEnumPropertyManagerPrivate::Data &data = it.value(); const int v = data.val; if (v >= 0 && v < data.enumNames.count()) return data.enumNames.at(v); return QString(); } /*! \reimp */ QIcon QtEnumPropertyManager::valueIcon(const QtProperty *property) const { const QtEnumPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QIcon(); const QtEnumPropertyManagerPrivate::Data &data = it.value(); const int v = data.val; return data.enumIcons.value(v); } /*! \fn void QtEnumPropertyManager::setValue(QtProperty *property, int value) Sets the value of the given \a property to \a value. The specified \a value must be less than the size of the given \a property's enumNames() list, and larger than (or equal to) 0. \sa value(), valueChanged() */ void QtEnumPropertyManager::setValue(QtProperty *property, int val) { const QtEnumPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtEnumPropertyManagerPrivate::Data data = it.value(); if (val >= data.enumNames.count()) return; if (val < 0 && data.enumNames.count() > 0) return; if (val < 0) val = -1; if (data.val == val) return; data.val = val; it.value() = data; emit propertyChanged(property); emit valueChanged(property, data.val); } /*! Sets the given \a property's list of enum names to \a enumNames. The \a property's current value is reset to 0 indicating the first item of the list. If the specified \a enumNames list is empty, the \a property's current value is set to -1. \sa enumNames(), enumNamesChanged() */ void QtEnumPropertyManager::setEnumNames(QtProperty *property, const QStringList &enumNames) { const QtEnumPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtEnumPropertyManagerPrivate::Data data = it.value(); if (data.enumNames == enumNames) return; data.enumNames = enumNames; data.val = -1; if (enumNames.count() > 0) data.val = 0; it.value() = data; emit enumNamesChanged(property, data.enumNames); emit propertyChanged(property); emit valueChanged(property, data.val); } /*! Sets the given \a property's map of enum values to their icons to \a enumIcons. Each enum value can have associated icon. This association is represented with passed \a enumIcons map. \sa enumNames(), enumNamesChanged() */ void QtEnumPropertyManager::setEnumIcons(QtProperty *property, const QMap &enumIcons) { const QtEnumPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; it.value().enumIcons = enumIcons; emit enumIconsChanged(property, it.value().enumIcons); emit propertyChanged(property); } /*! \reimp */ void QtEnumPropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QtEnumPropertyManagerPrivate::Data(); } /*! \reimp */ void QtEnumPropertyManager::uninitializeProperty(QtProperty *property) { d_ptr->m_values.remove(property); } // QtFlagPropertyManager class QtFlagPropertyManagerPrivate { QtFlagPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtFlagPropertyManager) public: void slotBoolChanged(QtProperty *property, bool value); void slotPropertyDestroyed(QtProperty *property); struct Data { Data() : val(-1) {} int val; QStringList flagNames; }; typedef QMap PropertyValueMap; PropertyValueMap m_values; QtBoolPropertyManager *m_boolPropertyManager; QMap > m_propertyToFlags; QMap m_flagToProperty; }; void QtFlagPropertyManagerPrivate::slotBoolChanged(QtProperty *property, bool value) { QtProperty *prop = m_flagToProperty.value(property, 0); if (prop == 0) return; QListIterator itProp(m_propertyToFlags[prop]); int level = 0; while (itProp.hasNext()) { QtProperty *p = itProp.next(); if (p == property) { int v = m_values[prop].val; if (value) { v |= (1 << level); } else { v &= ~(1 << level); } q_ptr->setValue(prop, v); return; } level++; } } void QtFlagPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) { QtProperty *flagProperty = m_flagToProperty.value(property, 0); if (flagProperty == 0) return; m_propertyToFlags[flagProperty].replace(m_propertyToFlags[flagProperty].indexOf(property), 0); m_flagToProperty.remove(property); } /*! \class QtFlagPropertyManager \brief The QtFlagPropertyManager provides and manages flag properties. Each flag property has an associated list of flag names which can be retrieved using the flagNames() function, and set using the corresponding setFlagNames() function. The flag manager provides properties with nested boolean subproperties representing each flag, i.e. a flag property's value is the binary combination of the subproperties' values. A property's value can be retrieved and set using the value() and setValue() slots respectively. The combination of flags is represented by single int value - that's why it's possible to store up to 32 independent flags in one flag property. The subproperties are created by a QtBoolPropertyManager object. This manager can be retrieved using the subBoolPropertyManager() function. In order to provide editing widgets for the subproperties in a property browser widget, this manager must be associated with an editor factory. In addition, QtFlagPropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes, and the flagNamesChanged() signal which is emitted whenever the list of flag names is altered. \sa QtAbstractPropertyManager, QtBoolPropertyManager */ /*! \fn void QtFlagPropertyManager::valueChanged(QtProperty *property, int value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! \fn void QtFlagPropertyManager::flagNamesChanged(QtProperty *property, const QStringList &names) This signal is emitted whenever a property created by this manager changes its flag names, passing a pointer to the \a property and the new \a names as parameters. \sa setFlagNames() */ /*! Creates a manager with the given \a parent. */ QtFlagPropertyManager::QtFlagPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtFlagPropertyManagerPrivate; d_ptr->q_ptr = this; d_ptr->m_boolPropertyManager = new QtBoolPropertyManager(this); connect(d_ptr->m_boolPropertyManager, SIGNAL(valueChanged(QtProperty *, bool)), this, SLOT(slotBoolChanged(QtProperty *, bool))); connect(d_ptr->m_boolPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), this, SLOT(slotPropertyDestroyed(QtProperty *))); } /*! Destroys this manager, and all the properties it has created. */ QtFlagPropertyManager::~QtFlagPropertyManager() { clear(); delete d_ptr; } /*! Returns the manager that produces the nested boolean subproperties representing each flag. In order to provide editing widgets for the subproperties in a property browser widget, this manager must be associated with an editor factory. \sa QtAbstractPropertyBrowser::setFactoryForManager() */ QtBoolPropertyManager *QtFlagPropertyManager::subBoolPropertyManager() const { return d_ptr->m_boolPropertyManager; } /*! Returns the given \a property's value. If the given property is not managed by this manager, this function returns 0. \sa flagNames(), setValue() */ int QtFlagPropertyManager::value(const QtProperty *property) const { return getValue(d_ptr->m_values, property, 0); } /*! Returns the given \a property's list of flag names. \sa value(), setFlagNames() */ QStringList QtFlagPropertyManager::flagNames(const QtProperty *property) const { return getData(d_ptr->m_values, &QtFlagPropertyManagerPrivate::Data::flagNames, property, QStringList()); } /*! \reimp */ QString QtFlagPropertyManager::valueText(const QtProperty *property) const { const QtFlagPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); const QtFlagPropertyManagerPrivate::Data &data = it.value(); QString str; int level = 0; const QChar bar = QLatin1Char('|'); const QStringList::const_iterator fncend = data.flagNames.constEnd(); for (QStringList::const_iterator it = data.flagNames.constBegin(); it != fncend; ++it) { if (data.val & (1 << level)) { if (!str.isEmpty()) str += bar; str += *it; } level++; } return str; } /*! \fn void QtFlagPropertyManager::setValue(QtProperty *property, int value) Sets the value of the given \a property to \a value. Nested properties are updated automatically. The specified \a value must be less than the binary combination of the property's flagNames() list size (i.e. less than 2\sup n, where \c n is the size of the list) and larger than (or equal to) 0. \sa value(), valueChanged() */ void QtFlagPropertyManager::setValue(QtProperty *property, int val) { const QtFlagPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtFlagPropertyManagerPrivate::Data data = it.value(); if (data.val == val) return; if (val > (1 << data.flagNames.count()) - 1) return; if (val < 0) return; data.val = val; it.value() = data; QListIterator itProp(d_ptr->m_propertyToFlags[property]); int level = 0; while (itProp.hasNext()) { QtProperty *prop = itProp.next(); if (prop) d_ptr->m_boolPropertyManager->setValue(prop, val & (1 << level)); level++; } emit propertyChanged(property); emit valueChanged(property, data.val); } /*! Sets the given \a property's list of flag names to \a flagNames. The property's current value is reset to 0 indicating the first item of the list. \sa flagNames(), flagNamesChanged() */ void QtFlagPropertyManager::setFlagNames(QtProperty *property, const QStringList &flagNames) { const QtFlagPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; QtFlagPropertyManagerPrivate::Data data = it.value(); if (data.flagNames == flagNames) return; data.flagNames = flagNames; data.val = 0; it.value() = data; QListIterator itProp(d_ptr->m_propertyToFlags[property]); while (itProp.hasNext()) { QtProperty *prop = itProp.next(); if (prop) { delete prop; d_ptr->m_flagToProperty.remove(prop); } } d_ptr->m_propertyToFlags[property].clear(); QStringListIterator itFlag(flagNames); while (itFlag.hasNext()) { const QString flagName = itFlag.next(); QtProperty *prop = d_ptr->m_boolPropertyManager->addProperty(); prop->setPropertyName(flagName); property->addSubProperty(prop); d_ptr->m_propertyToFlags[property].append(prop); d_ptr->m_flagToProperty[prop] = property; } emit flagNamesChanged(property, data.flagNames); emit propertyChanged(property); emit valueChanged(property, data.val); } /*! \reimp */ void QtFlagPropertyManager::initializeProperty(QtProperty *property) { d_ptr->m_values[property] = QtFlagPropertyManagerPrivate::Data(); d_ptr->m_propertyToFlags[property] = QList(); } /*! \reimp */ void QtFlagPropertyManager::uninitializeProperty(QtProperty *property) { QListIterator itProp(d_ptr->m_propertyToFlags[property]); while (itProp.hasNext()) { QtProperty *prop = itProp.next(); if (prop) { delete prop; d_ptr->m_flagToProperty.remove(prop); } } d_ptr->m_propertyToFlags.remove(property); d_ptr->m_values.remove(property); } // QtSizePolicyPropertyManager class QtSizePolicyPropertyManagerPrivate { QtSizePolicyPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtSizePolicyPropertyManager) public: QtSizePolicyPropertyManagerPrivate(); void slotIntChanged(QtProperty *property, int value); void slotEnumChanged(QtProperty *property, int value); void slotPropertyDestroyed(QtProperty *property); typedef QMap PropertyValueMap; PropertyValueMap m_values; QtIntPropertyManager *m_intPropertyManager; QtEnumPropertyManager *m_enumPropertyManager; QMap m_propertyToHPolicy; QMap m_propertyToVPolicy; QMap m_propertyToHStretch; QMap m_propertyToVStretch; QMap m_hPolicyToProperty; QMap m_vPolicyToProperty; QMap m_hStretchToProperty; QMap m_vStretchToProperty; }; QtSizePolicyPropertyManagerPrivate::QtSizePolicyPropertyManagerPrivate() { } void QtSizePolicyPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) { if (QtProperty *prop = m_hStretchToProperty.value(property, 0)) { QSizePolicy sp = m_values[prop]; sp.setHorizontalStretch(value); q_ptr->setValue(prop, sp); } else if (QtProperty *prop = m_vStretchToProperty.value(property, 0)) { QSizePolicy sp = m_values[prop]; sp.setVerticalStretch(value); q_ptr->setValue(prop, sp); } } void QtSizePolicyPropertyManagerPrivate::slotEnumChanged(QtProperty *property, int value) { if (QtProperty *prop = m_hPolicyToProperty.value(property, 0)) { QSizePolicy sp = m_values[prop]; sp.setHorizontalPolicy(metaEnumProvider()->indexToSizePolicy(value)); q_ptr->setValue(prop, sp); } else if (QtProperty *prop = m_vPolicyToProperty.value(property, 0)) { QSizePolicy sp = m_values[prop]; sp.setVerticalPolicy(metaEnumProvider()->indexToSizePolicy(value)); q_ptr->setValue(prop, sp); } } void QtSizePolicyPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) { if (QtProperty *pointProp = m_hStretchToProperty.value(property, 0)) { m_propertyToHStretch[pointProp] = 0; m_hStretchToProperty.remove(property); } else if (QtProperty *pointProp = m_vStretchToProperty.value(property, 0)) { m_propertyToVStretch[pointProp] = 0; m_vStretchToProperty.remove(property); } else if (QtProperty *pointProp = m_hPolicyToProperty.value(property, 0)) { m_propertyToHPolicy[pointProp] = 0; m_hPolicyToProperty.remove(property); } else if (QtProperty *pointProp = m_vPolicyToProperty.value(property, 0)) { m_propertyToVPolicy[pointProp] = 0; m_vPolicyToProperty.remove(property); } } /*! \class QtSizePolicyPropertyManager \brief The QtSizePolicyPropertyManager provides and manages QSizePolicy properties. A size policy property has nested \e horizontalPolicy, \e verticalPolicy, \e horizontalStretch and \e verticalStretch subproperties. The top-level property's value can be retrieved using the value() function, and set using the setValue() slot. The subproperties are created by QtIntPropertyManager and QtEnumPropertyManager objects. These managers can be retrieved using the subIntPropertyManager() and subEnumPropertyManager() functions respectively. In order to provide editing widgets for the subproperties in a property browser widget, these managers must be associated with editor factories. In addition, QtSizePolicyPropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes. \sa QtAbstractPropertyManager, QtIntPropertyManager, QtEnumPropertyManager */ /*! \fn void QtSizePolicyPropertyManager::valueChanged(QtProperty *property, const QSizePolicy &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! Creates a manager with the given \a parent. */ QtSizePolicyPropertyManager::QtSizePolicyPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtSizePolicyPropertyManagerPrivate; d_ptr->q_ptr = this; d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotIntChanged(QtProperty *, int))); d_ptr->m_enumPropertyManager = new QtEnumPropertyManager(this); connect(d_ptr->m_enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotEnumChanged(QtProperty *, int))); connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), this, SLOT(slotPropertyDestroyed(QtProperty *))); connect(d_ptr->m_enumPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), this, SLOT(slotPropertyDestroyed(QtProperty *))); } /*! Destroys this manager, and all the properties it has created. */ QtSizePolicyPropertyManager::~QtSizePolicyPropertyManager() { clear(); delete d_ptr; } /*! Returns the manager that creates the nested \e horizontalStretch and \e verticalStretch subproperties. In order to provide editing widgets for the mentioned subproperties in a property browser widget, this manager must be associated with an editor factory. \sa QtAbstractPropertyBrowser::setFactoryForManager() */ QtIntPropertyManager *QtSizePolicyPropertyManager::subIntPropertyManager() const { return d_ptr->m_intPropertyManager; } /*! Returns the manager that creates the nested \e horizontalPolicy and \e verticalPolicy subproperties. In order to provide editing widgets for the mentioned subproperties in a property browser widget, this manager must be associated with an editor factory. \sa QtAbstractPropertyBrowser::setFactoryForManager() */ QtEnumPropertyManager *QtSizePolicyPropertyManager::subEnumPropertyManager() const { return d_ptr->m_enumPropertyManager; } /*! Returns the given \a property's value. If the given property is not managed by this manager, this function returns the default size policy. \sa setValue() */ QSizePolicy QtSizePolicyPropertyManager::value(const QtProperty *property) const { return d_ptr->m_values.value(property, QSizePolicy()); } /*! \reimp */ QString QtSizePolicyPropertyManager::valueText(const QtProperty *property) const { const QtSizePolicyPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); const QSizePolicy sp = it.value(); const QtMetaEnumProvider *mep = metaEnumProvider(); const int hIndex = mep->sizePolicyToIndex(sp.horizontalPolicy()); const int vIndex = mep->sizePolicyToIndex(sp.verticalPolicy()); //! Unknown size policy on reading invalid uic3 files const QString hPolicy = hIndex != -1 ? mep->policyEnumNames().at(hIndex) : tr(""); const QString vPolicy = vIndex != -1 ? mep->policyEnumNames().at(vIndex) : tr(""); const QString str = tr("[%1, %2, %3, %4]").arg(hPolicy, vPolicy).arg(sp.horizontalStretch()).arg(sp.verticalStretch()); return str; } /*! \fn void QtSizePolicyPropertyManager::setValue(QtProperty *property, const QSizePolicy &value) Sets the value of the given \a property to \a value. Nested properties are updated automatically. \sa value(), valueChanged() */ void QtSizePolicyPropertyManager::setValue(QtProperty *property, const QSizePolicy &val) { const QtSizePolicyPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; if (it.value() == val) return; it.value() = val; d_ptr->m_enumPropertyManager->setValue(d_ptr->m_propertyToHPolicy[property], metaEnumProvider()->sizePolicyToIndex(val.horizontalPolicy())); d_ptr->m_enumPropertyManager->setValue(d_ptr->m_propertyToVPolicy[property], metaEnumProvider()->sizePolicyToIndex(val.verticalPolicy())); d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToHStretch[property], val.horizontalStretch()); d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToVStretch[property], val.verticalStretch()); emit propertyChanged(property); emit valueChanged(property, val); } /*! \reimp */ void QtSizePolicyPropertyManager::initializeProperty(QtProperty *property) { QSizePolicy val; d_ptr->m_values[property] = val; QtProperty *hPolicyProp = d_ptr->m_enumPropertyManager->addProperty(); hPolicyProp->setPropertyName(tr("Horizontal Policy")); d_ptr->m_enumPropertyManager->setEnumNames(hPolicyProp, metaEnumProvider()->policyEnumNames()); d_ptr->m_enumPropertyManager->setValue(hPolicyProp, metaEnumProvider()->sizePolicyToIndex(val.horizontalPolicy())); d_ptr->m_propertyToHPolicy[property] = hPolicyProp; d_ptr->m_hPolicyToProperty[hPolicyProp] = property; property->addSubProperty(hPolicyProp); QtProperty *vPolicyProp = d_ptr->m_enumPropertyManager->addProperty(); vPolicyProp->setPropertyName(tr("Vertical Policy")); d_ptr->m_enumPropertyManager->setEnumNames(vPolicyProp, metaEnumProvider()->policyEnumNames()); d_ptr->m_enumPropertyManager->setValue(vPolicyProp, metaEnumProvider()->sizePolicyToIndex(val.verticalPolicy())); d_ptr->m_propertyToVPolicy[property] = vPolicyProp; d_ptr->m_vPolicyToProperty[vPolicyProp] = property; property->addSubProperty(vPolicyProp); QtProperty *hStretchProp = d_ptr->m_intPropertyManager->addProperty(); hStretchProp->setPropertyName(tr("Horizontal Stretch")); d_ptr->m_intPropertyManager->setValue(hStretchProp, val.horizontalStretch()); d_ptr->m_intPropertyManager->setRange(hStretchProp, 0, 0xff); d_ptr->m_propertyToHStretch[property] = hStretchProp; d_ptr->m_hStretchToProperty[hStretchProp] = property; property->addSubProperty(hStretchProp); QtProperty *vStretchProp = d_ptr->m_intPropertyManager->addProperty(); vStretchProp->setPropertyName(tr("Vertical Stretch")); d_ptr->m_intPropertyManager->setValue(vStretchProp, val.verticalStretch()); d_ptr->m_intPropertyManager->setRange(vStretchProp, 0, 0xff); d_ptr->m_propertyToVStretch[property] = vStretchProp; d_ptr->m_vStretchToProperty[vStretchProp] = property; property->addSubProperty(vStretchProp); } /*! \reimp */ void QtSizePolicyPropertyManager::uninitializeProperty(QtProperty *property) { QtProperty *hPolicyProp = d_ptr->m_propertyToHPolicy[property]; if (hPolicyProp) { d_ptr->m_hPolicyToProperty.remove(hPolicyProp); delete hPolicyProp; } d_ptr->m_propertyToHPolicy.remove(property); QtProperty *vPolicyProp = d_ptr->m_propertyToVPolicy[property]; if (vPolicyProp) { d_ptr->m_vPolicyToProperty.remove(vPolicyProp); delete vPolicyProp; } d_ptr->m_propertyToVPolicy.remove(property); QtProperty *hStretchProp = d_ptr->m_propertyToHStretch[property]; if (hStretchProp) { d_ptr->m_hStretchToProperty.remove(hStretchProp); delete hStretchProp; } d_ptr->m_propertyToHStretch.remove(property); QtProperty *vStretchProp = d_ptr->m_propertyToVStretch[property]; if (vStretchProp) { d_ptr->m_vStretchToProperty.remove(vStretchProp); delete vStretchProp; } d_ptr->m_propertyToVStretch.remove(property); d_ptr->m_values.remove(property); } // QtFontPropertyManager: // QtFontPropertyManagerPrivate has a mechanism for reacting // to QApplication::fontDatabaseChanged() [4.5], which is emitted // when someone loads an application font. The signals are compressed // using a timer with interval 0, which then causes the family // enumeration manager to re-set its strings and index values // for each property. Q_GLOBAL_STATIC(QFontDatabase, fontDatabase) class QtFontPropertyManagerPrivate { QtFontPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtFontPropertyManager) public: QtFontPropertyManagerPrivate(); void slotIntChanged(QtProperty *property, int value); void slotEnumChanged(QtProperty *property, int value); void slotBoolChanged(QtProperty *property, bool value); void slotPropertyDestroyed(QtProperty *property); void slotFontDatabaseChanged(); void slotFontDatabaseDelayedChange(); QStringList m_familyNames; typedef QMap PropertyValueMap; PropertyValueMap m_values; QtIntPropertyManager *m_intPropertyManager; QtEnumPropertyManager *m_enumPropertyManager; QtBoolPropertyManager *m_boolPropertyManager; QMap m_propertyToFamily; QMap m_propertyToPixelSize; QMap m_propertyToBold; QMap m_propertyToItalic; QMap m_propertyToUnderline; QMap m_propertyToStrikeOut; QMap m_propertyToKerning; QMap m_familyToProperty; QMap m_pixelSizeToProperty; QMap m_boldToProperty; QMap m_italicToProperty; QMap m_underlineToProperty; QMap m_strikeOutToProperty; QMap m_kerningToProperty; bool m_settingValue; QTimer *m_fontDatabaseChangeTimer; }; QtFontPropertyManagerPrivate::QtFontPropertyManagerPrivate() : m_settingValue(false), m_fontDatabaseChangeTimer(0) { } void QtFontPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) { if (m_settingValue) return; if (QtProperty *prop = m_pixelSizeToProperty.value(property, 0)) { QFont f = m_values[prop]; f.setPixelSize(value); q_ptr->setValue(prop, f); } } void QtFontPropertyManagerPrivate::slotEnumChanged(QtProperty *property, int value) { if (m_settingValue) return; if (QtProperty *prop = m_familyToProperty.value(property, 0)) { QFont f = m_values[prop]; f.setFamily(m_familyNames.at(value)); q_ptr->setValue(prop, f); } } void QtFontPropertyManagerPrivate::slotBoolChanged(QtProperty *property, bool value) { if (m_settingValue) return; if (QtProperty *prop = m_boldToProperty.value(property, 0)) { QFont f = m_values[prop]; f.setBold(value); q_ptr->setValue(prop, f); } else if (QtProperty *prop = m_italicToProperty.value(property, 0)) { QFont f = m_values[prop]; f.setItalic(value); q_ptr->setValue(prop, f); } else if (QtProperty *prop = m_underlineToProperty.value(property, 0)) { QFont f = m_values[prop]; f.setUnderline(value); q_ptr->setValue(prop, f); } else if (QtProperty *prop = m_strikeOutToProperty.value(property, 0)) { QFont f = m_values[prop]; f.setStrikeOut(value); q_ptr->setValue(prop, f); } else if (QtProperty *prop = m_kerningToProperty.value(property, 0)) { QFont f = m_values[prop]; f.setKerning(value); q_ptr->setValue(prop, f); } } void QtFontPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) { if (QtProperty *pixelProp = m_pixelSizeToProperty.value(property, 0)) { m_propertyToPixelSize[pixelProp] = 0; m_pixelSizeToProperty.remove(property); } else if (QtProperty *pointProp = m_familyToProperty.value(property, 0)) { m_propertyToFamily[pointProp] = 0; m_familyToProperty.remove(property); } else if (QtProperty *pointProp = m_boldToProperty.value(property, 0)) { m_propertyToBold[pointProp] = 0; m_boldToProperty.remove(property); } else if (QtProperty *pointProp = m_italicToProperty.value(property, 0)) { m_propertyToItalic[pointProp] = 0; m_italicToProperty.remove(property); } else if (QtProperty *pointProp = m_underlineToProperty.value(property, 0)) { m_propertyToUnderline[pointProp] = 0; m_underlineToProperty.remove(property); } else if (QtProperty *pointProp = m_strikeOutToProperty.value(property, 0)) { m_propertyToStrikeOut[pointProp] = 0; m_strikeOutToProperty.remove(property); } else if (QtProperty *pointProp = m_kerningToProperty.value(property, 0)) { m_propertyToKerning[pointProp] = 0; m_kerningToProperty.remove(property); } } void QtFontPropertyManagerPrivate::slotFontDatabaseChanged() { if (!m_fontDatabaseChangeTimer) { m_fontDatabaseChangeTimer = new QTimer(q_ptr); m_fontDatabaseChangeTimer->setInterval(0); m_fontDatabaseChangeTimer->setSingleShot(true); QObject::connect(m_fontDatabaseChangeTimer, SIGNAL(timeout()), q_ptr, SLOT(slotFontDatabaseDelayedChange())); } if (!m_fontDatabaseChangeTimer->isActive()) m_fontDatabaseChangeTimer->start(); } void QtFontPropertyManagerPrivate::slotFontDatabaseDelayedChange() { typedef QMap PropertyPropertyMap; // rescan available font names const QStringList oldFamilies = m_familyNames; m_familyNames = fontDatabase()->families(); // Adapt all existing properties if (!m_propertyToFamily.empty()) { PropertyPropertyMap::const_iterator cend = m_propertyToFamily.constEnd(); for (PropertyPropertyMap::const_iterator it = m_propertyToFamily.constBegin(); it != cend; ++it) { QtProperty *familyProp = it.value(); const int oldIdx = m_enumPropertyManager->value(familyProp); int newIdx = m_familyNames.indexOf(oldFamilies.at(oldIdx)); if (newIdx < 0) newIdx = 0; m_enumPropertyManager->setEnumNames(familyProp, m_familyNames); m_enumPropertyManager->setValue(familyProp, newIdx); } } } /*! \class QtFontPropertyManager \brief The QtFontPropertyManager provides and manages QFont properties. A font property has nested \e family, \e pointSize, \e bold, \e italic, \e underline, \e strikeOut and \e kerning subproperties. The top-level property's value can be retrieved using the value() function, and set using the setValue() slot. The subproperties are created by QtIntPropertyManager, QtEnumPropertyManager and QtBoolPropertyManager objects. These managers can be retrieved using the corresponding subIntPropertyManager(), subEnumPropertyManager() and subBoolPropertyManager() functions. In order to provide editing widgets for the subproperties in a property browser widget, these managers must be associated with editor factories. In addition, QtFontPropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes. \sa QtAbstractPropertyManager, QtEnumPropertyManager, QtIntPropertyManager, QtBoolPropertyManager */ /*! \fn void QtFontPropertyManager::valueChanged(QtProperty *property, const QFont &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! Creates a manager with the given \a parent. */ QtFontPropertyManager::QtFontPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtFontPropertyManagerPrivate; d_ptr->q_ptr = this; #if QT_VERSION >= 0x040500 QObject::connect(qApp, SIGNAL(fontDatabaseChanged()), this, SLOT(slotFontDatabaseChanged())); #endif d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotIntChanged(QtProperty *, int))); d_ptr->m_enumPropertyManager = new QtEnumPropertyManager(this); connect(d_ptr->m_enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotEnumChanged(QtProperty *, int))); d_ptr->m_boolPropertyManager = new QtBoolPropertyManager(this); connect(d_ptr->m_boolPropertyManager, SIGNAL(valueChanged(QtProperty *, bool)), this, SLOT(slotBoolChanged(QtProperty *, bool))); connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), this, SLOT(slotPropertyDestroyed(QtProperty *))); connect(d_ptr->m_enumPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), this, SLOT(slotPropertyDestroyed(QtProperty *))); connect(d_ptr->m_boolPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), this, SLOT(slotPropertyDestroyed(QtProperty *))); } /*! Destroys this manager, and all the properties it has created. */ QtFontPropertyManager::~QtFontPropertyManager() { clear(); delete d_ptr; } /*! Returns the manager that creates the \e pointSize subproperty. In order to provide editing widgets for the \e pointSize property in a property browser widget, this manager must be associated with an editor factory. \sa QtAbstractPropertyBrowser::setFactoryForManager() */ QtIntPropertyManager *QtFontPropertyManager::subIntPropertyManager() const { return d_ptr->m_intPropertyManager; } /*! Returns the manager that create the \e family subproperty. In order to provide editing widgets for the \e family property in a property browser widget, this manager must be associated with an editor factory. \sa QtAbstractPropertyBrowser::setFactoryForManager() */ QtEnumPropertyManager *QtFontPropertyManager::subEnumPropertyManager() const { return d_ptr->m_enumPropertyManager; } /*! Returns the manager that creates the \e bold, \e italic, \e underline, \e strikeOut and \e kerning subproperties. In order to provide editing widgets for the mentioned properties in a property browser widget, this manager must be associated with an editor factory. \sa QtAbstractPropertyBrowser::setFactoryForManager() */ QtBoolPropertyManager *QtFontPropertyManager::subBoolPropertyManager() const { return d_ptr->m_boolPropertyManager; } /*! Returns the given \a property's value. If the given property is not managed by this manager, this function returns a font object that uses the application's default font. \sa setValue() */ QFont QtFontPropertyManager::value(const QtProperty *property) const { return d_ptr->m_values.value(property, QFont()); } /*! \reimp */ QString QtFontPropertyManager::valueText(const QtProperty *property) const { const QtFontPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); return QtPropertyBrowserUtils::fontValueText(it.value()); } /*! \reimp */ QIcon QtFontPropertyManager::valueIcon(const QtProperty *property) const { const QtFontPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QIcon(); return QtPropertyBrowserUtils::fontValueIcon(it.value()); } /*! \fn void QtFontPropertyManager::setValue(QtProperty *property, const QFont &value) Sets the value of the given \a property to \a value. Nested properties are updated automatically. \sa value(), valueChanged() */ void QtFontPropertyManager::setValue(QtProperty *property, const QFont &val) { const QtFontPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; const QFont oldVal = it.value(); if (oldVal == val && oldVal.resolve() == val.resolve()) return; it.value() = val; int idx = d_ptr->m_familyNames.indexOf(val.family()); if (idx == -1) idx = 0; bool settingValue = d_ptr->m_settingValue; d_ptr->m_settingValue = true; d_ptr->m_enumPropertyManager->setValue(d_ptr->m_propertyToFamily[property], idx); d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToPixelSize[property], val.pixelSize()); d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToBold[property], val.bold()); d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToItalic[property], val.italic()); d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToUnderline[property], val.underline()); d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToStrikeOut[property], val.strikeOut()); d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToKerning[property], val.kerning()); d_ptr->m_settingValue = settingValue; emit propertyChanged(property); emit valueChanged(property, val); } /*! \reimp */ void QtFontPropertyManager::initializeProperty(QtProperty *property) { QFont val; d_ptr->m_values[property] = val; QtProperty *familyProp = d_ptr->m_enumPropertyManager->addProperty(); familyProp->setPropertyName(tr("Family")); if (d_ptr->m_familyNames.empty()) d_ptr->m_familyNames = fontDatabase()->families(); d_ptr->m_enumPropertyManager->setEnumNames(familyProp, d_ptr->m_familyNames); int idx = d_ptr->m_familyNames.indexOf(val.family()); if (idx == -1) idx = 0; d_ptr->m_enumPropertyManager->setValue(familyProp, idx); d_ptr->m_propertyToFamily[property] = familyProp; d_ptr->m_familyToProperty[familyProp] = property; property->addSubProperty(familyProp); QtProperty *pixelSizeProp = d_ptr->m_intPropertyManager->addProperty(); pixelSizeProp->setPropertyName(tr("Pixel Size")); d_ptr->m_intPropertyManager->setValue(pixelSizeProp, val.pointSize()); d_ptr->m_intPropertyManager->setMinimum(pixelSizeProp, 1); d_ptr->m_propertyToPixelSize[property] = pixelSizeProp; d_ptr->m_pixelSizeToProperty[pixelSizeProp] = property; property->addSubProperty(pixelSizeProp); QtProperty *boldProp = d_ptr->m_boolPropertyManager->addProperty(); boldProp->setPropertyName(tr("Bold")); d_ptr->m_boolPropertyManager->setValue(boldProp, val.bold()); d_ptr->m_propertyToBold[property] = boldProp; d_ptr->m_boldToProperty[boldProp] = property; property->addSubProperty(boldProp); QtProperty *italicProp = d_ptr->m_boolPropertyManager->addProperty(); italicProp->setPropertyName(tr("Italic")); d_ptr->m_boolPropertyManager->setValue(italicProp, val.italic()); d_ptr->m_propertyToItalic[property] = italicProp; d_ptr->m_italicToProperty[italicProp] = property; property->addSubProperty(italicProp); QtProperty *underlineProp = d_ptr->m_boolPropertyManager->addProperty(); underlineProp->setPropertyName(tr("Underline")); d_ptr->m_boolPropertyManager->setValue(underlineProp, val.underline()); d_ptr->m_propertyToUnderline[property] = underlineProp; d_ptr->m_underlineToProperty[underlineProp] = property; property->addSubProperty(underlineProp); QtProperty *strikeOutProp = d_ptr->m_boolPropertyManager->addProperty(); strikeOutProp->setPropertyName(tr("Strikeout")); d_ptr->m_boolPropertyManager->setValue(strikeOutProp, val.strikeOut()); d_ptr->m_propertyToStrikeOut[property] = strikeOutProp; d_ptr->m_strikeOutToProperty[strikeOutProp] = property; property->addSubProperty(strikeOutProp); QtProperty *kerningProp = d_ptr->m_boolPropertyManager->addProperty(); kerningProp->setPropertyName(tr("Kerning")); d_ptr->m_boolPropertyManager->setValue(kerningProp, val.kerning()); d_ptr->m_propertyToKerning[property] = kerningProp; d_ptr->m_kerningToProperty[kerningProp] = property; property->addSubProperty(kerningProp); } /*! \reimp */ void QtFontPropertyManager::uninitializeProperty(QtProperty *property) { QtProperty *familyProp = d_ptr->m_propertyToFamily[property]; if (familyProp) { d_ptr->m_familyToProperty.remove(familyProp); delete familyProp; } d_ptr->m_propertyToFamily.remove(property); QtProperty *pixelSizeProp = d_ptr->m_propertyToPixelSize[property]; if (pixelSizeProp) { d_ptr->m_pixelSizeToProperty.remove(pixelSizeProp); delete pixelSizeProp; } d_ptr->m_propertyToPixelSize.remove(property); QtProperty *boldProp = d_ptr->m_propertyToBold[property]; if (boldProp) { d_ptr->m_boldToProperty.remove(boldProp); delete boldProp; } d_ptr->m_propertyToBold.remove(property); QtProperty *italicProp = d_ptr->m_propertyToItalic[property]; if (italicProp) { d_ptr->m_italicToProperty.remove(italicProp); delete italicProp; } d_ptr->m_propertyToItalic.remove(property); QtProperty *underlineProp = d_ptr->m_propertyToUnderline[property]; if (underlineProp) { d_ptr->m_underlineToProperty.remove(underlineProp); delete underlineProp; } d_ptr->m_propertyToUnderline.remove(property); QtProperty *strikeOutProp = d_ptr->m_propertyToStrikeOut[property]; if (strikeOutProp) { d_ptr->m_strikeOutToProperty.remove(strikeOutProp); delete strikeOutProp; } d_ptr->m_propertyToStrikeOut.remove(property); QtProperty *kerningProp = d_ptr->m_propertyToKerning[property]; if (kerningProp) { d_ptr->m_kerningToProperty.remove(kerningProp); delete kerningProp; } d_ptr->m_propertyToKerning.remove(property); d_ptr->m_values.remove(property); } // QtColorPropertyManager class QtColorPropertyManagerPrivate { QtColorPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtColorPropertyManager) public: void slotIntChanged(QtProperty *property, int value); void slotPropertyDestroyed(QtProperty *property); typedef QMap PropertyValueMap; PropertyValueMap m_values; QtIntPropertyManager *m_intPropertyManager; bool m_applyingValueChange; QMap m_propertyToR; QMap m_propertyToG; QMap m_propertyToB; QMap m_propertyToA; QMap m_rToProperty; QMap m_gToProperty; QMap m_bToProperty; QMap m_aToProperty; }; void QtColorPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) { if (m_applyingValueChange) return; if (QtProperty *prop = m_rToProperty.value(property, 0)) { QColor c = m_values[prop]; c.setRed(value); q_ptr->setValue(prop, c); } else if (QtProperty *prop = m_gToProperty.value(property, 0)) { QColor c = m_values[prop]; c.setGreen(value); q_ptr->setValue(prop, c); } else if (QtProperty *prop = m_bToProperty.value(property, 0)) { QColor c = m_values[prop]; c.setBlue(value); q_ptr->setValue(prop, c); } else if (QtProperty *prop = m_aToProperty.value(property, 0)) { QColor c = m_values[prop]; c.setAlpha(value); q_ptr->setValue(prop, c); } } void QtColorPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) { if (QtProperty *pointProp = m_rToProperty.value(property, 0)) { m_propertyToR[pointProp] = 0; m_rToProperty.remove(property); } else if (QtProperty *pointProp = m_gToProperty.value(property, 0)) { m_propertyToG[pointProp] = 0; m_gToProperty.remove(property); } else if (QtProperty *pointProp = m_bToProperty.value(property, 0)) { m_propertyToB[pointProp] = 0; m_bToProperty.remove(property); } else if (QtProperty *pointProp = m_aToProperty.value(property, 0)) { m_propertyToA[pointProp] = 0; m_aToProperty.remove(property); } } /*! \class QtColorPropertyManager \brief The QtColorPropertyManager provides and manages QColor properties. A color property has nested \e red, \e green and \e blue subproperties. The top-level property's value can be retrieved using the value() function, and set using the setValue() slot. The subproperties are created by a QtIntPropertyManager object. This manager can be retrieved using the subIntPropertyManager() function. In order to provide editing widgets for the subproperties in a property browser widget, this manager must be associated with an editor factory. In addition, QtColorPropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes. \sa QtAbstractPropertyManager, QtAbstractPropertyBrowser, QtIntPropertyManager */ /*! \fn void QtColorPropertyManager::valueChanged(QtProperty *property, const QColor &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! Creates a manager with the given \a parent. */ QtColorPropertyManager::QtColorPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtColorPropertyManagerPrivate; d_ptr->q_ptr = this; d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); d_ptr->m_applyingValueChange = false; connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotIntChanged(QtProperty *, int))); connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), this, SLOT(slotPropertyDestroyed(QtProperty *))); } /*! Destroys this manager, and all the properties it has created. */ QtColorPropertyManager::~QtColorPropertyManager() { clear(); delete d_ptr; } /*! Returns the manager that produces the nested \e red, \e green and \e blue subproperties. In order to provide editing widgets for the subproperties in a property browser widget, this manager must be associated with an editor factory. \sa QtAbstractPropertyBrowser::setFactoryForManager() */ QtIntPropertyManager *QtColorPropertyManager::subIntPropertyManager() const { return d_ptr->m_intPropertyManager; } /*! Returns the given \a property's value. If the given \a property is not managed by \e this manager, this function returns an invalid color. \sa setValue() */ QColor QtColorPropertyManager::value(const QtProperty *property) const { return d_ptr->m_values.value(property, QColor()); } /*! \reimp */ QString QtColorPropertyManager::valueText(const QtProperty *property) const { const QtColorPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); return QtPropertyBrowserUtils::colorValueText(it.value()); } /*! \reimp */ QIcon QtColorPropertyManager::valueIcon(const QtProperty *property) const { const QtColorPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QIcon(); if (!it.value().isValid()) return QIcon(); return QtPropertyBrowserUtils::brushValueIcon(QBrush(it.value())); } /*! \fn void QtColorPropertyManager::setValue(QtProperty *property, const QColor &value) Sets the value of the given \a property to \a value. Nested properties are updated automatically. \sa value(), valueChanged() */ void QtColorPropertyManager::setValue(QtProperty *property, const QColor &val) { const QtColorPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; if (it.value() == val) return; it.value() = val; d_ptr->m_applyingValueChange = true; d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToR[property], val.red()); d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToG[property], val.green()); d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToB[property], val.blue()); d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToA[property], val.alpha()); d_ptr->m_applyingValueChange = false; emit propertyChanged(property); emit valueChanged(property, val); } /*! \reimp */ void QtColorPropertyManager::initializeProperty(QtProperty *property) { QColor val; d_ptr->m_values[property] = val; QtProperty *rProp = d_ptr->m_intPropertyManager->addProperty(); rProp->setPropertyName(tr("Red")); d_ptr->m_intPropertyManager->setValue(rProp, val.red()); d_ptr->m_intPropertyManager->setRange(rProp, 0, 0xFF); d_ptr->m_propertyToR[property] = rProp; d_ptr->m_rToProperty[rProp] = property; property->addSubProperty(rProp); QtProperty *gProp = d_ptr->m_intPropertyManager->addProperty(); gProp->setPropertyName(tr("Green")); d_ptr->m_intPropertyManager->setValue(gProp, val.green()); d_ptr->m_intPropertyManager->setRange(gProp, 0, 0xFF); d_ptr->m_propertyToG[property] = gProp; d_ptr->m_gToProperty[gProp] = property; property->addSubProperty(gProp); QtProperty *bProp = d_ptr->m_intPropertyManager->addProperty(); bProp->setPropertyName(tr("Blue")); d_ptr->m_intPropertyManager->setValue(bProp, val.blue()); d_ptr->m_intPropertyManager->setRange(bProp, 0, 0xFF); d_ptr->m_propertyToB[property] = bProp; d_ptr->m_bToProperty[bProp] = property; property->addSubProperty(bProp); QtProperty *aProp = d_ptr->m_intPropertyManager->addProperty(); aProp->setPropertyName(tr("Alpha")); d_ptr->m_intPropertyManager->setValue(aProp, val.alpha()); d_ptr->m_intPropertyManager->setRange(aProp, 0, 0xFF); d_ptr->m_propertyToA[property] = aProp; d_ptr->m_aToProperty[aProp] = property; property->addSubProperty(aProp); } /*! \reimp */ void QtColorPropertyManager::uninitializeProperty(QtProperty *property) { QtProperty *rProp = d_ptr->m_propertyToR[property]; if (rProp) { d_ptr->m_rToProperty.remove(rProp); delete rProp; } d_ptr->m_propertyToR.remove(property); QtProperty *gProp = d_ptr->m_propertyToG[property]; if (gProp) { d_ptr->m_gToProperty.remove(gProp); delete gProp; } d_ptr->m_propertyToG.remove(property); QtProperty *bProp = d_ptr->m_propertyToB[property]; if (bProp) { d_ptr->m_bToProperty.remove(bProp); delete bProp; } d_ptr->m_propertyToB.remove(property); QtProperty *aProp = d_ptr->m_propertyToA[property]; if (aProp) { d_ptr->m_aToProperty.remove(aProp); delete aProp; } d_ptr->m_propertyToA.remove(property); d_ptr->m_values.remove(property); } // QtCursorPropertyManager // Make sure icons are removed as soon as QApplication is destroyed, otherwise, // handles are leaked on X11. static void clearCursorDatabase(); namespace { struct CursorDatabase : public QtCursorDatabase { CursorDatabase() { qAddPostRoutine(clearCursorDatabase); } }; } Q_GLOBAL_STATIC(QtCursorDatabase, cursorDatabase) static void clearCursorDatabase() { cursorDatabase()->clear(); } class QtCursorPropertyManagerPrivate { QtCursorPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtCursorPropertyManager) public: typedef QMap PropertyValueMap; PropertyValueMap m_values; }; /*! \class QtCursorPropertyManager \brief The QtCursorPropertyManager provides and manages QCursor properties. A cursor property has a current value which can be retrieved using the value() function, and set using the setValue() slot. In addition, QtCursorPropertyManager provides the valueChanged() signal which is emitted whenever a property created by this manager changes. \sa QtAbstractPropertyManager */ /*! \fn void QtCursorPropertyManager::valueChanged(QtProperty *property, const QCursor &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! Creates a manager with the given \a parent. */ QtCursorPropertyManager::QtCursorPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtCursorPropertyManagerPrivate; d_ptr->q_ptr = this; } /*! Destroys this manager, and all the properties it has created. */ QtCursorPropertyManager::~QtCursorPropertyManager() { clear(); delete d_ptr; } /*! Returns the given \a property's value. If the given \a property is not managed by this manager, this function returns a default QCursor object. \sa setValue() */ #ifndef QT_NO_CURSOR QCursor QtCursorPropertyManager::value(const QtProperty *property) const { return d_ptr->m_values.value(property, QCursor()); } #endif /*! \reimp */ QString QtCursorPropertyManager::valueText(const QtProperty *property) const { const QtCursorPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); return cursorDatabase()->cursorToShapeName(it.value()); } /*! \reimp */ QIcon QtCursorPropertyManager::valueIcon(const QtProperty *property) const { const QtCursorPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QIcon(); return cursorDatabase()->cursorToShapeIcon(it.value()); } /*! \fn void QtCursorPropertyManager::setValue(QtProperty *property, const QCursor &value) Sets the value of the given \a property to \a value. \sa value(), valueChanged() */ void QtCursorPropertyManager::setValue(QtProperty *property, const QCursor &value) { #ifndef QT_NO_CURSOR const QtCursorPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); if (it == d_ptr->m_values.end()) return; if (it.value().shape() == value.shape() && value.shape() != Qt::BitmapCursor) return; it.value() = value; emit propertyChanged(property); emit valueChanged(property, value); #endif } /*! \reimp */ void QtCursorPropertyManager::initializeProperty(QtProperty *property) { #ifndef QT_NO_CURSOR d_ptr->m_values[property] = QCursor(); #endif } /*! \reimp */ void QtCursorPropertyManager::uninitializeProperty(QtProperty *property) { d_ptr->m_values.remove(property); } #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif #include "moc_qtpropertymanager.cpp" #include "qtpropertymanager.moc" tiled-1.0.3/src/qtpropertybrowser/src/qtpropertymanager.h000066400000000000000000000662011315121121300237570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTPROPERTYMANAGER_H #define QTPROPERTYMANAGER_H #include "qtpropertybrowser.h" #include #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif class QDate; class QTime; class QDateTime; class QLocale; class QT_QTPROPERTYBROWSER_EXPORT QtGroupPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtGroupPropertyManager(QObject *parent = 0); ~QtGroupPropertyManager(); protected: virtual bool hasValue(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); }; class QtIntPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtIntPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtIntPropertyManager(QObject *parent = 0); ~QtIntPropertyManager(); int value(const QtProperty *property) const; int minimum(const QtProperty *property) const; int maximum(const QtProperty *property) const; int singleStep(const QtProperty *property) const; bool isReadOnly(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, int val); void setMinimum(QtProperty *property, int minVal); void setMaximum(QtProperty *property, int maxVal); void setRange(QtProperty *property, int minVal, int maxVal); void setSingleStep(QtProperty *property, int step); void setReadOnly(QtProperty *property, bool readOnly); Q_SIGNALS: void valueChanged(QtProperty *property, int val); void rangeChanged(QtProperty *property, int minVal, int maxVal); void singleStepChanged(QtProperty *property, int step); void readOnlyChanged(QtProperty *property, bool readOnly); protected: QString valueText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtIntPropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtIntPropertyManager) Q_DISABLE_COPY(QtIntPropertyManager) }; class QtBoolPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtBoolPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtBoolPropertyManager(QObject *parent = 0); ~QtBoolPropertyManager(); bool value(const QtProperty *property) const; bool textVisible(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, bool val); void setTextVisible(QtProperty *property, bool textVisible); Q_SIGNALS: void valueChanged(QtProperty *property, bool val); void textVisibleChanged(QtProperty *property, bool); protected: QString valueText(const QtProperty *property) const; QIcon valueIcon(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtBoolPropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtBoolPropertyManager) Q_DISABLE_COPY(QtBoolPropertyManager) }; class QtDoublePropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtDoublePropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtDoublePropertyManager(QObject *parent = 0); ~QtDoublePropertyManager(); double value(const QtProperty *property) const; double minimum(const QtProperty *property) const; double maximum(const QtProperty *property) const; double singleStep(const QtProperty *property) const; int decimals(const QtProperty *property) const; bool isReadOnly(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, double val); void setMinimum(QtProperty *property, double minVal); void setMaximum(QtProperty *property, double maxVal); void setRange(QtProperty *property, double minVal, double maxVal); void setSingleStep(QtProperty *property, double step); void setDecimals(QtProperty *property, int prec); void setReadOnly(QtProperty *property, bool readOnly); Q_SIGNALS: void valueChanged(QtProperty *property, double val); void rangeChanged(QtProperty *property, double minVal, double maxVal); void singleStepChanged(QtProperty *property, double step); void decimalsChanged(QtProperty *property, int prec); void readOnlyChanged(QtProperty *property, bool readOnly); protected: QString valueText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtDoublePropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtDoublePropertyManager) Q_DISABLE_COPY(QtDoublePropertyManager) }; class QtStringPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtStringPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtStringPropertyManager(QObject *parent = 0); ~QtStringPropertyManager(); QString value(const QtProperty *property) const; QRegExp regExp(const QtProperty *property) const; EchoMode echoMode(const QtProperty *property) const; bool isReadOnly(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, const QString &val); void setRegExp(QtProperty *property, const QRegExp ®Exp); void setEchoMode(QtProperty *property, EchoMode echoMode); void setReadOnly(QtProperty *property, bool readOnly); Q_SIGNALS: void valueChanged(QtProperty *property, const QString &val); void regExpChanged(QtProperty *property, const QRegExp ®Exp); void echoModeChanged(QtProperty *property, const int); void readOnlyChanged(QtProperty *property, bool); protected: QString valueText(const QtProperty *property) const; QString displayText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtStringPropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtStringPropertyManager) Q_DISABLE_COPY(QtStringPropertyManager) }; class QtDatePropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtDatePropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtDatePropertyManager(QObject *parent = 0); ~QtDatePropertyManager(); QDate value(const QtProperty *property) const; QDate minimum(const QtProperty *property) const; QDate maximum(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, const QDate &val); void setMinimum(QtProperty *property, const QDate &minVal); void setMaximum(QtProperty *property, const QDate &maxVal); void setRange(QtProperty *property, const QDate &minVal, const QDate &maxVal); Q_SIGNALS: void valueChanged(QtProperty *property, const QDate &val); void rangeChanged(QtProperty *property, const QDate &minVal, const QDate &maxVal); protected: QString valueText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtDatePropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtDatePropertyManager) Q_DISABLE_COPY(QtDatePropertyManager) }; class QtTimePropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtTimePropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtTimePropertyManager(QObject *parent = 0); ~QtTimePropertyManager(); QTime value(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, const QTime &val); Q_SIGNALS: void valueChanged(QtProperty *property, const QTime &val); protected: QString valueText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtTimePropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtTimePropertyManager) Q_DISABLE_COPY(QtTimePropertyManager) }; class QtDateTimePropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtDateTimePropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtDateTimePropertyManager(QObject *parent = 0); ~QtDateTimePropertyManager(); QDateTime value(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, const QDateTime &val); Q_SIGNALS: void valueChanged(QtProperty *property, const QDateTime &val); protected: QString valueText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtDateTimePropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtDateTimePropertyManager) Q_DISABLE_COPY(QtDateTimePropertyManager) }; class QtKeySequencePropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtKeySequencePropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtKeySequencePropertyManager(QObject *parent = 0); ~QtKeySequencePropertyManager(); QKeySequence value(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, const QKeySequence &val); Q_SIGNALS: void valueChanged(QtProperty *property, const QKeySequence &val); protected: QString valueText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtKeySequencePropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtKeySequencePropertyManager) Q_DISABLE_COPY(QtKeySequencePropertyManager) }; class QtCharPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtCharPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtCharPropertyManager(QObject *parent = 0); ~QtCharPropertyManager(); QChar value(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, const QChar &val); Q_SIGNALS: void valueChanged(QtProperty *property, const QChar &val); protected: QString valueText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtCharPropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtCharPropertyManager) Q_DISABLE_COPY(QtCharPropertyManager) }; class QtEnumPropertyManager; class QtLocalePropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtLocalePropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtLocalePropertyManager(QObject *parent = 0); ~QtLocalePropertyManager(); QtEnumPropertyManager *subEnumPropertyManager() const; QLocale value(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, const QLocale &val); Q_SIGNALS: void valueChanged(QtProperty *property, const QLocale &val); protected: QString valueText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtLocalePropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtLocalePropertyManager) Q_DISABLE_COPY(QtLocalePropertyManager) Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) }; class QtPointPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtPointPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtPointPropertyManager(QObject *parent = 0); ~QtPointPropertyManager(); QtIntPropertyManager *subIntPropertyManager() const; QPoint value(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, const QPoint &val); Q_SIGNALS: void valueChanged(QtProperty *property, const QPoint &val); protected: QString valueText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtPointPropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtPointPropertyManager) Q_DISABLE_COPY(QtPointPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) }; class QtPointFPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtPointFPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtPointFPropertyManager(QObject *parent = 0); ~QtPointFPropertyManager(); QtDoublePropertyManager *subDoublePropertyManager() const; QPointF value(const QtProperty *property) const; int decimals(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, const QPointF &val); void setDecimals(QtProperty *property, int prec); Q_SIGNALS: void valueChanged(QtProperty *property, const QPointF &val); void decimalsChanged(QtProperty *property, int prec); protected: QString valueText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtPointFPropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtPointFPropertyManager) Q_DISABLE_COPY(QtPointFPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotDoubleChanged(QtProperty *, double)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) }; class QtSizePropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtSizePropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtSizePropertyManager(QObject *parent = 0); ~QtSizePropertyManager(); QtIntPropertyManager *subIntPropertyManager() const; QSize value(const QtProperty *property) const; QSize minimum(const QtProperty *property) const; QSize maximum(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, const QSize &val); void setMinimum(QtProperty *property, const QSize &minVal); void setMaximum(QtProperty *property, const QSize &maxVal); void setRange(QtProperty *property, const QSize &minVal, const QSize &maxVal); Q_SIGNALS: void valueChanged(QtProperty *property, const QSize &val); void rangeChanged(QtProperty *property, const QSize &minVal, const QSize &maxVal); protected: QString valueText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtSizePropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtSizePropertyManager) Q_DISABLE_COPY(QtSizePropertyManager) Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) }; class QtSizeFPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtSizeFPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtSizeFPropertyManager(QObject *parent = 0); ~QtSizeFPropertyManager(); QtDoublePropertyManager *subDoublePropertyManager() const; QSizeF value(const QtProperty *property) const; QSizeF minimum(const QtProperty *property) const; QSizeF maximum(const QtProperty *property) const; int decimals(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, const QSizeF &val); void setMinimum(QtProperty *property, const QSizeF &minVal); void setMaximum(QtProperty *property, const QSizeF &maxVal); void setRange(QtProperty *property, const QSizeF &minVal, const QSizeF &maxVal); void setDecimals(QtProperty *property, int prec); Q_SIGNALS: void valueChanged(QtProperty *property, const QSizeF &val); void rangeChanged(QtProperty *property, const QSizeF &minVal, const QSizeF &maxVal); void decimalsChanged(QtProperty *property, int prec); protected: QString valueText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtSizeFPropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtSizeFPropertyManager) Q_DISABLE_COPY(QtSizeFPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotDoubleChanged(QtProperty *, double)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) }; class QtRectPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtRectPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtRectPropertyManager(QObject *parent = 0); ~QtRectPropertyManager(); QtIntPropertyManager *subIntPropertyManager() const; QRect value(const QtProperty *property) const; QRect constraint(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, const QRect &val); void setConstraint(QtProperty *property, const QRect &constraint); Q_SIGNALS: void valueChanged(QtProperty *property, const QRect &val); void constraintChanged(QtProperty *property, const QRect &constraint); protected: QString valueText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtRectPropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtRectPropertyManager) Q_DISABLE_COPY(QtRectPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) }; class QtRectFPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtRectFPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtRectFPropertyManager(QObject *parent = 0); ~QtRectFPropertyManager(); QtDoublePropertyManager *subDoublePropertyManager() const; QRectF value(const QtProperty *property) const; QRectF constraint(const QtProperty *property) const; int decimals(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, const QRectF &val); void setConstraint(QtProperty *property, const QRectF &constraint); void setDecimals(QtProperty *property, int prec); Q_SIGNALS: void valueChanged(QtProperty *property, const QRectF &val); void constraintChanged(QtProperty *property, const QRectF &constraint); void decimalsChanged(QtProperty *property, int prec); protected: QString valueText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtRectFPropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtRectFPropertyManager) Q_DISABLE_COPY(QtRectFPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotDoubleChanged(QtProperty *, double)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) }; class QtEnumPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtEnumPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtEnumPropertyManager(QObject *parent = 0); ~QtEnumPropertyManager(); int value(const QtProperty *property) const; QStringList enumNames(const QtProperty *property) const; QMap enumIcons(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, int val); void setEnumNames(QtProperty *property, const QStringList &names); void setEnumIcons(QtProperty *property, const QMap &icons); Q_SIGNALS: void valueChanged(QtProperty *property, int val); void enumNamesChanged(QtProperty *property, const QStringList &names); void enumIconsChanged(QtProperty *property, const QMap &icons); protected: QString valueText(const QtProperty *property) const; QIcon valueIcon(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtEnumPropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtEnumPropertyManager) Q_DISABLE_COPY(QtEnumPropertyManager) }; class QtFlagPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtFlagPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtFlagPropertyManager(QObject *parent = 0); ~QtFlagPropertyManager(); QtBoolPropertyManager *subBoolPropertyManager() const; int value(const QtProperty *property) const; QStringList flagNames(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, int val); void setFlagNames(QtProperty *property, const QStringList &names); Q_SIGNALS: void valueChanged(QtProperty *property, int val); void flagNamesChanged(QtProperty *property, const QStringList &names); protected: QString valueText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtFlagPropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtFlagPropertyManager) Q_DISABLE_COPY(QtFlagPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotBoolChanged(QtProperty *, bool)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) }; class QtSizePolicyPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtSizePolicyPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtSizePolicyPropertyManager(QObject *parent = 0); ~QtSizePolicyPropertyManager(); QtIntPropertyManager *subIntPropertyManager() const; QtEnumPropertyManager *subEnumPropertyManager() const; QSizePolicy value(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, const QSizePolicy &val); Q_SIGNALS: void valueChanged(QtProperty *property, const QSizePolicy &val); protected: QString valueText(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtSizePolicyPropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtSizePolicyPropertyManager) Q_DISABLE_COPY(QtSizePolicyPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) }; class QtFontPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtFontPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtFontPropertyManager(QObject *parent = 0); ~QtFontPropertyManager(); QtIntPropertyManager *subIntPropertyManager() const; QtEnumPropertyManager *subEnumPropertyManager() const; QtBoolPropertyManager *subBoolPropertyManager() const; QFont value(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, const QFont &val); Q_SIGNALS: void valueChanged(QtProperty *property, const QFont &val); protected: QString valueText(const QtProperty *property) const; QIcon valueIcon(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtFontPropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtFontPropertyManager) Q_DISABLE_COPY(QtFontPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotBoolChanged(QtProperty *, bool)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) Q_PRIVATE_SLOT(d_func(), void slotFontDatabaseChanged()) Q_PRIVATE_SLOT(d_func(), void slotFontDatabaseDelayedChange()) }; class QtColorPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtColorPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtColorPropertyManager(QObject *parent = 0); ~QtColorPropertyManager(); QtIntPropertyManager *subIntPropertyManager() const; QColor value(const QtProperty *property) const; public Q_SLOTS: void setValue(QtProperty *property, const QColor &val); Q_SIGNALS: void valueChanged(QtProperty *property, const QColor &val); protected: QString valueText(const QtProperty *property) const; QIcon valueIcon(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtColorPropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtColorPropertyManager) Q_DISABLE_COPY(QtColorPropertyManager) Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) }; class QtCursorPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtCursorPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtCursorPropertyManager(QObject *parent = 0); ~QtCursorPropertyManager(); #ifndef QT_NO_CURSOR QCursor value(const QtProperty *property) const; #endif public Q_SLOTS: void setValue(QtProperty *property, const QCursor &val); Q_SIGNALS: void valueChanged(QtProperty *property, const QCursor &val); protected: QString valueText(const QtProperty *property) const; QIcon valueIcon(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); private: QtCursorPropertyManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(QtCursorPropertyManager) Q_DISABLE_COPY(QtCursorPropertyManager) }; #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif #endif tiled-1.0.3/src/qtpropertybrowser/src/qttreepropertybrowser.cpp000066400000000000000000001133231315121121300252410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qttreepropertybrowser.h" #include #include #include #include #include #include #include #include #include #include #include #include static qreal defaultDpiScale() { if (const QScreen *screen = QGuiApplication::primaryScreen()) return screen->logicalDotsPerInchX() / 96.0; return 1.0; } static qreal dpiScaled(qreal value) { #ifdef Q_OS_MAC // On mac the DPI is always 72 so we should not scale it return value; #else static const qreal scale = defaultDpiScale(); return value * scale; #endif } static QSize dpiScaled(QSize value) { return QSize(qRound(dpiScaled(value.width())), qRound(dpiScaled(value.height()))); } #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif class QtPropertyEditorView; class QtTreePropertyBrowserPrivate { QtTreePropertyBrowser *q_ptr; Q_DECLARE_PUBLIC(QtTreePropertyBrowser) public: QtTreePropertyBrowserPrivate(); void init(QWidget *parent); void propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex); void propertyRemoved(QtBrowserItem *index); void propertyChanged(QtBrowserItem *index); QWidget *createEditor(QtProperty *property, QWidget *parent) const { return q_ptr->createEditor(property, parent); } QtProperty *indexToProperty(const QModelIndex &index) const; QTreeWidgetItem *indexToItem(const QModelIndex &index) const; QtBrowserItem *indexToBrowserItem(const QModelIndex &index) const; bool lastColumn(int column) const; void disableItem(QTreeWidgetItem *item) const; void enableItem(QTreeWidgetItem *item) const; bool hasValue(QTreeWidgetItem *item) const; void slotCollapsed(const QModelIndex &index); void slotExpanded(const QModelIndex &index); QColor calculatedBackgroundColor(QtBrowserItem *item) const; QtPropertyEditorView *treeWidget() const { return m_treeWidget; } bool markPropertiesWithoutValue() const { return m_markPropertiesWithoutValue; } QtBrowserItem *currentItem() const; void setCurrentItem(QtBrowserItem *browserItem, bool block); void editItem(QtBrowserItem *browserItem); QList selectedItems() const; void slotCurrentBrowserItemChanged(QtBrowserItem *item); void slotCurrentTreeItemChanged(QTreeWidgetItem *newItem, QTreeWidgetItem *); void slotItemSelectionChanged(); QTreeWidgetItem *editedItem() const; QtBrowserItem *editedBrowserItem() const; private: void updateItem(QTreeWidgetItem *item); QMap m_indexToItem; QMap m_itemToIndex; QMap m_indexToBackgroundColor; QtPropertyEditorView *m_treeWidget; bool m_headerVisible; bool m_allowMultiSelection; QtTreePropertyBrowser::ResizeMode m_resizeMode; class QtPropertyEditorDelegate *m_delegate; bool m_markPropertiesWithoutValue; bool m_browserChangedBlocked; QIcon m_expandIcon; }; // ------------ QtPropertyEditorView class QtPropertyEditorView : public QTreeWidget { Q_OBJECT public: QtPropertyEditorView(QWidget *parent = 0); void setEditorPrivate(QtTreePropertyBrowserPrivate *editorPrivate) { m_editorPrivate = editorPrivate; } QTreeWidgetItem *indexToItem(const QModelIndex &index) const { return itemFromIndex(index); } protected: void keyPressEvent(QKeyEvent *event); void mousePressEvent(QMouseEvent *event); void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; private: QtTreePropertyBrowserPrivate *m_editorPrivate; }; QtPropertyEditorView::QtPropertyEditorView(QWidget *parent) : QTreeWidget(parent), m_editorPrivate(0) { connect(header(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(resizeColumnToContents(int))); } void QtPropertyEditorView::drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItemV3 opt = option; bool hasValue = true; if (m_editorPrivate) { QtProperty *property = m_editorPrivate->indexToProperty(index); if (property) hasValue = property->hasValue(); } if (!hasValue && m_editorPrivate->markPropertiesWithoutValue()) { const QColor c = option.palette.color(QPalette::Dark); painter->fillRect(option.rect, c); opt.palette.setColor(QPalette::AlternateBase, c); } else { const QColor c = m_editorPrivate->calculatedBackgroundColor(m_editorPrivate->indexToBrowserItem(index)); if (c.isValid()) { painter->fillRect(option.rect, c); opt.palette.setColor(QPalette::AlternateBase, c.lighter(112)); } } QTreeWidget::drawRow(painter, opt, index); QColor color = static_cast(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt)); painter->save(); painter->setPen(QPen(color)); painter->drawLine(opt.rect.x(), opt.rect.bottom(), opt.rect.right(), opt.rect.bottom()); painter->restore(); } void QtPropertyEditorView::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Return: case Qt::Key_Enter: case Qt::Key_Space: // Trigger Edit if (!m_editorPrivate->editedItem()) if (const QTreeWidgetItem *item = currentItem()) if (item->columnCount() >= 2 && ((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled))) { event->accept(); // If the current position is at column 0, move to 1. QModelIndex index = currentIndex(); if (index.column() == 0) { index = index.sibling(index.row(), 1); setCurrentIndex(index); } edit(index); return; } break; default: break; } QTreeWidget::keyPressEvent(event); } void QtPropertyEditorView::mousePressEvent(QMouseEvent *event) { QTreeWidget::mousePressEvent(event); QTreeWidgetItem *item = itemAt(event->pos()); if (item) { if ((item != m_editorPrivate->editedItem()) && (event->button() == Qt::LeftButton) && (header()->logicalIndexAt(event->pos().x()) == 1) && ((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled))) { editItem(item, 1); } else if (!m_editorPrivate->hasValue(item) && m_editorPrivate->markPropertiesWithoutValue() && !rootIsDecorated()) { if (event->pos().x() + header()->offset() < 20) item->setExpanded(!item->isExpanded()); } } } // ------------ QtPropertyEditorDelegate class QtPropertyEditorDelegate : public QItemDelegate { Q_OBJECT public: QtPropertyEditorDelegate(QObject *parent = 0) : QItemDelegate(parent), m_editorPrivate(0), m_editedItem(0), m_editedWidget(0), m_disablePainting(false) {} void setEditorPrivate(QtTreePropertyBrowserPrivate *editorPrivate) { m_editorPrivate = editorPrivate; } QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; void setModelData(QWidget *, QAbstractItemModel *, const QModelIndex &) const {} void setEditorData(QWidget *, const QModelIndex &) const {} bool eventFilter(QObject *object, QEvent *event); void closeEditor(QtProperty *property); QTreeWidgetItem *editedItem() const { return m_editedItem; } protected: void drawDecoration(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QPixmap &pixmap) const; void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QString &text) const; private slots: void slotEditorDestroyed(QObject *object); private: int indentation(const QModelIndex &index) const; typedef QMap EditorToPropertyMap; mutable EditorToPropertyMap m_editorToProperty; typedef QMap PropertyToEditorMap; mutable PropertyToEditorMap m_propertyToEditor; QtTreePropertyBrowserPrivate *m_editorPrivate; mutable QTreeWidgetItem *m_editedItem; mutable QWidget *m_editedWidget; mutable bool m_disablePainting; }; int QtPropertyEditorDelegate::indentation(const QModelIndex &index) const { if (!m_editorPrivate) return 0; QTreeWidgetItem *item = m_editorPrivate->indexToItem(index); int indent = 0; while (item->parent()) { item = item->parent(); ++indent; } if (m_editorPrivate->treeWidget()->rootIsDecorated()) ++indent; return indent * m_editorPrivate->treeWidget()->indentation(); } void QtPropertyEditorDelegate::slotEditorDestroyed(QObject *object) { if (QWidget *w = qobject_cast(object)) { const EditorToPropertyMap::iterator it = m_editorToProperty.find(w); if (it != m_editorToProperty.end()) { m_propertyToEditor.remove(it.value()); m_editorToProperty.erase(it); } if (m_editedWidget == w) { m_editedWidget = 0; m_editedItem = 0; } } } void QtPropertyEditorDelegate::closeEditor(QtProperty *property) { if (QWidget *w = m_propertyToEditor.value(property, 0)) w->deleteLater(); } QWidget *QtPropertyEditorDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const { if (index.column() == 1 && m_editorPrivate) { QtProperty *property = m_editorPrivate->indexToProperty(index); QTreeWidgetItem *item = m_editorPrivate->indexToItem(index); if (property && item && (item->flags() & Qt::ItemIsEnabled)) { QWidget *editor = m_editorPrivate->createEditor(property, parent); if (editor) { editor->setAutoFillBackground(true); editor->installEventFilter(const_cast(this)); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); m_propertyToEditor[property] = editor; m_editorToProperty[editor] = property; m_editedItem = item; m_editedWidget = editor; } return editor; } } return 0; } void QtPropertyEditorDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_UNUSED(index) editor->setGeometry(option.rect.adjusted(0, 0, 0, -1)); } void QtPropertyEditorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { bool hasValue = true; if (m_editorPrivate) { QtProperty *property = m_editorPrivate->indexToProperty(index); if (property) hasValue = property->hasValue(); } QStyleOptionViewItemV3 opt = option; if ((m_editorPrivate && index.column() == 0) || !hasValue) { QtProperty *property = m_editorPrivate->indexToProperty(index); if (property && property->isModified()) { opt.font.setBold(true); opt.fontMetrics = QFontMetrics(opt.font); } } QColor c; if (!hasValue && m_editorPrivate->markPropertiesWithoutValue()) { c = opt.palette.color(QPalette::Dark); opt.palette.setColor(QPalette::Text, opt.palette.color(QPalette::BrightText)); } else { c = m_editorPrivate->calculatedBackgroundColor(m_editorPrivate->indexToBrowserItem(index)); if (c.isValid() && (opt.features & QStyleOptionViewItemV2::Alternate)) c = c.lighter(112); } if (c.isValid()) painter->fillRect(option.rect, c); opt.state &= ~QStyle::State_HasFocus; if (index.column() == 1) { QTreeWidgetItem *item = m_editorPrivate->indexToItem(index); if (m_editedItem && m_editedItem == item) m_disablePainting = true; } QItemDelegate::paint(painter, opt, index); if (option.type) m_disablePainting = false; opt.palette.setCurrentColorGroup(QPalette::Active); QColor color = static_cast(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt)); painter->save(); painter->setPen(QPen(color)); if (!m_editorPrivate || (!m_editorPrivate->lastColumn(index.column()) && hasValue)) { int right = (option.direction == Qt::LeftToRight) ? option.rect.right() : option.rect.left(); painter->drawLine(right, option.rect.y(), right, option.rect.bottom()); } painter->restore(); } void QtPropertyEditorDelegate::drawDecoration(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QPixmap &pixmap) const { if (m_disablePainting) return; QItemDelegate::drawDecoration(painter, option, rect, pixmap); } void QtPropertyEditorDelegate::drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QString &text) const { if (m_disablePainting) return; QItemDelegate::drawDisplay(painter, option, rect, text); } QSize QtPropertyEditorDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { return QItemDelegate::sizeHint(option, index) + dpiScaled(QSize(3, 4)); } bool QtPropertyEditorDelegate::eventFilter(QObject *object, QEvent *event) { if (event->type() == QEvent::FocusOut) { QFocusEvent *fe = static_cast(event); if (fe->reason() == Qt::ActiveWindowFocusReason) return false; } return QItemDelegate::eventFilter(object, event); } // -------- QtTreePropertyBrowserPrivate implementation QtTreePropertyBrowserPrivate::QtTreePropertyBrowserPrivate() : m_treeWidget(0), m_headerVisible(true), m_allowMultiSelection(false), m_resizeMode(QtTreePropertyBrowser::Stretch), m_delegate(0), m_markPropertiesWithoutValue(false), m_browserChangedBlocked(false) { } // Draw an icon indicating opened/closing branches static QIcon drawIndicatorIcon(const QPalette &palette, QStyle *style) { QPixmap pix(14, 14); pix.fill(Qt::transparent); QStyleOption branchOption; QRect r(QPoint(0, 0), pix.size()); branchOption.rect = QRect(2, 2, 9, 9); // ### hardcoded in qcommonstyle.cpp branchOption.palette = palette; branchOption.state = QStyle::State_Children; QPainter p; // Draw closed state p.begin(&pix); style->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p); p.end(); QIcon rc = pix; rc.addPixmap(pix, QIcon::Selected, QIcon::Off); // Draw opened state branchOption.state |= QStyle::State_Open; pix.fill(Qt::transparent); p.begin(&pix); style->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p); p.end(); rc.addPixmap(pix, QIcon::Normal, QIcon::On); rc.addPixmap(pix, QIcon::Selected, QIcon::On); return rc; } void QtTreePropertyBrowserPrivate::init(QWidget *parent) { QHBoxLayout *layout = new QHBoxLayout(parent); layout->setMargin(0); m_treeWidget = new QtPropertyEditorView(parent); m_treeWidget->setEditorPrivate(this); m_treeWidget->setIconSize(QSize(18, 18)); layout->addWidget(m_treeWidget); parent->setFocusProxy(m_treeWidget); m_treeWidget->setColumnCount(2); QStringList labels; labels.append(QCoreApplication::translate("QtTreePropertyBrowser", "Property")); labels.append(QCoreApplication::translate("QtTreePropertyBrowser", "Value")); m_treeWidget->setHeaderLabels(labels); m_treeWidget->setAlternatingRowColors(true); m_treeWidget->setEditTriggers(QAbstractItemView::EditKeyPressed); m_delegate = new QtPropertyEditorDelegate(parent); m_delegate->setEditorPrivate(this); m_treeWidget->setItemDelegate(m_delegate); #if QT_VERSION >= 0x050000 m_treeWidget->header()->setSectionsMovable(false); m_treeWidget->header()->setSectionResizeMode(QHeaderView::Stretch); #else m_treeWidget->header()->setMovable(false); m_treeWidget->header()->setResizeMode(QHeaderView::Stretch); #endif m_expandIcon = drawIndicatorIcon(q_ptr->palette(), q_ptr->style()); QObject::connect(m_treeWidget, SIGNAL(collapsed(const QModelIndex &)), q_ptr, SLOT(slotCollapsed(const QModelIndex &))); QObject::connect(m_treeWidget, SIGNAL(expanded(const QModelIndex &)), q_ptr, SLOT(slotExpanded(const QModelIndex &))); QObject::connect(m_treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), q_ptr, SLOT(slotCurrentTreeItemChanged(QTreeWidgetItem*,QTreeWidgetItem*))); QObject::connect(m_treeWidget, SIGNAL(itemSelectionChanged()), q_ptr, SLOT(slotItemSelectionChanged())); } QtBrowserItem *QtTreePropertyBrowserPrivate::currentItem() const { if (QTreeWidgetItem *treeItem = m_treeWidget->currentItem()) return m_itemToIndex.value(treeItem); return 0; } void QtTreePropertyBrowserPrivate::setCurrentItem(QtBrowserItem *browserItem, bool block) { const bool blocked = block ? m_treeWidget->blockSignals(true) : false; if (browserItem == 0) m_treeWidget->setCurrentItem(0); else m_treeWidget->setCurrentItem(m_indexToItem.value(browserItem)); if (block) m_treeWidget->blockSignals(blocked); } QtProperty *QtTreePropertyBrowserPrivate::indexToProperty(const QModelIndex &index) const { QTreeWidgetItem *item = m_treeWidget->indexToItem(index); QtBrowserItem *idx = m_itemToIndex.value(item); if (idx) return idx->property(); return 0; } QtBrowserItem *QtTreePropertyBrowserPrivate::indexToBrowserItem(const QModelIndex &index) const { QTreeWidgetItem *item = m_treeWidget->indexToItem(index); return m_itemToIndex.value(item); } QTreeWidgetItem *QtTreePropertyBrowserPrivate::indexToItem(const QModelIndex &index) const { return m_treeWidget->indexToItem(index); } bool QtTreePropertyBrowserPrivate::lastColumn(int column) const { return m_treeWidget->header()->visualIndex(column) == m_treeWidget->columnCount() - 1; } void QtTreePropertyBrowserPrivate::disableItem(QTreeWidgetItem *item) const { Qt::ItemFlags flags = item->flags(); if (flags & Qt::ItemIsEnabled) { flags &= ~Qt::ItemIsEnabled; item->setFlags(flags); m_delegate->closeEditor(m_itemToIndex[item]->property()); const int childCount = item->childCount(); for (int i = 0; i < childCount; i++) { QTreeWidgetItem *child = item->child(i); disableItem(child); } } } void QtTreePropertyBrowserPrivate::enableItem(QTreeWidgetItem *item) const { Qt::ItemFlags flags = item->flags(); flags |= Qt::ItemIsEnabled; item->setFlags(flags); const int childCount = item->childCount(); for (int i = 0; i < childCount; i++) { QTreeWidgetItem *child = item->child(i); QtProperty *property = m_itemToIndex[child]->property(); if (property->isEnabled()) { enableItem(child); } } } bool QtTreePropertyBrowserPrivate::hasValue(QTreeWidgetItem *item) const { QtBrowserItem *browserItem = m_itemToIndex.value(item); if (browserItem) return browserItem->property()->hasValue(); return false; } void QtTreePropertyBrowserPrivate::propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex) { QTreeWidgetItem *afterItem = m_indexToItem.value(afterIndex); QTreeWidgetItem *parentItem = m_indexToItem.value(index->parent()); QTreeWidgetItem *newItem = 0; if (parentItem) { newItem = new QTreeWidgetItem(parentItem, afterItem); } else { newItem = new QTreeWidgetItem(m_treeWidget, afterItem); } m_itemToIndex[newItem] = index; m_indexToItem[index] = newItem; newItem->setFlags(newItem->flags() | Qt::ItemIsEditable); m_treeWidget->setItemExpanded(newItem, true); updateItem(newItem); } void QtTreePropertyBrowserPrivate::propertyRemoved(QtBrowserItem *index) { QTreeWidgetItem *item = m_indexToItem.value(index); if (m_treeWidget->currentItem() == item) { m_treeWidget->setCurrentItem(0); } delete item; m_indexToItem.remove(index); m_itemToIndex.remove(item); m_indexToBackgroundColor.remove(index); } void QtTreePropertyBrowserPrivate::propertyChanged(QtBrowserItem *index) { QTreeWidgetItem *item = m_indexToItem.value(index); updateItem(item); } void QtTreePropertyBrowserPrivate::updateItem(QTreeWidgetItem *item) { QtProperty *property = m_itemToIndex[item]->property(); if (property->nameColor().isValid()) item->setForeground(0, QBrush(property->nameColor())); if (property->valueColor().isValid()) item->setForeground(1, QBrush(property->valueColor())); QIcon expandIcon; if (property->hasValue()) { QString toolTip = property->toolTip(); if (toolTip.isEmpty()) toolTip = property->displayText(); item->setToolTip(1, toolTip); item->setIcon(1, property->valueIcon()); property->displayText().isEmpty() ? item->setText(1, property->valueText()) : item->setText(1, property->displayText()); } else if (markPropertiesWithoutValue() && !m_treeWidget->rootIsDecorated()) { expandIcon = m_expandIcon; } item->setIcon(0, expandIcon); item->setFirstColumnSpanned(!property->hasValue()); item->setToolTip(0, property->propertyName()); item->setStatusTip(0, property->statusTip()); item->setWhatsThis(0, property->whatsThis()); item->setText(0, property->propertyName()); bool wasEnabled = item->flags() & Qt::ItemIsEnabled; bool isEnabled = wasEnabled; if (property->isEnabled()) { QTreeWidgetItem *parent = item->parent(); if (!parent || (parent->flags() & Qt::ItemIsEnabled)) isEnabled = true; else isEnabled = false; } else { isEnabled = false; } if (wasEnabled != isEnabled) { if (isEnabled) enableItem(item); else disableItem(item); } m_treeWidget->viewport()->update(); } QColor QtTreePropertyBrowserPrivate::calculatedBackgroundColor(QtBrowserItem *item) const { QtBrowserItem *i = item; const QMap::const_iterator itEnd = m_indexToBackgroundColor.constEnd(); while (i) { QMap::const_iterator it = m_indexToBackgroundColor.constFind(i); if (it != itEnd) return it.value(); i = i->parent(); } return QColor(); } void QtTreePropertyBrowserPrivate::slotCollapsed(const QModelIndex &index) { QTreeWidgetItem *item = indexToItem(index); QtBrowserItem *idx = m_itemToIndex.value(item); if (item) emit q_ptr->collapsed(idx); } void QtTreePropertyBrowserPrivate::slotExpanded(const QModelIndex &index) { QTreeWidgetItem *item = indexToItem(index); QtBrowserItem *idx = m_itemToIndex.value(item); if (item) emit q_ptr->expanded(idx); } void QtTreePropertyBrowserPrivate::slotCurrentBrowserItemChanged(QtBrowserItem *item) { if (!m_browserChangedBlocked && item != currentItem()) setCurrentItem(item, true); } void QtTreePropertyBrowserPrivate::slotCurrentTreeItemChanged(QTreeWidgetItem *newItem, QTreeWidgetItem *) { QtBrowserItem *browserItem = newItem ? m_itemToIndex.value(newItem) : 0; m_browserChangedBlocked = true; q_ptr->setCurrentItem(browserItem); m_browserChangedBlocked = false; } void QtTreePropertyBrowserPrivate::slotItemSelectionChanged() { emit q_ptr->selectedItemsChanged(); } QTreeWidgetItem *QtTreePropertyBrowserPrivate::editedItem() const { return m_delegate->editedItem(); } QtBrowserItem *QtTreePropertyBrowserPrivate::editedBrowserItem() const { return m_itemToIndex.value(editedItem()); } void QtTreePropertyBrowserPrivate::editItem(QtBrowserItem *browserItem) { if (QTreeWidgetItem *treeItem = m_indexToItem.value(browserItem, 0)) { m_treeWidget->setCurrentItem (treeItem, 1); m_treeWidget->editItem(treeItem, 1); } } QList QtTreePropertyBrowserPrivate::selectedItems() const { const QList selectedTreeItems = m_treeWidget->selectedItems(); QList browserItems; for (QTreeWidgetItem *treeItem : selectedTreeItems) if (QtBrowserItem *browserItem = m_itemToIndex.value(treeItem, 0)) browserItems.append(browserItem); return browserItems; } /*! \class QtTreePropertyBrowser \brief The QtTreePropertyBrowser class provides QTreeWidget based property browser. A property browser is a widget that enables the user to edit a given set of properties. Each property is represented by a label specifying the property's name, and an editing widget (e.g. a line edit or a combobox) holding its value. A property can have zero or more subproperties. QtTreePropertyBrowser provides a tree based view for all nested properties, i.e. properties that have subproperties can be in an expanded (subproperties are visible) or collapsed (subproperties are hidden) state. For example: \image qttreepropertybrowser.png Use the QtAbstractPropertyBrowser API to add, insert and remove properties from an instance of the QtTreePropertyBrowser class. The properties themselves are created and managed by implementations of the QtAbstractPropertyManager class. \sa QtGroupBoxPropertyBrowser, QtAbstractPropertyBrowser */ /*! \fn void QtTreePropertyBrowser::collapsed(QtBrowserItem *item) This signal is emitted when the \a item is collapsed. \sa expanded(), setExpanded() */ /*! \fn void QtTreePropertyBrowser::expanded(QtBrowserItem *item) This signal is emitted when the \a item is expanded. \sa collapsed(), setExpanded() */ /*! Creates a property browser with the given \a parent. */ QtTreePropertyBrowser::QtTreePropertyBrowser(QWidget *parent) : QtAbstractPropertyBrowser(parent) { d_ptr = new QtTreePropertyBrowserPrivate; d_ptr->q_ptr = this; d_ptr->init(this); connect(this, SIGNAL(currentItemChanged(QtBrowserItem*)), this, SLOT(slotCurrentBrowserItemChanged(QtBrowserItem*))); } /*! Destroys this property browser. Note that the properties that were inserted into this browser are \e not destroyed since they may still be used in other browsers. The properties are owned by the manager that created them. \sa QtProperty, QtAbstractPropertyManager */ QtTreePropertyBrowser::~QtTreePropertyBrowser() { delete d_ptr; } /*! \property QtTreePropertyBrowser::indentation \brief indentation of the items in the tree view. */ int QtTreePropertyBrowser::indentation() const { return d_ptr->m_treeWidget->indentation(); } void QtTreePropertyBrowser::setIndentation(int i) { d_ptr->m_treeWidget->setIndentation(i); } /*! \property QtTreePropertyBrowser::rootIsDecorated \brief whether to show controls for expanding and collapsing root items. */ bool QtTreePropertyBrowser::rootIsDecorated() const { return d_ptr->m_treeWidget->rootIsDecorated(); } void QtTreePropertyBrowser::setRootIsDecorated(bool show) { d_ptr->m_treeWidget->setRootIsDecorated(show); QMapIterator it(d_ptr->m_itemToIndex); while (it.hasNext()) { QtProperty *property = it.next().value()->property(); if (!property->hasValue()) d_ptr->updateItem(it.key()); } } /*! \property QtTreePropertyBrowser::alternatingRowColors \brief whether to draw the background using alternating colors. By default this property is set to true. */ bool QtTreePropertyBrowser::alternatingRowColors() const { return d_ptr->m_treeWidget->alternatingRowColors(); } void QtTreePropertyBrowser::setAlternatingRowColors(bool enable) { d_ptr->m_treeWidget->setAlternatingRowColors(enable); QMapIterator it(d_ptr->m_itemToIndex); } /*! \property QtTreePropertyBrowser::headerVisible \brief whether to show the header. */ bool QtTreePropertyBrowser::isHeaderVisible() const { return d_ptr->m_headerVisible; } void QtTreePropertyBrowser::setHeaderVisible(bool visible) { if (d_ptr->m_headerVisible == visible) return; d_ptr->m_headerVisible = visible; d_ptr->m_treeWidget->header()->setVisible(visible); } /*! \property QtTreePropertyBrowser::allowMultiSelection \brief whether to allow multiple selection items. */ bool QtTreePropertyBrowser::allowMultiSelection() const { return d_ptr->m_allowMultiSelection; } void QtTreePropertyBrowser::setAllowMultiSelection(bool multiSelection) { if (d_ptr->m_allowMultiSelection == multiSelection) return; d_ptr->m_allowMultiSelection = multiSelection; d_ptr->m_treeWidget->setSelectionMode(multiSelection ? QAbstractItemView::ExtendedSelection : QAbstractItemView::SingleSelection); } /*! \enum QtTreePropertyBrowser::ResizeMode The resize mode specifies the behavior of the header sections. \value Interactive The user can resize the sections. The sections can also be resized programmatically using setSplitterPosition(). \value Fixed The user cannot resize the section. The section can only be resized programmatically using setSplitterPosition(). \value Stretch QHeaderView will automatically resize the section to fill the available space. The size cannot be changed by the user or programmatically. \value ResizeToContents QHeaderView will automatically resize the section to its optimal size based on the contents of the entire column. The size cannot be changed by the user or programmatically. \sa setResizeMode() */ /*! \property QtTreePropertyBrowser::resizeMode \brief the resize mode of setions in the header. */ QtTreePropertyBrowser::ResizeMode QtTreePropertyBrowser::resizeMode() const { return d_ptr->m_resizeMode; } void QtTreePropertyBrowser::setResizeMode(QtTreePropertyBrowser::ResizeMode mode) { if (d_ptr->m_resizeMode == mode) return; d_ptr->m_resizeMode = mode; QHeaderView::ResizeMode m = QHeaderView::Stretch; switch (mode) { case QtTreePropertyBrowser::Interactive: m = QHeaderView::Interactive; break; case QtTreePropertyBrowser::Fixed: m = QHeaderView::Fixed; break; case QtTreePropertyBrowser::ResizeToContents: m = QHeaderView::ResizeToContents; break; case QtTreePropertyBrowser::Stretch: default: m = QHeaderView::Stretch; break; } #if QT_VERSION >= 0x050000 d_ptr->m_treeWidget->header()->setSectionResizeMode(m); #else d_ptr->m_treeWidget->header()->setResizeMode(m); #endif } /*! \property QtTreePropertyBrowser::splitterPosition \brief the position of the splitter between the colunms. */ int QtTreePropertyBrowser::splitterPosition() const { return d_ptr->m_treeWidget->header()->sectionSize(0); } void QtTreePropertyBrowser::setSplitterPosition(int position) { d_ptr->m_treeWidget->header()->resizeSection(0, position); } /*! Sets the \a item to either collapse or expanded, depending on the value of \a expanded. \sa isExpanded(), expanded(), collapsed() */ void QtTreePropertyBrowser::setExpanded(QtBrowserItem *item, bool expanded) { QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item); if (treeItem) treeItem->setExpanded(expanded); } /*! Returns true if the \a item is expanded; otherwise returns false. \sa setExpanded() */ bool QtTreePropertyBrowser::isExpanded(QtBrowserItem *item) const { QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item); if (treeItem) return treeItem->isExpanded(); return false; } /*! Returns true if the \a item is visible; otherwise returns false. \sa setItemVisible() \since 4.5 */ bool QtTreePropertyBrowser::isItemVisible(QtBrowserItem *item) const { if (const QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item)) return !treeItem->isHidden(); return false; } /*! Sets the \a item to be visible, depending on the value of \a visible. \sa isItemVisible() \since 4.5 */ void QtTreePropertyBrowser::setItemVisible(QtBrowserItem *item, bool visible) { if (QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item)) treeItem->setHidden(!visible); } /*! Sets the \a item's background color to \a color. Note that while item's background is rendered every second row is being drawn with alternate color (which is a bit lighter than items \a color) \sa backgroundColor(), calculatedBackgroundColor() */ void QtTreePropertyBrowser::setBackgroundColor(QtBrowserItem *item, const QColor &color) { if (!d_ptr->m_indexToItem.contains(item)) return; if (color.isValid()) d_ptr->m_indexToBackgroundColor[item] = color; else d_ptr->m_indexToBackgroundColor.remove(item); d_ptr->m_treeWidget->viewport()->update(); } /*! Returns the \a item's color. If there is no color set for item it returns invalid color. \sa calculatedBackgroundColor(), setBackgroundColor() */ QColor QtTreePropertyBrowser::backgroundColor(QtBrowserItem *item) const { return d_ptr->m_indexToBackgroundColor.value(item); } /*! Returns the \a item's color. If there is no color set for item it returns parent \a item's color (if there is no color set for parent it returns grandparent's color and so on). In case the color is not set for \a item and it's top level item it returns invalid color. \sa backgroundColor(), setBackgroundColor() */ QColor QtTreePropertyBrowser::calculatedBackgroundColor(QtBrowserItem *item) const { return d_ptr->calculatedBackgroundColor(item); } /*! \property QtTreePropertyBrowser::propertiesWithoutValueMarked \brief whether to enable or disable marking properties without value. When marking is enabled the item's background is rendered in dark color and item's foreground is rendered with light color. \sa propertiesWithoutValueMarked() */ void QtTreePropertyBrowser::setPropertiesWithoutValueMarked(bool mark) { if (d_ptr->m_markPropertiesWithoutValue == mark) return; d_ptr->m_markPropertiesWithoutValue = mark; QMapIterator it(d_ptr->m_itemToIndex); while (it.hasNext()) { QtProperty *property = it.next().value()->property(); if (!property->hasValue()) d_ptr->updateItem(it.key()); } d_ptr->m_treeWidget->viewport()->update(); } bool QtTreePropertyBrowser::propertiesWithoutValueMarked() const { return d_ptr->m_markPropertiesWithoutValue; } /*! \reimp */ void QtTreePropertyBrowser::itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem) { d_ptr->propertyInserted(item, afterItem); } /*! \reimp */ void QtTreePropertyBrowser::itemRemoved(QtBrowserItem *item) { d_ptr->propertyRemoved(item); } /*! \reimp */ void QtTreePropertyBrowser::itemChanged(QtBrowserItem *item) { d_ptr->propertyChanged(item); } /*! Sets the current item to \a item and opens the relevant editor for it. */ void QtTreePropertyBrowser::editItem(QtBrowserItem *item) { d_ptr->editItem(item); } /*! Returns the current item being edited, if any. */ QtBrowserItem *QtTreePropertyBrowser::editedItem() const { return d_ptr->editedBrowserItem(); } /*! Returns the selected items. \sa setAllowMultiSelection() */ QList QtTreePropertyBrowser::selectedItems() const { return d_ptr->selectedItems(); } #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif #include "moc_qttreepropertybrowser.cpp" #include "qttreepropertybrowser.moc" tiled-1.0.3/src/qtpropertybrowser/src/qttreepropertybrowser.h000066400000000000000000000121721315121121300247060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTTREEPROPERTYBROWSER_H #define QTTREEPROPERTYBROWSER_H #include "qtpropertybrowser.h" #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif class QTreeWidgetItem; class QtTreePropertyBrowserPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtTreePropertyBrowser : public QtAbstractPropertyBrowser { Q_OBJECT Q_ENUMS(ResizeMode) Q_PROPERTY(int indentation READ indentation WRITE setIndentation) Q_PROPERTY(bool rootIsDecorated READ rootIsDecorated WRITE setRootIsDecorated) Q_PROPERTY(bool alternatingRowColors READ alternatingRowColors WRITE setAlternatingRowColors) Q_PROPERTY(bool headerVisible READ isHeaderVisible WRITE setHeaderVisible) Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode) Q_PROPERTY(int splitterPosition READ splitterPosition WRITE setSplitterPosition) Q_PROPERTY(bool propertiesWithoutValueMarked READ propertiesWithoutValueMarked WRITE setPropertiesWithoutValueMarked) public: enum ResizeMode { Interactive, Stretch, Fixed, ResizeToContents }; QtTreePropertyBrowser(QWidget *parent = 0); ~QtTreePropertyBrowser(); int indentation() const; void setIndentation(int i); bool rootIsDecorated() const; void setRootIsDecorated(bool show); bool alternatingRowColors() const; void setAlternatingRowColors(bool enable); bool isHeaderVisible() const; void setHeaderVisible(bool visible); bool allowMultiSelection() const; void setAllowMultiSelection(bool multiSelection); ResizeMode resizeMode() const; void setResizeMode(ResizeMode mode); int splitterPosition() const; void setSplitterPosition(int position); void setExpanded(QtBrowserItem *item, bool expanded); bool isExpanded(QtBrowserItem *item) const; bool isItemVisible(QtBrowserItem *item) const; void setItemVisible(QtBrowserItem *item, bool visible); void setBackgroundColor(QtBrowserItem *item, const QColor &color); QColor backgroundColor(QtBrowserItem *item) const; QColor calculatedBackgroundColor(QtBrowserItem *item) const; void setPropertiesWithoutValueMarked(bool mark); bool propertiesWithoutValueMarked() const; void editItem(QtBrowserItem *item); QtBrowserItem *editedItem() const; QList selectedItems() const; Q_SIGNALS: void collapsed(QtBrowserItem *item); void expanded(QtBrowserItem *item); void selectedItemsChanged(); protected: virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem); virtual void itemRemoved(QtBrowserItem *item); virtual void itemChanged(QtBrowserItem *item); private: QtTreePropertyBrowserPrivate *d_ptr; Q_DECLARE_PRIVATE(QtTreePropertyBrowser) Q_DISABLE_COPY(QtTreePropertyBrowser) Q_PRIVATE_SLOT(d_func(), void slotCollapsed(const QModelIndex &)) Q_PRIVATE_SLOT(d_func(), void slotExpanded(const QModelIndex &)) Q_PRIVATE_SLOT(d_func(), void slotCurrentBrowserItemChanged(QtBrowserItem *)) Q_PRIVATE_SLOT(d_func(), void slotCurrentTreeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)) Q_PRIVATE_SLOT(d_func(), void slotItemSelectionChanged()) }; #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif #endif tiled-1.0.3/src/qtpropertybrowser/src/qtvariantproperty.cpp000066400000000000000000003117431315121121300243500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtvariantproperty.h" #include "qtpropertymanager.h" #include "qteditorfactory.h" #include #include #include #include #if defined(Q_CC_MSVC) # pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */ #endif #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif class QtEnumPropertyType { }; class QtFlagPropertyType { }; class QtGroupPropertyType { }; #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif Q_DECLARE_METATYPE(QtEnumPropertyType) Q_DECLARE_METATYPE(QtFlagPropertyType) Q_DECLARE_METATYPE(QtGroupPropertyType) #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif /*! Returns the type id for an enum property. Note that the property's value type can be retrieved using the valueType() function (which is QVariant::Int for the enum property type). \sa propertyType(), valueType() */ int QtVariantPropertyManager::enumTypeId() { return qMetaTypeId(); } /*! Returns the type id for a flag property. Note that the property's value type can be retrieved using the valueType() function (which is QVariant::Int for the flag property type). \sa propertyType(), valueType() */ int QtVariantPropertyManager::flagTypeId() { return qMetaTypeId(); } /*! Returns the type id for a group property. Note that the property's value type can be retrieved using the valueType() function (which is QVariant::Invalid for the group property type, since it doesn't provide any value). \sa propertyType(), valueType() */ int QtVariantPropertyManager::groupTypeId() { return qMetaTypeId(); } /*! Returns the type id for a icon map attribute. Note that the property's attribute type can be retrieved using the attributeType() function. \sa attributeType(), QtEnumPropertyManager::enumIcons() */ int QtVariantPropertyManager::iconMapTypeId() { return qMetaTypeId(); } typedef QMap PropertyMap; Q_GLOBAL_STATIC(PropertyMap, propertyToWrappedProperty) static QtProperty *wrappedProperty(QtProperty *property) { return propertyToWrappedProperty()->value(property, 0); } class QtVariantPropertyPrivate { QtVariantProperty *q_ptr; public: QtVariantPropertyPrivate(QtVariantPropertyManager *m) : manager(m) {} QtVariantPropertyManager *manager; }; /*! \class QtVariantProperty \brief The QtVariantProperty class is a convenience class handling QVariant based properties. QtVariantProperty provides additional API: A property's type, value type, attribute values and current value can easily be retrieved using the propertyType(), valueType(), attributeValue() and value() functions respectively. In addition, the attribute values and the current value can be set using the corresponding setValue() and setAttribute() functions. For example, instead of writing: \code QtVariantPropertyManager *variantPropertyManager; QtProperty *property; variantPropertyManager->setValue(property, 10); \endcode you can write: \code QtVariantPropertyManager *variantPropertyManager; QtVariantProperty *property; property->setValue(10); \endcode QtVariantProperty instances can only be created by the QtVariantPropertyManager class. \sa QtProperty, QtVariantPropertyManager, QtVariantEditorFactory */ /*! Creates a variant property using the given \a manager. Do not use this constructor to create variant property instances; use the QtVariantPropertyManager::addProperty() function instead. This constructor is used internally by the QtVariantPropertyManager::createProperty() function. \sa QtVariantPropertyManager */ QtVariantProperty::QtVariantProperty(QtVariantPropertyManager *manager) : QtProperty(manager), d_ptr(new QtVariantPropertyPrivate(manager)) { } /*! Destroys this property. \sa QtProperty::~QtProperty() */ QtVariantProperty::~QtVariantProperty() { delete d_ptr; } /*! Returns the property's current value. \sa valueType(), setValue() */ QVariant QtVariantProperty::value() const { return d_ptr->manager->value(this); } /*! Returns this property's value for the specified \a attribute. QtVariantPropertyManager provides a couple of related functions: \l{QtVariantPropertyManager::attributes()}{attributes()} and \l{QtVariantPropertyManager::attributeType()}{attributeType()}. \sa setAttribute() */ QVariant QtVariantProperty::attributeValue(const QString &attribute) const { return d_ptr->manager->attributeValue(this, attribute); } /*! Returns the type of this property's value. \sa propertyType() */ int QtVariantProperty::valueType() const { return d_ptr->manager->valueType(this); } /*! Returns this property's type. QtVariantPropertyManager provides several related functions: \l{QtVariantPropertyManager::enumTypeId()}{enumTypeId()}, \l{QtVariantPropertyManager::flagTypeId()}{flagTypeId()} and \l{QtVariantPropertyManager::groupTypeId()}{groupTypeId()}. \sa valueType() */ int QtVariantProperty::propertyType() const { return d_ptr->manager->propertyType(this); } /*! Sets the value of this property to \a value. The specified \a value must be of the type returned by valueType(), or of a type that can be converted to valueType() using the QVariant::canConvert() function; otherwise this function does nothing. \sa value() */ void QtVariantProperty::setValue(const QVariant &value) { d_ptr->manager->setValue(this, value); } /*! Sets the \a attribute of property to \a value. QtVariantPropertyManager provides the related \l{QtVariantPropertyManager::setAttribute()}{setAttribute()} function. \sa attributeValue() */ void QtVariantProperty::setAttribute(const QString &attribute, const QVariant &value) { d_ptr->manager->setAttribute(this, attribute, value); } class QtVariantPropertyManagerPrivate { QtVariantPropertyManager *q_ptr; Q_DECLARE_PUBLIC(QtVariantPropertyManager) public: QtVariantPropertyManagerPrivate(); bool m_creatingProperty; bool m_creatingSubProperties; bool m_destroyingSubProperties; int m_propertyType; void slotValueChanged(QtProperty *property, int val); void slotRangeChanged(QtProperty *property, int min, int max); void slotSingleStepChanged(QtProperty *property, int step); void slotValueChanged(QtProperty *property, double val); void slotRangeChanged(QtProperty *property, double min, double max); void slotSingleStepChanged(QtProperty *property, double step); void slotDecimalsChanged(QtProperty *property, int prec); void slotValueChanged(QtProperty *property, bool val); void slotValueChanged(QtProperty *property, const QString &val); void slotRegExpChanged(QtProperty *property, const QRegExp ®Exp); void slotEchoModeChanged(QtProperty *property, int); void slotValueChanged(QtProperty *property, const QDate &val); void slotRangeChanged(QtProperty *property, const QDate &min, const QDate &max); void slotValueChanged(QtProperty *property, const QTime &val); void slotValueChanged(QtProperty *property, const QDateTime &val); void slotValueChanged(QtProperty *property, const QKeySequence &val); void slotValueChanged(QtProperty *property, const QChar &val); void slotValueChanged(QtProperty *property, const QLocale &val); void slotValueChanged(QtProperty *property, const QPoint &val); void slotValueChanged(QtProperty *property, const QPointF &val); void slotValueChanged(QtProperty *property, const QSize &val); void slotRangeChanged(QtProperty *property, const QSize &min, const QSize &max); void slotValueChanged(QtProperty *property, const QSizeF &val); void slotRangeChanged(QtProperty *property, const QSizeF &min, const QSizeF &max); void slotValueChanged(QtProperty *property, const QRect &val); void slotConstraintChanged(QtProperty *property, const QRect &val); void slotValueChanged(QtProperty *property, const QRectF &val); void slotConstraintChanged(QtProperty *property, const QRectF &val); void slotValueChanged(QtProperty *property, const QColor &val); void slotEnumChanged(QtProperty *property, int val); void slotEnumNamesChanged(QtProperty *property, const QStringList &enumNames); void slotEnumIconsChanged(QtProperty *property, const QMap &enumIcons); void slotValueChanged(QtProperty *property, const QSizePolicy &val); void slotValueChanged(QtProperty *property, const QFont &val); void slotValueChanged(QtProperty *property, const QCursor &val); void slotFlagChanged(QtProperty *property, int val); void slotFlagNamesChanged(QtProperty *property, const QStringList &flagNames); void slotReadOnlyChanged(QtProperty *property, bool readOnly); void slotTextVisibleChanged(QtProperty *property, bool textVisible); void slotPropertyInserted(QtProperty *property, QtProperty *parent, QtProperty *after); void slotPropertyRemoved(QtProperty *property, QtProperty *parent); void valueChanged(QtProperty *property, const QVariant &val); int internalPropertyToType(QtProperty *property) const; QtVariantProperty *createSubProperty(QtVariantProperty *parent, QtVariantProperty *after, QtProperty *internal); void removeSubProperty(QtVariantProperty *property); QMap m_typeToPropertyManager; QMap > m_typeToAttributeToAttributeType; QMap > m_propertyToType; QMap m_typeToValueType; QMap m_internalToProperty; const QString m_constraintAttribute; const QString m_singleStepAttribute; const QString m_decimalsAttribute; const QString m_enumIconsAttribute; const QString m_enumNamesAttribute; const QString m_flagNamesAttribute; const QString m_maximumAttribute; const QString m_minimumAttribute; const QString m_regExpAttribute; const QString m_echoModeAttribute; const QString m_readOnlyAttribute; const QString m_textVisibleAttribute; }; QtVariantPropertyManagerPrivate::QtVariantPropertyManagerPrivate() : m_constraintAttribute(QLatin1String("constraint")), m_singleStepAttribute(QLatin1String("singleStep")), m_decimalsAttribute(QLatin1String("decimals")), m_enumIconsAttribute(QLatin1String("enumIcons")), m_enumNamesAttribute(QLatin1String("enumNames")), m_flagNamesAttribute(QLatin1String("flagNames")), m_maximumAttribute(QLatin1String("maximum")), m_minimumAttribute(QLatin1String("minimum")), m_regExpAttribute(QLatin1String("regExp")), m_echoModeAttribute(QLatin1String("echoMode")), m_readOnlyAttribute(QLatin1String("readOnly")), m_textVisibleAttribute(QLatin1String("textVisible")) { } int QtVariantPropertyManagerPrivate::internalPropertyToType(QtProperty *property) const { int type = 0; QtAbstractPropertyManager *internPropertyManager = property->propertyManager(); if (qobject_cast(internPropertyManager)) type = QVariant::Int; else if (qobject_cast(internPropertyManager)) type = QtVariantPropertyManager::enumTypeId(); else if (qobject_cast(internPropertyManager)) type = QVariant::Bool; else if (qobject_cast(internPropertyManager)) type = QVariant::Double; return type; } QtVariantProperty *QtVariantPropertyManagerPrivate::createSubProperty(QtVariantProperty *parent, QtVariantProperty *after, QtProperty *internal) { int type = internalPropertyToType(internal); if (!type) return 0; bool wasCreatingSubProperties = m_creatingSubProperties; m_creatingSubProperties = true; QtVariantProperty *varChild = q_ptr->addProperty(type, internal->propertyName()); m_creatingSubProperties = wasCreatingSubProperties; varChild->setPropertyName(internal->propertyName()); varChild->setToolTip(internal->toolTip()); varChild->setStatusTip(internal->statusTip()); varChild->setWhatsThis(internal->whatsThis()); parent->insertSubProperty(varChild, after); m_internalToProperty[internal] = varChild; propertyToWrappedProperty()->insert(varChild, internal); return varChild; } void QtVariantPropertyManagerPrivate::removeSubProperty(QtVariantProperty *property) { QtProperty *internChild = wrappedProperty(property); bool wasDestroyingSubProperties = m_destroyingSubProperties; m_destroyingSubProperties = true; delete property; m_destroyingSubProperties = wasDestroyingSubProperties; m_internalToProperty.remove(internChild); propertyToWrappedProperty()->remove(property); } void QtVariantPropertyManagerPrivate::slotPropertyInserted(QtProperty *property, QtProperty *parent, QtProperty *after) { if (m_creatingProperty) return; QtVariantProperty *varParent = m_internalToProperty.value(parent, 0); if (!varParent) return; QtVariantProperty *varAfter = 0; if (after) { varAfter = m_internalToProperty.value(after, 0); if (!varAfter) return; } createSubProperty(varParent, varAfter, property); } void QtVariantPropertyManagerPrivate::slotPropertyRemoved(QtProperty *property, QtProperty *parent) { Q_UNUSED(parent) QtVariantProperty *varProperty = m_internalToProperty.value(property, 0); if (!varProperty) return; removeSubProperty(varProperty); } void QtVariantPropertyManagerPrivate::valueChanged(QtProperty *property, const QVariant &val) { QtVariantProperty *varProp = m_internalToProperty.value(property, 0); if (!varProp) return; emit q_ptr->valueChanged(varProp, val); emit q_ptr->propertyChanged(varProp); } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, int val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, int min, int max) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min)); emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max)); } } void QtVariantPropertyManagerPrivate::slotSingleStepChanged(QtProperty *property, int step) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) emit q_ptr->attributeChanged(varProp, m_singleStepAttribute, QVariant(step)); } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, double val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, double min, double max) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min)); emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max)); } } void QtVariantPropertyManagerPrivate::slotSingleStepChanged(QtProperty *property, double step) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) emit q_ptr->attributeChanged(varProp, m_singleStepAttribute, QVariant(step)); } void QtVariantPropertyManagerPrivate::slotDecimalsChanged(QtProperty *property, int prec) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) emit q_ptr->attributeChanged(varProp, m_decimalsAttribute, QVariant(prec)); } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, bool val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QString &val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotRegExpChanged(QtProperty *property, const QRegExp ®Exp) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) emit q_ptr->attributeChanged(varProp, m_regExpAttribute, QVariant(regExp)); } void QtVariantPropertyManagerPrivate::slotEchoModeChanged(QtProperty *property, int mode) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) emit q_ptr->attributeChanged(varProp, m_echoModeAttribute, QVariant(mode)); } void QtVariantPropertyManagerPrivate::slotReadOnlyChanged(QtProperty *property, bool readOnly) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) emit q_ptr->attributeChanged(varProp, m_readOnlyAttribute, QVariant(readOnly)); } void QtVariantPropertyManagerPrivate::slotTextVisibleChanged(QtProperty *property, bool textVisible) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) emit q_ptr->attributeChanged(varProp, m_textVisibleAttribute, QVariant(textVisible)); } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QDate &val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, const QDate &min, const QDate &max) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min)); emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max)); } } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QTime &val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QDateTime &val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QKeySequence &val) { QVariant v; qVariantSetValue(v, val); valueChanged(property, v); } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QChar &val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QLocale &val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QPoint &val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QPointF &val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QSize &val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, const QSize &min, const QSize &max) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min)); emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max)); } } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QSizeF &val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, const QSizeF &min, const QSizeF &max) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min)); emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max)); } } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QRect &val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotConstraintChanged(QtProperty *property, const QRect &constraint) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) emit q_ptr->attributeChanged(varProp, m_constraintAttribute, QVariant(constraint)); } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QRectF &val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotConstraintChanged(QtProperty *property, const QRectF &constraint) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) emit q_ptr->attributeChanged(varProp, m_constraintAttribute, QVariant(constraint)); } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QColor &val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotEnumNamesChanged(QtProperty *property, const QStringList &enumNames) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) emit q_ptr->attributeChanged(varProp, m_enumNamesAttribute, QVariant(enumNames)); } void QtVariantPropertyManagerPrivate::slotEnumIconsChanged(QtProperty *property, const QMap &enumIcons) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { QVariant v; qVariantSetValue(v, enumIcons); emit q_ptr->attributeChanged(varProp, m_enumIconsAttribute, v); } } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QSizePolicy &val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QFont &val) { valueChanged(property, QVariant(val)); } void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QCursor &val) { #ifndef QT_NO_CURSOR valueChanged(property, QVariant(val)); #endif } void QtVariantPropertyManagerPrivate::slotFlagNamesChanged(QtProperty *property, const QStringList &flagNames) { if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) emit q_ptr->attributeChanged(varProp, m_flagNamesAttribute, QVariant(flagNames)); } /*! \class QtVariantPropertyManager \brief The QtVariantPropertyManager class provides and manages QVariant based properties. QtVariantPropertyManager provides the addProperty() function which creates QtVariantProperty objects. The QtVariantProperty class is a convenience class handling QVariant based properties inheriting QtProperty. A QtProperty object created by a QtVariantPropertyManager instance can be converted into a QtVariantProperty object using the variantProperty() function. The property's value can be retrieved using the value(), and set using the setValue() slot. In addition the property's type, and the type of its value, can be retrieved using the propertyType() and valueType() functions respectively. A property's type is a QVariant::Type enumerator value, and usually a property's type is the same as its value type. But for some properties the types differ, for example for enums, flags and group types in which case QtVariantPropertyManager provides the enumTypeId(), flagTypeId() and groupTypeId() functions, respectively, to identify their property type (the value types are QVariant::Int for the enum and flag types, and QVariant::Invalid for the group type). Use the isPropertyTypeSupported() function to check if a particular property type is supported. The currently supported property types are: \table \header \o Property Type \o Property Type Id \row \o int \o QVariant::Int \row \o double \o QVariant::Double \row \o bool \o QVariant::Bool \row \o QString \o QVariant::String \row \o QDate \o QVariant::Date \row \o QTime \o QVariant::Time \row \o QDateTime \o QVariant::DateTime \row \o QKeySequence \o QVariant::KeySequence \row \o QChar \o QVariant::Char \row \o QLocale \o QVariant::Locale \row \o QPoint \o QVariant::Point \row \o QPointF \o QVariant::PointF \row \o QSize \o QVariant::Size \row \o QSizeF \o QVariant::SizeF \row \o QRect \o QVariant::Rect \row \o QRectF \o QVariant::RectF \row \o QColor \o QVariant::Color \row \o QSizePolicy \o QVariant::SizePolicy \row \o QFont \o QVariant::Font \row \o QCursor \o QVariant::Cursor \row \o enum \o enumTypeId() \row \o flag \o flagTypeId() \row \o group \o groupTypeId() \endtable Each property type can provide additional attributes, e.g. QVariant::Int and QVariant::Double provides minimum and maximum values. The currently supported attributes are: \table \header \o Property Type \o Attribute Name \o Attribute Type \row \o \c int \o minimum \o QVariant::Int \row \o \o maximum \o QVariant::Int \row \o \o singleStep \o QVariant::Int \row \o \c double \o minimum \o QVariant::Double \row \o \o maximum \o QVariant::Double \row \o \o singleStep \o QVariant::Double \row \o bool \o textVisible \o QVariant::Bool \row \o \o decimals \o QVariant::Int \row \o QString \o regExp \o QVariant::RegExp \row \o \o echoMode \o QVariant::Int \row \o QDate \o minimum \o QVariant::Date \row \o \o maximum \o QVariant::Date \row \o QPointF \o decimals \o QVariant::Int \row \o QSize \o minimum \o QVariant::Size \row \o \o maximum \o QVariant::Size \row \o QSizeF \o minimum \o QVariant::SizeF \row \o \o maximum \o QVariant::SizeF \row \o \o decimals \o QVariant::Int \row \o QRect \o constraint \o QVariant::Rect \row \o QRectF \o constraint \o QVariant::RectF \row \o \o decimals \o QVariant::Int \row \o \c enum \o enumNames \o QVariant::StringList \row \o \o enumIcons \o iconMapTypeId() \row \o \c flag \o flagNames \o QVariant::StringList \endtable The attributes for a given property type can be retrieved using the attributes() function. Each attribute has a value type which can be retrieved using the attributeType() function, and a value accessible through the attributeValue() function. In addition, the value can be set using the setAttribute() slot. QtVariantManager also provides the valueChanged() signal which is emitted whenever a property created by this manager change, and the attributeChanged() signal which is emitted whenever an attribute of such a property changes. \sa QtVariantProperty, QtVariantEditorFactory */ /*! \fn void QtVariantPropertyManager::valueChanged(QtProperty *property, const QVariant &value) This signal is emitted whenever a property created by this manager changes its value, passing a pointer to the \a property and the new \a value as parameters. \sa setValue() */ /*! \fn void QtVariantPropertyManager::attributeChanged(QtProperty *property, const QString &attribute, const QVariant &value) This signal is emitted whenever an attribute of a property created by this manager changes its value, passing a pointer to the \a property, the \a attribute and the new \a value as parameters. \sa setAttribute() */ /*! Creates a manager with the given \a parent. */ QtVariantPropertyManager::QtVariantPropertyManager(QObject *parent) : QtAbstractPropertyManager(parent) { d_ptr = new QtVariantPropertyManagerPrivate; d_ptr->q_ptr = this; d_ptr->m_creatingProperty = false; d_ptr->m_creatingSubProperties = false; d_ptr->m_destroyingSubProperties = false; d_ptr->m_propertyType = 0; // IntPropertyManager QtIntPropertyManager *intPropertyManager = new QtIntPropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::Int] = intPropertyManager; d_ptr->m_typeToAttributeToAttributeType[QVariant::Int][d_ptr->m_minimumAttribute] = QVariant::Int; d_ptr->m_typeToAttributeToAttributeType[QVariant::Int][d_ptr->m_maximumAttribute] = QVariant::Int; d_ptr->m_typeToAttributeToAttributeType[QVariant::Int][d_ptr->m_singleStepAttribute] = QVariant::Int; d_ptr->m_typeToAttributeToAttributeType[QVariant::Int][d_ptr->m_readOnlyAttribute] = QVariant::Bool; d_ptr->m_typeToValueType[QVariant::Int] = QVariant::Int; connect(intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotValueChanged(QtProperty *, int))); connect(intPropertyManager, SIGNAL(rangeChanged(QtProperty *, int, int)), this, SLOT(slotRangeChanged(QtProperty *, int, int))); connect(intPropertyManager, SIGNAL(singleStepChanged(QtProperty *, int)), this, SLOT(slotSingleStepChanged(QtProperty *, int))); // DoublePropertyManager QtDoublePropertyManager *doublePropertyManager = new QtDoublePropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::Double] = doublePropertyManager; d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_minimumAttribute] = QVariant::Double; d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_maximumAttribute] = QVariant::Double; d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_singleStepAttribute] = QVariant::Double; d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_decimalsAttribute] = QVariant::Int; d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_readOnlyAttribute] = QVariant::Bool; d_ptr->m_typeToValueType[QVariant::Double] = QVariant::Double; connect(doublePropertyManager, SIGNAL(valueChanged(QtProperty *, double)), this, SLOT(slotValueChanged(QtProperty *, double))); connect(doublePropertyManager, SIGNAL(rangeChanged(QtProperty *, double, double)), this, SLOT(slotRangeChanged(QtProperty *, double, double))); connect(doublePropertyManager, SIGNAL(singleStepChanged(QtProperty *, double)), this, SLOT(slotSingleStepChanged(QtProperty *, double))); connect(doublePropertyManager, SIGNAL(decimalsChanged(QtProperty *, int)), this, SLOT(slotDecimalsChanged(QtProperty *, int))); // BoolPropertyManager QtBoolPropertyManager *boolPropertyManager = new QtBoolPropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::Bool] = boolPropertyManager; d_ptr->m_typeToAttributeToAttributeType[QVariant::Bool][d_ptr->m_textVisibleAttribute] = QVariant::Bool; d_ptr->m_typeToValueType[QVariant::Bool] = QVariant::Bool; connect(boolPropertyManager, SIGNAL(valueChanged(QtProperty *, bool)), this, SLOT(slotValueChanged(QtProperty *, bool))); connect(boolPropertyManager, SIGNAL(textVisibleChanged(QtProperty*, bool)), this, SLOT(slotTextVisibleChanged(QtProperty*, bool))); // StringPropertyManager QtStringPropertyManager *stringPropertyManager = new QtStringPropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::String] = stringPropertyManager; d_ptr->m_typeToValueType[QVariant::String] = QVariant::String; d_ptr->m_typeToAttributeToAttributeType[QVariant::String][d_ptr->m_regExpAttribute] = QVariant::RegExp; d_ptr->m_typeToAttributeToAttributeType[QVariant::String][d_ptr->m_echoModeAttribute] = QVariant::Int; d_ptr->m_typeToAttributeToAttributeType[QVariant::String][d_ptr->m_readOnlyAttribute] = QVariant::Bool; connect(stringPropertyManager, SIGNAL(valueChanged(QtProperty *, const QString &)), this, SLOT(slotValueChanged(QtProperty *, const QString &))); connect(stringPropertyManager, SIGNAL(regExpChanged(QtProperty *, const QRegExp &)), this, SLOT(slotRegExpChanged(QtProperty *, const QRegExp &))); connect(stringPropertyManager, SIGNAL(echoModeChanged(QtProperty*,int)), this, SLOT(slotEchoModeChanged(QtProperty*, int))); connect(stringPropertyManager, SIGNAL(readOnlyChanged(QtProperty*, bool)), this, SLOT(slotReadOnlyChanged(QtProperty*, bool))); // DatePropertyManager QtDatePropertyManager *datePropertyManager = new QtDatePropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::Date] = datePropertyManager; d_ptr->m_typeToValueType[QVariant::Date] = QVariant::Date; d_ptr->m_typeToAttributeToAttributeType[QVariant::Date][d_ptr->m_minimumAttribute] = QVariant::Date; d_ptr->m_typeToAttributeToAttributeType[QVariant::Date][d_ptr->m_maximumAttribute] = QVariant::Date; connect(datePropertyManager, SIGNAL(valueChanged(QtProperty *, const QDate &)), this, SLOT(slotValueChanged(QtProperty *, const QDate &))); connect(datePropertyManager, SIGNAL(rangeChanged(QtProperty *, const QDate &, const QDate &)), this, SLOT(slotRangeChanged(QtProperty *, const QDate &, const QDate &))); // TimePropertyManager QtTimePropertyManager *timePropertyManager = new QtTimePropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::Time] = timePropertyManager; d_ptr->m_typeToValueType[QVariant::Time] = QVariant::Time; connect(timePropertyManager, SIGNAL(valueChanged(QtProperty *, const QTime &)), this, SLOT(slotValueChanged(QtProperty *, const QTime &))); // DateTimePropertyManager QtDateTimePropertyManager *dateTimePropertyManager = new QtDateTimePropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::DateTime] = dateTimePropertyManager; d_ptr->m_typeToValueType[QVariant::DateTime] = QVariant::DateTime; connect(dateTimePropertyManager, SIGNAL(valueChanged(QtProperty *, const QDateTime &)), this, SLOT(slotValueChanged(QtProperty *, const QDateTime &))); // KeySequencePropertyManager QtKeySequencePropertyManager *keySequencePropertyManager = new QtKeySequencePropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::KeySequence] = keySequencePropertyManager; d_ptr->m_typeToValueType[QVariant::KeySequence] = QVariant::KeySequence; connect(keySequencePropertyManager, SIGNAL(valueChanged(QtProperty *, const QKeySequence &)), this, SLOT(slotValueChanged(QtProperty *, const QKeySequence &))); // CharPropertyManager QtCharPropertyManager *charPropertyManager = new QtCharPropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::Char] = charPropertyManager; d_ptr->m_typeToValueType[QVariant::Char] = QVariant::Char; connect(charPropertyManager, SIGNAL(valueChanged(QtProperty *, const QChar &)), this, SLOT(slotValueChanged(QtProperty *, const QChar &))); // LocalePropertyManager QtLocalePropertyManager *localePropertyManager = new QtLocalePropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::Locale] = localePropertyManager; d_ptr->m_typeToValueType[QVariant::Locale] = QVariant::Locale; connect(localePropertyManager, SIGNAL(valueChanged(QtProperty *, const QLocale &)), this, SLOT(slotValueChanged(QtProperty *, const QLocale &))); connect(localePropertyManager->subEnumPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotValueChanged(QtProperty *, int))); connect(localePropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); connect(localePropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); // PointPropertyManager QtPointPropertyManager *pointPropertyManager = new QtPointPropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::Point] = pointPropertyManager; d_ptr->m_typeToValueType[QVariant::Point] = QVariant::Point; connect(pointPropertyManager, SIGNAL(valueChanged(QtProperty *, const QPoint &)), this, SLOT(slotValueChanged(QtProperty *, const QPoint &))); connect(pointPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotValueChanged(QtProperty *, int))); connect(pointPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); connect(pointPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); // PointFPropertyManager QtPointFPropertyManager *pointFPropertyManager = new QtPointFPropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::PointF] = pointFPropertyManager; d_ptr->m_typeToValueType[QVariant::PointF] = QVariant::PointF; d_ptr->m_typeToAttributeToAttributeType[QVariant::PointF][d_ptr->m_decimalsAttribute] = QVariant::Int; connect(pointFPropertyManager, SIGNAL(valueChanged(QtProperty *, const QPointF &)), this, SLOT(slotValueChanged(QtProperty *, const QPointF &))); connect(pointFPropertyManager, SIGNAL(decimalsChanged(QtProperty *, int)), this, SLOT(slotDecimalsChanged(QtProperty *, int))); connect(pointFPropertyManager->subDoublePropertyManager(), SIGNAL(valueChanged(QtProperty *, double)), this, SLOT(slotValueChanged(QtProperty *, double))); connect(pointFPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); connect(pointFPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); // SizePropertyManager QtSizePropertyManager *sizePropertyManager = new QtSizePropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::Size] = sizePropertyManager; d_ptr->m_typeToValueType[QVariant::Size] = QVariant::Size; d_ptr->m_typeToAttributeToAttributeType[QVariant::Size][d_ptr->m_minimumAttribute] = QVariant::Size; d_ptr->m_typeToAttributeToAttributeType[QVariant::Size][d_ptr->m_maximumAttribute] = QVariant::Size; connect(sizePropertyManager, SIGNAL(valueChanged(QtProperty *, const QSize &)), this, SLOT(slotValueChanged(QtProperty *, const QSize &))); connect(sizePropertyManager, SIGNAL(rangeChanged(QtProperty *, const QSize &, const QSize &)), this, SLOT(slotRangeChanged(QtProperty *, const QSize &, const QSize &))); connect(sizePropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotValueChanged(QtProperty *, int))); connect(sizePropertyManager->subIntPropertyManager(), SIGNAL(rangeChanged(QtProperty *, int, int)), this, SLOT(slotRangeChanged(QtProperty *, int, int))); connect(sizePropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); connect(sizePropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); // SizeFPropertyManager QtSizeFPropertyManager *sizeFPropertyManager = new QtSizeFPropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::SizeF] = sizeFPropertyManager; d_ptr->m_typeToValueType[QVariant::SizeF] = QVariant::SizeF; d_ptr->m_typeToAttributeToAttributeType[QVariant::SizeF][d_ptr->m_minimumAttribute] = QVariant::SizeF; d_ptr->m_typeToAttributeToAttributeType[QVariant::SizeF][d_ptr->m_maximumAttribute] = QVariant::SizeF; d_ptr->m_typeToAttributeToAttributeType[QVariant::SizeF][d_ptr->m_decimalsAttribute] = QVariant::Int; connect(sizeFPropertyManager, SIGNAL(valueChanged(QtProperty *, const QSizeF &)), this, SLOT(slotValueChanged(QtProperty *, const QSizeF &))); connect(sizeFPropertyManager, SIGNAL(rangeChanged(QtProperty *, const QSizeF &, const QSizeF &)), this, SLOT(slotRangeChanged(QtProperty *, const QSizeF &, const QSizeF &))); connect(sizeFPropertyManager, SIGNAL(decimalsChanged(QtProperty *, int)), this, SLOT(slotDecimalsChanged(QtProperty *, int))); connect(sizeFPropertyManager->subDoublePropertyManager(), SIGNAL(valueChanged(QtProperty *, double)), this, SLOT(slotValueChanged(QtProperty *, double))); connect(sizeFPropertyManager->subDoublePropertyManager(), SIGNAL(rangeChanged(QtProperty *, double, double)), this, SLOT(slotRangeChanged(QtProperty *, double, double))); connect(sizeFPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); connect(sizeFPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); // RectPropertyManager QtRectPropertyManager *rectPropertyManager = new QtRectPropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::Rect] = rectPropertyManager; d_ptr->m_typeToValueType[QVariant::Rect] = QVariant::Rect; d_ptr->m_typeToAttributeToAttributeType[QVariant::Rect][d_ptr->m_constraintAttribute] = QVariant::Rect; connect(rectPropertyManager, SIGNAL(valueChanged(QtProperty *, const QRect &)), this, SLOT(slotValueChanged(QtProperty *, const QRect &))); connect(rectPropertyManager, SIGNAL(constraintChanged(QtProperty *, const QRect &)), this, SLOT(slotConstraintChanged(QtProperty *, const QRect &))); connect(rectPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotValueChanged(QtProperty *, int))); connect(rectPropertyManager->subIntPropertyManager(), SIGNAL(rangeChanged(QtProperty *, int, int)), this, SLOT(slotRangeChanged(QtProperty *, int, int))); connect(rectPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); connect(rectPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); // RectFPropertyManager QtRectFPropertyManager *rectFPropertyManager = new QtRectFPropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::RectF] = rectFPropertyManager; d_ptr->m_typeToValueType[QVariant::RectF] = QVariant::RectF; d_ptr->m_typeToAttributeToAttributeType[QVariant::RectF][d_ptr->m_constraintAttribute] = QVariant::RectF; d_ptr->m_typeToAttributeToAttributeType[QVariant::RectF][d_ptr->m_decimalsAttribute] = QVariant::Int; connect(rectFPropertyManager, SIGNAL(valueChanged(QtProperty *, const QRectF &)), this, SLOT(slotValueChanged(QtProperty *, const QRectF &))); connect(rectFPropertyManager, SIGNAL(constraintChanged(QtProperty *, const QRectF &)), this, SLOT(slotConstraintChanged(QtProperty *, const QRectF &))); connect(rectFPropertyManager, SIGNAL(decimalsChanged(QtProperty *, int)), this, SLOT(slotDecimalsChanged(QtProperty *, int))); connect(rectFPropertyManager->subDoublePropertyManager(), SIGNAL(valueChanged(QtProperty *, double)), this, SLOT(slotValueChanged(QtProperty *, double))); connect(rectFPropertyManager->subDoublePropertyManager(), SIGNAL(rangeChanged(QtProperty *, double, double)), this, SLOT(slotRangeChanged(QtProperty *, double, double))); connect(rectFPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); connect(rectFPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); // ColorPropertyManager QtColorPropertyManager *colorPropertyManager = new QtColorPropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::Color] = colorPropertyManager; d_ptr->m_typeToValueType[QVariant::Color] = QVariant::Color; connect(colorPropertyManager, SIGNAL(valueChanged(QtProperty *, const QColor &)), this, SLOT(slotValueChanged(QtProperty *, const QColor &))); connect(colorPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotValueChanged(QtProperty *, int))); connect(colorPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); connect(colorPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); // EnumPropertyManager int enumId = enumTypeId(); QtEnumPropertyManager *enumPropertyManager = new QtEnumPropertyManager(this); d_ptr->m_typeToPropertyManager[enumId] = enumPropertyManager; d_ptr->m_typeToValueType[enumId] = QVariant::Int; d_ptr->m_typeToAttributeToAttributeType[enumId][d_ptr->m_enumNamesAttribute] = QVariant::StringList; d_ptr->m_typeToAttributeToAttributeType[enumId][d_ptr->m_enumIconsAttribute] = iconMapTypeId(); connect(enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotValueChanged(QtProperty *, int))); connect(enumPropertyManager, SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)), this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &))); connect(enumPropertyManager, SIGNAL(enumIconsChanged(QtProperty *, const QMap &)), this, SLOT(slotEnumIconsChanged(QtProperty *, const QMap &))); // SizePolicyPropertyManager QtSizePolicyPropertyManager *sizePolicyPropertyManager = new QtSizePolicyPropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::SizePolicy] = sizePolicyPropertyManager; d_ptr->m_typeToValueType[QVariant::SizePolicy] = QVariant::SizePolicy; connect(sizePolicyPropertyManager, SIGNAL(valueChanged(QtProperty *, const QSizePolicy &)), this, SLOT(slotValueChanged(QtProperty *, const QSizePolicy &))); connect(sizePolicyPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotValueChanged(QtProperty *, int))); connect(sizePolicyPropertyManager->subIntPropertyManager(), SIGNAL(rangeChanged(QtProperty *, int, int)), this, SLOT(slotRangeChanged(QtProperty *, int, int))); connect(sizePolicyPropertyManager->subEnumPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotValueChanged(QtProperty *, int))); connect(sizePolicyPropertyManager->subEnumPropertyManager(), SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)), this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &))); connect(sizePolicyPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); connect(sizePolicyPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); // FontPropertyManager QtFontPropertyManager *fontPropertyManager = new QtFontPropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::Font] = fontPropertyManager; d_ptr->m_typeToValueType[QVariant::Font] = QVariant::Font; connect(fontPropertyManager, SIGNAL(valueChanged(QtProperty *, const QFont &)), this, SLOT(slotValueChanged(QtProperty *, const QFont &))); connect(fontPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotValueChanged(QtProperty *, int))); connect(fontPropertyManager->subIntPropertyManager(), SIGNAL(rangeChanged(QtProperty *, int, int)), this, SLOT(slotRangeChanged(QtProperty *, int, int))); connect(fontPropertyManager->subEnumPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotValueChanged(QtProperty *, int))); connect(fontPropertyManager->subEnumPropertyManager(), SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)), this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &))); connect(fontPropertyManager->subBoolPropertyManager(), SIGNAL(valueChanged(QtProperty *, bool)), this, SLOT(slotValueChanged(QtProperty *, bool))); connect(fontPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); connect(fontPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); // CursorPropertyManager QtCursorPropertyManager *cursorPropertyManager = new QtCursorPropertyManager(this); d_ptr->m_typeToPropertyManager[QVariant::Cursor] = cursorPropertyManager; d_ptr->m_typeToValueType[QVariant::Cursor] = QVariant::Cursor; connect(cursorPropertyManager, SIGNAL(valueChanged(QtProperty *, const QCursor &)), this, SLOT(slotValueChanged(QtProperty *, const QCursor &))); // FlagPropertyManager int flagId = flagTypeId(); QtFlagPropertyManager *flagPropertyManager = new QtFlagPropertyManager(this); d_ptr->m_typeToPropertyManager[flagId] = flagPropertyManager; d_ptr->m_typeToValueType[flagId] = QVariant::Int; d_ptr->m_typeToAttributeToAttributeType[flagId][d_ptr->m_flagNamesAttribute] = QVariant::StringList; connect(flagPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), this, SLOT(slotValueChanged(QtProperty *, int))); connect(flagPropertyManager, SIGNAL(flagNamesChanged(QtProperty *, const QStringList &)), this, SLOT(slotFlagNamesChanged(QtProperty *, const QStringList &))); connect(flagPropertyManager->subBoolPropertyManager(), SIGNAL(valueChanged(QtProperty *, bool)), this, SLOT(slotValueChanged(QtProperty *, bool))); connect(flagPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); connect(flagPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); // FlagPropertyManager int groupId = groupTypeId(); QtGroupPropertyManager *groupPropertyManager = new QtGroupPropertyManager(this); d_ptr->m_typeToPropertyManager[groupId] = groupPropertyManager; d_ptr->m_typeToValueType[groupId] = QVariant::Invalid; } /*! Destroys this manager, and all the properties it has created. */ QtVariantPropertyManager::~QtVariantPropertyManager() { clear(); delete d_ptr; } /*! Returns the given \a property converted into a QtVariantProperty. If the \a property was not created by this variant manager, the function returns 0. \sa createProperty() */ QtVariantProperty *QtVariantPropertyManager::variantProperty(const QtProperty *property) const { const QMap >::const_iterator it = d_ptr->m_propertyToType.constFind(property); if (it == d_ptr->m_propertyToType.constEnd()) return 0; return it.value().first; } /*! Returns true if the given \a propertyType is supported by this variant manager; otherwise false. \sa propertyType() */ bool QtVariantPropertyManager::isPropertyTypeSupported(int propertyType) const { if (d_ptr->m_typeToValueType.contains(propertyType)) return true; return false; } /*! Creates and returns a variant property of the given \a propertyType with the given \a name. If the specified \a propertyType is not supported by this variant manager, this function returns 0. Do not use the inherited QtAbstractPropertyManager::addProperty() function to create a variant property (that function will always return 0 since it will not be clear what type the property should have). \sa isPropertyTypeSupported() */ QtVariantProperty *QtVariantPropertyManager::addProperty(int propertyType, const QString &name) { if (!isPropertyTypeSupported(propertyType)) return 0; bool wasCreating = d_ptr->m_creatingProperty; d_ptr->m_creatingProperty = true; d_ptr->m_propertyType = propertyType; QtProperty *property = QtAbstractPropertyManager::addProperty(name); d_ptr->m_creatingProperty = wasCreating; d_ptr->m_propertyType = 0; if (!property) return 0; return variantProperty(property); } /*! Returns the given \a property's value. If the given \a property is not managed by this manager, this function returns an invalid variant. \sa setValue() */ QVariant QtVariantPropertyManager::value(const QtProperty *property) const { QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); if (internProp == 0) return QVariant(); QtAbstractPropertyManager *manager = internProp->propertyManager(); if (QtIntPropertyManager *intManager = qobject_cast(manager)) { return intManager->value(internProp); } else if (QtDoublePropertyManager *doubleManager = qobject_cast(manager)) { return doubleManager->value(internProp); } else if (QtBoolPropertyManager *boolManager = qobject_cast(manager)) { return boolManager->value(internProp); } else if (QtStringPropertyManager *stringManager = qobject_cast(manager)) { return stringManager->value(internProp); } else if (QtDatePropertyManager *dateManager = qobject_cast(manager)) { return dateManager->value(internProp); } else if (QtTimePropertyManager *timeManager = qobject_cast(manager)) { return timeManager->value(internProp); } else if (QtDateTimePropertyManager *dateTimeManager = qobject_cast(manager)) { return dateTimeManager->value(internProp); } else if (QtKeySequencePropertyManager *keySequenceManager = qobject_cast(manager)) { #if QT_VERSION < 0x050000 return keySequenceManager->value(internProp); #else return QVariant::fromValue(keySequenceManager->value(internProp)); #endif } else if (QtCharPropertyManager *charManager = qobject_cast(manager)) { return charManager->value(internProp); } else if (QtLocalePropertyManager *localeManager = qobject_cast(manager)) { return localeManager->value(internProp); } else if (QtPointPropertyManager *pointManager = qobject_cast(manager)) { return pointManager->value(internProp); } else if (QtPointFPropertyManager *pointFManager = qobject_cast(manager)) { return pointFManager->value(internProp); } else if (QtSizePropertyManager *sizeManager = qobject_cast(manager)) { return sizeManager->value(internProp); } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast(manager)) { return sizeFManager->value(internProp); } else if (QtRectPropertyManager *rectManager = qobject_cast(manager)) { return rectManager->value(internProp); } else if (QtRectFPropertyManager *rectFManager = qobject_cast(manager)) { return rectFManager->value(internProp); } else if (QtColorPropertyManager *colorManager = qobject_cast(manager)) { return colorManager->value(internProp); } else if (QtEnumPropertyManager *enumManager = qobject_cast(manager)) { return enumManager->value(internProp); } else if (QtSizePolicyPropertyManager *sizePolicyManager = qobject_cast(manager)) { return sizePolicyManager->value(internProp); } else if (QtFontPropertyManager *fontManager = qobject_cast(manager)) { return fontManager->value(internProp); #ifndef QT_NO_CURSOR } else if (QtCursorPropertyManager *cursorManager = qobject_cast(manager)) { return cursorManager->value(internProp); #endif } else if (QtFlagPropertyManager *flagManager = qobject_cast(manager)) { return flagManager->value(internProp); } return QVariant(); } /*! Returns the given \a property's value type. \sa propertyType() */ int QtVariantPropertyManager::valueType(const QtProperty *property) const { int propType = propertyType(property); return valueType(propType); } /*! \overload Returns the value type associated with the given \a propertyType. */ int QtVariantPropertyManager::valueType(int propertyType) const { if (d_ptr->m_typeToValueType.contains(propertyType)) return d_ptr->m_typeToValueType[propertyType]; return 0; } /*! Returns the given \a property's type. \sa valueType() */ int QtVariantPropertyManager::propertyType(const QtProperty *property) const { const QMap >::const_iterator it = d_ptr->m_propertyToType.constFind(property); if (it == d_ptr->m_propertyToType.constEnd()) return 0; return it.value().second; } /*! Returns the given \a property's value for the specified \a attribute If the given \a property was not created by \e this manager, or if the specified \a attribute does not exist, this function returns an invalid variant. \sa attributes(), attributeType(), setAttribute() */ QVariant QtVariantPropertyManager::attributeValue(const QtProperty *property, const QString &attribute) const { int propType = propertyType(property); if (!propType) return QVariant(); QMap >::ConstIterator it = d_ptr->m_typeToAttributeToAttributeType.find(propType); if (it == d_ptr->m_typeToAttributeToAttributeType.constEnd()) return QVariant(); QMap attributes = it.value(); QMap::ConstIterator itAttr = attributes.find(attribute); if (itAttr == attributes.constEnd()) return QVariant(); QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); if (internProp == 0) return QVariant(); QtAbstractPropertyManager *manager = internProp->propertyManager(); if (QtIntPropertyManager *intManager = qobject_cast(manager)) { if (attribute == d_ptr->m_maximumAttribute) return intManager->maximum(internProp); if (attribute == d_ptr->m_minimumAttribute) return intManager->minimum(internProp); if (attribute == d_ptr->m_singleStepAttribute) return intManager->singleStep(internProp); if (attribute == d_ptr->m_readOnlyAttribute) return intManager->isReadOnly(internProp); return QVariant(); } else if (QtDoublePropertyManager *doubleManager = qobject_cast(manager)) { if (attribute == d_ptr->m_maximumAttribute) return doubleManager->maximum(internProp); if (attribute == d_ptr->m_minimumAttribute) return doubleManager->minimum(internProp); if (attribute == d_ptr->m_singleStepAttribute) return doubleManager->singleStep(internProp); if (attribute == d_ptr->m_decimalsAttribute) return doubleManager->decimals(internProp); if (attribute == d_ptr->m_readOnlyAttribute) return doubleManager->isReadOnly(internProp); return QVariant(); } else if (QtBoolPropertyManager *boolManager = qobject_cast(manager)) { if (attribute == d_ptr->m_textVisibleAttribute) return boolManager->textVisible(internProp); return QVariant(); } else if (QtStringPropertyManager *stringManager = qobject_cast(manager)) { if (attribute == d_ptr->m_regExpAttribute) return stringManager->regExp(internProp); if (attribute == d_ptr->m_echoModeAttribute) return stringManager->echoMode(internProp); if (attribute == d_ptr->m_readOnlyAttribute) return stringManager->isReadOnly(internProp); return QVariant(); } else if (QtDatePropertyManager *dateManager = qobject_cast(manager)) { if (attribute == d_ptr->m_maximumAttribute) return dateManager->maximum(internProp); if (attribute == d_ptr->m_minimumAttribute) return dateManager->minimum(internProp); return QVariant(); } else if (QtPointFPropertyManager *pointFManager = qobject_cast(manager)) { if (attribute == d_ptr->m_decimalsAttribute) return pointFManager->decimals(internProp); return QVariant(); } else if (QtSizePropertyManager *sizeManager = qobject_cast(manager)) { if (attribute == d_ptr->m_maximumAttribute) return sizeManager->maximum(internProp); if (attribute == d_ptr->m_minimumAttribute) return sizeManager->minimum(internProp); return QVariant(); } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast(manager)) { if (attribute == d_ptr->m_maximumAttribute) return sizeFManager->maximum(internProp); if (attribute == d_ptr->m_minimumAttribute) return sizeFManager->minimum(internProp); if (attribute == d_ptr->m_decimalsAttribute) return sizeFManager->decimals(internProp); return QVariant(); } else if (QtRectPropertyManager *rectManager = qobject_cast(manager)) { if (attribute == d_ptr->m_constraintAttribute) return rectManager->constraint(internProp); return QVariant(); } else if (QtRectFPropertyManager *rectFManager = qobject_cast(manager)) { if (attribute == d_ptr->m_constraintAttribute) return rectFManager->constraint(internProp); if (attribute == d_ptr->m_decimalsAttribute) return rectFManager->decimals(internProp); return QVariant(); } else if (QtEnumPropertyManager *enumManager = qobject_cast(manager)) { if (attribute == d_ptr->m_enumNamesAttribute) return enumManager->enumNames(internProp); if (attribute == d_ptr->m_enumIconsAttribute) { QVariant v; qVariantSetValue(v, enumManager->enumIcons(internProp)); return v; } return QVariant(); } else if (QtFlagPropertyManager *flagManager = qobject_cast(manager)) { if (attribute == d_ptr->m_flagNamesAttribute) return flagManager->flagNames(internProp); return QVariant(); } return QVariant(); } /*! Returns a list of the given \a propertyType 's attributes. \sa attributeValue(), attributeType() */ QStringList QtVariantPropertyManager::attributes(int propertyType) const { QMap >::ConstIterator it = d_ptr->m_typeToAttributeToAttributeType.find(propertyType); if (it == d_ptr->m_typeToAttributeToAttributeType.constEnd()) return QStringList(); return it.value().keys(); } /*! Returns the type of the specified \a attribute of the given \a propertyType. If the given \a propertyType is not supported by \e this manager, or if the given \a propertyType does not possess the specified \a attribute, this function returns QVariant::Invalid. \sa attributes(), valueType() */ int QtVariantPropertyManager::attributeType(int propertyType, const QString &attribute) const { QMap >::ConstIterator it = d_ptr->m_typeToAttributeToAttributeType.find(propertyType); if (it == d_ptr->m_typeToAttributeToAttributeType.constEnd()) return 0; QMap attributes = it.value(); QMap::ConstIterator itAttr = attributes.find(attribute); if (itAttr == attributes.constEnd()) return 0; return itAttr.value(); } /*! \fn void QtVariantPropertyManager::setValue(QtProperty *property, const QVariant &value) Sets the value of the given \a property to \a value. The specified \a value must be of a type returned by valueType(), or of type that can be converted to valueType() using the QVariant::canConvert() function, otherwise this function does nothing. \sa value(), QtVariantProperty::setValue(), valueChanged() */ void QtVariantPropertyManager::setValue(QtProperty *property, const QVariant &val) { int propType = val.userType(); if (!propType) return; int valType = valueType(property); if (propType != valType && !val.canConvert(static_cast(valType))) return; QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); if (internProp == 0) return; QtAbstractPropertyManager *manager = internProp->propertyManager(); if (QtIntPropertyManager *intManager = qobject_cast(manager)) { intManager->setValue(internProp, val.value()); return; } else if (QtDoublePropertyManager *doubleManager = qobject_cast(manager)) { doubleManager->setValue(internProp, val.value()); return; } else if (QtBoolPropertyManager *boolManager = qobject_cast(manager)) { boolManager->setValue(internProp, val.value()); return; } else if (QtStringPropertyManager *stringManager = qobject_cast(manager)) { stringManager->setValue(internProp, val.value()); return; } else if (QtDatePropertyManager *dateManager = qobject_cast(manager)) { dateManager->setValue(internProp, val.value()); return; } else if (QtTimePropertyManager *timeManager = qobject_cast(manager)) { timeManager->setValue(internProp, val.value()); return; } else if (QtDateTimePropertyManager *dateTimeManager = qobject_cast(manager)) { dateTimeManager->setValue(internProp, val.value()); return; } else if (QtKeySequencePropertyManager *keySequenceManager = qobject_cast(manager)) { keySequenceManager->setValue(internProp, val.value()); return; } else if (QtCharPropertyManager *charManager = qobject_cast(manager)) { charManager->setValue(internProp, val.value()); return; } else if (QtLocalePropertyManager *localeManager = qobject_cast(manager)) { localeManager->setValue(internProp, val.value()); return; } else if (QtPointPropertyManager *pointManager = qobject_cast(manager)) { pointManager->setValue(internProp, val.value()); return; } else if (QtPointFPropertyManager *pointFManager = qobject_cast(manager)) { pointFManager->setValue(internProp, val.value()); return; } else if (QtSizePropertyManager *sizeManager = qobject_cast(manager)) { sizeManager->setValue(internProp, val.value()); return; } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast(manager)) { sizeFManager->setValue(internProp, val.value()); return; } else if (QtRectPropertyManager *rectManager = qobject_cast(manager)) { rectManager->setValue(internProp, val.value()); return; } else if (QtRectFPropertyManager *rectFManager = qobject_cast(manager)) { rectFManager->setValue(internProp, val.value()); return; } else if (QtColorPropertyManager *colorManager = qobject_cast(manager)) { colorManager->setValue(internProp, val.value()); return; } else if (QtEnumPropertyManager *enumManager = qobject_cast(manager)) { enumManager->setValue(internProp, val.value()); return; } else if (QtSizePolicyPropertyManager *sizePolicyManager = qobject_cast(manager)) { sizePolicyManager->setValue(internProp, val.value()); return; } else if (QtFontPropertyManager *fontManager = qobject_cast(manager)) { fontManager->setValue(internProp, val.value()); return; #ifndef QT_NO_CURSOR } else if (QtCursorPropertyManager *cursorManager = qobject_cast(manager)) { cursorManager->setValue(internProp, val.value()); return; #endif } else if (QtFlagPropertyManager *flagManager = qobject_cast(manager)) { flagManager->setValue(internProp, val.value()); return; } } /*! Sets the value of the specified \a attribute of the given \a property, to \a value. The new \a value's type must be of the type returned by attributeType(), or of a type that can be converted to attributeType() using the QVariant::canConvert() function, otherwise this function does nothing. \sa attributeValue(), QtVariantProperty::setAttribute(), attributeChanged() */ void QtVariantPropertyManager::setAttribute(QtProperty *property, const QString &attribute, const QVariant &value) { QVariant oldAttr = attributeValue(property, attribute); if (!oldAttr.isValid()) return; int attrType = value.userType(); if (!attrType) return; if (attrType != attributeType(propertyType(property), attribute) && !value.canConvert((QVariant::Type)attrType)) return; QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); if (internProp == 0) return; QtAbstractPropertyManager *manager = internProp->propertyManager(); if (QtIntPropertyManager *intManager = qobject_cast(manager)) { if (attribute == d_ptr->m_maximumAttribute) intManager->setMaximum(internProp, value.value()); else if (attribute == d_ptr->m_minimumAttribute) intManager->setMinimum(internProp, value.value()); else if (attribute == d_ptr->m_singleStepAttribute) intManager->setSingleStep(internProp, value.value()); else if (attribute == d_ptr->m_readOnlyAttribute) intManager->setReadOnly(internProp, value.value()); return; } else if (QtDoublePropertyManager *doubleManager = qobject_cast(manager)) { if (attribute == d_ptr->m_maximumAttribute) doubleManager->setMaximum(internProp, value.value()); if (attribute == d_ptr->m_minimumAttribute) doubleManager->setMinimum(internProp, value.value()); if (attribute == d_ptr->m_singleStepAttribute) doubleManager->setSingleStep(internProp, value.value()); if (attribute == d_ptr->m_decimalsAttribute) doubleManager->setDecimals(internProp, value.value()); if (attribute == d_ptr->m_readOnlyAttribute) doubleManager->setReadOnly(internProp, value.value()); return; } else if (QtBoolPropertyManager *boolManager = qobject_cast(manager)) { if (attribute == d_ptr->m_textVisibleAttribute) boolManager->setTextVisible(internProp, value.value()); return; } else if (QtStringPropertyManager *stringManager = qobject_cast(manager)) { if (attribute == d_ptr->m_regExpAttribute) stringManager->setRegExp(internProp, value.value()); if (attribute == d_ptr->m_echoModeAttribute) stringManager->setEchoMode(internProp, (EchoMode)value.value()); if (attribute == d_ptr->m_readOnlyAttribute) stringManager->setReadOnly(internProp, (EchoMode)value.value()); return; } else if (QtDatePropertyManager *dateManager = qobject_cast(manager)) { if (attribute == d_ptr->m_maximumAttribute) dateManager->setMaximum(internProp, value.value()); if (attribute == d_ptr->m_minimumAttribute) dateManager->setMinimum(internProp, value.value()); return; } else if (QtPointFPropertyManager *pointFManager = qobject_cast(manager)) { if (attribute == d_ptr->m_decimalsAttribute) pointFManager->setDecimals(internProp, value.value()); return; } else if (QtSizePropertyManager *sizeManager = qobject_cast(manager)) { if (attribute == d_ptr->m_maximumAttribute) sizeManager->setMaximum(internProp, value.value()); if (attribute == d_ptr->m_minimumAttribute) sizeManager->setMinimum(internProp, value.value()); return; } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast(manager)) { if (attribute == d_ptr->m_maximumAttribute) sizeFManager->setMaximum(internProp, value.value()); if (attribute == d_ptr->m_minimumAttribute) sizeFManager->setMinimum(internProp, value.value()); if (attribute == d_ptr->m_decimalsAttribute) sizeFManager->setDecimals(internProp, value.value()); return; } else if (QtRectPropertyManager *rectManager = qobject_cast(manager)) { if (attribute == d_ptr->m_constraintAttribute) rectManager->setConstraint(internProp, value.value()); return; } else if (QtRectFPropertyManager *rectFManager = qobject_cast(manager)) { if (attribute == d_ptr->m_constraintAttribute) rectFManager->setConstraint(internProp, value.value()); if (attribute == d_ptr->m_decimalsAttribute) rectFManager->setDecimals(internProp, value.value()); return; } else if (QtEnumPropertyManager *enumManager = qobject_cast(manager)) { if (attribute == d_ptr->m_enumNamesAttribute) enumManager->setEnumNames(internProp, value.value()); if (attribute == d_ptr->m_enumIconsAttribute) enumManager->setEnumIcons(internProp, value.value()); return; } else if (QtFlagPropertyManager *flagManager = qobject_cast(manager)) { if (attribute == d_ptr->m_flagNamesAttribute) flagManager->setFlagNames(internProp, value.value()); return; } } /*! \reimp */ bool QtVariantPropertyManager::hasValue(const QtProperty *property) const { if (propertyType(property) == groupTypeId()) return false; return true; } /*! \reimp */ QString QtVariantPropertyManager::valueText(const QtProperty *property) const { const QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); return internProp ? !internProp->displayText().isEmpty() ? internProp->displayText() : internProp->valueText() : QString(); } /*! \reimp */ QIcon QtVariantPropertyManager::valueIcon(const QtProperty *property) const { const QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); return internProp ? internProp->valueIcon() : QIcon(); } /*! \reimp */ void QtVariantPropertyManager::initializeProperty(QtProperty *property) { QtVariantProperty *varProp = variantProperty(property); if (!varProp) return; QMap::ConstIterator it = d_ptr->m_typeToPropertyManager.find(d_ptr->m_propertyType); if (it != d_ptr->m_typeToPropertyManager.constEnd()) { QtProperty *internProp = 0; if (!d_ptr->m_creatingSubProperties) { QtAbstractPropertyManager *manager = it.value(); internProp = manager->addProperty(); d_ptr->m_internalToProperty[internProp] = varProp; } propertyToWrappedProperty()->insert(varProp, internProp); if (internProp) { QList children = internProp->subProperties(); QListIterator itChild(children); QtVariantProperty *lastProperty = 0; while (itChild.hasNext()) { QtVariantProperty *prop = d_ptr->createSubProperty(varProp, lastProperty, itChild.next()); lastProperty = prop ? prop : lastProperty; } } } } /*! \reimp */ void QtVariantPropertyManager::uninitializeProperty(QtProperty *property) { const QMap >::iterator type_it = d_ptr->m_propertyToType.find(property); if (type_it == d_ptr->m_propertyToType.end()) return; PropertyMap::iterator it = propertyToWrappedProperty()->find(property); if (it != propertyToWrappedProperty()->end()) { QtProperty *internProp = it.value(); if (internProp) { d_ptr->m_internalToProperty.remove(internProp); if (!d_ptr->m_destroyingSubProperties) { delete internProp; } } propertyToWrappedProperty()->erase(it); } d_ptr->m_propertyToType.erase(type_it); } /*! \reimp */ QtProperty *QtVariantPropertyManager::createProperty() { if (!d_ptr->m_creatingProperty) return 0; QtVariantProperty *property = new QtVariantProperty(this); d_ptr->m_propertyToType.insert(property, qMakePair(property, d_ptr->m_propertyType)); return property; } ///////////////////////////// class QtVariantEditorFactoryPrivate { QtVariantEditorFactory *q_ptr; Q_DECLARE_PUBLIC(QtVariantEditorFactory) public: QtSpinBoxFactory *m_spinBoxFactory; QtDoubleSpinBoxFactory *m_doubleSpinBoxFactory; QtCheckBoxFactory *m_checkBoxFactory; QtLineEditFactory *m_lineEditFactory; QtDateEditFactory *m_dateEditFactory; QtTimeEditFactory *m_timeEditFactory; QtDateTimeEditFactory *m_dateTimeEditFactory; QtKeySequenceEditorFactory *m_keySequenceEditorFactory; QtCharEditorFactory *m_charEditorFactory; QtEnumEditorFactory *m_comboBoxFactory; QtCursorEditorFactory *m_cursorEditorFactory; QtColorEditorFactory *m_colorEditorFactory; QtFontEditorFactory *m_fontEditorFactory; QMap m_factoryToType; QMap m_typeToFactory; }; /*! \class QtVariantEditorFactory \brief The QtVariantEditorFactory class provides widgets for properties created by QtVariantPropertyManager objects. The variant factory provides the following widgets for the specified property types: \table \header \o Property Type \o Widget \row \o \c int \o QSpinBox \row \o \c double \o QDoubleSpinBox \row \o \c bool \o QCheckBox \row \o QString \o QLineEdit \row \o QDate \o QDateEdit \row \o QTime \o QTimeEdit \row \o QDateTime \o QDateTimeEdit \row \o QKeySequence \o customized editor \row \o QChar \o customized editor \row \o \c enum \o QComboBox \row \o QCursor \o QComboBox \endtable Note that QtVariantPropertyManager supports several additional property types for which the QtVariantEditorFactory class does not provide editing widgets, e.g. QPoint and QSize. To provide widgets for other types using the variant approach, derive from the QtVariantEditorFactory class. \sa QtAbstractEditorFactory, QtVariantPropertyManager */ /*! Creates a factory with the given \a parent. */ QtVariantEditorFactory::QtVariantEditorFactory(QObject *parent) : QtAbstractEditorFactory(parent) { d_ptr = new QtVariantEditorFactoryPrivate(); d_ptr->q_ptr = this; d_ptr->m_spinBoxFactory = new QtSpinBoxFactory(this); d_ptr->m_factoryToType[d_ptr->m_spinBoxFactory] = QVariant::Int; d_ptr->m_typeToFactory[QVariant::Int] = d_ptr->m_spinBoxFactory; d_ptr->m_doubleSpinBoxFactory = new QtDoubleSpinBoxFactory(this); d_ptr->m_factoryToType[d_ptr->m_doubleSpinBoxFactory] = QVariant::Double; d_ptr->m_typeToFactory[QVariant::Double] = d_ptr->m_doubleSpinBoxFactory; d_ptr->m_checkBoxFactory = new QtCheckBoxFactory(this); d_ptr->m_factoryToType[d_ptr->m_checkBoxFactory] = QVariant::Bool; d_ptr->m_typeToFactory[QVariant::Bool] = d_ptr->m_checkBoxFactory; d_ptr->m_lineEditFactory = new QtLineEditFactory(this); d_ptr->m_factoryToType[d_ptr->m_lineEditFactory] = QVariant::String; d_ptr->m_typeToFactory[QVariant::String] = d_ptr->m_lineEditFactory; d_ptr->m_dateEditFactory = new QtDateEditFactory(this); d_ptr->m_factoryToType[d_ptr->m_dateEditFactory] = QVariant::Date; d_ptr->m_typeToFactory[QVariant::Date] = d_ptr->m_dateEditFactory; d_ptr->m_timeEditFactory = new QtTimeEditFactory(this); d_ptr->m_factoryToType[d_ptr->m_timeEditFactory] = QVariant::Time; d_ptr->m_typeToFactory[QVariant::Time] = d_ptr->m_timeEditFactory; d_ptr->m_dateTimeEditFactory = new QtDateTimeEditFactory(this); d_ptr->m_factoryToType[d_ptr->m_dateTimeEditFactory] = QVariant::DateTime; d_ptr->m_typeToFactory[QVariant::DateTime] = d_ptr->m_dateTimeEditFactory; d_ptr->m_keySequenceEditorFactory = new QtKeySequenceEditorFactory(this); d_ptr->m_factoryToType[d_ptr->m_keySequenceEditorFactory] = QVariant::KeySequence; d_ptr->m_typeToFactory[QVariant::KeySequence] = d_ptr->m_keySequenceEditorFactory; d_ptr->m_charEditorFactory = new QtCharEditorFactory(this); d_ptr->m_factoryToType[d_ptr->m_charEditorFactory] = QVariant::Char; d_ptr->m_typeToFactory[QVariant::Char] = d_ptr->m_charEditorFactory; d_ptr->m_cursorEditorFactory = new QtCursorEditorFactory(this); d_ptr->m_factoryToType[d_ptr->m_cursorEditorFactory] = QVariant::Cursor; d_ptr->m_typeToFactory[QVariant::Cursor] = d_ptr->m_cursorEditorFactory; d_ptr->m_colorEditorFactory = new QtColorEditorFactory(this); d_ptr->m_factoryToType[d_ptr->m_colorEditorFactory] = QVariant::Color; d_ptr->m_typeToFactory[QVariant::Color] = d_ptr->m_colorEditorFactory; d_ptr->m_fontEditorFactory = new QtFontEditorFactory(this); d_ptr->m_factoryToType[d_ptr->m_fontEditorFactory] = QVariant::Font; d_ptr->m_typeToFactory[QVariant::Font] = d_ptr->m_fontEditorFactory; d_ptr->m_comboBoxFactory = new QtEnumEditorFactory(this); const int enumId = QtVariantPropertyManager::enumTypeId(); d_ptr->m_factoryToType[d_ptr->m_comboBoxFactory] = enumId; d_ptr->m_typeToFactory[enumId] = d_ptr->m_comboBoxFactory; } /*! Destroys this factory, and all the widgets it has created. */ QtVariantEditorFactory::~QtVariantEditorFactory() { delete d_ptr; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtVariantEditorFactory::connectPropertyManager(QtVariantPropertyManager *manager) { QList intPropertyManagers = manager->findChildren(); QListIterator itInt(intPropertyManagers); while (itInt.hasNext()) d_ptr->m_spinBoxFactory->addPropertyManager(itInt.next()); QList doublePropertyManagers = manager->findChildren(); QListIterator itDouble(doublePropertyManagers); while (itDouble.hasNext()) d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itDouble.next()); QList boolPropertyManagers = manager->findChildren(); QListIterator itBool(boolPropertyManagers); while (itBool.hasNext()) d_ptr->m_checkBoxFactory->addPropertyManager(itBool.next()); QList stringPropertyManagers = manager->findChildren(); QListIterator itString(stringPropertyManagers); while (itString.hasNext()) d_ptr->m_lineEditFactory->addPropertyManager(itString.next()); QList datePropertyManagers = manager->findChildren(); QListIterator itDate(datePropertyManagers); while (itDate.hasNext()) d_ptr->m_dateEditFactory->addPropertyManager(itDate.next()); QList timePropertyManagers = manager->findChildren(); QListIterator itTime(timePropertyManagers); while (itTime.hasNext()) d_ptr->m_timeEditFactory->addPropertyManager(itTime.next()); QList dateTimePropertyManagers = manager->findChildren(); QListIterator itDateTime(dateTimePropertyManagers); while (itDateTime.hasNext()) d_ptr->m_dateTimeEditFactory->addPropertyManager(itDateTime.next()); QList keySequencePropertyManagers = manager->findChildren(); QListIterator itKeySequence(keySequencePropertyManagers); while (itKeySequence.hasNext()) d_ptr->m_keySequenceEditorFactory->addPropertyManager(itKeySequence.next()); QList charPropertyManagers = manager->findChildren(); QListIterator itChar(charPropertyManagers); while (itChar.hasNext()) d_ptr->m_charEditorFactory->addPropertyManager(itChar.next()); QList localePropertyManagers = manager->findChildren(); QListIterator itLocale(localePropertyManagers); while (itLocale.hasNext()) d_ptr->m_comboBoxFactory->addPropertyManager(itLocale.next()->subEnumPropertyManager()); QList pointPropertyManagers = manager->findChildren(); QListIterator itPoint(pointPropertyManagers); while (itPoint.hasNext()) d_ptr->m_spinBoxFactory->addPropertyManager(itPoint.next()->subIntPropertyManager()); QList pointFPropertyManagers = manager->findChildren(); QListIterator itPointF(pointFPropertyManagers); while (itPointF.hasNext()) d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itPointF.next()->subDoublePropertyManager()); QList sizePropertyManagers = manager->findChildren(); QListIterator itSize(sizePropertyManagers); while (itSize.hasNext()) d_ptr->m_spinBoxFactory->addPropertyManager(itSize.next()->subIntPropertyManager()); QList sizeFPropertyManagers = manager->findChildren(); QListIterator itSizeF(sizeFPropertyManagers); while (itSizeF.hasNext()) d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itSizeF.next()->subDoublePropertyManager()); QList rectPropertyManagers = manager->findChildren(); QListIterator itRect(rectPropertyManagers); while (itRect.hasNext()) d_ptr->m_spinBoxFactory->addPropertyManager(itRect.next()->subIntPropertyManager()); QList rectFPropertyManagers = manager->findChildren(); QListIterator itRectF(rectFPropertyManagers); while (itRectF.hasNext()) d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itRectF.next()->subDoublePropertyManager()); QList colorPropertyManagers = manager->findChildren(); QListIterator itColor(colorPropertyManagers); while (itColor.hasNext()) { QtColorPropertyManager *manager = itColor.next(); d_ptr->m_colorEditorFactory->addPropertyManager(manager); d_ptr->m_spinBoxFactory->addPropertyManager(manager->subIntPropertyManager()); } QList enumPropertyManagers = manager->findChildren(); QListIterator itEnum(enumPropertyManagers); while (itEnum.hasNext()) d_ptr->m_comboBoxFactory->addPropertyManager(itEnum.next()); QList sizePolicyPropertyManagers = manager->findChildren(); QListIterator itSizePolicy(sizePolicyPropertyManagers); while (itSizePolicy.hasNext()) { QtSizePolicyPropertyManager *manager = itSizePolicy.next(); d_ptr->m_spinBoxFactory->addPropertyManager(manager->subIntPropertyManager()); d_ptr->m_comboBoxFactory->addPropertyManager(manager->subEnumPropertyManager()); } QList fontPropertyManagers = manager->findChildren(); QListIterator itFont(fontPropertyManagers); while (itFont.hasNext()) { QtFontPropertyManager *manager = itFont.next(); d_ptr->m_fontEditorFactory->addPropertyManager(manager); d_ptr->m_spinBoxFactory->addPropertyManager(manager->subIntPropertyManager()); d_ptr->m_comboBoxFactory->addPropertyManager(manager->subEnumPropertyManager()); d_ptr->m_checkBoxFactory->addPropertyManager(manager->subBoolPropertyManager()); } QList cursorPropertyManagers = manager->findChildren(); QListIterator itCursor(cursorPropertyManagers); while (itCursor.hasNext()) d_ptr->m_cursorEditorFactory->addPropertyManager(itCursor.next()); QList flagPropertyManagers = manager->findChildren(); QListIterator itFlag(flagPropertyManagers); while (itFlag.hasNext()) d_ptr->m_checkBoxFactory->addPropertyManager(itFlag.next()->subBoolPropertyManager()); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtVariantEditorFactory::createEditor(QtVariantPropertyManager *manager, QtProperty *property, QWidget *parent) { const int propType = manager->propertyType(property); QtAbstractEditorFactoryBase *factory = d_ptr->m_typeToFactory.value(propType, 0); if (!factory) return 0; return factory->createEditor(wrappedProperty(property), parent); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtVariantEditorFactory::disconnectPropertyManager(QtVariantPropertyManager *manager) { QList intPropertyManagers = manager->findChildren(); QListIterator itInt(intPropertyManagers); while (itInt.hasNext()) d_ptr->m_spinBoxFactory->removePropertyManager(itInt.next()); QList doublePropertyManagers = manager->findChildren(); QListIterator itDouble(doublePropertyManagers); while (itDouble.hasNext()) d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itDouble.next()); QList boolPropertyManagers = manager->findChildren(); QListIterator itBool(boolPropertyManagers); while (itBool.hasNext()) d_ptr->m_checkBoxFactory->removePropertyManager(itBool.next()); QList stringPropertyManagers = manager->findChildren(); QListIterator itString(stringPropertyManagers); while (itString.hasNext()) d_ptr->m_lineEditFactory->removePropertyManager(itString.next()); QList datePropertyManagers = manager->findChildren(); QListIterator itDate(datePropertyManagers); while (itDate.hasNext()) d_ptr->m_dateEditFactory->removePropertyManager(itDate.next()); QList timePropertyManagers = manager->findChildren(); QListIterator itTime(timePropertyManagers); while (itTime.hasNext()) d_ptr->m_timeEditFactory->removePropertyManager(itTime.next()); QList dateTimePropertyManagers = manager->findChildren(); QListIterator itDateTime(dateTimePropertyManagers); while (itDateTime.hasNext()) d_ptr->m_dateTimeEditFactory->removePropertyManager(itDateTime.next()); QList keySequencePropertyManagers = manager->findChildren(); QListIterator itKeySequence(keySequencePropertyManagers); while (itKeySequence.hasNext()) d_ptr->m_keySequenceEditorFactory->removePropertyManager(itKeySequence.next()); QList charPropertyManagers = manager->findChildren(); QListIterator itChar(charPropertyManagers); while (itChar.hasNext()) d_ptr->m_charEditorFactory->removePropertyManager(itChar.next()); QList localePropertyManagers = manager->findChildren(); QListIterator itLocale(localePropertyManagers); while (itLocale.hasNext()) d_ptr->m_comboBoxFactory->removePropertyManager(itLocale.next()->subEnumPropertyManager()); QList pointPropertyManagers = manager->findChildren(); QListIterator itPoint(pointPropertyManagers); while (itPoint.hasNext()) d_ptr->m_spinBoxFactory->removePropertyManager(itPoint.next()->subIntPropertyManager()); QList pointFPropertyManagers = manager->findChildren(); QListIterator itPointF(pointFPropertyManagers); while (itPointF.hasNext()) d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itPointF.next()->subDoublePropertyManager()); QList sizePropertyManagers = manager->findChildren(); QListIterator itSize(sizePropertyManagers); while (itSize.hasNext()) d_ptr->m_spinBoxFactory->removePropertyManager(itSize.next()->subIntPropertyManager()); QList sizeFPropertyManagers = manager->findChildren(); QListIterator itSizeF(sizeFPropertyManagers); while (itSizeF.hasNext()) d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itSizeF.next()->subDoublePropertyManager()); QList rectPropertyManagers = manager->findChildren(); QListIterator itRect(rectPropertyManagers); while (itRect.hasNext()) d_ptr->m_spinBoxFactory->removePropertyManager(itRect.next()->subIntPropertyManager()); QList rectFPropertyManagers = manager->findChildren(); QListIterator itRectF(rectFPropertyManagers); while (itRectF.hasNext()) d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itRectF.next()->subDoublePropertyManager()); QList colorPropertyManagers = manager->findChildren(); QListIterator itColor(colorPropertyManagers); while (itColor.hasNext()) { QtColorPropertyManager *manager = itColor.next(); d_ptr->m_colorEditorFactory->removePropertyManager(manager); d_ptr->m_spinBoxFactory->removePropertyManager(manager->subIntPropertyManager()); } QList enumPropertyManagers = manager->findChildren(); QListIterator itEnum(enumPropertyManagers); while (itEnum.hasNext()) d_ptr->m_comboBoxFactory->removePropertyManager(itEnum.next()); QList sizePolicyPropertyManagers = manager->findChildren(); QListIterator itSizePolicy(sizePolicyPropertyManagers); while (itSizePolicy.hasNext()) { QtSizePolicyPropertyManager *manager = itSizePolicy.next(); d_ptr->m_spinBoxFactory->removePropertyManager(manager->subIntPropertyManager()); d_ptr->m_comboBoxFactory->removePropertyManager(manager->subEnumPropertyManager()); } QList fontPropertyManagers = manager->findChildren(); QListIterator itFont(fontPropertyManagers); while (itFont.hasNext()) { QtFontPropertyManager *manager = itFont.next(); d_ptr->m_fontEditorFactory->removePropertyManager(manager); d_ptr->m_spinBoxFactory->removePropertyManager(manager->subIntPropertyManager()); d_ptr->m_comboBoxFactory->removePropertyManager(manager->subEnumPropertyManager()); d_ptr->m_checkBoxFactory->removePropertyManager(manager->subBoolPropertyManager()); } QList cursorPropertyManagers = manager->findChildren(); QListIterator itCursor(cursorPropertyManagers); while (itCursor.hasNext()) d_ptr->m_cursorEditorFactory->removePropertyManager(itCursor.next()); QList flagPropertyManagers = manager->findChildren(); QListIterator itFlag(flagPropertyManagers); while (itFlag.hasNext()) d_ptr->m_checkBoxFactory->removePropertyManager(itFlag.next()->subBoolPropertyManager()); } #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif #include "moc_qtvariantproperty.cpp" tiled-1.0.3/src/qtpropertybrowser/src/qtvariantproperty.h000066400000000000000000000211151315121121300240040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTVARIANTPROPERTY_H #define QTVARIANTPROPERTY_H #include "qtpropertybrowser.h" #include #include #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif typedef QMap QtIconMap; class QtVariantPropertyManager; class QtVariantPropertyPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtVariantProperty : public QtProperty { public: ~QtVariantProperty(); QVariant value() const; QVariant attributeValue(const QString &attribute) const; int valueType() const; int propertyType() const; void setValue(const QVariant &value); void setAttribute(const QString &attribute, const QVariant &value); protected: QtVariantProperty(QtVariantPropertyManager *manager); private: friend class QtVariantPropertyManager; QtVariantPropertyPrivate *d_ptr; }; class QtVariantPropertyManagerPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtVariantPropertyManager : public QtAbstractPropertyManager { Q_OBJECT public: QtVariantPropertyManager(QObject *parent = 0); ~QtVariantPropertyManager(); virtual QtVariantProperty *addProperty(int propertyType, const QString &name = QString()); int propertyType(const QtProperty *property) const; int valueType(const QtProperty *property) const; QtVariantProperty *variantProperty(const QtProperty *property) const; virtual bool isPropertyTypeSupported(int propertyType) const; virtual int valueType(int propertyType) const; virtual QStringList attributes(int propertyType) const; virtual int attributeType(int propertyType, const QString &attribute) const; virtual QVariant value(const QtProperty *property) const; virtual QVariant attributeValue(const QtProperty *property, const QString &attribute) const; static int enumTypeId(); static int flagTypeId(); static int groupTypeId(); static int iconMapTypeId(); public Q_SLOTS: virtual void setValue(QtProperty *property, const QVariant &val); virtual void setAttribute(QtProperty *property, const QString &attribute, const QVariant &value); Q_SIGNALS: void valueChanged(QtProperty *property, const QVariant &val); void attributeChanged(QtProperty *property, const QString &attribute, const QVariant &val); protected: virtual bool hasValue(const QtProperty *property) const; QString valueText(const QtProperty *property) const; QIcon valueIcon(const QtProperty *property) const; virtual void initializeProperty(QtProperty *property); virtual void uninitializeProperty(QtProperty *property); virtual QtProperty *createProperty(); private: QtVariantPropertyManagerPrivate *d_ptr; Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int)) Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, double)) Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, double, double)) Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, double)) Q_PRIVATE_SLOT(d_func(), void slotDecimalsChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, bool)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QString &)) Q_PRIVATE_SLOT(d_func(), void slotRegExpChanged(QtProperty *, const QRegExp &)) Q_PRIVATE_SLOT(d_func(), void slotEchoModeChanged(QtProperty *, int)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QDate &)) Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, const QDate &, const QDate &)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QTime &)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QDateTime &)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QKeySequence &)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QChar &)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QLocale &)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QPoint &)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QPointF &)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QSize &)) Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, const QSize &, const QSize &)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QSizeF &)) Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, const QSizeF &, const QSizeF &)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QRect &)) Q_PRIVATE_SLOT(d_func(), void slotConstraintChanged(QtProperty *, const QRect &)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QRectF &)) Q_PRIVATE_SLOT(d_func(), void slotConstraintChanged(QtProperty *, const QRectF &)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QColor &)) Q_PRIVATE_SLOT(d_func(), void slotEnumNamesChanged(QtProperty *, const QStringList &)) Q_PRIVATE_SLOT(d_func(), void slotEnumIconsChanged(QtProperty *, const QMap &)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QSizePolicy &)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QFont &)) Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QCursor &)) Q_PRIVATE_SLOT(d_func(), void slotFlagNamesChanged(QtProperty *, const QStringList &)) Q_PRIVATE_SLOT(d_func(), void slotReadOnlyChanged(QtProperty *, bool)) Q_PRIVATE_SLOT(d_func(), void slotTextVisibleChanged(QtProperty *, bool)) Q_PRIVATE_SLOT(d_func(), void slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)) Q_PRIVATE_SLOT(d_func(), void slotPropertyRemoved(QtProperty *, QtProperty *)) Q_DECLARE_PRIVATE(QtVariantPropertyManager) Q_DISABLE_COPY(QtVariantPropertyManager) }; class QtVariantEditorFactoryPrivate; class QT_QTPROPERTYBROWSER_EXPORT QtVariantEditorFactory : public QtAbstractEditorFactory { Q_OBJECT public: QtVariantEditorFactory(QObject *parent = 0); ~QtVariantEditorFactory(); protected: void connectPropertyManager(QtVariantPropertyManager *manager); QWidget *createEditor(QtVariantPropertyManager *manager, QtProperty *property, QWidget *parent); void disconnectPropertyManager(QtVariantPropertyManager *manager); private: QtVariantEditorFactoryPrivate *d_ptr; Q_DECLARE_PRIVATE(QtVariantEditorFactory) Q_DISABLE_COPY(QtVariantEditorFactory) }; #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif Q_DECLARE_METATYPE(QIcon) Q_DECLARE_METATYPE(QtIconMap) #endif tiled-1.0.3/src/qtsingleapplication/000077500000000000000000000000001315121121300174435ustar00rootroot00000000000000tiled-1.0.3/src/qtsingleapplication/README.TXT000066400000000000000000000016411315121121300210030ustar00rootroot00000000000000Qt Solutions Component: Single Application The QtSingleApplication component provides support for applications that can be only started once per user. Version history: 2.0: - Version 1.3 ported to Qt 4. 2.1: - Fix compilation problem on Mac. 2.2: - Really fix the Mac compilation problem. - Mac: fix crash due to wrong object releasing. - Mac: Fix memory leak. 2.3: - Windows: Force creation of internal widget to make it work with Qt 4.2. 2.4: - Fix the system for automatic window raising on message reception. NOTE: minor API change. 2.5: - Mac: Fix isRunning() to work and report correctly. 2.6: - - initialize() is now obsolete, no longer necessary to call it - - Fixed race condition where multiple instances migth be started - - QtSingleCoreApplication variant provided for non-GUI (console) usage - Complete reimplementation. Visible changes: - LGPL release. tiled-1.0.3/src/qtsingleapplication/common.pri000066400000000000000000000012471315121121300214530ustar00rootroot00000000000000exists(config.pri):infile(config.pri, SOLUTIONS_LIBRARY, yes): CONFIG += qtsingleapplication-uselib TEMPLATE += fakelib greaterThan(QT_MAJOR_VERSION, 5)|\ if(equals(QT_MAJOR_VERSION, 5):greaterThan(QT_MINOR_VERSION, 4))|\ if(equals(QT_MAJOR_VERSION, 5):equals(QT_MINOR_VERSION, 4):greaterThan(QT_PATCH_VERSION, 1)) { QTSINGLEAPPLICATION_LIBNAME = $$qt5LibraryTarget(QtSolutions_SingleApplication-head) } else { QTSINGLEAPPLICATION_LIBNAME = $$qtLibraryTarget(QtSolutions_SingleApplication-head) } TEMPLATE -= fakelib QTSINGLEAPPLICATION_LIBDIR = $$PWD/lib unix:qtsingleapplication-uselib:!qtsingleapplication-buildlib:QMAKE_RPATHDIR += $$QTSINGLEAPPLICATION_LIBDIR tiled-1.0.3/src/qtsingleapplication/qtsingleapplication.qbs000066400000000000000000000010171315121121300242230ustar00rootroot00000000000000import qbs 1.0 StaticLibrary { name: "qtsingleapplication" Depends { name: "cpp" } Depends { name: "Qt"; submodules: ["widgets", "network"]; versionAtLeast: "5.4" } cpp.includePaths: ["src"] cpp.cxxLanguageVersion: "c++11" files: [ "src/qtlocalpeer.cpp", "src/qtlocalpeer.h", "src/qtsingleapplication.cpp", "src/qtsingleapplication.h", ] Export { Depends { name: "cpp" } Depends { name: "Qt.network" } cpp.includePaths: "src" } } tiled-1.0.3/src/qtsingleapplication/src/000077500000000000000000000000001315121121300202325ustar00rootroot00000000000000tiled-1.0.3/src/qtsingleapplication/src/QtLockedFile000066400000000000000000000000321315121121300224560ustar00rootroot00000000000000#include "qtlockedfile.h" tiled-1.0.3/src/qtsingleapplication/src/QtSingleApplication000066400000000000000000000000411315121121300240620ustar00rootroot00000000000000#include "qtsingleapplication.h" tiled-1.0.3/src/qtsingleapplication/src/qtlocalpeer.cpp000066400000000000000000000151131315121121300232520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtlocalpeer.h" #include #include #include #if defined(Q_OS_WIN) #include #include typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*); static PProcessIdToSessionId pProcessIdToSessionId = 0; #endif #if defined(Q_OS_UNIX) #include #include #include #endif namespace QtLP_Private { #include "qtlockedfile.cpp" #if defined(Q_OS_WIN) #include "qtlockedfile_win.cpp" #else #include "qtlockedfile_unix.cpp" #endif } const char* QtLocalPeer::ack = "ack"; QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId) : QObject(parent), id(appId) { QString prefix = id; if (id.isEmpty()) { id = QCoreApplication::applicationFilePath(); #if defined(Q_OS_WIN) id = id.toLower(); #endif prefix = id.section(QLatin1Char('/'), -1); } prefix.remove(QRegExp(QLatin1String("[^a-zA-Z]"))); prefix.truncate(6); QByteArray idc = id.toUtf8(); quint16 idNum = qChecksum(idc.constData(), idc.size()); socketName = QLatin1String("qtsingleapp-") + prefix + QLatin1Char('-') + QString::number(idNum, 16); #if defined(Q_OS_WIN) if (!pProcessIdToSessionId) { QLibrary lib("kernel32"); pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); } if (pProcessIdToSessionId) { DWORD sessionId = 0; pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); socketName += QLatin1Char('-') + QString::number(sessionId, 16); } #else socketName += QLatin1Char('-') + QString::number(::getuid(), 16); #endif server = new QLocalServer(this); QString lockName = QDir(QDir::tempPath()).absolutePath() + QLatin1Char('/') + socketName + QLatin1String("-lockfile"); lockFile.setFileName(lockName); lockFile.open(QIODevice::ReadWrite); } bool QtLocalPeer::isClient() { if (lockFile.isLocked()) return false; if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) return true; bool res = server->listen(socketName); #if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0)) // ### Workaround if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); res = server->listen(socketName); } #endif if (!res) qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qUtf8Printable(server->errorString())); QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection())); return false; } bool QtLocalPeer::sendMessage(const QString &message, int timeout) { if (!isClient()) return false; QLocalSocket socket; bool connOk = false; for(int i = 0; i < 2; i++) { // Try twice, in case the other instance is just starting up socket.connectToServer(socketName); connOk = socket.waitForConnected(timeout/2); if (connOk || i) break; int ms = 250; #if defined(Q_OS_WIN) Sleep(DWORD(ms)); #else struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; nanosleep(&ts, NULL); #endif } if (!connOk) return false; QByteArray uMsg(message.toUtf8()); QDataStream ds(&socket); ds.writeBytes(uMsg.constData(), uMsg.size()); bool res = socket.waitForBytesWritten(timeout); if (res) { res &= socket.waitForReadyRead(timeout); // wait for ack if (res) res &= (socket.read(qstrlen(ack)) == ack); } return res; } void QtLocalPeer::receiveConnection() { QLocalSocket* socket = server->nextPendingConnection(); if (!socket) return; while (socket->bytesAvailable() < (int)sizeof(quint32)) socket->waitForReadyRead(); QDataStream ds(socket); QByteArray uMsg; quint32 remaining; ds >> remaining; uMsg.resize(remaining); int got = 0; char* uMsgBuf = uMsg.data(); do { got = ds.readRawData(uMsgBuf, remaining); remaining -= got; uMsgBuf += got; } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); if (got < 0) { qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); delete socket; return; } QString message(QString::fromUtf8(uMsg)); socket->write(ack, qstrlen(ack)); socket->waitForBytesWritten(1000); socket->waitForDisconnected(1000); // make sure client reads ack delete socket; emit messageReceived(message); //### (might take a long time to return) } tiled-1.0.3/src/qtsingleapplication/src/qtlocalpeer.h000066400000000000000000000052051315121121300227200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTLOCALPEER_H #define QTLOCALPEER_H #include #include #include #include "qtlockedfile.h" class QtLocalPeer : public QObject { Q_OBJECT public: QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); bool isClient(); bool sendMessage(const QString &message, int timeout); QString applicationId() const { return id; } Q_SIGNALS: void messageReceived(const QString &message); protected Q_SLOTS: void receiveConnection(); protected: QString id; QString socketName; QLocalServer* server; QtLP_Private::QtLockedFile lockFile; private: static const char* ack; }; #endif // QTLOCALPEER_H tiled-1.0.3/src/qtsingleapplication/src/qtlockedfile.cpp000066400000000000000000000137421315121121300234130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtlockedfile.h" /*! \class QtLockedFile \brief The QtLockedFile class extends QFile with advisory locking functions. A file may be locked in read or write mode. Multiple instances of \e QtLockedFile, created in multiple processes running on the same machine, may have a file locked in read mode. Exactly one instance may have it locked in write mode. A read and a write lock cannot exist simultaneously on the same file. The file locks are advisory. This means that nothing prevents another process from manipulating a locked file using QFile or file system functions offered by the OS. Serialization is only guaranteed if all processes that access the file use QLockedFile. Also, while holding a lock on a file, a process must not open the same file again (through any API), or locks can be unexpectedly lost. The lock provided by an instance of \e QtLockedFile is released whenever the program terminates. This is true even when the program crashes and no destructors are called. */ /*! \enum QtLockedFile::LockMode This enum describes the available lock modes. \value ReadLock A read lock. \value WriteLock A write lock. \value NoLock Neither a read lock nor a write lock. */ /*! Constructs an unlocked \e QtLockedFile object. This constructor behaves in the same way as \e QFile::QFile(). \sa QFile::QFile() */ QtLockedFile::QtLockedFile() : QFile() { #ifdef Q_OS_WIN wmutex = 0; rmutex = 0; #endif m_lock_mode = NoLock; } /*! Constructs an unlocked QtLockedFile object with file \a name. This constructor behaves in the same way as \e QFile::QFile(const QString&). \sa QFile::QFile() */ QtLockedFile::QtLockedFile(const QString &name) : QFile(name) { #ifdef Q_OS_WIN wmutex = 0; rmutex = 0; #endif m_lock_mode = NoLock; } /*! Opens the file in OpenMode \a mode. This is identical to QFile::open(), with the one exception that the Truncate mode flag is disallowed. Truncation would conflict with the advisory file locking, since the file would be modified before the write lock is obtained. If truncation is required, use resize(0) after obtaining the write lock. Returns true if successful; otherwise false. \sa QFile::open(), QFile::resize() */ bool QtLockedFile::open(OpenMode mode) { if (mode & QIODevice::Truncate) { qWarning("QtLockedFile::open(): Truncate mode not allowed."); return false; } return QFile::open(mode); } /*! Returns \e true if this object has a in read or write lock; otherwise returns \e false. \sa lockMode() */ bool QtLockedFile::isLocked() const { return m_lock_mode != NoLock; } /*! Returns the type of lock currently held by this object, or \e QtLockedFile::NoLock. \sa isLocked() */ QtLockedFile::LockMode QtLockedFile::lockMode() const { return m_lock_mode; } /*! \fn bool QtLockedFile::lock(LockMode mode, bool block = true) Obtains a lock of type \a mode. The file must be opened before it can be locked. If \a block is true, this function will block until the lock is aquired. If \a block is false, this function returns \e false immediately if the lock cannot be aquired. If this object already has a lock of type \a mode, this function returns \e true immediately. If this object has a lock of a different type than \a mode, the lock is first released and then a new lock is obtained. This function returns \e true if, after it executes, the file is locked by this object, and \e false otherwise. \sa unlock(), isLocked(), lockMode() */ /*! \fn bool QtLockedFile::unlock() Releases a lock. If the object has no lock, this function returns immediately. This function returns \e true if, after it executes, the file is not locked by this object, and \e false otherwise. \sa lock(), isLocked(), lockMode() */ /*! \fn QtLockedFile::~QtLockedFile() Destroys the \e QtLockedFile object. If any locks were held, they are released. */ tiled-1.0.3/src/qtsingleapplication/src/qtlockedfile.h000066400000000000000000000063071315121121300230570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTLOCKEDFILE_H #define QTLOCKEDFILE_H #include #ifdef Q_OS_WIN #include #endif #if defined(Q_OS_WIN) # if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) # define QT_QTLOCKEDFILE_EXPORT # elif defined(QT_QTLOCKEDFILE_IMPORT) # if defined(QT_QTLOCKEDFILE_EXPORT) # undef QT_QTLOCKEDFILE_EXPORT # endif # define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport) # elif defined(QT_QTLOCKEDFILE_EXPORT) # undef QT_QTLOCKEDFILE_EXPORT # define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport) # endif #else # define QT_QTLOCKEDFILE_EXPORT #endif namespace QtLP_Private { class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile { public: enum LockMode { NoLock = 0, ReadLock, WriteLock }; QtLockedFile(); QtLockedFile(const QString &name); ~QtLockedFile(); bool open(OpenMode mode); bool lock(LockMode mode, bool block = true); bool unlock(); bool isLocked() const; LockMode lockMode() const; private: #ifdef Q_OS_WIN Qt::HANDLE wmutex; Qt::HANDLE rmutex; QVector rmutexes; QString mutexname; Qt::HANDLE getMutexHandle(int idx, bool doCreate); bool waitMutex(Qt::HANDLE mutex, bool doBlock); #endif LockMode m_lock_mode; }; } #endif tiled-1.0.3/src/qtsingleapplication/src/qtlockedfile_unix.cpp000066400000000000000000000066141315121121300244560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include "qtlockedfile.h" bool QtLockedFile::lock(LockMode mode, bool block) { if (!isOpen()) { qWarning("QtLockedFile::lock(): file is not opened"); return false; } if (mode == NoLock) return unlock(); if (mode == m_lock_mode) return true; if (m_lock_mode != NoLock) unlock(); struct flock fl; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; int cmd = block ? F_SETLKW : F_SETLK; int ret = fcntl(handle(), cmd, &fl); if (ret == -1) { if (errno != EINTR && errno != EAGAIN) qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); return false; } m_lock_mode = mode; return true; } bool QtLockedFile::unlock() { if (!isOpen()) { qWarning("QtLockedFile::unlock(): file is not opened"); return false; } if (!isLocked()) return true; struct flock fl; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; fl.l_type = F_UNLCK; int ret = fcntl(handle(), F_SETLKW, &fl); if (ret == -1) { qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); return false; } m_lock_mode = NoLock; return true; } QtLockedFile::~QtLockedFile() { if (isOpen()) unlock(); } tiled-1.0.3/src/qtsingleapplication/src/qtlockedfile_win.cpp000066400000000000000000000146611315121121300242710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtlockedfile.h" #include #include #define MUTEX_PREFIX "QtLockedFile mutex " // Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS #define MAX_READERS MAXIMUM_WAIT_OBJECTS #if QT_VERSION >= 0x050000 #define QT_WA(unicode, ansi) unicode #endif Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) { if (mutexname.isEmpty()) { QFileInfo fi(*this); mutexname = QString::fromLatin1(MUTEX_PREFIX) + fi.absoluteFilePath().toLower(); } QString mname(mutexname); if (idx >= 0) mname += QString::number(idx); Qt::HANDLE mutex; if (doCreate) { QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); }, { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } ); if (!mutex) { qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); return 0; } } else { QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); }, { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } ); if (!mutex) { if (GetLastError() != ERROR_FILE_NOT_FOUND) qErrnoWarning("QtLockedFile::lock(): OpenMutex failed"); return 0; } } return mutex; } bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock) { Q_ASSERT(mutex); DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); switch (res) { case WAIT_OBJECT_0: case WAIT_ABANDONED: return true; break; case WAIT_TIMEOUT: break; default: qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); } return false; } bool QtLockedFile::lock(LockMode mode, bool block) { if (!isOpen()) { qWarning("QtLockedFile::lock(): file is not opened"); return false; } if (mode == NoLock) return unlock(); if (mode == m_lock_mode) return true; if (m_lock_mode != NoLock) unlock(); if (!wmutex && !(wmutex = getMutexHandle(-1, true))) return false; if (!waitMutex(wmutex, block)) return false; if (mode == ReadLock) { int idx = 0; for (; idx < MAX_READERS; idx++) { rmutex = getMutexHandle(idx, false); if (!rmutex || waitMutex(rmutex, false)) break; CloseHandle(rmutex); } bool ok = true; if (idx >= MAX_READERS) { qWarning("QtLockedFile::lock(): too many readers"); rmutex = 0; ok = false; } else if (!rmutex) { rmutex = getMutexHandle(idx, true); if (!rmutex || !waitMutex(rmutex, false)) ok = false; } if (!ok && rmutex) { CloseHandle(rmutex); rmutex = 0; } ReleaseMutex(wmutex); if (!ok) return false; } else { Q_ASSERT(rmutexes.isEmpty()); for (int i = 0; i < MAX_READERS; i++) { Qt::HANDLE mutex = getMutexHandle(i, false); if (mutex) rmutexes.append(mutex); } if (rmutexes.size()) { DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), TRUE, block ? INFINITE : 0); if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { if (res != WAIT_TIMEOUT) qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky unlock(); return false; } } } m_lock_mode = mode; return true; } bool QtLockedFile::unlock() { if (!isOpen()) { qWarning("QtLockedFile::unlock(): file is not opened"); return false; } if (!isLocked()) return true; if (m_lock_mode == ReadLock) { ReleaseMutex(rmutex); CloseHandle(rmutex); rmutex = 0; } else { foreach(Qt::HANDLE mutex, rmutexes) { ReleaseMutex(mutex); CloseHandle(mutex); } rmutexes.clear(); ReleaseMutex(wmutex); } m_lock_mode = QtLockedFile::NoLock; return true; } QtLockedFile::~QtLockedFile() { if (isOpen()) unlock(); if (wmutex) CloseHandle(wmutex); } tiled-1.0.3/src/qtsingleapplication/src/qtsingleapplication.cpp000066400000000000000000000270101315121121300250100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtsingleapplication.h" #include "qtlocalpeer.h" #include /*! \class QtSingleApplication qtsingleapplication.h \brief The QtSingleApplication class provides an API to detect and communicate with running instances of an application. This class allows you to create applications where only one instance should be running at a time. I.e., if the user tries to launch another instance, the already running instance will be activated instead. Another usecase is a client-server system, where the first started instance will assume the role of server, and the later instances will act as clients of that server. By default, the full path of the executable file is used to determine whether two processes are instances of the same application. You can also provide an explicit identifier string that will be compared instead. The application should create the QtSingleApplication object early in the startup phase, and call isRunning() to find out if another instance of this application is already running. If isRunning() returns false, it means that no other instance is running, and this instance has assumed the role as the running instance. In this case, the application should continue with the initialization of the application user interface before entering the event loop with exec(), as normal. The messageReceived() signal will be emitted when the running application receives messages from another instance of the same application. When a message is received it might be helpful to the user to raise the application so that it becomes visible. To facilitate this, QtSingleApplication provides the setActivationWindow() function and the activateWindow() slot. If isRunning() returns true, another instance is already running. It may be alerted to the fact that another instance has started by using the sendMessage() function. Also data such as startup parameters (e.g. the name of the file the user wanted this new instance to open) can be passed to the running instance with this function. Then, the application should terminate (or enter client mode). If isRunning() returns true, but sendMessage() fails, that is an indication that the running instance is frozen. Here's an example that shows how to convert an existing application to use QtSingleApplication. It is very simple and does not make use of all QtSingleApplication's functionality (see the examples for that). \code // Original int main(int argc, char **argv) { QApplication app(argc, argv); MyMainWidget mmw; mmw.show(); return app.exec(); } // Single instance int main(int argc, char **argv) { QtSingleApplication app(argc, argv); if (app.isRunning()) return !app.sendMessage(someDataString); MyMainWidget mmw; app.setActivationWindow(&mmw); mmw.show(); return app.exec(); } \endcode Once this QtSingleApplication instance is destroyed (normally when the process exits or crashes), when the user next attempts to run the application this instance will not, of course, be encountered. The next instance to call isRunning() or sendMessage() will assume the role as the new running instance. For console (non-GUI) applications, QtSingleCoreApplication may be used instead of this class, to avoid the dependency on the QtGui library. \sa QtSingleCoreApplication */ void QtSingleApplication::sysInit(const QString &appId) { actWin = 0; peer = new QtLocalPeer(this, appId); connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); } /*! Creates a QtSingleApplication object. The application identifier will be QCoreApplication::applicationFilePath(). \a argc, \a argv, and \a GUIenabled are passed on to the QAppliation constructor. If you are creating a console application (i.e. setting \a GUIenabled to false), you may consider using QtSingleCoreApplication instead. */ QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled) : QApplication(argc, argv, GUIenabled) { sysInit(); } /*! Creates a QtSingleApplication object with the application identifier \a appId. \a argc and \a argv are passed on to the QAppliation constructor. */ QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv) : QApplication(argc, argv) { sysInit(appId); } #if QT_VERSION < 0x050000 /*! Creates a QtSingleApplication object. The application identifier will be QCoreApplication::applicationFilePath(). \a argc, \a argv, and \a type are passed on to the QAppliation constructor. */ QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type) : QApplication(argc, argv, type) { sysInit(); } # if defined(Q_WS_X11) /*! Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be QCoreApplication::applicationFilePath(). \a dpy, \a visual, and \a cmap are passed on to the QApplication constructor. */ QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap) : QApplication(dpy, visual, cmap) { sysInit(); } /*! Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a argv, \a visual, and \a cmap are passed on to the QApplication constructor. */ QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) : QApplication(dpy, argc, argv, visual, cmap) { sysInit(); } /*! Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be \a appId. \a dpy, \a argc, \a argv, \a visual, and \a cmap are passed on to the QApplication constructor. */ QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) : QApplication(dpy, argc, argv, visual, cmap) { sysInit(appId); } # endif // Q_WS_X11 #endif // QT_VERSION < 0x050000 /*! Returns true if another instance of this application is running; otherwise false. This function does not find instances of this application that are being run by a different user (on Windows: that are running in another session). \sa sendMessage() */ bool QtSingleApplication::isRunning() { return peer->isClient(); } /*! Tries to send the text \a message to the currently running instance. The QtSingleApplication object in the running instance will emit the messageReceived() signal when it receives the message. This function returns true if the message has been sent to, and processed by, the current instance. If there is no instance currently running, or if the running instance fails to process the message within \a timeout milliseconds, this function return false. \sa isRunning(), messageReceived() */ bool QtSingleApplication::sendMessage(const QString &message, int timeout) { return peer->sendMessage(message, timeout); } /*! Returns the application identifier. Two processes with the same identifier will be regarded as instances of the same application. */ QString QtSingleApplication::id() const { return peer->applicationId(); } /*! Sets the activation window of this application to \a aw. The activation window is the widget that will be activated by activateWindow(). This is typically the application's main window. If \a activateOnMessage is true (the default), the window will be activated automatically every time a message is received, just prior to the messageReceived() signal being emitted. \sa activateWindow(), messageReceived() */ void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage) { actWin = aw; if (activateOnMessage) connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); else disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); } /*! Returns the applications activation window if one has been set by calling setActivationWindow(), otherwise returns 0. \sa setActivationWindow() */ QWidget* QtSingleApplication::activationWindow() const { return actWin; } /*! De-minimizes, raises, and activates this application's activation window. This function does nothing if no activation window has been set. This is a convenience function to show the user that this application instance has been activated when he has tried to start another instance. This function should typically be called in response to the messageReceived() signal. By default, that will happen automatically, if an activation window has been set. \sa setActivationWindow(), messageReceived(), initialize() */ void QtSingleApplication::activateWindow() { if (actWin) { actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized); actWin->raise(); actWin->activateWindow(); } } /*! \fn void QtSingleApplication::messageReceived(const QString& message) This signal is emitted when the current instance receives a \a message from another instance of this application. \sa sendMessage(), setActivationWindow(), activateWindow() */ /*! \fn void QtSingleApplication::initialize(bool dummy = true) \obsolete */ tiled-1.0.3/src/qtsingleapplication/src/qtsingleapplication.h000066400000000000000000000076171315121121300244700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTSINGLEAPPLICATION_H #define QTSINGLEAPPLICATION_H #include class QtLocalPeer; #if defined(Q_OS_WIN) # if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT) # define QT_QTSINGLEAPPLICATION_EXPORT # elif defined(QT_QTSINGLEAPPLICATION_IMPORT) # if defined(QT_QTSINGLEAPPLICATION_EXPORT) # undef QT_QTSINGLEAPPLICATION_EXPORT # endif # define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport) # elif defined(QT_QTSINGLEAPPLICATION_EXPORT) # undef QT_QTSINGLEAPPLICATION_EXPORT # define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport) # endif #else # define QT_QTSINGLEAPPLICATION_EXPORT #endif class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication { Q_OBJECT public: QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); QtSingleApplication(const QString &id, int &argc, char **argv); #if QT_VERSION < 0x050000 QtSingleApplication(int &argc, char **argv, Type type); # if defined(Q_WS_X11) QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); # endif // Q_WS_X11 #endif // QT_VERSION < 0x050000 bool isRunning(); QString id() const; void setActivationWindow(QWidget* aw, bool activateOnMessage = true); QWidget* activationWindow() const; // Obsolete: void initialize(bool dummy = true) { isRunning(); Q_UNUSED(dummy) } public Q_SLOTS: bool sendMessage(const QString &message, int timeout = 5000); void activateWindow(); Q_SIGNALS: void messageReceived(const QString &message); private: void sysInit(const QString &appId = QString()); QtLocalPeer *peer; QWidget *actWin; }; #endif // QTSINGLEAPPLICATION_H tiled-1.0.3/src/qtsingleapplication/src/qtsingleapplication.pri000066400000000000000000000011101315121121300250110ustar00rootroot00000000000000include(../common.pri) INCLUDEPATH += $$PWD DEPENDPATH += $$PWD QT *= network greaterThan(QT_MAJOR_VERSION, 4): QT *= widgets qtsingleapplication-uselib:!qtsingleapplication-buildlib { LIBS += -L$$QTSINGLEAPPLICATION_LIBDIR -l$$QTSINGLEAPPLICATION_LIBNAME } else { SOURCES += $$PWD/qtsingleapplication.cpp $$PWD/qtlocalpeer.cpp HEADERS += $$PWD/qtsingleapplication.h $$PWD/qtlocalpeer.h } win32 { contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSINGLEAPPLICATION_EXPORT else:qtsingleapplication-uselib:DEFINES += QT_QTSINGLEAPPLICATION_IMPORT } tiled-1.0.3/src/qtsingleapplication/src/qtsinglecoreapplication.cpp000066400000000000000000000123551315121121300256670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtsinglecoreapplication.h" #include "qtlocalpeer.h" /*! \class QtSingleCoreApplication qtsinglecoreapplication.h \brief A variant of the QtSingleApplication class for non-GUI applications. This class is a variant of QtSingleApplication suited for use in console (non-GUI) applications. It is an extension of QCoreApplication (instead of QApplication). It does not require the QtGui library. The API and usage is identical to QtSingleApplication, except that functions relating to the "activation window" are not present, for obvious reasons. Please refer to the QtSingleApplication documentation for explanation of the usage. A QtSingleCoreApplication instance can communicate to a QtSingleApplication instance if they share the same application id. Hence, this class can be used to create a light-weight command-line tool that sends commands to a GUI application. \sa QtSingleApplication */ /*! Creates a QtSingleCoreApplication object. The application identifier will be QCoreApplication::applicationFilePath(). \a argc and \a argv are passed on to the QCoreAppliation constructor. */ QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv) : QCoreApplication(argc, argv) { peer = new QtLocalPeer(this); connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); } /*! Creates a QtSingleCoreApplication object with the application identifier \a appId. \a argc and \a argv are passed on to the QCoreAppliation constructor. */ QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv) : QCoreApplication(argc, argv) { peer = new QtLocalPeer(this, appId); connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); } /*! Returns true if another instance of this application is running; otherwise false. This function does not find instances of this application that are being run by a different user (on Windows: that are running in another session). \sa sendMessage() */ bool QtSingleCoreApplication::isRunning() { return peer->isClient(); } /*! Tries to send the text \a message to the currently running instance. The QtSingleCoreApplication object in the running instance will emit the messageReceived() signal when it receives the message. This function returns true if the message has been sent to, and processed by, the current instance. If there is no instance currently running, or if the running instance fails to process the message within \a timeout milliseconds, this function return false. \sa isRunning(), messageReceived() */ bool QtSingleCoreApplication::sendMessage(const QString &message, int timeout) { return peer->sendMessage(message, timeout); } /*! Returns the application identifier. Two processes with the same identifier will be regarded as instances of the same application. */ QString QtSingleCoreApplication::id() const { return peer->applicationId(); } /*! \fn void QtSingleCoreApplication::messageReceived(const QString& message) This signal is emitted when the current instance receives a \a message from another instance of this application. \sa sendMessage() */ tiled-1.0.3/src/qtsingleapplication/src/qtsinglecoreapplication.h000066400000000000000000000050251315121121300253300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTSINGLECOREAPPLICATION_H #define QTSINGLECOREAPPLICATION_H #include class QtLocalPeer; class QtSingleCoreApplication : public QCoreApplication { Q_OBJECT public: QtSingleCoreApplication(int &argc, char **argv); QtSingleCoreApplication(const QString &id, int &argc, char **argv); bool isRunning(); QString id() const; public Q_SLOTS: bool sendMessage(const QString &message, int timeout = 5000); Q_SIGNALS: void messageReceived(const QString &message); private: QtLocalPeer* peer; }; #endif // QTSINGLECOREAPPLICATION_H tiled-1.0.3/src/qtsingleapplication/src/qtsinglecoreapplication.pri000066400000000000000000000005041315121121300256700ustar00rootroot00000000000000INCLUDEPATH += $$PWD DEPENDPATH += $$PWD HEADERS += $$PWD/qtsinglecoreapplication.h $$PWD/qtlocalpeer.h SOURCES += $$PWD/qtsinglecoreapplication.cpp $$PWD/qtlocalpeer.cpp QT *= network win32:contains(TEMPLATE, lib):contains(CONFIG, shared) { DEFINES += QT_QTSINGLECOREAPPLICATION_EXPORT=__declspec(dllexport) } tiled-1.0.3/src/src.pro000066400000000000000000000002401315121121300146760ustar00rootroot00000000000000TEMPLATE = subdirs CONFIG += ordered SUBDIRS = libtiled tiled plugins \ tmxviewer \ tmxrasterizer \ automappingconverter \ terraingenerator tiled-1.0.3/src/terraingenerator/000077500000000000000000000000001315121121300167445ustar00rootroot00000000000000tiled-1.0.3/src/terraingenerator/main.cpp000066400000000000000000000526231315121121300204040ustar00rootroot00000000000000/* * main.cpp * Copyright 2012, Thorbjørn Lindeijer * Copyright 2015, Przemysław Grzywacz * * This file is part of the Terrain Generator tool. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "mapreader.h" #include "mapwriter.h" #include "terrain.h" #include "tile.h" #include "tileset.h" #include #include #include #include #include #include using namespace Tiled; namespace { struct CommandLineOptions { CommandLineOptions() : showHelp(false) , showVersion(false) , overwrite(false) , embedImage(false) , columns(16) {} bool showHelp; bool showVersion; bool overwrite; bool embedImage; int columns; QString target; QStringList sources; QStringList terrainPriority; QList combineList; }; } // anonymous namespace static void showHelp() { // TODO: Make translatable qWarning() << "Usage: terraingenerator [options]\n\n" "Options:\n" " -h --help : Display this help.\n" " -v --version : Display the version.\n" " --overwrite : Target is overwritten rather than extended.\n" " --columns N : Amount of columns in the target tileset image (default: 16).\n" " -e --embed-image : Tile images will be embedded in the TSX file instead\n" " of being saved as a separated PNG file.\n" " -c --combine T1[ T2 [Tn ...]]\n" " : Specify the terrains to combine together (all combinations).\n" " -s --source TS1[ TS2 [TSn ...]]\n" " : Add source tilesets, order is not important.\n" " -o --output OUT : Specify output tileset filename.\n" " -p --priority T1[ T2 [Tn ...]]\n" " : Add terrain names to priority list (T1 < T2 < Tn).\n" ; } static void showVersion() { qWarning().noquote() << "Terrain Generator" << QCoreApplication::applicationVersion(); } static bool parseCommandLineArguments(CommandLineOptions &options) { const QStringList arguments = QCoreApplication::arguments(); bool inPriority = false; bool inSource = false; bool inCombine = false; int argCount = 0; for (int i = 1; i < arguments.size(); ++i) { const QString &arg = arguments.at(i); // Process source option. if (inSource) { if (arg.at(0) == QLatin1Char('-')) { // Some other option is starting here. if (argCount == 0) { qWarning() << "Missing arguments for --source option."; } inSource = false; } else { // Append the source file. argCount++; options.sources.append(arg); continue; } } // Process priority option. if (inPriority) { if (arg.at(0) == QLatin1Char('-')) { // Some other option is starting here. if (argCount == 0) { qWarning() << "Missing arguments for --priority option."; } inPriority = false; } else { // Append the terrain name. argCount++; options.terrainPriority.append(arg); continue; } } // Process combine option. if (inCombine) { if (arg.at(0) == QLatin1Char('-')) { // Some other option is starting here. if (argCount == 0) { qWarning() << "Missing arguments for --combine option."; } inCombine = false; } else { // Append the terrain name. argCount++; options.combineList.last().append(arg); continue; } } // Process other options. if (arg == QLatin1String("--help") || arg == QLatin1String("-h")) { options.showHelp = true; } else if (arg == QLatin1String("--version") || arg == QLatin1String("-v")) { options.showVersion = true; } else if (arg == QLatin1String("-o") || arg == QLatin1String("--output")) { i++; if (i >= arguments.size()) { qWarning() << "Missing argument to" << arg << "option"; return false; } const QString& arg2 = arguments.at(i); if (arg2.at(0) == QLatin1Char('-')) { i--; qWarning() << "Missing argument to" << arg << "option"; return false; } else { options.target = arg2; } } else if (arg == QLatin1String("--overwrite")) { options.overwrite = true; } else if (arg == QLatin1String("-e") || arg == QLatin1String("--embed-image")) { options.embedImage = true; } else if (arg == QLatin1String("-c") || arg == QLatin1String("--combine")) { // What follows is a list of terrain names to combine together. inCombine = true; options.combineList.append(QStringList()); argCount = 0; } else if (arg == QLatin1String("-p") || arg == QLatin1String("--priority")) { // What follows is a list of terrain names. inPriority = true; argCount = 0; } else if (arg == QLatin1String("-s") || arg == QLatin1String("--source")) { // What follows is a list of input tilesets. inSource = true; argCount = 0; } else if (arg == QLatin1String("--columns")) { i++; if (i >= arguments.size()) { qWarning() << "Missing argument to" << arg << "option"; return false; } const QString& arg2 = arguments.at(i); bool ok = false; options.columns = arg2.toInt(&ok); if (!ok || options.columns <= 0) { qWarning() << "Invalid or missing argument to" << arg << "option"; return false; } } else if (arg.at(0) == QLatin1Char('-')) { qWarning() << "Unknown option" << arg; options.showHelp = true; } else { qWarning() << "Unknown argument" << arg; } } return true; } static bool hasTerrain(const Tileset &tileset, const QString &name) { for (Terrain *terrain : tileset.terrains()) if (terrain->name() == name) return true; return false; } static unsigned short terrainId(const QString &name, const Tileset &tileset) { for (Terrain *terrain : tileset.terrains()) if (terrain->name() == name) return terrain->id(); return 0xFF; } static QString nameOf(Terrain *terrain) { return terrain ? terrain->name() : QString(); } struct TileTerrainNames { TileTerrainNames() {} explicit TileTerrainNames(Tile *tile) : topLeft(nameOf(tile->terrainAtCorner(0))) , topRight(nameOf(tile->terrainAtCorner(1))) , bottomLeft(nameOf(tile->terrainAtCorner(2))) , bottomRight(nameOf(tile->terrainAtCorner(3))) { } TileTerrainNames(QString topLeft, QString topRight, QString bottomLeft, QString bottomRight) : topLeft(topLeft) , topRight(topRight) , bottomLeft(bottomLeft) , bottomRight(bottomRight) {} unsigned toTerrain(const Tileset &tileset) const { return makeTerrain(terrainId(topLeft, tileset), terrainId(topRight, tileset), terrainId(bottomLeft, tileset), terrainId(bottomRight, tileset)); } TileTerrainNames filter(const QString &terrainName) const { return TileTerrainNames(topLeft == terrainName ? topLeft : QString(), topRight == terrainName ? topRight : QString(), bottomLeft == terrainName ? bottomLeft : QString(), bottomRight == terrainName ? bottomRight : QString()); } QStringList terrainList() const { QStringList list; list << topLeft; if (!list.contains(topRight)) list << topRight; if (!list.contains(bottomLeft)) list << bottomLeft; if (!list.contains(bottomRight)) list << bottomRight; return list; } bool operator < (const TileTerrainNames &other) const { if (topLeft != other.topLeft) return topLeft < other.topLeft; if (topRight != other.topRight) return topRight < other.topRight; if (bottomLeft != other.bottomLeft) return bottomLeft < other.bottomLeft; return bottomRight < other.bottomRight; } QString topLeft; QString topRight; QString bottomLeft; QString bottomRight; }; struct TerrainLessThan { bool operator () (const QString &terrainA, const QString &terrainB) const { return terrainPriority[terrainA] < terrainPriority[terrainB]; } QMap terrainPriority; }; static QDebug operator<<(QDebug dbg, const TileTerrainNames &t) { dbg.nospace() << '[' << t.topLeft << ", " << t.topRight << ", " << t.bottomLeft << ", " << t.bottomRight << ']'; return dbg.space(); } static bool isEmpty(const QImage &image) { if (image.format() == QImage::Format_RGB32) return false; Q_ASSERT(image.format() == QImage::Format_ARGB32 || image.format() == QImage::Format_ARGB32_Premultiplied); const QRgb *rgb = reinterpret_cast(image.constBits()); const QRgb * const last = rgb + image.byteCount() / 4; for (; rgb != last; ++rgb) if (qAlpha(*rgb) > 0) return false; return true; } int main(int argc, char *argv[]) { QGuiApplication a(argc, argv); a.setOrganizationDomain(QLatin1String("mapeditor.org")); a.setApplicationName(QLatin1String("TerrainGenerator")); a.setApplicationVersion(QLatin1String("1.0")); CommandLineOptions options; if (!parseCommandLineArguments(options)) { // Something went wrong, abort. return 1; } if (options.showVersion) showVersion(); if (options.showHelp) showHelp(); if (options.showVersion || options.showHelp) return 0; if (options.target.isEmpty()) { qWarning() << "Error: No target tileset provided"; showHelp(); return 1; } if (options.sources.isEmpty()) { qWarning() << "Error: No source tilesets provided"; showHelp(); return 1; } // Check terrain priorities. if (options.terrainPriority.isEmpty()) { qWarning("Error: No terrain priorities set (option -p)."); showHelp(); return 1; } MapReader reader; SharedTileset targetTileset; QList sources; if (!options.overwrite && QFile::exists(options.target)) { targetTileset = reader.readTileset(options.target); if (!targetTileset) { qCritical("Error reading target tileset:\n%s", qUtf8Printable(reader.errorString())); } // Remove empty tiles from the end of the tileset int nextTileId = targetTileset->nextTileId(); for (int id = nextTileId - 1; id >= 0; --id) { if (Tile *tile = targetTileset->findTile(id)) { if (isEmpty(tile->image().toImage())) { targetTileset->deleteTile(id); nextTileId = id; continue; } } break; } targetTileset->setNextTileId(nextTileId); // If the target tileset already exists, it is also a source tileset sources.append(targetTileset); } // Read source tilesets. for (const QString &sourceFileName : options.sources) { SharedTileset source = reader.readTileset(sourceFileName); if (!source) { qCritical("Error reading source tileset '%s':\n%s", qUtf8Printable(sourceFileName), qUtf8Printable(reader.errorString())); } sources.append(source); } // If the target tileset does not exist yet, create it if (!targetTileset) { QString name = QFileInfo(options.target).completeBaseName(); const SharedTileset &firstSource = sources.first(); int tileWidth = firstSource->tileWidth(); int tileHeight = firstSource->tileHeight(); targetTileset = Tileset::create(name, tileWidth, tileHeight); } // Set up a mapping from terrain to tile, for quick lookup QMap terrainToTile; for (const SharedTileset &tileset : sources) for (Tile *tile : tileset->tiles()) if (tile->terrain() != 0xFFFFFFFF) if (!terrainToTile.contains(TileTerrainNames(tile))) // TODO: Optimize terrainToTile.insert(TileTerrainNames(tile), tile); // Set up the list of all terrains, mapped by name. QMap terrains; for (const SharedTileset &tileset : sources) for (Terrain *terrain : tileset->terrains()) if (!terrains.contains(terrain->name())) terrains.insert(terrain->name(), terrain); // Check if there is anything to combine. if (options.combineList.size() == 0) { qWarning() << "No terrain specified to combine (-c option)."; } else { // Dump the combine lists. qWarning() << "Terrains to combine:"; for (const QStringList &combine : options.combineList) { if (combine.isEmpty()) { qCritical("Empty combine set"); } qWarning() << combine; // Make sure every terrain from this set was defined. for (const QString &terrainName : combine) if (!terrains.contains(terrainName)) qCritical("Terrain %s is in combine list, however it wasn't defined by any tileset.", qUtf8Printable(terrainName)); } } // Setup terrain priorities. TerrainLessThan lessThan; int priority = 0; for (const QString &terrainName : options.terrainPriority) { lessThan.terrainPriority.insert(terrainName, priority); ++priority; } qDebug() << "Terrains found:" << terrains.keys(); // Check if all terrains from priority list were found and loaded. for (const QString &terrainName : lessThan.terrainPriority.keys()) if (!terrains.contains(terrainName)) qWarning() << "Terrain" << terrainName << "from priority list not found."; // Add terrain names not specified from command line. for (const QString &terrainName : terrains.keys()) { if (!lessThan.terrainPriority.contains(terrainName)) { qWarning() << "No priority set for" << terrainName; lessThan.terrainPriority.insert(terrainName, priority); ++priority; } } // Add terrains that are not defined in the target tileset yet // TODO: This step should be more configurable for (Terrain *terrain : terrains) { if (!hasTerrain(*targetTileset, terrain->name())) { Tile *terrainTile = terrain->imageTile(); QPixmap terrainImage = terrainTile->image(); Tile *newTerrainTile = targetTileset->addTile(terrainImage); newTerrainTile->setProperties(terrainTile->properties()); Terrain *newTerrain = targetTileset->addTerrain(terrain->name(), newTerrainTile->id()); // WARNING: This assumes the terrain tile has this terrain on all // its corners. newTerrainTile->setTerrain(makeTerrain(newTerrain->id())); terrainToTile.insert(TileTerrainNames(newTerrainTile), newTerrainTile); } } // Prepare a list of terrain combinations. QVector process; for (const QStringList &combine : options.combineList) { QList terrainList; // Get the terrains to combine for (const QString &terrainName : combine) terrainList.append(terrains[terrainName]); // Construct a vector with all terrain combinations to process for (Terrain *topLeft : terrainList) { for (Terrain *topRight : terrainList) { for (Terrain *bottomLeft : terrainList) { for (Terrain *bottomRight : terrainList) { process.append(TileTerrainNames(topLeft->name(), topRight->name(), bottomLeft->name(), bottomRight->name())); } } } } } // Go through each combination of terrains and add the tile to the target // tileset if it's not in there yet. for (const TileTerrainNames &terrainNames : process) { Tile *tile = terrainToTile.value(terrainNames); if (tile && tile->tileset() == targetTileset) continue; QPixmap image; Properties properties; if (!tile) { qWarning() << "Generating" << terrainNames; // Start a new image QImage tileImage = QImage(targetTileset->tileWidth(), targetTileset->tileHeight(), QImage::Format_ARGB32); tileImage.fill(Qt::transparent); QPainter painter(&tileImage); QStringList terrainList = terrainNames.terrainList(); qSort(terrainList.begin(), terrainList.end(), lessThan); // Draw the lowest terrain to avoid pixel gaps QString baseTerrain = terrainList.first(); QPixmap baseImage = terrains[baseTerrain]->imageTile()->image(); painter.drawPixmap(0, 0, baseImage); for (const QString &terrainName : terrainList) { TileTerrainNames filtered = terrainNames.filter(terrainName); Tile *tile = terrainToTile.value(filtered); if (!tile) { qWarning() << "Missing" << filtered; continue; } painter.drawPixmap(0, 0, tile->image()); properties.merge(tile->properties()); } image = QPixmap::fromImage(tileImage); } else { qWarning() << "Copying" << terrainNames << "from" << QFileInfo(tile->tileset()->fileName()).fileName(); image = tile->image(); properties = tile->properties(); } Tile *newTile = targetTileset->addTile(image); newTile->setTerrain(terrainNames.toTerrain(*targetTileset)); newTile->setProperties(properties); terrainToTile.insert(terrainNames, newTile); } if (targetTileset->tileCount() == 0) qCritical("Target tileset is empty"); if (options.embedImage) { // Make sure there is no source name, this way the image will be saved in the TSX file. targetTileset->setImageSource(QString()); } else { // Save the target tileset image as separate file. int columns = qMin(options.columns, targetTileset->tileCount()); int rows = targetTileset->tileCount() / options.columns; if (targetTileset->tileCount() % options.columns > 0) ++rows; qWarning() << "Writing external tileset image."; // Save the target tileset image QImage image(targetTileset->tileWidth() * columns, targetTileset->tileHeight() * rows, QImage::Format_ARGB32); image.fill(Qt::transparent); QPainter painter(&image); for (Tile *tile : targetTileset->tiles()) { int x = (tile->id() % options.columns) * targetTileset->tileWidth(); int y = (tile->id() / options.columns) * targetTileset->tileHeight(); painter.drawPixmap(x, y, tile->image()); } QString imageFileName = QFileInfo(options.target).completeBaseName(); imageFileName += ".png"; image.save(imageFileName); targetTileset->setImageSource(imageFileName); targetTileset->setColumnCount(options.columns); } // Save the target tileset MapWriter writer; targetTileset->setFileName(QString()); writer.writeTileset(*targetTileset, options.target); return 0; } tiled-1.0.3/src/terraingenerator/terraingenerator.pro000066400000000000000000000014361315121121300230450ustar00rootroot00000000000000include(../../tiled.pri) include(../libtiled/libtiled.pri) TEMPLATE = app TARGET = terraingenerator target.path = $${PREFIX}/bin INSTALLS += target CONFIG += console TEMPLATE = app win32|!isEmpty(TILED_LINUX_ARCHIVE) { DESTDIR = ../.. } else { DESTDIR = ../../bin } macx { QMAKE_LIBDIR_FLAGS += -L$$OUT_PWD/../../bin/Tiled.app/Contents/Frameworks } else:win32 { LIBS += -L$$OUT_PWD/../../lib } else { QMAKE_LIBDIR_FLAGS += -L$$OUT_PWD/../../lib } # Make sure the executable can find libtiled !win32:!macx:!cygwin:contains(RPATH, yes) { QMAKE_RPATHDIR += \$\$ORIGIN/../lib # It is not possible to use ORIGIN in QMAKE_RPATHDIR, so a bit manually QMAKE_LFLAGS += -Wl,-z,origin \'-Wl,-rpath,$$join(QMAKE_RPATHDIR, ":")\' QMAKE_RPATHDIR = } SOURCES += main.cpp tiled-1.0.3/src/terraingenerator/terraingenerator.qbs000066400000000000000000000003571315121121300230330ustar00rootroot00000000000000import qbs 1.0 TiledQtGuiApplication { name: "terraingenerator" consoleApplication: true Depends { name: "libtiled" } cpp.includePaths: ["."] cpp.defines: ["QT_NO_FOREACH"] files: [ "main.cpp", ] } tiled-1.0.3/src/tiled/000077500000000000000000000000001315121121300144725ustar00rootroot00000000000000tiled-1.0.3/src/tiled/Info.plist000066400000000000000000000034201315121121300164410ustar00rootroot00000000000000 CFBundleDevelopmentRegion English CFBundleExecutable Tiled CFBundleGetInfoString Tiled 1.0.3, Copyright 2008-2017 Thorbjørn Lindeijer, GNU General Public License CFBundleIconFile tiled-icon-mac CFBundleIdentifier org.mapeditor.Tiled CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleShortVersionString 1.0.3 CFBundleVersion 1.0.3 CSResourcesFileMapped NSHumanReadableCopyright Copyright 2008-2017 Thorbjørn Lindeijer NSHighResolutionCapable CFBundleDocumentTypes CFBundleTypeName Tiled Map CFBundleTypeIconFile tmx-icon-mac CFBundleTypeRole Editor CFBundleTypeExtensions tmx NSAppTransportSecurity NSExceptionDomains update.mapeditor.org NSExceptionAllowsInsecureHTTPLoads SUFeedURL http://update.mapeditor.org/appcast-osx.xml SUPublicDSAKeyFile dsa_pub.pem SUEnableAutomaticChecks SUScheduledCheckInterval 86400 tiled-1.0.3/src/tiled/aboutdialog.cpp000066400000000000000000000052061315121121300174730ustar00rootroot00000000000000/* * aboutdialog.cpp * Copyright 2008-2009, Thorbjørn Lindeijer * Copyright 2009, Dennis Honeyman * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "aboutdialog.h" #include "tiledproxystyle.h" #include "utils.h" #include #include #include #include using namespace Tiled::Internal; AboutDialog::AboutDialog(QWidget *parent): QDialog(parent) { setupUi(this); logo->setMinimumWidth(Utils::dpiScaled(logo->minimumWidth())); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); connect(textBrowser->document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged, this, [this](const QSizeF &size) { textBrowser->setMinimumHeight(int(std::ceil(size.height() + textBrowser->document()->documentMargin()))); }); const QString html = QCoreApplication::translate( "AboutDialog", "

Tiled Map Editor
Version %1

\n" "

Copyright 2008-2017 Thorbjørn Lindeijer
(see the AUTHORS file for a full list of contributors)

\n" "

You may modify and redistribute this program under the terms of the GPL (version 2 or later). " "A copy of the GPL is contained in the 'COPYING' file distributed with Tiled.

\n" "

http://www.mapeditor.org/

\n") .arg(QApplication::applicationVersion()); textBrowser->setHtml(html); if (auto *style = qobject_cast(QApplication::style())) if (style->isDark()) logo->setPixmap(QPixmap(QString::fromUtf8(":/images/about-tiled-logo-white.png"))); connect(donateButton, SIGNAL(clicked()), SLOT(donate())); } void AboutDialog::donate() { QDesktopServices::openUrl(QUrl(QLatin1String("http://www.mapeditor.org/donate"))); } tiled-1.0.3/src/tiled/aboutdialog.h000066400000000000000000000021741315121121300171410ustar00rootroot00000000000000/* * aboutdialog.h * Copyright 2008-2009, Thorbjørn Lindeijer * Copyright 2009, Dennis Honeyman * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include "ui_aboutdialog.h" namespace Tiled { namespace Internal { class AboutDialog : public QDialog, private Ui::AboutDialog { Q_OBJECT public: AboutDialog(QWidget *parent = nullptr); private slots: void donate(); }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/aboutdialog.ui000066400000000000000000000065021315121121300173260ustar00rootroot00000000000000 AboutDialog 0 0 452 476 About Tiled QLayout::SetFixedSize Qt::Horizontal 0 20 400 200 :/images/about-tiled-logo.png Qt::AlignCenter Qt::Horizontal 0 20 true QLayout::SetDefaultConstraint Qt::Horizontal QSizePolicy::Expanding 40 20 Donate OK true pushButton clicked() AboutDialog close() 460 347 255 185 tiled-1.0.3/src/tiled/abstractobjecttool.cpp000066400000000000000000000231531315121121300210720ustar00rootroot00000000000000/* * abstractobjecttool.cpp * Copyright 2011, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "abstractobjecttool.h" #include "map.h" #include "mapdocument.h" #include "mapobject.h" #include "mapobjectitem.h" #include "maprenderer.h" #include "mapscene.h" #include "objectgroup.h" #include "raiselowerhelper.h" #include "resizemapobject.h" #include "tile.h" #include "utils.h" #include #include #include #include using namespace Tiled; using namespace Tiled::Internal; static bool isTileObject(MapObject *mapObject) { return !mapObject->cell().isEmpty(); } static bool isResizedTileObject(MapObject *mapObject) { if (const auto tile = mapObject->cell().tile()) return mapObject->size() != tile->size(); return false; } AbstractObjectTool::AbstractObjectTool(const QString &name, const QIcon &icon, const QKeySequence &shortcut, QObject *parent) : AbstractTool(name, icon, shortcut, parent) , mMapScene(nullptr) { } void AbstractObjectTool::activate(MapScene *scene) { mMapScene = scene; } void AbstractObjectTool::deactivate(MapScene *) { mMapScene = nullptr; } void AbstractObjectTool::keyPressed(QKeyEvent *event) { switch (event->key()) { case Qt::Key_PageUp: raise(); return; case Qt::Key_PageDown: lower(); return; case Qt::Key_Home: raiseToTop(); return; case Qt::Key_End: lowerToBottom(); return; case Qt::Key_D: if (event->modifiers() & Qt::ControlModifier) { duplicateObjects(); return; } break; } event->ignore(); } void AbstractObjectTool::mouseLeft() { setStatusInfo(QString()); } void AbstractObjectTool::mouseMoved(const QPointF &pos, Qt::KeyboardModifiers) { // Take into account the offset of the current layer QPointF offsetPos = pos; if (Layer *layer = currentLayer()) offsetPos -= layer->totalOffset(); const QPoint pixelPos = offsetPos.toPoint(); const QPointF tilePosF = mapDocument()->renderer()->screenToTileCoords(offsetPos); const int x = (int) std::floor(tilePosF.x()); const int y = (int) std::floor(tilePosF.y()); setStatusInfo(QString(QLatin1String("%1, %2 (%3, %4)")).arg(x).arg(y).arg(pixelPos.x()).arg(pixelPos.y())); } void AbstractObjectTool::mousePressed(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::RightButton) { showContextMenu(topMostObjectItemAt(event->scenePos()), event->screenPos()); } } void AbstractObjectTool::updateEnabledState() { setEnabled(currentObjectGroup() != nullptr); } ObjectGroup *AbstractObjectTool::currentObjectGroup() const { if (!mapDocument()) return nullptr; return dynamic_cast(mapDocument()->currentLayer()); } QList AbstractObjectTool::objectItemsAt(QPointF pos) const { const QList &items = mMapScene->items(pos); QList objectList; for (auto item : items) { if (MapObjectItem *objectItem = qgraphicsitem_cast(item)) objectList.append(objectItem); } return objectList; } MapObjectItem *AbstractObjectTool::topMostObjectItemAt(QPointF pos) const { const QList &items = mMapScene->items(pos); for (QGraphicsItem *item : items) { if (MapObjectItem *objectItem = qgraphicsitem_cast(item)) return objectItem; } return nullptr; } void AbstractObjectTool::duplicateObjects() { mapDocument()->duplicateObjects(mapDocument()->selectedObjects()); } void AbstractObjectTool::removeObjects() { mapDocument()->removeObjects(mapDocument()->selectedObjects()); } void AbstractObjectTool::resetTileSize() { QList commands; for (auto mapObject : mapDocument()->selectedObjects()) { if (!isResizedTileObject(mapObject)) continue; commands << new ResizeMapObject(mapDocument(), mapObject, mapObject->cell().tile()->size(), mapObject->size()); } if (!commands.isEmpty()) { QUndoStack *undoStack = mapDocument()->undoStack(); undoStack->beginMacro(tr("Reset Tile Size")); for (auto command : commands) undoStack->push(command); undoStack->endMacro(); } } void AbstractObjectTool::flipHorizontally() { mapDocument()->flipSelectedObjects(FlipHorizontally); } void AbstractObjectTool::flipVertically() { mapDocument()->flipSelectedObjects(FlipVertically); } void AbstractObjectTool::raise() { RaiseLowerHelper(mMapScene).raise(); } void AbstractObjectTool::lower() { RaiseLowerHelper(mMapScene).lower(); } void AbstractObjectTool::raiseToTop() { RaiseLowerHelper(mMapScene).raiseToTop(); } void AbstractObjectTool::lowerToBottom() { RaiseLowerHelper(mMapScene).lowerToBottom(); } /** * Shows the context menu for map objects. The menu allows you to duplicate and * remove the map objects, or to edit their properties. */ void AbstractObjectTool::showContextMenu(MapObjectItem *clickedObjectItem, QPoint screenPos) { QSet selection = mMapScene->selectedObjectItems(); if (clickedObjectItem && !selection.contains(clickedObjectItem)) { selection.clear(); selection.insert(clickedObjectItem); mMapScene->setSelectedObjectItems(selection); } if (selection.isEmpty()) return; const QList &selectedObjects = mapDocument()->selectedObjects(); const QList objectGroups = mapDocument()->map()->objectGroups(); QMenu menu; QAction *duplicateAction = menu.addAction(tr("Duplicate %n Object(s)", "", selection.size()), this, SLOT(duplicateObjects())); QAction *removeAction = menu.addAction(tr("Remove %n Object(s)", "", selection.size()), this, SLOT(removeObjects())); duplicateAction->setIcon(QIcon(QLatin1String(":/images/16x16/stock-duplicate-16.png"))); removeAction->setIcon(QIcon(QLatin1String(":/images/16x16/edit-delete.png"))); bool anyTileObjectSelected = std::any_of(selectedObjects.begin(), selectedObjects.end(), isTileObject); if (anyTileObjectSelected) { auto resetTileSizeAction = menu.addAction(tr("Reset Tile Size"), this, SLOT(resetTileSize())); resetTileSizeAction->setEnabled(std::any_of(selectedObjects.begin(), selectedObjects.end(), isResizedTileObject)); } menu.addSeparator(); menu.addAction(tr("Flip Horizontally"), this, SLOT(flipHorizontally()), QKeySequence(tr("X"))); menu.addAction(tr("Flip Vertically"), this, SLOT(flipVertically()), QKeySequence(tr("Y"))); ObjectGroup *objectGroup = RaiseLowerHelper::sameObjectGroup(selection); if (objectGroup && objectGroup->drawOrder() == ObjectGroup::IndexOrder) { menu.addSeparator(); menu.addAction(tr("Raise Object"), this, SLOT(raise()), QKeySequence(tr("PgUp"))); menu.addAction(tr("Lower Object"), this, SLOT(lower()), QKeySequence(tr("PgDown"))); menu.addAction(tr("Raise Object to Top"), this, SLOT(raiseToTop()), QKeySequence(tr("Home"))); menu.addAction(tr("Lower Object to Bottom"), this, SLOT(lowerToBottom()), QKeySequence(tr("End"))); } if (objectGroups.size() > 1) { menu.addSeparator(); QMenu *moveToLayerMenu = menu.addMenu(tr("Move %n Object(s) to Layer", "", selectedObjects.size())); for (ObjectGroup *objectGroup : objectGroups) { QAction *action = moveToLayerMenu->addAction(objectGroup->name()); action->setData(QVariant::fromValue(objectGroup)); } } menu.addSeparator(); QIcon propIcon(QLatin1String(":images/16x16/document-properties.png")); QAction *propertiesAction = menu.addAction(propIcon, tr("Object &Properties...")); Utils::setThemeIcon(removeAction, "edit-delete"); Utils::setThemeIcon(propertiesAction, "document-properties"); QAction *action = menu.exec(screenPos); if (!action) return; if (action == propertiesAction) { MapObject *mapObject = selectedObjects.first(); mapDocument()->setCurrentObject(mapObject); emit mapDocument()->editCurrentObject(); return; } if (ObjectGroup *objectGroup = action->data().value()) { mapDocument()->moveObjectsToGroup(mapDocument()->selectedObjects(), objectGroup); } } tiled-1.0.3/src/tiled/abstractobjecttool.h000066400000000000000000000047341315121121300205430ustar00rootroot00000000000000/* * abstractobjecttool.h * Copyright 2011, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "abstracttool.h" namespace Tiled { class MapObject; class ObjectGroup; namespace Internal { class MapObjectItem; /** * A convenient base class for tools that work on object layers. Implements * the standard context menu. */ class AbstractObjectTool : public AbstractTool { Q_OBJECT public: /** * Constructs an abstract object tool with the given \a name and \a icon. */ AbstractObjectTool(const QString &name, const QIcon &icon, const QKeySequence &shortcut, QObject *parent = nullptr); void activate(MapScene *scene) override; void deactivate(MapScene *scene) override; void keyPressed(QKeyEvent *event) override; void mouseLeft() override; void mouseMoved(const QPointF &pos, Qt::KeyboardModifiers modifiers) override; void mousePressed(QGraphicsSceneMouseEvent *event) override; protected: /** * Overridden to only enable this tool when the currently selected layer is * an object group. */ void updateEnabledState() override; MapScene *mapScene() const { return mMapScene; } ObjectGroup *currentObjectGroup() const; QList objectItemsAt(QPointF pos) const; MapObjectItem *topMostObjectItemAt(QPointF pos) const; private slots: void duplicateObjects(); void removeObjects(); void resetTileSize(); void flipHorizontally(); void flipVertically(); void raise(); void lower(); void raiseToTop(); void lowerToBottom(); private: void showContextMenu(MapObjectItem *clickedObject, QPoint screenPos); MapScene *mMapScene; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/abstracttiletool.cpp000066400000000000000000000104421315121121300205560ustar00rootroot00000000000000/* * abstracttiletool.cpp * Copyright 2009-2010, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "abstracttiletool.h" #include "brushitem.h" #include "map.h" #include "mapdocument.h" #include "maprenderer.h" #include "mapscene.h" #include "tile.h" #include "tilelayer.h" #include using namespace Tiled; using namespace Tiled::Internal; AbstractTileTool::AbstractTileTool(const QString &name, const QIcon &icon, const QKeySequence &shortcut, QObject *parent) : AbstractTool(name, icon, shortcut, parent) , mTilePositionMethod(OnTiles) , mBrushItem(new BrushItem) , mBrushVisible(false) { mBrushItem->setVisible(false); mBrushItem->setZValue(10000); } AbstractTileTool::~AbstractTileTool() { delete mBrushItem; } void AbstractTileTool::activate(MapScene *scene) { scene->addItem(mBrushItem); } void AbstractTileTool::deactivate(MapScene *scene) { scene->removeItem(mBrushItem); } void AbstractTileTool::mouseEntered() { setBrushVisible(true); } void AbstractTileTool::mouseLeft() { setBrushVisible(false); } void AbstractTileTool::mouseMoved(const QPointF &pos, Qt::KeyboardModifiers) { // Take into account the offset of the current layer QPointF offsetPos = pos; if (Layer *layer = currentLayer()) { offsetPos -= layer->totalOffset(); mBrushItem->setLayerOffset(layer->totalOffset()); } const MapRenderer *renderer = mapDocument()->renderer(); const QPointF tilePosF = renderer->screenToTileCoords(offsetPos); QPoint tilePos; if (mTilePositionMethod == BetweenTiles) tilePos = tilePosF.toPoint(); else tilePos = QPoint((int) std::floor(tilePosF.x()), (int) std::floor(tilePosF.y())); if (mTilePosition != tilePos) { mTilePosition = tilePos; tilePositionChanged(tilePos); updateStatusInfo(); } } void AbstractTileTool::mapDocumentChanged(MapDocument *oldDocument, MapDocument *newDocument) { Q_UNUSED(oldDocument) mBrushItem->setMapDocument(newDocument); } void AbstractTileTool::updateEnabledState() { setEnabled(currentTileLayer() != nullptr); } void AbstractTileTool::updateStatusInfo() { if (mBrushVisible) { int tileId = -1; if (const TileLayer *tileLayer = currentTileLayer()) { const QPoint pos = tilePosition() - tileLayer->position(); if (tileLayer->contains(pos)) tileId = tileLayer->cellAt(pos).tileId(); } QString tileIdString = tileId >= 0 ? QString::number(tileId) : tr("empty"); setStatusInfo(QString(QLatin1String("%1, %2 [%3]")) .arg(mTilePosition.x()) .arg(mTilePosition.y()) .arg(tileIdString)); } else { setStatusInfo(QString()); } } void AbstractTileTool::setBrushVisible(bool visible) { if (mBrushVisible == visible) return; mBrushVisible = visible; updateStatusInfo(); updateBrushVisibility(); } void AbstractTileTool::updateBrushVisibility() { // Show the tile brush only when a visible tile layer is selected bool showBrush = false; if (mBrushVisible) { if (Layer *layer = currentTileLayer()) { if (layer->isVisible()) showBrush = true; } } mBrushItem->setVisible(showBrush); } TileLayer *AbstractTileTool::currentTileLayer() const { if (!mapDocument()) return nullptr; return dynamic_cast(mapDocument()->currentLayer()); } tiled-1.0.3/src/tiled/abstracttiletool.h000066400000000000000000000073211315121121300202250ustar00rootroot00000000000000/* * abstracttiletool.h * Copyright 2009-2010, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "abstracttool.h" namespace Tiled { class TileLayer; namespace Internal { class BrushItem; class MapDocument; /** * A convenient base class for tile based tools. */ class AbstractTileTool : public AbstractTool { Q_OBJECT public: /** * Constructs an abstract tile tool with the given \a name and \a icon. */ AbstractTileTool(const QString &name, const QIcon &icon, const QKeySequence &shortcut, QObject *parent = nullptr); ~AbstractTileTool(); void activate(MapScene *scene) override; void deactivate(MapScene *scene) override; void mouseEntered() override; void mouseLeft() override; void mouseMoved(const QPointF &pos, Qt::KeyboardModifiers modifiers) override; protected: void mapDocumentChanged(MapDocument *oldDocument, MapDocument *newDocument) override; /** * Overridden to only enable this tool when the currently selected layer is * a tile layer. */ void updateEnabledState() override; /** * New virtual method to implement for tile tools. This method is called * on mouse move events, but only when the tile position changes. */ virtual void tilePositionChanged(const QPoint &tilePos) = 0; /** * Updates the status info with the current tile position. When the mouse * is not in the view, the status info is set to an empty string. * * This behaviour can be overridden in a subclass. This method is * automatically called after each call to tilePositionChanged() and when * the brush visibility changes. */ virtual void updateStatusInfo(); bool isBrushVisible() const { return mBrushVisible; } /** * Determines what the tile position means. */ enum TilePositionMethod { OnTiles, /**< Tile position is the tile the mouse is on. */ BetweenTiles /**< Tile position is between the tiles. */ }; void setTilePositionMethod(TilePositionMethod method) { mTilePositionMethod = method; } /** * Returns the last recorded tile position of the mouse. */ QPoint tilePosition() const { return mTilePosition; } /** * Returns the brush item. The brush item is used to give an indication of * what a tile tool is going to do when used. It is automatically shown or * hidden based on whether the mouse is in the scene and whether the * currently selected layer is a tile layer. */ BrushItem *brushItem() const { return mBrushItem; } /** * Returns the current tile layer, or null if no tile layer is currently * selected. */ TileLayer *currentTileLayer() const; private: void setBrushVisible(bool visible); void updateBrushVisibility(); TilePositionMethod mTilePositionMethod; BrushItem *mBrushItem; QPoint mTilePosition; bool mBrushVisible; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/abstracttool.cpp000066400000000000000000000060021315121121300176750ustar00rootroot00000000000000/* * abstracttool.cpp * Copyright 2009-2013, Thorbjørn Lindeijer * Copyright 2010, Jeff Bland * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "abstracttool.h" #include "mapdocument.h" #include namespace Tiled { namespace Internal { AbstractTool::AbstractTool(const QString &name, const QIcon &icon, const QKeySequence &shortcut, QObject *parent) : QObject(parent) , mName(name) , mIcon(icon) , mShortcut(shortcut) , mEnabled(false) , mMapDocument(nullptr) { } /** * Sets the current status information for this tool. This information will be * displayed in the status bar. */ void AbstractTool::setStatusInfo(const QString &statusInfo) { if (mStatusInfo != statusInfo) { mStatusInfo = statusInfo; emit statusInfoChanged(mStatusInfo); } } /** * Sets the cursor used by this tool. This will be the cursor set on the * viewport of the MapView while the tool is active. */ void AbstractTool::setCursor(const QCursor &cursor) { mCursor = cursor; emit cursorChanged(cursor); } void AbstractTool::setEnabled(bool enabled) { if (mEnabled == enabled) return; mEnabled = enabled; emit enabledChanged(enabled); } void AbstractTool::keyPressed(QKeyEvent *event) { event->ignore(); } void AbstractTool::setMapDocument(MapDocument *mapDocument) { if (mMapDocument == mapDocument) return; if (mMapDocument) { disconnect(mMapDocument, &MapDocument::layerChanged, this, &AbstractTool::updateEnabledState); disconnect(mMapDocument, &MapDocument::currentLayerChanged, this, &AbstractTool::updateEnabledState); } MapDocument *oldDocument = mMapDocument; mMapDocument = mapDocument; mapDocumentChanged(oldDocument, mMapDocument); if (mMapDocument) { connect(mMapDocument, &MapDocument::layerChanged, this, &AbstractTool::updateEnabledState); connect(mMapDocument, &MapDocument::currentLayerChanged, this, &AbstractTool::updateEnabledState); } updateEnabledState(); } void AbstractTool::updateEnabledState() { setEnabled(mMapDocument != nullptr); } Layer *AbstractTool::currentLayer() const { return mMapDocument ? mMapDocument->currentLayer() : nullptr; } } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/abstracttool.h000066400000000000000000000136671315121121300173610ustar00rootroot00000000000000/* * abstracttool.h * Copyright 2009-2013, Thorbjørn Lindeijer * Copyright 2010, Jeff Bland * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include #include #include #include #include #include class QEvent; class QKeyEvent; namespace Tiled { class Layer; namespace Internal { class MapDocument; class MapScene; /** * An abstraction of any kind of tool used to edit the map. * * Events that hit the MapScene are forwarded to the current tool, which can * handle them as appropriate for that tool. * * A tool will usually add one or more QGraphicsItems to the scene in order to * represent it to the user. */ class AbstractTool : public QObject { Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName) Q_PROPERTY(QIcon icon READ icon WRITE setIcon) Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut) Q_PROPERTY(QString statusInfo READ statusInfo WRITE setStatusInfo NOTIFY statusInfoChanged) Q_PROPERTY(QCursor cursor READ cursor WRITE setCursor NOTIFY cursorChanged) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) public: /** * Constructs an abstract tool with the given \a name and \a icon. */ AbstractTool(const QString &name, const QIcon &icon, const QKeySequence &shortcut, QObject *parent = nullptr); virtual ~AbstractTool() {} QString name() const; void setName(const QString &name); QIcon icon() const; void setIcon(const QIcon &icon); QKeySequence shortcut() const; void setShortcut(const QKeySequence &shortcut); QString statusInfo() const; void setStatusInfo(const QString &statusInfo); QCursor cursor() const; void setCursor(const QCursor &cursor); bool isEnabled() const; void setEnabled(bool enabled); /** * Activates this tool. If the tool plans to add any items to the scene, it * probably wants to do it here. */ virtual void activate(MapScene *scene) = 0; /** * Deactivates this tool. Should do any necessary cleanup to make sure the * tool is no longer active. */ virtual void deactivate(MapScene *scene) = 0; virtual void keyPressed(QKeyEvent *); /** * Called when the mouse entered the scene. This is usually an appropriate * time to make a hover item visible. */ virtual void mouseEntered() = 0; /** * Called when the mouse left the scene. */ virtual void mouseLeft() = 0; /** * Called when the mouse cursor moves in the scene. */ virtual void mouseMoved(const QPointF &pos, Qt::KeyboardModifiers modifiers) = 0; /** * Called when a mouse button is pressed on the scene. */ virtual void mousePressed(QGraphicsSceneMouseEvent *event) = 0; /** * Called when a mouse button is released on the scene. */ virtual void mouseReleased(QGraphicsSceneMouseEvent *event) = 0; /** * Called when the user presses or releases a modifier key resulting * in a change of modifier status, and when the tool is enabled with * a modifier key pressed. */ virtual void modifiersChanged(Qt::KeyboardModifiers) {} /** * Called when the application language changed. */ virtual void languageChanged() = 0; public slots: void setMapDocument(MapDocument *mapDocument); protected: /** * Can be used to respond to the map document changing. */ virtual void mapDocumentChanged(MapDocument *oldDocument, MapDocument *newDocument) { Q_UNUSED(oldDocument) Q_UNUSED(newDocument) } MapDocument *mapDocument() const { return mMapDocument; } Layer *currentLayer() const; protected slots: /** * By default, this function is called after the current map has changed * and when the current layer changes. It can be overridden to implement * custom logic for when the tool should be enabled. * * The default implementation enables tools when a map document is set. */ virtual void updateEnabledState(); signals: void statusInfoChanged(const QString &statusInfo); void cursorChanged(const QCursor &cursor); void enabledChanged(bool enabled); private: QString mName; QIcon mIcon; QKeySequence mShortcut; QString mStatusInfo; QCursor mCursor; bool mEnabled; MapDocument *mMapDocument; }; inline QString AbstractTool::name() const { return mName; } inline void AbstractTool::setName(const QString &name) { mName = name; } inline QIcon AbstractTool::icon() const { return mIcon; } inline void AbstractTool::setIcon(const QIcon &icon) { mIcon = icon; } inline QKeySequence AbstractTool::shortcut() const { return mShortcut; } inline void AbstractTool::setShortcut(const QKeySequence &shortcut) { mShortcut = shortcut; } inline QString AbstractTool::statusInfo() const { return mStatusInfo; } inline QCursor AbstractTool::cursor() const { return mCursor; } inline bool AbstractTool::isEnabled() const { return mEnabled; } } // namespace Internal } // namespace Tiled Q_DECLARE_METATYPE(Tiled::Internal::AbstractTool*) tiled-1.0.3/src/tiled/actionmanager.cpp000066400000000000000000000030761315121121300200140ustar00rootroot00000000000000/* * actionmanager.cpp * Copyright 2016, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "actionmanager.h" #include namespace Tiled { namespace Internal { class ActionManagerPrivate { public: QHash mIdToAction; }; static ActionManager *m_instance = nullptr; static ActionManagerPrivate *d; ActionManager::ActionManager(QObject *parent) : QObject(parent) { m_instance = this; d = new ActionManagerPrivate; } ActionManager::~ActionManager() { delete d; } void ActionManager::registerAction(QAction *action, Id id) { Q_ASSERT_X(!d->mIdToAction.contains(id), "ActionManager::registerAction", "duplicate id"); d->mIdToAction.insert(id, action); } QAction *ActionManager::action(Id id) { auto act = d->mIdToAction.value(id); Q_ASSERT_X(act, "ActionManager::action", "unknown id"); return act; } } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/actionmanager.h000066400000000000000000000024531315121121300174570ustar00rootroot00000000000000/* * actionmanager.h * Copyright 2016, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "id.h" #include class QAction; namespace Tiled { namespace Internal { class MainWindow; /** * Manager of global actions. */ class ActionManager : public QObject { Q_OBJECT public: static void registerAction(QAction *action, Id id); static QAction *action(Id id); signals: void actionAdded(Id id); private: explicit ActionManager(QObject *parent = nullptr); ~ActionManager(); friend class Tiled::Internal::MainWindow; // creation }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/addpropertydialog.cpp000066400000000000000000000057131315121121300207210ustar00rootroot00000000000000/* * addpropertydialog.cpp * Copyright 2015, CaptainFrog * Copyright 2016, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "addpropertydialog.h" #include "ui_addpropertydialog.h" #include "preferences.h" #include "properties.h" #include "utils.h" #include #include using namespace Tiled; using namespace Tiled::Internal; static const char * const TYPE_KEY = "AddPropertyDialog/PropertyType"; AddPropertyDialog::AddPropertyDialog(QWidget *parent) : QDialog(parent) , mUi(new Ui::AddPropertyDialog) { setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); mUi->setupUi(this); resize(Utils::dpiScaled(size())); QString stringType = typeToName(QVariant::String); // Add possible types from QVariant mUi->typeBox->addItem(typeToName(QVariant::Bool), false); mUi->typeBox->addItem(typeToName(QVariant::Color), QColor()); mUi->typeBox->addItem(typeToName(QVariant::Double), 0.0); mUi->typeBox->addItem(typeToName(filePathTypeId()), QVariant::fromValue(FilePath())); mUi->typeBox->addItem(typeToName(QVariant::Int), 0); mUi->typeBox->addItem(stringType, QString()); mUi->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); // Restore previously used type Preferences *prefs = Preferences::instance(); QSettings *s = prefs->settings(); QString lastType = s->value(QLatin1String(TYPE_KEY), stringType).toString(); mUi->typeBox->setCurrentText(lastType); connect(mUi->name, &QLineEdit::textChanged, this, &AddPropertyDialog::nameChanged); connect(mUi->typeBox, &QComboBox::currentTextChanged, this, &AddPropertyDialog::typeChanged); } AddPropertyDialog::~AddPropertyDialog() { delete mUi; } QString AddPropertyDialog::propertyName() const { return mUi->name->text(); } QVariant AddPropertyDialog::propertyValue() const { return mUi->typeBox->currentData(); } void AddPropertyDialog::nameChanged(const QString &text) { mUi->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.isEmpty()); } void AddPropertyDialog::typeChanged(const QString &text) { Preferences *prefs = Preferences::instance(); QSettings *s = prefs->settings(); s->setValue(QLatin1String(TYPE_KEY), text); } tiled-1.0.3/src/tiled/addpropertydialog.h000066400000000000000000000024311315121121300203600ustar00rootroot00000000000000/* * addpropertydialog.h * Copyright 2015, CaptainFrog * Copyright 2016, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include namespace Ui { class AddPropertyDialog; } class AddPropertyDialog : public QDialog { Q_OBJECT public: explicit AddPropertyDialog(QWidget *parent = nullptr); ~AddPropertyDialog(); QString propertyName() const; QVariant propertyValue() const; private slots: void nameChanged(const QString &text); void typeChanged(const QString &text); private: Ui::AddPropertyDialog *mUi; }; tiled-1.0.3/src/tiled/addpropertydialog.ui000066400000000000000000000040351315121121300205500ustar00rootroot00000000000000 AddPropertyDialog 0 0 298 87 Add Property QLayout::SetMinAndMaxSize false Property name Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok name buttonBox accepted() AddPropertyDialog accept() 302 96 157 105 buttonBox rejected() AddPropertyDialog reject() 338 96 286 105 tiled-1.0.3/src/tiled/addremovelayer.cpp000066400000000000000000000030561315121121300202050ustar00rootroot00000000000000/* * addremovelayer.cpp * Copyright 2009-2017, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "addremovelayer.h" #include "layer.h" #include "layermodel.h" #include "mapdocument.h" namespace Tiled { namespace Internal { AddRemoveLayer::AddRemoveLayer(MapDocument *mapDocument, int index, Layer *layer, GroupLayer *parentLayer) : mMapDocument(mapDocument) , mLayer(layer) , mParentLayer(parentLayer) , mIndex(index) { } AddRemoveLayer::~AddRemoveLayer() { delete mLayer; } void AddRemoveLayer::addLayer() { mMapDocument->layerModel()->insertLayer(mParentLayer, mIndex, mLayer); mLayer = nullptr; } void AddRemoveLayer::removeLayer() { mLayer = mMapDocument->layerModel()->takeLayerAt(mParentLayer, mIndex); } } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/addremovelayer.h000066400000000000000000000046621315121121300176560ustar00rootroot00000000000000/* * addremovelayer.h * Copyright 2009-2017, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include namespace Tiled { class GroupLayer; class Layer; namespace Internal { class MapDocument; /** * Abstract base class for AddLayer and RemoveLayer. */ class AddRemoveLayer : public QUndoCommand { public: AddRemoveLayer(MapDocument *mapDocument, int index, Layer *layer, GroupLayer *parentLayer); ~AddRemoveLayer(); protected: void addLayer(); void removeLayer(); private: MapDocument *mMapDocument; Layer *mLayer; GroupLayer *mParentLayer; int mIndex; }; /** * Undo command that adds a layer to a map. */ class AddLayer : public AddRemoveLayer { public: /** * Creates an undo command that adds the \a layer to \a parentLayer at * \a index. */ AddLayer(MapDocument *mapDocument, int index, Layer *layer, GroupLayer *parentLayer) : AddRemoveLayer(mapDocument, index, layer, parentLayer) { setText(QCoreApplication::translate("Undo Commands", "Add Layer")); } void undo() override { removeLayer(); } void redo() override { addLayer(); } }; /** * Undo command that removes a layer from a map. */ class RemoveLayer : public AddRemoveLayer { public: /** * Creates an undo command that removes the layer at \a index. */ RemoveLayer(MapDocument *mapDocument, int index, GroupLayer *parentLayer) : AddRemoveLayer(mapDocument, index, nullptr, parentLayer) { setText(QCoreApplication::translate("Undo Commands", "Remove Layer")); } void undo() override { addLayer(); } void redo() override { removeLayer(); } }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/addremovemapobject.cpp000066400000000000000000000057241315121121300210410ustar00rootroot00000000000000/* * addremovemapobject.cpp * Copyright 2009, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "addremovemapobject.h" #include "mapdocument.h" #include "mapobject.h" #include "objectgroup.h" #include "mapobjectmodel.h" #include using namespace Tiled; using namespace Tiled::Internal; AddRemoveMapObject::AddRemoveMapObject(MapDocument *mapDocument, ObjectGroup *objectGroup, MapObject *mapObject, bool ownObject, QUndoCommand *parent) : QUndoCommand(parent) , mMapDocument(mapDocument) , mMapObject(mapObject) , mObjectGroup(objectGroup) , mIndex(-1) , mOwnsObject(ownObject) { } AddRemoveMapObject::~AddRemoveMapObject() { if (mOwnsObject) delete mMapObject; } void AddRemoveMapObject::addObject() { mMapDocument->mapObjectModel()->insertObject(mObjectGroup, mIndex, mMapObject); mOwnsObject = false; } void AddRemoveMapObject::removeObject() { mIndex = mMapDocument->mapObjectModel()->removeObject(mObjectGroup, mMapObject); mOwnsObject = true; } AddMapObject::AddMapObject(MapDocument *mapDocument, ObjectGroup *objectGroup, MapObject *mapObject, QUndoCommand *parent) : AddRemoveMapObject(mapDocument, objectGroup, mapObject, true, parent) { setText(QCoreApplication::translate("Undo Commands", "Add Object")); } void AddMapObject::undo() { removeObject(); QUndoCommand::undo(); // undo child commands } void AddMapObject::redo() { QUndoCommand::redo(); // redo child commands addObject(); } RemoveMapObject::RemoveMapObject(MapDocument *mapDocument, MapObject *mapObject, QUndoCommand *parent) : AddRemoveMapObject(mapDocument, mapObject->objectGroup(), mapObject, false, parent) { setText(QCoreApplication::translate("Undo Commands", "Remove Object")); } tiled-1.0.3/src/tiled/addremovemapobject.h000066400000000000000000000042321315121121300204770ustar00rootroot00000000000000/* * addremovemapobject.h * Copyright 2009, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include namespace Tiled { class MapObject; class ObjectGroup; namespace Internal { class MapDocument; /** * Abstract base class for AddMapObject and RemoveMapObject. */ class AddRemoveMapObject : public QUndoCommand { public: AddRemoveMapObject(MapDocument *mapDocument, ObjectGroup *objectGroup, MapObject *mapObject, bool ownObject, QUndoCommand *parent = nullptr); ~AddRemoveMapObject(); protected: void addObject(); void removeObject(); private: MapDocument *mMapDocument; MapObject *mMapObject; ObjectGroup *mObjectGroup; int mIndex; bool mOwnsObject; }; /** * Undo command that adds an object to a map. */ class AddMapObject : public AddRemoveMapObject { public: AddMapObject(MapDocument *mapDocument, ObjectGroup *objectGroup, MapObject *mapObject, QUndoCommand *parent = nullptr); void undo() override; void redo() override; }; /** * Undo command that removes an object from a map. */ class RemoveMapObject : public AddRemoveMapObject { public: RemoveMapObject(MapDocument *mapDocument, MapObject *mapObject, QUndoCommand *parent = nullptr); void undo() override { addObject(); } void redo() override { removeObject(); } }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/addremoveterrain.cpp000066400000000000000000000042701315121121300205340ustar00rootroot00000000000000/* * addremoveterrain.cpp * Copyright 2012, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "addremoveterrain.h" #include "terrain.h" #include "tileset.h" #include "tilesetdocument.h" #include "tilesetterrainmodel.h" #include using namespace Tiled; using namespace Tiled::Internal; AddRemoveTerrain::AddRemoveTerrain(TilesetDocument *tilesetDocument, int index, Terrain *terrain) : mTilesetDocument(tilesetDocument) , mTileset(tilesetDocument->tileset().data()) , mIndex(index) , mTerrain(terrain) { } AddRemoveTerrain::~AddRemoveTerrain() { delete mTerrain; } void AddRemoveTerrain::removeTerrain() { Q_ASSERT(!mTerrain); mTerrain = mTilesetDocument->terrainModel()->takeTerrainAt(mIndex); } void AddRemoveTerrain::addTerrain() { Q_ASSERT(mTerrain); mTilesetDocument->terrainModel()->insertTerrain(mIndex, mTerrain); mTerrain = nullptr; } AddTerrain::AddTerrain(TilesetDocument *tilesetDocument, Terrain *terrain) : AddRemoveTerrain(tilesetDocument, terrain->tileset()->terrainCount(), terrain) { setText(QCoreApplication::translate("Undo Commands", "Add Terrain")); } RemoveTerrain::RemoveTerrain(TilesetDocument *tilesetDocument, Terrain *terrain) : AddRemoveTerrain(tilesetDocument, terrain->id(), nullptr) { setText(QCoreApplication::translate("Undo Commands", "Remove Terrain")); } tiled-1.0.3/src/tiled/addremoveterrain.h000066400000000000000000000035771315121121300202120ustar00rootroot00000000000000/* * addremoveterrain.h * Copyright 2012, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include namespace Tiled { class Terrain; class Tileset; namespace Internal { class TilesetDocument; /** * Abstract base class for AddTerrain and RemoveTerrain. */ class AddRemoveTerrain : public QUndoCommand { public: AddRemoveTerrain(TilesetDocument *tilesetDocument, int index, Terrain *terrain); ~AddRemoveTerrain(); protected: void addTerrain(); void removeTerrain(); private: TilesetDocument *mTilesetDocument; Tileset *mTileset; int mIndex; Terrain *mTerrain; }; /** * Adds a terrain to a map. */ class AddTerrain : public AddRemoveTerrain { public: AddTerrain(TilesetDocument *tilesetDocument, Terrain *terrain); void undo() override { removeTerrain(); } void redo() override { addTerrain(); } }; /** * Removes a terrain from a map. */ class RemoveTerrain : public AddRemoveTerrain { public: RemoveTerrain(TilesetDocument *tilesetDocument, Terrain *terrain); void undo() override { addTerrain(); } void redo() override { removeTerrain(); } }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/addremovetiles.cpp000066400000000000000000000037121315121121300202100ustar00rootroot00000000000000/* * addremovetiles.cpp * Copyright 2013, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "addremovetiles.h" #include "tile.h" #include "tilesetdocument.h" #include namespace Tiled { namespace Internal { AddRemoveTiles::AddRemoveTiles(TilesetDocument *tilesetDocument, const QList &tiles, bool add) : mTilesetDocument(tilesetDocument) , mTiles(tiles) , mTilesAdded(!add) { } AddRemoveTiles::~AddRemoveTiles() { if (!mTilesAdded) qDeleteAll(mTiles); } void AddRemoveTiles::addTiles() { mTilesetDocument->addTiles(mTiles); mTilesAdded = true; } void AddRemoveTiles::removeTiles() { mTilesetDocument->removeTiles(mTiles); mTilesAdded = false; } AddTiles::AddTiles(TilesetDocument *tilesetDocument, const QList &tiles) : AddRemoveTiles(tilesetDocument, tiles, true) { setText(QCoreApplication::translate("Undo Commands", "Add Tiles")); } RemoveTiles::RemoveTiles(TilesetDocument *tilesetDocument, const QList &tiles) : AddRemoveTiles(tilesetDocument, tiles, false) { setText(QCoreApplication::translate("Undo Commands", "Remove Tiles")); } } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/addremovetiles.h000066400000000000000000000036441315121121300176610ustar00rootroot00000000000000/* * addremovetiles.h * Copyright 2013, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include namespace Tiled { class Tile; namespace Internal { class TilesetDocument; /** * Abstract base class for AddTiles and RemoveTiles. */ class AddRemoveTiles : public QUndoCommand { public: AddRemoveTiles(TilesetDocument *tilesetDocument, const QList &tiles, bool add); ~AddRemoveTiles(); protected: void addTiles(); void removeTiles(); private: TilesetDocument *mTilesetDocument; QList mTiles; bool mTilesAdded; }; /** * Undo command that adds tiles to a tileset. */ class AddTiles : public AddRemoveTiles { public: AddTiles(TilesetDocument *tilesetDocument, const QList &tiles); void undo() override { removeTiles(); } void redo() override { addTiles(); } }; /** * Undo command that removes tiles from a tileset. */ class RemoveTiles : public AddRemoveTiles { public: RemoveTiles(TilesetDocument *tilesetDocument, const QList &tiles); void undo() override { addTiles(); } void redo() override { removeTiles(); } }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/addremovetileset.cpp000066400000000000000000000044651315121121300205470ustar00rootroot00000000000000/* * addremovetileset.cpp * Copyright 2010, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "addremovetileset.h" #include "map.h" #include "mapdocument.h" #include "tilesetmanager.h" using namespace Tiled; using namespace Tiled::Internal; AddRemoveTileset::AddRemoveTileset(MapDocument *mapDocument, int index, const SharedTileset &tileset, QUndoCommand *parent) : QUndoCommand(parent) , mMapDocument(mapDocument) , mTileset(tileset) , mIndex(index) { // Make sure the tileset manager keeps watching this tileset TilesetManager::instance()->addReference(mTileset); } AddRemoveTileset::~AddRemoveTileset() { TilesetManager::instance()->removeReference(mTileset); } void AddRemoveTileset::removeTileset() { mMapDocument->removeTilesetAt(mIndex); } void AddRemoveTileset::addTileset() { mMapDocument->insertTileset(mIndex, mTileset); } AddTileset::AddTileset(MapDocument *mapDocument, const SharedTileset &tileset, QUndoCommand *parent) : AddRemoveTileset(mapDocument, mapDocument->map()->tilesets().size(), tileset, parent) { setText(QCoreApplication::translate("Undo Commands", "Add Tileset")); } RemoveTileset::RemoveTileset(MapDocument *mapDocument, int index) : AddRemoveTileset(mapDocument, index, mapDocument->map()->tilesetAt(index)) { setText(QCoreApplication::translate("Undo Commands", "Remove Tileset")); } tiled-1.0.3/src/tiled/addremovetileset.h000066400000000000000000000037421315121121300202110ustar00rootroot00000000000000/* * addremovetileset.h * Copyright 2010, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "tileset.h" #include #include namespace Tiled { namespace Internal { class MapDocument; /** * Abstract base class for AddTileset and RemoveTileset. */ class AddRemoveTileset : public QUndoCommand { public: AddRemoveTileset(MapDocument *mapDocument, int index, const SharedTileset &tileset, QUndoCommand *parent = nullptr); ~AddRemoveTileset(); protected: void addTileset(); void removeTileset(); private: MapDocument *mMapDocument; SharedTileset mTileset; int mIndex; }; /** * Adds a tileset to a map. */ class AddTileset : public AddRemoveTileset { public: AddTileset(MapDocument *mapDocument, const SharedTileset &tileset, QUndoCommand *parent = nullptr); void undo() override { removeTileset(); } void redo() override { addTileset(); } }; /** * Removes a tileset from a map. */ class RemoveTileset : public AddRemoveTileset { public: RemoveTileset(MapDocument *mapDocument, int index); void undo() override { addTileset(); } void redo() override { removeTileset(); } }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/adjusttileindexes.cpp000066400000000000000000000215561315121121300207370ustar00rootroot00000000000000/* * adjusttileindexes.cpp * Copyright 2015, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "adjusttileindexes.h" #include "changemapobject.h" #include "changeproperties.h" #include "changetileanimation.h" #include "changetileobjectgroup.h" #include "changetileprobability.h" #include "changetileterrain.h" #include "map.h" #include "mapdocument.h" #include "mapobject.h" #include "objectgroup.h" #include "painttilelayer.h" #include "tile.h" #include "tilelayer.h" #include "tilesetdocument.h" #include namespace Tiled { namespace Internal { AdjustTileIndexes::AdjustTileIndexes(MapDocument *mapDocument, const Tileset &tileset) : QUndoCommand(QCoreApplication::translate("Undo Commands", "Adjust Tile Indexes")) { int oldColumnCount = tileset.expectedColumnCount(); int newColumnCount = tileset.columnCount(); auto isFromTileset = [&](const Cell &cell) -> bool { return cell.tileset() == &tileset; }; auto adjustCell = [&](Cell cell) -> Cell { int tileIndex = cell.tileId(); int row = tileIndex / oldColumnCount; int column = tileIndex % oldColumnCount; if (column < newColumnCount) { int newTileIndex = row * newColumnCount + column; cell.setTile(cell.tileset(), newTileIndex); } else { cell.setTile(nullptr); } return cell; }; QVector objectChanges; // Adjust tile references from map layers LayerIterator iterator(mapDocument->map()); while (Layer *layer = iterator.next()) { switch (layer->layerType()) { case Layer::TileLayerType: { TileLayer *tileLayer = static_cast(layer); QRegion region = tileLayer->region(isFromTileset).translated(-layer->position()); if (!region.isEmpty()) { const QRect boundingRect(region.boundingRect()); auto changedLayer = new TileLayer(QString(), 0, 0, boundingRect.width(), boundingRect.height()); for (const QRect &rect : region.rects()) { for (int x = rect.left(); x <= rect.right(); ++x) { for (int y = rect.top(); y <= rect.bottom(); ++y) { Cell cell = adjustCell(tileLayer->cellAt(x, y)); changedLayer->setCell(x - boundingRect.x(), y - boundingRect.y(), cell); } } } new PaintTileLayer(mapDocument, tileLayer, boundingRect.x() + tileLayer->x(), boundingRect.y() + tileLayer->y(), changedLayer, this); delete changedLayer; } break; } case Layer::ObjectGroupType: for (MapObject *mapObject : *static_cast(layer)) { if (isFromTileset(mapObject->cell())) { MapObjectCell change; change.object = mapObject; change.cell = adjustCell(mapObject->cell()); objectChanges.append(change); } } break; case Layer::ImageLayerType: case Layer::GroupLayerType: break; } } if (!objectChanges.isEmpty()) new ChangeMapObjectCells(mapDocument, objectChanges, this); } AdjustTileMetaData::AdjustTileMetaData(TilesetDocument *tilesetDocument) : QUndoCommand(QCoreApplication::translate("Undo Commands", "Adjust Tile Indexes")) { const Tileset &tileset = *tilesetDocument->tileset(); int oldColumnCount = tileset.expectedColumnCount(); int newColumnCount = tileset.columnCount(); auto adjustTile = [&](const Tile *tile) -> Tile* { int tileIndex = tile->id(); int row = tileIndex / oldColumnCount; int column = tileIndex % oldColumnCount; if (column < newColumnCount) { int newTileIndex = row * newColumnCount + column; return tileset.findTile(newTileIndex); } return nullptr; }; // Adjust tile meta data QList tilesChangingProbability; QList tileProbabilities; ChangeTileTerrain::Changes terrainChanges; QSet tilesToReset; auto adjustAnimationFrames = [&](const QVector &frames) -> QVector { QVector newFrames; for (const Frame &frame : frames) { if (Tile *tile = tileset.findTile(frame.tileId)) { if (Tile *newTile = adjustTile(tile)) newFrames.append(Frame { newTile->id(), frame.duration }); } } return newFrames; }; auto applyMetaData = [&](Tile *toTile, const Properties &properties, unsigned terrain, float probability, ObjectGroup *objectGroup, const QVector &frames) { if (properties != toTile->properties()) { new ChangeProperties(tilesetDocument, QCoreApplication::translate("MapDocument", "Tile"), toTile, properties, this); } if (terrain != toTile->terrain()) { terrainChanges.insert(toTile, ChangeTileTerrain::Change(toTile->terrain(), terrain)); } if (probability != toTile->probability()) { tilesChangingProbability.append(toTile); tileProbabilities.append(probability); } if (objectGroup != toTile->objectGroup()) new ChangeTileObjectGroup(tilesetDocument, toTile, objectGroup, this); if (frames != toTile->frames()) new ChangeTileAnimation(tilesetDocument, toTile, frames, this); }; auto moveMetaData = [&](Tile *fromTile) { Tile *toTile = adjustTile(fromTile); if (toTile == fromTile) return; tilesToReset.insert(fromTile); // We may still need to reset "fromTile" if (!toTile) return; tilesToReset.remove(toTile); // "toTile" no longer needs to get reset // Copy meta data from "fromTile" to "toTile" ObjectGroup *objectGroup = nullptr; if (fromTile->objectGroup()) objectGroup = fromTile->objectGroup()->clone(); applyMetaData(toTile, fromTile->properties(), fromTile->terrain(), fromTile->probability(), objectGroup, adjustAnimationFrames(fromTile->frames())); }; QMapIterator iterator{tileset.tiles()}; if (newColumnCount > oldColumnCount) { // Increasing column count means information is copied to higher tiles, // so we need to iterate backwards. iterator.toBack(); while (iterator.hasPrevious()) moveMetaData(iterator.previous().value()); } else { while (iterator.hasNext()) moveMetaData(iterator.next().value()); } // Reset meta data on tiles that nothing was copied to QSetIterator resetIterator(tilesToReset); while (resetIterator.hasNext()) { applyMetaData(resetIterator.next(), Properties(), -1, 1.0f, nullptr, QVector()); } if (!tilesChangingProbability.isEmpty()) { new ChangeTileProbability(tilesetDocument, tilesChangingProbability, tileProbabilities, this); } if (!terrainChanges.isEmpty()) new ChangeTileTerrain(tilesetDocument, terrainChanges, this); } } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/adjusttileindexes.h000066400000000000000000000026001315121121300203710ustar00rootroot00000000000000/* * adjusttileindexes.h * Copyright 2015, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include namespace Tiled { class Tileset; namespace Internal { class MapDocument; class TilesetDocument; /** * Adjusts tile indexes based on a change in the number of columns in a tileset * image. */ class AdjustTileIndexes : public QUndoCommand { public: AdjustTileIndexes(MapDocument *mapDocument, const Tileset &tileset); }; /** * Adjusts tile meta-data based on a change in the number of columns in a * tileset image. */ class AdjustTileMetaData : public QUndoCommand { public: AdjustTileMetaData(TilesetDocument *tilesetDocument); }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/automapper.cpp000066400000000000000000001003531315121121300173550ustar00rootroot00000000000000/* * automapper.cpp * Copyright 2010-2012, Stefan Beller, stefanbeller@googlemail.com * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "automapper.h" #include "addremovelayer.h" #include "addremovemapobject.h" #include "addremovetileset.h" #include "automappingutils.h" #include "changeproperties.h" #include "geometry.h" #include "layermodel.h" #include "map.h" #include "mapdocument.h" #include "mapobject.h" #include "maprenderer.h" #include "object.h" #include "objectgroup.h" #include "tile.h" #include "tilelayer.h" #include "tilesetmanager.h" #include using namespace Tiled; using namespace Tiled::Internal; /* * About the order of the methods in this file. * The Automapper class has 3 bigger public functions, that is * prepareLoad(), prepareAutoMap() and autoMap(). * These three functions make use of lots of different private methods, which * are put directly below each of these functions. */ AutoMapper::AutoMapper(MapDocument *workingDocument, Map *rules, const QString &rulePath) : mMapDocument(workingDocument) , mMapWork(workingDocument ? workingDocument->map() : nullptr) , mMapRules(rules) , mLayerInputRegions(nullptr) , mLayerOutputRegions(nullptr) , mRulePath(rulePath) , mDeleteTiles(false) , mAutoMappingRadius(0) , mNoOverlappingRules(false) { Q_ASSERT(mMapRules); TilesetManager *tilesetManager = TilesetManager::instance(); tilesetManager->addReferences(rules->tilesets()); if (!setupRuleMapProperties()) return; if (!setupRuleMapTileLayers()) return; if (!setupRuleList()) return; } AutoMapper::~AutoMapper() { cleanUpRulesMap(); } QSet AutoMapper::getTouchedTileLayers() const { return mTouchedTileLayers; } bool AutoMapper::ruleLayerNameUsed(QString ruleLayerName) const { return mInputRules.names.contains(ruleLayerName); } bool AutoMapper::setupRuleMapProperties() { QMapIterator it(mMapRules->properties()); while (it.hasNext()) { it.next(); const QString &name = it.key(); const QVariant &value = it.value(); bool raiseWarning = true; if (name.compare(QLatin1String("deletetiles"), Qt::CaseInsensitive) == 0) { if (value.canConvert(QVariant::Bool)) { mDeleteTiles = value.toBool(); raiseWarning = false; } } else if (name.compare(QLatin1String("automappingradius"), Qt::CaseInsensitive) == 0) { if (value.canConvert(QVariant::Int)) { mAutoMappingRadius = value.toInt(); raiseWarning = false; } } else if (name.compare(QLatin1String("nooverlappingrules"), Qt::CaseInsensitive) == 0) { if (value.canConvert(QVariant::Bool)) { mNoOverlappingRules = value.toBool(); raiseWarning = false; } } if (raiseWarning) { mWarning += tr("'%1': Property '%2' = '%3' does not make sense. " "Ignoring this property.") .arg(mRulePath, name, value.toString()) + QLatin1Char('\n'); } } return true; } bool AutoMapper::setupRuleMapTileLayers() { Q_ASSERT(mLayerList.isEmpty()); Q_ASSERT(mAddedTilesets.isEmpty()); Q_ASSERT(!mLayerInputRegions); Q_ASSERT(!mLayerOutputRegions); Q_ASSERT(mInputRules.isEmpty()); Q_ASSERT(mInputRules.names.isEmpty()); QString error; for (Layer *layer : mMapRules->layers()) { const QString layerName = layer->name(); if (layerName.startsWith(QLatin1String("regions"), Qt::CaseInsensitive)) { bool inputAndOutput = layerName.compare(QLatin1String("regions"), Qt::CaseInsensitive) == 0; if (inputAndOutput || layerName.endsWith(QLatin1String("input"), Qt::CaseInsensitive)) { if (mLayerInputRegions) { error += tr("'regions_input' layer must not occur more than once."); error += QLatin1Char('\n'); } if (TileLayer *tileLayer = layer->asTileLayer()) { mLayerInputRegions = tileLayer; } else { error += tr("'regions_*' layers must be tile layers."); error += QLatin1Char('\n'); } } if (inputAndOutput || layerName.endsWith(QLatin1String("output"), Qt::CaseInsensitive)) { if (mLayerOutputRegions) { error += tr("'regions_output' layer must not occur more than once."); error += QLatin1Char('\n'); } if (TileLayer *tileLayer = layer->asTileLayer()) { mLayerOutputRegions = tileLayer; } else { error += tr("'regions_*' layers must be tile layers."); error += QLatin1Char('\n'); } } continue; } int nameStartPosition = layerName.indexOf(QLatin1Char('_')) + 1; // both 'rule' and 'output' layers will require and underscore and // rely on the correct position detected of the underscore if (nameStartPosition == 0) { error += tr("Did you forget an underscore in layer '%1'?").arg(layerName); error += QLatin1Char('\n'); continue; } QString name = layerName.mid(nameStartPosition); // all characters behind the underscore (excluded) QString index = layerName.left(nameStartPosition); // all before the underscore (included) if (index.startsWith(QLatin1String("output"), Qt::CaseInsensitive)) index.remove(0, 6); else if (index.startsWith(QLatin1String("inputnot"), Qt::CaseInsensitive)) index.remove(0, 8); else if (index.startsWith(QLatin1String("input"), Qt::CaseInsensitive)) index.remove(0, 5); if (layerName.startsWith(QLatin1String("input"), Qt::CaseInsensitive)) { bool isNotList = layerName.startsWith(QLatin1String("inputnot"), Qt::CaseInsensitive); TileLayer *tileLayer = layer->asTileLayer(); if (!tileLayer) { error += tr("'input_*' and 'inputnot_*' layers must be tile layers."); error += QLatin1Char('\n'); continue; } mInputRules.names.insert(name); if (!mInputRules.contains(index)) mInputRules.insert(index, InputIndex()); if (!mInputRules[index].contains(name)) mInputRules[index].insert(name, InputConditions()); if (isNotList) mInputRules[index][name].listNo.append(tileLayer); else mInputRules[index][name].listYes.append(tileLayer); continue; } if (layerName.startsWith(QLatin1String("output"), Qt::CaseInsensitive)) { if (layer->isTileLayer()) mTouchedTileLayers.insert(name); else if (layer->isObjectGroup()) mTouchedObjectGroups.insert(name); Layer::TypeFlag type = layer->layerType(); int layerIndex = mMapWork->indexOfLayer(name, type); bool found = false; for (RuleOutput &translationTable : mLayerList) { if (translationTable.index == index) { translationTable.insert(layer, layerIndex); found = true; break; } } if (!found) { mLayerList.append(RuleOutput()); mLayerList.last().insert(layer, layerIndex); mLayerList.last().index = index; } continue; } error += tr("Layer '%1' is not recognized as a valid layer for Automapping.") .arg(layerName) + QLatin1Char('\n'); } if (!mLayerInputRegions) error += tr("No 'regions' or 'regions_input' layer found.") + QLatin1Char('\n'); if (!mLayerOutputRegions) error += tr("No 'regions' or 'regions_output' layer found.") + QLatin1Char('\n'); if (mInputRules.isEmpty()) error += tr("No input_ layer found!") + QLatin1Char('\n'); // no need to check for mInputNotRules.size() == 0 here. // these layers are not necessary. if (!error.isEmpty()) { error = mRulePath + QLatin1Char('\n') + error; mError += error; return false; } return true; } static bool compareRuleRegion(const QRegion &r1, const QRegion &r2) { const QPoint &p1 = r1.boundingRect().topLeft(); const QPoint &p2 = r2.boundingRect().topLeft(); return p1.y() < p2.y() || (p1.y() == p2.y() && p1.x() < p2.x()); } bool AutoMapper::setupRuleList() { Q_ASSERT(mRulesInput.isEmpty()); Q_ASSERT(mRulesOutput.isEmpty()); Q_ASSERT(mLayerInputRegions); Q_ASSERT(mLayerOutputRegions); QVector combinedRegions = coherentRegions(mLayerInputRegions->region() + mLayerOutputRegions->region()); qSort(combinedRegions.begin(), combinedRegions.end(), compareRuleRegion); const QVector rulesInput = coherentRegions(mLayerInputRegions->region()); const QVector rulesOutput = coherentRegions(mLayerOutputRegions->region()); mRulesInput.resize(combinedRegions.size()); mRulesOutput.resize(combinedRegions.size()); for (const QRegion ® : rulesInput) { for (int i = 0; i < combinedRegions.size(); ++i) { if (reg.intersects(combinedRegions[i])) { mRulesInput[i] += reg; break; } } } for (const QRegion ® : rulesOutput) { for (int i = 0; i < combinedRegions.size(); ++i) { if (reg.intersects(combinedRegions[i])) { mRulesOutput[i] += reg; break; } } } Q_ASSERT(mRulesInput.size() == mRulesOutput.size()); for (int i = 0; i < mRulesInput.size(); ++i) { const QRegion checkCoherent = mRulesInput.at(i).united(mRulesOutput.at(i)); Q_ASSERT(coherentRegions(checkCoherent).size() == 1); } return true; } bool AutoMapper::prepareAutoMap() { mError.clear(); mWarning.clear(); if (!setupMissingLayers()) return false; if (!setupCorrectIndexes()) return false; if (!setupTilesets()) return false; return true; } bool AutoMapper::setupMissingLayers() { QUndoStack *undoStack = mMapDocument->undoStack(); // make sure all needed layers are there: foreach (const QString &name, mTouchedTileLayers) { if (mMapWork->indexOfLayer(name, Layer::TileLayerType) != -1) continue; const int index = mMapWork->layerCount(); TileLayer *tileLayer = new TileLayer(name, 0, 0, mMapWork->width(), mMapWork->height()); undoStack->push(new AddLayer(mMapDocument, index, tileLayer, nullptr)); mAddedLayers.append(tileLayer); } foreach (const QString &name, mTouchedObjectGroups) { if (mMapWork->indexOfLayer(name, Layer::ObjectGroupType) != -1) continue; const int index = mMapWork->layerCount(); ObjectGroup *objectGroup = new ObjectGroup(name, 0, 0); undoStack->push(new AddLayer(mMapDocument, index, objectGroup, nullptr)); mAddedLayers.append(objectGroup); } return true; } bool AutoMapper::setupCorrectIndexes() { // make sure all indexes of the layer translation tables are correct. for (RuleOutput &translationTable : mLayerList) { foreach (Layer *layerKey, translationTable.keys()) { QString name = layerKey->name(); const int pos = name.indexOf(QLatin1Char('_')) + 1; name = name.right(name.length() - pos); const int index = translationTable.value(layerKey, -1); if (index >= mMapWork->layerCount() || index == -1 || name != mMapWork->layerAt(index)->name()) { int newIndex = mMapWork->indexOfLayer(name, layerKey->layerType()); Q_ASSERT(newIndex != -1); translationTable.insert(layerKey, newIndex); } } } return true; } bool AutoMapper::setupTilesets() { Q_ASSERT(mAddedTilesets.isEmpty()); mMapDocument->unifyTilesets(mMapRules, mAddedTilesets); const auto &addedTilesets = mAddedTilesets; for (const SharedTileset &tileset : addedTilesets) mMapDocument->undoStack()->push(new AddTileset(mMapDocument, tileset)); return true; } void AutoMapper::autoMap(QRegion *where) { Q_ASSERT(mRulesInput.size() == mRulesOutput.size()); // first resize the active area if (mAutoMappingRadius) { QRegion region; for (const QRect &r : where->rects()) { region += r.adjusted(- mAutoMappingRadius, - mAutoMappingRadius, + mAutoMappingRadius, + mAutoMappingRadius); } *where += region; } // delete all the relevant area, if the property "DeleteTiles" is set if (mDeleteTiles) { const QRegion setLayersRegion = getSetLayersRegion(); for (RuleOutput &translationTable : mLayerList) { foreach (Layer *layer, translationTable.keys()) { const int index = translationTable.value(layer); Layer *dstLayer = mMapWork->layerAt(index); const QRegion region = setLayersRegion.intersected(*where); TileLayer *dstTileLayer = dstLayer->asTileLayer(); if (dstTileLayer) { dstTileLayer->erase(region); } else { eraseRegionObjectGroup(mMapDocument, dstLayer->asObjectGroup(), region); } } } } // Increase the given region where the next automapper should work. // This needs to be done, so you can rely on the order of the rules at all // locations QRegion ret; foreach (const QRect &rect, where->rects()) { for (int i = 0; i < mRulesInput.size(); ++i) { // at the moment the parallel execution does not work yet // TODO: make multithreading available! // either by dividing the rules or the region to multiple threads ret = ret.united(applyRule(i, rect)); } } *where = where->united(ret); } QRegion AutoMapper::getSetLayersRegion() const { QRegion result; for (const QString &name : mInputRules.names) { const int index = mMapWork->indexOfLayer(name, Layer::TileLayerType); if (index == -1) continue; TileLayer *setLayer = mMapWork->layerAt(index)->asTileLayer(); result |= setLayer->region(); } return result; } static bool compareLayerTo(const TileLayer *setLayer, const QVector &listYes, const QVector &listNo, const QRegion &ruleRegion, const QPoint &offset); QRect AutoMapper::applyRule(const int ruleIndex, const QRect &where) { QRect ret; if (mLayerList.isEmpty()) return ret; const QRegion &ruleInputRegion = mRulesInput.at(ruleIndex); const QRegion &ruleOutputRegion = mRulesOutput.at(ruleIndex); QRect rbr = ruleInputRegion.boundingRect(); // Since the rule itself is translated, we need to adjust the borders of the // loops. Decrease the size at all sides by one: There must be at least one // tile overlap to the rule. const int minX = where.left() - rbr.left() - rbr.width() + 1; const int minY = where.top() - rbr.top() - rbr.height() + 1; const int maxX = where.right() - rbr.left() + rbr.width() - 1; const int maxY = where.bottom() - rbr.top() + rbr.height() - 1; // In this list of regions it is stored which parts or the map have already // been altered by exactly this rule. We store all the altered parts to // make sure there are no overlaps of the same rule applied to // (neighbouring) places QVector appliedRegions; if (mNoOverlappingRules) appliedRegions.resize(mMapWork->layerCount()); for (int y = minY; y <= maxY; ++y) for (int x = minX; x <= maxX; ++x) { bool anyMatch = false; const auto &inputRules = mInputRules; for (const InputIndex &inputIndex : inputRules) { bool allLayerNamesMatch = true; QMapIterator inputIndexIterator(inputIndex); while (inputIndexIterator.hasNext()) { inputIndexIterator.next(); const QString &name = inputIndexIterator.key(); const InputConditions &conditions = inputIndexIterator.value(); const int i = mMapWork->indexOfLayer(name, Layer::TileLayerType); if (i == -1) { allLayerNamesMatch = false; } else { const TileLayer *setLayer = mMapWork->layerAt(i)->asTileLayer(); allLayerNamesMatch &= compareLayerTo(setLayer, conditions.listYes, conditions.listNo, ruleInputRegion, QPoint(x, y)); } } if (allLayerNamesMatch) { anyMatch = true; break; } } if (anyMatch) { // choose by chance which group of rule_layers should be used: const int r = qrand() % mLayerList.size(); const RuleOutput &translationTable = mLayerList.at(r); if (!mNoOverlappingRules) { copyMapRegion(ruleOutputRegion, QPoint(x, y), translationTable); ret = ret.united(rbr.translated(QPoint(x, y))); continue; } bool missmatch = false; const QList layers = translationTable.keys(); // check if there are no overlaps within this rule. QVector ruleRegionInLayer; for (int i = 0; i < layers.size(); ++i) { Layer *layer = layers.at(i); QRegion appliedPlace; if (TileLayer *tileLayer = layer->asTileLayer()) appliedPlace = tileLayer->region(); else if (ObjectGroup *objectGroup = layer->asObjectGroup()) appliedPlace = tileRegionOfObjectGroup(objectGroup); else continue; ruleRegionInLayer.append(appliedPlace.intersected(ruleOutputRegion)); if (appliedRegions.at(i).intersects(ruleRegionInLayer.at(i).translated(x, y))) { missmatch = true; break; } } if (missmatch) continue; copyMapRegion(ruleOutputRegion, QPoint(x, y), translationTable); ret = ret.united(rbr.translated(QPoint(x, y))); for (int i = 0; i < translationTable.size(); ++i) appliedRegions[i] += ruleRegionInLayer[i].translated(x, y); } } return ret; } /** * Returns a list of all cells which can be found within all tile layers * within the given region. */ static QVector cellsInRegion(const QVector &list, const QRegion &r) { QVector cells; for (const TileLayer *tilelayer : list) { foreach (const QRect &rect, r.rects()) { for (int x = rect.left(); x <= rect.right(); ++x) { for (int y = rect.top(); y <= rect.bottom(); ++y) { const Cell &cell = tilelayer->cellAt(x, y); if (!cells.contains(cell)) cells.append(cell); } } } } return cells; } /** * This function is one of the core functions for understanding the * automapping. * In this function a certain region (of the set layer) is compared to * several other layers (ruleSet and ruleNotSet). * This comparison will determine if a rule of automapping matches, * so if this rule is applied at this region given * by a QRegion and Offset given by a QPoint. * * This compares the tile layer setLayer to several others given * in the QList listYes (ruleSet) and OList listNo (ruleNotSet). * The tile layer setLayer is examined at QRegion ruleRegion + offset * The tile layers within listYes and listNo are examined at QRegion ruleRegion. * * Basically all matches between setLayer and a layer of listYes are considered * good, while all matches between setLayer and listNo are considered bad and * lead to canceling the comparison, returning false. * * The comparison is done for each position within the QRegion ruleRegion. * If all positions of the region are considered "good" return true. * * Now there are several cases to distinguish: * - both listYes and listNo are empty: * This should not happen, because with that configuration, absolutely * no condition is given. * return false, assuming this is an errornous rule being applied * * - both listYes and listNo are not empty: * When comparing a tile at a certain position of tile layer setLayer * to all available tiles in listYes, there must be at least * one layer, in which there is a match of tiles of setLayer and * listYes to consider this position good. * In listNo there must not be a match to consider this position * good. * If there are no tiles within all available tiles within all layers * of one list, all tiles in setLayer are considered good, * while inspecting this list. * All available tiles are all tiles within the whole rule region in * all tile layers of the list. * * - either of both lists are not empty * When comparing a certain position of tile layer setLayer * to all Tiles at the corresponding position this can happen: * A tile of setLayer matches a tile of a layer in the list. Then this * is considered as good, if the layer is from the listYes. * Otherwise it is considered bad. * * Exception, when having only the listYes: * if at the examined position there are no tiles within all Layers * of the listYes, all tiles except all used tiles within * the layers of that list are considered good. * * This exception was added to have a better functionality * (need of less layers.) * It was not added to the case, when having only listNo layers to * avoid total symmetry between those lists. * * If all positions are considered good, return true. * return false otherwise. * * @return bool, if the tile layer matches the given list of layers. */ static bool compareLayerTo(const TileLayer *setLayer, const QVector &listYes, const QVector &listNo, const QRegion &ruleRegion, const QPoint &offset) { if (listYes.isEmpty() && listNo.isEmpty()) return false; QVector cells; if (listNo.isEmpty()) cells = cellsInRegion(listYes, ruleRegion); foreach (const QRect &rect, ruleRegion.rects()) { for (int x = rect.left(); x <= rect.right(); ++x) { for (int y = rect.top(); y <= rect.bottom(); ++y) { // this is only used in the case where only one list has layers // it is needed for the exception mentioned above bool ruleDefinedListYes = false; bool matchListYes = false; bool matchListNo = false; if (!setLayer->contains(x + offset.x(), y + offset.y())) { foreach (const TileLayer *comparedTileLayer, listYes) { if (!comparedTileLayer->contains(x, y)) return false; const Cell &c2 = comparedTileLayer->cellAt(x, y); if (!c2.isEmpty()) return false; } continue; } const Cell &c1 = setLayer->cellAt(x + offset.x(), y + offset.y()); // ruleDefined will be set when there is a tile in at least // one layer. if there is a tile in at least one layer, only // the given tiles in the different listYes layers are valid. // if there is given no tile at all in the listYes layers, // consider all tiles valid. for (const TileLayer *comparedTileLayer : listYes) { if (!comparedTileLayer->contains(x, y)) return false; const Cell &c2 = comparedTileLayer->cellAt(x, y); if (!c2.isEmpty()) ruleDefinedListYes = true; if (!c2.isEmpty() && c1 == c2) matchListYes = true; } for (const TileLayer *comparedTileLayer : listNo) { if (!comparedTileLayer->contains(x, y)) return false; const Cell &c2 = comparedTileLayer->cellAt(x, y); if (!c2.isEmpty() && c1 == c2) matchListNo = true; } // when there are only layers in the listNo // check only if these layers are unmatched // no need to check explicitly the exception in this case. if (listYes.isEmpty()) { if (matchListNo) return false; else continue; } // when there are only layers in the listYes // check if these layers are matched, or if the exception works if (listNo.isEmpty()) { if (matchListYes) continue; if (!ruleDefinedListYes && !cells.contains(c1)) continue; return false; } // there are layers in both lists: // no need to consider ruleDefinedListXXX if ((matchListYes || !ruleDefinedListYes) && !matchListNo) continue; else return false; } } } return true; } void AutoMapper::copyMapRegion(const QRegion ®ion, QPoint offset, const RuleOutput &layerTranslation) { for (auto it = layerTranslation.begin(), end = layerTranslation.end(); it != end; ++it) { Layer *from = it.key(); Layer *to = mMapWork->layerAt(it.value()); foreach (const QRect &rect, region.rects()) { if (TileLayer *fromTileLayer = from->asTileLayer()) { TileLayer *toTileLayer = to->asTileLayer(); Q_ASSERT(toTileLayer); //TODO check this before in prepareAutomap or such! copyTileRegion(fromTileLayer, rect.x(), rect.y(), rect.width(), rect.height(), toTileLayer, rect.x() + offset.x(), rect.y() + offset.y()); } else if (ObjectGroup *fromObjectGroup = from->asObjectGroup()) { ObjectGroup *toObjectGroup = to->asObjectGroup(); copyObjectRegion(fromObjectGroup, rect.x(), rect.y(), rect.width(), rect.height(), toObjectGroup, rect.x() + offset.x(), rect.y() + offset.y()); } else { Q_ASSERT(false); } } // Copy any custom properties set on the output layer if (!from->properties().isEmpty()) { Properties mergedProperties = to->properties(); mergedProperties.merge(from->properties()); if (mergedProperties != to->properties()) { QUndoStack *undoStack = mMapDocument->undoStack(); undoStack->push(new ChangeProperties(mMapDocument, QString(), to, mergedProperties)); } } } } void AutoMapper::copyTileRegion(const TileLayer *srcLayer, int srcX, int srcY, int width, int height, TileLayer *dstLayer, int dstX, int dstY) { const int startX = qMax(dstX, 0); const int startY = qMax(dstY, 0); const int endX = qMin(dstX + width, dstLayer->width()); const int endY = qMin(dstY + height, dstLayer->height()); const int offsetX = srcX - dstX; const int offsetY = srcY - dstY; for (int x = startX; x < endX; ++x) { for (int y = startY; y < endY; ++y) { const Cell &cell = srcLayer->cellAt(x + offsetX, y + offsetY); if (!cell.isEmpty()) { // this is without graphics update, it's done afterwards for all dstLayer->setCell(x, y, cell); } } } } void AutoMapper::copyObjectRegion(const ObjectGroup *srcLayer, int srcX, int srcY, int width, int height, ObjectGroup *dstLayer, int dstX, int dstY) { QUndoStack *undo = mMapDocument->undoStack(); const QRectF rect = QRectF(srcX, srcY, width, height); const QRectF pixelRect = mMapDocument->renderer()->tileToPixelCoords(rect); const QList objects = objectsInRegion(srcLayer, pixelRect.toAlignedRect()); QPointF pixelOffset = mMapDocument->renderer()->tileToPixelCoords(dstX, dstY); pixelOffset -= pixelRect.topLeft(); for (MapObject *obj : objects) { MapObject *clone = obj->clone(); clone->resetId(); clone->setX(clone->x() + pixelOffset.x()); clone->setY(clone->y() + pixelOffset.y()); undo->push(new AddMapObject(mMapDocument, dstLayer, clone)); } } void AutoMapper::cleanAll() { cleanTilesets(); cleanTileLayers(); } void AutoMapper::cleanTilesets() { QUndoStack *undoStack = mMapDocument->undoStack(); const auto &addedTilesets = mAddedTilesets; for (const SharedTileset &tileset : addedTilesets) { if (mMapWork->isTilesetUsed(tileset.data())) continue; const int index = mMapWork->indexOfTileset(tileset); if (index == -1) continue; undoStack->push(new RemoveTileset(mMapDocument, index)); } mAddedTilesets.clear(); } void AutoMapper::cleanTileLayers() { QUndoStack *undoStack = mMapDocument->undoStack(); const auto &addedLayers = mAddedLayers; for (Layer *layer : addedLayers) { if (!layer->isEmpty()) continue; const int index = layer->siblingIndex(); GroupLayer *parentLayer = layer->parentLayer(); undoStack->push(new RemoveLayer(mMapDocument, index, parentLayer)); } mAddedLayers.clear(); } void AutoMapper::cleanUpRulesMap() { cleanTilesets(); TilesetManager *tilesetManager = TilesetManager::instance(); tilesetManager->removeReferences(mMapRules->tilesets()); delete mMapRules; mMapRules = nullptr; cleanUpRuleMapLayers(); mRulesInput.clear(); mRulesOutput.clear(); } void AutoMapper::cleanUpRuleMapLayers() { cleanTileLayers(); mLayerList.clear(); // do not delete these, they are owned by the rules map mLayerInputRegions = nullptr; mLayerOutputRegions = nullptr; mInputRules.clear(); } tiled-1.0.3/src/tiled/automapper.h000066400000000000000000000252641315121121300170310ustar00rootroot00000000000000/* * automapper.h * Copyright 2010-2012, Stefan Beller, stefanbeller@googlemail.com * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "tileset.h" #include #include #include #include #include #include namespace Tiled { class Layer; class Map; class MapObject; class ObjectGroup; class TileLayer; namespace Internal { class MapDocument; class InputConditions { public: QVector listYes; // "input" QVector listNo; // "inputnot" }; // Maps layer names to their conditions typedef QMap InputIndex; // Maps an index to a group of input layers class InputLayers : public QMap { public: QSet names; // all names }; class RuleOutput : public QMap { public: QString index; }; /** * This class does all the work for the automapping feature. * basically it can do the following: * - check the rules map for rules and store them * - compare TileLayers (i. e. check if/where a certain rule must be applied) * - copy regions of Maps (multiple Layers, the layerlist is a * lookup-table for matching the Layers) */ class AutoMapper : public QObject { Q_OBJECT public: /** * Constructs an AutoMapper. * All data structures, which only rely on the rules map are setup * here. * * @param workingDocument: the map to work on. * @param rules: The rule map which should be used for automapping. The * AutoMapper takes ownership of this map. * @param rulePath: The filepath to the rule map. */ AutoMapper(MapDocument *workingDocument, Map *rules, const QString &rulePath); ~AutoMapper(); /** * Checks if the passed \a ruleLayerName is used in this instance * of Automapper. */ bool ruleLayerNameUsed(QString ruleLayerName) const; /** * Call prepareLoad first! Returns a set of strings describing the tile * layers, which could be touched considering the given layers of the * rule map. */ QSet getTouchedTileLayers() const; /** * This needs to be called directly before the autoMap call. * It sets up some data structures which change rapidly, so it is quite * painful to keep these data structures up to date all time. (indices of * layers of the working map) */ bool prepareAutoMap(); /** * Here is done all the automapping. */ void autoMap(QRegion *where); /** * This cleans all data structures, which are setup via prepareAutoMap, * so the auto mapper becomes ready for its next automatic mapping. */ void cleanAll(); /** * Contains all errors until operation was canceled. * The errorlist is cleared within prepareLoad and prepareAutoMap. */ QString errorString() const { return mError; } /** * Contains all warnings which occur at loading a rules map or while * automapping. * The errorlist is cleared within prepareLoad and prepareAutoMap. */ QString warningString() const { return mWarning; } private: /** * Reads the map properties of the rulesmap. * @return returns true when anything is ok, false when errors occurred. */ bool setupRuleMapProperties(); void cleanUpRulesMap(); /** * Searches the rules layer for regions and stores these in \a rules. * @return returns true when anything is ok, false when errors occurred. */ bool setupRuleList(); /** * Sets up the layers in the rules map, which are used for automapping. * The layers are detected and put in the internal data structures * @return returns true when anything is ok, false when errors occurred. */ bool setupRuleMapTileLayers(); /** * Checks if all needed layers in the working map are there. * If not, add them in the correct order. */ bool setupMissingLayers(); /** * Checks if the layers setup as in setupRuleMapLayers are still right. * If it's not right, correct them. * @return returns true if everything went fine. false is returned when * no set layer was found */ bool setupCorrectIndexes(); /** * sets up the tilesets which are used in automapping. * @return returns true when anything is ok, false when errors occurred. */ bool setupTilesets(); /** * Returns the conjunction of all regions of all setlayers. */ QRegion getSetLayersRegion() const; /** * This copies all Tiles from TileLayer src to TileLayer dst * * In src the Tiles are taken from the rectangle given by * src_x, src_y, width and height. * In dst they get copied to a rectangle given by * dst_x, dst_y, width, height . * if there is no tile in src TileLayer, there will nothing be copied, * so the maybe existing tile in dst will not be overwritten. * */ void copyTileRegion(const TileLayer *src_lr, int src_x, int src_y, int width, int height, TileLayer *dst_lr, int dst_x, int dst_y); /** * This copies all objects from the \a src_lr ObjectGroup to the \a dst_lr * in the given rectangle. * * The rectangle is described by the upper left corner \a src_x \a src_y * and its \a width and \a height. The parameter \a dst_x and \a dst_y * offset the copied objects in the destination object group. */ void copyObjectRegion(const ObjectGroup *src_lr, int src_x, int src_y, int width, int height, ObjectGroup *dst_lr, int dst_x, int dst_y); /** * This copies multiple TileLayers from one map to another. * Only the region \a region is considered for copying. * In the destination it will come to the region translated by Offset. * The parameter \a LayerTranslation is a map of which layers of the rulesmap * should get copied into which layers of the working map. */ void copyMapRegion(const QRegion ®ion, QPoint Offset, const RuleOutput &LayerTranslation); /** * This goes through all the positions of the mMapWork and checks if * there fits the rule given by the region in mMapRuleSet. * if there is a match all Layers are copied to mMapWork. * @param ruleIndex: the region which should be compared to all positions * of mMapWork will be looked up in mRulesInput and mRulesOutput * @return where: an rectangle where the rule actually got applied */ QRect applyRule(const int ruleIndex, const QRect &where); /** * Cleans up the data structures filled by setupRuleMapLayers(), * so the next rule can be processed. */ void cleanUpRuleMapLayers(); /** * Cleans up the data structures filled by setupTilesets(), * so the next rule can be processed. */ void cleanTilesets(); /** * Cleans up the added tile layers setup by setupMissingLayers(), * so we have a minimal addition of tile layers by the automapping. */ void cleanTileLayers(); /** * where to work in */ MapDocument *mMapDocument; /** * the same as mMapDocument->map() */ Map *mMapWork; /** * map containing the rules, usually different than mMapWork */ Map *mMapRules; /** * This contains all added tilesets as pointers. * if rules use Tilesets which are not in the mMapWork they are added. * keep track of them, because we need to delete them afterwards, * when they still are unused * they will be added while setupTilesets(). */ QVector mAddedTilesets; /** * description see: mAddedTilesets */ QVector mAddedLayers; /** * Points to the tilelayer, which defines the input regions. */ TileLayer *mLayerInputRegions; /** * Points to the tilelayer, which defines the output regions. */ TileLayer *mLayerOutputRegions; /** * Contains all tilelayer pointers, which names begin with input* * It is sorted by index and name */ InputLayers mInputRules; /** * List of Regions in mMapRules to know where the input rules are */ QVector mRulesInput; /** * List of regions in mMapRules to know where the output of a * rule is. * mRulesOutput[i] is the output of that rule, * which has the input at mRulesInput[i], meaning that mRulesInput * and mRulesOutput must match with the indexes. */ QVector mRulesOutput; /** * The inner set with layers to indexes is needed for translating * tile layers from mMapRules to mMapWork. * * The key is the pointer to the layer in the rulemap. The * pointer to the layer within the working map is not hardwired, but the * position in the layerlist, where it was found the last time. * This loosely bound pointer ensures we will get the right layer, since we * need to check before anyway, and it is still fast. * * The list is used to hold different translation tables * => one of the tables is chosen by chance, so randomness is available */ QVector mLayerList; /** * store the name of the processed rules file, to have detailed * error messages available */ QString mRulePath; /** * determines if all tiles in all touched layers should be deleted first. */ bool mDeleteTiles; /** * This variable determines, how many overlapping tiles should be used. * The bigger the more area is remapped at an automapping operation. * This can lead to higher latency, but provides a better behavior on * interactive automapping. * It defaults to zero. */ int mAutoMappingRadius; /** * Determines if a rule is allowed to overlap itself. */ bool mNoOverlappingRules; QSet mTouchedTileLayers; QSet mTouchedObjectGroups; QString mError; QString mWarning; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/automapperwrapper.cpp000066400000000000000000000077531315121121300207700ustar00rootroot00000000000000/* * automapperwrapper.cpp * Copyright 2010-2011, Stefan Beller, stefanbeller@googlemail.com * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "automapperwrapper.h" #include "map.h" #include "mapdocument.h" #include "tile.h" #include "tilelayer.h" using namespace Tiled; using namespace Tiled::Internal; AutoMapperWrapper::AutoMapperWrapper(MapDocument *mapDocument, QVector autoMapper, QRegion *where) { mMapDocument = mapDocument; Map *map = mMapDocument->map(); QSet touchedLayers; int index = 0; while (index < autoMapper.size()) { AutoMapper *a = autoMapper.at(index); if (a->prepareAutoMap()) { touchedLayers |= a->getTouchedTileLayers(); index++; } else { autoMapper.remove(index); } } foreach (const QString &layerName, touchedLayers) { const int layerIndex = map->indexOfLayer(layerName); Q_ASSERT(layerIndex != -1); mLayersBefore.append(static_cast(map->layerAt(layerIndex)->clone())); } for (AutoMapper *a : autoMapper) a->autoMap(where); int beforeIndex = 0; foreach (const QString &layerName, touchedLayers) { const int layerIndex = map->indexOfLayer(layerName); // layer index exists, because AutoMapper is still alive, don't check Q_ASSERT(layerIndex != -1); TileLayer *before = mLayersBefore.at(beforeIndex); TileLayer *after = static_cast(map->layerAt(layerIndex)); if (before->drawMargins() != after->drawMargins()) emit mMapDocument->tileLayerDrawMarginsChanged(after); // reduce memory usage by saving only diffs QRect diffRegion = before->computeDiffRegion(after).boundingRect(); TileLayer *before1 = before->copy(diffRegion); TileLayer *after1 = after->copy(diffRegion); before1->setPosition(diffRegion.topLeft()); after1->setPosition(diffRegion.topLeft()); before1->setName(before->name()); after1->setName(after->name()); mLayersBefore.replace(beforeIndex, before1); mLayersAfter.append(after1); delete before; ++beforeIndex; } for (AutoMapper *a : autoMapper) a->cleanAll(); } AutoMapperWrapper::~AutoMapperWrapper() { qDeleteAll(mLayersAfter); qDeleteAll(mLayersBefore); } void AutoMapperWrapper::undo() { Map *map = mMapDocument->map(); for (TileLayer *layer : mLayersBefore) { const int layerIndex = map->indexOfLayer(layer->name()); if (layerIndex != -1) patchLayer(layerIndex, layer); } } void AutoMapperWrapper::redo() { Map *map = mMapDocument->map(); for (TileLayer *layer : mLayersAfter) { const int layerIndex = map->indexOfLayer(layer->name()); if (layerIndex != -1) patchLayer(layerIndex, layer); } } void AutoMapperWrapper::patchLayer(int layerIndex, TileLayer *layer) { Map *map = mMapDocument->map(); QRect b = layer->bounds(); Q_ASSERT(map->layerAt(layerIndex)->asTileLayer()); TileLayer *t = static_cast(map->layerAt(layerIndex)); t->setCells(b.left() - t->x(), b.top() - t->y(), layer, b.translated(-t->position())); emit mMapDocument->regionChanged(b, t); } tiled-1.0.3/src/tiled/automapperwrapper.h000066400000000000000000000032341315121121300204230ustar00rootroot00000000000000/* * automapperwrapper.h * Copyright 2010-2011, Stefan Beller, stefanbeller@googlemail.com * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "automapper.h" #include #include namespace Tiled { namespace Internal { class MapDocument; /** * This is a wrapper class for the AutoMapper class. * Here in this class only undo/redo functionality all rulemaps * is provided. * This class will take a snapshot of the layers before and after the * automapping is done. In between instances of AutoMapper are doing the work. */ class AutoMapperWrapper : public QUndoCommand { public: AutoMapperWrapper(MapDocument *mapDocument, QVector autoMapper, QRegion *where); ~AutoMapperWrapper(); void undo() override; void redo() override; private: void patchLayer(int layerIndex, TileLayer *layer); MapDocument *mMapDocument; QVector mLayersAfter; QVector mLayersBefore; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/automappingmanager.cpp000066400000000000000000000135211315121121300210570ustar00rootroot00000000000000/* * automappingmanager.cpp * Copyright 2010-2011, Stefan Beller, stefanbeller@googlemail.com * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "automappingmanager.h" #include "automapperwrapper.h" #include "map.h" #include "mapdocument.h" #include "tilelayer.h" #include "tmxmapformat.h" #include "preferences.h" #include #include #include using namespace Tiled; using namespace Tiled::Internal; AutomappingManager::AutomappingManager(QObject *parent) : QObject(parent) , mMapDocument(nullptr) , mLoaded(false) { } AutomappingManager::~AutomappingManager() { cleanUp(); } void AutomappingManager::autoMap() { if (!mMapDocument) return; Map *map = mMapDocument->map(); int w = map->width(); int h = map->height(); autoMapInternal(QRect(0, 0, w, h), nullptr); } void AutomappingManager::autoMap(const QRegion &where, Layer *touchedLayer) { if (Preferences::instance()->automappingDrawing()) autoMapInternal(where, touchedLayer); } void AutomappingManager::autoMapInternal(const QRegion &where, Layer *touchedLayer) { mError.clear(); mWarning.clear(); if (!mMapDocument) return; const bool automatic = touchedLayer != nullptr; if (!mLoaded) { const QString mapPath = QFileInfo(mMapDocument->fileName()).path(); const QString rulesFileName = mapPath + QLatin1String("/rules.txt"); if (loadFile(rulesFileName)) { mLoaded = true; } else { emit errorsOccurred(automatic); return; } } QVector passedAutoMappers; if (touchedLayer) { foreach (AutoMapper *a, mAutoMappers) { if (a->ruleLayerNameUsed(touchedLayer->name())) passedAutoMappers.append(a); } } else { passedAutoMappers = mAutoMappers; } if (!passedAutoMappers.isEmpty()) { // use a copy of the region, so each automapper can manipulate it and the // following automappers do see the impact QRegion region(where); QUndoStack *undoStack = mMapDocument->undoStack(); undoStack->beginMacro(tr("Apply AutoMap rules")); AutoMapperWrapper *aw = new AutoMapperWrapper(mMapDocument, passedAutoMappers, ®ion); undoStack->push(aw); undoStack->endMacro(); } foreach (AutoMapper *automapper, mAutoMappers) { mWarning += automapper->warningString(); mError += automapper->errorString(); } if (!mWarning.isEmpty()) emit warningsOccurred(automatic); if (!mError.isEmpty()) emit errorsOccurred(automatic); } bool AutomappingManager::loadFile(const QString &filePath) { bool ret = true; const QString absPath = QFileInfo(filePath).path(); QFile rulesFile(filePath); if (!rulesFile.exists()) { mError += tr("No rules file found at:\n%1").arg(filePath) + QLatin1Char('\n'); return false; } if (!rulesFile.open(QIODevice::ReadOnly | QIODevice::Text)) { mError += tr("Error opening rules file:\n%1").arg(filePath) + QLatin1Char('\n'); return false; } QTextStream in(&rulesFile); QString line = in.readLine(); for (; !line.isNull(); line = in.readLine()) { QString rulePath = line.trimmed(); if (rulePath.isEmpty() || rulePath.startsWith(QLatin1Char('#')) || rulePath.startsWith(QLatin1String("//"))) continue; if (QFileInfo(rulePath).isRelative()) rulePath = absPath + QLatin1Char('/') + rulePath; if (!QFileInfo(rulePath).exists()) { mError += tr("File not found:\n%1").arg(rulePath) + QLatin1Char('\n'); ret = false; continue; } if (rulePath.endsWith(QLatin1String(".tmx"), Qt::CaseInsensitive)) { TmxMapFormat tmxFormat; QScopedPointer rules(tmxFormat.read(rulePath)); if (!rules) { mError += tr("Opening rules map failed:\n%1").arg( tmxFormat.errorString()) + QLatin1Char('\n'); ret = false; continue; } AutoMapper *autoMapper = new AutoMapper(mMapDocument, rules.take(), rulePath); mWarning += autoMapper->warningString(); const QString error = autoMapper->errorString(); if (error.isEmpty()) { mAutoMappers.append(autoMapper); } else { mError += error; delete autoMapper; } } if (rulePath.endsWith(QLatin1String(".txt"), Qt::CaseInsensitive)) { if (!loadFile(rulePath)) ret = false; } } return ret; } void AutomappingManager::setMapDocument(MapDocument *mapDocument) { cleanUp(); if (mMapDocument) mMapDocument->disconnect(this); mMapDocument = mapDocument; if (mMapDocument) { connect(mMapDocument, SIGNAL(regionEdited(QRegion,Layer*)), this, SLOT(autoMap(QRegion,Layer*))); } mLoaded = false; } void AutomappingManager::cleanUp() { qDeleteAll(mAutoMappers); mAutoMappers.clear(); } tiled-1.0.3/src/tiled/automappingmanager.h000066400000000000000000000067301315121121300205300ustar00rootroot00000000000000/* * automappingmanager.h * Copyright 2010-2011, Stefan Beller, stefanbeller@googlemail.com * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include #include #include namespace Tiled { class Layer; namespace Internal { class AutoMapper; class MapDocument; /** * This class is a superior class to the AutoMapper and AutoMapperWrapper class. * It uses these classes to do the whole automapping process. */ class AutomappingManager : public QObject { Q_OBJECT public: /** * Constructor. */ AutomappingManager(QObject *parent = nullptr); ~AutomappingManager(); void setMapDocument(MapDocument *mapDocument); QString errorString() const { return mError; } QString warningString() const { return mWarning; } signals: /** * This signal is emitted after automapping was done and an error occurred. */ void errorsOccurred(bool automatic); /** * This signal is emitted after automapping was done and a warning occurred. */ void warningsOccurred(bool automatic); public slots: /** * This triggers an automapping on the whole current map document. */ void autoMap(); private slots: void autoMap(const QRegion &where, Layer *touchedLayer); private: Q_DISABLE_COPY(AutomappingManager) /** * This function parses a rules file. * For each path which is a rule, (file extension is tmx) an AutoMapper * object is setup. * * If a file extension is txt, this file will be opened and searched for * rules again. * * @return if the loading was successful: return true if it succeeded. */ bool loadFile(const QString &filePath); /** * Applies automapping to the Region \a where, considering only layer * \a touchedLayer has changed. * There will only those Automappers be used which have a rule layer * touching the \a touchedLayer * If layer is 0, all Automappers are used. */ void autoMapInternal(const QRegion &where, Layer *touchedLayer); /** * deletes all its data structures */ void cleanUp(); /** * The current map document. */ MapDocument *mMapDocument; /** * For each new file of rules a new AutoMapper is setup. In this vector we * can store all of the AutoMappers in order. */ QVector mAutoMappers; /** * This tells you if the rules for the current map document were already * loaded. */ bool mLoaded; /** * Contains all errors which occurred until canceling. * If mError is not empty, no serious result can be expected. */ QString mError; /** * Contains all strings, which try to explain unusual and unexpected * behavior. */ QString mWarning; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/automappingutils.cpp000066400000000000000000000072311315121121300206060ustar00rootroot00000000000000/* * automappingutils.cpp * Copyright 2012, Stefan Beller, stefanbeller@googlemail.com * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "automappingutils.h" #include "addremovemapobject.h" #include "mapdocument.h" #include "mapobject.h" #include "maprenderer.h" #include "objectgroup.h" #include namespace Tiled { namespace Internal { void eraseRegionObjectGroup(MapDocument *mapDocument, ObjectGroup *layer, const QRegion &where) { QUndoStack *undo = mapDocument->undoStack(); const auto objects = layer->objects(); for (MapObject *obj : objects) { // TODO: we are checking bounds, which is only correct for rectangles and // tile objects. polygons and polylines are not covered correctly by this // erase method (we are in fact deleting too many objects) // TODO2: toAlignedRect may even break rects. // Convert the boundary of the object into tile space const QRectF objBounds = obj->boundsUseTile(); QPointF tl = mapDocument->renderer()->pixelToTileCoords(objBounds.topLeft()); QPointF tr = mapDocument->renderer()->pixelToTileCoords(objBounds.topRight()); QPointF br = mapDocument->renderer()->pixelToTileCoords(objBounds.bottomRight()); QPointF bl = mapDocument->renderer()->pixelToTileCoords(objBounds.bottomLeft()); QRectF objInTileSpace; objInTileSpace.setTopLeft(tl); objInTileSpace.setTopRight(tr); objInTileSpace.setBottomRight(br); objInTileSpace.setBottomLeft(bl); const QRect objAlignedRect = objInTileSpace.toAlignedRect(); if (where.intersects(objAlignedRect)) undo->push(new RemoveMapObject(mapDocument, obj)); } } QRegion tileRegionOfObjectGroup(const ObjectGroup *layer) { QRegion ret; for (MapObject *obj : layer->objects()) { // TODO: we are using bounds, which is only correct for rectangles and // tile objects. polygons and polylines are not probably covering less // tiles. ret += obj->bounds().toAlignedRect(); } return ret; } const QList objectsInRegion(const ObjectGroup *layer, const QRegion &where) { QList ret; for (MapObject *obj : layer->objects()) { // TODO: we are checking bounds, which is only correct for rectangles and // tile objects. polygons and polylines are not covered correctly by this // erase method (we are in fact deleting too many objects) // TODO2: toAlignedRect may even break rects. const QRect rect = obj->boundsUseTile().toAlignedRect(); // QRegion::intersects() returns false for empty regions even if they are // contained within the region, so we also check for containment of the // top left to include the case of zero size objects. if (where.intersects(rect) || where.contains(rect.topLeft())) ret += obj; } return ret; } } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/automappingutils.h000066400000000000000000000024171315121121300202540ustar00rootroot00000000000000/* * automappingutils.h * Copyright 2012, Stefan Beller, stefanbeller@googlemail.com * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include namespace Tiled { class MapObject; class ObjectGroup; namespace Internal { class MapDocument; const QList objectsInRegion(const ObjectGroup *layer, const QRegion &where); void eraseRegionObjectGroup(MapDocument *mapDocument, ObjectGroup *layer, const QRegion &where); QRegion tileRegionOfObjectGroup(const ObjectGroup *layer); } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/autoupdater.cpp000066400000000000000000000016731315121121300175420ustar00rootroot00000000000000/* * autoupdater.cpp * Copyright 2016, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "autoupdater.h" AutoUpdater *AutoUpdater::sInstance = nullptr; AutoUpdater::AutoUpdater() { sInstance = this; } AutoUpdater::~AutoUpdater() { sInstance = nullptr; } tiled-1.0.3/src/tiled/autoupdater.h000066400000000000000000000022531315121121300172020ustar00rootroot00000000000000/* * autoupdater.h * Copyright 2016, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include class AutoUpdater { public: AutoUpdater(); virtual ~AutoUpdater(); virtual void checkForUpdates() = 0; virtual void setAutomaticallyChecksForUpdates(bool on) = 0; virtual bool automaticallyChecksForUpdates() = 0; virtual QDateTime lastUpdateCheckDate() = 0; static AutoUpdater *instance() { return sInstance; } private: static AutoUpdater *sInstance; }; tiled-1.0.3/src/tiled/brokenlinks.cpp000066400000000000000000000516261315121121300175310ustar00rootroot00000000000000/* * brokenlinks.cpp * Copyright 2015, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "brokenlinks.h" #include "changetileimagesource.h" #include "documentmanager.h" #include "map.h" #include "mapdocument.h" #include "preferences.h" #include "replacetileset.h" #include "tmxmapformat.h" #include "tile.h" #include "tilesetchanges.h" #include "tilesetdocument.h" #include "tilesetmanager.h" #include "utils.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Tiled { namespace Internal { QString BrokenLink::filePath() const { switch (type) { case TilesetImageSource: return _tileset->imageSource(); case MapTilesetReference: return _tileset->fileName(); case TilesetTileImageSource: return _tile->imageSource(); } return QString(); } Tileset *BrokenLink::tileset() const { switch (type) { case TilesetImageSource: case MapTilesetReference: return _tileset; case TilesetTileImageSource: return _tile->tileset(); } return nullptr; } BrokenLinksModel::BrokenLinksModel(QObject *parent) : QAbstractListModel(parent) , mDocument(nullptr) { } void BrokenLinksModel::setDocument(Document *document) { if (auto mapDocument = qobject_cast(mDocument)) { mapDocument->disconnect(this); for (const SharedTileset &tileset : mapDocument->map()->tilesets()) disconnectFromTileset(tileset); } else if (auto tilesetDocument = qobject_cast(mDocument)) { disconnectFromTileset(tilesetDocument->tileset()); } mDocument = document; refresh(); if (mDocument) { if (auto mapDocument = qobject_cast(mDocument)) { connect(mapDocument, &MapDocument::tilesetReplaced, this, &BrokenLinksModel::tilesetReplaced); connect(mapDocument, &MapDocument::tilesetAdded, this, &BrokenLinksModel::tilesetAdded); connect(mapDocument, &MapDocument::tilesetRemoved, this, &BrokenLinksModel::tilesetRemoved); for (const SharedTileset &tileset : mapDocument->map()->tilesets()) connectToTileset(tileset); } else if (auto tilesetDocument = qobject_cast(mDocument)) { connectToTileset(tilesetDocument->tileset()); } connect(mDocument, &Document::ignoreBrokenLinksChanged, this, &BrokenLinksModel::refresh); } } void BrokenLinksModel::refresh() { bool brokenLinksBefore = hasBrokenLinks(); beginResetModel(); mBrokenLinks.clear(); if (mDocument && !mDocument->ignoreBrokenLinks()) { auto processTileset = [this](const SharedTileset &tileset) { if (tileset->isCollection()) { for (Tile *tile : tileset->tiles()) { if (!tile->imageSource().isEmpty() && !tile->imageLoaded()) { BrokenLink link; link.type = TilesetTileImageSource; link._tile = tile; mBrokenLinks.append(link); } } } else { if (!tileset->imageLoaded()) { BrokenLink link; link.type = TilesetImageSource; link._tileset = tileset.data(); mBrokenLinks.append(link); } } }; if (auto mapDocument = qobject_cast(mDocument)) { for (const SharedTileset &tileset : mapDocument->map()->tilesets()) { if (!tileset->fileName().isEmpty() && !tileset->loaded()) { BrokenLink link; link.type = MapTilesetReference; link._tileset = tileset.data(); mBrokenLinks.append(link); } else { processTileset(tileset); } } } else if (auto tilesetDocument = qobject_cast(mDocument)) { processTileset(tilesetDocument->tileset()); } } endResetModel(); bool brokenLinksAfter = hasBrokenLinks(); if (brokenLinksBefore != brokenLinksAfter) emit hasBrokenLinksChanged(brokenLinksAfter); } int BrokenLinksModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : mBrokenLinks.count(); } int BrokenLinksModel::columnCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : 3; // file name | path | type } QVariant BrokenLinksModel::data(const QModelIndex &index, int role) const { const BrokenLink &link = mBrokenLinks.at(index.row()); switch (role) { case Qt::DisplayRole: switch (index.column()) { case 0: return QFileInfo(link.filePath()).fileName(); case 1: return QFileInfo(link.filePath()).path(); case 2: switch (link.type) { case MapTilesetReference: return tr("Tileset"); case TilesetImageSource: return tr("Tileset image"); case TilesetTileImageSource: return tr("Tile image"); } break; } break; case Qt::DecorationRole: switch (index.column()) { case 0: // todo: status icon break; } break; } return QVariant(); } QVariant BrokenLinksModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { switch (section) { case 0: return tr("File name"); case 1: return tr("Location"); case 2: return tr("Type"); } } return QVariant(); } void BrokenLinksModel::tileImageSourceChanged(Tile *tile) { auto matchesTile = [tile](const BrokenLink &link) { return link.type == TilesetTileImageSource && link._tile == tile; }; QVector::iterator it = std::find_if(mBrokenLinks.begin(), mBrokenLinks.end(), matchesTile); if (!tile->imageSource().isEmpty() && !tile->imageLoaded()) { if (it != mBrokenLinks.end()) { int linkIndex = it - mBrokenLinks.begin(); emit dataChanged(index(linkIndex, 0), index(linkIndex, 1)); } else { refresh(); // lazy way of adding an entry for this tile } } else if (it != mBrokenLinks.end()) { removeLink(it - mBrokenLinks.begin()); } } void BrokenLinksModel::tilesetChanged(Tileset *tileset) { Q_UNUSED(tileset) // This may mean either the tileset properties changed or tiles were // added/removed from the tileset. Easiest to just refresh entirely. refresh(); } void BrokenLinksModel::tilesetAdded(int index, Tileset *tileset) { Q_UNUSED(index) connectToTileset(tileset->sharedPointer()); } void BrokenLinksModel::tilesetRemoved(Tileset *tileset) { disconnectFromTileset(tileset->sharedPointer()); } void BrokenLinksModel::tilesetReplaced(int index, Tileset *newTileset, Tileset *oldTileset) { Q_UNUSED(index) disconnectFromTileset(oldTileset->sharedPointer()); connectToTileset(newTileset->sharedPointer()); refresh(); } void BrokenLinksModel::connectToTileset(const SharedTileset &tileset) { auto tilesetDocument = DocumentManager::instance()->findTilesetDocument(tileset); if (tilesetDocument) { connect(tilesetDocument, &TilesetDocument::tileImageSourceChanged, this, &BrokenLinksModel::tileImageSourceChanged); connect(tilesetDocument, &TilesetDocument::tilesetChanged, this, &BrokenLinksModel::tilesetChanged); } } void BrokenLinksModel::disconnectFromTileset(const SharedTileset &tileset) { auto tilesetDocument = DocumentManager::instance()->findTilesetDocument(tileset->sharedPointer()); if (tilesetDocument) tilesetDocument->disconnect(this); } void BrokenLinksModel::removeLink(int index) { beginRemoveRows(QModelIndex(), index, index); mBrokenLinks.remove(index); endRemoveRows(); if (!hasBrokenLinks()) emit hasBrokenLinksChanged(false); } BrokenLinksWidget::BrokenLinksWidget(BrokenLinksModel *brokenLinksModel, QWidget *parent) : QWidget(parent) , mBrokenLinksModel(brokenLinksModel) , mTitleLabel(new QLabel(this)) , mDescriptionLabel(new QLabel(this)) , mView(new QTreeView(this)) , mButtons(new QDialogButtonBox(QDialogButtonBox::Ignore, Qt::Horizontal, this)) { mTitleLabel->setText(tr("Some files could not be found")); mDescriptionLabel->setText(tr("One or more referenced files could not be found. You can help locate them below.")); mDescriptionLabel->setWordWrap(true); mLocateButton = mButtons->addButton(tr("Locate File..."), QDialogButtonBox::ActionRole); mLocateButton->setEnabled(false); QFont font = mTitleLabel->font(); font.setBold(true); mTitleLabel->setFont(font); mProxyModel = new QSortFilterProxyModel(this); mProxyModel->setSortLocaleAware(true); mProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); mProxyModel->setSourceModel(mBrokenLinksModel); mView->setModel(mProxyModel); mView->setRootIsDecorated(false); mView->setItemsExpandable(false); mView->setUniformRowHeights(true); mView->setSortingEnabled(true); mView->sortByColumn(0, Qt::AscendingOrder); mView->setSelectionMode(QAbstractItemView::ExtendedSelection); mView->header()->setStretchLastSection(false); mView->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); mView->header()->setSectionResizeMode(1, QHeaderView::Stretch); mView->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents); QBoxLayout *layout = new QVBoxLayout; layout->addWidget(mTitleLabel); layout->addWidget(mDescriptionLabel); layout->addWidget(mView); layout->addWidget(mButtons); setLayout(layout); connect(mButtons, &QDialogButtonBox::clicked, this, &BrokenLinksWidget::clicked); connect(mView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &BrokenLinksWidget::selectionChanged); connect(mView, &QTreeView::doubleClicked, this, [this](const QModelIndex &proxyIndex) { const auto index = mProxyModel->mapToSource(proxyIndex); const BrokenLink &link = mBrokenLinksModel->brokenLink(index.row()); tryFixLink(link); }); // For some reason a model reset doesn't trigger the selectionChanged signal, // so we need to handle that explicitly. connect(brokenLinksModel, &BrokenLinksModel::modelReset, this, [this](){ selectionChanged(); }); } void BrokenLinksWidget::clicked(QAbstractButton *button) { if (button == mButtons->button(QDialogButtonBox::Ignore)) { mBrokenLinksModel->document()->setIgnoreBrokenLinks(true); } else if (button == mLocateButton) { const auto proxySelection = mView->selectionModel()->selectedRows(); if (proxySelection.isEmpty()) return; QVector links; links.reserve(proxySelection.size()); for (const QModelIndex &proxyIndex : proxySelection) { const auto index = mProxyModel->mapToSource(proxyIndex); links.append(mBrokenLinksModel->brokenLink(index.row())); } tryFixLinks(links); } } void BrokenLinksWidget::selectionChanged() { const auto selection = mView->selectionModel()->selectedRows(); mLocateButton->setEnabled(!selection.isEmpty()); bool isTileset = qobject_cast(mBrokenLinksModel->document()) != nullptr; if (!selection.isEmpty()) { const auto firstIndex = selection.first(); const BrokenLink &link = mBrokenLinksModel->brokenLink(firstIndex.row()); switch (link.type) { case Tiled::Internal::MapTilesetReference: mLocateButton->setText(tr("Locate File...")); break; case Tiled::Internal::TilesetTileImageSource: case Tiled::Internal::TilesetImageSource: if (isTileset) mLocateButton->setText(tr("Locate File...")); else mLocateButton->setText(tr("Open Tileset...")); break; } } } void BrokenLinksWidget::tryFixLinks(const QVector &links) { if (links.isEmpty()) return; if (links.size() == 1) return tryFixLink(links.first()); // If any of the links need to be fixed in a tileset, open the first such tileset and abort Document *document = mBrokenLinksModel->document(); bool editingTileset = qobject_cast(document) != nullptr; for (const BrokenLink &link : links) { if (link.type == TilesetImageSource || link.type == TilesetTileImageSource) { if (!editingTileset) { // We need to open the tileset document in order to be able to make changes to it... const SharedTileset tileset = link.tileset()->sharedPointer(); DocumentManager::instance()->openTileset(tileset); return; } } } // todo: fix caption after string freeze (and the text on the button) static QString startingLocation = QFileInfo(links.first().filePath()).path(); const QString directory = QFileDialog::getExistingDirectory(window(), tr("Locate File"), startingLocation); if (directory.isEmpty()) return; startingLocation = directory; const QDir dir(directory); const auto files = dir.entryList(QDir::Files | QDir::Readable | QDir::NoDotAndDotDot).toSet(); // See if any of the links we're looking for is located in this directory for (const BrokenLink &link : links) { const QString fileName = QFileInfo(link.filePath()).fileName(); if (files.contains(fileName)) if (!tryFixLink(link, dir.filePath(fileName))) break; } // todo: provide better feedback (like maybe a dialog showing any errors // or the number of links fixed) } void BrokenLinksWidget::tryFixLink(const BrokenLink &link) { Document *document = mBrokenLinksModel->document(); Preferences *prefs = Preferences::instance(); if (link.type == TilesetImageSource || link.type == TilesetTileImageSource) { auto tilesetDocument = qobject_cast(document); if (!tilesetDocument) { // We need to open the tileset document in order to be able to make changes to it... const SharedTileset tileset = link.tileset()->sharedPointer(); DocumentManager::instance()->openTileset(tileset); return; } QString startLocation = QFileInfo(prefs->lastPath(Preferences::ImageFile)).absolutePath(); startLocation += QLatin1Char('/'); startLocation += QFileInfo(link.filePath()).fileName(); QString newFileName = QFileDialog::getOpenFileName(window(), tr("Locate File"), startLocation, Utils::readableImageFormatsFilter()); if (newFileName.isEmpty()) return; QImageReader reader(newFileName); QImage image = reader.read(); if (image.isNull()) { QMessageBox::critical(this, tr("Error Loading Image"), reader.errorString()); return; } if (link.type == TilesetImageSource) { TilesetParameters parameters(*link._tileset); parameters.imageSource = newFileName; auto command = new ChangeTilesetParameters(tilesetDocument, parameters); tilesetDocument->undoStack()->push(command); } else { auto command = new ChangeTileImageSource(tilesetDocument, link._tile, newFileName); tilesetDocument->undoStack()->push(command); } prefs->setLastPath(Preferences::ImageFile, newFileName); } else if (link.type == MapTilesetReference) { const QString allFilesFilter = tr("All Files (*)"); QString selectedFilter = allFilesFilter; QString filter = allFilesFilter; FormatHelper helper(FileFormat::Read, filter); QString start = prefs->lastPath(Preferences::ExternalTileset); const QString fileName = QFileDialog::getOpenFileName(this, tr("Locate External Tileset"), start, helper.filter(), &selectedFilter); if (fileName.isEmpty()) return; QString error; // It could be, that we have already loaded this tileset. SharedTileset newTileset = TilesetManager::instance()->findTileset(fileName); if (!newTileset || !newTileset->loaded()) { newTileset = Tiled::readTileset(fileName, &error); if (!newTileset) { QMessageBox::critical(window(), tr("Error Reading Tileset"), error); return; } } MapDocument *mapDocument = static_cast(document); int index = mapDocument->map()->tilesets().indexOf(link._tileset->sharedPointer()); if (index != -1) document->undoStack()->push(new ReplaceTileset(mapDocument, index, newTileset)); prefs->setLastPath(Preferences::ExternalTileset, QFileInfo(fileName).path()); } } // todo: look into sharing some code between this function and the one above bool BrokenLinksWidget::tryFixLink(const BrokenLink &link, const QString &newFilePath) { Q_ASSERT(!newFilePath.isEmpty()); Document *document = mBrokenLinksModel->document(); if (link.type == TilesetImageSource || link.type == TilesetTileImageSource) { auto tilesetDocument = qobject_cast(document); Q_ASSERT(tilesetDocument); QImageReader reader(newFilePath); QImage image = reader.read(); if (image.isNull()) { QMessageBox::critical(this, tr("Error Loading Image"), reader.errorString()); return false; } if (link.type == TilesetImageSource) { TilesetParameters parameters(*link._tileset); parameters.imageSource = newFilePath; auto command = new ChangeTilesetParameters(tilesetDocument, parameters); tilesetDocument->undoStack()->push(command); } else { auto command = new ChangeTileImageSource(tilesetDocument, link._tile, newFilePath); tilesetDocument->undoStack()->push(command); } } else if (link.type == MapTilesetReference) { QString error; // It could be, that we have already loaded this tileset. SharedTileset newTileset = TilesetManager::instance()->findTileset(newFilePath); if (!newTileset || !newTileset->loaded()) { newTileset = Tiled::readTileset(newFilePath, &error); if (!newTileset) { QMessageBox::critical(window(), tr("Error Reading Tileset"), error); return false; } } MapDocument *mapDocument = static_cast(document); int index = mapDocument->map()->tilesets().indexOf(link._tileset->sharedPointer()); if (index != -1) document->undoStack()->push(new ReplaceTileset(mapDocument, index, newTileset)); } return true; } } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/brokenlinks.h000066400000000000000000000071261315121121300171720ustar00rootroot00000000000000/* * brokenlinks.h * Copyright 2015, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "tileset.h" #include #include class QAbstractButton; class QDialogButtonBox; class QItemSelection; class QLabel; class QSortFilterProxyModel; class QTreeView; namespace Tiled { class Tile; class Tileset; namespace Internal { class Document; class TilesetDocument; enum BrokenLinkType { MapTilesetReference, TilesetTileImageSource, TilesetImageSource, }; struct BrokenLink { BrokenLinkType type; union { Tileset *_tileset; Tile *_tile; }; QString filePath() const; Tileset *tileset() const; }; class BrokenLinksModel : public QAbstractListModel { Q_OBJECT Q_PROPERTY(bool hasBrokenLinks READ hasBrokenLinks NOTIFY hasBrokenLinksChanged) public: BrokenLinksModel(QObject *parent = nullptr); void setDocument(Document *document); Document *document() const; void refresh(); bool hasBrokenLinks() const; const BrokenLink &brokenLink(int index) const; int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role) const override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override; signals: void hasBrokenLinksChanged(bool hasBrokenLinks); private slots: void tileImageSourceChanged(Tile *tile); void tilesetChanged(Tileset *tileset); void tilesetAdded(int index, Tileset *tileset); void tilesetRemoved(Tileset *tileset); void tilesetReplaced(int index, Tileset *newTileset, Tileset *oldTileset); private: void connectToTileset(const SharedTileset &tileset); void disconnectFromTileset(const SharedTileset &tileset); void removeLink(int index); Document *mDocument; QVector mBrokenLinks; }; inline Document *BrokenLinksModel::document() const { return mDocument; } inline bool BrokenLinksModel::hasBrokenLinks() const { return !mBrokenLinks.isEmpty(); } inline const BrokenLink &BrokenLinksModel::brokenLink(int index) const { return mBrokenLinks.at(index); } class BrokenLinksWidget : public QWidget { Q_OBJECT public: BrokenLinksWidget(BrokenLinksModel *brokenLinksModel, QWidget *parent = nullptr); signals: void ignore(); private slots: void clicked(QAbstractButton *button); void selectionChanged(); private: void tryFixLinks(const QVector &links); void tryFixLink(const BrokenLink &link); bool tryFixLink(const BrokenLink &link, const QString &newFilePath); BrokenLinksModel *mBrokenLinksModel; QSortFilterProxyModel *mProxyModel; QLabel *mTitleLabel; QLabel *mDescriptionLabel; QTreeView *mView; QDialogButtonBox *mButtons; QAbstractButton *mLocateButton; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/brushitem.cpp000066400000000000000000000121701315121121300172010ustar00rootroot00000000000000/* * brushitem.cpp * Copyright 2008-2010, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "brushitem.h" #include "map.h" #include "mapdocument.h" #include "maprenderer.h" #include "painttilelayer.h" #include "tile.h" #include "tilelayer.h" #include #include #include #include using namespace Tiled; using namespace Tiled::Internal; BrushItem::BrushItem(): mMapDocument(nullptr) { setFlag(QGraphicsItem::ItemUsesExtendedStyleOption); } /** * Sets the map document this brush is operating on. */ void BrushItem::setMapDocument(MapDocument *mapDocument) { if (mMapDocument == mapDocument) return; mMapDocument = mapDocument; // The tiles in the stamp may no longer be valid clear(); } /** * Sets a tile layer representing this brush. When no tile layer is set, * the brush only draws the selection color. */ void BrushItem::setTileLayer(const SharedTileLayer &tileLayer) { mTileLayer = tileLayer; mRegion = tileLayer ? tileLayer->region() : QRegion(); updateBoundingRect(); update(); } /** * Sets a tile layer as well as the region that should be highlighted along * with it. This allows highlighting of areas that are not covered by tiles in * the given tile layer. */ void BrushItem::setTileLayer(const SharedTileLayer &tileLayer, const QRegion ®ion) { mTileLayer = tileLayer; mRegion = region; updateBoundingRect(); update(); } /** * Changes the position of the tile layer, if one is set. */ void BrushItem::setTileLayerPosition(const QPoint &pos) { if (!mTileLayer) return; const QPoint oldPosition(mTileLayer->x(), mTileLayer->y()); if (oldPosition == pos) return; mRegion.translate(pos - oldPosition); mTileLayer->setX(pos.x()); mTileLayer->setY(pos.y()); updateBoundingRect(); } /** * Sets the region of tiles that this brush item occupies. */ void BrushItem::setTileRegion(const QRegion ®ion) { if (mRegion == region) return; mRegion = region; updateBoundingRect(); } /** * Sets the layer offset used by the currently active layer. */ void BrushItem::setLayerOffset(const QPointF &offset) { setPos(offset); } QRectF BrushItem::boundingRect() const { return mBoundingRect; } void BrushItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) { QColor insideMapHighlight = QApplication::palette().highlight().color(); insideMapHighlight.setAlpha(64); QColor outsideMapHighlight = QColor(255, 0, 0, 64); int mapWidth = mMapDocument->map()->width(); int mapHeight = mMapDocument->map()->height(); QRegion mapRegion = QRegion(0, 0, mapWidth, mapHeight); QRegion insideMapRegion = mRegion.intersected(mapRegion); QRegion outsideMapRegion = mRegion.subtracted(mapRegion); const MapRenderer *renderer = mMapDocument->renderer(); if (mTileLayer) { const qreal opacity = painter->opacity(); painter->setOpacity(0.75); renderer->drawTileLayer(painter, mTileLayer.data(), option->exposedRect); painter->setOpacity(opacity); } renderer->drawTileSelection(painter, insideMapRegion, insideMapHighlight, option->exposedRect); renderer->drawTileSelection(painter, outsideMapRegion, outsideMapHighlight, option->exposedRect); } void BrushItem::updateBoundingRect() { prepareGeometryChange(); if (!mMapDocument) { mBoundingRect = QRectF(); return; } const QRect bounds = mRegion.boundingRect(); mBoundingRect = mMapDocument->renderer()->boundingRect(bounds); // Adjust for amount of pixels tiles extend at the top and to the right if (mTileLayer) { QSize tileSize = mMapDocument->map()->tileSize(); QMargins drawMargins = mTileLayer->drawMargins(); drawMargins.setTop(drawMargins.top() - tileSize.height()); drawMargins.setRight(drawMargins.right() - tileSize.width()); // Since we're also drawing a tile selection, we should not apply // negative margins mBoundingRect.adjust(qMin(0, -drawMargins.left()), qMin(0, -drawMargins.top()), qMax(0, drawMargins.right()), qMax(0, drawMargins.bottom())); } } tiled-1.0.3/src/tiled/brushitem.h000066400000000000000000000045431315121121300166530ustar00rootroot00000000000000/* * brushitem.h * Copyright 2008-2010, Thorbjørn Lindeijer * Copyright 2010 Stefan Beller * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "tilelayer.h" #include namespace Tiled { namespace Internal { class MapDocument; /** * This brush item is used to represent a brush in a map scene before it is * used. */ class BrushItem : public QGraphicsItem { public: BrushItem(); void setMapDocument(MapDocument *mapDocument); void clear(); void setTileLayer(const SharedTileLayer &tileLayer); void setTileLayer(const SharedTileLayer &tileLayer, const QRegion ®ion); const SharedTileLayer &tileLayer() const; void setTileLayerPosition(const QPoint &pos); void setTileRegion(const QRegion ®ion); QRegion tileRegion() const; void setLayerOffset(const QPointF &offset); // QGraphicsItem QRectF boundingRect() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; private: void updateBoundingRect(); MapDocument *mMapDocument; SharedTileLayer mTileLayer; QRegion mRegion; QRectF mBoundingRect; }; /** * Clears the tile layer and region set on this item. */ inline void BrushItem::clear() { setTileLayer(SharedTileLayer()); } /** * Returns the current tile layer. */ inline const SharedTileLayer &BrushItem::tileLayer() const { return mTileLayer; } /** * Returns the region of the current tile layer or the region that was set * using setTileRegion. */ inline QRegion BrushItem::tileRegion() const { return mRegion; } } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/bucketfilltool.cpp000066400000000000000000000254241315121121300202270ustar00rootroot00000000000000/* * bucketfilltool.cpp * Copyright 2009-2010, Jeff Bland * Copyright 2010, Thorbjørn Lindeijer * Copyright 2010, Jared Adams * Copyright 2011, Stefan Beller * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "bucketfilltool.h" #include "addremovetileset.h" #include "brushitem.h" #include "tilepainter.h" #include "tile.h" #include "mapscene.h" #include "mapdocument.h" #include "painttilelayer.h" #include using namespace Tiled; using namespace Tiled::Internal; BucketFillTool::BucketFillTool(QObject *parent) : AbstractTileTool(tr("Bucket Fill Tool"), QIcon(QLatin1String( ":images/22x22/stock-tool-bucket-fill.png")), QKeySequence(tr("F")), parent) , mIsActive(false) , mLastShiftStatus(false) , mIsRandom(false) , mLastRandomStatus(false) { } BucketFillTool::~BucketFillTool() { } void BucketFillTool::activate(MapScene *scene) { AbstractTileTool::activate(scene); mIsActive = true; tilePositionChanged(tilePosition()); } void BucketFillTool::deactivate(MapScene *scene) { AbstractTileTool::deactivate(scene); mFillRegion = QRegion(); mIsActive = false; } static void fillWithStamp(TileLayer &layer, const TileStamp &stamp, const QRegion &mask) { const QSize size = stamp.maxSize(); // Fill the entire layer with random variations of the stamp for (int y = 0; y < layer.height(); y += size.height()) { for (int x = 0; x < layer.width(); x += size.width()) { const TileStampVariation variation = stamp.randomVariation(); layer.setCells(x, y, variation.tileLayer()); } } // Erase tiles outside of the masked region. This can easily be faster than // avoiding to place tiles outside of the region in the first place. layer.erase(QRegion(0, 0, layer.width(), layer.height()) - mask); } void BucketFillTool::tilePositionChanged(const QPoint &tilePos) { // Skip filling if the stamp is empty if (mStamp.isEmpty()) return; // Make sure that a tile layer is selected TileLayer *tileLayer = currentTileLayer(); if (!tileLayer) return; bool shiftPressed = QApplication::keyboardModifiers() & Qt::ShiftModifier; bool fillRegionChanged = false; TilePainter regionComputer(mapDocument(), tileLayer); // If the stamp is a single tile, ignore it when making the region if (!shiftPressed && mStamp.variations().size() == 1) { const TileStampVariation &variation = mStamp.variations().first(); TileLayer *stampLayer = variation.tileLayer(); if (stampLayer->size() == QSize(1, 1) && stampLayer->cellAt(0, 0) == regionComputer.cellAt(tilePos)) return; } // This clears the connections so we don't get callbacks clearConnections(mapDocument()); // Optimization: we don't need to recalculate the fill area // if the new mouse position is still over the filled region // and the shift modifier hasn't changed. if (!mFillRegion.contains(tilePos) || shiftPressed != mLastShiftStatus) { // Clear overlay to make way for a new one clearOverlay(); // Cache information about how the fill region was created mLastShiftStatus = shiftPressed; // Get the new fill region if (!shiftPressed) { // If not holding shift, a region is generated from the current pos mFillRegion = regionComputer.computePaintableFillRegion(tilePos); } else { // If holding shift, the region is the selection bounds mFillRegion = mapDocument()->selectedArea(); // Fill region is the whole map if there is no selection if (mFillRegion.isEmpty()) mFillRegion = tileLayer->bounds(); // The mouse needs to be in the region if (!mFillRegion.contains(tilePos)) mFillRegion = QRegion(); } fillRegionChanged = true; } // Ensure that a fill region was created before making an overlay layer if (mFillRegion.isEmpty()) return; if (mLastRandomStatus != mIsRandom) { mLastRandomStatus = mIsRandom; fillRegionChanged = true; } if (!mFillOverlay) { // Create a new overlay region const QRect fillBounds = mFillRegion.boundingRect(); mFillOverlay = SharedTileLayer(new TileLayer(QString(), fillBounds.x(), fillBounds.y(), fillBounds.width(), fillBounds.height())); } // Paint the new overlay if (!mIsRandom) { if (fillRegionChanged || mStamp.variations().size() > 1) { fillWithStamp(*mFillOverlay, mStamp, mFillRegion.translated(-mFillOverlay->position())); fillRegionChanged = true; } } else { randomFill(*mFillOverlay, mFillRegion); fillRegionChanged = true; } if (fillRegionChanged) { // Update the brush item to draw the overlay brushItem()->setTileLayer(mFillOverlay); } // Create connections to know when the overlay should be cleared makeConnections(); } void BucketFillTool::mousePressed(QGraphicsSceneMouseEvent *event) { if (event->button() != Qt::LeftButton || mFillRegion.isEmpty()) return; if (!brushItem()->isVisible()) return; const TileLayer *preview = mFillOverlay.data(); if (!preview) return; PaintTileLayer *paint = new PaintTileLayer(mapDocument(), currentTileLayer(), preview->x(), preview->y(), preview); paint->setText(QCoreApplication::translate("Undo Commands", "Fill Area")); if (!mMissingTilesets.isEmpty()) { for (const SharedTileset &tileset : mMissingTilesets) new AddTileset(mapDocument(), tileset, paint); mMissingTilesets.clear(); } QRegion fillRegion(mFillRegion); mapDocument()->undoStack()->push(paint); emit mapDocument()->regionEdited(fillRegion, currentTileLayer()); } void BucketFillTool::mouseReleased(QGraphicsSceneMouseEvent *) { } void BucketFillTool::modifiersChanged(Qt::KeyboardModifiers) { // Don't need to recalculate fill region if there was no fill region if (!mFillOverlay) return; tilePositionChanged(tilePosition()); } void BucketFillTool::languageChanged() { setName(tr("Bucket Fill Tool")); setShortcut(QKeySequence(tr("F"))); } void BucketFillTool::mapDocumentChanged(MapDocument *oldDocument, MapDocument *newDocument) { AbstractTileTool::mapDocumentChanged(oldDocument, newDocument); clearConnections(oldDocument); if (newDocument) updateRandomListAndMissingTilesets(); clearOverlay(); } void BucketFillTool::setStamp(const TileStamp &stamp) { // Clear any overlay that we presently have with an old stamp clearOverlay(); mStamp = stamp; updateRandomListAndMissingTilesets(); if (mIsActive && brushItem()->isVisible()) tilePositionChanged(tilePosition()); } void BucketFillTool::clearOverlay() { // Clear connections before clearing overlay so there is no // risk of getting a callback and causing an infinite loop clearConnections(mapDocument()); brushItem()->clear(); mFillOverlay.clear(); mFillRegion = QRegion(); } void BucketFillTool::makeConnections() { if (!mapDocument()) return; // Overlay may need to be cleared if a region changed connect(mapDocument(), &MapDocument::regionChanged, this, &BucketFillTool::clearOverlay); // Overlay needs to be cleared if we switch to another layer connect(mapDocument(), &MapDocument::currentLayerChanged, this, &BucketFillTool::clearOverlay); // Overlay needs be cleared if the selection changes, since // the overlay may be bound or may need to be bound to the selection connect(mapDocument(), &MapDocument::selectedAreaChanged, this, &BucketFillTool::clearOverlay); } void BucketFillTool::clearConnections(MapDocument *mapDocument) { if (!mapDocument) return; disconnect(mapDocument, &MapDocument::regionChanged, this, &BucketFillTool::clearOverlay); disconnect(mapDocument, &MapDocument::currentLayerChanged, this, &BucketFillTool::clearOverlay); disconnect(mapDocument, &MapDocument::selectedAreaChanged, this, &BucketFillTool::clearOverlay); } void BucketFillTool::setRandom(bool value) { if (mIsRandom == value) return; mIsRandom = value; updateRandomListAndMissingTilesets(); // Don't need to recalculate fill region if there was no fill region if (!mFillOverlay) return; tilePositionChanged(tilePosition()); } void BucketFillTool::randomFill(TileLayer &tileLayer, const QRegion ®ion) const { if (region.isEmpty() || mRandomCellPicker.isEmpty()) return; for (const QRect &rect : region.translated(-tileLayer.position()).rects()) { for (int _x = rect.left(); _x <= rect.right(); ++_x) { for (int _y = rect.top(); _y <= rect.bottom(); ++_y) { tileLayer.setCell(_x, _y, mRandomCellPicker.pick()); } } } } void BucketFillTool::updateRandomListAndMissingTilesets() { mRandomCellPicker.clear(); mMissingTilesets.clear(); for (const TileStampVariation &variation : mStamp.variations()) { mapDocument()->unifyTilesets(variation.map, mMissingTilesets); if (mIsRandom) { for (const Cell &cell : *variation.tileLayer()) { if (const Tile *tile = cell.tile()) mRandomCellPicker.add(cell, tile->probability()); } } } } tiled-1.0.3/src/tiled/bucketfilltool.h000066400000000000000000000062531315121121300176730ustar00rootroot00000000000000/* * bucketfilltool.h * Copyright 2009-2010, Jeff Bland * Copyright 2010, Thorbjørn Lindeijer * Copyright 2011, Stefan Beller * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "abstracttiletool.h" #include "randompicker.h" #include "tilelayer.h" #include "tilestamp.h" namespace Tiled { namespace Internal { class MapDocument; /** * Implements a tool that bucket fills (flood fills) a region with a repeatable * stamp. */ class BucketFillTool : public AbstractTileTool { Q_OBJECT public: BucketFillTool(QObject *parent = nullptr); ~BucketFillTool(); void activate(MapScene *scene) override; void deactivate(MapScene *scene) override; void mousePressed(QGraphicsSceneMouseEvent *event) override; void mouseReleased(QGraphicsSceneMouseEvent *event) override; void modifiersChanged(Qt::KeyboardModifiers) override; void languageChanged() override; /** * Sets the stamp that is drawn when filling. */ void setStamp(const TileStamp &stamp); /** * This returns the current stamp used for filling. */ const TileStamp &stamp() const { return mStamp; } public slots: void setRandom(bool value); protected: void tilePositionChanged(const QPoint &tilePos) override; void mapDocumentChanged(MapDocument *oldDocument, MapDocument *newDocument) override; private slots: void clearOverlay(); private: void makeConnections(); void clearConnections(MapDocument *mapDocument); TileStamp mStamp; SharedTileLayer mFillOverlay; QRegion mFillRegion; QVector mMissingTilesets; bool mIsActive; bool mLastShiftStatus; /** * Indicates if the tool is using the random mode. */ bool mIsRandom; /** * Contains the value of mIsRandom at that time, when the latest call of * tilePositionChanged() took place. * This variable is needed to detect if the random mode was changed during * mFillOverlay being brushed at an area. */ bool mLastRandomStatus; RandomPicker mRandomCellPicker; /** * Updates the list of random cells. * This is done by taking all non-null tiles from the original stamp mStamp. */ void updateRandomListAndMissingTilesets(); /** * Fills the given \a region in the given \a tileLayer with random tiles. */ void randomFill(TileLayer &tileLayer, const QRegion ®ion) const; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changeimagelayerposition.cpp000066400000000000000000000031431315121121300222510ustar00rootroot00000000000000/* * changeimagelayerposition.cpp * Copyright 2014, Michael Aquilina * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "changeimagelayerposition.h" #include "mapdocument.h" #include "imagelayer.h" #include using namespace Tiled; using namespace Tiled::Internal; ChangeImageLayerPosition::ChangeImageLayerPosition( MapDocument *mapDocument, ImageLayer *imageLayer, const QPoint &newPos) : QUndoCommand( QCoreApplication::translate( "Undo Commands", "Change Image Layer Position")) , mMapDocument(mapDocument) , mImageLayer(imageLayer) , mUndoPos(imageLayer->position()) , mRedoPos(newPos) { } void ChangeImageLayerPosition::redo() { mImageLayer->setPosition(mRedoPos); emit mMapDocument->imageLayerChanged(mImageLayer); } void ChangeImageLayerPosition::undo() { mImageLayer->setPosition(mUndoPos); emit mMapDocument->imageLayerChanged(mImageLayer); } tiled-1.0.3/src/tiled/changeimagelayerposition.h000066400000000000000000000031501315121121300217140ustar00rootroot00000000000000/* * changeimagelayerproperties.h * Copyright 2014, Michael Aquilina * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include namespace Tiled { class ImageLayer; namespace Internal { class MapDocument; class ChangeImageLayerPosition : public QUndoCommand { public: /** * Constructs a new 'Change Image Layer Position' command. * * @param mapDocument the map document of the layer's map * @param imageLayer the image layer to modify * @param newPos the new position of the image layer */ ChangeImageLayerPosition(MapDocument *mapDocument, ImageLayer *imageLayer, const QPoint &newPos); void undo() override; void redo() override; private: MapDocument *mMapDocument; ImageLayer *mImageLayer; const QPoint mUndoPos; const QPoint mRedoPos; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changeimagelayerproperties.cpp000066400000000000000000000041211315121121300225760ustar00rootroot00000000000000/* * changeimagelayerproperties.cpp * Copyright 2010, Jeff Bland * Copyright 2010, Thorbjørn Lindeijer * Copyright 2011, Gregory Nickonov * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "changeimagelayerproperties.h" #include "mapdocument.h" #include "imagelayer.h" #include using namespace Tiled; using namespace Tiled::Internal; ChangeImageLayerProperties::ChangeImageLayerProperties( MapDocument *mapDocument, ImageLayer *imageLayer, const QColor &color, const QString &path) : QUndoCommand( QCoreApplication::translate( "Undo Commands", "Change Image Layer Properties")) , mMapDocument(mapDocument) , mImageLayer(imageLayer) , mUndoColor(imageLayer->transparentColor()) , mRedoColor(color) , mUndoPath(imageLayer->imageSource()) , mRedoPath(path) { } void ChangeImageLayerProperties::redo() { mImageLayer->setTransparentColor(mRedoColor); if (mRedoPath.isEmpty()) mImageLayer->resetImage(); else mImageLayer->loadFromImage(mRedoPath); emit mMapDocument->imageLayerChanged(mImageLayer); } void ChangeImageLayerProperties::undo() { mImageLayer->setTransparentColor(mUndoColor); if (mUndoPath.isEmpty()) mImageLayer->resetImage(); else mImageLayer->loadFromImage(mUndoPath); emit mMapDocument->imageLayerChanged(mImageLayer); } tiled-1.0.3/src/tiled/changeimagelayerproperties.h000066400000000000000000000036441315121121300222540ustar00rootroot00000000000000/* * changeimagelayerproperties.h * Copyright 2010, Jeff Bland * Copyright 2010, Thorbjørn Lindeijer * Copyright 2011, Gregory Nickonov * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include #include namespace Tiled { class ImageLayer; namespace Internal { class MapDocument; class ChangeImageLayerProperties : public QUndoCommand { public: /** * Constructs a new 'Change Image Layer Properties' command. * * @param mapDocument the map document of the layer's map * @param imageLayer the image layer to modify * @param newColor the new transparent color to apply * @param newPath the new image source to apply */ ChangeImageLayerProperties(MapDocument *mapDocument, ImageLayer *imageLayer, const QColor &newColor, const QString &newPath); void undo() override; void redo() override; private: MapDocument *mMapDocument; ImageLayer *mImageLayer; const QColor mUndoColor; const QColor mRedoColor; const QString mUndoPath; const QString mRedoPath; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changelayer.cpp000066400000000000000000000060341315121121300174630ustar00rootroot00000000000000/* * changelayer.cpp * Copyright 2012-2013, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "changelayer.h" #include "layer.h" #include "layermodel.h" #include "map.h" #include "mapdocument.h" #include namespace Tiled { namespace Internal { SetLayerVisible::SetLayerVisible(MapDocument *mapDocument, Layer *layer, bool visible) : mMapDocument(mapDocument) , mLayer(layer) , mVisible(visible) { if (visible) setText(QCoreApplication::translate("Undo Commands", "Show Layer")); else setText(QCoreApplication::translate("Undo Commands", "Hide Layer")); } void SetLayerVisible::swap() { const bool previousVisible = mLayer->isVisible(); mMapDocument->layerModel()->setLayerVisible(mLayer, mVisible); mVisible = previousVisible; } SetLayerOpacity::SetLayerOpacity(MapDocument *mapDocument, Layer *layer, float opacity) : mMapDocument(mapDocument) , mLayer(layer) , mOldOpacity(layer->opacity()) , mNewOpacity(opacity) { setText(QCoreApplication::translate("Undo Commands", "Change Layer Opacity")); } bool SetLayerOpacity::mergeWith(const QUndoCommand *other) { const SetLayerOpacity *o = static_cast(other); if (!(mMapDocument == o->mMapDocument && mLayer == o->mLayer)) return false; mNewOpacity = o->mNewOpacity; return true; } void SetLayerOpacity::setOpacity(float opacity) { mMapDocument->layerModel()->setLayerOpacity(mLayer, opacity); } SetLayerOffset::SetLayerOffset(MapDocument *mapDocument, Layer *layer, const QPointF &offset, QUndoCommand *parent) : QUndoCommand(parent) , mMapDocument(mapDocument) , mLayer(layer) , mOldOffset(layer->offset()) , mNewOffset(offset) { setText(QCoreApplication::translate("Undo Commands", "Change Layer Offset")); } void SetLayerOffset::setOffset(const QPointF &offset) { mMapDocument->layerModel()->setLayerOffset(mLayer, offset); } } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changelayer.h000066400000000000000000000050011315121121300171210ustar00rootroot00000000000000/* * changelayer.h * Copyright 2012-2013, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "undocommands.h" #include #include namespace Tiled { class Layer; namespace Internal { class MapDocument; /** * Used for changing layer visibility. */ class SetLayerVisible : public QUndoCommand { public: SetLayerVisible(MapDocument *mapDocument, Layer *layer, bool visible); void undo() override { swap(); } void redo() override { swap(); } private: void swap(); MapDocument *mMapDocument; Layer *mLayer; bool mVisible; }; /** * Used for changing layer opacity. */ class SetLayerOpacity : public QUndoCommand { public: SetLayerOpacity(MapDocument *mapDocument, Layer *layer, float opacity); void undo() override { setOpacity(mOldOpacity); } void redo() override { setOpacity(mNewOpacity); } int id() const override { return Cmd_ChangeLayerOpacity; } bool mergeWith(const QUndoCommand *other) override; private: void setOpacity(float opacity); MapDocument *mMapDocument; Layer *mLayer; float mOldOpacity; float mNewOpacity; }; /** * Used for changing the layer offset. */ class SetLayerOffset : public QUndoCommand { public: SetLayerOffset(MapDocument *mapDocument, Layer *layer, const QPointF &offset, QUndoCommand *parent = nullptr); void undo() override { setOffset(mOldOffset); } void redo() override { setOffset(mNewOffset); } int id() const override { return Cmd_ChangeLayerOffset; } private: void setOffset(const QPointF &offset); MapDocument *mMapDocument; Layer *mLayer; QPointF mOldOffset; QPointF mNewOffset; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changemapobject.cpp000066400000000000000000000107701315121121300203150ustar00rootroot00000000000000/* * changemapobject.cpp * Copyright 2009, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "changemapobject.h" #include "mapdocument.h" #include "mapobjectmodel.h" #include using namespace Tiled; using namespace Tiled::Internal; ChangeMapObject::ChangeMapObject(MapDocument *mapDocument, MapObject *mapObject, MapObject::Property property, const QVariant &value) : QUndoCommand(QCoreApplication::translate("Undo Commands", "Change Object")) , mMapDocument(mapDocument) , mMapObject(mapObject) , mProperty(property) , mValue(value) { switch (property) { case MapObject::VisibleProperty: if (value.toBool()) setText(QCoreApplication::translate("Undo Commands", "Show Object")); else setText(QCoreApplication::translate("Undo Commands", "Hide Object")); break; default: break; } } void ChangeMapObject::swap() { QVariant oldValue = mMapObject->mapObjectProperty(mProperty); mMapDocument->mapObjectModel()->setObjectProperty(mMapObject, mProperty, mValue); std::swap(mValue, oldValue); } ChangeMapObjectCells::ChangeMapObjectCells(MapDocument *mapDocument, const QVector &changes, QUndoCommand *parent) : QUndoCommand(parent) , mMapObjectModel(mapDocument->mapObjectModel()) , mChanges(changes) { } static QList objectList(const QVector &changes) { QList result; result.reserve(changes.size()); for (const MapObjectCell &change : changes) result.append(change.object); return result; } void ChangeMapObjectCells::swap() { for (MapObjectCell &change : mChanges) { auto cell = change.object->cell(); change.object->setCell(change.cell); change.cell = cell; } emit mMapObjectModel->objectsChanged(objectList(mChanges)); } ChangeMapObjectsTile::ChangeMapObjectsTile(MapDocument *mapDocument, const QList &mapObjects, Tile *tile) : QUndoCommand(QCoreApplication::translate("Undo Commands", "Change %n Object/s Tile", nullptr, mapObjects.size())) , mMapDocument(mapDocument) , mMapObjects(mapObjects) , mTile(tile) { for (MapObject *object : mMapObjects) { Cell cell = object->cell(); mOldCells.append(cell); Tile *tile = cell.tile(); // Update the size if the object's tile is valid and the sizes match mUpdateSize.append(tile && object->size() == tile->size()); } } static void setObjectCell(MapObject *object, const Cell &cell, const bool updateSize) { object->setCell(cell); if (updateSize) object->setSize(cell.tile()->size()); } void ChangeMapObjectsTile::undo() { restoreTiles(); QUndoCommand::undo(); // undo child commands } void ChangeMapObjectsTile::redo() { QUndoCommand::redo(); // redo child commands changeTiles(); } void ChangeMapObjectsTile::restoreTiles() { for (int i = 0; i < mMapObjects.size(); ++i) setObjectCell(mMapObjects[i], mOldCells[i], mUpdateSize[i]); emit mMapDocument->mapObjectModel()->objectsChanged(mMapObjects); } void ChangeMapObjectsTile::changeTiles() { for (int i = 0; i < mMapObjects.size(); ++i) { Cell cell = mMapObjects[i]->cell(); cell.setTile(mTile); setObjectCell(mMapObjects[i], cell, mUpdateSize[i]); } emit mMapDocument->mapObjectModel()->objectsChanged(mMapObjects); } tiled-1.0.3/src/tiled/changemapobject.h000066400000000000000000000051421315121121300177570ustar00rootroot00000000000000/* * changemapobject.h * Copyright 2009, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "mapobject.h" #include "tilelayer.h" #include #include namespace Tiled { class MapObject; class Tile; namespace Internal { class MapDocument; class MapObjectModel; class ChangeMapObject : public QUndoCommand { public: /** * Creates an undo command that sets the given \a object's \a property to * \a value. */ ChangeMapObject(MapDocument *mapDocument, MapObject *object, MapObject::Property property, const QVariant &value); void undo() override { swap(); } void redo() override { swap(); } private: void swap(); MapDocument *mMapDocument; MapObject *mMapObject; MapObject::Property mProperty; QVariant mValue; }; struct MapObjectCell { MapObject *object; Cell cell; }; class ChangeMapObjectCells : public QUndoCommand { public: /** * Creates an undo command that applies the given map object changes. */ ChangeMapObjectCells(MapDocument *mapDocument, const QVector &changes, QUndoCommand *parent = nullptr); void undo() override { swap(); } void redo() override { swap(); } private: void swap(); MapObjectModel *mMapObjectModel; QVector mChanges; }; class ChangeMapObjectsTile : public QUndoCommand { public: ChangeMapObjectsTile(MapDocument *mapDocument, const QList &mapObjects, Tile *tile); void undo() override; void redo() override; private: void changeTiles(); void restoreTiles(); MapDocument *mMapDocument; const QList mMapObjects; Tile * const mTile; QVector mOldCells; QVector mUpdateSize; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changemapobjectsorder.cpp000066400000000000000000000043771315121121300215420ustar00rootroot00000000000000/* * changemapobjectsorder.cpp * Copyright 2013, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "changemapobjectsorder.h" #include "mapdocument.h" #include "mapobjectmodel.h" #include "objectgroup.h" #include using namespace Tiled; using namespace Tiled::Internal; ChangeMapObjectsOrder::ChangeMapObjectsOrder(MapDocument *mapDocument, ObjectGroup *objectGroup, int from, int to, int count, QUndoCommand *parent) : QUndoCommand(parent) , mMapDocument(mapDocument) , mObjectGroup(objectGroup) , mFrom(from) , mTo(to) , mCount(count) { if (mTo > mFrom) setText(QCoreApplication::translate("Undo Commands", "Raise Object")); else setText(QCoreApplication::translate("Undo Commands", "Lower Object")); } void ChangeMapObjectsOrder::undo() { int to = mFrom; int from = mTo; // When reversing the operation, either the 'from' or the 'to' index will // need to be adapted to take into account the number of objects moved. if (from > to) from -= mCount; else to += mCount; mMapDocument->mapObjectModel()->moveObjects(mObjectGroup, from, to, mCount); } void ChangeMapObjectsOrder::redo() { mMapDocument->mapObjectModel()->moveObjects(mObjectGroup, mFrom, mTo, mCount); } tiled-1.0.3/src/tiled/changemapobjectsorder.h000066400000000000000000000026521315121121300212010ustar00rootroot00000000000000/* * changemapobjectsorder.h * Copyright 2013, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include namespace Tiled { class ObjectGroup; namespace Internal { class MapDocument; class ChangeMapObjectsOrder : public QUndoCommand { public: ChangeMapObjectsOrder(MapDocument *mapDocument, ObjectGroup *objectGroup, int from, int to, int count, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: MapDocument *mMapDocument; ObjectGroup *mObjectGroup; int mFrom; int mTo; int mCount; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changemapproperty.cpp000066400000000000000000000135501315121121300207320ustar00rootroot00000000000000/* * changemapproperty.cpp * Copyright 2012, Emmanuel Barroga emmanuelbarroga@gmail.com * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "changemapproperty.h" #include "map.h" #include "mapdocument.h" #include "objectgroup.h" #include using namespace Tiled; using namespace Tiled::Internal; ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument, ChangeMapProperty::Property property, int value) : mMapDocument(mapDocument) , mProperty(property) , mIntValue(value) { switch (property) { case TileWidth: setText(QCoreApplication::translate("Undo Commands", "Change Tile Width")); break; case TileHeight: setText(QCoreApplication::translate("Undo Commands", "Change Tile Height")); break; case HexSideLength: setText(QCoreApplication::translate("Undo Commands", "Change Hex Side Length")); break; default: break; } } ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument, const QColor &backgroundColor) : QUndoCommand(QCoreApplication::translate("Undo Commands", "Change Background Color")) , mMapDocument(mapDocument) , mProperty(BackgroundColor) , mBackgroundColor(backgroundColor) { } ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument, Map::StaggerAxis staggerAxis) : QUndoCommand(QCoreApplication::translate("Undo Commands", "Change Stagger Axis")) , mMapDocument(mapDocument) , mProperty(StaggerAxis) , mStaggerAxis(staggerAxis) { } ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument, Map::StaggerIndex staggerIndex) : QUndoCommand(QCoreApplication::translate("Undo Commands", "Change Stagger Index")) , mMapDocument(mapDocument) , mProperty(StaggerIndex) , mStaggerIndex(staggerIndex) { } ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument, Map::Orientation orientation) : QUndoCommand(QCoreApplication::translate("Undo Commands", "Change Orientation")) , mMapDocument(mapDocument) , mProperty(Orientation) , mOrientation(orientation) { } ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument, Map::RenderOrder renderOrder) : QUndoCommand(QCoreApplication::translate("Undo Commands", "Change Render Order")) , mMapDocument(mapDocument) , mProperty(RenderOrder) , mRenderOrder(renderOrder) { } ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument, Map::LayerDataFormat layerDataFormat) : QUndoCommand(QCoreApplication::translate("Undo Commands", "Change Layer Data Format")) , mMapDocument(mapDocument) , mProperty(LayerDataFormat) , mLayerDataFormat(layerDataFormat) { } void ChangeMapProperty::redo() { swap(); } void ChangeMapProperty::undo() { swap(); } void ChangeMapProperty::swap() { Map *map = mMapDocument->map(); switch (mProperty) { case TileWidth: { const int tileWidth = map->tileWidth(); map->setTileWidth(mIntValue); mIntValue = tileWidth; break; } case TileHeight: { const int tileHeight = map->tileHeight(); map->setTileHeight(mIntValue); mIntValue = tileHeight; break; } case Orientation: { const Map::Orientation orientation = map->orientation(); map->setOrientation(mOrientation); mOrientation = orientation; mMapDocument->createRenderer(); break; } case HexSideLength: { const int hexSideLength = map->hexSideLength(); map->setHexSideLength(mIntValue); mIntValue = hexSideLength; break; } case StaggerAxis: { const Map::StaggerAxis staggerAxis = map->staggerAxis(); map->setStaggerAxis(mStaggerAxis); mStaggerAxis = staggerAxis; break; } case StaggerIndex: { const Map::StaggerIndex staggerIndex = map->staggerIndex(); map->setStaggerIndex(mStaggerIndex); mStaggerIndex = staggerIndex; break; } case RenderOrder: { const Map::RenderOrder renderOrder = map->renderOrder(); map->setRenderOrder(mRenderOrder); mRenderOrder = renderOrder; break; } case BackgroundColor: { const QColor backgroundColor = map->backgroundColor(); map->setBackgroundColor(mBackgroundColor); mBackgroundColor = backgroundColor; break; } case LayerDataFormat: { const Map::LayerDataFormat layerDataFormat = map->layerDataFormat(); map->setLayerDataFormat(mLayerDataFormat); mLayerDataFormat = layerDataFormat; break; } } emit mMapDocument->mapChanged(); } tiled-1.0.3/src/tiled/changemapproperty.h000066400000000000000000000072501315121121300203770ustar00rootroot00000000000000/* * changemapproperty.h * Copyright 2012, Emmanuel Barroga emmanuelbarroga@gmail.com * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "map.h" #include #include namespace Tiled { namespace Internal { class MapDocument; class ChangeMapProperty : public QUndoCommand { public: enum Property { TileWidth, TileHeight, HexSideLength, StaggerAxis, StaggerIndex, Orientation, RenderOrder, BackgroundColor, LayerDataFormat }; /** * Constructs a command that changes the value of the given property. * * Can only be used for the HexSideLength property. * * @param mapDocument the map document of the map * @param backgroundColor the new color to apply for the background */ ChangeMapProperty(MapDocument *mapDocument, Property property, int value); /** * Constructs a command that changes the map background color. * * @param mapDocument the map document of the map * @param backgroundColor the new color to apply for the background */ ChangeMapProperty(MapDocument *mapDocument, const QColor &backgroundColor); /** * Constructs a command that changes the map stagger axis. * * @param mapDocument the map document of the map * @param orientation the new map stagger axis */ ChangeMapProperty(MapDocument *mapDocument, Map::StaggerAxis staggerAxis); /** * Constructs a command that changes the map stagger index. * * @param mapDocument the map document of the map * @param orientation the new map stagger index */ ChangeMapProperty(MapDocument *mapDocument, Map::StaggerIndex staggerIndex); /** * Constructs a command that changes the map orientation. * * @param mapDocument the map document of the map * @param orientation the new map orientation */ ChangeMapProperty(MapDocument *mapDocument, Map::Orientation orientation); /** * Constructs a command that changes the render order. * * @param mapDocument the map document of the map * @param renderOrder the new map render order */ ChangeMapProperty(MapDocument *mapDocument, Map::RenderOrder renderOrder); /** * Constructs a command that changes the layer data format. * * @param mapDocument the map document of the map * @param layerDataFormat the new layer data format */ ChangeMapProperty(MapDocument *mapDocument, Map::LayerDataFormat layerDataFormat); void undo() override; void redo() override; private: void swap(); MapDocument *mMapDocument; Property mProperty; QColor mBackgroundColor; union { int mIntValue; Map::StaggerAxis mStaggerAxis; Map::StaggerIndex mStaggerIndex; Map::Orientation mOrientation; Map::RenderOrder mRenderOrder; Map::LayerDataFormat mLayerDataFormat; }; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changeobjectgroupproperties.cpp000066400000000000000000000036631315121121300230140ustar00rootroot00000000000000/* * changeobjectgroupproperties.cpp * Copyright 2010, Jeff Bland * Copyright 2010, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "changeobjectgroupproperties.h" #include "mapdocument.h" #include "objectgroup.h" #include "mapobjectmodel.h" #include using namespace Tiled; using namespace Tiled::Internal; ChangeObjectGroupProperties::ChangeObjectGroupProperties( MapDocument *mapDocument, ObjectGroup *objectGroup, const QColor &newColor, ObjectGroup::DrawOrder newDrawOrder) : QUndoCommand( QCoreApplication::translate( "Undo Commands", "Change Object Layer Properties")) , mMapDocument(mapDocument) , mObjectGroup(objectGroup) , mUndoColor(objectGroup->color()) , mRedoColor(newColor) , mUndoDrawOrder(objectGroup->drawOrder()) , mRedoDrawOrder(newDrawOrder) { } void ChangeObjectGroupProperties::redo() { mObjectGroup->setColor(mRedoColor); mObjectGroup->setDrawOrder(mRedoDrawOrder); emit mMapDocument->objectGroupChanged(mObjectGroup); } void ChangeObjectGroupProperties::undo() { mObjectGroup->setColor(mUndoColor); mObjectGroup->setDrawOrder(mUndoDrawOrder); emit mMapDocument->objectGroupChanged(mObjectGroup); } tiled-1.0.3/src/tiled/changeobjectgroupproperties.h000066400000000000000000000035341315121121300224560ustar00rootroot00000000000000/* * changeobjectgroupproperties.h * Copyright 2010, Jeff Bland * Copyright 2010, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "objectgroup.h" #include #include namespace Tiled { namespace Internal { class MapDocument; class ChangeObjectGroupProperties : public QUndoCommand { public: /** * Constructs a new 'Change Object Layer Properties' command. * * @param mapDocument the map document of the object group's map * @param objectGroup the object group in to modify * @param newColor the new color to apply */ ChangeObjectGroupProperties(MapDocument *mapDocument, ObjectGroup *objectGroup, const QColor &newColor, ObjectGroup::DrawOrder newDrawOrder); void undo() override; void redo() override; private: MapDocument *mMapDocument; ObjectGroup *mObjectGroup; const QColor mUndoColor; const QColor mRedoColor; ObjectGroup::DrawOrder mUndoDrawOrder; ObjectGroup::DrawOrder mRedoDrawOrder; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changepolygon.cpp000066400000000000000000000037041315121121300200370ustar00rootroot00000000000000/* * changepolygon.cpp * Copyright 2011, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "changepolygon.h" #include "mapdocument.h" #include "mapobject.h" #include "mapobjectmodel.h" #include using namespace Tiled; using namespace Tiled::Internal; ChangePolygon::ChangePolygon(MapDocument *mapDocument, MapObject *mapObject, const QPolygonF &oldPolygon) : mMapDocument(mapDocument) , mMapObject(mapObject) , mOldPolygon(oldPolygon) , mNewPolygon(mapObject->polygon()) { setText(QCoreApplication::translate("Undo Commands", "Change Polygon")); } ChangePolygon::ChangePolygon(MapDocument *mapDocument, MapObject *mapObject, const QPolygonF &newPolygon, const QPolygonF &oldPolygon) : mMapDocument(mapDocument) , mMapObject(mapObject) , mOldPolygon(oldPolygon) , mNewPolygon(newPolygon) { setText(QCoreApplication::translate("Undo Commands", "Change Polygon")); } void ChangePolygon::undo() { mMapDocument->mapObjectModel()->setObjectPolygon(mMapObject, mOldPolygon); } void ChangePolygon::redo() { mMapDocument->mapObjectModel()->setObjectPolygon(mMapObject, mNewPolygon); } tiled-1.0.3/src/tiled/changepolygon.h000066400000000000000000000031771315121121300175100ustar00rootroot00000000000000/* * changepolygon.h * Copyright 2011, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include namespace Tiled { class MapObject; namespace Internal { class MapDocument; /** * Changes the polygon of a MapObject. * * This class expects the polygon to be already changed, and takes the previous * polygon in the constructor. */ class ChangePolygon : public QUndoCommand { public: ChangePolygon(MapDocument *mapDocument, MapObject *mapObject, const QPolygonF &oldPolygon); ChangePolygon(MapDocument *mapDocument, MapObject *mapObject, const QPolygonF &newPolygon, const QPolygonF &oldPolygon); void undo() override; void redo() override; private: MapDocument *mMapDocument; MapObject *mMapObject; QPolygonF mOldPolygon; QPolygonF mNewPolygon; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changeproperties.cpp000066400000000000000000000113061315121121300205410ustar00rootroot00000000000000/* * changeproperties.cpp * Copyright 2008-2010, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "changeproperties.h" #include "document.h" #include using namespace Tiled; using namespace Tiled::Internal; ChangeProperties::ChangeProperties(Document *document, const QString &kind, Object *object, const Properties &newProperties, QUndoCommand *parent) : QUndoCommand(parent) , mDocument(document) , mObject(object) , mNewProperties(newProperties) { if (kind.isEmpty()) { setText(QCoreApplication::translate("Undo Commands", "Change Properties")); } else { setText(QCoreApplication::translate("Undo Commands", "Change %1 Properties").arg(kind)); } } void ChangeProperties::redo() { swapProperties(); } void ChangeProperties::undo() { swapProperties(); } void ChangeProperties::swapProperties() { const Properties oldProperties = mObject->properties(); mDocument->setProperties(mObject, mNewProperties); mNewProperties = oldProperties; } SetProperty::SetProperty(Document *document, const QList &objects, const QString &name, const QVariant &value, QUndoCommand *parent) : QUndoCommand(parent) , mDocument(document) , mObjects(objects) , mName(name) , mValue(value) { for (Object *obj : objects) { ObjectProperty prop; prop.existed = obj->hasProperty(mName); prop.previousValue = obj->property(mName); mProperties.append(prop); } if (mObjects.size() > 1 || mObjects.at(0)->hasProperty(mName)) setText(QCoreApplication::translate("Undo Commands", "Set Property")); else setText(QCoreApplication::translate("Undo Commands", "Add Property")); } void SetProperty::undo() { for (int i = 0; i < mObjects.size(); ++i) { if (mProperties.at(i).existed) mDocument->setProperty(mObjects.at(i), mName, mProperties.at(i).previousValue); else mDocument->removeProperty(mObjects.at(i), mName); } } void SetProperty::redo() { const QList &objects = mObjects; for (Object *obj : objects) mDocument->setProperty(obj, mName, mValue); } RemoveProperty::RemoveProperty(Document *document, const QList &objects, const QString &name, QUndoCommand *parent) : QUndoCommand(parent) , mDocument(document) , mObjects(objects) , mName(name) { for (Object *obj : objects) mPreviousValues.append(obj->property(mName)); setText(QCoreApplication::translate("Undo Commands", "Remove Property")); } void RemoveProperty::undo() { for (int i = 0; i < mObjects.size(); ++i) mDocument->setProperty(mObjects.at(i), mName, mPreviousValues.at(i)); } void RemoveProperty::redo() { const QList &objects = mObjects; for (Object *obj : objects) mDocument->removeProperty(obj, mName); } RenameProperty::RenameProperty(Document *document, const QList &objects, const QString &oldName, const QString &newName) { setText(QCoreApplication::translate("Undo Commands", "Rename Property")); // Remove the old name from all objects new RemoveProperty(document, objects, oldName, this); // Different objects may have different values for the same property, // or may not have a value at all. for (Object *object : objects) { if (!object->hasProperty(oldName)) continue; const QList objects { object }; const QVariant value = object->property(oldName); new SetProperty(document, objects, newName, value, this); } } tiled-1.0.3/src/tiled/changeproperties.h000066400000000000000000000076371315121121300202220ustar00rootroot00000000000000/* * changeproperties.h * Copyright 2008-2010, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "object.h" #include #include #include namespace Tiled { namespace Internal { class Document; class ChangeProperties : public QUndoCommand { public: /** * Constructs a new 'Change Properties' command. * * @param document the document owning the object * @param kind the kind of properties (Map, Layer, Object, etc.) * @param object the object of which the properties should be changed * @param newProperties the new properties that should be applied */ ChangeProperties(Document *document, const QString &kind, Object *object, const Properties &newProperties, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: void swapProperties(); Document *mDocument; Object *mObject; Properties mNewProperties; }; class SetProperty : public QUndoCommand { public: /** * Constructs a new 'Set Property' command. * * @param document the document owning the objects * @param objects the objects of which the property should be changed * @param name the name of the property to be changed * @param value the new value of the property * @param type the (new) type ot the property to be changed */ SetProperty(Document *document, const QList &objects, const QString &name, const QVariant &value, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: struct ObjectProperty { QVariant previousValue; bool existed; }; QVector mProperties; Document *mDocument; QList mObjects; QString mName; QVariant mValue; }; class RemoveProperty : public QUndoCommand { public: /** * Constructs a new 'Remove Property' command. * * @param document the document owning the objects * @param objects the objects from which the property should be removed * @param name the name of the property to be removed */ RemoveProperty(Document *document, const QList &objects, const QString &name, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: Document *mDocument; QList mObjects; QVector mPreviousValues; QString mName; }; class RenameProperty : public QUndoCommand { public: /** * Constructs a new 'Rename Property' command. * * @param document the document owning the object * @param object the object of which the property should be renamed * @param oldName the old name of the property * @param newName the new name of the property */ RenameProperty(Document *document, const QList &objects, const QString &oldName, const QString &newName); }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changeselectedarea.cpp000066400000000000000000000031371315121121300207710ustar00rootroot00000000000000/* * changeselectedarea.cpp * Copyright 2009-2010, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "changeselectedarea.h" #include "mapdocument.h" #include using namespace Tiled::Internal; ChangeSelectedArea::ChangeSelectedArea(MapDocument *mapDocument, const QRegion &newSelection, QUndoCommand *parent) : QUndoCommand(QCoreApplication::translate("Undo Commands", "Change Selection"), parent) , mMapDocument(mapDocument) , mSelection(newSelection) { } void ChangeSelectedArea::undo() { swapSelection(); } void ChangeSelectedArea::redo() { swapSelection(); } void ChangeSelectedArea::swapSelection() { const QRegion oldSelection = mMapDocument->selectedArea(); mMapDocument->setSelectedArea(mSelection); mSelection = oldSelection; } tiled-1.0.3/src/tiled/changeselectedarea.h000066400000000000000000000026201315121121300204320ustar00rootroot00000000000000/* * changeselectedarea.h * Copyright 2009, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include namespace Tiled { namespace Internal { class MapDocument; class ChangeSelectedArea: public QUndoCommand { public: /** * Creates an undo command that sets the selection of \a mapDocument to * the given \a selection. */ ChangeSelectedArea(MapDocument *mapDocument, const QRegion &selection, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: void swapSelection(); MapDocument *mMapDocument; QRegion mSelection; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changetile.cpp000066400000000000000000000030551315121121300173040ustar00rootroot00000000000000/* * changetile.cpp * Copyright 2017, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "changetile.h" #include "tile.h" #include "tilesetdocument.h" #include namespace Tiled { namespace Internal { ChangeTileType::ChangeTileType(TilesetDocument *tilesetDocument, const QList &tiles, const QString &type) : QUndoCommand(QCoreApplication::translate("Undo Commands", "Change Tile Type")) , mTilesetDocument(tilesetDocument) , mTiles(tiles) { mTypes.fill(type, tiles.size()); } void ChangeTileType::swap() { for (int i = 0, size = mTiles.size(); i < size; ++i) { Tile *tile = mTiles.at(i); QString oldType = tile->type(); mTilesetDocument->setTileType(tile, mTypes.at(i)); mTypes[i] = oldType; } } } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changetile.h000066400000000000000000000026311315121121300167500ustar00rootroot00000000000000/* * changetile.h * Copyright 2017, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include namespace Tiled { class Tile; namespace Internal { class TilesetDocument; class ChangeTileType : public QUndoCommand { public: /** * Creates an undo command that sets the given \a tile's \a type. */ ChangeTileType(TilesetDocument *tilesetDocument, const QList &tiles, const QString &type); void undo() override { swap(); } void redo() override { swap(); } private: void swap(); TilesetDocument *mTilesetDocument; const QList mTiles; QVector mTypes; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changetileanimation.cpp000066400000000000000000000032641315121121300212060ustar00rootroot00000000000000/* * changetileanimation.cpp * Copyright 2014, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "changetileanimation.h" #include "tilesetdocument.h" #include "tilesetmanager.h" #include namespace Tiled { namespace Internal { ChangeTileAnimation::ChangeTileAnimation(TilesetDocument *document, Tile *tile, const QVector &frames, QUndoCommand *parent) : QUndoCommand(QCoreApplication::translate( "Undo Commands", "Change Tile Animation"), parent) , mTilesetDocument(document) , mTile(tile) , mFrames(frames) { } void ChangeTileAnimation::swap() { const QVector frames = mTile->frames(); mTile->setFrames(mFrames); mFrames = frames; TilesetManager::instance()->resetTileAnimations(); emit mTilesetDocument->tileAnimationChanged(mTile); } } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changetileanimation.h000066400000000000000000000025621315121121300206530ustar00rootroot00000000000000/* * changetileanimation.h * Copyright 2014, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "tile.h" #include namespace Tiled { namespace Internal { class TilesetDocument; class ChangeTileAnimation : public QUndoCommand { public: ChangeTileAnimation(TilesetDocument *document, Tile *tile, const QVector &frames, QUndoCommand *parent = nullptr); void undo() override { swap(); } void redo() override { swap(); } private: void swap(); TilesetDocument *mTilesetDocument; Tile *mTile; QVector mFrames; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changetileimagesource.cpp000066400000000000000000000031771315121121300215350ustar00rootroot00000000000000/* * changetileimagesource.cpp * Copyright 2015, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "changetileimagesource.h" #include "tilesetdocument.h" #include "tile.h" #include namespace Tiled { namespace Internal { ChangeTileImageSource::ChangeTileImageSource(TilesetDocument *tilesetDocument, Tile *tile, const QString &imageSource) : mTilesetDocument(tilesetDocument) , mTile(tile) , mOldImageSource(tile->imageSource()) , mNewImageSource(imageSource) { setText(QCoreApplication::translate("Undo Commands", "Change Tile Image")); } void ChangeTileImageSource::apply(const QString &imageSource) { mTilesetDocument->setTileImage(mTile, QPixmap(imageSource), imageSource); } } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changetileimagesource.h000066400000000000000000000026071315121121300211770ustar00rootroot00000000000000/* * changetileimagesource.h * Copyright 2015, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include namespace Tiled { class Tile; namespace Internal { class TilesetDocument; class ChangeTileImageSource : public QUndoCommand { public: ChangeTileImageSource(TilesetDocument *tilesetDocument, Tile *tile, const QString &imageSource); void undo() { apply(mOldImageSource); } void redo() { apply(mNewImageSource); } private: void apply(const QString &imageSource); TilesetDocument *mTilesetDocument; Tile *mTile; QString mOldImageSource; QString mNewImageSource; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changetileobjectgroup.cpp000066400000000000000000000033221315121121300215450ustar00rootroot00000000000000/* * changetileobjectgroup.cpp * Copyright 2013, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "changetileobjectgroup.h" #include "tilesetdocument.h" #include "objectgroup.h" #include "tile.h" #include namespace Tiled { namespace Internal { ChangeTileObjectGroup::ChangeTileObjectGroup(TilesetDocument *tilesetDocument, Tile *tile, ObjectGroup *objectGroup, QUndoCommand *parent) : QUndoCommand(QCoreApplication::translate( "Undo Commands", "Change Tile Collision"), parent) , mTilesetDocument(tilesetDocument) , mTile(tile) , mObjectGroup(objectGroup) { } ChangeTileObjectGroup::~ChangeTileObjectGroup() { delete mObjectGroup; } void ChangeTileObjectGroup::swap() { mObjectGroup = mTile->swapObjectGroup(mObjectGroup); emit mTilesetDocument->tileObjectGroupChanged(mTile); } } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changetileobjectgroup.h000066400000000000000000000031031315121121300212070ustar00rootroot00000000000000/* * changetileobjectgroup.h * Copyright 2013, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include namespace Tiled { class ObjectGroup; class Tile; namespace Internal { class TilesetDocument; class ChangeTileObjectGroup : public QUndoCommand { public: /** * Creates a command that changes the ObjectGroup of the given \a tile. The * command takes ownership of the \a objectGroup. */ ChangeTileObjectGroup(TilesetDocument *tilesetDocument, Tile *tile, ObjectGroup *objectGroup, QUndoCommand *parent = nullptr); ~ChangeTileObjectGroup(); void undo() override { swap(); } void redo() override { swap(); } private: void swap(); TilesetDocument *mTilesetDocument; Tile *mTile; ObjectGroup *mObjectGroup; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changetileprobability.cpp000066400000000000000000000046241315121121300215500ustar00rootroot00000000000000/* * changetileprobability.cpp * Copyright 2015, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "changetileprobability.h" #include "tilesetdocument.h" #include "tile.h" #include namespace Tiled { namespace Internal { ChangeTileProbability::ChangeTileProbability(TilesetDocument *tilesetDocument, const QList& tiles, float probability) : mTilesetDocument(tilesetDocument) , mTiles(tiles) { mProbabilities.reserve(tiles.size()); for (int i = 0; i < tiles.size(); ++ i) mProbabilities.append(probability); setText(QCoreApplication::translate("Undo Commands", "Change Tile Probability")); } ChangeTileProbability::ChangeTileProbability(TilesetDocument *tilesetDocument, const QList &tiles, const QList &probabilities, QUndoCommand *parent) : QUndoCommand(parent) , mTilesetDocument(tilesetDocument) , mTiles(tiles) , mProbabilities(probabilities) { Q_ASSERT(mTiles.size() == mProbabilities.size()); setText(QCoreApplication::translate("Undo Commands", "Change Tile Probability")); } void ChangeTileProbability::swap() { for (int i = 0; i < mTiles.size(); ++ i) { Tile *tile = mTiles[i]; float probability = tile->probability(); tile->setProbability(mProbabilities[i]); mProbabilities[i] = probability; emit mTilesetDocument->tileProbabilityChanged(tile); } } } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changetileprobability.h000066400000000000000000000031011315121121300212020ustar00rootroot00000000000000/* * changetileprobability.h * Copyright 2015, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include namespace Tiled { class Tile; namespace Internal { class TilesetDocument; class ChangeTileProbability : public QUndoCommand { public: ChangeTileProbability(TilesetDocument *tilesetDocument, const QList &tiles, float probability); ChangeTileProbability(TilesetDocument *tilesetDocument, const QList &tiles, const QList &probabilities, QUndoCommand *parent = nullptr); void undo() override { swap(); } void redo() override { swap(); } private: void swap(); TilesetDocument *mTilesetDocument; QList mTiles; QList mProbabilities; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changetileterrain.cpp000066400000000000000000000072521315121121300206740ustar00rootroot00000000000000/* * changetileterrain.cpp * Copyright 2012, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "changetileterrain.h" #include "tilesetdocument.h" #include "tile.h" #include namespace Tiled { namespace Internal { ChangeTileTerrain::ChangeTileTerrain() : mTilesetDocument(nullptr) , mTileset(nullptr) , mMergeable(false) { initText(); } ChangeTileTerrain::ChangeTileTerrain(TilesetDocument *tilesetDocument, Tile *tile, unsigned terrain) : mTilesetDocument(tilesetDocument) , mTileset(tile->tileset()) , mMergeable(true) { initText(); mChanges.insert(tile, Change(tile->terrain(), terrain)); } ChangeTileTerrain::ChangeTileTerrain(TilesetDocument *tilesetDocument, const Changes &changes, QUndoCommand *parent) : QUndoCommand(parent) , mTilesetDocument(tilesetDocument) , mTileset(changes.begin().key()->tileset()) , mChanges(changes) , mMergeable(true) { initText(); } void ChangeTileTerrain::undo() { if (mChanges.isEmpty()) return; Changes::const_iterator i = mChanges.constBegin(); QList changedTiles; changedTiles.reserve(mChanges.size()); while (i != mChanges.constEnd()) { Tile *tile = i.key(); const Change &change = i.value(); tile->setTerrain(change.from); changedTiles.append(tile); ++i; } emit mTilesetDocument->tileTerrainChanged(changedTiles); } void ChangeTileTerrain::redo() { if (mChanges.isEmpty()) return; Changes::const_iterator i = mChanges.constBegin(); QList changedTiles; changedTiles.reserve(mChanges.size()); while (i != mChanges.constEnd()) { Tile *tile = i.key(); const Change &change = i.value(); tile->setTerrain(change.to); changedTiles.append(tile); ++i; } emit mTilesetDocument->tileTerrainChanged(changedTiles); } bool ChangeTileTerrain::mergeWith(const QUndoCommand *other) { if (!mMergeable) return false; const ChangeTileTerrain *o = static_cast(other); if (o->mTilesetDocument && !(mTilesetDocument == o->mTilesetDocument && mTileset == o->mTileset)) return false; Changes::const_iterator i = o->mChanges.constBegin(); Changes::const_iterator i_end = o->mChanges.constEnd(); while (i != i_end) { Tile *tile = i.key(); const Change &change = i.value(); Changes::iterator tileChange = mChanges.find(tile); if (tileChange != mChanges.end()) tileChange->to = change.to; else mChanges.insert(tile, change); ++i; } mMergeable = o->mMergeable; return true; } void ChangeTileTerrain::initText() { setText(QCoreApplication::translate("Undo Commands", "Change Tile Terrain")); } } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/changetileterrain.h000066400000000000000000000041311315121121300203320ustar00rootroot00000000000000/* * changetileterrain.h * Copyright 2012, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include #include "undocommands.h" namespace Tiled { class Tile; class Tileset; namespace Internal { class TilesetDocument; class ChangeTileTerrain : public QUndoCommand { public: struct Change { Change(unsigned from, unsigned to) : from(from), to(to) {} unsigned from; unsigned to; }; typedef QMap Changes; /** * Constructs an empty command that changes no terrain. When merged into * a previous terrain change command, it prevents that command from merging * with future commands. */ ChangeTileTerrain(); /** * Changes the terrain of \a tile. */ ChangeTileTerrain(TilesetDocument *tilesetDocument, Tile *tile, unsigned terrain); /** * Applies the given terrain \a changes. */ ChangeTileTerrain(TilesetDocument *tilesetDocument, const Changes &changes, QUndoCommand *parent = nullptr); void undo() override; void redo() override; int id() const override { return Cmd_ChangeTileTerrain; } bool mergeWith(const QUndoCommand *other) override; private: void initText(); TilesetDocument *mTilesetDocument; Tileset *mTileset; Changes mChanges; bool mMergeable; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/clickablelabel.cpp000066400000000000000000000022601315121121300201070ustar00rootroot00000000000000/* * clickablelabel.cpp * Copyright 2016, Ava Brumfield * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "clickablelabel.h" using namespace Tiled; using namespace Tiled::Internal; ClickableLabel::ClickableLabel(QWidget *parent) : QLabel(parent) { } void ClickableLabel::mouseMoveEvent(QMouseEvent *event) { emit mouseMoved(event); } void ClickableLabel::mousePressEvent(QMouseEvent *event) { emit mousePressed(event); } void ClickableLabel::mouseReleaseEvent(QMouseEvent *event) { emit mouseReleased(event); } tiled-1.0.3/src/tiled/clickablelabel.h000066400000000000000000000023771315121121300175650ustar00rootroot00000000000000/* * clickablelabel.h * Copyright 2016, Ava Brumfield * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include namespace Tiled { namespace Internal { class ClickableLabel : public QLabel { Q_OBJECT public: ClickableLabel(QWidget *parent = nullptr); signals: void mouseMoved(QMouseEvent *); void mousePressed(QMouseEvent *); void mouseReleased(QMouseEvent *); protected: void mouseMoveEvent(QMouseEvent *) override; void mousePressEvent(QMouseEvent *) override; void mouseReleaseEvent(QMouseEvent *) override; }; } // namespace Tiled } // namespace Internal tiled-1.0.3/src/tiled/clipboardmanager.cpp000066400000000000000000000170031315121121300204710ustar00rootroot00000000000000/* * clipboardmanager.cpp * Copyright 2009, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "clipboardmanager.h" #include "addremovemapobject.h" #include "map.h" #include "mapdocument.h" #include "mapobject.h" #include "maprenderer.h" #include "mapview.h" #include "objectgroup.h" #include "snaphelper.h" #include "tmxmapformat.h" #include "tile.h" #include "tilelayer.h" #include #include #include #include #include #include static const char * const TMX_MIMETYPE = "text/tmx"; using namespace Tiled; using namespace Tiled::Internal; ClipboardManager *ClipboardManager::mInstance; ClipboardManager::ClipboardManager() : mClipboard(QApplication::clipboard()) , mHasMap(false) , mHasProperties(false) { connect(mClipboard, &QClipboard::dataChanged, this, &ClipboardManager::update); update(); } /** * Returns the clipboard manager instance. Creates the instance when it * doesn't exist yet. */ ClipboardManager *ClipboardManager::instance() { if (!mInstance) mInstance = new ClipboardManager; return mInstance; } /** * Deletes the clipboard manager instance if it exists. */ void ClipboardManager::deleteInstance() { delete mInstance; mInstance = nullptr; } /** * Retrieves the map from the clipboard. Returns null when there was no map or * loading failed. */ Map *ClipboardManager::map() const { const QMimeData *mimeData = mClipboard->mimeData(); const QByteArray data = mimeData->data(QLatin1String(TMX_MIMETYPE)); if (data.isEmpty()) return nullptr; TmxMapFormat format; return format.fromByteArray(data); } /** * Sets the given map on the clipboard. */ void ClipboardManager::setMap(const Map &map) { TmxMapFormat format; QMimeData *mimeData = new QMimeData; mimeData->setData(QLatin1String(TMX_MIMETYPE), format.toByteArray(&map)); mClipboard->setMimeData(mimeData); } Properties ClipboardManager::properties() const { const QMimeData *mimeData = mClipboard->mimeData(); const QByteArray data = mimeData->data(QLatin1String(PROPERTIES_MIMETYPE)); const QJsonDocument document = QJsonDocument::fromBinaryData(data); return Properties::fromJson(document.array()); } void ClipboardManager::setProperties(const Properties &properties) { const QJsonDocument document(properties.toJson()); QMimeData *mimeData = new QMimeData; mimeData->setData(QLatin1String(PROPERTIES_MIMETYPE), document.toBinaryData()); mimeData->setText(QString::fromUtf8(document.toJson())); mClipboard->setMimeData(mimeData); } /** * Convenience method to copy the current selection to the clipboard. * Deals with either tile selection or object selection. */ void ClipboardManager::copySelection(const MapDocument *mapDocument) { const Layer *currentLayer = mapDocument->currentLayer(); if (!currentLayer) return; const Map *map = mapDocument->map(); const QRegion &selectedArea = mapDocument->selectedArea(); const QList &selectedObjects = mapDocument->selectedObjects(); const TileLayer *tileLayer = dynamic_cast(currentLayer); Layer *copyLayer = nullptr; if (!selectedArea.isEmpty() && tileLayer) { const QRegion area = selectedArea.intersected(tileLayer->bounds()); // Copy the selected part of the layer copyLayer = tileLayer->copy(area.translated(-tileLayer->position())); copyLayer->setPosition(area.boundingRect().topLeft()); } else if (!selectedObjects.isEmpty()) { // Create a new object group with clones of the selected objects ObjectGroup *objectGroup = new ObjectGroup; for (const MapObject *mapObject : selectedObjects) objectGroup->addObject(mapObject->clone()); copyLayer = objectGroup; } else { return; } // Create a temporary map to write to the clipboard Map copyMap(map->orientation(), 0, 0, map->tileWidth(), map->tileHeight()); copyMap.setRenderOrder(map->renderOrder()); // Resolve the set of tilesets used by this layer foreach (const SharedTileset &tileset, copyLayer->usedTilesets()) copyMap.addTileset(tileset); copyMap.addLayer(copyLayer); setMap(copyMap); } /** * Convenience method that deals with some of the logic related to pasting * a group of objects. */ void ClipboardManager::pasteObjectGroup(const ObjectGroup *objectGroup, MapDocument *mapDocument, const MapView *view, PasteFlags flags) { Layer *currentLayer = mapDocument->currentLayer(); if (!currentLayer) return; ObjectGroup *currentObjectGroup = currentLayer->asObjectGroup(); if (!currentObjectGroup) return; QPointF insertPos; if (!(flags & PasteInPlace)) { // Determine where to insert the objects const MapRenderer *renderer = mapDocument->renderer(); const QPointF center = objectGroup->objectsBoundingRect().center(); // Take the mouse position if the mouse is on the view, otherwise // take the center of the view. QPoint viewPos; if (view->underMouse()) viewPos = view->mapFromGlobal(QCursor::pos()); else viewPos = QPoint(view->width() / 2, view->height() / 2); const QPointF scenePos = view->mapToScene(viewPos); insertPos = renderer->screenToPixelCoords(scenePos) - center; SnapHelper(renderer).snap(insertPos); } QUndoStack *undoStack = mapDocument->undoStack(); QList pastedObjects; pastedObjects.reserve(objectGroup->objectCount()); undoStack->beginMacro(tr("Paste Objects")); for (const MapObject *mapObject : objectGroup->objects()) { if (flags & PasteNoTileObjects && !mapObject->cell().isEmpty()) continue; MapObject *objectClone = mapObject->clone(); objectClone->resetId(); objectClone->setPosition(objectClone->position() + insertPos); pastedObjects.append(objectClone); undoStack->push(new AddMapObject(mapDocument, currentObjectGroup, objectClone)); } undoStack->endMacro(); mapDocument->setSelectedObjects(pastedObjects); } void ClipboardManager::update() { bool hasMap = false; bool hasProperties = false; if (const QMimeData *data = mClipboard->mimeData()) { hasMap = data->hasFormat(QLatin1String(TMX_MIMETYPE)); hasProperties = data->hasFormat(QLatin1String(PROPERTIES_MIMETYPE)); } if (hasMap != mHasMap) { mHasMap = hasMap; emit hasMapChanged(); } if (hasProperties != mHasProperties) { mHasProperties = hasProperties; emit hasPropertiesChanged(); } } tiled-1.0.3/src/tiled/clipboardmanager.h000066400000000000000000000047441315121121300201460ustar00rootroot00000000000000/* * clipboardmanager.h * Copyright 2009, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "properties.h" #include class QClipboard; namespace Tiled { class ObjectGroup; class Map; namespace Internal { class MapDocument; class MapView; /** * The clipboard manager deals with interaction with the clipboard. */ class ClipboardManager : public QObject { Q_OBJECT public: static ClipboardManager *instance(); static void deleteInstance(); bool hasMap() const; Map *map() const; void setMap(const Map &map); bool hasProperties() const; Properties properties() const; void setProperties(const Properties &properties); void copySelection(const MapDocument *mapDocument); enum PasteFlag { PasteDefault = 0x0, PasteNoTileObjects = 0x1, PasteInPlace = 0x2, }; Q_DECLARE_FLAGS(PasteFlags, PasteFlag) Q_FLAGS(PasteFlags) void pasteObjectGroup(const ObjectGroup *objectGroup, MapDocument *mapDocument, const MapView *view, PasteFlags flags = PasteDefault); signals: void hasMapChanged(); void hasPropertiesChanged(); private slots: void update(); private: ClipboardManager(); Q_DISABLE_COPY(ClipboardManager) QClipboard *mClipboard; bool mHasMap; bool mHasProperties; static ClipboardManager *mInstance; }; /** * Returns whether the clipboard has a map. */ inline bool ClipboardManager::hasMap() const { return mHasMap; } /** * Returns whether the clipboard holds some custom properties. */ inline bool ClipboardManager::hasProperties() const { return mHasProperties; } Q_DECLARE_OPERATORS_FOR_FLAGS(ClipboardManager::PasteFlags) } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/colorbutton.cpp000066400000000000000000000044201315121121300175500ustar00rootroot00000000000000/* * colorbutton.cpp * Copyright 2009, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "colorbutton.h" #include #include #include #include using namespace Tiled; using namespace Tiled::Internal; ColorButton::ColorButton(QWidget *parent) : QToolButton(parent) { int defaultIconSize = style()->pixelMetric(QStyle::PM_ButtonIconSize); setIconSize(QSize(defaultIconSize * 2, defaultIconSize)); setColor(Qt::white); connect(this, &QToolButton::clicked, this, &ColorButton::pickColor); } void ColorButton::setColor(const QColor &color) { if (mColor == color || !color.isValid()) return; mColor = color; updateIcon(); emit colorChanged(color); } void ColorButton::changeEvent(QEvent *e) { QToolButton::changeEvent(e); switch (e->type()) { case QEvent::StyleChange: { int defaultIconSize = style()->pixelMetric(QStyle::PM_ButtonIconSize); setIconSize(QSize(defaultIconSize * 2, defaultIconSize)); updateIcon(); break; } default: break; } } void ColorButton::pickColor() { QColor newColor = QColorDialog::getColor(mColor, this); if (newColor.isValid()) setColor(newColor); } void ColorButton::updateIcon() { QSize size(iconSize()); size.rwidth() -= 2; size.rheight() -= 2; QPixmap pixmap(size); pixmap.fill(mColor); QPainter painter(&pixmap); QColor border(Qt::black); border.setAlpha(128); painter.setPen(border); painter.drawRect(0, 0, pixmap.width() - 1, pixmap.height() - 1); setIcon(QIcon(pixmap)); } tiled-1.0.3/src/tiled/colorbutton.h000066400000000000000000000026541315121121300172240ustar00rootroot00000000000000/* * colorbutton.h * Copyright 2009, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include namespace Tiled { namespace Internal { /** * A tool button for letting the user pick a color. When clicked it shows a * color dialog and it has an icon to represent the currently chosen color. */ class ColorButton : public QToolButton { Q_OBJECT public: ColorButton(QWidget *parent = nullptr); QColor color() const { return mColor; } void setColor(const QColor &color); signals: void colorChanged(const QColor &color); protected: void changeEvent(QEvent *e) override; private: void pickColor(); void updateIcon(); QColor mColor; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/command.cpp000066400000000000000000000162251315121121300166220ustar00rootroot00000000000000/* * command.cpp * Copyright 2011, Jeff Bland * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "command.h" #include "documentmanager.h" #include "mapdocument.h" #include "mapobject.h" #include #include using namespace Tiled; using namespace Tiled::Internal; QString Command::finalCommand() const { QString finalCommand = command; // Perform variable replacement if (Document *document = DocumentManager::instance()->currentDocument()) { const QString fileName = document->fileName(); finalCommand.replace(QLatin1String("%mapfile"), QString(QLatin1String("\"%1\"")).arg(fileName)); QFileInfo fileInfo(fileName); QString mapPath = fileInfo.absolutePath(); finalCommand.replace( QLatin1String("%mappath"), QString(QLatin1String("\"%1\"")).arg(mapPath)); if (MapDocument *mapDocument = qobject_cast(document)) { if (const Layer *layer = mapDocument->currentLayer()) { finalCommand.replace(QLatin1String("%layername"), QString(QLatin1String("\"%1\"")).arg(layer->name())); } } if (MapObject *currentObject = dynamic_cast(document->currentObject())) { finalCommand.replace(QLatin1String("%objecttype"), QString(QLatin1String("\"%1\"")).arg(currentObject->type())); finalCommand.replace(QLatin1String("%objectid"), QString(QLatin1String("\"%1\"")).arg(currentObject->id())); } } return finalCommand; } void Command::execute(bool inTerminal) const { if (saveBeforeExecute) { Document *document = DocumentManager::instance()->currentDocument(); if (document) document->save(document->fileName()); } // Start the process new CommandProcess(*this, inTerminal); } QVariant Command::toQVariant() const { QHash hash; hash[QLatin1String("Enabled")] = isEnabled; hash[QLatin1String("Name")] = name; hash[QLatin1String("Command")] = command; hash[QLatin1String("Shortcut")] = shortcut; hash[QLatin1String("SaveBeforeExecute")] = saveBeforeExecute; return hash; } Command Command::fromQVariant(const QVariant &variant) { const QHash hash = variant.toHash(); const QString namePref = QLatin1String("Name"); const QString commandPref = QLatin1String("Command"); const QString enablePref = QLatin1String("Enabled"); const QString shortcutPref = QLatin1String("Shortcut"); const QString saveBeforeExecutePref = QLatin1String("SaveBeforeExecute"); Command command; if (hash.contains(enablePref)) command.isEnabled = hash[enablePref].toBool(); if (hash.contains(namePref)) command.name = hash[namePref].toString(); if (hash.contains(commandPref)) command.command = hash[commandPref].toString(); if (hash.contains(shortcutPref)) command.shortcut = hash[shortcutPref].value(); if (hash.contains(saveBeforeExecutePref)) command.saveBeforeExecute = hash[saveBeforeExecutePref].toBool(); return command; } CommandProcess::CommandProcess(const Command &command, bool inTerminal) : QProcess(DocumentManager::instance()) , mName(command.name) , mFinalCommand(command.finalCommand()) #ifdef Q_OS_MAC , mFile(QDir::tempPath() + QLatin1String("/tiledXXXXXX.command")) #endif { // Give an error if the command is empty or just whitespace if (mFinalCommand.trimmed().isEmpty()) { handleError(QProcess::FailedToStart); return; } // Modify the command to run in a terminal if (inTerminal) { #ifdef Q_OS_LINUX static bool hasGnomeTerminal = QProcess::execute( QLatin1String("which gnome-terminal")) == 0; if (hasGnomeTerminal) mFinalCommand = QLatin1String("gnome-terminal -x ") + mFinalCommand; else mFinalCommand = QLatin1String("xterm -e ") + mFinalCommand; #elif defined(Q_OS_MAC) // The only way I know to launch a Terminal with a command on mac is // to make a .command file and open it. The client command invoke the // executable directly (rather than using open) in order to get std // output in the terminal. Otherwise, you can use the Console // application to see the output. // Create and write the command to a .command file if (!mFile.open()) { handleError(tr("Unable to create/open %1").arg(mFile.fileName())); return; } mFile.write(mFinalCommand.toLocal8Bit()); mFile.close(); // Add execute permission to the file int chmodRet = QProcess::execute(QString(QLatin1String( "chmod +x \"%1\"")).arg(mFile.fileName())); if (chmodRet != 0) { handleError(tr("Unable to add executable permissions to %1") .arg(mFile.fileName())); return; } // Use open command to launch the command in the terminal // -W makes it not return immediately // -n makes it open a new instance of terminal if it is open already mFinalCommand = QString(QLatin1String("open -W -n \"%1\"")) .arg(mFile.fileName()); #endif } connect(this, SIGNAL(error(QProcess::ProcessError)), SLOT(handleError(QProcess::ProcessError))); connect(this, SIGNAL(finished(int)), SLOT(deleteLater())); start(mFinalCommand); } void CommandProcess::handleError(QProcess::ProcessError error) { QString errorStr; switch (error) { case QProcess::FailedToStart: errorStr = tr("The command failed to start."); break; case QProcess::Crashed: errorStr = tr("The command crashed."); break; case QProcess::Timedout: errorStr = tr("The command timed out."); break; default: errorStr = tr("An unknown error occurred."); } handleError(errorStr); } void CommandProcess::handleError(const QString &error) { QString title = tr("Error Executing %1").arg(mName); QString message = error + QLatin1String("\n\n") + mFinalCommand; QWidget *parent = DocumentManager::instance()->widget(); QMessageBox::warning(parent, title, message); // Make sure this object gets deleted if the process failed to start deleteLater(); } tiled-1.0.3/src/tiled/command.h000066400000000000000000000044321315121121300162640ustar00rootroot00000000000000/* * command.h * Copyright 2011, Jeff Bland * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include #include #include #ifdef Q_OS_MAC #include #endif namespace Tiled { namespace Internal { struct Command { Command(bool isEnabled = true, QString name = QString(), QString command = QString(), QKeySequence shortcut = QKeySequence(), bool saveBeforeExecute = true) : isEnabled(isEnabled) , name(std::move(name)) , command(std::move(command)) , shortcut(shortcut) , saveBeforeExecute(saveBeforeExecute) {} bool isEnabled; QString name; QString command; QKeySequence shortcut; bool saveBeforeExecute; /** * Returns the final command with replaced tokens. */ QString finalCommand() const; /** * Executes the command in the operating system shell or terminal * application. */ void execute(bool inTerminal = false) const; /** * Stores this command in a QVariant. */ QVariant toQVariant() const; /** * Generates a command from a QVariant. */ static Command fromQVariant(const QVariant &variant); }; class CommandProcess : public QProcess { Q_OBJECT public: CommandProcess(const Command &command, bool inTerminal = false); private slots: void handleError(QProcess::ProcessError); private: void handleError(const QString &); QString mName; QString mFinalCommand; #ifdef Q_OS_MAC QTemporaryFile mFile; #endif }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/commandbutton.cpp000066400000000000000000000055771315121121300200660ustar00rootroot00000000000000/* * commandbutton.cpp * Copyright 2010, Jeff Bland * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "commandbutton.h" #include "commanddatamodel.h" #include "commanddialog.h" #include "commandmanager.h" #include "utils.h" #include #include #include using namespace Tiled; using namespace Tiled::Utils; using namespace Tiled::Internal; CommandButton::CommandButton(QWidget *parent) : QToolButton(parent) , mMenu(new QMenu(this)) { setIcon(QIcon(QLatin1String(":images/24x24/system-run.png"))); setThemeIcon(this, "system-run"); retranslateUi(); setPopupMode(QToolButton::MenuButtonPopup); setMenu(mMenu); CommandManager::instance()->registerMenu(mMenu); connect(this, SIGNAL(clicked()), SLOT(runCommand())); } void CommandButton::runCommand() { Command command; QAction *action = dynamic_cast(sender()); if (action && action->data().isValid()) { //run the command passed by the action command = Command::fromQVariant(action->data()); } else { //run the default command command = CommandDataModel().firstEnabledCommand(); if (!command.isEnabled) { QMessageBox msgBox(window()); msgBox.setIcon(QMessageBox::Warning); msgBox.setWindowTitle(tr("Error Executing Command")); msgBox.setText(tr("You do not have any commands setup.")); msgBox.addButton(QMessageBox::Ok); msgBox.addButton(tr("Edit commands..."), QMessageBox::ActionRole); msgBox.setDefaultButton(QMessageBox::Ok); msgBox.setEscapeButton(QMessageBox::Ok); QAbstractButton *button = msgBox.buttons().last(); connect(button, SIGNAL(clicked()), SLOT(showDialog())); msgBox.exec(); return; } } command.execute(); } void CommandButton::showDialog() { CommandDialog dialog(window()); dialog.exec(); } void CommandButton::changeEvent(QEvent *event) { QToolButton::changeEvent(event); switch (event->type()) { case QEvent::LanguageChange: retranslateUi(); break; default: break; } } void CommandButton::retranslateUi() { setToolTip(tr("Execute Command")); } tiled-1.0.3/src/tiled/commandbutton.h000066400000000000000000000023031315121121300175130ustar00rootroot00000000000000/* * commandbutton.h * Copyright 2010, Jeff Bland * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include class QMenu; namespace Tiled { namespace Internal { class MainWindow; class DocumentManager; class CommandButton : public QToolButton { Q_OBJECT public: CommandButton(QWidget *parent); protected: void changeEvent(QEvent *event) override; private slots: void runCommand(); void showDialog(); private: void retranslateUi(); QMenu *mMenu; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/commanddatamodel.cpp000066400000000000000000000372441315121121300205010ustar00rootroot00000000000000/* * commanddatamodel.cpp * Copyright 2010, Jeff Bland * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "commanddatamodel.h" #include #include #include #include using namespace Tiled; using namespace Tiled::Internal; const char *commandMimeType = "application/x-tiled-commandptr"; CommandDataModel::CommandDataModel(QObject *parent) : QAbstractTableModel(parent) { // Load command list const QVariant variant = mSettings.value(QLatin1String("commandList")); const QList commands = variant.toList(); for (const QVariant &commandVariant : commands) mCommands.append(Command::fromQVariant(commandVariant)); // Add default commands the first time the app has booted up. // This is useful on its own and helps demonstrate how to use the commands. const QString addedDefaultKey = QLatin1String("addedDefaultCommands"); const bool addedDefault = mSettings.value(addedDefaultKey, false).toBool(); if (!addedDefault) { // Disable default commands by default so user gets an informative // warning when clicking the command button for the first time Command command(false); #ifdef Q_OS_LINUX command.command = QLatin1String("gedit %mapfile"); #elif defined(Q_OS_MAC) command.command = QLatin1String("open -t %mapfile"); #endif if (!command.command.isEmpty()) { command.name = tr("Open in text editor"); mCommands.push_back(command); } commit(); mSettings.setValue(addedDefaultKey, true); } } void CommandDataModel::commit() { // Save command list QList commands; foreach (const Command &command, mCommands) commands.append(command.toQVariant()); mSettings.setValue(QLatin1String("commandList"), commands); } Command CommandDataModel::firstEnabledCommand() const { for (const Command &command : mCommands) if (command.isEnabled) return command; return Command(false); } bool CommandDataModel::removeRows(int row, int count, const QModelIndex &parent) { if (row < 0 || row + count > mCommands.size()) return false; beginRemoveRows(parent, row, row + count); mCommands.erase(mCommands.begin() + row, mCommands.begin() + row + count); endRemoveRows(); return true; } void CommandDataModel::removeRows(QModelIndexList indices) { while (!indices.empty()) { const int row = indices.takeFirst().row(); if (row >= mCommands.size()) continue; beginRemoveRows(QModelIndex(), row, row); mCommands.removeAt(row); // Decrement later indices since we removed a row for (QModelIndex &index : indices) if (index.row() > row) index = index.sibling(index.row() - 1, index.column()); endRemoveRows(); } } int CommandDataModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : mCommands.size() + 1; } int CommandDataModel::columnCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : 3; } QVariant CommandDataModel::data(const QModelIndex &index, int role) const { const bool isNormalRow = index.row() < mCommands.size(); Command command; if (isNormalRow) command = mCommands[index.row()]; switch (role) { case Qt::DisplayRole: case Qt::EditRole: if (isNormalRow) { if (index.column() == NameColumn) return command.name; if (index.column() == ShortcutColumn) return command.shortcut; } else { if (index.column() == NameColumn) { if (role == Qt::EditRole) return QString(); else return tr(""); } } break; case Qt::ToolTipRole: if (isNormalRow) { if (index.column() == NameColumn) return tr("Set a name for this command"); if (index.column() == ShortcutColumn) return tr("Shortcut for this command"); if (index.column() == EnabledColumn) return tr("Show or hide this command in the command list"); } else if (index.column() == NameColumn) return tr("Add a new command"); break; case Qt::CheckStateRole: if (isNormalRow && index.column() == EnabledColumn) return command.isEnabled ? 2 : 0; break; } return QVariant(); } bool CommandDataModel::setData(const QModelIndex &index, const QVariant &value, int role) { const bool isNormalRow = index.row() < mCommands.size(); bool isModified = false; bool shouldAppend = false; Command command; if (isNormalRow) { // Get the command as it exists already command = mCommands[index.row()]; // Modify the command based on the passed date switch (role) { case Qt::EditRole: { const QString text = value.toString(); if (!text.isEmpty()) { if (index.column() == NameColumn) { command.name = value.toString(); isModified = true; } } break; } case Qt::CheckStateRole: if (index.column() == EnabledColumn) { command.isEnabled = value.toInt() > 0; isModified = true; } break; } } else { // If final row was edited, insert the new command if (role == Qt::EditRole && index.column() == NameColumn) { command.name = value.toString(); if (!command.name.isEmpty() && command.name != tr("")) { isModified = true; shouldAppend = true; } } } if (isModified) { // Write the modified command to our cache if (shouldAppend) mCommands.push_back(command); else mCommands[index.row()] = command; // Reset if there could be new rows or reordering, else emit dataChanged if (shouldAppend || index.column() == NameColumn) { beginResetModel(); endResetModel(); } else { emit dataChanged(index, index); } } return isModified; } Qt::ItemFlags CommandDataModel::flags(const QModelIndex &index) const { const bool isNormalRow = index.row() < mCommands.size(); Qt::ItemFlags f = QAbstractTableModel::flags(index); if (isNormalRow) { f |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; if (index.column() == EnabledColumn) f |= Qt::ItemIsUserCheckable; else if (index.column() == NameColumn) f |= Qt::ItemIsEditable; } else { f |= Qt::ItemIsDropEnabled; if (index.column() == NameColumn) f |= Qt::ItemIsEditable; } return f; } QVariant CommandDataModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role != Qt::DisplayRole || orientation != Qt::Horizontal) return QVariant(); const char *sectionLabels[3] = { QT_TR_NOOP("Name"), QT_TR_NOOP("Shortcut"), QT_TR_NOOP("Enable") }; return tr(sectionLabels[section]); } QMenu *CommandDataModel::contextMenu(QWidget *parent, const QModelIndex &index) { QMenu *menu = nullptr; const int row = index.row(); if (row >= 0 && row < mCommands.size()) { menu = new QMenu(parent); if (row > 0) { QAction *action = menu->addAction(tr("Move Up")); QSignalMapper *mapper = new QSignalMapper(action); mapper->setMapping(action, row); connect(action, SIGNAL(triggered()), mapper, SLOT(map())); connect(mapper, SIGNAL(mapped(int)), SLOT(moveUp(int))); } if (row+1 < mCommands.size()) { QAction *action = menu->addAction(tr("Move Down")); QSignalMapper *mapper = new QSignalMapper(action); mapper->setMapping(action, row + 1); connect(action, SIGNAL(triggered()), mapper, SLOT(map())); connect(mapper, SIGNAL(mapped(int)), SLOT(moveUp(int))); } menu->addSeparator(); { QAction *action = menu->addAction(tr("Execute")); QSignalMapper *mapper = new QSignalMapper(action); mapper->setMapping(action, row); connect(action, SIGNAL(triggered()), mapper, SLOT(map())); connect(mapper, SIGNAL(mapped(int)), SLOT(execute(int))); } #if defined(Q_OS_LINUX) || defined(Q_OS_MAC) { QAction *action = menu->addAction(tr("Execute in Terminal")); QSignalMapper *mapper = new QSignalMapper(action); mapper->setMapping(action, row); connect(action, SIGNAL(triggered()), mapper, SLOT(map())); connect(mapper, SIGNAL(mapped(int)), SLOT(executeInTerminal(int))); } #endif menu->addSeparator(); { QAction *action = menu->addAction(tr("Delete")); QSignalMapper *mapper = new QSignalMapper(action); mapper->setMapping(action, row); connect(action, SIGNAL(triggered()), mapper, SLOT(map())); connect(mapper, SIGNAL(mapped(int)), SLOT(remove(int))); } } return menu; } QMimeData *CommandDataModel::mimeData(const QModelIndexList &indices) const { int row = -1; for (const QModelIndex &index : indices) { // Only generate mime data on command rows if (index.row() < 0 || index.row() >= mCommands.size()) return nullptr; // Currently only one row at a time is supported for drags // Note: we can get multiple indexes in the same row (different columns) if (row != -1 && index.row() != row) return nullptr; row = index.row(); } const Command &command = mCommands[row]; QMimeData* mimeData = new QMimeData(); // Text data is used if command is dragged to a text editor or terminal mimeData->setText(command.finalCommand()); // Ptr is used if command is dragged onto another command // We could store the index instead, the only difference would be that if // the item is moved or deleted somehow during the drag, the ptr approach // will result in a no-op instead of moving the wrong thing. const Command *addr = &command; mimeData->setData(QLatin1String(commandMimeType), QByteArray((const char *)&addr, sizeof(addr))); return mimeData; } QStringList CommandDataModel::mimeTypes() const { QStringList result(QLatin1String("text/plain")); result.append(QLatin1String(commandMimeType)); return result; } Qt::DropActions CommandDataModel::supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; } bool CommandDataModel::dropMimeData(const QMimeData *data, Qt::DropAction, int, int, const QModelIndex &parent) { if (!parent.isValid()) return false; const int dstRow = parent.row(); if (data->hasFormat(QLatin1String(commandMimeType))) { // Get the ptr to the command that was being dragged const QByteArray byteData = data->data(QLatin1String(commandMimeType)); Q_ASSERT(byteData.length() == sizeof(Command*)); const Command *addr = *(Command**)byteData.data(); // Find the command in the command list so we can move/copy it for (int srcRow = 0; srcRow < mCommands.size(); ++srcRow) if (addr == &mCommands[srcRow]) { // If a command is dropped on another command, // move the src command into the position of the dst command. if (dstRow < mCommands.size()) return move(srcRow, dstRow); // If a command is dropped elsewhere, create a copy of it if (dstRow == mCommands.size()) { append(Command(addr->isEnabled, tr("%1 (copy)").arg(addr->name), addr->command)); return true; } } } if (data->hasText()) { // If text is dropped on a valid command, just replace the data if (dstRow < mCommands.size()) return setData(parent, data->text(), Qt::EditRole); // If text is dropped elsewhere, create a new command // Assume the dropped text is the command, not the name if (dstRow == mCommands.size()) { append(Command(true, tr("New command"), data->text())); return true; } } return false; } void CommandDataModel::setCommand(const QModelIndex &index, const QString &value) { const bool isNormalRow = index.row() < mCommands.size(); if (isNormalRow) mCommands[index.row()].command = value; } void CommandDataModel::setShortcut(const QModelIndex &index, const QKeySequence &value) { const bool isNormalRow = index.row() < mCommands.size(); if (isNormalRow) { mCommands[index.row()].shortcut = value; QModelIndex shortcutIndex = this->index(index.row(), ShortcutColumn); emit dataChanged(shortcutIndex, shortcutIndex); } } void CommandDataModel::setSaveBeforeExecute(const QModelIndex &index, bool value) { const bool isNormalRow = index.row() < mCommands.size(); if (isNormalRow) mCommands[index.row()].saveBeforeExecute = value; } Command CommandDataModel::command(const QModelIndex &index) const { const bool isNormalRow = index.row() < mCommands.size(); if (isNormalRow) return mCommands[index.row()]; else return Command(); } bool CommandDataModel::move(int commandIndex, int newIndex) { if (commandIndex < 0 || commandIndex >= mCommands.size() || newIndex < 0 || newIndex >= mCommands.size() || newIndex == commandIndex) return false; if (!beginMoveRows(QModelIndex(), commandIndex, commandIndex, QModelIndex(), newIndex > commandIndex ? newIndex + 1 : newIndex)) return false; if (commandIndex - newIndex == 1 || newIndex - commandIndex == 1) // Swapping is probably more efficient than removing/inserting mCommands.swap(commandIndex, newIndex); else { const Command command = mCommands.at(commandIndex); mCommands.removeAt(commandIndex); mCommands.insert(newIndex, command); } endMoveRows(); return true; } void CommandDataModel::append(const Command &command) { beginInsertRows(QModelIndex(), mCommands.size(), mCommands.size()); mCommands.append(command); endInsertRows(); } void CommandDataModel::moveUp(int commandIndex) { move(commandIndex, commandIndex - 1); } void CommandDataModel::execute(int commandIndex) const { mCommands.at(commandIndex).execute(); } void CommandDataModel::executeInTerminal(int commandIndex) const { mCommands.at(commandIndex).execute(true); } void CommandDataModel::remove(int commandIndex) { removeRow(commandIndex); } tiled-1.0.3/src/tiled/commanddatamodel.h000066400000000000000000000114561315121121300201430ustar00rootroot00000000000000/* * commanddatamodel.h * Copyright 2010, Jeff Bland * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "command.h" #include #include class QMenu; namespace Tiled { namespace Internal { class CommandDataModel : public QAbstractTableModel { Q_OBJECT public: enum { NameColumn, ShortcutColumn, EnabledColumn }; /** * Constructs the object and parses the users settings to allow easy * programmatic access to the command list. */ CommandDataModel(QObject *parent = nullptr); /** * Saves the data to the users preferences. */ void commit(); Command firstEnabledCommand() const; /** * Returns a list of all the commands. */ const QList &allCommands() const { return mCommands; } /** * Remove the given row or rows from the model. */ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; /** * Deletes the commands associated with the given row indices. */ void removeRows(QModelIndexList indices); /** * Returns the number of rows (this includes the row). */ int rowCount(const QModelIndex &parent = QModelIndex()) const override; /** * Returns the number of columns. */ int columnCount(const QModelIndex &parent = QModelIndex()) const override; /** * Returns the data at index for the given role. */ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; /** * Sets the data at index to the given value. * for the given role */ bool setData(const QModelIndex &index, const QVariant &value, int role) override; /** * Returns flags for the item at index. */ Qt::ItemFlags flags(const QModelIndex &index) const override; /** * Returns the header data for the given section and role. * orientation should be Qt::Horizontal. */ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::EditRole) const override; /** * Returns a menu containing a list of appropriate actions for the item at * index, or 0 if there are no actions for the index. */ QMenu *contextMenu(QWidget *parent, const QModelIndex &index); /** * Returns mime data for the first index in indexes. */ QMimeData *mimeData(const QModelIndexList &indexes) const override; /** * Returns a list of mime types that can represent a command. */ QStringList mimeTypes() const override; /** * Returns the drop actions that can be performed. */ Qt::DropActions supportedDropActions() const override; /** * Handles dropping of mime data onto parent. */ bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override; void setCommand(const QModelIndex &index, const QString &value); void setShortcut(const QModelIndex &index, const QKeySequence &value); void setSaveBeforeExecute(const QModelIndex &index, bool value); Command command(const QModelIndex &index) const; public slots: /** * Moves the command at commandIndex to newIndex>. */ bool move(int commandIndex, int newIndex); /** * Appends command to the command list. */ void append(const Command &command); /** * Moves the command at commandIndex up one index, if possible. */ void moveUp(int commandIndex); /** * Executes the command at commandIndex. */ void execute(int commandIndex) const; /** * Executes the command at commandIndex within the systems native * terminal if available. */ void executeInTerminal(int commandIndex) const; /** * Deletes the command at commandIndex. */ void remove(int commandIndex); private: QSettings mSettings; QList mCommands; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/commanddialog.cpp000066400000000000000000000135721315121121300200040ustar00rootroot00000000000000/* * commanddialog.cpp * Copyright 2010, Jeff Bland * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "commanddialog.h" #include "ui_commanddialog.h" #include "commanddatamodel.h" #include "commandmanager.h" #include "utils.h" #include #include #include #include #include #include using namespace Tiled; using namespace Tiled::Internal; CommandDialog::CommandDialog(QWidget *parent) : QDialog(parent) , mUi(new Ui::CommandDialog) { mUi->setupUi(this); resize(Utils::dpiScaled(size())); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); setWindowTitle(tr("Edit Commands")); Utils::restoreGeometry(this); connect(mUi->saveBox, &QCheckBox::stateChanged, this, &CommandDialog::setSaveBeforeExecute); connect(mUi->keySequenceEdit, &QKeySequenceEdit::keySequenceChanged, this, &CommandDialog::setShortcut); connect(mUi->commandEdit, &QLineEdit::textChanged, this, &CommandDialog::setCommand); connect(mUi->treeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &CommandDialog::updateWidgets); connect(mUi->browseButton, &QPushButton::clicked, this, &CommandDialog::openFileDialog); } CommandDialog::~CommandDialog() { Utils::saveGeometry(this); delete mUi; } void CommandDialog::closeEvent(QCloseEvent *event) { QDialog::closeEvent(event); mUi->treeView->model()->commit(); CommandManager::instance()->updateActions(); } void CommandDialog::setShortcut(const QKeySequence &keySequence) { const QModelIndex ¤t = mUi->treeView->currentIndex(); if (current.row() < mUi->treeView->model()->rowCount()) mUi->treeView->model()->setShortcut(current, keySequence); } void CommandDialog::setSaveBeforeExecute(int state) { const QModelIndex ¤t = mUi->treeView->currentIndex(); if (current.row() < mUi->treeView->model()->rowCount()) mUi->treeView->model()->setSaveBeforeExecute(current, state); } void CommandDialog::setCommand(const QString &text) { const QModelIndex ¤t = mUi->treeView->currentIndex(); if (current.row() < mUi->treeView->model()->rowCount()) mUi->treeView->model()->setCommand(current, text); } void CommandDialog::updateWidgets(const QModelIndex ¤t, const QModelIndex &) { bool enable = (current.row() < mUi->treeView->model()->rowCount() - 1); mUi->saveBox->setEnabled(enable); mUi->commandEdit->setEnabled(enable); mUi->browseButton->setEnabled(enable); mUi->keySequenceEdit->setEnabled(enable); mUi->clearButton->setEnabled(enable); mUi->saveBox->setEnabled(enable); if (enable) { const Command command = mUi->treeView->model()->command(current); mUi->commandEdit->setText(command.command); mUi->keySequenceEdit->setKeySequence(command.shortcut); mUi->saveBox->setChecked(command.saveBeforeExecute); } else { mUi->commandEdit->clear(); mUi->keySequenceEdit->clear(); } } void CommandDialog::openFileDialog() { QString caption = tr("Select Executable"); QString dir = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation); QString executableName = QFileDialog::getOpenFileName(this, caption, dir); if (!executableName.isEmpty()) mUi->commandEdit->setText(executableName); } CommandTreeView::CommandTreeView(QWidget *parent) : QTreeView(parent) , mModel(CommandManager::instance()->commandDataModel()) { setModel(mModel); setRootIsDecorated(false); // Setup resizing so the command column stretches setColumnWidth(0, 200); QHeaderView *h = header(); h->setStretchLastSection(false); h->setSectionResizeMode(CommandDataModel::NameColumn, QHeaderView::Stretch); h->setSectionResizeMode(CommandDataModel::ShortcutColumn, QHeaderView::Fixed); h->setSectionResizeMode(CommandDataModel::EnabledColumn, QHeaderView::ResizeToContents); // Allow deletion via keyboard QShortcut *d = new QShortcut(QKeySequence::Delete, this); d->setContext(Qt::WidgetShortcut); connect(d, SIGNAL(activated()), SLOT(removeSelectedCommands())); connect(mModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), SLOT(handleRowsRemoved(QModelIndex, int, int))); } void CommandTreeView::contextMenuEvent(QContextMenuEvent *event) { QModelIndex index = indexAt(event->pos()); // Generate a run a menu for the index QMenu *menu = mModel->contextMenu(this, index); if (menu) menu->exec(event->globalPos()); } void CommandTreeView::handleRowsRemoved(const QModelIndex &parent, int, int) { if (parent.isValid()) return; // Reselect the same row index of the removed row QItemSelectionModel *sModel = selectionModel(); QModelIndex index = sModel->currentIndex(); sModel->select(index.sibling(index.row() + 1,index.column()), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); } void CommandTreeView::removeSelectedCommands() { QItemSelectionModel *selection = selectionModel(); const QModelIndexList indices = selection->selectedRows(); mModel->removeRows(indices); } tiled-1.0.3/src/tiled/commanddialog.h000066400000000000000000000044031315121121300174420ustar00rootroot00000000000000/* * commanddialog.h * Copyright 2010, Jeff Bland * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include namespace Ui { class CommandDialog; } namespace Tiled { namespace Internal { class CommandDataModel; class CommandDialog : public QDialog { Q_OBJECT public: CommandDialog(QWidget *parent = nullptr); ~CommandDialog(); /** * Saves the changes to the users preferences. * Automatically called when the dialog is closed. */ void closeEvent(QCloseEvent *event) override; public slots: void setShortcut(const QKeySequence &keySequence); void setSaveBeforeExecute(int state); void setCommand(const QString &text); void updateWidgets(const QModelIndex ¤t, const QModelIndex&); void openFileDialog(); private: Ui::CommandDialog *mUi; }; class CommandTreeView : public QTreeView { Q_OBJECT public: CommandTreeView(QWidget *parent); /** * Returns the model used by this view in CommandDataMode form. */ CommandDataModel *model() const { return mModel; } private slots: /** * Displays a context menu for the item at event's position. */ void contextMenuEvent(QContextMenuEvent *event) override; /** * Fixes the selection after rows have been removed. */ void handleRowsRemoved(const QModelIndex &parent, int start, int end); /** * Gets the currently selected rows and tells the model to delete them. */ void removeSelectedCommands(); private: CommandDataModel *mModel; }; } // namespace Internal } // namespace Tiled tiled-1.0.3/src/tiled/commanddialog.ui000066400000000000000000000127271315121121300176400ustar00rootroot00000000000000 CommandDialog 0 0 701 273 0 0 Properties true 0 0 QAbstractItemView::DragDrop true QAbstractItemView::ExtendedSelection QAbstractItemView::SelectRows 0 0 Executable: Browse... 0 0 Shortcut: 0 0 Clear &Save map before executing Qt::Vertical 20 40 6 Qt::Horizontal 40 20 0 0 Close Tiled::Internal::CommandTreeView QTreeView
commanddialog.h
pushButton clicked() CommandDialog close() 468 287 474 214 clearButton clicked() keySequenceEdit clear() 411 252 328 251
tiled-1.0.3/src/tiled/commandlineparser.cpp000066400000000000000000000114511315121121300207030ustar00rootroot00000000000000/* * commandlineparser.cpp * Copyright 2011, Ben Longbons * Copyright 2011, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "commandlineparser.h" #include #include using namespace Tiled; using namespace Tiled::Internal; CommandLineParser::CommandLineParser() : mLongestArgument(0) , mShowHelp(false) { } void CommandLineParser::registerOption(Callback callback, void *data, QChar shortName, const QString &longName, const QString &help) { mOptions.append(Option(callback, data, shortName, longName, help)); const int length = longName.length(); if (mLongestArgument < length) mLongestArgument = length; } bool CommandLineParser::parse(const QStringList &arguments) { mFilesToOpen.clear(); mShowHelp = false; QStringList todo = arguments; mCurrentProgramName = QFileInfo(todo.takeFirst()).fileName(); int index = 0; bool noMoreArguments = false; while (!todo.isEmpty()) { index++; const QString arg = todo.takeFirst(); if (arg.isEmpty()) continue; if (noMoreArguments || arg.at(0) != QLatin1Char('-')) { mFilesToOpen.append(arg); continue; } if (arg.length() == 1) { // Traditionally a single hyphen means read file from stdin, // write file to stdout. This isn't supported right now. qWarning().noquote() << tr("Bad argument %1: lonely hyphen").arg(index); showHelp(); return false; } // Long options if (arg.at(1) == QLatin1Char('-')) { // Double hypen "--" means no more options will follow if (arg.length() == 2) { noMoreArguments = true; continue; } if (!handleLongOption(arg)) { qWarning().noquote() << tr("Unknown long argument %1: %2").arg(index).arg(arg); mShowHelp = true; break; } continue; } // Short options for (int i = 1; i < arg.length(); ++i) { const QChar c = arg.at(i); if (!handleShortOption(c)) { qWarning().noquote() << tr("Unknown short argument %1.%2: %3").arg(index).arg(i).arg(c); mShowHelp = true; break; } } } if (mShowHelp) { showHelp(); return false; } return true; } void CommandLineParser::showHelp() const { qWarning().noquote() << tr("Usage:\n %1 [options] [files...]").arg(mCurrentProgramName) << "\n\n" << tr("Options:"); qWarning(" -h %-*s : %s", mLongestArgument, "--help", qUtf8Printable(tr("Display this help"))); for (const Option &option : mOptions) { if (!option.shortName.isNull()) { qWarning(" -%c %-*s : %s", option.shortName.toLatin1(), mLongestArgument, qUtf8Printable(option.longName), qUtf8Printable(option.help)); } else { qWarning(" %-*s : %s", mLongestArgument, qUtf8Printable(option.longName), qUtf8Printable(option.help)); } } qWarning(); } bool CommandLineParser::handleLongOption(const QString &longName) { if (longName == QLatin1String("--help")) { mShowHelp = true; return true; } foreach (const Option &option, mOptions) { if (longName == option.longName) { option.callback(option.data); return true; } } return false; } bool CommandLineParser::handleShortOption(QChar c) { if (c == QLatin1Char('h')) { mShowHelp = true; return true; } foreach (const Option &option, mOptions) { if (c == option.shortName) { option.callback(option.data); return true; } } return false; } tiled-1.0.3/src/tiled/commandlineparser.h000066400000000000000000000101401315121121300203420ustar00rootroot00000000000000/* * commandlineparser.h * Copyright 2011, Ben Longbons * Copyright 2011, Thorbjørn Lindeijer * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #include #include namespace Tiled { namespace Internal { /** * C-style callback function taking an arbitrary data pointer. */ typedef void (*Callback)(void *data); /** * A template function that will static-cast the given \a object to a type T * and call the member function of T given in the second template argument. */ template void MemberFunctionCall(void *object) { T *t = static_cast(object); (t->*memberFunction)(); } /** * A simple command line parser. Options should be registered through * registerOption(). * * The help option (-h/--help) is provided by the parser based on the * registered options. */ class CommandLineParser { Q_DECLARE_TR_FUNCTIONS(CommandLineParser) public: CommandLineParser(); /** * Registers an option with the parser. When an option with the given * \a shortName or \a longName is encountered, \a callback is called with * \a data as its only parameter. */ void registerOption(Callback callback, void *data, QChar shortName, const QString &longName, const QString &help); /** * Convenience overload that allows registering an option with a callback * as a member function of a class. The class type and the member function * are given as template parameters, while the instance is passed in as * \a handler. * * \overload */ template void registerOption(T *handler, QChar shortName, const QString &longName, const QString &help) { registerOption(&MemberFunctionCall, handler, shortName, longName, help); } /** * Parses the given \a arguments. Returns false when the application is not * expected to run (either there was a parsing error, or the help was * requested). */ bool parse(const QStringList &arguments); /** * Returns the files to open that were found among the arguments. */ const QStringList &filesToOpen() const { return mFilesToOpen; } private: void showHelp() const; bool handleLongOption(const QString &longName); bool handleShortOption(QChar c); /** * Internal definition of a command line option. */ struct Option { Option() : callback(nullptr) , data(nullptr) {} Option(Callback callback, void *data, QChar shortName, QString longName, QString help) : callback(callback) , data(data) , shortName(shortName) , longName(std::move(longName)) , help(std::move(help)) {} Callback callback; void *data; QChar shortName; QString longName; QString help; }; QVector

m! D~*d-hP9@X= Ac @$ Zt|*ˡs{&`U`d$27d/p#?O{@&2C pYmJ'@̰r?͙mO'T|{Y1$ǣ$)<0Pl&;Q?n\1FI\QkXBU-&*^8Qf [9^ ~ɻ5 3G|f'5/FPP?_/籯ՀR֊/dn D>TSf5'Kg"k_8.z"at 37n&;jOWl霊+cvuja-yySBXy<{evtYOC 1`!SwtO}8G`}H42%7ŀ4@}HI.J?׵}prEAΘGjog'MK@Vb$h8?zz ;;;K/"9Bd ~c.}rRɟ?䌐w/w$4RO@(PЎNcA~`:z \=ʀJ[Nt(%={"+^gK1/Me>Zb)8_~8#]ctO#0zDX#4"W`U l9dG`k;dF bMZ̽>JQ9G_ BEĨȓy|(98AdGxwuu rKĸ"6A \heV)l'p?W>'1*"[L|^;dϯ[uJVb 'K]k"kOf?eks#s:F\h+y )͸0)+ٟ^o@vfNG6_YPi[Cop={bɾ{4 k{<%J:B`~^Wőm?{_Պ~{8R'F4_Y>{>=CbəB@. 6 =^rOJQX,(*j}߂Fp ICƆ+nO,8w'OԎD@n 8|}wNAء6ٵ,tFϐf2~Α m:;N<5~/@ݏt!@n~;]dE%{pI0^8P^eo?>~MاO8g~vI@tB7RurFEt=?f;eZSךnrxߝlKlc=rwx"`kh `lQ +{㓹'ݭvHo @7:/?.~9`ZM f$'O/*>i Xmp'`*}&#Gu=իWE%@G@1ǰο.>e pp<fi^>: S8Ou'|Ha_uNcGc"Ci;q:]#+DZ%w/|Lym[|}|b*|[}rhG ُNg_0|D|ϊ~rkfț~ >υo^6/((Ma-uf]v$-&K&{'=+^}wT-}g}X R`_?FAg\'{ %-~ w'[+89HbM)l*wlתɬeLq[?.9pĽIl౲$G*۲$q0A9Ss;`6]:ÇwiqΔs 1dQr ~/r n {,4|`^nۻf N濛vڷf  k*  Ã2quwDYvl.4:&^O)#ej@-3m W"W|wGUkS9HaR2ki쭁ݜ([¶VOc[8V;kX$JRYSU :cTXŜ1l]82kېs ے;RDs(ĮQ}Q-h)gz$t8/gUЧc%6Gt !q0N '`D)$' oa["2u3Yۦf`U(ïۺm 6'ä#o1${dh>VVnE[~p@ͼ{_AZ|Ѣ:z#=S2OÂ3 @[F; @\ONAK yEI' l҉ؓqPOgOd^ڇpGuh ^;oIQ(kʒ_$D Zl'7s#5F/}ndwWzp%s#&_͵*쭝Ep2@` ` 5 025U&̿mlOtYVMS$@k4Aۓ`''jê)h 0!' v`V;G>!oӀh%c^<@?NsEG %P7Op+8)HE59`?I'{qֺ!8ݑ p'0QT7{1L0|F^BQ4o,mTWoTߞ;ųn-G߿:V85AĖdV~'[;-5F2oTz+Y<ڦ hJF}e6fٜ3/4pP ₱>7bE"~b~{Fq8 @1gS J%, <Ni1ϳ{V @߻v>`65,HD@D +3x6id#G!2rB% c YA<.. (_05WdO4e-%;KWE_4[ʌǿp)4z \hsekq@=Iz~ [x2k^7!;-A v^??Y ~ꄎ>Wn*?nӟ*@'b:D+ 4byOe5NbOc{W:8함$)05,Mc-kj}>;kSEeaڴL=6c T)ZM~cEh@9~2v@,-Zc 0z " 7-TG"mSTGp JeϬUXƧOzځ+-7ӌ[0p۷nZȟ.0ش>X}Y2VMf۫'9]uSL~xX(<+f[M1" ($7VbA[rraf!^pܵz dEO|JRZ0m\S\ ]ܿW~(;"J~gMO`Ubٕ>'♕'XoIX$U銾pUgj/:>OT&zYSq0 Ϩ&I175LL #$"onKexUO6mf6/0Q'UIH*m*P /v Pp {̂&ms/΋ ޓ4T@S՝LJA:կ?8S|*:\-ljY}8_Q~X+bGŽ~7RACy8*΀â 㕂>=} Rc<'Pթty[rS(<.L~`oC2guT2&1oˬ=?Bp2a&IDϻ"/ ea~^uVz7G~+DDnG :cB['UTW^o/ Gg*Ґi#A6/بx%Ht7Z Eq?/a <__);__ΫӕzE~<,l߲g߿hRE?vh`Юim,/@5Ds-@̳(ҭ@E EG nUYcƼqǿݥ~n.b|z4ەm37:㏀@}(msBAKs}q`K!7mTcҨ`IԿw3oËu[G[y@>Tt ^6ëmqz-FP`ɿK .J?'+y oN{ޚik~6@}Y*QeY3ߜn $k_='G@ϱ"#$`U HA$IO fg%&p [ ~.>U;;_rS$,ͥ??neZpg md琟mMwF:ŧO9@Rآx:}ݧ@@VB$/3^k/΍(Y& :[Y([/z(Kl'ggo?xgON>LbNV$W;Ķ``$-Bh k`f&/ Sϴ~"tdLS#'4T41{P-u7'@ų(/aaHֿx 'ْ+ڑwg\p NnU<_=/ .P^ >)\j&8o[lfr$Վ8,8wH hHY>x"+;_Ej_:Y!o胳=7p_SVq.C?)8h20SVODSU#_eKN.~$Sp1)ȌjU a`W1@ԿyYo̽ʺ26;|ySՃ ^qg1?Yʁ~>Hs{MQ ( tK=RQԚ "|  |/m4-D~r>߽0/ q_fErw*ߣT$F剁 +IeME_2ݦ"(/'sE>2Ib57cXKkdXȑm ꏤԎ!2|T*@,/gϏ_O6b 0jK٢ߵk'W/5Ji!()B 5v?Q(mY>5LK~@vզu*%M =Z JtSz[Ԛ@挫725qv<%v@@&g*D3GrZN8@ˁ0jlϲ{γH@>Sr{j^(b/+`.ܛ5A gn}7\Hg -`;2IٶTF"Abl o\oV lU *Ill&@ր#f'8*ӢQfH~%Z L9f[<-2pTfܨ p_qjǺJOP+,~X" jɆ@pfIՏj@@~=j8=JD cA.5籋& @@7|=hn''?P7 퇖t[(S[3~  Tĺ}**OeK! Lem* qX6,Kcmf   zV6M%~`GOv@ctnVI$:3$K og{ ,7@ElKxksdz#̻߇=ic;)kvnO'? pF/_4x!ɏd  Vt7 ѐ[D Zrߨ1 ~~+T5P?ed%y_]~)Xb-^k]%l@WO`$Q)+M̓f*C@/Q?}D|rQеf 2ch~@caR~4/{AYwuarX"Dq-h9U^& p{u@"}%p: p{|] RA`, ?:=靹:}qm<u]%J4<f)*4[NySܜZdG ԙ#' M#hJ]$gCw~A>+%BG .[DzM @cm~oF3 ^6{aփ? O9N`́E"vӉ@}ǗE|zw|KE6G<7_]&:  \ o\leMZHvT% eI۷ `G5X9A Ll dQQe@~F҇=}2Xf` @}}{z/0zZㆰU/eau'0/;MF]/܇ dv;윲s7uT>^^r}Ќ8O1[@%q/`$AVMw5'L㟝s`:[fI ipCm]$&,z(3L8ȫK nɏM0(2AN-ec[;K~F[|;Xܱ=%tȕkGogҔ p2zlAȇu,?#s??JɃOgD/ٺ[|ѝܧwB0^x ?wdU{}~:q`Dgɀ7Ni]B[־+MaqmVLYTAv: C~c(H=HYOs}b3>Hӗ.>_6nϏ& ?5@{( }ϧ"ˁR]==ˊ`XNk?^wH{r`[~P{ qg̋~FO!F&-A&,6=͖UwțL d.O# ؠpS 8DL|3`On!~Ȣc6Y~X}1gTA(c[ܚVq3h.3zNJ?*jI_ @`H{j(#-hKney/RwDI@Ҹ (㵩Sx@q}-fs,0F%wͮ2XA#d}ߟk1@y }f`pL`2Sطn*k۔n7L X;^3ULd@lE Co-Yr,xiooh%; NsC_䵾T7;)+sTHv*4N)ٹCAh.ٵx~hks/D+C%!Bɯ?oKOea`XמS_EIУ !^Xm+R`˺B8]ު$ִ"Q6bkXmQ[[l9NdyPĞ̾=7,8Y@PG,2,-ǃ3}(l0 CL{|>n&3vvl: 7(@|H=|0 {|M9U 1RU@}?.-%eC0SGm?Jb1ⷻ6uyXr3A2v kX25:?}8Hb &$v-HdE)?Z P0n F`!\c<ƖWW%-$9 P- F1|\YX`tNAXPt8׭+6PmQ)kMߋ0/ Y f, US F-щt_W)P} AAŁ航~''aoO$S<`y?x)ߤ}T'k?e akUOf%ms0I-$`uD,427&&B<_*roaOR*ZbIbEcD|Nkw@ߡ%Ba7`b+G~xXu~/wB[AJXTԥ@}$-|ؖїkz?PþwLdjSnG*\XJUQGח: CGe{t-2'Q&JD*WŽ3 ^ ) 9`\ zi쾍֌ũ0W7]l۷v x ? D렱<3XYcG=WAۨ8'I ?YHVkn4v$ Z`hڔ3{b4pM-~X-"4VfvÍ # P'? RˁTKt&tI5"~' /bBPN $?y,8`DOv6Zd+`̻Ypw5-) ɪluႬ~q!߾uSDߴd`΁[VLeAALC(D?x>6ǀo*3cPgn 0j%ҶH2"?yP7 /"(sGҠ#g2UpĬDDO_?B{d}\*nۋ ydwX8m@#$GwX(u]GVoV/HbKR53m5:%r uG@Č@81Ih s;q_ 0YhVPD"2؎SX4 ް$5' ٪lG LA6A2O?>b~A8ظ4yh Sq֒?ӊyJUpE "9T'tĂxi nX,#j' X/,-CGzvύ)Ép[յOlO;2j@ %D7W /x5@n!\JN#[ f-|pDgh :@I5ؼ]FzSr˶~տc[zDdz t|Q0F@<.6[Ko:#)t"bjpPwMsC[ fhAdTaB uHx]]L*9q"Ƚ{u$$幖:㟁 K ܕ.6=h *@ĝ0}WAտӕnQM Mo"AMIamhZaח& kMf;WMek&l𬿲 Y[~O_RYIV.>_RQH Rt?@c}9rB= 8(/4Cvސ0HW_@i?uA^ _בw-!`[fD̫z #d es jS4)g$bp~k8z _n)3zP( k{#n3S D5ᵤ1?8]?= Ylj`Ll[;ILԗ&j @db~ wG3~׬TGLX21E *S5Xd4 ]a܏Vow+۷ht`O DnSOSlFvJn>n#?Anvu U8~z16 hN~27\i,_P{@ފJn Sv/:b96Zjuی>m``0f5d-7<`X nQ0 X0U@V$D2x<.d_$ed T?`N$R VIyS՛ZqBP:c|o;B9w Ub.w{v":w]4l 6¿_!2Ε$@gN ;5Kd=NHپ| "'&G*G' $okl V@Xp:Xk! dU[^ m[v;WՂɃG(t3?Պ%/J A/I!KS@ 0UD2͙Pxژ{ X0+-*ÒxNħߩ\geEw̯V2p&h/_<]+VFe @U1Lvea`Dr)"|DZDE@Baۺa'@+梅hpXj'Qh(OF ߗ 30 ǟW 'πgEb&9L D00 ]it: ΔuP^>~8 _7@}*S5AX" V,3hY ֻW+//5F0~TX (:|=Ѽl(wԤ}k< եɖ)P\@w~e֓,28*3II*'S{IG!(W"NeyG tB׿R@3QEz;kŹu<'d_0=zC:^ *oX]MԮXV^QVv/ht1E.GNrAD$h c+L@XSvVWjU$x'nۚnJ%R(# &BC $w@(hb?Fd! J nwٿ'ढ़>Q@6%@\;GJ}77۩e},:2wl\ݽcS=hڸmY*lPV.`˗-[HtPWXW[97,ʋ"6/(wT%]?7Ƕ- > ܫRD?/I$x`zY\/4 a_$=3:oc[bm@{ݑ7mj"7@n[Š!9Fe }OV‰@[H5 TPCEG͹\" O ) |2.ۏ4mZ]cc}[ct{Ql,_%*+VWɷX_6%oQF hXUӄd-0"![G_e=&Wxl'* j({n wͲV=t)SOOs,odECP؉`1'coUmtXE+yp\7ѿ"3 -OwHvۉsCX!/R/{s zB`h P5 !X T]Pă8:.DCUnZ[6];Uy@0d߼n ֯\C}cbU}4j/v,F+j6:""t3C`Or ]15%?Ocya\_J'&_x/go 1 ^Efe b0=!FD<yii$,upXhp8dF@;_D Vwmpm5l?R -C}nE}>ɕ]pٍ ; n,K〪]q${*VbyDf3Q[[S)u+z+PoP|5r\;D4lC 0X~Cyr ll)  uV@͆DA6-1@A71c]'Kx1q9ӕ o`EHT+5 @{ Vdi"``lb / #Gi /gKu쾧ne@V0VT?7ÝӚ1˪}qOsw Z-X] Eo)׭҂,ۄ#1&Hף%@3~^ Xp1[\ZZ~]h^^3Sl{U q;lCֿh@7yĐaT B;P6QO 2?* P֯dzy2s5&Yd6xtAoύ;6jD-͚G3z#h10{|:2!J*H t= u"@{=P -(\ bqIYuMh X(I}3Ih E,Y?V_4[,2QWd'9b9P LoP/QUv ;g<:u$Ce}G k^P;zn}t/INz|u `+Íȡƒ hxWxiPkU,dɀ`zD97^)Kf5Mw]Z`7m\050և,L!A?Zo 3-P'uN3^{wΚ3']?H*d!:U{%_rS( /rk)::{clm6[%mY4־[%[-زCHLB@ 84i8 U l !CH9٫@NMiwoEsfe{\)\h(v\$U2s@վ 2m7%{&H}yߍ\U }U#\ 0  l΃ˠB@?lcE0`7#t\nh!HP%ғIav:?\Á\|f܂%dnY$P׆ol@@]k{djg :Aˣ$p[wVړ&֯ Y #H)w@{pۅ,,T"7X?U |{Zl(dF8jkۍ{ Н?l޶7"΃ "+#$cW9V|vbvj wt^{m^CK"')c!Eqi yO^xx²? 9 '¸b }Jz̀er|u=p5Lۜ:&DSedl[Cw @[M\u̡Ў@\8`PTu<1T̖".T#WeV#V}χ/@[CCԏ2Nh*H*#!P>ǏC @\য়.i\Nz١08HÑ铻~7;+2P~dS? g@Յ +ib X}FT2>9gPrQ`0iUcD@ @f\jwTl&є,rIN pC#?x}ٿ`[F^V+ x, \`Ui PྫtG~.~2 0AC[B ~3N 0Bؕ+g(bqNdZA؊ 33C*xݺ*jS Y+֬eh`0 k ;dIW~]|.+?ݗH}+fm{= GZ ?'1|Le w^!@''/f TV#p&f#-T}Oƪ;=v ik6uُTG1޸;@n!Ŭ_|$&@O_$Cd#x*uA ion<0AA;p彃7^c*@,?(THU(u=u+ ݸɞ`/n]n<ا߷iܬmIO={ﲐ~[R^ܴxrv1a ;sۗõ߃ki!;g#]}9d_Z`Gw #  `Gwu&;!@IFwg Ç/ rڔKkJzr f$yʮ` ޝ}ֽjWk9S ,=&u+z8ߍ~l. /z#Hc (EZ98o^)I*S\~Ou#p#X4Dr9) 1o{H@ j?JςM?Fz@T{L~_K6;1JF$ dC;@b37-+?dFdG6h)h }3FȭZyF!~`}n~Rn FVL}_ n \ `,;J ۆ_Gd` _+po#qPmOQ=DCH_ }x@/χ U;`H l* ~9z @J}ۂ"CU   I i}P_Å{5?֛Nek *d0X,vw-@_q"fynL{jQ{1_aO29sRv*6vP웊6lwe*;ZxJ}sܹ@ r=Y*}[#`.%E_;->,$c॑ @OG Ҭ\B\#l5Rh͛-IyI`b=` @ ?Jx_%S T 3Y/o@0D Б+C xUM$:YY3EEaIe3 -~>o=8UK:*AP1U||+Rk߻0D(G[‘%SAqJ~v] s\v;/Y}+`SqIQ召9sUfO?յҠXH39?pѪbw\c\цU?߮ B2(" ; j  1Pk_ރvVesuhN `{ֱS{|x7 0JEBhhk#͋vE/' bh׊P@$BiFaT0i7*EZfo&7&[_+AZCPn}E_S˟*=u| k(h@X̭}qE"0f`eGCBQ@fO49cSlZ)yO$_ԀRs<bAXh=_  Q{{c߮NǀU@@Ɔ0!;OiZvj ?L7󏒾=o{;˚ :6_}H+ 0,EmdivwMfKĬGNh) 2ui@P~tߢwo3㽹ltw;ٻG p믃/峁u<6jqpgun\ei.6 {B <33Wf(1Jޕlo@K@q^U6aT B\j{ ,ћI"`z#Ui `XxQi5F͜q@q?ស癀]4\VU}T.Dwm\9A? Y~.~ 6CŰL̲x9ɤ;-83@2V2w܇ OC=8ґ?ҙ=^v¢|>ήo Q{GUu'U(9pC C[Pli'<)˫̆@._ _ŭܫ1NE.#}58aʀS ͏ 1O=}d5=[~魞C[1%"7Ƴgׇ LT^ #VUwJ[`I?_q"(,̞* C58&86& @ӃwwB' n=7f,%۩ǜ`IO#*,( ƍX{Y ]lAU[ $ޫ0qp!b=hm,|pP|OuU@pt V%{ 2*Z ZO$A6=ؚ.Vt L} MNc-@?v_7Q9#f8(Dz9R%Z(ӯ~yފIXpt?Z&@d: amm{kOپ\nq$,d,͎&@U^"Nx_ɞ9^<}:1C eHi'ca: 8Hd@ ē@jчw*Sm sVXh$h p[*qF <Ԛ vץqk_?*WN/,1#VJKq<`ГaFh\Ѐ&=z׳`?_;:o# \ ̀Nߝ;`^LB8( 0샃("`O^vg#?-R }o j2cVKOg;k7x;SO3"$"p"xiON!h0I 6\w`j ؑtK"0jg}{0)7 O*XhJKb|K\KJ릑 {ejyv͵:pۦ*@5v8[ է`C`}᪰|.}06"+p/`TOY! JC*蟼*Xk u2y]VoIW Pc!#Npj҃sB#"NE N|(0 04(I{lNTv#ͼߓJ{@3Xf [Q d]|U0,+(V1YEK~jgJF@3^o8(* ,OUDئj@mҕ˿7vWP AB«]m㭋ۆ\[}p\cf{TUqO,0A;PS־ %@"Zs9zY%X 4c* z|F '5+zy6Pcjwզr7@ߟ7HO')hnI *àFyeF{@ `=2^paF,ېpA,h F!SHy.wUߍ qEA oãa "t؟cp$7̩/n_H;!ob-g9QaIbྞ];fJ-o{,m$H)5۞NC[i  .lw;ҕzj2 @,wg`{Ÿ%d0[  #Y;=UY$cU+NOlqMD|A{1/9~twk_XO, @gKE /٣ ?@UH_ `ڏk{ު`/H{Z~쏖>it ֽ-Wd+ aJ=k_xLABes2BD/X,#>N\.x ~j} @ʅEZ7#_y|5ȣf@=^Xsv-bȇQyzqn x~8BE"P@ GN"&{޷32jObᡷPuj p ` %|z?dl@̘Gsa@};2٩6 +a~!/ ۞N x}ސMxbm< !_io*VR( xV_.m.Ⱥ$ 6> *ߜU=dTj[2 "Vs8 f"@+W@Z $ʐ @mCg?U*"i`4 @x="Ba: Hp=Ӎ~*_{[79ڵ.߾լ&]ghe3{Ad|W@{o tUesع!op. ~qc.Pۘ <Q?b@s\oKLZsB~r6;LwfN8o5}`E[[`=l$t9=*VA@ ='yuǐb9YEz.fC捠4G?9VdPH&Cͺ OX_qړϏ?0ԥq ~o45sAz Wv"ӛi`):JhpaayȡPy.wܿY ^'b@'oV} }B%5x`wv0pw˘,5!B@3_|}\ B>NjϞb7%B +X/ " };r/zkRԎ\jxN v\MhQN&kmOg3pW^7zW ֩.rӞbg a~ [) 9}/؛w0*v R0s w3#+uHR?BUw7#/, -jeU}eS`fP\i72i={^4v"3bq@7@)yZ>z"8e},lzi_U=q\U 6D>₠$H\gg'z7g-Κtv;ݸTLAˠZlNOb8Vތ/"HGQ.V?e@EU Yˆ>N1x:H-}hK] *D|ȈK;@46RH-<șL| T8!fpe w s x  ̕DJ P 1f@[Ru?<_:;ԙ+#8֙ڞj0x}FJ%*4/h P5 IտVS*0o4?T^|fdłؖ@ "Z } /q Nb *`2@@ l*#wk}KM$| -X@~kmtvEwMYomkJgru_#3@c]A]``2MÅc%  ` 1@@Q$᏷Z.MKwhV{%f>JX> ^ ,Zg>p,͖ z\F2ojȠ Chփ{Z*>#H& s67{/j쨩 Hq Mp!?0E$/ N}vP':vόx_t;I9bf>'`k/@?/ tf>w..AX- $_Td" E2$I}N&|#@Չ1B@$sRUGZG`5oU!<!o2wdP5jLH{x_9!/FU>JC/i_jj\}F 9hF*G*Yyȋ HZl>D}#t|ka`4[+T3%PWUGIp>^Ed o8Gҹewa uvaPHN,,{88 pCpZc^`6@~~/#O ЊD}Zw"x߷.nU,Fw'?q&d=Wmm@5fS4':k(ŃkD"!~LzD@hg$ 狴Xj-"[T-RX^3DY2zWٿ2yuS@#{%A ZŁ o+Z,o爵pM\OѡU"xLqhr#x!{,z -V<w@ yP'=J u3tmC*@?I4@_E=ZѢ_&-* 2"py<@ģ&?7Vʦ!`iyw,Pe@2-1Pa,*>`*{#Dk$d G\2l9Pҕsl~Pf e[ lHf6FP80z.2x+D@!B@q>3Y]_x?/w?/'~on6@%"۳:Up 99<"i %ee5Q4@pa3qRM{Lg]uM" $"4{ˁq9 -ǃc*R:"Ȣ (jT0IZ8ZQ{@-BCew|?K!?|ny>7y-h5Y?VrWT U/ ĉL tJF<ӻ6,V]vdGA4E*wWC'1`,sMPs %3V#;=_nUJ߶f6G]WއkDK}@6@/7቟o!$Hz!{/vNOOQ0XzI\Uwu'W]XX)m/b`CկIUf?f %P[RV2gi+ /o|rR_JD4H 2qQ4@طs, T=$B}LIMCO"}s?#2@_7pZ/ځi ڙ$NxG]LG2hJ X 8sA82XJ5׏48'Wo6#sw%ĖZG+k2RmB 8\$ i_n-q$0IB@?i|}]p ߪ8(%;naWԜe0̾甖óߞ!OM~Fo޽x:-ҍɧ_g73T T ,߱) 1^Dxd=%K.fP; T8UM `2`^Hv] УDzk!`"Wx }w }ܬ57jr!<'[o /Oly,%sT#.1`+O={J> ]@X}W;w KCeAP94U0 @$`ݮuS܌H#(.; (( mI1`~ 0VOB>d+. %>ϹE* S߳+ -e&0o'U7gd7@BD$_t{DػOrE lOP Q?_۞eM=gpM#fMa _*# 0# 8T7iQd}d9wi{{0_ %'gvM`1n'S ~I1+ppm&2y_|ĒP}H͢F[@/& H@u_9=/ERTA&"XHK KD#z$pLt#x~sAGyҷ9]۬*׵ńh"ǤO(90+gI1 \OK&JC4@/.B+z"+@֤EJˇ*'e ~`٢&G_xDMrN|("Fe} Tw PQM7`6I0 Cހ$p ( &tNyoBps?=;J{>ZE?Zcwm394'3}e`7#'/?Yf@@UyepIX4@6"%+) b@+֭0\UQA"0BHu@4Dt lMs8Ufk0!`߀q$ @P)#b_{w}iRDt >yq.SK}d>>0^%tVX8 !y B\[+'#%wzb@q: 17Ry > |yATo}ʲZ+wn%ѬN?=I0 *={k}h5.`BCϼ=_xzylLd!!Rou@@lvLU7D@sXwu#y`wK3ۿ{wZ:$NN:[cx=IOMO{KO~'}k A ȟ}>߹o~ 3O}ah8 zZ稤͗$^1k6L@$r-_??z"MvF޾"p# y+a&;]3[EC"HD ܭZD$ahEM^W$'ƹ3 @`?w?5DB`cP)>B%[0Q;|!|*` P$I)`ՕV2pvO|rֶ.9w/b8&V !@m&6X=on-~gK>N- %PDV ;%"$ ċL8< (u}_D'~:Q ^;|#y@ĀK0<$ϵجRУj|PT&$e(S3#˂|5~[ 9E;0<Čλ\'58h,&;;K&&?x"t/|$՛>??@@AABBCCDDEEGGHHIIJJKKMMNNOOPPQQRRSSTTUUVVWWXXYYZZ[[]]^^__``aaccffgghhiijjkkllmmnnooqqrrssuuvvwwxxyyzz{{||}}~~=_ IDATx흉_}j,G 9 hjնikb466"m6QzV 5xpjl@E^P3{컻yy4` 2@RW]g>ѹ\}ge\Wmf@M|C㫞@0v?gO;%|%w,RɎz'|tsԍ|*58ҁY8hOvziTmQ&e D(<Ȑ.n'B}+,0b+,͎ Ahȑ  D(юwBlaj} s&f $c }RMoE~ a,9MO>Ѡ4Q_F`M~dLIp7XAާi,t缭Dy˳_9 ػ 5HUkz..DwLOMqM9`t";n~>J6r~_߅cnPܯfsەSlLEUۂH_#kcɚ~U ^9X%{ n4tymh 8Ni;5mq <A[wd$'4q>qn)J++ߠ?)pp}pq弇:Gc9y~|~lQ9'sQ d pAh>}TL@֠V~^rYyG @M{˨} ;kVC:[T]s@^;@rS  `ijTS"f5J9@G~Dp!HC(`qx@lBQ>j3T_cSc7kU&2Xz 6k> 9۸*?'\qO U1M]<7V,}ר-'Xpr^xyhO&[(pƯf"*ΠN>bk崧'oa\JMkPN"3('1qs 'YFn Am7FҒLN\`>͋P-{ym a?1:^E۷$J/}B0ظ#m1ψlr"hB5($II;OX3'taL P$b Lj4Ij3 T,>A Bm xPnx&(O3NCmȍk^⚡{DQyB̖΃HBT^'PA$d 2@ dbMڋ7Or?PT;9ǥUޓ$Q4 壾})|gw/=T;9ߔVuC_N @S{xqDuz]qai+3<3Qa  9 װg >?vr!U-+ Sy6{5=,_>tߥN j )Xo{lVKT;9  @SMbf5E8 n\ӳ,>r (4u',Ms6ѭ?ZGUEu$,M+{)mrg\FvQ=r]ۻb#gGK;l]349ZCd-΄F'OʃÞ=R#v;MLަ?Jko"3}2Z|Q` ZtX 4}G쇇X d 2@ 0^`%{_8 Z}/pvb{{C&z  (Fꄉ]jl\CфRޘ_kU;h)IbD@) 73 aV2@ d 0hX.\OO{SI]~C]3]z5Hv.G<7NWR] pxW|ه $%Tt?gF͛f ٽTtٯ  =ɮx 'M3]|OBf2R8{~=f3(H}ΠP2 𾞓IN[(ž+Wilj;Ik ?<MDn 6 w4eQM& ; kx&ymGh[jNG$}M;!ymݕr&*KUc ٝmPyHď ȕo0V땓W.ч=ix\@Ay<~hc̟>ⵧU ]dix>('UW}DσCgWY, d _|T^sw߬4M';moVTYtRS}жf:*ߩ>h[}uVS}P}XlNwZlMg `$*'dY>sYdY粝jOoWoqk] j'rZ3(_`Otyވ+z`b'rR@@o_eONd7"u2om+NJOo"{&cڹvu>T;AQ5->h/@lWz; M 2@ daCЩt&F0" 0:#kw*;Sj 2@=R d n6`ʺM0-0-0-̓ 2@#?zIENDB`tiled-1.0.3/src/plugins/replicaisland/island.png000066400000000000000000002227121315121121300216520ustar00rootroot00000000000000PNG  IHDRŐgtEXtSoftwareAdobe ImageReadyqe<%lIDATx] |S(ΡSdžB;mI-(K[Pp(oPQ(ABmrQ`HDюJ(jE8闓sNN^B={X/髒85|5RzQ϶gpCy՚|IOW }.I!I=gI'̯ٗ)9_kݙ#S/ʜRQzic{k^,K ' ?mSZ993+3{ig8c1wr|g[ϝs&{peF}n揊v.p_o|Ǭ;ICm(I/yEvYsc[zI?9dScifgĵzQ׸,^cۦZbaqu]wU-Zj5C+V䷻vlNN]}7޽=;e.Y=ݻMKKKZc3ڵk3*::z%*==}_nV>&ܹ鳸ܫ/:v "cAvzV$XO軲tْt̓;ʍ~y&6u/m(%eZ"c K79/[< ѵij" ŪGl!,wo>]4]Dk,&j 0|qU^X*un>۾T)1Ң1/MfOO0<>[0*Q|C_4F!];$x}m~?X'l^wBu׺|qLyi?+Aiэ} |{f@>+=1"@JtkW^iђHyQ˖-"#prͶ@vv޽{ׯj߾}~ue뻤tʸGQݲbZov\LL{]t9ؽ{uDJLL| ))i!YYYyyyB v-R B#256TonR"}9/}GNn:dk@=.pp= Oz(.@(&$H+I@6'vȟaܗIZpڋ)$''"]v@Hm!4nݐ4ƴW4/4hPzh \W mӦͭ {H?ҳgϭԳ Y]6KIN(HMI~(+3kV戴qVk^'Z 1D簕oGvע&,&Jm}B~.\C74#/*:)=sthmogHqlBD||ϿտRts\g歧3e;K+3f}WHxc"@YP-Ҟe!4"nB_͚wܗ{ ,vb Ӷm[P,LA* ]':1N{)]2'065sA:cmVΝ;-۱^zU"Sh>!!>019;=-u~fSS;wq J޽{ٳG9k6"%{Ai6 {zDBTxwMҙgD(?~tòƨi:vsdu13 eX8 btO)a"gS9ZP0O J\/([oQZUezѮ85EqM0`BG/?\S 7F0o{i篥r|OSb}H#c[=#}<3"  +ߑ'ػwk kF_|lrҀ"DZĐt\GZvӡC^?q,jt:/]QQ[SNK@8D`-SRJJJ{ΤpKRSSvHyh\f"D>#W*:մge]vH2-, 43,U+fq/?# U '޼оH0F,Y:Q+*OF:_jX-FCxoY$ozܮ9kȞPT,j0@\wW\T-s0v\xP 6>[+TZh/0|H /;>7{SI~`?[0.k hvys|>Ogo=q_}<^,g " vkVxohW&''_Dx'r4 5N'{k*wD,jB`}Yv~ӪeKZұS'QW^Dbd1g' go`Y_@dNNݻw,!J?D+C& $^$8_ G?tiii7$ӕCC!$&/dn?!/Dӽ| Ń*f%%)ĄۏH`B8%JLEnLY7퇣W §6>/,"K^=V hΟ@Ga`> 26կ)Hq($S P#?9o1J 83II4i^|W6K-]vI&89B i@r1}I Ii1~.%oHbQijq]|TT;.755v:)ؽ,$Y^111Ӷ2N:<zbRbMVV7=zCxkqY&Oڼ?S"o7㻌xs ( èiv?7e98,cLҵW (0?3co4ޅ)wqο'lL۰cǎrN2#- H\M҉$4絴Hj&%%M6kZ:t4ηDvf`ȠOnOXJFFԔ{ND1: +m[n&2pl_ww1:hWS\VDnyˇ7TFRьi ؀p H?Lʉ j%x-Ltt*b͔"3*2סYī>XIXa/<ˠ|^?b+D`Qg2VL_+;>k!:/ѯ?Au9Na,}C&We|_tqi0809@' ]w݅$E] iQ$lwY,w?$dffZINۛI^OnwVެu[hqmj˖-Fov_|ݫWw @c%cn"-qݾ!-5ekf2v";N7Co'McHKK[Ax?[kWEzot^@0q;ZD&k ,,-XV'~橢*Sbwt|OA]^@"Ũb,F 9U kst#`>cۦt\|ě8'+ UkwXA$'^1qm/aкpC9@#6?e69 %z?QF=L?3d<3?G䪨#FhD }OXF,$&H o&v{+\4Rdxum֭[lq]&{۵k/t\Kh_wgy]allSY]i۶;v|#!!wDD8Hǵٟ}>+h"pNjvN f($@Aa"f8 \ @eZ2c[rexS_gjZ<)d ]\m9{pUO܁6+j(K7.%iV:hl¥*,T {9V-b Biz#jQL"~WPƟ8*=xS?.fuN-(bwAsX7P;u?js ҂hw}7 d(I. KT ei-l~9ݻw%  $$%'_Oݱe9-[VA)C:Dgii;2'f3Co|I_@@t<9DN썬5WE:HQrx f&qf"`V?/LX~uP34J ٩]j`!( Zr&Az/-+8)Nv揢%jZK8S /NI;}KT]+P0(oXT`tNH<`_H  ,:U {WV39,`_ V(?,Z& {+ $,K}ILLIR{i7p>~Kb" ծ=r4#e#0wXF*꣉<6}j{~=Hp dgg{CtU$0(2@#  2JDB1ÄXCX 9,jௗ\$\DWWPY(h-H#J`RhfiӌT6oD٣9ծUՊlUήTY@GK\W#/OC}X*埗_d|1o:0ᦘ`C>Z3]n|"RH^<3 /MKns_@ oFz `JG[_~7кv %y_K҅I.$M%{& PRZT @N|ٷo7'}O'ާ珶ifm-igWD4Jr:D-ovPEj~? `/d4e"p H Pv(h^<֢ ZHADf G6vcD~5GoroCӇ Zzɕ˜L8M @ie}|ܔ:.ρtN_$J0:>+xz>~o9 esgFfrM+d3X'0Ҹ'@#Џ6O mAҍn"'$].2};vL}jvma=Dv=Iclt:e욕}&}>}m"!/"!uϱtncfPax8k-@ n~ՊW)}3'S%Z9pLl7iۊ}@B9V,)2JmD+ ; N{yjt{/~>Vg_1wZX}zA @CX E8n![Q<|?8vqf'_ҡ61͘\޲k jhZT٠A܌2. D$&NW6\ qƖ wC" -Iz8!0>{>Z7ꪫb(&$ sZtttwއnzUa"Rպ"@- 3;t谜ĻDJ#?"A>}m#3p9y!&LK:h@}/HDAu9a' 9CJyW| 2hPI,ΩUJK)XqRZ!E iiZZ_$^KU:6fpN׫|w`YrǴ^=k2By;1Tp,!NQ^ ;KO12X6W鬘0} jd{YO(a55^8K|z/"2~[j$i֍@$ 0޽ L0˭k1'++ߩg;@@:?gV}##@D25Q<` 3Pjv # Ij׀v5og< br#  XVW9~*͋솴?,Q >=g \h]ŅDfY冒G^!0daŴI)qr"eADk/nrdc]e`G,Ag/\3 @;#ʞti͋#L˻~o}/gv56lX#]jժ }v=p?Gi |op4߿EM p56fjtbߊ>!k}l% C:ޯ֭.IIIeVt s9KODq&PN-x3& +!U s$ױ=HXd"_wդ$饩i>MJʉXؼFDS~e~\|ݞ1L' Vlh|aG o_mY;MCbFd욤r.Ee8PP{q\ke(?3_e%N]ap?݃:ujFٙ@>w  X/44iRo!6F _:"w&`Gp:5]~ h~?ONJ>MJ r&>9ྯ]Ocf{ D@ܳgO D$:7q_ӯ_Q-m>8__x}C8$;`DEQ[@I]0F$( ֺ"mnW thj"( e\ i}XkSDcpUPKJWPl֋`mOė BY#@GlR@1C*@-7|\sA_ʗ]W̲e]ٴX s-nSxg֭[7#LҔH>O 0w} o֋@/%}vYvve"КL#}I'Gcp 2d ^Աcdž#hժɉNe6k&" ,is`rr:o/++ocNB;~:C}ID~}|OO>h3%"dƗhXd@ۜsCm-tLBXZ&@6.x"9xк ? "O\#Ň.K_1 ҈0v1R;!,x<%Cm@ H>V%xq!`zA49IE,; WP.Z<[p̞ϖ:wC `C>_ f(cZ>OZyH%lJ7Cx^EssT K`}o{"7f&-%BvkP7tSc" b!-~YrRGkqwď>K#1RIO>C=zt?ۻ9={|NllL5q""G_{ȃ,pocef\`a!e~~} f$^HY#_-rrx.*IΉ󉺇GC a aGCBy}vg*1{YG3` R 5 AU.&D֮sboAp\k ็/?LŜ!a]{k׮]JLLXiii3ޯD &2h$ Zdw"77))i].]%𾟶A!Ё% Z_zw64ik׬Pw{||DBNBwJJO?8ۻwOOO;.g{!>O޽z~~lLa:Xc OI+VdQ[`/f8/$u;JKƏT W2o$l %e>̋j> y<ɚt.,$hˑz@\``0P߽Nx!gX%|AD*$VWc׽Qh)\j0ծ??=ph1 YVd5 4ow[N!K4x֗Cߙ/ru>}ZFF߷%SNxnXE<ϣmI$Ѵ󦅅!"%zfO-.oDq%3@;w4%?]d%S]7cD`>k׶_:od@)weg#t,6hDAqJK@8Fr\':OޡWb}84R.@X9PkzJَ|jetxek"}z!@PِȫF_15ի}tŔŽŮj+ nxAͿ&yVbi`,8Aޟ2v,N 8_Ҿ}qD^"0ޚ"83I~ҋ{%%$GPGEGڶmw+k HHI"W 4ȑ#7n".mWC:'گDÄs>?g&svv7 ?d}y@ , ݉ҹ|O}PPP4EE_l:챠+%r H:>jR^ӢHW"]/4Q@l|5p> (!QE,+;[%"|pJ  ?%7L**@rѕ@'Ws^D.hժUmێ%_m"P͞$h6߿%y}^ݷw"}"@OHKKkKm[tttm>{$݉L ͠ǀPoF}=99 ࿰hrrzԵkOD~ꞝS}!"]FFڷؘo۵k.LX~&W^ @YN>D/ƂB4OmhnE ޥ~ ~C.zXߊ}Xy7? q7 +LZ;M:na"Rd0ӺhܣV:<w%7Xn. >\}p柚OSȴfDՀcV&-[LnݺN:!ٹs-A@5?V '77i׽" m#g۶mMH : w%0OI  ѝ4^Mbb?HzUʔy"RA~ԷO%#6lN;JDh  +/ѵVM\jH$ uOd9;8WRPl9PA{4wAukJ?wDs-hg6]#AD>rq!G-xm~\|,jtb/u#R%0:u=hvXx`{kZhtױcI#t. mO@ڄߜ@?w^Y~=[ccc 'PN >N^z@$aPFFF4gkw*a#~="iZ=ÿ"(У{w|]KqqvԱ6::Aqm8@A!8UR'*e哢XlX&XID" /)w.F $a<`_$>78@,[Vim\ cts[s*!ͨN|f8e@ 84 ]r\qrt""!kUV#I~4=III @!mVW幹9#n9=H}Opڮ]{|W>ߡv?KPRSSo&RCEi7[w|L~C|G%%%PK>)"Dc8E;:~y:Z" ;}4V8=ߟm!?0|{JTm0?W>;۪"3۔m+a;]6Ҕ.KrGXZ&iQ1cnkcݒ9o%SvKEm0rheZطCypWZAEGN-rqmϲ ?\Htp"(#i zd M)'X~lYFX4ЧFXb ^Jgʨe%`%XBl@#@?rC':sˆ[j C,|J$i"W\2ܒȿ=`bX>Q̪`Oմ8T{wqU\v? yg,Mz߅ks=4+\:%->23RB!vudlȭxs߀x܃wFz7K7[pcl+gS]>s!5J|ϙ$(>;U~$j[Vfc>~w_u֋j̀_pHAC,5ן0(qhDFroi D%2Wa|Dž؛ .%;ˁ5yE̕7g`42H3S@xe@_щͮK _8jءǔV({a]5Sɋ1ZPOщ&L3 |Gt `(@ӰD3ؗ<˒7>$v*h~;;, \Jus- XOLA!좁XVe1d%焹Θ4xD"M % ~r?0IRF8#cXE80 s2u'p>@xA bxCk \<6!QUկلNm|ύĂp]'HtBqfh&AXj~w$ 4Kf+ A<UH)glZ9Sihz2d}A&~ۼ۽N-&zLD=W'CV% `y$zyt;oE6SAXPO$ 4K_@h h9fqlmO͌  `O4df} !_ӗZW f-+8EQM(@Ƅ#.\G*rjh4*O$ óHX; u0a5|N$ċySN(Vܬ@2 z_y$V±Y"VF$K6KG7ɦ2!aWt1* cV;r蚍3l{sE@kQaKK)Fs0J.ݯUA婲,ScQ o\5W*++/DϪq? J:l0d o!O$ No ߃P2E &|/bٙb7=x1^}<^vߝC:Ɯ'-!F U+LvAST @$ hԼvlwpb|2X|@c !+{$*֩pMQhin}Y8_Vcs0V1+o`!&}yRu2Q&s̑Ǝ7hD*C%%nlG4R^%{а:blö(#je@ؾ?x;X7 ML~3 $o^00"IX|^Z1~9=e5pə>A64MH&IDu8 D(OkCYfKVͳ?z -s2T}o }6G7 ؾU+| S+y`$Ke:`4_plXM.< !Lt< 07Dp?@ F6 /[ṔF旖[]!MC*2WDsU9UN(Jk-4G#R'47uL+ rI`J71A#z |u,rJS+Vմџ{i#IoDTo"xK!Z @XpA.ǁB7tO\G cW tS@HI(L (?@O~@S3ns"6b?4b=2_ƫ0bf/,vfbFTrp$";mM7Ȁ$MPjf0WN,fN1l[PĨn9roifxT3 B$ kw"[؊C1)+;c"{haA>Rѧ@76NuT-S&fN#G\qWjif b+э9sfY| Ug0oS(%AދAvn/UK x.F XS8Y>{TOgc\ ͗>z%?@+w V\ l+@ָHTKl#% |gipEG5)+)5nشq %UD LJ7QPcL@_.nK\>vT1յEw͠['Fx\ j!,'ܭ B,PGp]~\X&Oq=+ -UgܗXptҘp)8s@SXGHb&/>h;ԊE+@,pao:'`7ly.Yuy5Ő/`ј0j/U&2!?Pd;+@i`9sAլH," e#Zjl8h_R{ @WML @C )w({T䀣#Ȓ1] Ч yQ7v)\%tЯ`!_IyO'. r6枚OYX f\,Z31ҔBw[l5a4WJ;/̀` Ff[Pn_M̨)M,T@ #*(F? Sj f["eh-˛X8^*3AD\]2B*>RڹntrHSH#>7Y[ Ĺۊ}< 8WV 7a? ld#FA u#GN+(wUe̗,M'WkPeImviyޫڌVf<PW^P[=N{^.7X."sMJŃȁb W*2Oc<A{VO.-^XZ6wt3,BX9̀sw_=s.F\[4"$ wvi~ c]\o~[|8W^z%Hٹ'+D7׻ )7 X7\tuB"eΦ˜J? rE:XPPT} ?p3~M"įb̝;S܇Ikк#BAf)DvU<όO`P59%+`:PE?'rQ {Db jBLAj>~%DlY?= |ona!RgyLXCHF=ր"~B FX@5%Z2uѐ8yp=Yorh/ynBB%- 5ޖ,K_>w9bYtj>;Wko\kz$4WI i8P(N1XZ(m&`01P`@[iV[I?*yCv/Dp3IW*[rC/bW%+@Mj + 0JF* ɓ>{щj)FܢݦW=!\~bC1>J#$b:* @KSӼHZ'3 3>fDv@#bi`/\Vg8AxhuD,+`P@ZL 4@1Bo߾W }76Y!Z%i4{e !Q&rgS TD ??,4?Z~ fE!uYD72u2RV1Dm~Fg?|byh3Ejp"Wqϰ@~ +O*)$>'R  _M&KH#wIR% P=& ^?l„bP# x4^uɇRy@&\%DQ2̞"fs7B)LqM%@$~8X!{ GiaIC]91hQ 5L7D( W}1Ab(]qo4Xk.}%}6`k@$仪AMQ!.  2wjlA#I@T!YN 댰m{ӊO+u P|9jfꈔK!T0bıQ2cwπ9$"@Ɲ20`,K,2EP PyB^'LQZ?Aka&)@ۄԻx"a Y Wy UfPR m!(z@i1pi4Vl} >;C)1}S5k [oxLFkiYm[[!BaRTC}D@7 @Po_KA޾3$@ֹcq )6"\J[G ű A³I廒#/-V(Y[912Jp3X7m.(~>KG 7)[[dSI9(5"DЯ h}tJ5K ji‘Z@"6 \a-&&rլZI"0)Y4> GQF>@f@EP>.yH:a&{qx^p3[IYs&^- -~oaZ&=4*\n%=2'ZJXʞp~p^Cv\7?z )clfDO T _qr,DTK'FI)| UQꬄ<3.rWVp Nw6,w[$ _iT3I2eDp`&É%kŎu8Go܅m/Ir;B@ZRϼl 7oSZ着\ G+(:Jҏrx1UPSw8TF$$ 9^C eMpek]<v N9c}M!A;xRK +/yHRb JI[@vNr;ac !cK,r+x`;oR /@qw|,wV߮rU])C±+?~ {G;#IN,OH#Zʡsv'9\Y}uJOK$K=:WN*o#!'Ot23# u6$!aKJ WCI,(ͻ Rُ77H&>,n%'JJ>KVBQ:'* b;`_A*(g`DYz2@-$Юr')>uF14nUNA@&hO$p]瞠SdFLȖo@ֹK.~d޹::IK_HJ1QDkf+Ifn(-|&=.?OҤ(LHM3]XEDz{aQrEOC@оu=[y鞫cD&nwg$ѣM-Y"}> |Ujn 9z@LWIbwj|Y&ՁKgt. ]1+AjK Ł0ξg3%.de`+3 / e mj~? + p>׎='eܽ`3g+]Hb`d㲭yrzR7X<=^8(fI[ܓ?&HVNmw]}:ɱ`7"ۊm c½GGu^y*A&:<_L+] pLz/O[䱒tKO#ђL(໲RMVVHu O' kֿ<'aQ C _=~ A`FPJ4~Pk% YH``oje:kT1)8g0gzZ:M ,~ǽYt bb/s|3>V YXG]ہ o|aAЦRWoKGz4r~lI:pzNv$H_p ː gl]B?)ɫZkujAE^ HG󤈖g敊Y<6Nip3%)ܧZP:"mQx-hLqX$ynZN0ɱ 鱉AfNq|~d?iiw_*ܚK?EYv?@Qҩc\_o`?@E  Ɂ2GXGr%4i$M"! @7NޘU"A1xm\T{6揊j*PA36%IP#  ،s|(J:0V{5`RWyFz`nz[)z-?I-\2>QPo~yqjTfѥ҉r,ÇU.8L#-;T)՞x[&OXΜ9#=!#"=Z"99 +H!n)$Djퟁp1F?&,yH:` B̥ja{s|he(\ A 8Xb)j%_Ϋ>)nT\\PIn| f6n Q1+Iׯ S&?tւ,wq|M8F87UUUJUUUҩ:uɪ2Ǫ~tmU'XfTb  OV/I?糼}@HnխKsYʍd wpvG@0 ؟WHYX @'B'OS}Zju`& p?o+:軺6FL<)A-YC( 0{h^myc#%HFj|-tCk{m%{LUePxVuAv7KU3&RMME B!( }Իjq /M3xz)\GY|w,-}$N$ 9$^+> j9YjsdϲlMg.mMneBX;[D` 1=)pr~!Y,|s?^g  Wg'H'okօ_ͯ%y/@2GRM;Lyrƚ$!RUe?΁4 к#4"Ϲ܇t(qJ8[ 2VVοWgřF7wHc>iYF\!"Ъ_/@}9%W?ցE2  Ke芠w"-s9 ҇z뚿y? rq~6Gw#Hwv[|b d(0݉', a!_ͯÝ!Gu(}H̓~?4D@!I K.9oOqKV( bd`U~!k xICa] !P"࠿ѩ(I糼Vo,^Vy5Qf] (j|qATjB7IdMb;&Ug;p?P_?[b%g!/lgG%Nʖ[,mxH{o霌Q#*G&\UHI 3QwCoQZf(Po "M(LD_QB@N6RK@~҄fb)BךIilz٩QU˻X_e3 ~F!n갸e'c#eyX|EjOwnlj<^K$ͪͩ^UZ ৌ3I$bF`_4A/W3+k `zzH(p\!gKW%qH'[yW VsֿzB[)Fb):"#jo4 <Rgc낚6}`yn]$guq. C4F'6)8Z7Xt 4 0i&}%׺򦥬e5 h%pJ$^{RuS\vun*"OP nK\__@%'z^\*geIw-LU&V9* `_m1udUZԑ>J^&mD2X]~c~)sANo@;Z.k+l/Gv (9C`E}#O.цd A[ V"*F`"NZP/ +%u@|;K1&쀣t2KT(}DiD;TZ|,R#CDTASySV0B޹8Y4hF|Wv3ۅ򥱅F#<,Ы"ǦIa6ظ%K\=ћh1V`lU:0E56: bvg'$cG_&Y&b`(hwYZ-MEtE @#I> "F" v3@i((.>w"oJ-DB"D̴¼_.~>a)>Nm ijx}8* ^!@1*'9.-@nw_B BR~MrAC#=\*_ :`ϟ+c-HFp@̽!f|aMV5 b{!.6 7p28R|OLQ@q`=B\@~g;-Q"pK~YrsRK%lKwk %w:g4ij=?ze0Fӱ;Aފ,9")`.IQgp%CORj}j~à }hj`߯rk4zI@CbɺҤ RU@c/@ s9T+seU9ه[2a[[bBC<~$$Eehoo+,Ybkcw  Wو m" l?KHh,v68Em.PZD qP/e|9>qGo@XLw񎑎?1& GLֺQܨVfƮ%۝HC_U'@s0I(4fV'ګ?i>"ã&\2]JHĨ ;X  ZBhV"QEJy,|h}M*A y"[-hF*P tR:Ǭߖ~{H#bP"%7]@Rӻ,yjpƼY(5\%IUO&$7RR0>7;Y0*[<Arf6F ?|M_*}`K ?ȔMs[}4{{[G0½73#YMxy<\-Y&7W 3 ,i(Q,SkB%l7B&4 N|81Fi-gY7[ZXaq~=p&R8R@5|o--~ bHA{>J-q}HlIYK[dɾ%e_~ϹZvKpBY"3q0 Z3sd49;땍kYDd"qb>=YJWOm|4Rs _:.ͻח@P$ PoI*!<1p4,xzLax{7tYs9S0.f! \/NyF߳$CzaYgnWr)ho0(FZ<&V.d[v@$zڿyh$@ܡo}J9T˘XQ((zi¤AJ q2,co1ĠlՂ&_K^#^O(T1LؒQ0EY`mI@r#K-~ XȔ/wώص@A~rpcKOS% -ԅj ld|2>Apͼ3>Z._ cLI dqQ. 5*(_"}&mgڰCK=L20mC[:!!^%gw,n;$!jđ8*ǎv6@Bf@(-!jYZZjJh30}=Gh,':\-l3"=3(ӧ @ݷj I 2Tk<}d,O0EЈD#j۔}'#/@=t|h i?9?BtD(S-kj,kaE5<&Pw[r6_:(Hm| v9ew=5]j@!:L)"  !?襙Y\ }y v!zrh=p1Ns(ge c]vn}Cuh}xqNx@QGlaH\ $@G޿f$%Y#@2s߯#UŴNw<|^+ IMw@7"d&fӵnW^#w__ D!'j fy({":A@kgx!@,DF}EB汷̯]OP* qJp( /`HG"h:}ݓ-*, 8O5ym~_o]!Py2z:xG.2zE8l["K@zťlF[ywjq 8=փp ɉ_@bQb1!pmHԏd?NΌcfsEa}GJ(D1><MsQ8Ժ"IŊz IG7 )(_"눱/*N,x5d5T7y(P* O4HVHP 6̲*DzkPD "Xlku dz.b?l~ߧ"}@o x֥I!ܟGǑ!8o$1N.c ([|h捰"}~[\+{]o1#@-{^x^ KCgq&9M Gȋf[TbLډ* !?7ixwK|%`0 CohT/'c$IJZ~}17ZzzC**ON֗S"o `*8GF4(R kKSao 0; o`$ir` `oN$^pqSZՇ];RCvj!P|sM% ݗwkndwqHLEC D@ީkDR*FϐɜQ~`D&}$PiKߢ7\kq~I/@MШxPSxLhw)[AtqdAxyebPm>/%_,\ygDR ȣ%}  v6fFp%&ԺBuI.-JpTxJl}Fc?}h}`ky  -&ոDDR=ժuFd'?x` kf (Po +u6,KBM7!De9п-?snʻ1Y}Ok ȥ#4@*U?G Jd~G^~t \+/ AbEAz"kr~_B@}MDf#ea_PHJK`r$S*CܛG`臧<@ İ<B:JXA5zu?33 /J6-(`ŎT0='VbjB&`$tSvXPullR"^H_3o wݭHOc:ܶ-*|idEywi䁍H 5:ZRN;߿_dmKV;t|̵xVm#-"Uv(j~k DA}~1`FxBYRkP~3;`]dVDk]u,k 0?m{gۊ|D@ܙZ}=GrZG=~Pjd;@4/ qOQ3O4 y8H?aR6&o Va[+_s'}^vW-Ρ)DR ^i?H}{-@RAZ|18_rXt2EdN F~ @*fрtF U(E~A<@(3{:@C`t $ Q1K _4(VY;ٺ$~m 򱵦$giO2֚B.!HSDD`#3 #8~m@c&F9?<+ h$e U~p=d`z䰼ԑhvq"tPa+ 䯙1~40 sB5hnh5(Lg")X7>@ľ)+T媁<@2 HdM *}Z@.\8ctA?frG^dw]+ੑ=~Kmo߽gOu q=sC|b;4 8o7 8ϽKJzx{'G$a8Ey)005o``*MiMHk(axd OeN6]EŎ0yJMSʷIDgӖ)@*y \ &5}o #b J[ uF?${Q[d`(*f~ C{o/Ok`Nfc\U.Ba0j{~khmK?>6p⟙@@dĀb1sSRdF5ƌIG(HԘI'o.SKGMKD%µ+j.Ra*Rɦ4ObRIf|\);VR$ˁpm'1<\G}*j["w#V joiصEWm7#( <;=6Wg[템%J =t|H  fш=! JGa HM?DP/'H`^x7{y@>icIЛkwĘ`PY@$4;ZD"'1h$RR*K_Q( H<"8cH>8}pfݯt]ї8= ֮߿`&7΋~ќWsf$  =ls@ʇp[Ofmc(-!2JDF ! Js 4RԡB#oʴR:Tvޢ$Qݹ_ 88x"u;Ţ}Hf3k" zg.9//L 2zߞ;rY*PoŐsa82GfC lAT<SAf Hx`1=$ъF&מЋljTsFX (O銼؇[]q{AS "U̘8?"|if?%덲ĨXH>UzV |ӣ_2j$+#I_Nu҃!5A#D#r@ H\0{Ư/,y+a\[? Ah8f:rA?pH?@ K"7 x{CO.Oa?93(pV{o@2>|qZ@=R$Jr4ŴY<4 U5Є@DP)g'=a$I&uT0sxXZsRir ٻǘތ$SH"wje džuM@2HO\Y^8K^Iȇ:}b5Xh I??0-%C`~fBL7b#oWb% s ӶcJ(r`s)&imzPvb$XWy@}ĚPU?!=F]RpC"">Z`n?f@_Ok  t% *f~ڼ yTL4tiCXSG%{VAuzdeV ژq>]5 /LݦDz?73,À40)(>$Ї_,L'pi Wg]W;pp Yhh!FX_l}LBh{{c Ykϖz"t'RX H$k-2_]pJ=>fA}Bι//L倯'Fu7(œպߝOub@@_,Sȃ7R7ao+7gG4A |HޝqUAa̳j# j~zo,4Qox?Fʝb%*(FWӍOlynDN$ 7?z"=@gO O |j QXe](%`TD#) vr$p?Z_o4~$ sضaC:*4y=ٮ|p©E4<?y+Z"@" hjs෭.|?C.6NLSf)7hqBzTS@}Q߃@% @H5HǏ[xO:̨kI)|/ $J'|u?g~ǽ{?LQt,UFޤ~gXf6I2q%dH j/o_!]ӟ4 Tw YF}_w!oI$[ix<-=P,8%_Qh myӂbMх(@|)Um'¡} zrpyKB Y1H@*xzf  .$2zDH@)Gz'u7 W `Iq(Mrx j @KP)@sFqG NU>Pu)|x}A_ .G!l6~{"? /<>h"lUqHP[{lIa!_$R[ؽ=ׯ1K޻G$x(nv~-+Glkڂ3 y.]sÅ"M~!z> a{ 㽖`BǞH-ldZ;=, -Ԩ\[I$>7t bD1 Z!n*. FBNJuo3>-k.:^}r?"4"A?& ż>O@}O^aCz>]ؒB4Q 5S"  @ B+҅hΩ|_ez?ȃxRg&g[ ɮ(sx{^v /NR'>,AQ(<~}? J&W~{eGcF^?/8̲#ޚk4Dc^{w:a~Nׂ 5pow ">0 PuV8iO`Buu=>?g?v{>ۯ7D,H[aW8 ޿0^T.% v<ό=%]?˗EoD%069  ~j-"@O4 YBf O=! i*yY E,6"\ q礻R*?>;#s^D}0߷(fMgQ@߿jv\GX:wjT :OE`J{/yA-E@P"JR2eA=!H4 `tN<>6_0j bjҢ# %DL>tgu'PvRGDeG@#{BPg&hh$;&uCb}SA@DII(?vm/m~&>fT' B(H3lSA*}$#~dׇı#{ xu 1v允:+ABžB: wbf@L .^>~-|#B ú,RaK//hрqΞB0+a}TO|Ė@3@Q}`*I_;RBNZBӃ@~@H-R+#mJk_,߿|`FAe0q *1* <ZSɮop wg|`|R'xIYڵ%~gk鰸R#p}ץ3 }}YV@^w__ rV{x幙)NJ.~R R&F_vl$WՊ$ /A- }>r' }^;R`UǏg3pt&Һe}FܛW bu(D)~Lu4N=lT Mgo/cOf}\Wr{pwJ@HGQUBdIޱM؛:,[>k-z&W197o0<*>=篶ss!?վj:@\2 :N P|OיA p|K&b-Ep^Zm}&BA-b-@J_ ݉\Pl:lfj}>B8ͮRBTHG]@"`Nz86t?ZXm$DzcU!1o?/xQ2 jn ۥcIǔKzK[,>x_lqK^F$참9wl($fHj3 ^x];g_n2KUp:q+#G^M)PZT|ɢړC8spd}xmH#Ba0/ uQ5}AޮFyC8$tWw}Ha:G7ێH7]!XӔJI ɑC6׏ ЃL[4@]9b ܽK:>̥7Ibp6 % >wJkn|%x k(x,mBm iB]o<s~B3_+:"1 Gn tPAū<Zl'գ?|i>[CKG58 Hwe9p>sPP8Qyҗ(-0+=Ñu!i"ԽooBd@7 ~ОOb~<^I}NTwr€@\1 U3L>#)t؏H( FcIǡ^@ Zjf_ɼ0Vh2џkĮ~5G u<+" xQ+}1@Uk{ `SBZd?_y=@Okd[DuHdt%Uvg !9 YjLlujv)Ua$=ŪݕmnCMϽk I<}СCv4E6mܖR)> "`Xw;6m=$69AKk ~qo}%Ǟ=\%({[ sX] Rǻy<K}… L1Gr[䬛~gʶ;C9t\@GɩU٤x @/ }Ag}oz@?b`r'ލa̙3O<;u["u ܖr >3@:^@wUj[h禷'ӯf|dχ1~zC|.n*`'+صm6vigJ<,?J_ZcҥM4͙3͘15;YKK ۷s۰͛7%BC@"Y$1*+e/ݞ/M6Kv-|Ѿu]!h >w(^|o8{T!ÓkH Pc5Z<R0e6~x6lذ`yyfVVV4hj*++]<:H 9r[nj &6EZ -ɗ=m?kM$C9V1+2Ǣ;v̎v8xm'k猿&v7C 7GVso8txL}lo Z y_d*'TzQn{?uW^a]n1ۘS*]z=渳=wrۍՔX` kjzp4w}gVuEƆquQs.sUݢnjlֆ2kZK6Tk%8 LKgR5,V9?=3]=X(3-TkcHS@رcĉҥK*k>HHF x4]y] i7V1ц֍cz}jSy/+rF$6٬_f_,Do怸}!l۸r`]r(|f- [4lFS%u=o!k'͚~f-o_`NŶ/dǭsɷewWDa>{i5Shf,{a.ؕElBVfD( `* ( nkJԩSy56jٳYmmV^SbMٖ-[K .* 4m-C;k;n]_hƤ8gZ Pŭy2dV[#۠ Hbܑϼ2|uޥگ齿*k`p[5u}hoͷsW{ݼ= ϗ* a'E kgyŷԼF@0j{ܧoӌXo-㑃_f/nLð6-yv#_xGc!TlHQ eee*3f 6mT# tj6nkjQܖRw6k;Ԏao]Xzy{؂}NV2 Z:Hj:r[[W-ay>xn!I] +Z Q[ɁEM\ ]oov/ٞELG]\RME|Xe<wI!{bu {8S@x>MoŠ6"\= At.n.^;"{EІI^UUe/))[ޭHCn: k: 4?9՟ݓs14I ph|@S&yh亪~UA.$gQQb{qT 3jWAړcO#|;Om7?o^V+qQe ,#i=pψ;l,wc=C"텡b& CıW?xvϢDVt)ߏ?liڢ㽨9l~/#kj#=],+YהeuQe1` sL!Ho(lVk5Z +@^?Rnki( `˜taJ0U$T ?Nd׎ )ZAzo=W,Xh (CC?@P?qt𵵵@"]`I{c/fc>ID 0& m92mag}5~w!?HB9 ?l2Dz. Hie|}o޷YY4SzO[ȘyCO-Mmv^b 69D0:joFAx GVX8|^?g46rH^7p@ QpCjL8Z_=|3Xw; <*6bwa3{~s` rP ϿAƇ )t ^?1 )tlr`Ƀkz WmYYG \O=#M[Ш/Rtͣ팦ݑ!O)j«{mШ@$TuZc"Z#>Z-Ol}Qw0|1OK<ɓ' swk;ttuN>w7g:آ3'.FȖ;{o{]):=PY>o'J/\luY Xcca#Kdݲ&g=@D@E`恋޿o;fb{oʣF늵OB"}<<pqLxyOѨ_Ӹ/; @De@\ʇmz{F %5A4l9ٸ[X孾\@ȣG?a9?yJT7#$wVf"8fTQ#vֹsAsͻ|ُ͜-ZT=xgcg߂XH~1yz\i˽KC"¼5{H rpeg Qލ{>4)߾Aq5A D%@REP_<𫯾ItU s{BAnT;6Dr& a(CϿQGYVݛ{q8o>P6ZP0m˂ j$2BjmkpbL `A 6[KߖuQm}bqѺtF;v:yd?:<$E`A:db{1gE ~C<|Yצ9gF>)q9 5sPL뿶'<믏2BbŵU? }wH\p@ZoGMl1]MlA`GwE?R/G`<_Pi8?}*lGF$N$CȫU Dpa4ےps/.<. G OU$fzM}}!|3<= /Ǣ~^' K\TA~ yKx@ uH@̹iG+ f*( {P:yU"!mPk:\_ "`_f.dvsb2BE/$q$Ax9ܛ"f-n$f00>Nз>a ?s>$zX "׋(Q==/V FP(OŐ*Hu@5t<\Oi ԩS{/Qu70ЧO&?ªWgvyz^Ky|0DD%샖\)oD(BN\x,6ۈ%p6t73D r - >=N '  `x+ "2D)u6^TIb'/`(FRZ(O?LiS8ȏظfk$G$!?:HM"kćC$@|KDsGFZm?_:O1mv Yte+}f6bo^ ]0a"HZ8@Ȇl#SO &A}Q<B=4 ާǐ #-"4QH'Uֺ^d?ǹKa}εr *`gک5 T|P8p'y2Kt `ZQ0: $üА:j?%laȊe\) `(EFpc@z[_%lb c׮B+'~vvfw@i 2J\[ *iH6=1 }7amJĪfL!w   %peBܖbn+5LsьGd"o5j! "azDvod~g}( ~zXzQH@K -^X %PiYVKWZ }ɳWPȶ6VddXc~55.?LQ?q f(-< Mn y1-1@ޢ/zoNyf=SHǣE@>}(|Cޯ5 ~$, q qeTx~}ci ŜElDUx}5bFXF(C?I ziAcz9`" ]zʶjܘGL-GӇb mC7'A *J>:I]D@Yi0ٸC:G׀8$UmToꉕ~ +kMZ68_>Ѐ(!R}>*@QJ%"_} 'JvH@I믙_ƶ5Tj$uE|gP ".b'- dXvnL@^ Y4GiCMżB] PO`mԮ@Ł~ nzgM . ם{]L ykrϴm jʹό m@ \X,8$7;K;J<`>uЌ"sk- :t֫k=>+0Ӄ-zut忸=h $~E?HHC:8 0@ޡ41CxEzHU:" )`l77BJlƇ)R@1HadWׂliDJ}JڊBzEߌP^/Ռvf$Օ)NɅhm4"أoa sd)m<5 O F3[-ATE=KhP}uO =xi=ȽS3F}Ncx`ʠ q?H`O4PCHd  9 *C]+|{&u!D~-0 ȅQFDG|P$"Hy"0HHo4gp;D; x}mҹh X6P0%qH75F (a *',Yei?W;d=}Θ z F ͘ >dn}1@v N_^|ηWZz@2!>N- Da:3A  0ZA\7jВ7M CaZ{K.U֭[O/_ޞ?~!:12@/W% 8Qd7B~|[Cb3X657hܧx帿|3(H QF|zr@1!`}50۪Ul*QϏUT:=7B(aeee^}V\X>W)mw畞{ݧx^T◴{dGN1D8) 8q1"@e;y}t?x}ֿY52[^Q_97i!^+M_^7gu:DG\ ABqY?Y71\|mҏťM;[ ʴ= .9"#Hm I$L+{BՒN`w : cz?SR*)?Vdih$`kE[+y2]JassELOJAc@@|7c,S-I\eP=Z,A eU!ğq хpyKIFիW@1oϜ9d&z TzމpFj`#`Ma׮`5+x__b`жzM+" JS{DWȏ^ųr=<94I=0п4Ty+-ucmXR3piEP?-0VP[ku_v}Ȑ&hDLB8]r[ҟYPj*}?EFwR) 1 7G6~'}"I!L&D< jMq i !lps: )8֯_% HϞ=;LEa!7 xR DRـU+Y!Hd`fVR& e79um#mFM Cta PgگA= e:FSWooJB@1 шD8Zk^c%2#jhZ h?ɼi-L5 _Q#$ 7SDxh},cr徙_|sܳgf@[@sEU ~1m)OR'ԩSK.u5551g{o&zjTGxF Q%U myV9F @3(%"j_okVTS_Z%OD( :VX b1u}xߛEH3L$5/#aOQn" iKFۇ a9<G6@Z rK/1`Ns @O_">65ԩS'x"(N D ":( "= >*@lC6bvc>MXfk~kEi#mQA* 0I-0uʁd$O2๱@d+؄#ԩ@3o:"2I$^d*(!`HZkUPfĚ1 qc|Lf<0@ DCiۭ*nٲ} yoy#܎tk؞[܎nelHc3Q044sFZhFOhzvP8cnʧ)U 8"NQrML\ D#K+DFH"0#> z`)$ WG>@ z=\mw̜U{ɫwC3%FQ|IUÙ~@^+ 1!PwG1W1Bh/D:K`x`c(`g4=~<.N-3Y&vȳl5lz'dYi[=뿦 k_v T04&(]ȻoiU<=7#F#g_A$yy@ӟ.4#ukx D`8pΜ"u-v lhE@5")MhSaT8~V$sy{")âUlx&i"D H%?&#ǔ0eŝ2c38YF>H`yR`_w.eaOxa Gi.ihΤcMꔴ;GkX'M6)rDQA _x_7-yhP($U@?/wDHVT`0H,y-NC{{yL9+.4o^q ? }Maɿ𲕢!zw+{SK^{93 *FVH>l:p$ @D"U:Jycp"y #"#]R-B@8Akg;Vso"% dg:0!ۛ§>={[Z~=1rE*D+ăwwt_P 0Nhfb<0ulkJ y^{{q>7"4#paA0YmdXP0C$(= W'[Z̘Y*'IձgRpxSFD@ 7R[sD("o(O:E  쓇}&Ο9$"|>"HW*vWB*H V*xˮ½&v\'}:q|ҵ lP4HFPAF"^P&8?@7m:hC_NP\RHB@)PSceӧgϾ#L@l3N;]D|A3ųOx&O=0p!@ =?nH6V~3*@޿Q_OoF DT0Tx( ?dG_YYZHY v&CoZsOy8 *hwlɐhmmT%U "fih?Н+&붽q@ˢ*i^*Q;vĘ7iohP1G"=TESy]qP&A2xG &ƒ c&z We G}hy@*71b%H}v)zt(LUt0?UUUǎ[Xn#Yr|s[À}>&?T+@[8)^>@ZZBD]H,vk[i:}d&>=$ttJy{^:M__gތZ(paq5ϙSS%y #} lpKOfGwq'ıJ^O1GA$uŅ]ŁpZPȇ=F^ >(K?C>)(-N/?WW4'+ؑ&c`I ܹs^<[9#o 쯙)\gvF;4T~`~YN4U RFs@ml(R( Dqb"zFN~lehcg U'"S'G+IvZ/-= JǎΚi7:^ϻY`m_do^>jq7oh-V69ټEA v5c A S"TA?-@R@$ZUCZvO)O*X@aL&0}޺ʧJ~3zFU<:njr\`]x9=_??SAO1/ `gQŀH~E#@nZ8ح7סoͼ_')]TGQ/P_D\]ڶ0s \ @s=\d# q.Ja7 'QQ"He9dDQ?աm $jP'{X%c$$1cnCߴi}{kKdOڇ?GDps\"/#Ր}V6hJ eZaHuA!Tإ_TPy(,% 4~ @ H T *a{T>FM]Fp?@VS_Q Dȥe0f_ oh`ۜVgZ'klpG<ZoNO^k0jgz>m ;+ cג$*+:~VBt3iה{(("FnZ7s&"/]ұf6I>!ȒSGfV-2#?jx91"Æ4 Iu#SB~|ʞV;3NC/?/LwND0rJ·6mUP6lXpС\ 7NUѣGg>%U{es^ZЧ H ?:h0(ʑof_lUSs.m`֭` pfN=\Nc! |)a ;Zz8@֍KOM ؾdLC,@A&=QޞO|7EP~(yj` id {K>v>7H%f?:uVvUwǛcG Ԉng){P"ɴJ$΋wApBE/lԾzM _|N>G s:h?gy݁Oc?4!(%R%|u|%ug{A T ?7} Hf@BG?vaS!'8 $Aq3-IĠM j f Y 4+`\7߁)%/m;TzpRC(#`-i 5ܜױ+Ս+Yilfk4P@f.L:ws i* Däc ޞLUFɀiUt &յYҟ ,p9w*Vǐ( 0Ol(DCq)bF?3_X?2/T%`,>/ *~G Hk-? @Ap{՘xZa~x=z`GTǂ=.?y1yLٳg/\%3,~pѕuC&M}2BQҾuJ~9d,U0Fgm;[Zj._J|>PNj 7;TBQ*b#u@Q Q28V!__H}RAF R!WQ삒^p{٤ID`%%BüHvABnAW,^^!PLZ@ǘZ, z"\m8'|=yH -Ǐ >ZN/%K^SW;{$osM ~J:r]ְo:}t@g_hSp?$"jd:B{sk]Mq~[\%9lZXp3ԍ0T+Wޮ)Xmj=33ά"%M`^n]w_NꫪѲ2ZٻDA*D^dC#|T?q7T 5E(u 3bkV:L@ޏ"R uk*j&$ 0!;(nWN8o:w}L!r 62Y#'O{ <-{p3j`T =w;T*RqH|þ~4o>ϙ=Ys\?yJLG?:%vH`d  =90ZGjBXA~2to gY엏n E5]L czP RF7Z}#T^1?隣:(`{VMVdab@2>*>Lhbf=„DY}ʐض*4 P>['6ii A"@W,]7lŊ;@͚lƌq*|,6A*Te'͞ 1w= ᑾk Ep*ڇݓY[E, A#;~^0־_J?rwW;nҺeP.ll6E~}wTǫfy_@ͯ|}Q|$Tֈ*"aãjN=:1c VY,uzvM@{!]p`Wf@r`,pŊes?*@΁99O '<JU@@[~z9Je#!׏xa޲`{8\e~46y#Ge@^~=tYԖ13l:?O!/oޖ7ZMsdG?J^"( m!, f̘i=j`#f0D;l_ {`vnVȪK#`Sum5 QH|]UŵꂟjC ~Ы&@T[0 \W_:Q-] T-!{Qp!0h_%'ܼUL $w_EFf/CGۇk|1nFV Ogcm폗1<}?+V@©}}TG&/Iзy ;u!?}t@_%ڙ 6O rRYǚK=QNUTj%vfA &S]lu) E\?l\r5Z^M7OmT.Jx,̚yu$0TIp^gIpeOIŘs$nInIﲫ%L9%\xVR–tPZetX$ܨV<E{^Ȅأ=[ځ*u-W̻z|j֯yVm[a*jK Xծjh''_BE5D|eY% qNd0Vi {Qc6L̈́?( l{~W ˆ8Zڽ4 4RgV=uuČKشcs YޡE\9scWVjǾp)s )p}%^" qy*^NT~bXgؔNl%Aty QugjFFW­5{௎} \@]MMMz^W<}Yd"!1c/*{A>iO9%@B< `|}${A0ڇg0[!B}` `Vxn D{>'x NʊrNʂpDUp-Zd?({яz% WWqFM _-so(nKx2|M," pMiͰTSFac%@z@Jwd 'Ϧ knJ +Y%lUwƩY52t$ "懰 Ӧ+!  &x"D FQ|_wspΙN!{p`FôQ;m9P \YYv~mCO@}?۷J<r|w|d q\R0p2܌3^d͙C<9DC_zQ"Ci'".~eong-?WɂW~M QzgE‹%bY?/! Z疳g[D wND!Y`jf~uDcb?qm`P%I\d:?<5g2co<h:&@Do.KJJ8h%j쇩%~F2zdʱ޶m`'Q̞=5T&=;"9"' ϹWgj@_%3mX}@,ߔc TA"V %w{bZ'zfJ՛I~?zaڻ%% @/4HY;)ߙ6dDe=ރ$^c6knpN"Ke0,#SDZ%Xğ/wY}  gr?Ap,2mDɽ e,rQ]b/|,h@mB@P[8 /T볥.Ug`&lgyuxZ.k*gw|@G%{gyDt}w~>΅ϧ@f*QjꛑDiT:7 2s5Q09 ɀ1Qzd y8^.9So~|ٯsRTFOh(vo(2i:l<] g"@A` `zB>s}ŞB|t_4m-tO-e6Y[V.Y_})>1 *8aF,c `Bi 2QIJFlեlL̤zv|>zEρ}5uV72 #{z Y{= pˣwF Y葀X>V˓Ɍ(P~UXY?e]sqdFsacM6[T1,aG*zE?>>T1(B@"t.]˗/̝HZPA7E曽RZ 8. &aoR+C̿$XvT}ժ<'aBM`՛qZF']~0%Cp&'cڊLA_3* /7أ["b:_<: `1?'aٲCe# &= 4T'0%m2vh2y~=WCq`-_my c?K{6,##@?'T.5BK%KwykƌS?'VO8g@> ȟ6CLL}hljaT'@AVjIFA5VH#!?M=.A܇l8B%ļ(Ua2x>~ PwQ;fr@< D!x ğ:"8:Ϟ,9i yLEocnD `J@ܱly){z-;fikr\s׏*2~/;#}(DR=UP!*nLw.TP CFǮ2O`j]:Q1T7?B V :YVPGӖ3g|v[o{~L p3OOz@^A,GmZ {"rr-CKل3{McZq߹=wn7Ί룄/_y~:y.<nUKD&j⤀BrYsf'Og pM&C77ADIAP% ƄuݳT =G?'ՇVqllL(6b4ŕ}G&Fg+ GCB 1(ٿ~H!:(3ضN4b660 3QaT]E= [<}|}jV`o*,yU:ˀ2#~&l &$ \Gf-ޮ9Y!C XoR:.l҂i>:u1k21pt>B\[5Thׅއ@ZA>81?A|ޜ? "}i@dfwN?ʏ`-҉p{!UDd,I"`|;Vb`ҥAd +Ȓ ^/-- Vmo][]?o.oٞ(ӫV!A`, :e,7 83'z C& [.˙hK)ݑqSwɒE{JJ#nz-=n_ j&9 ~)+ )@N?F-K͍Ǐ0mӽ8?"~8u䣵ײkr ֭^]r-vSxᮘx-eXWfN$$@Ѱ9>~r,Pb*hQֿrFw?`T qzXrb4y2 )h $93\Xxd@(&vD~'H,a{iwg.[>k:%lƉeuSED?aT2v?ed,WWWs7;vl8{,0qDH10 HX^յ?Twyd L-|hi+_E"_f`$@ހhwy?,|=%Q=V%>?4?ݿd =bc4% /3gx*C@A|"~ebsĀUNX~cu$KkrY-WJ/ae%Yc˘|~)[ (#_{ΠC O& $Kh7>ӞM1nh-i[dHPt? 0nL#~!^@C vk#=uI12MY e C*  _OHH5dd5`ٲIɮS3{tOkVot}  U5BCdǣ)U*]ĪVf9lUH?GP4CII%>2O] ik(d? .7i@%$8+rxA9FmT O TU[bXk,JO$pkW,DϵzI@wgPΖK8kThĖЈ-S2';~1 ~ve`sC_u@r|:'7=^6c#_?{ ll{MvD_.X8k#~r@uh@:`( ((V^/os~q-X,ĖL'i@}$[re9sobq.Vl۵nbϭ$Sd|h[,>@2VL>B S@ xe8ʆh$ ~ (H]# <\vf 6h}׎^{)]7ducnf@ܽ"Az{}0Ef "U[فڰx`M֔5@a! #UA>\E?hؐ\4UݸRe{.oH'Я? ͅP@=)@QyID$x .ON0Ľ=ٻ\{L`JpslME@c}K¿.NĬihabVdeծZ -t)A>\':FhI:81Fm+X`lgK-_'KQQ Ձ35bQ,nL}+Czn˔@&nԷۤ(U5\#=i,?r۲a V@]6{o]j6X*-o1&4' !… u`K,}ok?Ͼ?ܽ Ԩ5hqu*m<;O~Kз0g5A7% khh=vFX 6k\=lFGD@&E@'vض)YJ|k#kUeTG3VqDEV'"mSl%*\9ΐԪ%;eI)n(4G? \(O+P/}p TT&hԐ/ н=7O7m" ۧ|O]i ͫ}gu6Aׁw4͉(} ' C# v^,JL}ͫ) e>w+~[Vϻȍ,3}rQ{ ?O79} >]@R 7p 4(^c;YǙ5WVD  )Z qy>:v̰|݉/UД{=FQT|zE+UOV"@A pa$k0?J[U :AGQ=ǖ6MGivɮz 4 2!O`b;X [_@qg8$q`mm]X@>ZUE0 npWжic::(FD H,RM?0 vX5Id3 )=9@dQH|DKM#yeE.۲ϣ4Q!pǙeQ "wNd*^*@\Pafoht/ꊟe Fj|zd"a?m&Q x祬 P_dO"D+{8nu]zAv{ce21St$ "@kxA*H=$L(@A&ƑZi GU`Ūlb>lgGIĒR_7ސqzsܿYx4 _A@P ?< |;+`fH/m'@yg5?mVdj@ }!E2a*P·8H6.BD4 †DVNNS@rLƎzޤpF+ 6D<>vHL (4a[׎2m+}WFHsq(G/,-cU翁K?vUTc_7|;ȫW[X7 Dƭ0ќ,i-Dw mTq_"D *\$(ӿ\vA֬`VhfJ !{Z*"@Ǡ*`lqTRߝz`xZK(@RHC6@Ȩh-o+ζGS SOzEp2,>9YuUgDYU/7_D$/LsfB9OuZٹ/^^(È(W@m@ G&$o/w&\&xNb*bl8;T1L! ?`OzG|v j|Ym$6=fP&k"C&$@Ӿtݳ=:OaZصu].+ʵF[ZDxzz[ngF tcuT >?#w8( !ޓ/a5b9@tr@^<;?LЯkuڒ,?4]2@uPE.> ب-ڵqKh`Ӣ^t:0`k.(;l*So۰/ K.՚ /j_7Z,h3{UdzD G]l `jdӒ<>5E-hdDFDB=EU rDE4nޖn͔ٿ/1@A 4"n!ƴ6MO}g }9+6br%uH];Y"7i{#`{w%P!n5d# @ J@<`3#TMK޻]f@qA0@`jۮYp{8H'uO~/f؝ 1 @y=UfK]_7[fiSzB@,yH-8Iq@2xJz&CGu ĉz S|o  VWVqy&-#3N#NhFB9f=qyf$»- -:_sL.c[-Qл׀wwO! u:ԋ 'kjwVh)frP508!Hʊz~clk6;Ezz׾pQoPe'lD-/pQĖZ*ԱTjdp B9@rSb0+p?FbDdM>gׁA!pÉpf?g @5j^SS@L%v488"\*`ofƲ-9I8(oa]u:D_g۵mewzu1v 0e -6j8SP5> DGd׳ 2Om$"@^wPǿ״i.}˟ ty%#*LY\3"+7ml?qJ"@m $ԏ VF@-2U3"uPߘx2GrLF{=N&D0@!0hB= X?ZH=)!{% ?OLȒk>D"5bQL!@FxK p&8[*@xĈ誱݇[#Ci@*3%KQ&:O`F>^Y?H&ۏEXYsl5AB7n=v}f*RV {E @_/@7߄sUTpo6" T= jg uS"5[ӫR'4o@v*ΣR< ,kz׾SgB)! @HP^&bI]nxfc4:AV ]h0 /_v0jā 1zov P߽Tҹ@>ۿ[_?ܼ?W^'G|ةC _h8 1&:/<ïD|ͯ(NGBIZ pfeҿ[˖*i.}by\O'@+߯x4B.%5jTzf?۷ IAc纚,yfK;Ұ+#rnj_򗈨Ɵ^T8?}7P }7dɀLtv(`( DOe?xӻ1=婀w6ChSfB@1gor ?+(ÞSHTgF(8Siގy|\ùIl(b?G[Os󪶶VIWO,X^^nD%%%qe/ ְ661Tjo6 =byfB??`rfսjfg q~;~_W@_󊁪S0%捈@$F ,y6ͤ@L ,jt7n{#\ {.o4%.[6X$6 XХX[(9F`TA{ŊybȽRV/P̯?H{{j: .'0 ݻ#F@5N;_}UY_yUOw<=+׎ꑩ z$A"r,0cPEoog>=l .ҁ@uVzATA"׾@bDˁT04<D?*^W/6HDB>U-dJ'!D7۷m qg+** ݙ2DOP4)$nu5v>c ?do#<//D+dTI I^GW08Wpސ|^/$)x^t ϔww!p7:6'@ {0!HK@"Ck6FaB$"S@e{:@V^$/AhI T@d# {ZZ#թ}"`M>]=WS{lҤI<˗/gX(I#Sm|I'_xQ~3gD;~d?QW_#=~&U!sY@KA@|'}}ˀ,D|W}~1sD-Jb}?N[,SA# 0D{v+@o/ZW_*5+А'șz}P@9>UyyiHD޵Ō}Kz׆@0Jϭ5ltr'!Grj:`=`3~<&hwM@oDl [`#pQX<m=UU(@kjjb |<[/8TbW%_G>N1%8PTUU'ȚCP,c7BP_DR! JO>k/^~1@f8T/ɵQ%ЩuܺW\o+i]@ϵzk N?o ā@mq')\'"Nމ- 28 J^>7O. Wx맆#2]g$?5+FPyޞzݮy\'P @ZkHYii)s\ڨ U蕪^۷odq H<[JDYkZczٿwk8؏HP裏гcX-@^xc1 l_$wB{"yi(+5%F(Nff tr،O!#KeXPoA>|=uȋ=FW_ b@U*8Wle bsf! Uzَj}@vf_ ~]]!r#dP]Wd`OkrP_rl {cQ2{S>?q{En5 9qSG{,ǽV Uk >zٸS=P\ԶXVn(viwm/y J"PJ`z=*"Zqt/3 +`^DVabQu <A{X1, @R~@0pWe&;7B9^GGG(> h ?~uwwj?>^T,*Y~P-Q\C91r9c~C;ﰫWr_FT%M5{}I3@[zyp2;[Bv8%BpumZтJvB\Z$#+`׏?3@& NO|gFPzGر697L^mM6qNN Xd"Q (UB IQ2 6@n%VUG'kooA/ ՛WgeVnD_U~mFO?Q~ҥKϹq;y$G = "©ۚJ,l2b'Gɢi N\:{6-zˀ(CVh8'3#t,[[@ڝ;wV^[x3%'u}QiӦ1*hѢVϸ(𛛛gG d nc5%FORs~2y*~) fN5~I S|wdF?:=*Jb{y^zҸ_$Rvrs %=F`޽{+d'@*h!h#ԏJF\{p]5S*? nMdPB?\ [9v,0256.|u5w_臯FOmkc 4% 6qfߥe5"r@@#]``wG}dbiY;tׯ>m+tq;::By *茤IENDB`tiled-1.0.3/src/plugins/replicaisland/lab.png000066400000000000000000002004561315121121300211370ustar00rootroot00000000000000PNG  IHDRŐgtEXtSoftwareAdobe ImageReadyqe<IDATxiWy:u8?#u-u?.!50\B.8 @l6ƖlY-njukV[-vd!1Ii 8|w=Kl^}v-dU~ߚaE1K._\Mo:_Ncy[Rmo+|w^0ſ~۷o/nZ/+,G}ػwo?^___nݺzᇋ 6a<߳gIp CB3A?'ikΝfH]vGrܳXp⾻.-6Z_v~}ktp`1mG/It-,u=Ь7Q9ϝ;x|Aַ5 n}Graa`l Ł{,o|2cl޼9xM|˖-} 6` /B;lB7m׾ ꩧo(կ~5~>p7߁+_uۿPjZs1.\xxla5{hW808=z4g7o(?,3Am۶?e߽kwkz=Xmb}׺E}꧟CVWt_f϶0?箻ꪫ̗O~EMȼ?Os;any_^+?7M2/3d!$ŦO~RGD2`lFڤ~ eb?S؈ 7M6.AGf&Ά]_DUa,<3Yk:3ڷco#2AC|V@:1C/~?Fk?BVg"dC`$پ6XyW!}WgzJqhߡbuEK2;@q$ûe&im_fkL8ω_+o;r, -)@>F25=:f͝Gs{WqNiuӱPo @=3FzdD,X`Nl2id_ K~pwV`0o$PO~zI|?lx66p.`/KVfsHwhO][h5g?Hʧ N?pq 9e~ƥScc(yM2}oo}<ڤ )?q쉓 }?/53jiW_kfjq׶M5g|jl stuϝ/TZtB$>w 7NVi $Q*Ω!) L &SDg(#wsRWuYsz@\?L8U]"lM\\{i+ 5J!N|? #g!`8D<q{>s j=Z>kW>?7Ylݸ%O\ ܴ=#mpB^xE7]glhpYSsxvؑ;kv۶l϶67_K.Ilt6H~,4&M*q A:52jd¦JԍP5ac)yQ_~cC0 i?^#w5rBQi[CD0́gg!c}okdWwמbp`}Y>hĴe3ZtU y}&@{@v5cL—FI?cp g}8kc-u~ڒ>0ȓ5~MO31Ŗ/kwӯ"0:a<~w߿gD7c>et7SEO_3_lhCL6&9W|ʏ2ˮhYmOR<'B†a9x\5/1Zmلl|W+;|)~" +bUU; 6mjJn~0};g>/ @xZ;£LLO.{"2[C##uL8O}~ִ-e>#\lٱ2 ! ac`3BYўꞶ;/FGMxtsMu:o:98ȸ?kqЖ-  &ykܙB@rFR- -OQPO`%)é_8~箂 xh+t8[]FP"e*!>Q= )s\q߲➛.fjӥż 1Q9_f7n&"ub&?pN?vl:qIz D}cyM㜛sYcֲ }OgkhW^ 5}q#$))T5j^j`탃>;"$PRpKUdG i ,&-0=zVB0=h( 3]vjOe5u'Ue'?k-$k$\y@aZT0a~I¤s 0=Yw4 )}@Ӗw5_Bޡ.XuF8 }B@{UXU2֪;dPfiwqw3`l'2 qO}[rKaoQr26U*n`\ g؃y"0>Dl&굑mŞ۲o?S&cAK[pYr.WmE8O{U4()<|J7;ᴗ`x!N|g`+B7v;l\ {]*WTϜv-ljWo8IsYfLlO$"[-B&sCXq? p0LPm E, oų3t;\nUPNXLbܡXD?ר}`FS7jo 1:Ҧ4'ِ$bκ< I"l紮RՐ0Y.g3Xs὜>߬39]-w?[~x9tZٕ0Qiݦ`"=\qv77&y׿dHfe /mM ws@6[zb"7kxWf~E0:>ڧ~և2}4/3D-bl?g})>#:Ѻ,رPnۓӳzmnLַܿܟzh]■wN'[!\+_̻UO_J _-O`'ZM '8"lXx631ſ9P֨ē8L f~}' %|ׯg<ݫ*|g.m D[.E'n0nP:Ya g# ̨̦E)oǿJ=֭9i~?~_X\`_!֟S:s p_@C^ӰkW)._;`~xc7"0XeȾZ&bdfտDj_t?j?Wڿ̓{huG ?V{$_ѹV?8p6f&fS35ZC6t{5dn_Ŀ2)R͌;iv&6sIߠ T _ T W]*7CͣM7ʓrBac +3nM3>=3* ۰~CVႀ^ Zc-\($B 9+A27~0%pN`Hl`?(u_m GAeU_@γ_0_y+YaN }QGQ Ͽ{T#[#jpܹm$3x.##11n* 3O/?GheʶœOGsOP?k}Kځ̆¾aQ$zDx3#h&?M8Yy_FoµgN]bMoS_tŒEKN %>dg6әZ[ſ>"]*0ptT,iʧaaj`s*!ҕ;tuw}mw[$I%IqF.g֭JfHx@4SOBE6K}،Vm S?fDa#<>D?1(}>P_ꥫV,Z1Yxpu:gמw>v`}$b\4}{S}xk"8w;gkQ7% JǢU/S@oXԷ$rh3EdfDʗ]Т&E2ƙqp8LI4> ߏq!_;_r)nlE:X23'Huך3hP]tqmnzܲeJVͲ1 p}7@8?39AO4?S9bT~=c쾎kn)fcM/Icl$GOg1~p 8sY{?4Ki *,ܙ?N!6y>Ou $ʼn Ry<5R! \ާ^7sY`W;;:/:gkK?R㿕vVQ)CgWJ #;FNb(w~1_;0cpO UpX Zdg~&W+  mkTM톪{6wrTpWL^O16|yWfc£Dzޖu5#ghPNj#d_w9ᡲybcͽ$ ϩ`l44zYڔq |2&]pe*4 u?X_70ٵPq 8 :_`=}t7S̙ٱy8Pe,acaG88w^ X jg"P !}a`p U3+s DjS.۹v/4O @?25AheF &*Lb\ΧhH9< g3:Bϩ2۾ *}*X &|&#jpP~ؓ 1Mhu$2zUt=N؅.e_QȊg~oό'An}嫳`ƵC4?-b"l^|͊z?\mh†8p`FTxeRnw#;}{-~e*H|Q}85 c}ډ?p& p'O:]Rǭ'9pUIyկ~Ur>xҬ>cţ? wصxgx*ZHNk8xzbЮz`kz `,'k< /9v`V{3imƜQE?LTWB쑸o&AnҮUNqcE2y=P}7h3'5e+_qo:ןG:07CZ }i |?@[ (SgeU *|&~-_1H_$~~`r2x>ڗU# ?Pϊ\`ͅ yׯ߽jx؜=9~ޥR5) ɼnO?t>yA| XN0=d;3 ^ />O0l_6 ֠f\֖ʹVE?XWXE?g¸C׋:?,:Z<{-~/ }Og_i |Ŵ-@gV* Еڷ\aa~2 hh t6iU>urr>h ~y: Ø5,(ɡogONp| 3eGoM%}O>ǒ{DsA4q;&ơ]ֵ\jԏ n+GN!9Aȱ`^k{^#= _1N1ϧE8gu94Eod ˥qNln2=~WP` ԥpﺸt~p/ÈQzoXg>y8ƅ9\ %O Pf_ ˚lϿ v'Gm:]m VU{1-ͧnRh?)Fx']n /BDWPwec62m#MJ6 Dxn@E)u7TwiizxGa"}ޓW{«ڧ UÃ'ԇz-_.sNHk3JaXCa@:c?bnrȆ8kC9f:FepRoY(d{!+L1h?lEk\qo)cE26sf̡&6,~61oNa.ywLZ;?;e ?o΋/Xo<ت|Z["aU像 *|d1<;m `ó1~ 232H?0ڞFCޛ|N '.dKl$,]0C2 fQ%@X`N{648ү>p> Яl1 ~٦~^G#ys90[(L]E9A`ԯ93z @_{UV| ?7=b6T}rC4fZ|O{v^#PFEp/:YcY|<' 'O}9KIB _mn;C# &ѯO3MKFּ\!1V }*q6?;?M<c4nBĿ!ߜkUsHR7OUО.D r,'L3<=t{˗WwU"ZHWKtO0v. }cMy >0r~ûicQigO#{7zVz;py>m|` \izY1:~-1tɲs]mŢe5`zV'8ƵG?m1F;ɷLx o{ Mҿ~Szy:,*֮^[3Tj_n]eۛA%v 3~`hD}!v\7uζ@1@_70!D4?\q\uj@GL>_di+µRDAq JYP=OJb1@ |JsB${;m+ ĤKup6{s{K|?Rai?u[}k>Xz|17\rIqe[V>Z,|,|{۸MղPkܟ/}C_r饗NJko/޶pxSŻ/6g… |3ysG {a5ÔS7tO0K]zW^C拹z;!U/Q=t闏U~w꾖ƏWL Uзées8ڐc1Z:/ }?0=d<^}Q>qU:sT}y;*sE>M$PM+rqT99&igF ̥W0T>};ٞ 8nLl~&qO־)]/CD=F5=hdp$\^h Xٲ7`ϱ $y6&268o&??)>яV b>xl 0mp y7x n^󌼵= bzH6YCpx+߁е3\;k{7ϙRњ&g ܸ148ccSA 7rr/CAC'^8!R.S:1 [e`bZE-3H*GMrDeCH@oh |qKcJֿ=dUMTDk WVa>3L  1 F30E$|΀0Pј_|?և`O !h=<o≪]Vo}flp#[cpSW2Ac^nKYkPCD;0z7Znd= O}X?CǢe7tS3;}}Uk1?ٻ9 ؓyO롆#}Y{{2J24k|_+3c=|VG72sXCc7˚4<vyFޚ8 X?8=k2=@;D5bZ4<(~lRAk$_| FaڷL3WGr(Ew/,>wk6A#`C/׆1+9ND&jӖE#ϪDVW18s Z1qq-O_)ޣ{FKoL[mPWn7'sbi!8DLk=:|ߙ0d^7\f4{O@g6Y_7~i×;̧C_< &|O$=[ ȿOMTG,3|Ɯ#.s~h5\Ǎ8*Д]=9!FRjHRAbEhM V6tu/*F7* sf͚LXK8Wn5GWw~tSorLK`\-#c5jNXvq4]>c_OnFi$?LkX'mF7?⅐[&.L5Z c/ Gkx=ތ@ߘc \:^3'Eb 'į~g#=: ^&/znQo7T TAr|ͺlEVAN .P}̘_m` ,d{w.{7գz"@ /3ﴡ=gƧիWb192[SآvB沊+PTx4%zYЫ̞;0J"^=D'>qYא)"lt)EFSZà,YrJ@{bߪV^m~O"FL>2B<ӞnJ@`'\sQp|&JS#1?EY<*GVGZT|ľ(sz=OX`N(xĪ|j:拦惎pbGsZ.{$^߾>]%i.\7驆߀iǻj:ZN?+5 e :ឺGKy"lP0 Q 1@!Jn}ׯ9,cWj>bw~#o|n@[6_t'.Y&w+rhi!ܶeo綾 39yET333M}'̹!RX*ѿ|땜;U˺N -5s{́ _Z!k/ƠKslL .=bwW׭܌'?^coJ}!02oT] ̄@\?4b ȁ^ h[-9;lx;nUu('~0`O0FǘZ gxw0buD5J2174swJ>h%^Q9yw=AĘHڀЮ gxߘ\ga 0^t.ZYxV{\ g.`FB 7wVHu\3UbȮ~wPW+_x>R7m,w[|[پxEfz|tm+eoGK^ Αyd;cؽݰZۿ̏~O#R'L#t-gd L7%>tG`l\MO=\IgXWiw-Wxo}咕5O~;<50gj|1oрz<_ſ[Փ19LIkIΦ~#0Z#A8jo1BlrONZ{ 7ȣ}ZboZ}3.|}н.6s%uRRQ,e 4oʧ}>(Cf~> s{_ c1djfkhG:3Sſov[ :ׯ^W;8ֿ?k7{SrO 5dٟHN(Y_UkҌ:7^!y8,}Ec|J'##Fm}[Iؿo&{w'CtGK{0{>k0N#ۆAZ_wC"ٹU(b_믟2VNOHtt#+ /l)P?O'Ef* ׳n[zo4'2eZ! ښ?7t{S kP]oXpf ?F:`\jPJx́ s/]pY+ׯnsʼnC8 W[D&Q*?\Jcj~ܑSpqbν`bkч{EM׿nOQKp޻Fch63hhJ6Oj28ƸQ^U} ]/{/1gp#h&I{^+'31nHW~&"'bEW,]wA`h"s TZ`5 ` ڀqauE'p~p V=}= z@bj}>s}=P|F 靂"}7sg­F⵭BW^+)i4:6=x9khbA>_}Uu**QD9.@ZU4V M7jr>wopʧ 4tG[ǻo-55S?cJu?N?!]5z⫿x/_<狁֊I~ɴQ>VFr>|bܽ'3}Ojh8z5s`{D??,)|G8}DgL%njt{cmp1nj6[O]2m^ Y+##xP629 TWw|~^|_ȩ)N'}90>a:ۯX׽7M}an::}7-W_+Ŏ+xG+'2soU"9_GM~y}@Ɯy |+N%=)y)|7WeN7L:gg Ğa}g{gL]AC9 xx9T@. o_+h&l+UtKgggQ@"s$MAH*}'B5x^{E7|؊+'w YOJU%G2?ZGI7Ӹ 2?|`k?U<˿|x/[~zq'|7ު`U׮a߱e~@cCr4{ݹ8Wu;`*Ҷ0#p/]b^TQpڪ`9.'&VO2Of.?\3V/}gAl}m?F8'=m$$ ^Up G7cW3 ϘO2<|;I'i,?Q|bg+_):GsoUH} G9lsdgs=xxɧ;)Ga0|NPC}4XS8Os֯߼g}k%cΞNKF=eT7؟Up`?m /㟞9$5kPn`";>U}Έ2F:o$q@OxֿG?O2<[nymŊWD~wd뮻/~/αz.Wԥg B ƅa}{6X*p_Y/ј\eY88 ^k?pnRm} pC;ia I̗ͤI߿~F&]m‚[&߁3 Йo/hGk@* 9A N"ϩaxp2&S" ACt x$zW,_6Yߧι߉2Fp783Ʃ;_eӯ߄5qg M "~ٖxƺFc#3. F+)oߚ˫6_n.?u>d EX|yO<1?96_>}_Lxb?>HG3 Gcbce3p͠MyBO)`?^gR]P bz[-n ^/_妠U4-NB*Nպc clQL!џ~1Tї}:%}NGKcF>WoAտG'\q ~0*Lj1yG/؈lkǮLd`ǭG[FInHuU}_C'0Lu7Y|p`˸}^ = ^@d^U~w)xo !۰(o{Lb:f(X̜y "x(. }sbp`sѻYεuT?7^?vsr5苆_-Z4!>/%!8k8¨볟… c˸6Ǹ膫F.c\><*.@G,rh)oJA#ҰDj#QN4SbQp8*3Q{"ǜP9ֽ끀bضBr-B1Q>Si9 6$ҵ6pbpg>ߔz,ꁒ&qݛ?}=6Jlxda_ᮯ/.T5Ox6?m|gZ s^,o‚ >G?m^? ރa]gzw(:@Sbx_hhUp׫?z c||7!FRS I΁gbyFh:Fܙ`,c>w&p*豨G;Fa/9|y|UgZؾm{/=)~e'=]0^gR(sg E( CHYѯ ^+t7?"0VwڿM o~YM.+75[+:px_qd_-ho?Ld1)χ> .k|uQbcG>SKpb޼y2 YOax tNT]~T׍g)3 FnO$AA9 QĦX> }gx߼׬N8O%J9=0;gXX<=} Ϫ|]thr>xgocXC<8=P/_}~vYX IXj3g֕@6JL#h2}[ aq)jhw Y*!k*?cdN¿rmV}R!h 38 HJQ3`'jRߧ,/1w%8яLOͧmlqOo!"Om>m?Eur~r>x-Ͻ=,b>]7~&vp߰j]ϙ:3vIN-s֯_[eT;5շ߁eӯ$. 3? X ޑ^z-K2V&É"\!$. <0=EF/7ImS^A]ݤw?Y>m5 m/M޶57"dыB/ 2>ekd!~vG+,E-[r07a~l֡z5˺ǶtmL 쿲MU:g-2g~'+N ;iz~ zpD/ $Tv#mNX:2~MOYZ!ډ5%P1W!tNQCF6t]W}+vAQ7߈?1w]|;ڟO>;}Eb??yQݟ=B{  Xx~W3GjؾZ 13bO{^g0vԞ81Sl2T_|q1.̛% !s#{ƫ AB`}_;^gV|慙iR0.J1#WJ]ņl ^;"?#poL;(H\.02c`Xb}uoe'YsKzo&yKaHLRΧFZUkuVG&Sʞ'BbQKB͞]3/o ٗ9>#Qwsՙue,ɻgZ-oyK.| !3Ia17 tM%\Pg|zWc#\cS6b ohBe]/ho 7w}JTdKk?𾞾)at aښg _~wT.鿋!օN$?" 8C aR0`|q1( s$[g_2~ro|c>r)K|)[ЩR·Nn{?~&-3o>Lt3xL[a"gSL a\͘]zWq饗̙d1QHԳB֓= _”^ڃV%OxČ5fnvI!Seu!xǨ܌Va a|?zLRbOӾjiswTrֿf@/ZsZrg  In35F@P r !H Ȁ K & SŽbcs|.N%~o~S} t POaF^32ҳ{>Txmj&x}AACpܹsOb_~yqm EKPd~ +{&FFqgC`̽,QHdz-F(@5r2`CD4\|3)E]9Wn~ :kI_؛m`DQﶶ}ƀp4yв}s@;-g`:H=C"m3Wt;/4> Q׈Olp!ktyb3Ռ~%|O%5E?c:`?UFx-{744 mq9; ѦRmP&N3x:8| !+D3|0TBdЍ m!T {:L):O O57x0>pn喺Vt-D1(Q37xC+1HldGxl&s de M]lU\?O"FX}^"G[+F ٯ (\Qt3a_`ǀ$u rcj@;[=!mɧ~lp*l*hP>隞% ҡmtm3n( 4eHeYpo 722SD6`dSg-DRY}9PTnb y9 Pq_^;'8IB൭%L9}GDY ֑RhJ+4< Q#hK16t?6Z=@1|0cCR;~kFH] 5OUǫEߺς `«to_ձiwL8zgyyWZ\@7c@:崡64ُFtw+)"' Oѯ|liE/^:DkaP`,dԹ́S2;`ߍD5\.aQu\GejBe פ~a~Ι"ߌ)̟%Kd) P1LS1rj|X_`| 潗a4]bEHP@3/h'د{pUp7&C@0,`mժUτ@tOgap|‡3>0\&}?[?Z$e˖͟?FgNbPm 6O9.pA}DȘ^`{9„zWM?|<óQ|taMnG\ٴ Tj%0Y>y` !0lxwox"µؾ1!KХʹPq7#F{3hҳss~aM0) eB = ~1~n6<Z .&~ +C K Bhk!{MA?>hFߒ`̫4d]1~c˶I{O`ͲO^=w܎QFż]{/zT[ D~\{t+Ҵ.|_1p?Y>jى?, t}8V崏o>uAfZ?@#揻#8>;-0vDEUq/&`ƾG`2_X6X_OFk!= ͸[[| )7!ÔԼK09o mVH[h#+?yK3l] c/Rvý㿮ŝcO~ZsP=i9b`}oUח  y 2DF "(40DvSg /~6e0IȘi/~  'Nrp)Bk'7:]g HA٫282X( J9^QqQx2abXIcƔөNtIԹ[uk޵ֻnݻϼ4we"Ze_il(o@8/X *M6!1Ct8 8w}m47)"@;_1SO-Y9__/sgh Pl0ah2ESޫAsWhO; ̾N`+6-l_e;c[~cLpZ9'|޲ AP`"M>l{W̿7/l̔*`咧,("ZrpCm1[dܫίxxẃ;#G9wV b'ăg}!9³tvyWn-A=jl!yoy^ZgdA҈`奎D1F+YZ!`># CNy:;~`?m F* $Ժ**v#LTM${罳y`8(qOaj|j*\V5|3W@Nmvg5D)e "p #J?ǹM46p#\+wEʣGNIwP;n@/MF7 rȳD Z qu|iWi.۠ n]@"v.kXpne-%7OL&nhO S備s:ڙg"dk (,aR \J/$j=qos}>o'. xIs͗0\y˗{LtDp>R*u  (ԮmgzT\k Kqwkr+$㬦\+;Ld GN]ZKKzQ؟rGq ^Q>+1Y?5cs-W owg{˩AL^v]q{$aڴiu,<\ YT3@{$L6v1 O3⻙`Zۗ4 O[&0&\er Iq VR0Dz8?DDUܤGY m ] Y Jy.xz_yv|Q8~;n$-]Cpb)eD~(Je0>;C=7/v%B_v qڵ'߱Eogִl9Gvh,c66Fz3~;S Ў  <ϙ57m MO@Zڕkq`=yi.86<^}5p> Y/}֝_R備\|*緾9M[D\Y5t`l HÎ]i.?j%/-vE0q5z-u|iъWMʴ,DmN `_9i"J|OeIz<v;@[.q|[>-!,I !A6%i< ;wklMPt~p~_3iR~ X39+S f\D996TB .39092G REk(dN1gm'TJ]{;x&l( WC.W ~C)/P^ +6s_LZ&غvc󒃪y ;or|WEH0휟m1#qW_} `_9C칇aϔ7j};K`yw=U<<4ZEr5+^]\/srlAp!'V7OTG8$}nz/_w5s=gN ~<[zU;fNkn~eŕ;+soo/R[7UqѵIMww̹ݿw=~yCќG8cw_Ƚ{9&r>_dOpƻc{QϚb@L*ƄvXCWV E˞jW  vUTOyTMjv?"%*Vc NN lp|C]D% V-)蜀 U)c}2%5 d{,쯂?I)G\xe؟AUxFq?*v_Zyi޸nqd8W-~ rRN(Xi61rC!cw1<~e\4V @l Z+w(E[w39sfU xbh` Z5Y7x䞇<4G>\qMklK_ܺ +Z;|/x֗Rn$on %;_-۫$ھ˝vt勇;^ yiK_ǣ 1(oʇxϞ2myo}n+{-/}>tƄhSLvLS<_o֬YcniC^ 7 |HAy1b po ",*̙SsL.<*mAQ&\{yx"1,qw*BRA4k嚹v{ី7Q zP4i*J3X3fέP""J.&Pҗ92NGGɋҵڹM@; Y}>Z'@rz`BQU7Op6o Z^[kX^i3z ?M,~jvOS?}lsDcOZ)|gR/T5@e^öuEg _r0l=s(&E&'e.S=4bM**Mqu0DK(6yaG?Ǿ?d1CN: ޗ"+F}0✍Vxw\!'N4&'!`biӯ`A%\!&ZUT>w[q˰,IiiW~^z[e{]kCEh1̺9M'-6z߫Jh>z{3x`f={[K4Yʺ덳W>2c97D # @8)'KJJ;oU.mpgb! ë,^rq }AN Z"xWs0K*0mlo… J|?$@\҄ 2>m้=!A_}今AxobzӎojB)'>LG8 ~ T fRDZsH7Jo@ yX0a&&?R(QGUYPM@K7KL*'!rbR8yy ̋*܀ OR: @Cg0'2$AÐg>X[S78Ț%eR?GNEFEk-wفC3~{D:"퟈\Ɵq!Fb 5?IKU\R*&@iBh祍jD(;Cx7 YVy+m/~a/%1mW?}#@p!H6Ȗ~SN>Sژ4A1=y#ni' U?4!g<<3{qǟ13U<pVf k$J p@[kSQ%N򧈊-K/oz~_Zղ4 (VXYl";_FXe~i)^ a 3ίD$sA|I35&~Xp/6lIFH8?#',8W0!pyZ _6E6<.I>oׯYغ#eXp ~֪ [/[/]l )eIK#BϟWE@;ڄ&{4C>IMExXkrd@a-8?fbc?UT]CGm1:+(j^{ z,_~7)'j+Ja{{RAI{?SKQ*?bUTM'1Q2c B@]V cHIJ!O=TId@W>ŚS"`Ge"?Cy c q3hS8W@aT4t]W¯үQ)G+oϯ{/{vy k* m=ڮW׿)L?o9Ua1@,!pA_ІϤB9$28JJ@n—|duw3(C$^p'RL>$7%YΕG gqƟj,Axތ-WeT c˫8WP6S='v[7l1ϗ=}}%SW>fMe ȳ?JBP7 Içj3i(X⎙84TU&z %hh& $X Ev4J&_]>zGs!Xx؆c/q[%ٴo'هPɹh18sV#6m|Mg7p)i[f~Ҁ>m&@~$?Վ`W1yK[gR^&)B ]"?$&3LĴs^`b8OKNt" 3I&yV~>ـ i?"Kxw)]xd"g=ŀO[%qs6L_i DDZ͡1B%gp /@ ymYJ._-h .3ؙ R"M+ևF5H&vLRr 8yؗ J*,&Mr$ O 3㐦QdI ɻ$S3nijD .qjW4Dߐ9|ȌFjqc h}& sVq\|!\8^r%!]tQj@402+&18΀8114H\?r/Uk+dN'Y+\53"z>:k_kIImi18šD"8?I#, %3񣍬_,`WA>*=a_ec?ڴdv>hc(ρ<7mڔv䯼)%Y?iN9?DUc д)2}ݗ? IxCLghBeq ?@$r@ xC -ȑi5"LxUZ3i#hL~z0|y16e doڱBHCp4DΣe(H#R`VI@ME9s+V3s{Nm{_/̚6@'@c vGׇZ6σSchN5g1vx>ϸ" c2 y3xvj<@7 䢾%3_ѷoì;7$뗌GVkc̾ ɊYjDPTTTl>}zFg yS%9Bvoٴڼeu%WrP_t dL2/-39Ę7&& &p&l⽿T=rژtpJɅͧ2@*&e& H@Ƅ$GSU˜hH"I@. |qq5/__E!  ;x?L?L4"0fCI) hF{mj"Gv?cc1YP.H:Ono3b߿{wq]7[mZϞ>>wں7ݿsloyG ~;Ÿ=.^]Ϟu0;/`xl^` =Ly% S&9  2o?< 0>~ann:mTImwǘ~{1T}׾կ,Tj{wZ3 5%qԉW?Юׯ.lpEAU0"fϞdSlW' K)j ?HdLLך:L@ld@/?,Ni}αx1APqLO"g٣39vʁRP&ܿ4N'*O6ҟ=v=z frC߀Lz?hh:~pl$X<ɎhJ"W;~vym!Ø ;DS@ 9~j`bV/+i{.ogndNs17{@f/i`ZϟG&ဥOz+.Zleǖ{|}5^|_lE%{bOWg4c> V~(\)ʫ?JS'M xL".9~Iޏg )`rRX`dεZ$TL*%,'&m?ĒfK@&;}N}׭[r ԗMN|g$C(wZѸ>Υ9tQy<@doXONA9󛞱"kMcctَCHV9[bREz>L퐋{>^ wZ>?k /U3Ŋ+=xymhsh"6c#.] ɖ[عV*/\O\i {t_Jڣ0@y# Abҷ6Dod1= Rl jOڠbӃ}<"-)O@ـ?]>r}GZ>ВPO*~nQ%z?h~qN`y"gz ??CcgD?)Bcg-@GK3CQZbl.?# 4 L8fk @ŀd}f睙8qb @xt :8ۼxZU)f׃ozz-,Yp׮]UxZE & mxۡ h'q4cЪ _&gnc|k g⼴K;da⡝sBX&Zܣ@LfG$PWTO:g}WY?v\awm1w;b!-_YW|4Dd 6^d#3\8_D nſl_~=P)so/lνA)F.VxZ`gCRh SKT LN]϶+W$1ŋwSOBx 70v@Kx+P^1LiKK‹@"/ /01P-c =T8ONC"00HOD9^{f?KDAc}nL]:aT+hZ7vw ixLCd\hGm@zkLڞ۰l&.fZ8vai;6c6zyv_ѨW\g?]3hO`a V"'SEG KQ Z7@~T=彠 1 <dL}?{?)Jm!Y8S8Vxq߬_Q(JgǬEnu\h8aLvU?t+sE;0Y+L`\קv`ap(7<|G@LW P1yaI=H"M'򴔩J]d ?5!8իW2&;<_uOh4y d?~wHq؎vaS۩];Q@yǢyhTlóMOw, MF?^D q篸_|=yF@xW4?@ydѵًc)/I6z& \vJW ٛ=W[vpB9Vnѿ%kOv+8fSݯtz/Qń~Fln@^Z}JԆ&E‚`/Б"T__%}G̉x>kdۅD2yŸ!/ K]* ,6hv;oցlȎ+W5E '0-+ G, 6 Ѧzp!k~?L\;&\Bdoƚwx/Q 鑃`/@#]qNG df=#JBFyDJ&8`}Bq?"(GD 'k=F 篼Qh2sh15s7|h@pSO;ؽi[Io,!p,{J/;ԼGx[5&̠%(hN0w"R"/l~w=&,Ay17mHd ,W`( hވ#7//[ӊ`⨘3gN%ns`B c)(~ ?sF˥mlL.mlCcM9/J/T1b.X~:~ &a&u(ϟ_*^RЯ""7 /cO.G<]GNm-S *%qhcO>ކy<+7!k* @19u伇,z˻ޗ2;*y^۷o7:ϟh }Uqo9{sn*xϫ~oMޢED"䞃gP:S1K0ӳV'$SO8# yGǕOapŊd6/J\}Օ|\s'b Atĉ/#8i*!ǟgsU_&M<X@kO{-'%_y*d+@vnbnSq} xpIcX7ݯcr(wX:: @ ~גfG|>-HCRtI@@$:TH:b:pb4|QMqo'NS}__u{YU󮺭tmW[[8Ĭy+tǔq1G",9j z:ZVCF񍃼TP:[IU+6$cpcÉ'!kg5[T|{ ˶?. MC8[KGult0!-I@( H@ z:tj΃x_1yEn|8q$'_$ŕ~@~ϛ:q @̫:.]]-G[h&D`E  `] `T `7::t.wߖ0H2u;NI 8q$Ϫ)Uﳪ*@+&ڭ xk@yB] ~:D l Z p`V+@gC:vTp ۦ$ޫW/J3 Ɖ'N%[^zǏ!x֗DNѶM @pI~ yLs̉kԶ%KZrߡC/HTh't'vjC "aРAnē_|Ν;azꊺ]v>ur|M^ >=6&Px7-|& Yϗ/_Lnzݎ$"{-5`/dZ Ho|Pn" tp[?gϞ=a1q tV̀ㅇwX=jӣtb.ؾ9 cˊe7xL׼sTK-,qId"I嬢κ& T )zSD@ր8]tKu#2F&H_Мx}~Q_W#Xl [ N>XWBoq%.q:Rꏝ5/;Qvk;ܻAG"u|xi :VC1 }WU5FwIF?ak}) ~ @]w8PԜ0P6w޽$.05DoG~G,Z? טc߸hGu.ȻCf+Y]{O<~B OZY0L:t7rQd"ݺuYE zծ'z.oZlH5+n/j u>v5]+KĕO#Y#ŕV%_h -sw_o{=z{|ݐ O7km+@eZ8vr7;tlr D &ٞ %zǐdHP9_^|(׼j![=7:+V~׈W#%V~U>"8B @iWTk]juY-{ԧZNVV1^Ǫ}ݷkK';-[)KdT$Xp ʉUuhfH@.\I,)ۺǏ+k(}/t=ɵ[*&-pRNK˘'?ү3.vl~ȀxQ %CPQT #g#}iw ͛\AI@`Bkk-uHƥ%nNuM_S˼ҫK"o/KNW$uB YY4[I|JWAw~=e8:0@#r$:7E_@:P `[O:56A >;4 0U`" B\/9Ա~KIǔ8ml{.@S'<{:Z /SJ'eZM3K<`?H/n@YxA0}=\رFk "P /nɁvT@6", sqk,_LKuɕ)I&9 ?āz ǜ8zHp 26Eۯ0l%~B:a{h&ֿMp0bVWd@x0#"|82:ir[-o[ؚ-E޿-1o U̞ 9. Do,OP!TJ3fӦMGѦ\[iSi&0Mۯ8+6/o޷ 0YTR}wg䕊T$)껉^{hp'ٶx`#*`IhMgz*N<&3_^s:pFH IK"WWVwr @a`9 &%)7s [7Kg*/Gki.nj ƻm2xכhF UL'hQ,kop(yOqE ޏ_?I"~iy?vt@C(֤p"2^+@D"ŁD@i @r Twީ|q@DNG$F@؟`̘1vrVi_3kI 1QQ3\s: g@,)- 'soT.+{{'׽D*{3OAYeRsO*T C5%k,1Җ!%^z%\נAZu2\$@]60% _K" ʁN"d+ƐK_Q|zFW%W^:gekWwu &8ÓeJ9FqS (j@ @h?E8@/n(PWC xa޽{EH5ᆭˤmB8@NuvoI6.It9rT>]:OIc$7qT.@6ee.@Vr r@^V6Q-p6@۲N!m-((:c; &|"+EGK H=Ғ(D0*m=cv(n N*ws &Mp Od 5_]Oiy7g9OE:@\FokҶE6k,L*}pkKRAf9^D_~f8ii 87"OY3Μ7DFɟ4遌2k1$]gq`i@LV$ x@5 .5o4_#t5x9綗B h˕ae4koT#6`NXYۯLy8\G?!|/@k #NZ Yл?4O;?}O?>}[L~2yo)?`"YH耽D E:6B L+cyu=Ϣt>Q6Ȣq}ޗd4>e "OrrC8$>Z#8iY$?KL O}#idxK׼^|J ޖ!-Q?=q#CA2% k @5+jZ4w7-`Y}GgXBJj+3r5 G4- 9E$)^^xq$rќ垑w1A`ő?a‚@Ȩ^V#7_u. iz}zssCJ@TX`:K@ -]k=tGyLh翆-P-liAAAtlG}&ut@|lJGpVvrǜ8^#9czygǜ74pw$9r?hPaJO?"_ iE:u:kB@xdѫfyK'va!^n"JS,p]Qٶ&r'Ϳ0`g_2Q >2oٗU u/77aB_Tt+_u]'LA@8JF,CJ+θ) #-PP{IQd zjQ"VN:.p3t1vgkQ@V>Zu-GpbIsҗ>b}O\ķEOXԛL0-::]67+M KϾ<`½>`,;yK8SEJT䡾m|Ppp:%~cGƸ_}i$ Pª:+k݆w[K2 j8U]|Ä/2i_GE]rɍŋr}谩ǏZܸo/e0<}2>7 8(>޹6 ]ҐRW?y҃:4[U@۳LHuGp~5@AZҷ8Bwulg|o˸?<}Р S7kB&_YGץ}$Gg$;Yr@L?C&l?_o;kuP&NtY?s3]:}O|*rmabr'vůޮ(J~X+ Wƃ3ȑg@`nj)J 0la21`$֬ :Ek6~N-6K/ٴٚOw?bĴZPi:րLD Qg4gQFUcH;Xo"p]5WVG,W_)zגc_a$OA9Ҙ)t޽ -,q~Ẹ>-ML8eʜf?r<ʧ\|V~cJF`?` _pl}%xy:D/Z=z䑲/\쿗&4C'YRornc7++@Ks%i@62pdN_8|ha?;Os!;S@QR8 S"Y-m-NL8,~|␣zdd yBšGu[2ii7E޼Gӂ?&z? <016 ޟڗkZ̹߳Ȍÿ鑑|T;~~}N{>/@ X:߫1}NtRIeb֚{ݑ''p 'q=pn40XS0U0PT=,"vv%S]K &%^K9O@ude$Z2 LL8:ڮϟ8kgmə]y5Ͽχd pA?uK.)^ѡ?If{,W\qט{rrS//~e/?pljg_@[~C2"NusϠApYpI ~G&+&<;o[w7Jp;+b 7oG~Yݶqlg9A>}. $%vq$o?sG8[_*ao_%Xa:2eNF\OyQulX|&DLp9'Z@= oas!C^ðaSRI~XB  \w~Sj,4Q O:lF@߾}+jB~)GpR @uE,]Id<#KwVJVNfY O=@z棕ڞe0|f)C`)6ɒ5͐.~?hpA.66uptYf/F5%{+k<#8$_2z‚.L䞢sݓ{%c!w%+ 9 ?.L'瘬y ѓ%8{2&šqRֆBX/=#] 06X+V" ٳ?¿}W ϝc5`?oī CV`?8p#m$p \@7 5 #-<#],YhM@ 3JL‰W>x%\7+O5`, w@5R ,l0nHZ."@΀(>|96s1`TK'!^kpd~kGtݛKL<5oI"qy "C]lBOՀ)wVbڿ>o߽V0C>#F\d@`0*їB!@z[hC& 1m4ɕ󴧉z,9,#.}xA>+w֐]2?~_&RՇ< hm!@~@H( Baд1FߧϹu?hYvĈEh9mbjSϨ~{W,$>?tB_? 8`כ|Ď+vVZEI ^٤\?w4u6,`+P=q90g9á:tJ bQϲ}GZUX8qbZ\p-u,Ȃ#жśKn[ū?R/ 7ݴNnA7n@ Ot/ OIe !C.0ݺg9#m,3QF ٞ؟p:1%GC^@2SMI;@2lUzե^ =gvŰsfM%Ӂ?){߷n@;#5$AJɓ'ӧOO+!=OLPuw(l#hOoyߢ}m׾_KjfRzwﱵ5lv8&X\ W<U:hZاOBbFʭwoOcD}6 #4y:μ,q張W]9yeޕsV8sUfdҤMhFYlOT?~FxlW -?SD?`pQ@Z.Qr82uTqk6Zl_u'[_{rbpxv[g7),ݼ'YiOi{TL"37R"Iڡ{I q??`K~{_УL8 J-Ϛ=zZM}9F8#rV~@+?O"9j !gL>䑲@+g_ YjN\dxdC@$8q~Ta 7N>|쌴fA:P9P{)GrJR<'=/yk{߿)͚E.Zm'?ʻ6C7n_Ϫ~'붽_s:׀'oY߶] a&$a T瞧~o%q9ką!Yg W˂#%eeeM^ Bm71M{Y쓒ot?MgO/7(DG3Ϻ&mM*0jkSjTԶM8?W˂#/`s4E8VKsM34̹c#Y{$3>Mf"~DRk'ޛ MK3Qa$@ey%JV*+ 8X'_#QBŸ9=n-g)qve бN?f'7]q?eQM*矴?}b#@a&)ϼ JF ),@q$Cҁ?y1C@;b$Qd$/ pi7CL4g/7?p/47;@&ЧO& 9@k$qפ'K׼Q9!e߮Lf"^($Gd&"7c\27Vƌ۲??h8 8ެ7;v@y%H#6@|~Auo/x<j߾]4H껉:`ą)sϽ<)iU'9̩ v@>-pʔ90@Mp awh*_Xo?c({357-^P {N]-/D:`y#(++S>8^u]Ƒ~#%q3;4 70b B.`B҄\AB HY Bǀ@efلdV;xfk:֮+qǩˇv眾NzC}^#}$םkON&W5 6;b,JZ??Gno̪Jx> wcUݴik p(spDyO|Zڞ?Qu}}V R?L3fx07w`Ub&91AuEcStXo(O0_ :x*ź&PZPZP_~MR./<..Q۴V%#Ჲ'| 5* ;#yi> &@w88ÀBf8xڣE%T+7b0د*G ?"5$ I]Gs!AW/ -WjqNj B N%*<li>}Q t NHTm\1ʗJI)eq FŸVQ&C{J--Yf೮Bnor'BwBLh0Nʸ}b XP\wԩ/v4$@cY9t>mRrr!@ч:?zEzӬB`#c^ Q4LDzT$.k5dX{,1wW0>;=JЮ7]LqRW{z~!;6 81!|>>L `nen&V+ -PTk~we4kNj:>Ŀx焋?O(xmTD@Ci|j MO/k)DJ1R~}ReN|OeVSuMv7/`csNz L5kJP '?PG@ZV 0  Г}-%9O]q;0.\3֛D`[V$?oqyDH05 ""~[nn.@Pſ4/TîO} w;K48`@2j?~F 5pFÓ&DglmlA[ʪt| :#W (Ƀ|- ss\V,{ScJ1߼b_ښ55`)=˩>&@אX6n;DL"@ HG!/@zG@〭ǎ87F\ҥK~3;d GG?tT!-~ w.ENl,9\zBe9, T|?9g` ssWqfE}ZXn^vWAOJعS`MLqVX:!^hVOy7?ogתK-_-fy :Y>dO~а-=@6Uwx<w5f`\gm \+2Vn}<Њ?x t|p[}xPD?B7纬17񇻟 :'L $fϷ3@~ 3IyhًR@?w++ \O+H u0L?Q447fn-1Ԕm➛r.nVw[37kזJiiUƍ&Z\ڣիpcxZ na= zb<,Y@9 I3]l 5|9ځ}B -];wn=;3g\IU((E71OT xV3vs@|{P"m[c>wXYN$rǵ!55ODylH6,@`MXܴ4[EEEAA/_-722-orZL&m (C?^x@O;({z _^_"ʀO=? &Y\7u/Siro1_;zZxO =U[[7O8VzaC0#y̑!y ,UuuO\8kr"Я?U1`L]CFgQ9(gP{-z9 c-,@؅'|6w/;K4F]o,i6z)vH%-.QPrcPVxR5014=?hnc⏵YX<-+W Ya\|Jtek]jV]  >#apIݓ\f6Pd`[_'[WCYjk=Ĵ1{%/goqCP187/rMD aK{2|p7G'ؚ7GB wr*3^o$x/>c'fU---MMM6M*ŗ.$ZM@y2̙3*;uxyN]vr(t@t@KG}sTΟ L"c4߁8A<GS}#V0z-8=Yж%t/@(_D7a/ : ߸nS@-P?SJ5k Y _dJJ|)..&x& g?G&.InhMcH0 ZRL|v;ON ~!c r ҥ9 tځ9S8{I#Ώ:]vH liS/sæ ]|_Py?jYrbnUr)V+-~uҎ ׊?BӾRGW`l x6r载?Ajmm{R{R27 *wXiz|5@I1~> ;D3xRM*-+YKԇ?JֿU"@zO0om=Ȅ&=))E,_~d''BBL7 40S@nӿj;ݴik8+í*R^~Q/ 0dw$:)¶Isayt3 b1W}ߣH!y\ 5ztC' *"tKe{*9p!fM0F߿Wn-{+k$[dLẇcb)~b}8DAϙ[ 0l& %G`j<!jk;I _n$&&?vlƍN0 @ Dg$jimݺ l& 0v'N;Cvax}!wn, jq {x0?%^8)İ/1<bҒk=qR'@K:3xi# 0uV xolzppe}?YH&@Hi' yx9JU!ytTP(y-huUNǷt<Ma:q ̧jCse{(LJͅ[wt L\dD>QG~ XժpC%٭+*4 BOӊ?Q+[ & Hzp/mf/mߌѦg_.චphL!xF/RQCe1[!V4=f__/RjUvm}^)>> ʕVſx' HHc#"6HIIyҚ5?L65Z5b}a7a F +-IkN[/ SXt?NKdxGs0YsarKow?H#Ȩr?CI ZZ/O#WA4oK!ˢ6zKp` @}}TSc@ccMjNS 0Kvt2 BꔅU\hÑQbTJ1..I\( Lcb`eWaqbT*زQq l 12,""#Fm|%=).-`&la(lğ~Al~*ʢLi >}Źyv86g8 6kٺ~|Ǯ#_ϵ.|06X Hl;M]8'b{ XIdXy0~-?x%# 76O%eXiAIENDB`tiled-1.0.3/src/plugins/replicaisland/objects.png000066400000000000000000001665531315121121300220430ustar00rootroot00000000000000PNG  IHDR`u pHYsHHFk>bKGDC IDATxXR]P((E"6@%nXb)DML31 |F!yٙev~sBFҾ5&`E ˄+OD,3ۺآ,_>2=z.}T3M4UpƦVIrޝz[WHW:G|w3Oijc%rPQbY$rŧTk7OJ"V;[v6GBK"?n3˴m6j xǨQPh]ڨ[.Dt?N'+[CCJ{{{8|0۷CYY(((ܡ{Ҟ∱$0h)]2JC!-n1?SwwNQYp!8 -[Q莽ǵXX*;oK5 BvAXpmL4 !<`(?d3I$=iWPkد@f&@L 4yBHN7oB}>|~-/3E-22B{voK#.{L!nt\΍G@\zu ~%j<`%p#44͛Lꄸ))Tݎ Kय़wz|gȸgAq KO0lDwi0EGT m@K22eiθ(xtZz^t@r:uS>T 5+Z^-dKxCBZ|2+$Br [>10;w S:n)\VQ~g6E E!!8bm>~@ۂགྷMBc/~,'wa)?nf{)dS~tɓ'piرc̝;q[n1\Hwzݰ}'EM*qt8O]O uA~3'=ZiWr_Li.mp=0hyr^x|~Nh] ?t9\rr{SC6Џek8! _ )SGkh):PFFqI>--z!|MK&42sd% !fhofWgFJU:{-*Gi50ೇƛh}P#g@h8 U i B _- BI@~=^)Pˡ-<&R ''OUcܒ.۶ׅN^2?tޫsDnˢ[Ma|]T C}& qy9VR 9jJ376ӋϮO"[WCtW 4}s:}W<^+dh/!!qGHj'm4̤Ӫgtt4Sty _EQIk}o{VhSZW!iXIQP)"9Rb 6.z>* 䫀~o1̫#`~ l窂Z=X1{Bw'lFƚontax=w@˝D5h/lƥs0RRG jkkʕ+Ӷ`k^~R5z;_v?  }Ueڊ4|պZnO5X 5 7$uezTQoƒesZ!?K^& mn<;cN+t?4/5;R7X*79 }}M2//C'z/W8bQ%ގ & m* _N ,r\RP^vS6XSSw<1i([?r>!?'wZhQOG)&Tክ ޥQN->GiMyRJOPYY9LC}(Qх&r?+>>9`ua'nhh~^Q|Is{-P4w%oO$R^ڽ-k?)w.vK >-P 1Ȅi6pau{Vz'u# >@Fs=xۂ*t A  _߿mEm][5@y NkXH!VYY gφGE].GNj*"V>EaADHurJ̵kHGdHAi`۶#m F!K_逢!q4P1#Cq-:(,<Ɯ+_ H!>Sp@J@ 2S)))?i;- S)8C^>y_1~`Fk'2QHW(=㛇oh?"}ˡikGӝه0Le`!1tO0<^ZhB]yL Ę<-Gxp[: vaT.S- OSINH9߶869#:}zTˬ&3囎}-E"#-Юy @n|TmW“MLG)x2p.uJ? :} +!!0CzV~;PEO$ UUã=UP Md 8߆@ ^h֌eѥܥP`(; vG;/#"nܹcśs[a!ƒp <^Ng"|t65 T-*OY3QmD=qu~;B,{ EuAlPdG#)4R E:chF~LHt Q9slh2v4o> ר(큏>e@n&.VӎxuN:N8t_eK xah<4Kx8:6!x"@$: _!/[_0CѰ4/OQvBMAA۷;Ey_OKa_L `GuH:MvCP)QE7N:+թZ (x4!F}}FP/΢!.(x+;[tyԭ>ӻs-"Ln* w'RqOU5sE'nHA@I.O ݱ4vMvz:}(GPi L 2Bi9 ( էmpTAMa{6au0ϲBO !̥NS{1Lm ^0w|7y@RZ-aÄ4ϣj'-Nz -yHг _+޴kBGCR }=]WAHs;bQ񆮇:_άH&F>d9K,҄jh;UvԛJeggÝ{]үxMmU&\٦(Cm\RhXJj4~mA+30rWRU))4ԵD{[ӐX=`l:ꅂGm= !uE"IDGHFW4_ef3OF Ao!6BQu pbP7XE-//Ỏjl#)F-*0>N =V)F/wϊxt$V7:w=j@1Gl0~*)&DBLz1H<@ꌽ{(+;VrK.sH>J4pbF$e8b I'ADtx5Gz[oNghMɦJ 'HՑD梻,IiN}` z[Om5wpK=@ j$TixzzM0!jɒ%-[vlF9h me$J}辞8> ,F]rIЛeP1|oDޕoMn WEEE6l>{,3fUߖ xk=Yo>kɾk:N둄+yg \.n-dm>eK%pQqZFY{̺}.Uo7)sK644̣Q]p>oMc 2XND퉶#9@+791.;>f<>&$$bklBǨ@{ Q( :Dqݧ*T\8^ڴڻO>o[[֭cNQڳklYT ;*G{[7}e6˷a(.v8L8Hx/#$yfƠA˝R)=Wh)0Pixozg{<{(X(.j@G/EŠuiڦKljo]>Y Õ:Ö D*S= AP8v늆p?;%%4RX`%Yyְv|%32xRiiq+& \m燄hG .@GdD<*ww)@"#'v./GxLE:5huvԞp7PXy0sZXg8y-G }tdkp(IK`d Q|T6gtʿgxKl$QlxOܾ>zҎNM6wt1 C#YHO@ X>zs(]]@vvL&BYTDQa(7,/7M˶)S&e폖8|sDzp4ֻN>]m ?qɯUx:~nsVja= @B0Y9+'imY LcUږM[L9Pt}[O32qq;ٖ} 9e`fΎ} 3?Q* WMA8(WTPXXQz"!bj>uL4 -| <;>z바W@ gg QZÎ _KL'%>:gO{wAqyĠT/v& 0SWWSd+z6ޖYY:rڛ!hVЄx/p/a( T0,@zPdT"nTT읦;\h|G|R2^p@2QpvPГaD,ܰʂW| ׮߀K7Iaڜbclު_Hkii]= |gɑ#89X[ [4xpeڭ~*]@ *\yM[fr?P( mo0ƳՎ\. Lr+h"WV7/d~ǽl|)w' _ꋆî•WaH͛+<>EA 2Xh'tAS4o.耟b\z+ؓYOxc|rCL(*aظi,XpaPyGAccc@W^?hԷU4l(Nj*CHu?X`0/r|(wJ ) e9Jy3 !'/rwnn;f:NVjl[ccB΋!p`985ŗs@xv9S W$RF]ʿ`C>}#:eUL-"PTTT~TSSc@n%WIf5|g?b=}\^^ _5?( <|?ee(@;R{J_-u.9,' 1q\-Jikkj6m|"53?e(!9Pګ}@tICϱ p֎yWW^^a%₯S}}үPNa?a8R8=y$~gFT2QqV* dWw@ !|-g43lIB!=vvi‘y Ƽ> ˕7ygEXG|z:::󼼼dgfd H9>[# |{; j :"p%X%%e 7L4^o:B>AlxW-tNcbb!"#UuI8%*ACsd ͍V: N &uݽ̔ ޔ۱a˪U=M;[.k /BЕ@l{+ӕ!2; O.z`e~}q$5voIT~9_ NՃVXtfDL$#AuY[?vQhij5ɶ' 2d$HԴuLhO 'js:y]hp$\bB// Ri12f0VwyVE_쁌 uwylSRGKN:NN؅'ҤT >_GKtHZ |'5 $z@V*aB" 8Nu;NC3_]CYSCl[Nԑ醳.YOGHdIPpI y-L|*&P =Q2$e/gHR*ϙNFrrZ;_ҁٶxQ:moIݕF}*)Wnu'7$ts#,6L e0?f;A4 #?}).rY _)/+ {Z!uzD\F7XQ=->J^=şI9H@AF=W]"uW^YEWB#9g߾#3؇z!XKStaQF^}_P p@7wtwkN6B; bb.ns_:mcŜsJf 72&33!p۞VC IMݐgL>vgK!=qU22p۽yR+xúЁQ dGH u;jPZ؂9`zg(]YK%HUIr|&mѧj܎/E h:嵐`"7D#v]E#4#/{9i4%HA:r!:Bu9:eso(22\]_0#i^SS~۹^ rm6ba-KN/Åe|&D#$Fىa' mePk~w۟@UMCZIYe#,*cXO)ԟI2j 2TMNzhx:P:mw" b)|vQ#jj5a]2ϹD$ҥo*K_0g`-ʣ`Eoc}n?t8Ίm`(0ܯ @%p +&x$pf/ u"uL=F9|少ph\h1vuF$#vmgqpJgòtV 19}8,Hr~]Qؓ%ɼ}U67| Swp$A#Z0ȾvYkߠg"L``'066ln*7ƻMu׍Mh~+38Aj?p.\3X=Y_o,^xL0.l'5|F>!oz:੄Nx{>wTwG[~ðOo]~t fAsE n"m?e`m[C!Х)ġ>Sڞ肭*%^ 1';o5Uꀭ0_##O!ٯs0# \c5giAA5φijb?rth#xծlڂtn~ :fWUv6f9{S-amĊGwJJʠo𳌌E%%:圝[":wQTi`nLONRG׀3㙊ٱ"xh"g$!@#N,phg"6k"5w%rM c}iXەTDdt>~v{ ^ J͖?%%P))ǃG577wzKѾ6!(|<3Sȅ1n$n "0`_7C7k1NeJQMN6ډmbwpjs>l,5]QI8 ɕۗ91$lB[tI[0#| _#r; +bLc ? 9[llP8xt,]]&w3NN^wmtoąuVP*+jRIAm:q{F6! :@a\]]=TUTw(`4SPUyֹkldڿ&⚊ad; 7#@^Z\K KM_)@^& ՗&cX-SY0-@p5!p՞#dҒGQ4kA'j5Doc*ZJ?i)蚨*+*虫vTOHl`bz9^YkhIٱihʥ svrzΕᔖ$UdrUP84L'҉DO⵵ Sc nT8T\&A|+?Bs[s@1 9gϒӌGp)?Qg;MSI^R+jR(*Ȓ[X-˛H1Y+͝;7b4UUUUƍ=7olpK#:SBeFel{ӕUWٯ-URAt*T Ņ@D~^llʒ/JKKLMM=A<6e49k%[>< gAٳttKVc|0phbU(kr'LiĈ(449..~~~ _z?yl'Vň3ٙ\d|5{7.rټXk &u9ЅiVraWzgFhdu]>E5}?۷Om۶=\ٷn0E!8se0tH<~l!ҶC ,2#!S4>Łuֱ" \ɤI߳gOWaEpځ:rkpJ{Zl krvwq؎z C[CC|> H?`x+^`GXtUq׬p1C, u u4Qc(vgK7S|=,45TE (Xtċs^'fff)hѢb&PiD撗s}}=sGNxر% PsMŐ&,|j8u_ 7o|!uիW7zyyE7z&E&1Rۚ!w/ GOB:O^!tF9C C'eL-3ٞe0iҚTÃ52N(sBH;;"q\077(((r]vu"ކRna -m|.99Hw)iC-g26m> aذa@~9 7WWq o4vO--m{@S8Aw 9Y1,?!hJB~B k;D>}:s=||{ùsLꥪM9dY[|&!Q޳WSDȘ30tRX SAЪw~X6 K1 Z;I&](ָ>A\^qI3'uM>l-5qbN]]|OD!@NNN/H([[GTt愴83a„kXM?H|/9߅u7iobW -6MkkNr %}}}̛7?tDdL̚5qD́8GЄBwL4nw 4_U Ym}{a}`_\ a쁌K`փk.ט*A8%c"AH" #xZ`~[k07nRHQ.$]7ڍ3Pv@z\d ',ZO88N,3%tq9}jj74Cii)cxY`{$Ϫ|:FO RՁƶOV]b<[R ֹ@9tbJ[<%_^ e`]&s`cr,;\?ฤ7nZ{YčD |wH UK]gu4wjƠ9Q㤬s [Ž1'N#o`>x'K-v%5z:ػ-?:!>/N2ϟ, 555̴̘1c3/o;ʈ)@ kȽc% a'vOֆCە~6ӆkt!'ݕa \Ltt^br͛7޽{o7nٳgXJFrF#M3qΈ ׬13'}d$˙EAwTIAK(ľ!,\I@aHam +d i@K %WK{Qqq>RC2%L &k *ӗpµ|Oq P}̘1;(pRѪ(p~? 347rwwgÃYb(G<եϫ; ,E{#*ߧC^4V;̏]v|GYƇC; ;)-ogDYAm[iQv,7n((GpÒ$}2̏^mN )Ώ1!PnGҥKGmEQi؞J :C n|y F28Os=fdӥd?(3K6fi;+qY2.u׳#-;vI"2Ks kinq|N[~~~3-K,i?dȐbbbFFǀ6PuqL ,ݴrFeՌ`1u>M3A/whMRP<TŘ9R cqH ")?FKlHB a[Z':lPUZMLG\&UVO<(.̴npׂWuL2&y2cdE"G?>!!!w;Ex/88w4~0:;{k_lPu%p2K}4I2g&Tz^ GcޚnY:Yn_7 #Q)/Zx,"Q1/B(%X"cX`Ae!ɱ( 7Liz/C/N>͚;w #/uۈc.8 x3ZҐU4hIo]-}. -\AGz?QO|ԕ5-)'j= umRpՇֺ?_޲2,Kz7D(M %7IE676&]ZzXʍT QsϑHB6i&?j߾1}1OP2h VA,5 |]<i1cԆ^%4vo AH9~B& aN8pd$jRaX'Uc\5XO${Ca}"₍@& Wy=tODNC8s1+b֜9sO>رc?z?FDD\7-^8QZMnP>o6B[m_n-uΞ=4l)zҮS=ע=_6i`aB1PZ\%8wi-.N ȩ=piÈ= n֕MwT(i20I 7l6B҇B/(ip,n$weBIr#ɒpB*hj*MyKH Ƈ?8nn sx:Sp` 4+l@{#`/$әraq򼼼h =iVSSSG_r O?eDرc5k񪮮E$+W1󆑋]ۄ|T +37E z 1wd2{8 +Qia3h%9€?6^V;2:X47Z}d]an bSCK'>?Ei>kKKL]9.6/-2{*χt> v>͸^[Qk@_>LŁd`&Ϙ(pjRD&2d(oN.rܮC#`{5]A yD}MM^~i,O[n2%~3XY9 !d{L| ] #&AM`7xf7!9K9_*]v ֮ $4n`/ޟaߓ MgR=-LQ&S(myvOߛ[K}v!af:|h.HG 26[ Re4HCK^nқXA][ 5v|3a+l%Ѯ~Cd֏5xgl2uXCpY/,-%-IMImt56> 02d@s fG>Gfg݃]ǗՖѣf*4vbl3hǔ1%l WE`1f j@ \&O4J.qJ/8} ya(P a uXDY,: Ԧ`(ˉöRpe3h +GIc+S&5)3@>m<"{l~e9 b耂\/ֱ}[y2haEU"I洨[@ŋlZu4IՀ#s iD)oՃw[n|E%lȕcT<;Py07恖nK36`I <ȉ0!QQc>Jf5K@g8#)"M֤BؒYw I'OA̞]oQ=(>V4JD61b28d]b ٞ+r!h!&AG`bxӤ`h*TZT<~0z?Z E3w캩Ge n355mb:ԩг7Yի]>ٴ<</vJ/0e<0I`Lk6)pX~Y#rzA渽A]ynt%>΍&&&LH!AAAM'O>WWW7dƍ]&;Ê҆19:EhF.^1~AA` l&1\i_K ̊g1埢ui\(shF/ 9!P$Hz8/\7,gv(Wn)`O(É̱N?/Yj.jpNNe:ʅhi{;uB dRR=tɍPڱ$*!:%N=r3Vҹ:]L_x"WH-Oc50d`l/l*J_#S}19--h'"7YNbVl4dЖĤ'!>6ߍ7i`yŁjkk nF1EK.6?ǒ?|CSTիI\h‰'2d/O D۶gS⃋/^V]]=3D͛78qaj$ȸ9CeT'?[) F)`gz^~dL9OrX56;c?H~dkQdo#ԨwgRhyݙ8,r'ՀMB nsVG͛7oraaymt\h5u@zZS)г~}n\쪪*_ WB#,R@z%´0s0]%5FfTP"[E>DQzd]ݱ_WDZiDڙIJ $$耫1>N9K?,$R칠?CW4'bo~Ӑq)8]!U]=OAӱ4fo* "͎3aB˳\xՃ70e;8RaxbC˻5;>@,̨]F P$ 1 MNlKݙMo8[}T?e_/U=by-"s y'%؂nMDDD#u/NEoIE(++\'$ZˢQP)"kal쫘#:'K1iPN( BYvMRzA:B|HAӞvgE)wn}HCS:w`U\M*ػ1"Wi;(U@@DIU Ш-1W5 b}yryw=C 4{ށWÀHaY/=?sj)5ѽI}鈜W ^I~5< UW i3vZHM=[LʎIwin&^pEEEW`$ɈҐ)Y ғGϞGcl߷[h&ƚv'e8~T,|Y2^?BR4n/w1U]MOw^\1k--3m 'KUe+y2x3\2e/^l;̀o4ڭw _]:+|{/d6222js45uttUUnjޥsB:n#J:d޽eҲ%5Wuz&ޚa>J#sBĭ8#[ajBW ׍)vS-skfOjyjyZ| USךeim?QG|bRҲQ1/憫j]A$$t ]H'ҍt$]Igҝl [&(?XZZ={asZ_[E^'IN}DHovIZa`3)v P0l'-#kix;_hM$h4}յc+yEV<kfG!1% b-m؊wcg~صoFrJC7IOIH&&H҉t#IWҙt'l# UGO(Ϻ,)gVؿf%`Y%c 3yvA_Isj0pY{#t,*BX ߢE,,1 cWN@K a膙0:lzm MðpwG'xpŠO;ϳq]EZ*`jn7ab-eT~ t?q =}|Śiӷ=j綝d,II҅t"HGҕt&l"F?m_`(/FYi Ңjb^L&>6SMDT\VĪ+j*Pn@ZhX^^tzt[K:C󴖸!rsa?O;_2rںW1%0s*j~јy ӱ 1ͽ;?f 9ʈl_[,Jl]Lw1ߠƗ0OWP,YReX}*--E@@O2'+˝se>SVVE9] Å %`xH;z=/'ӥ[- Ko/1Fs n>s?`p\!ybP\U1/tvAvns++[s̄"$dLM:.F:3N6-dF6dsso HY>s<*"=hr(Vm|{0ޯm3AKJJ#)0`0n8s$OHA""΅PMA^p'/HB)3 y=:ܡL6do*:vXOuɭIR+~:1%xʌ." ۻGKiYf&LM٩XW +U %p&r c붝+Vm@ج|9II"$t ]H'ҍt$]Igҝl [&l$[f9#BWij*"mP]!.J!/"4x?&!dV4 >Hii; \'iih)<i9~XBL Ãs5F'@cmh[f l5'0@~RaZ.feM@1FGc::*;׃3c2%ѣF WASYWȪ N_W}U6:zEgcXIə`X7egG+II"$tS+p:3N6-dF6d3ތzfr,Jy;"Q[A Bt"fDr^CpqcZ 90(WDgKVgg5F#c<߯iK!c]0QIȑ#O11uTaucCuFvD .S0sdL0* 9 2P;7PS.Lutail ZÔy9@\/H^Mz8~pCr1t{=oܸp;vH`яmuqdbg>|DnG{_t kFKCQְwwQrV;νџ^W{\?ׇjpf dd .1=|`1iBOM2H$٤B:n#J:dB6md#J6 |OԵaGr^cᗨ<{.?նʯ5tZ?q`\B"2iSU:E<7 Y$d D+L 7g6md#J6 |ZZZo͛8|0֮] rׯ_Gvv:iiS@ODGG% PuEy8 d0TԅsDZ QsmšL kw#/u;ۓ'[,&Ɓhr/{@%Ή -ۮ3:蚂k3W ^ez==|̾3g{4cFlS55@e03DƊ: JdʹP@oi! @JH0H!(QQ8*"yEjk7^qoy׆ \bVeyl܊h2 eRܜ[q;~ρVD9WVr]p9On{c_c*.4MPn'.mw%Y.;k/, m=S _!Nck۷o|˞ڂ&M k,o]&#$$AHOMX9s1=p2Os¢xC$҇ sPcUY Zpds2e#l ,}MN@S!2r|z<)$} \# @y=;//KR6'LQp'nǥy L"m.%ܵȞ=SyM n3y8fTIY g0*! #a^aKX^|AANn xXZYgaQ֭[sss۷oMuuu'kSYz%ċxoAH&&H׺+L d Dd+g3 BϞ*WBOWO`UUC}}}6惀i0eTLƎ"}]yiFr3AxhsVPm8Йkyd:+)oyqCr|p- <"tH5uCpmѣGmFR{cSylr.y >k1 AKYH! iޙSXb0PV0>s3}H+YJ*߯!uPhBY8{g\8 pr{.;1o'MD:za$_UMj]t:5f+lfXXH1/xU:t C sCѓH'"X#-uqcXFIf -5.5:كπWe@TD.^P7v>ҁCrOy=  >>>ڏ ZmAd$>J,e{20`^l'ԱeƁz<`3?x0eswbC@D/$e53m^I(XbZׄDedJ.]\{g/a Mm`5M#;io8p`{S;0G!^Eg"ěd,II҅t"HGҕt&l"FlnFًk]r W\yFiYa^V0c2&O%v<9zZ%+XŜ a*#ZZ0g 'S{Zst][Ak|Mm&A㌋Ij5Qg(X7K `d>|- |v z#6{8|=n|?1Rp3d^֤+KL݇Wi+{k9F{8\ -v()^jK֬4I2uUeaT7QR59Ե'@UcMhvdmfUVVnfalZRYz%ċxoAH&&H҉t#IWҙt'l#4гg. iѵk8􂬬{@O IϴXHhmN9$'Gji.I lf5 u hf c3:gƪhk˜R-O[GwhMz_rԫW{+^K?@:Λ.j8kMqzG)_Wcsgiֆy5U~9m>+8(uGK_t,0e9@b) Kݽ? 䴊K*a< IeX&˼6׆f^ER eZ3JXC$響 !1T3, ^ēx E2I6@Ncr:3l"6H~^!Gz6͛aOAhy0Tf֮wlje%*Yy,a䢬 CM*Xu<&SZfg!մ`ie$: |j,S4\J&I; B֭[Ԣ.9WDmJfhDY{ k]'OAT  Uq`i{ ^Ɓ}8x*$C1A:˧Ś!uV-`|UZVymm)F׆Na8`9k>%hi?:! =CE<7 Y$d.Ӎt$]Igҝl [&9N=c!FAAGr!(GX>=>8MSr@4ug@L;&03r&#g2P91rxh9s5 ٱtL8pkw+y [G덮c}(Ć]nL<`]'$s6Žu) p4;#7GT.Ѧ\qO*ۃKޢMUXwa}FţrCzQ#%{XJ膤 9;%d4/KH+aXR^^b~#_5\bnddd%fZ!,=CE<7 Y$d.t$]Igҝl [&^3X_XXXUUm۶q3h Y,s,ֶjJ=Q1K52ײ]^ ree;(؂ɳk Z֯O]Y5s FHkVBmP}:+ Gܧ  %am Y_(Wir<{)~ [}N\z!h =k;U.ƺEUTm8%wbgE;V0pzT9/M^ ;#)HGH衭ކy+rs ]fZ4MLL`ggOOY(녑ZP*KгăxOM2^{$t ]H7*G fΝ;2k P}4KeaSҳRɼ!#ڳ߷:v׷*k`pJy2[+?`YLAo$=aazqg}iqc#4LvWCu1~)>_/i(>QJhvcO^'y8䶐yDܜv8Gr-o3vn;{Z} {.Үؽvm>a[~l+چOp~ֱɑE?Ga6'\ZZZ/h^ldd$mm.KII9vݣ2Tg"эy{QbҮ]nAÖ-[hVVQ6^1–N&͝1cnsF^HICP|V~5V~(Kqk6YS#; M]g1ڦZCZwamrӦ:wlx8::Oi6Qee%pR`h &~'O_(<~.f\YQ+q{1kq*${`OR)k: ' jTGA[QCMKsUf^3f3JjB!$E T2PE :T}BDtL =K<m,,w^zKMT+**Wzv$trN܋h :Й rǼ sG /M.ٌIX7-P3a=3W7eCI^ٙ_5ّ2Z f4@x{Gί'UeNyi'=>YDͱɱϯ,z`ldnxr? 6MOm&z|'I7+^ꌥ/G^a=e,ԉg{ N];Gr_^aD05Ge,=C/XvrrJ'G17nv7j1,ǩ]hV=$lJFc M_SQ1DÑ2lrIG<(9C )8BA R{AlG8kAB0 vRPIυO^*v ڥ'#< SJ'1UXa Pz|dd Yc#jABq5rc ~PUM'LAB\]6x7o͟#R{M 0ۛ 蘮'zgS}W1#[&Pd uo(+ \-Z8w)BsFnv8D%}(8t{?LBK.b]f|,xu lgStx5Zkx6e-NZfM[vj]3?\wVM1|F]]]1|J 忟rYh$gҷih\~{r,ͱW{FoRGlrBc-X[3 ܶ -n~4C?FffWx^,^}ZsOZ-8Uxś1#&&Ӛ$?Z{Ȏ.)\Qm+o94Hb''"""=133㖕ٳgC__( GƼX^=7EZZѵebʝ(.ߊel5Dd,]w|'eG{(?܆ W8kr81HNmp~zhߪeKק|s~\<}_iky/ūt!,Y{~Zwy)Dزu+hkeπ@,Z#Oˏ'_ +qlre,BZt]-]2n߶M`7Qh֭GwTuvaþRPr*L*?c* %Y q'?O_ Ash[x`X^Ms..].Z_SW(?am~ 1X:1ӱf6X _YcwNJ,  Z gPQg''Z#Qǎ_XPX[8RUE_d>xUH~韓_o#{Pudk6?#WprW=TJ$O[d~= Uذn ~$v܅EːlxɈH\mɟv~3#['b/"'_t]|׻=zujQaڈho!U?^ *t]ǎ:a_q;4!7/@ ?iۏ BFfi[y?& xmۡ[ j0bYKvz.ܾ刊NrowV bcQܫi""н; ÑS-0&+x1P6]b3 +m£>gӘ `!zA}_Aht5 "+ 5ZuDXci9ˌ^ w$/TD9#)*^k0="~`SSSȌ;pJt3j`~lFut`B6ih;|<l1Hҳ5666\i4!EV22Hgod& MI>iiIl` d$gd3:)ʐIWg/F/HشZkIK聣Fjȍb!,O- \Q'Fа_rrr'j>NJJgԻV:w\a&* :@-D/u/t"_ },L)'CNTij `G 8=JBIKS٦'oA\--^,_Q8& MCTb%.{صyL)8; XaLk]k[Rp=0+sזǟD2~4XBmmH 1ItSz D#LUѕP~ H^?)$C r9UqRHSWnbZ]:>j ^R$in2*eg  B4x?viu$O5MmPZ~YϔX*(++B,?I+**#Go~ D!4"!hnp(ίE͙ ؞ضm;nݺu~PBʍ9;3ӹg%cBf̘u8ׯŽOOݿ40]ݦxZ%UsbK_H> Hwh =د'vCH z(Cb@/|ק;:Es6MHHZQ;u@@3Z Ik|# y&>~>6Ԁy/@u(Szy9h ZN䑞ۛqu KqXYZ8Ir($s3$kdP Iu:clPcuDUot"ݿW_tዞ)0k="Hs sk1u1ѹꖡ<'(‘̜5|>e*&9'iy 2 ϏWT=ؾe#nZ7?sQ1wOH Dbس0qmǍ|=l7@G TC!@oXSsM?&ڪb]^#&8zK[to#waEDm*>\B}v{;5M6㢞=jPX&!.]ʵo>[~DZ2$ZY' z'̅" ^ P6Bh&U4gҤzQmOxbold3l"?+3M9L&?L~|\ 凓؄NuV xV"ڵC~e9۴_E~~kM-[btj^2l.:Rm 5a.o섡'Z*qݹN)A'DvV6/ǴmCLt k5]'BYbl (F67$D3xcy[mnH7 ؜}p?l+*$m6N1ܾ8-UHlkx-) ZB_~/_mHCHEǞ\ض~Ďvh&;YT N4:!9JIJ`x-z̛$l$/*oX8I`Y]5c<}pl hۦekVm;oͧ-[,FxCEzH}ӮFw ~}a8?whvћ^ 8 >VE^ykldYy ( &?7y?\=}'Bϫ, 5g5C;Áep9G~C`;tuPkk[V{*&7K~4:'=p+F-[h@׀<BBzu+÷ 5&=g^a)uf9H!\4&#О>I ]/7hj/?64kk 4SuY5Xio1~PwQ6-[~ëmRb`%3`!#K;Mmd#Upl廠IYʁ)xs8gA>"޺Z|f-W~MBBrX[Z:0 ϔX%bعkGq|R|.U u0V=Ut[ei*(˰k.n\ic6pM6l%y %hں^3!g5wnd|RCZZeCU:zn00/L|o4Z:PVams9CPY~z!2NOjyz'nF&5PVkc \9ovc:s l#V![acޜq 爏a)y>)y/ln8%{Z:.ox̅h<)қ8%gRR +q)SRgլ ;BxҺ%}.cFBqؿxLGNWҙN6-dF6-/9 Dtn(Yl2tN@$ I&G&~RP ={Q(JMke/tD.Cn&,-B)MǮy{WMW:z͜A R[Ž`Z*P}_I'N7ґJ:dB6mdȻZQ<'Ҟl$M{ˋ&φ6M^A\SNgR*,)ۉcCq|JL ʆc I}YPoʱ~m™sF9jŋdh kbV2R3c:pNL7ґt%Iwl!6>m < u@HW<TSfi}21aN~ 膨X%Q~h|>>dQV?]GhٝpђyE3΄#ߔ?D{ w$|F4`ۯ8N?d 2y 9b͆Y\O4~&#?zR:Xg~‚~îOpE]FY-6 )GDyd Ӊt#9]Τ;@MdW$Eۋ O&rƤ,{ |~ac'cO,mXU vU΋q:aWG͝M/A{;c@uc|~/~U΃tb ?lsυF§v~;bǪWp9χ >l|榳_Ie|x LyQx+ąK?skϏ/ق8/dPV7r䐏gqҥKe/^nbݻpy&!49;b#[a*RϮ}I"$ӁB:n#J:dB6mvyY1 /&{qg]P;IY87 OT4N,>3lBsl_xEaCfUxLAo=O@?6*+L-B>9k-'.ڍvč F_ njݻ12YU?{ݩ3},;}#c?BiGycO_Tu•AQ0%V7Vir1ěd,II҅t"HGҕә d TH^= 8PQh9%d[D&u*>u0ڻ PG#нذ/<0"N5QA;b]W1wGIwcc~6|㿿tnv T>b^hE k <!{4J~t_lǹ==1CLJ|]Na:ahWp(׉A\*%#nnr&y'#6ǹ 7p}p+CLrLJUװ)%%]cd|BUcɃG/[uat0uC7wc\~1Owf!8̷J~=J@OZ/II"$t ]H'ҍӑte:dB65#1ga!C-QhIu8{t.U% Ѱxy?bVt̼ @ګj[|QÑ{6//֬={=uj Y;pO{Q3.$JEŐK^Vg^$ŷFg#GnޙgXs}霮׶k= eOC4j`9@xRD\ 69xY u?<y8tÉkpnOtk/tOQh Cm0 '"1(6D_ Mj kgq=M֡(P"5Px d 5M-2ʍJz"p٨1nm zQy|5ԖA5X*|!ƀܕU~'i)B>(35Ѵ+:E{|xY 5T3, ^ēx E2I6@NnLGҕt&lj7|0\'``K  ͜fTtkם0Ew2Fml\+>SS^$xV0﷘00"8{hH-^_vѧ83+x]?"'!pCxb>D 1ɟ|].^Swtl6qx#,\XJ%٢PLr{^ -&,MDblveyI81O [n.(s7 ̃Z#+f }w^.ob<ObYX>;*,t DiwpciG,۽zD߶ƌ` kUZ=*CeYƃxO`H&&8]NHΤ;@M `*PA1ǫ `]x?-C7D0\? ""~W7ɀE9=12iρKwdndE]<`r7dCRqN ~r`3=wY-a|9sa!YaEqʄM23!n1ؿz^oU>|nrزڃ]j+G]αxm/FQc"a(d0d12:ed$5,x*BZ_pX玨( 3g#lV b#>Be?9VޡyCw.Jv)!>="CIfC$P*: Lb/vLϋn;5Ge,=CE<7 Y$d D+L d D54_H@bA9 @A/>z8-.Z}mZr $b&{ hG1c3k1(02J+\b^Ko׶񘧣pBR.\-߭rTbG!bsv@xr1r!bDX,eڍKE.1vv-QI!)GCTSisT `C * KT$}8FGuke5My,!aā89I7Lē'KpN&L2j C2 ɓC^+s8h{WֆgA.BBQD,TLr  @Dl؅yf/rQW>;{̉9g&$Fh]g4ϟYQ!xyh49 h>zӾ;,kC5Q^mC>b/u/sSV >4>y8/_r\es\us-&nms/'[V8nϴ-8(42/Sr 2aD@D?mKD&\|.jDSɧZ9?vR#2=|HM"%+ 0qftg^RtL.plfz wNOo~ m¡a[Ovk1MGB~P$zGb>5ݟ+HǟuEJ_;Po)ipmLӆ$mX%ӃH~J.N-tr8=n/I Uõuqލ7x30' Zx]Ͼm˯!k'BD vm=O3 1iUhA0h1@7g }D2 E.DI0s@yB|i|p^2,.S,ຸNm6q۸Vn3}>q2# U:tG1|)y8ڙB3% _ؗwFIBlD| B_4;E$ȷ%V| UTË``t'b'ERfc󒉶"ŸEwQA>NoA [}%iOy4Fpn.؇ u&k66/h.j ӓk}PwiWLگh(=7@ݿ|2jg/->|%l.E ul8sf->L۷,GʕSs7|zxD7t _xqrO%q# xIpYS.)OG9=hʼ_fdr6[Dh#(6!Lجdߎ,X+'Jw"Gcpr_(a\m !Sد~DIȚJѷ k:֊9}y;Nc3zAqO~mCIvmFC__֋bR$iYɾXXӱVO+5q"mӃkʡ0#a (O1ktlԬǛ6N(H3\[_w`Ϟc^l۱W/0Lx2)q5NzY%4jg&I1n'މ5axޝ.x "Z=-jS0wHkKLj]e{OmQwYy_ y8/_r\es\us-&nms/'[R=C 8z2)\j{ph||=r2%`LLLXʟd&cs}:ngd<$^2CNnX ZXd_ nau00@ES/H"dlNO'qY٘E(5| jۈ#עZESytN0h0v}ҭsgL"dlNOڭY٘E*q5NR ~k{m tXT m#lf a:(7Xh]햳8zKGwLt-0yy brD.®pX%<>& t !j4RHx.|| Gv]sƼx ^(T䲹亹 nm6s۹-mLSʚ ZqfkL+ J&o覍"g_~'S׿qQw(gןTk}ķy]^ /TBqK6s۹ Ld^ߙBEy ")OiBoi䷋? +ןT|3f kr}>q߸z5L nƫzu7 Q5L.:nnm6r[6#0',Er%hCvpl)s8 M&3OOnGl1sOj#A䄿WVw WD@p\Vf;~yrdӢ-dp5$[k!֗觋S8RQ+nMW=[ESlLO'S+PcNtE.䲹亹 nۘiWsFGHY?٧KK [X1)SV3dH@f͚5Cxg` hjժ7Z[W\Ex2bZ`* 7)&4$v1fn N=7p\VF?\^g19yಸL.ຸNm6ežpot3=3D39XMv&VS1ϚG鿰XY԰xǥuGݚZi)c8,/F;7ʍ6%ɡ6DXh[U6ediڈQCǽȟRpw-Ö;fW3| _epY\&up]\X7mJFv}>}>SSiߒiVnIn7bir.)*_\*Wѱch аqx61y4rt (^Ψ_ tM5;}1+i_Eb|>HqA~$ *CD5< WiVK`~u,wPC~Qrڍb[aYC? \1yoCjh`:Ƥ_-k .䲹UίkfF/JjʄkiwaB2)_TjLN&uAmo6A$S2:7oID$o"ڦBf,;rʴK# dZЕi~<)v BQDA 1r&WQiI(&&24 ddz(rJrEB t*#q*n?;#$S$?!͞1 z^UBVUV 8OI0liTfHe)."I}#E1vTLjٌQ[$5JA,kшPZ:W=[1&DZLD9SJ"$d,|0QJE(GhYm}v tn)RZK:ׄ'22-Z6Q PYz2d% dFU5$JˉcX1q,I(Jl^ZӲEVutծ!91!](#itme҆e$dbS3 jI[J+JsA&ȉ4kvsxjUS}뢟=4}t8]Th2 lO HD3P%|LQ\$_;2/}lCu0X :#HǜӈjU%i!lr`b x&2cd=A%J{ iڂ[69>VڒcfcM$#\0Z-1Z#Zӹb0 Y9>!f S2A-de&1$J[k?Plzr%qlvv'mƄzD7I5ǜFP!MkXz9YI ̰)Z[.(VHb9A=ii9LMAv^ʩk,6hUA՘|cۋd3 0Ӱf8,xn~ J>a얢9Z5,y|HuZD61(ɏ"1E&Ï}B&j9P|?ךkVclZ?6쁹9bA"q8MOynIXn4\D$3 {Q Q-[џlQF4CyUM2yB@63ӓr;(!&xXlE.8aCɟ k9ɷh4rZG "MO4GY r`keF"6 Ö<ӈDMZpawL6 2]4D7*@-y( t8sk cM$JUC dSpZ~FaXmLgnR5e&Q*#ey&he1VIev ]]\Kl>4b*pY2AAOA[13S30ljF~ _Jfۧ L_e5 oh1A tM; B!5 /N9SLCL>҄襜ui(fȻ#>&9s_5!_-~JW.CSL[ y2}r"'ٙ%NwNNc)&]D&lW1c%N'L?S7d}9~!%7 s|k5Tw6 KXc.E- >f5OAlĥh)]Two҆\I046|Lhlzhʏ` ZwYB8„cQ.c;cӓf]G(.Ρ\#=7B"$$ ?p4;q/`@*F1H؎$c c3Y܎TR 姨ijǩb%-ؚ( 嵛Wư9ؐ[[\^ؐPs|lv2q|ul%M{+P?Mt$]Acyć+& ?f7MVe<`kUaU e歞L3%J"ɿ [Da&+6"^ͤ] W0ljȁvr}>6;Y1xQ]PDu%S8pL#IwDd'yU kFG Rc֫_SLh%ʩ%a%^'ʏL&#/)U91Yy])Os|7TUi>WDMP;ʏ*d":bai%L<֠Z,W2Pu$J_~Lus҈ɜ8y2w4)_i|<) 7][BA/g(y XA#E$;FD Eѹ1!_O^nҲ==H#p)A\. B˵6 d8$r\k:7Zmu \o*b`ꍊ¬Y0{lغu+΅aNxڭ.M-6aܹbpL4 Q8Nާ} 6oNL4M'4s?_?S3dWmkznCb3]AxRЍ19 Fn<Ү@$!;[_ǻkKxw"j|c 1?/qq={=?hNB: x"_.8̿?Ԩ]tnO1o_Ӌ3n0_`Xp#mKvW'zXfcU[*pQM5! 'u^R >y(|=KaƉ*U_h5RB.zi ܃Owu/Dǣ&x$pQɉDҹD&ڵk? >"Cq,W.hq4n(]`b9sl:w5rM8&[_`J̿.`_Ez8r+&/\%nZƞX0WO4,ˏ[ v5ǵ+ۡw!# Q }ϊ0FNĺ;up^N!oUE~9q=%<q3CGD=bk/+$L{4IH~wgģeK2?G۩=DF 5BVF} q!!۵k'@qfΜӧcZ kk̠_Πs'*4@zO>NM0X130L3ggLGi`f??3gȗSF2Cc^c,{xu9i甦:/<:?mzN}MK\W'M"_x0iCY}$xBo 8|"O(^n||'/6óDGDyJ3Hz <MI4 '/bĉ"D:7oW0C?Q'??P4^ n&HSa&G\h0 :Y'ȧ=v06#^OpY1‹ф',="r2Aq[dE)~pX(x! &H$鐠AُskVI%\9Ҕ;#Y</ _l0Q/}Bgln.1;&MH=qo_{~߭z'0J4UEܴej;b-]& C IwF~SȲ_~(!TO59OgIBÓ5exM9*L,DD~{ W0ƹfCeW"\WTDAZq='oµ p:i*o=q0/75Ex֩xP! ߂!򿛆C!D:ˊZbB !eDD@;K) B`BrkDN[^ xD(\Uw"ǘ:TFr7sib˾2^6Ѹddn7ŃjH:ʏV 7| >^<|q,64 ' L &DD"m<$R^_ *\/[N|ݓxA&IG$nHxjx6p]+ݙ(P_oѮI9U W#3Gqۨ+&|T Rë}ձoQ<: I]pg&G@RI `w"`"`"`"`"`"`"`"YFΟDY#qz~˜׫|by(x뜫!`ni QBE!0Ś˔U'u~!Lsgmk/V pF ֐۰4u']%H|؝h"S?&!^l2xJ'#?_B@_"/ЗGoƾD@_"Y R}}F@nN)`b^ v[eݟ-Tp5VP0aiDܮ +@1907P j*ԓl+*8S,z ̆dxw4) H~;"@ʶg;\e rіjHQH wpZ)vc73݈D@KEdnJBJ=k$ &hz$dddvgsȤJ9OKcջ:YClv:[`V$!.f#n5& Cx|L0 %ݜ2\lG4^lEPN'}E1%!'tyC4y괣km&DvG,\mrml;" v)DvYk((#"|h!6iFx޵W Q@A" S/7yDgz9c4qCvS|^v K0&D>[&$?"pcn'Z{+JJx!|x1v &K\Xw^oչ5uh?~cǚ29RѣZfyСl{4JsNwvR /}6LZVSÚR-U%aDJT""`˯7䦘҄pC.9)ߚCht%q˨kMOFM "co"cgT^" \TLiX b,EG V_I`ay+2q %p1#?/Ǚ ~_I%.~ogϞ͵cǎʕ+͜9sŋDGGO_būe˖5k֥"4&^F 7ө3'# 9ZbDs")?+npruՑ/33J8Q9KH^ZT]1 =x-/2O5yD%X A',%!;hw ^o&+D zH hعx49jxiǡ֓kߴ͛ׯ_/aÆ3f 000X]vGDD|g >80wQ f(9.WCYZ/~bf@yA?s럗|.||\M3AF8nW,~R`HI3AC^# l*,9l*֛و gCdI[=PX.6xu" 9>r&~/P5[/Nt6lٲe˷/ ~є)S0bĈk֬AB2nj@yNxGDwrY:mKpʒO_=2GаyQ uKYWp ׹ p0&| dks v=r8Ԟ4H$w7G8%^uqgQî.p|Ly\Džy vIg |5" "`o0~,?p1U|LQ1;? E-]Td1 Ա[Z&wJm>GЎ:;%nrd3i 8O'O02 *# 5aE 0"]xKV=#Ȓ i+mڠhGR#;9 n'߶mH>}>!R^Z6*U|< ˇsrm:W|FZU7+7y 9>&"ND2"$O4x($TrziXu1Vo)W[wvqkwIfg{Mk;UNڕ3zɊzv.*m"Vٙ)/  =^)&\4Ez%L8{v ̮u""~7: Ph":`'P_?/gu*mX>)~=u~Zeҭo4@ }$D.~gSIu4 E: &J"ɷKk`9k]_ZdȲ@7!`IP}l$:΄ UQ" 64,o XaVKnƀ3: w%Cإ^%9_\/F3nL39%R &P6`s3B?T&D^L*)af_p" RytX=~OO9\tocR.nMYit#![F* kT!4w-NTiU UR\*v~D> Ӄ- 'Qn }"`=f>*#|NT"<XuCE_PFtΒZY`/PYNگG,$yCd S v~a1 v!=xDͦhUe%˼d%-gZe2O\G~/=WoleżvNaT +)r[,O$ w\WDMc4L+';mQN.R/;?Te?-=c^AԂ!_ :8,)EfS"4#-\zV+k~j4?B ]yUL:Q(׆%`\jg)=3}*)WW$K 5 Թs< yẮ"j. {+CA_`p~tri/D%!2.WOD"`Zy 0xfi㊕3-i#gPMJ"IF&TͰ(} S/-*r˼d/6KIHr~ _mzW_E%C#-/\I$Ɋx Sk-6NbR1 3^D<-aK%q/^(TI$:uIXvb~H9?mxD|a9>k_h:*tS%$f)8htQs`):PS_͕ʒ$䏐+<3O?Z]y VB~͑D)&s:Rmdb^ XeĜDӟJf(J"J`]3cv%v{=+~Ğ@a8ZՀB! %DeRѽnn{m>v G}0sچjݺ[}% >lAFtt B2%['ha& "IYtkv]kl=pYsPۡ6SѾ.[ ֛@s  8j/g m'"IY >lZI>q1t6kR ]l' ]Aym҈npsEꛬh@D 9s̑?~?y?n%Fm!ƢCcN'=< 4I;Ŧ80V̏^yYoJ@Wn,XЙUP! E?IC f-A]H E{P4Ocf"z {B`dLʫBf={I¤*U\/899Zj077G…r78ڈI-nE;~-jMG h<{:-!߼l <Τ%۬ۍWhwJ|s2,#Peo>[n>^~;w`„ y"A*UBѢEY#h~&E;W=d.BQ` F1QmLԘAN#Pwrcb|mBנ*򑂥wMR"pt*D(н|5j'?aaacccpncB(aO*w-B5g E|}a(]XQ(g4v3q߼l=(=y: z5qG5 %ٺcTumڴ Ƅ={Οhee%5! ,&x}F+USWWMZ]l6fS|a1}&,gBpT?銍g?:܇0<8Af){k((wנ=҃gA+Pe~_gKKtDÆ Eխ[%J*A"X3Ic̎/9ϫ"j2?ǐ&!Sa:) &MV~t(ʍ2&q(w wPk t?{ͮl| ZwB6w.2@6^/$}Tv,0icc˖-˾` .hMtpQsڝ{ԬeB}wװemQm(v+={LB3}Z )o;Z(ݡlkOIHiO}?kM~"^…Q\A@QӱcUsLsS()WP[g+mEqBZ G{]^G_X{AIOBr_Bvg`9:v(N=0ի'^R<_&xqw^*}"* ArR]V3"&sV%8%j%E!%3f D35?i=;;;T\8SL@e*} jl8̜k֊+d|Nt2j[r7 FκRR!sҥ?,l֪UKT&'L *x|b8E °STD kxX8&ǢXC;yߡZlU(񩉖^&4xLLLRȷ<2 Ļ*>TeSiDJn]sz3# C+a6p@ ~H>րNK7$:[N&J(/dI2&!tL8`gy&#WKҩ}BVJw#:EG+`6w:z Cg~$PM0,E~(/dI25kD&[jpkA?o3fm|o ]"F=1i8_iFlؑl=2MF} &BZ{ziTrV%Zt5"O-[75ڮh f}ðq_lkĩU#zwֲX/qנB֤_ ɒHI,:3B%JYP(߹P_veN03tuV|b>!m*W5es_Xh[ߥ7$K"'1,n5l7h;U짼ƳҀi OĜIڮPɠAe&W3%}ǡPdeP&`c\&oHDORCl@zu >Sv(Sj־ɯie:,=t@RKPc"hD0u7 C$TӰr~YKgTBQ\f=ٿ)VXFVg蹯s9 8 zXηA"$?^9p{ùpW\FгnW(($*|HfhZB5tS$gOvl?,^~mBEMD)V6~s4O*yn$H"$H"$A]$D/$RwK!wjղlcʇ?5+6lUA_?t$D -jgĴz[nnc~r]c;ŊIwNIx9&|9>Q'tي\~|eнy *fK7t#&#QbG:.II$*n/ ۴&nS##Eʘ@&Pro~`= }!=xI͖D~.t}j. ԑ$d" =ڍ0HMw1{*k*j`h(dbYQ}){:=c'Q9>!fLIjDdW9t{h7cpp~8x/6A{C 11ߘt8d4 K䏾a`Mj1P$d t,u;1nh8N^.%*q?n "/>ÊϰSDǚpZ4G'dSQnB1sC.K"I«Z屴ӨYobLj{qu\}c螫9ʦ*f8:S.O)#jRQ?7^z軯q{yO߉$lޥ{ZՀ~AchBvmqҞWh73n$dD{9?cvmLY^N CGך5" Y > B371\yhh^Qgul\,$ߠ{=.]w5mZ&ds}q!>,NM ^&i@I$ɢȄ)kY sΣ72܆䅨hSAAV?hO8|@PQ.K"IQМm๻FA~Fl8)N?0 aOȁ1$GK9 8![s/WP٤,$Iey /!{ ZOgnQ" _ܳ GGGtI0z#.U5: {yK7XI2l \zZB"߆"UP 2 l{9lxi,8ӁV̀2(v ހAeyt!; F@@41o940Kp[4 /x ӎ?/; /2e<`|:Ym4LG( zNMFGWWݷ5hvu#U1(83_>Ѡ\ #aSh he:ܹۧ=i˾4ЁN̷6=G(a״S-)㴌2N%fږB@}Q0 F(`Q0 F9L(Xx5 ?IENDB`tiled-1.0.3/src/plugins/replicaisland/plugin.json000066400000000000000000000000331315121121300220510ustar00rootroot00000000000000{ "defaultEnable": false } tiled-1.0.3/src/plugins/replicaisland/replicaisland.pro000066400000000000000000000003041315121121300232150ustar00rootroot00000000000000include(../plugin.pri) DEFINES += REPLICAISLAND_LIBRARY SOURCES += replicaislandplugin.cpp HEADERS += replicaislandplugin.h\ replicaisland_global.h RESOURCES += \ replicaisland.qrc tiled-1.0.3/src/plugins/replicaisland/replicaisland.qbs000066400000000000000000000003711315121121300232060ustar00rootroot00000000000000import qbs 1.0 TiledPlugin { cpp.defines: ["REPLICAISLAND_LIBRARY"] files: [ "plugin.json", "replicaisland_global.h", "replicaislandplugin.cpp", "replicaislandplugin.h", "replicaisland.qrc", ] } tiled-1.0.3/src/plugins/replicaisland/replicaisland.qrc000066400000000000000000000006051315121121300232060ustar00rootroot00000000000000 grass.png island.png sewage.png cave.png lab.png titletileset.png tutorial.png collision_map.png objects.png hotspots.png tiled-1.0.3/src/plugins/replicaisland/replicaisland_global.h000066400000000000000000000017771315121121300242030ustar00rootroot00000000000000/* * Replica Island Tiled Plugin * Copyright 2011, Eric Kidd * Copyright 2011, seeseekey * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include #if defined(REPLICAISLAND_LIBRARY) # define REPLICAISLANDSHARED_EXPORT Q_DECL_EXPORT #else # define REPLICAISLANDSHARED_EXPORT Q_DECL_IMPORT #endif tiled-1.0.3/src/plugins/replicaisland/replicaislandplugin.cpp000066400000000000000000000242771315121121300244350ustar00rootroot00000000000000/* * Replica Island Tiled Plugin * Copyright 2011, Eric Kidd * Copyright 2011, seeseekey * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "replicaislandplugin.h" #include "map.h" #include "savefile.h" #include "tile.h" #include "tileset.h" #include "tilelayer.h" #include "compression.h" #include #include using namespace ReplicaIsland; static Tiled::SharedTileset tilesetForLayer(int type, int tileIndex, const QVector &typeTilesets, const QVector &tileIndexTilesets) { if (type == 0) return tileIndexTilesets[tileIndex]; else return typeTilesets[type]; } ReplicaIslandPlugin::ReplicaIslandPlugin() { } Tiled::Map *ReplicaIslandPlugin::read(const QString &fileName) { using namespace Tiled; // Read data. QFile file(fileName); if (!file.open(QIODevice::ReadOnly)) { mError = tr("Cannot open Replica Island map file!"); return 0; } QDataStream in(&file); in.setByteOrder(QDataStream::LittleEndian); in.setFloatingPointPrecision(QDataStream::SinglePrecision); // Parse file header. quint8 mapSignature, layerCount, backgroundIndex; in >> mapSignature >> layerCount >> backgroundIndex; if (in.status() == QDataStream::ReadPastEnd || mapSignature != 96) { mError = tr("Can't parse file header!"); return 0; } // Create our map, setting width and height to 0 until we load a layer. Map *map = new Map(Map::Orthogonal, 0, 0, 32, 32); map->setProperty("background_index", QString::number(backgroundIndex)); // Load our Tilesets. QVector typeTilesets, tileIndexTilesets; loadTilesetsFromResources(map, typeTilesets, tileIndexTilesets); // Load each of our layers. for (quint8 i = 0; i < layerCount; i++) { // Parse layer header. quint8 type, tileIndex, levelSignature; float scrollSpeed; qint32 width, height; in >> type >> tileIndex >> scrollSpeed >> levelSignature >> width >> height; if (in.status() == QDataStream::ReadPastEnd || levelSignature != 42) { delete map; mError = tr("Can't parse layer header!"); return 0; } // Make sure our width and height are consistent. if (map->width() == 0) map->setWidth(width); if (map->height() == 0) map->setHeight(height); if (map->width() != width || map->height() != height) { delete map; mError = tr("Inconsistent layer sizes!"); return 0; } // Create a layer object. TileLayer *layer = new TileLayer(layerTypeToName(type), 0, 0, width, height); layer->setProperty("type", QString::number(type)); layer->setProperty("tile_index", QString::number(tileIndex)); layer->setProperty("scroll_speed", QString::number(scrollSpeed, 'f')); map->addLayer(layer); // Look up the tileset for this layer. SharedTileset tileset = tilesetForLayer(type, tileIndex, typeTilesets, tileIndexTilesets); // Read our tile data all at once. QByteArray tileData(width*height, '\0'); int bytesRead = in.readRawData(tileData.data(), tileData.size()); if (bytesRead != tileData.size()) { delete map; mError = tr("File ended in middle of layer!"); return 0; } quint8 *tp = reinterpret_cast(tileData.data()); // Add the tiles to our layer. for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { quint8 tile_id = *tp++; if (tile_id != 255) { Tile *tile = tileset->findTile(tile_id); layer->setCell(x, y, Cell(tile)); } } } } // Make sure we read the entire *.bin file. if (in.status() != QDataStream::Ok || !in.atEnd()) { delete map; mError = tr("Unexpected data at end of file!"); return 0; } return map; } void ReplicaIslandPlugin::loadTilesetsFromResources( Tiled::Map *map, QVector &typeTilesets, QVector &tileIndexTilesets) { // Create tilesets for type 0 to 3, inclusive. typeTilesets.append(Tiled::SharedTileset()); // Use a tileIndexTileset. typeTilesets.append(loadTilesetFromResource("collision_map")); typeTilesets.append(loadTilesetFromResource("objects")); typeTilesets.append(loadTilesetFromResource("hotspots")); addTilesetsToMap(map, typeTilesets); // Create tilesets for tileIndex 0 to 7, inclusive. tileIndexTilesets.append(loadTilesetFromResource("grass")); tileIndexTilesets.append(loadTilesetFromResource("island")); tileIndexTilesets.append(loadTilesetFromResource("sewage")); tileIndexTilesets.append(loadTilesetFromResource("cave")); tileIndexTilesets.append(loadTilesetFromResource("lab")); // The titletileset is also known as "lighting". tileIndexTilesets.append(loadTilesetFromResource("titletileset")); tileIndexTilesets.append(loadTilesetFromResource("tutorial")); addTilesetsToMap(map, tileIndexTilesets); } Tiled::SharedTileset ReplicaIslandPlugin::loadTilesetFromResource(const QString &name) { using namespace Tiled; SharedTileset tileset(Tileset::create(name, 32, 32)); tileset->loadFromImage(QImage(":/" + name + ".png"), name + ".png"); return tileset; } void ReplicaIslandPlugin::addTilesetsToMap(Tiled::Map *map, const QVector &tilesets) { using namespace Tiled; for (const Tiled::SharedTileset &tileset : tilesets) if (tileset) map->addTileset(tileset); } QString ReplicaIslandPlugin::layerTypeToName(char type) { switch (type) { case 0: return "Background"; case 1: return "Collision"; case 2: return "Objects"; case 3: return "Hot spots"; default: return "Unknown layer type"; } } QString ReplicaIslandPlugin::nameFilter() const { return tr("Replica Island map files (*.bin)"); } QString ReplicaIslandPlugin::shortName() const { return QLatin1String("replicaisland"); } bool ReplicaIslandPlugin::supportsFile(const QString &fileName) const { // Check the file extension first. if (!fileName.endsWith(QLatin1String(".bin"), Qt::CaseInsensitive)) return false; // Since we may have lots of Android-related *.bin files that aren't // maps, check our signature byte, too. QFile f(fileName); if (!f.open(QIODevice::ReadOnly)) return false; char signature; qint64 read = f.read(&signature, 1); return (read == 1 || signature == 96); } QString ReplicaIslandPlugin::errorString() const { return mError; } // Writer bool ReplicaIslandPlugin::write(const Tiled::Map *map, const QString &fileName) { using namespace Tiled; // Open up a temporary file for saving the level. SaveFile file(fileName); if (!file.open(QIODevice::WriteOnly)) { mError = tr("Could not open file for writing."); return false; } // Create an output stream for serializing data. QDataStream out(file.device()); out.setByteOrder(QDataStream::LittleEndian); out.setFloatingPointPrecision(QDataStream::SinglePrecision); // Write out the signature and file header. out << static_cast(96); // Signature. out << static_cast(map->layerCount()); bool ok; out << static_cast(map->property("background_index").toInt(&ok)); if (!ok) { mError = tr("You must define a background_index property on the map!"); return false; } // Write out each layer. for (int i = 0; i < map->layerCount(); i++) { TileLayer *layer = map->layerAt(i)->asTileLayer(); if (!layer) { mError = tr("Can't save non-tile layer!"); return false; } if (!writeLayer(out, layer)) return false; } if (!file.commit()) { mError = file.errorString(); return false; } return true; } // Write out a map layer. bool ReplicaIslandPlugin::writeLayer(QDataStream &out, Tiled::TileLayer *layer) { using namespace Tiled; // Write out the layer header. bool ok; out << static_cast(layer->property("type").toInt(&ok)); if (!ok) { mError = tr("You must define a type property on each layer!"); return false; } out << static_cast(layer->property("tile_index").toInt(&ok)); if (!ok) { mError = tr("You must define a tile_index property on each layer!"); return false; } out << layer->property("scroll_speed").toFloat(&ok); if (!ok) { mError = tr("You must define a scroll_speed property on each layer!"); return false; } out << static_cast(42); // Layer signature. out << static_cast(layer->width()); out << static_cast(layer->height()); // Write out the raw tile data. We assume that the user has used the // correct tileset for this layer. for (int y = 0; y < layer->height(); y++) { for (int x = 0; x < layer->width(); x++) { Tile *tile = layer->cellAt(x, y).tile(); if (tile) out << static_cast(tile->id()); else out << static_cast(255); } } return true; } tiled-1.0.3/src/plugins/replicaisland/replicaislandplugin.h000066400000000000000000000044341315121121300240730ustar00rootroot00000000000000/* * Replica Island Tiled Plugin * Copyright 2011, Eric Kidd * Copyright 2011, seeseekey * * This file is part of Tiled. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #pragma once #include "replicaisland_global.h" #include "map.h" #include "mapformat.h" #include namespace Tiled { class TileLayer; } namespace ReplicaIsland { /** * Read and write maps in Replica Island format. Replica Island is an * open source side-scrolling video game for Android. */ class REPLICAISLANDSHARED_EXPORT ReplicaIslandPlugin : public Tiled::MapFormat { Q_OBJECT Q_INTERFACES(Tiled::MapFormat) Q_PLUGIN_METADATA(IID "org.mapeditor.MapFormat" FILE "plugin.json") public: /** * Create an instance of the plugin. */ ReplicaIslandPlugin(); Tiled::Map *read(const QString &fileName) override; QString nameFilter() const override; QString shortName() const override; bool supportsFile(const QString &fileName) const override; QString errorString() const override; bool write(const Tiled::Map *map, const QString &fileName) override; private: QString mError; void loadTilesetsFromResources(Tiled::Map *map, QVector &typeTilesets, QVector &tileIndexTilesets); Tiled::SharedTileset loadTilesetFromResource(const QString &name); void addTilesetsToMap(Tiled::Map *map, const QVector &tilesets); QString layerTypeToName(char type); bool writeLayer(QDataStream &out, Tiled::TileLayer *layer); }; } // namespace ReplicaIsland tiled-1.0.3/src/plugins/replicaisland/sewage.png000066400000000000000000001657621315121121300216660ustar00rootroot00000000000000PNG  IHDRŐgIDATxYl[W.Fޤ WTepq<$q8r(۲A[ ' ++k{xi|zCU[<,r-oHII8^ͮ2L5;e,==4>5V;;Ç!u_^˕X>cTez=N-IV\gڎ8_cSSi^\+uBϞG33QVP*ϠĽ^;%x%;`iŻ0qhJL{"ZLH~=0YeߘOb_f/lcѥ8cy\749;7x({+g^Xa*Ӕ b`||6b V ߬vk${%D[}4m*F (+:Yh(kD31^7; _;*@\J=;Lw&T(^Q(W$t AT;6'X<!}h7w^So%`!0GJbgHFooVviX@ C41V4 @zh@umm8dxI>I =)J&x@8)(_Z>7}mGIR,VcqZ@gL8כn /dkP 3=۽q%}j6PMVs7ou`{*shtʭ׿e z.,w!&?!pbtG3 3Zvw~Ǐ l舠goi1 ;~ 5D;R W3}'̄fb|pUI{oo庆{~jf&bϪ\_&o-$!f'Q>P۽w Hӹls''Vuja$9Sa.5짬B71@ IA!&ZTd߳vG_###;>=6|ONϵV[vM9JL4:jdREumʿ׋'Xwjg*ߣUg+?߰zV\w2 & bTvE 9cޗtԖVYQ.oY\c'XS.2=pd2 o>˗ҥK\?NN(:M~@?~f?06ޘFͨ?kRbMW3=)Ι{\j'SзTSF:EyyJڳaK*L(0 t8Z~[=-ՍNYj)Z-c5T5Kc!?0+-Ӵw~+ E8Qg>>ޟ3KZvzD۠znoj/Ӵh!CDΌsRBo)"L7YMɊ`ъ W6`ނ?ޅj>8T=7MeeTPP@yyy\233upܹ5H;@q[V$B$[vob$|S"hs8Fnsfh`J3)QجGhdfFf [d+cɡ<*@no?Vjqm[,+}30zߘ]k|spN(SvGLYe`& (@|r<܎90z` YXpԜuV]?9U:%3xҗŋ;Zq6_ j mMۀSŸ]6a ăpmt?|zode"#.WzohzkjwyHTO6Rѥ>MqX 6L80YpS/*D&R NlEwWMc` -HjBL~ G ./Y`4iKʒ>чeSOg`^PS{8pBMx1LwJ'c XLB˟+7"@>\.y2 ߟfuM]4l/L7sŚTv44kZԿp<+yG6w73b_n?,xo>Ȱ}e4oXT@G$RE'G. 8(@,>N-X pePɈ0IT@ha;LՁW,bueuYlglJuMvc`~eQW@ʷn\Bgmӭ*:[ò&ˠ!mfs0CCjzP>uOՅlyK&C꿕\KMja^J/5uF+gΩe}E?*s`D\/ߧD 7%`1Yӟ,`$)da6  İ"+ی^S%|3Fƿ+W?==}ڵki;o5RGfy G6v|()`4o±@'[Z6Gcz4000N=Mʢ&W Cl`V(_h0qZGJ1({hsc{m\G#@&0)&qTUDxX:p lO3%8Z'2F{Qf,Q->r[ސ>Jr\e`&o*hdcQ:`7p9` )0/a>VR@]l@.fwӀ\t+AVff yI \ho}V!@#ZsS423NSCܑ`B_p3@(6Ip#"B]LbG& B(Ep3ke:I;1' #1bc9Mdn&W$0'O(#7V2A1qSY{"r:b/v ֶ|jfkF)(C& qlЂ<1xhl Dli4R~A.7o&ļÀت#50o>/('CnCHK)(u~ `by҃;&lYь&Uֺ7-GO6!p/ĵU?2w##덭5v)eoE4 5 >T7KwھSVTJ/r)I}\PyϡtPm!MTRZ{TޛAA^Fn -70>J>['}HQw?G+z( TڥđI鍇4  xF*9-Xp7Xh4(J์A2Ē>` l T*A,cA"X1Esn,̌aaWA҃{ `vTk"̏Hk߱z?Y=;~/RBQ>DXEf ~fݨ % tRNQaO)3T l]{ߡY!D/Ӌs4ᛠb˦vwyɵ!f᭤nn1VW6xᪧ\.Ȑtmkd\I: 4PT~_ҟA5T;\/I ?uwکeNA@$}VQEi0VLֈx,E[bc5߈pgcJ0:=A%WL=rq6d;=GlWKhrƧcSSHʲ7f`Q0υ?/Ѝ} Y>Xb)NsD(Xo"*$p"209t ˦QѝM壗vSʔ~1Mws^蠑N<|\%uWnlqS. Ph9SǸ?Pp+Ew:Өr ]Q08Nӥ_B7x*"&눅ݽFG:"X-|UVZ`TnC },'P ̊+2dT@s18ſ4?!.=m:-7v}_Ή=͝O1*;MƹMo83sp<v4P#mݻ~#'Vo!#a@g_9ROx!B?9 FiXH'48:Cv&0?1ixjn͝_Ἣ{i?AMPFT=| ~ g\iOmSea?,Cj3Y$L0cSQdز*v9QW T9N|? z<;Jl0 9,L+ڈ^âΎrEXdC\t>wS OJɹ (πr3$1r83 4ȻY@hj]uӌwf4: e]5uz49x+APpOǨo!8pLni @EK>_^y*f֣I&w|MW>)ao|}nw NV3- )g0wtɴVh*YLGaGSS2BPlY6O4V̏D={h yuc#ɸnf1HI}%45NvX8s/_&߭=:OBHwdzqf:pQ' lDo~Oi$@ӭVfƔiݷgKyufT@a)Fi3.aR`buUsqA ^ovơ sC P`41P@ bxE/{rf_ˉl`^ 4BvޒLe<:9 򃈜$+ 88wW)崟t%r/#AuoluSh^Xcxb i+.#lvObGjSdʿH!m2w58Ӆ+_2W4rKt%7ͭ Uq :"Qnԥэhn5}MOҝtݭ?MYu|N)8ƥ^bWݟSv'~{vl`l3XFʨem7\?M9^9] __'wr`\H#spn,fJΟDK: '@"2x rUx#QP?8ALU NI[zIXCINhk#l6,MD3ʚ&R-+,M^=SHkjYcAM[$A$Ś5t* eo`^yH(58uZ&Ji*רj0FnpuOP-:y4Av?_H @L'=O9St@>J~4 ɥ+o >[M,L:XO\lxxA-/ iLUFGkv/& Z>SCÑmQpu</E rHPF,yc},琓,VTPYe%'E\dhJ͛ ߟ[^~w"v$3h5}wܯ[w+5OgfZ H.ݽ'5]!"-v-qȩKhhz@/9ۮ?PO2 [<2bbOuBk-GΓ}+} ^[ z`lz4"YPrY0< -9t :BAdf1A&h(~[MLG"1,@X00@d/bH,򴽚BHn{_86(x4kfK e'CgpK߿s'ɘɟb{{,g@Ts<2akkb,Д5TVw':of+jd|+s! 08%P1Vn|;NT^|L~/@f/³ِO†i^lT'-.V[ҕ*5!9[v4rrsvV֚xV?f?~9I5ˍp>5#6bo\NO k&7 g/,H @R-Q(;`./z3IJ0>=`5ޔkZ& },d+ʍ?uv }s=:}M}AMqcޗ4oFM}7B0^W/k.2<3[ `W$`7U;n&,D  %H0<-!,(?\ W 4F7)G@40u8n`KB8"޿ ~ܹneeQ}}}vY7cAbcy4Z f]Yd#'ord?OVhz^";x&+ N+(hom:+m0@( < P` _u!'vrIZ|gҢNAx\XSGU߾V&m[Xʟuаg<Ћc=01ceM=&tfwcv⪝Ηk װ"iۖ *)H W}{{WUF;[Z~̵sQVPdg(U E7cܣ6.Ap٭H{vZU}!QCBm9vnV=q/Y&P]QhVT~,z^y)gBNJWNk4%&bLb ],1fc2b!b m/e7<%L:zo.\s׿yEb oREdeGzv+((j53ؤ0r4Lha?R{-J\jeY{|cm; #?^q~߿3s_¾K`m5?V;eINmyQ,Fplɴl@qw=` HR,@v9oL7o3ɵ8#Wfƈb͡)yf =%(FE&Gy7, YkEjb"01X|e񖷃4+ߢ {%j`Joi rOv[8&~ʾJػt-#F̦܋"9>Nu z3 ,Uo#Ȁk;3nW<} v& S *Nnh;EHHIy4U ϮHl@4Yl(PI >yKkn^[^0@qg %n~rDiО?J4 16m"k1ӟq s-!6ymJёd dLNC[te|9!*/'#zhl1fɗxg VA6?D\'i ` Z۱ݻwh$ׁnWJYeotAÅͶs>{>~_\6~&y% Pp}SuͿeBUTIKEe_SvcESAd|vފ4e9:jϾm [%-11ĸ8<!bd_*5)m`dPА2!"kl_=H0-oDaR͸i;e3A--J@~2<>QΕ 7gkl gU3%%0|_#VnÍ Oc1RG[+c'Z}M~1_I8I!8@O!ح;KW~SG?+{owԘkf!ǝ}ϏhqmSVö?a8Z ˕/3/@ ȿ` bA}T-ETNDEEE{T!; лt>]s^ w S(`ʒ>N/oW\xo.3,vƥefH/@pXy¹O7?>'QzZF|j/A}w(:o}|]tOݷ>\ :g.rw2zFMu2Idy=x}!EiǪYY<^r2:7LMA!3TRRrSrzc̽a_8 Gh牙qERY]M%unx Dw1dG @F0Kn,=~|0k]|gѧTzk/]=n|@@^:I/۔.e{Uq?^E;׼UwS'2` ԬAb!b,ͯ,@0`B<jl׮:Rd迤18ÔŰ)ەY-bXL,PPNKy3> Z[U Le`M65ʘ:\ } pS-E>3x5T]xxTT1mN]7?`  ޣsy}?FS|d}!|F$1?BM DKwt@@NA6X/[SU[4d-ʹwK$ 0j ϏD^^hB @w[b⚟mZ\\'!OE$˘5RqFUmb: V#1S{Dy`010H\% e'3=H/O9_4RqG):o^bg4;Tًy$Kz@-fڟ[CPk~999! >M$K F5I!h'Od-X ?QKa$p\!h(=0 Q H+Sl P_"1K6*x툶m25փk-Nuur_$ 7Ѧ|5cti ^pH˝`UD /k7~]gb!ٙg@3<]O:s}ʻm7;x '#ތ:>?O\߻kjga+tm_xU^Afe))++Wd?vd?AŒuGWzzBGJ\S!l'-/^ʌ_{Ʋg+oEJ1ynt)]AoRgzqi)p6>D#>ϰ#UsC6P?Nڿ[ߘXCVR| V<* w.m͛O*g*y>hO!*n @PjPB0G$Nivvc>Ācr՞ɺS4p k:ߦ;zO9Թߒ: ^[wD2><4/ ?hk={ `s8Ǯ߸A|!€&Iz4ݛ,"\@.vd<PKPwpk0x yVT 5;p(pAꃅFWTWsWQAt-]D^nZ?t\V&Q 0Q="2uvqNL@-f-NXĵhھt]7L*dj33h9/>@ݨ;v= "h:"1 ~/_cܰi̱z9IWܿfe=QЯhk/(@<8pUI*NP֑A`H78 "pjf)P@H7AW8h|ڥ<%Jc T$phSjRɈw$YO"c.;̱bA.. XEg&0aD,FyOuK0J@uo+,ȁ؂O $_dmLAJ(:.jdފEJn-X/ǧ6XL1Egߪ1W Ud4^vrޔ6@>@w-(=/1Ps@t_dlN7"x)np~:h+rk1<_4A⟼)h)F# ۙ,N1?WmȲ&L853ǿ(W\8oRh],;_-(#7ڟ`t{(W67Wr?a;|+q_zT-w% P\9[XcJtEXugX>svb&C%)Lpqfɿi@fV\BZl0:!% @Al&#}'oϕꗕUc70S`~/Np/MDfu7K ng?Gs"e)'.g@ xw\T' @aև\7&.}F>o),f"h|M@_BV؉a|07I˳xvܴ0 9,L])`ken,Ś'>Wި,?w I;crIQ,Pwba<7 f >?/ʇL Ôr{2ys_h[j9:%r0-'?^@4Qrw B`[J[h7NK^%`lq ~t|R؛g,'n5 EȕbgVo~/b13h(7L*0?B1*۷o>&a&uK b~'d6f2,|T+dV` V|MHS}jOegw|Wrտ~g߷_}5 Bwe硫OB2Yx1i biAНr\Y/N*059cvZf(0[xÞshN&r{Xf E5ARSU v2AӞ@Z;'4n!₍< r"=V,{;EX?8^^k?ay9y=?Z @3)}G9ޗ)17<פPVQDoӒ CEKAȂ11qS oIHgvoXci!vK"xz+/7cp!HN9C'OTʅ %/3o]"+mQa!*pc͓DͿxݰ VʗǺRqN> ~yor`ť(o(]!ꇔyw/-(<q l ?Adوojk p@DW%Khlk[$Kٷ)_7UY, 0AhEU6{Zhpr9#c9gNOY$JKcu;X辳S6gtwt__<t_4Щ(^ʻ]?6e}4? F^ۇ^G KDFAT^J@Ie ]VxkdpdFruIBbܗ-ovm YC&Tv[&c R<3$\_!_K~TUWs$$I8fD;Sy:_7@\fe$B{FD$>>3/̆{{Wa{1Xi#Rrs};Z2e0`V_ߧ܌}*ǥg~E9p @KQ_+ " |!8-TsPN>oc ogH)l%oKH'o,3bDβ(~V뛳B4#H@&F8A;06}&;Po߾CEM`%b @baBbiN9=EC<$9 3x.'gKs,Dj+nOegwQ79uxd0>6}?;*I{k{s(€ 92b+LY8AX`@23d4cMNq#t!Xb.emP%)2Sw^tЁ]q~wǝlq^ͭ#"J*@,PXYb!R=EGej%gExGh?~jKǝ LBIgſ=jw{ș{T;mj(<cvRTsac|F{upO6@+쀬Ř!hwp 7n0HCCNH{@4ԨQKUi<ȼ3.iLls;2sGP݅7T|UG_qБ. đu̡ )/+WFFFXv[$B=S &ci=IcJfao?@NfghO)> @bR~7tv ~ + (:Mn:"W2G_ ?필|wwU}F`2KKKS-feuQ%.2y~;} @xYɽ=Œ33R%pB+#)sNmDa~*/{&JЉzM7/tm4YrQchaחGWt*`}8~)0Fzs hl9R 0IX拏ѢR#kt PsdKw?p떪p4vb'uBp8\zd}t)Q=LM6e#QaMŝQ;_^|>y S˵)K/~(H~f(g_<vZkEs4n^C(!k!+Ilя??1d N$ՄZ.7Yȓeޫ!mܤ?__91[\_q.ddgoYT"K>,8@w;FG1#X ™'5Gl hū@#x@YV!խ "MjVq?+@ b}/@E333)'' gK$>w7oߦ;99QE'}i$9 L#8˿L4^ C/Хwcʚ~$^onJA ?q@k͗.mg!4c&H"2DޭȲ]ʯoiVɬf(YW5v2`?dQ{  uLh3!>f ƺXY:`mH"gS g3ZhȐ!leכl}_! oMWW/Z??x.)`ボQ&6''S8k~7%. *QJ?`f\321(1XmE7m:fSQKa,Ocl*3(dԂXL(;eo0K~Ҵ_Q= Bh&@Ya?Y\\nh|A(7!|pJ` 1?~AƃY?\$7^wrE?1/RԬE^ Ekˆ1[|{";+k4Vghս#=֊T|\r/灛=Ʌq}SJT:H_95^ٳx]%@79@6 ,w"+AlIn{ȿIJBuX+RɄٽ(RU43nG2,21H[PFP*6@v/[vvTK3_@g<c*j~T}4fgy~jjj[,䧇 Gqj /[ $j.*5zp @sq#,nߌ;0)#``Ϋ@b$rqQZG\בxwS JH$-.CG`?q?—96Uk\(3nyHK^ &ޡqwwwӟ(lWK3AX΀vA !¥#JJ8V20זg黎I.Ȫ9,9"/dn~@%ޣ`G4_}%g ߋ#w, CZ4Z&ٚ49Їҵ֑QӋOу}Fnⶅ}ww  Yk8sDf\M{QDJJÞ'xgAhmg٪d?,4:(H9?@e _qÍ#r}u/}:=?(8J'߼OZ;.@YGiTًq({>шL EZfiBe +TZZz0fpcLּCTrU*&<]|3||[2?Żr0|x'en,Wަh@82@G6ls NsOJyo3oي!ݲmcvzzdȽ׻NdG>Q=b)*f65q0e@x )r "Xr8bb׍)"=0$3K?gxQ|P.N#D6mK!J<ʊM=WDVI0}mlss㡉/;+VEw}|+7L!" P\J4@)//\}F6 Yetq3@7Z9\];r (;\_:>Xps=J3oC/\`,=N `~#J!eN_RuT$S%(![R v1kX(|"|0r9S@BH:>j,C{!_HS` $Ȼt-brF2H"QS vr#\6E GU6`7| &scCտQqRݤ[x$ <39A(%LXɓ$)`N5Рsp3pC,ؽCf5"%Q0Z9{(_e0Rr̮da-ZІ=?ZߐHoa/D}v|#"b-LB4}u8^q:9h 'hOL@D0 >k(UdOgvEgÙo1 8 Q7L?R?bڂ QF" `ͣ@,"Y 3ZɌ&X*i&"IAUn:-K<Ǽ"S ĕ@(\¼|tq8g̲3훧97--loeȞzYEMYꚚup{܉)?\{sq0}`ds:Ok  ʒei3)`T@= z<;!,,͹hfaZI3vE&h˟Q*adW)~9M\xqYU>EYx<xL㧲 ߸#V BvV<DXD % ŋ~⛟@P|6S3V,.>o~~:|c)8=ʏԪl4Eb¡6鶶X@Mpl^copG 9;D @_-c ol:[+,Q3QY72nGs d(czFB,Xb1I4 X!O x˟$Pĸ()| \PeڵU|{QG Dq!0<_SZ{vxӗUR5SsƟ8 QM #Cc *@?"40^u*ϽFgwɀ`@W5g`|\1u " 3C)GQ33 ܆V$Sj!dj.왝p Q?=] DCzzLPpTB1}+p 駼ř[ ݘ^6<|ńk^u3 EL|P^KK@HKˬg=կe 1pV(ӱ?7@._;fK((mp?LUIemm` =ӗ?U' 逵#S8h=Ҩ i/+aAP qJ7}szԏ PХٗr܎`lj*MĢ8SB)v݌pB^$D," /UqÛ]۷ueͥ ֊-3 NXaU t7/O]l"묎 8܉1((Hm.h "C3/W;ҁQH rGW,{iʙ {~*ƙ aM/LeL EԿ\j>5pm&ll? d~@PpTk?yor`ť_ӝP޷B@ݕy*:o ac;sO $\[㸐CH&)V_6>4Z%Y+LV#\D-]H&V)a;6RVkwEU2.s |i Jby/PAѣG$Z"X?RvӧOKr/AaLW{;J ?ʋ(^ʿ]?6e}4T)?b}Ef[-/¹F a0UKs-D`WL#/TrnSݧI wRͅ|߭tpa 9"b<)z{".Z1e]?^;^;)\&~'.j*qwd-D,ZV*Sa\)h%J3 ygb;փ Oe_ W] 0\p @Ks@"Gl:lT՟{`2?~n|uysk3H@qЇ 4]{7#pj7e}+x4ОG_ 1~$I';kffuljjU/iߝ_X8p8{ g{ߡt(a{;k>? l4 )pA' 6Go(pOd(gGNlq 1K4_=]zUrw~& B6h04PBً3@+NhTA?,im%_#hQ/U|?RPFr+.r8+*?x`ČVAC, .GS>xݥ_3%o oR5S7/qjϿMEPaj[KAw+z2 F\? 89Bx0VYvs"900dU&|@A3żέv饉W9 ` =)~L?s?[η҃ X %~'!Ѿ`F „6:ʼȍ7-z8 UVW떄22.7=6P!Z*]+9IvlW.!qd3bUb #EtOECj8 ƿ e~׆F6/%'Z%ݣyCs;o^^ ?&s?¯w@dC@4@ 0]b" p 䧽XHDîRFH $L]kÀtL)P3 6aW##0k  1_>x۹H@(r~\s\D83]4u2ecWE xgE%%%qqѣ ɟ)қ%@y+GS;o^B%mbߟ w;3~H #R`$ owUߦtg,%@)uf_ڟ5?USO4sP;9+ymמ 9~`Ho`15H7 v!ߡ]5j)ly9Yʙdق0 Q"albbvlᾷr =fNh ,?kmsUrݿN.k/L:Oeȯ/0&941Δ֚dBs UR?ʪu^X^ю;R-ֻe &v7/0~/W<?ZR)xVyA(m4xY}&P XxܿwpŪV3&>D(z]P_/Y,uqR W, =S/iֶ;%2"Dh,#4I{_QQQ $A񋾂Ґ3u:BGFVpG)A/Ç4`i=.ɘ|^x./ VjyxwA€L2q+|gElg+ˊE@@@r01Hu&)~&6 av,;]u^׸pDkrHX\DG`Į^ )rVJr P*bHK/';?gM棊uc2P<^gB"0FPZZjO & T8ȱW\1gs.0I1n JJ7͓i`@daY+dz)`~=Jy9X ~}8YI9ەwlȲ8t7gz pUiuf[#x+oX?a?NӦJ(}U}~_ԚvU_k OHĔ.y 1 !_ջJ/@J%c#RnH3!b#o,uq)n `Fo1q4vKge'ܴtC'_ᅕB`@w5 kxFG?PnX\m} y: {qh5̸ K3?<߿׀8 ֻΨXN 0Qd*`[FX% U]-T7F#ZoJU,W2vݻ{;rGȉ}sZ*jNY ~U Oc%DWEbuڡѫsߑ=Yq4^X:?<^ɗt={_/ZNZ,$V6}>VX%-ժ[7uϱc*Pa?:W>fHc?7؞Vx|t޵{4$ ;W>u .>|K/6/[`w\- JrDY;`QTJᾦ9c(4ė)?sƯNY,3 '_=BjE}?p<'}^=[ZΗԎ%wgbC37uuD'9x1y"\pn"dHEF(Og^ڷ?>zαБ#t+tiMG?Ҩ0nYèQD/s{xfbBnH~g&Q F~Cb70e%Cʕ+$PfW?~{NA(WG=!G"2ԾT;~ Jʑ?«O^|ѯ9(g*ǐ~|do8D1h*"Ws< cPΡadD BQo&, EԵ~=`;ܫ^8xwbȎX Za_ٷu+\r< &6T d߽ wo$`>0S3ZBW:¸(_S/B7/Fa%:{x^l}mk۟+jd^L><(M9%[(~>UAM{~ވ؏W=3lC ï ȌsF|7,-<6}Wd7&E.a au}Aoju%62㈜KzynH]je_'#W* 'l4*# 0 *k]%{EJ3>Ͷ׳2VSޣCpƌblFX&ٗaRi4"[8t{aᶝ8t1=Vn_32͵,4RLczV5W~ }1|1W3_6b9okξ(y"QJL AQ[- .6M޼ b?% *VG۽$Mx{jj +c7 >a&Rh `0 \>FWK:Rz`ޗmٶ7T0}hࣜw_v(K, p pʾ|/3g9bV]F}oMhma<Oًi\0*) {ax%_e_} ݺN_u~czMzT\<>7~Sz%&b+enӸ=t<6W1B}:UK>ˌnAޒ;3K^ub F}at&F)ukAr #)^;L'رc.V}dðό}Hm%:-s!J#> uiXnl1:|5Gy r7LJo.`e݅zpifFo~o|a R+̀WeO/^HGHFOcԖ@c.Ç[@{0gS_t)xo5>w q&_,=f_QG@u*_H&RF\e&b" PiZh)Өofk.Eb{ _ػ\g={7Dɽ|zL]C/$ pTtz5Jq|EVY;vL;_z {~8c>8|C d{ ZUA,K`Dz>|ϭ0{-xiy \ }:gTy :1pg?][E]whsQy `@9~$/`\Q..Hq]mc|4w0}׮]Np0/eyA{@׾6x mIU}%?.=p|uyMZhp<ɽ(*0qZsG+Kz{suO5*wh@x;pnb{Ʌr{>F|l PIC> 7 hIERbN__\f7}kpc/9FW`~X 9cui/1S9` }sL"[rYPVZe*`1zrIץW_<6Hԙ};=5"pb]9_yC3gH+k* 08_Zg&@H\$8@3|w13.VxW~S׮]AM̸=g ،|c/>J@"g,+xpb7v(ogbny}ꖼ 0.5"Eon|y ~c>_s G,+WT< d>&}@Z^kNd#zdc)_9Da@Ҵd(=iCeeyt|zEwQ)YʜS1)Ք _Eo~QV[w2JO?\#0HC R d x C/$xE_:ziTK2 *<RnsכaE_2e8kȥvU w)ֿ[ 4A0Ò?H2qp ]."D:ļL/ {Oo?~ 摥קH9p=j0q!iM@YOϙO# pܗ'Zw"r2߿,{W`*@OvZ|Yτw^)?~uӴ<;d`/N/\p3Fhʧ w(dIO9`K6YAo$p#v!4|@w۠g#t{&2< tzL}r1\kPEzXtb&2 F0T@%?rycQߏ*n^=ܩx%ˁ;VR[ƴszK {ds/\"KC|JaDa tWGW@Dn ӫy(U'V "}z?KO 5z!L/ gN˗\cW1'@9U_;ǤGbԏG1_>Wvcd+<Ѹ O,:@j_LȁhkrOF8GZ1`FBﱛ2<jLS9aPf4OOΛlr^|qqb{\}{`5I|y.ZamsqϤߟu \6Ԋg N.r_ZN`<"(?_| ^vޖ84ьfPԩĮob- 5Smc#XV] <$641 OK&$$Xkjj2SȜG1B-ٳg)<<Ҩ}^J9 ->%KXՎIIIIyG?ee?m^>Gk(˔I`4QUm-7m+V؟ogVJ T@Cc=e%9%. 11)c!ȣ0hF3]]BV9E\ a? Z@ 8Ԥ #R=$e12Xc>̦;&M1Y!zTQVI`4qaCfF`DofRJi Q '?(IQ͛")